Skip to content

feat: add dependent root to proposer preferences - #9303

Merged
nflaig merged 9 commits into
unstablefrom
nflaig/dependent-root
Apr 30, 2026
Merged

feat: add dependent root to proposer preferences#9303
nflaig merged 9 commits into
unstablefrom
nflaig/dependent-root

Conversation

@nflaig

@nflaig nflaig commented Apr 29, 2026

Copy link
Copy Markdown
Member

@nflaig
nflaig requested a review from a team as a code owner April 29, 2026 12:28

@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 integrates the dependentRoot field into ProposerPreferences, updating the SSZ container, error types, and gossip validation logic. The SeenProposerPreferences cache is refactored to include dependentRoot in its indexing. Review feedback identifies a logic error in the epoch calculation and proposer selection during validation and notes that the manual state caching in importBlock.ts is redundant.

Comment thread packages/beacon-node/src/chain/validation/proposerPreferences.ts Outdated
Comment thread packages/beacon-node/src/chain/blocks/importBlock.ts Outdated

@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: 472259da8a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/beacon-node/src/chain/blocks/importBlock.ts Outdated
@github-actions

github-actions Bot commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: be0589f Previous: 07452fe Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 944.21 us/op 947.79 us/op 1.00
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 41.156 us/op 37.973 us/op 1.08
BLS verify - blst 758.74 us/op 637.08 us/op 1.19
BLS verifyMultipleSignatures 3 - blst 1.3704 ms/op 1.3386 ms/op 1.02
BLS verifyMultipleSignatures 8 - blst 2.1675 ms/op 2.1351 ms/op 1.02
BLS verifyMultipleSignatures 32 - blst 6.8751 ms/op 6.7111 ms/op 1.02
BLS verifyMultipleSignatures 64 - blst 13.273 ms/op 13.039 ms/op 1.02
BLS verifyMultipleSignatures 128 - blst 25.606 ms/op 25.382 ms/op 1.01
BLS deserializing 10000 signatures 632.02 ms/op 605.88 ms/op 1.04
BLS deserializing 100000 signatures 6.3386 s/op 6.1649 s/op 1.03
BLS verifyMultipleSignatures - same message - 3 - blst 811.06 us/op 755.88 us/op 1.07
BLS verifyMultipleSignatures - same message - 8 - blst 888.32 us/op 907.96 us/op 0.98
BLS verifyMultipleSignatures - same message - 32 - blst 1.5206 ms/op 1.4705 ms/op 1.03
BLS verifyMultipleSignatures - same message - 64 - blst 2.3032 ms/op 2.2636 ms/op 1.02
BLS verifyMultipleSignatures - same message - 128 - blst 3.9913 ms/op 3.9208 ms/op 1.02
BLS aggregatePubkeys 32 - blst 17.600 us/op 16.866 us/op 1.04
BLS aggregatePubkeys 128 - blst 62.991 us/op 59.820 us/op 1.05
getSlashingsAndExits - default max 46.843 us/op 46.753 us/op 1.00
getSlashingsAndExits - 2k 326.53 us/op 321.08 us/op 1.02
proposeBlockBody type=full, size=empty 759.31 us/op 912.52 us/op 0.83
isKnown best case - 1 super set check 163.00 ns/op 166.00 ns/op 0.98
isKnown normal case - 2 super set checks 163.00 ns/op 160.00 ns/op 1.02
isKnown worse case - 16 super set checks 160.00 ns/op 160.00 ns/op 1.00
validate api signedAggregateAndProof - struct 1.5154 ms/op 1.5242 ms/op 0.99
validate gossip signedAggregateAndProof - struct 1.5150 ms/op 1.5209 ms/op 1.00
batch validate gossip attestation - vc 640000 - chunk 32 103.78 us/op 104.98 us/op 0.99
batch validate gossip attestation - vc 640000 - chunk 64 91.440 us/op 93.943 us/op 0.97
batch validate gossip attestation - vc 640000 - chunk 128 84.802 us/op 85.347 us/op 0.99
batch validate gossip attestation - vc 640000 - chunk 256 80.881 us/op 81.793 us/op 0.99
bytes32 toHexString 283.00 ns/op 283.00 ns/op 1.00
bytes32 Buffer.toString(hex) 170.00 ns/op 175.00 ns/op 0.97
bytes32 Buffer.toString(hex) from Uint8Array 240.00 ns/op 245.00 ns/op 0.98
bytes32 Buffer.toString(hex) + 0x 170.00 ns/op 176.00 ns/op 0.97
Return object 10000 times 0.20960 ns/op 0.21220 ns/op 0.99
Throw Error 10000 times 3.3167 us/op 3.2898 us/op 1.01
toHex 105.99 ns/op 93.363 ns/op 1.14
Buffer.from 92.122 ns/op 85.832 ns/op 1.07
shared Buffer 60.452 ns/op 58.972 ns/op 1.03
fastMsgIdFn sha256 / 200 bytes 1.5060 us/op 1.4730 us/op 1.02
fastMsgIdFn h32 xxhash / 200 bytes 151.00 ns/op 157.00 ns/op 0.96
fastMsgIdFn h64 xxhash / 200 bytes 210.00 ns/op 207.00 ns/op 1.01
fastMsgIdFn sha256 / 1000 bytes 4.8190 us/op 4.7360 us/op 1.02
fastMsgIdFn h32 xxhash / 1000 bytes 238.00 ns/op 244.00 ns/op 0.98
fastMsgIdFn h64 xxhash / 1000 bytes 254.00 ns/op 255.00 ns/op 1.00
fastMsgIdFn sha256 / 10000 bytes 42.594 us/op 41.905 us/op 1.02
fastMsgIdFn h32 xxhash / 10000 bytes 1.2620 us/op 1.2490 us/op 1.01
fastMsgIdFn h64 xxhash / 10000 bytes 822.00 ns/op 799.00 ns/op 1.03
send data - 1000 256B messages 4.0349 ms/op 3.9837 ms/op 1.01
send data - 1000 512B messages 4.0580 ms/op 4.1471 ms/op 0.98
send data - 1000 1024B messages 4.5218 ms/op 4.2645 ms/op 1.06
send data - 1000 1200B messages 4.4554 ms/op 4.4096 ms/op 1.01
send data - 1000 2048B messages 4.6241 ms/op 4.6900 ms/op 0.99
send data - 1000 4096B messages 5.3941 ms/op 5.5404 ms/op 0.97
send data - 1000 16384B messages 15.295 ms/op 13.457 ms/op 1.14
send data - 1000 65536B messages 233.45 ms/op 223.88 ms/op 1.04
enrSubnets - fastDeserialize 64 bits 708.00 ns/op 742.00 ns/op 0.95
enrSubnets - ssz BitVector 64 bits 276.00 ns/op 259.00 ns/op 1.07
enrSubnets - fastDeserialize 4 bits 101.00 ns/op 95.000 ns/op 1.06
enrSubnets - ssz BitVector 4 bits 279.00 ns/op 263.00 ns/op 1.06
prioritizePeers score -10:0 att 32-0.1 sync 2-0 204.12 us/op 202.37 us/op 1.01
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 251.76 us/op 234.12 us/op 1.08
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 358.23 us/op 355.40 us/op 1.01
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 599.40 us/op 597.60 us/op 1.00
prioritizePeers score 0:0 att 64-1 sync 4-1 703.37 us/op 708.02 us/op 0.99
array of 16000 items push then shift 1.2877 us/op 1.2893 us/op 1.00
LinkedList of 16000 items push then shift 6.7060 ns/op 7.1430 ns/op 0.94
array of 16000 items push then pop 68.150 ns/op 67.106 ns/op 1.02
LinkedList of 16000 items push then pop 6.0180 ns/op 5.9060 ns/op 1.02
array of 24000 items push then shift 1.9130 us/op 1.8910 us/op 1.01
LinkedList of 24000 items push then shift 6.6250 ns/op 6.4940 ns/op 1.02
array of 24000 items push then pop 94.195 ns/op 93.661 ns/op 1.01
LinkedList of 24000 items push then pop 5.9560 ns/op 5.9050 ns/op 1.01
intersect bitArray bitLen 8 4.7350 ns/op 4.5970 ns/op 1.03
intersect array and set length 8 29.466 ns/op 28.054 ns/op 1.05
intersect bitArray bitLen 128 24.016 ns/op 23.096 ns/op 1.04
intersect array and set length 128 504.39 ns/op 469.43 ns/op 1.07
bitArray.getTrueBitIndexes() bitLen 128 1.0460 us/op 1.0800 us/op 0.97
bitArray.getTrueBitIndexes() bitLen 248 1.7780 us/op 1.8100 us/op 0.98
bitArray.getTrueBitIndexes() bitLen 512 3.6410 us/op 3.7220 us/op 0.98
Full columns - reconstruct all 6 blobs 128.28 us/op 103.39 us/op 1.24
Full columns - reconstruct half of the blobs out of 6 95.627 us/op 82.160 us/op 1.16
Full columns - reconstruct single blob out of 6 34.711 us/op 31.869 us/op 1.09
Half columns - reconstruct all 6 blobs 398.56 ms/op 376.59 ms/op 1.06
Half columns - reconstruct half of the blobs out of 6 198.00 ms/op 189.67 ms/op 1.04
Half columns - reconstruct single blob out of 6 71.727 ms/op 68.425 ms/op 1.05
Full columns - reconstruct all 10 blobs 218.54 us/op 173.99 us/op 1.26
Full columns - reconstruct half of the blobs out of 10 134.19 us/op 98.752 us/op 1.36
Full columns - reconstruct single blob out of 10 34.250 us/op 28.882 us/op 1.19
Half columns - reconstruct all 10 blobs 663.26 ms/op 631.45 ms/op 1.05
Half columns - reconstruct half of the blobs out of 10 338.03 ms/op 320.43 ms/op 1.05
Half columns - reconstruct single blob out of 10 74.813 ms/op 69.294 ms/op 1.08
Full columns - reconstruct all 20 blobs 1.8004 ms/op 1.6471 ms/op 1.09
Full columns - reconstruct half of the blobs out of 20 198.77 us/op 255.06 us/op 0.78
Full columns - reconstruct single blob out of 20 29.356 us/op 78.553 us/op 0.37
Half columns - reconstruct all 20 blobs 1.3397 s/op 1.2450 s/op 1.08
Half columns - reconstruct half of the blobs out of 20 677.39 ms/op 623.74 ms/op 1.09
Half columns - reconstruct single blob out of 20 72.171 ms/op 67.218 ms/op 1.07
Set add up to 64 items then delete first 2.1507 us/op 2.0916 us/op 1.03
OrderedSet add up to 64 items then delete first 3.3788 us/op 3.2602 us/op 1.04
Set add up to 64 items then delete last 2.1473 us/op 2.1711 us/op 0.99
OrderedSet add up to 64 items then delete last 3.4356 us/op 3.3136 us/op 1.04
Set add up to 64 items then delete middle 2.1889 us/op 2.1285 us/op 1.03
OrderedSet add up to 64 items then delete middle 4.9932 us/op 4.8449 us/op 1.03
Set add up to 128 items then delete first 4.2363 us/op 4.1674 us/op 1.02
OrderedSet add up to 128 items then delete first 6.3502 us/op 6.4063 us/op 0.99
Set add up to 128 items then delete last 4.0430 us/op 3.8827 us/op 1.04
OrderedSet add up to 128 items then delete last 6.1919 us/op 5.9382 us/op 1.04
Set add up to 128 items then delete middle 4.0162 us/op 3.8714 us/op 1.04
OrderedSet add up to 128 items then delete middle 12.496 us/op 11.838 us/op 1.06
Set add up to 256 items then delete first 7.8084 us/op 7.7524 us/op 1.01
OrderedSet add up to 256 items then delete first 11.761 us/op 11.890 us/op 0.99
Set add up to 256 items then delete last 7.8914 us/op 7.6726 us/op 1.03
OrderedSet add up to 256 items then delete last 12.210 us/op 11.807 us/op 1.03
Set add up to 256 items then delete middle 7.8626 us/op 7.6529 us/op 1.03
OrderedSet add up to 256 items then delete middle 40.302 us/op 35.137 us/op 1.15
pass gossip attestations to forkchoice per slot 2.6446 ms/op 2.4804 ms/op 1.07
forkChoice updateHead vc 100000 bc 64 eq 0 409.59 us/op 368.36 us/op 1.11
forkChoice updateHead vc 600000 bc 64 eq 0 2.4814 ms/op 2.2298 ms/op 1.11
forkChoice updateHead vc 1000000 bc 64 eq 0 4.1160 ms/op 3.6909 ms/op 1.12
forkChoice updateHead vc 600000 bc 320 eq 0 2.4681 ms/op 2.2111 ms/op 1.12
forkChoice updateHead vc 600000 bc 1200 eq 0 2.5354 ms/op 2.2295 ms/op 1.14
forkChoice updateHead vc 600000 bc 7200 eq 0 4.1746 ms/op 2.6509 ms/op 1.57
forkChoice updateHead vc 600000 bc 64 eq 1000 3.0220 ms/op 2.7150 ms/op 1.11
forkChoice updateHead vc 600000 bc 64 eq 10000 3.1369 ms/op 2.8336 ms/op 1.11
forkChoice updateHead vc 600000 bc 64 eq 300000 7.9391 ms/op 6.4353 ms/op 1.23
computeDeltas 1400000 validators 0% inactive 12.907 ms/op 11.879 ms/op 1.09
computeDeltas 1400000 validators 10% inactive 12.208 ms/op 11.022 ms/op 1.11
computeDeltas 1400000 validators 20% inactive 11.166 ms/op 10.015 ms/op 1.11
computeDeltas 1400000 validators 50% inactive 8.4455 ms/op 7.7732 ms/op 1.09
computeDeltas 2100000 validators 0% inactive 19.730 ms/op 17.831 ms/op 1.11
computeDeltas 2100000 validators 10% inactive 18.596 ms/op 16.605 ms/op 1.12
computeDeltas 2100000 validators 20% inactive 16.767 ms/op 15.098 ms/op 1.11
computeDeltas 2100000 validators 50% inactive 12.668 ms/op 8.7892 ms/op 1.44
altair processAttestation - 250000 vs - 7PWei normalcase 1.8552 ms/op 1.6613 ms/op 1.12
altair processAttestation - 250000 vs - 7PWei worstcase 2.9355 ms/op 2.4792 ms/op 1.18
altair processAttestation - setStatus - 1/6 committees join 103.92 us/op 98.411 us/op 1.06
altair processAttestation - setStatus - 1/3 committees join 202.86 us/op 196.34 us/op 1.03
altair processAttestation - setStatus - 1/2 committees join 289.19 us/op 279.77 us/op 1.03
altair processAttestation - setStatus - 2/3 committees join 369.23 us/op 358.00 us/op 1.03
altair processAttestation - setStatus - 4/5 committees join 513.11 us/op 478.02 us/op 1.07
altair processAttestation - setStatus - 100% committees join 626.44 us/op 589.31 us/op 1.06
altair processBlock - 250000 vs - 7PWei normalcase 3.6036 ms/op 2.9232 ms/op 1.23
altair processBlock - 250000 vs - 7PWei normalcase hashState 15.842 ms/op 15.067 ms/op 1.05
altair processBlock - 250000 vs - 7PWei worstcase 19.823 ms/op 19.760 ms/op 1.00
altair processBlock - 250000 vs - 7PWei worstcase hashState 40.987 ms/op 39.012 ms/op 1.05
phase0 processBlock - 250000 vs - 7PWei normalcase 1.4606 ms/op 1.3835 ms/op 1.06
phase0 processBlock - 250000 vs - 7PWei worstcase 17.847 ms/op 17.267 ms/op 1.03
altair processEth1Data - 250000 vs - 7PWei normalcase 298.17 us/op 282.02 us/op 1.06
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:16 3.7950 us/op 3.4750 us/op 1.09
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:220 21.583 us/op 19.635 us/op 1.10
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:43 6.2130 us/op 5.3100 us/op 1.17
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:19 4.1720 us/op 4.2490 us/op 0.98
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1021 94.910 us/op 83.784 us/op 1.13
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11778 1.4232 ms/op 1.3426 ms/op 1.06
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.8947 ms/op 1.6910 ms/op 1.12
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.9258 ms/op 1.7730 ms/op 1.09
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 3.9383 ms/op 3.7708 ms/op 1.04
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.1326 ms/op 1.9237 ms/op 1.11
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.2742 ms/op 4.1983 ms/op 1.02
Tree 40 250000 create 340.12 ms/op 351.80 ms/op 0.97
Tree 40 250000 get(125000) 95.193 ns/op 88.940 ns/op 1.07
Tree 40 250000 set(125000) 1.0345 us/op 936.81 ns/op 1.10
Tree 40 250000 toArray() 17.367 ms/op 13.425 ms/op 1.29
Tree 40 250000 iterate all - toArray() + loop 23.710 ms/op 14.322 ms/op 1.66
Tree 40 250000 iterate all - get(i) 46.691 ms/op 37.470 ms/op 1.25
Array 250000 create 2.3919 ms/op 2.0998 ms/op 1.14
Array 250000 clone - spread 731.99 us/op 660.96 us/op 1.11
Array 250000 get(125000) 0.30200 ns/op 0.28000 ns/op 1.08
Array 250000 set(125000) 0.31000 ns/op 0.28400 ns/op 1.09
Array 250000 iterate all - loop 58.396 us/op 55.000 us/op 1.06
phase0 afterProcessEpoch - 250000 vs - 7PWei 63.111 ms/op 48.210 ms/op 1.31
Array.fill - length 1000000 2.1795 ms/op 2.0232 ms/op 1.08
Array push - length 1000000 9.2564 ms/op 8.8386 ms/op 1.05
Array.get 0.20914 ns/op 0.19524 ns/op 1.07
Uint8Array.get 0.24421 ns/op 0.23182 ns/op 1.05
phase0 beforeProcessEpoch - 250000 vs - 7PWei 13.092 ms/op 17.850 ms/op 0.73
altair processEpoch - mainnet_e81889 300.64 ms/op 334.34 ms/op 0.90
mainnet_e81889 - altair beforeProcessEpoch 23.863 ms/op 35.815 ms/op 0.67
mainnet_e81889 - altair processJustificationAndFinalization 6.1760 us/op 6.2390 us/op 0.99
mainnet_e81889 - altair processInactivityUpdates 4.3038 ms/op 4.0025 ms/op 1.08
mainnet_e81889 - altair processRewardsAndPenalties 23.870 ms/op 16.257 ms/op 1.47
mainnet_e81889 - altair processRegistryUpdates 613.00 ns/op 535.00 ns/op 1.15
mainnet_e81889 - altair processSlashings 144.00 ns/op 126.00 ns/op 1.14
mainnet_e81889 - altair processEth1DataReset 149.00 ns/op 122.00 ns/op 1.22
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.6201 ms/op 4.6259 ms/op 0.35
mainnet_e81889 - altair processSlashingsReset 743.00 ns/op 701.00 ns/op 1.06
mainnet_e81889 - altair processRandaoMixesReset 1.5570 us/op 1.2570 us/op 1.24
mainnet_e81889 - altair processHistoricalRootsUpdate 144.00 ns/op 151.00 ns/op 0.95
mainnet_e81889 - altair processParticipationFlagUpdates 458.00 ns/op 406.00 ns/op 1.13
mainnet_e81889 - altair processSyncCommitteeUpdates 139.00 ns/op 104.00 ns/op 1.34
mainnet_e81889 - altair afterProcessEpoch 41.789 ms/op 41.223 ms/op 1.01
capella processEpoch - mainnet_e217614 850.78 ms/op 1.0139 s/op 0.84
mainnet_e217614 - capella beforeProcessEpoch 81.630 ms/op 59.996 ms/op 1.36
mainnet_e217614 - capella processJustificationAndFinalization 5.5870 us/op 6.8040 us/op 0.82
mainnet_e217614 - capella processInactivityUpdates 14.124 ms/op 18.148 ms/op 0.78
mainnet_e217614 - capella processRewardsAndPenalties 92.857 ms/op 107.29 ms/op 0.87
mainnet_e217614 - capella processRegistryUpdates 4.6240 us/op 4.3700 us/op 1.06
mainnet_e217614 - capella processSlashings 152.00 ns/op 129.00 ns/op 1.18
mainnet_e217614 - capella processEth1DataReset 147.00 ns/op 129.00 ns/op 1.14
mainnet_e217614 - capella processEffectiveBalanceUpdates 5.8826 ms/op 5.4493 ms/op 1.08
mainnet_e217614 - capella processSlashingsReset 707.00 ns/op 689.00 ns/op 1.03
mainnet_e217614 - capella processRandaoMixesReset 1.1260 us/op 1.2890 us/op 0.87
mainnet_e217614 - capella processHistoricalRootsUpdate 149.00 ns/op 131.00 ns/op 1.14
mainnet_e217614 - capella processParticipationFlagUpdates 452.00 ns/op 420.00 ns/op 1.08
mainnet_e217614 - capella afterProcessEpoch 107.50 ms/op 107.56 ms/op 1.00
phase0 processEpoch - mainnet_e58758 370.04 ms/op 306.43 ms/op 1.21
mainnet_e58758 - phase0 beforeProcessEpoch 89.319 ms/op 60.217 ms/op 1.48
mainnet_e58758 - phase0 processJustificationAndFinalization 7.4190 us/op 5.1310 us/op 1.45
mainnet_e58758 - phase0 processRewardsAndPenalties 18.421 ms/op 17.307 ms/op 1.06
mainnet_e58758 - phase0 processRegistryUpdates 2.3330 us/op 2.2090 us/op 1.06
mainnet_e58758 - phase0 processSlashings 147.00 ns/op 128.00 ns/op 1.15
mainnet_e58758 - phase0 processEth1DataReset 141.00 ns/op 127.00 ns/op 1.11
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.2021 ms/op 887.48 us/op 1.35
mainnet_e58758 - phase0 processSlashingsReset 1.0340 us/op 872.00 ns/op 1.19
mainnet_e58758 - phase0 processRandaoMixesReset 1.3680 us/op 1.2080 us/op 1.13
mainnet_e58758 - phase0 processHistoricalRootsUpdate 290.00 ns/op 136.00 ns/op 2.13
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.2940 us/op 1.0820 us/op 1.20
mainnet_e58758 - phase0 afterProcessEpoch 34.467 ms/op 32.999 ms/op 1.04
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.1137 ms/op 1.1199 ms/op 0.99
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 1.7907 ms/op 1.4845 ms/op 1.21
altair processInactivityUpdates - 250000 normalcase 11.460 ms/op 10.784 ms/op 1.06
altair processInactivityUpdates - 250000 worstcase 11.770 ms/op 11.143 ms/op 1.06
phase0 processRegistryUpdates - 250000 normalcase 2.3630 us/op 2.3570 us/op 1.00
phase0 processRegistryUpdates - 250000 badcase_full_deposits 150.03 us/op 150.55 us/op 1.00
phase0 processRegistryUpdates - 250000 worstcase 0.5 64.373 ms/op 54.398 ms/op 1.18
altair processRewardsAndPenalties - 250000 normalcase 17.167 ms/op 14.465 ms/op 1.19
altair processRewardsAndPenalties - 250000 worstcase 16.210 ms/op 14.172 ms/op 1.14
phase0 getAttestationDeltas - 250000 normalcase 5.5269 ms/op 5.3962 ms/op 1.02
phase0 getAttestationDeltas - 250000 worstcase 5.5719 ms/op 5.3942 ms/op 1.03
phase0 processSlashings - 250000 worstcase 62.931 us/op 57.844 us/op 1.09
altair processSyncCommitteeUpdates - 250000 10.307 ms/op 9.7485 ms/op 1.06
BeaconState.hashTreeRoot - No change 206.00 ns/op 188.00 ns/op 1.10
BeaconState.hashTreeRoot - 1 full validator 70.341 us/op 86.019 us/op 0.82
BeaconState.hashTreeRoot - 32 full validator 798.51 us/op 972.02 us/op 0.82
BeaconState.hashTreeRoot - 512 full validator 6.5276 ms/op 6.6711 ms/op 0.98
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 104.41 us/op 86.213 us/op 1.21
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.3758 ms/op 1.4260 ms/op 0.96
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 15.308 ms/op 22.114 ms/op 0.69
BeaconState.hashTreeRoot - 1 balances 72.134 us/op 89.574 us/op 0.81
BeaconState.hashTreeRoot - 32 balances 730.05 us/op 930.82 us/op 0.78
BeaconState.hashTreeRoot - 512 balances 5.1271 ms/op 5.2920 ms/op 0.97
BeaconState.hashTreeRoot - 250000 balances 108.02 ms/op 121.28 ms/op 0.89
aggregationBits - 2048 els - zipIndexesInBitList 20.391 us/op 18.522 us/op 1.10
regular array get 100000 times 23.653 us/op 22.682 us/op 1.04
wrappedArray get 100000 times 23.603 us/op 22.633 us/op 1.04
arrayWithProxy get 100000 times 9.8357 ms/op 9.7910 ms/op 1.00
ssz.Root.equals 21.890 ns/op 21.354 ns/op 1.03
byteArrayEquals 21.660 ns/op 21.146 ns/op 1.02
Buffer.compare 8.9560 ns/op 8.8010 ns/op 1.02
processSlot - 1 slots 9.7340 us/op 10.202 us/op 0.95
processSlot - 32 slots 2.3882 ms/op 2.6470 ms/op 0.90
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 5.2822 ms/op 4.8714 ms/op 1.08
getCommitteeAssignments - req 1 vs - 250000 vc 1.7073 ms/op 1.6618 ms/op 1.03
getCommitteeAssignments - req 100 vs - 250000 vc 3.5520 ms/op 3.4025 ms/op 1.04
getCommitteeAssignments - req 1000 vs - 250000 vc 3.8030 ms/op 3.6549 ms/op 1.04
findModifiedValidators - 10000 modified validators 916.72 ms/op 768.12 ms/op 1.19
findModifiedValidators - 1000 modified validators 553.63 ms/op 472.34 ms/op 1.17
findModifiedValidators - 100 modified validators 359.70 ms/op 258.59 ms/op 1.39
findModifiedValidators - 10 modified validators 273.44 ms/op 155.88 ms/op 1.75
findModifiedValidators - 1 modified validators 186.11 ms/op 153.95 ms/op 1.21
findModifiedValidators - no difference 194.81 ms/op 134.69 ms/op 1.45
migrate state 1500000 validators, 3400 modified, 2000 new 3.8337 s/op 3.6613 s/op 1.05
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 3.8000 ns/op 3.6200 ns/op 1.05
state getBlockRootAtSlot - 250000 vs - 7PWei 383.61 ns/op 476.59 ns/op 0.80
computeProposerIndex 100000 validators 1.3622 ms/op 1.2714 ms/op 1.07
getNextSyncCommitteeIndices 1000 validators 2.9324 ms/op 2.7206 ms/op 1.08
getNextSyncCommitteeIndices 10000 validators 25.676 ms/op 24.075 ms/op 1.07
getNextSyncCommitteeIndices 100000 validators 91.277 ms/op 83.009 ms/op 1.10
computeProposers - vc 250000 571.13 us/op 514.02 us/op 1.11
computeEpochShuffling - vc 250000 38.902 ms/op 39.423 ms/op 0.99
getNextSyncCommittee - vc 250000 9.6674 ms/op 9.4211 ms/op 1.03
nodejs block root to RootHex using toHex 100.32 ns/op 90.628 ns/op 1.11
nodejs block root to RootHex using toRootHex 62.863 ns/op 54.660 ns/op 1.15
nodejs fromHex(blob) 962.06 us/op 794.72 us/op 1.21
nodejs fromHexInto(blob) 637.89 us/op 623.59 us/op 1.02
nodejs block root to RootHex using the deprecated toHexString 489.09 ns/op 444.79 ns/op 1.10
nodejs byteArrayEquals 32 bytes (block root) 26.082 ns/op 24.696 ns/op 1.06
nodejs byteArrayEquals 48 bytes (pubkey) 37.805 ns/op 35.787 ns/op 1.06
nodejs byteArrayEquals 96 bytes (signature) 41.752 ns/op 32.763 ns/op 1.27
nodejs byteArrayEquals 1024 bytes 49.643 ns/op 46.234 ns/op 1.07
nodejs byteArrayEquals 131072 bytes (blob) 1.7575 us/op 1.6661 us/op 1.05
browser block root to RootHex using toHex 147.50 ns/op 137.60 ns/op 1.07
browser block root to RootHex using toRootHex 131.05 ns/op 125.25 ns/op 1.05
browser fromHex(blob) 1.6304 ms/op 1.5683 ms/op 1.04
browser fromHexInto(blob) 633.51 us/op 627.28 us/op 1.01
browser block root to RootHex using the deprecated toHexString 341.96 ns/op 480.72 ns/op 0.71
browser byteArrayEquals 32 bytes (block root) 28.040 ns/op 27.798 ns/op 1.01
browser byteArrayEquals 48 bytes (pubkey) 39.455 ns/op 39.190 ns/op 1.01
browser byteArrayEquals 96 bytes (signature) 73.789 ns/op 73.230 ns/op 1.01
browser byteArrayEquals 1024 bytes 754.27 ns/op 746.78 ns/op 1.01
browser byteArrayEquals 131072 bytes (blob) 94.805 us/op 94.211 us/op 1.01

