diff --git a/specs/_features/eip7002/beacon-chain.md b/specs/_features/eip7002/beacon-chain.md index 57a1b1b82..bc9d94948 100644 --- a/specs/_features/eip7002/beacon-chain.md +++ b/specs/_features/eip7002/beacon-chain.md @@ -42,7 +42,7 @@ This mechanism relies on the changes proposed by [EIP-7002](http://eips.ethereum | Name | Value | | - | - | -| `MAX_EXITS_PER_BLOCK` | `2**4` (= 16) | +| `MAX_EXECUTION_LAYER_EXITS` | `2**4` (= 16) | ## Containers @@ -80,7 +80,7 @@ class ExecutionPayload(Container): transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] excess_data_gas: uint256 - exits: List[ExecutionLayerExit, MAX_EXITS_PER_BLOCK] # [New in EIP7002] + exits: List[ExecutionLayerExit, MAX_EXECUTION_LAYER_EXITS] # [New in EIP7002] ``` #### `ExecutionPayloadHeader` @@ -243,11 +243,9 @@ def process_execution_layer_exit(state: BeaconState, execution_layer_exit: Execu validator = state.validators[validator_index] # Verify withdrawal credentials - is_correct_source_address = ( - validator.withdrawal_credentials[:1] == ETH1_ADDRESS_WITHDRAWAL_PREFIX - and validator.withdrawal_credentials[12:] == execution_layer_exit.source_address - ) - if not is_correct_source_address: + is_execution_address = validator.withdrawal_credentials[:1] == ETH1_ADDRESS_WITHDRAWAL_PREFIX + is_correct_source_address = validator.withdrawal_credentials[12:] == execution_layer_exit.source_address + if not (is_execution_address and is_correct_source_address): return # Verify the validator is active if not is_active_validator(validator, get_current_epoch(state)): diff --git a/specs/_features/eip7002/fork.md b/specs/_features/eip7002/fork.md index ad3164f7f..9698b9fbc 100644 --- a/specs/_features/eip7002/fork.md +++ b/specs/_features/eip7002/fork.md @@ -89,6 +89,7 @@ def upgrade_to_eip7002(pre: deneb.BeaconState) -> BeaconState: transactions_root=pre.latest_execution_payload_header.transactions_root, withdrawals_root=pre.latest_execution_payload_header.withdrawals_root, excess_data_gas=uint256(0), + exits_root=Root(), # [New in EIP-7002] ) post = BeaconState( # Versioning diff --git a/tests/core/pyspec/eth2spec/test/eip7002/block_processing/test_process_execution_layer_exit.py b/tests/core/pyspec/eth2spec/test/eip7002/block_processing/test_process_execution_layer_exit.py index a7adce945..11772fc63 100644 --- a/tests/core/pyspec/eth2spec/test/eip7002/block_processing/test_process_execution_layer_exit.py +++ b/tests/core/pyspec/eth2spec/test/eip7002/block_processing/test_process_execution_layer_exit.py @@ -40,3 +40,48 @@ def test_incorrect_source_address(spec, state): ) yield from run_execution_layer_exit_processing(spec, state, execution_layer_exit, success=False) + + +@with_eip7002_and_later +@spec_state_test +def test_incorrect_withdrawal_credential_prefix(spec, state): + # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit + state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH + + current_epoch = spec.get_current_epoch(state) + validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_pubkey = state.validators[validator_index].pubkey + address = b'\x22' * 20 + set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, address=address) + # Set incorrect prefix + state.validators[validator_index].withdrawal_credentials = ( + spec.BLS_WITHDRAWAL_PREFIX + + state.validators[validator_index].withdrawal_credentials[1:] + ) + execution_layer_exit = spec.ExecutionLayerExit( + source_address=address, + validator_pubkey=validator_pubkey, + ) + + yield from run_execution_layer_exit_processing(spec, state, execution_layer_exit, success=False) + + +@with_eip7002_and_later +@spec_state_test +def test_on_exit_initiated_validator(spec, state): + # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit + state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH + + current_epoch = spec.get_current_epoch(state) + validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_pubkey = state.validators[validator_index].pubkey + address = b'\x22' * 20 + set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, address=address) + # Initiate exit earlier + spec.initiate_validator_exit(state, validator_index) + execution_layer_exit = spec.ExecutionLayerExit( + source_address=address, + validator_pubkey=validator_pubkey, + ) + + yield from run_execution_layer_exit_processing(spec, state, execution_layer_exit, success=False) diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_layer_exits.py b/tests/core/pyspec/eth2spec/test/helpers/execution_layer_exits.py index 1a23f068d..e0dda75d1 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_layer_exits.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_layer_exits.py @@ -14,6 +14,7 @@ def run_execution_layer_exit_processing(spec, state, execution_layer_exit, valid - execution_layer_exit ('execution_layer_exit') - post-state ('post'). If ``valid == False``, run expecting ``AssertionError`` + If ``success == False``, it doesn't initiate exit successfully """ validator_index = get_validator_index_by_pubkey(state, execution_layer_exit.validator_pubkey) diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_transition.py b/tests/core/pyspec/eth2spec/test/helpers/fork_transition.py index c3bff021f..00f2d9994 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_transition.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_transition.py @@ -162,6 +162,8 @@ def do_fork(state, spec, post_spec, fork_epoch, with_block=True, sync_aggregate= state = post_spec.upgrade_to_deneb(state) elif post_spec.fork == EIP6110: state = post_spec.upgrade_to_eip6110(state) + elif post_spec.fork == EIP7002: + state = post_spec.upgrade_to_eip7002(state) assert state.fork.epoch == fork_epoch