Skip to content

feat: builder selection, broadcast validation, stateless flow for gloas block production - #9595

Merged
twoeths merged 55 commits into
unstablefrom
nflaig/stateless-flow
Jul 27, 2026
Merged

feat: builder selection, broadcast validation, stateless flow for gloas block production#9595
twoeths merged 55 commits into
unstablefrom
nflaig/stateless-flow

Conversation

@nflaig

@nflaig nflaig commented Jul 5, 2026

Copy link
Copy Markdown
Member
  • per remove BlindedExecutionPayloadEnvelope ethereum/beacon-APIs#624
  • validator client defaults to the stateless flow if multiple beacon nodes are configured
  • add --payloadLocal flag to configure behavior stateless vs. stateful
  • produceBlockV4 now respects builder_selection and builder_boost_factor
  • post-gloas the validator client defaults to the default builder selection strategy (uses in-protocol p2p bids and local block, selecting by value), explicit --builder.selection config is still honored
  • implement broadcast_validation for publishing execution payload envelopes (except equivocation checks)
  • extend oapi spec test framework to support {schema: type: boolean} in query params and request headers
  • remove builderonly builder selection option, it's a safety concern and adds unnecessary complexity

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread packages/beacon-node/src/api/impl/beacon/blocks/index.ts
Comment thread packages/beacon-node/src/api/impl/validator/index.ts
Comment thread packages/api/src/beacon/routes/beacon/block.ts Outdated
Comment thread packages/cli/src/cmds/validator/options.ts Outdated
Comment thread packages/validator/src/services/validatorStore.ts Outdated
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: 2ffe458 Previous: 4001398 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 848.67 us/op 892.51 us/op 0.95
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 38.792 us/op 39.707 us/op 0.98
BLS verify - blst 656.07 us/op 712.85 us/op 0.92
BLS verifyMultipleSignatures 3 - blst 1.3582 ms/op 1.3668 ms/op 0.99
BLS verifyMultipleSignatures 8 - blst 2.1556 ms/op 2.1764 ms/op 0.99
BLS verifyMultipleSignatures 32 - blst 7.1090 ms/op 6.8732 ms/op 1.03
BLS verifyMultipleSignatures 64 - blst 13.699 ms/op 13.605 ms/op 1.01
BLS verifyMultipleSignatures 128 - blst 25.772 ms/op 25.973 ms/op 0.99
BLS deserializing 10000 signatures 637.16 ms/op 645.65 ms/op 0.99
BLS deserializing 100000 signatures 6.4478 s/op 6.6012 s/op 0.98
BLS verifyMultipleSignatures - same message - 3 - blst 791.10 us/op 789.92 us/op 1.00
BLS verifyMultipleSignatures - same message - 8 - blst 944.89 us/op 948.19 us/op 1.00
BLS verifyMultipleSignatures - same message - 32 - blst 1.4804 ms/op 1.5389 ms/op 0.96
BLS verifyMultipleSignatures - same message - 64 - blst 2.4780 ms/op 2.4690 ms/op 1.00
BLS verifyMultipleSignatures - same message - 128 - blst 4.1297 ms/op 4.1134 ms/op 1.00
BLS aggregatePubkeys 32 - blst 17.821 us/op 17.859 us/op 1.00
BLS aggregatePubkeys 128 - blst 63.779 us/op 63.461 us/op 1.01
getSlashingsAndExits - default max 49.593 us/op 46.159 us/op 1.07
getSlashingsAndExits - 2k 328.25 us/op 330.92 us/op 0.99
proposeBlockBody type=full, size=empty 642.43 us/op 659.29 us/op 0.97
isKnown best case - 1 super set check 178.00 ns/op 182.00 ns/op 0.98
isKnown normal case - 2 super set checks 172.00 ns/op 166.00 ns/op 1.04
isKnown worse case - 16 super set checks 168.00 ns/op 184.00 ns/op 0.91
validate api signedAggregateAndProof - struct 1.5250 ms/op 1.5395 ms/op 0.99
validate gossip signedAggregateAndProof - struct 1.5340 ms/op 1.5358 ms/op 1.00
batch validate gossip attestation - vc 640000 - chunk 32 110.10 us/op 111.93 us/op 0.98
batch validate gossip attestation - vc 640000 - chunk 64 96.326 us/op 97.778 us/op 0.99
batch validate gossip attestation - vc 640000 - chunk 128 89.471 us/op 91.163 us/op 0.98
batch validate gossip attestation - vc 640000 - chunk 256 87.955 us/op 87.106 us/op 1.01
bytes32 toHexString 293.00 ns/op 294.00 ns/op 1.00
bytes32 Buffer.toString(hex) 180.00 ns/op 179.00 ns/op 1.01
bytes32 Buffer.toString(hex) from Uint8Array 253.00 ns/op 246.00 ns/op 1.03
bytes32 Buffer.toString(hex) + 0x 178.00 ns/op 181.00 ns/op 0.98
Return object 10000 times 0.21890 ns/op 0.21660 ns/op 1.01
Throw Error 10000 times 3.4576 us/op 3.4863 us/op 0.99
toHex 99.739 ns/op 101.27 ns/op 0.98
Buffer.from 89.795 ns/op 95.288 ns/op 0.94
shared Buffer 61.345 ns/op 60.527 ns/op 1.01
fastMsgIdFn sha256 / 200 bytes 1.5460 us/op 1.5070 us/op 1.03
fastMsgIdFn h32 xxhash / 200 bytes 159.00 ns/op 162.00 ns/op 0.98
fastMsgIdFn h64 xxhash / 200 bytes 223.00 ns/op 218.00 ns/op 1.02
fastMsgIdFn sha256 / 1000 bytes 4.8650 us/op 4.8890 us/op 1.00
fastMsgIdFn h32 xxhash / 1000 bytes 254.00 ns/op 244.00 ns/op 1.04
fastMsgIdFn h64 xxhash / 1000 bytes 261.00 ns/op 265.00 ns/op 0.98
fastMsgIdFn sha256 / 10000 bytes 43.097 us/op 43.176 us/op 1.00
fastMsgIdFn h32 xxhash / 10000 bytes 1.2990 us/op 1.2870 us/op 1.01
fastMsgIdFn h64 xxhash / 10000 bytes 839.00 ns/op 834.00 ns/op 1.01
send data - 1000 256B messages 4.2785 ms/op 5.1457 ms/op 0.83
send data - 1000 512B messages 5.1588 ms/op 5.9728 ms/op 0.86
send data - 1000 1024B messages 5.6966 ms/op 6.2512 ms/op 0.91
send data - 1000 1200B messages 6.5480 ms/op 8.5089 ms/op 0.77
send data - 1000 2048B messages 10.079 ms/op 17.122 ms/op 0.59
send data - 1000 4096B messages 56.846 ms/op 112.62 ms/op 0.50
send data - 1000 16384B messages 362.54 ms/op 375.64 ms/op 0.97
send data - 1000 65536B messages 965.42 ms/op 1.7644 s/op 0.55
enrSubnets - fastDeserialize 64 bits 755.00 ns/op 786.00 ns/op 0.96
enrSubnets - ssz BitVector 64 bits 273.00 ns/op 272.00 ns/op 1.00
enrSubnets - fastDeserialize 4 bits 102.00 ns/op 105.00 ns/op 0.97
enrSubnets - ssz BitVector 4 bits 277.00 ns/op 274.00 ns/op 1.01
prioritizePeers score -10:0 att 32-0.1 sync 2-0 204.39 us/op 213.18 us/op 0.96
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 228.69 us/op 241.41 us/op 0.95
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 333.34 us/op 355.15 us/op 0.94
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 593.66 us/op 638.56 us/op 0.93
prioritizePeers score 0:0 att 64-1 sync 4-1 703.44 us/op 721.89 us/op 0.97
array of 16000 items push then shift 1.3143 us/op 1.3181 us/op 1.00
LinkedList of 16000 items push then shift 7.4950 ns/op 7.6070 ns/op 0.99
array of 16000 items push then pop 65.943 ns/op 76.460 ns/op 0.86
LinkedList of 16000 items push then pop 6.0950 ns/op 6.2120 ns/op 0.98
array of 24000 items push then shift 1.9510 us/op 1.9740 us/op 0.99
LinkedList of 24000 items push then shift 6.8820 ns/op 7.2490 ns/op 0.95
array of 24000 items push then pop 92.085 ns/op 111.78 ns/op 0.82
LinkedList of 24000 items push then pop 6.0580 ns/op 6.2740 ns/op 0.97
intersect bitArray bitLen 8 3.9160 ns/op 4.0250 ns/op 0.97
intersect array and set length 8 29.586 ns/op 30.477 ns/op 0.97
intersect bitArray bitLen 128 23.558 ns/op 24.098 ns/op 0.98
intersect array and set length 128 500.82 ns/op 513.07 ns/op 0.98
bitArray.getTrueBitIndexes() bitLen 128 916.00 ns/op 967.00 ns/op 0.95
bitArray.getTrueBitIndexes() bitLen 248 1.6560 us/op 1.7410 us/op 0.95
bitArray.getTrueBitIndexes() bitLen 512 3.4710 us/op 3.6740 us/op 0.94
Full columns - reconstruct all 6 blobs 182.42 us/op 156.33 us/op 1.17
Full columns - reconstruct half of the blobs out of 6 90.662 us/op 85.463 us/op 1.06
Full columns - reconstruct single blob out of 6 30.816 us/op 35.587 us/op 0.87
Half columns - reconstruct all 6 blobs 396.27 ms/op 408.72 ms/op 0.97
Half columns - reconstruct half of the blobs out of 6 200.34 ms/op 203.88 ms/op 0.98
Half columns - reconstruct single blob out of 6 71.602 ms/op 71.196 ms/op 1.01
Set add up to 64 items then delete first 1.6724 us/op 1.7187 us/op 0.97
OrderedSet add up to 64 items then delete first 2.5693 us/op 2.6213 us/op 0.98
Set add up to 64 items then delete last 1.8781 us/op 1.9439 us/op 0.97
OrderedSet add up to 64 items then delete last 2.9421 us/op 2.8931 us/op 1.02
Set add up to 64 items then delete middle 1.9193 us/op 1.9262 us/op 1.00
OrderedSet add up to 64 items then delete middle 4.4879 us/op 4.3902 us/op 1.02
Set add up to 128 items then delete first 3.6725 us/op 3.8600 us/op 0.95
OrderedSet add up to 128 items then delete first 5.5099 us/op 5.9104 us/op 0.93
Set add up to 128 items then delete last 3.6469 us/op 3.7490 us/op 0.97
OrderedSet add up to 128 items then delete last 5.6973 us/op 5.6032 us/op 1.02
Set add up to 128 items then delete middle 3.6326 us/op 3.7668 us/op 0.96
OrderedSet add up to 128 items then delete middle 11.724 us/op 11.597 us/op 1.01
Set add up to 256 items then delete first 7.5119 us/op 7.6673 us/op 0.98
OrderedSet add up to 256 items then delete first 11.178 us/op 12.095 us/op 0.92
Set add up to 256 items then delete last 7.4410 us/op 7.2314 us/op 1.03
OrderedSet add up to 256 items then delete last 11.908 us/op 11.588 us/op 1.03
Set add up to 256 items then delete middle 7.5281 us/op 7.2067 us/op 1.04
OrderedSet add up to 256 items then delete middle 36.519 us/op 35.470 us/op 1.03
runFastConfirmationRules vc:100000 bc:96 eq:0 4.6582 ms/op 4.5352 ms/op 1.03
runFastConfirmationRules vc:600000 bc:96 eq:0 37.256 ms/op 34.787 ms/op 1.07
runFastConfirmationRules vc:1000000 bc:96 eq:0 62.112 ms/op 57.986 ms/op 1.07
runFastConfirmationRules vc:600000 bc:320 eq:0 37.646 ms/op 35.322 ms/op 1.07
runFastConfirmationRules vc:100000 bc:96 eq:1000 1.1159 s/op 1.1136 s/op 1.00
pass gossip attestations to forkchoice per slot 2.6589 ms/op 2.6281 ms/op 1.01
forkChoice updateHead vc 100000 bc 64 eq 0 423.82 us/op 412.66 us/op 1.03
forkChoice updateHead vc 600000 bc 64 eq 0 2.5178 ms/op 2.4515 ms/op 1.03
forkChoice updateHead vc 1000000 bc 64 eq 0 4.1922 ms/op 4.0830 ms/op 1.03
forkChoice updateHead vc 600000 bc 320 eq 0 2.5160 ms/op 2.4786 ms/op 1.02
forkChoice updateHead vc 600000 bc 1200 eq 0 2.5572 ms/op 2.6070 ms/op 0.98
forkChoice updateHead vc 600000 bc 7200 eq 0 2.9284 ms/op 2.8684 ms/op 1.02
forkChoice updateHead vc 600000 bc 64 eq 1000 2.5336 ms/op 2.4628 ms/op 1.03
forkChoice updateHead vc 600000 bc 64 eq 10000 2.6224 ms/op 2.5672 ms/op 1.02
forkChoice updateHead vc 600000 bc 64 eq 300000 6.5391 ms/op 6.5621 ms/op 1.00
computeDeltas 1400000 validators 0% inactive 12.455 ms/op 12.303 ms/op 1.01
computeDeltas 1400000 validators 10% inactive 11.746 ms/op 11.626 ms/op 1.01
computeDeltas 1400000 validators 20% inactive 11.010 ms/op 10.963 ms/op 1.00
computeDeltas 1400000 validators 50% inactive 9.0276 ms/op 8.9129 ms/op 1.01
computeDeltas 2100000 validators 0% inactive 18.689 ms/op 18.412 ms/op 1.02
computeDeltas 2100000 validators 10% inactive 17.592 ms/op 17.531 ms/op 1.00
computeDeltas 2100000 validators 20% inactive 16.524 ms/op 16.351 ms/op 1.01
computeDeltas 2100000 validators 50% inactive 11.115 ms/op 10.910 ms/op 1.02
altair processAttestation - 250000 vs - 7PWei normalcase 1.6891 ms/op 1.8797 ms/op 0.90
altair processAttestation - 250000 vs - 7PWei worstcase 2.4435 ms/op 2.4435 ms/op 1.00
altair processAttestation - setStatus - 1/6 committees join 98.606 us/op 102.05 us/op 0.97
altair processAttestation - setStatus - 1/3 committees join 194.18 us/op 209.59 us/op 0.93
altair processAttestation - setStatus - 1/2 committees join 287.34 us/op 291.33 us/op 0.99
altair processAttestation - setStatus - 2/3 committees join 369.99 us/op 380.88 us/op 0.97
altair processAttestation - setStatus - 4/5 committees join 515.46 us/op 536.85 us/op 0.96
altair processAttestation - setStatus - 100% committees join 588.83 us/op 625.88 us/op 0.94
altair processBlock - 250000 vs - 7PWei normalcase 2.8647 ms/op 3.5830 ms/op 0.80
altair processBlock - 250000 vs - 7PWei normalcase hashState 14.086 ms/op 15.421 ms/op 0.91
altair processBlock - 250000 vs - 7PWei worstcase 19.580 ms/op 20.872 ms/op 0.94
altair processBlock - 250000 vs - 7PWei worstcase hashState 38.303 ms/op 41.282 ms/op 0.93
phase0 processBlock - 250000 vs - 7PWei normalcase 1.2956 ms/op 1.3561 ms/op 0.96
phase0 processBlock - 250000 vs - 7PWei worstcase 17.038 ms/op 16.414 ms/op 1.04
altair processEth1Data - 250000 vs - 7PWei normalcase 300.65 us/op 316.43 us/op 0.95
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:16 3.2100 us/op 3.4460 us/op 0.93
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:220 21.957 us/op 21.942 us/op 1.00
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:43 6.0050 us/op 5.9890 us/op 1.00
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:19 3.6370 us/op 4.8150 us/op 0.76
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1021 97.511 us/op 90.481 us/op 1.08
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11778 1.4133 ms/op 1.4215 ms/op 0.99
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.8228 ms/op 1.8590 ms/op 0.98
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.8448 ms/op 1.8706 ms/op 0.99
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 3.9325 ms/op 3.7336 ms/op 1.05
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.1986 ms/op 2.1087 ms/op 1.04
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.3028 ms/op 4.2521 ms/op 1.01
Tree 40 250000 create 342.65 ms/op 312.19 ms/op 1.10
Tree 40 250000 get(125000) 114.63 ns/op 95.075 ns/op 1.21
Tree 40 250000 set(125000) 1.0474 us/op 1.0274 us/op 1.02
Tree 40 250000 toArray() 22.064 ms/op 10.225 ms/op 2.16
Tree 40 250000 iterate all - toArray() + loop 16.925 ms/op 10.086 ms/op 1.68
Tree 40 250000 iterate all - get(i) 40.166 ms/op 39.272 ms/op 1.02
Array 250000 create 2.1638 ms/op 2.4119 ms/op 0.90
Array 250000 clone - spread 661.00 us/op 760.03 us/op 0.87
Array 250000 get(125000) 0.30200 ns/op 0.29700 ns/op 1.02
Array 250000 set(125000) 0.30400 ns/op 0.30200 ns/op 1.01
Array 250000 iterate all - loop 58.473 us/op 58.595 us/op 1.00
phase0 afterProcessEpoch - 250000 vs - 7PWei 38.880 ms/op 62.389 ms/op 0.62
Array.fill - length 1000000 1.9977 ms/op 2.2139 ms/op 0.90
Array push - length 1000000 7.2741 ms/op 8.4684 ms/op 0.86
Array.get 0.20614 ns/op 0.20966 ns/op 0.98
Uint8Array.get 0.24003 ns/op 0.24103 ns/op 1.00
phase0 beforeProcessEpoch - 250000 vs - 7PWei 12.158 ms/op 13.246 ms/op 0.92
altair processEpoch - mainnet_e81889 230.45 ms/op 268.93 ms/op 0.86
mainnet_e81889 - altair beforeProcessEpoch 14.280 ms/op 37.041 ms/op 0.39
mainnet_e81889 - altair processJustificationAndFinalization 5.4630 us/op 5.3900 us/op 1.01
mainnet_e81889 - altair processInactivityUpdates 3.5247 ms/op 3.6947 ms/op 0.95
mainnet_e81889 - altair processRewardsAndPenalties 17.977 ms/op 17.392 ms/op 1.03
mainnet_e81889 - altair processRegistryUpdates 578.00 ns/op 583.00 ns/op 0.99
mainnet_e81889 - altair processSlashings 145.00 ns/op 147.00 ns/op 0.99
mainnet_e81889 - altair processEth1DataReset 146.00 ns/op 147.00 ns/op 0.99
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.6345 ms/op 1.3027 ms/op 1.25
mainnet_e81889 - altair processSlashingsReset 723.00 ns/op 713.00 ns/op 1.01
mainnet_e81889 - altair processRandaoMixesReset 1.0740 us/op 1.0840 us/op 0.99
mainnet_e81889 - altair processHistoricalRootsUpdate 154.00 ns/op 143.00 ns/op 1.08
mainnet_e81889 - altair processParticipationFlagUpdates 465.00 ns/op 459.00 ns/op 1.01
mainnet_e81889 - altair processSyncCommitteeUpdates 127.00 ns/op 122.00 ns/op 1.04
mainnet_e81889 - altair afterProcessEpoch 43.201 ms/op 41.501 ms/op 1.04
capella processEpoch - mainnet_e217614 778.21 ms/op 761.08 ms/op 1.02
mainnet_e217614 - capella beforeProcessEpoch 57.437 ms/op 56.640 ms/op 1.01
mainnet_e217614 - capella processJustificationAndFinalization 5.2890 us/op 5.5380 us/op 0.96
mainnet_e217614 - capella processInactivityUpdates 10.999 ms/op 13.196 ms/op 0.83
mainnet_e217614 - capella processRewardsAndPenalties 86.696 ms/op 90.285 ms/op 0.96
mainnet_e217614 - capella processRegistryUpdates 4.4650 us/op 4.5780 us/op 0.98
mainnet_e217614 - capella processSlashings 154.00 ns/op 140.00 ns/op 1.10
mainnet_e217614 - capella processEth1DataReset 144.00 ns/op 136.00 ns/op 1.06
mainnet_e217614 - capella processEffectiveBalanceUpdates 5.3131 ms/op 12.265 ms/op 0.43
mainnet_e217614 - capella processSlashingsReset 689.00 ns/op 692.00 ns/op 1.00
mainnet_e217614 - capella processRandaoMixesReset 1.1760 us/op 1.1920 us/op 0.99
mainnet_e217614 - capella processHistoricalRootsUpdate 144.00 ns/op 139.00 ns/op 1.04
mainnet_e217614 - capella processParticipationFlagUpdates 456.00 ns/op 460.00 ns/op 0.99
mainnet_e217614 - capella afterProcessEpoch 109.81 ms/op 109.82 ms/op 1.00
phase0 processEpoch - mainnet_e58758 255.03 ms/op 292.29 ms/op 0.87
mainnet_e58758 - phase0 beforeProcessEpoch 50.219 ms/op 61.189 ms/op 0.82
mainnet_e58758 - phase0 processJustificationAndFinalization 5.4080 us/op 5.9150 us/op 0.91
mainnet_e58758 - phase0 processRewardsAndPenalties 15.441 ms/op 15.279 ms/op 1.01
mainnet_e58758 - phase0 processRegistryUpdates 2.3270 us/op 2.2790 us/op 1.02
mainnet_e58758 - phase0 processSlashings 154.00 ns/op 155.00 ns/op 0.99
mainnet_e58758 - phase0 processEth1DataReset 144.00 ns/op 140.00 ns/op 1.03
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 988.02 us/op 826.91 us/op 1.19
mainnet_e58758 - phase0 processSlashingsReset 851.00 ns/op 839.00 ns/op 1.01
mainnet_e58758 - phase0 processRandaoMixesReset 1.1520 us/op 1.6210 us/op 0.71
mainnet_e58758 - phase0 processHistoricalRootsUpdate 150.00 ns/op 142.00 ns/op 1.06
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.1800 us/op 1.0550 us/op 1.12
mainnet_e58758 - phase0 afterProcessEpoch 34.899 ms/op 33.903 ms/op 1.03
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.0182 ms/op 1.0199 ms/op 1.00
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 1.6670 ms/op 1.2445 ms/op 1.34
altair processInactivityUpdates - 250000 normalcase 10.990 ms/op 10.738 ms/op 1.02
altair processInactivityUpdates - 250000 worstcase 10.805 ms/op 10.763 ms/op 1.00
phase0 processRegistryUpdates - 250000 normalcase 3.0330 us/op 3.4130 us/op 0.89
phase0 processRegistryUpdates - 250000 badcase_full_deposits 149.75 us/op 145.05 us/op 1.03
phase0 processRegistryUpdates - 250000 worstcase 0.5 51.203 ms/op 61.481 ms/op 0.83
altair processRewardsAndPenalties - 250000 normalcase 14.391 ms/op 13.971 ms/op 1.03
altair processRewardsAndPenalties - 250000 worstcase 13.643 ms/op 14.063 ms/op 0.97
phase0 getAttestationDeltas - 250000 normalcase 5.5292 ms/op 5.6743 ms/op 0.97
phase0 getAttestationDeltas - 250000 worstcase 5.5036 ms/op 5.7361 ms/op 0.96
phase0 processSlashings - 250000 worstcase 59.325 us/op 62.054 us/op 0.96
altair processSyncCommitteeUpdates - 250000 10.280 ms/op 10.186 ms/op 1.01
BeaconState.hashTreeRoot - No change 178.00 ns/op 193.00 ns/op 0.92
BeaconState.hashTreeRoot - 1 full validator 60.969 us/op 59.750 us/op 1.02
BeaconState.hashTreeRoot - 32 full validator 668.90 us/op 655.24 us/op 1.02
BeaconState.hashTreeRoot - 512 full validator 6.2191 ms/op 5.8810 ms/op 1.06
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 73.599 us/op 78.784 us/op 0.93
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.0917 ms/op 1.2407 ms/op 0.88
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 13.379 ms/op 14.032 ms/op 0.95
BeaconState.hashTreeRoot - 1 balances 58.691 us/op 59.438 us/op 0.99
BeaconState.hashTreeRoot - 32 balances 605.40 us/op 576.20 us/op 1.05
BeaconState.hashTreeRoot - 512 balances 5.1499 ms/op 4.5820 ms/op 1.12
BeaconState.hashTreeRoot - 250000 balances 121.15 ms/op 105.28 ms/op 1.15
aggregationBits - 2048 els - zipIndexesInBitList 19.453 us/op 19.585 us/op 0.99
regular array get 100000 times 23.349 us/op 23.167 us/op 1.01
wrappedArray get 100000 times 23.210 us/op 23.137 us/op 1.00
arrayWithProxy get 100000 times 11.135 ms/op 10.379 ms/op 1.07
ssz.Root.equals 21.972 ns/op 21.742 ns/op 1.01
byteArrayEquals 21.645 ns/op 21.541 ns/op 1.00
Buffer.compare 8.9790 ns/op 8.9510 ns/op 1.00
processSlot - 1 slots 8.5290 us/op 9.3890 us/op 0.91
processSlot - 32 slots 2.1902 ms/op 1.9757 ms/op 1.11
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 2.9912 ms/op 2.1699 ms/op 1.38
getCommitteeAssignments - req 1 vs - 250000 vc 1.6932 ms/op 1.7141 ms/op 0.99
getCommitteeAssignments - req 100 vs - 250000 vc 3.4727 ms/op 3.4900 ms/op 1.00
getCommitteeAssignments - req 1000 vs - 250000 vc 3.7332 ms/op 3.7213 ms/op 1.00
findModifiedValidators - 10000 modified validators 683.73 ms/op 788.58 ms/op 0.87
findModifiedValidators - 1000 modified validators 533.90 ms/op 518.42 ms/op 1.03
findModifiedValidators - 100 modified validators 295.78 ms/op 301.30 ms/op 0.98
findModifiedValidators - 10 modified validators 166.53 ms/op 260.45 ms/op 0.64
findModifiedValidators - 1 modified validators 215.86 ms/op 145.37 ms/op 1.48
findModifiedValidators - no difference 198.13 ms/op 146.62 ms/op 1.35
migrate state 1500000 validators, 3400 modified, 2000 new 2.7761 s/op 2.5361 s/op 1.09
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 3.8200 ns/op 3.7700 ns/op 1.01
state getBlockRootAtSlot - 250000 vs - 7PWei 274.30 ns/op 280.53 ns/op 0.98
computeProposerIndex 100000 validators 1.3681 ms/op 1.3457 ms/op 1.02
getNextSyncCommitteeIndices 1000 validators 2.9379 ms/op 2.8965 ms/op 1.01
getNextSyncCommitteeIndices 10000 validators 25.971 ms/op 25.473 ms/op 1.02
getNextSyncCommitteeIndices 100000 validators 85.233 ms/op 87.952 ms/op 0.97
computeProposers - vc 250000 573.81 us/op 553.08 us/op 1.04
computeEpochShuffling - vc 250000 41.447 ms/op 39.342 ms/op 1.05
getNextSyncCommittee - vc 250000 9.6951 ms/op 9.4688 ms/op 1.02
nodejs block root to RootHex using toHex 100.53 ns/op 97.077 ns/op 1.04
nodejs block root to RootHex using toRootHex 63.462 ns/op 62.602 ns/op 1.01
nodejs fromHex(blob) 766.39 us/op 729.84 us/op 1.05
nodejs fromHexInto(blob) 639.91 us/op 633.81 us/op 1.01
nodejs block root to RootHex using the deprecated toHexString 470.25 ns/op 378.50 ns/op 1.24
nodejs byteArrayEquals 32 bytes (block root) 26.409 ns/op 26.053 ns/op 1.01
nodejs byteArrayEquals 48 bytes (pubkey) 38.419 ns/op 37.733 ns/op 1.02
nodejs byteArrayEquals 96 bytes (signature) 36.289 ns/op 35.905 ns/op 1.01
nodejs byteArrayEquals 1024 bytes 43.806 ns/op 43.048 ns/op 1.02
nodejs byteArrayEquals 131072 bytes (blob) 1.7609 us/op 1.7574 us/op 1.00
browser block root to RootHex using toHex 145.64 ns/op 145.43 ns/op 1.00
browser block root to RootHex using toRootHex 130.60 ns/op 129.97 ns/op 1.00
browser fromHex(blob) 1.5238 ms/op 1.6342 ms/op 0.93
browser fromHexInto(blob) 633.60 us/op 634.64 us/op 1.00
browser block root to RootHex using the deprecated toHexString 327.84 ns/op 482.15 ns/op 0.68
browser byteArrayEquals 32 bytes (block root) 28.229 ns/op 28.082 ns/op 1.01
browser byteArrayEquals 48 bytes (pubkey) 39.854 ns/op 39.625 ns/op 1.01
browser byteArrayEquals 96 bytes (signature) 74.249 ns/op 74.525 ns/op 1.00
browser byteArrayEquals 1024 bytes 754.97 ns/op 758.09 ns/op 1.00
browser byteArrayEquals 131072 bytes (blob) 94.926 us/op 95.555 us/op 0.99