by benchmarkbot/action

// [IGNORE] The block with root `dependent_root` has been seen by the node.
// Sync lookup only to not trigger disk reload from gossip input.
const cpEpoch = proposalEpoch - 1;
const checkpointState = chain.regen.getCheckpointStateSync({epoch: cpEpoch, rootHex: dependentRootHex});

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.

there is a tiny chance at the time of preparing for next epoch, head root is not the proposer root
and we don't have this checkpoint state in memory

maybe get head state first, make sure it has the view of this dependent root
then fallback to getting cp state this way

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.

right, I updated that, noticed we can use head state likely most of the time anyways, so it should cover the edge case you described, we only use getCheckpointStateSync if head state is not viable, the remaining question is if we should load from disk or not, but I think it's safer to not do that, also proposer preferences are only valid for current + next epoch, so we should have it cached

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.

the proposer look ahead is 2 epochs while we store checkpoint states of the last 3 epochs in memory so should not need that

wemeetagain
wemeetagain previously approved these changes Apr 30, 2026
@nflaig
nflaig enabled auto-merge (squash) April 30, 2026 08:08
wemeetagain
wemeetagain previously approved these changes Apr 30, 2026
for (const slot of this.validatorIndexesBySlot.keys()) {
if (slot < currentSlot) {
this.validatorIndexesBySlot.delete(slot);
for (const [dependentRoot, slotMap] of this.validatorBySlotByDependentRoot.entries()) {

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.

why not storing by slot as key of the 1st map? that would help pruning easier

@nflaig
nflaig merged commit 1a52372 into unstable Apr 30, 2026
18 of 19 checks passed
@nflaig
nflaig deleted the nflaig/dependent-root branch April 30, 2026 08:32
@codecov

codecov Bot commented Apr 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.59%. Comparing base (07452fe) to head (a43b12a).
⚠️ Report is 1 commits behind head on unstable.

Additional details and impacted files
@@            Coverage Diff            @@
##           unstable    #9303   +/-   ##
=========================================
  Coverage     52.59%   52.59%           
=========================================
  Files           848      848           
  Lines         61100    61100           
  Branches       4505     4505           
=========================================
  Hits          32135    32135           
  Misses        28901    28901           
  Partials         64       64           
🚀 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.

nflaig pushed a commit that referenced this pull request Apr 30, 2026
**Motivation**

As suggested by @twoeths in #9303, the current map nesting in
`SeenProposerPreferences` (`Map<dependentRoot, Map<slot,
validatorIndex>>`) makes pruning inefficient — it requires iterating
through every dependent root and checking each slot individually.

**Description**

Swaps the map nesting to `Map<slot, Map<dependentRoot, validatorIndex>>`
so that pruning can delete entire slot entries directly from the outer
map. No changes to the public API; `isKnown`, `add`, and `prune` all
retain their existing signatures and behavior.

Closes #9309

**AI Assistance Disclosure**

- [x] External Contributors: I have read the [contributor
guidelines](https://github.com/ChainSafe/lodestar/blob/unstable/CONTRIBUTING.md#ai-assistance-notice)
and disclosed my usage of AI below.

Used Claude to discuss the approach and review the implementation.

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@wemeetagain

Copy link
Copy Markdown
Member

🎉 This PR is included in v1.43.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.

3 participants