From 26390afedaba6c804523079a6924229b5e317b6b Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Tue, 29 Sep 2026 12:09:23 +0100 Subject: [PATCH 01/17] engine: add inclusion list claims and grouped inclusion lists (EIP-XXXX) --- src/engine/eipxxxx.md | 129 ++++++++++++++++++++++++ src/engine/openrpc/methods/payload.yaml | 92 +++++++++++++++++ src/engine/openrpc/schemas/payload.yaml | 13 +++ 3 files changed, 234 insertions(+) create mode 100644 src/engine/eipxxxx.md diff --git a/src/engine/eipxxxx.md b/src/engine/eipxxxx.md new file mode 100644 index 000000000..c7a520fa4 --- /dev/null +++ b/src/engine/eipxxxx.md @@ -0,0 +1,129 @@ +# Engine API -- EIP-XXXX + +Engine API changes introduced in EIP-XXXX. + +This specification is based on and extends [Engine API - Bogota](./bogota.md) specification. + +## Table of contents + + + + +- [Constants](#constants) +- [Structures](#structures) + - [InclusionListClaimV1](#inclusionlistclaimv1) +- [Methods](#methods) + - [engine_newPayloadV7](#engine_newpayloadv7) + - [Request](#request) + - [Response](#response) + - [Specification](#specification) + - [engine_getPayloadV7](#engine_getpayloadv7) + - [Request](#request-1) + - [Response](#response-1) + - [Specification](#specification-1) + - [Update the methods of previous forks](#update-the-methods-of-previous-forks) + - [Bogota API](#bogota-api) + + + +## Constants + +| Name | Value | +| - | - | +| `INCLUSION_LIST_COMMITTEE_SIZE` | `uint64(16) = 2**4` | +| `MAX_INCLUSION_LIST_CLAIMS` | `uint64(1024) = 2**10` | + +## Structures + +### InclusionListClaimV1 + +This structure maps onto the inclusion list claim defined in EIP-XXXX. The fields are encoded as follows: + +- `transactionHash`: `DATA`, 32 Bytes - `keccak256` of the claimed inclusion list transaction, `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). +- `transactionIndex`: `QUANTITY`, 64 Bits - index in `executionPayload.transactions` at which the omission of the claimed transaction is evaluated. + +## Methods + +### engine_newPayloadV7 + +Method parameter list is extended with `inclusionListClaims`, and inclusion list transactions are grouped per inclusion list. + +#### Request + +* method: `engine_newPayloadV7` +* params: + 1. `executionPayload`: [`ExecutionPayloadV4`](./amsterdam.md#executionpayloadv4). + 2. `expectedBlobVersionedHashes`: `Array of DATA`, 32 Bytes - Array of expected blob versioned hashes to validate. + 3. `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. + 4. `executionRequests`: `Array of DATA` - List of execution layer triggered requests. Each list element is a `requests` byte array as defined by [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685). The first byte of each element is the `request_type` and the remaining bytes are the `request_data`. Elements of the list **MUST** be ordered by `request_type` in ascending order. Elements with empty `request_data` **MUST** be excluded from the list. + 5. `inclusionLists`: `Array of Array of DATA` - Array of inclusion lists, one per inclusion list committee member, each an array of transaction objects in the order of that inclusion list. Each transaction object is a byte list (`DATA`) representing `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). + 6. `inclusionListClaims`: `Array of InclusionListClaimV1` - Array of inclusion list claims committed to by the builder of the payload. +* timeout: 6s + +#### Response + +* result: [`PayloadStatusV2`](./bogota.md#payloadstatusv2) +* error: code and message set in case an exception happens while processing the payload. + +#### Specification + +This method follows the same specification as [`engine_newPayloadV6`](./bogota.md#engine_newpayloadv6) with the following changes: + +1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the payload is less than the EIP-XXXX activation timestamp. + +2. Client software **MUST** return `-32602: Invalid params` error if any of the following holds: + + 1. `inclusionLists` has more than `INCLUSION_LIST_COMMITTEE_SIZE` elements. + + 2. The sum of the byte lengths of the transactions in an element of `inclusionLists` exceeds `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. The total byte length of all inclusion list transactions is therefore at most `INCLUSION_LIST_COMMITTEE_SIZE * MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. + + 3. `inclusionListClaims` has more than `MAX_INCLUSION_LIST_CLAIMS` elements. + +3. Client software **MUST** determine whether the payload satisfied the inclusion list constraints with respect to `inclusionLists` and `inclusionListClaims` as defined in EIP-XXXX. Duplicate, unmatched and out-of-range claims **MUST NOT** cause an error; they are resolved as defined in EIP-XXXX. + +4. Client software **MUST** retain `inclusionLists` and `inclusionListClaims` for a payload with `ACCEPTED` status. Client software **MAY** discard them once the payload is no longer the tip of a branch. + +### engine_getPayloadV7 + +This method is updated to return `inclusionListClaims`. + +#### Request + +* method: `engine_getPayloadV7` +* params: + 1. `payloadId`: `DATA`, 8 Bytes - Identifier of the payload build process +* timeout: 1s + +#### Response + +* result: `object` + - `executionPayload`: [`ExecutionPayloadV4`](./amsterdam.md#executionpayloadv4) + - `blockValue` : `QUANTITY`, 256 Bits - The expected value to be received by the `feeRecipient` in wei + - `blobsBundle`: [`BlobsBundleV2`](./osaka.md#blobsbundlev2) - Bundle with data corresponding to blob transactions included into `executionPayload` + - `shouldOverrideBuilder` : `BOOLEAN` - Suggestion from the execution layer to use this `executionPayload` instead of an externally provided one + - `executionRequests`: `Array of DATA` - Execution layer triggered requests obtained from the `executionPayload` transaction execution. + - `inclusionListClaims`: `Array of InclusionListClaimV1` - Inclusion list claims for transactions omitted from `executionPayload`. +* error: code and message set in case an exception happens while getting the payload. + +#### Specification + +This method follows the same specification as [`engine_getPayloadV6`](./amsterdam.md#engine_getpayloadv6) with the following changes: + +1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the built payload is less than the EIP-XXXX activation timestamp. + +2. `inclusionListClaims` **MUST NOT** have more than `MAX_INCLUSION_LIST_CLAIMS` elements. Each claim **MUST** refer to a transaction of the `inclusionListTransactions` used to build the payload that is omitted from `executionPayload`, and **SHOULD** have an index at which that omission is excused as defined in EIP-XXXX. + +### Update the methods of previous forks + +#### Bogota API + +For the following methods: + +- [`engine_newPayloadV6`](./bogota.md#engine_newpayloadv6) +- [`engine_getPayloadV6`](./amsterdam.md#engine_getpayloadv6) + +a validation **MUST** be added: + +1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the payload is greater than or equal to the EIP-XXXX activation timestamp. + +For [`engine_forkchoiceUpdatedV5`](./bogota.md#engine_forkchoiceupdatedv5), if the payload referenced by `forkchoiceState.headBlockHash` was received with [`engine_newPayloadV7`](#engine_newpayloadv7), client software **MUST** use the retained `inclusionLists` and `inclusionListClaims` if it checks whether the payload satisfies the inclusion list constraints while processing the call. diff --git a/src/engine/openrpc/methods/payload.yaml b/src/engine/openrpc/methods/payload.yaml index f109bf109..defc97187 100644 --- a/src/engine/openrpc/methods/payload.yaml +++ b/src/engine/openrpc/methods/payload.yaml @@ -1211,3 +1211,95 @@ executionRequests: - '0x96a96086cff07df17668f35f7418ef8798079167e3f4f9b72ecde17b28226137cf454ab1dd20ef5d924786ab3483c2f9003f5102dabe0a27b1746098d1dc17a5d3fbd478759fea9287e4e419b3c3cef20100000000000000b1acdb2c4d3df3f1b8d3bfd33421660df358d84d78d16c4603551935f4b67643373e7eb63dcb16ec359be0ec41fee33b03a16e80745f2374ff1d3c352508ac5d857c6476d3c3bcf7e6ca37427c9209f17be3af5264c0e2132b3dd1156c28b4e9f000000000000000a5c85a60ba2905c215f6a12872e62b1ee037051364244043a5f639aa81b04a204c55e7cc851f29c7c183be253ea1510b001db70c485b6264692f26b8aeaab5b0c384180df8e2184a21a808a3ec8e86ca01000000000000009561731785b48cf1886412234531e4940064584463e96ac63a1a154320227e333fb51addc4a89b7e0d3f862d7c1fd4ea03bd8eb3d8806f1e7daf591cbbbb92b0beb74d13c01617f22c5026b4f9f9f294a8a7c32db895de3b01bee0132c9209e1f100000000000000' - '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b85103a5617937691dfeeb89b86a80d5dc9e3c9d3a1a0e7ce311e26e0bb732eabaa47ffa288f0d54de28209a62a7d29d0000000000000000000000000000000000000000000000000000010f698daeed734da114470da559bd4b4c7259e1f7952555241dcbc90cf194a2ef676fc6005f3672fada2a3645edb297a75530100000000000000' +- name: engine_newPayloadV7 + summary: Runs execution payload validation + externalDocs: + description: Method specification + url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eipxxxx.md#engine_newpayloadv7 + params: + - name: Execution payload + required: true + schema: + $ref: '#/components/schemas/ExecutionPayloadV4' + - name: Expected blob versioned hashes + required: true + schema: + type: array + items: + $ref: '#/components/schemas/hash32' + - name: Parent beacon block root + required: true + schema: + $ref: '#/components/schemas/hash32' + - name: Execution requests + required: true + schema: + type: array + items: + $ref: '#/components/schemas/bytes' + - name: Inclusion lists + required: true + schema: + type: array + items: + type: array + items: + $ref: '#/components/schemas/bytes' + - name: Inclusion list claims + required: true + schema: + type: array + items: + $ref: '#/components/schemas/InclusionListClaimV1' + result: + name: Payload status + schema: + $ref: '#/components/schemas/PayloadStatusV2' + errors: + - code: -32602 + message: Invalid params + - code: -38005 + message: Unsupported fork +- name: engine_getPayloadV7 + summary: Obtains execution payload from payload build process + externalDocs: + description: Method specification + url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eipxxxx.md#engine_getpayloadv7 + params: + - name: Payload id + required: true + schema: + $ref: '#/components/schemas/bytes8' + result: + name: Response object + schema: + type: object + required: + - executionPayload + - blockValue + - blobsBundle + - shouldOverrideBuilder + - executionRequests + - inclusionListClaims + properties: + executionPayload: + $ref: '#/components/schemas/ExecutionPayloadV4' + blockValue: + $ref: '#/components/schemas/uint256' + blobsBundle: + $ref: '#/components/schemas/BlobsBundleV2' + shouldOverrideBuilder: + type: boolean + executionRequests: + type: array + items: + $ref: '#/components/schemas/bytes' + inclusionListClaims: + type: array + items: + $ref: '#/components/schemas/InclusionListClaimV1' + errors: + - code: -38001 + message: Unknown payload + - code: -38005 + message: Unsupported fork diff --git a/src/engine/openrpc/schemas/payload.yaml b/src/engine/openrpc/schemas/payload.yaml index e947eaba4..6fde404a5 100644 --- a/src/engine/openrpc/schemas/payload.yaml +++ b/src/engine/openrpc/schemas/payload.yaml @@ -420,3 +420,16 @@ BlobsBundleV2: type: array items: $ref: '#/components/schemas/bytes' +InclusionListClaimV1: + title: Inclusion list claim object V1 + type: object + required: + - transactionHash + - transactionIndex + properties: + transactionHash: + title: Transaction hash + $ref: '#/components/schemas/hash32' + transactionIndex: + title: Transaction index + $ref: '#/components/schemas/uint64' From 5ff66a9a98c8af83d0fd371d135aea9224440730 Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Tue, 29 Sep 2026 12:50:18 +0100 Subject: [PATCH 02/17] engine: rename to EIP-8369 and add forkchoiceUpdatedV6 with grouped inclusion lists --- src/engine/{eipxxxx.md => eip8369.md} | 76 +++++++++++++++++++--- src/engine/openrpc/methods/forkchoice.yaml | 35 ++++++++++ src/engine/openrpc/methods/payload.yaml | 4 +- src/engine/openrpc/schemas/forkchoice.yaml | 34 ++++++++++ 4 files changed, 137 insertions(+), 12 deletions(-) rename src/engine/{eipxxxx.md => eip8369.md} (56%) diff --git a/src/engine/eipxxxx.md b/src/engine/eip8369.md similarity index 56% rename from src/engine/eipxxxx.md rename to src/engine/eip8369.md index c7a520fa4..f167b3f39 100644 --- a/src/engine/eipxxxx.md +++ b/src/engine/eip8369.md @@ -1,6 +1,6 @@ -# Engine API -- EIP-XXXX +# Engine API -- EIP-8369 -Engine API changes introduced in EIP-XXXX. +Engine API changes for the [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805) rules that apply to the [EIP-8369](https://eips.ethereum.org/EIPS/eip-8369) eligibility profiles. This specification is based on and extends [Engine API - Bogota](./bogota.md) specification. @@ -12,6 +12,9 @@ This specification is based on and extends [Engine API - Bogota](./bogota.md) sp - [Constants](#constants) - [Structures](#structures) - [InclusionListClaimV1](#inclusionlistclaimv1) + - [PayloadAttributesV6](#payloadattributesv6) +- [Routines](#routines) + - [Payload building](#payload-building) - [Methods](#methods) - [engine_newPayloadV7](#engine_newpayloadv7) - [Request](#request) @@ -21,6 +24,10 @@ This specification is based on and extends [Engine API - Bogota](./bogota.md) sp - [Request](#request-1) - [Response](#response-1) - [Specification](#specification-1) + - [engine_forkchoiceUpdatedV6](#engine_forkchoiceupdatedv6) + - [Request](#request-2) + - [Response](#response-2) + - [Specification](#specification-2) - [Update the methods of previous forks](#update-the-methods-of-previous-forks) - [Bogota API](#bogota-api) @@ -37,11 +44,34 @@ This specification is based on and extends [Engine API - Bogota](./bogota.md) sp ### InclusionListClaimV1 -This structure maps onto the inclusion list claim defined in EIP-XXXX. The fields are encoded as follows: +This structure maps onto the inclusion list claim defined in EIP-7805. The fields are encoded as follows: - `transactionHash`: `DATA`, 32 Bytes - `keccak256` of the claimed inclusion list transaction, `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). - `transactionIndex`: `QUANTITY`, 64 Bits - index in `executionPayload.transactions` at which the omission of the claimed transaction is evaluated. +### PayloadAttributesV6 + +This structure has the syntax of [`PayloadAttributesV5`](./bogota.md#payloadattributesv5), with `inclusionListTransactions` replaced by `inclusionLists`. + +- `timestamp`: `QUANTITY`, 64 Bits - value for the `timestamp` field of the new payload +- `prevRandao`: `DATA`, 32 Bytes - value for the `prevRandao` field of the new payload +- `suggestedFeeRecipient`: `DATA`, 20 Bytes - suggested value for the `feeRecipient` field of the new payload +- `withdrawals`: `Array of WithdrawalV1` - Array of withdrawals, each object is an `OBJECT` containing the fields of a `WithdrawalV1` structure. +- `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. +- `slotNumber`: `QUANTITY`, 64 Bits - value for the `slotNumber` field of the new payload +- `targetGasLimit`: `QUANTITY`, 64 Bits - target value for the `gasLimit` field of the new payload +- `inclusionLists`: `Array of Array of DATA` - Array of inclusion lists, with the same encoding and limits as the `inclusionLists` parameter of [`engine_newPayloadV7`](#engine_newpayloadv7). + +## Routines + +### Payload building + +This routine follows the same specification as [Payload building](./bogota.md#payload-building) with the following changes to the processing flow: + +1. Client software **MUST** take `inclusionLists` into account during the payload build process. The built `ExecutionPayload` together with the claims returned by [`engine_getPayloadV7`](#engine_getpayloadv7) **MUST** satisfy the inclusion list constraints with respect to `inclusionLists` as defined in EIP-7805. + +2. To determine which omissions are excused, client software **SHOULD** apply the VERIFY budget fill to each element of `inclusionLists` separately, as defined in EIP-7805, and claim an evaluation index for each admitted Profile 2 transaction it omits that would pass the replay at the end of the payload. + ## Methods ### engine_newPayloadV7 @@ -69,7 +99,7 @@ Method parameter list is extended with `inclusionListClaims`, and inclusion list This method follows the same specification as [`engine_newPayloadV6`](./bogota.md#engine_newpayloadv6) with the following changes: -1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the payload is less than the EIP-XXXX activation timestamp. +1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the payload is less than the EIP-8369 activation timestamp. 2. Client software **MUST** return `-32602: Invalid params` error if any of the following holds: @@ -79,7 +109,7 @@ This method follows the same specification as [`engine_newPayloadV6`](./bogota.m 3. `inclusionListClaims` has more than `MAX_INCLUSION_LIST_CLAIMS` elements. -3. Client software **MUST** determine whether the payload satisfied the inclusion list constraints with respect to `inclusionLists` and `inclusionListClaims` as defined in EIP-XXXX. Duplicate, unmatched and out-of-range claims **MUST NOT** cause an error; they are resolved as defined in EIP-XXXX. +3. Client software **MUST** determine whether the payload satisfied the inclusion list constraints with respect to `inclusionLists` and `inclusionListClaims` as defined in EIP-7805. Duplicate, unmatched and out-of-range claims **MUST NOT** cause an error; they are resolved as defined in EIP-7805. 4. Client software **MUST** retain `inclusionLists` and `inclusionListClaims` for a payload with `ACCEPTED` status. Client software **MAY** discard them once the payload is no longer the tip of a branch. @@ -109,9 +139,36 @@ This method is updated to return `inclusionListClaims`. This method follows the same specification as [`engine_getPayloadV6`](./amsterdam.md#engine_getpayloadv6) with the following changes: -1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the built payload is less than the EIP-XXXX activation timestamp. +1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the built payload is less than the EIP-8369 activation timestamp. + +2. `inclusionListClaims` **MUST NOT** have more than `MAX_INCLUSION_LIST_CLAIMS` elements. Each claim **MUST** refer to a transaction of the `inclusionLists` used to build the payload that is omitted from `executionPayload`, and **SHOULD** have an index at which that omission is excused as defined in EIP-7805. + +### engine_forkchoiceUpdatedV6 + +#### Request + +* method: `engine_forkchoiceUpdatedV6` +* params: + 1. `forkchoiceState`: [`ForkchoiceStateV1`](./paris.md#forkchoicestatev1). + 2. `payloadAttributes`: `Object|null` - Instance of [`PayloadAttributesV6`](#payloadattributesv6) or `null`. + 3. `custodyColumns`: `DATA|null`, 16 Bytes - Interpreted as a bitarray of length `CELLS_PER_EXT_BLOB` indicating which column indices form the CL's custody set, or `null` if the CL does not provide custody services. +* timeout: 8s + +#### Response + +Refer to the response for [`engine_forkchoiceUpdatedV5`](./bogota.md#engine_forkchoiceupdatedv5). + +#### Specification + +This method follows the same specification as [`engine_forkchoiceUpdatedV5`](./bogota.md#engine_forkchoiceupdatedv5) with the following changes to the processing flow: + +1. Extend point (8) of the `engine_forkchoiceUpdatedV1` [specification](./paris.md#specification-1) by defining the following sequence of checks that **MUST** be run over `payloadAttributes`: -2. `inclusionListClaims` **MUST NOT** have more than `MAX_INCLUSION_LIST_CLAIMS` elements. Each claim **MUST** refer to a transaction of the `inclusionListTransactions` used to build the payload that is omitted from `executionPayload`, and **SHOULD** have an index at which that omission is excused as defined in EIP-XXXX. + 1. `payloadAttributes` matches the [`PayloadAttributesV6`](#payloadattributesv6) structure and `payloadAttributes.inclusionLists` is within the limits of [`engine_newPayloadV7`](#engine_newpayloadv7), return `-38003: Invalid payload attributes` on failure. + + 2. `payloadAttributes.timestamp` is less than the EIP-8369 activation timestamp, return `-38005: Unsupported fork` on failure. + +2. Client software **MUST** use the retained `inclusionLists` and `inclusionListClaims` if it validates the payload referenced by `forkchoiceState.headBlockHash` and checks whether it satisfies the inclusion list constraints while processing the call. ### Update the methods of previous forks @@ -121,9 +178,8 @@ For the following methods: - [`engine_newPayloadV6`](./bogota.md#engine_newpayloadv6) - [`engine_getPayloadV6`](./amsterdam.md#engine_getpayloadv6) +- [`engine_forkchoiceUpdatedV5`](./bogota.md#engine_forkchoiceupdatedv5) a validation **MUST** be added: -1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the payload is greater than or equal to the EIP-XXXX activation timestamp. - -For [`engine_forkchoiceUpdatedV5`](./bogota.md#engine_forkchoiceupdatedv5), if the payload referenced by `forkchoiceState.headBlockHash` was received with [`engine_newPayloadV7`](#engine_newpayloadv7), client software **MUST** use the retained `inclusionLists` and `inclusionListClaims` if it checks whether the payload satisfies the inclusion list constraints while processing the call. +1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the payload, or of `payloadAttributes` for `engine_forkchoiceUpdatedV5`, is greater than or equal to the EIP-8369 activation timestamp. diff --git a/src/engine/openrpc/methods/forkchoice.yaml b/src/engine/openrpc/methods/forkchoice.yaml index badee9ff3..e50838573 100644 --- a/src/engine/openrpc/methods/forkchoice.yaml +++ b/src/engine/openrpc/methods/forkchoice.yaml @@ -231,3 +231,38 @@ message: Unsupported fork - code: -38006 message: Too deep reorg +- name: engine_forkchoiceUpdatedV6 + summary: Updates the forkchoice state + externalDocs: + description: Method specification + url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eip8369.md#engine_forkchoiceupdatedv6 + params: + - name: Forkchoice state + required: true + schema: + $ref: '#/components/schemas/ForkchoiceStateV1' + - name: Payload attributes + required: false + schema: + $ref: '#/components/schemas/PayloadAttributesV6' + - name: Custody columns + required: false + schema: + oneOf: + - $ref: '#/components/schemas/bytes16' + - type: 'null' + result: + name: Response object + schema: + $ref: '#/components/schemas/ForkchoiceUpdatedResponseV2' + errors: + - code: -38002 + message: Invalid forkchoice state + - code: -38003 + message: Invalid payload attributes + - code: -32602 + message: Invalid params + - code: -38005 + message: Unsupported fork + - code: -38006 + message: Too deep reorg diff --git a/src/engine/openrpc/methods/payload.yaml b/src/engine/openrpc/methods/payload.yaml index defc97187..6a242ae5f 100644 --- a/src/engine/openrpc/methods/payload.yaml +++ b/src/engine/openrpc/methods/payload.yaml @@ -1215,7 +1215,7 @@ summary: Runs execution payload validation externalDocs: description: Method specification - url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eipxxxx.md#engine_newpayloadv7 + url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eip8369.md#engine_newpayloadv7 params: - name: Execution payload required: true @@ -1264,7 +1264,7 @@ summary: Obtains execution payload from payload build process externalDocs: description: Method specification - url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eipxxxx.md#engine_getpayloadv7 + url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eip8369.md#engine_getpayloadv7 params: - name: Payload id required: true diff --git a/src/engine/openrpc/schemas/forkchoice.yaml b/src/engine/openrpc/schemas/forkchoice.yaml index 14d75411d..8c7d44313 100644 --- a/src/engine/openrpc/schemas/forkchoice.yaml +++ b/src/engine/openrpc/schemas/forkchoice.yaml @@ -157,3 +157,37 @@ PayloadAttributesV5: type: array items: $ref: '#/components/schemas/bytes' +PayloadAttributesV6: + title: Payload attributes object V6 + type: object + required: + - timestamp + - prevRandao + - suggestedFeeRecipient + - withdrawals + - parentBeaconBlockRoot + - slotNumber + - targetGasLimit + - inclusionLists + properties: + timestamp: + $ref: '#/components/schemas/PayloadAttributesV4/properties/timestamp' + prevRandao: + $ref: '#/components/schemas/PayloadAttributesV4/properties/prevRandao' + suggestedFeeRecipient: + $ref: '#/components/schemas/PayloadAttributesV4/properties/suggestedFeeRecipient' + withdrawals: + $ref: '#/components/schemas/PayloadAttributesV4/properties/withdrawals' + parentBeaconBlockRoot: + $ref: '#/components/schemas/PayloadAttributesV4/properties/parentBeaconBlockRoot' + slotNumber: + $ref: '#/components/schemas/PayloadAttributesV4/properties/slotNumber' + targetGasLimit: + $ref: '#/components/schemas/PayloadAttributesV4/properties/targetGasLimit' + inclusionLists: + title: Inclusion lists + type: array + items: + type: array + items: + $ref: '#/components/schemas/bytes' From bdda9df08d3a51ba7b8726b492c8fae20b0b5039 Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Tue, 29 Sep 2026 13:13:35 +0100 Subject: [PATCH 03/17] engine: move inclusion list claims and grouped inclusion lists into Bogota methods --- src/engine/bogota.md | 40 ++++- src/engine/eip8369.md | 185 --------------------- src/engine/openrpc/methods/forkchoice.yaml | 35 ---- src/engine/openrpc/methods/payload.yaml | 107 ++---------- src/engine/openrpc/schemas/forkchoice.yaml | 32 ---- 5 files changed, 45 insertions(+), 354 deletions(-) delete mode 100644 src/engine/eip8369.md diff --git a/src/engine/bogota.md b/src/engine/bogota.md index ba61fabb7..a6d8953b2 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -13,6 +13,7 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. - [Structures](#structures) - [PayloadAttributesV5](#payloadattributesv5) - [PayloadStatusV2](#payloadstatusv2) + - [InclusionListClaimV1](#inclusionlistclaimv1) - [Routines](#routines) - [Payload building](#payload-building) - [Methods](#methods) @@ -20,6 +21,7 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. - [Request](#request) - [Response](#response) - [Specification](#specification) + - [engine_getPayloadV6](#engine_getpayloadv6) - [engine_getInclusionListV1](#engine_getinclusionlistv1) - [Request](#request-1) - [Response](#response-1) @@ -38,6 +40,8 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. | Name | Value | | - | - | | `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST` | `uint64(8192) = 2**13` | +| `INCLUSION_LIST_COMMITTEE_SIZE` | `uint64(16) = 2**4` | +| `MAX_INCLUSION_LIST_CLAIMS` | `uint64(1024) = 2**10` | ## Structures @@ -52,7 +56,7 @@ This structure has the syntax of [`PayloadAttributesV4`](./amsterdam.md#payloada - `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. - `slotNumber`: `QUANTITY`, 64 Bits - value for the `slotNumber` field of the new payload - `targetGasLimit`: `QUANTITY`, 64 Bits - target value for the `gasLimit` field of the new payload -- `inclusionListTransactions`: `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). +- `inclusionListTransactions`: `Array of Array of DATA` - Array of inclusion lists, one per inclusion list committee member, each an array of transaction objects in the order of that inclusion list. Each transaction object is a byte list (`DATA`) representing `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). ### PayloadStatusV2 @@ -63,19 +67,26 @@ This structure has the syntax of `PayloadStatusV1` and appends a single field: ` - `validationError`: `String|null` - a message providing additional details on the validation error if the payload is classified as `INVALID`. - `inclusionListSatisfied`: `BOOLEAN|null` - whether the payload satisfied the inclusion list constraints if it is deemed `VALID`; `null` otherwise. +### InclusionListClaimV1 + +This structure maps onto the inclusion list claim defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). The fields are encoded as follows: + +- `transactionHash`: `DATA`, 32 Bytes - `keccak256` of the claimed inclusion list transaction, `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). +- `transactionIndex`: `QUANTITY`, 64 Bits - index in `executionPayload.transactions` at which the omission of the claimed transaction is evaluated. + ## Routines ### Payload building This routine follows the same specification as [Payload building](./paris.md#payload-building) with the following changes to the processing flow: -1. Client software **MUST** take `inclusionListTransactions` into account during the payload build process. The built `ExecutionPayload` **MUST** satisfy the inclusion list constraints with respect to `inclusionListTransactions` as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). +1. Client software **MUST** take `inclusionListTransactions` into account during the payload build process. The built `ExecutionPayload`, together with the `inclusionListClaims` returned by [`engine_getPayloadV6`](#engine_getpayloadv6), **MUST** satisfy the inclusion list constraints with respect to `inclusionListTransactions` as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). ## Methods ### engine_newPayloadV6 -Method parameter list is extended with `inclusionListTransactions`. +Method parameter list is extended with `inclusionListTransactions` and `inclusionListClaims`. #### Request @@ -85,7 +96,8 @@ Method parameter list is extended with `inclusionListTransactions`. 2. `expectedBlobVersionedHashes`: `Array of DATA`, 32 Bytes - Array of expected blob versioned hashes to validate. 3. `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. 4. `executionRequests`: `Array of DATA` - List of execution layer triggered requests. Each list element is a `requests` byte array as defined by [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685). The first byte of each element is the `request_type` and the remaining bytes are the `request_data`. Elements of the list **MUST** be ordered by `request_type` in ascending order. Elements with empty `request_data` **MUST** be excluded from the list. - 5. `inclusionListTransactions`: `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). + 5. `inclusionListTransactions`: `Array of Array of DATA` - Array of inclusion lists, one per inclusion list committee member, each an array of transaction objects in the order of that inclusion list. Each transaction object is a byte list (`DATA`) representing `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). + 6. `inclusionListClaims`: `Array of InclusionListClaimV1` - Array of inclusion list claims committed to by the builder of the payload, as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). * timeout: 6s #### Response @@ -99,13 +111,23 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda 1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the payload does not fall within the time frame of the Bogota fork. -2. Client software **MUST** set `inclusionListSatisfied` in the following way: +2. Client software **MUST** return `-32602: Invalid params` error if `inclusionListTransactions` has more than `INCLUSION_LIST_COMMITTEE_SIZE` elements, if the sum of the byte lengths of the transactions in any element exceeds `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`, or if `inclusionListClaims` has more than `MAX_INCLUSION_LIST_CLAIMS` elements. Duplicate, unmatched and out-of-range claims **MUST NOT** cause an error; they are resolved as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). + +3. Client software **MUST** set `inclusionListSatisfied` in the following way: - 1. If the payload is deemed `VALID`, `inclusionListSatisfied` **MUST** be set to whether the payload satisfied the inclusion list constraints. + 1. If the payload is deemed `VALID`, `inclusionListSatisfied` **MUST** be set to whether the payload satisfied the inclusion list constraints with respect to `inclusionListTransactions` and `inclusionListClaims`. 2. Otherwise, `inclusionListSatisfied` **MUST** be `null`. -3. Client software **MUST** retain `inclusionListTransactions` for a payload with `ACCEPTED` status. Client software **MAY** discard them once the payload is no longer the tip of a branch. +4. Client software **MUST** retain `inclusionListTransactions` and `inclusionListClaims` for a payload with `ACCEPTED` status. Client software **MAY** discard them once the payload is no longer the tip of a branch. + +### engine_getPayloadV6 + +For a payload whose `timestamp` falls within the time frame of the Bogota fork, the response of [`engine_getPayloadV6`](./amsterdam.md#engine_getpayloadv6) is extended with a single field: + +- `inclusionListClaims`: `Array of InclusionListClaimV1` - Inclusion list claims for transactions omitted from `executionPayload`, with at most `MAX_INCLUSION_LIST_CLAIMS` elements. + +Each claim **MUST** refer to a transaction of the `inclusionListTransactions` used to build the payload that is omitted from `executionPayload`, and **SHOULD** have an index at which that omission is excused as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). The field **MUST** be omitted for a payload that does not fall within the time frame of the Bogota fork. ### engine_getInclusionListV1 @@ -156,7 +178,7 @@ This method follows the same specification as [`engine_forkchoiceUpdatedV4`](./a 1. Extend point (8) of the `engine_forkchoiceUpdatedV1` [specification](./paris.md#specification-1) by defining the following sequence of checks that **MUST** be run over `payloadAttributes`: - 1. `payloadAttributes` matches the [`PayloadAttributesV5`](#payloadattributesv5) structure, return `-38003: Invalid payload attributes` on failure. + 1. `payloadAttributes` matches the [`PayloadAttributesV5`](#payloadattributesv5) structure and `payloadAttributes.inclusionListTransactions` is within the limits of [`engine_newPayloadV6`](#engine_newpayloadv6), return `-38003: Invalid payload attributes` on failure. 2. `payloadAttributes.timestamp` does not fall within the time frame of the Bogota fork, return `-38005: Unsupported fork` on failure. @@ -164,7 +186,7 @@ This method follows the same specification as [`engine_forkchoiceUpdatedV4`](./a 1. If the payload referenced by `forkchoiceState.headBlockHash` is deemed `VALID`, `payloadStatus.inclusionListSatisfied` **MUST** be set to whether the payload satisfied the inclusion list constraints. - 2. Client software **MUST** use the retained `inclusionListTransactions` if it validates the payload and checks whether the payload satisfies the inclusion list constraints while processing the call. + 2. Client software **MUST** use the retained `inclusionListTransactions` and `inclusionListClaims` if it validates the payload and checks whether the payload satisfies the inclusion list constraints while processing the call. 3. Otherwise, `payloadStatus.inclusionListSatisfied` **MUST** be `null`. diff --git a/src/engine/eip8369.md b/src/engine/eip8369.md deleted file mode 100644 index f167b3f39..000000000 --- a/src/engine/eip8369.md +++ /dev/null @@ -1,185 +0,0 @@ -# Engine API -- EIP-8369 - -Engine API changes for the [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805) rules that apply to the [EIP-8369](https://eips.ethereum.org/EIPS/eip-8369) eligibility profiles. - -This specification is based on and extends [Engine API - Bogota](./bogota.md) specification. - -## Table of contents - - - - -- [Constants](#constants) -- [Structures](#structures) - - [InclusionListClaimV1](#inclusionlistclaimv1) - - [PayloadAttributesV6](#payloadattributesv6) -- [Routines](#routines) - - [Payload building](#payload-building) -- [Methods](#methods) - - [engine_newPayloadV7](#engine_newpayloadv7) - - [Request](#request) - - [Response](#response) - - [Specification](#specification) - - [engine_getPayloadV7](#engine_getpayloadv7) - - [Request](#request-1) - - [Response](#response-1) - - [Specification](#specification-1) - - [engine_forkchoiceUpdatedV6](#engine_forkchoiceupdatedv6) - - [Request](#request-2) - - [Response](#response-2) - - [Specification](#specification-2) - - [Update the methods of previous forks](#update-the-methods-of-previous-forks) - - [Bogota API](#bogota-api) - - - -## Constants - -| Name | Value | -| - | - | -| `INCLUSION_LIST_COMMITTEE_SIZE` | `uint64(16) = 2**4` | -| `MAX_INCLUSION_LIST_CLAIMS` | `uint64(1024) = 2**10` | - -## Structures - -### InclusionListClaimV1 - -This structure maps onto the inclusion list claim defined in EIP-7805. The fields are encoded as follows: - -- `transactionHash`: `DATA`, 32 Bytes - `keccak256` of the claimed inclusion list transaction, `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). -- `transactionIndex`: `QUANTITY`, 64 Bits - index in `executionPayload.transactions` at which the omission of the claimed transaction is evaluated. - -### PayloadAttributesV6 - -This structure has the syntax of [`PayloadAttributesV5`](./bogota.md#payloadattributesv5), with `inclusionListTransactions` replaced by `inclusionLists`. - -- `timestamp`: `QUANTITY`, 64 Bits - value for the `timestamp` field of the new payload -- `prevRandao`: `DATA`, 32 Bytes - value for the `prevRandao` field of the new payload -- `suggestedFeeRecipient`: `DATA`, 20 Bytes - suggested value for the `feeRecipient` field of the new payload -- `withdrawals`: `Array of WithdrawalV1` - Array of withdrawals, each object is an `OBJECT` containing the fields of a `WithdrawalV1` structure. -- `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. -- `slotNumber`: `QUANTITY`, 64 Bits - value for the `slotNumber` field of the new payload -- `targetGasLimit`: `QUANTITY`, 64 Bits - target value for the `gasLimit` field of the new payload -- `inclusionLists`: `Array of Array of DATA` - Array of inclusion lists, with the same encoding and limits as the `inclusionLists` parameter of [`engine_newPayloadV7`](#engine_newpayloadv7). - -## Routines - -### Payload building - -This routine follows the same specification as [Payload building](./bogota.md#payload-building) with the following changes to the processing flow: - -1. Client software **MUST** take `inclusionLists` into account during the payload build process. The built `ExecutionPayload` together with the claims returned by [`engine_getPayloadV7`](#engine_getpayloadv7) **MUST** satisfy the inclusion list constraints with respect to `inclusionLists` as defined in EIP-7805. - -2. To determine which omissions are excused, client software **SHOULD** apply the VERIFY budget fill to each element of `inclusionLists` separately, as defined in EIP-7805, and claim an evaluation index for each admitted Profile 2 transaction it omits that would pass the replay at the end of the payload. - -## Methods - -### engine_newPayloadV7 - -Method parameter list is extended with `inclusionListClaims`, and inclusion list transactions are grouped per inclusion list. - -#### Request - -* method: `engine_newPayloadV7` -* params: - 1. `executionPayload`: [`ExecutionPayloadV4`](./amsterdam.md#executionpayloadv4). - 2. `expectedBlobVersionedHashes`: `Array of DATA`, 32 Bytes - Array of expected blob versioned hashes to validate. - 3. `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. - 4. `executionRequests`: `Array of DATA` - List of execution layer triggered requests. Each list element is a `requests` byte array as defined by [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685). The first byte of each element is the `request_type` and the remaining bytes are the `request_data`. Elements of the list **MUST** be ordered by `request_type` in ascending order. Elements with empty `request_data` **MUST** be excluded from the list. - 5. `inclusionLists`: `Array of Array of DATA` - Array of inclusion lists, one per inclusion list committee member, each an array of transaction objects in the order of that inclusion list. Each transaction object is a byte list (`DATA`) representing `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). - 6. `inclusionListClaims`: `Array of InclusionListClaimV1` - Array of inclusion list claims committed to by the builder of the payload. -* timeout: 6s - -#### Response - -* result: [`PayloadStatusV2`](./bogota.md#payloadstatusv2) -* error: code and message set in case an exception happens while processing the payload. - -#### Specification - -This method follows the same specification as [`engine_newPayloadV6`](./bogota.md#engine_newpayloadv6) with the following changes: - -1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the payload is less than the EIP-8369 activation timestamp. - -2. Client software **MUST** return `-32602: Invalid params` error if any of the following holds: - - 1. `inclusionLists` has more than `INCLUSION_LIST_COMMITTEE_SIZE` elements. - - 2. The sum of the byte lengths of the transactions in an element of `inclusionLists` exceeds `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. The total byte length of all inclusion list transactions is therefore at most `INCLUSION_LIST_COMMITTEE_SIZE * MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. - - 3. `inclusionListClaims` has more than `MAX_INCLUSION_LIST_CLAIMS` elements. - -3. Client software **MUST** determine whether the payload satisfied the inclusion list constraints with respect to `inclusionLists` and `inclusionListClaims` as defined in EIP-7805. Duplicate, unmatched and out-of-range claims **MUST NOT** cause an error; they are resolved as defined in EIP-7805. - -4. Client software **MUST** retain `inclusionLists` and `inclusionListClaims` for a payload with `ACCEPTED` status. Client software **MAY** discard them once the payload is no longer the tip of a branch. - -### engine_getPayloadV7 - -This method is updated to return `inclusionListClaims`. - -#### Request - -* method: `engine_getPayloadV7` -* params: - 1. `payloadId`: `DATA`, 8 Bytes - Identifier of the payload build process -* timeout: 1s - -#### Response - -* result: `object` - - `executionPayload`: [`ExecutionPayloadV4`](./amsterdam.md#executionpayloadv4) - - `blockValue` : `QUANTITY`, 256 Bits - The expected value to be received by the `feeRecipient` in wei - - `blobsBundle`: [`BlobsBundleV2`](./osaka.md#blobsbundlev2) - Bundle with data corresponding to blob transactions included into `executionPayload` - - `shouldOverrideBuilder` : `BOOLEAN` - Suggestion from the execution layer to use this `executionPayload` instead of an externally provided one - - `executionRequests`: `Array of DATA` - Execution layer triggered requests obtained from the `executionPayload` transaction execution. - - `inclusionListClaims`: `Array of InclusionListClaimV1` - Inclusion list claims for transactions omitted from `executionPayload`. -* error: code and message set in case an exception happens while getting the payload. - -#### Specification - -This method follows the same specification as [`engine_getPayloadV6`](./amsterdam.md#engine_getpayloadv6) with the following changes: - -1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the built payload is less than the EIP-8369 activation timestamp. - -2. `inclusionListClaims` **MUST NOT** have more than `MAX_INCLUSION_LIST_CLAIMS` elements. Each claim **MUST** refer to a transaction of the `inclusionLists` used to build the payload that is omitted from `executionPayload`, and **SHOULD** have an index at which that omission is excused as defined in EIP-7805. - -### engine_forkchoiceUpdatedV6 - -#### Request - -* method: `engine_forkchoiceUpdatedV6` -* params: - 1. `forkchoiceState`: [`ForkchoiceStateV1`](./paris.md#forkchoicestatev1). - 2. `payloadAttributes`: `Object|null` - Instance of [`PayloadAttributesV6`](#payloadattributesv6) or `null`. - 3. `custodyColumns`: `DATA|null`, 16 Bytes - Interpreted as a bitarray of length `CELLS_PER_EXT_BLOB` indicating which column indices form the CL's custody set, or `null` if the CL does not provide custody services. -* timeout: 8s - -#### Response - -Refer to the response for [`engine_forkchoiceUpdatedV5`](./bogota.md#engine_forkchoiceupdatedv5). - -#### Specification - -This method follows the same specification as [`engine_forkchoiceUpdatedV5`](./bogota.md#engine_forkchoiceupdatedv5) with the following changes to the processing flow: - -1. Extend point (8) of the `engine_forkchoiceUpdatedV1` [specification](./paris.md#specification-1) by defining the following sequence of checks that **MUST** be run over `payloadAttributes`: - - 1. `payloadAttributes` matches the [`PayloadAttributesV6`](#payloadattributesv6) structure and `payloadAttributes.inclusionLists` is within the limits of [`engine_newPayloadV7`](#engine_newpayloadv7), return `-38003: Invalid payload attributes` on failure. - - 2. `payloadAttributes.timestamp` is less than the EIP-8369 activation timestamp, return `-38005: Unsupported fork` on failure. - -2. Client software **MUST** use the retained `inclusionLists` and `inclusionListClaims` if it validates the payload referenced by `forkchoiceState.headBlockHash` and checks whether it satisfies the inclusion list constraints while processing the call. - -### Update the methods of previous forks - -#### Bogota API - -For the following methods: - -- [`engine_newPayloadV6`](./bogota.md#engine_newpayloadv6) -- [`engine_getPayloadV6`](./amsterdam.md#engine_getpayloadv6) -- [`engine_forkchoiceUpdatedV5`](./bogota.md#engine_forkchoiceupdatedv5) - -a validation **MUST** be added: - -1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the payload, or of `payloadAttributes` for `engine_forkchoiceUpdatedV5`, is greater than or equal to the EIP-8369 activation timestamp. diff --git a/src/engine/openrpc/methods/forkchoice.yaml b/src/engine/openrpc/methods/forkchoice.yaml index e50838573..badee9ff3 100644 --- a/src/engine/openrpc/methods/forkchoice.yaml +++ b/src/engine/openrpc/methods/forkchoice.yaml @@ -231,38 +231,3 @@ message: Unsupported fork - code: -38006 message: Too deep reorg -- name: engine_forkchoiceUpdatedV6 - summary: Updates the forkchoice state - externalDocs: - description: Method specification - url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eip8369.md#engine_forkchoiceupdatedv6 - params: - - name: Forkchoice state - required: true - schema: - $ref: '#/components/schemas/ForkchoiceStateV1' - - name: Payload attributes - required: false - schema: - $ref: '#/components/schemas/PayloadAttributesV6' - - name: Custody columns - required: false - schema: - oneOf: - - $ref: '#/components/schemas/bytes16' - - type: 'null' - result: - name: Response object - schema: - $ref: '#/components/schemas/ForkchoiceUpdatedResponseV2' - errors: - - code: -38002 - message: Invalid forkchoice state - - code: -38003 - message: Invalid payload attributes - - code: -32602 - message: Invalid params - - code: -38005 - message: Unsupported fork - - code: -38006 - message: Too deep reorg diff --git a/src/engine/openrpc/methods/payload.yaml b/src/engine/openrpc/methods/payload.yaml index 6a242ae5f..a09e9b342 100644 --- a/src/engine/openrpc/methods/payload.yaml +++ b/src/engine/openrpc/methods/payload.yaml @@ -1105,7 +1105,15 @@ schema: type: array items: - $ref: '#/components/schemas/bytes' + type: array + items: + $ref: '#/components/schemas/bytes' + - name: Inclusion list claims + required: true + schema: + type: array + items: + $ref: '#/components/schemas/InclusionListClaimV1' result: name: Payload status schema: @@ -1148,6 +1156,11 @@ type: array items: $ref: '#/components/schemas/bytes' + inclusionListClaims: + title: Inclusion list claims, present only for Bogota payloads + type: array + items: + $ref: '#/components/schemas/InclusionListClaimV1' errors: - code: -38001 message: Unknown payload @@ -1211,95 +1224,3 @@ executionRequests: - '0x96a96086cff07df17668f35f7418ef8798079167e3f4f9b72ecde17b28226137cf454ab1dd20ef5d924786ab3483c2f9003f5102dabe0a27b1746098d1dc17a5d3fbd478759fea9287e4e419b3c3cef20100000000000000b1acdb2c4d3df3f1b8d3bfd33421660df358d84d78d16c4603551935f4b67643373e7eb63dcb16ec359be0ec41fee33b03a16e80745f2374ff1d3c352508ac5d857c6476d3c3bcf7e6ca37427c9209f17be3af5264c0e2132b3dd1156c28b4e9f000000000000000a5c85a60ba2905c215f6a12872e62b1ee037051364244043a5f639aa81b04a204c55e7cc851f29c7c183be253ea1510b001db70c485b6264692f26b8aeaab5b0c384180df8e2184a21a808a3ec8e86ca01000000000000009561731785b48cf1886412234531e4940064584463e96ac63a1a154320227e333fb51addc4a89b7e0d3f862d7c1fd4ea03bd8eb3d8806f1e7daf591cbbbb92b0beb74d13c01617f22c5026b4f9f9f294a8a7c32db895de3b01bee0132c9209e1f100000000000000' - '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b85103a5617937691dfeeb89b86a80d5dc9e3c9d3a1a0e7ce311e26e0bb732eabaa47ffa288f0d54de28209a62a7d29d0000000000000000000000000000000000000000000000000000010f698daeed734da114470da559bd4b4c7259e1f7952555241dcbc90cf194a2ef676fc6005f3672fada2a3645edb297a75530100000000000000' -- name: engine_newPayloadV7 - summary: Runs execution payload validation - externalDocs: - description: Method specification - url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eip8369.md#engine_newpayloadv7 - params: - - name: Execution payload - required: true - schema: - $ref: '#/components/schemas/ExecutionPayloadV4' - - name: Expected blob versioned hashes - required: true - schema: - type: array - items: - $ref: '#/components/schemas/hash32' - - name: Parent beacon block root - required: true - schema: - $ref: '#/components/schemas/hash32' - - name: Execution requests - required: true - schema: - type: array - items: - $ref: '#/components/schemas/bytes' - - name: Inclusion lists - required: true - schema: - type: array - items: - type: array - items: - $ref: '#/components/schemas/bytes' - - name: Inclusion list claims - required: true - schema: - type: array - items: - $ref: '#/components/schemas/InclusionListClaimV1' - result: - name: Payload status - schema: - $ref: '#/components/schemas/PayloadStatusV2' - errors: - - code: -32602 - message: Invalid params - - code: -38005 - message: Unsupported fork -- name: engine_getPayloadV7 - summary: Obtains execution payload from payload build process - externalDocs: - description: Method specification - url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eip8369.md#engine_getpayloadv7 - params: - - name: Payload id - required: true - schema: - $ref: '#/components/schemas/bytes8' - result: - name: Response object - schema: - type: object - required: - - executionPayload - - blockValue - - blobsBundle - - shouldOverrideBuilder - - executionRequests - - inclusionListClaims - properties: - executionPayload: - $ref: '#/components/schemas/ExecutionPayloadV4' - blockValue: - $ref: '#/components/schemas/uint256' - blobsBundle: - $ref: '#/components/schemas/BlobsBundleV2' - shouldOverrideBuilder: - type: boolean - executionRequests: - type: array - items: - $ref: '#/components/schemas/bytes' - inclusionListClaims: - type: array - items: - $ref: '#/components/schemas/InclusionListClaimV1' - errors: - - code: -38001 - message: Unknown payload - - code: -38005 - message: Unsupported fork diff --git a/src/engine/openrpc/schemas/forkchoice.yaml b/src/engine/openrpc/schemas/forkchoice.yaml index 8c7d44313..ab50c0a20 100644 --- a/src/engine/openrpc/schemas/forkchoice.yaml +++ b/src/engine/openrpc/schemas/forkchoice.yaml @@ -155,38 +155,6 @@ PayloadAttributesV5: inclusionListTransactions: title: Inclusion list transactions type: array - items: - $ref: '#/components/schemas/bytes' -PayloadAttributesV6: - title: Payload attributes object V6 - type: object - required: - - timestamp - - prevRandao - - suggestedFeeRecipient - - withdrawals - - parentBeaconBlockRoot - - slotNumber - - targetGasLimit - - inclusionLists - properties: - timestamp: - $ref: '#/components/schemas/PayloadAttributesV4/properties/timestamp' - prevRandao: - $ref: '#/components/schemas/PayloadAttributesV4/properties/prevRandao' - suggestedFeeRecipient: - $ref: '#/components/schemas/PayloadAttributesV4/properties/suggestedFeeRecipient' - withdrawals: - $ref: '#/components/schemas/PayloadAttributesV4/properties/withdrawals' - parentBeaconBlockRoot: - $ref: '#/components/schemas/PayloadAttributesV4/properties/parentBeaconBlockRoot' - slotNumber: - $ref: '#/components/schemas/PayloadAttributesV4/properties/slotNumber' - targetGasLimit: - $ref: '#/components/schemas/PayloadAttributesV4/properties/targetGasLimit' - inclusionLists: - title: Inclusion lists - type: array items: type: array items: From 60b0306e5f0278701ebcf2d1dc170915a390ec65 Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Tue, 29 Sep 2026 14:03:53 +0100 Subject: [PATCH 04/17] engine: return inclusion list claims from a new engine_getPayloadV7 --- src/engine/bogota.md | 42 +++++++++++++++++----- src/engine/openrpc/methods/payload.yaml | 48 ++++++++++++++++++++++--- 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/src/engine/bogota.md b/src/engine/bogota.md index a6d8953b2..3a00609dd 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -21,15 +21,18 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. - [Request](#request) - [Response](#response) - [Specification](#specification) - - [engine_getPayloadV6](#engine_getpayloadv6) - - [engine_getInclusionListV1](#engine_getinclusionlistv1) + - [engine_getPayloadV7](#engine_getpayloadv7) - [Request](#request-1) - [Response](#response-1) - [Specification](#specification-1) - - [engine_forkchoiceUpdatedV5](#engine_forkchoiceupdatedv5) + - [engine_getInclusionListV1](#engine_getinclusionlistv1) - [Request](#request-2) - [Response](#response-2) - [Specification](#specification-2) + - [engine_forkchoiceUpdatedV5](#engine_forkchoiceupdatedv5) + - [Request](#request-3) + - [Response](#response-3) + - [Specification](#specification-3) - [Update the methods of previous forks](#update-the-methods-of-previous-forks) - [Amsterdam API](#amsterdam-api) @@ -80,7 +83,7 @@ This structure maps onto the inclusion list claim defined in [EIP-7805](https:// This routine follows the same specification as [Payload building](./paris.md#payload-building) with the following changes to the processing flow: -1. Client software **MUST** take `inclusionListTransactions` into account during the payload build process. The built `ExecutionPayload`, together with the `inclusionListClaims` returned by [`engine_getPayloadV6`](#engine_getpayloadv6), **MUST** satisfy the inclusion list constraints with respect to `inclusionListTransactions` as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). +1. Client software **MUST** take `inclusionListTransactions` into account during the payload build process. The built `ExecutionPayload`, together with the `inclusionListClaims` returned by [`engine_getPayloadV7`](#engine_getpayloadv7), **MUST** satisfy the inclusion list constraints with respect to `inclusionListTransactions` as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). ## Methods @@ -121,13 +124,35 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda 4. Client software **MUST** retain `inclusionListTransactions` and `inclusionListClaims` for a payload with `ACCEPTED` status. Client software **MAY** discard them once the payload is no longer the tip of a branch. -### engine_getPayloadV6 +### engine_getPayloadV7 + +This method is updated to return `inclusionListClaims`. + +#### Request + +* method: `engine_getPayloadV7` +* params: + 1. `payloadId`: `DATA`, 8 Bytes - Identifier of the payload build process +* timeout: 1s + +#### Response + +* result: `object` + - `executionPayload`: [`ExecutionPayloadV4`](./amsterdam.md#executionpayloadv4) + - `blockValue` : `QUANTITY`, 256 Bits - The expected value to be received by the `feeRecipient` in wei + - `blobsBundle`: [`BlobsBundleV2`](./osaka.md#blobsbundlev2) - Bundle with data corresponding to blob transactions included into `executionPayload` + - `shouldOverrideBuilder` : `BOOLEAN` - Suggestion from the execution layer to use this `executionPayload` instead of an externally provided one + - `executionRequests`: `Array of DATA` - Execution layer triggered requests obtained from the `executionPayload` transaction execution. + - `inclusionListClaims`: `Array of InclusionListClaimV1` - Inclusion list claims for transactions omitted from `executionPayload`. +* error: code and message set in case an exception happens while getting the payload. + +#### Specification -For a payload whose `timestamp` falls within the time frame of the Bogota fork, the response of [`engine_getPayloadV6`](./amsterdam.md#engine_getpayloadv6) is extended with a single field: +This method follows the same specification as [`engine_getPayloadV6`](./amsterdam.md#engine_getpayloadv6) with the following changes: -- `inclusionListClaims`: `Array of InclusionListClaimV1` - Inclusion list claims for transactions omitted from `executionPayload`, with at most `MAX_INCLUSION_LIST_CLAIMS` elements. +1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the built payload does not fall within the time frame of the Bogota fork. -Each claim **MUST** refer to a transaction of the `inclusionListTransactions` used to build the payload that is omitted from `executionPayload`, and **SHOULD** have an index at which that omission is excused as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). The field **MUST** be omitted for a payload that does not fall within the time frame of the Bogota fork. +2. `inclusionListClaims` **MUST NOT** have more than `MAX_INCLUSION_LIST_CLAIMS` elements. Each claim **MUST** refer to a transaction of the `inclusionListTransactions` used to build the payload that is omitted from `executionPayload`, and **SHOULD** have an index at which that omission is excused as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). ### engine_getInclusionListV1 @@ -197,6 +222,7 @@ This method follows the same specification as [`engine_forkchoiceUpdatedV4`](./a For the following methods: - [`engine_newPayloadV5`](./amsterdam.md#engine_newpayloadv5) +- [`engine_getPayloadV6`](./amsterdam.md#engine_getpayloadv6) - [`engine_forkchoiceUpdatedV4`](./amsterdam.md#engine_forkchoiceupdatedv4) a validation **MUST** be added: diff --git a/src/engine/openrpc/methods/payload.yaml b/src/engine/openrpc/methods/payload.yaml index a09e9b342..ff3c658ae 100644 --- a/src/engine/openrpc/methods/payload.yaml +++ b/src/engine/openrpc/methods/payload.yaml @@ -1156,11 +1156,6 @@ type: array items: $ref: '#/components/schemas/bytes' - inclusionListClaims: - title: Inclusion list claims, present only for Bogota payloads - type: array - items: - $ref: '#/components/schemas/InclusionListClaimV1' errors: - code: -38001 message: Unknown payload @@ -1224,3 +1219,46 @@ executionRequests: - '0x96a96086cff07df17668f35f7418ef8798079167e3f4f9b72ecde17b28226137cf454ab1dd20ef5d924786ab3483c2f9003f5102dabe0a27b1746098d1dc17a5d3fbd478759fea9287e4e419b3c3cef20100000000000000b1acdb2c4d3df3f1b8d3bfd33421660df358d84d78d16c4603551935f4b67643373e7eb63dcb16ec359be0ec41fee33b03a16e80745f2374ff1d3c352508ac5d857c6476d3c3bcf7e6ca37427c9209f17be3af5264c0e2132b3dd1156c28b4e9f000000000000000a5c85a60ba2905c215f6a12872e62b1ee037051364244043a5f639aa81b04a204c55e7cc851f29c7c183be253ea1510b001db70c485b6264692f26b8aeaab5b0c384180df8e2184a21a808a3ec8e86ca01000000000000009561731785b48cf1886412234531e4940064584463e96ac63a1a154320227e333fb51addc4a89b7e0d3f862d7c1fd4ea03bd8eb3d8806f1e7daf591cbbbb92b0beb74d13c01617f22c5026b4f9f9f294a8a7c32db895de3b01bee0132c9209e1f100000000000000' - '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b85103a5617937691dfeeb89b86a80d5dc9e3c9d3a1a0e7ce311e26e0bb732eabaa47ffa288f0d54de28209a62a7d29d0000000000000000000000000000000000000000000000000000010f698daeed734da114470da559bd4b4c7259e1f7952555241dcbc90cf194a2ef676fc6005f3672fada2a3645edb297a75530100000000000000' +- name: engine_getPayloadV7 + summary: Obtains execution payload from payload build process + externalDocs: + description: Method specification + url: https://github.com/ethereum/execution-apis/blob/main/src/engine/bogota.md#engine_getpayloadv7 + params: + - name: Payload id + required: true + schema: + $ref: '#/components/schemas/bytes8' + result: + name: Response object + schema: + type: object + required: + - executionPayload + - blockValue + - blobsBundle + - shouldOverrideBuilder + - executionRequests + - inclusionListClaims + properties: + executionPayload: + $ref: '#/components/schemas/ExecutionPayloadV4' + blockValue: + $ref: '#/components/schemas/uint256' + blobsBundle: + $ref: '#/components/schemas/BlobsBundleV2' + shouldOverrideBuilder: + type: boolean + executionRequests: + type: array + items: + $ref: '#/components/schemas/bytes' + inclusionListClaims: + type: array + items: + $ref: '#/components/schemas/InclusionListClaimV1' + errors: + - code: -38001 + message: Unknown payload + - code: -38005 + message: Unsupported fork From b31d15a49282b62a41b9f5f03ee54886cbe868e1 Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Tue, 29 Sep 2026 14:21:34 +0100 Subject: [PATCH 05/17] engine: replace grouped inclusion lists with membership bitvectors --- src/engine/bogota.md | 32 ++++++++++++++-------- src/engine/openrpc/methods/payload.yaml | 10 +++++-- src/engine/openrpc/schemas/forkchoice.yaml | 10 +++++-- src/engine/openrpc/schemas/payload.yaml | 4 +++ 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/engine/bogota.md b/src/engine/bogota.md index 3a00609dd..e62fcac32 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -50,7 +50,7 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. ### PayloadAttributesV5 -This structure has the syntax of [`PayloadAttributesV4`](./amsterdam.md#payloadattributesv4) and appends a single field: `inclusionListTransactions`. +This structure has the syntax of [`PayloadAttributesV4`](./amsterdam.md#payloadattributesv4) and appends the fields `inclusionListTransactions` and `inclusionListMembership`. - `timestamp`: `QUANTITY`, 64 Bits - value for the `timestamp` field of the new payload - `prevRandao`: `DATA`, 32 Bytes - value for the `prevRandao` field of the new payload @@ -59,7 +59,8 @@ This structure has the syntax of [`PayloadAttributesV4`](./amsterdam.md#payloada - `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. - `slotNumber`: `QUANTITY`, 64 Bits - value for the `slotNumber` field of the new payload - `targetGasLimit`: `QUANTITY`, 64 Bits - target value for the `gasLimit` field of the new payload -- `inclusionListTransactions`: `Array of Array of DATA` - Array of inclusion lists, one per inclusion list committee member, each an array of transaction objects in the order of that inclusion list. Each transaction object is a byte list (`DATA`) representing `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). +- `inclusionListTransactions`: `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). +- `inclusionListMembership`: `Array of DATA`, 2 Bytes - Array of inclusion list memberships, one per element of `inclusionListTransactions` at the same position. Each element is a bitvector of length `INCLUSION_LIST_COMMITTEE_SIZE`, encoded as SSZ `Bitvector[INCLUSION_LIST_COMMITTEE_SIZE]`, in which bit `i` is set if and only if the inclusion list of the inclusion list committee member at committee position `i` carries the transaction. ### PayloadStatusV2 @@ -83,13 +84,13 @@ This structure maps onto the inclusion list claim defined in [EIP-7805](https:// This routine follows the same specification as [Payload building](./paris.md#payload-building) with the following changes to the processing flow: -1. Client software **MUST** take `inclusionListTransactions` into account during the payload build process. The built `ExecutionPayload`, together with the `inclusionListClaims` returned by [`engine_getPayloadV7`](#engine_getpayloadv7), **MUST** satisfy the inclusion list constraints with respect to `inclusionListTransactions` as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). +1. Client software **MUST** take `inclusionListTransactions` into account during the payload build process. The built `ExecutionPayload`, together with the `inclusionListClaims` returned by [`engine_getPayloadV7`](#engine_getpayloadv7), **MUST** satisfy the inclusion list constraints with respect to `inclusionListTransactions` and `inclusionListMembership` as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). ## Methods ### engine_newPayloadV6 -Method parameter list is extended with `inclusionListTransactions` and `inclusionListClaims`. +Method parameter list is extended with `inclusionListTransactions`, `inclusionListMembership` and `inclusionListClaims`. #### Request @@ -99,8 +100,9 @@ Method parameter list is extended with `inclusionListTransactions` and `inclusio 2. `expectedBlobVersionedHashes`: `Array of DATA`, 32 Bytes - Array of expected blob versioned hashes to validate. 3. `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. 4. `executionRequests`: `Array of DATA` - List of execution layer triggered requests. Each list element is a `requests` byte array as defined by [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685). The first byte of each element is the `request_type` and the remaining bytes are the `request_data`. Elements of the list **MUST** be ordered by `request_type` in ascending order. Elements with empty `request_data` **MUST** be excluded from the list. - 5. `inclusionListTransactions`: `Array of Array of DATA` - Array of inclusion lists, one per inclusion list committee member, each an array of transaction objects in the order of that inclusion list. Each transaction object is a byte list (`DATA`) representing `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). - 6. `inclusionListClaims`: `Array of InclusionListClaimV1` - Array of inclusion list claims committed to by the builder of the payload, as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). + 5. `inclusionListTransactions`: `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). + 6. `inclusionListMembership`: `Array of DATA`, 2 Bytes - Array of inclusion list memberships, one per element of `inclusionListTransactions` at the same position. Each element is a bitvector of length `INCLUSION_LIST_COMMITTEE_SIZE`, encoded as SSZ `Bitvector[INCLUSION_LIST_COMMITTEE_SIZE]`, in which bit `i` is set if and only if the inclusion list of the inclusion list committee member at committee position `i` carries the transaction. + 7. `inclusionListClaims`: `Array of InclusionListClaimV1` - Array of inclusion list claims committed to by the builder of the payload, as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). * timeout: 6s #### Response @@ -114,15 +116,23 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda 1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the payload does not fall within the time frame of the Bogota fork. -2. Client software **MUST** return `-32602: Invalid params` error if `inclusionListTransactions` has more than `INCLUSION_LIST_COMMITTEE_SIZE` elements, if the sum of the byte lengths of the transactions in any element exceeds `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`, or if `inclusionListClaims` has more than `MAX_INCLUSION_LIST_CLAIMS` elements. Duplicate, unmatched and out-of-range claims **MUST NOT** cause an error; they are resolved as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). +2. Client software **MUST** return `-32602: Invalid params` error if any of the following holds: + + 1. `inclusionListMembership` does not have the same number of elements as `inclusionListTransactions`. + + 2. An element of `inclusionListMembership` is not exactly `INCLUSION_LIST_COMMITTEE_SIZE / 8` bytes, or has no bit set. + + 3. For some committee position `i`, the sum of the byte lengths of the transactions whose membership has bit `i` set exceeds `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. + + 4. `inclusionListClaims` has more than `MAX_INCLUSION_LIST_CLAIMS` elements. Duplicate, unmatched and out-of-range claims **MUST NOT** cause an error; they are resolved as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). 3. Client software **MUST** set `inclusionListSatisfied` in the following way: - 1. If the payload is deemed `VALID`, `inclusionListSatisfied` **MUST** be set to whether the payload satisfied the inclusion list constraints with respect to `inclusionListTransactions` and `inclusionListClaims`. + 1. If the payload is deemed `VALID`, `inclusionListSatisfied` **MUST** be set to whether the payload satisfied the inclusion list constraints with respect to `inclusionListTransactions`, `inclusionListMembership` and `inclusionListClaims`. 2. Otherwise, `inclusionListSatisfied` **MUST** be `null`. -4. Client software **MUST** retain `inclusionListTransactions` and `inclusionListClaims` for a payload with `ACCEPTED` status. Client software **MAY** discard them once the payload is no longer the tip of a branch. +4. Client software **MUST** retain `inclusionListTransactions`, `inclusionListMembership` and `inclusionListClaims` for a payload with `ACCEPTED` status. Client software **MAY** discard them once the payload is no longer the tip of a branch. ### engine_getPayloadV7 @@ -203,7 +213,7 @@ This method follows the same specification as [`engine_forkchoiceUpdatedV4`](./a 1. Extend point (8) of the `engine_forkchoiceUpdatedV1` [specification](./paris.md#specification-1) by defining the following sequence of checks that **MUST** be run over `payloadAttributes`: - 1. `payloadAttributes` matches the [`PayloadAttributesV5`](#payloadattributesv5) structure and `payloadAttributes.inclusionListTransactions` is within the limits of [`engine_newPayloadV6`](#engine_newpayloadv6), return `-38003: Invalid payload attributes` on failure. + 1. `payloadAttributes` matches the [`PayloadAttributesV5`](#payloadattributesv5) structure and `payloadAttributes.inclusionListTransactions` and `payloadAttributes.inclusionListMembership` satisfy the conditions of point (2) of [`engine_newPayloadV6`](#engine_newpayloadv6), return `-38003: Invalid payload attributes` on failure. 2. `payloadAttributes.timestamp` does not fall within the time frame of the Bogota fork, return `-38005: Unsupported fork` on failure. @@ -211,7 +221,7 @@ This method follows the same specification as [`engine_forkchoiceUpdatedV4`](./a 1. If the payload referenced by `forkchoiceState.headBlockHash` is deemed `VALID`, `payloadStatus.inclusionListSatisfied` **MUST** be set to whether the payload satisfied the inclusion list constraints. - 2. Client software **MUST** use the retained `inclusionListTransactions` and `inclusionListClaims` if it validates the payload and checks whether the payload satisfies the inclusion list constraints while processing the call. + 2. Client software **MUST** use the retained `inclusionListTransactions`, `inclusionListMembership` and `inclusionListClaims` if it validates the payload and checks whether the payload satisfies the inclusion list constraints while processing the call. 3. Otherwise, `payloadStatus.inclusionListSatisfied` **MUST** be `null`. diff --git a/src/engine/openrpc/methods/payload.yaml b/src/engine/openrpc/methods/payload.yaml index ff3c658ae..65a3b34d9 100644 --- a/src/engine/openrpc/methods/payload.yaml +++ b/src/engine/openrpc/methods/payload.yaml @@ -1105,9 +1105,13 @@ schema: type: array items: - type: array - items: - $ref: '#/components/schemas/bytes' + $ref: '#/components/schemas/bytes' + - name: Inclusion list membership + required: true + schema: + type: array + items: + $ref: '#/components/schemas/InclusionListMembershipV1' - name: Inclusion list claims required: true schema: diff --git a/src/engine/openrpc/schemas/forkchoice.yaml b/src/engine/openrpc/schemas/forkchoice.yaml index ab50c0a20..cc7e63a25 100644 --- a/src/engine/openrpc/schemas/forkchoice.yaml +++ b/src/engine/openrpc/schemas/forkchoice.yaml @@ -137,6 +137,7 @@ PayloadAttributesV5: - slotNumber - targetGasLimit - inclusionListTransactions + - inclusionListMembership properties: timestamp: $ref: '#/components/schemas/PayloadAttributesV4/properties/timestamp' @@ -156,6 +157,9 @@ PayloadAttributesV5: title: Inclusion list transactions type: array items: - type: array - items: - $ref: '#/components/schemas/bytes' + $ref: '#/components/schemas/bytes' + inclusionListMembership: + title: Inclusion list membership + type: array + items: + $ref: '#/components/schemas/InclusionListMembershipV1' diff --git a/src/engine/openrpc/schemas/payload.yaml b/src/engine/openrpc/schemas/payload.yaml index 6fde404a5..ae97901ea 100644 --- a/src/engine/openrpc/schemas/payload.yaml +++ b/src/engine/openrpc/schemas/payload.yaml @@ -433,3 +433,7 @@ InclusionListClaimV1: transactionIndex: title: Transaction index $ref: '#/components/schemas/uint64' +InclusionListMembershipV1: + title: Inclusion list membership bitvector over the inclusion list committee + type: string + pattern: ^0x[0-9a-f]{4}$ From 4f0c98baf38a01a0386d770842711b9eadc12021 Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Tue, 29 Sep 2026 14:53:48 +0100 Subject: [PATCH 06/17] engine: bound the Profile 2 VERIFY cost of engine_getInclusionListV1 --- src/engine/bogota.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/engine/bogota.md b/src/engine/bogota.md index e62fcac32..5de338be0 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -187,6 +187,8 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 3. The total byte length of the transaction list **MUST NOT** exceed `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. + 4. When [EIP-8141](https://eips.ethereum.org/EIPS/eip-8141) is active, the total VERIFY budget cost of the Profile 2 candidates in the transaction list **MUST NOT** exceed `MAX_VERIFY_GAS_PER_IL`, with the cost, the candidates and the constant as defined in [EIP-8369](https://eips.ethereum.org/EIPS/eip-8369). + 2. The strategy for selecting transactions is implementation dependent. ### engine_forkchoiceUpdatedV5 From 0a7ac8d7c9084a76d9f20b7bcd038e2456f6c144 Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Thu, 8 Oct 2026 13:26:56 +0100 Subject: [PATCH 07/17] engine: set MAX_INCLUSION_LIST_CLAIMS to 2**12 --- src/engine/bogota.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/bogota.md b/src/engine/bogota.md index 5de338be0..71837359b 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -44,7 +44,7 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. | - | - | | `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST` | `uint64(8192) = 2**13` | | `INCLUSION_LIST_COMMITTEE_SIZE` | `uint64(16) = 2**4` | -| `MAX_INCLUSION_LIST_CLAIMS` | `uint64(1024) = 2**10` | +| `MAX_INCLUSION_LIST_CLAIMS` | `uint64(4096) = 2**12` | ## Structures @@ -187,7 +187,7 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 3. The total byte length of the transaction list **MUST NOT** exceed `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. - 4. When [EIP-8141](https://eips.ethereum.org/EIPS/eip-8141) is active, the total VERIFY budget cost of the Profile 2 candidates in the transaction list **MUST NOT** exceed `MAX_VERIFY_GAS_PER_IL`, with the cost, the candidates and the constant as defined in [EIP-8369](https://eips.ethereum.org/EIPS/eip-8369). + 4. When [EIP-8141](https://eips.ethereum.org/EIPS/eip-8141) is active, the total VERIFY budget cost of the Profile 2 candidates in the transaction list **MUST NOT** exceed `MAX_VERIFY_GAS_PER_IL`, with the cost, the candidates and the constant as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). 2. The strategy for selecting transactions is implementation dependent. From 33104ce787932af843fdfb8c8dc7b7e313ed934c Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Sat, 10 Oct 2026 01:48:23 +0100 Subject: [PATCH 08/17] engine: bind inclusion verdicts to explicit claim context --- src/engine/bogota.md | 35 +++++------ src/engine/openrpc/methods/forkchoice.yaml | 6 +- .../openrpc/methods/inclusion_list.yaml | 3 +- src/engine/openrpc/methods/payload.yaml | 16 ++--- src/engine/openrpc/schemas/forkchoice.yaml | 22 +------ src/engine/openrpc/schemas/payload.yaml | 59 +++++++++++++------ 6 files changed, 71 insertions(+), 70 deletions(-) diff --git a/src/engine/bogota.md b/src/engine/bogota.md index 71837359b..eebacf058 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -45,6 +45,9 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. | `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST` | `uint64(8192) = 2**13` | | `INCLUSION_LIST_COMMITTEE_SIZE` | `uint64(16) = 2**4` | | `MAX_INCLUSION_LIST_CLAIMS` | `uint64(4096) = 2**12` | +| `MAX_VERIFY_GAS_PER_IL` | `uint64(1048576) = 2**20` | + +The VERIFY budget and claim cap are defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805#constants), including their activation conditions. ## Structures @@ -62,6 +65,8 @@ This structure has the syntax of [`PayloadAttributesV4`](./amsterdam.md#payloada - `inclusionListTransactions`: `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). - `inclusionListMembership`: `Array of DATA`, 2 Bytes - Array of inclusion list memberships, one per element of `inclusionListTransactions` at the same position. Each element is a bitvector of length `INCLUSION_LIST_COMMITTEE_SIZE`, encoded as SSZ `Bitvector[INCLUSION_LIST_COMMITTEE_SIZE]`, in which bit `i` is set if and only if the inclusion list of the inclusion list committee member at committee position `i` carries the transaction. +The transaction list contains distinct, nonempty byte strings; its order is unrestricted. Membership uses only the inclusion lists selected by the consensus layer under EIP-7805. Bit `i` is bit `i % 8` of byte `i // 8`, with bit zero the least significant bit: committee positions `{0, 9}` encode as `0x0102`, and `{15}` as `0x0080`. The same rules apply to `engine_newPayloadV6`. + ### PayloadStatusV2 This structure has the syntax of `PayloadStatusV1` and appends a single field: `inclusionListSatisfied` @@ -78,6 +83,8 @@ This structure maps onto the inclusion list claim defined in [EIP-7805](https:// - `transactionHash`: `DATA`, 32 Bytes - `keccak256` of the claimed inclusion list transaction, `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). - `transactionIndex`: `QUANTITY`, 64 Bits - index in `executionPayload.transactions` at which the omission of the claimed transaction is evaluated. +Index zero is before the first transaction; `len(executionPayload.transactions)` is the end of the payload. The claim list retains its committed order and duplicates. The consensus layer checks its commitment; the execution layer applies EIP-7805's evaluation rules. + ## Routines ### Payload building @@ -118,21 +125,23 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda 2. Client software **MUST** return `-32602: Invalid params` error if any of the following holds: - 1. `inclusionListMembership` does not have the same number of elements as `inclusionListTransactions`. + 1. `inclusionListTransactions` contains an empty or duplicate byte string, or `inclusionListMembership` does not have the same number of elements as `inclusionListTransactions`. 2. An element of `inclusionListMembership` is not exactly `INCLUSION_LIST_COMMITTEE_SIZE / 8` bytes, or has no bit set. 3. For some committee position `i`, the sum of the byte lengths of the transactions whose membership has bit `i` set exceeds `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. - 4. `inclusionListClaims` has more than `MAX_INCLUSION_LIST_CLAIMS` elements. Duplicate, unmatched and out-of-range claims **MUST NOT** cause an error; they are resolved as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). + 4. `inclusionListClaims` has more than `MAX_INCLUSION_LIST_CLAIMS` elements or an element does not match `InclusionListClaimV1`, including a malformed hash or a noncanonical or overflowing `uint64` index. + + Otherwise well-formed transaction byte strings **MUST NOT** cause an RPC error solely because their transaction encoding or validity checks fail. Well-formed duplicate or unmatched claims, and indices above the payload transaction count, **MUST NOT** cause an RPC error: EIP-7805 ignores repeated transaction hashes and irrelevant claims, and clamps remaining indices to the end of the payload. Exceeding the VERIFY budget is likewise handled by EIP-7805's per-member fill, not as an RPC error. 3. Client software **MUST** set `inclusionListSatisfied` in the following way: - 1. If the payload is deemed `VALID`, `inclusionListSatisfied` **MUST** be set to whether the payload satisfied the inclusion list constraints with respect to `inclusionListTransactions`, `inclusionListMembership` and `inclusionListClaims`. + 1. If the payload is deemed `VALID`, `inclusionListSatisfied` **MUST** be set to whether the payload satisfied the inclusion list constraints with respect to this call's `inclusionListTransactions`, `inclusionListMembership` and `inclusionListClaims`, even if execution validity was already known. A failed inclusion list check **MUST NOT** change execution validity to `INVALID`. 2. Otherwise, `inclusionListSatisfied` **MUST** be `null`. -4. Client software **MUST** retain `inclusionListTransactions`, `inclusionListMembership` and `inclusionListClaims` for a payload with `ACCEPTED` status. Client software **MAY** discard them once the payload is no longer the tip of a branch. +4. An inclusion list verdict is specific to the supplied transactions, membership and claims, not just the execution block hash. After an `ACCEPTED` or `SYNCING` response, the consensus layer **MUST** retain these inputs for the relevant beacon block and repeat this method with them once execution validation can complete. `engine_forkchoiceUpdatedV5` does not return an inclusion list verdict. ### engine_getPayloadV7 @@ -162,7 +171,7 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the built payload does not fall within the time frame of the Bogota fork. -2. `inclusionListClaims` **MUST NOT** have more than `MAX_INCLUSION_LIST_CLAIMS` elements. Each claim **MUST** refer to a transaction of the `inclusionListTransactions` used to build the payload that is omitted from `executionPayload`, and **SHOULD** have an index at which that omission is excused as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). +2. `inclusionListClaims` **MUST NOT** have more than `MAX_INCLUSION_LIST_CLAIMS` elements. Each claim **MUST** identify a distinct omitted Profile 2 candidate from the `inclusionListTransactions` used to build the payload, with an index no greater than `len(executionPayload.transactions)` at which its omission is excused under EIP-7805. When Profile 2 is inactive under EIP-7805, the list **MUST** be empty. ### engine_getInclusionListV1 @@ -187,7 +196,7 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 3. The total byte length of the transaction list **MUST NOT** exceed `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. - 4. When [EIP-8141](https://eips.ethereum.org/EIPS/eip-8141) is active, the total VERIFY budget cost of the Profile 2 candidates in the transaction list **MUST NOT** exceed `MAX_VERIFY_GAS_PER_IL`, with the cost, the candidates and the constant as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). + 4. When Profile 2 is active under EIP-7805, the total VERIFY budget cost of the distinct Profile 2 candidates in the transaction list **SHOULD NOT** exceed `MAX_VERIFY_GAS_PER_IL`, using EIP-7805's candidate and cost definitions. This is a selection recommendation, not an inclusion list validity rule. 2. The strategy for selecting transactions is implementation dependent. @@ -205,7 +214,7 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda #### Response * result: `object` - - `payloadStatus`: [`PayloadStatusV2`](#payloadstatusv2), with the same `status` value restrictions as [`engine_forkchoiceUpdatedV4`](./amsterdam.md#engine_forkchoiceupdatedv4). + - `payloadStatus`: `PayloadStatusV1`, with the same `status` value restrictions as [`engine_forkchoiceUpdatedV4`](./amsterdam.md#engine_forkchoiceupdatedv4). - `payloadId`: `DATA|null`, 8 Bytes - identifier of the payload build process or `null` * error: code and message set in case an exception happens while the validating payload, updating the forkchoice or initiating the payload build process. @@ -215,17 +224,9 @@ This method follows the same specification as [`engine_forkchoiceUpdatedV4`](./a 1. Extend point (8) of the `engine_forkchoiceUpdatedV1` [specification](./paris.md#specification-1) by defining the following sequence of checks that **MUST** be run over `payloadAttributes`: - 1. `payloadAttributes` matches the [`PayloadAttributesV5`](#payloadattributesv5) structure and `payloadAttributes.inclusionListTransactions` and `payloadAttributes.inclusionListMembership` satisfy the conditions of point (2) of [`engine_newPayloadV6`](#engine_newpayloadv6), return `-38003: Invalid payload attributes` on failure. - - 2. `payloadAttributes.timestamp` does not fall within the time frame of the Bogota fork, return `-38005: Unsupported fork` on failure. - -2. Extend point (9) of the `engine_forkchoiceUpdatedV1` [specification](./paris.md#specification-1) by defining `payloadStatus.inclusionListSatisfied`: - - 1. If the payload referenced by `forkchoiceState.headBlockHash` is deemed `VALID`, `payloadStatus.inclusionListSatisfied` **MUST** be set to whether the payload satisfied the inclusion list constraints. - - 2. Client software **MUST** use the retained `inclusionListTransactions`, `inclusionListMembership` and `inclusionListClaims` if it validates the payload and checks whether the payload satisfies the inclusion list constraints while processing the call. + 1. `payloadAttributes` matches the [`PayloadAttributesV5`](#payloadattributesv5) structure and `payloadAttributes.inclusionListTransactions` and `payloadAttributes.inclusionListMembership` pass checks (2.1) through (2.3) of [`engine_newPayloadV6`](#engine_newpayloadv6), return `-38003: Invalid payload attributes` on failure. Invalid transaction encodings or transaction validity failures are handled by EIP-7805, not rejected as invalid attributes. - 3. Otherwise, `payloadStatus.inclusionListSatisfied` **MUST** be `null`. + 2. `payloadAttributes.timestamp` falls within the time frame of the Bogota fork, return `-38005: Unsupported fork` on failure. ### Update the methods of previous forks diff --git a/src/engine/openrpc/methods/forkchoice.yaml b/src/engine/openrpc/methods/forkchoice.yaml index badee9ff3..080315104 100644 --- a/src/engine/openrpc/methods/forkchoice.yaml +++ b/src/engine/openrpc/methods/forkchoice.yaml @@ -209,7 +209,9 @@ - name: Payload attributes required: false schema: - $ref: '#/components/schemas/PayloadAttributesV5' + oneOf: + - $ref: '#/components/schemas/PayloadAttributesV5' + - type: 'null' - name: Custody columns required: false schema: @@ -219,7 +221,7 @@ result: name: Response object schema: - $ref: '#/components/schemas/ForkchoiceUpdatedResponseV2' + $ref: '#/components/schemas/ForkchoiceUpdatedResponseV1' errors: - code: -38002 message: Invalid forkchoice state diff --git a/src/engine/openrpc/methods/inclusion_list.yaml b/src/engine/openrpc/methods/inclusion_list.yaml index e55433cf6..cb5984417 100644 --- a/src/engine/openrpc/methods/inclusion_list.yaml +++ b/src/engine/openrpc/methods/inclusion_list.yaml @@ -8,5 +8,6 @@ name: Inclusion list transactions schema: type: array + maxItems: 8192 items: - $ref: '#/components/schemas/bytes' + $ref: '#/components/schemas/InclusionListTransactionV1' diff --git a/src/engine/openrpc/methods/payload.yaml b/src/engine/openrpc/methods/payload.yaml index 65a3b34d9..d8412e5d3 100644 --- a/src/engine/openrpc/methods/payload.yaml +++ b/src/engine/openrpc/methods/payload.yaml @@ -1103,21 +1103,15 @@ - name: Inclusion list transactions required: true schema: - type: array - items: - $ref: '#/components/schemas/bytes' + $ref: '#/components/schemas/InclusionListTransactionsV1' - name: Inclusion list membership required: true schema: - type: array - items: - $ref: '#/components/schemas/InclusionListMembershipV1' + $ref: '#/components/schemas/InclusionListMembershipsV1' - name: Inclusion list claims required: true schema: - type: array - items: - $ref: '#/components/schemas/InclusionListClaimV1' + $ref: '#/components/schemas/InclusionListClaimsV1' result: name: Payload status schema: @@ -1258,9 +1252,7 @@ items: $ref: '#/components/schemas/bytes' inclusionListClaims: - type: array - items: - $ref: '#/components/schemas/InclusionListClaimV1' + $ref: '#/components/schemas/InclusionListClaimsV1' errors: - code: -38001 message: Unknown payload diff --git a/src/engine/openrpc/schemas/forkchoice.yaml b/src/engine/openrpc/schemas/forkchoice.yaml index cc7e63a25..fe4d1d888 100644 --- a/src/engine/openrpc/schemas/forkchoice.yaml +++ b/src/engine/openrpc/schemas/forkchoice.yaml @@ -27,18 +27,6 @@ ForkchoiceUpdatedResponseV1: payloadId: title: Payload id $ref: '#/components/schemas/bytes8' -ForkchoiceUpdatedResponseV2: - title: Forkchoice updated response object V2 - type: object - required: - - payloadStatus - properties: - payloadStatus: - title: Payload status - $ref: '#/components/schemas/RestrictedPayloadStatusV2' - payloadId: - title: Payload id - $ref: '#/components/schemas/bytes8' PayloadAttributesV1: title: Payload attributes object V1 type: object @@ -154,12 +142,6 @@ PayloadAttributesV5: targetGasLimit: $ref: '#/components/schemas/PayloadAttributesV4/properties/targetGasLimit' inclusionListTransactions: - title: Inclusion list transactions - type: array - items: - $ref: '#/components/schemas/bytes' + $ref: '#/components/schemas/InclusionListTransactionsV1' inclusionListMembership: - title: Inclusion list membership - type: array - items: - $ref: '#/components/schemas/InclusionListMembershipV1' + $ref: '#/components/schemas/InclusionListMembershipsV1' diff --git a/src/engine/openrpc/schemas/payload.yaml b/src/engine/openrpc/schemas/payload.yaml index ae97901ea..af33ef7c5 100644 --- a/src/engine/openrpc/schemas/payload.yaml +++ b/src/engine/openrpc/schemas/payload.yaml @@ -51,34 +51,27 @@ PayloadStatusNoInvalidBlockHash: PayloadStatusV2: $ref: '#/components/schemas/PayloadStatusNoInvalidBlockHash' title: Payload status object V2 + required: + - status + - latestValidHash + - validationError + - inclusionListSatisfied properties: status: $ref: '#/components/schemas/PayloadStatusNoInvalidBlockHash/properties/status' latestValidHash: - $ref: '#/components/schemas/PayloadStatusNoInvalidBlockHash/properties/latestValidHash' + oneOf: + - $ref: '#/components/schemas/hash32' + - type: 'null' validationError: - $ref: '#/components/schemas/PayloadStatusNoInvalidBlockHash/properties/validationError' + type: + - string + - 'null' inclusionListSatisfied: title: Whether the payload satisfied the inclusion list constraints oneOf: - type: boolean - type: 'null' -RestrictedPayloadStatusV2: - $ref: '#/components/schemas/PayloadStatusV2' - properties: - status: - $ref: '#/components/schemas/PayloadStatusV2/properties/status' - description: Set of possible values is restricted to VALID, INVALID, SYNCING - enum: - - VALID - - INVALID - - SYNCING - latestValidHash: - $ref: '#/components/schemas/PayloadStatusV2/properties/latestValidHash' - validationError: - $ref: '#/components/schemas/PayloadStatusV2/properties/validationError' - inclusionListSatisfied: - $ref: '#/components/schemas/PayloadStatusV2/properties/inclusionListSatisfied' ExecutionPayloadV1: title: Execution payload object V1 type: object @@ -432,8 +425,38 @@ InclusionListClaimV1: $ref: '#/components/schemas/hash32' transactionIndex: title: Transaction index + description: Index before a payload transaction, with the transaction count denoting the end; larger uint64 values are clamped to the end by EIP-7805. $ref: '#/components/schemas/uint64' +InclusionListClaimsV1: + title: Ordered inclusion list claims + description: The committed list is passed unchanged, including duplicate claims; EIP-7805 defines their evaluation. + type: array + maxItems: 4096 + items: + $ref: '#/components/schemas/InclusionListClaimV1' +InclusionListTransactionV1: + title: Nonempty inclusion list transaction bytes + description: Transaction validity is evaluated under EIP-7805 rather than JSON-RPC parameter validation. + type: string + pattern: ^0x([0-9a-f]{2})+$ + maxLength: 16386 +InclusionListTransactionsV1: + title: Distinct inclusion list transaction bytes + type: array + uniqueItems: true + maxItems: 131072 + items: + $ref: '#/components/schemas/InclusionListTransactionV1' InclusionListMembershipV1: title: Inclusion list membership bitvector over the inclusion list committee + description: SSZ Bitvector[16], with bit i in bit i modulo 8 of byte i divided by 8; positions 0 and 9 encode as 0x0102. type: string pattern: ^0x[0-9a-f]{4}$ + not: + const: '0x0000' +InclusionListMembershipsV1: + title: Membership per inclusion list transaction + type: array + maxItems: 131072 + items: + $ref: '#/components/schemas/InclusionListMembershipV1' From 7c01d32eb77d30f37391fca5318a26823cb21562 Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Sat, 10 Oct 2026 01:51:32 +0100 Subject: [PATCH 09/17] Add inclusion list schema names to spelling dictionary --- wordlist.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wordlist.txt b/wordlist.txt index 8e86c9f63..4df254e76 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -64,6 +64,11 @@ graphql greppable gwei https +InclusionListClaimV +InclusionListClaimsV +InclusionListMembershipV +InclusionListMembershipsV +InclusionListTransactionsV interop ipc js From 801c2965eb9ad48458eff759bcd916e1174da1a5 Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Tue, 13 Oct 2026 11:23:54 +0100 Subject: [PATCH 10/17] engine: support deferred inclusion checks by context --- src/engine/bogota.md | 50 +++++++++++++++---- src/engine/common.md | 1 + src/engine/openrpc/methods/forkchoice.yaml | 11 +++- .../openrpc/methods/inclusion_list.yaml | 45 +++++++++++++++++ src/engine/openrpc/schemas/forkchoice.yaml | 14 ++++++ src/engine/openrpc/schemas/payload.yaml | 23 +++++++++ wordlist.txt | 1 + 7 files changed, 135 insertions(+), 10 deletions(-) diff --git a/src/engine/bogota.md b/src/engine/bogota.md index eebacf058..53b2d9fb3 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -15,6 +15,7 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. - [PayloadStatusV2](#payloadstatusv2) - [InclusionListClaimV1](#inclusionlistclaimv1) - [Routines](#routines) + - [Inclusion-check contexts](#inclusion-check-contexts) - [Payload building](#payload-building) - [Methods](#methods) - [engine_newPayloadV6](#engine_newpayloadv6) @@ -33,6 +34,10 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. - [Request](#request-3) - [Response](#response-3) - [Specification](#specification-3) + - [engine_getInclusionListStatusV1](#engine_getinclusionliststatusv1) + - [Request](#request-4) + - [Response](#response-4) + - [Specification](#specification-4) - [Update the methods of previous forks](#update-the-methods-of-previous-forks) - [Amsterdam API](#amsterdam-api) @@ -69,12 +74,13 @@ The transaction list contains distinct, nonempty byte strings; its order is unre ### PayloadStatusV2 -This structure has the syntax of `PayloadStatusV1` and appends a single field: `inclusionListSatisfied` +This structure has the syntax of `PayloadStatusV1` and appends `inclusionListSatisfied` and `inclusionListContextId`. - `status`: `enum` - `"VALID" | "INVALID" | "SYNCING" | "ACCEPTED"` - `latestValidHash`: `DATA|null`, 32 Bytes - the hash of the most recent *valid* block in the branch defined by payload and its ancestors - `validationError`: `String|null` - a message providing additional details on the validation error if the payload is classified as `INVALID`. -- `inclusionListSatisfied`: `BOOLEAN|null` - whether the payload satisfied the inclusion list constraints if it is deemed `VALID`; `null` otherwise. +- `inclusionListSatisfied`: `BOOLEAN|null` - the completed inclusion verdict for a `VALID` payload; `null` while either check is pending, if execution is invalid, or if no context was requested. +- `inclusionListContextId`: `DATA|null`, 32 Bytes - opaque identifier of the inclusion-check context, or `null` if none was registered or requested. ### InclusionListClaimV1 @@ -87,6 +93,14 @@ Index zero is before the first transaction; `len(executionPayload.transactions)` ## Routines +### Inclusion-check contexts + +An inclusion-check context binds an execution block hash to the exact `inclusionListTransactions`, `inclusionListMembership` and `inclusionListClaims` supplied to `engine_newPayloadV6`. Identifiers are issued by the execution layer, are local to the Engine API, and are not part of the execution payload or any consensus commitment. An identifier **MUST NOT** be rebound to different inputs, including across restarts. Clients **MAY** reuse an identifier for identical inputs and share execution data between contexts. + +Execution validation and inclusion checking may complete asynchronously. For a retained context, the execution layer **MUST** schedule inclusion checking once execution is `VALID`; it **MUST NOT** require resubmission to start that check. A completed verdict **MUST NOT** change for that context. Inclusion failure **MUST NOT** change execution validity or the processing of forkchoice or payload building. + +Clients **MAY** bound retained contexts and evict them, including on restart. Queries for an unknown or evicted identifier **MUST** return `-38007: Unknown inclusion context`. The consensus layer **MUST** retain the original inputs until it records a completed verdict or abandons the block, and resubmit them through `engine_newPayloadV6` on this error. A pending verdict **MUST NOT** be interpreted as satisfied. Execution optimism remains governed by the consensus specification. + ### Payload building This routine follows the same specification as [Payload building](./paris.md#payload-building) with the following changes to the processing flow: @@ -135,13 +149,9 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda Otherwise well-formed transaction byte strings **MUST NOT** cause an RPC error solely because their transaction encoding or validity checks fail. Well-formed duplicate or unmatched claims, and indices above the payload transaction count, **MUST NOT** cause an RPC error: EIP-7805 ignores repeated transaction hashes and irrelevant claims, and clamps remaining indices to the end of the payload. Exceeding the VERIFY budget is likewise handled by EIP-7805's per-member fill, not as an RPC error. -3. Client software **MUST** set `inclusionListSatisfied` in the following way: - - 1. If the payload is deemed `VALID`, `inclusionListSatisfied` **MUST** be set to whether the payload satisfied the inclusion list constraints with respect to this call's `inclusionListTransactions`, `inclusionListMembership` and `inclusionListClaims`, even if execution validity was already known. A failed inclusion list check **MUST NOT** change execution validity to `INVALID`. +3. Client software **MUST** evaluate inclusion against this call's inputs, even if execution validity is already known. It **MUST** return `inclusionListSatisfied` as the completed boolean verdict only if execution is `VALID`; otherwise, including while inclusion checking is pending, it **MUST** return `null`. - 2. Otherwise, `inclusionListSatisfied` **MUST** be `null`. - -4. An inclusion list verdict is specific to the supplied transactions, membership and claims, not just the execution block hash. After an `ACCEPTED` or `SYNCING` response, the consensus layer **MUST** retain these inputs for the relevant beacon block and repeat this method with them once execution validation can complete. `engine_forkchoiceUpdatedV5` does not return an inclusion list verdict. +4. Unless execution is `INVALID`, client software **MUST** register an [inclusion-check context](#inclusion-check-contexts) and return its `inclusionListContextId`. For an `INVALID` response, this field **MUST** be `null`. The consensus layer can retrieve deferred results using `engine_getInclusionListStatusV1`, or `engine_forkchoiceUpdatedV5` when selecting that context's execution block as head. ### engine_getPayloadV7 @@ -209,12 +219,13 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 1. `forkchoiceState`: [`ForkchoiceStateV1`](./paris.md#forkchoicestatev1). 2. `payloadAttributes`: `Object|null` - Instance of [`PayloadAttributesV5`](#payloadattributesv5) or `null`. 3. `custodyColumns`: `DATA|null`, 16 Bytes - Interpreted as a bitarray of length `CELLS_PER_EXT_BLOB` indicating which column indices form the CL's custody set, or `null` if the CL does not provide custody services. + 4. `inclusionListContextId`: `DATA|null`, 32 Bytes - Context to query for `forkchoiceState.headBlockHash`, or `null` (also the default if omitted). * timeout: 8s #### Response * result: `object` - - `payloadStatus`: `PayloadStatusV1`, with the same `status` value restrictions as [`engine_forkchoiceUpdatedV4`](./amsterdam.md#engine_forkchoiceupdatedv4). + - `payloadStatus`: [`PayloadStatusV2`](#payloadstatusv2), with the same `status` value restrictions as [`engine_forkchoiceUpdatedV4`](./amsterdam.md#engine_forkchoiceupdatedv4). - `payloadId`: `DATA|null`, 8 Bytes - identifier of the payload build process or `null` * error: code and message set in case an exception happens while the validating payload, updating the forkchoice or initiating the payload build process. @@ -222,12 +233,33 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda This method follows the same specification as [`engine_forkchoiceUpdatedV4`](./amsterdam.md#engine_forkchoiceupdatedv4) with the following changes to the processing flow: +Before processing forkchoice or payload attributes, a non-null `inclusionListContextId` **MUST** be checked: return `-38007: Unknown inclusion context` if unavailable, or `-32602: Invalid params` if bound to a block other than `headBlockHash`. These errors **MUST NOT** change forkchoice or start a payload build. The response echoes the requested context ID and reports its completed inclusion verdict only when `payloadStatus.status` is `VALID`; a pending check returns `null` without delaying forkchoice processing. When no context is requested, both inclusion fields **MUST** be `null`. Head inclusion inputs **MUST NOT** be taken from `payloadAttributes`, which describes a child build. + 1. Extend point (8) of the `engine_forkchoiceUpdatedV1` [specification](./paris.md#specification-1) by defining the following sequence of checks that **MUST** be run over `payloadAttributes`: 1. `payloadAttributes` matches the [`PayloadAttributesV5`](#payloadattributesv5) structure and `payloadAttributes.inclusionListTransactions` and `payloadAttributes.inclusionListMembership` pass checks (2.1) through (2.3) of [`engine_newPayloadV6`](#engine_newpayloadv6), return `-38003: Invalid payload attributes` on failure. Invalid transaction encodings or transaction validity failures are handled by EIP-7805, not rejected as invalid attributes. 2. `payloadAttributes.timestamp` falls within the time frame of the Bogota fork, return `-38005: Unsupported fork` on failure. +### engine_getInclusionListStatusV1 + +#### Request + +* method: `engine_getInclusionListStatusV1` +* params: + 1. `inclusionListContextId`: `DATA`, 32 Bytes - Identifier returned by `engine_newPayloadV6`. +* timeout: 1s + +#### Response + +* result: [`PayloadStatusV2`](#payloadstatusv2) +* error: code and message set in case an exception happens while retrieving the status. + +#### Specification + +1. Client software **MUST** return `-38007: Unknown inclusion context` if the context is unavailable. +2. Otherwise, it **MUST** return the context's current execution status, echo its identifier, and set `inclusionListSatisfied` according to `engine_newPayloadV6` point (3). If execution has not completed and the required state is available, it **MUST** schedule validation. This method does not update forkchoice or initiate a payload build, and **MUST NOT** wait for pending validation or inclusion checking to finish. + ### Update the methods of previous forks #### Amsterdam API diff --git a/src/engine/common.md b/src/engine/common.md index 64ca875f5..4282c4374 100644 --- a/src/engine/common.md +++ b/src/engine/common.md @@ -100,6 +100,7 @@ The list of error codes introduced by this specification can be found below. | -38004 | Too large request | Number of requested entities is too large. | | -38005 | Unsupported fork | Payload belongs to a fork that is not supported. | | -38006 | Too deep reorg | Reorg depth exceeds limitation. | +| -38007 | Unknown inclusion context | Inclusion-check context does not exist / is not available. | Each error returns a `null` `data` value, except `-32000` which returns the `data` object with a `err` member that explains the error encountered. diff --git a/src/engine/openrpc/methods/forkchoice.yaml b/src/engine/openrpc/methods/forkchoice.yaml index 080315104..262cee70b 100644 --- a/src/engine/openrpc/methods/forkchoice.yaml +++ b/src/engine/openrpc/methods/forkchoice.yaml @@ -218,10 +218,17 @@ oneOf: - $ref: '#/components/schemas/bytes16' - type: 'null' + - name: Inclusion list context id + required: false + schema: + title: Head inclusion check context + oneOf: + - $ref: '#/components/schemas/hash32' + - type: 'null' result: name: Response object schema: - $ref: '#/components/schemas/ForkchoiceUpdatedResponseV1' + $ref: '#/components/schemas/ForkchoiceUpdatedResponseV2' errors: - code: -38002 message: Invalid forkchoice state @@ -233,3 +240,5 @@ message: Unsupported fork - code: -38006 message: Too deep reorg + - code: -38007 + message: Unknown inclusion context diff --git a/src/engine/openrpc/methods/inclusion_list.yaml b/src/engine/openrpc/methods/inclusion_list.yaml index cb5984417..1dd6a5edb 100644 --- a/src/engine/openrpc/methods/inclusion_list.yaml +++ b/src/engine/openrpc/methods/inclusion_list.yaml @@ -11,3 +11,48 @@ maxItems: 8192 items: $ref: '#/components/schemas/InclusionListTransactionV1' +- name: engine_getInclusionListStatusV1 + summary: Obtains the execution and inclusion status for a registered context + externalDocs: + description: Method specification + url: https://github.com/ethereum/execution-apis/blob/main/src/engine/bogota.md#engine_getinclusionliststatusv1 + params: + - name: Inclusion list context id + required: true + schema: + $ref: '#/components/schemas/hash32' + result: + name: Payload status + schema: + title: Execution and inclusion status + $ref: '#/components/schemas/PayloadStatusV2' + errors: + - code: -38007 + message: Unknown inclusion context + - code: -32602 + message: Invalid params + examples: + - name: Pending inclusion check for a valid execution payload + params: + - name: Inclusion list context id + value: '0x1111111111111111111111111111111111111111111111111111111111111111' + result: + name: Payload status + value: + status: VALID + latestValidHash: '0x2222222222222222222222222222222222222222222222222222222222222222' + validationError: null + inclusionListSatisfied: null + inclusionListContextId: '0x1111111111111111111111111111111111111111111111111111111111111111' + - name: Completed unsatisfied inclusion check + params: + - name: Inclusion list context id + value: '0x1111111111111111111111111111111111111111111111111111111111111111' + result: + name: Payload status + value: + status: VALID + latestValidHash: '0x2222222222222222222222222222222222222222222222222222222222222222' + validationError: null + inclusionListSatisfied: false + inclusionListContextId: '0x1111111111111111111111111111111111111111111111111111111111111111' diff --git a/src/engine/openrpc/schemas/forkchoice.yaml b/src/engine/openrpc/schemas/forkchoice.yaml index fe4d1d888..f873e80bb 100644 --- a/src/engine/openrpc/schemas/forkchoice.yaml +++ b/src/engine/openrpc/schemas/forkchoice.yaml @@ -27,6 +27,20 @@ ForkchoiceUpdatedResponseV1: payloadId: title: Payload id $ref: '#/components/schemas/bytes8' +ForkchoiceUpdatedResponseV2: + title: Forkchoice updated response object V2 + type: object + required: + - payloadStatus + - payloadId + properties: + payloadStatus: + $ref: '#/components/schemas/RestrictedPayloadStatusV2' + payloadId: + title: Payload id + oneOf: + - $ref: '#/components/schemas/bytes8' + - type: 'null' PayloadAttributesV1: title: Payload attributes object V1 type: object diff --git a/src/engine/openrpc/schemas/payload.yaml b/src/engine/openrpc/schemas/payload.yaml index af33ef7c5..2cb75328c 100644 --- a/src/engine/openrpc/schemas/payload.yaml +++ b/src/engine/openrpc/schemas/payload.yaml @@ -56,6 +56,7 @@ PayloadStatusV2: - latestValidHash - validationError - inclusionListSatisfied + - inclusionListContextId properties: status: $ref: '#/components/schemas/PayloadStatusNoInvalidBlockHash/properties/status' @@ -72,6 +73,28 @@ PayloadStatusV2: oneOf: - type: boolean - type: 'null' + inclusionListContextId: + title: Inclusion check context identifier + oneOf: + - $ref: '#/components/schemas/hash32' + - type: 'null' +RestrictedPayloadStatusV2: + $ref: '#/components/schemas/PayloadStatusV2' + properties: + status: + $ref: '#/components/schemas/PayloadStatusV2/properties/status' + enum: + - VALID + - INVALID + - SYNCING + latestValidHash: + $ref: '#/components/schemas/PayloadStatusV2/properties/latestValidHash' + validationError: + $ref: '#/components/schemas/PayloadStatusV2/properties/validationError' + inclusionListSatisfied: + $ref: '#/components/schemas/PayloadStatusV2/properties/inclusionListSatisfied' + inclusionListContextId: + $ref: '#/components/schemas/PayloadStatusV2/properties/inclusionListContextId' ExecutionPayloadV1: title: Execution payload object V1 type: object diff --git a/wordlist.txt b/wordlist.txt index 4df254e76..5ecc8c285 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -60,6 +60,7 @@ getblobsv getclientversionv getinclusionlistv getInclusionListV +getInclusionListStatusV graphql greppable gwei From cb797158e2b265d825005e6ab9e1c6efc81bb354 Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Tue, 13 Oct 2026 12:27:20 +0100 Subject: [PATCH 11/17] engine: rename claim evaluationIndex and align profile activation --- src/engine/bogota.md | 8 ++++---- src/engine/openrpc/schemas/payload.yaml | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/engine/bogota.md b/src/engine/bogota.md index 53b2d9fb3..a946195e0 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -52,7 +52,7 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. | `MAX_INCLUSION_LIST_CLAIMS` | `uint64(4096) = 2**12` | | `MAX_VERIFY_GAS_PER_IL` | `uint64(1048576) = 2**20` | -The VERIFY budget and claim cap are defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805#constants), including their activation conditions. +Both EIP-7805 profiles apply from Bogota activation. The VERIFY budget and claim cap are defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805#constants). ## Structures @@ -87,7 +87,7 @@ This structure has the syntax of `PayloadStatusV1` and appends `inclusionListSat This structure maps onto the inclusion list claim defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). The fields are encoded as follows: - `transactionHash`: `DATA`, 32 Bytes - `keccak256` of the claimed inclusion list transaction, `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). -- `transactionIndex`: `QUANTITY`, 64 Bits - index in `executionPayload.transactions` at which the omission of the claimed transaction is evaluated. +- `evaluationIndex`: `QUANTITY`, 64 Bits - index in `executionPayload.transactions` at which the omission of the claimed transaction is evaluated. Index zero is before the first transaction; `len(executionPayload.transactions)` is the end of the payload. The claim list retains its committed order and duplicates. The consensus layer checks its commitment; the execution layer applies EIP-7805's evaluation rules. @@ -181,7 +181,7 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the built payload does not fall within the time frame of the Bogota fork. -2. `inclusionListClaims` **MUST NOT** have more than `MAX_INCLUSION_LIST_CLAIMS` elements. Each claim **MUST** identify a distinct omitted Profile 2 candidate from the `inclusionListTransactions` used to build the payload, with an index no greater than `len(executionPayload.transactions)` at which its omission is excused under EIP-7805. When Profile 2 is inactive under EIP-7805, the list **MUST** be empty. +2. `inclusionListClaims` **MUST NOT** have more than `MAX_INCLUSION_LIST_CLAIMS` elements. Each claim **MUST** identify a distinct omitted Profile 2 candidate from the `inclusionListTransactions` used to build the payload, with an index no greater than `len(executionPayload.transactions)` at which its omission is excused under EIP-7805. ### engine_getInclusionListV1 @@ -206,7 +206,7 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 3. The total byte length of the transaction list **MUST NOT** exceed `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. - 4. When Profile 2 is active under EIP-7805, the total VERIFY budget cost of the distinct Profile 2 candidates in the transaction list **SHOULD NOT** exceed `MAX_VERIFY_GAS_PER_IL`, using EIP-7805's candidate and cost definitions. This is a selection recommendation, not an inclusion list validity rule. + 4. The total VERIFY budget cost of the distinct Profile 2 candidates in the transaction list **SHOULD NOT** exceed `MAX_VERIFY_GAS_PER_IL`, using EIP-7805's candidate and cost definitions. This is a selection recommendation, not an inclusion list validity rule. 2. The strategy for selecting transactions is implementation dependent. diff --git a/src/engine/openrpc/schemas/payload.yaml b/src/engine/openrpc/schemas/payload.yaml index 2cb75328c..6f8dba3a1 100644 --- a/src/engine/openrpc/schemas/payload.yaml +++ b/src/engine/openrpc/schemas/payload.yaml @@ -441,13 +441,13 @@ InclusionListClaimV1: type: object required: - transactionHash - - transactionIndex + - evaluationIndex properties: transactionHash: title: Transaction hash $ref: '#/components/schemas/hash32' - transactionIndex: - title: Transaction index + evaluationIndex: + title: Evaluation index description: Index before a payload transaction, with the transaction count denoting the end; larger uint64 values are clamped to the end by EIP-7805. $ref: '#/components/schemas/uint64' InclusionListClaimsV1: From c6375a758198f1ceb16a26b2a33640cc2a8779ef Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Tue, 13 Oct 2026 12:36:22 +0100 Subject: [PATCH 12/17] engine: rename omission claims consistently --- src/engine/bogota.md | 24 ++++++++++++------------ src/engine/openrpc/methods/payload.yaml | 10 +++++----- src/engine/openrpc/schemas/payload.yaml | 10 +++++----- wordlist.txt | 4 ++-- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/engine/bogota.md b/src/engine/bogota.md index a946195e0..65a67f4a0 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -13,7 +13,7 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. - [Structures](#structures) - [PayloadAttributesV5](#payloadattributesv5) - [PayloadStatusV2](#payloadstatusv2) - - [InclusionListClaimV1](#inclusionlistclaimv1) + - [OmissionClaimV1](#omissionclaimv1) - [Routines](#routines) - [Inclusion-check contexts](#inclusion-check-contexts) - [Payload building](#payload-building) @@ -49,7 +49,7 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. | - | - | | `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST` | `uint64(8192) = 2**13` | | `INCLUSION_LIST_COMMITTEE_SIZE` | `uint64(16) = 2**4` | -| `MAX_INCLUSION_LIST_CLAIMS` | `uint64(4096) = 2**12` | +| `MAX_OMISSION_CLAIMS` | `uint64(4096) = 2**12` | | `MAX_VERIFY_GAS_PER_IL` | `uint64(1048576) = 2**20` | Both EIP-7805 profiles apply from Bogota activation. The VERIFY budget and claim cap are defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805#constants). @@ -82,9 +82,9 @@ This structure has the syntax of `PayloadStatusV1` and appends `inclusionListSat - `inclusionListSatisfied`: `BOOLEAN|null` - the completed inclusion verdict for a `VALID` payload; `null` while either check is pending, if execution is invalid, or if no context was requested. - `inclusionListContextId`: `DATA|null`, 32 Bytes - opaque identifier of the inclusion-check context, or `null` if none was registered or requested. -### InclusionListClaimV1 +### OmissionClaimV1 -This structure maps onto the inclusion list claim defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). The fields are encoded as follows: +This structure maps onto the omission claim defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). The fields are encoded as follows: - `transactionHash`: `DATA`, 32 Bytes - `keccak256` of the claimed inclusion list transaction, `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). - `evaluationIndex`: `QUANTITY`, 64 Bits - index in `executionPayload.transactions` at which the omission of the claimed transaction is evaluated. @@ -95,7 +95,7 @@ Index zero is before the first transaction; `len(executionPayload.transactions)` ### Inclusion-check contexts -An inclusion-check context binds an execution block hash to the exact `inclusionListTransactions`, `inclusionListMembership` and `inclusionListClaims` supplied to `engine_newPayloadV6`. Identifiers are issued by the execution layer, are local to the Engine API, and are not part of the execution payload or any consensus commitment. An identifier **MUST NOT** be rebound to different inputs, including across restarts. Clients **MAY** reuse an identifier for identical inputs and share execution data between contexts. +An inclusion-check context binds an execution block hash to the exact `inclusionListTransactions`, `inclusionListMembership` and `omissionClaims` supplied to `engine_newPayloadV6`. Identifiers are issued by the execution layer, are local to the Engine API, and are not part of the execution payload or any consensus commitment. An identifier **MUST NOT** be rebound to different inputs, including across restarts. Clients **MAY** reuse an identifier for identical inputs and share execution data between contexts. Execution validation and inclusion checking may complete asynchronously. For a retained context, the execution layer **MUST** schedule inclusion checking once execution is `VALID`; it **MUST NOT** require resubmission to start that check. A completed verdict **MUST NOT** change for that context. Inclusion failure **MUST NOT** change execution validity or the processing of forkchoice or payload building. @@ -105,13 +105,13 @@ Clients **MAY** bound retained contexts and evict them, including on restart. Qu This routine follows the same specification as [Payload building](./paris.md#payload-building) with the following changes to the processing flow: -1. Client software **MUST** take `inclusionListTransactions` into account during the payload build process. The built `ExecutionPayload`, together with the `inclusionListClaims` returned by [`engine_getPayloadV7`](#engine_getpayloadv7), **MUST** satisfy the inclusion list constraints with respect to `inclusionListTransactions` and `inclusionListMembership` as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). +1. Client software **MUST** take `inclusionListTransactions` into account during the payload build process. The built `ExecutionPayload`, together with the `omissionClaims` returned by [`engine_getPayloadV7`](#engine_getpayloadv7), **MUST** satisfy the inclusion list constraints with respect to `inclusionListTransactions` and `inclusionListMembership` as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). ## Methods ### engine_newPayloadV6 -Method parameter list is extended with `inclusionListTransactions`, `inclusionListMembership` and `inclusionListClaims`. +Method parameter list is extended with `inclusionListTransactions`, `inclusionListMembership` and `omissionClaims`. #### Request @@ -123,7 +123,7 @@ Method parameter list is extended with `inclusionListTransactions`, `inclusionLi 4. `executionRequests`: `Array of DATA` - List of execution layer triggered requests. Each list element is a `requests` byte array as defined by [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685). The first byte of each element is the `request_type` and the remaining bytes are the `request_data`. Elements of the list **MUST** be ordered by `request_type` in ascending order. Elements with empty `request_data` **MUST** be excluded from the list. 5. `inclusionListTransactions`: `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). 6. `inclusionListMembership`: `Array of DATA`, 2 Bytes - Array of inclusion list memberships, one per element of `inclusionListTransactions` at the same position. Each element is a bitvector of length `INCLUSION_LIST_COMMITTEE_SIZE`, encoded as SSZ `Bitvector[INCLUSION_LIST_COMMITTEE_SIZE]`, in which bit `i` is set if and only if the inclusion list of the inclusion list committee member at committee position `i` carries the transaction. - 7. `inclusionListClaims`: `Array of InclusionListClaimV1` - Array of inclusion list claims committed to by the builder of the payload, as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). + 7. `omissionClaims`: `Array of OmissionClaimV1` - Array of omission claims committed to by the builder of the payload, as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). * timeout: 6s #### Response @@ -145,7 +145,7 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda 3. For some committee position `i`, the sum of the byte lengths of the transactions whose membership has bit `i` set exceeds `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. - 4. `inclusionListClaims` has more than `MAX_INCLUSION_LIST_CLAIMS` elements or an element does not match `InclusionListClaimV1`, including a malformed hash or a noncanonical or overflowing `uint64` index. + 4. `omissionClaims` has more than `MAX_OMISSION_CLAIMS` elements or an element does not match `OmissionClaimV1`, including a malformed hash or a noncanonical or overflowing `uint64` index. Otherwise well-formed transaction byte strings **MUST NOT** cause an RPC error solely because their transaction encoding or validity checks fail. Well-formed duplicate or unmatched claims, and indices above the payload transaction count, **MUST NOT** cause an RPC error: EIP-7805 ignores repeated transaction hashes and irrelevant claims, and clamps remaining indices to the end of the payload. Exceeding the VERIFY budget is likewise handled by EIP-7805's per-member fill, not as an RPC error. @@ -155,7 +155,7 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda ### engine_getPayloadV7 -This method is updated to return `inclusionListClaims`. +This method is updated to return `omissionClaims`. #### Request @@ -172,7 +172,7 @@ This method is updated to return `inclusionListClaims`. - `blobsBundle`: [`BlobsBundleV2`](./osaka.md#blobsbundlev2) - Bundle with data corresponding to blob transactions included into `executionPayload` - `shouldOverrideBuilder` : `BOOLEAN` - Suggestion from the execution layer to use this `executionPayload` instead of an externally provided one - `executionRequests`: `Array of DATA` - Execution layer triggered requests obtained from the `executionPayload` transaction execution. - - `inclusionListClaims`: `Array of InclusionListClaimV1` - Inclusion list claims for transactions omitted from `executionPayload`. + - `omissionClaims`: `Array of OmissionClaimV1` - Omission claims for transactions omitted from `executionPayload`. * error: code and message set in case an exception happens while getting the payload. #### Specification @@ -181,7 +181,7 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the built payload does not fall within the time frame of the Bogota fork. -2. `inclusionListClaims` **MUST NOT** have more than `MAX_INCLUSION_LIST_CLAIMS` elements. Each claim **MUST** identify a distinct omitted Profile 2 candidate from the `inclusionListTransactions` used to build the payload, with an index no greater than `len(executionPayload.transactions)` at which its omission is excused under EIP-7805. +2. `omissionClaims` **MUST NOT** have more than `MAX_OMISSION_CLAIMS` elements. Each claim **MUST** identify a distinct omitted Profile 2 candidate from the `inclusionListTransactions` used to build the payload, with an index no greater than `len(executionPayload.transactions)` at which its omission is excused under EIP-7805. ### engine_getInclusionListV1 diff --git a/src/engine/openrpc/methods/payload.yaml b/src/engine/openrpc/methods/payload.yaml index d8412e5d3..1484be0d6 100644 --- a/src/engine/openrpc/methods/payload.yaml +++ b/src/engine/openrpc/methods/payload.yaml @@ -1108,10 +1108,10 @@ required: true schema: $ref: '#/components/schemas/InclusionListMembershipsV1' - - name: Inclusion list claims + - name: Omission claims required: true schema: - $ref: '#/components/schemas/InclusionListClaimsV1' + $ref: '#/components/schemas/OmissionClaimsV1' result: name: Payload status schema: @@ -1237,7 +1237,7 @@ - blobsBundle - shouldOverrideBuilder - executionRequests - - inclusionListClaims + - omissionClaims properties: executionPayload: $ref: '#/components/schemas/ExecutionPayloadV4' @@ -1251,8 +1251,8 @@ type: array items: $ref: '#/components/schemas/bytes' - inclusionListClaims: - $ref: '#/components/schemas/InclusionListClaimsV1' + omissionClaims: + $ref: '#/components/schemas/OmissionClaimsV1' errors: - code: -38001 message: Unknown payload diff --git a/src/engine/openrpc/schemas/payload.yaml b/src/engine/openrpc/schemas/payload.yaml index 6f8dba3a1..f74f5bbd6 100644 --- a/src/engine/openrpc/schemas/payload.yaml +++ b/src/engine/openrpc/schemas/payload.yaml @@ -436,8 +436,8 @@ BlobsBundleV2: type: array items: $ref: '#/components/schemas/bytes' -InclusionListClaimV1: - title: Inclusion list claim object V1 +OmissionClaimV1: + title: Omission claim object V1 type: object required: - transactionHash @@ -450,13 +450,13 @@ InclusionListClaimV1: title: Evaluation index description: Index before a payload transaction, with the transaction count denoting the end; larger uint64 values are clamped to the end by EIP-7805. $ref: '#/components/schemas/uint64' -InclusionListClaimsV1: - title: Ordered inclusion list claims +OmissionClaimsV1: + title: Ordered omission claims description: The committed list is passed unchanged, including duplicate claims; EIP-7805 defines their evaluation. type: array maxItems: 4096 items: - $ref: '#/components/schemas/InclusionListClaimV1' + $ref: '#/components/schemas/OmissionClaimV1' InclusionListTransactionV1: title: Nonempty inclusion list transaction bytes description: Transaction validity is evaluated under EIP-7805 rather than JSON-RPC parameter validation. diff --git a/wordlist.txt b/wordlist.txt index 5ecc8c285..1f479ff11 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -65,8 +65,8 @@ graphql greppable gwei https -InclusionListClaimV -InclusionListClaimsV +OmissionClaimV +OmissionClaimsV InclusionListMembershipV InclusionListMembershipsV InclusionListTransactionsV From fa26676c50dd435b91fac92e345c153192d78ff8 Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Wed, 14 Oct 2026 19:48:31 +0100 Subject: [PATCH 13/17] engine: separate ILs and remove inclusion context handles --- src/engine/bogota.md | 73 +++++-------------- src/engine/common.md | 1 - src/engine/openrpc/methods/forkchoice.yaml | 11 +-- .../openrpc/methods/inclusion_list.yaml | 45 ------------ src/engine/openrpc/methods/payload.yaml | 8 +- src/engine/openrpc/schemas/forkchoice.yaml | 23 +----- src/engine/openrpc/schemas/payload.yaml | 50 +++---------- wordlist.txt | 5 +- 8 files changed, 35 insertions(+), 181 deletions(-) diff --git a/src/engine/bogota.md b/src/engine/bogota.md index 65a67f4a0..b112bb26c 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -15,7 +15,7 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. - [PayloadStatusV2](#payloadstatusv2) - [OmissionClaimV1](#omissionclaimv1) - [Routines](#routines) - - [Inclusion-check contexts](#inclusion-check-contexts) + - [Deferred inclusion checking](#deferred-inclusion-checking) - [Payload building](#payload-building) - [Methods](#methods) - [engine_newPayloadV6](#engine_newpayloadv6) @@ -34,10 +34,6 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. - [Request](#request-3) - [Response](#response-3) - [Specification](#specification-3) - - [engine_getInclusionListStatusV1](#engine_getinclusionliststatusv1) - - [Request](#request-4) - - [Response](#response-4) - - [Specification](#specification-4) - [Update the methods of previous forks](#update-the-methods-of-previous-forks) - [Amsterdam API](#amsterdam-api) @@ -58,7 +54,7 @@ Both EIP-7805 profiles apply from Bogota activation. The VERIFY budget and claim ### PayloadAttributesV5 -This structure has the syntax of [`PayloadAttributesV4`](./amsterdam.md#payloadattributesv4) and appends the fields `inclusionListTransactions` and `inclusionListMembership`. +This structure has the syntax of [`PayloadAttributesV4`](./amsterdam.md#payloadattributesv4) and appends `inclusionLists`. - `timestamp`: `QUANTITY`, 64 Bits - value for the `timestamp` field of the new payload - `prevRandao`: `DATA`, 32 Bytes - value for the `prevRandao` field of the new payload @@ -67,20 +63,18 @@ This structure has the syntax of [`PayloadAttributesV4`](./amsterdam.md#payloada - `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. - `slotNumber`: `QUANTITY`, 64 Bits - value for the `slotNumber` field of the new payload - `targetGasLimit`: `QUANTITY`, 64 Bits - target value for the `gasLimit` field of the new payload -- `inclusionListTransactions`: `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). -- `inclusionListMembership`: `Array of DATA`, 2 Bytes - Array of inclusion list memberships, one per element of `inclusionListTransactions` at the same position. Each element is a bitvector of length `INCLUSION_LIST_COMMITTEE_SIZE`, encoded as SSZ `Bitvector[INCLUSION_LIST_COMMITTEE_SIZE]`, in which bit `i` is set if and only if the inclusion list of the inclusion list committee member at committee position `i` carries the transaction. +- `inclusionLists`: `Array of Array of DATA` - Exactly `INCLUSION_LIST_COMMITTEE_SIZE` transaction lists, in committee-position order. Each transaction is the exact nonempty EIP-2718 envelope or legacy RLP bytes. An empty list denotes no applicable IL at that position. -The transaction list contains distinct, nonempty byte strings; its order is unrestricted. Membership uses only the inclusion lists selected by the consensus layer under EIP-7805. Bit `i` is bit `i % 8` of byte `i // 8`, with bit zero the least significant bit: committee positions `{0, 9}` encode as `0x0102`, and `{15}` as `0x0080`. The same rules apply to `engine_newPayloadV6`. +The consensus layer selects valid, non-equivocating ILs under EIP-7805. A member holding several committee positions supplies the same list at each. Entries retain their order and duplicates; the per-list byte limit applies before deduplication. The execution layer fills each list's budget independently and may share decoding, signature verification and replay work across lists. The same rules apply to `engine_newPayloadV6`. ### PayloadStatusV2 -This structure has the syntax of `PayloadStatusV1` and appends `inclusionListSatisfied` and `inclusionListContextId`. +This structure has the syntax of `PayloadStatusV1` and appends `inclusionListSatisfied`. - `status`: `enum` - `"VALID" | "INVALID" | "SYNCING" | "ACCEPTED"` - `latestValidHash`: `DATA|null`, 32 Bytes - the hash of the most recent *valid* block in the branch defined by payload and its ancestors - `validationError`: `String|null` - a message providing additional details on the validation error if the payload is classified as `INVALID`. -- `inclusionListSatisfied`: `BOOLEAN|null` - the completed inclusion verdict for a `VALID` payload; `null` while either check is pending, if execution is invalid, or if no context was requested. -- `inclusionListContextId`: `DATA|null`, 32 Bytes - opaque identifier of the inclusion-check context, or `null` if none was registered or requested. +- `inclusionListSatisfied`: `BOOLEAN|null` - the completed inclusion verdict for this call's exact inputs and a `VALID` payload; `null` while execution or inclusion checking is pending, or if execution is invalid. ### OmissionClaimV1 @@ -93,25 +87,23 @@ Index zero is before the first transaction; `len(executionPayload.transactions)` ## Routines -### Inclusion-check contexts +### Deferred inclusion checking -An inclusion-check context binds an execution block hash to the exact `inclusionListTransactions`, `inclusionListMembership` and `omissionClaims` supplied to `engine_newPayloadV6`. Identifiers are issued by the execution layer, are local to the Engine API, and are not part of the execution payload or any consensus commitment. An identifier **MUST NOT** be rebound to different inputs, including across restarts. Clients **MAY** reuse an identifier for identical inputs and share execution data between contexts. +Execution validation and inclusion checking may complete asynchronously. A pending inclusion verdict is `null`, including when execution is already `VALID`. The consensus layer **MUST** retain the original `engine_newPayloadV6` inputs and repeat that call until a completed verdict is returned or the block is abandoned; it **MUST NOT** substitute a later IL view or treat a pending check as satisfied. -Execution validation and inclusion checking may complete asynchronously. For a retained context, the execution layer **MUST** schedule inclusion checking once execution is `VALID`; it **MUST NOT** require resubmission to start that check. A completed verdict **MUST NOT** change for that context. Inclusion failure **MUST NOT** change execution validity or the processing of forkchoice or payload building. - -Clients **MAY** bound retained contexts and evict them, including on restart. Queries for an unknown or evicted identifier **MUST** return `-38007: Unknown inclusion context`. The consensus layer **MUST** retain the original inputs until it records a completed verdict or abandons the block, and resubmit them through `engine_newPayloadV6` on this error. A pending verdict **MUST NOT** be interpreted as satisfied. Execution optimism remains governed by the consensus specification. +The execution layer **MUST** schedule inclusion checking when execution is `VALID` and the required state is available. Repeated calls **MUST NOT** restart identical in-progress work. Clients **MAY** cache results and share execution data, but an inclusion verdict **MUST** apply to the call's exact execution block, `inclusionLists` and `omissionClaims`; execution hash alone is insufficient. A completed verdict for identical inputs **MUST NOT** change. Inclusion failure **MUST NOT** change execution validity or forkchoice processing. ### Payload building This routine follows the same specification as [Payload building](./paris.md#payload-building) with the following changes to the processing flow: -1. Client software **MUST** take `inclusionListTransactions` into account during the payload build process. The built `ExecutionPayload`, together with the `omissionClaims` returned by [`engine_getPayloadV7`](#engine_getpayloadv7), **MUST** satisfy the inclusion list constraints with respect to `inclusionListTransactions` and `inclusionListMembership` as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). +1. Client software **MUST** take `inclusionLists` into account during the payload build process. The built `ExecutionPayload`, together with the `omissionClaims` returned by [`engine_getPayloadV7`](#engine_getpayloadv7), **MUST** satisfy the inclusion list constraints with respect to `inclusionLists` as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). ## Methods ### engine_newPayloadV6 -Method parameter list is extended with `inclusionListTransactions`, `inclusionListMembership` and `omissionClaims`. +Method parameter list is extended with `inclusionLists` and `omissionClaims`. #### Request @@ -121,9 +113,8 @@ Method parameter list is extended with `inclusionListTransactions`, `inclusionLi 2. `expectedBlobVersionedHashes`: `Array of DATA`, 32 Bytes - Array of expected blob versioned hashes to validate. 3. `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. 4. `executionRequests`: `Array of DATA` - List of execution layer triggered requests. Each list element is a `requests` byte array as defined by [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685). The first byte of each element is the `request_type` and the remaining bytes are the `request_data`. Elements of the list **MUST** be ordered by `request_type` in ascending order. Elements with empty `request_data` **MUST** be excluded from the list. - 5. `inclusionListTransactions`: `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). - 6. `inclusionListMembership`: `Array of DATA`, 2 Bytes - Array of inclusion list memberships, one per element of `inclusionListTransactions` at the same position. Each element is a bitvector of length `INCLUSION_LIST_COMMITTEE_SIZE`, encoded as SSZ `Bitvector[INCLUSION_LIST_COMMITTEE_SIZE]`, in which bit `i` is set if and only if the inclusion list of the inclusion list committee member at committee position `i` carries the transaction. - 7. `omissionClaims`: `Array of OmissionClaimV1` - Array of omission claims committed to by the builder of the payload, as defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). + 5. `inclusionLists`: `Array of Array of DATA` - Separate ILs as defined in [`PayloadAttributesV5`](#payloadattributesv5). + 6. `omissionClaims`: `Array of OmissionClaimV1` - The ordered omission claims committed to by the builder, as defined in EIP-7805. * timeout: 6s #### Response @@ -139,20 +130,14 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda 2. Client software **MUST** return `-32602: Invalid params` error if any of the following holds: - 1. `inclusionListTransactions` contains an empty or duplicate byte string, or `inclusionListMembership` does not have the same number of elements as `inclusionListTransactions`. - - 2. An element of `inclusionListMembership` is not exactly `INCLUSION_LIST_COMMITTEE_SIZE / 8` bytes, or has no bit set. - - 3. For some committee position `i`, the sum of the byte lengths of the transactions whose membership has bit `i` set exceeds `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. + 1. `inclusionLists` does not have exactly `INCLUSION_LIST_COMMITTEE_SIZE` entries, an entry is not a list of nonempty byte strings, or the total transaction byte length of any entry exceeds `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. - 4. `omissionClaims` has more than `MAX_OMISSION_CLAIMS` elements or an element does not match `OmissionClaimV1`, including a malformed hash or a noncanonical or overflowing `uint64` index. + 2. `omissionClaims` has more than `MAX_OMISSION_CLAIMS` elements or an element does not match `OmissionClaimV1`, including a malformed hash or a noncanonical or overflowing `uint64` index. Otherwise well-formed transaction byte strings **MUST NOT** cause an RPC error solely because their transaction encoding or validity checks fail. Well-formed duplicate or unmatched claims, and indices above the payload transaction count, **MUST NOT** cause an RPC error: EIP-7805 ignores repeated transaction hashes and irrelevant claims, and clamps remaining indices to the end of the payload. Exceeding the VERIFY budget is likewise handled by EIP-7805's per-member fill, not as an RPC error. 3. Client software **MUST** evaluate inclusion against this call's inputs, even if execution validity is already known. It **MUST** return `inclusionListSatisfied` as the completed boolean verdict only if execution is `VALID`; otherwise, including while inclusion checking is pending, it **MUST** return `null`. -4. Unless execution is `INVALID`, client software **MUST** register an [inclusion-check context](#inclusion-check-contexts) and return its `inclusionListContextId`. For an `INVALID` response, this field **MUST** be `null`. The consensus layer can retrieve deferred results using `engine_getInclusionListStatusV1`, or `engine_forkchoiceUpdatedV5` when selecting that context's execution block as head. - ### engine_getPayloadV7 This method is updated to return `omissionClaims`. @@ -181,7 +166,7 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the built payload does not fall within the time frame of the Bogota fork. -2. `omissionClaims` **MUST NOT** have more than `MAX_OMISSION_CLAIMS` elements. Each claim **MUST** identify a distinct omitted Profile 2 candidate from the `inclusionListTransactions` used to build the payload, with an index no greater than `len(executionPayload.transactions)` at which its omission is excused under EIP-7805. +2. `omissionClaims` **MUST NOT** have more than `MAX_OMISSION_CLAIMS` elements. Each claim **MUST** identify a distinct omitted Profile 2 candidate from the `inclusionLists` used to build the payload, with an index no greater than `len(executionPayload.transactions)` at which its omission is excused under EIP-7805. ### engine_getInclusionListV1 @@ -219,13 +204,12 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 1. `forkchoiceState`: [`ForkchoiceStateV1`](./paris.md#forkchoicestatev1). 2. `payloadAttributes`: `Object|null` - Instance of [`PayloadAttributesV5`](#payloadattributesv5) or `null`. 3. `custodyColumns`: `DATA|null`, 16 Bytes - Interpreted as a bitarray of length `CELLS_PER_EXT_BLOB` indicating which column indices form the CL's custody set, or `null` if the CL does not provide custody services. - 4. `inclusionListContextId`: `DATA|null`, 32 Bytes - Context to query for `forkchoiceState.headBlockHash`, or `null` (also the default if omitted). * timeout: 8s #### Response * result: `object` - - `payloadStatus`: [`PayloadStatusV2`](#payloadstatusv2), with the same `status` value restrictions as [`engine_forkchoiceUpdatedV4`](./amsterdam.md#engine_forkchoiceupdatedv4). + - `payloadStatus`: [`PayloadStatusV1`](./paris.md#payloadstatusv1), with the same `status` value restrictions as [`engine_forkchoiceUpdatedV4`](./amsterdam.md#engine_forkchoiceupdatedv4). - `payloadId`: `DATA|null`, 8 Bytes - identifier of the payload build process or `null` * error: code and message set in case an exception happens while the validating payload, updating the forkchoice or initiating the payload build process. @@ -233,33 +217,14 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda This method follows the same specification as [`engine_forkchoiceUpdatedV4`](./amsterdam.md#engine_forkchoiceupdatedv4) with the following changes to the processing flow: -Before processing forkchoice or payload attributes, a non-null `inclusionListContextId` **MUST** be checked: return `-38007: Unknown inclusion context` if unavailable, or `-32602: Invalid params` if bound to a block other than `headBlockHash`. These errors **MUST NOT** change forkchoice or start a payload build. The response echoes the requested context ID and reports its completed inclusion verdict only when `payloadStatus.status` is `VALID`; a pending check returns `null` without delaying forkchoice processing. When no context is requested, both inclusion fields **MUST** be `null`. Head inclusion inputs **MUST NOT** be taken from `payloadAttributes`, which describes a child build. +This method reports execution validity only. Inclusion results are obtained by repeating `engine_newPayloadV6` with the original inputs; `payloadAttributes` describes the child build and cannot supply the head's inclusion inputs. 1. Extend point (8) of the `engine_forkchoiceUpdatedV1` [specification](./paris.md#specification-1) by defining the following sequence of checks that **MUST** be run over `payloadAttributes`: - 1. `payloadAttributes` matches the [`PayloadAttributesV5`](#payloadattributesv5) structure and `payloadAttributes.inclusionListTransactions` and `payloadAttributes.inclusionListMembership` pass checks (2.1) through (2.3) of [`engine_newPayloadV6`](#engine_newpayloadv6), return `-38003: Invalid payload attributes` on failure. Invalid transaction encodings or transaction validity failures are handled by EIP-7805, not rejected as invalid attributes. + 1. `payloadAttributes` matches the [`PayloadAttributesV5`](#payloadattributesv5) structure and `payloadAttributes.inclusionLists` passes check (2.1) of [`engine_newPayloadV6`](#engine_newpayloadv6), return `-38003: Invalid payload attributes` on failure. Invalid transaction encodings or transaction validity failures are handled by EIP-7805, not rejected as invalid attributes. 2. `payloadAttributes.timestamp` falls within the time frame of the Bogota fork, return `-38005: Unsupported fork` on failure. -### engine_getInclusionListStatusV1 - -#### Request - -* method: `engine_getInclusionListStatusV1` -* params: - 1. `inclusionListContextId`: `DATA`, 32 Bytes - Identifier returned by `engine_newPayloadV6`. -* timeout: 1s - -#### Response - -* result: [`PayloadStatusV2`](#payloadstatusv2) -* error: code and message set in case an exception happens while retrieving the status. - -#### Specification - -1. Client software **MUST** return `-38007: Unknown inclusion context` if the context is unavailable. -2. Otherwise, it **MUST** return the context's current execution status, echo its identifier, and set `inclusionListSatisfied` according to `engine_newPayloadV6` point (3). If execution has not completed and the required state is available, it **MUST** schedule validation. This method does not update forkchoice or initiate a payload build, and **MUST NOT** wait for pending validation or inclusion checking to finish. - ### Update the methods of previous forks #### Amsterdam API diff --git a/src/engine/common.md b/src/engine/common.md index 4282c4374..64ca875f5 100644 --- a/src/engine/common.md +++ b/src/engine/common.md @@ -100,7 +100,6 @@ The list of error codes introduced by this specification can be found below. | -38004 | Too large request | Number of requested entities is too large. | | -38005 | Unsupported fork | Payload belongs to a fork that is not supported. | | -38006 | Too deep reorg | Reorg depth exceeds limitation. | -| -38007 | Unknown inclusion context | Inclusion-check context does not exist / is not available. | Each error returns a `null` `data` value, except `-32000` which returns the `data` object with a `err` member that explains the error encountered. diff --git a/src/engine/openrpc/methods/forkchoice.yaml b/src/engine/openrpc/methods/forkchoice.yaml index 262cee70b..080315104 100644 --- a/src/engine/openrpc/methods/forkchoice.yaml +++ b/src/engine/openrpc/methods/forkchoice.yaml @@ -218,17 +218,10 @@ oneOf: - $ref: '#/components/schemas/bytes16' - type: 'null' - - name: Inclusion list context id - required: false - schema: - title: Head inclusion check context - oneOf: - - $ref: '#/components/schemas/hash32' - - type: 'null' result: name: Response object schema: - $ref: '#/components/schemas/ForkchoiceUpdatedResponseV2' + $ref: '#/components/schemas/ForkchoiceUpdatedResponseV1' errors: - code: -38002 message: Invalid forkchoice state @@ -240,5 +233,3 @@ message: Unsupported fork - code: -38006 message: Too deep reorg - - code: -38007 - message: Unknown inclusion context diff --git a/src/engine/openrpc/methods/inclusion_list.yaml b/src/engine/openrpc/methods/inclusion_list.yaml index 1dd6a5edb..cb5984417 100644 --- a/src/engine/openrpc/methods/inclusion_list.yaml +++ b/src/engine/openrpc/methods/inclusion_list.yaml @@ -11,48 +11,3 @@ maxItems: 8192 items: $ref: '#/components/schemas/InclusionListTransactionV1' -- name: engine_getInclusionListStatusV1 - summary: Obtains the execution and inclusion status for a registered context - externalDocs: - description: Method specification - url: https://github.com/ethereum/execution-apis/blob/main/src/engine/bogota.md#engine_getinclusionliststatusv1 - params: - - name: Inclusion list context id - required: true - schema: - $ref: '#/components/schemas/hash32' - result: - name: Payload status - schema: - title: Execution and inclusion status - $ref: '#/components/schemas/PayloadStatusV2' - errors: - - code: -38007 - message: Unknown inclusion context - - code: -32602 - message: Invalid params - examples: - - name: Pending inclusion check for a valid execution payload - params: - - name: Inclusion list context id - value: '0x1111111111111111111111111111111111111111111111111111111111111111' - result: - name: Payload status - value: - status: VALID - latestValidHash: '0x2222222222222222222222222222222222222222222222222222222222222222' - validationError: null - inclusionListSatisfied: null - inclusionListContextId: '0x1111111111111111111111111111111111111111111111111111111111111111' - - name: Completed unsatisfied inclusion check - params: - - name: Inclusion list context id - value: '0x1111111111111111111111111111111111111111111111111111111111111111' - result: - name: Payload status - value: - status: VALID - latestValidHash: '0x2222222222222222222222222222222222222222222222222222222222222222' - validationError: null - inclusionListSatisfied: false - inclusionListContextId: '0x1111111111111111111111111111111111111111111111111111111111111111' diff --git a/src/engine/openrpc/methods/payload.yaml b/src/engine/openrpc/methods/payload.yaml index 1484be0d6..cb3fec75a 100644 --- a/src/engine/openrpc/methods/payload.yaml +++ b/src/engine/openrpc/methods/payload.yaml @@ -1100,14 +1100,10 @@ type: array items: $ref: '#/components/schemas/bytes' - - name: Inclusion list transactions + - name: Inclusion lists required: true schema: - $ref: '#/components/schemas/InclusionListTransactionsV1' - - name: Inclusion list membership - required: true - schema: - $ref: '#/components/schemas/InclusionListMembershipsV1' + $ref: '#/components/schemas/InclusionListsV1' - name: Omission claims required: true schema: diff --git a/src/engine/openrpc/schemas/forkchoice.yaml b/src/engine/openrpc/schemas/forkchoice.yaml index f873e80bb..69073a9de 100644 --- a/src/engine/openrpc/schemas/forkchoice.yaml +++ b/src/engine/openrpc/schemas/forkchoice.yaml @@ -27,20 +27,6 @@ ForkchoiceUpdatedResponseV1: payloadId: title: Payload id $ref: '#/components/schemas/bytes8' -ForkchoiceUpdatedResponseV2: - title: Forkchoice updated response object V2 - type: object - required: - - payloadStatus - - payloadId - properties: - payloadStatus: - $ref: '#/components/schemas/RestrictedPayloadStatusV2' - payloadId: - title: Payload id - oneOf: - - $ref: '#/components/schemas/bytes8' - - type: 'null' PayloadAttributesV1: title: Payload attributes object V1 type: object @@ -138,8 +124,7 @@ PayloadAttributesV5: - parentBeaconBlockRoot - slotNumber - targetGasLimit - - inclusionListTransactions - - inclusionListMembership + - inclusionLists properties: timestamp: $ref: '#/components/schemas/PayloadAttributesV4/properties/timestamp' @@ -155,7 +140,5 @@ PayloadAttributesV5: $ref: '#/components/schemas/PayloadAttributesV4/properties/slotNumber' targetGasLimit: $ref: '#/components/schemas/PayloadAttributesV4/properties/targetGasLimit' - inclusionListTransactions: - $ref: '#/components/schemas/InclusionListTransactionsV1' - inclusionListMembership: - $ref: '#/components/schemas/InclusionListMembershipsV1' + inclusionLists: + $ref: '#/components/schemas/InclusionListsV1' diff --git a/src/engine/openrpc/schemas/payload.yaml b/src/engine/openrpc/schemas/payload.yaml index f74f5bbd6..4a85639f4 100644 --- a/src/engine/openrpc/schemas/payload.yaml +++ b/src/engine/openrpc/schemas/payload.yaml @@ -56,7 +56,6 @@ PayloadStatusV2: - latestValidHash - validationError - inclusionListSatisfied - - inclusionListContextId properties: status: $ref: '#/components/schemas/PayloadStatusNoInvalidBlockHash/properties/status' @@ -73,28 +72,6 @@ PayloadStatusV2: oneOf: - type: boolean - type: 'null' - inclusionListContextId: - title: Inclusion check context identifier - oneOf: - - $ref: '#/components/schemas/hash32' - - type: 'null' -RestrictedPayloadStatusV2: - $ref: '#/components/schemas/PayloadStatusV2' - properties: - status: - $ref: '#/components/schemas/PayloadStatusV2/properties/status' - enum: - - VALID - - INVALID - - SYNCING - latestValidHash: - $ref: '#/components/schemas/PayloadStatusV2/properties/latestValidHash' - validationError: - $ref: '#/components/schemas/PayloadStatusV2/properties/validationError' - inclusionListSatisfied: - $ref: '#/components/schemas/PayloadStatusV2/properties/inclusionListSatisfied' - inclusionListContextId: - $ref: '#/components/schemas/PayloadStatusV2/properties/inclusionListContextId' ExecutionPayloadV1: title: Execution payload object V1 type: object @@ -463,23 +440,14 @@ InclusionListTransactionV1: type: string pattern: ^0x([0-9a-f]{2})+$ maxLength: 16386 -InclusionListTransactionsV1: - title: Distinct inclusion list transaction bytes - type: array - uniqueItems: true - maxItems: 131072 - items: - $ref: '#/components/schemas/InclusionListTransactionV1' -InclusionListMembershipV1: - title: Inclusion list membership bitvector over the inclusion list committee - description: SSZ Bitvector[16], with bit i in bit i modulo 8 of byte i divided by 8; positions 0 and 9 encode as 0x0102. - type: string - pattern: ^0x[0-9a-f]{4}$ - not: - const: '0x0000' -InclusionListMembershipsV1: - title: Membership per inclusion list transaction +InclusionListsV1: + title: Inclusion lists by committee position + description: Preserve each selected IL, including duplicates; each list has an aggregate 8192-byte limit before deduplication. type: array - maxItems: 131072 + minItems: 16 + maxItems: 16 items: - $ref: '#/components/schemas/InclusionListMembershipV1' + type: array + maxItems: 8192 + items: + $ref: '#/components/schemas/InclusionListTransactionV1' diff --git a/wordlist.txt b/wordlist.txt index 1f479ff11..ded829561 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -60,16 +60,13 @@ getblobsv getclientversionv getinclusionlistv getInclusionListV -getInclusionListStatusV graphql greppable gwei https OmissionClaimV OmissionClaimsV -InclusionListMembershipV -InclusionListMembershipsV -InclusionListTransactionsV +InclusionListsV interop ipc js From 32c55d0660e71aac9663a751d9842b5fe8e15277 Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Wed, 14 Oct 2026 22:55:37 +0100 Subject: [PATCH 14/17] engine: query deferred inclusion verdicts by identifier --- src/engine/bogota.md | 48 +++++++++++++++---- src/engine/common.md | 1 + .../openrpc/methods/inclusion_list.yaml | 19 ++++++++ src/engine/openrpc/schemas/payload.yaml | 6 +++ 4 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/engine/bogota.md b/src/engine/bogota.md index b112bb26c..4c8b1b0f8 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -30,10 +30,14 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. - [Request](#request-2) - [Response](#response-2) - [Specification](#specification-2) - - [engine_forkchoiceUpdatedV5](#engine_forkchoiceupdatedv5) + - [engine_getInclusionListVerdictV1](#engine_getinclusionlistverdictv1) - [Request](#request-3) - [Response](#response-3) - [Specification](#specification-3) + - [engine_forkchoiceUpdatedV5](#engine_forkchoiceupdatedv5) + - [Request](#request-4) + - [Response](#response-4) + - [Specification](#specification-4) - [Update the methods of previous forks](#update-the-methods-of-previous-forks) - [Amsterdam API](#amsterdam-api) @@ -69,18 +73,19 @@ The consensus layer selects valid, non-equivocating ILs under EIP-7805. A member ### PayloadStatusV2 -This structure has the syntax of `PayloadStatusV1` and appends `inclusionListSatisfied`. +This structure has the syntax of `PayloadStatusV1` and appends `inclusionListSatisfied` and `inclusionCheckId`. - `status`: `enum` - `"VALID" | "INVALID" | "SYNCING" | "ACCEPTED"` - `latestValidHash`: `DATA|null`, 32 Bytes - the hash of the most recent *valid* block in the branch defined by payload and its ancestors - `validationError`: `String|null` - a message providing additional details on the validation error if the payload is classified as `INVALID`. -- `inclusionListSatisfied`: `BOOLEAN|null` - the completed inclusion verdict for this call's exact inputs and a `VALID` payload; `null` while execution or inclusion checking is pending, or if execution is invalid. +- `inclusionListSatisfied`: `BOOLEAN|null` - the completed verdict for `inclusionCheckId`; `null` while pending or when execution is not `VALID`. +- `inclusionCheckId`: `DATA|null`, 32 Bytes - identifier defined below, present exactly when execution is `VALID`, including for a completed check. ### OmissionClaimV1 This structure maps onto the omission claim defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). The fields are encoded as follows: -- `transactionHash`: `DATA`, 32 Bytes - `keccak256` of the claimed inclusion list transaction, `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). +- `transactionHash`: `DATA`, 32 Bytes - Ordinary transaction hash of the claimed inclusion list transaction. - `evaluationIndex`: `QUANTITY`, 64 Bits - index in `executionPayload.transactions` at which the omission of the claimed transaction is evaluated. Index zero is before the first transaction; `len(executionPayload.transactions)` is the end of the payload. The claim list retains its committed order and duplicates. The consensus layer checks its commitment; the execution layer applies EIP-7805's evaluation rules. @@ -89,9 +94,13 @@ Index zero is before the first transaction; `len(executionPayload.transactions)` ### Deferred inclusion checking -Execution validation and inclusion checking may complete asynchronously. A pending inclusion verdict is `null`, including when execution is already `VALID`. The consensus layer **MUST** retain the original `engine_newPayloadV6` inputs and repeat that call until a completed verdict is returned or the block is abandoned; it **MUST NOT** substitute a later IL view or treat a pending check as satisfied. +Execution validation and inclusion checking may complete asynchronously. Once execution is `VALID`, the EL **MUST** schedule inclusion checking and promptly return its identifier and current verdict without waiting for that check. The CL polls [`engine_getInclusionListVerdictV1`](#engine_getinclusionlistverdictv1); pending is never satisfaction. Inclusion failure **MUST NOT** change execution validity or forkchoice processing. + +The identifier is `keccak256(b"engine/inclusion-check/v1" || RLP([blockHash, inclusionLists, claims]))`, where `claims` is `[[transactionHash, evaluationIndex], ...]`. Hashes and transactions are byte strings; indices use canonical RLP unsigned integers. Preserve list boundaries, committee positions, transaction order, duplicate entries and claim order. `blockHash` is the validated execution payload hash; all other `newPayload` validation requirements still apply before issuing or reusing an identifier. -The execution layer **MUST** schedule inclusion checking when execution is `VALID` and the required state is available. Repeated calls **MUST NOT** restart identical in-progress work. Clients **MAY** cache results and share execution data, but an inclusion verdict **MUST** apply to the call's exact execution block, `inclusionLists` and `omissionClaims`; execution hash alone is insufficient. A completed verdict for identical inputs **MUST NOT** change. Inclusion failure **MUST NOT** change execution validity or forkchoice processing. +An identifier names one check. Identical in-progress checks **MUST** share work and a completed verdict **MUST NOT** change. Implementations **MAY** share execution data across checks. If prior execution did not retain the required insertion states and both gas counters, checking may require re-execution; authenticated BAL-indexed reconstruction can avoid this only with the corresponding gas counters available. + +The CL **MUST** retain the original inputs until completion or abandonment and associate the identifier with its beacon block and frozen IL view. The EL **MAY** evict checks to bound local resources. After `Unknown inclusion check`, including after an EL restart, the CL **MAY** resubmit those original inputs; it **MUST NOT** substitute a later view. Polling itself never creates or restarts work. The identifier is local API state, not a consensus commitment. ### Payload building @@ -136,7 +145,7 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda Otherwise well-formed transaction byte strings **MUST NOT** cause an RPC error solely because their transaction encoding or validity checks fail. Well-formed duplicate or unmatched claims, and indices above the payload transaction count, **MUST NOT** cause an RPC error: EIP-7805 ignores repeated transaction hashes and irrelevant claims, and clamps remaining indices to the end of the payload. Exceeding the VERIFY budget is likewise handled by EIP-7805's per-member fill, not as an RPC error. -3. Client software **MUST** evaluate inclusion against this call's inputs, even if execution validity is already known. It **MUST** return `inclusionListSatisfied` as the completed boolean verdict only if execution is `VALID`; otherwise, including while inclusion checking is pending, it **MUST** return `null`. +3. Client software **MUST** evaluate inclusion against this call's inputs, even if execution validity is already known. It **MUST** return `inclusionListSatisfied` as the completed boolean verdict only if execution is `VALID`; otherwise, including while inclusion checking is pending, it **MUST** return `null`. It **MUST** return `inclusionCheckId` exactly when execution is `VALID`, following [Deferred inclusion checking](#deferred-inclusion-checking). Known execution validity **MUST NOT** be held until inclusion checking completes. ### engine_getPayloadV7 @@ -166,7 +175,7 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the built payload does not fall within the time frame of the Bogota fork. -2. `omissionClaims` **MUST NOT** have more than `MAX_OMISSION_CLAIMS` elements. Each claim **MUST** identify a distinct omitted Profile 2 candidate from the `inclusionLists` used to build the payload, with an index no greater than `len(executionPayload.transactions)` at which its omission is excused under EIP-7805. +2. `omissionClaims` **MUST NOT** have more than `MAX_OMISSION_CLAIMS` elements. The EL **MUST** emit only claims it has verified: each identifies a distinct omitted Profile 2 candidate from the build's `inclusionLists`, with an index no greater than `len(executionPayload.transactions)` at which EIP-7805 excuses its omission. ### engine_getInclusionListV1 @@ -195,8 +204,29 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 2. The strategy for selecting transactions is implementation dependent. +### engine_getInclusionListVerdictV1 + +#### Request + +* method: `engine_getInclusionListVerdictV1` +* params: + 1. `inclusionCheckId`: `DATA`, 32 Bytes - Identifier returned by `engine_newPayloadV6`. +* timeout: 1s + +#### Response + +* result: `BOOLEAN|null` - Completed verdict, or `null` while the identified check is pending. +* error: `-38007: Unknown inclusion check` if the identifier is unknown or evicted. + +#### Specification + +1. Client software **MUST** return the current verdict promptly, without waiting for pending work or starting a new check. +2. An unknown identifier **MUST** return the error above, not `null`. + ### engine_forkchoiceUpdatedV5 +Compared with V4, only the payload attributes change to `PayloadAttributesV5`; the response remains `PayloadStatusV1`. + #### Request * method: `engine_forkchoiceUpdatedV5` @@ -217,7 +247,7 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda This method follows the same specification as [`engine_forkchoiceUpdatedV4`](./amsterdam.md#engine_forkchoiceupdatedv4) with the following changes to the processing flow: -This method reports execution validity only. Inclusion results are obtained by repeating `engine_newPayloadV6` with the original inputs; `payloadAttributes` describes the child build and cannot supply the head's inclusion inputs. +This method reports execution validity only. Deferred inclusion results are obtained with `engine_getInclusionListVerdictV1`; `payloadAttributes` describes the child build and cannot supply the head's inclusion inputs. 1. Extend point (8) of the `engine_forkchoiceUpdatedV1` [specification](./paris.md#specification-1) by defining the following sequence of checks that **MUST** be run over `payloadAttributes`: diff --git a/src/engine/common.md b/src/engine/common.md index 64ca875f5..db853a6a9 100644 --- a/src/engine/common.md +++ b/src/engine/common.md @@ -100,6 +100,7 @@ The list of error codes introduced by this specification can be found below. | -38004 | Too large request | Number of requested entities is too large. | | -38005 | Unsupported fork | Payload belongs to a fork that is not supported. | | -38006 | Too deep reorg | Reorg depth exceeds limitation. | +| -38007 | Unknown inclusion check | Inclusion check identifier is unknown or evicted. | Each error returns a `null` `data` value, except `-32000` which returns the `data` object with a `err` member that explains the error encountered. diff --git a/src/engine/openrpc/methods/inclusion_list.yaml b/src/engine/openrpc/methods/inclusion_list.yaml index cb5984417..571f5bcd3 100644 --- a/src/engine/openrpc/methods/inclusion_list.yaml +++ b/src/engine/openrpc/methods/inclusion_list.yaml @@ -11,3 +11,22 @@ maxItems: 8192 items: $ref: '#/components/schemas/InclusionListTransactionV1' +- name: engine_getInclusionListVerdictV1 + summary: Obtains the current verdict of an existing inclusion check + externalDocs: + description: Method specification + url: https://github.com/ethereum/execution-apis/blob/main/src/engine/bogota.md#engine_getinclusionlistverdictv1 + params: + - name: inclusionCheckId + required: true + schema: + $ref: '#/components/schemas/hash32' + result: + name: Inclusion list verdict + schema: + oneOf: + - type: boolean + - type: 'null' + errors: + - code: -38007 + message: Unknown inclusion check diff --git a/src/engine/openrpc/schemas/payload.yaml b/src/engine/openrpc/schemas/payload.yaml index 4a85639f4..e192aee72 100644 --- a/src/engine/openrpc/schemas/payload.yaml +++ b/src/engine/openrpc/schemas/payload.yaml @@ -56,6 +56,7 @@ PayloadStatusV2: - latestValidHash - validationError - inclusionListSatisfied + - inclusionCheckId properties: status: $ref: '#/components/schemas/PayloadStatusNoInvalidBlockHash/properties/status' @@ -72,6 +73,11 @@ PayloadStatusV2: oneOf: - type: boolean - type: 'null' + inclusionCheckId: + title: Identifier of the inclusion check for a VALID payload + oneOf: + - $ref: '#/components/schemas/hash32' + - type: 'null' ExecutionPayloadV1: title: Execution payload object V1 type: object From 22382fb9e7d292878ca88c775d45a65e47200dbf Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Wed, 14 Oct 2026 22:57:52 +0100 Subject: [PATCH 15/17] Add inclusion verdict API terms to spellcheck dictionary --- wordlist.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wordlist.txt b/wordlist.txt index ded829561..b96ec4d35 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -60,6 +60,8 @@ getblobsv getclientversionv getinclusionlistv getInclusionListV +getinclusionlistverdictv +getInclusionListVerdictV graphql greppable gwei @@ -131,3 +133,4 @@ yaml yParity ZkExecutionErrors ZK +ILs From a3f63f9d188c967c77b0b7db3507c68549b008aa Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Thu, 15 Oct 2026 09:33:40 +0100 Subject: [PATCH 16/17] engine: specify undecidable checks, verdict retention and claim index encoding Add MAX_VERIFY_GAS_PER_TX and note that the Bogota IL shapes replace the FOCIL devnet shapes. --- src/engine/bogota.md | 13 ++++++++++--- wordlist.txt | 2 ++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/engine/bogota.md b/src/engine/bogota.md index 4c8b1b0f8..fae7779be 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -51,8 +51,11 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. | `INCLUSION_LIST_COMMITTEE_SIZE` | `uint64(16) = 2**4` | | `MAX_OMISSION_CLAIMS` | `uint64(4096) = 2**12` | | `MAX_VERIFY_GAS_PER_IL` | `uint64(1048576) = 2**20` | +| `MAX_VERIFY_GAS_PER_TX` | `uint64(262144) = 2**18` | -Both EIP-7805 profiles apply from Bogota activation. The VERIFY budget and claim cap are defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805#constants). +Both EIP-7805 profiles apply from Bogota activation. The VERIFY budgets and claim cap are defined in [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805#constants). + +`engine_newPayloadV6`, `PayloadAttributesV5` and `engine_forkchoiceUpdatedV5` replace the earlier FOCIL devnet shapes in place: the flat `inclusionListTransactions` list becomes separate `inclusionLists` plus `omissionClaims`, and `engine_forkchoiceUpdatedV5` returns `PayloadStatusV1` again. Test fixtures and releases built for the earlier shapes **MUST** be regenerated. ## Structures @@ -100,7 +103,11 @@ The identifier is `keccak256(b"engine/inclusion-check/v1" || RLP([blockHash, inc An identifier names one check. Identical in-progress checks **MUST** share work and a completed verdict **MUST NOT** change. Implementations **MAY** share execution data across checks. If prior execution did not retain the required insertion states and both gas counters, checking may require re-execution; authenticated BAL-indexed reconstruction can avoid this only with the corresponding gas counters available. -The CL **MUST** retain the original inputs until completion or abandonment and associate the identifier with its beacon block and frozen IL view. The EL **MAY** evict checks to bound local resources. After `Unknown inclusion check`, including after an EL restart, the CL **MAY** resubmit those original inputs; it **MUST NOT** substitute a later view. Polling itself never creates or restarts work. The identifier is local API state, not a consensus commitment. +If the EL cannot reconstruct the state or gas counters a check requires, the check stays pending; missing local data **MUST NOT** produce a verdict. The EL **MAY** complete the check once the data is available, or evict it; a resubmission **MAY** run the check again once the data is available. A check that stays pending at the proposal-slot parent decision gets the CL's empty-payload fallback defined by EIP-7805. + +The EL **SHOULD** retain a completed verdict at least until its block is finalized or pruned from fork choice, that is, until a finalized block reported through `engine_forkchoiceUpdated` has a block number at least that of the checked block. The EL **MAY** evict pending checks to bound local resources, and **MAY** evict a completed verdict earlier only under resource pressure. Eviction never changes a verdict; it only makes the identifier unknown. + +The CL **MUST** retain the original inputs until completion or abandonment and associate the identifier with its beacon block and frozen IL view. After `Unknown inclusion check`, including after an EL restart, the CL **MAY** resubmit those original inputs; it **MUST NOT** substitute a later view. Polling itself never creates or restarts work. The identifier is local API state, not a consensus commitment. ### Payload building @@ -141,7 +148,7 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda 1. `inclusionLists` does not have exactly `INCLUSION_LIST_COMMITTEE_SIZE` entries, an entry is not a list of nonempty byte strings, or the total transaction byte length of any entry exceeds `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`. - 2. `omissionClaims` has more than `MAX_OMISSION_CLAIMS` elements or an element does not match `OmissionClaimV1`, including a malformed hash or a noncanonical or overflowing `uint64` index. + 2. `omissionClaims` has more than `MAX_OMISSION_CLAIMS` elements or an element does not match `OmissionClaimV1`, including a `transactionHash` that is not 32 bytes of `DATA`, or an `evaluationIndex` that does not follow the `QUANTITY` [encoding](./common.md#encoding) or exceeds `2**64 - 1`. For example, an `evaluationIndex` of `"0x01"`, `"0x"` or `"0x10000000000000000"` **MUST** return `-32602`. Otherwise well-formed transaction byte strings **MUST NOT** cause an RPC error solely because their transaction encoding or validity checks fail. Well-formed duplicate or unmatched claims, and indices above the payload transaction count, **MUST NOT** cause an RPC error: EIP-7805 ignores repeated transaction hashes and irrelevant claims, and clamps remaining indices to the end of the payload. Exceeding the VERIFY budget is likewise handled by EIP-7805's per-member fill, not as an RPC error. diff --git a/wordlist.txt b/wordlist.txt index b96ec4d35..57a1725ab 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -30,6 +30,7 @@ CLs configurationv CRC crypto +devnet DocToc eg eip @@ -52,6 +53,7 @@ exitv FCU FCUs feeRecipient +FOCIL forkchoiceupdatedresponsev FP Fulu From 51451e8da347984945b9c24f57408d9e51132922 Mon Sep 17 00:00:00 2001 From: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Date: Tue, 27 Oct 2026 13:00:00 +0000 Subject: [PATCH 17/17] Return completed inclusion verdicts with newPayload --- src/engine/bogota.md | 50 ++++--------------- src/engine/common.md | 1 - .../openrpc/methods/inclusion_list.yaml | 19 ------- src/engine/openrpc/schemas/payload.yaml | 8 +-- wordlist.txt | 1 - 5 files changed, 10 insertions(+), 69 deletions(-) diff --git a/src/engine/bogota.md b/src/engine/bogota.md index fae7779be..d7cba8bd7 100644 --- a/src/engine/bogota.md +++ b/src/engine/bogota.md @@ -15,7 +15,7 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. - [PayloadStatusV2](#payloadstatusv2) - [OmissionClaimV1](#omissionclaimv1) - [Routines](#routines) - - [Deferred inclusion checking](#deferred-inclusion-checking) + - [Inclusion checking](#inclusion-checking) - [Payload building](#payload-building) - [Methods](#methods) - [engine_newPayloadV6](#engine_newpayloadv6) @@ -30,14 +30,10 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam. - [Request](#request-2) - [Response](#response-2) - [Specification](#specification-2) - - [engine_getInclusionListVerdictV1](#engine_getinclusionlistverdictv1) + - [engine_forkchoiceUpdatedV5](#engine_forkchoiceupdatedv5) - [Request](#request-3) - [Response](#response-3) - [Specification](#specification-3) - - [engine_forkchoiceUpdatedV5](#engine_forkchoiceupdatedv5) - - [Request](#request-4) - - [Response](#response-4) - - [Specification](#specification-4) - [Update the methods of previous forks](#update-the-methods-of-previous-forks) - [Amsterdam API](#amsterdam-api) @@ -76,13 +72,12 @@ The consensus layer selects valid, non-equivocating ILs under EIP-7805. A member ### PayloadStatusV2 -This structure has the syntax of `PayloadStatusV1` and appends `inclusionListSatisfied` and `inclusionCheckId`. +This structure has the syntax of `PayloadStatusV1` and appends `inclusionListSatisfied`. - `status`: `enum` - `"VALID" | "INVALID" | "SYNCING" | "ACCEPTED"` - `latestValidHash`: `DATA|null`, 32 Bytes - the hash of the most recent *valid* block in the branch defined by payload and its ancestors - `validationError`: `String|null` - a message providing additional details on the validation error if the payload is classified as `INVALID`. -- `inclusionListSatisfied`: `BOOLEAN|null` - the completed verdict for `inclusionCheckId`; `null` while pending or when execution is not `VALID`. -- `inclusionCheckId`: `DATA|null`, 32 Bytes - identifier defined below, present exactly when execution is `VALID`, including for a completed check. +- `inclusionListSatisfied`: `BOOLEAN|null` - the completed inclusion verdict when `status` is `VALID`; `null` otherwise. ### OmissionClaimV1 @@ -95,19 +90,11 @@ Index zero is before the first transaction; `len(executionPayload.transactions)` ## Routines -### Deferred inclusion checking - -Execution validation and inclusion checking may complete asynchronously. Once execution is `VALID`, the EL **MUST** schedule inclusion checking and promptly return its identifier and current verdict without waiting for that check. The CL polls [`engine_getInclusionListVerdictV1`](#engine_getinclusionlistverdictv1); pending is never satisfaction. Inclusion failure **MUST NOT** change execution validity or forkchoice processing. - -The identifier is `keccak256(b"engine/inclusion-check/v1" || RLP([blockHash, inclusionLists, claims]))`, where `claims` is `[[transactionHash, evaluationIndex], ...]`. Hashes and transactions are byte strings; indices use canonical RLP unsigned integers. Preserve list boundaries, committee positions, transaction order, duplicate entries and claim order. `blockHash` is the validated execution payload hash; all other `newPayload` validation requirements still apply before issuing or reusing an identifier. - -An identifier names one check. Identical in-progress checks **MUST** share work and a completed verdict **MUST NOT** change. Implementations **MAY** share execution data across checks. If prior execution did not retain the required insertion states and both gas counters, checking may require re-execution; authenticated BAL-indexed reconstruction can avoid this only with the corresponding gas counters available. +### Inclusion checking -If the EL cannot reconstruct the state or gas counters a check requires, the check stays pending; missing local data **MUST NOT** produce a verdict. The EL **MAY** complete the check once the data is available, or evict it; a resubmission **MAY** run the check again once the data is available. A check that stays pending at the proposal-slot parent decision gets the CL's empty-payload fallback defined by EIP-7805. +A `VALID` response to `engine_newPayloadV6` **MUST** include the completed inclusion verdict for that call's separate ILs and omission claims. An unsatisfied inclusion list **MUST NOT** change execution validity or forkchoice processing. Forkchoice responses do not report inclusion satisfaction. -The EL **SHOULD** retain a completed verdict at least until its block is finalized or pruned from fork choice, that is, until a finalized block reported through `engine_forkchoiceUpdated` has a block number at least that of the checked block. The EL **MAY** evict pending checks to bound local resources, and **MAY** evict a completed verdict earlier only under resource pressure. Eviction never changes a verdict; it only makes the identifier unknown. - -The CL **MUST** retain the original inputs until completion or abandonment and associate the identifier with its beacon block and frozen IL view. After `Unknown inclusion check`, including after an EL restart, the CL **MAY** resubmit those original inputs; it **MUST NOT** substitute a later view. Polling itself never creates or restarts work. The identifier is local API state, not a consensus commitment. +Checking may require re-execution if prior execution did not retain the required insertion states and both gas counters. Authenticated BAL-indexed reconstruction can avoid this only with the corresponding gas counters available. Missing local data **MUST NOT** excuse an omission or produce a `VALID` response before inclusion checking completes; normal execution-sync statuses and RPC timeout/error handling apply. ### Payload building @@ -152,7 +139,7 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda Otherwise well-formed transaction byte strings **MUST NOT** cause an RPC error solely because their transaction encoding or validity checks fail. Well-formed duplicate or unmatched claims, and indices above the payload transaction count, **MUST NOT** cause an RPC error: EIP-7805 ignores repeated transaction hashes and irrelevant claims, and clamps remaining indices to the end of the payload. Exceeding the VERIFY budget is likewise handled by EIP-7805's per-member fill, not as an RPC error. -3. Client software **MUST** evaluate inclusion against this call's inputs, even if execution validity is already known. It **MUST** return `inclusionListSatisfied` as the completed boolean verdict only if execution is `VALID`; otherwise, including while inclusion checking is pending, it **MUST** return `null`. It **MUST** return `inclusionCheckId` exactly when execution is `VALID`, following [Deferred inclusion checking](#deferred-inclusion-checking). Known execution validity **MUST NOT** be held until inclusion checking completes. +3. Client software **MUST** evaluate inclusion against this call's inputs, even if execution validity is already known. It **MUST** complete inclusion checking before returning `VALID`, with `inclusionListSatisfied` set to the boolean verdict. For any other execution status, `inclusionListSatisfied` **MUST** be `null`. ### engine_getPayloadV7 @@ -211,25 +198,6 @@ This method follows the same specification as [`engine_getPayloadV6`](./amsterda 2. The strategy for selecting transactions is implementation dependent. -### engine_getInclusionListVerdictV1 - -#### Request - -* method: `engine_getInclusionListVerdictV1` -* params: - 1. `inclusionCheckId`: `DATA`, 32 Bytes - Identifier returned by `engine_newPayloadV6`. -* timeout: 1s - -#### Response - -* result: `BOOLEAN|null` - Completed verdict, or `null` while the identified check is pending. -* error: `-38007: Unknown inclusion check` if the identifier is unknown or evicted. - -#### Specification - -1. Client software **MUST** return the current verdict promptly, without waiting for pending work or starting a new check. -2. An unknown identifier **MUST** return the error above, not `null`. - ### engine_forkchoiceUpdatedV5 Compared with V4, only the payload attributes change to `PayloadAttributesV5`; the response remains `PayloadStatusV1`. @@ -254,7 +222,7 @@ Compared with V4, only the payload attributes change to `PayloadAttributesV5`; t This method follows the same specification as [`engine_forkchoiceUpdatedV4`](./amsterdam.md#engine_forkchoiceupdatedv4) with the following changes to the processing flow: -This method reports execution validity only. Deferred inclusion results are obtained with `engine_getInclusionListVerdictV1`; `payloadAttributes` describes the child build and cannot supply the head's inclusion inputs. +This method reports execution validity only. Inclusion results are returned by `engine_newPayloadV6`; `payloadAttributes` describes the child build and cannot supply the head's inclusion inputs. 1. Extend point (8) of the `engine_forkchoiceUpdatedV1` [specification](./paris.md#specification-1) by defining the following sequence of checks that **MUST** be run over `payloadAttributes`: diff --git a/src/engine/common.md b/src/engine/common.md index db853a6a9..64ca875f5 100644 --- a/src/engine/common.md +++ b/src/engine/common.md @@ -100,7 +100,6 @@ The list of error codes introduced by this specification can be found below. | -38004 | Too large request | Number of requested entities is too large. | | -38005 | Unsupported fork | Payload belongs to a fork that is not supported. | | -38006 | Too deep reorg | Reorg depth exceeds limitation. | -| -38007 | Unknown inclusion check | Inclusion check identifier is unknown or evicted. | Each error returns a `null` `data` value, except `-32000` which returns the `data` object with a `err` member that explains the error encountered. diff --git a/src/engine/openrpc/methods/inclusion_list.yaml b/src/engine/openrpc/methods/inclusion_list.yaml index 571f5bcd3..cb5984417 100644 --- a/src/engine/openrpc/methods/inclusion_list.yaml +++ b/src/engine/openrpc/methods/inclusion_list.yaml @@ -11,22 +11,3 @@ maxItems: 8192 items: $ref: '#/components/schemas/InclusionListTransactionV1' -- name: engine_getInclusionListVerdictV1 - summary: Obtains the current verdict of an existing inclusion check - externalDocs: - description: Method specification - url: https://github.com/ethereum/execution-apis/blob/main/src/engine/bogota.md#engine_getinclusionlistverdictv1 - params: - - name: inclusionCheckId - required: true - schema: - $ref: '#/components/schemas/hash32' - result: - name: Inclusion list verdict - schema: - oneOf: - - type: boolean - - type: 'null' - errors: - - code: -38007 - message: Unknown inclusion check diff --git a/src/engine/openrpc/schemas/payload.yaml b/src/engine/openrpc/schemas/payload.yaml index e192aee72..1ffc6fb94 100644 --- a/src/engine/openrpc/schemas/payload.yaml +++ b/src/engine/openrpc/schemas/payload.yaml @@ -56,7 +56,6 @@ PayloadStatusV2: - latestValidHash - validationError - inclusionListSatisfied - - inclusionCheckId properties: status: $ref: '#/components/schemas/PayloadStatusNoInvalidBlockHash/properties/status' @@ -69,15 +68,10 @@ PayloadStatusV2: - string - 'null' inclusionListSatisfied: - title: Whether the payload satisfied the inclusion list constraints + title: Completed inclusion verdict for VALID execution, otherwise null oneOf: - type: boolean - type: 'null' - inclusionCheckId: - title: Identifier of the inclusion check for a VALID payload - oneOf: - - $ref: '#/components/schemas/hash32' - - type: 'null' ExecutionPayloadV1: title: Execution payload object V1 type: object diff --git a/wordlist.txt b/wordlist.txt index 57a1725ab..edc896321 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -63,7 +63,6 @@ getclientversionv getinclusionlistv getInclusionListV getinclusionlistverdictv -getInclusionListVerdictV graphql greppable gwei