2828 - [ ` PendingBalanceDeposit ` ] ( #pendingbalancedeposit )
2929 - [ ` PendingPartialWithdrawal ` ] ( #pendingpartialwithdrawal )
3030 - [ ` ExecutionLayerWithdrawalRequest ` ] ( #executionlayerwithdrawalrequest )
31- - [ ` Consolidation ` ] ( #consolidation )
32- - [ ` SignedConsolidation ` ] ( #signedconsolidation )
31+ - [ ` ExecutionLayerConsolidationRequest ` ] ( #executionlayerconsolidationrequest )
3332 - [ ` PendingConsolidation ` ] ( #pendingconsolidation )
3433 - [ Modified Containers] ( #modified-containers )
3534 - [ ` AttesterSlashing ` ] ( #attesterslashing )
9594 - [ New ` process_execution_layer_withdrawal_request ` ] ( #new-process_execution_layer_withdrawal_request )
9695 - [ Deposit receipts] ( #deposit-receipts )
9796 - [ New ` process_deposit_receipt ` ] ( #new-process_deposit_receipt )
98- - [ Consolidations ] ( #consolidations )
99- - [ New ` process_consolidation ` ] ( #new-process_consolidation )
97+ - [ Execution layer consolidation requests ] ( #execution-layer-consolidation-requests )
98+ - [ New ` process_execution_layer_consolidation_request ` ] ( #new-process_execution_layer_consolidation_request )
10099- [ Testing] ( #testing )
101100
102101<!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -165,16 +164,16 @@ The following values are (non-configurable) constants used throughout the specif
165164
166165| Name | Value |
167166| - | - |
168- | ` MAX_CONSOLIDATIONS ` | ` uint64(1) ` |
167+ | ` MAX_ATTESTER_SLASHINGS_ELECTRA ` | ` 2**0 ` (= 1) | * [ New in Electra: EIP7549 ] * |
168+ | ` MAX_ATTESTATIONS_ELECTRA ` | ` 2**3 ` (= 8) | * [ New in Electra: EIP7549 ] * |
169169
170170### Execution
171171
172172| Name | Value | Description |
173173| - | - | - |
174174| ` MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD ` | ` uint64(2**13) ` (= 8,192) | * [ New in Electra: EIP6110 ] * Maximum number of deposit receipts allowed in each payload |
175- | ` MAX_ATTESTER_SLASHINGS_ELECTRA ` | ` 2**0 ` (= 1) | * [ New in Electra: EIP7549 ] * |
176- | ` MAX_ATTESTATIONS_ELECTRA ` | ` 2**3 ` (= 8) | * [ New in Electra: EIP7549 ] * |
177175| ` MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD ` | ` uint64(2**4) ` (= 16)| * [ New in Electra: EIP7002 ] * Maximum number of execution layer withdrawal requests in each payload |
176+ | ` MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD ` | ` uint64(1) ` (= 1) | * [ New in Electra: EIP7002 ] * Maximum number of execution layer consolidation requests in each payload |
178177
179178### Withdrawals processing
180179
@@ -239,25 +238,15 @@ class ExecutionLayerWithdrawalRequest(Container):
239238 amount: Gwei
240239```
241240
242- #### ` Consolidation `
243-
244- * Note* : The container is new in EIP7251.
245-
246- ``` python
247- class Consolidation (Container ):
248- source_index: ValidatorIndex
249- target_index: ValidatorIndex
250- epoch: Epoch
251- ```
252-
253- #### ` SignedConsolidation `
241+ #### ` ExecutionLayerConsolidationRequest `
254242
255243* Note* : The container is new in EIP7251.
256244
257245``` python
258- class SignedConsolidation (Container ):
259- message: Consolidation
260- signature: BLSSignature
246+ class ExecutionLayerConsolidationRequest (Container ):
247+ source_address: ExecutionAddress
248+ source_pubkey: BLSPubkey
249+ target_pubkey: BLSPubkey
261250```
262251
263252#### ` PendingConsolidation `
@@ -320,7 +309,6 @@ class BeaconBlockBody(Container):
320309 execution_payload: ExecutionPayload # [Modified in Electra:EIP6110:EIP7002]
321310 bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES ]
322311 blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK ]
323- consolidations: List[SignedConsolidation, MAX_CONSOLIDATIONS ] # [New in Electra:EIP7251]
324312```
325313
326314#### ` ExecutionPayload `
@@ -349,6 +337,8 @@ class ExecutionPayload(Container):
349337 deposit_receipts: List[DepositReceipt, MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD ] # [New in Electra:EIP6110]
350338 # [New in Electra:EIP7002:EIP7251]
351339 withdrawal_requests: List[ExecutionLayerWithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD ]
340+ # [New in Electra:EIP7251]
341+ consolidation_requests: List[ExecutionLayerConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD ]
352342```
353343
354344#### ` ExecutionPayloadHeader `
@@ -376,6 +366,7 @@ class ExecutionPayloadHeader(Container):
376366 excess_blob_gas: uint64
377367 deposit_receipts_root: Root # [New in Electra:EIP6110]
378368 withdrawal_requests_root: Root # [New in Electra:EIP7002:EIP7251]
369+ consolidation_requests_root: Root # [New in Electra:EIP7251]
379370```
380371
381372#### ` BeaconState `
@@ -1035,6 +1026,7 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody, executi
10351026 excess_blob_gas = payload.excess_blob_gas,
10361027 deposit_receipts_root = hash_tree_root(payload.deposit_receipts), # [New in Electra:EIP6110]
10371028 withdrawal_requests_root = hash_tree_root(payload.withdrawal_requests), # [New in Electra:EIP7002:EIP7251]
1029+ consolidation_requests_root = hash_tree_root(payload.consolidation_requests), # [New in Electra:EIP7251]
10381030 )
10391031```
10401032
@@ -1064,10 +1056,11 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
10641056 for_ops(body.deposits, process_deposit) # [Modified in Electra:EIP7251]
10651057 for_ops(body.voluntary_exits, process_voluntary_exit) # [Modified in Electra:EIP7251]
10661058 for_ops(body.bls_to_execution_changes, process_bls_to_execution_change)
1059+ for_ops(body.execution_payload.deposit_receipts, process_deposit_receipt) # [New in Electra:EIP6110]
10671060 # [New in Electra:EIP7002:EIP7251]
10681061 for_ops(body.execution_payload.withdrawal_requests, process_execution_layer_withdrawal_request)
1069- for_ops(body.execution_payload.deposit_receipts, process_deposit_receipt) # [New in Electra:EIP6110 ]
1070- for_ops(body.consolidations, process_consolidation) # [New in Electra:EIP7251]
1062+ # [New in Electra:EIP7251 ]
1063+ for_ops(body.execution_payload.consolidation_requests, process_execution_layer_consolidation_request)
10711064```
10721065
10731066##### Attestations
@@ -1314,43 +1307,62 @@ def process_deposit_receipt(state: BeaconState, deposit_receipt: DepositReceipt)
13141307 )
13151308```
13161309
1317- ##### Consolidations
1310+ ##### Execution layer consolidation requests
13181311
1319- ###### New ` process_consolidation `
1312+ ###### New ` process_execution_layer_consolidation_request `
13201313
13211314``` python
1322- def process_consolidation (state : BeaconState, signed_consolidation : SignedConsolidation) -> None :
1323- # If the pending consolidations queue is full, no consolidations are allowed in the block
1324- assert len (state.pending_consolidations) < PENDING_CONSOLIDATIONS_LIMIT
1325- # If there is too little available consolidation churn limit, no consolidations are allowed in the block
1326- assert get_consolidation_churn_limit(state) > MIN_ACTIVATION_BALANCE
1327- consolidation = signed_consolidation.message
1315+ def process_execution_layer_consolidation_request (
1316+ state : BeaconState,
1317+ execution_layer_consolidation_request : ExecutionLayerConsolidationRequest
1318+ ) -> None :
1319+ # If the pending consolidations queue is full, consolidation requests are ignored
1320+ if len (state.pending_consolidations) == PENDING_CONSOLIDATIONS_LIMIT :
1321+ return
1322+ # If there is too little available consolidation churn limit, consolidation requests are ignored
1323+ if get_consolidation_churn_limit(state) <= MIN_ACTIVATION_BALANCE :
1324+ return
1325+
1326+ validator_pubkeys = [v.pubkey for v in state.validators]
1327+ # Verify pubkeys exists
1328+ request_source_pubkey = execution_layer_consolidation_request.source_pubkey
1329+ request_target_pubkey = execution_layer_consolidation_request.target_pubkey
1330+ if request_source_pubkey not in validator_pubkeys:
1331+ return
1332+ if request_target_pubkey not in validator_pubkeys:
1333+ return
1334+ source_index = ValidatorIndex(validator_pubkeys.index(request_source_pubkey))
1335+ target_index = ValidatorIndex(validator_pubkeys.index(request_target_pubkey))
1336+ source_validator = state.validators[source_index]
1337+ target_validator = state.validators[target_index]
1338+
13281339 # Verify that source != target, so a consolidation cannot be used as an exit.
1329- assert consolidation.source_index != consolidation.target_index
1340+ if source_index == target_index:
1341+ return
1342+
1343+ # Verify source withdrawal credentials
1344+ has_correct_credential = has_execution_withdrawal_credential(source_validator)
1345+ is_correct_source_address = (
1346+ source_validator.withdrawal_credentials[12 :] == execution_layer_consolidation_request.source_address
1347+ )
1348+ if not (has_correct_credential and is_correct_source_address):
1349+ return
1350+
1351+ # Verify that target has execution withdrawal credentials
1352+ if not has_execution_withdrawal_credential(target_validator):
1353+ return
13301354
1331- source_validator = state.validators[consolidation.source_index]
1332- target_validator = state.validators[consolidation.target_index]
13331355 # Verify the source and the target are active
13341356 current_epoch = get_current_epoch(state)
1335- assert is_active_validator(source_validator, current_epoch)
1336- assert is_active_validator(target_validator, current_epoch)
1357+ if not is_active_validator(source_validator, current_epoch):
1358+ return
1359+ if not is_active_validator(target_validator, current_epoch):
1360+ return
13371361 # Verify exits for source and target have not been initiated
1338- assert source_validator.exit_epoch == FAR_FUTURE_EPOCH
1339- assert target_validator.exit_epoch == FAR_FUTURE_EPOCH
1340- # Consolidations must specify an epoch when they become valid; they are not valid before then
1341- assert current_epoch >= consolidation.epoch
1342-
1343- # Verify the source and the target have Execution layer withdrawal credentials
1344- assert has_execution_withdrawal_credential(source_validator)
1345- assert has_execution_withdrawal_credential(target_validator)
1346- # Verify the same withdrawal address
1347- assert source_validator.withdrawal_credentials[12 :] == target_validator.withdrawal_credentials[12 :]
1348-
1349- # Verify consolidation is signed by the source and the target
1350- domain = compute_domain(DOMAIN_CONSOLIDATION , genesis_validators_root = state.genesis_validators_root)
1351- signing_root = compute_signing_root(consolidation, domain)
1352- pubkeys = [source_validator.pubkey, target_validator.pubkey]
1353- assert bls.FastAggregateVerify(pubkeys, signing_root, signed_consolidation.signature)
1362+ if source_validator.exit_epoch != FAR_FUTURE_EPOCH :
1363+ return
1364+ if target_validator.exit_epoch != FAR_FUTURE_EPOCH :
1365+ return
13541366
13551367 # Initiate source validator exit and append pending consolidation
13561368 source_validator.exit_epoch = compute_consolidation_epoch_and_update_churn(
@@ -1360,8 +1372,8 @@ def process_consolidation(state: BeaconState, signed_consolidation: SignedConsol
13601372 source_validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY
13611373 )
13621374 state.pending_consolidations.append(PendingConsolidation(
1363- source_index = consolidation. source_index,
1364- target_index = consolidation. target_index
1375+ source_index = source_index,
1376+ target_index = target_index
13651377 ))
13661378```
13671379
0 commit comments