Skip to content

feat: integrate gossip validation spec tests - #8965

Merged
nflaig merged 9 commits into
unstablefrom
nflaig/gossip-validation-tests
Mar 3, 2026
Merged

feat: integrate gossip validation spec tests#8965
nflaig merged 9 commits into
unstablefrom
nflaig/gossip-validation-tests

Conversation

@nflaig

@nflaig nflaig commented Feb 27, 2026

Copy link
Copy Markdown
Member

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the robustness of the beacon node's gossip validation by integrating official Ethereum consensus specification tests. It introduces a dedicated testing framework to rigorously verify the handling of various gossip messages, such as blocks, attestations, and slashings, against the expected spec behavior. This ensures greater compliance with the protocol and improves the network's resilience against invalid or malicious messages.

Highlights

  • Attester Slashing Validation: Implemented an additional gossip-side check for attester slashings to ensure intersecting validators are currently slashable, aligning with spec requirements.
  • Block Validation Stricter Enforcement: Updated block validation logic to change the GossipAction from IGNORE to REJECT when a block is from a higher slot than its parent, enforcing stricter validation.
  • New Gossip Validation Test Framework: Introduced a new test utility file, gossipValidation.ts, which provides a comprehensive framework for running Ethereum consensus spec tests for various gossip topics, including a custom clock for simulating gossip disparity.
  • Integration of Spec Tests: Refactored networking.test.ts to integrate the new gossip validation spec tests, allowing for comprehensive testing of different gossip message types against the official specifications.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • packages/beacon-node/src/chain/validation/attesterSlashing.ts
    • Imported isSlashableValidator from @lodestar/state-transition.
    • Added a new validation check to ensure that at least one intersecting validator in an attester slashing is currently slashable, throwing an INVALID error if not.
  • packages/beacon-node/src/chain/validation/block.ts
    • Changed the GossipAction from IGNORE to REJECT for blocks that are from a higher slot than their parent, making this validation error more critical.
  • packages/beacon-node/test/spec/presets/networking.test.ts
    • Imported it, ForkName, describeDirectorySpecTest, readdirSyncSpec, runGossipValidationTest, and TestRunnerCustom.
    • Modified the networking test runner to handle specific gossip topics (gossip_beacon_block, gossip_beacon_aggregate_and_proof, etc.) using the new runGossipValidationTest utility.
    • Defined a set of SKIPPED_GOSSIP_TESTS with reasons for skipping certain gossip validation tests.
    • Updated the specTestIterator to use RunnerType.custom for networking tests.
  • packages/beacon-node/test/spec/utils/gossipValidation.ts
    • Added a new file containing the runGossipValidationTest function, which sets up a BeaconChain environment, loads test data (meta.yaml, ssz_snappy files), and iterates through messages to validate them against expected outcomes ("valid", "ignore", "reject").
    • Introduced GossipTestClock to simulate gossip clock disparity for accurate spec conformance testing.
    • Implemented helper functions loadMeta, loadSszSnappy, loadState, loadBlockRootHex, resolveFinalizedCheckpoint, setFinalizedCheckpoint, isDescendantAtFinalizedCheckpoint, and mapErrorToResult.
    • Included validateMessageForTopic to dispatch validation calls based on the gossip topic (block, aggregate, attestation, proposer slashing, attester slashing, voluntary exit).
Activity
  • No specific activity (comments, reviews, etc.) was provided in the context.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@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 gossip validation spec tests by introducing a new test runner and helper utilities. It also includes a couple of logic fixes in attesterSlashing and block validation to align with spec requirements. The new test infrastructure is comprehensive, setting up a full BeaconChain instance to run validation against. The changes look good overall. I've found one potential issue in the new test helper where its validation logic for block parents seems to diverge from the production implementation, which could lead to incorrect test failures. My detailed comment addresses this.

Comment thread packages/beacon-node/test/spec/utils/gossipValidation.ts Outdated
@github-actions

github-actions Bot commented Feb 27, 2026

Copy link
Copy Markdown
Contributor

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: af1a0b1 Previous: bb33751 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 1.0877 ms/op 1.0326 ms/op 1.05
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 39.026 us/op 36.373 us/op 1.07
BLS verify - blst 835.17 us/op 808.07 us/op 1.03
BLS verifyMultipleSignatures 3 - blst 2.2419 ms/op 1.1439 ms/op 1.96
BLS verifyMultipleSignatures 8 - blst 2.2560 ms/op 1.6141 ms/op 1.40
BLS verifyMultipleSignatures 32 - blst 7.3185 ms/op 4.8008 ms/op 1.52
BLS verifyMultipleSignatures 64 - blst 10.998 ms/op 8.8159 ms/op 1.25
BLS verifyMultipleSignatures 128 - blst 17.557 ms/op 16.823 ms/op 1.04
BLS deserializing 10000 signatures 693.65 ms/op 653.23 ms/op 1.06
BLS deserializing 100000 signatures 6.8500 s/op 6.5359 s/op 1.05
BLS verifyMultipleSignatures - same message - 3 - blst 871.59 us/op 876.73 us/op 0.99
BLS verifyMultipleSignatures - same message - 8 - blst 1.3175 ms/op 988.91 us/op 1.33
BLS verifyMultipleSignatures - same message - 32 - blst 1.6825 ms/op 1.6166 ms/op 1.04
BLS verifyMultipleSignatures - same message - 64 - blst 2.5529 ms/op 2.5074 ms/op 1.02
BLS verifyMultipleSignatures - same message - 128 - blst 4.2874 ms/op 4.1767 ms/op 1.03
BLS aggregatePubkeys 32 - blst 18.706 us/op 18.528 us/op 1.01
BLS aggregatePubkeys 128 - blst 66.313 us/op 66.227 us/op 1.00
getSlashingsAndExits - default max 64.730 us/op 63.870 us/op 1.01
getSlashingsAndExits - 2k 317.67 us/op 318.79 us/op 1.00
isKnown best case - 1 super set check 201.00 ns/op 209.00 ns/op 0.96
isKnown normal case - 2 super set checks 192.00 ns/op 207.00 ns/op 0.93
isKnown worse case - 16 super set checks 193.00 ns/op 206.00 ns/op 0.94
validate api signedAggregateAndProof - struct 1.4327 ms/op 1.3276 ms/op 1.08
validate gossip signedAggregateAndProof - struct 1.5303 ms/op 1.3533 ms/op 1.13
batch validate gossip attestation - vc 640000 - chunk 32 122.43 us/op 112.15 us/op 1.09
batch validate gossip attestation - vc 640000 - chunk 64 106.87 us/op 97.578 us/op 1.10
batch validate gossip attestation - vc 640000 - chunk 128 98.438 us/op 90.168 us/op 1.09
batch validate gossip attestation - vc 640000 - chunk 256 92.126 us/op 86.851 us/op 1.06
bytes32 toHexString 444.00 ns/op 369.00 ns/op 1.20
bytes32 Buffer.toString(hex) 284.00 ns/op 248.00 ns/op 1.15
bytes32 Buffer.toString(hex) from Uint8Array 327.00 ns/op 335.00 ns/op 0.98
bytes32 Buffer.toString(hex) + 0x 233.00 ns/op 245.00 ns/op 0.95
Return object 10000 times 0.22970 ns/op 0.22380 ns/op 1.03
Throw Error 10000 times 4.2170 us/op 4.2249 us/op 1.00
toHex 136.43 ns/op 136.90 ns/op 1.00
Buffer.from 124.47 ns/op 118.05 ns/op 1.05
shared Buffer 75.167 ns/op 82.648 ns/op 0.91
fastMsgIdFn sha256 / 200 bytes 1.9380 us/op 1.8200 us/op 1.06
fastMsgIdFn h32 xxhash / 200 bytes 196.00 ns/op 195.00 ns/op 1.01
fastMsgIdFn h64 xxhash / 200 bytes 341.00 ns/op 257.00 ns/op 1.33
fastMsgIdFn sha256 / 1000 bytes 6.1280 us/op 5.7950 us/op 1.06
fastMsgIdFn h32 xxhash / 1000 bytes 462.00 ns/op 284.00 ns/op 1.63
fastMsgIdFn h64 xxhash / 1000 bytes 309.00 ns/op 311.00 ns/op 0.99
fastMsgIdFn sha256 / 10000 bytes 53.273 us/op 51.453 us/op 1.04
fastMsgIdFn h32 xxhash / 10000 bytes 1.3630 us/op 1.3590 us/op 1.00
fastMsgIdFn h64 xxhash / 10000 bytes 1.1800 us/op 895.00 ns/op 1.32
send data - 1000 256B messages 5.3719 ms/op 4.8113 ms/op 1.12
send data - 1000 512B messages 5.0515 ms/op 4.5546 ms/op 1.11
send data - 1000 1024B messages 5.8916 ms/op 4.6644 ms/op 1.26
send data - 1000 1200B messages 5.9475 ms/op 4.4678 ms/op 1.33
send data - 1000 2048B messages 6.7659 ms/op 5.1774 ms/op 1.31
send data - 1000 4096B messages 9.5676 ms/op 6.1477 ms/op 1.56
send data - 1000 16384B messages 36.677 ms/op 32.793 ms/op 1.12
send data - 1000 65536B messages 93.322 ms/op 90.704 ms/op 1.03
enrSubnets - fastDeserialize 64 bits 905.00 ns/op 1.6170 us/op 0.56
enrSubnets - ssz BitVector 64 bits 316.00 ns/op 331.00 ns/op 0.95
enrSubnets - fastDeserialize 4 bits 129.00 ns/op 130.00 ns/op 0.99
enrSubnets - ssz BitVector 4 bits 341.00 ns/op 334.00 ns/op 1.02
prioritizePeers score -10:0 att 32-0.1 sync 2-0 272.99 us/op 231.12 us/op 1.18
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 251.88 us/op 283.68 us/op 0.89
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 420.64 us/op 378.61 us/op 1.11
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 684.08 us/op 699.38 us/op 0.98
prioritizePeers score 0:0 att 64-1 sync 4-1 943.06 us/op 871.83 us/op 1.08
array of 16000 items push then shift 1.5741 us/op 1.6667 us/op 0.94
LinkedList of 16000 items push then shift 7.1770 ns/op 7.9840 ns/op 0.90
array of 16000 items push then pop 73.468 ns/op 75.765 ns/op 0.97
LinkedList of 16000 items push then pop 6.9400 ns/op 7.2000 ns/op 0.96
array of 24000 items push then shift 2.3091 us/op 2.3761 us/op 0.97
LinkedList of 24000 items push then shift 7.2500 ns/op 7.7090 ns/op 0.94
array of 24000 items push then pop 102.71 ns/op 106.29 ns/op 0.97
LinkedList of 24000 items push then pop 6.9790 ns/op 7.2860 ns/op 0.96
intersect bitArray bitLen 8 5.5370 ns/op 5.6340 ns/op 0.98
intersect array and set length 8 34.602 ns/op 33.101 ns/op 1.05
intersect bitArray bitLen 128 28.067 ns/op 28.307 ns/op 0.99
intersect array and set length 128 540.58 ns/op 538.11 ns/op 1.00
bitArray.getTrueBitIndexes() bitLen 128 1.0310 us/op 1.0300 us/op 1.00
bitArray.getTrueBitIndexes() bitLen 248 2.1630 us/op 1.7900 us/op 1.21
bitArray.getTrueBitIndexes() bitLen 512 3.7230 us/op 3.8660 us/op 0.96
Full columns - reconstruct all 6 blobs 324.03 us/op 288.40 us/op 1.12
Full columns - reconstruct half of the blobs out of 6 105.47 us/op 119.66 us/op 0.88
Full columns - reconstruct single blob out of 6 32.975 us/op 32.471 us/op 1.02
Half columns - reconstruct all 6 blobs 262.60 ms/op 271.97 ms/op 0.97
Half columns - reconstruct half of the blobs out of 6 133.67 ms/op 137.83 ms/op 0.97
Half columns - reconstruct single blob out of 6 49.161 ms/op 50.972 ms/op 0.96
Full columns - reconstruct all 10 blobs 414.17 us/op 361.65 us/op 1.15
Full columns - reconstruct half of the blobs out of 10 159.24 us/op 172.16 us/op 0.92
Full columns - reconstruct single blob out of 10 30.294 us/op 31.121 us/op 0.97
Half columns - reconstruct all 10 blobs 437.67 ms/op 454.95 ms/op 0.96
Half columns - reconstruct half of the blobs out of 10 223.81 ms/op 227.86 ms/op 0.98
Half columns - reconstruct single blob out of 10 49.361 ms/op 53.501 ms/op 0.92
Full columns - reconstruct all 20 blobs 794.60 us/op 727.65 us/op 1.09
Full columns - reconstruct half of the blobs out of 20 264.44 us/op 344.41 us/op 0.77
Full columns - reconstruct single blob out of 20 31.141 us/op 32.123 us/op 0.97
Half columns - reconstruct all 20 blobs 881.67 ms/op 904.44 ms/op 0.97
Half columns - reconstruct half of the blobs out of 20 452.72 ms/op 452.41 ms/op 1.00
Half columns - reconstruct single blob out of 20 51.325 ms/op 51.840 ms/op 0.99
Set add up to 64 items then delete first 2.0613 us/op 2.0675 us/op 1.00
OrderedSet add up to 64 items then delete first 3.0441 us/op 3.0406 us/op 1.00
Set add up to 64 items then delete last 2.3316 us/op 2.3448 us/op 0.99
OrderedSet add up to 64 items then delete last 3.3061 us/op 3.5185 us/op 0.94
Set add up to 64 items then delete middle 2.3285 us/op 2.3750 us/op 0.98
OrderedSet add up to 64 items then delete middle 4.9715 us/op 5.0959 us/op 0.98
Set add up to 128 items then delete first 4.8690 us/op 4.7904 us/op 1.02
OrderedSet add up to 128 items then delete first 7.1378 us/op 6.9062 us/op 1.03
Set add up to 128 items then delete last 4.6554 us/op 4.7982 us/op 0.97
OrderedSet add up to 128 items then delete last 6.8020 us/op 7.0331 us/op 0.97
Set add up to 128 items then delete middle 4.5967 us/op 4.6227 us/op 0.99
OrderedSet add up to 128 items then delete middle 13.229 us/op 13.503 us/op 0.98
Set add up to 256 items then delete first 9.8015 us/op 10.223 us/op 0.96
OrderedSet add up to 256 items then delete first 15.398 us/op 15.076 us/op 1.02
Set add up to 256 items then delete last 9.7710 us/op 10.240 us/op 0.95
OrderedSet add up to 256 items then delete last 13.863 us/op 15.014 us/op 0.92
Set add up to 256 items then delete middle 9.4212 us/op 9.9108 us/op 0.95
OrderedSet add up to 256 items then delete middle 41.350 us/op 42.166 us/op 0.98
pass gossip attestations to forkchoice per slot 2.5051 ms/op 2.5735 ms/op 0.97
forkChoice updateHead vc 100000 bc 64 eq 0 494.62 us/op 482.88 us/op 1.02
forkChoice updateHead vc 600000 bc 64 eq 0 2.8935 ms/op 2.9261 ms/op 0.99
forkChoice updateHead vc 1000000 bc 64 eq 0 4.8173 ms/op 4.8190 ms/op 1.00
forkChoice updateHead vc 600000 bc 320 eq 0 2.9429 ms/op 2.8672 ms/op 1.03
forkChoice updateHead vc 600000 bc 1200 eq 0 2.9893 ms/op 2.9924 ms/op 1.00
forkChoice updateHead vc 600000 bc 7200 eq 0 3.2617 ms/op 3.3447 ms/op 0.98
forkChoice updateHead vc 600000 bc 64 eq 1000 3.3569 ms/op 3.3899 ms/op 0.99
forkChoice updateHead vc 600000 bc 64 eq 10000 3.4897 ms/op 3.5121 ms/op 0.99
forkChoice updateHead vc 600000 bc 64 eq 300000 9.1364 ms/op 8.4937 ms/op 1.08
computeDeltas 1400000 validators 0% inactive 14.307 ms/op 14.379 ms/op 0.99
computeDeltas 1400000 validators 10% inactive 13.416 ms/op 13.422 ms/op 1.00
computeDeltas 1400000 validators 20% inactive 12.493 ms/op 12.498 ms/op 1.00
computeDeltas 1400000 validators 50% inactive 9.7726 ms/op 9.8649 ms/op 0.99
computeDeltas 2100000 validators 0% inactive 21.479 ms/op 21.270 ms/op 1.01
computeDeltas 2100000 validators 10% inactive 20.101 ms/op 20.339 ms/op 0.99
computeDeltas 2100000 validators 20% inactive 18.693 ms/op 18.822 ms/op 0.99
computeDeltas 2100000 validators 50% inactive 14.620 ms/op 14.676 ms/op 1.00
altair processAttestation - 250000 vs - 7PWei normalcase 1.8302 ms/op 1.7900 ms/op 1.02
altair processAttestation - 250000 vs - 7PWei worstcase 2.6825 ms/op 2.6672 ms/op 1.01
altair processAttestation - setStatus - 1/6 committees join 116.46 us/op 143.81 us/op 0.81
altair processAttestation - setStatus - 1/3 committees join 228.93 us/op 250.97 us/op 0.91
altair processAttestation - setStatus - 1/2 committees join 318.91 us/op 352.39 us/op 0.90
altair processAttestation - setStatus - 2/3 committees join 411.19 us/op 442.74 us/op 0.93
altair processAttestation - setStatus - 4/5 committees join 567.88 us/op 620.42 us/op 0.92
altair processAttestation - setStatus - 100% committees join 664.76 us/op 748.03 us/op 0.89
altair processBlock - 250000 vs - 7PWei normalcase 3.5585 ms/op 5.1007 ms/op 0.70
altair processBlock - 250000 vs - 7PWei normalcase hashState 18.531 ms/op 22.708 ms/op 0.82
altair processBlock - 250000 vs - 7PWei worstcase 22.971 ms/op 29.384 ms/op 0.78
altair processBlock - 250000 vs - 7PWei worstcase hashState 62.175 ms/op 63.146 ms/op 0.98
phase0 processBlock - 250000 vs - 7PWei normalcase 2.0419 ms/op 2.2617 ms/op 0.90
phase0 processBlock - 250000 vs - 7PWei worstcase 27.532 ms/op 21.930 ms/op 1.26
altair processEth1Data - 250000 vs - 7PWei normalcase 370.62 us/op 377.29 us/op 0.98
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:16 9.4090 us/op 6.0320 us/op 1.56
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:220 40.390 us/op 38.406 us/op 1.05
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:43 15.054 us/op 10.789 us/op 1.40
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:19 10.445 us/op 6.8730 us/op 1.52
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1021 243.75 us/op 150.76 us/op 1.62
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11778 1.7480 ms/op 1.9220 ms/op 0.91
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 2.1936 ms/op 2.3717 ms/op 0.92
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 2.2138 ms/op 2.4009 ms/op 0.92
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 4.5107 ms/op 4.4760 ms/op 1.01
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.6189 ms/op 5.0220 ms/op 0.52
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.9527 ms/op 4.9652 ms/op 1.00
Tree 40 250000 create 394.13 ms/op 376.66 ms/op 1.05
Tree 40 250000 get(125000) 125.54 ns/op 128.35 ns/op 0.98
Tree 40 250000 set(125000) 1.2317 us/op 1.2659 us/op 0.97
Tree 40 250000 toArray() 13.932 ms/op 12.993 ms/op 1.07
Tree 40 250000 iterate all - toArray() + loop 14.220 ms/op 13.629 ms/op 1.04
Tree 40 250000 iterate all - get(i) 44.746 ms/op 45.648 ms/op 0.98
Array 250000 create 2.4741 ms/op 2.5338 ms/op 0.98
Array 250000 clone - spread 810.10 us/op 851.07 us/op 0.95
Array 250000 get(125000) 0.47800 ns/op 0.35800 ns/op 1.34
Array 250000 set(125000) 0.34500 ns/op 0.35900 ns/op 0.96
Array 250000 iterate all - loop 61.732 us/op 62.770 us/op 0.98
phase0 afterProcessEpoch - 250000 vs - 7PWei 40.256 ms/op 39.735 ms/op 1.01
Array.fill - length 1000000 2.9348 ms/op 2.8208 ms/op 1.04
Array push - length 1000000 9.2588 ms/op 9.6151 ms/op 0.96
Array.get 0.20916 ns/op 0.21724 ns/op 0.96
Uint8Array.get 0.22221 ns/op 0.22418 ns/op 0.99
phase0 beforeProcessEpoch - 250000 vs - 7PWei 12.637 ms/op 13.948 ms/op 0.91
altair processEpoch - mainnet_e81889 231.79 ms/op 254.21 ms/op 0.91
mainnet_e81889 - altair beforeProcessEpoch 21.040 ms/op 18.916 ms/op 1.11
mainnet_e81889 - altair processJustificationAndFinalization 6.6670 us/op 5.4860 us/op 1.22
mainnet_e81889 - altair processInactivityUpdates 3.8000 ms/op 3.7629 ms/op 1.01
mainnet_e81889 - altair processRewardsAndPenalties 21.820 ms/op 17.868 ms/op 1.22
mainnet_e81889 - altair processRegistryUpdates 643.00 ns/op 602.00 ns/op 1.07
mainnet_e81889 - altair processSlashings 215.00 ns/op 165.00 ns/op 1.30
mainnet_e81889 - altair processEth1DataReset 152.00 ns/op 165.00 ns/op 0.92
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.7727 ms/op 1.9976 ms/op 0.89
mainnet_e81889 - altair processSlashingsReset 767.00 ns/op 789.00 ns/op 0.97
mainnet_e81889 - altair processRandaoMixesReset 1.4340 us/op 1.0640 us/op 1.35
mainnet_e81889 - altair processHistoricalRootsUpdate 164.00 ns/op 164.00 ns/op 1.00
mainnet_e81889 - altair processParticipationFlagUpdates 630.00 ns/op 480.00 ns/op 1.31
mainnet_e81889 - altair processSyncCommitteeUpdates 130.00 ns/op 127.00 ns/op 1.02
mainnet_e81889 - altair afterProcessEpoch 43.764 ms/op 41.575 ms/op 1.05
capella processEpoch - mainnet_e217614 866.04 ms/op 781.07 ms/op 1.11
mainnet_e217614 - capella beforeProcessEpoch 59.622 ms/op 56.420 ms/op 1.06
mainnet_e217614 - capella processJustificationAndFinalization 5.5860 us/op 5.2150 us/op 1.07
mainnet_e217614 - capella processInactivityUpdates 14.344 ms/op 15.278 ms/op 0.94
mainnet_e217614 - capella processRewardsAndPenalties 110.50 ms/op 100.77 ms/op 1.10
mainnet_e217614 - capella processRegistryUpdates 5.7100 us/op 5.6920 us/op 1.00
mainnet_e217614 - capella processSlashings 164.00 ns/op 167.00 ns/op 0.98
mainnet_e217614 - capella processEth1DataReset 177.00 ns/op 165.00 ns/op 1.07
mainnet_e217614 - capella processEffectiveBalanceUpdates 11.886 ms/op 11.064 ms/op 1.07
mainnet_e217614 - capella processSlashingsReset 1.0970 us/op 792.00 ns/op 1.39
mainnet_e217614 - capella processRandaoMixesReset 1.4470 us/op 1.0640 us/op 1.36
mainnet_e217614 - capella processHistoricalRootsUpdate 315.00 ns/op 171.00 ns/op 1.84
mainnet_e217614 - capella processParticipationFlagUpdates 942.00 ns/op 509.00 ns/op 1.85
mainnet_e217614 - capella afterProcessEpoch 115.42 ms/op 113.03 ms/op 1.02
phase0 processEpoch - mainnet_e58758 261.80 ms/op 220.75 ms/op 1.19
mainnet_e58758 - phase0 beforeProcessEpoch 47.487 ms/op 48.069 ms/op 0.99
mainnet_e58758 - phase0 processJustificationAndFinalization 5.7640 us/op 5.3780 us/op 1.07
mainnet_e58758 - phase0 processRewardsAndPenalties 24.770 ms/op 18.341 ms/op 1.35
mainnet_e58758 - phase0 processRegistryUpdates 2.8380 us/op 2.7390 us/op 1.04
mainnet_e58758 - phase0 processSlashings 288.00 ns/op 166.00 ns/op 1.73
mainnet_e58758 - phase0 processEth1DataReset 171.00 ns/op 160.00 ns/op 1.07
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 933.82 us/op 887.93 us/op 1.05
mainnet_e58758 - phase0 processSlashingsReset 1.0880 us/op 863.00 ns/op 1.26
mainnet_e58758 - phase0 processRandaoMixesReset 1.1570 us/op 1.0700 us/op 1.08
mainnet_e58758 - phase0 processHistoricalRootsUpdate 244.00 ns/op 155.00 ns/op 1.57
mainnet_e58758 - phase0 processParticipationRecordUpdates 848.00 ns/op 851.00 ns/op 1.00
mainnet_e58758 - phase0 afterProcessEpoch 34.687 ms/op 34.999 ms/op 0.99
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.2938 ms/op 1.7378 ms/op 0.74
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 1.9446 ms/op 1.9587 ms/op 0.99
altair processInactivityUpdates - 250000 normalcase 13.302 ms/op 12.129 ms/op 1.10
altair processInactivityUpdates - 250000 worstcase 12.637 ms/op 11.922 ms/op 1.06
phase0 processRegistryUpdates - 250000 normalcase 5.1750 us/op 4.5260 us/op 1.14
phase0 processRegistryUpdates - 250000 badcase_full_deposits 361.83 us/op 181.31 us/op 2.00
phase0 processRegistryUpdates - 250000 worstcase 0.5 74.234 ms/op 63.640 ms/op 1.17
altair processRewardsAndPenalties - 250000 normalcase 16.929 ms/op 16.801 ms/op 1.01
altair processRewardsAndPenalties - 250000 worstcase 15.960 ms/op 16.295 ms/op 0.98
phase0 getAttestationDeltas - 250000 normalcase 6.7988 ms/op 6.4447 ms/op 1.05
phase0 getAttestationDeltas - 250000 worstcase 6.9305 ms/op 6.4942 ms/op 1.07
phase0 processSlashings - 250000 worstcase 120.53 us/op 76.250 us/op 1.58
altair processSyncCommitteeUpdates - 250000 11.010 ms/op 10.906 ms/op 1.01
BeaconState.hashTreeRoot - No change 196.00 ns/op 197.00 ns/op 0.99
BeaconState.hashTreeRoot - 1 full validator 81.534 us/op 76.115 us/op 1.07
BeaconState.hashTreeRoot - 32 full validator 865.21 us/op 1.0386 ms/op 0.83
BeaconState.hashTreeRoot - 512 full validator 7.6954 ms/op 7.7433 ms/op 0.99
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 110.39 us/op 100.71 us/op 1.10
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.8133 ms/op 1.5337 ms/op 1.18
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 18.120 ms/op 16.207 ms/op 1.12
BeaconState.hashTreeRoot - 1 balances 72.391 us/op 73.020 us/op 0.99
BeaconState.hashTreeRoot - 32 balances 884.06 us/op 869.05 us/op 1.02
BeaconState.hashTreeRoot - 512 balances 6.0209 ms/op 6.1932 ms/op 0.97
BeaconState.hashTreeRoot - 250000 balances 148.40 ms/op 136.05 ms/op 1.09
aggregationBits - 2048 els - zipIndexesInBitList 20.205 us/op 20.438 us/op 0.99
regular array get 100000 times 23.832 us/op 24.177 us/op 0.99
wrappedArray get 100000 times 23.918 us/op 24.086 us/op 0.99
arrayWithProxy get 100000 times 13.441 ms/op 14.560 ms/op 0.92
ssz.Root.equals 23.283 ns/op 23.310 ns/op 1.00
byteArrayEquals 23.235 ns/op 22.920 ns/op 1.01
Buffer.compare 9.8870 ns/op 9.7290 ns/op 1.02
processSlot - 1 slots 10.922 us/op 9.3260 us/op 1.17
processSlot - 32 slots 2.5160 ms/op 2.2793 ms/op 1.10
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 4.3053 ms/op 4.3132 ms/op 1.00
getCommitteeAssignments - req 1 vs - 250000 vc 1.8406 ms/op 1.8388 ms/op 1.00
getCommitteeAssignments - req 100 vs - 250000 vc 3.6587 ms/op 3.5901 ms/op 1.02
getCommitteeAssignments - req 1000 vs - 250000 vc 3.8860 ms/op 3.8602 ms/op 1.01
findModifiedValidators - 10000 modified validators 419.66 ms/op 545.68 ms/op 0.77
findModifiedValidators - 1000 modified validators 432.27 ms/op 521.72 ms/op 0.83
findModifiedValidators - 100 modified validators 295.75 ms/op 255.01 ms/op 1.16
findModifiedValidators - 10 modified validators 152.07 ms/op 145.92 ms/op 1.04
findModifiedValidators - 1 modified validators 139.45 ms/op 122.78 ms/op 1.14
findModifiedValidators - no difference 111.94 ms/op 145.36 ms/op 0.77
migrate state 1500000 validators, 3400 modified, 2000 new 1.0515 s/op 947.09 ms/op 1.11
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 4.2000 ns/op 3.9500 ns/op 1.06
state getBlockRootAtSlot - 250000 vs - 7PWei 525.00 ns/op 470.66 ns/op 1.12
computeProposerIndex 100000 validators 1.4876 ms/op 1.4867 ms/op 1.00
getNextSyncCommitteeIndices 1000 validators 117.38 ms/op 112.64 ms/op 1.04
getNextSyncCommitteeIndices 10000 validators 120.05 ms/op 112.05 ms/op 1.07
getNextSyncCommitteeIndices 100000 validators 119.30 ms/op 111.99 ms/op 1.07
computeProposers - vc 250000 628.14 us/op 585.88 us/op 1.07
computeEpochShuffling - vc 250000 41.841 ms/op 41.490 ms/op 1.01
getNextSyncCommittee - vc 250000 10.408 ms/op 10.483 ms/op 0.99
nodejs block root to RootHex using toHex 147.19 ns/op 135.71 ns/op 1.08
nodejs block root to RootHex using toRootHex 84.238 ns/op 86.810 ns/op 0.97
nodejs fromHex(blob) 223.24 us/op 296.21 us/op 0.75
nodejs fromHexInto(blob) 691.96 us/op 670.88 us/op 1.03
nodejs block root to RootHex using the deprecated toHexString 528.13 ns/op 509.33 ns/op 1.04
nodejs byteArrayEquals 32 bytes (block root) 28.116 ns/op 27.120 ns/op 1.04
nodejs byteArrayEquals 48 bytes (pubkey) 40.230 ns/op 38.796 ns/op 1.04
nodejs byteArrayEquals 96 bytes (signature) 40.738 ns/op 38.410 ns/op 1.06
nodejs byteArrayEquals 1024 bytes 46.547 ns/op 43.150 ns/op 1.08
nodejs byteArrayEquals 131072 bytes (blob) 1.8406 us/op 1.7785 us/op 1.03
browser block root to RootHex using toHex 160.97 ns/op 160.34 ns/op 1.00
browser block root to RootHex using toRootHex 151.48 ns/op 147.52 ns/op 1.03
browser fromHex(blob) 1.2640 ms/op 961.76 us/op 1.31
browser fromHexInto(blob) 723.33 us/op 693.93 us/op 1.04
browser block root to RootHex using the deprecated toHexString 388.82 ns/op 363.74 ns/op 1.07
browser byteArrayEquals 32 bytes (block root) 32.068 ns/op 30.168 ns/op 1.06
browser byteArrayEquals 48 bytes (pubkey) 44.580 ns/op 41.257 ns/op 1.08
browser byteArrayEquals 96 bytes (signature) 87.660 ns/op 81.390 ns/op 1.08
browser byteArrayEquals 1024 bytes 818.65 ns/op 762.15 ns/op 1.07
browser byteArrayEquals 131072 bytes (blob) 103.32 us/op 96.228 us/op 1.07

by benchmarkbot/action

@nflaig
nflaig marked this pull request as ready for review February 27, 2026 21:44
@nflaig
nflaig requested a review from a team as a code owner February 27, 2026 21:44

@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: 4d1e782f2a

ℹ️ 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/test/spec/utils/gossipValidation.ts
Comment thread packages/beacon-node/test/spec/utils/gossipValidation.ts
@nflaig
nflaig force-pushed the nflaig/gossip-validation-tests branch from d72f6ee to ab22b6c Compare February 27, 2026 22:13
This reverts commit ab22b6c.
@nflaig

nflaig commented Feb 27, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@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 Ethereum consensus gossip validation spec tests. A new test runner and supporting infrastructure have been added to execute these tests. The changes also include fixes to the gossip validation logic for attestations, attester slashings, and blocks to align with the consensus specs, which were likely identified while implementing the new tests. The changes are correct and improve spec compliance. The new test infrastructure is well-structured.

…8967)

Fixes all gossip validation spec test failures on
`nflaig/gossip-validation-tests`.

**Root cause:** Lodestar's custom YAML int parser (`loadYaml` via
`int.ts`) returns ALL integers as BigInt. The test harness was passing
these BigInts directly to arithmetic operations expecting Number,
causing `Cannot mix BigInt and other types` TypeErrors. Additionally,
`mapErrorToResult` didn't catch plain `Error` thrown by
`pubkeyCache.getOrThrow`, and `subnet_id` was passed as BigInt to
attestation validation.

**Fixes:**
- `Number()` conversions for BigInt YAML values: `genesisTime`,
`current_time_ms`, `offset_ms`, `epoch`, `subnet_id`
- `mapErrorToResult` catches all `Error` types (not just `TypeError |
RangeError`)
- Null guard for `finalized_checkpoint.epoch`

**Results:** 138/138 passing (74 gossip validation + 64 networking
utility)

---------

Co-authored-by: lodekeeper <lodekeeper@users.noreply.github.com>

@wemeetagain wemeetagain left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

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

looks good to me
@nflaig do we have to wait for a new spec test release to validate this?

@nflaig

nflaig commented Mar 3, 2026

Copy link
Copy Markdown
Member Author

looks good to me @nflaig do we have to wait for a new spec test release to validate this?

I've built the spec tests manually and we are passing 74/74 of the gossip validation tests, that said right now this is a no-op until the next spec release

there is no harm in already merging this, if spec test layout changes we need to adapt our test runner but that shouldn't be too much effort

@nflaig
nflaig merged commit 192806a into unstable Mar 3, 2026
24 of 25 checks passed
@nflaig
nflaig deleted the nflaig/gossip-validation-tests branch March 3, 2026 12:32
@codecov

codecov Bot commented Mar 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.26%. Comparing base (bb33751) to head (2686ee4).
⚠️ Report is 1 commits behind head on unstable.

Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #8965      +/-   ##
============================================
- Coverage     52.26%   52.26%   -0.01%     
============================================
  Files           848      848              
  Lines         62928    62926       -2     
  Branches       4639     4639              
============================================
- Hits          32891    32889       -2     
  Misses        29970    29970              
  Partials         67       67              
🚀 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.

lodekeeper pushed a commit to lodekeeper/lodestar that referenced this pull request Mar 13, 2026
@wemeetagain

Copy link
Copy Markdown
Member

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

4 participants