Skip to content

feat: cache builder deposit signatures for gloas fork transition - #9727

Open
twoeths wants to merge 5 commits into
unstablefrom
te/gloas_onboard_builders_at_fork
Open

feat: cache builder deposit signatures for gloas fork transition#9727
twoeths wants to merge 5 commits into
unstablefrom
te/gloas_onboard_builders_at_fork

Conversation

@twoeths

@twoeths twoeths commented Jul 30, 2026

Copy link
Copy Markdown
Member

Motivation

  • at gloas fork transition, we need to loop through all builder deposits and it takes time to validate all signatures once
  • this PR introduce a cache to pre-verify buidler deposit signatures 2 epochs before gloas

Description

  • change PendingDeposit ssz type to ContainerNodeStruct so that we can speed up the loop and cache by the object itself
  • new single instance BuilderDepositSignatureCache
    • this is populated in PrepareNextSlot 2 epochs before gloas transition
    • do batch signature verification there
    • skip if we either have next proposer duty or epoch transition
    • clear once gloas first finalized epoch
  • at gloas fork transition, we only need to get validation result from the cache, if not we validate one by one (just a fallback)
  • for now we cache 10k builder deposits per loop (~2.7s to verify on our infrastructure). I added metrics and logs so that we can monitor on testnets and see if we need to tweak for mainnet

AI Assistance Disclosure

  • created with the help of Claude

@twoeths
twoeths marked this pull request as ready for review July 30, 2026 06:43
@twoeths
twoeths requested a review from a team as a code owner July 30, 2026 06:43
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

⚠️ Performance Alert ⚠️

Possible performance regression was detected for some benchmarks.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold.

Benchmark suite Current: 114e86a Previous: d96240a Ratio
Full columns - reconstruct all 6 blobs 479.26 us/op 122.00 us/op 3.93
Full benchmark results
Benchmark suite Current: 114e86a Previous: d96240a Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 1.1796 ms/op 905.84 us/op 1.30
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 40.098 us/op 40.994 us/op 0.98
BLS verify - blst 766.38 us/op 726.62 us/op 1.05
BLS verifyMultipleSignatures 3 - blst 1.3799 ms/op 1.3435 ms/op 1.03
BLS verifyMultipleSignatures 8 - blst 2.2039 ms/op 2.1060 ms/op 1.05
BLS verifyMultipleSignatures 32 - blst 7.0577 ms/op 6.5893 ms/op 1.07
BLS verifyMultipleSignatures 64 - blst 13.998 ms/op 13.486 ms/op 1.04
BLS verifyMultipleSignatures 128 - blst 26.200 ms/op 25.287 ms/op 1.04
BLS deserializing 10000 signatures 654.92 ms/op 640.44 ms/op 1.02
BLS deserializing 100000 signatures 6.4735 s/op 6.4458 s/op 1.00
BLS verifyMultipleSignatures - same message - 3 - blst 802.76 us/op 695.75 us/op 1.15
BLS verifyMultipleSignatures - same message - 8 - blst 855.95 us/op 897.84 us/op 0.95
BLS verifyMultipleSignatures - same message - 32 - blst 1.6047 ms/op 1.5525 ms/op 1.03
BLS verifyMultipleSignatures - same message - 64 - blst 2.4990 ms/op 2.3606 ms/op 1.06
BLS verifyMultipleSignatures - same message - 128 - blst 4.1060 ms/op 3.9685 ms/op 1.03
BLS aggregatePubkeys 32 - blst 18.050 us/op 17.268 us/op 1.05
BLS aggregatePubkeys 128 - blst 63.830 us/op 61.254 us/op 1.04
getSlashingsAndExits - default max 49.992 us/op 47.056 us/op 1.06
getSlashingsAndExits - 2k 408.54 us/op 339.17 us/op 1.20
proposeBlockBody type=full, size=empty 1.6897 ms/op 3.4439 ms/op 0.49
isKnown best case - 1 super set check 165.00 ns/op 161.00 ns/op 1.02
isKnown normal case - 2 super set checks 166.00 ns/op 167.00 ns/op 0.99
isKnown worse case - 16 super set checks 164.00 ns/op 163.00 ns/op 1.01
validate api signedAggregateAndProof - struct 1.5292 ms/op 1.4760 ms/op 1.04
validate gossip signedAggregateAndProof - struct 1.5372 ms/op 1.4912 ms/op 1.03
batch validate gossip attestation - vc 640000 - chunk 32 108.67 us/op 106.88 us/op 1.02
batch validate gossip attestation - vc 640000 - chunk 64 93.608 us/op 93.952 us/op 1.00
batch validate gossip attestation - vc 640000 - chunk 128 86.740 us/op 86.852 us/op 1.00
batch validate gossip attestation - vc 640000 - chunk 256 83.580 us/op 82.565 us/op 1.01
bytes32 toHexString 288.00 ns/op 273.00 ns/op 1.05
bytes32 Buffer.toString(hex) 167.00 ns/op 164.00 ns/op 1.02
bytes32 Buffer.toString(hex) from Uint8Array 240.00 ns/op 240.00 ns/op 1.00
bytes32 Buffer.toString(hex) + 0x 168.00 ns/op 165.00 ns/op 1.02
Return object 10000 times 0.21510 ns/op 0.21420 ns/op 1.00
Throw Error 10000 times 3.4905 us/op 3.3383 us/op 1.05
toHex 101.22 ns/op 105.97 ns/op 0.96
Buffer.from 91.639 ns/op 87.072 ns/op 1.05
shared Buffer 64.768 ns/op 57.837 ns/op 1.12
fastMsgIdFn sha256 / 200 bytes 1.4780 us/op 1.4740 us/op 1.00
fastMsgIdFn h32 xxhash / 200 bytes 173.00 ns/op 158.00 ns/op 1.09
fastMsgIdFn h64 xxhash / 200 bytes 211.00 ns/op 209.00 ns/op 1.01
fastMsgIdFn sha256 / 1000 bytes 4.7350 us/op 4.7020 us/op 1.01
fastMsgIdFn h32 xxhash / 1000 bytes 264.00 ns/op 247.00 ns/op 1.07
fastMsgIdFn h64 xxhash / 1000 bytes 265.00 ns/op 254.00 ns/op 1.04
fastMsgIdFn sha256 / 10000 bytes 41.799 us/op 41.762 us/op 1.00
fastMsgIdFn h32 xxhash / 10000 bytes 1.2730 us/op 1.2580 us/op 1.01
fastMsgIdFn h64 xxhash / 10000 bytes 823.00 ns/op 804.00 ns/op 1.02
send data - 1000 256B messages 4.1930 ms/op 4.1793 ms/op 1.00
send data - 1000 512B messages 5.6496 ms/op 5.1590 ms/op 1.10
send data - 1000 1024B messages 5.8690 ms/op 5.8955 ms/op 1.00
send data - 1000 1200B messages 10.520 ms/op 6.4392 ms/op 1.63
send data - 1000 2048B messages 11.283 ms/op 11.050 ms/op 1.02
send data - 1000 4096B messages 107.24 ms/op 46.077 ms/op 2.33
send data - 1000 16384B messages 312.90 ms/op 155.91 ms/op 2.01
send data - 1000 65536B messages 1.5891 s/op 960.41 ms/op 1.65
enrSubnets - fastDeserialize 64 bits 794.00 ns/op 754.00 ns/op 1.05
enrSubnets - ssz BitVector 64 bits 264.00 ns/op 265.00 ns/op 1.00
enrSubnets - fastDeserialize 4 bits 103.00 ns/op 103.00 ns/op 1.00
enrSubnets - ssz BitVector 4 bits 265.00 ns/op 255.00 ns/op 1.04
prioritizePeers score -10:0 att 32-0.1 sync 2-0 210.68 us/op 196.86 us/op 1.07
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 238.50 us/op 222.26 us/op 1.07
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 346.67 us/op 325.78 us/op 1.06
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 607.29 us/op 581.31 us/op 1.04
prioritizePeers score 0:0 att 64-1 sync 4-1 707.64 us/op 679.33 us/op 1.04
array of 16000 items push then shift 1.3175 us/op 1.2425 us/op 1.06
LinkedList of 16000 items push then shift 7.7130 ns/op 7.3720 ns/op 1.05
array of 16000 items push then pop 66.459 ns/op 65.217 ns/op 1.02
LinkedList of 16000 items push then pop 6.1030 ns/op 5.9360 ns/op 1.03
array of 24000 items push then shift 1.9566 us/op 1.8543 us/op 1.06
LinkedList of 24000 items push then shift 7.0640 ns/op 6.8950 ns/op 1.02
array of 24000 items push then pop 96.965 ns/op 92.779 ns/op 1.05
LinkedList of 24000 items push then pop 6.1520 ns/op 5.9600 ns/op 1.03
intersect bitArray bitLen 8 4.0140 ns/op 3.8730 ns/op 1.04
intersect array and set length 8 30.313 ns/op 29.153 ns/op 1.04
intersect bitArray bitLen 128 24.117 ns/op 23.246 ns/op 1.04
intersect array and set length 128 507.39 ns/op 493.75 ns/op 1.03
bitArray.getTrueBitIndexes() bitLen 128 940.00 ns/op 918.00 ns/op 1.02
bitArray.getTrueBitIndexes() bitLen 248 1.7060 us/op 1.6660 us/op 1.02
bitArray.getTrueBitIndexes() bitLen 512 3.6150 us/op 3.4590 us/op 1.05
Full columns - reconstruct all 6 blobs 479.26 us/op 122.00 us/op 3.93
Full columns - reconstruct half of the blobs out of 6 102.06 us/op 59.800 us/op 1.71
Full columns - reconstruct single blob out of 6 35.975 us/op 45.577 us/op 0.79
Half columns - reconstruct all 6 blobs 400.98 ms/op 380.21 ms/op 1.05
Half columns - reconstruct half of the blobs out of 6 203.31 ms/op 192.30 ms/op 1.06
Half columns - reconstruct single blob out of 6 70.147 ms/op 67.766 ms/op 1.04
Set add up to 64 items then delete first 1.6786 us/op 1.6168 us/op 1.04
OrderedSet add up to 64 items then delete first 2.5708 us/op 2.4763 us/op 1.04
Set add up to 64 items then delete last 1.8956 us/op 1.8102 us/op 1.05
OrderedSet add up to 64 items then delete last 2.9424 us/op 2.7384 us/op 1.07
Set add up to 64 items then delete middle 1.9272 us/op 1.8259 us/op 1.06
OrderedSet add up to 64 items then delete middle 4.5293 us/op 4.1728 us/op 1.09
Set add up to 128 items then delete first 3.7077 us/op 3.6041 us/op 1.03
OrderedSet add up to 128 items then delete first 5.5684 us/op 5.6398 us/op 0.99
Set add up to 128 items then delete last 3.6990 us/op 3.4404 us/op 1.08
OrderedSet add up to 128 items then delete last 5.9217 us/op 5.2428 us/op 1.13
Set add up to 128 items then delete middle 3.7158 us/op 3.4627 us/op 1.07
OrderedSet add up to 128 items then delete middle 11.881 us/op 10.910 us/op 1.09
Set add up to 256 items then delete first 7.6288 us/op 7.1344 us/op 1.07
OrderedSet add up to 256 items then delete first 12.603 us/op 11.279 us/op 1.12
Set add up to 256 items then delete last 7.4019 us/op 7.0136 us/op 1.06
OrderedSet add up to 256 items then delete last 11.997 us/op 10.936 us/op 1.10
Set add up to 256 items then delete middle 7.3898 us/op 6.9228 us/op 1.07
OrderedSet add up to 256 items then delete middle 36.984 us/op 34.139 us/op 1.08
runFastConfirmationRules vc:100000 bc:96 eq:0 4.9187 ms/op 4.4265 ms/op 1.11
runFastConfirmationRules vc:600000 bc:96 eq:0 39.224 ms/op 34.318 ms/op 1.14
runFastConfirmationRules vc:1000000 bc:96 eq:0 60.129 ms/op 58.955 ms/op 1.02
runFastConfirmationRules vc:600000 bc:320 eq:0 35.265 ms/op 34.539 ms/op 1.02
runFastConfirmationRules vc:100000 bc:96 eq:1000 1.1490 s/op 1.0962 s/op 1.05
pass gossip attestations to forkchoice per slot 2.8680 ms/op 3.3851 ms/op 0.85
forkChoice updateHead vc 100000 bc 64 eq 0 420.81 us/op 410.23 us/op 1.03
forkChoice updateHead vc 600000 bc 64 eq 0 2.4899 ms/op 2.4419 ms/op 1.02
forkChoice updateHead vc 1000000 bc 64 eq 0 4.1560 ms/op 4.1172 ms/op 1.01
forkChoice updateHead vc 600000 bc 320 eq 0 2.4860 ms/op 2.5211 ms/op 0.99
forkChoice updateHead vc 600000 bc 1200 eq 0 2.5310 ms/op 2.5975 ms/op 0.97
forkChoice updateHead vc 600000 bc 7200 eq 0 2.9055 ms/op 4.7321 ms/op 0.61
forkChoice updateHead vc 600000 bc 64 eq 1000 2.5052 ms/op 2.4547 ms/op 1.02
forkChoice updateHead vc 600000 bc 64 eq 10000 2.5915 ms/op 2.5641 ms/op 1.01
forkChoice updateHead vc 600000 bc 64 eq 300000 6.7821 ms/op 6.4445 ms/op 1.05
computeDeltas 1400000 validators 0% inactive 12.411 ms/op 12.135 ms/op 1.02
computeDeltas 1400000 validators 10% inactive 11.883 ms/op 11.765 ms/op 1.01
computeDeltas 1400000 validators 20% inactive 11.180 ms/op 13.472 ms/op 0.83
computeDeltas 1400000 validators 50% inactive 9.0414 ms/op 8.8283 ms/op 1.02
computeDeltas 2100000 validators 0% inactive 18.837 ms/op 18.106 ms/op 1.04
computeDeltas 2100000 validators 10% inactive 17.883 ms/op 17.035 ms/op 1.05
computeDeltas 2100000 validators 20% inactive 16.727 ms/op 16.238 ms/op 1.03
computeDeltas 2100000 validators 50% inactive 11.115 ms/op 10.651 ms/op 1.04
altair processAttestation - 250000 vs - 7PWei normalcase 2.7069 ms/op 2.0226 ms/op 1.34
altair processAttestation - 250000 vs - 7PWei worstcase 2.5491 ms/op 2.9172 ms/op 0.87
altair processAttestation - setStatus - 1/6 committees join 102.93 us/op 105.93 us/op 0.97
altair processAttestation - setStatus - 1/3 committees join 212.23 us/op 215.36 us/op 0.99
altair processAttestation - setStatus - 1/2 committees join 300.10 us/op 290.51 us/op 1.03
altair processAttestation - setStatus - 2/3 committees join 376.30 us/op 381.73 us/op 0.99
altair processAttestation - setStatus - 4/5 committees join 516.62 us/op 508.46 us/op 1.02
altair processAttestation - setStatus - 100% committees join 602.38 us/op 589.66 us/op 1.02
altair processBlock - 250000 vs - 7PWei normalcase 2.8305 ms/op 4.6006 ms/op 0.62
altair processBlock - 250000 vs - 7PWei normalcase hashState 11.912 ms/op 19.282 ms/op 0.62
altair processBlock - 250000 vs - 7PWei worstcase 19.285 ms/op 22.460 ms/op 0.86
altair processBlock - 250000 vs - 7PWei worstcase hashState 39.878 ms/op 46.674 ms/op 0.85
phase0 processBlock - 250000 vs - 7PWei normalcase 1.3202 ms/op 1.3707 ms/op 0.96
phase0 processBlock - 250000 vs - 7PWei worstcase 16.967 ms/op 16.971 ms/op 1.00
altair processEth1Data - 250000 vs - 7PWei normalcase 294.87 us/op 290.66 us/op 1.01
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:16 3.0520 us/op 4.1680 us/op 0.73
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:220 20.921 us/op 20.429 us/op 1.02
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:43 6.6180 us/op 5.4890 us/op 1.21
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:19 3.7810 us/op 3.7510 us/op 1.01
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1021 88.013 us/op 89.203 us/op 0.99
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11778 1.3460 ms/op 1.3576 ms/op 0.99
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.7728 ms/op 1.7869 ms/op 0.99
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.7557 ms/op 1.8208 ms/op 0.96
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 3.5630 ms/op 4.2840 ms/op 0.83
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.0378 ms/op 2.0506 ms/op 0.99
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 3.9218 ms/op 4.6817 ms/op 0.84
Tree 40 250000 create 305.84 ms/op 341.09 ms/op 0.90
Tree 40 250000 get(125000) 99.157 ns/op 94.768 ns/op 1.05
Tree 40 250000 set(125000) 1.0381 us/op 1.0169 us/op 1.02
Tree 40 250000 toArray() 9.0912 ms/op 15.868 ms/op 0.57
Tree 40 250000 iterate all - toArray() + loop 9.1649 ms/op 14.635 ms/op 0.63
Tree 40 250000 iterate all - get(i) 35.019 ms/op 38.710 ms/op 0.90
Array 250000 create 2.0572 ms/op 2.1499 ms/op 0.96
Array 250000 clone - spread 647.25 us/op 670.64 us/op 0.97
Array 250000 get(125000) 0.29300 ns/op 0.30100 ns/op 0.97
Array 250000 set(125000) 0.29500 ns/op 0.30300 ns/op 0.97
Array 250000 iterate all - loop 56.518 us/op 58.666 us/op 0.96
phase0 afterProcessEpoch - 250000 vs - 7PWei 39.247 ms/op 59.007 ms/op 0.67
Array.fill - length 1000000 2.2140 ms/op 2.6672 ms/op 0.83
Array push - length 1000000 7.5055 ms/op 10.996 ms/op 0.68
Array.get 0.20437 ns/op 0.20351 ns/op 1.00
Uint8Array.get 0.24671 ns/op 0.23976 ns/op 1.03
phase0 beforeProcessEpoch - 250000 vs - 7PWei 18.184 ms/op 14.165 ms/op 1.28
altair processEpoch - mainnet_e81889 234.96 ms/op 270.59 ms/op 0.87
mainnet_e81889 - altair beforeProcessEpoch 13.188 ms/op 15.503 ms/op 0.85
mainnet_e81889 - altair processJustificationAndFinalization 4.8960 us/op 6.1500 us/op 0.80
mainnet_e81889 - altair processInactivityUpdates 3.4900 ms/op 4.4823 ms/op 0.78
mainnet_e81889 - altair processRewardsAndPenalties 16.738 ms/op 21.515 ms/op 0.78
mainnet_e81889 - altair processRegistryUpdates 568.00 ns/op 557.00 ns/op 1.02
mainnet_e81889 - altair processSlashings 158.00 ns/op 147.00 ns/op 1.07
mainnet_e81889 - altair processEth1DataReset 148.00 ns/op 143.00 ns/op 1.03
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.7184 ms/op 3.2190 ms/op 0.53
mainnet_e81889 - altair processSlashingsReset 710.00 ns/op 714.00 ns/op 0.99
mainnet_e81889 - altair processRandaoMixesReset 1.3270 us/op 1.2840 us/op 1.03
mainnet_e81889 - altair processHistoricalRootsUpdate 155.00 ns/op 142.00 ns/op 1.09
mainnet_e81889 - altair processParticipationFlagUpdates 454.00 ns/op 454.00 ns/op 1.00
mainnet_e81889 - altair processSyncCommitteeUpdates 128.00 ns/op 117.00 ns/op 1.09
mainnet_e81889 - altair afterProcessEpoch 42.226 ms/op 41.630 ms/op 1.01
capella processEpoch - mainnet_e217614 780.02 ms/op 824.14 ms/op 0.95
mainnet_e217614 - capella beforeProcessEpoch 56.186 ms/op 58.252 ms/op 0.96
mainnet_e217614 - capella processJustificationAndFinalization 6.2000 us/op 6.4290 us/op 0.96
mainnet_e217614 - capella processInactivityUpdates 13.348 ms/op 15.925 ms/op 0.84
mainnet_e217614 - capella processRewardsAndPenalties 93.311 ms/op 98.752 ms/op 0.94
mainnet_e217614 - capella processRegistryUpdates 4.6600 us/op 4.5810 us/op 1.02
mainnet_e217614 - capella processSlashings 155.00 ns/op 163.00 ns/op 0.95
mainnet_e217614 - capella processEth1DataReset 154.00 ns/op 157.00 ns/op 0.98
mainnet_e217614 - capella processEffectiveBalanceUpdates 18.823 ms/op 15.719 ms/op 1.20
mainnet_e217614 - capella processSlashingsReset 715.00 ns/op 698.00 ns/op 1.02
mainnet_e217614 - capella processRandaoMixesReset 1.4640 us/op 1.3570 us/op 1.08
mainnet_e217614 - capella processHistoricalRootsUpdate 182.00 ns/op 152.00 ns/op 1.20
mainnet_e217614 - capella processParticipationFlagUpdates 474.00 ns/op 476.00 ns/op 1.00
mainnet_e217614 - capella afterProcessEpoch 116.38 ms/op 109.29 ms/op 1.06
phase0 processEpoch - mainnet_e58758 327.29 ms/op 313.47 ms/op 1.04
mainnet_e58758 - phase0 beforeProcessEpoch 66.910 ms/op 68.194 ms/op 0.98
mainnet_e58758 - phase0 processJustificationAndFinalization 6.0540 us/op 6.3520 us/op 0.95
mainnet_e58758 - phase0 processRewardsAndPenalties 15.245 ms/op 16.142 ms/op 0.94
mainnet_e58758 - phase0 processRegistryUpdates 2.3100 us/op 2.2760 us/op 1.01
mainnet_e58758 - phase0 processSlashings 149.00 ns/op 151.00 ns/op 0.99
mainnet_e58758 - phase0 processEth1DataReset 148.00 ns/op 148.00 ns/op 1.00
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 834.71 us/op 826.04 us/op 1.01
mainnet_e58758 - phase0 processSlashingsReset 927.00 ns/op 872.00 ns/op 1.06
mainnet_e58758 - phase0 processRandaoMixesReset 1.3260 us/op 1.3580 us/op 0.98
mainnet_e58758 - phase0 processHistoricalRootsUpdate 150.00 ns/op 161.00 ns/op 0.93
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.1600 us/op 1.2020 us/op 0.97
mainnet_e58758 - phase0 afterProcessEpoch 35.194 ms/op 34.234 ms/op 1.03
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.0970 ms/op 1.0689 ms/op 1.03
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 1.6585 ms/op 1.7045 ms/op 0.97
altair processInactivityUpdates - 250000 normalcase 10.544 ms/op 12.394 ms/op 0.85
altair processInactivityUpdates - 250000 worstcase 11.281 ms/op 13.632 ms/op 0.83
phase0 processRegistryUpdates - 250000 normalcase 2.4260 us/op 2.1810 us/op 1.11
phase0 processRegistryUpdates - 250000 badcase_full_deposits 142.22 us/op 142.78 us/op 1.00
phase0 processRegistryUpdates - 250000 worstcase 0.5 70.249 ms/op 58.252 ms/op 1.21
altair processRewardsAndPenalties - 250000 normalcase 13.594 ms/op 18.470 ms/op 0.74
altair processRewardsAndPenalties - 250000 worstcase 13.025 ms/op 18.309 ms/op 0.71
phase0 getAttestationDeltas - 250000 normalcase 5.3897 ms/op 21.387 ms/op 0.25
phase0 getAttestationDeltas - 250000 worstcase 5.3927 ms/op 5.5323 ms/op 0.97
phase0 processSlashings - 250000 worstcase 58.887 us/op 61.009 us/op 0.97
altair processSyncCommitteeUpdates - 250000 9.9735 ms/op 12.488 ms/op 0.80
BeaconState.hashTreeRoot - No change 181.00 ns/op 190.00 ns/op 0.95
BeaconState.hashTreeRoot - 1 full validator 56.866 us/op 85.614 us/op 0.66
BeaconState.hashTreeRoot - 32 full validator 623.16 us/op 895.86 us/op 0.70
BeaconState.hashTreeRoot - 512 full validator 5.8664 ms/op 9.4594 ms/op 0.62
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 67.808 us/op 116.72 us/op 0.58
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.0158 ms/op 1.5618 ms/op 0.65
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 12.662 ms/op 22.253 ms/op 0.57
BeaconState.hashTreeRoot - 1 balances 54.531 us/op 87.259 us/op 0.62
BeaconState.hashTreeRoot - 32 balances 530.25 us/op 758.86 us/op 0.70
BeaconState.hashTreeRoot - 512 balances 4.5413 ms/op 6.0838 ms/op 0.75
BeaconState.hashTreeRoot - 250000 balances 98.380 ms/op 131.94 ms/op 0.75
aggregationBits - 2048 els - zipIndexesInBitList 18.844 us/op 19.263 us/op 0.98
regular array get 100000 times 22.795 us/op 23.006 us/op 0.99
wrappedArray get 100000 times 22.744 us/op 23.105 us/op 0.98
arrayWithProxy get 100000 times 11.024 ms/op 10.043 ms/op 1.10
ssz.Root.equals 21.571 ns/op 21.548 ns/op 1.00
byteArrayEquals 21.337 ns/op 21.376 ns/op 1.00
Buffer.compare 8.9240 ns/op 8.8650 ns/op 1.01
processSlot - 1 slots 8.0430 us/op 8.3410 us/op 0.96
processSlot - 32 slots 1.5551 ms/op 2.1578 ms/op 0.72
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 3.3022 ms/op 4.6843 ms/op 0.70
getCommitteeAssignments - req 1 vs - 250000 vc 1.7415 ms/op 1.7044 ms/op 1.02
getCommitteeAssignments - req 100 vs - 250000 vc 3.5367 ms/op 3.4069 ms/op 1.04
getCommitteeAssignments - req 1000 vs - 250000 vc 3.7953 ms/op 3.6755 ms/op 1.03
findModifiedValidators - 10000 modified validators 799.17 ms/op 732.14 ms/op 1.09
findModifiedValidators - 1000 modified validators 511.56 ms/op 437.09 ms/op 1.17
findModifiedValidators - 100 modified validators 318.98 ms/op 307.02 ms/op 1.04
findModifiedValidators - 10 modified validators 242.30 ms/op 290.56 ms/op 0.83
findModifiedValidators - 1 modified validators 252.34 ms/op 153.91 ms/op 1.64
findModifiedValidators - no difference 147.41 ms/op 155.52 ms/op 0.95
migrate state 1500000 validators, 3400 modified, 2000 new 3.0519 s/op 2.6982 s/op 1.13
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 3.8300 ns/op 3.5500 ns/op 1.08
state getBlockRootAtSlot - 250000 vs - 7PWei 301.57 ns/op 326.09 ns/op 0.92
computeProposerIndex 100000 validators 1.3456 ms/op 1.3100 ms/op 1.03
getNextSyncCommitteeIndices 1000 validators 2.9264 ms/op 2.8300 ms/op 1.03
getNextSyncCommitteeIndices 10000 validators 25.811 ms/op 24.829 ms/op 1.04
getNextSyncCommitteeIndices 100000 validators 85.056 ms/op 87.866 ms/op 0.97
computeProposers - vc 250000 562.37 us/op 557.74 us/op 1.01
computeEpochShuffling - vc 250000 39.527 ms/op 40.159 ms/op 0.98
getNextSyncCommittee - vc 250000 9.6094 ms/op 10.942 ms/op 0.88
nodejs block root to RootHex using toHex 107.79 ns/op 101.61 ns/op 1.06
nodejs block root to RootHex using toRootHex 65.809 ns/op 62.883 ns/op 1.05
nodejs fromHex(blob) 733.55 us/op 753.35 us/op 0.97
nodejs fromHexInto(blob) 664.10 us/op 626.25 us/op 1.06
nodejs block root to RootHex using the deprecated toHexString 456.40 ns/op 449.54 ns/op 1.02
nodejs byteArrayEquals 32 bytes (block root) 26.257 ns/op 26.015 ns/op 1.01
nodejs byteArrayEquals 48 bytes (pubkey) 37.883 ns/op 36.887 ns/op 1.03
nodejs byteArrayEquals 96 bytes (signature) 37.305 ns/op 33.849 ns/op 1.10
nodejs byteArrayEquals 1024 bytes 46.127 ns/op 41.425 ns/op 1.11
nodejs byteArrayEquals 131072 bytes (blob) 1.7849 us/op 1.7475 us/op 1.02
browser block root to RootHex using toHex 146.79 ns/op 144.79 ns/op 1.01
browser block root to RootHex using toRootHex 132.00 ns/op 132.30 ns/op 1.00
browser fromHex(blob) 1.5410 ms/op 1.5643 ms/op 0.99
browser fromHexInto(blob) 642.35 us/op 627.06 us/op 1.02
browser block root to RootHex using the deprecated toHexString 321.93 ns/op 321.79 ns/op 1.00
browser byteArrayEquals 32 bytes (block root) 28.227 ns/op 27.923 ns/op 1.01
browser byteArrayEquals 48 bytes (pubkey) 39.735 ns/op 38.849 ns/op 1.02
browser byteArrayEquals 96 bytes (signature) 73.915 ns/op 73.804 ns/op 1.00
browser byteArrayEquals 1024 bytes 758.17 ns/op 739.42 ns/op 1.03
browser byteArrayEquals 131072 bytes (blob) 96.030 us/op 95.839 us/op 1.00

by benchmarkbot/action

@codecov

codecov Bot commented Jul 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.52%. Comparing base (82546f1) to head (aa035b0).
⚠️ Report is 2 commits behind head on unstable.

Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #9727      +/-   ##
============================================
- Coverage     52.52%   52.52%   -0.01%     
============================================
  Files           848      848              
  Lines         60242    60241       -1     
  Branches       4430     4430              
============================================
- Hits          31642    31641       -1     
  Misses        28541    28541              
  Partials         59       59              
🚀 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: aa035b011d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// each node.value by reference — the stable cache key.
const queue: electra.PendingDeposit[] = [];
let scannedPendingDeposits = 0;
for (const deposit of state.pendingDeposits.getAllReadonlyValues()) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid materializing the full pending-deposit list

When the pre-Gloas pending-deposit queue is large, this call builds an array for every state.pendingDeposits element before the loop can hit the maxBuilderDeposits break. That means the per-slot cap only limits BLS verifications, not the list traversal/allocation work, so a large validator-deposit backlog can still make every prepareNextSlot tick do unbounded work in the fork window; iterate by index or by a bounded range instead.

Useful? React with 👍 / 👎.

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.

we loop through a lit of 2M validators on mainnet while pending deposits are <50k on mainnet
also switching through ContainerNodeStruct makes it way faster, see #9054
so should not be an issue with the loop

} else {
// Batch failed: at least one signature is invalid - verify each individually
for (let s = 0; s < signatureSets.length; s++) {
results[signatureSetDepositIndices[s]] = verify(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Catch per-deposit BLS verification failures

When any item in a failed batch has bytes that parsed but make verify(..., true, true) throw during subgroup or infinity checks, this fallback exits before writing results for the rest of the chunk. In the pre-Gloas scanner that exception is caught only by prepareNextSlot, so a single malformed builder deposit can make every run abort and leave subsequent valid builders uncached; keep the per-item path consistent with isValidDepositSignature by treating thrown verifies as false.

Useful? React with 👍 / 👎.

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.

added unit tests and fixed in 457e9cd

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

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants