3030 - [ Extended Containers] ( #extended-containers )
3131 - [ ` BeaconState ` ] ( #beaconstate )
3232 - [ ` BeaconBlockBody ` ] ( #beaconblockbody )
33+ - [ ` ExecutionPayload ` ] ( #executionpayload )
34+ - [ ` ExecutionPayloadHeader ` ] ( #executionpayloadheader )
3335- [ Helpers] ( #helpers )
3436 - [ Predicates] ( #predicates )
3537 - [ Updated ` is_eligible_for_activation_queue ` ] ( #updated-is_eligible_for_activation_queue )
7577 - [ New ` process_consolidation ` ] ( #new-process_consolidation )
7678 - [ Voluntary exits] ( #voluntary-exits )
7779 - [ Updated ` process_voluntary_exit ` ] ( #updated-process_voluntary_exit )
80+ - [ Testing] ( #testing )
7881
7982<!-- END doctoc generated TOC please keep comment here to allow auto update -->
8083<!-- /TOC -->
8184
8285## Introduction
8386
84- See [ a modest proposal] ( https://notes.ethereum.org/@mikeneuder/increase-maxeb ) , the [ diff view] ( https://github.com/michaelneuder/consensus-specs/pull/3/files ) and
87+ See [ a modest proposal] ( https://notes.ethereum.org/@mikeneuder/increase-maxeb ) , the [ diff view] ( https://github.com/michaelneuder/consensus-specs/pull/3/files ) and
8588[ security considerations] ( https://notes.ethereum.org/@fradamt/meb-increase-security ) .
8689
8790* Note:* This specification is built upon [ Deneb] ( ../../deneb/beacon-chain.md ) .
@@ -136,6 +139,7 @@ The following values are (non-configurable) constants used throughout the specif
136139
137140| Name | Value | Description |
138141| - | - | - |
142+ | ` MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD ` | ` uint64(16) ` |
139143| ` MAX_PARTIAL_WITHDRAWALS_PER_PAYLOAD ` | ` uint64(2**3) ` (= 8) | Maximum amount of partial withdrawals allowed in each payload |
140144
141145### State list lengths
@@ -282,12 +286,64 @@ class BeaconBlockBody(Container):
282286 voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS ]
283287 sync_aggregate: SyncAggregate
284288 # Execution
285- execution_payload: ExecutionPayload
289+ execution_payload: ExecutionPayload
286290 bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES ]
287291 blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK ]
288292 consolidations: List[SignedConsolidation, MAX_CONSOLIDATIONS ] # [New in EIP-7251]
289293```
290294
295+ #### ` ExecutionPayload `
296+
297+ ``` python
298+ class ExecutionPayload (Container ):
299+ # Execution block header fields
300+ parent_hash: Hash32
301+ fee_recipient: ExecutionAddress # 'beneficiary' in the yellow paper
302+ state_root: Bytes32
303+ receipts_root: Bytes32
304+ logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM ]
305+ prev_randao: Bytes32 # 'difficulty' in the yellow paper
306+ block_number: uint64 # 'number' in the yellow paper
307+ gas_limit: uint64
308+ gas_used: uint64
309+ timestamp: uint64
310+ extra_data: ByteList[MAX_EXTRA_DATA_BYTES ]
311+ base_fee_per_gas: uint256
312+ # Extra payload fields
313+ block_hash: Hash32 # Hash of execution block
314+ transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD ]
315+ withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD ]
316+ blob_gas_used: uint64
317+ excess_blob_gas: uint64
318+ withdraw_requests: List[ExecutionLayerWithdrawRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD ] # [New in EIP-7251]
319+ ```
320+
321+ #### ` ExecutionPayloadHeader `
322+
323+ ``` python
324+ class ExecutionPayloadHeader (Container ):
325+ # Execution block header fields
326+ parent_hash: Hash32
327+ fee_recipient: ExecutionAddress
328+ state_root: Bytes32
329+ receipts_root: Bytes32
330+ logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM ]
331+ prev_randao: Bytes32
332+ block_number: uint64
333+ gas_limit: uint64
334+ gas_used: uint64
335+ timestamp: uint64
336+ extra_data: ByteList[MAX_EXTRA_DATA_BYTES ]
337+ base_fee_per_gas: uint256
338+ # Extra payload fields
339+ block_hash: Hash32 # Hash of execution block
340+ transactions_root: Root
341+ withdrawals_root: Root
342+ blob_gas_used: uint64
343+ excess_blob_gas: uint64
344+ withdraw_requests_root: Root # [New in EIP-7251]
345+ ```
346+
291347## Helpers
292348
293349### Predicates
@@ -386,7 +442,7 @@ def get_churn_limit(state: BeaconState) -> Gwei:
386442 Return the churn limit for the current epoch.
387443 """
388444 churn = max (
389- MIN_PER_EPOCH_CHURN_LIMIT_EIP7251 ,
445+ MIN_PER_EPOCH_CHURN_LIMIT_EIP7251 ,
390446 get_total_active_balance(state) // CHURN_LIMIT_QUOTIENT
391447 )
392448 return churn - churn % EFFECTIVE_BALANCE_INCREMENT
@@ -472,7 +528,6 @@ def queue_excess_active_balance(state: BeaconState, index: ValidatorIndex) -> No
472528
473529#### New ` compute_exit_epoch_and_update_churn `
474530
475-
476531``` python
477532def compute_exit_epoch_and_update_churn (state : BeaconState, exit_balance : Gwei) -> Epoch:
478533 earliest_exit_epoch = compute_activation_exit_epoch(get_current_epoch(state))
@@ -566,16 +621,23 @@ def process_epoch(state: BeaconState) -> None:
566621 process_effective_balance_updates(state) # [Modified in EIP7251]
567622 process_slashings_reset(state)
568623 process_randao_mixes_reset(state)
624+ process_historical_summaries_update(state)
625+ process_participation_flag_updates(state)
626+ process_sync_committee_updates(state)
569627```
570628
571629#### Updated ` process_registry_updates `
572630
631+ ` process_registry_updates ` uses the updated definition of ` initiate_validator_exit `
632+ and changes how the activation epochs are computed for eligible validators.
633+
573634``` python
574635def process_registry_updates (state : BeaconState) -> None :
575636 # Process activation eligibility and ejections
576637 for index, validator in enumerate (state.validators):
577638 if is_eligible_for_activation_queue(validator):
578639 validator.activation_eligibility_epoch = get_current_epoch(state) + 1
640+
579641 if (
580642 is_active_validator(validator, get_current_epoch(state))
581643 and validator.effective_balance <= EJECTION_BALANCE
@@ -607,7 +669,7 @@ def process_pending_balance_deposits(state: BeaconState) -> None:
607669 state.pending_balance_deposits = state.pending_balance_deposits[next_deposit_index:]
608670
609671 if len (state.pending_balance_deposits) == 0 :
610- state.deposit_balance_to_consume = 0
672+ state.deposit_balance_to_consume = Gwei( 0 )
611673 else :
612674 state.deposit_balance_to_consume = available_for_processing - processed_amount
613675```
@@ -638,6 +700,8 @@ def process_pending_consolidations(state: BeaconState) -> None:
638700
639701#### Updated ` process_effective_balance_updates `
640702
703+ ` process_effective_balance_updates ` is updated with a new limit for the maximum effective balance.
704+
641705``` python
642706def process_effective_balance_updates (state : BeaconState) -> None :
643707 # Update effective balances with hysteresis
@@ -760,7 +824,7 @@ def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
760824 state.next_withdrawal_validator_index = next_validator_index
761825```
762826
763- #### Operations
827+ #### Operations
764828
765829##### Updated ` process_operations `
766830
@@ -779,14 +843,16 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
779843 for_ops(body.deposits, process_deposit) # [Modified in EIP7251]
780844 for_ops(body.voluntary_exits, process_voluntary_exit) # [Modified in EIP7251]
781845 for_ops(body.bls_to_execution_changes, process_bls_to_execution_change)
782- for_ops(body.execution_payload.withdraw_requests, process_execution_layer_withdraw_request) # New in EIP7251
783- for_ops(body.consolidations, process_consolidation) # New in EIP7251
846+ for_ops(body.execution_payload.withdraw_requests, process_execution_layer_withdraw_request) # [ New in EIP7251]
847+ for_ops(body.consolidations, process_consolidation) # [ New in EIP7251]
784848```
785849
786850##### Deposits
787851
788852###### Updated ` apply_deposit `
789853
854+ * NOTE* : ` process_deposit ` is updated with a new definition of ` apply_deposit ` .
855+
790856``` python
791857def apply_deposit (state : BeaconState,
792858 pubkey : BLSPubkey,
@@ -819,7 +885,7 @@ def apply_deposit(state: BeaconState,
819885def is_valid_deposit_signature (pubkey : BLSPubkey,
820886 withdrawal_credentials : Bytes32,
821887 amount : uint64,
822- signature : BLSSignature) -> None :
888+ signature : BLSSignature) -> bool :
823889 deposit_message = DepositMessage(
824890 pubkey = pubkey,
825891 withdrawal_credentials = withdrawal_credentials,
@@ -862,7 +928,7 @@ def get_validator_from_deposit(pubkey: BLSPubkey, withdrawal_credentials: Bytes3
862928 )
863929```
864930
865- ##### Withdrawals
931+ ##### Withdrawals
866932
867933###### New ` process_execution_layer_withdraw_request `
868934
@@ -874,7 +940,7 @@ def process_execution_layer_withdraw_request(
874940 amount = execution_layer_withdraw_request.amount
875941 is_full_exit_request = amount == FULL_EXIT_REQUEST_AMOUNT
876942
877- # If partial withdrawal queue is full, only full exits are processed
943+ # If partial withdrawal queue is full, only full exits are processed
878944 if len (state.pending_partial_withdrawals) >= PENDING_PARTIAL_WITHDRAWALS_LIMIT and not is_full_exit_request:
879945 return
880946
@@ -947,7 +1013,7 @@ def process_consolidation(state: BeaconState, signed_consolidation: SignedConsol
9471013 assert source_validator.exit_epoch == FAR_FUTURE_EPOCH
9481014 assert target_validator.exit_epoch == FAR_FUTURE_EPOCH
9491015 # Consolidations must specify an epoch when they become valid; they are not valid before then
950- assert current_epoch >= consolidation.epoch
1016+ assert current_epoch >= consolidation.epoch
9511017
9521018 # Verify the source and the target have Execution layer withdrawal credentials
9531019 assert has_execution_withdrawal_credential(source_validator)
@@ -989,12 +1055,70 @@ def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVolu
9891055 assert get_current_epoch(state) >= voluntary_exit.epoch
9901056 # Verify the validator has been active long enough
9911057 assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
1058+ # Only exit validator if it has no pending withdrawals in the queue
1059+ assert get_pending_balance_to_withdraw(state, voluntary_exit.validator_index) == 0 # [New in EIP7251]
9921060 # Verify signature
993- domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT , voluntary_exit.epoch )
1061+ domain = compute_domain( DOMAIN_VOLUNTARY_EXIT , CAPELLA_FORK_VERSION , state.genesis_validators_root )
9941062 signing_root = compute_signing_root(voluntary_exit, domain)
9951063 assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature)
996- # Only exit validator if it has no pending withdrawals in the queue
997- assert get_pending_balance_to_withdraw(state, voluntary_exit.validator_index) == 0 # [New in EIP7251]
9981064 # Initiate exit
9991065 initiate_validator_exit(state, voluntary_exit.validator_index)
10001066```
1067+
1068+ ## Testing
1069+
1070+ * Note* : The function ` initialize_beacon_state_from_eth1 ` is modified for pure EIP-7251 testing only.
1071+
1072+ ``` python
1073+ def initialize_beacon_state_from_eth1 (eth1_block_hash : Hash32,
1074+ eth1_timestamp : uint64,
1075+ deposits : Sequence[Deposit],
1076+ execution_payload_header : ExecutionPayloadHeader= ExecutionPayloadHeader()
1077+ ) -> BeaconState:
1078+ fork = Fork(
1079+ previous_version = EIP7251_FORK_VERSION , # [Modified in EIP-7251] for testing only
1080+ current_version = EIP7251_FORK_VERSION , # [Modified in EIP-7251]
1081+ epoch = GENESIS_EPOCH ,
1082+ )
1083+ state = BeaconState(
1084+ genesis_time = eth1_timestamp + GENESIS_DELAY ,
1085+ fork = fork,
1086+ eth1_data = Eth1Data(block_hash = eth1_block_hash, deposit_count = uint64(len (deposits))),
1087+ latest_block_header = BeaconBlockHeader(body_root = hash_tree_root(BeaconBlockBody())),
1088+ randao_mixes = [eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR , # Seed RANDAO with Eth1 entropy
1089+ )
1090+
1091+ # Process deposits
1092+ leaves = list (map (lambda deposit : deposit.data, deposits))
1093+ for index, deposit in enumerate (deposits):
1094+ deposit_data_list = List[DepositData, 2 ** DEPOSIT_CONTRACT_TREE_DEPTH ](* leaves[:index + 1 ])
1095+ state.eth1_data.deposit_root = hash_tree_root(deposit_data_list)
1096+ process_deposit(state, deposit)
1097+
1098+ # Process deposit balance updates
1099+ for deposit in state.pending_balance_deposits:
1100+ increase_balance(state, deposit.index, deposit.amount)
1101+ state.pending_balance_deposits = []
1102+
1103+ # Process activations
1104+ for index, validator in enumerate (state.validators):
1105+ balance = state.balances[index]
1106+ validator.effective_balance = min (balance - balance % EFFECTIVE_BALANCE_INCREMENT , MAX_EFFECTIVE_BALANCE )
1107+ if validator.effective_balance == MAX_EFFECTIVE_BALANCE :
1108+ validator.activation_eligibility_epoch = GENESIS_EPOCH
1109+ validator.activation_epoch = GENESIS_EPOCH
1110+
1111+ # Set genesis validators root for domain separation and chain versioning
1112+ state.genesis_validators_root = hash_tree_root(state.validators)
1113+
1114+ # Fill in sync committees
1115+ # Note: A duplicate committee is assigned for the current and next committee at genesis
1116+ state.current_sync_committee = get_next_sync_committee(state)
1117+ state.next_sync_committee = get_next_sync_committee(state)
1118+
1119+ # Initialize the execution payload header
1120+ # If empty, will initialize a chain that has not yet gone through the Merge transition
1121+ state.latest_execution_payload_header = execution_payload_header
1122+
1123+ return state
1124+ ```
0 commit comments