Skip to content

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

Merged
nflaig merged 12 commits into
unstablefrom
te/gloas_onboard_builders_at_fork
Aug 7, 2026
Merged

feat: cache builder deposit signatures for gloas fork transition#9727
nflaig merged 12 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: b3be023 Previous: 1f20df4 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 1.0023 ms/op 899.30 us/op 1.11
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 41.802 us/op 38.291 us/op 1.09
BLS verify - blst 711.13 us/op 705.88 us/op 1.01
BLS verifyMultipleSignatures 3 - blst 1.3738 ms/op 1.3815 ms/op 0.99
BLS verifyMultipleSignatures 8 - blst 2.1982 ms/op 2.2002 ms/op 1.00
BLS verifyMultipleSignatures 32 - blst 6.8724 ms/op 6.9778 ms/op 0.98
BLS verifyMultipleSignatures 64 - blst 13.247 ms/op 13.765 ms/op 0.96
BLS verifyMultipleSignatures 128 - blst 25.856 ms/op 26.331 ms/op 0.98
BLS deserializing 10000 signatures 642.86 ms/op 625.33 ms/op 1.03
BLS deserializing 100000 signatures 6.4257 s/op 6.2857 s/op 1.02
BLS verifyMultipleSignatures - same message - 3 - blst 820.18 us/op 779.65 us/op 1.05
BLS verifyMultipleSignatures - same message - 8 - blst 853.22 us/op 938.83 us/op 0.91
BLS verifyMultipleSignatures - same message - 32 - blst 1.5468 ms/op 1.5585 ms/op 0.99
BLS verifyMultipleSignatures - same message - 64 - blst 2.4704 ms/op 2.3305 ms/op 1.06
BLS verifyMultipleSignatures - same message - 128 - blst 4.0894 ms/op 4.0163 ms/op 1.02
BLS aggregatePubkeys 32 - blst 17.761 us/op 17.550 us/op 1.01
BLS aggregatePubkeys 128 - blst 63.465 us/op 62.711 us/op 1.01
getSlashingsAndExits - default max 49.658 us/op 52.394 us/op 0.95
getSlashingsAndExits - 2k 418.81 us/op 361.55 us/op 1.16
proposeBlockBody type=full, size=empty 630.49 us/op 1.5342 ms/op 0.41
isKnown best case - 1 super set check 166.00 ns/op 162.00 ns/op 1.02
isKnown normal case - 2 super set checks 165.00 ns/op 165.00 ns/op 1.00
isKnown worse case - 16 super set checks 163.00 ns/op 165.00 ns/op 0.99
validate api signedAggregateAndProof - struct 1.5398 ms/op 1.5785 ms/op 0.98
validate gossip signedAggregateAndProof - struct 1.5216 ms/op 1.5751 ms/op 0.97
batch validate gossip attestation - vc 640000 - chunk 32 111.97 us/op 109.69 us/op 1.02
batch validate gossip attestation - vc 640000 - chunk 64 97.069 us/op 97.203 us/op 1.00
batch validate gossip attestation - vc 640000 - chunk 128 91.504 us/op 92.045 us/op 0.99
batch validate gossip attestation - vc 640000 - chunk 256 88.332 us/op 89.141 us/op 0.99
bytes32 toHexString 309.00 ns/op 284.00 ns/op 1.09
bytes32 Buffer.toString(hex) 169.00 ns/op 183.00 ns/op 0.92
bytes32 Buffer.toString(hex) from Uint8Array 235.00 ns/op 242.00 ns/op 0.97
bytes32 Buffer.toString(hex) + 0x 170.00 ns/op 182.00 ns/op 0.93
Return object 10000 times 0.21630 ns/op 0.21560 ns/op 1.00
Throw Error 10000 times 3.4274 us/op 3.3392 us/op 1.03
toHex 106.92 ns/op 94.165 ns/op 1.14
Buffer.from 90.825 ns/op 85.101 ns/op 1.07
shared Buffer 68.052 ns/op 58.542 ns/op 1.16
fastMsgIdFn sha256 / 200 bytes 1.5170 us/op 1.4880 us/op 1.02
fastMsgIdFn h32 xxhash / 200 bytes 154.00 ns/op 155.00 ns/op 0.99
fastMsgIdFn h64 xxhash / 200 bytes 194.00 ns/op 202.00 ns/op 0.96
fastMsgIdFn sha256 / 1000 bytes 4.8180 us/op 4.7110 us/op 1.02
fastMsgIdFn h32 xxhash / 1000 bytes 245.00 ns/op 247.00 ns/op 0.99
fastMsgIdFn h64 xxhash / 1000 bytes 253.00 ns/op 255.00 ns/op 0.99
fastMsgIdFn sha256 / 10000 bytes 42.922 us/op 41.828 us/op 1.03
fastMsgIdFn h32 xxhash / 10000 bytes 1.2970 us/op 1.2910 us/op 1.00
fastMsgIdFn h64 xxhash / 10000 bytes 829.00 ns/op 838.00 ns/op 0.99
send data - 1000 256B messages 4.6284 ms/op 4.3443 ms/op 1.07
send data - 1000 512B messages 5.3956 ms/op 5.8342 ms/op 0.92
send data - 1000 1024B messages 5.9405 ms/op 5.8566 ms/op 1.01
send data - 1000 1200B messages 13.652 ms/op 8.3714 ms/op 1.63
send data - 1000 2048B messages 15.010 ms/op 9.9882 ms/op 1.50
send data - 1000 4096B messages 140.76 ms/op 63.397 ms/op 2.22
send data - 1000 16384B messages 424.51 ms/op 318.63 ms/op 1.33
send data - 1000 65536B messages 1.8775 s/op 1.9120 s/op 0.98
enrSubnets - fastDeserialize 64 bits 849.00 ns/op 802.00 ns/op 1.06
enrSubnets - ssz BitVector 64 bits 269.00 ns/op 274.00 ns/op 0.98
enrSubnets - fastDeserialize 4 bits 107.00 ns/op 103.00 ns/op 1.04
enrSubnets - ssz BitVector 4 bits 271.00 ns/op 280.00 ns/op 0.97
prioritizePeers score -10:0 att 32-0.1 sync 2-0 210.53 us/op 208.84 us/op 1.01
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 239.95 us/op 236.19 us/op 1.02
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 352.55 us/op 328.50 us/op 1.07
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 605.50 us/op 584.33 us/op 1.04
prioritizePeers score 0:0 att 64-1 sync 4-1 710.34 us/op 711.52 us/op 1.00
array of 16000 items push then shift 1.3017 us/op 1.3233 us/op 0.98
LinkedList of 16000 items push then shift 7.7880 ns/op 7.0450 ns/op 1.11
array of 16000 items push then pop 70.239 ns/op 67.265 ns/op 1.04
LinkedList of 16000 items push then pop 6.2740 ns/op 6.1530 ns/op 1.02
array of 24000 items push then shift 1.9330 us/op 1.9557 us/op 0.99
LinkedList of 24000 items push then shift 7.2840 ns/op 6.6310 ns/op 1.10
array of 24000 items push then pop 100.88 ns/op 94.264 ns/op 1.07
LinkedList of 24000 items push then pop 6.2860 ns/op 6.1390 ns/op 1.02
intersect bitArray bitLen 8 3.9690 ns/op 3.9520 ns/op 1.00
intersect array and set length 8 30.291 ns/op 30.301 ns/op 1.00
intersect bitArray bitLen 128 23.790 ns/op 23.954 ns/op 0.99
intersect array and set length 128 510.33 ns/op 512.61 ns/op 1.00
bitArray.getTrueBitIndexes() bitLen 128 990.00 ns/op 935.00 ns/op 1.06
bitArray.getTrueBitIndexes() bitLen 248 1.7520 us/op 1.7000 us/op 1.03
bitArray.getTrueBitIndexes() bitLen 512 3.7230 us/op 3.6690 us/op 1.01
Full columns - reconstruct all 6 blobs 193.94 us/op 133.50 us/op 1.45
Full columns - reconstruct half of the blobs out of 6 72.745 us/op 74.963 us/op 0.97
Full columns - reconstruct single blob out of 6 36.143 us/op 32.161 us/op 1.12
Half columns - reconstruct all 6 blobs 405.94 ms/op 403.86 ms/op 1.01
Half columns - reconstruct half of the blobs out of 6 203.55 ms/op 201.81 ms/op 1.01
Half columns - reconstruct single blob out of 6 71.721 ms/op 73.495 ms/op 0.98
Set add up to 64 items then delete first 1.6777 us/op 2.0385 us/op 0.82
OrderedSet add up to 64 items then delete first 2.5498 us/op 3.2571 us/op 0.78
Set add up to 64 items then delete last 1.8903 us/op 2.0310 us/op 0.93
OrderedSet add up to 64 items then delete last 2.8268 us/op 3.1924 us/op 0.89
Set add up to 64 items then delete middle 1.8878 us/op 2.0292 us/op 0.93
OrderedSet add up to 64 items then delete middle 4.3372 us/op 4.6077 us/op 0.94
Set add up to 128 items then delete first 3.7959 us/op 4.0973 us/op 0.93
OrderedSet add up to 128 items then delete first 5.8645 us/op 6.2692 us/op 0.94
Set add up to 128 items then delete last 3.5966 us/op 3.7832 us/op 0.95
OrderedSet add up to 128 items then delete last 5.4530 us/op 5.6631 us/op 0.96
Set add up to 128 items then delete middle 3.6251 us/op 3.7231 us/op 0.97
OrderedSet add up to 128 items then delete middle 11.940 us/op 11.394 us/op 1.05
Set add up to 256 items then delete first 7.5551 us/op 7.8619 us/op 0.96
OrderedSet add up to 256 items then delete first 12.750 us/op 12.182 us/op 1.05
Set add up to 256 items then delete last 7.5558 us/op 7.5053 us/op 1.01
OrderedSet add up to 256 items then delete last 11.816 us/op 11.834 us/op 1.00
Set add up to 256 items then delete middle 7.2481 us/op 7.6830 us/op 0.94
OrderedSet add up to 256 items then delete middle 35.489 us/op 34.636 us/op 1.02
runFastConfirmationRules vc:100000 bc:96 eq:0 4.8063 ms/op 4.7123 ms/op 1.02
runFastConfirmationRules vc:600000 bc:96 eq:0 36.960 ms/op 34.687 ms/op 1.07
runFastConfirmationRules vc:1000000 bc:96 eq:0 62.374 ms/op 59.690 ms/op 1.04
runFastConfirmationRules vc:600000 bc:320 eq:0 37.623 ms/op 37.154 ms/op 1.01
runFastConfirmationRules vc:100000 bc:96 eq:1000 1.1896 s/op 1.1295 s/op 1.05
pass gossip attestations to forkchoice per slot 2.6840 ms/op 2.5728 ms/op 1.04
forkChoice updateHead vc 100000 bc 64 eq 0 434.51 us/op 446.38 us/op 0.97
forkChoice updateHead vc 600000 bc 64 eq 0 2.5922 ms/op 2.6414 ms/op 0.98
forkChoice updateHead vc 1000000 bc 64 eq 0 4.2244 ms/op 4.4112 ms/op 0.96
forkChoice updateHead vc 600000 bc 320 eq 0 2.5681 ms/op 2.6614 ms/op 0.96
forkChoice updateHead vc 600000 bc 1200 eq 0 2.7396 ms/op 2.7000 ms/op 1.01
forkChoice updateHead vc 600000 bc 7200 eq 0 3.6712 ms/op 3.1076 ms/op 1.18
forkChoice updateHead vc 600000 bc 64 eq 1000 2.5383 ms/op 2.8271 ms/op 0.90
forkChoice updateHead vc 600000 bc 64 eq 10000 2.6738 ms/op 2.7830 ms/op 0.96
forkChoice updateHead vc 600000 bc 64 eq 300000 6.9511 ms/op 6.9939 ms/op 0.99
computeDeltas 1400000 validators 0% inactive 12.630 ms/op 13.188 ms/op 0.96
computeDeltas 1400000 validators 10% inactive 12.108 ms/op 12.832 ms/op 0.94
computeDeltas 1400000 validators 20% inactive 11.313 ms/op 11.843 ms/op 0.96
computeDeltas 1400000 validators 50% inactive 9.5119 ms/op 9.3946 ms/op 1.01
computeDeltas 2100000 validators 0% inactive 18.810 ms/op 20.227 ms/op 0.93
computeDeltas 2100000 validators 10% inactive 18.016 ms/op 19.426 ms/op 0.93
computeDeltas 2100000 validators 20% inactive 17.096 ms/op 18.182 ms/op 0.94
computeDeltas 2100000 validators 50% inactive 11.405 ms/op 14.508 ms/op 0.79
altair processAttestation - 250000 vs - 7PWei normalcase 2.1500 ms/op 1.7693 ms/op 1.22
altair processAttestation - 250000 vs - 7PWei worstcase 2.8936 ms/op 2.4838 ms/op 1.16
altair processAttestation - setStatus - 1/6 committees join 109.71 us/op 107.81 us/op 1.02
altair processAttestation - setStatus - 1/3 committees join 205.38 us/op 210.85 us/op 0.97
altair processAttestation - setStatus - 1/2 committees join 294.92 us/op 293.58 us/op 1.00
altair processAttestation - setStatus - 2/3 committees join 377.08 us/op 381.84 us/op 0.99
altair processAttestation - setStatus - 4/5 committees join 528.73 us/op 523.56 us/op 1.01
altair processAttestation - setStatus - 100% committees join 622.87 us/op 617.13 us/op 1.01
altair processBlock - 250000 vs - 7PWei normalcase 4.9186 ms/op 2.8599 ms/op 1.72
altair processBlock - 250000 vs - 7PWei normalcase hashState 16.895 ms/op 17.625 ms/op 0.96
altair processBlock - 250000 vs - 7PWei worstcase 23.564 ms/op 20.202 ms/op 1.17
altair processBlock - 250000 vs - 7PWei worstcase hashState 43.254 ms/op 41.069 ms/op 1.05
phase0 processBlock - 250000 vs - 7PWei normalcase 1.5401 ms/op 1.3809 ms/op 1.12
phase0 processBlock - 250000 vs - 7PWei worstcase 18.236 ms/op 17.586 ms/op 1.04
altair processEth1Data - 250000 vs - 7PWei normalcase 298.68 us/op 311.85 us/op 0.96
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:16 3.3650 us/op 3.8250 us/op 0.88
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:220 21.528 us/op 23.521 us/op 0.92
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:43 7.0390 us/op 6.1790 us/op 1.14
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:19 4.2300 us/op 3.5300 us/op 1.20
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1021 96.168 us/op 102.10 us/op 0.94
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11778 1.4356 ms/op 1.3950 ms/op 1.03
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.9074 ms/op 1.8678 ms/op 1.02
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.8789 ms/op 1.8377 ms/op 1.02
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 3.7810 ms/op 3.7107 ms/op 1.02
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.1461 ms/op 2.0900 ms/op 1.03
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.2145 ms/op 3.9978 ms/op 1.05
Tree 40 250000 create 364.86 ms/op 357.08 ms/op 1.02
Tree 40 250000 get(125000) 101.33 ns/op 106.15 ns/op 0.95
Tree 40 250000 set(125000) 1.0690 us/op 1.1657 us/op 0.92
Tree 40 250000 toArray() 16.901 ms/op 11.315 ms/op 1.49
Tree 40 250000 iterate all - toArray() + loop 18.977 ms/op 11.266 ms/op 1.68
Tree 40 250000 iterate all - get(i) 43.373 ms/op 35.128 ms/op 1.23
Array 250000 create 2.3444 ms/op 2.0191 ms/op 1.16
Array 250000 clone - spread 723.65 us/op 636.07 us/op 1.14
Array 250000 get(125000) 0.30300 ns/op 0.29500 ns/op 1.03
Array 250000 set(125000) 0.30500 ns/op 0.30200 ns/op 1.01
Array 250000 iterate all - loop 58.345 us/op 57.309 us/op 1.02
phase0 afterProcessEpoch - 250000 vs - 7PWei 54.131 ms/op 48.669 ms/op 1.11
Array.fill - length 1000000 2.3094 ms/op 2.0285 ms/op 1.14
Array push - length 1000000 9.2897 ms/op 8.3333 ms/op 1.11
Array.get 0.21384 ns/op 0.19979 ns/op 1.07
Uint8Array.get 0.25271 ns/op 0.24889 ns/op 1.02
phase0 beforeProcessEpoch - 250000 vs - 7PWei 14.708 ms/op 12.537 ms/op 1.17
altair processEpoch - mainnet_e81889 286.50 ms/op 303.59 ms/op 0.94
mainnet_e81889 - altair beforeProcessEpoch 38.736 ms/op 36.248 ms/op 1.07
mainnet_e81889 - altair processJustificationAndFinalization 6.4550 us/op 6.3670 us/op 1.01
mainnet_e81889 - altair processInactivityUpdates 3.7402 ms/op 3.3947 ms/op 1.10
mainnet_e81889 - altair processRewardsAndPenalties 20.003 ms/op 17.912 ms/op 1.12
mainnet_e81889 - altair processRegistryUpdates 567.00 ns/op 540.00 ns/op 1.05
mainnet_e81889 - altair processSlashings 141.00 ns/op 138.00 ns/op 1.02
mainnet_e81889 - altair processEth1DataReset 134.00 ns/op 134.00 ns/op 1.00
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.6628 ms/op 1.7442 ms/op 0.95
mainnet_e81889 - altair processSlashingsReset 1.9160 us/op 704.00 ns/op 2.72
mainnet_e81889 - altair processRandaoMixesReset 5.0120 us/op 1.2790 us/op 3.92
mainnet_e81889 - altair processHistoricalRootsUpdate 695.00 ns/op 146.00 ns/op 4.76
mainnet_e81889 - altair processParticipationFlagUpdates 455.00 ns/op 441.00 ns/op 1.03
mainnet_e81889 - altair processSyncCommitteeUpdates 112.00 ns/op 120.00 ns/op 0.93
mainnet_e81889 - altair afterProcessEpoch 44.155 ms/op 40.809 ms/op 1.08
capella processEpoch - mainnet_e217614 835.58 ms/op 953.00 ms/op 0.88
mainnet_e217614 - capella beforeProcessEpoch 60.633 ms/op 62.683 ms/op 0.97
mainnet_e217614 - capella processJustificationAndFinalization 6.3300 us/op 6.9530 us/op 0.91
mainnet_e217614 - capella processInactivityUpdates 16.022 ms/op 12.776 ms/op 1.25
mainnet_e217614 - capella processRewardsAndPenalties 102.73 ms/op 100.87 ms/op 1.02
mainnet_e217614 - capella processRegistryUpdates 4.6280 us/op 4.6460 us/op 1.00
mainnet_e217614 - capella processSlashings 138.00 ns/op 147.00 ns/op 0.94
mainnet_e217614 - capella processEth1DataReset 137.00 ns/op 145.00 ns/op 0.94
mainnet_e217614 - capella processEffectiveBalanceUpdates 13.528 ms/op 5.2193 ms/op 2.59
mainnet_e217614 - capella processSlashingsReset 715.00 ns/op 691.00 ns/op 1.03
mainnet_e217614 - capella processRandaoMixesReset 1.3500 us/op 1.3540 us/op 1.00
mainnet_e217614 - capella processHistoricalRootsUpdate 136.00 ns/op 145.00 ns/op 0.94
mainnet_e217614 - capella processParticipationFlagUpdates 451.00 ns/op 451.00 ns/op 1.00
mainnet_e217614 - capella afterProcessEpoch 110.90 ms/op 109.50 ms/op 1.01
phase0 processEpoch - mainnet_e58758 323.92 ms/op 304.19 ms/op 1.06
mainnet_e58758 - phase0 beforeProcessEpoch 66.152 ms/op 56.466 ms/op 1.17
mainnet_e58758 - phase0 processJustificationAndFinalization 6.3880 us/op 6.1140 us/op 1.04
mainnet_e58758 - phase0 processRewardsAndPenalties 16.073 ms/op 17.350 ms/op 0.93
mainnet_e58758 - phase0 processRegistryUpdates 2.3490 us/op 2.1820 us/op 1.08
mainnet_e58758 - phase0 processSlashings 304.00 ns/op 252.00 ns/op 1.21
mainnet_e58758 - phase0 processEth1DataReset 136.00 ns/op 143.00 ns/op 0.95
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 894.69 us/op 883.40 us/op 1.01
mainnet_e58758 - phase0 processSlashingsReset 966.00 ns/op 820.00 ns/op 1.18
mainnet_e58758 - phase0 processRandaoMixesReset 1.3310 us/op 1.3370 us/op 1.00
mainnet_e58758 - phase0 processHistoricalRootsUpdate 137.00 ns/op 148.00 ns/op 0.93
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.2120 us/op 1.2010 us/op 1.01
mainnet_e58758 - phase0 afterProcessEpoch 33.202 ms/op 33.785 ms/op 0.98
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.0254 ms/op 1.2793 ms/op 0.80
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 1.7057 ms/op 1.5490 ms/op 1.10
altair processInactivityUpdates - 250000 normalcase 12.162 ms/op 10.217 ms/op 1.19
altair processInactivityUpdates - 250000 worstcase 12.493 ms/op 10.588 ms/op 1.18
phase0 processRegistryUpdates - 250000 normalcase 2.3240 us/op 2.4540 us/op 0.95
phase0 processRegistryUpdates - 250000 badcase_full_deposits 150.00 us/op 153.29 us/op 0.98
phase0 processRegistryUpdates - 250000 worstcase 0.5 71.614 ms/op 50.512 ms/op 1.42
altair processRewardsAndPenalties - 250000 normalcase 16.273 ms/op 14.025 ms/op 1.16
altair processRewardsAndPenalties - 250000 worstcase 14.404 ms/op 13.688 ms/op 1.05
phase0 getAttestationDeltas - 250000 normalcase 5.5004 ms/op 5.3909 ms/op 1.02
phase0 getAttestationDeltas - 250000 worstcase 5.5052 ms/op 5.4223 ms/op 1.02
phase0 processSlashings - 250000 worstcase 64.068 us/op 61.300 us/op 1.05
altair processSyncCommitteeUpdates - 250000 10.185 ms/op 10.137 ms/op 1.00
BeaconState.hashTreeRoot - No change 172.00 ns/op 177.00 ns/op 0.97
BeaconState.hashTreeRoot - 1 full validator 78.551 us/op 87.853 us/op 0.89
BeaconState.hashTreeRoot - 32 full validator 847.36 us/op 946.56 us/op 0.90
BeaconState.hashTreeRoot - 512 full validator 7.9768 ms/op 6.8029 ms/op 1.17
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 102.92 us/op 77.640 us/op 1.33
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.4949 ms/op 2.3545 ms/op 0.63
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 16.023 ms/op 13.866 ms/op 1.16
BeaconState.hashTreeRoot - 1 balances 82.993 us/op 83.609 us/op 0.99
BeaconState.hashTreeRoot - 32 balances 753.43 us/op 577.78 us/op 1.30
BeaconState.hashTreeRoot - 512 balances 5.8418 ms/op 5.1409 ms/op 1.14
BeaconState.hashTreeRoot - 250000 balances 199.36 ms/op 167.63 ms/op 1.19
aggregationBits - 2048 els - zipIndexesInBitList 21.269 us/op 19.898 us/op 1.07
regular array get 100000 times 22.925 us/op 23.089 us/op 0.99
wrappedArray get 100000 times 23.014 us/op 23.088 us/op 1.00
arrayWithProxy get 100000 times 10.614 ms/op 13.745 ms/op 0.77
ssz.Root.equals 21.505 ns/op 21.791 ns/op 0.99
byteArrayEquals 21.293 ns/op 21.613 ns/op 0.99
Buffer.compare 9.4830 ns/op 9.0650 ns/op 1.05
processSlot - 1 slots 9.9090 us/op 9.8280 us/op 1.01
processSlot - 32 slots 2.0706 ms/op 2.3218 ms/op 0.89
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 4.2999 ms/op 4.1915 ms/op 1.03
getCommitteeAssignments - req 1 vs - 250000 vc 1.6831 ms/op 1.5897 ms/op 1.06
getCommitteeAssignments - req 100 vs - 250000 vc 3.4414 ms/op 3.2718 ms/op 1.05
getCommitteeAssignments - req 1000 vs - 250000 vc 3.6855 ms/op 3.5245 ms/op 1.05
findModifiedValidators - 10000 modified validators 721.17 ms/op 684.03 ms/op 1.05
findModifiedValidators - 1000 modified validators 631.41 ms/op 431.15 ms/op 1.46
findModifiedValidators - 100 modified validators 364.81 ms/op 303.89 ms/op 1.20
findModifiedValidators - 10 modified validators 304.64 ms/op 147.65 ms/op 2.06
findModifiedValidators - 1 modified validators 198.40 ms/op 146.88 ms/op 1.35
findModifiedValidators - no difference 215.91 ms/op 163.33 ms/op 1.32
migrate state 1500000 validators, 3400 modified, 2000 new 3.3524 s/op 3.5822 s/op 0.94
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 3.7300 ns/op 3.5200 ns/op 1.06
state getBlockRootAtSlot - 250000 vs - 7PWei 402.28 ns/op 360.05 ns/op 1.12
computeProposerIndex 100000 validators 1.3658 ms/op 1.2894 ms/op 1.06
getNextSyncCommitteeIndices 1000 validators 2.9276 ms/op 2.7203 ms/op 1.08
getNextSyncCommitteeIndices 10000 validators 25.688 ms/op 24.151 ms/op 1.06
getNextSyncCommitteeIndices 100000 validators 89.603 ms/op 84.430 ms/op 1.06
computeProposers - vc 250000 574.70 us/op 533.40 us/op 1.08
computeEpochShuffling - vc 250000 40.048 ms/op 38.893 ms/op 1.03
getNextSyncCommittee - vc 250000 9.5515 ms/op 9.2066 ms/op 1.04
nodejs block root to RootHex using toHex 100.92 ns/op 96.879 ns/op 1.04
nodejs block root to RootHex using toRootHex 65.836 ns/op 63.156 ns/op 1.04
nodejs fromHex(blob) 886.19 us/op 819.39 us/op 1.08
nodejs fromHexInto(blob) 668.33 us/op 683.05 us/op 0.98
nodejs block root to RootHex using the deprecated toHexString 537.28 ns/op 473.39 ns/op 1.13
nodejs byteArrayEquals 32 bytes (block root) 26.016 ns/op 26.439 ns/op 0.98
nodejs byteArrayEquals 48 bytes (pubkey) 37.682 ns/op 37.965 ns/op 0.99
nodejs byteArrayEquals 96 bytes (signature) 39.098 ns/op 40.915 ns/op 0.96
nodejs byteArrayEquals 1024 bytes 43.599 ns/op 44.911 ns/op 0.97
nodejs byteArrayEquals 131072 bytes (blob) 1.7613 us/op 1.7782 us/op 0.99
browser block root to RootHex using toHex 146.31 ns/op 149.00 ns/op 0.98
browser block root to RootHex using toRootHex 131.59 ns/op 133.40 ns/op 0.99
browser fromHex(blob) 1.7954 ms/op 1.6581 ms/op 1.08
browser fromHexInto(blob) 645.81 us/op 675.09 us/op 0.96
browser block root to RootHex using the deprecated toHexString 372.43 ns/op 338.07 ns/op 1.10
browser byteArrayEquals 32 bytes (block root) 28.318 ns/op 28.231 ns/op 1.00
browser byteArrayEquals 48 bytes (pubkey) 39.818 ns/op 39.810 ns/op 1.00
browser byteArrayEquals 96 bytes (signature) 74.634 ns/op 74.682 ns/op 1.00
browser byteArrayEquals 1024 bytes 761.68 ns/op 758.52 ns/op 1.00
browser byteArrayEquals 131072 bytes (blob) 96.141 us/op 95.821 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".

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

@wemeetagain wemeetagain 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.

This looks really good

@nflaig nflaig added this to the v1.46.0 milestone Aug 7, 2026
@nflaig
nflaig merged commit 49b1d65 into unstable Aug 7, 2026
19 checks passed
@nflaig
nflaig deleted the te/gloas_onboard_builders_at_fork branch August 7, 2026 13:41
@wemeetagain

Copy link
Copy Markdown
Member

🎉 This PR is included in v1.46.0 🎉

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

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants