Skip to content

feat: only give proposer boost to canonical proposer#9313

Merged
ensi321 merged 5 commits into
unstablefrom
nc/proposer-boost-canonical-check
May 22, 2026
Merged

feat: only give proposer boost to canonical proposer#9313
ensi321 merged 5 commits into
unstablefrom
nc/proposer-boost-canonical-check

Conversation

@ensi321

@ensi321 ensi321 commented Apr 30, 2026

Copy link
Copy Markdown
Member

closes #9231

Per consensus-specs PR #4807, `update_proposer_boost_root` now only sets
`proposer_boost_root` when the imported block's `proposer_index` matches
the head state's expected proposer for the slot, so a divergent proposer
shuffling on a non-canonical fork cannot nullify proposer boost.

`onBlock` gains an `expectedProposerIndex` argument; `importBlock`
resolves it via `headState.currentProposers` / `nextProposers` (O(1),
backed by `state.proposerLookahead` post-fulu) — same fast path used by
the proposer-preferences gossip validator.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@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 onBlock method in the fork choice implementation to include an expectedProposerIndex parameter, which is used to restrict proposer boost to blocks from the expected proposer. Changes include updating the IForkChoice interface, the importBlock logic, and relevant tests. A review comment suggests refactoring the logic for determining the expected proposer index to avoid duplication between the main code and test utilities.

Comment on lines +120 to +126
let expectedProposerIndex: number | null = null;
const headState = this.getHeadState();
if (headState.epoch === blockEpoch) {
expectedProposerIndex = headState.currentProposers[blockSlot % SLOTS_PER_EPOCH];
} else if (headState.epoch + 1 === blockEpoch) {
expectedProposerIndex = headState.nextProposers[blockSlot % SLOTS_PER_EPOCH];
}

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.

medium

The logic for determining the expected proposer index from the head state is duplicated in packages/beacon-node/test/spec/utils/gossipValidation.ts. Consider encapsulating this logic into a shared helper function or using the existing state.getBeaconProposer(slot) method with appropriate error handling. This would improve maintainability and ensure consistency across the codebase when resolving proposers from a given state.

@github-actions

github-actions Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Performance Report

🚀🚀 Significant benchmark improvement detected

Benchmark suite Current: cd3ffe8 Previous: 6c85077 Ratio
Full columns - reconstruct all 20 blobs 492.83 us/op 1.5226 ms/op 0.32
Full benchmark results
Benchmark suite Current: cd3ffe8 Previous: 6c85077 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 879.25 us/op 1.3166 ms/op 0.67
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 39.786 us/op 42.333 us/op 0.94
BLS verify - blst 641.88 us/op 711.16 us/op 0.90
BLS verifyMultipleSignatures 3 - blst 1.3638 ms/op 1.3581 ms/op 1.00
BLS verifyMultipleSignatures 8 - blst 2.1843 ms/op 2.1719 ms/op 1.01
BLS verifyMultipleSignatures 32 - blst 6.8823 ms/op 6.9628 ms/op 0.99
BLS verifyMultipleSignatures 64 - blst 13.337 ms/op 13.266 ms/op 1.01
BLS verifyMultipleSignatures 128 - blst 26.034 ms/op 25.831 ms/op 1.01
BLS deserializing 10000 signatures 605.47 ms/op 636.33 ms/op 0.95
BLS deserializing 100000 signatures 6.1244 s/op 6.3870 s/op 0.96
BLS verifyMultipleSignatures - same message - 3 - blst 825.37 us/op 807.79 us/op 1.02
BLS verifyMultipleSignatures - same message - 8 - blst 901.62 us/op 894.05 us/op 1.01
BLS verifyMultipleSignatures - same message - 32 - blst 1.5442 ms/op 1.5540 ms/op 0.99
BLS verifyMultipleSignatures - same message - 64 - blst 2.3817 ms/op 2.4420 ms/op 0.98
BLS verifyMultipleSignatures - same message - 128 - blst 3.8902 ms/op 4.0683 ms/op 0.96
BLS aggregatePubkeys 32 - blst 16.884 us/op 17.498 us/op 0.96
BLS aggregatePubkeys 128 - blst 59.992 us/op 62.765 us/op 0.96
getSlashingsAndExits - default max 45.110 us/op 47.536 us/op 0.95
getSlashingsAndExits - 2k 327.80 us/op 359.26 us/op 0.91
proposeBlockBody type=full, size=empty 1.2322 ms/op 692.53 us/op 1.78
isKnown best case - 1 super set check 176.00 ns/op 171.00 ns/op 1.03
isKnown normal case - 2 super set checks 175.00 ns/op 163.00 ns/op 1.07
isKnown worse case - 16 super set checks 173.00 ns/op 162.00 ns/op 1.07
validate api signedAggregateAndProof - struct 1.5317 ms/op 1.5158 ms/op 1.01
validate gossip signedAggregateAndProof - struct 1.5270 ms/op 1.5113 ms/op 1.01
batch validate gossip attestation - vc 640000 - chunk 32 107.29 us/op 106.25 us/op 1.01
batch validate gossip attestation - vc 640000 - chunk 64 92.905 us/op 92.170 us/op 1.01
batch validate gossip attestation - vc 640000 - chunk 128 86.451 us/op 86.859 us/op 1.00
batch validate gossip attestation - vc 640000 - chunk 256 83.529 us/op 83.187 us/op 1.00
bytes32 toHexString 296.00 ns/op 285.00 ns/op 1.04
bytes32 Buffer.toString(hex) 167.00 ns/op 172.00 ns/op 0.97
bytes32 Buffer.toString(hex) from Uint8Array 237.00 ns/op 243.00 ns/op 0.98
bytes32 Buffer.toString(hex) + 0x 170.00 ns/op 172.00 ns/op 0.99
Return object 10000 times 0.21320 ns/op 0.21170 ns/op 1.01
Throw Error 10000 times 3.3734 us/op 3.2678 us/op 1.03
toHex 106.15 ns/op 101.58 ns/op 1.05
Buffer.from 88.047 ns/op 88.361 ns/op 1.00
shared Buffer 56.577 ns/op 61.700 ns/op 0.92
fastMsgIdFn sha256 / 200 bytes 1.5010 us/op 1.4730 us/op 1.02
fastMsgIdFn h32 xxhash / 200 bytes 159.00 ns/op 153.00 ns/op 1.04
fastMsgIdFn h64 xxhash / 200 bytes 202.00 ns/op 211.00 ns/op 0.96
fastMsgIdFn sha256 / 1000 bytes 4.8460 us/op 4.7170 us/op 1.03
fastMsgIdFn h32 xxhash / 1000 bytes 245.00 ns/op 244.00 ns/op 1.00
fastMsgIdFn h64 xxhash / 1000 bytes 256.00 ns/op 257.00 ns/op 1.00
fastMsgIdFn sha256 / 10000 bytes 42.299 us/op 41.582 us/op 1.02
fastMsgIdFn h32 xxhash / 10000 bytes 1.2940 us/op 1.2760 us/op 1.01
fastMsgIdFn h64 xxhash / 10000 bytes 841.00 ns/op 832.00 ns/op 1.01
send data - 1000 256B messages 4.1493 ms/op 4.1467 ms/op 1.00
send data - 1000 512B messages 4.5496 ms/op 4.2348 ms/op 1.07
send data - 1000 1024B messages 4.2903 ms/op 4.5559 ms/op 0.94
send data - 1000 1200B messages 4.4623 ms/op 4.6847 ms/op 0.95
send data - 1000 2048B messages 5.2957 ms/op 4.6401 ms/op 1.14
send data - 1000 4096B messages 5.6428 ms/op 5.5728 ms/op 1.01
send data - 1000 16384B messages 18.193 ms/op 19.935 ms/op 0.91
send data - 1000 65536B messages 189.76 ms/op 232.01 ms/op 0.82
enrSubnets - fastDeserialize 64 bits 753.00 ns/op 751.00 ns/op 1.00
enrSubnets - ssz BitVector 64 bits 263.00 ns/op 262.00 ns/op 1.00
enrSubnets - fastDeserialize 4 bits 106.00 ns/op 103.00 ns/op 1.03
enrSubnets - ssz BitVector 4 bits 270.00 ns/op 261.00 ns/op 1.03
prioritizePeers score -10:0 att 32-0.1 sync 2-0 200.25 us/op 208.44 us/op 0.96
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 244.53 us/op 234.34 us/op 1.04
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 351.41 us/op 361.49 us/op 0.97
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 595.43 us/op 603.29 us/op 0.99
prioritizePeers score 0:0 att 64-1 sync 4-1 718.48 us/op 700.91 us/op 1.03
array of 16000 items push then shift 1.1916 us/op 1.2996 us/op 0.92
LinkedList of 16000 items push then shift 7.1580 ns/op 6.8030 ns/op 1.05
array of 16000 items push then pop 66.541 ns/op 66.277 ns/op 1.00
LinkedList of 16000 items push then pop 5.6720 ns/op 5.9170 ns/op 0.96
array of 24000 items push then shift 1.7582 us/op 1.9304 us/op 0.91
LinkedList of 24000 items push then shift 6.7120 ns/op 6.5630 ns/op 1.02
array of 24000 items push then pop 91.067 ns/op 92.432 ns/op 0.99
LinkedList of 24000 items push then pop 5.7660 ns/op 5.9790 ns/op 0.96
intersect bitArray bitLen 8 4.5250 ns/op 4.7380 ns/op 0.96
intersect array and set length 8 27.747 ns/op 29.330 ns/op 0.95
intersect bitArray bitLen 128 22.797 ns/op 24.440 ns/op 0.93
intersect array and set length 128 495.61 ns/op 494.96 ns/op 1.00
bitArray.getTrueBitIndexes() bitLen 128 1.0700 us/op 1.0510 us/op 1.02
bitArray.getTrueBitIndexes() bitLen 248 1.7990 us/op 1.7710 us/op 1.02
bitArray.getTrueBitIndexes() bitLen 512 3.5670 us/op 3.5990 us/op 0.99
Full columns - reconstruct all 6 blobs 107.68 us/op 167.31 us/op 0.64
Full columns - reconstruct half of the blobs out of 6 195.66 us/op 97.485 us/op 2.01
Full columns - reconstruct single blob out of 6 32.923 us/op 35.435 us/op 0.93
Half columns - reconstruct all 6 blobs 385.92 ms/op 377.07 ms/op 1.02
Half columns - reconstruct half of the blobs out of 6 194.18 ms/op 192.52 ms/op 1.01
Half columns - reconstruct single blob out of 6 71.303 ms/op 66.868 ms/op 1.07
Full columns - reconstruct all 10 blobs 187.58 us/op 193.46 us/op 0.97
Full columns - reconstruct half of the blobs out of 10 103.53 us/op 111.90 us/op 0.93
Full columns - reconstruct single blob out of 10 32.601 us/op 32.103 us/op 1.02
Half columns - reconstruct all 10 blobs 643.76 ms/op 678.12 ms/op 0.95
Half columns - reconstruct half of the blobs out of 10 319.98 ms/op 338.76 ms/op 0.94
Half columns - reconstruct single blob out of 10 69.183 ms/op 72.393 ms/op 0.96
Full columns - reconstruct all 20 blobs 492.83 us/op 1.5226 ms/op 0.32
Full columns - reconstruct half of the blobs out of 20 169.13 us/op 214.09 us/op 0.79
Full columns - reconstruct single blob out of 20 30.306 us/op 33.486 us/op 0.91
Half columns - reconstruct all 20 blobs 1.2650 s/op 1.3028 s/op 0.97
Half columns - reconstruct half of the blobs out of 20 632.52 ms/op 648.52 ms/op 0.98
Half columns - reconstruct single blob out of 20 68.875 ms/op 69.243 ms/op 0.99
Set add up to 64 items then delete first 2.3602 us/op 2.7689 us/op 0.85
OrderedSet add up to 64 items then delete first 3.0998 us/op 3.5728 us/op 0.87
Set add up to 64 items then delete last 2.2012 us/op 2.4902 us/op 0.88
OrderedSet add up to 64 items then delete last 3.0559 us/op 3.3930 us/op 0.90
Set add up to 64 items then delete middle 1.9829 us/op 2.1874 us/op 0.91
OrderedSet add up to 64 items then delete middle 4.3949 us/op 4.8976 us/op 0.90
Set add up to 128 items then delete first 3.9232 us/op 4.4085 us/op 0.89
OrderedSet add up to 128 items then delete first 6.1108 us/op 6.7932 us/op 0.90
Set add up to 128 items then delete last 3.5796 us/op 4.1837 us/op 0.86
OrderedSet add up to 128 items then delete last 5.4233 us/op 5.8703 us/op 0.92
Set add up to 128 items then delete middle 3.5759 us/op 3.9395 us/op 0.91
OrderedSet add up to 128 items then delete middle 11.001 us/op 12.008 us/op 0.92
Set add up to 256 items then delete first 7.3045 us/op 8.0746 us/op 0.90
OrderedSet add up to 256 items then delete first 11.391 us/op 12.612 us/op 0.90
Set add up to 256 items then delete last 7.1201 us/op 7.8338 us/op 0.91
OrderedSet add up to 256 items then delete last 10.825 us/op 11.780 us/op 0.92
Set add up to 256 items then delete middle 7.0678 us/op 7.8055 us/op 0.91
OrderedSet add up to 256 items then delete middle 33.118 us/op 36.215 us/op 0.91
pass gossip attestations to forkchoice per slot 2.5448 ms/op 2.6267 ms/op 0.97
forkChoice updateHead vc 100000 bc 64 eq 0 492.12 us/op 417.24 us/op 1.18
forkChoice updateHead vc 600000 bc 64 eq 0 2.9095 ms/op 2.4301 ms/op 1.20
forkChoice updateHead vc 1000000 bc 64 eq 0 4.8794 ms/op 4.1039 ms/op 1.19
forkChoice updateHead vc 600000 bc 320 eq 0 2.9009 ms/op 2.4726 ms/op 1.17
forkChoice updateHead vc 600000 bc 1200 eq 0 2.9804 ms/op 2.5552 ms/op 1.17
forkChoice updateHead vc 600000 bc 7200 eq 0 3.3140 ms/op 2.9114 ms/op 1.14
forkChoice updateHead vc 600000 bc 64 eq 1000 3.5615 ms/op 3.0449 ms/op 1.17
forkChoice updateHead vc 600000 bc 64 eq 10000 3.6611 ms/op 3.1539 ms/op 1.16
forkChoice updateHead vc 600000 bc 64 eq 300000 7.8577 ms/op 7.0715 ms/op 1.11
computeDeltas 1400000 validators 0% inactive 14.480 ms/op 13.987 ms/op 1.04
computeDeltas 1400000 validators 10% inactive 13.070 ms/op 13.231 ms/op 0.99
computeDeltas 1400000 validators 20% inactive 12.065 ms/op 12.047 ms/op 1.00
computeDeltas 1400000 validators 50% inactive 9.4223 ms/op 8.9844 ms/op 1.05
computeDeltas 2100000 validators 0% inactive 20.671 ms/op 21.088 ms/op 0.98
computeDeltas 2100000 validators 10% inactive 19.560 ms/op 19.747 ms/op 0.99
computeDeltas 2100000 validators 20% inactive 18.154 ms/op 18.409 ms/op 0.99
computeDeltas 2100000 validators 50% inactive 14.099 ms/op 13.624 ms/op 1.03
altair processAttestation - 250000 vs - 7PWei normalcase 1.9058 ms/op 1.6824 ms/op 1.13
altair processAttestation - 250000 vs - 7PWei worstcase 2.5463 ms/op 2.4472 ms/op 1.04
altair processAttestation - setStatus - 1/6 committees join 96.578 us/op 103.00 us/op 0.94
altair processAttestation - setStatus - 1/3 committees join 191.79 us/op 210.03 us/op 0.91
altair processAttestation - setStatus - 1/2 committees join 276.86 us/op 299.83 us/op 0.92
altair processAttestation - setStatus - 2/3 committees join 359.65 us/op 379.87 us/op 0.95
altair processAttestation - setStatus - 4/5 committees join 488.09 us/op 510.79 us/op 0.96
altair processAttestation - setStatus - 100% committees join 593.03 us/op 598.49 us/op 0.99
altair processBlock - 250000 vs - 7PWei normalcase 3.8268 ms/op 2.8368 ms/op 1.35
altair processBlock - 250000 vs - 7PWei normalcase hashState 13.357 ms/op 11.494 ms/op 1.16
altair processBlock - 250000 vs - 7PWei worstcase 21.177 ms/op 20.026 ms/op 1.06
altair processBlock - 250000 vs - 7PWei worstcase hashState 45.274 ms/op 43.768 ms/op 1.03
phase0 processBlock - 250000 vs - 7PWei normalcase 1.4000 ms/op 1.2916 ms/op 1.08
phase0 processBlock - 250000 vs - 7PWei worstcase 18.126 ms/op 17.320 ms/op 1.05
altair processEth1Data - 250000 vs - 7PWei normalcase 317.58 us/op 294.50 us/op 1.08
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:16 3.0450 us/op 3.4640 us/op 0.88
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:220 19.610 us/op 20.881 us/op 0.94
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:43 5.5650 us/op 6.1150 us/op 0.91
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:19 3.4950 us/op 3.7350 us/op 0.94
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1021 93.826 us/op 92.792 us/op 1.01
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11778 1.4277 ms/op 1.4351 ms/op 0.99
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.8083 ms/op 1.8783 ms/op 0.96
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.7766 ms/op 1.8735 ms/op 0.95
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 3.7872 ms/op 3.7199 ms/op 1.02
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.0368 ms/op 2.1064 ms/op 0.97
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.7038 ms/op 3.9765 ms/op 1.18
Tree 40 250000 create 342.46 ms/op 328.76 ms/op 1.04
Tree 40 250000 get(125000) 102.94 ns/op 94.799 ns/op 1.09
Tree 40 250000 set(125000) 1.1232 us/op 1.0318 us/op 1.09
Tree 40 250000 toArray() 10.866 ms/op 10.088 ms/op 1.08
Tree 40 250000 iterate all - toArray() + loop 10.435 ms/op 9.8982 ms/op 1.05
Tree 40 250000 iterate all - get(i) 40.207 ms/op 38.560 ms/op 1.04
Array 250000 create 2.1542 ms/op 2.1680 ms/op 0.99
Array 250000 clone - spread 672.40 us/op 682.40 us/op 0.99
Array 250000 get(125000) 0.29200 ns/op 0.29600 ns/op 0.99
Array 250000 set(125000) 0.30000 ns/op 0.30500 ns/op 0.98
Array 250000 iterate all - loop 57.219 us/op 58.182 us/op 0.98
phase0 afterProcessEpoch - 250000 vs - 7PWei 39.011 ms/op 62.602 ms/op 0.62
Array.fill - length 1000000 2.1281 ms/op 2.3278 ms/op 0.91
Array push - length 1000000 7.3615 ms/op 8.9185 ms/op 0.83
Array.get 0.21315 ns/op 0.20692 ns/op 1.03
Uint8Array.get 0.23527 ns/op 0.25511 ns/op 0.92
phase0 beforeProcessEpoch - 250000 vs - 7PWei 16.216 ms/op 13.992 ms/op 1.16
altair processEpoch - mainnet_e81889 313.61 ms/op 260.89 ms/op 1.20
mainnet_e81889 - altair beforeProcessEpoch 22.713 ms/op 13.478 ms/op 1.69
mainnet_e81889 - altair processJustificationAndFinalization 8.1480 us/op 5.5350 us/op 1.47
mainnet_e81889 - altair processInactivityUpdates 4.8792 ms/op 3.5020 ms/op 1.39
mainnet_e81889 - altair processRewardsAndPenalties 19.592 ms/op 19.541 ms/op 1.00
mainnet_e81889 - altair processRegistryUpdates 519.00 ns/op 521.00 ns/op 1.00
mainnet_e81889 - altair processSlashings 132.00 ns/op 131.00 ns/op 1.01
mainnet_e81889 - altair processEth1DataReset 128.00 ns/op 126.00 ns/op 1.02
mainnet_e81889 - altair processEffectiveBalanceUpdates 4.8518 ms/op 1.7641 ms/op 2.75
mainnet_e81889 - altair processSlashingsReset 812.00 ns/op 703.00 ns/op 1.16
mainnet_e81889 - altair processRandaoMixesReset 1.4020 us/op 1.1610 us/op 1.21
mainnet_e81889 - altair processHistoricalRootsUpdate 129.00 ns/op 129.00 ns/op 1.00
mainnet_e81889 - altair processParticipationFlagUpdates 424.00 ns/op 444.00 ns/op 0.95
mainnet_e81889 - altair processSyncCommitteeUpdates 106.00 ns/op 105.00 ns/op 1.01
mainnet_e81889 - altair afterProcessEpoch 41.037 ms/op 40.484 ms/op 1.01
capella processEpoch - mainnet_e217614 979.28 ms/op 896.44 ms/op 1.09
mainnet_e217614 - capella beforeProcessEpoch 55.698 ms/op 57.859 ms/op 0.96
mainnet_e217614 - capella processJustificationAndFinalization 6.8670 us/op 5.7200 us/op 1.20
mainnet_e217614 - capella processInactivityUpdates 11.829 ms/op 14.391 ms/op 0.82
mainnet_e217614 - capella processRewardsAndPenalties 102.37 ms/op 100.77 ms/op 1.02
mainnet_e217614 - capella processRegistryUpdates 4.6310 us/op 4.5930 us/op 1.01
mainnet_e217614 - capella processSlashings 132.00 ns/op 134.00 ns/op 0.99
mainnet_e217614 - capella processEth1DataReset 126.00 ns/op 130.00 ns/op 0.97
mainnet_e217614 - capella processEffectiveBalanceUpdates 5.8131 ms/op 15.987 ms/op 0.36
mainnet_e217614 - capella processSlashingsReset 694.00 ns/op 698.00 ns/op 0.99
mainnet_e217614 - capella processRandaoMixesReset 1.3060 us/op 1.2880 us/op 1.01
mainnet_e217614 - capella processHistoricalRootsUpdate 130.00 ns/op 133.00 ns/op 0.98
mainnet_e217614 - capella processParticipationFlagUpdates 437.00 ns/op 438.00 ns/op 1.00
mainnet_e217614 - capella afterProcessEpoch 105.38 ms/op 109.54 ms/op 0.96
phase0 processEpoch - mainnet_e58758 334.53 ms/op 285.91 ms/op 1.17
mainnet_e58758 - phase0 beforeProcessEpoch 66.335 ms/op 55.317 ms/op 1.20
mainnet_e58758 - phase0 processJustificationAndFinalization 6.5050 us/op 5.5030 us/op 1.18
mainnet_e58758 - phase0 processRewardsAndPenalties 15.443 ms/op 15.420 ms/op 1.00
mainnet_e58758 - phase0 processRegistryUpdates 2.2950 us/op 2.2880 us/op 1.00
mainnet_e58758 - phase0 processSlashings 132.00 ns/op 389.00 ns/op 0.34
mainnet_e58758 - phase0 processEth1DataReset 132.00 ns/op 132.00 ns/op 1.00
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 878.52 us/op 846.65 us/op 1.04
mainnet_e58758 - phase0 processSlashingsReset 835.00 ns/op 1.1100 us/op 0.75
mainnet_e58758 - phase0 processRandaoMixesReset 1.3980 us/op 1.5700 us/op 0.89
mainnet_e58758 - phase0 processHistoricalRootsUpdate 290.00 ns/op 134.00 ns/op 2.16
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.3390 us/op 1.3460 us/op 0.99
mainnet_e58758 - phase0 afterProcessEpoch 32.679 ms/op 35.047 ms/op 0.93
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.0217 ms/op 1.2484 ms/op 0.82
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 1.8512 ms/op 1.6070 ms/op 1.15
altair processInactivityUpdates - 250000 normalcase 10.560 ms/op 10.943 ms/op 0.97
altair processInactivityUpdates - 250000 worstcase 10.288 ms/op 10.775 ms/op 0.95
phase0 processRegistryUpdates - 250000 normalcase 2.0970 us/op 2.2420 us/op 0.94
phase0 processRegistryUpdates - 250000 badcase_full_deposits 152.10 us/op 154.18 us/op 0.99
phase0 processRegistryUpdates - 250000 worstcase 0.5 57.681 ms/op 63.253 ms/op 0.91
altair processRewardsAndPenalties - 250000 normalcase 15.419 ms/op 15.051 ms/op 1.02
altair processRewardsAndPenalties - 250000 worstcase 15.204 ms/op 13.986 ms/op 1.09
phase0 getAttestationDeltas - 250000 normalcase 5.3485 ms/op 5.4072 ms/op 0.99
phase0 getAttestationDeltas - 250000 worstcase 7.4271 ms/op 5.4884 ms/op 1.35
phase0 processSlashings - 250000 worstcase 59.885 us/op 60.186 us/op 0.99
altair processSyncCommitteeUpdates - 250000 10.036 ms/op 10.255 ms/op 0.98
BeaconState.hashTreeRoot - No change 168.00 ns/op 178.00 ns/op 0.94
BeaconState.hashTreeRoot - 1 full validator 72.385 us/op 74.601 us/op 0.97
BeaconState.hashTreeRoot - 32 full validator 1.0256 ms/op 820.90 us/op 1.25
BeaconState.hashTreeRoot - 512 full validator 6.8571 ms/op 6.7983 ms/op 1.01
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 86.969 us/op 76.535 us/op 1.14
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.5141 ms/op 1.3131 ms/op 1.15
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 14.423 ms/op 14.181 ms/op 1.02
BeaconState.hashTreeRoot - 1 balances 84.756 us/op 67.310 us/op 1.26
BeaconState.hashTreeRoot - 32 balances 797.88 us/op 672.14 us/op 1.19
BeaconState.hashTreeRoot - 512 balances 5.0123 ms/op 5.5378 ms/op 0.91
BeaconState.hashTreeRoot - 250000 balances 158.19 ms/op 130.64 ms/op 1.21
aggregationBits - 2048 els - zipIndexesInBitList 19.816 us/op 19.977 us/op 0.99
regular array get 100000 times 22.774 us/op 22.903 us/op 0.99
wrappedArray get 100000 times 22.750 us/op 22.970 us/op 0.99
arrayWithProxy get 100000 times 10.292 ms/op 10.271 ms/op 1.00
ssz.Root.equals 21.583 ns/op 21.575 ns/op 1.00
byteArrayEquals 21.375 ns/op 21.390 ns/op 1.00
Buffer.compare 9.4140 ns/op 8.8850 ns/op 1.06
processSlot - 1 slots 8.7710 us/op 8.2300 us/op 1.07
processSlot - 32 slots 2.2737 ms/op 1.8109 ms/op 1.26
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 2.4800 ms/op 3.1413 ms/op 0.79
getCommitteeAssignments - req 1 vs - 250000 vc 1.5793 ms/op 1.6794 ms/op 0.94
getCommitteeAssignments - req 100 vs - 250000 vc 3.2743 ms/op 3.4233 ms/op 0.96
getCommitteeAssignments - req 1000 vs - 250000 vc 3.5258 ms/op 3.6877 ms/op 0.96
findModifiedValidators - 10000 modified validators 751.41 ms/op 765.77 ms/op 0.98
findModifiedValidators - 1000 modified validators 424.99 ms/op 486.94 ms/op 0.87
findModifiedValidators - 100 modified validators 253.21 ms/op 298.54 ms/op 0.85
findModifiedValidators - 10 modified validators 154.27 ms/op 175.95 ms/op 0.88
findModifiedValidators - 1 modified validators 164.37 ms/op 187.54 ms/op 0.88
findModifiedValidators - no difference 168.31 ms/op 191.01 ms/op 0.88
migrate state 1500000 validators, 3400 modified, 2000 new 3.5186 s/op 2.7784 s/op 1.27
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 3.8200 ns/op 3.7400 ns/op 1.02
state getBlockRootAtSlot - 250000 vs - 7PWei 516.94 ns/op 279.08 ns/op 1.85
computeProposerIndex 100000 validators 1.3175 ms/op 1.3263 ms/op 0.99
getNextSyncCommitteeIndices 1000 validators 2.7920 ms/op 2.8801 ms/op 0.97
getNextSyncCommitteeIndices 10000 validators 24.636 ms/op 25.414 ms/op 0.97
getNextSyncCommitteeIndices 100000 validators 87.572 ms/op 87.248 ms/op 1.00
computeProposers - vc 250000 519.96 us/op 545.46 us/op 0.95
computeEpochShuffling - vc 250000 38.590 ms/op 39.257 ms/op 0.98
getNextSyncCommittee - vc 250000 9.9082 ms/op 9.4190 ms/op 1.05
nodejs block root to RootHex using toHex 85.746 ns/op 97.349 ns/op 0.88
nodejs block root to RootHex using toRootHex 51.753 ns/op 60.717 ns/op 0.85
nodejs fromHex(blob) 856.29 us/op 768.49 us/op 1.11
nodejs fromHexInto(blob) 609.17 us/op 636.33 us/op 0.96
nodejs block root to RootHex using the deprecated toHexString 465.42 ns/op 548.86 ns/op 0.85
nodejs byteArrayEquals 32 bytes (block root) 25.918 ns/op 25.977 ns/op 1.00
nodejs byteArrayEquals 48 bytes (pubkey) 36.626 ns/op 37.579 ns/op 0.97
nodejs byteArrayEquals 96 bytes (signature) 32.581 ns/op 36.741 ns/op 0.89
nodejs byteArrayEquals 1024 bytes 39.158 ns/op 44.702 ns/op 0.88
nodejs byteArrayEquals 131072 bytes (blob) 1.7169 us/op 1.7526 us/op 0.98
browser block root to RootHex using toHex 141.22 ns/op 145.03 ns/op 0.97
browser block root to RootHex using toRootHex 127.78 ns/op 130.92 ns/op 0.98
browser fromHex(blob) 1.6619 ms/op 1.5678 ms/op 1.06
browser fromHexInto(blob) 615.32 us/op 645.98 us/op 0.95
browser block root to RootHex using the deprecated toHexString 331.83 ns/op 373.25 ns/op 0.89
browser byteArrayEquals 32 bytes (block root) 27.507 ns/op 28.278 ns/op 0.97
browser byteArrayEquals 48 bytes (pubkey) 39.027 ns/op 39.769 ns/op 0.98
browser byteArrayEquals 96 bytes (signature) 72.921 ns/op 74.276 ns/op 0.98
browser byteArrayEquals 1024 bytes 743.09 ns/op 760.09 ns/op 0.98
browser byteArrayEquals 131072 bytes (blob) 94.004 us/op 95.781 us/op 0.98

by benchmarkbot/action

The retroactive proposer-boost spec change from v1.7.0-alpha.1 is now
implemented, so `voting_source_beyond_two_epoch`,
`justified_update_always_if_better`, and `justified_update_not_realized_finality`
pass across all forks (altair → gloas, 21 fixtures total).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ensi321 ensi321 marked this pull request as ready for review May 1, 2026 07:46
@ensi321 ensi321 requested a review from a team as a code owner May 1, 2026 07:46
Comment thread packages/beacon-node/test/unit/chain/forkChoice/forkChoice.test.ts Outdated
Comment thread packages/beacon-node/src/chain/blocks/importBlock.ts Outdated

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

may want something like

getBeaconProposerOrNull(slot: Slot): ValidatorIndex | null {
  // or just call the current getBeaconProposer() and catch return null
  const epoch = computeEpochAtSlot(slot);
  if (epoch === this.currentShuffling.epoch) return this.proposers[slot % SLOTS_PER_EPOCH];
  if (epoch === this.nextEpoch) return this.getBeaconProposersNextEpoch()[slot % SLOTS_PER_EPOCH];
  return null;
}

and use that everywhere

looks good to me other than that

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

lgtm

@ensi321 ensi321 merged commit 055b83c into unstable May 22, 2026
24 of 26 checks passed
@ensi321 ensi321 deleted the nc/proposer-boost-canonical-check branch May 22, 2026 15:33
this.proposerBoostRoot === null
this.proposerBoostRoot === null &&
expectedProposerIndex !== null &&
block.proposerIndex === expectedProposerIndex

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 will be changed in ethereum/consensus-specs#5306 to use dependent root instead

@wemeetagain

Copy link
Copy Markdown
Member

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

Proposer reorg blocks if is_proposer_equivocation

4 participants