Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
26390af
engine: add inclusion list claims and grouped inclusion lists (EIP-XXXX)
Marchhill Sep 29, 2026
5ff66a9
engine: rename to EIP-8369 and add forkchoiceUpdatedV6 with grouped i…
Marchhill Sep 29, 2026
bdda9df
engine: move inclusion list claims and grouped inclusion lists into B…
Marchhill Sep 29, 2026
60b0306
engine: return inclusion list claims from a new engine_getPayloadV7
Marchhill Sep 29, 2026
b31d15a
engine: replace grouped inclusion lists with membership bitvectors
Marchhill Sep 29, 2026
4f0c98b
engine: bound the Profile 2 VERIFY cost of engine_getInclusionListV1
Marchhill Sep 29, 2026
0a7ac8d
engine: set MAX_INCLUSION_LIST_CLAIMS to 2**12
Marchhill Oct 8, 2026
33104ce
engine: bind inclusion verdicts to explicit claim context
Marchhill Oct 10, 2026
7c01d32
Add inclusion list schema names to spelling dictionary
Marchhill Oct 10, 2026
801c296
engine: support deferred inclusion checks by context
Marchhill Oct 13, 2026
cb79715
engine: rename claim evaluationIndex and align profile activation
Marchhill Oct 13, 2026
c6375a7
engine: rename omission claims consistently
Marchhill Oct 13, 2026
fa26676
engine: separate ILs and remove inclusion context handles
Marchhill Oct 14, 2026
32c55d0
engine: query deferred inclusion verdicts by identifier
Marchhill Oct 14, 2026
22382fb
Add inclusion verdict API terms to spellcheck dictionary
Marchhill Oct 14, 2026
a3f63f9
engine: specify undecidable checks, verdict retention and claim index…
Marchhill Oct 15, 2026
51451e8
Return completed inclusion verdicts with newPayload
Marchhill Oct 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 87 additions & 24 deletions src/engine/bogota.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,27 @@ This specification is based on and extends [Engine API - Amsterdam](./amsterdam.
- [Structures](#structures)
- [PayloadAttributesV5](#payloadattributesv5)
- [PayloadStatusV2](#payloadstatusv2)
- [OmissionClaimV1](#omissionclaimv1)
- [Routines](#routines)
- [Inclusion checking](#inclusion-checking)
- [Payload building](#payload-building)
- [Methods](#methods)
- [engine_newPayloadV6](#engine_newpayloadv6)
- [Request](#request)
- [Response](#response)
- [Specification](#specification)
- [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)

Expand All @@ -38,12 +44,20 @@ 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_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 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

### 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 `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
Expand All @@ -52,30 +66,47 @@ 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).
- `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 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 a single field: `inclusionListSatisfied`
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` - whether the payload satisfied the inclusion list constraints if it is deemed `VALID`; `null` otherwise.
- `inclusionListSatisfied`: `BOOLEAN|null` - the completed inclusion verdict when `status` is `VALID`; `null` otherwise.

### 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 - 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.

## Routines

### Inclusion checking

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.

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

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 `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`.
Method parameter list is extended with `inclusionLists` and `omissionClaims`.

#### Request

Expand All @@ -85,7 +116,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. `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
Expand All @@ -99,13 +131,45 @@ 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 any of the following holds:

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 `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.

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

1. If the payload is deemed `VALID`, `inclusionListSatisfied` **MUST** be set to whether the payload satisfied the inclusion list constraints.
This method is updated to return `omissionClaims`.

2. Otherwise, `inclusionListSatisfied` **MUST** be `null`.
#### 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.
- `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

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.
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 does not fall within the time frame of the Bogota fork.

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

Expand All @@ -130,10 +194,14 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda

3. The total byte length of the transaction list **MUST NOT** exceed `MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST`.

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.

### engine_forkchoiceUpdatedV5

Compared with V4, only the payload attributes change to `PayloadAttributesV5`; the response remains `PayloadStatusV1`.

#### Request

* method: `engine_forkchoiceUpdatedV5`
Expand All @@ -146,27 +214,21 @@ This method follows the same specification as [`engine_newPayloadV5`](./amsterda
#### 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.

#### Specification

This method follows the same specification as [`engine_forkchoiceUpdatedV4`](./amsterdam.md#engine_forkchoiceupdatedv4) 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`:
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. `payloadAttributes` matches the [`PayloadAttributesV5`](#payloadattributesv5) structure, 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.
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. 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.
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.

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

Expand All @@ -175,6 +237,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:
Expand Down
6 changes: 4 additions & 2 deletions src/engine/openrpc/methods/forkchoice.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -219,7 +221,7 @@
result:
name: Response object
schema:
$ref: '#/components/schemas/ForkchoiceUpdatedResponseV2'
$ref: '#/components/schemas/ForkchoiceUpdatedResponseV1'
errors:
- code: -38002
message: Invalid forkchoice state
Expand Down
3 changes: 2 additions & 1 deletion src/engine/openrpc/methods/inclusion_list.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
name: Inclusion list transactions
schema:
type: array
maxItems: 8192
items:
$ref: '#/components/schemas/bytes'
$ref: '#/components/schemas/InclusionListTransactionV1'
Loading