Skip to content

feat: implement non-eip-7688 changes in alpha.12 - #9606

Merged
ensi321 merged 13 commits into
unstablefrom
nc/alpha.12
Jul 24, 2026
Merged

feat: implement non-eip-7688 changes in alpha.12#9606
ensi321 merged 13 commits into
unstablefrom
nc/alpha.12

Conversation

@ensi321

@ensi321 ensi321 commented Jul 7, 2026

Copy link
Copy Markdown
Member

Depends on #9390

@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 updates the fast confirmation test suite to temporarily skip two failing Electra 'is_one_confirmed' test cases ('is_one_confirmed_fails_large_validator_slashed' and 'is_one_confirmed_fails_recently_activated_validator_voting_in_empty_slot') due to known issues that require a broader overhaul of the fast-confirmation rule (FCR). There are no review comments, so I have no feedback to provide.

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.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: 68a8a32 Previous: 8455854 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 881.58 us/op 859.34 us/op 1.03
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 40.269 us/op 42.453 us/op 0.95
BLS verify - blst 635.12 us/op 724.38 us/op 0.88
BLS verifyMultipleSignatures 3 - blst 1.3631 ms/op 1.2927 ms/op 1.05
BLS verifyMultipleSignatures 8 - blst 2.1717 ms/op 2.0911 ms/op 1.04
BLS verifyMultipleSignatures 32 - blst 6.7273 ms/op 6.5940 ms/op 1.02
BLS verifyMultipleSignatures 64 - blst 12.961 ms/op 12.961 ms/op 1.00
BLS verifyMultipleSignatures 128 - blst 25.227 ms/op 24.877 ms/op 1.01
BLS deserializing 10000 signatures 616.13 ms/op 632.04 ms/op 0.97
BLS deserializing 100000 signatures 6.1441 s/op 6.1589 s/op 1.00
BLS verifyMultipleSignatures - same message - 3 - blst 808.17 us/op 748.98 us/op 1.08
BLS verifyMultipleSignatures - same message - 8 - blst 953.77 us/op 793.83 us/op 1.20
BLS verifyMultipleSignatures - same message - 32 - blst 1.4963 ms/op 1.4812 ms/op 1.01
BLS verifyMultipleSignatures - same message - 64 - blst 2.3345 ms/op 2.2349 ms/op 1.04
BLS verifyMultipleSignatures - same message - 128 - blst 3.9083 ms/op 3.8758 ms/op 1.01
BLS aggregatePubkeys 32 - blst 17.234 us/op 16.948 us/op 1.02
BLS aggregatePubkeys 128 - blst 61.919 us/op 60.898 us/op 1.02
getSlashingsAndExits - default max 47.880 us/op 45.583 us/op 1.05
getSlashingsAndExits - 2k 345.30 us/op 350.93 us/op 0.98
proposeBlockBody type=full, size=empty 712.37 us/op 582.38 us/op 1.22
isKnown best case - 1 super set check 170.00 ns/op 166.00 ns/op 1.02
isKnown normal case - 2 super set checks 166.00 ns/op 165.00 ns/op 1.01
isKnown worse case - 16 super set checks 176.00 ns/op 167.00 ns/op 1.05
validate api signedAggregateAndProof - struct 1.5115 ms/op 1.4366 ms/op 1.05
validate gossip signedAggregateAndProof - struct 1.5045 ms/op 1.4371 ms/op 1.05
batch validate gossip attestation - vc 640000 - chunk 32 104.57 us/op 104.59 us/op 1.00
batch validate gossip attestation - vc 640000 - chunk 64 90.809 us/op 92.168 us/op 0.99
batch validate gossip attestation - vc 640000 - chunk 128 84.210 us/op 86.987 us/op 0.97
batch validate gossip attestation - vc 640000 - chunk 256 80.654 us/op 84.180 us/op 0.96
bytes32 toHexString 289.00 ns/op 271.00 ns/op 1.07
bytes32 Buffer.toString(hex) 162.00 ns/op 159.00 ns/op 1.02
bytes32 Buffer.toString(hex) from Uint8Array 226.00 ns/op 219.00 ns/op 1.03
bytes32 Buffer.toString(hex) + 0x 162.00 ns/op 158.00 ns/op 1.03
Return object 10000 times 0.20800 ns/op 0.20430 ns/op 1.02
Throw Error 10000 times 3.2949 us/op 3.3136 us/op 0.99
toHex 98.820 ns/op 95.211 ns/op 1.04
Buffer.from 88.591 ns/op 90.673 ns/op 0.98
shared Buffer 60.520 ns/op 56.442 ns/op 1.07
fastMsgIdFn sha256 / 200 bytes 1.4610 us/op 1.4290 us/op 1.02
fastMsgIdFn h32 xxhash / 200 bytes 155.00 ns/op 145.00 ns/op 1.07
fastMsgIdFn h64 xxhash / 200 bytes 196.00 ns/op 195.00 ns/op 1.01
fastMsgIdFn sha256 / 1000 bytes 4.6980 us/op 4.5360 us/op 1.04
fastMsgIdFn h32 xxhash / 1000 bytes 237.00 ns/op 226.00 ns/op 1.05
fastMsgIdFn h64 xxhash / 1000 bytes 246.00 ns/op 235.00 ns/op 1.05
fastMsgIdFn sha256 / 10000 bytes 42.073 us/op 40.111 us/op 1.05
fastMsgIdFn h32 xxhash / 10000 bytes 1.2530 us/op 1.2480 us/op 1.00
fastMsgIdFn h64 xxhash / 10000 bytes 806.00 ns/op 808.00 ns/op 1.00
send data - 1000 256B messages 4.2160 ms/op 4.0229 ms/op 1.05
send data - 1000 512B messages 4.9187 ms/op 5.5960 ms/op 0.88
send data - 1000 1024B messages 5.4572 ms/op 5.2650 ms/op 1.04
send data - 1000 1200B messages 6.0845 ms/op 6.1323 ms/op 0.99
send data - 1000 2048B messages 11.194 ms/op 15.624 ms/op 0.72
send data - 1000 4096B messages 67.997 ms/op 24.889 ms/op 2.73
send data - 1000 16384B messages 361.43 ms/op 173.56 ms/op 2.08
send data - 1000 65536B messages 1.3780 s/op 542.88 ms/op 2.54
enrSubnets - fastDeserialize 64 bits 751.00 ns/op 697.00 ns/op 1.08
enrSubnets - ssz BitVector 64 bits 259.00 ns/op 290.00 ns/op 0.89
enrSubnets - fastDeserialize 4 bits 103.00 ns/op 97.000 ns/op 1.06
enrSubnets - ssz BitVector 4 bits 271.00 ns/op 292.00 ns/op 0.93
prioritizePeers score -10:0 att 32-0.1 sync 2-0 205.58 us/op 191.51 us/op 1.07
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 232.17 us/op 218.36 us/op 1.06
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 339.51 us/op 317.96 us/op 1.07
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 597.55 us/op 564.64 us/op 1.06
prioritizePeers score 0:0 att 64-1 sync 4-1 698.78 us/op 659.04 us/op 1.06
array of 16000 items push then shift 1.3018 us/op 1.1854 us/op 1.10
LinkedList of 16000 items push then shift 7.4330 ns/op 7.1870 ns/op 1.03
array of 16000 items push then pop 81.703 ns/op 61.132 ns/op 1.34
LinkedList of 16000 items push then pop 6.1030 ns/op 5.7120 ns/op 1.07
array of 24000 items push then shift 1.9209 us/op 1.7524 us/op 1.10
LinkedList of 24000 items push then shift 6.6580 ns/op 6.7530 ns/op 0.99
array of 24000 items push then pop 114.99 ns/op 87.168 ns/op 1.32
LinkedList of 24000 items push then pop 6.1320 ns/op 5.7260 ns/op 1.07
intersect bitArray bitLen 8 4.7400 ns/op 4.5350 ns/op 1.05
intersect array and set length 8 30.402 ns/op 27.951 ns/op 1.09
intersect bitArray bitLen 128 23.993 ns/op 23.212 ns/op 1.03
intersect array and set length 128 503.08 ns/op 472.38 ns/op 1.06
bitArray.getTrueBitIndexes() bitLen 128 948.00 ns/op 881.00 ns/op 1.08
bitArray.getTrueBitIndexes() bitLen 248 1.7090 us/op 1.5890 us/op 1.08
bitArray.getTrueBitIndexes() bitLen 512 3.6180 us/op 3.3190 us/op 1.09
Full columns - reconstruct all 6 blobs 130.60 us/op 155.53 us/op 0.84
Full columns - reconstruct half of the blobs out of 6 81.556 us/op 159.31 us/op 0.51
Full columns - reconstruct single blob out of 6 37.043 us/op 63.963 us/op 0.58
Half columns - reconstruct all 6 blobs 396.64 ms/op 362.11 ms/op 1.10
Half columns - reconstruct half of the blobs out of 6 197.89 ms/op 181.25 ms/op 1.09
Half columns - reconstruct single blob out of 6 70.523 ms/op 63.990 ms/op 1.10
Set add up to 64 items then delete first 1.6461 us/op 1.5210 us/op 1.08
OrderedSet add up to 64 items then delete first 2.5152 us/op 2.3552 us/op 1.07
Set add up to 64 items then delete last 1.8931 us/op 1.7531 us/op 1.08
OrderedSet add up to 64 items then delete last 2.7843 us/op 2.6136 us/op 1.07
Set add up to 64 items then delete middle 1.8810 us/op 1.7443 us/op 1.08
OrderedSet add up to 64 items then delete middle 4.2448 us/op 4.0010 us/op 1.06
Set add up to 128 items then delete first 3.7971 us/op 3.5052 us/op 1.08
OrderedSet add up to 128 items then delete first 5.7994 us/op 5.3939 us/op 1.08
Set add up to 128 items then delete last 3.6566 us/op 3.4058 us/op 1.07
OrderedSet add up to 128 items then delete last 5.3497 us/op 5.0982 us/op 1.05
Set add up to 128 items then delete middle 3.6148 us/op 3.3934 us/op 1.07
OrderedSet add up to 128 items then delete middle 11.153 us/op 10.755 us/op 1.04
Set add up to 256 items then delete first 7.5004 us/op 6.9678 us/op 1.08
OrderedSet add up to 256 items then delete first 12.042 us/op 11.208 us/op 1.07
Set add up to 256 items then delete last 7.1246 us/op 6.8647 us/op 1.04
OrderedSet add up to 256 items then delete last 11.245 us/op 10.712 us/op 1.05
Set add up to 256 items then delete middle 7.4766 us/op 6.8605 us/op 1.09
OrderedSet add up to 256 items then delete middle 34.963 us/op 33.215 us/op 1.05
runFastConfirmationRules vc:100000 bc:96 eq:0 4.6370 ms/op 4.2406 ms/op 1.09
runFastConfirmationRules vc:600000 bc:96 eq:0 35.489 ms/op 32.925 ms/op 1.08
runFastConfirmationRules vc:1000000 bc:96 eq:0 59.014 ms/op 54.889 ms/op 1.08
runFastConfirmationRules vc:600000 bc:320 eq:0 36.565 ms/op 33.141 ms/op 1.10
runFastConfirmationRules vc:100000 bc:96 eq:1000 1.2706 s/op 1.0334 s/op 1.23
pass gossip attestations to forkchoice per slot 2.5893 ms/op 2.4423 ms/op 1.06
forkChoice updateHead vc 100000 bc 64 eq 0 450.38 us/op 566.10 us/op 0.80
forkChoice updateHead vc 600000 bc 64 eq 0 2.7777 ms/op 2.2926 ms/op 1.21
forkChoice updateHead vc 1000000 bc 64 eq 0 4.6960 ms/op 3.8671 ms/op 1.21
forkChoice updateHead vc 600000 bc 320 eq 0 2.8121 ms/op 2.3138 ms/op 1.22
forkChoice updateHead vc 600000 bc 1200 eq 0 2.8495 ms/op 2.3302 ms/op 1.22
forkChoice updateHead vc 600000 bc 7200 eq 0 3.2732 ms/op 2.5792 ms/op 1.27
forkChoice updateHead vc 600000 bc 64 eq 1000 2.8588 ms/op 2.2910 ms/op 1.25
forkChoice updateHead vc 600000 bc 64 eq 10000 2.9523 ms/op 2.3851 ms/op 1.24
forkChoice updateHead vc 600000 bc 64 eq 300000 7.1057 ms/op 5.9725 ms/op 1.19
computeDeltas 1400000 validators 0% inactive 13.751 ms/op 11.474 ms/op 1.20
computeDeltas 1400000 validators 10% inactive 12.297 ms/op 10.913 ms/op 1.13
computeDeltas 1400000 validators 20% inactive 11.814 ms/op 10.361 ms/op 1.14
computeDeltas 1400000 validators 50% inactive 9.5725 ms/op 8.6392 ms/op 1.11
computeDeltas 2100000 validators 0% inactive 19.821 ms/op 17.467 ms/op 1.13
computeDeltas 2100000 validators 10% inactive 18.912 ms/op 16.444 ms/op 1.15
computeDeltas 2100000 validators 20% inactive 17.666 ms/op 15.477 ms/op 1.14
computeDeltas 2100000 validators 50% inactive 14.430 ms/op 10.354 ms/op 1.39
altair processAttestation - 250000 vs - 7PWei normalcase 1.7405 ms/op 1.7460 ms/op 1.00
altair processAttestation - 250000 vs - 7PWei worstcase 2.4458 ms/op 2.5657 ms/op 0.95
altair processAttestation - setStatus - 1/6 committees join 103.68 us/op 96.130 us/op 1.08
altair processAttestation - setStatus - 1/3 committees join 206.48 us/op 186.65 us/op 1.11
altair processAttestation - setStatus - 1/2 committees join 290.10 us/op 261.46 us/op 1.11
altair processAttestation - setStatus - 2/3 committees join 373.48 us/op 345.81 us/op 1.08
altair processAttestation - setStatus - 4/5 committees join 533.27 us/op 555.46 us/op 0.96
altair processAttestation - setStatus - 100% committees join 613.29 us/op 604.89 us/op 1.01
altair processBlock - 250000 vs - 7PWei normalcase 4.5079 ms/op 3.8202 ms/op 1.18
altair processBlock - 250000 vs - 7PWei normalcase hashState 15.430 ms/op 17.689 ms/op 0.87
altair processBlock - 250000 vs - 7PWei worstcase 21.145 ms/op 20.892 ms/op 1.01
altair processBlock - 250000 vs - 7PWei worstcase hashState 42.813 ms/op 40.055 ms/op 1.07
phase0 processBlock - 250000 vs - 7PWei normalcase 1.4234 ms/op 1.4845 ms/op 0.96
phase0 processBlock - 250000 vs - 7PWei worstcase 17.722 ms/op 19.120 ms/op 0.93
altair processEth1Data - 250000 vs - 7PWei normalcase 287.51 us/op 274.62 us/op 1.05
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:16 3.1720 us/op 4.0420 us/op 0.78
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:220 20.468 us/op 19.476 us/op 1.05
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:43 5.5870 us/op 6.2170 us/op 0.90
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:19 3.4810 us/op 3.7860 us/op 0.92
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1021 92.241 us/op 89.357 us/op 1.03
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11778 1.4404 ms/op 1.3266 ms/op 1.09
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.8710 ms/op 1.7258 ms/op 1.08
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.8539 ms/op 1.7371 ms/op 1.07
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 3.7677 ms/op 3.4877 ms/op 1.08
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.1277 ms/op 1.9714 ms/op 1.08
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.0718 ms/op 3.7636 ms/op 1.08
Tree 40 250000 create 348.94 ms/op 309.20 ms/op 1.13
Tree 40 250000 get(125000) 101.94 ns/op 90.924 ns/op 1.12
Tree 40 250000 set(125000) 1.0707 us/op 965.42 ns/op 1.11
Tree 40 250000 toArray() 17.778 ms/op 14.004 ms/op 1.27
Tree 40 250000 iterate all - toArray() + loop 16.535 ms/op 13.837 ms/op 1.19
Tree 40 250000 iterate all - get(i) 45.643 ms/op 36.214 ms/op 1.26
Array 250000 create 2.4794 ms/op 2.0501 ms/op 1.21
Array 250000 clone - spread 780.88 us/op 638.84 us/op 1.22
Array 250000 get(125000) 0.29100 ns/op 0.28200 ns/op 1.03
Array 250000 set(125000) 0.29800 ns/op 0.28400 ns/op 1.05
Array 250000 iterate all - loop 57.015 us/op 55.825 us/op 1.02
phase0 afterProcessEpoch - 250000 vs - 7PWei 40.797 ms/op 47.095 ms/op 0.87
Array.fill - length 1000000 2.4882 ms/op 2.0015 ms/op 1.24
Array push - length 1000000 10.250 ms/op 8.5871 ms/op 1.19
Array.get 0.20616 ns/op 0.19897 ns/op 1.04
Uint8Array.get 0.24755 ns/op 0.22448 ns/op 1.10
phase0 beforeProcessEpoch - 250000 vs - 7PWei 18.110 ms/op 14.559 ms/op 1.24
altair processEpoch - mainnet_e81889 272.23 ms/op 252.08 ms/op 1.08
mainnet_e81889 - altair beforeProcessEpoch 38.051 ms/op 14.186 ms/op 2.68
mainnet_e81889 - altair processJustificationAndFinalization 5.8650 us/op 5.8730 us/op 1.00
mainnet_e81889 - altair processInactivityUpdates 3.6408 ms/op 3.3195 ms/op 1.10
mainnet_e81889 - altair processRewardsAndPenalties 20.909 ms/op 18.569 ms/op 1.13
mainnet_e81889 - altair processRegistryUpdates 529.00 ns/op 514.00 ns/op 1.03
mainnet_e81889 - altair processSlashings 126.00 ns/op 125.00 ns/op 1.01
mainnet_e81889 - altair processEth1DataReset 126.00 ns/op 123.00 ns/op 1.02
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.6153 ms/op 4.0126 ms/op 0.40
mainnet_e81889 - altair processSlashingsReset 701.00 ns/op 626.00 ns/op 1.12
mainnet_e81889 - altair processRandaoMixesReset 1.2340 us/op 1.2130 us/op 1.02
mainnet_e81889 - altair processHistoricalRootsUpdate 125.00 ns/op 126.00 ns/op 0.99
mainnet_e81889 - altair processParticipationFlagUpdates 430.00 ns/op 424.00 ns/op 1.01
mainnet_e81889 - altair processSyncCommitteeUpdates 102.00 ns/op 103.00 ns/op 0.99
mainnet_e81889 - altair afterProcessEpoch 42.549 ms/op 39.887 ms/op 1.07
capella processEpoch - mainnet_e217614 775.92 ms/op 760.56 ms/op 1.02
mainnet_e217614 - capella beforeProcessEpoch 61.880 ms/op 68.885 ms/op 0.90
mainnet_e217614 - capella processJustificationAndFinalization 5.8970 us/op 6.9320 us/op 0.85
mainnet_e217614 - capella processInactivityUpdates 15.537 ms/op 17.103 ms/op 0.91
mainnet_e217614 - capella processRewardsAndPenalties 88.139 ms/op 96.894 ms/op 0.91
mainnet_e217614 - capella processRegistryUpdates 4.4310 us/op 4.4730 us/op 0.99
mainnet_e217614 - capella processSlashings 127.00 ns/op 128.00 ns/op 0.99
mainnet_e217614 - capella processEth1DataReset 123.00 ns/op 126.00 ns/op 0.98
mainnet_e217614 - capella processEffectiveBalanceUpdates 13.746 ms/op 18.316 ms/op 0.75
mainnet_e217614 - capella processSlashingsReset 676.00 ns/op 664.00 ns/op 1.02
mainnet_e217614 - capella processRandaoMixesReset 1.1750 us/op 1.4530 us/op 0.81
mainnet_e217614 - capella processHistoricalRootsUpdate 124.00 ns/op 123.00 ns/op 1.01
mainnet_e217614 - capella processParticipationFlagUpdates 452.00 ns/op 458.00 ns/op 0.99
mainnet_e217614 - capella afterProcessEpoch 105.22 ms/op 107.10 ms/op 0.98
phase0 processEpoch - mainnet_e58758 295.82 ms/op 292.97 ms/op 1.01
mainnet_e58758 - phase0 beforeProcessEpoch 65.222 ms/op 60.028 ms/op 1.09
mainnet_e58758 - phase0 processJustificationAndFinalization 6.1620 us/op 5.8940 us/op 1.05
mainnet_e58758 - phase0 processRewardsAndPenalties 16.706 ms/op 16.143 ms/op 1.03
mainnet_e58758 - phase0 processRegistryUpdates 2.2360 us/op 2.2050 us/op 1.01
mainnet_e58758 - phase0 processSlashings 131.00 ns/op 136.00 ns/op 0.96
mainnet_e58758 - phase0 processEth1DataReset 132.00 ns/op 124.00 ns/op 1.06
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.0400 ms/op 811.83 us/op 1.28
mainnet_e58758 - phase0 processSlashingsReset 933.00 ns/op 890.00 ns/op 1.05
mainnet_e58758 - phase0 processRandaoMixesReset 1.2370 us/op 1.3270 us/op 0.93
mainnet_e58758 - phase0 processHistoricalRootsUpdate 131.00 ns/op 212.00 ns/op 0.62
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.0640 us/op 1.1500 us/op 0.93
mainnet_e58758 - phase0 afterProcessEpoch 34.241 ms/op 32.052 ms/op 1.07
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.0087 ms/op 985.74 us/op 1.02
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 1.6196 ms/op 2.1925 ms/op 0.74
altair processInactivityUpdates - 250000 normalcase 10.709 ms/op 10.196 ms/op 1.05
altair processInactivityUpdates - 250000 worstcase 10.930 ms/op 10.698 ms/op 1.02
phase0 processRegistryUpdates - 250000 normalcase 2.1570 us/op 3.6620 us/op 0.59
phase0 processRegistryUpdates - 250000 badcase_full_deposits 137.84 us/op 142.70 us/op 0.97
phase0 processRegistryUpdates - 250000 worstcase 0.5 63.226 ms/op 60.842 ms/op 1.04
altair processRewardsAndPenalties - 250000 normalcase 16.319 ms/op 15.402 ms/op 1.06
altair processRewardsAndPenalties - 250000 worstcase 15.646 ms/op 14.871 ms/op 1.05
phase0 getAttestationDeltas - 250000 normalcase 5.4759 ms/op 5.1919 ms/op 1.05
phase0 getAttestationDeltas - 250000 worstcase 5.6471 ms/op 5.2950 ms/op 1.07
phase0 processSlashings - 250000 worstcase 63.996 us/op 59.764 us/op 1.07
altair processSyncCommitteeUpdates - 250000 10.346 ms/op 9.8134 ms/op 1.05
BeaconState.hashTreeRoot - No change 167.00 ns/op 174.00 ns/op 0.96
BeaconState.hashTreeRoot - 1 full validator 69.655 us/op 76.259 us/op 0.91
BeaconState.hashTreeRoot - 32 full validator 711.37 us/op 854.74 us/op 0.83
BeaconState.hashTreeRoot - 512 full validator 6.4564 ms/op 7.9964 ms/op 0.81
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 88.418 us/op 90.443 us/op 0.98
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.4211 ms/op 1.3231 ms/op 1.07
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 14.726 ms/op 15.126 ms/op 0.97
BeaconState.hashTreeRoot - 1 balances 72.765 us/op 69.383 us/op 1.05
BeaconState.hashTreeRoot - 32 balances 719.74 us/op 703.41 us/op 1.02
BeaconState.hashTreeRoot - 512 balances 5.7061 ms/op 5.7424 ms/op 0.99
BeaconState.hashTreeRoot - 250000 balances 118.48 ms/op 120.41 ms/op 0.98
aggregationBits - 2048 els - zipIndexesInBitList 20.922 us/op 19.602 us/op 1.07
regular array get 100000 times 22.735 us/op 22.677 us/op 1.00
wrappedArray get 100000 times 22.729 us/op 22.455 us/op 1.01
arrayWithProxy get 100000 times 10.940 ms/op 10.508 ms/op 1.04
ssz.Root.equals 21.247 ns/op 20.882 ns/op 1.02
byteArrayEquals 21.073 ns/op 20.734 ns/op 1.02
Buffer.compare 9.0030 ns/op 8.5890 ns/op 1.05
processSlot - 1 slots 8.3960 us/op 9.6870 us/op 0.87
processSlot - 32 slots 1.9500 ms/op 2.0178 ms/op 0.97
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 3.9850 ms/op 5.7693 ms/op 0.69
getCommitteeAssignments - req 1 vs - 250000 vc 1.6673 ms/op 1.6491 ms/op 1.01
getCommitteeAssignments - req 100 vs - 250000 vc 3.4308 ms/op 3.3703 ms/op 1.02
getCommitteeAssignments - req 1000 vs - 250000 vc 3.6660 ms/op 3.6194 ms/op 1.01
findModifiedValidators - 10000 modified validators 893.06 ms/op 822.46 ms/op 1.09
findModifiedValidators - 1000 modified validators 721.11 ms/op 618.64 ms/op 1.17
findModifiedValidators - 100 modified validators 314.29 ms/op 327.12 ms/op 0.96
findModifiedValidators - 10 modified validators 268.58 ms/op 249.70 ms/op 1.08
findModifiedValidators - 1 modified validators 183.19 ms/op 144.30 ms/op 1.27
findModifiedValidators - no difference 188.57 ms/op 173.11 ms/op 1.09
migrate state 1500000 validators, 3400 modified, 2000 new 2.9723 s/op 2.9456 s/op 1.01
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 3.6500 ns/op 3.6600 ns/op 1.00
state getBlockRootAtSlot - 250000 vs - 7PWei 339.44 ns/op 340.50 ns/op 1.00
computeProposerIndex 100000 validators 1.3368 ms/op 1.2937 ms/op 1.03
getNextSyncCommitteeIndices 1000 validators 2.8501 ms/op 2.7761 ms/op 1.03
getNextSyncCommitteeIndices 10000 validators 25.073 ms/op 24.612 ms/op 1.02
getNextSyncCommitteeIndices 100000 validators 85.953 ms/op 80.565 ms/op 1.07
computeProposers - vc 250000 540.08 us/op 539.28 us/op 1.00
computeEpochShuffling - vc 250000 39.603 ms/op 39.116 ms/op 1.01
getNextSyncCommittee - vc 250000 9.3991 ms/op 9.1070 ms/op 1.03
nodejs block root to RootHex using toHex 104.33 ns/op 97.770 ns/op 1.07
nodejs block root to RootHex using toRootHex 65.043 ns/op 61.507 ns/op 1.06
nodejs fromHex(blob) 824.63 us/op 783.71 us/op 1.05
nodejs fromHexInto(blob) 655.44 us/op 607.85 us/op 1.08
nodejs block root to RootHex using the deprecated toHexString 498.18 ns/op 445.40 ns/op 1.12
nodejs byteArrayEquals 32 bytes (block root) 25.421 ns/op 25.066 ns/op 1.01
nodejs byteArrayEquals 48 bytes (pubkey) 36.654 ns/op 36.321 ns/op 1.01
nodejs byteArrayEquals 96 bytes (signature) 39.865 ns/op 33.553 ns/op 1.19
nodejs byteArrayEquals 1024 bytes 44.507 ns/op 39.985 ns/op 1.11
nodejs byteArrayEquals 131072 bytes (blob) 1.7288 us/op 1.7302 us/op 1.00
browser block root to RootHex using toHex 144.31 ns/op 138.76 ns/op 1.04
browser block root to RootHex using toRootHex 129.03 ns/op 125.71 ns/op 1.03
browser fromHex(blob) 1.5434 ms/op 1.4960 ms/op 1.03
browser fromHexInto(blob) 650.68 us/op 603.38 us/op 1.08
browser block root to RootHex using the deprecated toHexString 344.33 ns/op 442.48 ns/op 0.78
browser byteArrayEquals 32 bytes (block root) 26.865 ns/op 26.578 ns/op 1.01
browser byteArrayEquals 48 bytes (pubkey) 37.854 ns/op 37.587 ns/op 1.01
browser byteArrayEquals 96 bytes (signature) 70.853 ns/op 70.339 ns/op 1.01
browser byteArrayEquals 1024 bytes 721.88 ns/op 718.40 ns/op 1.00
browser byteArrayEquals 131072 bytes (blob) 90.786 us/op 90.772 us/op 1.00

