/ test_libs / pyspec / eth2spec / test / block_processing / test_process_proposer_slashing.py
test_process_proposer_slashing.py
  1  import eth2spec.phase0.spec as spec
  2  from eth2spec.phase0.spec import (
  3      get_current_epoch,
  4      process_proposer_slashing,
  5  )
  6  from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls
  7  from eth2spec.test.helpers.block_header import sign_block_header
  8  from eth2spec.test.helpers.keys import privkeys
  9  from eth2spec.test.helpers.proposer_slashings import get_valid_proposer_slashing
 10  from eth2spec.test.helpers.state import get_balance
 11  
 12  
 13  def run_proposer_slashing_processing(state, proposer_slashing, valid=True):
 14      """
 15      Run ``process_proposer_slashing``, yielding:
 16        - pre-state ('pre')
 17        - proposer_slashing ('proposer_slashing')
 18        - post-state ('post').
 19      If ``valid == False``, run expecting ``AssertionError``
 20      """
 21  
 22      yield 'pre', state
 23      yield 'proposer_slashing', proposer_slashing
 24  
 25      if not valid:
 26          expect_assertion_error(lambda: process_proposer_slashing(state, proposer_slashing))
 27          yield 'post', None
 28          return
 29  
 30      pre_proposer_balance = get_balance(state, proposer_slashing.proposer_index)
 31  
 32      process_proposer_slashing(state, proposer_slashing)
 33      yield 'post', state
 34  
 35      # check if slashed
 36      slashed_validator = state.validator_registry[proposer_slashing.proposer_index]
 37      assert slashed_validator.slashed
 38      assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
 39      assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
 40  
 41      # lost whistleblower reward
 42      assert (
 43          get_balance(state, proposer_slashing.proposer_index) <
 44          pre_proposer_balance
 45      )
 46  
 47  
 48  @spec_state_test
 49  def test_success(state):
 50      proposer_slashing = get_valid_proposer_slashing(state, signed_1=True, signed_2=True)
 51  
 52      yield from run_proposer_slashing_processing(state, proposer_slashing)
 53  
 54  
 55  @always_bls
 56  @spec_state_test
 57  def test_invalid_sig_1(state):
 58      proposer_slashing = get_valid_proposer_slashing(state, signed_1=False, signed_2=True)
 59      yield from run_proposer_slashing_processing(state, proposer_slashing, False)
 60  
 61  
 62  @always_bls
 63  @spec_state_test
 64  def test_invalid_sig_2(state):
 65      proposer_slashing = get_valid_proposer_slashing(state, signed_1=True, signed_2=False)
 66      yield from run_proposer_slashing_processing(state, proposer_slashing, False)
 67  
 68  
 69  @always_bls
 70  @spec_state_test
 71  def test_invalid_sig_1_and_2(state):
 72      proposer_slashing = get_valid_proposer_slashing(state, signed_1=False, signed_2=False)
 73      yield from run_proposer_slashing_processing(state, proposer_slashing, False)
 74  
 75  
 76  @spec_state_test
 77  def test_invalid_proposer_index(state):
 78      proposer_slashing = get_valid_proposer_slashing(state, signed_1=True, signed_2=True)
 79      # Index just too high (by 1)
 80      proposer_slashing.proposer_index = len(state.validator_registry)
 81  
 82      yield from run_proposer_slashing_processing(state, proposer_slashing, False)
 83  
 84  
 85  @spec_state_test
 86  def test_epochs_are_different(state):
 87      proposer_slashing = get_valid_proposer_slashing(state, signed_1=True, signed_2=False)
 88  
 89      # set slots to be in different epochs
 90      proposer_slashing.header_2.slot += spec.SLOTS_PER_EPOCH
 91      sign_block_header(state, proposer_slashing.header_2, privkeys[proposer_slashing.proposer_index])
 92  
 93      yield from run_proposer_slashing_processing(state, proposer_slashing, False)
 94  
 95  
 96  @spec_state_test
 97  def test_headers_are_same(state):
 98      proposer_slashing = get_valid_proposer_slashing(state, signed_1=True, signed_2=False)
 99  
100      # set headers to be the same
101      proposer_slashing.header_2 = proposer_slashing.header_1
102  
103      yield from run_proposer_slashing_processing(state, proposer_slashing, False)
104  
105  
106  @spec_state_test
107  def test_proposer_is_not_activated(state):
108      proposer_slashing = get_valid_proposer_slashing(state, signed_1=True, signed_2=True)
109  
110      # set proposer to be not active yet
111      state.validator_registry[proposer_slashing.proposer_index].activation_epoch = get_current_epoch(state) + 1
112  
113      yield from run_proposer_slashing_processing(state, proposer_slashing, False)
114  
115  
116  @spec_state_test
117  def test_proposer_is_slashed(state):
118      proposer_slashing = get_valid_proposer_slashing(state, signed_1=True, signed_2=True)
119  
120      # set proposer to slashed
121      state.validator_registry[proposer_slashing.proposer_index].slashed = True
122  
123      yield from run_proposer_slashing_processing(state, proposer_slashing, False)
124  
125  
126  @spec_state_test
127  def test_proposer_is_withdrawn(state):
128      proposer_slashing = get_valid_proposer_slashing(state, signed_1=True, signed_2=True)
129  
130      # move 1 epoch into future, to allow for past withdrawable epoch
131      state.slot += spec.SLOTS_PER_EPOCH
132      # set proposer withdrawable_epoch in past
133      current_epoch = get_current_epoch(state)
134      proposer_index = proposer_slashing.proposer_index
135      state.validator_registry[proposer_index].withdrawable_epoch = current_epoch - 1
136  
137      yield from run_proposer_slashing_processing(state, proposer_slashing, False)