Skip to content

Gloas (ePBS) builder-API support #489

Description

@0w3n-d

Status

Helix currently implements the Bellatrix→Fulu builder-API shape: getHeader, registerValidator, getPayload. Gloas (ePBS) replaces these with getExecutionPayloadBid, submitBuilderPreferences, and submitSignedBeaconBlock respectively — a different flow, not a version bump of the same one. This issue scopes what's needed for helix to support it.

Why

Gloas (EIP-7732) removes the execution payload from the beacon block body entirely. The block carries a SignedExecutionPayloadBid directly, and the full payload is revealed after the block is proposed via a SignedExecutionPayloadEnvelope broadcast to the PTC — not returned synchronously to the proposer. There's no more "blinded block" concept. Based on the Gloas builder-API spec: builder.md, validator.md, merged via ethereum/builder-specs#165.

Resolved design question: does helix need a gossip/libp2p stack for envelope publishing? No — a connected beacon node's own HTTP API bridges HTTP↔gossip for every Gloas primitive (POST /eth/v1/beacon/execution_payload_envelopes publishes to gossip on helix's behalf; /eth/v1/events?topics=... streams gossip observations back). helix stays HTTP-only.

Resolved design question: who holds the on-chain builder identity (deposit, builder_index, signing key) that signs SignedExecutionPayloadBid/SignedExecutionPayloadEnvelope? For now, helix signs under its own configured identity (reusing the relay's existing signing key; builder_index is a placeholder RelayConfig field until a real on-chain registration exists), the same centralizing-trust model it already uses for SignedBuilderBid. Supporting external builders submitting their own signed bids/envelopes is deferred (tracked separately, not yet a step).

Resolved design question: does helix's builder→relay submit_block wire shape need to become progressive-list-aware to carry Gloas payloads? No. crates/types/src/bid_submission.rs's ExecutionPayload/SignedBidSubmission is helix's own bounded-list builder↔relay representation, shared unchanged across Bellatrix–Fulu — it is not a mirror of the real per-fork consensus SSZ types. External builders keep submitting via the same bounded-list shape for Gloas; helix converts to the real, progressive-list consensus types (ExecutionPayloadGloas/ExecutionRequestsGloas) only at the outbound bid/envelope boundary (step 5).

Resolved design question: ExecutionPayloadBid splits value/execution_payment into two separate fields. Since submitBuilderPreferences's max_execution_payment is a proposer-side cap rather than something a builder declares, and helix's existing submission only carries one value, execution_payment is set equal to value for now. Revisit if/when payment splitting becomes a real product need.

Affected surface

File Role today Gloas impact
crates/relay/src/api/proposer/get_header.rs serves SignedBuilderBid Parallel Gloas path serving SignedExecutionPayloadBid; different auth model (SignedBuilderRequestAuth), new parent_root param
crates/relay/src/api/proposer/header_stream.rs SSE stream of SignedBuilderBid frames Needs a Gloas frame type
crates/relay/src/api/proposer/register.rs validator registration submitBuilderPreferences stores max_execution_payment per-slot per-proposer instead of a long-lived registration
crates/relay/src/api/proposer/get_payload.rs diffs blinded block header vs. held payload No blinded-block concept in Gloas; replaced by accept-full-block + trigger envelope construction
crates/relay/src/auctioneer/get_payload.rs::unblind() reconstructs full block from blinded + held payload No unblinding step for Gloas; new, differently-shaped path
crates/relay/src/api/builder/submit_block.rs builder→relay bid submission Unchanged wire shape; Gloas fork now decodes via the same bounded-list path as Fulu (step 5)
crates/types/src/builder_bid.rs flat BuilderBid, no per-fork enum New standalone ExecutionPayloadBid/SignedExecutionPayloadBid type, not an extension
crates/types/src/hydration.rs dehydrate/rehydrate per fork Gloas now decodes via the same shape as Fulu; real progressive-list conversion lives in execution_payload.rs/fields.rs (step 5)

Steps (each becomes one PR)

(Reordered from the original numbering: this step used to be "step 6, backfill hydration.rs/execution_payload.rs" and the old step 5 — updating submit_block's wire shape — turned out to be blocked on it, since helix's ExecutionPayload had no Gloas representation at all. The old step 5's actual remaining work (reading real submissions and serving a real signed bid/envelope) is folded into the new step 6 above.)

Open questions

  • Re-verify endpoint names/shapes against whatever CL version is actually targeted once Gloas nears a release tag rather than a devnet branch.

Activity

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions