Skip to content

Conversation

@twoeths
Copy link
Contributor

@twoeths twoeths commented Jan 22, 2026

Motivation

Description

  • implement IBeaconStateView interface
  • implement the ts BeaconStateView

blocked by #8728 to build successfully

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @twoeths, 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 introduces a significant architectural improvement by implementing a BeaconStateView and its corresponding interface. This new abstraction layer encapsulates the complex BeaconState object, offering a simplified, read-only perspective that enhances code clarity and maintainability. By migrating existing state-accessing logic to this view, the PR aims to enforce better data encapsulation and prepare the codebase for future evolutions, particularly in areas like light client synchronization and state proof generation.

Highlights

  • Introduced BeaconStateView: A new class BeaconStateView and its interface IBeaconStateView have been added to provide a read-only, abstracted layer over the CachedBeaconStateAllForks. This promotes immutability and a cleaner API for state access.
  • Refactored State Access: Existing modules like processAttestationsAltair.ts, upgradeStateToAltair.ts, rootCache.ts, and shufflingDecisionRoot.ts have been updated to utilize the new IBeaconStateView interface, centralizing state interaction.
  • Light Client Proof Utilities: New files lightClient/proofs.ts and lightClient/types.ts were introduced to facilitate the generation of sync committee witnesses and proofs for various state components, crucial for light client functionality.
  • Type Enhancements: The capella/types.ts file now exports HistoricalSummaries, and validatorStatus.ts includes a new GeneralValidatorStatus type and a utility function mapToGeneralStatus for broader validator status categorization.

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

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.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

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 introduces the BeaconStateView interface and its implementation, providing a read-only facade over the CachedBeaconStateAllForks. This is a positive step towards encapsulating state access logic and improving maintainability. The changes also include refactoring RootCache and proposerShufflingDecisionRoot to utilize this new view, ensuring consistency. New types and utility functions for light client proofs and validator status mapping have also been added. Overall, the changes are well-structured and align with the goal of abstracting state access. There are a few areas identified for potential improvement regarding robustness and efficiency.

Comment on lines +21 to +25
const n2 = n1.left;
const n5 = n2.right;
const n10 = n5.left;
const n21 = n10.right;
const n43 = n21.right;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The direct access to n1.left, n2.right, etc., in getSyncCommitteesWitness relies heavily on the internal structure of the Tree and node properties. This makes the code brittle to future changes in the SSZ tree structure. If the SSZ structure is modified, these direct accesses could break silently or produce incorrect proofs, which is a critical correctness issue for light client proofs. It would be more robust to use explicit GINDEXes or a more abstract way to navigate the tree if available, or at least add comments explaining the gindex for each node access to make it easier to maintain.

Comment on lines +331 to +352
getValidatorsByStatus(statuses: Set<string>, currentEpoch: Epoch): phase0.Validator[] {
const validators: phase0.Validator[] = [];
const validatorsArr = this.cachedState.validators.getAllReadonlyValues();

for (const validator of validatorsArr) {
const validatorStatus = getValidatorStatus(validator, currentEpoch);
if (statuses.has(validatorStatus) || statuses.has(mapToGeneralStatus(validatorStatus))) {
validators.push(validator);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The getValidatorsByStatus method creates a new array validatorsArr by calling this.cachedState.validators.getAllReadonlyValues() on every invocation. If this method is called frequently and the validator list is large, this could lead to unnecessary memory allocations and performance overhead. Consider iterating directly over the cachedState.validators view or caching the getAllReadonlyValues() result if appropriate to improve efficiency.

@twoeths twoeths force-pushed the te/beacon_state_view_2 branch from 9bf8e0f to 6884d19 Compare January 26, 2026 07:14
@github-actions
Copy link
Contributor

github-actions bot commented Jan 26, 2026

⚠️ Performance Alert ⚠️

Possible performance regression was detected for some benchmarks.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold.

Benchmark suite Current: 36cbb0c Previous: 1067fed Ratio
200 bytes - uncompress - snappyjs 19.673 us/op 1.3812 us/op 14.24
Full benchmark results
Benchmark suite Current: 36cbb0c Previous: 1067fed Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 992.04 us/op 1.2360 ms/op 0.80
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 36.138 us/op 38.178 us/op 0.95
BLS verify - blst 848.29 us/op 905.34 us/op 0.94
BLS verifyMultipleSignatures 3 - blst 1.3415 ms/op 1.2364 ms/op 1.09
BLS verifyMultipleSignatures 8 - blst 2.0878 ms/op 1.9054 ms/op 1.10
BLS verifyMultipleSignatures 32 - blst 4.4428 ms/op 6.0126 ms/op 0.74
BLS verifyMultipleSignatures 64 - blst 8.2181 ms/op 10.736 ms/op 0.77
BLS verifyMultipleSignatures 128 - blst 15.699 ms/op 18.303 ms/op 0.86
BLS deserializing 10000 signatures 617.09 ms/op 690.93 ms/op 0.89
BLS deserializing 100000 signatures 6.1248 s/op 6.8847 s/op 0.89
BLS verifyMultipleSignatures - same message - 3 - blst 883.48 us/op 1.4622 ms/op 0.60
BLS verifyMultipleSignatures - same message - 8 - blst 1.0683 ms/op 1.0980 ms/op 0.97
BLS verifyMultipleSignatures - same message - 32 - blst 1.6226 ms/op 1.8420 ms/op 0.88
BLS verifyMultipleSignatures - same message - 64 - blst 2.5187 ms/op 2.7117 ms/op 0.93
BLS verifyMultipleSignatures - same message - 128 - blst 4.1786 ms/op 4.4528 ms/op 0.94
BLS aggregatePubkeys 32 - blst 17.945 us/op 18.938 us/op 0.95
BLS aggregatePubkeys 128 - blst 62.428 us/op 67.882 us/op 0.92
getSlashingsAndExits - default max 41.643 us/op 63.050 us/op 0.66
getSlashingsAndExits - 2k 317.24 us/op 303.55 us/op 1.05
isKnown best case - 1 super set check 410.00 ns/op 201.00 ns/op 2.04
isKnown normal case - 2 super set checks 388.00 ns/op 196.00 ns/op 1.98
isKnown worse case - 16 super set checks 397.00 ns/op 196.00 ns/op 2.03
InMemoryCheckpointStateCache - add get delete 2.0870 us/op 2.4480 us/op 0.85
validate api signedAggregateAndProof - struct 1.4520 ms/op 1.7310 ms/op 0.84
validate gossip signedAggregateAndProof - struct 1.7263 ms/op 1.7325 ms/op 1.00
batch validate gossip attestation - vc 640000 - chunk 32 105.26 us/op 115.27 us/op 0.91
batch validate gossip attestation - vc 640000 - chunk 64 90.443 us/op 101.93 us/op 0.89
batch validate gossip attestation - vc 640000 - chunk 128 82.955 us/op 96.397 us/op 0.86
batch validate gossip attestation - vc 640000 - chunk 256 80.776 us/op 89.536 us/op 0.90
bytes32 toHexString 497.00 ns/op 347.00 ns/op 1.43
bytes32 Buffer.toString(hex) 397.00 ns/op 243.00 ns/op 1.63
bytes32 Buffer.toString(hex) from Uint8Array 555.00 ns/op 433.00 ns/op 1.28
bytes32 Buffer.toString(hex) + 0x 403.00 ns/op 243.00 ns/op 1.66
Object access 1 prop 0.29700 ns/op 0.12600 ns/op 2.36
Map access 1 prop 0.30000 ns/op 0.12400 ns/op 2.42
Object get x1000 5.1120 ns/op 5.3640 ns/op 0.95
Map get x1000 0.51600 ns/op 0.37300 ns/op 1.38
Object set x1000 19.516 ns/op 28.533 ns/op 0.68
Map set x1000 16.194 ns/op 20.093 ns/op 0.81
Return object 10000 times 0.21970 ns/op 0.22860 ns/op 0.96
Throw Error 10000 times 3.0986 us/op 4.1264 us/op 0.75
toHex 91.402 ns/op 127.49 ns/op 0.72
Buffer.from 95.560 ns/op 118.91 ns/op 0.80
shared Buffer 57.293 ns/op 82.262 ns/op 0.70
fastMsgIdFn sha256 / 200 bytes 1.6850 us/op 1.8030 us/op 0.93
fastMsgIdFn h32 xxhash / 200 bytes 375.00 ns/op 211.00 ns/op 1.78
fastMsgIdFn h64 xxhash / 200 bytes 429.00 ns/op 292.00 ns/op 1.47
fastMsgIdFn sha256 / 1000 bytes 4.7960 us/op 5.9900 us/op 0.80
fastMsgIdFn h32 xxhash / 1000 bytes 459.00 ns/op 281.00 ns/op 1.63
fastMsgIdFn h64 xxhash / 1000 bytes 468.00 ns/op 366.00 ns/op 1.28
fastMsgIdFn sha256 / 10000 bytes 39.987 us/op 51.044 us/op 0.78
fastMsgIdFn h32 xxhash / 10000 bytes 1.4330 us/op 1.4040 us/op 1.02
fastMsgIdFn h64 xxhash / 10000 bytes 999.00 ns/op 946.00 ns/op 1.06
100 bytes - compress - snappyjs 1.0314 us/op 1.5040 us/op 0.69
100 bytes - compress - snappy 1.0392 us/op 1.0972 us/op 0.95
100 bytes - compress - snappy-wasm 1.0372 us/op 577.97 ns/op 1.79
100 bytes - compress - snappy-wasm - prealloc 1.8454 us/op 1.7987 us/op 1.03
200 bytes - compress - snappyjs 1.1974 us/op 1.5948 us/op 0.75
200 bytes - compress - snappy 1.1036 us/op 1.3442 us/op 0.82
200 bytes - compress - snappy-wasm 1.2109 us/op 990.36 ns/op 1.22
200 bytes - compress - snappy-wasm - prealloc 2.0070 us/op 1.8481 us/op 1.09
300 bytes - compress - snappyjs 2.5525 us/op 2.0784 us/op 1.23
300 bytes - compress - snappy 1.9652 us/op 1.6475 us/op 1.19
300 bytes - compress - snappy-wasm 1.1994 us/op 782.07 ns/op 1.53
300 bytes - compress - snappy-wasm - prealloc 1.6975 us/op 1.9833 us/op 0.86
400 bytes - compress - snappyjs 1.8664 us/op 1.9945 us/op 0.94
400 bytes - compress - snappy 1.3186 us/op 1.3474 us/op 0.98
400 bytes - compress - snappy-wasm 902.53 ns/op 1.0413 us/op 0.87
400 bytes - compress - snappy-wasm - prealloc 1.4119 us/op 1.2406 us/op 1.14
500 bytes - compress - snappyjs 2.3330 us/op 3.1205 us/op 0.75
500 bytes - compress - snappy 1.5018 us/op 1.4646 us/op 1.03
500 bytes - compress - snappy-wasm 1.9292 us/op 1.1232 us/op 1.72
500 bytes - compress - snappy-wasm - prealloc 2.4534 us/op 1.2325 us/op 1.99
1000 bytes - compress - snappyjs 4.9186 us/op 5.0622 us/op 0.97
1000 bytes - compress - snappy 1.4972 us/op 1.5490 us/op 0.97
1000 bytes - compress - snappy-wasm 3.7508 us/op 1.8039 us/op 2.08
1000 bytes - compress - snappy-wasm - prealloc 2.7931 us/op 2.0619 us/op 1.35
10000 bytes - compress - snappyjs 29.186 us/op 25.219 us/op 1.16
10000 bytes - compress - snappy 32.705 us/op 25.329 us/op 1.29
10000 bytes - compress - snappy-wasm 17.720 us/op 21.000 us/op 0.84
10000 bytes - compress - snappy-wasm - prealloc 26.427 us/op 19.117 us/op 1.38
100 bytes - uncompress - snappyjs 614.86 ns/op 989.83 ns/op 0.62
100 bytes - uncompress - snappy 1.1650 us/op 1.2222 us/op 0.95
100 bytes - uncompress - snappy-wasm 1.0624 us/op 1.0005 us/op 1.06
100 bytes - uncompress - snappy-wasm - prealloc 1.0394 us/op 1.1495 us/op 0.90
200 bytes - uncompress - snappyjs 19.673 us/op 1.3812 us/op 14.24
200 bytes - uncompress - snappy 1.1045 us/op 1.2487 us/op 0.88
200 bytes - uncompress - snappy-wasm 938.55 ns/op 1.1217 us/op 0.84
200 bytes - uncompress - snappy-wasm - prealloc 761.23 ns/op 1.3633 us/op 0.56
300 bytes - uncompress - snappyjs 896.21 ns/op 1.1030 us/op 0.81
300 bytes - uncompress - snappy 1.5620 us/op 1.2167 us/op 1.28
300 bytes - uncompress - snappy-wasm 1.0119 us/op 1.6512 us/op 0.61
300 bytes - uncompress - snappy-wasm - prealloc 1.1092 us/op 1.5985 us/op 0.69
400 bytes - uncompress - snappyjs 1.2847 us/op 1.9870 us/op 0.65
400 bytes - uncompress - snappy 1.6028 us/op 1.2432 us/op 1.29
400 bytes - uncompress - snappy-wasm 1.1042 us/op 959.04 ns/op 1.15
400 bytes - uncompress - snappy-wasm - prealloc 2.2069 us/op 1.1992 us/op 1.84
500 bytes - uncompress - snappyjs 2.0669 us/op 1.8773 us/op 1.10
500 bytes - uncompress - snappy 5.1943 us/op 2.1357 us/op 2.43
500 bytes - uncompress - snappy-wasm 1.6541 us/op 1.2307 us/op 1.34
500 bytes - uncompress - snappy-wasm - prealloc 1.6818 us/op 1.2069 us/op 1.39
1000 bytes - uncompress - snappyjs 3.3464 us/op 2.2944 us/op 1.46
1000 bytes - uncompress - snappy 1.5771 us/op 1.6124 us/op 0.98
1000 bytes - uncompress - snappy-wasm 1.4618 us/op 1.0270 us/op 1.42
1000 bytes - uncompress - snappy-wasm - prealloc 1.4516 us/op 1.3233 us/op 1.10
10000 bytes - uncompress - snappyjs 17.294 us/op 20.659 us/op 0.84
10000 bytes - uncompress - snappy 18.727 us/op 23.599 us/op 0.79
10000 bytes - uncompress - snappy-wasm 25.376 us/op 24.531 us/op 1.03
10000 bytes - uncompress - snappy-wasm - prealloc 21.374 us/op 19.195 us/op 1.11
send data - 1000 256B messages 17.172 ms/op 14.471 ms/op 1.19
send data - 1000 512B messages 15.960 ms/op 16.185 ms/op 0.99
send data - 1000 1024B messages 23.773 ms/op 21.399 ms/op 1.11
send data - 1000 1200B messages 24.356 ms/op 32.164 ms/op 0.76
send data - 1000 2048B messages 26.788 ms/op 25.919 ms/op 1.03
send data - 1000 4096B messages 42.692 ms/op 33.290 ms/op 1.28
send data - 1000 16384B messages 100.59 ms/op 127.22 ms/op 0.79
send data - 1000 65536B messages 383.96 ms/op 264.24 ms/op 1.45
enrSubnets - fastDeserialize 64 bits 1.0360 us/op 936.00 ns/op 1.11
enrSubnets - ssz BitVector 64 bits 619.00 ns/op 463.00 ns/op 1.34
enrSubnets - fastDeserialize 4 bits 326.00 ns/op 133.00 ns/op 2.45
enrSubnets - ssz BitVector 4 bits 547.00 ns/op 335.00 ns/op 1.63
prioritizePeers score -10:0 att 32-0.1 sync 2-0 214.53 us/op 310.58 us/op 0.69
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 295.80 us/op 258.31 us/op 1.15
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 384.91 us/op 554.10 us/op 0.69
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 666.90 us/op 831.44 us/op 0.80
prioritizePeers score 0:0 att 64-1 sync 4-1 865.26 us/op 875.49 us/op 0.99
array of 16000 items push then shift 1.3217 us/op 1.5801 us/op 0.84
LinkedList of 16000 items push then shift 8.3370 ns/op 7.1590 ns/op 1.16
array of 16000 items push then pop 72.294 ns/op 76.415 ns/op 0.95
LinkedList of 16000 items push then pop 8.7050 ns/op 7.0810 ns/op 1.23
array of 24000 items push then shift 1.9063 us/op 2.3991 us/op 0.79
LinkedList of 24000 items push then shift 7.3680 ns/op 7.4080 ns/op 0.99
array of 24000 items push then pop 93.929 ns/op 108.47 ns/op 0.87
LinkedList of 24000 items push then pop 6.4060 ns/op 7.0500 ns/op 0.91
intersect bitArray bitLen 8 4.8520 ns/op 5.7030 ns/op 0.85
intersect array and set length 8 29.744 ns/op 33.345 ns/op 0.89
intersect bitArray bitLen 128 26.248 ns/op 28.562 ns/op 0.92
intersect array and set length 128 498.30 ns/op 550.07 ns/op 0.91
bitArray.getTrueBitIndexes() bitLen 128 1.1620 us/op 1.2910 us/op 0.90
bitArray.getTrueBitIndexes() bitLen 248 1.9150 us/op 1.8050 us/op 1.06
bitArray.getTrueBitIndexes() bitLen 512 3.6790 us/op 4.7100 us/op 0.78
Full columns - reconstruct all 6 blobs 246.60 us/op 270.09 us/op 0.91
Full columns - reconstruct half of the blobs out of 6 121.27 us/op 122.61 us/op 0.99
Full columns - reconstruct single blob out of 6 34.829 us/op 31.151 us/op 1.12
Half columns - reconstruct all 6 blobs 262.91 ms/op 259.39 ms/op 1.01
Half columns - reconstruct half of the blobs out of 6 132.83 ms/op 131.10 ms/op 1.01
Half columns - reconstruct single blob out of 6 47.226 ms/op 48.193 ms/op 0.98
Full columns - reconstruct all 10 blobs 259.35 us/op 293.35 us/op 0.88
Full columns - reconstruct half of the blobs out of 10 177.06 us/op 158.26 us/op 1.12
Full columns - reconstruct single blob out of 10 36.850 us/op 31.682 us/op 1.16
Half columns - reconstruct all 10 blobs 410.55 ms/op 438.76 ms/op 0.94
Half columns - reconstruct half of the blobs out of 10 211.25 ms/op 221.78 ms/op 0.95
Half columns - reconstruct single blob out of 10 47.433 ms/op 48.888 ms/op 0.97
Full columns - reconstruct all 20 blobs 1.1239 ms/op 707.73 us/op 1.59
Full columns - reconstruct half of the blobs out of 20 306.90 us/op 287.11 us/op 1.07
Full columns - reconstruct single blob out of 20 28.963 us/op 30.285 us/op 0.96
Half columns - reconstruct all 20 blobs 815.63 ms/op 866.99 ms/op 0.94
Half columns - reconstruct half of the blobs out of 20 402.64 ms/op 434.54 ms/op 0.93
Half columns - reconstruct single blob out of 20 45.935 ms/op 47.785 ms/op 0.96
Set add up to 64 items then delete first 1.6695 us/op 2.0303 us/op 0.82
OrderedSet add up to 64 items then delete first 2.5100 us/op 2.9550 us/op 0.85
Set add up to 64 items then delete last 1.9103 us/op 2.2389 us/op 0.85
OrderedSet add up to 64 items then delete last 2.7857 us/op 3.3910 us/op 0.82
Set add up to 64 items then delete middle 1.8926 us/op 2.2806 us/op 0.83
OrderedSet add up to 64 items then delete middle 4.2280 us/op 4.9273 us/op 0.86
Set add up to 128 items then delete first 3.7473 us/op 4.6861 us/op 0.80
OrderedSet add up to 128 items then delete first 5.7026 us/op 6.6270 us/op 0.86
Set add up to 128 items then delete last 3.6228 us/op 4.5244 us/op 0.80
OrderedSet add up to 128 items then delete last 5.1281 us/op 6.8237 us/op 0.75
Set add up to 128 items then delete middle 3.3923 us/op 4.4173 us/op 0.77
OrderedSet add up to 128 items then delete middle 10.663 us/op 12.950 us/op 0.82
Set add up to 256 items then delete first 7.0325 us/op 9.8325 us/op 0.72
OrderedSet add up to 256 items then delete first 11.557 us/op 14.028 us/op 0.82
Set add up to 256 items then delete last 6.7877 us/op 9.4010 us/op 0.72
OrderedSet add up to 256 items then delete last 12.353 us/op 14.125 us/op 0.87
Set add up to 256 items then delete middle 7.0821 us/op 9.0241 us/op 0.78
OrderedSet add up to 256 items then delete middle 33.786 us/op 39.595 us/op 0.85
pass gossip attestations to forkchoice per slot 2.1121 ms/op 2.3961 ms/op 0.88
forkChoice updateHead vc 100000 bc 64 eq 0 434.74 us/op 474.46 us/op 0.92
forkChoice updateHead vc 600000 bc 64 eq 0 2.7436 ms/op 2.8342 ms/op 0.97
forkChoice updateHead vc 1000000 bc 64 eq 0 4.4629 ms/op 4.7150 ms/op 0.95
forkChoice updateHead vc 600000 bc 320 eq 0 2.6879 ms/op 2.8458 ms/op 0.94
forkChoice updateHead vc 600000 bc 1200 eq 0 2.6501 ms/op 2.8725 ms/op 0.92
forkChoice updateHead vc 600000 bc 7200 eq 0 2.8554 ms/op 3.1184 ms/op 0.92
forkChoice updateHead vc 600000 bc 64 eq 1000 2.8539 ms/op 3.2485 ms/op 0.88
forkChoice updateHead vc 600000 bc 64 eq 10000 2.9424 ms/op 3.3669 ms/op 0.87
forkChoice updateHead vc 600000 bc 64 eq 300000 7.2072 ms/op 8.6400 ms/op 0.83
computeDeltas 1400000 validators 0% inactive 13.087 ms/op 13.817 ms/op 0.95
computeDeltas 1400000 validators 10% inactive 12.589 ms/op 13.181 ms/op 0.96
computeDeltas 1400000 validators 20% inactive 11.405 ms/op 12.281 ms/op 0.93
computeDeltas 1400000 validators 50% inactive 8.2718 ms/op 9.6139 ms/op 0.86
computeDeltas 2100000 validators 0% inactive 19.467 ms/op 21.139 ms/op 0.92
computeDeltas 2100000 validators 10% inactive 18.972 ms/op 19.793 ms/op 0.96
computeDeltas 2100000 validators 20% inactive 17.427 ms/op 18.442 ms/op 0.94
computeDeltas 2100000 validators 50% inactive 12.922 ms/op 14.427 ms/op 0.90
altair processAttestation - 250000 vs - 7PWei normalcase 1.6680 ms/op 1.8611 ms/op 0.90
altair processAttestation - 250000 vs - 7PWei worstcase 2.4262 ms/op 2.7453 ms/op 0.88
altair processAttestation - setStatus - 1/6 committees join 89.209 us/op 113.90 us/op 0.78
altair processAttestation - setStatus - 1/3 committees join 186.32 us/op 224.48 us/op 0.83
altair processAttestation - setStatus - 1/2 committees join 263.31 us/op 316.12 us/op 0.83
altair processAttestation - setStatus - 2/3 committees join 337.43 us/op 393.48 us/op 0.86
altair processAttestation - setStatus - 4/5 committees join 523.02 us/op 556.19 us/op 0.94
altair processAttestation - setStatus - 100% committees join 582.74 us/op 656.32 us/op 0.89
altair processBlock - 250000 vs - 7PWei normalcase 2.8764 ms/op 3.4801 ms/op 0.83
altair processBlock - 250000 vs - 7PWei normalcase hashState 14.244 ms/op 16.438 ms/op 0.87
altair processBlock - 250000 vs - 7PWei worstcase 23.814 ms/op 24.852 ms/op 0.96
altair processBlock - 250000 vs - 7PWei worstcase hashState 55.023 ms/op 71.819 ms/op 0.77
phase0 processBlock - 250000 vs - 7PWei normalcase 1.2109 ms/op 1.5155 ms/op 0.80
phase0 processBlock - 250000 vs - 7PWei worstcase 18.988 ms/op 20.434 ms/op 0.93
altair processEth1Data - 250000 vs - 7PWei normalcase 301.17 us/op 354.46 us/op 0.85
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:16 5.2950 us/op 5.8600 us/op 0.90
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:220 34.303 us/op 59.027 us/op 0.58
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:43 9.3120 us/op 16.581 us/op 0.56
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:19 6.1330 us/op 7.4220 us/op 0.83
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1021 154.04 us/op 252.19 us/op 0.61
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11778 1.4168 ms/op 1.9562 ms/op 0.72
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.8766 ms/op 2.3838 ms/op 0.79
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.9510 ms/op 2.3811 ms/op 0.82
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 3.7905 ms/op 4.5787 ms/op 0.83
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 1.8558 ms/op 2.4749 ms/op 0.75
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 3.6893 ms/op 4.6275 ms/op 0.80
Tree 40 250000 create 326.11 ms/op 403.82 ms/op 0.81
Tree 40 250000 get(125000) 87.721 ns/op 123.04 ns/op 0.71
Tree 40 250000 set(125000) 986.56 ns/op 1.2060 us/op 0.82
Tree 40 250000 toArray() 16.333 ms/op 12.741 ms/op 1.28
Tree 40 250000 iterate all - toArray() + loop 14.544 ms/op 12.754 ms/op 1.14
Tree 40 250000 iterate all - get(i) 37.919 ms/op 42.450 ms/op 0.89
Array 250000 create 2.1330 ms/op 2.4888 ms/op 0.86
Array 250000 clone - spread 689.22 us/op 805.73 us/op 0.86
Array 250000 get(125000) 0.48500 ns/op 0.33600 ns/op 1.44
Array 250000 set(125000) 0.48600 ns/op 0.33800 ns/op 1.44
Array 250000 iterate all - loop 55.736 us/op 59.309 us/op 0.94
phase0 afterProcessEpoch - 250000 vs - 7PWei 38.473 ms/op 40.277 ms/op 0.96
Array.fill - length 1000000 2.4577 ms/op 2.7553 ms/op 0.89
Array push - length 1000000 10.103 ms/op 9.4066 ms/op 1.07
Array.get 0.19937 ns/op 0.21043 ns/op 0.95
Uint8Array.get 0.20074 ns/op 0.22103 ns/op 0.91
phase0 beforeProcessEpoch - 250000 vs - 7PWei 13.363 ms/op 12.528 ms/op 1.07
altair processEpoch - mainnet_e81889 195.07 ms/op 271.29 ms/op 0.72
mainnet_e81889 - altair beforeProcessEpoch 15.352 ms/op 14.850 ms/op 1.03
mainnet_e81889 - altair processJustificationAndFinalization 5.3100 us/op 5.3000 us/op 1.00
mainnet_e81889 - altair processInactivityUpdates 3.4317 ms/op 3.5590 ms/op 0.96
mainnet_e81889 - altair processRewardsAndPenalties 16.656 ms/op 18.221 ms/op 0.91
mainnet_e81889 - altair processRegistryUpdates 793.00 ns/op 651.00 ns/op 1.22
mainnet_e81889 - altair processSlashings 370.00 ns/op 165.00 ns/op 2.24
mainnet_e81889 - altair processEth1DataReset 364.00 ns/op 160.00 ns/op 2.27
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.3100 ms/op 1.9723 ms/op 0.66
mainnet_e81889 - altair processSlashingsReset 1.1160 us/op 801.00 ns/op 1.39
mainnet_e81889 - altair processRandaoMixesReset 1.1940 us/op 1.2050 us/op 0.99
mainnet_e81889 - altair processHistoricalRootsUpdate 360.00 ns/op 245.00 ns/op 1.47
mainnet_e81889 - altair processParticipationFlagUpdates 668.00 ns/op 519.00 ns/op 1.29
mainnet_e81889 - altair processSyncCommitteeUpdates 321.00 ns/op 172.00 ns/op 1.87
mainnet_e81889 - altair afterProcessEpoch 40.064 ms/op 54.746 ms/op 0.73
capella processEpoch - mainnet_e217614 699.25 ms/op 841.79 ms/op 0.83
mainnet_e217614 - capella beforeProcessEpoch 56.159 ms/op 74.254 ms/op 0.76
mainnet_e217614 - capella processJustificationAndFinalization 4.9700 us/op 5.8390 us/op 0.85
mainnet_e217614 - capella processInactivityUpdates 11.973 ms/op 13.864 ms/op 0.86
mainnet_e217614 - capella processRewardsAndPenalties 83.163 ms/op 106.93 ms/op 0.78
mainnet_e217614 - capella processRegistryUpdates 4.7160 us/op 5.6910 us/op 0.83
mainnet_e217614 - capella processSlashings 350.00 ns/op 271.00 ns/op 1.29
mainnet_e217614 - capella processEth1DataReset 348.00 ns/op 173.00 ns/op 2.01
mainnet_e217614 - capella processEffectiveBalanceUpdates 5.3726 ms/op 17.743 ms/op 0.30
mainnet_e217614 - capella processSlashingsReset 928.00 ns/op 821.00 ns/op 1.13
mainnet_e217614 - capella processRandaoMixesReset 1.1840 us/op 1.1270 us/op 1.05
mainnet_e217614 - capella processHistoricalRootsUpdate 424.00 ns/op 203.00 ns/op 2.09
mainnet_e217614 - capella processParticipationFlagUpdates 690.00 ns/op 573.00 ns/op 1.20
mainnet_e217614 - capella afterProcessEpoch 108.31 ms/op 113.26 ms/op 0.96
phase0 processEpoch - mainnet_e58758 243.65 ms/op 268.66 ms/op 0.91
mainnet_e58758 - phase0 beforeProcessEpoch 43.096 ms/op 48.141 ms/op 0.90
mainnet_e58758 - phase0 processJustificationAndFinalization 5.8910 us/op 8.2650 us/op 0.71
mainnet_e58758 - phase0 processRewardsAndPenalties 16.609 ms/op 21.271 ms/op 0.78
mainnet_e58758 - phase0 processRegistryUpdates 2.5580 us/op 2.6570 us/op 0.96
mainnet_e58758 - phase0 processSlashings 371.00 ns/op 171.00 ns/op 2.17
mainnet_e58758 - phase0 processEth1DataReset 366.00 ns/op 172.00 ns/op 2.13
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 870.60 us/op 1.1089 ms/op 0.79
mainnet_e58758 - phase0 processSlashingsReset 1.0660 us/op 824.00 ns/op 1.29
mainnet_e58758 - phase0 processRandaoMixesReset 1.3010 us/op 1.3270 us/op 0.98
mainnet_e58758 - phase0 processHistoricalRootsUpdate 345.00 ns/op 214.00 ns/op 1.61
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.1340 us/op 843.00 ns/op 1.35
mainnet_e58758 - phase0 afterProcessEpoch 31.772 ms/op 34.839 ms/op 0.91
phase0 processEffectiveBalanceUpdates - 250000 normalcase 991.02 us/op 1.0736 ms/op 0.92
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 1.4648 ms/op 1.4804 ms/op 0.99
altair processInactivityUpdates - 250000 normalcase 9.8361 ms/op 11.696 ms/op 0.84
altair processInactivityUpdates - 250000 worstcase 9.1767 ms/op 11.674 ms/op 0.79
phase0 processRegistryUpdates - 250000 normalcase 3.9260 us/op 7.5600 us/op 0.52
phase0 processRegistryUpdates - 250000 badcase_full_deposits 227.67 us/op 365.08 us/op 0.62
phase0 processRegistryUpdates - 250000 worstcase 0.5 57.368 ms/op 65.380 ms/op 0.88
altair processRewardsAndPenalties - 250000 normalcase 13.330 ms/op 21.444 ms/op 0.62
altair processRewardsAndPenalties - 250000 worstcase 16.297 ms/op 19.159 ms/op 0.85
phase0 getAttestationDeltas - 250000 normalcase 4.3860 ms/op 6.4021 ms/op 0.69
phase0 getAttestationDeltas - 250000 worstcase 4.3986 ms/op 6.6158 ms/op 0.66
phase0 processSlashings - 250000 worstcase 89.263 us/op 121.50 us/op 0.73
altair processSyncCommitteeUpdates - 250000 8.6095 ms/op 10.977 ms/op 0.78
BeaconState.hashTreeRoot - No change 366.00 ns/op 267.00 ns/op 1.37
BeaconState.hashTreeRoot - 1 full validator 86.108 us/op 90.379 us/op 0.95
BeaconState.hashTreeRoot - 32 full validator 923.46 us/op 848.44 us/op 1.09
BeaconState.hashTreeRoot - 512 full validator 6.3608 ms/op 7.4120 ms/op 0.86
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 112.09 us/op 113.70 us/op 0.99
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.4299 ms/op 1.7549 ms/op 0.81
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 13.313 ms/op 17.128 ms/op 0.78
BeaconState.hashTreeRoot - 1 balances 88.864 us/op 77.021 us/op 1.15
BeaconState.hashTreeRoot - 32 balances 765.92 us/op 843.22 us/op 0.91
BeaconState.hashTreeRoot - 512 balances 5.1986 ms/op 6.1045 ms/op 0.85
BeaconState.hashTreeRoot - 250000 balances 152.52 ms/op 167.03 ms/op 0.91
aggregationBits - 2048 els - zipIndexesInBitList 20.012 us/op 20.581 us/op 0.97
regular array get 100000 times 22.081 us/op 24.292 us/op 0.91
wrappedArray get 100000 times 22.130 us/op 24.280 us/op 0.91
arrayWithProxy get 100000 times 10.106 ms/op 17.467 ms/op 0.58
ssz.Root.equals 20.616 ns/op 23.412 ns/op 0.88
byteArrayEquals 20.084 ns/op 22.763 ns/op 0.88
Buffer.compare 8.5630 ns/op 9.7980 ns/op 0.87
processSlot - 1 slots 8.5980 us/op 12.207 us/op 0.70
processSlot - 32 slots 1.4843 ms/op 2.1399 ms/op 0.69
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 2.5881 ms/op 3.2871 ms/op 0.79
getCommitteeAssignments - req 1 vs - 250000 vc 1.6538 ms/op 1.8208 ms/op 0.91
getCommitteeAssignments - req 100 vs - 250000 vc 3.3775 ms/op 3.5943 ms/op 0.94
getCommitteeAssignments - req 1000 vs - 250000 vc 3.6298 ms/op 3.8471 ms/op 0.94
findModifiedValidators - 10000 modified validators 536.39 ms/op 550.27 ms/op 0.97
findModifiedValidators - 1000 modified validators 394.11 ms/op 499.12 ms/op 0.79
findModifiedValidators - 100 modified validators 244.80 ms/op 296.03 ms/op 0.83
findModifiedValidators - 10 modified validators 140.47 ms/op 236.90 ms/op 0.59
findModifiedValidators - 1 modified validators 151.98 ms/op 145.09 ms/op 1.05
findModifiedValidators - no difference 141.17 ms/op 171.47 ms/op 0.82
migrate state 1500000 validators, 3400 modified, 2000 new 876.37 ms/op 995.42 ms/op 0.88
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 5.4800 ns/op 4.1200 ns/op 1.33
state getBlockRootAtSlot - 250000 vs - 7PWei 515.07 ns/op 624.24 ns/op 0.83
computeProposerIndex 100000 validators 1.3136 ms/op 1.5525 ms/op 0.85
getNextSyncCommitteeIndices 1000 validators 94.470 ms/op 117.24 ms/op 0.81
getNextSyncCommitteeIndices 10000 validators 90.809 ms/op 117.42 ms/op 0.77
getNextSyncCommitteeIndices 100000 validators 90.491 ms/op 117.33 ms/op 0.77
computeProposers - vc 250000 564.34 us/op 657.65 us/op 0.86
computeEpochShuffling - vc 250000 37.526 ms/op 41.330 ms/op 0.91
getNextSyncCommittee - vc 250000 9.2711 ms/op 10.467 ms/op 0.89
nodejs block root to RootHex using toHex 114.15 ns/op 142.75 ns/op 0.80
nodejs block root to RootHex using toRootHex 75.235 ns/op 86.144 ns/op 0.87
nodejs fromHex(blob) 195.39 us/op 329.50 us/op 0.59
nodejs fromHexInto(blob) 651.56 us/op 676.64 us/op 0.96
nodejs block root to RootHex using the deprecated toHexString 528.41 ns/op 509.99 ns/op 1.04
browser block root to RootHex using toHex 274.90 ns/op 260.11 ns/op 1.06
browser block root to RootHex using toRootHex 130.17 ns/op 147.43 ns/op 0.88
browser fromHex(blob) 788.63 us/op 1.3659 ms/op 0.58
browser fromHexInto(blob) 667.80 us/op 688.65 us/op 0.97
browser block root to RootHex using the deprecated toHexString 364.68 ns/op 380.73 ns/op 0.96

by benchmarkbot/action

import {BeaconStateAllForks, CachedBeaconStateAllForks} from "../types.js";
import {SyncCommitteeWitness} from "./types.js";

export function getSyncCommitteesWitness(fork: ForkName, state: BeaconStateAllForks): SyncCommitteeWitness {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this was moved from

export function getSyncCommitteesWitness(fork: ForkName, state: BeaconStateAllForks): SyncCommitteeWitness {

although it does not look like it belongs to state-transition, it couples with BeaconStateAllForks and this is the only place we can leave it

@twoeths twoeths marked this pull request as ready for review January 26, 2026 11:17
@twoeths twoeths requested a review from a team as a code owner January 26, 2026 11:17
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.

2 participants