by benchmarkbot/action

ensi321 added a commit that referenced this pull request Jul 7, 2026
@ensi321 ensi321 changed the title feat: upgrade to v1.7.0-alpha.12 spec feat: implement non-eip-7688 changes in alpha.12 Jul 16, 2026
ensi321 added a commit that referenced this pull request Jul 16, 2026
Enable the v1.7.0-alpha.12 consensus-spec-tests on the EIP-7688 branch.
With progressive containers in place the gloas ssz_static / state-transition
/ fork-choice suites pass; the remaining failures are all NOT EIP-7688 related
and handled elsewhere:

- ALPHA12-MISC (unskip in #9606): builder-deposit / builder-exit processing and
  the alpha.12 constant bumps (PAYLOAD_DUE_BPS, MIN_BUILDER_WITHDRAWABILITY_DELAY,
  MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD) land on the follow-up alpha.12-misc branch.
- FCR rework: gloas fast_confirmation suite + two is_one_confirmed cases.
- cell-level DAS: fulu PartialDataColumnGroupID ssz_static.
- ssz 1.6.2: consolidations-at-limit hits an @chainsafe/ssz@1.6.1 stack overflow
  at mainnet scale (issue #9656); clears when ssz 1.6.2 is synced via unstable.

Also:
- Bump spec-tests-version.json to v1.7.0-alpha.12.
- Re-sync ethspecify specrefs to v1.7.0-alpha.12: drop entries for spec objects
  removed/renamed at alpha.12 (get_dependent_root, get_proposer_dependent_root,
  get_proposer_preferences_signature, is_epoch_boundary, BUILDER_REGISTRY_LIMIT,
  BUILDER_PENDING_WITHDRAWALS_LIMIT), source the new gloas/electra SSZ types,
  gloas p2p size-bound presets, and get_shuffling_dependent_root /
  get_signed_proposer_preferences / is_valid_indexed_attestation / is_not_epoch_boundary,
  and except the unimplemented heze + attestation-upgrade + slot-based gindex helpers.
  `ethspecify check` reports 1144 valid references.
- Fix the ProgressiveTestStruct ssz_generic type: field A is ProgressiveList[byte]
  (a byte list, hex JSON) so it must be ProgressiveByteListType, not
  ProgressiveListBasicType. Fixes all phase0/ssz_generic/containers/ProgressiveTestStruct cases.

Verified green: minimal 55235, mainnet 7185, general 5367, bls 90, config-sync,
params-preset; ethspecify check 1144 valid. lint + check-types clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ensi321 and others added 10 commits July 20, 2026 23:28
- PAYLOAD_DUE_BPS 7500 -> 5000 (consensus-specs #5414)
- MIN_BUILDER_WITHDRAWABILITY_DELAY mainnet 8192 -> 64 (consensus-specs
#5426)
- MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD 256 -> 64 (consensus-specs
#5420)
- EnvelopesByRange cap uses MAX_REQUEST_PAYLOADS (consensus-specs #5383)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Aligns the builder withdrawal prefix with consensus-specs #5416 (was
0x03)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ethereum/consensus-specs#5429

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
see ethereum/consensus-specs#5439

Builder deposit requests are ignored unless the withdrawal credentials
start with `BUILDER_WITHDRAWAL_PREFIX`. Accepted new builders are
registered with `PAYLOAD_BUILDER_VERSION`.

Checks:
- `pnpm exec biome check
packages/state-transition/src/block/processBuilderDepositRequest.ts
packages/state-transition/test/unit/block/processBuilderDepositRequest.test.ts
packages/state-transition/test/unit/block/processBuilderExitRequest.test.ts`
- `pnpm --filter @lodestar/state-transition check-types`

> This PR was written primarily by Codex.
consensus-specs #5436 (in v1.7.0-alpha.12) removed MAX_SIGNED_BEACON_BLOCK_SIZE,
and EIP-7688 progressive lists removed BUILDER_REGISTRY_LIMIT and
BUILDER_PENDING_WITHDRAWALS_LIMIT from the gloas preset. Post-gloas beacon
block gossip is now bounded by MAX_PAYLOAD_SIZE per
https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.12/specs/phase0/p2p-interface.md#the-gossip-domain-gossipsub

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
consensus-specs #5436 removed the deposits bounds from the gloas block and
envelope gossip REJECT conditions (execution requests deposits are unbounded
progressive lists). The extra checks would reject spec-valid messages.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
total active balance exceeds Number.MAX_SAFE_INTEGER at mainnet scale
(~16M increments * 1e9 = 3.4e16), making the quorum threshold diverge from
spec integer math. Keep the intermediate computation in bigint; the final
threshold (~total_balance/32 * 6/10) is safely below 2**53.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All fixes referenced by the TODO GLOAS #9606 markers have landed on this
branch, spec tests and config/preset e2e sync tests pass unmodified.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…oval

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ensi321
ensi321 marked this pull request as ready for review July 21, 2026 07:16
@ensi321
ensi321 requested a review from a team as a code owner July 21, 2026 07:16
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.51%. Comparing base (17a4805) to head (a241c05).

Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #9606      +/-   ##
============================================
- Coverage     52.52%   52.51%   -0.01%     
============================================
  Files           848      848              
  Lines         60394    60388       -6     
  Branches       4458     4458              
============================================
- Hits          31719    31713       -6     
  Misses        28614    28614              
  Partials         61       61              
🚀 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: a241c0503c

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

if (
block !== null &&
attData.index === 1 &&
!chain.forkChoice.hasPayloadHexUnsafe(toRootHex(attData.beaconBlockRoot))

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 Mirror imported-payload gating for aggregates

This updates the unaggregated attestation path to require forkChoice.hasPayloadHexUnsafe, but the aggregate path still uses chain.seenPayloadEnvelope in packages/beacon-node/src/chain/validation/aggregateAndProof.ts:99. In Gloas, an index == 1 aggregate submitted through publishAggregateAndProofsV2 can therefore be accepted and published while the envelope is only in seenPayloadEnvelopeInputCache and not fully imported with data, even though the alpha.12 gossip rule requires is_payload_verified for beacon_aggregate_and_proof too. Please apply the same fork-choice payload check there.

Useful? React with 👍 / 👎.

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.

yes this is valid

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.

Addressed as of c00a00bc8c ("fix: require imported payload for index==1 aggregate gossip"): the index == 1 aggregate path in aggregateAndProof.ts now gates on !chain.forkChoice.hasPayloadHexUnsafe(toRootHex(attData.beaconBlockRoot)) → IGNORE EXECUTION_PAYLOAD_NOT_SEEN, structurally identical to the unaggregated path in attestation.ts:330. No seenPayloadEnvelope reference remains in the file, so publishAggregateAndProofsV2 now enforces the same is_payload_verified gossip rule. Good catch by the bot.

skippedTests: [
// TODO-GLOAS: re-enable after gloas light client is implemented
/\/gloas_fork$/,
// TODO GLOAS: Unskip in #9606

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.

it's great to see we removed a lot of skipped tests in this PR

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.

Thanks 🙏 — most of the gloas handlers that were stubbed through the earlier alphas are implemented now, so the skips could go. A few remain with TODOs for follow-up (the on_payload_attestation_message fork-choice handler, the gloas light-client path, and the networking runner that's been skipped since alpha.5).

Comment on lines +35 to +36
// total active balance exceeds Number.MAX_SAFE_INTEGER at mainnet scale, keep the intermediate math in bigint
const perSlotBalance =

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.

is this true? how was this caught, seems like a new spec test?

@ensi321 ensi321 Jul 23, 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.

I think so.

Total active EB is like 34M ETH on mainnet, multiply by EFFECTIVE_BALANCE_INCREMENT = 34M * 10^9 = 3.4 * 10^16 Gwei. Which is greater than MAX_SAFE_INTEGER.

No spec test for this. Just caught this when reviewing with claude.

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.

@lodekeeper can you confirm this math, I assumed Number was safe to use for anything that is accounted for in gwei due to max eth supply cap

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.

Confirmed — ensi321 is right, it does overflow, and the current bigint version (from c7663acefa) handles it correctly.

The overflow is on the intermediate totalActiveBalanceIncrements * EFFECTIVE_BALANCE_INCREMENT, which reconstructs total active balance in gwei:

  • totalActiveBalanceIncrements is tracked in ETH units (epochCache.ts:370 keeps it that way precisely to fit total network balance in a JS number), so ~34M at today's mainnet.
  • × EFFECTIVE_BALANCE_INCREMENT (1e9) → total active balance in gwei ≈ 3.4e16, vs MAX_SAFE_INTEGER ≈ 9.007e15 → ~3.8× over. At ensi321's 41M ETH it's 4.1e16 (~4.6×). Conclusion holds regardless of the exact staking figure.

On your assumption — that's the part that doesn't hold. The safe ceiling for a gwei value in a JS number is MAX_SAFE_INTEGER / 1e9 ≈ 9.01M ETH:

  • A single validator balance is always fine — even MAX_EFFECTIVE_BALANCE_ELECTRA (2048 ETH = 2.048e12 gwei) is ~4000× under the limit.
  • Any sum across the validator set is not: total active balance (~34M ETH) already passes ~9M ETH, and the supply cap makes it worse, not safer — ~120M ETH in gwei is 1.2e17, ~13× MAX_SAFE_INTEGER. So "accounted for in gwei ⇒ safe in Number" is true per-validator, not for aggregates.

The function itself is fine: all intermediate math stays in bigint and only the final result is cast back — and that result is small (perSlot × 6/10 ≈ 6.4e14 at 34M ETH, ≤ ~2.25e15 even if the entire supply were staked), comfortably under MAX_SAFE_INTEGER. So no further change needed here; epochCache.ts:392 (throw if totalActiveBalanceIncrements itself ≥ MAX_SAFE_INTEGER) is the backstop on the input side.

And yeah — no spec test would catch this as-is: it's silent precision loss, not a throw, so a unit test would need a state built at realistic mainnet-scale total balance to surface it.

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.

realized we also use bigint for the ssz type

export type Gwei = UintBn64;

so this change is needed, that's a good catch

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.

Yeah — and it's worth pinning down why that's consistent, because the two Gwei representations are used deliberately here.

Gwei = UintBn64 (bigint) is the right type for full-total balances that can exceed 2^53 — e.g. depositBalanceToConsume/exitBalanceToConsume (sszTypes.ts:522-523). But the field this threshold actually feeds — BuilderPendingPayment.weight (sszTypes.ts:239) — is intentionally UintNum64 (number), and that's correct rather than an oversight: weight accumulates only the same-slot attesting balance for one payment (processAttestationsAltair.ts:153, existingWeight + paymentWeightToAdd * EFFECTIVE_BALANCE_INCREMENT), so it's bounded by ~one slot's committee ≈ total_active_balance / 32. That's ~1.06e15 gwei at 34M ETH staked, and still only ~3.75e15 even if the entire supply were staked — comfortably under MAX_SAFE_INTEGER (it wouldn't reach it until ~288M ETH active, well past the supply cap).

So the overflow was specifically the intermediate full-total reconstruction inside the threshold fn (totalActiveBalanceIncrements × EFFECTIVE_BALANCE_INCREMENT ≈ 3.4e16, before the ÷32) — which is why the bigint-intermediate / small-Number-result shape is the right fix, and why the number-typed weight on the other side of the >= compare is fine as-is. Same reason the accumulation at :153 can stay in plain number: it's per-slot-scoped and never materializes the full total in one value.

tl;dr the split is intentional — full-total balances → Gwei/UintBn64; per-slot / bounded sums → UintNum64. weight is correctly the latter, so c7663acefa (bigint intermediates) is the whole of it, no further change needed.

ensi321 and others added 2 commits July 23, 2026 15:30
Mirror the beacon_attestation is_payload_verified gating (#9611) on the
beacon_aggregate_and_proof topic per
https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.12/specs/gloas/p2p-interface.md#modified-beacon_aggregate_and_proof
An index==1 aggregate was accepted once the envelope was merely seen on
gossip, before it was imported and verified.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ensi321
ensi321 merged commit 3d99c9c into unstable Jul 24, 2026
19 checks passed
@ensi321
ensi321 deleted the nc/alpha.12 branch July 24, 2026 08:14
@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

None yet

Development

Successfully merging this pull request may close these issues.

7 participants