From 687b262f0d96f3b331758b35520ec27597585d15 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 20 Sep 2019 11:27:42 -0500 Subject: [PATCH] add test case for crosslink tie breaking between epochs --- .../eth2spec/test/helpers/attestations.py | 5 +- .../test_process_crosslinks.py | 52 +++++++++++++++++-- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/helpers/attestations.py b/test_libs/pyspec/eth2spec/test/helpers/attestations.py index 868517018..43d9bf44f 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/attestations.py +++ b/test_libs/pyspec/eth2spec/test/helpers/attestations.py @@ -138,10 +138,11 @@ def fill_aggregate_attestation(spec, state, attestation): attestation.aggregation_bits[i] = True -def add_attestation_to_state(spec, state, attestation, slot): +def add_attestations_to_state(spec, state, attestations, slot): block = build_empty_block_for_next_slot(spec, state) block.slot = slot - block.body.attestations.append(attestation) + for attestation in attestations: + block.body.attestations.append(attestation) spec.process_slots(state, block.slot) sign_block(spec, state, block) spec.state_transition(state, block) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py index 41d784c50..a335896df 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py @@ -7,7 +7,7 @@ from eth2spec.test.helpers.state import ( ) from eth2spec.test.helpers.block import apply_empty_block from eth2spec.test.helpers.attestations import ( - add_attestation_to_state, + add_attestations_to_state, fill_aggregate_attestation, get_valid_attestation, sign_attestation, @@ -36,7 +36,7 @@ def test_single_crosslink_update_from_current_epoch(spec, state): attestation = get_valid_attestation(spec, state, signed=True) fill_aggregate_attestation(spec, state, attestation) - add_attestation_to_state(spec, state, attestation, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) + add_attestations_to_state(spec, state, [attestation], state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) assert len(state.current_epoch_attestations) == 1 @@ -57,7 +57,7 @@ def test_single_crosslink_update_from_previous_epoch(spec, state): attestation = get_valid_attestation(spec, state, signed=True) fill_aggregate_attestation(spec, state, attestation) - add_attestation_to_state(spec, state, attestation, state.slot + spec.SLOTS_PER_EPOCH) + add_attestations_to_state(spec, state, [attestation], state.slot + spec.SLOTS_PER_EPOCH) assert len(state.previous_epoch_attestations) == 1 @@ -95,7 +95,7 @@ def test_double_late_crosslink(spec, state): # add attestation_1 to next epoch next_epoch(spec, state) - add_attestation_to_state(spec, state, attestation_1, state.slot + 1) + add_attestations_to_state(spec, state, [attestation_1], state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) for _ in range(spec.SLOTS_PER_EPOCH): attestation_2 = get_valid_attestation(spec, state) @@ -110,7 +110,7 @@ def test_double_late_crosslink(spec, state): # add attestation_2 in the next epoch after attestation_1 has # already updated the relevant crosslink next_epoch(spec, state) - add_attestation_to_state(spec, state, attestation_2, state.slot + 1) + add_attestations_to_state(spec, state, [attestation_2], state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) assert len(state.previous_epoch_attestations) == 1 assert len(state.current_epoch_attestations) == 0 @@ -130,3 +130,45 @@ def test_double_late_crosslink(spec, state): attestation_2.data.crosslink.shard): assert crosslink_deltas[0][index] == 0 assert crosslink_deltas[1][index] > 0 + + +@with_all_phases +@spec_state_test +def test_tied_crosslink_between_epochs(spec, state): + """ + Addresses scenario found at Interop described by this test case + https://github.com/djrtwo/interop-test-cases/tree/master/tests/night_one_16_crosslinks + + Ensure that ties on crosslinks between epochs are broken by previous epoch. + """ + prev_attestation = get_valid_attestation(spec, state, signed=True) + fill_aggregate_attestation(spec, state, prev_attestation) + + # add attestation at start of next epoch + next_epoch(spec, state) + add_attestations_to_state(spec, state, [prev_attestation], state.slot) + + # create attestation from current epoch for same shard + for _ in range(spec.SLOTS_PER_EPOCH): + cur_attestation = get_valid_attestation(spec, state) + if cur_attestation.data.crosslink.shard == prev_attestation.data.crosslink.shard: + sign_attestation(spec, state, cur_attestation) + break + next_slot(spec, state) + fill_aggregate_attestation(spec, state, cur_attestation) + + add_attestations_to_state(spec, state, [cur_attestation], state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) + + shard = prev_attestation.data.crosslink.shard + pre_crosslink = deepcopy(state.current_crosslinks[shard]) + + assert prev_attestation.data.crosslink != cur_attestation.data.crosslink + assert state.current_crosslinks[shard] == spec.Crosslink() + assert len(state.previous_epoch_attestations) == 1 + assert len(state.current_epoch_attestations) == 1 + + yield from run_process_crosslinks(spec, state) + + assert state.previous_crosslinks[shard] != state.current_crosslinks[shard] + assert pre_crosslink != state.current_crosslinks[shard] + assert state.current_crosslinks[shard] == prev_attestation.data.crosslink