by benchmarkbot/action

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;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@nflaig nflaig Jul 17, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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", {

@nflaig nflaig Jul 14, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated, but I thought we always logged this as a warn so users can notice it more easily in the logs

@nflaig
nflaig marked this pull request as ready for review July 14, 2026 16:51
@nflaig
nflaig requested a review from a team as a code owner July 14, 2026 16:51
@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.52%. Comparing base (4001398) to head (ef4f390).

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:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/beacon-node/src/api/impl/beacon/blocks/index.ts Outdated
Regenerating the block state is a beacon node internal failure, not a client error. Also include the slot in the message.
nflaig added 11 commits July 24, 2026 20:18
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,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not part of the current spec but we should re-add it to v4

@nflaig
nflaig marked this pull request as ready for review July 25, 2026 14:42
@nflaig
nflaig requested review from twoeths and wemeetagain July 25, 2026 14:51
@twoeths
twoeths merged commit 6568180 into unstable Jul 27, 2026
19 checks passed
@twoeths
twoeths deleted the nflaig/stateless-flow branch July 27, 2026 03:51
ensi321 added a commit that referenced this pull request Jul 28, 2026
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.
wemeetagain pushed a commit that referenced this pull request Aug 7, 2026
…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
@wemeetagain

Copy link
Copy Markdown
Member

🎉 This PR is included in v1.46.0 🎉

matthewkeil added a commit that referenced this pull request Aug 13, 2026
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>
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.

5 participants