/ test_libs / pyspec / eth2spec / test / epoch_processing / test_process_crosslinks.py
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