Skip to content

Conversation

@twoeths
Copy link
Contributor

@twoeths twoeths commented Jan 9, 2026

Motivation

  • currently state repositories (StateArchiveRepository + CheckpointStateRepository) tightly coupled with BeaconStateAllForks which make it hard when we migrate to a generic BeaconStateView (to be come later, see Decouple beacon-node and state-transition #8650)
  • so we need to let these repos to work with Uint8Array and let consumers decide how to create a type/view of BeaconState from there

Description

  • separate the abstract repository to be extended from a newly created BinaryRepository
  • then let StateArchiveRepository + CheckpointStateRepository to be extended from BinaryRepository
    • the benefit is consumer can only use methods in BinaryRepository, it's a compile time check, vs calling methods in Repository and throw runtime error which make it harder to detect errors
    • so we only need to validate this PR via compilation instead of having to launch a node to confirm, and it's tricky to detect error there
  • update consumers accordingly

Closes #8729

@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 focuses on generalizing state repositories to work with raw byte arrays instead of specific BeaconState types. This change facilitates future migrations to a more generic state view and improves error detection by enforcing repository method usage at compile time. The updates involve creating a BinaryRepository abstraction, modifying state retrieval methods, and updating consumers to handle Uint8Array state data.

Highlights

  • Decoupling State Repositories: The primary goal is to decouple state repositories (StateArchiveRepository and CheckpointStateRepository) from BeaconStateAllForks. This prepares the codebase for a future migration to a generic BeaconStateView.
  • BinaryRepository Abstraction: Introduces a new BinaryRepository class that the state repositories extend. This enforces that consumers only use methods available in BinaryRepository, providing a compile-time check and preventing runtime errors.
  • Consumer Updates: Updates consumers of the state repositories to work with Uint8Array, allowing them to decide how to create a type/view of BeaconState from the binary data.
  • State Retrieval Changes: Modifies getNearestState to retrieve state as Uint8Array and deserialize it using getStateTypeFromBytes. Removes getByRoot from BeaconChain as it's deemed not useful enough and encourages using getHistoricalStateBySlot for finalized states.
  • Init State Changes: Removes initStateFromDb function, likely due to the shift in how states are handled and retrieved.

🧠 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 effectively generalizes the state repositories (StateArchiveRepository and CheckpointStateRepository) by introducing a BinaryRepository base class. This decouples them from BeaconStateAllForks and allows them to work with raw Uint8Array data, which is a great improvement for flexibility and compile-time type safety. The refactoring in abstractRepository.ts is clean and separates concerns well. The consumer code has been updated accordingly, for instance by removing initStateFromDb and adjusting how states are retrieved. I have one suggestion to improve the type safety and readability of the decodeKey implementation in StateArchiveRepository.

/**
* Restore the latest beacon state from db
*/
export async function initStateFromDb(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

remove unused function

// returning 1 per 100s of states that are persisted in the archive state is not useful enough
// and it causes consumers having to loadState and createCachedBeaconState again
// if state is finalized, consumers need to use getHistoricalStateBySlot() api instead
return null;
Copy link
Contributor Author

Choose a reason for hiding this comment

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


const state = states[0];
const stateBytes = stateBytesArr[0];
const state = getStateTypeFromBytes(config, stateBytes).deserializeToViewDU(stateBytes);
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 code make it ready for us to migrate to BeaconStateView later

@github-actions
Copy link
Contributor

github-actions bot commented Jan 9, 2026

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: b109f38 Previous: 88333c8 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 1.3226 ms/op 1.2722 ms/op 1.04
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 52.811 us/op 39.485 us/op 1.34
BLS verify - blst 973.54 us/op 871.93 us/op 1.12
BLS verifyMultipleSignatures 3 - blst 1.4957 ms/op 1.2791 ms/op 1.17
BLS verifyMultipleSignatures 8 - blst 2.6488 ms/op 1.9310 ms/op 1.37
BLS verifyMultipleSignatures 32 - blst 7.1339 ms/op 5.6861 ms/op 1.25
BLS verifyMultipleSignatures 64 - blst 11.237 ms/op 11.001 ms/op 1.02
BLS verifyMultipleSignatures 128 - blst 20.359 ms/op 18.118 ms/op 1.12
BLS deserializing 10000 signatures 782.58 ms/op 703.32 ms/op 1.11
BLS deserializing 100000 signatures 7.5910 s/op 7.1807 s/op 1.06
BLS verifyMultipleSignatures - same message - 3 - blst 955.17 us/op 943.74 us/op 1.01
BLS verifyMultipleSignatures - same message - 8 - blst 1.1225 ms/op 1.1012 ms/op 1.02
BLS verifyMultipleSignatures - same message - 32 - blst 1.9166 ms/op 1.8910 ms/op 1.01
BLS verifyMultipleSignatures - same message - 64 - blst 2.9010 ms/op 2.6222 ms/op 1.11
BLS verifyMultipleSignatures - same message - 128 - blst 4.7418 ms/op 4.4856 ms/op 1.06
BLS aggregatePubkeys 32 - blst 21.343 us/op 19.903 us/op 1.07
BLS aggregatePubkeys 128 - blst 74.907 us/op 71.184 us/op 1.05
getSlashingsAndExits - default max 72.681 us/op 74.138 us/op 0.98
getSlashingsAndExits - 2k 335.62 us/op 347.12 us/op 0.97
isKnown best case - 1 super set check 207.00 ns/op 228.00 ns/op 0.91
isKnown normal case - 2 super set checks 202.00 ns/op 228.00 ns/op 0.89
isKnown worse case - 16 super set checks 203.00 ns/op 232.00 ns/op 0.88
InMemoryCheckpointStateCache - add get delete 2.4720 us/op 2.4940 us/op 0.99
validate api signedAggregateAndProof - struct 1.5046 ms/op 1.6322 ms/op 0.92
validate gossip signedAggregateAndProof - struct 1.5019 ms/op 1.6484 ms/op 0.91
batch validate gossip attestation - vc 640000 - chunk 32 127.23 us/op 133.47 us/op 0.95
batch validate gossip attestation - vc 640000 - chunk 64 127.71 us/op 124.67 us/op 1.02
batch validate gossip attestation - vc 640000 - chunk 128 104.84 us/op 109.61 us/op 0.96
batch validate gossip attestation - vc 640000 - chunk 256 98.949 us/op 97.681 us/op 1.01
bytes32 toHexString 370.00 ns/op 427.00 ns/op 0.87
bytes32 Buffer.toString(hex) 236.00 ns/op 284.00 ns/op 0.83
bytes32 Buffer.toString(hex) from Uint8Array 325.00 ns/op 369.00 ns/op 0.88
bytes32 Buffer.toString(hex) + 0x 239.00 ns/op 243.00 ns/op 0.98
Object access 1 prop 0.12200 ns/op 0.12300 ns/op 0.99
Map access 1 prop 0.12200 ns/op 0.12000 ns/op 1.02
Object get x1000 5.6540 ns/op 5.7690 ns/op 0.98
Map get x1000 0.38800 ns/op 0.38500 ns/op 1.01
Object set x1000 31.113 ns/op 31.090 ns/op 1.00
Map set x1000 21.627 ns/op 21.266 ns/op 1.02
Return object 10000 times 0.24080 ns/op 0.23630 ns/op 1.02
Throw Error 10000 times 4.2302 us/op 4.1924 us/op 1.01
toHex 139.62 ns/op 153.18 ns/op 0.91
Buffer.from 136.03 ns/op 132.44 ns/op 1.03
shared Buffer 79.129 ns/op 79.186 ns/op 1.00
fastMsgIdFn sha256 / 200 bytes 1.9020 us/op 1.8720 us/op 1.02
fastMsgIdFn h32 xxhash / 200 bytes 206.00 ns/op 203.00 ns/op 1.01
fastMsgIdFn h64 xxhash / 200 bytes 278.00 ns/op 280.00 ns/op 0.99
fastMsgIdFn sha256 / 1000 bytes 6.5230 us/op 6.1570 us/op 1.06
fastMsgIdFn h32 xxhash / 1000 bytes 300.00 ns/op 291.00 ns/op 1.03
fastMsgIdFn h64 xxhash / 1000 bytes 321.00 ns/op 345.00 ns/op 0.93
fastMsgIdFn sha256 / 10000 bytes 58.699 us/op 54.144 us/op 1.08
fastMsgIdFn h32 xxhash / 10000 bytes 1.4750 us/op 1.4390 us/op 1.03
fastMsgIdFn h64 xxhash / 10000 bytes 976.00 ns/op 943.00 ns/op 1.03
100 bytes - compress - snappyjs 1.3647 us/op 1.2551 us/op 1.09
100 bytes - compress - snappy 1.2531 us/op 1.2382 us/op 1.01
100 bytes - compress - snappy-wasm 766.32 ns/op 721.67 ns/op 1.06
100 bytes - compress - snappy-wasm - prealloc 1.0096 us/op 1.3288 us/op 0.76
200 bytes - compress - snappyjs 1.9146 us/op 1.9723 us/op 0.97
200 bytes - compress - snappy 1.5168 us/op 1.5041 us/op 1.01
200 bytes - compress - snappy-wasm 663.94 ns/op 1.4910 us/op 0.45
200 bytes - compress - snappy-wasm - prealloc 1.2267 us/op 1.5609 us/op 0.79
300 bytes - compress - snappyjs 2.0869 us/op 2.0254 us/op 1.03
300 bytes - compress - snappy 1.6428 us/op 1.5401 us/op 1.07
300 bytes - compress - snappy-wasm 865.46 ns/op 892.02 ns/op 0.97
300 bytes - compress - snappy-wasm - prealloc 1.8845 us/op 2.1913 us/op 0.86
400 bytes - compress - snappyjs 2.4632 us/op 2.8740 us/op 0.86
400 bytes - compress - snappy 1.4719 us/op 1.5015 us/op 0.98
400 bytes - compress - snappy-wasm 961.71 ns/op 1.0069 us/op 0.96
400 bytes - compress - snappy-wasm - prealloc 1.2607 us/op 1.2946 us/op 0.97
500 bytes - compress - snappyjs 3.3898 us/op 2.5984 us/op 1.30
500 bytes - compress - snappy 2.5956 us/op 1.6788 us/op 1.55
500 bytes - compress - snappy-wasm 1.5199 us/op 1.0525 us/op 1.44
500 bytes - compress - snappy-wasm - prealloc 2.3083 us/op 1.3295 us/op 1.74
1000 bytes - compress - snappyjs 5.2066 us/op 4.6398 us/op 1.12
1000 bytes - compress - snappy 1.8180 us/op 1.6374 us/op 1.11
1000 bytes - compress - snappy-wasm 2.3874 us/op 1.6260 us/op 1.47
1000 bytes - compress - snappy-wasm - prealloc 2.4857 us/op 2.3290 us/op 1.07
10000 bytes - compress - snappyjs 29.378 us/op 28.174 us/op 1.04
10000 bytes - compress - snappy 27.799 us/op 19.559 us/op 1.42
10000 bytes - compress - snappy-wasm 24.570 us/op 16.550 us/op 1.48
10000 bytes - compress - snappy-wasm - prealloc 32.155 us/op 16.283 us/op 1.97
100 bytes - uncompress - snappyjs 738.76 ns/op 743.25 ns/op 0.99
100 bytes - uncompress - snappy 1.1785 us/op 1.2219 us/op 0.96
100 bytes - uncompress - snappy-wasm 655.64 ns/op 678.14 ns/op 0.97
100 bytes - uncompress - snappy-wasm - prealloc 814.14 ns/op 996.95 ns/op 0.82
200 bytes - uncompress - snappyjs 1.1398 us/op 1.0071 us/op 1.13
200 bytes - uncompress - snappy 1.4076 us/op 1.3421 us/op 1.05
200 bytes - uncompress - snappy-wasm 948.47 ns/op 1.4241 us/op 0.67
200 bytes - uncompress - snappy-wasm - prealloc 1.5193 us/op 1.3733 us/op 1.11
300 bytes - uncompress - snappyjs 1.5962 us/op 1.2527 us/op 1.27
300 bytes - uncompress - snappy 1.3932 us/op 1.4251 us/op 0.98
300 bytes - uncompress - snappy-wasm 890.83 ns/op 750.22 ns/op 1.19
300 bytes - uncompress - snappy-wasm - prealloc 1.6142 us/op 1.3159 us/op 1.23
400 bytes - uncompress - snappyjs 2.0531 us/op 1.1987 us/op 1.71
400 bytes - uncompress - snappy 1.4196 us/op 1.2223 us/op 1.16
400 bytes - uncompress - snappy-wasm 1.0219 us/op 993.42 ns/op 1.03
400 bytes - uncompress - snappy-wasm - prealloc 1.2846 us/op 1.9561 us/op 0.66
500 bytes - uncompress - snappyjs 2.9596 us/op 1.6223 us/op 1.82
500 bytes - uncompress - snappy 4.1066 us/op 2.5220 us/op 1.63
500 bytes - uncompress - snappy-wasm 1.2407 us/op 997.42 ns/op 1.24
500 bytes - uncompress - snappy-wasm - prealloc 1.3700 us/op 1.2404 us/op 1.10
1000 bytes - uncompress - snappyjs 2.2522 us/op 2.4026 us/op 0.94
1000 bytes - uncompress - snappy 1.6945 us/op 1.4865 us/op 1.14
1000 bytes - uncompress - snappy-wasm 1.4091 us/op 1.3294 us/op 1.06
1000 bytes - uncompress - snappy-wasm - prealloc 1.6657 us/op 1.7035 us/op 0.98
10000 bytes - uncompress - snappyjs 25.308 us/op 31.320 us/op 0.81
10000 bytes - uncompress - snappy 28.961 us/op 27.850 us/op 1.04
10000 bytes - uncompress - snappy-wasm 14.362 us/op 32.753 us/op 0.44
10000 bytes - uncompress - snappy-wasm - prealloc 13.963 us/op 18.403 us/op 0.76
send data - 1000 256B messages 14.375 ms/op 17.834 ms/op 0.81
send data - 1000 512B messages 19.171 ms/op 18.272 ms/op 1.05
send data - 1000 1024B messages 24.281 ms/op 25.831 ms/op 0.94
send data - 1000 1200B messages 33.165 ms/op 32.006 ms/op 1.04
send data - 1000 2048B messages 28.874 ms/op 30.345 ms/op 0.95
send data - 1000 4096B messages 41.405 ms/op 38.367 ms/op 1.08
send data - 1000 16384B messages 105.77 ms/op 111.80 ms/op 0.95
send data - 1000 65536B messages 240.90 ms/op 285.22 ms/op 0.84
enrSubnets - fastDeserialize 64 bits 926.00 ns/op 925.00 ns/op 1.00
enrSubnets - ssz BitVector 64 bits 347.00 ns/op 375.00 ns/op 0.93
enrSubnets - fastDeserialize 4 bits 134.00 ns/op 164.00 ns/op 0.82
enrSubnets - ssz BitVector 4 bits 348.00 ns/op 358.00 ns/op 0.97
prioritizePeers score -10:0 att 32-0.1 sync 2-0 237.64 us/op 235.57 us/op 1.01
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 264.70 us/op 262.92 us/op 1.01
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 381.31 us/op 376.60 us/op 1.01
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 706.11 us/op 706.10 us/op 1.00
prioritizePeers score 0:0 att 64-1 sync 4-1 854.03 us/op 846.06 us/op 1.01
array of 16000 items push then shift 1.6550 us/op 1.6814 us/op 0.98
LinkedList of 16000 items push then shift 7.5370 ns/op 7.7920 ns/op 0.97
array of 16000 items push then pop 76.904 ns/op 82.781 ns/op 0.93
LinkedList of 16000 items push then pop 7.2500 ns/op 7.5140 ns/op 0.96
array of 24000 items push then shift 2.4562 us/op 2.4864 us/op 0.99
LinkedList of 24000 items push then shift 7.7100 ns/op 7.8540 ns/op 0.98
array of 24000 items push then pop 108.43 ns/op 109.18 ns/op 0.99
LinkedList of 24000 items push then pop 7.2680 ns/op 7.3470 ns/op 0.99
intersect bitArray bitLen 8 5.8810 ns/op 5.8150 ns/op 1.01
intersect array and set length 8 34.800 ns/op 34.255 ns/op 1.02
intersect bitArray bitLen 128 28.365 ns/op 29.262 ns/op 0.97
intersect array and set length 128 583.99 ns/op 569.10 ns/op 1.03
bitArray.getTrueBitIndexes() bitLen 128 1.0340 us/op 1.0410 us/op 0.99
bitArray.getTrueBitIndexes() bitLen 248 1.8060 us/op 1.7960 us/op 1.01
bitArray.getTrueBitIndexes() bitLen 512 3.7460 us/op 3.9170 us/op 0.96
Full columns - reconstruct all 6 blobs 268.52 us/op 283.10 us/op 0.95
Full columns - reconstruct half of the blobs out of 6 118.75 us/op 104.56 us/op 1.14
Full columns - reconstruct single blob out of 6 32.565 us/op 33.673 us/op 0.97
Half columns - reconstruct all 6 blobs 269.26 ms/op 287.39 ms/op 0.94
Half columns - reconstruct half of the blobs out of 6 135.20 ms/op 142.43 ms/op 0.95
Half columns - reconstruct single blob out of 6 49.952 ms/op 53.088 ms/op 0.94
Full columns - reconstruct all 10 blobs 278.33 us/op 401.90 us/op 0.69
Full columns - reconstruct half of the blobs out of 10 190.21 us/op 217.63 us/op 0.87
Full columns - reconstruct single blob out of 10 31.486 us/op 34.299 us/op 0.92
Half columns - reconstruct all 10 blobs 445.84 ms/op 471.59 ms/op 0.95
Half columns - reconstruct half of the blobs out of 10 224.28 ms/op 236.99 ms/op 0.95
Half columns - reconstruct single blob out of 10 49.381 ms/op 52.387 ms/op 0.94
Full columns - reconstruct all 20 blobs 736.36 us/op 1.1757 ms/op 0.63
Full columns - reconstruct half of the blobs out of 20 315.55 us/op 386.41 us/op 0.82
Full columns - reconstruct single blob out of 20 30.805 us/op 31.604 us/op 0.97
Half columns - reconstruct all 20 blobs 880.93 ms/op 910.65 ms/op 0.97
Half columns - reconstruct half of the blobs out of 20 442.30 ms/op 461.37 ms/op 0.96
Half columns - reconstruct single blob out of 20 49.938 ms/op 50.647 ms/op 0.99
Set add up to 64 items then delete first 2.0847 us/op 2.1301 us/op 0.98
OrderedSet add up to 64 items then delete first 3.0929 us/op 3.0703 us/op 1.01
Set add up to 64 items then delete last 2.3797 us/op 2.3142 us/op 1.03
OrderedSet add up to 64 items then delete last 3.5569 us/op 3.3705 us/op 1.06
Set add up to 64 items then delete middle 2.4124 us/op 2.3371 us/op 1.03
OrderedSet add up to 64 items then delete middle 5.2165 us/op 4.9298 us/op 1.06
Set add up to 128 items then delete first 4.8450 us/op 4.9137 us/op 0.99
OrderedSet add up to 128 items then delete first 6.9381 us/op 7.3665 us/op 0.94
Set add up to 128 items then delete last 4.8125 us/op 4.6619 us/op 1.03
OrderedSet add up to 128 items then delete last 7.1405 us/op 6.7700 us/op 1.05
Set add up to 128 items then delete middle 4.6416 us/op 4.6007 us/op 1.01
OrderedSet add up to 128 items then delete middle 13.497 us/op 13.755 us/op 0.98
Set add up to 256 items then delete first 10.400 us/op 10.545 us/op 0.99
OrderedSet add up to 256 items then delete first 14.771 us/op 15.818 us/op 0.93
Set add up to 256 items then delete last 9.8583 us/op 9.2912 us/op 1.06
OrderedSet add up to 256 items then delete last 14.895 us/op 13.990 us/op 1.06
Set add up to 256 items then delete middle 9.7515 us/op 9.2348 us/op 1.06
OrderedSet add up to 256 items then delete middle 41.376 us/op 40.715 us/op 1.02
pass gossip attestations to forkchoice per slot 2.5531 ms/op 2.5662 ms/op 0.99
forkChoice updateHead vc 100000 bc 64 eq 0 501.39 us/op 497.27 us/op 1.01
forkChoice updateHead vc 600000 bc 64 eq 0 3.0087 ms/op 2.9807 ms/op 1.01
forkChoice updateHead vc 1000000 bc 64 eq 0 4.9962 ms/op 4.9501 ms/op 1.01
forkChoice updateHead vc 600000 bc 320 eq 0 3.0149 ms/op 2.9721 ms/op 1.01
forkChoice updateHead vc 600000 bc 1200 eq 0 3.0420 ms/op 3.0759 ms/op 0.99
forkChoice updateHead vc 600000 bc 7200 eq 0 3.3107 ms/op 3.4450 ms/op 0.96
forkChoice updateHead vc 600000 bc 64 eq 1000 3.3739 ms/op 3.5658 ms/op 0.95
forkChoice updateHead vc 600000 bc 64 eq 10000 3.5445 ms/op 3.5346 ms/op 1.00
forkChoice updateHead vc 600000 bc 64 eq 300000 9.0716 ms/op 9.4761 ms/op 0.96
computeDeltas 1400000 validators 0% inactive 14.415 ms/op 14.621 ms/op 0.99
computeDeltas 1400000 validators 10% inactive 14.343 ms/op 13.488 ms/op 1.06
computeDeltas 1400000 validators 20% inactive 13.189 ms/op 12.748 ms/op 1.03
computeDeltas 1400000 validators 50% inactive 10.392 ms/op 9.9937 ms/op 1.04
computeDeltas 2100000 validators 0% inactive 22.374 ms/op 21.899 ms/op 1.02
computeDeltas 2100000 validators 10% inactive 20.637 ms/op 20.478 ms/op 1.01
computeDeltas 2100000 validators 20% inactive 19.963 ms/op 19.156 ms/op 1.04
computeDeltas 2100000 validators 50% inactive 15.301 ms/op 15.076 ms/op 1.01
altair processAttestation - 250000 vs - 7PWei normalcase 1.9169 ms/op 2.0023 ms/op 0.96
altair processAttestation - 250000 vs - 7PWei worstcase 2.6984 ms/op 3.0423 ms/op 0.89
altair processAttestation - setStatus - 1/6 committees join 119.94 us/op 140.71 us/op 0.85
altair processAttestation - setStatus - 1/3 committees join 236.91 us/op 245.84 us/op 0.96
altair processAttestation - setStatus - 1/2 committees join 329.77 us/op 362.39 us/op 0.91
altair processAttestation - setStatus - 2/3 committees join 424.75 us/op 441.87 us/op 0.96
altair processAttestation - setStatus - 4/5 committees join 582.73 us/op 609.31 us/op 0.96
altair processAttestation - setStatus - 100% committees join 697.99 us/op 763.16 us/op 0.91
altair processBlock - 250000 vs - 7PWei normalcase 4.2081 ms/op 4.5449 ms/op 0.93
altair processBlock - 250000 vs - 7PWei normalcase hashState 18.798 ms/op 19.231 ms/op 0.98
altair processBlock - 250000 vs - 7PWei worstcase 24.213 ms/op 26.056 ms/op 0.93
altair processBlock - 250000 vs - 7PWei worstcase hashState 56.899 ms/op 59.286 ms/op 0.96
phase0 processBlock - 250000 vs - 7PWei normalcase 1.5012 ms/op 1.7488 ms/op 0.86
phase0 processBlock - 250000 vs - 7PWei worstcase 22.113 ms/op 19.974 ms/op 1.11
altair processEth1Data - 250000 vs - 7PWei normalcase 369.69 us/op 379.71 us/op 0.97
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:15 7.1870 us/op 8.1520 us/op 0.88
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:219 43.314 us/op 47.781 us/op 0.91
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:42 10.560 us/op 15.901 us/op 0.66
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:18 6.8480 us/op 9.6840 us/op 0.71
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1020 183.98 us/op 156.17 us/op 1.18
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11777 1.9325 ms/op 3.6100 ms/op 0.54
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 2.4454 ms/op 2.9349 ms/op 0.83
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 2.4489 ms/op 2.2823 ms/op 1.07
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 4.6869 ms/op 4.8207 ms/op 0.97
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.4717 ms/op 2.3362 ms/op 1.06
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.7391 ms/op 4.7886 ms/op 0.99
Tree 40 250000 create 420.30 ms/op 379.67 ms/op 1.11
Tree 40 250000 get(125000) 124.65 ns/op 122.66 ns/op 1.02
Tree 40 250000 set(125000) 1.4120 us/op 1.1998 us/op 1.18
Tree 40 250000 toArray() 16.469 ms/op 12.632 ms/op 1.30
Tree 40 250000 iterate all - toArray() + loop 16.969 ms/op 12.421 ms/op 1.37
Tree 40 250000 iterate all - get(i) 45.690 ms/op 41.876 ms/op 1.09
Array 250000 create 2.5330 ms/op 2.5091 ms/op 1.01
Array 250000 clone - spread 819.72 us/op 824.93 us/op 0.99
Array 250000 get(125000) 0.34400 ns/op 0.35000 ns/op 0.98
Array 250000 set(125000) 0.35600 ns/op 0.42900 ns/op 0.83
Array 250000 iterate all - loop 62.380 us/op 61.808 us/op 1.01
phase0 afterProcessEpoch - 250000 vs - 7PWei 42.180 ms/op 42.948 ms/op 0.98
Array.fill - length 1000000 2.8784 ms/op 3.2803 ms/op 0.88
Array push - length 1000000 10.308 ms/op 11.946 ms/op 0.86
Array.get 0.22182 ns/op 0.21807 ns/op 1.02
Uint8Array.get 0.23563 ns/op 0.22105 ns/op 1.07
phase0 beforeProcessEpoch - 250000 vs - 7PWei 15.888 ms/op 13.740 ms/op 1.16
altair processEpoch - mainnet_e81889 261.18 ms/op 241.65 ms/op 1.08
mainnet_e81889 - altair beforeProcessEpoch 18.754 ms/op 16.307 ms/op 1.15
mainnet_e81889 - altair processJustificationAndFinalization 5.6490 us/op 5.7970 us/op 0.97
mainnet_e81889 - altair processInactivityUpdates 3.8340 ms/op 3.8327 ms/op 1.00
mainnet_e81889 - altair processRewardsAndPenalties 18.798 ms/op 24.191 ms/op 0.78
mainnet_e81889 - altair processRegistryUpdates 629.00 ns/op 867.00 ns/op 0.73
mainnet_e81889 - altair processSlashings 168.00 ns/op 221.00 ns/op 0.76
mainnet_e81889 - altair processEth1DataReset 165.00 ns/op 167.00 ns/op 0.99
mainnet_e81889 - altair processEffectiveBalanceUpdates 2.0834 ms/op 1.9531 ms/op 1.07
mainnet_e81889 - altair processSlashingsReset 813.00 ns/op 1.0430 us/op 0.78
mainnet_e81889 - altair processRandaoMixesReset 1.1370 us/op 1.0650 us/op 1.07
mainnet_e81889 - altair processHistoricalRootsUpdate 165.00 ns/op 208.00 ns/op 0.79
mainnet_e81889 - altair processParticipationFlagUpdates 494.00 ns/op 649.00 ns/op 0.76
mainnet_e81889 - altair processSyncCommitteeUpdates 130.00 ns/op 160.00 ns/op 0.81
mainnet_e81889 - altair afterProcessEpoch 44.869 ms/op 43.894 ms/op 1.02
capella processEpoch - mainnet_e217614 790.44 ms/op 770.28 ms/op 1.03
mainnet_e217614 - capella beforeProcessEpoch 69.356 ms/op 70.620 ms/op 0.98
mainnet_e217614 - capella processJustificationAndFinalization 5.5860 us/op 6.0220 us/op 0.93
mainnet_e217614 - capella processInactivityUpdates 15.720 ms/op 14.129 ms/op 1.11
mainnet_e217614 - capella processRewardsAndPenalties 95.977 ms/op 116.14 ms/op 0.83
mainnet_e217614 - capella processRegistryUpdates 5.9400 us/op 5.6340 us/op 1.05
mainnet_e217614 - capella processSlashings 173.00 ns/op 229.00 ns/op 0.76
mainnet_e217614 - capella processEth1DataReset 167.00 ns/op 243.00 ns/op 0.69
mainnet_e217614 - capella processEffectiveBalanceUpdates 24.009 ms/op 17.922 ms/op 1.34
mainnet_e217614 - capella processSlashingsReset 829.00 ns/op 802.00 ns/op 1.03
mainnet_e217614 - capella processRandaoMixesReset 1.1380 us/op 1.1650 us/op 0.98
mainnet_e217614 - capella processHistoricalRootsUpdate 163.00 ns/op 229.00 ns/op 0.71
mainnet_e217614 - capella processParticipationFlagUpdates 509.00 ns/op 517.00 ns/op 0.98
mainnet_e217614 - capella afterProcessEpoch 117.05 ms/op 116.40 ms/op 1.01
phase0 processEpoch - mainnet_e58758 248.66 ms/op 234.46 ms/op 1.06
mainnet_e58758 - phase0 beforeProcessEpoch 50.407 ms/op 58.201 ms/op 0.87
mainnet_e58758 - phase0 processJustificationAndFinalization 5.8550 us/op 6.8450 us/op 0.86
mainnet_e58758 - phase0 processRewardsAndPenalties 19.968 ms/op 22.711 ms/op 0.88
mainnet_e58758 - phase0 processRegistryUpdates 2.8940 us/op 2.8530 us/op 1.01
mainnet_e58758 - phase0 processSlashings 211.00 ns/op 216.00 ns/op 0.98
mainnet_e58758 - phase0 processEth1DataReset 171.00 ns/op 182.00 ns/op 0.94
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.1534 ms/op 1.0626 ms/op 1.09
mainnet_e58758 - phase0 processSlashingsReset 915.00 ns/op 973.00 ns/op 0.94
mainnet_e58758 - phase0 processRandaoMixesReset 1.1140 us/op 1.0980 us/op 1.01
mainnet_e58758 - phase0 processHistoricalRootsUpdate 167.00 ns/op 222.00 ns/op 0.75
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.0180 us/op 1.1580 us/op 0.88
mainnet_e58758 - phase0 afterProcessEpoch 36.497 ms/op 36.520 ms/op 1.00
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.4655 ms/op 1.7770 ms/op 0.82
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 2.0983 ms/op 3.2296 ms/op 0.65
altair processInactivityUpdates - 250000 normalcase 14.020 ms/op 14.095 ms/op 0.99
altair processInactivityUpdates - 250000 worstcase 12.841 ms/op 13.918 ms/op 0.92
phase0 processRegistryUpdates - 250000 normalcase 5.0780 us/op 6.7970 us/op 0.75
phase0 processRegistryUpdates - 250000 badcase_full_deposits 272.79 us/op 387.88 us/op 0.70
phase0 processRegistryUpdates - 250000 worstcase 0.5 68.663 ms/op 75.365 ms/op 0.91
altair processRewardsAndPenalties - 250000 normalcase 17.909 ms/op 26.780 ms/op 0.67
altair processRewardsAndPenalties - 250000 worstcase 17.769 ms/op 18.169 ms/op 0.98
phase0 getAttestationDeltas - 250000 normalcase 6.9486 ms/op 7.0693 ms/op 0.98
phase0 getAttestationDeltas - 250000 worstcase 6.2309 ms/op 7.0110 ms/op 0.89
phase0 processSlashings - 250000 worstcase 105.45 us/op 122.94 us/op 0.86
altair processSyncCommitteeUpdates - 250000 11.235 ms/op 11.066 ms/op 1.02
BeaconState.hashTreeRoot - No change 198.00 ns/op 225.00 ns/op 0.88
BeaconState.hashTreeRoot - 1 full validator 84.343 us/op 73.742 us/op 1.14
BeaconState.hashTreeRoot - 32 full validator 1.2853 ms/op 904.73 us/op 1.42
BeaconState.hashTreeRoot - 512 full validator 7.9970 ms/op 7.3950 ms/op 1.08
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 112.08 us/op 86.873 us/op 1.29
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.8635 ms/op 1.5246 ms/op 1.22
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 16.900 ms/op 22.407 ms/op 0.75
BeaconState.hashTreeRoot - 1 balances 90.500 us/op 86.014 us/op 1.05
BeaconState.hashTreeRoot - 32 balances 1.2288 ms/op 846.65 us/op 1.45
BeaconState.hashTreeRoot - 512 balances 6.2170 ms/op 6.0910 ms/op 1.02
BeaconState.hashTreeRoot - 250000 balances 146.56 ms/op 144.77 ms/op 1.01
aggregationBits - 2048 els - zipIndexesInBitList 21.180 us/op 21.446 us/op 0.99
regular array get 100000 times 25.037 us/op 25.018 us/op 1.00
wrappedArray get 100000 times 25.286 us/op 25.017 us/op 1.01
arrayWithProxy get 100000 times 17.177 ms/op 15.133 ms/op 1.14
ssz.Root.equals 24.302 ns/op 24.010 ns/op 1.01
byteArrayEquals 23.483 ns/op 23.510 ns/op 1.00
Buffer.compare 10.103 ns/op 10.024 ns/op 1.01
processSlot - 1 slots 12.563 us/op 12.346 us/op 1.02
processSlot - 32 slots 2.6532 ms/op 2.5401 ms/op 1.04
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 3.6302 ms/op 4.5017 ms/op 0.81
getCommitteeAssignments - req 1 vs - 250000 vc 1.9786 ms/op 1.9726 ms/op 1.00
getCommitteeAssignments - req 100 vs - 250000 vc 3.8393 ms/op 3.9679 ms/op 0.97
getCommitteeAssignments - req 1000 vs - 250000 vc 4.0892 ms/op 4.1235 ms/op 0.99
findModifiedValidators - 10000 modified validators 404.38 ms/op 595.01 ms/op 0.68
findModifiedValidators - 1000 modified validators 429.83 ms/op 372.29 ms/op 1.15
findModifiedValidators - 100 modified validators 279.54 ms/op 330.11 ms/op 0.85
findModifiedValidators - 10 modified validators 178.21 ms/op 188.38 ms/op 0.95
findModifiedValidators - 1 modified validators 152.47 ms/op 145.09 ms/op 1.05
findModifiedValidators - no difference 169.39 ms/op 175.60 ms/op 0.96
migrate state 1500000 validators, 3400 modified, 2000 new 1.1571 s/op 1.1836 s/op 0.98
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 4.2900 ns/op 4.4100 ns/op 0.97
state getBlockRootAtSlot - 250000 vs - 7PWei 666.59 ns/op 570.66 ns/op 1.17
computeProposerIndex 100000 validators 1.6132 ms/op 1.6798 ms/op 0.96
getNextSyncCommitteeIndices 1000 validators 123.26 ms/op 132.01 ms/op 0.93
getNextSyncCommitteeIndices 10000 validators 121.52 ms/op 127.79 ms/op 0.95
getNextSyncCommitteeIndices 100000 validators 122.27 ms/op 126.34 ms/op 0.97
computeProposers - vc 250000 673.51 us/op 691.66 us/op 0.97
computeEpochShuffling - vc 250000 42.468 ms/op 68.414 ms/op 0.62
getNextSyncCommittee - vc 250000 10.775 ms/op 12.390 ms/op 0.87
nodejs block root to RootHex using toHex 147.08 ns/op 147.96 ns/op 0.99
nodejs block root to RootHex using toRootHex 88.344 ns/op 102.30 ns/op 0.86
nodejs fromHex(blob) 422.82 us/op 267.08 us/op 1.58
nodejs fromHexInto(blob) 747.90 us/op 746.62 us/op 1.00
nodejs block root to RootHex using the deprecated toHexString 605.05 ns/op 578.30 ns/op 1.05
browser block root to RootHex using toHex 273.24 ns/op 315.90 ns/op 0.86
browser block root to RootHex using toRootHex 157.62 ns/op 161.35 ns/op 0.98
browser fromHex(blob) 936.77 us/op 990.97 us/op 0.95
browser fromHexInto(blob) 736.70 us/op 737.04 us/op 1.00
browser block root to RootHex using the deprecated toHexString 392.75 ns/op 417.86 ns/op 0.94

by benchmarkbot/action

import {getRootIndex, getRootIndexKey, storeRootIndex} from "./stateArchiveIndex.js";

export class StateArchiveRepository extends Repository<Slot, BeaconStateAllForks> {
export type BeaconStateArchive = {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

generic type to work with the current CachedBeaconStateAllForks and the future BeaconStateView

* By default, SSZ-encoded values,
* indexed by root
*/
export abstract class Repository<I extends Id, T> extends BinaryRepository<I> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

nothing change here, just a refactor to move methods without value (T) to BinaryRepository
no need to change anything at the consumer side

@twoeths twoeths changed the title feat: generalize state repositories refactor: generalize state repositories Jan 9, 2026
@twoeths twoeths marked this pull request as ready for review January 9, 2026 09:54
@twoeths twoeths requested a review from a team as a code owner January 9, 2026 09:54
// returning 1 per 100s of states that are persisted in the archive state is not useful enough
// and it causes consumers having to loadState and createCachedBeaconState again
// if state is finalized, consumers need to use getHistoricalStateBySlot() api instead
return null;
Copy link
Member

Choose a reason for hiding this comment

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

same concern as raised here #8728 (comment)

optsBuff.lt = this.maxKey;
}

// Set at least on max key
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Set at least on max key
// Set at least one max key

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.

State repositories to work with Uint8Array instead of BeaconStateAllForks

3 participants