engineapi: switch Engine API SSZ to execution-apis#793#21729
Draft
yperbasis wants to merge 1 commit into
Draft
Conversation
Replace the execution-apis#764 surface (version-scoped /engine/vN/...
endpoints) with the fork-scoped REST surface of execution-apis#793:
POST/GET /engine/v2/{fork}/payloads, POST /engine/v2/{fork}/forkchoice,
fork-era-scoped bodies endpoints, POST /engine/v2/blobs/v{1..3}, JSON
GET /engine/v2/capabilities + /engine/v2/identity, and RFC 7807
problem+json errors. PayloadStatus.validation_error becomes
Optional[String]; expectedBlobVersionedHashes is recomputed from the
payload transactions; PayloadAttributes SSZ for Electra/Fulu now uses
the Cancun shape instead of falling into the Gloas branch.
Closes #21600
Contributor
There was a problem hiding this comment.
Pull request overview
Updates Erigon’s authenticated SSZ-REST Engine API transport to match the newer draft surface from execution-apis#793, replacing the previously implemented #764-based endpoints. This affects both HTTP routing (/engine/v2/…) and several SSZ wire types/codecs used by newPayload/getPayload/forkchoice/blobs/bodies.
Changes:
- Replaces legacy
/engine/v{N}/…SSZ-REST endpoints with fork-scoped/engine/v2/{fork}/…endpoints plus JSON discovery endpoints (GET /engine/v2/capabilities,GET /engine/v2/identity) and RFC7807application/problem+jsonerror responses. - Updates SSZ codecs for the new envelopes/responses (newPayload envelope, BuiltPayload field order, forkchoice update + optional custody columns, blob/body entry wrappers).
- Rewrites SSZ-REST tests to target the new surface, error mapping, and wire-format details (including the PayloadStatus spec example).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| execution/engineapi/sszrest_wire.go | Implements new fork-scoped SSZ schemas/codecs for payload envelopes, forkchoice update, BuiltPayload, bodies, and blobs responses. |
| execution/engineapi/sszrest_handler.go | Replaces routing with /engine/v2/... fork-scoped handlers, adds JSON discovery endpoints, and standardizes errors to RFC7807 problem+json. |
| execution/engineapi/engine_types/ssz.go | Updates SSZ encoding/decoding for PayloadStatus.validation_error optionality and fixes fork-branching for PayloadAttributes encoding. |
| execution/engineapi/sszrest_test.go | Rewrites tests to validate new endpoints, routing/error behavior, and updated SSZ wire formats. |
| execution/engineapi/engine_api_methods.go | Removes legacy SSZ-REST endpoint strings from engine_exchangeCapabilities advertised capabilities. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+307
to
311
| switch { | ||
| case version < clparams.DenebVersion: | ||
| return ssz2.MarshalSSZ(nil, payload, blockValue[:]) | ||
| case clparams.DenebVersion: | ||
| case version < clparams.ElectraVersion: | ||
| return ssz2.MarshalSSZ(nil, payload, blockValue[:], blobsBundle, resp.ShouldOverrideBuilder) |
Comment on lines
+324
to
+328
| switch { | ||
| case version < clparams.DenebVersion: | ||
| err = ssz2.UnmarshalSSZ(buf, int(version), payload, blockValue[:]) | ||
| case version < clparams.ElectraVersion: | ||
| err = ssz2.UnmarshalSSZ(buf, int(version), payload, blockValue[:], blobsBundle, &shouldOverride) |
This was referenced Jun 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #21600.
PR #21203 implemented the Engine API SSZ transport per execution-apis#764, which has since been closed in favour of execution-apis#793. This PR replaces the execution-apis#764 surface with the execution-apis#793 one.
New surface
POST /engine/v2/{fork}/payloadsengine_newPayloadV{1..5}— SSZExecutionPayloadEnvelope;expectedBlobVersionedHashesremoved, recomputed frompayload.transactionsGET /engine/v2/{fork}/payloads/{id}engine_getPayloadV{1..6}— SSZBuiltPayload(new field order),Cache-Control: no-storePOST /engine/v2/{fork}/forkchoiceengine_forkchoiceUpdatedV{1..4}— optionalpayload_attributes; optionalcustody_columns(Amsterdam) decoded but ignored for nowPOST /engine/v2/{fork}/bodies/hash,GET /engine/v2/{fork}/bodies?from=N&count=Mengine_getPayloadBodiesBy*— new in the SSZ transport; fork-era-scoped, out-of-era/missing blocks come backavailable=falsePOST /engine/v2/blobs/v{1..3}engine_getBlobsV{1..3}—BlobEntry{available, contents}lists,204 No Contentfor can't-serve / v2 all-or-nothing missGET /engine/v2/capabilities,GET /engine/v2/identityThe fork segment maps
paris…amsterdam→Bellatrix…Gloas; unscheduled forks return400 unsupported-fork. Errors are RFC 7807application/problem+jsonwith the spec's type URIs; wrongContent-Type→ 415; trailing slashes → 404. The old/engine/v{N}/...endpoints are gone (404), and their strings are removed fromengine_exchangeCapabilities(discovery now happens viaGET /engine/v2/capabilities). HTTP/2 cleartext required no transport work:node.StartHTTPEndpointalready wraps handlers in h2c.Wire-format changes
PayloadStatus.validation_erroris nowOptional[String](List[List[byte, 1024], 1]), so absence is distinguishable from an empty message. A test pins the spec's 41-byteVALIDexample byte-for-byte.BuiltPayloaduses the spec's field order (execution_requestsbeforeshould_override_builder) and carries requests as opaqueList[ByteList].PayloadAttributesSSZ for Electra/Fulu fell into the Gloas branch; Prague/Osaka now correctly use the Cancun shape.Caveat:
engine_getBlobsV4/POST /blobs/v4The spec says ELs MUST serve at least the blobs revision matching their current fork —
/blobs/v4(Amsterdam cell-range selection) once Amsterdam is live. This PR does not implement/blobs/v4because Erigon has noengine_getBlobsV4implementation anywhere yet (the JSON-RPC API also stops at V3).GET /capabilitieshonestly advertises{"blobs": ["v1", "v2", "v3"]}./blobs/v4should be added in a follow-up together withengine_getBlobsV4itself.Interpretation notes
execution-apis#793 is still a draft and only pins the Amsterdam container shapes. Where the spec is not explicit:
BuiltPayloadvariants drop the fields their fork didn't have, mirroring the JSON-RPC method progression (e.g. the Paris envelope is just{payload}, the Cancun one addsparent_beacon_block_root).Verification
sszrest_test.gowas rewritten against the new spec first (red), then the implementation brought it to green;go test ./execution/engineapi/...passes.make erigon integrationbuilds; scopedgolangci-linton the changed packages reports 0 issues.curl --http2-prior-knowledge(JWT-authenticated): capabilities/identity JSON, all problem+json error paths, fork-scoped routing, legacy endpoints 404, and a bodies-by-range SSZ response verified byte-by-byte.