/ test_libs / pyspec / eth2spec / test / block_processing / test_process_transfer.py
test_process_transfer.py
  1  import eth2spec.phase0.spec as spec
  2  from eth2spec.phase0.spec import (
  3      get_active_validator_indices,
  4      get_beacon_proposer_index,
  5      get_current_epoch,
  6      process_transfer,
  7  )
  8  from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls
  9  from eth2spec.test.helpers.state import next_epoch
 10  from eth2spec.test.helpers.block import apply_empty_block
 11  from eth2spec.test.helpers.transfers import get_valid_transfer
 12  
 13  
 14  def run_transfer_processing(state, transfer, valid=True):
 15      """
 16      Run ``process_transfer``, yielding:
 17        - pre-state ('pre')
 18        - transfer ('transfer')
 19        - post-state ('post').
 20      If ``valid == False``, run expecting ``AssertionError``
 21      """
 22  
 23      proposer_index = get_beacon_proposer_index(state)
 24      pre_transfer_sender_balance = state.balances[transfer.sender]
 25      pre_transfer_recipient_balance = state.balances[transfer.recipient]
 26      pre_transfer_proposer_balance = state.balances[proposer_index]
 27  
 28      yield 'pre', state
 29      yield 'transfer', transfer
 30  
 31      if not valid:
 32          expect_assertion_error(lambda: process_transfer(state, transfer))
 33          yield 'post', None
 34          return
 35  
 36      process_transfer(state, transfer)
 37      yield 'post', state
 38  
 39      sender_balance = state.balances[transfer.sender]
 40      recipient_balance = state.balances[transfer.recipient]
 41      assert sender_balance == pre_transfer_sender_balance - transfer.amount - transfer.fee
 42      assert recipient_balance == pre_transfer_recipient_balance + transfer.amount
 43      assert state.balances[proposer_index] == pre_transfer_proposer_balance + transfer.fee
 44  
 45  
 46  @spec_state_test
 47  def test_success_non_activated(state):
 48      transfer = get_valid_transfer(state, signed=True)
 49      # un-activate so validator can transfer
 50      state.validator_registry[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
 51  
 52      yield from run_transfer_processing(state, transfer)
 53  
 54  
 55  @spec_state_test
 56  def test_success_withdrawable(state):
 57      next_epoch(state)
 58      apply_empty_block(state)
 59  
 60      transfer = get_valid_transfer(state, signed=True)
 61  
 62      # withdrawable_epoch in past so can transfer
 63      state.validator_registry[transfer.sender].withdrawable_epoch = get_current_epoch(state) - 1
 64  
 65      yield from run_transfer_processing(state, transfer)
 66  
 67  
 68  @spec_state_test
 69  def test_success_active_above_max_effective(state):
 70      sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1]
 71      state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE + 1
 72      transfer = get_valid_transfer(state, sender_index=sender_index, amount=1, fee=0, signed=True)
 73  
 74      yield from run_transfer_processing(state, transfer)
 75  
 76  
 77  @spec_state_test
 78  def test_success_active_above_max_effective_fee(state):
 79      sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1]
 80      state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE + 1
 81      transfer = get_valid_transfer(state, sender_index=sender_index, amount=0, fee=1, signed=True)
 82  
 83      yield from run_transfer_processing(state, transfer)
 84  
 85  
 86  @always_bls
 87  @spec_state_test
 88  def test_invalid_signature(state):
 89      transfer = get_valid_transfer(state)
 90      # un-activate so validator can transfer
 91      state.validator_registry[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
 92      
 93      yield from run_transfer_processing(state, transfer, False)
 94  
 95  
 96  @spec_state_test
 97  def test_active_but_transfer_past_effective_balance(state):
 98      sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1]
 99      amount = spec.MAX_EFFECTIVE_BALANCE // 32
100      state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE
101      transfer = get_valid_transfer(state, sender_index=sender_index, amount=amount, fee=0, signed=True)
102  
103      yield from run_transfer_processing(state, transfer, False)
104  
105  
106  @spec_state_test
107  def test_incorrect_slot(state):
108      transfer = get_valid_transfer(state, slot=state.slot + 1, signed=True)
109      # un-activate so validator can transfer
110      state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
111  
112      yield from run_transfer_processing(state, transfer, False)
113  
114  
115  @spec_state_test
116  def test_insufficient_balance_for_fee(state):
117      sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1]
118      state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE
119      transfer = get_valid_transfer(state, sender_index=sender_index, amount=0, fee=1, signed=True)
120  
121      # un-activate so validator can transfer
122      state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
123  
124      yield from run_transfer_processing(state, transfer, False)
125  
126  
127  @spec_state_test
128  def test_insufficient_balance(state):
129      sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1]
130      state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE
131      transfer = get_valid_transfer(state, sender_index=sender_index, amount=1, fee=0, signed=True)
132  
133      # un-activate so validator can transfer
134      state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
135  
136      yield from run_transfer_processing(state, transfer, False)
137  
138  
139  @spec_state_test
140  def test_no_dust_sender(state):
141      sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1]
142      balance = state.balances[sender_index]
143      transfer = get_valid_transfer(state, sender_index=sender_index, amount=balance - spec.MIN_DEPOSIT_AMOUNT + 1, fee=0, signed=True)
144  
145      # un-activate so validator can transfer
146      state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
147  
148      yield from run_transfer_processing(state, transfer, False)
149  
150  
151  @spec_state_test
152  def test_no_dust_recipient(state):
153      sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1]
154      state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE + 1
155      transfer = get_valid_transfer(state, sender_index=sender_index, amount=1, fee=0, signed=True)
156      state.balances[transfer.recipient] = 0
157  
158      # un-activate so validator can transfer
159      state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
160  
161      yield from run_transfer_processing(state, transfer, False)
162  
163  
164  @spec_state_test
165  def test_invalid_pubkey(state):
166      transfer = get_valid_transfer(state, signed=True)
167      state.validator_registry[transfer.sender].withdrawal_credentials = spec.ZERO_HASH
168  
169      # un-activate so validator can transfer
170      state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
171  
172      yield from run_transfer_processing(state, transfer, False)