feat: proxy REST+SSZ Engine API over h2c (execution-apis #793)#48
Open
barnabasbusa wants to merge 3 commits into
Open
feat: proxy REST+SSZ Engine API over h2c (execution-apis #793)#48barnabasbusa wants to merge 3 commits into
barnabasbusa wants to merge 3 commits into
Conversation
Maps Engine API REST URL paths to method names (e.g. /engine/v3/payloads → engine_newPayloadV3) for improved log readability when proxying SSZ-encoded traffic. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The HTTP/1.1-only server dropped consensus clients that speak the
REST+SSZ Engine API (execution-apis #793), which uses HTTP/2 cleartext
prior-knowledge — the connection was reset and clients fell back to
JSON-RPC, so #793 traffic was never observable through the snooper.
- Wrap the downstream server in h2c so it accepts both HTTP/1.1
(JSON-RPC) and HTTP/2 cleartext (REST+SSZ) on the same port.
- Forward each call to the EL using the same HTTP version it arrived
on: HTTP/2 for REST+SSZ, HTTP/1.1 for JSON-RPC.
- Extend SSZ route matching to the #793 fork-scoped endpoints
(/engine/v2/{fork}/payloads|forkchoice|bodies), independently
versioned blobs (/blobs/vN), and the unscoped identity endpoint.
- Show the resolved Engine API method inline on REQUEST/RESPONSE lines
(' -> engine_forkchoiceUpdatedV3') instead of a trailing field, and
echo it on responses so request/response pairs are easy to read.
SSZ bodies were logged as an opaque '<N bytes>' placeholder. SSZ isn't self-describing so we can't pretty-print it like JSON, but emitting the raw body as hex (honouring truncation) keeps the on-wire content visible and decodable offline. The byte count remains on the line via 'length'.
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.
Summary
Makes the snooper proxy the REST+SSZ Engine API (execution-apis #793) instead of dropping it.
That transport uses HTTP/2 cleartext (h2c) prior-knowledge. The snooper's server was HTTP/1.1-only, so when a consensus client opened an h2c connection (e.g.
GET /engine/v2/capabilities) the connection was reset — the client then silently fell back to JSON-RPC, and none of the #793 traffic was ever observable through the snooper.Changes
h2c downstream server — wrap the handler in
h2c.NewHandlerso the proxy accepts both HTTP/1.1 (JSON-RPC) and HTTP/2 cleartext (REST+SSZ) on the same port.Protocol-matched upstream — forward each call to the EL using the same HTTP version it arrived on (autodetected per request from the inbound connection): HTTP/2 for REST+SSZ, HTTP/1.1 for JSON-RPC. No client is forced onto a transport it didn't choose.
#793 route matching — extend
ssz/route.goto the fork-scoped endpoints (/engine/v2/{fork}/payloads|forkchoice|bodies), independently-versioned blobs (/engine/v2/blobs/vN), and the unscopedidentityendpoint, with tests.Readable logs — show the autodetected protocol and resolved Engine API method inline on REQUEST/RESPONSE lines, e.g.
Supersedes
Includes and replaces the closed #36 (which only added method-name detection for log readability); this PR adds the actual h2c proxying needed to carry the traffic.
Testing
Verified live in a Kurtosis devnet (geth
ssz-engine-apibranch + consensoor):GET /engine/v2/capabilities,/engine/v2/identity, and the fork-scopedPOST /engine/v2/amsterdam/{forkchoice,payloads}/GET .../payloads/{id}SSZ calls all proxy with200and are logged with the correct method. JSON-RPC clients (lighthouse, teku) are unaffected and continue over HTTP/1.1.go test ./...passes.🤖 Generated with Claude Code