Skip to content

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

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

feat: cache builder deposit signatures for gloas fork transition#9727
twoeths wants to merge 11 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 Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: a2733d4 Previous: 65cfb73 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 868.39 us/op 1.6303 ms/op 0.53
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 37.496 us/op 41.107 us/op 0.91
BLS verify - blst 679.20 us/op 758.32 us/op 0.90
BLS verifyMultipleSignatures 3 - blst 1.3128 ms/op 1.3689 ms/op 0.96
BLS verifyMultipleSignatures 8 - blst 2.0887 ms/op 2.1904 ms/op 0.95
BLS verifyMultipleSignatures 32 - blst 6.5978 ms/op 6.9492 ms/op 0.95
BLS verifyMultipleSignatures 64 - blst 12.917 ms/op 13.648 ms/op 0.95
BLS verifyMultipleSignatures 128 - blst 24.965 ms/op 25.779 ms/op 0.97
BLS deserializing 10000 signatures 625.17 ms/op 635.03 ms/op 0.98
BLS deserializing 100000 signatures 6.1897 s/op 6.3416 s/op 0.98
BLS verifyMultipleSignatures - same message - 3 - blst 773.72 us/op 777.51 us/op 1.00
BLS verifyMultipleSignatures - same message - 8 - blst 805.22 us/op 893.02 us/op 0.90
BLS verifyMultipleSignatures - same message - 32 - blst 1.4670 ms/op 1.5036 ms/op 0.98
BLS verifyMultipleSignatures - same message - 64 - blst 2.3303 ms/op 2.2863 ms/op 1.02
BLS verifyMultipleSignatures - same message - 128 - blst 3.9137 ms/op 4.0544 ms/op 0.97
BLS aggregatePubkeys 32 - blst 16.875 us/op 17.700 us/op 0.95
BLS aggregatePubkeys 128 - blst 60.296 us/op 63.261 us/op 0.95
getSlashingsAndExits - default max 47.473 us/op 47.059 us/op 1.01
getSlashingsAndExits - 2k 447.77 us/op 341.96 us/op 1.31
proposeBlockBody type=full, size=empty 794.71 us/op 660.01 us/op 1.20
isKnown best case - 1 super set check 164.00 ns/op 174.00 ns/op 0.94
isKnown normal case - 2 super set checks 162.00 ns/op 158.00 ns/op 1.03
isKnown worse case - 16 super set checks 162.00 ns/op 161.00 ns/op 1.01
validate api signedAggregateAndProof - struct 1.4827 ms/op 1.5454 ms/op 0.96
validate gossip signedAggregateAndProof - struct 1.4836 ms/op 1.5269 ms/op 0.97
batch validate gossip attestation - vc 640000 - chunk 32 113.88 us/op 108.10 us/op 1.05
batch validate gossip attestation - vc 640000 - chunk 64 99.889 us/op 94.397 us/op 1.06
batch validate gossip attestation - vc 640000 - chunk 128 96.805 us/op 87.732 us/op 1.10
batch validate gossip attestation - vc 640000 - chunk 256 89.966 us/op 83.138 us/op 1.08
bytes32 toHexString 290.00 ns/op 300.00 ns/op 0.97
bytes32 Buffer.toString(hex) 170.00 ns/op 162.00 ns/op 1.05
bytes32 Buffer.toString(hex) from Uint8Array 226.00 ns/op 231.00 ns/op 0.98
bytes32 Buffer.toString(hex) + 0x 169.00 ns/op 165.00 ns/op 1.02
Return object 10000 times 0.20930 ns/op 0.21220 ns/op 0.99
Throw Error 10000 times 3.1888 us/op 3.6481 us/op 0.87
toHex 99.174 ns/op 99.762 ns/op 0.99
Buffer.from 84.130 ns/op 92.044 ns/op 0.91
shared Buffer 56.513 ns/op 61.866 ns/op 0.91
fastMsgIdFn sha256 / 200 bytes 1.4320 us/op 1.4870 us/op 0.96
fastMsgIdFn h32 xxhash / 200 bytes 152.00 ns/op 147.00 ns/op 1.03
fastMsgIdFn h64 xxhash / 200 bytes 203.00 ns/op 196.00 ns/op 1.04
fastMsgIdFn sha256 / 1000 bytes 4.5830 us/op 4.7870 us/op 0.96
fastMsgIdFn h32 xxhash / 1000 bytes 236.00 ns/op 237.00 ns/op 1.00
fastMsgIdFn h64 xxhash / 1000 bytes 248.00 ns/op 247.00 ns/op 1.00
fastMsgIdFn sha256 / 10000 bytes 40.722 us/op 41.899 us/op 0.97
fastMsgIdFn h32 xxhash / 10000 bytes 1.2590 us/op 1.2630 us/op 1.00
fastMsgIdFn h64 xxhash / 10000 bytes 828.00 ns/op 814.00 ns/op 1.02
send data - 1000 256B messages 4.8319 ms/op 4.3527 ms/op 1.11
send data - 1000 512B messages 6.2676 ms/op 5.7711 ms/op 1.09
send data - 1000 1024B messages 6.3984 ms/op 5.4626 ms/op 1.17
send data - 1000 1200B messages 8.0604 ms/op 6.3265 ms/op 1.27
send data - 1000 2048B messages 15.451 ms/op 8.1056 ms/op 1.91
send data - 1000 4096B messages 132.68 ms/op 50.387 ms/op 2.63
send data - 1000 16384B messages 322.40 ms/op 317.07 ms/op 1.02
send data - 1000 65536B messages 2.1365 s/op 1.6309 s/op 1.31
enrSubnets - fastDeserialize 64 bits 776.00 ns/op 712.00 ns/op 1.09
enrSubnets - ssz BitVector 64 bits 270.00 ns/op 249.00 ns/op 1.08
enrSubnets - fastDeserialize 4 bits 103.00 ns/op 98.000 ns/op 1.05
enrSubnets - ssz BitVector 4 bits 275.00 ns/op 254.00 ns/op 1.08
prioritizePeers score -10:0 att 32-0.1 sync 2-0 277.98 us/op 216.55 us/op 1.28
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 235.68 us/op 231.95 us/op 1.02
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 330.95 us/op 320.39 us/op 1.03
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 616.01 us/op 594.29 us/op 1.04
prioritizePeers score 0:0 att 64-1 sync 4-1 708.61 us/op 659.15 us/op 1.08
array of 16000 items push then shift 1.2585 us/op 1.2047 us/op 1.04
LinkedList of 16000 items push then shift 8.4960 ns/op 6.8150 ns/op 1.25
array of 16000 items push then pop 69.780 ns/op 65.313 ns/op 1.07
LinkedList of 16000 items push then pop 6.4220 ns/op 6.0330 ns/op 1.06
array of 24000 items push then shift 1.8116 us/op 1.9162 us/op 0.95
LinkedList of 24000 items push then shift 7.7130 ns/op 6.3040 ns/op 1.22
array of 24000 items push then pop 102.74 ns/op 93.547 ns/op 1.10
LinkedList of 24000 items push then pop 6.4840 ns/op 5.9790 ns/op 1.08
intersect bitArray bitLen 8 3.8540 ns/op 3.8900 ns/op 0.99
intersect array and set length 8 29.354 ns/op 30.229 ns/op 0.97
intersect bitArray bitLen 128 24.918 ns/op 23.311 ns/op 1.07
intersect array and set length 128 489.49 ns/op 517.99 ns/op 0.94
bitArray.getTrueBitIndexes() bitLen 128 939.00 ns/op 908.00 ns/op 1.03
bitArray.getTrueBitIndexes() bitLen 248 1.6680 us/op 1.6360 us/op 1.02
bitArray.getTrueBitIndexes() bitLen 512 3.5180 us/op 3.4020 us/op 1.03
Full columns - reconstruct all 6 blobs 200.76 us/op 113.97 us/op 1.76
Full columns - reconstruct half of the blobs out of 6 96.413 us/op 80.289 us/op 1.20
Full columns - reconstruct single blob out of 6 39.339 us/op 31.472 us/op 1.25
Half columns - reconstruct all 6 blobs 405.19 ms/op 388.57 ms/op 1.04
Half columns - reconstruct half of the blobs out of 6 201.57 ms/op 195.12 ms/op 1.03
Half columns - reconstruct single blob out of 6 70.707 ms/op 69.706 ms/op 1.01
Set add up to 64 items then delete first 2.1245 us/op 1.6961 us/op 1.25
OrderedSet add up to 64 items then delete first 3.3019 us/op 2.5568 us/op 1.29
Set add up to 64 items then delete last 2.3270 us/op 1.9158 us/op 1.21
OrderedSet add up to 64 items then delete last 3.2681 us/op 2.8247 us/op 1.16
Set add up to 64 items then delete middle 2.0835 us/op 1.9232 us/op 1.08
OrderedSet add up to 64 items then delete middle 4.7429 us/op 4.2700 us/op 1.11
Set add up to 128 items then delete first 4.2058 us/op 3.8218 us/op 1.10
OrderedSet add up to 128 items then delete first 6.4832 us/op 5.8880 us/op 1.10
Set add up to 128 items then delete last 4.4564 us/op 3.6519 us/op 1.22
OrderedSet add up to 128 items then delete last 6.3860 us/op 5.4691 us/op 1.17
Set add up to 128 items then delete middle 3.8914 us/op 3.6763 us/op 1.06
OrderedSet add up to 128 items then delete middle 12.382 us/op 11.305 us/op 1.10
Set add up to 256 items then delete first 8.2024 us/op 7.6924 us/op 1.07
OrderedSet add up to 256 items then delete first 12.876 us/op 11.856 us/op 1.09
Set add up to 256 items then delete last 7.9734 us/op 6.6322 us/op 1.20
OrderedSet add up to 256 items then delete last 12.175 us/op 10.601 us/op 1.15
Set add up to 256 items then delete middle 7.8805 us/op 6.8853 us/op 1.14
OrderedSet add up to 256 items then delete middle 38.800 us/op 32.995 us/op 1.18
runFastConfirmationRules vc:100000 bc:96 eq:0 5.6032 ms/op 4.2375 ms/op 1.32
runFastConfirmationRules vc:600000 bc:96 eq:0 39.574 ms/op 33.126 ms/op 1.19
runFastConfirmationRules vc:1000000 bc:96 eq:0 61.547 ms/op 55.331 ms/op 1.11
runFastConfirmationRules vc:600000 bc:320 eq:0 36.446 ms/op 34.947 ms/op 1.04
runFastConfirmationRules vc:100000 bc:96 eq:1000 1.1234 s/op 1.0749 s/op 1.05
pass gossip attestations to forkchoice per slot 2.7008 ms/op 2.5549 ms/op 1.06
forkChoice updateHead vc 100000 bc 64 eq 0 408.38 us/op 485.08 us/op 0.84
forkChoice updateHead vc 600000 bc 64 eq 0 2.4406 ms/op 2.8290 ms/op 0.86
forkChoice updateHead vc 1000000 bc 64 eq 0 4.2349 ms/op 4.7160 ms/op 0.90
forkChoice updateHead vc 600000 bc 320 eq 0 2.4999 ms/op 2.8593 ms/op 0.87
forkChoice updateHead vc 600000 bc 1200 eq 0 2.5240 ms/op 2.9000 ms/op 0.87
forkChoice updateHead vc 600000 bc 7200 eq 0 4.6684 ms/op 3.2497 ms/op 1.44
forkChoice updateHead vc 600000 bc 64 eq 1000 2.5513 ms/op 2.9085 ms/op 0.88
forkChoice updateHead vc 600000 bc 64 eq 10000 2.4798 ms/op 2.9863 ms/op 0.83
forkChoice updateHead vc 600000 bc 64 eq 300000 6.4864 ms/op 6.8687 ms/op 0.94
computeDeltas 1400000 validators 0% inactive 12.003 ms/op 13.802 ms/op 0.87
computeDeltas 1400000 validators 10% inactive 11.350 ms/op 12.698 ms/op 0.89
computeDeltas 1400000 validators 20% inactive 10.765 ms/op 11.964 ms/op 0.90
computeDeltas 1400000 validators 50% inactive 8.7646 ms/op 9.7682 ms/op 0.90
computeDeltas 2100000 validators 0% inactive 18.059 ms/op 20.030 ms/op 0.90
computeDeltas 2100000 validators 10% inactive 16.819 ms/op 19.067 ms/op 0.88
computeDeltas 2100000 validators 20% inactive 15.831 ms/op 17.936 ms/op 0.88
computeDeltas 2100000 validators 50% inactive 10.595 ms/op 14.555 ms/op 0.73
altair processAttestation - 250000 vs - 7PWei normalcase 3.1906 ms/op 1.7119 ms/op 1.86
altair processAttestation - 250000 vs - 7PWei worstcase 3.7906 ms/op 2.4312 ms/op 1.56
altair processAttestation - setStatus - 1/6 committees join 129.31 us/op 107.99 us/op 1.20
altair processAttestation - setStatus - 1/3 committees join 242.66 us/op 207.69 us/op 1.17
altair processAttestation - setStatus - 1/2 committees join 345.87 us/op 292.97 us/op 1.18
altair processAttestation - setStatus - 2/3 committees join 439.70 us/op 379.96 us/op 1.16
altair processAttestation - setStatus - 4/5 committees join 605.42 us/op 519.66 us/op 1.17
altair processAttestation - setStatus - 100% committees join 720.18 us/op 613.65 us/op 1.17
altair processBlock - 250000 vs - 7PWei normalcase 5.6045 ms/op 2.9042 ms/op 1.93
altair processBlock - 250000 vs - 7PWei normalcase hashState 22.263 ms/op 17.575 ms/op 1.27
altair processBlock - 250000 vs - 7PWei worstcase 24.226 ms/op 19.792 ms/op 1.22
altair processBlock - 250000 vs - 7PWei worstcase hashState 46.807 ms/op 43.673 ms/op 1.07
phase0 processBlock - 250000 vs - 7PWei normalcase 1.6167 ms/op 1.4469 ms/op 1.12
phase0 processBlock - 250000 vs - 7PWei worstcase 19.830 ms/op 16.643 ms/op 1.19
altair processEth1Data - 250000 vs - 7PWei normalcase 287.52 us/op 295.16 us/op 0.97
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:16 6.3730 us/op 3.3970 us/op 1.88
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:220 21.349 us/op 20.573 us/op 1.04
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:43 6.1450 us/op 6.1390 us/op 1.00
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:19 4.0840 us/op 3.8660 us/op 1.06
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1021 95.885 us/op 93.605 us/op 1.02
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11778 1.4394 ms/op 1.3203 ms/op 1.09
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.9426 ms/op 1.7282 ms/op 1.12
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.9029 ms/op 1.8358 ms/op 1.04
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 5.0356 ms/op 3.4317 ms/op 1.47
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.1926 ms/op 2.0978 ms/op 1.05
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 5.2968 ms/op 4.0758 ms/op 1.30
Tree 40 250000 create 370.36 ms/op 331.16 ms/op 1.12
Tree 40 250000 get(125000) 91.158 ns/op 103.47 ns/op 0.88
Tree 40 250000 set(125000) 1.0704 us/op 1.0730 us/op 1.00
Tree 40 250000 toArray() 23.401 ms/op 11.822 ms/op 1.98
Tree 40 250000 iterate all - toArray() + loop 23.717 ms/op 10.189 ms/op 2.33
Tree 40 250000 iterate all - get(i) 43.146 ms/op 39.906 ms/op 1.08
Array 250000 create 2.3544 ms/op 2.0846 ms/op 1.13
Array 250000 clone - spread 711.84 us/op 648.58 us/op 1.10
Array 250000 get(125000) 0.29700 ns/op 0.30000 ns/op 0.99
Array 250000 set(125000) 0.29700 ns/op 0.30300 ns/op 0.98
Array 250000 iterate all - loop 57.693 us/op 57.715 us/op 1.00
phase0 afterProcessEpoch - 250000 vs - 7PWei 54.276 ms/op 39.683 ms/op 1.37
Array.fill - length 1000000 2.3546 ms/op 2.0853 ms/op 1.13
Array push - length 1000000 10.534 ms/op 7.4492 ms/op 1.41
Array.get 0.20827 ns/op 0.20942 ns/op 0.99
Uint8Array.get 0.23076 ns/op 0.23887 ns/op 0.97
phase0 beforeProcessEpoch - 250000 vs - 7PWei 24.938 ms/op 18.130 ms/op 1.38
altair processEpoch - mainnet_e81889 347.83 ms/op 305.34 ms/op 1.14
mainnet_e81889 - altair beforeProcessEpoch 26.159 ms/op 35.294 ms/op 0.74
mainnet_e81889 - altair processJustificationAndFinalization 8.4600 us/op 6.2300 us/op 1.36
mainnet_e81889 - altair processInactivityUpdates 8.9590 ms/op 3.6783 ms/op 2.44
mainnet_e81889 - altair processRewardsAndPenalties 23.475 ms/op 18.503 ms/op 1.27
mainnet_e81889 - altair processRegistryUpdates 639.00 ns/op 543.00 ns/op 1.18
mainnet_e81889 - altair processSlashings 188.00 ns/op 131.00 ns/op 1.44
mainnet_e81889 - altair processEth1DataReset 237.00 ns/op 132.00 ns/op 1.80
mainnet_e81889 - altair processEffectiveBalanceUpdates 3.4147 ms/op 5.7760 ms/op 0.59
mainnet_e81889 - altair processSlashingsReset 759.00 ns/op 682.00 ns/op 1.11
mainnet_e81889 - altair processRandaoMixesReset 1.6180 us/op 1.2990 us/op 1.25
mainnet_e81889 - altair processHistoricalRootsUpdate 197.00 ns/op 130.00 ns/op 1.52
mainnet_e81889 - altair processParticipationFlagUpdates 586.00 ns/op 441.00 ns/op 1.33
mainnet_e81889 - altair processSyncCommitteeUpdates 124.00 ns/op 103.00 ns/op 1.20
mainnet_e81889 - altair afterProcessEpoch 42.059 ms/op 40.595 ms/op 1.04
capella processEpoch - mainnet_e217614 790.23 ms/op 1.0442 s/op 0.76
mainnet_e217614 - capella beforeProcessEpoch 69.224 ms/op 63.525 ms/op 1.09
mainnet_e217614 - capella processJustificationAndFinalization 6.6710 us/op 7.5680 us/op 0.88
mainnet_e217614 - capella processInactivityUpdates 15.880 ms/op 11.111 ms/op 1.43
mainnet_e217614 - capella processRewardsAndPenalties 87.769 ms/op 93.640 ms/op 0.94
mainnet_e217614 - capella processRegistryUpdates 4.4270 us/op 4.5510 us/op 0.97
mainnet_e217614 - capella processSlashings 147.00 ns/op 150.00 ns/op 0.98
mainnet_e217614 - capella processEth1DataReset 146.00 ns/op 143.00 ns/op 1.02
mainnet_e217614 - capella processEffectiveBalanceUpdates 18.304 ms/op 16.977 ms/op 1.08
mainnet_e217614 - capella processSlashingsReset 685.00 ns/op 697.00 ns/op 0.98
mainnet_e217614 - capella processRandaoMixesReset 1.4220 us/op 1.5060 us/op 0.94
mainnet_e217614 - capella processHistoricalRootsUpdate 190.00 ns/op 143.00 ns/op 1.33
mainnet_e217614 - capella processParticipationFlagUpdates 464.00 ns/op 472.00 ns/op 0.98
mainnet_e217614 - capella afterProcessEpoch 105.83 ms/op 109.87 ms/op 0.96
phase0 processEpoch - mainnet_e58758 324.11 ms/op 360.94 ms/op 0.90
mainnet_e58758 - phase0 beforeProcessEpoch 78.582 ms/op 70.505 ms/op 1.11
mainnet_e58758 - phase0 processJustificationAndFinalization 6.5260 us/op 7.0010 us/op 0.93
mainnet_e58758 - phase0 processRewardsAndPenalties 16.350 ms/op 16.259 ms/op 1.01
mainnet_e58758 - phase0 processRegistryUpdates 2.1860 us/op 2.2840 us/op 0.96
mainnet_e58758 - phase0 processSlashings 143.00 ns/op 144.00 ns/op 0.99
mainnet_e58758 - phase0 processEth1DataReset 141.00 ns/op 137.00 ns/op 1.03
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.9223 ms/op 807.89 us/op 2.38
mainnet_e58758 - phase0 processSlashingsReset 880.00 ns/op 1.1710 us/op 0.75
mainnet_e58758 - phase0 processRandaoMixesReset 1.3080 us/op 1.3660 us/op 0.96
mainnet_e58758 - phase0 processHistoricalRootsUpdate 145.00 ns/op 143.00 ns/op 1.01
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.1760 us/op 1.2530 us/op 0.94
mainnet_e58758 - phase0 afterProcessEpoch 32.505 ms/op 33.091 ms/op 0.98
phase0 processEffectiveBalanceUpdates - 250000 normalcase 977.29 us/op 1.0267 ms/op 0.95
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 1.5626 ms/op 1.8990 ms/op 0.82
altair processInactivityUpdates - 250000 normalcase 12.180 ms/op 12.016 ms/op 1.01
altair processInactivityUpdates - 250000 worstcase 12.104 ms/op 10.767 ms/op 1.12
phase0 processRegistryUpdates - 250000 normalcase 2.4220 us/op 2.4260 us/op 1.00
phase0 processRegistryUpdates - 250000 badcase_full_deposits 140.30 us/op 147.42 us/op 0.95
phase0 processRegistryUpdates - 250000 worstcase 0.5 65.618 ms/op 65.062 ms/op 1.01
altair processRewardsAndPenalties - 250000 normalcase 16.241 ms/op 15.520 ms/op 1.05
altair processRewardsAndPenalties - 250000 worstcase 15.932 ms/op 16.077 ms/op 0.99
phase0 getAttestationDeltas - 250000 normalcase 5.3555 ms/op 5.3587 ms/op 1.00
phase0 getAttestationDeltas - 250000 worstcase 5.3543 ms/op 5.3969 ms/op 0.99
phase0 processSlashings - 250000 worstcase 58.110 us/op 59.978 us/op 0.97
altair processSyncCommitteeUpdates - 250000 11.227 ms/op 10.285 ms/op 1.09
BeaconState.hashTreeRoot - No change 184.00 ns/op 179.00 ns/op 1.03
BeaconState.hashTreeRoot - 1 full validator 73.488 us/op 70.427 us/op 1.04
BeaconState.hashTreeRoot - 32 full validator 863.23 us/op 952.95 us/op 0.91
BeaconState.hashTreeRoot - 512 full validator 7.9455 ms/op 6.8544 ms/op 1.16
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 102.08 us/op 105.07 us/op 0.97
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.4856 ms/op 1.5520 ms/op 0.96
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 18.744 ms/op 14.617 ms/op 1.28
BeaconState.hashTreeRoot - 1 balances 83.338 us/op 84.293 us/op 0.99
BeaconState.hashTreeRoot - 32 balances 718.08 us/op 929.70 us/op 0.77
BeaconState.hashTreeRoot - 512 balances 6.2754 ms/op 5.2085 ms/op 1.20
BeaconState.hashTreeRoot - 250000 balances 122.06 ms/op 133.65 ms/op 0.91
aggregationBits - 2048 els - zipIndexesInBitList 19.575 us/op 19.890 us/op 0.98
regular array get 100000 times 22.846 us/op 23.429 us/op 0.98
wrappedArray get 100000 times 22.848 us/op 23.468 us/op 0.97
arrayWithProxy get 100000 times 9.9603 ms/op 10.220 ms/op 0.97
ssz.Root.equals 21.336 ns/op 21.647 ns/op 0.99
byteArrayEquals 21.106 ns/op 21.364 ns/op 0.99
Buffer.compare 8.7400 ns/op 9.0190 ns/op 0.97
processSlot - 1 slots 9.2200 us/op 8.5130 us/op 1.08
processSlot - 32 slots 2.1026 ms/op 2.3101 ms/op 0.91
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 4.4625 ms/op 5.8329 ms/op 0.77
getCommitteeAssignments - req 1 vs - 250000 vc 1.6347 ms/op 1.6856 ms/op 0.97
getCommitteeAssignments - req 100 vs - 250000 vc 3.3634 ms/op 3.4580 ms/op 0.97
getCommitteeAssignments - req 1000 vs - 250000 vc 3.6043 ms/op 3.6891 ms/op 0.98
findModifiedValidators - 10000 modified validators 762.85 ms/op 627.91 ms/op 1.21
findModifiedValidators - 1000 modified validators 498.29 ms/op 500.66 ms/op 1.00
findModifiedValidators - 100 modified validators 355.35 ms/op 290.59 ms/op 1.22
findModifiedValidators - 10 modified validators 169.43 ms/op 201.17 ms/op 0.84
findModifiedValidators - 1 modified validators 163.82 ms/op 168.26 ms/op 0.97
findModifiedValidators - no difference 168.59 ms/op 180.47 ms/op 0.93
migrate state 1500000 validators, 3400 modified, 2000 new 2.9246 s/op 3.7807 s/op 0.77
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 3.7100 ns/op 3.7500 ns/op 0.99
state getBlockRootAtSlot - 250000 vs - 7PWei 289.61 ns/op 436.58 ns/op 0.66
computeProposerIndex 100000 validators 1.2957 ms/op 1.3714 ms/op 0.94
getNextSyncCommitteeIndices 1000 validators 2.7880 ms/op 2.9380 ms/op 0.95
getNextSyncCommitteeIndices 10000 validators 24.477 ms/op 26.005 ms/op 0.94
getNextSyncCommitteeIndices 100000 validators 81.649 ms/op 91.610 ms/op 0.89
computeProposers - vc 250000 536.85 us/op 561.42 us/op 0.96
computeEpochShuffling - vc 250000 39.895 ms/op 41.064 ms/op 0.97
getNextSyncCommittee - vc 250000 9.1532 ms/op 9.6636 ms/op 0.95
nodejs block root to RootHex using toHex 93.332 ns/op 105.13 ns/op 0.89
nodejs block root to RootHex using toRootHex 59.940 ns/op 64.855 ns/op 0.92
nodejs fromHex(blob) 727.57 us/op 913.70 us/op 0.80
nodejs fromHexInto(blob) 608.97 us/op 611.69 us/op 1.00
nodejs block root to RootHex using the deprecated toHexString 432.88 ns/op 436.51 ns/op 0.99
nodejs byteArrayEquals 32 bytes (block root) 25.088 ns/op 24.837 ns/op 1.01
nodejs byteArrayEquals 48 bytes (pubkey) 36.497 ns/op 36.112 ns/op 1.01
nodejs byteArrayEquals 96 bytes (signature) 33.481 ns/op 32.865 ns/op 1.02
nodejs byteArrayEquals 1024 bytes 40.624 ns/op 40.557 ns/op 1.00
nodejs byteArrayEquals 131072 bytes (blob) 1.7266 us/op 1.7380 us/op 0.99
browser block root to RootHex using toHex 140.91 ns/op 140.39 ns/op 1.00
browser block root to RootHex using toRootHex 128.52 ns/op 127.21 ns/op 1.01
browser fromHex(blob) 1.5084 ms/op 1.7763 ms/op 0.85
browser fromHexInto(blob) 615.80 us/op 678.93 us/op 0.91
browser block root to RootHex using the deprecated toHexString 316.06 ns/op 345.52 ns/op 0.91
browser byteArrayEquals 32 bytes (block root) 27.338 ns/op 28.226 ns/op 0.97
browser byteArrayEquals 48 bytes (pubkey) 38.417 ns/op 39.730 ns/op 0.97
browser byteArrayEquals 96 bytes (signature) 74.074 ns/op 75.260 ns/op 0.98
browser byteArrayEquals 1024 bytes 735.94 ns/op 768.63 ns/op 0.96
browser byteArrayEquals 131072 bytes (blob) 93.180 us/op 96.883 us/op 0.96

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

Comment thread packages/state-transition/src/util/preVerifyBuilderDeposits.ts
Comment thread packages/state-transition/src/block/processDeposit.ts Outdated
try {
batchValid =
signatureSets.length >= 2
? verifyMultipleAggregateSignatures(signatureSets, true, true)

@ensi321 ensi321 Aug 4, 2026

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.

I wonder if there can be attackers that submit a bunch of deposits with invalid signature that force us to fall back to verify one by one which makes lodestar hard to keep up.

They only need 1 bad deposit per batch (32 deposits) to nullify all the optimizations here

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.

this is a valid concern but also the attacker would burn the eth, so it's basically a trade-off here, we want the batch sizes to be large enough to get benefits from batching but not too large so an invalid signature can't waste too much time/compute

* keyed by the value object. Capped at `maxBuilderDeposits` new verifications per call; a later tick
* resumes past the cached deposits. Caller guarantees the fork-epoch + non-epoch-transition gates.
*/
export function preVerifyBuilderDepositsPreGloas(

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.

Can we time-box this? If we run out of time, we should just keep the result on batches that we have verified so far and return, instead of letting this run unbound

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.

For example, before calling verifyDepositSignatures for a chunk, check how much time left. If no time remaining, give up.

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.

sounds like a good idea too me if it doesn't add too much complexity

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 is a good idea, will also resolve the invalid signatures concern above

nflaig
nflaig previously approved these changes Aug 5, 2026

@nflaig nflaig left a comment

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.

Looks pretty good to me, ideally we want this on devnet-8 before the fork happens

@nflaig
nflaig requested review from ensi321 and wemeetagain August 6, 2026 10:23
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