From b1a4ebd78101c9b0554dc2d49f11b98302e037fc Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 10 Dec 2021 15:47:18 +0600 Subject: [PATCH 1/9] Engine API: add getPayloadBodies method --- src/engine/specification.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/engine/specification.md b/src/engine/specification.md index 58f6f8eba..2cc50b6b0 100644 --- a/src/engine/specification.md +++ b/src/engine/specification.md @@ -17,6 +17,7 @@ This document specifies the Engine API methods that the Consensus Layer uses to - [ExecutionPayloadV1](#executionpayloadv1) - [ForkchoiceStateV1](#forkchoicestatev1) - [PayloadAttributesV1](#payloadattributesv1) + - [ExecutionPayloadBodyV1](#executionpayloadbodyv1) - [Core](#core) - [engine_executePayloadV1](#engine_executepayloadv1) - [Request](#request) @@ -31,6 +32,10 @@ This document specifies the Engine API methods that the Consensus Layer uses to - [Request](#request-2) - [Response](#response-2) - [Specification](#specification-2) + - [engine_getPayloadBodiesV1](#engine_getpayloadbodiesv1) + - [Request](#request-3) + - [Response](#response-3) + - [Specification](#specification-3) @@ -165,6 +170,12 @@ This structure contains the attributes required to initiate a payload build proc - `random`: `DATA`, 32 Bytes - value for the `random` field of the new payload - `suggestedFeeRecipient`: `DATA`, 20 Bytes - suggested value for the `feeRecipient` field of the new payload +### 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) + + ## Core ### engine_executePayloadV1 @@ -256,3 +267,22 @@ The payload build process is specified as follows: 2. The call **MUST** return `-32001: Unknown payload` error if the build process identified by the `payloadId` does not exist. 3. Client software **MAY** stop the corresponding build process after serving this call. + +### engine_getPayloadBodiesV1 + +#### Request + +* method: `engine_getPayloadBodiesV1` +* params: + 1. `Array of DATA`, 32 Bytes - Array of `block_hash` field values of the `ExecutionPayload` structure + +#### 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. + +2. Client software **MUST** skip the payload body in the response array if the data of this body is missing. 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, C.body]`. From 6be10880ca2847f403862c2ae8af3d00225c3766 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 10 Dec 2021 19:52:12 +0600 Subject: [PATCH 2/9] Engine API: fix spellchecker --- wordlist.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/wordlist.txt b/wordlist.txt index d372d3132..aa7a1e5dc 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -1,5 +1,6 @@ apis attributesv +bodyv bytecode eip endian From f500c4831d284305e4e4df3704cf0b960a7e33db Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 10 Dec 2021 19:53:33 +0600 Subject: [PATCH 3/9] Engine API: fix spellchecker. Take 2 --- wordlist.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/wordlist.txt b/wordlist.txt index aa7a1e5dc..ff90fabf4 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -1,6 +1,7 @@ apis attributesv bodyv +bodiesv bytecode eip endian From 832c938c5c7aa687d41bdd8c6da7699fff6b6be9 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Fri, 6 May 2022 08:17:50 +0200 Subject: [PATCH 4/9] add by-range request Similar to the consensus p2p spec, a by-range request allows execution clients to store finalized blocks in linear by-number storage instead of relying on by-hash indices, significantly increasing efficiency in fetching them from cold storage. Clients whose database design does not permit efficient by-number lookups may opt to not implement this call, but must then give a well-known error code allowing consensus later clients to fall back to a less efficient method of fetching the blocks. This specification assumes that execution clients know nothing of slot numbers as seen on the consensus layer. Should execution clients later learn about these, the specification may be amended to work with slot numbers instead. Until then, consensus clients must be careful to compute block numbers correctly. Consensus clients must also be careful when this request is used to fetch non-finalized blocks, reverting to by-root requests if an unexpected chain is returned. --- src/engine/specification.md | 38 ++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/engine/specification.md b/src/engine/specification.md index 8a3edd3d5..1edd55929 100644 --- a/src/engine/specification.md +++ b/src/engine/specification.md @@ -41,10 +41,14 @@ This document specifies the Engine API methods that the Consensus Layer uses to - [Request](#request-3) - [Response](#response-3) - [Specification](#specification-3) - - [engine_getPayloadBodiesV1](#engine_getpayloadbodiesv1) + - [engine_getPayloadBodiesByRootV1](#engine_getpayloadbodiesbyrootv1) - [Request](#request-4) - [Response](#response-4) - [Specification](#specification-4) + - [engine_getPayloadBodiesByRangeV1](#engine_getpayloadbodiesbyrangev1) + - [Request](#request-5) + - [Response](#response-5) + - [Specification](#specification-5) @@ -388,11 +392,11 @@ The payload build process is specified as follows: [json-rpc-spec]: https://playground.open-rpc.org/?schemaUrl=https://raw.githubusercontent.com/ethereum/execution-apis/assembled-spec/openrpc.json&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false 1. Client software **MAY** stop the corresponding build process after serving this call. -### engine_getPayloadBodiesV1 +### engine_getPayloadBodiesByRootV1 #### Request -* method: `engine_getPayloadBodiesV1` +* method: `engine_getPayloadBodiesByRootV1` * params: 1. `Array of DATA`, 32 Bytes - Array of `block_hash` field values of the `ExecutionPayload` structure @@ -406,3 +410,31 @@ The payload build process is specified as follows: 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** skip the payload body in the response array if the data of this body is missing. 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, C.body]`. + +1. Clients that support `engine_getPayloadBodiesByRangeV1` are not required to respond to requests for finalized blocks by root. + +1. This request maps to [`BeaconBlocksByRoot`](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#beaconblocksbyrange=) 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 + +#### 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. + * Clients that don't support fetching bodies by range **MUST** return the error code `-32601 Method not found The method does not exist / is not available.`. Callers may then revert to `engine_getPayloadBodiesByRootV1`. + +#### 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 `forkChoiceUpdated` call. + +1. Client software **MUST** skip the payload body for any blocks that have been pruned by the execution client 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. + Callers must be careful to not confuse `start` with a slot number, instead mapping the slot to a block number. From 1091c2de924c70718293c6a5f0f955ea43b644b9 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Fri, 6 May 2022 08:37:11 +0200 Subject: [PATCH 5/9] fight spellchecker --- src/engine/specification.md | 3 +-- wordlist.txt | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/engine/specification.md b/src/engine/specification.md index 1edd55929..91d72ef6d 100644 --- a/src/engine/specification.md +++ b/src/engine/specification.md @@ -390,7 +390,6 @@ The payload build process is specified as follows: 6. Considering the absence of the `TERMINAL_BLOCK_NUMBER` setting, Consensus Layer client software **MAY** use `0` value for the `terminalBlockNumber` field in the input parameters of this call. [json-rpc-spec]: https://playground.open-rpc.org/?schemaUrl=https://raw.githubusercontent.com/ethereum/execution-apis/assembled-spec/openrpc.json&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false -1. Client software **MAY** stop the corresponding build process after serving this call. ### engine_getPayloadBodiesByRootV1 @@ -437,4 +436,4 @@ The payload build process is specified as follows: 1. Client software **MUST** skip the payload body for any blocks that have been pruned by the execution client 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. - Callers must be careful to not confuse `start` with a slot number, instead mapping the slot to a block number. + 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 requests non-finalized blocks by root in order to avoid race conditions around the current view of the canonical chain. diff --git a/wordlist.txt b/wordlist.txt index 4d37624ea..cd0d5267a 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -1,7 +1,8 @@ apis attributesv bodyv -bodiesv +bodiesbyrangev +bodiesbyrootv bytecode configurationv eip From e189c5b738b0dd72be69193d8acadd9e10df1a92 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Tue, 10 May 2022 16:31:08 +0200 Subject: [PATCH 6/9] Update src/engine/specification.md Co-authored-by: Mikhail Kalinin --- src/engine/specification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/specification.md b/src/engine/specification.md index 91d72ef6d..a2a4d99ad 100644 --- a/src/engine/specification.md +++ b/src/engine/specification.md @@ -436,4 +436,4 @@ The payload build process is specified as follows: 1. Client software **MUST** skip the payload body for any blocks that have been pruned by the execution client 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. - 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 requests 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 root in order to avoid race conditions around the current view of the canonical chain. From e19aa80b1466ee809d5efcc02857f8a7c3d79aef Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Tue, 10 May 2022 16:31:19 +0200 Subject: [PATCH 7/9] Update src/engine/specification.md Co-authored-by: Mikhail Kalinin --- src/engine/specification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/specification.md b/src/engine/specification.md index a2a4d99ad..30e7b0ddd 100644 --- a/src/engine/specification.md +++ b/src/engine/specification.md @@ -410,7 +410,7 @@ The payload build process is specified as follows: 1. Client software **MUST** skip the payload body in the response array if the data of this body is missing. 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, C.body]`. -1. Clients that support `engine_getPayloadBodiesByRangeV1` are not required to respond to requests for finalized blocks by root. +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#beaconblocksbyrange=) in the consensus layer `p2p` specification. Callers must be careful to use the execution block root, instead of the beacon block root. From e1989ed135dec412c507663120c47d2178e88e25 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Tue, 31 May 2022 12:45:50 +0200 Subject: [PATCH 8/9] `ByRoot` -> `ByHash` --- src/engine/specification.md | 8 ++++---- wordlist.txt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/engine/specification.md b/src/engine/specification.md index f29056d59..0f5ab8d65 100644 --- a/src/engine/specification.md +++ b/src/engine/specification.md @@ -42,7 +42,7 @@ This document specifies the Engine API methods that the Consensus Layer uses to - [Request](#request-3) - [Response](#response-3) - [Specification](#specification-3) - - [engine_getPayloadBodiesByRootV1](#engine_getpayloadbodiesbyrootv1) + - [engine_getPayloadBodiesByHashV1](#engine_getpayloadbodiesByHashV1) - [Request](#request-4) - [Response](#response-4) - [Specification](#specification-4) @@ -404,11 +404,11 @@ The payload build process is specified as follows: [json-rpc-spec]: https://playground.open-rpc.org/?schemaUrl=https://raw.githubusercontent.com/ethereum/execution-apis/assembled-spec/openrpc.json&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false -### engine_getPayloadBodiesByRootV1 +### engine_getPayloadBodiesByHashV1 #### Request -* method: `engine_getPayloadBodiesByRootV1` +* method: `engine_getPayloadBodiesByHashV1` * params: 1. `Array of DATA`, 32 Bytes - Array of `block_hash` field values of the `ExecutionPayload` structure @@ -440,7 +440,7 @@ The payload build process is specified as follows: * result: `Array of ExecutionPayloadBodyV1` - Array of [`ExecutionPayloadBodyV1`](#ExecutionPayloadBodyV1) objects. * error: code and message set in case an exception happens while processing the method call. - * Clients that don't support fetching bodies by range **MUST** return the error code `-32601 Method not found The method does not exist / is not available.`. Callers may then revert to `engine_getPayloadBodiesByRootV1`. + * Clients that don't support fetching bodies by range **MUST** return the error code `-32601 Method not found The method does not exist / is not available.`. Callers may then revert to `engine_getPayloadBodiesByHashV1`. #### Specification diff --git a/wordlist.txt b/wordlist.txt index bcde3de98..159fe466d 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -2,7 +2,7 @@ apis attributesv bodyv bodiesbyrangev -bodiesbyrootv +bodiesbyhashv bytecode configurationv crypto From de8fd3debe46096771f032eef7f8cff7c0404e68 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Thu, 29 Sep 2022 16:15:37 +0200 Subject: [PATCH 9/9] Allow `nil` in response --- src/engine/specification.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/engine/specification.md b/src/engine/specification.md index 0f5ab8d65..2d4bd7915 100644 --- a/src/engine/specification.md +++ b/src/engine/specification.md @@ -421,7 +421,7 @@ The payload build process is specified as follows: 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** skip the payload body in the response array if the data of this body is missing. 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, C.body]`. +1. Client software **MUST** place responses in the order given in the request, using `nil` 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, nil, C.body]`. 1. Clients that support `engine_getPayloadBodiesByRangeV1` **MAY NOT** respond to requests for finalized blocks by hash. @@ -445,8 +445,9 @@ The payload build process is specified as follows: #### 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 `forkChoiceUpdated` call. - -1. Client software **MUST** skip the payload body for any blocks that have been pruned by the execution client or where the request extends past the current latest known block. +1. Client software **MUST** support `count` values of at least 32 blocks. +1. Client software **MUST** place `nil` 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.