From c03864ec41a06f2d7f740736f8268bc7e403b22c Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Wed, 11 Jan 2023 16:06:06 +0600 Subject: [PATCH 1/7] Engine API: define payload bodies requests --- src/engine/shanghai.md | 69 +++++++++++++++++++++++++++++++++++++++++- wordlist.txt | 3 ++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/engine/shanghai.md b/src/engine/shanghai.md index 52d733a34..3a7a54241 100644 --- a/src/engine/shanghai.md +++ b/src/engine/shanghai.md @@ -10,6 +10,7 @@ Engine API changes introduced in Shanghai. - [Structures](#structures) - [WithdrawalV1](#withdrawalv1) - [ExecutionPayloadV2](#executionpayloadv2) + - [ExecutionPayloadBodyV1](#executionpayloadbodyv1) - [PayloadAttributesV2](#payloadattributesv2) - [Methods](#methods) - [engine_newPayloadV2](#engine_newpayloadv2) @@ -24,6 +25,14 @@ Engine API changes introduced in Shanghai. - [Request](#request-2) - [Response](#response-2) - [Specification](#specification-2) + - [engine_getPayloadBodiesByHashV1](#engine_getpayloadbodiesbyhashv1) + - [Request](#request-3) + - [Response](#response-3) + - [Specification](#specification-3) + - [engine_getPayloadBodiesByRangeV1](#engine_getpayloadbodiesbyrangev1) + - [Request](#request-4) + - [Response](#response-4) + - [Specification](#specification-4) @@ -61,6 +70,11 @@ This structure has the syntax of `ExecutionPayloadV1` and appends a single field - `transactions`: `Array of DATA` - Array of transaction objects, each object is a byte list (`DATA`) representing `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) - `withdrawals`: `Array of WithdrawalV1` - Array of withdrawals, each object is an `OBJECT` containing the fields of a `WithdrawalV1` structure. +### ExecutionPayloadBodyV1 +This structure contains a body of an execution payload. The fields are encoded as follows: +- `transactions`: `Array of DATA` - Array of transaction objects, each object is a byte list (`DATA`) representing `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) +- `withdrawals`: `Array of WithdrawalV1` - Array of withdrawals, each object is an `OBJECT` containing the fields of a `WithdrawalV1` structure. + ### PayloadAttributesV2 This structure has the syntax of `PayloadAttributesV1` and appends a single field: `withdrawals`. @@ -134,4 +148,57 @@ This method follows the same specification as [`engine_forkchoiceUpdatedV1`](./p This method follows the same specification as [`engine_getPayloadV1`](./paris.md#engine_getpayloadv1) with the addition of the following: - 1. Client software **SHOULD** use the sum of the block's priority fees or any other algorithm to determine `blockValue`. \ No newline at end of file + 1. Client software **SHOULD** use the sum of the block's priority fees or any other algorithm to determine `blockValue`. + +### engine_getPayloadBodiesByHashV1 + +#### Request + +* method: `engine_getPayloadBodiesByHashV1` +* params: + 1. `Array of DATA`, 32 Bytes - Array of `block_hash` field values of the `ExecutionPayload` structure +* timeout: 10s + +#### Response + +* result: `Array of ExecutionPayloadBodyV1` - Array of [`ExecutionPayloadBodyV1`](#ExecutionPayloadBodyV1) objects. +* error: code and message set in case an exception happens while processing the method call. + +#### Specification + +1. Given array of block hashes client software **MUST** respond with array of `ExecutionPayloadBodyV1` objects with the corresponding hashes respecting the order of block hashes in the input array. + +1. Client software **MUST** place responses in the order given in the request, using `null` for any missing blocks. For instance, if the request is `[A.block_hash, B.block_hash, C.block_hash]` and client software has data of payloads `A` and `C`, but doesn't have data of `B`, the response **MUST** be `[A.body, null, C.body]`. + +1. Clients that support `engine_getPayloadBodiesByRangeV1` **MAY NOT** respond to requests for finalized blocks by hash. + +1. This request maps to [`BeaconBlocksByRoot`](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#beaconblocksbyroot) in the consensus layer `p2p` specification. Callers must be careful to use the execution block root, instead of the beacon block root. + +### engine_getPayloadBodiesByRangeV1 + +#### Request + +* method: `engine_getPayloadBodiesByRangeV1` +* params: + 1. `start`: `QUANTITY`, 64 bits - Starting block number + 1. `count`: `QUANITTY`, 64 bits - Number of blocks to return +* timeout: 10s + +#### Response + +* result: `Array of ExecutionPayloadBodyV1` - Array of [`ExecutionPayloadBodyV1`](#ExecutionPayloadBodyV1) objects. +* error: code and message set in case an exception happens while processing the method call. + +#### Specification + +1. Given a `start` and a `count`, the client software **MUST** respond with array of `ExecutionPayloadBodyV1` objects with the corresponding execution block number respecting the order of blocks in the canonical chain, as selected by the latest `engine_forkchoiceUpdated` call. + +1. Client software **MUST** support `count` values of at least 32 blocks. + +1. Client software **MUST** place `null` in the response array for any blocks that have been pruned or where the request extends past the current latest known block. + +1. This request maps to [`BeaconBlocksByRange`](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#beaconblocksbyrange) in the consensus layer `p2p` specification. + +1. Callers must be careful to not confuse `start` with a slot number, instead mapping the slot to a block number. Callers must also be careful to request non-finalized blocks by root in order to avoid race conditions around the current view of the canonical chain. + +1. Callers must be careful to verify the hash of the received blocks when requesting non-finalized parts of the chain since the response is prone to being re-orged. diff --git a/wordlist.txt b/wordlist.txt index 5ff2b089b..bc03ceac9 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -1,5 +1,8 @@ apis attributesv +bodyv +bodiesbyrangev +bodiesbyhashv bytecode configurationv crypto From 68ef3550d637d043326e2b92d399b44c0b07de78 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Wed, 11 Jan 2023 18:18:26 +0600 Subject: [PATCH 2/7] Apply suggestions from code review Co-authored-by: Jacek Sieka --- src/engine/shanghai.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/shanghai.md b/src/engine/shanghai.md index 3a7a54241..b32294c53 100644 --- a/src/engine/shanghai.md +++ b/src/engine/shanghai.md @@ -172,7 +172,7 @@ This method follows the same specification as [`engine_getPayloadV1`](./paris.md 1. Clients that support `engine_getPayloadBodiesByRangeV1` **MAY NOT** respond to requests for finalized blocks by hash. -1. This request maps to [`BeaconBlocksByRoot`](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#beaconblocksbyroot) in the consensus layer `p2p` specification. Callers must be careful to use the execution block root, instead of the beacon block root. +1. This request maps to [`BeaconBlocksByRoot`](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#beaconblocksbyroot) in the consensus layer `p2p` specification. Callers must be careful to use the execution block hash, instead of the beacon block root. ### engine_getPayloadBodiesByRangeV1 @@ -199,6 +199,6 @@ This method follows the same specification as [`engine_getPayloadV1`](./paris.md 1. This request maps to [`BeaconBlocksByRange`](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#beaconblocksbyrange) in the consensus layer `p2p` specification. -1. Callers must be careful to not confuse `start` with a slot number, instead mapping the slot to a block number. Callers must also be careful to request non-finalized blocks by root in order to avoid race conditions around the current view of the canonical chain. +1. Callers must be careful to not confuse `start` with a slot number, instead mapping the slot to a block number. Callers must also be careful to request non-finalized blocks by hash in order to avoid race conditions around the current view of the canonical chain. 1. Callers must be careful to verify the hash of the received blocks when requesting non-finalized parts of the chain since the response is prone to being re-orged. From aef7136aa4ccd3ae4bb35b9333280c37a4ea992c Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 13 Jan 2023 13:10:08 +0600 Subject: [PATCH 3/7] Update src/engine/shanghai.md Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com> --- src/engine/shanghai.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/shanghai.md b/src/engine/shanghai.md index b32294c53..4c96349ee 100644 --- a/src/engine/shanghai.md +++ b/src/engine/shanghai.md @@ -170,7 +170,7 @@ This method follows the same specification as [`engine_getPayloadV1`](./paris.md 1. Client software **MUST** place responses in the order given in the request, using `null` for any missing blocks. For instance, if the request is `[A.block_hash, B.block_hash, C.block_hash]` and client software has data of payloads `A` and `C`, but doesn't have data of `B`, the response **MUST** be `[A.body, null, C.body]`. -1. Clients that support `engine_getPayloadBodiesByRangeV1` **MAY NOT** respond to requests for finalized blocks by hash. +1. Clients **MAY NOT** respond to requests for finalized blocks by hash. 1. This request maps to [`BeaconBlocksByRoot`](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#beaconblocksbyroot) in the consensus layer `p2p` specification. Callers must be careful to use the execution block hash, instead of the beacon block root. From 2e7cef9b0f9a3f9ef032c0275f97489955f9cf7a Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 13 Jan 2023 13:14:37 +0600 Subject: [PATCH 4/7] Add handling pre-Shanghai bodies --- src/engine/shanghai.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/engine/shanghai.md b/src/engine/shanghai.md index 4c96349ee..486df68b8 100644 --- a/src/engine/shanghai.md +++ b/src/engine/shanghai.md @@ -170,7 +170,9 @@ This method follows the same specification as [`engine_getPayloadV1`](./paris.md 1. Client software **MUST** place responses in the order given in the request, using `null` for any missing blocks. For instance, if the request is `[A.block_hash, B.block_hash, C.block_hash]` and client software has data of payloads `A` and `C`, but doesn't have data of `B`, the response **MUST** be `[A.body, null, C.body]`. -1. Clients **MAY NOT** respond to requests for finalized blocks by hash. +1. Client software **MAY NOT** respond to requests for finalized blocks by hash. + +1. Client software **MUST** set `withdrawals` field to `null` for bodies of pre-Shanghai blocks. 1. This request maps to [`BeaconBlocksByRoot`](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#beaconblocksbyroot) in the consensus layer `p2p` specification. Callers must be careful to use the execution block hash, instead of the beacon block root. @@ -197,6 +199,8 @@ This method follows the same specification as [`engine_getPayloadV1`](./paris.md 1. Client software **MUST** place `null` in the response array for any blocks that have been pruned or where the request extends past the current latest known block. +1. Client software **MUST** set `withdrawals` field to `null` for bodies of pre-Shanghai blocks. + 1. This request maps to [`BeaconBlocksByRange`](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#beaconblocksbyrange) in the consensus layer `p2p` specification. 1. Callers must be careful to not confuse `start` with a slot number, instead mapping the slot to a block number. Callers must also be careful to request non-finalized blocks by hash in order to avoid race conditions around the current view of the canonical chain. From a11ac53bc2910a0c4b2c9c92dba9e9aad984db69 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Tue, 17 Jan 2023 22:33:35 +0100 Subject: [PATCH 5/7] More null values --- src/engine/shanghai.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/shanghai.md b/src/engine/shanghai.md index 486df68b8..2da87c924 100644 --- a/src/engine/shanghai.md +++ b/src/engine/shanghai.md @@ -197,7 +197,10 @@ This method follows the same specification as [`engine_getPayloadV1`](./paris.md 1. Client software **MUST** support `count` values of at least 32 blocks. -1. Client software **MUST** place `null` in the response array for any blocks that have been pruned or where the request extends past the current latest known block. +1. Client software **MUST**: + * Place `null` in the response array for pruned blocks. + * Omit `null` values where the request extends past the current latest known block, i.e. no trailing `nulls` are allowed in this case. + * Return array of `null` values if all blocks from requested range are pruned and the range is behind the latest known block. 1. Client software **MUST** set `withdrawals` field to `null` for bodies of pre-Shanghai blocks. From f60ac1769c7b656d451fb339dae7c4d7b21fcd80 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 20 Jan 2023 09:55:56 +0100 Subject: [PATCH 6/7] Provide example responses for ByRange --- src/engine/shanghai.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/engine/shanghai.md b/src/engine/shanghai.md index c6b519136..5d099934c 100644 --- a/src/engine/shanghai.md +++ b/src/engine/shanghai.md @@ -208,10 +208,13 @@ This method follows the same specification as [`engine_getPayloadV1`](./paris.md 1. Client software **MUST** support `count` values of at least 32 blocks. -1. Client software **MUST**: - * Place `null` in the response array for pruned blocks. - * Omit `null` values where the request extends past the current latest known block, i.e. no trailing `nulls` are allowed in this case. - * Return array of `null` values if all blocks from requested range are pruned and the range is behind the latest known block. +1. Client software **MUST** place `null` in the response array for unavailable blocks which numbers are lower than a number of the latest known block. Client software **MUST NOT** return trailing `null` values if the request extends past the current latest known block. Consider the following response examples: + * `[B1.body, B2.body, ..., Bn.body]` -- entire requested range is filled with block bodies, + * `[null, null, B3.body, ..., Bn.body]` -- first two blocks are unavailable (either pruned or not yet downloaded), + * `[null, null, ..., null]` -- requested range is behind the latest known block and all blocks are unavailable, + * `[B1.body, B2.body, B3.body, B4.body]` -- `B4` is the latest known block and trailing `null` values are trimmed, + * `[]` -- entire requested range is beyond the latest known block, + * `[null, null, B3.body, B4.body]` -- first two blocks are unavailable, `B4` is the latest known block. 1. Client software **MUST** set `withdrawals` field to `null` for bodies of pre-Shanghai blocks. From 19fb76ec62dd7affb5ed61bd1436a1bddbc04ac2 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 20 Jan 2023 17:45:58 +0100 Subject: [PATCH 7/7] Note that EL is expected to carry the full history --- src/engine/shanghai.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/shanghai.md b/src/engine/shanghai.md index 5d099934c..8c228f1db 100644 --- a/src/engine/shanghai.md +++ b/src/engine/shanghai.md @@ -208,7 +208,7 @@ This method follows the same specification as [`engine_getPayloadV1`](./paris.md 1. Client software **MUST** support `count` values of at least 32 blocks. -1. Client software **MUST** place `null` in the response array for unavailable blocks which numbers are lower than a number of the latest known block. Client software **MUST NOT** return trailing `null` values if the request extends past the current latest known block. Consider the following response examples: +1. Client software **MUST** place `null` in the response array for unavailable blocks which numbers are lower than a number of the latest known block. Client software **MUST NOT** return trailing `null` values if the request extends past the current latest known block. Execution Layer client software is expected to download and carry the full block history until EIP-4444 or a similar proposal takes into effect. Consider the following response examples: * `[B1.body, B2.body, ..., Bn.body]` -- entire requested range is filled with block bodies, * `[null, null, B3.body, ..., Bn.body]` -- first two blocks are unavailable (either pruned or not yet downloaded), * `[null, null, ..., null]` -- requested range is behind the latest known block and all blocks are unavailable,