Skip to content

Commit 0de1252

Browse files
authored
Merge pull request #3775 from fradamt/EL-consolidations
EL-triggered consolidations
2 parents 50972f9 + 143b9e6 commit 0de1252

File tree

10 files changed

+887
-934
lines changed

10 files changed

+887
-934
lines changed

presets/mainnet/electra.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ MAX_ATTESTER_SLASHINGS_ELECTRA: 1
3030
# `uint64(2**3)` (= 8)
3131
MAX_ATTESTATIONS_ELECTRA: 8
3232
# `uint64(2**0)` (= 1)
33-
MAX_CONSOLIDATIONS: 1
33+
MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: 1
3434

3535
# Execution
3636
# ---------------------------------------------------------------

presets/minimal/electra.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ MAX_ATTESTER_SLASHINGS_ELECTRA: 1
3030
# `uint64(2**3)` (= 8)
3131
MAX_ATTESTATIONS_ELECTRA: 8
3232
# `uint64(2**0)` (= 1)
33-
MAX_CONSOLIDATIONS: 1
33+
MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: 1
3434

3535
# Execution
3636
# ---------------------------------------------------------------

specs/electra/beacon-chain.md

Lines changed: 68 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@
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)
@@ -95,8 +94,8 @@
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

specs/electra/fork.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ def upgrade_to_electra(pre: deneb.BeaconState) -> BeaconState:
9191
blob_gas_used=pre.latest_execution_payload_header.blob_gas_used,
9292
excess_blob_gas=pre.latest_execution_payload_header.excess_blob_gas,
9393
deposit_receipts_root=Root(), # [New in Electra:EIP6110]
94-
withdrawal_requests_root=Root(), # [New in Electra:EIP7002],
94+
withdrawal_requests_root=Root(), # [New in Electra:EIP7002]
95+
consolidation_requests_root=Root(), # [New in Electra:EIP7251]
9596
)
9697

9798
exit_epochs = [v.exit_epoch for v in pre.validators if v.exit_epoch != FAR_FUTURE_EPOCH]

0 commit comments

Comments
 (0)