Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ensure that epoch of attestation slot matches the target epoch #1509

Merged
merged 1 commit into from
Dec 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions specs/core/0_beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -1482,6 +1482,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
data = attestation.data
assert data.index < get_committee_count_at_slot(state, data.slot)
assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
assert data.target.epoch == compute_epoch_at_slot(data.slot)
assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH

committee = get_beacon_committee(state, data.slot, data.index)
Expand Down
1 change: 1 addition & 0 deletions specs/core/0_fork-choice.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ def on_attestation(store: Store, attestation: Attestation) -> None:
# Use GENESIS_EPOCH for previous when genesis to avoid underflow
previous_epoch = current_epoch - 1 if current_epoch > GENESIS_EPOCH else GENESIS_EPOCH
assert target.epoch in [current_epoch, previous_epoch]
assert target.epoch == compute_epoch_at_slot(attestation.data.slot)

# Attestations target be for a known block. If target block is unknown, delay consideration until the block is found
assert target.root in store.blocks
Expand Down
23 changes: 23 additions & 0 deletions test_libs/pyspec/eth2spec/test/fork_choice/test_on_attestation.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,29 @@ def test_on_attestation_past_epoch(spec, state):
run_on_attestation(spec, state, store, attestation, False)


@with_all_phases
@spec_state_test
def test_on_attestation_mismatched_target_and_slot(spec, state):
store = spec.get_genesis_store(state)
spec.on_tick(store, store.time + spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH)

block = build_empty_block_for_next_slot(spec, state)
signed_block = state_transition_and_sign_block(spec, state, block)

# store block in store
spec.on_block(store, signed_block)

attestation = get_valid_attestation(spec, state, slot=block.slot)
attestation.data.target.epoch += 1
sign_attestation(spec, state, attestation)

assert attestation.data.target.epoch == spec.GENESIS_EPOCH + 1
assert spec.compute_epoch_at_slot(attestation.data.slot) == spec.GENESIS_EPOCH
assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == spec.GENESIS_EPOCH + 1

run_on_attestation(spec, state, store, attestation, False)


@with_all_phases
@spec_state_test
def test_on_attestation_target_not_in_store(spec, state):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,20 @@ def test_invalid_index(spec, state):
yield from run_attestation_processing(spec, state, attestation, False)


@with_all_phases
@spec_state_test
def test_mismatched_target_and_slot(spec, state):
next_epoch(spec, state)
next_epoch(spec, state)

attestation = get_valid_attestation(spec, state)
attestation.data.slot = attestation.data.slot - spec.SLOTS_PER_EPOCH

sign_attestation(spec, state, attestation)

yield from run_attestation_processing(spec, state, attestation, False)


@with_all_phases
@spec_state_test
def test_old_target_epoch(spec, state):
Expand Down