test_process_crosslinks.py
1 from copy import deepcopy 2 3 import eth2spec.phase0.spec as spec 4 from eth2spec.phase0.spec import ( 5 cache_state, 6 get_crosslink_deltas, 7 process_crosslinks, 8 ) 9 from eth2spec.phase0.state_transition import ( 10 state_transition, 11 ) 12 from eth2spec.test.context import spec_state_test 13 from eth2spec.test.helpers.state import ( 14 next_epoch, 15 next_slot 16 ) 17 from eth2spec.test.helpers.block import apply_empty_block, sign_block 18 from eth2spec.test.helpers.attestations import ( 19 add_attestation_to_state, 20 build_empty_block_for_next_slot, 21 fill_aggregate_attestation, 22 get_crosslink_committee, 23 get_valid_attestation, 24 sign_attestation, 25 ) 26 27 28 def run_process_crosslinks(state, valid=True): 29 """ 30 Run ``process_crosslinks``, yielding: 31 - pre-state ('pre') 32 - post-state ('post'). 33 If ``valid == False``, run expecting ``AssertionError`` 34 """ 35 # transition state to slot before state transition 36 slot = state.slot + (spec.SLOTS_PER_EPOCH - state.slot % spec.SLOTS_PER_EPOCH) - 1 37 block = build_empty_block_for_next_slot(state) 38 block.slot = slot 39 sign_block(state, block) 40 state_transition(state, block) 41 42 # cache state before epoch transition 43 cache_state(state) 44 45 yield 'pre', state 46 process_crosslinks(state) 47 yield 'post', state 48 49 50 @spec_state_test 51 def test_no_attestations(state): 52 yield from run_process_crosslinks(state) 53 54 for shard in range(spec.SHARD_COUNT): 55 assert state.previous_crosslinks[shard] == state.current_crosslinks[shard] 56 57 58 @spec_state_test 59 def test_single_crosslink_update_from_current_epoch(state): 60 next_epoch(state) 61 62 attestation = get_valid_attestation(state, signed=True) 63 64 fill_aggregate_attestation(state, attestation) 65 add_attestation_to_state(state, attestation, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) 66 67 assert len(state.current_epoch_attestations) == 1 68 69 shard = attestation.data.shard 70 pre_crosslink = deepcopy(state.current_crosslinks[shard]) 71 72 yield from run_process_crosslinks(state) 73 74 assert state.previous_crosslinks[shard] != state.current_crosslinks[shard] 75 assert pre_crosslink != state.current_crosslinks[shard] 76 77 78 @spec_state_test 79 def test_single_crosslink_update_from_previous_epoch(state): 80 next_epoch(state) 81 82 attestation = get_valid_attestation(state, signed=True) 83 84 fill_aggregate_attestation(state, attestation) 85 add_attestation_to_state(state, attestation, state.slot + spec.SLOTS_PER_EPOCH) 86 87 assert len(state.previous_epoch_attestations) == 1 88 89 shard = attestation.data.shard 90 pre_crosslink = deepcopy(state.current_crosslinks[shard]) 91 92 crosslink_deltas = get_crosslink_deltas(state) 93 94 yield from run_process_crosslinks(state) 95 96 assert state.previous_crosslinks[shard] != state.current_crosslinks[shard] 97 assert pre_crosslink != state.current_crosslinks[shard] 98 99 # ensure rewarded 100 for index in get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.shard): 101 assert crosslink_deltas[0][index] > 0 102 assert crosslink_deltas[1][index] == 0 103 104 105 @spec_state_test 106 def test_double_late_crosslink(state): 107 if spec.get_epoch_committee_count(state, spec.get_current_epoch(state)) < spec.SHARD_COUNT: 108 print("warning: ignoring test, test-assumptions are incompatible with configuration") 109 return 110 111 next_epoch(state) 112 state.slot += 4 113 114 attestation_1 = get_valid_attestation(state, signed=True) 115 fill_aggregate_attestation(state, attestation_1) 116 117 # add attestation_1 to next epoch 118 next_epoch(state) 119 add_attestation_to_state(state, attestation_1, state.slot + 1) 120 121 for slot in range(spec.SLOTS_PER_EPOCH): 122 attestation_2 = get_valid_attestation(state) 123 if attestation_2.data.shard == attestation_1.data.shard: 124 sign_attestation(state, attestation_2) 125 break 126 next_slot(state) 127 apply_empty_block(state) 128 129 fill_aggregate_attestation(state, attestation_2) 130 131 # add attestation_2 in the next epoch after attestation_1 has 132 # already updated the relevant crosslink 133 next_epoch(state) 134 add_attestation_to_state(state, attestation_2, state.slot + 1) 135 136 assert len(state.previous_epoch_attestations) == 1 137 assert len(state.current_epoch_attestations) == 0 138 139 crosslink_deltas = get_crosslink_deltas(state) 140 141 yield from run_process_crosslinks(state) 142 143 shard = attestation_2.data.shard 144 145 # ensure that the current crosslinks were not updated by the second attestation 146 assert state.previous_crosslinks[shard] == state.current_crosslinks[shard] 147 # ensure no reward, only penalties for the failed crosslink 148 for index in get_crosslink_committee(state, attestation_2.data.target_epoch, attestation_2.data.shard): 149 assert crosslink_deltas[0][index] == 0 150 assert crosslink_deltas[1][index] > 0