feat: builder selection, broadcast validation, stateless flow for gloas block production - #9595
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for both stateless and stateful block production flows in the post-Gloas fork, allowing validators to request full block contents (including the execution payload envelope, KZG proofs, and blobs) when self-building. It updates the produceBlockV4 and publishExecutionPayloadEnvelope endpoints, implements broadcast validation logic, and updates the CLI, types, and tests accordingly. The review feedback highlights two important improvements: validating the submitted blob and KZG proof counts against expected values in the stateless flow to prevent downstream errors, and using optional chaining when accessing blobsBundle properties to avoid potential runtime crashes during block production.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Performance Report✔️ no performance regression detected Full benchmark results
|
| if (builderBid === null && builderSelection === routes.validator.BuilderSelection.BuilderOnly) { | ||
| throw new ApiError(400, `No builder bid available for slot=${slot} with builderSelection=builderonly`); | ||
| } | ||
| const buildLocalBlock = builderSelection !== routes.validator.BuilderSelection.BuilderOnly; |
There was a problem hiding this comment.
I feel like this builderonly option shouldn't exist at all, but removing it would be a breaking change, at the same time, I don't know why anyone would use this, was added by Gajinder, if I remember correctly this was relevant for dvts at some point, but there is no known users that I am aware of now
There was a problem hiding this comment.
technically every hard fork is a breaking change. I don't think we have to support this thing forever. Happy to retire it, think about a deprecation strategy.
There was a problem hiding this comment.
technically every hard fork is a breaking change.
not really, I mean yes, users have to upgrade their node but with 0 other changes otherwise, but regarding builder settings, if we go with the proposal from terence/potuz, this needs to be reworked anyways
| * TODO GLOAS: re-evaluate cutoff timing | ||
| * TODO GLOAS: re-evaluate cutoff timing due to attestation deadline changes in gloas | ||
| */ | ||
| const BLOCK_PRODUCTION_RACE_CUTOFF_MS = 2_000; |
There was a problem hiding this comment.
this may be fine even for gloas if the deadline is at 3 seconds since we only need to publish the tiny beacon block, but if the attestation deadline is further reduced, this needs to be revisited for sure
also worth considering using a _BPS value instead of _MS to scale with slot duration
| // handle shouldOverrideBuilder separately | ||
| if (engine.status === "fulfilled" && engine.value.shouldOverrideBuilder) { | ||
| logger.info("Selected engine block: censorship suspected in builder blocks", { | ||
| logger.warn("Selected engine block: censorship suspected in builder blocks", { |
There was a problem hiding this comment.
unrelated, but I thought we always logged this as a warn so users can notice it more easily in the logs
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## unstable #9595 +/- ##
============================================
- Coverage 52.53% 52.52% -0.01%
============================================
Files 848 848
Lines 60307 60242 -65
Branches 4450 4430 -20
============================================
- Hits 31680 31642 -38
+ Misses 28566 28541 -25
+ Partials 61 59 -2 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7b04cb9e76
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Regenerating the block state is a beacon node internal failure, not a client error. Also include the slot in the message.
Also include the slot in the not-found error message.
Split the combined publish log into separate beacon block and execution payload envelope logs, use a clear stateless/stateful flow label instead of executionPayloadIncluded, add slot/blockRoot to the block publish error, and log the builder payment value for builder-bid blocks.
produceBlockV4 dropped the execution_payload_value that produceBlockV3 returned, which is a regression: multi-BN validator clients (Vero, Vouch) sum consensus + execution value to pick the best block across beacon nodes, and for self-builds the value is otherwise unavailable (the bid value is zero). Re-add it to the meta and Eth-Execution-Payload-Value header, and log it in the block proposal flow.
| /** Consensus rewards paid to the proposer for this block, in Wei */ | ||
| consensusBlockValue: ssz.UintBn64, | ||
| /** Local execution payload value when self-building, or builder bid value when committing to a bid, in Wei */ | ||
| executionPayloadValue: ssz.UintBn64, |
There was a problem hiding this comment.
not part of the current spec but we should re-add it to v4
Gloas block production (#9595) returns `BlockContents` containing the execution payload envelope for the stateless self-build flow. Heze was still mapped to `fulu.BlockContents`, which has no envelope and carries a fulu block, so produceBlockV4 would have serialized the wrong shape at the heze boundary.
…elopes (#9757) Follow-up to #9595 that implements `broadcast_validation=consensus_and_equivocation` for block and execution payload envelope publishing - track block roots per slot/proposer once their signatures have been verified through gossip or block import - reject equivocating blocks submitted through `publishBlockV2` before broadcast - reject execution payload envelopes before import or gossip, with a final check after async validation - verify and retain the first conflicting repeat proposal without allowing invalid signatures to poison the cache - run full signature verification for non-local blocks using `consensus` or `consensus_and_equivocation` validation - add focused cache, gossip validation, and api regression tests
|
🎉 This PR is included in v1.46.0 🎉 |
Follow-up to #9595 that removes Lodestar-specific selection modes from Gloas block production and uses `builder_boost_factor` as the selection input ethereum/beacon-APIs#630 will move `produceBlockV4` to a `BuilderConfig` request body and add builder-API bid routing. That wire-format change is not implemented here. This keeps `builder_boost_factor` as the global Gloas selection control so the same preference can apply to p2p and builder-API bids once that flow is implemented. - remove the non-standard `builder_selection` parameter from `produceBlockV4` - keep `--builder.selection` as validator client aliases for `builder_boost_factor` - treat the legacy `executiononly` option as `executionalways` post-Gloas so a viable builder bid can prevent a missed proposal - keep builder bids available as fallback unless the circuit breaker is active - keep strict fee recipient checks for local payloads while relying on proposer-preferences validation for external bids - persist produced Gloas blocks with the selected engine or builder source - update the operator docs and focused block production tests > This PR was written primarily by Codex. --------- Co-authored-by: Matthew Keil <github@mail.matthewkeil.com>
--payloadLocalflag to configure behavior stateless vs. statefulproduceBlockV4now respectsbuilder_selectionandbuilder_boost_factordefaultbuilder selection strategy (uses in-protocol p2p bids and local block, selecting by value), explicit--builder.selectionconfig is still honoredbroadcast_validationfor publishing execution payload envelopes (exceptequivocationchecks){schema: type: boolean}in query params and request headersbuilderonlybuilder selection option, it's a safety concern and adds unnecessary complexity