diff --git a/pysetup/spec_builders/electra.py b/pysetup/spec_builders/electra.py index 2ab1f5ecfb..859cf6d4ec 100644 --- a/pysetup/spec_builders/electra.py +++ b/pysetup/spec_builders/electra.py @@ -10,6 +10,7 @@ class ElectraSpecBuilder(BaseSpecBuilder): def imports(cls, preset_name: str): return f''' from eth2spec.deneb import {preset_name} as deneb +from eth2spec.utils.ssz.ssz_impl import serialize ''' @classmethod @@ -28,7 +29,6 @@ class NoopExecutionEngine(ExecutionEngine): def notify_new_payload(self: ExecutionEngine, execution_payload: ExecutionPayload, - execution_requests: ExecutionRequests, parent_beacon_block_root: Root) -> bool: return True @@ -45,7 +45,8 @@ def get_payload(self: ExecutionEngine, payload_id: PayloadId) -> GetPayloadRespo def is_valid_block_hash(self: ExecutionEngine, execution_payload: ExecutionPayload, - parent_beacon_block_root: Root) -> bool: + parent_beacon_block_root: Root, + execution_requests_hash: Hash32) -> bool: return True def is_valid_versioned_hashes(self: ExecutionEngine, new_payload_request: NewPayloadRequest) -> bool: diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index c231e718e7..9dfd3ec4a4 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -12,6 +12,7 @@ - [Constants](#constants) - [Misc](#misc) - [Withdrawal prefixes](#withdrawal-prefixes) + - [Execution layer triggered requests](#execution-layer-triggered-requests) - [Preset](#preset) - [Gwei values](#gwei-values) - [Rewards and penalties](#rewards-and-penalties) @@ -77,13 +78,14 @@ - [Request data](#request-data) - [Modified `NewPayloadRequest`](#modified-newpayloadrequest) - [Engine APIs](#engine-apis) - - [Modified `notify_new_payload`](#modified-notify_new_payload) + - [Modified `is_valid_block_hash`](#modified-is_valid_block_hash) - [Modified `verify_and_notify_new_payload`](#modified-verify_and_notify_new_payload) - [Block processing](#block-processing) - [Withdrawals](#withdrawals) - [Modified `get_expected_withdrawals`](#modified-get_expected_withdrawals) - [Modified `process_withdrawals`](#modified-process_withdrawals) - [Execution payload](#execution-payload) + - [New `compute_execution_requests_hash`](#new-compute_execution_requests_hash) - [Modified `process_execution_payload`](#modified-process_execution_payload) - [Operations](#operations) - [Modified `process_operations`](#modified-process_operations) @@ -136,6 +138,14 @@ The following values are (non-configurable) constants used throughout the specif | - | - | | `COMPOUNDING_WITHDRAWAL_PREFIX` | `Bytes1('0x02')` | +### Execution layer triggered requests + +| Name | Value | +| - | - | +| `DEPOSIT_REQUEST_TYPE` | `Bytes1('0x00')` | +| `WITHDRAWAL_REQUEST_TYPE` | `Bytes1('0x01')` | +| `CONSOLIDATION_REQUEST_TYPE` | `Bytes1('0x02')` | + ## Preset ### Gwei values @@ -978,23 +988,22 @@ class NewPayloadRequest(object): execution_payload: ExecutionPayload versioned_hashes: Sequence[VersionedHash] parent_beacon_block_root: Root - execution_requests: ExecutionRequests # [New in Electra] + execution_requests: ExecutionRequests # [New in Electra:EIP7685] ``` #### Engine APIs -##### Modified `notify_new_payload` +##### Modified `is_valid_block_hash` -*Note*: The function `notify_new_payload` is modified to include the additional `execution_requests` parameter in Electra. +*Note*: The function `is_valid_block_hash` is modified to include the additional `execution_requests_hash` parameter for EIP-7685. ```python -def notify_new_payload(self: ExecutionEngine, - execution_payload: ExecutionPayload, - execution_requests: ExecutionRequests, - parent_beacon_block_root: Root) -> bool: +def is_valid_block_hash(self: ExecutionEngine, + execution_payload: ExecutionPayload, + parent_beacon_block_root: Root, + execution_requests_hash: Hash32) -> bool: """ - Return ``True`` if and only if ``execution_payload`` and ``execution_requests`` - are valid with respect to ``self.execution_state``. + Return ``True`` if and only if ``execution_payload.block_hash`` is computed correctly. """ ... ``` @@ -1011,19 +1020,22 @@ def verify_and_notify_new_payload(self: ExecutionEngine, Return ``True`` if and only if ``new_payload_request`` is valid with respect to ``self.execution_state``. """ execution_payload = new_payload_request.execution_payload - execution_requests = new_payload_request.execution_requests # [New in Electra] parent_beacon_block_root = new_payload_request.parent_beacon_block_root - - if not self.is_valid_block_hash(execution_payload, parent_beacon_block_root): + # [New in Electra] + execution_requests_hash = compute_execution_requests_hash(new_payload_request.execution_requests) + + # [Modified in Electra:EIP7685] + if not self.is_valid_block_hash( + execution_payload, + parent_beacon_block_root, + execution_requests_hash): return False if not self.is_valid_versioned_hashes(new_payload_request): return False - # [Modified in Electra] if not self.notify_new_payload( - execution_payload, - execution_requests, + execution_payload, parent_beacon_block_root): return False @@ -1139,6 +1151,20 @@ def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None: #### Execution payload +##### New `compute_execution_requests_hash` + +*Note*: Computes commitment to the execution layer triggered requests data. +The computation algorithm is defined by [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685). + +```python +def compute_execution_requests_hash(execution_requests: ExecutionRequests) -> Hash32: + deposit_requests = DEPOSIT_REQUEST_TYPE + serialize(execution_requests.deposits) + withdrawal_requests = WITHDRAWAL_REQUEST_TYPE + serialize(execution_requests.withdrawals) + consolidation_requests = CONSOLIDATION_REQUEST_TYPE + serialize(execution_requests.consolidations) + + return hash(hash(deposit_requests) + hash(withdrawal_requests) + hash(consolidation_requests)) +``` + ##### Modified `process_execution_payload` *Note*: The function `process_execution_payload` is modified to pass `execution_requests` into `execution_engine.verify_and_notify_new_payload` (via the updated `NewPayloadRequest`). @@ -1160,9 +1186,9 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody, executi assert execution_engine.verify_and_notify_new_payload( NewPayloadRequest( execution_payload=payload, - execution_requests=body.execution_requests, # [New in Electra] versioned_hashes=versioned_hashes, parent_beacon_block_root=state.latest_block_header.parent_root, + execution_requests=body.execution_requests, # [New in Electra] ) ) # Cache execution payload header