From f0eb3b9a5c6889e2fb9f8fdca8f85439bdfc36ed Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sat, 6 Apr 2024 14:21:36 -0600 Subject: [PATCH] add EIP-7251 `initialize_beacon_state_from_eth1` function --- specs/_features/eip7251/beacon-chain.md | 59 +++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/specs/_features/eip7251/beacon-chain.md b/specs/_features/eip7251/beacon-chain.md index 583b16d2ee..8563843ba6 100644 --- a/specs/_features/eip7251/beacon-chain.md +++ b/specs/_features/eip7251/beacon-chain.md @@ -77,6 +77,7 @@ - [New `process_consolidation`](#new-process_consolidation) - [Voluntary exits](#voluntary-exits) - [Updated `process_voluntary_exit`](#updated-process_voluntary_exit) +- [Testing](#testing) @@ -1063,3 +1064,61 @@ def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVolu # Initiate exit initiate_validator_exit(state, voluntary_exit.validator_index) ``` + +## Testing + +*Note*: The function `initialize_beacon_state_from_eth1` is modified for pure EIP-7251 testing only. + +```python +def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32, + eth1_timestamp: uint64, + deposits: Sequence[Deposit], + execution_payload_header: ExecutionPayloadHeader=ExecutionPayloadHeader() + ) -> BeaconState: + fork = Fork( + previous_version=EIP7251_FORK_VERSION, # [Modified in EIP-7251] for testing only + current_version=EIP7251_FORK_VERSION, # [Modified in EIP-7251] + epoch=GENESIS_EPOCH, + ) + state = BeaconState( + genesis_time=eth1_timestamp + GENESIS_DELAY, + fork=fork, + eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))), + latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())), + randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy + ) + + # Process deposits + leaves = list(map(lambda deposit: deposit.data, deposits)) + for index, deposit in enumerate(deposits): + deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1]) + state.eth1_data.deposit_root = hash_tree_root(deposit_data_list) + process_deposit(state, deposit) + + # Process deposit balance updates + for deposit in state.pending_balance_deposits: + increase_balance(state, deposit.index, deposit.amount) + state.pending_balance_deposits = [] + + # Process activations + for index, validator in enumerate(state.validators): + balance = state.balances[index] + validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE) + if validator.effective_balance == MAX_EFFECTIVE_BALANCE: + validator.activation_eligibility_epoch = GENESIS_EPOCH + validator.activation_epoch = GENESIS_EPOCH + + # Set genesis validators root for domain separation and chain versioning + state.genesis_validators_root = hash_tree_root(state.validators) + + # Fill in sync committees + # Note: A duplicate committee is assigned for the current and next committee at genesis + state.current_sync_committee = get_next_sync_committee(state) + state.next_sync_committee = get_next_sync_committee(state) + + # Initialize the execution payload header + # If empty, will initialize a chain that has not yet gone through the Merge transition + state.latest_execution_payload_header = execution_payload_header + + return state +```