Skip to content

feat: use BuilderConfig POST for Gloas block production - #323

Draft
AntiD2ta wants to merge 3 commits into
feat/gloas-submit-proposer-preferencesfrom
produce-block-v4-builder-config
Draft

feat: use BuilderConfig POST for Gloas block production#323
AntiD2ta wants to merge 3 commits into
feat/gloas-submit-proposer-preferencesfrom
produce-block-v4-builder-config

Conversation

@AntiD2ta

@AntiD2ta AntiD2ta commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Switch Gloas produceBlockV4 to the POST contract. Requests carry a required BuilderConfig and negotiate JSON or SSZ. Responses retain builder routing metadata and reject inconsistent payload contents.

Review guide

Start with http/epbsproposal.go. It builds the POST request, selects the response codec, and checks the block, envelope, builder index, and execution-request commitments.

spec/gloas/builderconfig.go and its generated SSZ files define the request types. builderconfig_json.go handles JSON encoding and bounds checks.

api/epbsproposalopts.go, api/versionedepbsproposal.go, and api/submitproposalopts.go show the public changes.

Behaviour

  • The client sends POST only. It does not retry the former GET route.
  • A builder-backed response may contain a bare block when include_payload=true.
  • Missing execution value remains unknown.
  • Eth-Builder-Url is retained in response metadata and may be sent when publishing the signed block.

Validation

  • Node-free JSON and SSZ request and response tests cover headers, bodies, metadata, bounds, and custom presets.
  • go generate ./spec/gloas
  • gosilent test ./api ./spec/gloas
  • Focused HTTP protocol tests
  • go build ./...
  • Live JSON and SSZ requests against Prysm commit 393e9b3c8c7b58bee90da9ae03d0f89988427afb

Use the pinned Gloas POST request contract with generated BuilderConfig codecs, negotiated JSON or SSZ transport, and validated response commitments.

Files: API proposal and publication options; Gloas BuilderConfig types/codegen; HTTP production, integrity, and transport tests.

Validation: focused protocol tests, API/spec/mock/multi/root tests, build, code generation stability, and live Prysm JSON/SSZ decoding passed. Full suite has unrelated legacy JSON error-string failures; golangci-lint lacks its configured attgo plugin.
@AntiD2ta AntiD2ta changed the title produce block v4 builder config feat: use BuilderConfig POST for Gloas block production Sep 2, 2026
Restore the POST response-body bound. post() was changed to pass a zero
limit, which readResponseBody treats as "unbounded", so every POST
endpoint but block production went back to an unbounded io.ReadAll --
undoing 90e1f9e. maxEPBSResponseSize keeps its 64MiB value for those and
for the four ePBS fetch endpoints that share it; block production passes
its own, much larger, limits under their own names.

Accept an empty builders list. The pinned contract documents an empty
list as a valid request ("Empty means request none, so only p2p bids are
considered", and a local-preferred build is requested with an empty list
and builder_boost_factor 0), with maxItems 64 and no minimum. A nil
slice said the same thing but was refused, while an empty non-nil slice
was accepted; the underlying defect was MarshalJSON emitting
"builders":null for a nil slice, which the required array -- and this
package's own decoder -- reject.

Complete BuilderConfig YAML support. BuilderEntry,
SignedBuilderRequestAuth and BuilderRequestAuth had no MarshalYAML, so a
config with any builder in it serialised reflection-derived keys and raw
byte arrays; BuilderConfig had no UnmarshalYAML, so a round trip
silently dropped min_bid and builder_boost_factor. The URL needs an
explicitly quoted scalar: goccy emits "https://..." plain, and the
embedded colon makes the enclosing flow document re-parse it as a nested
mapping. The existing test only marshalled an empty builders list, so it
saw none of this.

Restore TestVersionedEPBSProposalProposerIndex,
TestVersionedEPBSProposalRoot and the BodyRoot BeaconBlockBodyRootUnset
subtest, which were deleted, leaving ProposerIndex() and Root()
untested. Root() is what the envelope-matches-block guard and a
proposer's signature both rest on.

Also: drop the redundant Value test that duplicated a table case and
reattach the doc comment it had orphaned, use errors.New for the
constant-string fmt.Errorf calls, and collapse the single-case
table-driven tests to direct assertions.
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