Skip to content

feat: add Bogota to the REST + SSZ engine spec - #920

Open
barnabasbusa wants to merge 3 commits into
ethereum:mainfrom
barnabasbusa:bbusa/rest-ssz-bogota
Open

barnabasbusa wants to merge 3 commits into
ethereum:mainfrom
barnabasbusa:bbusa/rest-ssz-bogota

Conversation

@barnabasbusa

Copy link
Copy Markdown
Member

The REST + SSZ engine spec from #793 covers Paris through Amsterdam only, so the Bogota (Heze) FOCIL changes from bogota.md (EIP-7805) have no wire shape there. This adds bogota as an Eth-Execution-Version value with PayloadAttributesBogota and ExecutionPayloadEnvelopeBogota carrying inclusion_list_transactions, PayloadStatusBogota/ForkchoiceUpdateResponseBogota carrying inclusion_list_satisfied, Bogota aliases for the payload, body and built-payload containers, and a fork-scoped GET /inclusion-list endpoint that replaces engine_getInclusionListV1. It follows what is merged in bogota.md today; the open Bogota PRs (#864, #886, #911) don't touch the REST + SSZ files and would need matching updates here if they land.

@jihoonsong jihoonsong left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. I'd defer approving this to whoever has been following SSZ engine APIs closely so far.

Comment thread src/engine/refactor-ssz.md Resolved
Comment thread src/engine/refactor-ssz.md Resolved
Comment thread src/engine/refactor-ssz.md Resolved
Comment thread src/engine/refactor-ssz.md Resolved
Comment thread src/engine/refactor-ssz.md Resolved
nflaig added a commit to ChainSafe/lodestar that referenced this pull request Oct 9, 2026
Implements the REST engine API with SSZ encoded bodies from
[execution-apis#793](https://github.com/ethereum/execution-apis/blob/main/src/engine/refactor.md)
next to the existing JSON-RPC transport. The transport is picked per
execution client connection from `GET /engine/v1/capabilities`, so nodes
on an execution client without the REST API keep working unchanged, and
the REST API is used by default where it is advertised.

- add the engine API wire containers, composed from the consensus
payload types with `Optional[T]` encoded as `List[T, 1]`
- split `ExecutionEngineHttp` into a JSON-RPC and a REST transport
behind `IEngineTransport`, the engine keeps the request queue, engine
state, payload id cache and result handling
- probe the capabilities once per connection and again after a
disconnect. In `auto` mode an execution client without the REST API (a
4xx other than 401, 403, 408 or 429) or with a capabilities document
that cannot be parsed selects JSON-RPC until it reconnects, the latter
with a warning. Timeouts, 408, 429 and 5xx use JSON-RPC and probe again
after 12 seconds, 401 and 403 stay errors. Forks and `/blobs/vN`
revisions that are not advertised stay on JSON-RPC, and a fork rejected
with `unsupported-fork` despite being advertised falls back to JSON-RPC
until reconnect
- REST is only negotiated with a single execution URL, multiple URLs
keep JSON-RPC and its fallback across URLs. `ssz` requires a single URL
and never falls back, `json-rpc` never probes
- validate the blob versioned hashes of the payload's type-3
transactions against the beacon commitments before submitting over REST,
since the envelope has no `expected_blob_versioned_hashes` and the EL
can no longer run that check. JSON-RPC keeps delegating it to the EL
- honor the advertised request limits, oversized requests fail locally
and are not split
- add `--execution.engineApi auto|ssz|json-rpc` (default `auto`) and the
`lodestar_execution_engine_api_requests_total{transport}` counter, the
REST client reports the same per-route client metrics including the
request and response bytes from #10195. Transport selection and
fallbacks are logged at debug level
- decode `/blobs/v2` responses as views into the response body instead
of copying, the response is all-or-nothing so every byte is needed,
`/blobs/v1` keeps copies since partial responses carry zero-filled
entries
- send `X-Engine-Client-Version` as the JSON `ClientVersionV1` object
since the spec does not pin a format and that is what Nethermind parses
- malformed SSZ or JSON on a 2xx response and HTTP errors are classified
as engine errors, only transport failures mark the execution client
offline

The client speaks HTTP/1.1 only, neither reth nor Nethermind negotiates
h2c on the cleartext engine port today. Left for follow-ups: HTTP/2,
`/blobs/v3` and `/blobs/v4`, `custody_columns` on forkchoice updates,
and the `bogota` header value once
[execution-apis#920](ethereum/execution-apis#920)
lands. Heze stays on JSON-RPC in `auto` mode until then.

Verified on kurtosis devnets (minimal preset, blob spam), see the
interop reports in the comments for the per-route numbers:

- reth `v2.7.0` and `main`: everything over REST including `/blobs/v2`,
blobs resolved into data columns on a non-supernode, fulu at genesis and
an electra to fulu transition with the blob revision switching at the
fork boundary
- Nethermind `master` after
[NethermindEth/nethermind#14302](NethermindEth/nethermind#14302):
same two scenarios, everything over REST. Before the fix every
forkchoice update with payload attributes was rejected with
`unsupported-fork` on chainspec networks
([NethermindEth/nethermind#14006](NethermindEth/nethermind#14006))
and the per-fork fallback kept the node proposing over JSON-RPC
- geth and Nethermind 1.38.0: `404` on capabilities, JSON-RPC for the
whole run

Supersedes #10155.

---------

Co-authored-by: Cayman <caymannava@gmail.com>
Co-authored-by: Nazar Hussain <nazarhussain@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants