Skip to content

feat(engine): REST+SSZ engine API (execution-apis #793)#7

Open
barnabasbusa wants to merge 1 commit into
mainfrom
feat/engine-rest-ssz-793
Open

feat(engine): REST+SSZ engine API (execution-apis #793)#7
barnabasbusa wants to merge 1 commit into
mainfrom
feat/engine-rest-ssz-793

Conversation

@barnabasbusa
Copy link
Copy Markdown
Collaborator

Summary

Switches the engine API from the #764 SSZ-over-JSON-RPC transport to the #793 resource-oriented REST API: fork-scoped endpoints under /engine/v2/{fork}/... with SSZ bodies over HTTP/2 (h2c via httpx), structured JSON for capabilities/identity, RFC-7807 problem responses, and the restricted PayloadStatus enum (no INVALID_BLOCK_HASH).

Legacy JSON-RPC stays as the transition-window fallback: if the EL doesn't expose /engine/v2/... (or doesn't advertise the URL fork via GET /engine/v2/capabilities), every call falls back to JSON-RPC for the connection's lifetime.

What changed

  • engine/ssz_types.py — rewritten for #793: per-fork ExecutionPayloadEnvelope (params folded in, expectedBlobVersionedHashes removed), ForkchoiceUpdate (with Amsterdam custody_columns), BuiltPayload (new field order), blob-pool v1v4 and historical-bodies containers, plus per-fork dispatch tables. New PayloadStatus (uint8 enum, Optional[String] validation_error) — serializes to exactly the 41 bytes in the spec's worked example.
  • engine/client.pyhttpx transport (h2c prior-knowledge for v2, HTTP/1.1 for the JSON-RPC fallback). GET /engine/v2/capabilities probe, GET /engine/v2/identity + X-Engine-Client-Version header, CL→EL fork mapping (gloas→amsterdam, …). newPayload/forkchoiceUpdated/getPayload/getBlobs/bodies route via v2 when the fork is advertised, else JSON-RPC.
  • node.py — best-effort blob backfill from the EL pool (engine getBlobs) for gossiped blocks carrying commitments; reconstructs Deneb/Electra sidecars, fetches PeerDAS cell proofs (column reconstruction left to the existing data-column path). Runs in the background, never blocks import.
  • pyproject.toml — add httpx[http2]; cli.py — update --engine-force-json help.

Notes / deliberate scoping

  • target_gas_limit kept in the Amsterdam PayloadAttributes. #793's container sketch omits it, but geth's post-Amsterdam build path requires it (the sketch self-describes its types as placeholders).
  • getPayloadBodies implemented but not wired into the node — consensoor syncs state over HTTP and the EL self-syncs, so there's no consumer yet. Client methods remain available + tested.
  • Blob backfill uses a placeholder inclusion proof, matching the store's existing proposer-side blob handling (consensoor has no KZG-verify / merkle-proof machinery yet).
  • #793 is a draft and no EL ships it yet, so against current devnets the v2 probe 404s and everything falls back to JSON-RPC (the spec's intended transition behavior). The real h2c wire path is unverified against a live v2-capable EL.

Test plan

  • All #793 SSZ containers round-trip; PayloadStatus == 41-byte spec example
  • Dispatcher routing (paris/cancun/amsterdam) builds correct paths + envelopes via mocked transport
  • Capabilities probe: v2-enabled, fallback-to-JSON-RPC, --engine-force-json skip; identity v2
  • get_blobs fork→revision selection (amsterdam→v4/v3, osaka→v3, cancun→v1, none→None)
  • Node blob backfill: v1 reconstruction, partial backfill, cell-proof skip, EL-can't-serve no-op, already-have short-circuit
  • End-to-end against a live /engine/v2-capable EL (none available yet)

Replaces the #764 SSZ-over-JSON-RPC transport with the #793 resource-
oriented REST engine API: fork-scoped endpoints under /engine/v2/{fork}/...
with SSZ bodies over HTTP/2 (h2c via httpx), structured JSON for
capabilities/identity, RFC-7807 errors, and the restricted PayloadStatus
enum (no INVALID_BLOCK_HASH). Legacy JSON-RPC stays as the transition-
window fallback: if the EL doesn't expose /engine/v2 (or doesn't advertise
the URL fork), every call falls back to JSON-RPC for the connection.

- ssz_types: per-fork ExecutionPayloadEnvelope (params folded in,
  expected_blob_versioned_hashes removed), ForkchoiceUpdate (with
  Amsterdam custody_columns), BuiltPayload (new field order), blob-pool
  v1-v4 and historical-bodies containers, plus per-fork dispatch tables.
- client: httpx transport (h2c for v2, HTTP/1.1 for JSON-RPC fallback),
  GET /engine/v2/capabilities probe, GET /engine/v2/identity +
  X-Engine-Client-Version header, CL->EL fork mapping. newPayload/
  forkchoiceUpdated/getPayload/getBlobs/bodies route via v2 when the fork
  is advertised, else JSON-RPC.
- node: best-effort blob backfill from the EL pool (engine getBlobs) on
  gossiped blocks with commitments; reconstructs Deneb/Electra sidecars,
  fetches PeerDAS cell proofs (column reconstruction left to the existing
  data-column path).
- keep target_gas_limit in the Amsterdam PayloadAttributes: #793 omits it
  but geth's post-Amsterdam build path requires it.

getPayloadBodies is implemented on the client but intentionally not wired
into the node: consensoor syncs state over HTTP and the EL self-syncs, so
there is no consumer yet.
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.

1 participant