这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@ensi321
Copy link
Contributor

@ensi321 ensi321 commented Sep 23, 2025

For context please view https://discord.com/channels/593655374469660673/1229813597501395028/1419794786121945141 .

The latest spec requires cell indices to be sorted in recover_cells_and_kzg_proofs so we need to sort them before passing it to kzg.

@ensi321 ensi321 requested a review from a team as a code owner September 23, 2025 02:58
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ensi321, 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 addresses a critical compliance requirement from the latest specification for KZG operations. It ensures that cell indices are correctly sorted before being processed by the recoverCellsAndKzgProofs function, preventing potential issues with KZG recovery. The changes primarily involve adding a sorting step and updating related logic to handle this new requirement, along with a corresponding validation in a test utility.

Highlights

  • Spec Compliance: Implemented sorting of cell indices in ascending order before passing them to the recoverCellsAndKzgProofs function, aligning with the latest specification requirements for KZG operations.
  • Optimization/Edge Case Handling: Modified the dataColumnMatrixRecovery function to directly return already sorted partialSidecars if all columns are present, avoiding unnecessary re-sorting.
  • Test Utility Enhancement: Added a validation check in the recoverCellsAndKzgProofs test utility function to return null if the provided cell_indices are not sorted, reflecting the new spec requirement.
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

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 aims to fix an issue where cell indices were not sorted before being passed to recoverCellsAndKzgProofs, as required by the latest spec. The change correctly sorts the partialSidecars in dataColumnMatrixRecovery. However, I've found a critical bug in how the sorted array is used to gather cellIndices, which would lead to incorrect data recovery. I've also pointed out a minor redundancy. The changes in the test file to validate sorted indices are a good addition.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 23, 2025

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: 3df564b Previous: 83de5b8 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 1.2551 ms/op 979.12 us/op 1.28
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 48.829 us/op 37.179 us/op 1.31
BLS verify - blst 1.1029 ms/op 859.30 us/op 1.28
BLS verifyMultipleSignatures 3 - blst 1.6717 ms/op 1.6711 ms/op 1.00
BLS verifyMultipleSignatures 8 - blst 2.8543 ms/op 2.3458 ms/op 1.22
BLS verifyMultipleSignatures 32 - blst 6.0227 ms/op 5.6329 ms/op 1.07
BLS verifyMultipleSignatures 64 - blst 13.818 ms/op 10.815 ms/op 1.28
BLS verifyMultipleSignatures 128 - blst 22.920 ms/op 17.618 ms/op 1.30
BLS deserializing 10000 signatures 735.89 ms/op 719.59 ms/op 1.02
BLS deserializing 100000 signatures 7.0790 s/op 7.1073 s/op 1.00
BLS verifyMultipleSignatures - same message - 3 - blst 906.85 us/op 913.06 us/op 0.99
BLS verifyMultipleSignatures - same message - 8 - blst 1.1858 ms/op 1.1881 ms/op 1.00
BLS verifyMultipleSignatures - same message - 32 - blst 1.7063 ms/op 1.7130 ms/op 1.00
BLS verifyMultipleSignatures - same message - 64 - blst 2.6013 ms/op 2.6386 ms/op 0.99
BLS verifyMultipleSignatures - same message - 128 - blst 4.4382 ms/op 4.4392 ms/op 1.00
BLS aggregatePubkeys 32 - blst 19.387 us/op 19.868 us/op 0.98
BLS aggregatePubkeys 128 - blst 67.655 us/op 70.925 us/op 0.95
notSeenSlots=1 numMissedVotes=1 numBadVotes=10 58.547 ms/op 54.504 ms/op 1.07
notSeenSlots=1 numMissedVotes=0 numBadVotes=4 57.560 ms/op 56.465 ms/op 1.02
notSeenSlots=2 numMissedVotes=1 numBadVotes=10 50.913 ms/op 42.025 ms/op 1.21
getSlashingsAndExits - default max 77.312 us/op 74.862 us/op 1.03
getSlashingsAndExits - 2k 324.42 us/op 328.58 us/op 0.99
isKnown best case - 1 super set check 216.00 ns/op 214.00 ns/op 1.01
isKnown normal case - 2 super set checks 208.00 ns/op 207.00 ns/op 1.00
isKnown worse case - 16 super set checks 215.00 ns/op 210.00 ns/op 1.02
InMemoryCheckpointStateCache - add get delete 2.6910 us/op 2.4760 us/op 1.09
validate api signedAggregateAndProof - struct 1.7299 ms/op 1.8461 ms/op 0.94
validate gossip signedAggregateAndProof - struct 1.9951 ms/op 2.5847 ms/op 0.77
batch validate gossip attestation - vc 640000 - chunk 32 117.08 us/op 117.73 us/op 0.99
batch validate gossip attestation - vc 640000 - chunk 64 100.86 us/op 104.24 us/op 0.97
batch validate gossip attestation - vc 640000 - chunk 128 93.840 us/op 97.264 us/op 0.96
batch validate gossip attestation - vc 640000 - chunk 256 99.206 us/op 98.564 us/op 1.01
pickEth1Vote - no votes 971.13 us/op 986.65 us/op 0.98
pickEth1Vote - max votes 5.7630 ms/op 5.7759 ms/op 1.00
pickEth1Vote - Eth1Data hashTreeRoot value x2048 12.882 ms/op 11.081 ms/op 1.16
pickEth1Vote - Eth1Data hashTreeRoot tree x2048 20.904 ms/op 15.055 ms/op 1.39
pickEth1Vote - Eth1Data fastSerialize value x2048 451.03 us/op 512.73 us/op 0.88
pickEth1Vote - Eth1Data fastSerialize tree x2048 3.8523 ms/op 3.1140 ms/op 1.24
bytes32 toHexString 372.00 ns/op 384.00 ns/op 0.97
bytes32 Buffer.toString(hex) 277.00 ns/op 265.00 ns/op 1.05
bytes32 Buffer.toString(hex) from Uint8Array 445.00 ns/op 350.00 ns/op 1.27
bytes32 Buffer.toString(hex) + 0x 248.00 ns/op 262.00 ns/op 0.95
Object access 1 prop 0.12300 ns/op 0.12800 ns/op 0.96
Map access 1 prop 0.16500 ns/op 0.12600 ns/op 1.31
Object get x1000 5.9790 ns/op 6.0160 ns/op 0.99
Map get x1000 6.3630 ns/op 6.4230 ns/op 0.99
Object set x1000 30.415 ns/op 28.482 ns/op 1.07
Map set x1000 19.360 ns/op 19.320 ns/op 1.00
Return object 10000 times 0.30970 ns/op 0.29080 ns/op 1.06
Throw Error 10000 times 4.4925 us/op 4.3435 us/op 1.03
toHex 140.20 ns/op 135.16 ns/op 1.04
Buffer.from 133.03 ns/op 128.31 ns/op 1.04
shared Buffer 84.121 ns/op 97.747 ns/op 0.86
fastMsgIdFn sha256 / 200 bytes 2.2410 us/op 2.2330 us/op 1.00
fastMsgIdFn h32 xxhash / 200 bytes 264.00 ns/op 207.00 ns/op 1.28
fastMsgIdFn h64 xxhash / 200 bytes 271.00 ns/op 287.00 ns/op 0.94
fastMsgIdFn sha256 / 1000 bytes 7.4660 us/op 7.5590 us/op 0.99
fastMsgIdFn h32 xxhash / 1000 bytes 392.00 ns/op 340.00 ns/op 1.15
fastMsgIdFn h64 xxhash / 1000 bytes 342.00 ns/op 339.00 ns/op 1.01
fastMsgIdFn sha256 / 10000 bytes 68.464 us/op 66.247 us/op 1.03
fastMsgIdFn h32 xxhash / 10000 bytes 1.8990 us/op 1.8700 us/op 1.02
fastMsgIdFn h64 xxhash / 10000 bytes 1.3720 us/op 1.2500 us/op 1.10
send data - 1000 256B messages 17.950 ms/op 15.843 ms/op 1.13
send data - 1000 512B messages 22.393 ms/op 19.933 ms/op 1.12
send data - 1000 1024B messages 27.538 ms/op 27.895 ms/op 0.99
send data - 1000 1200B messages 25.359 ms/op 24.430 ms/op 1.04
send data - 1000 2048B messages 24.343 ms/op 26.143 ms/op 0.93
send data - 1000 4096B messages 26.681 ms/op 27.390 ms/op 0.97
send data - 1000 16384B messages 43.578 ms/op 43.360 ms/op 1.01
send data - 1000 65536B messages 118.25 ms/op 119.90 ms/op 0.99
enrSubnets - fastDeserialize 64 bits 888.00 ns/op 914.00 ns/op 0.97
enrSubnets - ssz BitVector 64 bits 317.00 ns/op 334.00 ns/op 0.95
enrSubnets - fastDeserialize 4 bits 138.00 ns/op 136.00 ns/op 1.01
enrSubnets - ssz BitVector 4 bits 322.00 ns/op 328.00 ns/op 0.98
prioritizePeers score -10:0 att 32-0.1 sync 2-0 239.42 us/op 249.60 us/op 0.96
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 269.70 us/op 270.74 us/op 1.00
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 376.81 us/op 388.66 us/op 0.97
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 721.28 us/op 718.56 us/op 1.00
prioritizePeers score 0:0 att 64-1 sync 4-1 893.58 us/op 872.52 us/op 1.02
array of 16000 items push then shift 2.0020 us/op 1.6612 us/op 1.21
LinkedList of 16000 items push then shift 8.8700 ns/op 7.3760 ns/op 1.20
array of 16000 items push then pop 77.247 ns/op 79.308 ns/op 0.97
LinkedList of 16000 items push then pop 7.4810 ns/op 7.3690 ns/op 1.02
array of 24000 items push then shift 2.4794 us/op 2.4706 us/op 1.00
LinkedList of 24000 items push then shift 7.9170 ns/op 7.3350 ns/op 1.08
array of 24000 items push then pop 112.46 ns/op 107.25 ns/op 1.05
LinkedList of 24000 items push then pop 7.3850 ns/op 7.2480 ns/op 1.02
intersect bitArray bitLen 8 6.4010 ns/op 6.5080 ns/op 0.98
intersect array and set length 8 39.036 ns/op 38.695 ns/op 1.01
intersect bitArray bitLen 128 31.574 ns/op 30.343 ns/op 1.04
intersect array and set length 128 632.57 ns/op 634.39 ns/op 1.00
bitArray.getTrueBitIndexes() bitLen 128 1.0230 us/op 1.0490 us/op 0.98
bitArray.getTrueBitIndexes() bitLen 248 1.8010 us/op 1.8350 us/op 0.98
bitArray.getTrueBitIndexes() bitLen 512 3.7450 us/op 3.7810 us/op 0.99
Buffer.concat 32 items 671.00 ns/op 628.00 ns/op 1.07
Uint8Array.set 32 items 1.0200 us/op 1.0800 us/op 0.94
Buffer.copy 3.5990 us/op 2.5610 us/op 1.41
Uint8Array.set - with subarray 1.7820 us/op 1.7360 us/op 1.03
Uint8Array.set - without subarray 994.00 ns/op 897.00 ns/op 1.11
getUint32 - dataview 200.00 ns/op 206.00 ns/op 0.97
getUint32 - manual 115.00 ns/op 125.00 ns/op 0.92
Set add up to 64 items then delete first 2.2695 us/op 2.0712 us/op 1.10
OrderedSet add up to 64 items then delete first 3.4521 us/op 3.3763 us/op 1.02
Set add up to 64 items then delete last 2.6303 us/op 2.4977 us/op 1.05
OrderedSet add up to 64 items then delete last 3.9451 us/op 3.7468 us/op 1.05
Set add up to 64 items then delete middle 2.5076 us/op 2.4010 us/op 1.04
OrderedSet add up to 64 items then delete middle 5.5791 us/op 5.2914 us/op 1.05
Set add up to 128 items then delete first 5.2166 us/op 5.1723 us/op 1.01
OrderedSet add up to 128 items then delete first 7.6408 us/op 8.0814 us/op 0.95
Set add up to 128 items then delete last 5.2600 us/op 5.0933 us/op 1.03
OrderedSet add up to 128 items then delete last 7.9410 us/op 7.4976 us/op 1.06
Set add up to 128 items then delete middle 4.9402 us/op 5.0701 us/op 0.97
OrderedSet add up to 128 items then delete middle 16.386 us/op 14.137 us/op 1.16
Set add up to 256 items then delete first 10.808 us/op 11.116 us/op 0.97
OrderedSet add up to 256 items then delete first 16.046 us/op 16.246 us/op 0.99
Set add up to 256 items then delete last 11.053 us/op 10.109 us/op 1.09
OrderedSet add up to 256 items then delete last 18.842 us/op 15.193 us/op 1.24
Set add up to 256 items then delete middle 10.030 us/op 9.9972 us/op 1.00
OrderedSet add up to 256 items then delete middle 43.637 us/op 43.028 us/op 1.01
transfer serialized Status (84 B) 2.2880 us/op 2.3500 us/op 0.97
copy serialized Status (84 B) 1.3820 us/op 1.1600 us/op 1.19
transfer serialized SignedVoluntaryExit (112 B) 2.3090 us/op 2.2800 us/op 1.01
copy serialized SignedVoluntaryExit (112 B) 1.1960 us/op 1.1730 us/op 1.02
transfer serialized ProposerSlashing (416 B) 2.5140 us/op 2.7270 us/op 0.92
copy serialized ProposerSlashing (416 B) 1.5940 us/op 1.2640 us/op 1.26
transfer serialized Attestation (485 B) 2.3380 us/op 2.3290 us/op 1.00
copy serialized Attestation (485 B) 1.5690 us/op 1.2460 us/op 1.26
transfer serialized AttesterSlashing (33232 B) 3.1470 us/op 2.4900 us/op 1.26
copy serialized AttesterSlashing (33232 B) 4.4980 us/op 3.4300 us/op 1.31
transfer serialized Small SignedBeaconBlock (128000 B) 3.4800 us/op 3.0080 us/op 1.16
copy serialized Small SignedBeaconBlock (128000 B) 11.084 us/op 8.7840 us/op 1.26
transfer serialized Avg SignedBeaconBlock (200000 B) 3.8920 us/op 3.3730 us/op 1.15
copy serialized Avg SignedBeaconBlock (200000 B) 15.689 us/op 18.061 us/op 0.87
transfer serialized BlobsSidecar (524380 B) 4.2420 us/op 3.2700 us/op 1.30
copy serialized BlobsSidecar (524380 B) 67.821 us/op 60.774 us/op 1.12
transfer serialized Big SignedBeaconBlock (1000000 B) 4.1870 us/op 3.3660 us/op 1.24
copy serialized Big SignedBeaconBlock (1000000 B) 118.39 us/op 120.31 us/op 0.98
pass gossip attestations to forkchoice per slot 3.0481 ms/op 2.8818 ms/op 1.06
forkChoice updateHead vc 100000 bc 64 eq 0 452.59 us/op 465.61 us/op 0.97
forkChoice updateHead vc 600000 bc 64 eq 0 2.8061 ms/op 2.8953 ms/op 0.97
forkChoice updateHead vc 1000000 bc 64 eq 0 4.9331 ms/op 4.9363 ms/op 1.00
forkChoice updateHead vc 600000 bc 320 eq 0 2.8782 ms/op 2.8665 ms/op 1.00
forkChoice updateHead vc 600000 bc 1200 eq 0 2.9596 ms/op 2.9085 ms/op 1.02
forkChoice updateHead vc 600000 bc 7200 eq 0 3.0896 ms/op 3.1086 ms/op 0.99
forkChoice updateHead vc 600000 bc 64 eq 1000 10.426 ms/op 10.610 ms/op 0.98
forkChoice updateHead vc 600000 bc 64 eq 10000 10.590 ms/op 10.543 ms/op 1.00
forkChoice updateHead vc 600000 bc 64 eq 300000 13.469 ms/op 14.191 ms/op 0.95
computeDeltas 500000 validators 300 proto nodes 4.0095 ms/op 4.0032 ms/op 1.00
computeDeltas 500000 validators 1200 proto nodes 4.0944 ms/op 4.0377 ms/op 1.01
computeDeltas 500000 validators 7200 proto nodes 3.9828 ms/op 4.0329 ms/op 0.99
computeDeltas 750000 validators 300 proto nodes 5.9138 ms/op 5.9911 ms/op 0.99
computeDeltas 750000 validators 1200 proto nodes 5.8317 ms/op 5.9510 ms/op 0.98
computeDeltas 750000 validators 7200 proto nodes 6.0664 ms/op 5.9983 ms/op 1.01
computeDeltas 1400000 validators 300 proto nodes 11.123 ms/op 11.357 ms/op 0.98
computeDeltas 1400000 validators 1200 proto nodes 11.014 ms/op 11.293 ms/op 0.98
computeDeltas 1400000 validators 7200 proto nodes 11.370 ms/op 11.230 ms/op 1.01
computeDeltas 2100000 validators 300 proto nodes 17.182 ms/op 16.996 ms/op 1.01
computeDeltas 2100000 validators 1200 proto nodes 16.977 ms/op 16.984 ms/op 1.00
computeDeltas 2100000 validators 7200 proto nodes 16.478 ms/op 16.911 ms/op 0.97
altair processAttestation - 250000 vs - 7PWei normalcase 2.0021 ms/op 2.0570 ms/op 0.97
altair processAttestation - 250000 vs - 7PWei worstcase 3.1757 ms/op 3.0652 ms/op 1.04
altair processAttestation - setStatus - 1/6 committees join 113.82 us/op 129.91 us/op 0.88
altair processAttestation - setStatus - 1/3 committees join 234.44 us/op 246.42 us/op 0.95
altair processAttestation - setStatus - 1/2 committees join 330.52 us/op 351.36 us/op 0.94
altair processAttestation - setStatus - 2/3 committees join 438.77 us/op 456.33 us/op 0.96
altair processAttestation - setStatus - 4/5 committees join 603.91 us/op 630.33 us/op 0.96
altair processAttestation - setStatus - 100% committees join 712.08 us/op 731.25 us/op 0.97
altair processBlock - 250000 vs - 7PWei normalcase 10.960 ms/op 4.4503 ms/op 2.46
altair processBlock - 250000 vs - 7PWei normalcase hashState 33.915 ms/op 33.990 ms/op 1.00
altair processBlock - 250000 vs - 7PWei worstcase 41.422 ms/op 41.465 ms/op 1.00
altair processBlock - 250000 vs - 7PWei worstcase hashState 94.814 ms/op 87.142 ms/op 1.09
phase0 processBlock - 250000 vs - 7PWei normalcase 1.5083 ms/op 2.5004 ms/op 0.60
phase0 processBlock - 250000 vs - 7PWei worstcase 29.782 ms/op 24.714 ms/op 1.21
altair processEth1Data - 250000 vs - 7PWei normalcase 337.53 us/op 347.28 us/op 0.97
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:15 9.4330 us/op 5.6250 us/op 1.68
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:219 41.986 us/op 35.285 us/op 1.19
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:42 16.100 us/op 12.647 us/op 1.27
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:18 10.179 us/op 10.065 us/op 1.01
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1020 139.12 us/op 143.92 us/op 0.97
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11777 2.6002 ms/op 1.8403 ms/op 1.41
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 2.2756 ms/op 2.4158 ms/op 0.94
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 2.2736 ms/op 2.3777 ms/op 0.96
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 4.3097 ms/op 4.6069 ms/op 0.94
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.7117 ms/op 2.4458 ms/op 1.11
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.5031 ms/op 4.7226 ms/op 0.95
Tree 40 250000 create 439.86 ms/op 434.17 ms/op 1.01
Tree 40 250000 get(125000) 142.06 ns/op 145.98 ns/op 0.97
Tree 40 250000 set(125000) 1.5424 us/op 1.5156 us/op 1.02
Tree 40 250000 toArray() 19.792 ms/op 17.959 ms/op 1.10
Tree 40 250000 iterate all - toArray() + loop 17.931 ms/op 15.655 ms/op 1.15
Tree 40 250000 iterate all - get(i) 57.510 ms/op 52.786 ms/op 1.09
Array 250000 create 3.2069 ms/op 3.1955 ms/op 1.00
Array 250000 clone - spread 849.15 us/op 1.6214 ms/op 0.52
Array 250000 get(125000) 0.42300 ns/op 0.42200 ns/op 1.00
Array 250000 set(125000) 0.44700 ns/op 0.43700 ns/op 1.02
Array 250000 iterate all - loop 97.525 us/op 106.26 us/op 0.92
phase0 afterProcessEpoch - 250000 vs - 7PWei 42.177 ms/op 42.644 ms/op 0.99
Array.fill - length 1000000 3.4263 ms/op 3.7047 ms/op 0.92
Array push - length 1000000 13.335 ms/op 13.406 ms/op 0.99
Array.get 0.29098 ns/op 0.28208 ns/op 1.03
Uint8Array.get 0.44344 ns/op 0.44912 ns/op 0.99
phase0 beforeProcessEpoch - 250000 vs - 7PWei 17.349 ms/op 16.713 ms/op 1.04
altair processEpoch - mainnet_e81889 267.23 ms/op 268.31 ms/op 1.00
mainnet_e81889 - altair beforeProcessEpoch 18.372 ms/op 16.873 ms/op 1.09
mainnet_e81889 - altair processJustificationAndFinalization 6.1340 us/op 8.4900 us/op 0.72
mainnet_e81889 - altair processInactivityUpdates 4.8775 ms/op 4.3143 ms/op 1.13
mainnet_e81889 - altair processRewardsAndPenalties 43.990 ms/op 36.453 ms/op 1.21
mainnet_e81889 - altair processRegistryUpdates 721.00 ns/op 719.00 ns/op 1.00
mainnet_e81889 - altair processSlashings 193.00 ns/op 189.00 ns/op 1.02
mainnet_e81889 - altair processEth1DataReset 179.00 ns/op 193.00 ns/op 0.93
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.1966 ms/op 1.2079 ms/op 0.99
mainnet_e81889 - altair processSlashingsReset 917.00 ns/op 1.2160 us/op 0.75
mainnet_e81889 - altair processRandaoMixesReset 1.2360 us/op 1.1850 us/op 1.04
mainnet_e81889 - altair processHistoricalRootsUpdate 178.00 ns/op 180.00 ns/op 0.99
mainnet_e81889 - altair processParticipationFlagUpdates 528.00 ns/op 726.00 ns/op 0.73
mainnet_e81889 - altair processSyncCommitteeUpdates 138.00 ns/op 142.00 ns/op 0.97
mainnet_e81889 - altair afterProcessEpoch 43.666 ms/op 44.768 ms/op 0.98
capella processEpoch - mainnet_e217614 1.0637 s/op 987.68 ms/op 1.08
mainnet_e217614 - capella beforeProcessEpoch 68.815 ms/op 65.911 ms/op 1.04
mainnet_e217614 - capella processJustificationAndFinalization 6.2180 us/op 6.2210 us/op 1.00
mainnet_e217614 - capella processInactivityUpdates 15.884 ms/op 15.492 ms/op 1.03
mainnet_e217614 - capella processRewardsAndPenalties 195.54 ms/op 198.51 ms/op 0.99
mainnet_e217614 - capella processRegistryUpdates 8.3650 us/op 7.8060 us/op 1.07
mainnet_e217614 - capella processSlashings 196.00 ns/op 194.00 ns/op 1.01
mainnet_e217614 - capella processEth1DataReset 189.00 ns/op 197.00 ns/op 0.96
mainnet_e217614 - capella processEffectiveBalanceUpdates 4.4208 ms/op 12.667 ms/op 0.35
mainnet_e217614 - capella processSlashingsReset 959.00 ns/op 1.1450 us/op 0.84
mainnet_e217614 - capella processRandaoMixesReset 1.3010 us/op 1.3290 us/op 0.98
mainnet_e217614 - capella processHistoricalRootsUpdate 202.00 ns/op 207.00 ns/op 0.98
mainnet_e217614 - capella processParticipationFlagUpdates 576.00 ns/op 597.00 ns/op 0.96
mainnet_e217614 - capella afterProcessEpoch 120.95 ms/op 123.15 ms/op 0.98
phase0 processEpoch - mainnet_e58758 334.88 ms/op 323.84 ms/op 1.03
mainnet_e58758 - phase0 beforeProcessEpoch 81.815 ms/op 87.743 ms/op 0.93
mainnet_e58758 - phase0 processJustificationAndFinalization 6.7250 us/op 6.0800 us/op 1.11
mainnet_e58758 - phase0 processRewardsAndPenalties 39.387 ms/op 47.432 ms/op 0.83
mainnet_e58758 - phase0 processRegistryUpdates 3.6820 us/op 3.4450 us/op 1.07
mainnet_e58758 - phase0 processSlashings 199.00 ns/op 191.00 ns/op 1.04
mainnet_e58758 - phase0 processEth1DataReset 177.00 ns/op 183.00 ns/op 0.97
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.5706 ms/op 1.2529 ms/op 1.25
mainnet_e58758 - phase0 processSlashingsReset 1.1160 us/op 994.00 ns/op 1.12
mainnet_e58758 - phase0 processRandaoMixesReset 1.3290 us/op 1.2900 us/op 1.03
mainnet_e58758 - phase0 processHistoricalRootsUpdate 256.00 ns/op 186.00 ns/op 1.38
mainnet_e58758 - phase0 processParticipationRecordUpdates 967.00 ns/op 930.00 ns/op 1.04
mainnet_e58758 - phase0 afterProcessEpoch 37.549 ms/op 36.681 ms/op 1.02
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.6707 ms/op 2.0786 ms/op 0.80
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 2.6873 ms/op 1.9285 ms/op 1.39
altair processInactivityUpdates - 250000 normalcase 22.838 ms/op 23.207 ms/op 0.98
altair processInactivityUpdates - 250000 worstcase 20.177 ms/op 22.532 ms/op 0.90
phase0 processRegistryUpdates - 250000 normalcase 7.8210 us/op 6.6840 us/op 1.17
phase0 processRegistryUpdates - 250000 badcase_full_deposits 336.03 us/op 442.83 us/op 0.76
phase0 processRegistryUpdates - 250000 worstcase 0.5 129.41 ms/op 115.31 ms/op 1.12
altair processRewardsAndPenalties - 250000 normalcase 28.668 ms/op 30.355 ms/op 0.94
altair processRewardsAndPenalties - 250000 worstcase 31.057 ms/op 35.201 ms/op 0.88
phase0 getAttestationDeltas - 250000 normalcase 8.2242 ms/op 6.2561 ms/op 1.31
phase0 getAttestationDeltas - 250000 worstcase 8.4901 ms/op 6.2566 ms/op 1.36
phase0 processSlashings - 250000 worstcase 134.57 us/op 113.50 us/op 1.19
altair processSyncCommitteeUpdates - 250000 12.342 ms/op 11.605 ms/op 1.06
BeaconState.hashTreeRoot - No change 238.00 ns/op 282.00 ns/op 0.84
BeaconState.hashTreeRoot - 1 full validator 83.346 us/op 79.193 us/op 1.05
BeaconState.hashTreeRoot - 32 full validator 911.64 us/op 936.46 us/op 0.97
BeaconState.hashTreeRoot - 512 full validator 11.962 ms/op 15.390 ms/op 0.78
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 117.97 us/op 113.91 us/op 1.04
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.7414 ms/op 1.6997 ms/op 1.02
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 26.252 ms/op 21.352 ms/op 1.23
BeaconState.hashTreeRoot - 1 balances 75.391 us/op 77.269 us/op 0.98
BeaconState.hashTreeRoot - 32 balances 779.82 us/op 919.36 us/op 0.85
BeaconState.hashTreeRoot - 512 balances 9.3043 ms/op 7.9227 ms/op 1.17
BeaconState.hashTreeRoot - 250000 balances 162.62 ms/op 167.20 ms/op 0.97
aggregationBits - 2048 els - zipIndexesInBitList 23.351 us/op 23.758 us/op 0.98
byteArrayEquals 32 56.566 ns/op 57.849 ns/op 0.98
Buffer.compare 32 18.388 ns/op 19.084 ns/op 0.96
byteArrayEquals 1024 1.6778 us/op 1.7055 us/op 0.98
Buffer.compare 1024 27.179 ns/op 27.968 ns/op 0.97
byteArrayEquals 16384 26.721 us/op 26.990 us/op 0.99
Buffer.compare 16384 199.40 ns/op 228.74 ns/op 0.87
byteArrayEquals 123687377 196.06 ms/op 202.32 ms/op 0.97
Buffer.compare 123687377 6.7269 ms/op 7.8139 ms/op 0.86
byteArrayEquals 32 - diff last byte 53.182 ns/op 55.648 ns/op 0.96
Buffer.compare 32 - diff last byte 17.331 ns/op 18.327 ns/op 0.95
byteArrayEquals 1024 - diff last byte 1.6017 us/op 1.6687 us/op 0.96
Buffer.compare 1024 - diff last byte 25.340 ns/op 27.580 ns/op 0.92
byteArrayEquals 16384 - diff last byte 25.459 us/op 26.533 us/op 0.96
Buffer.compare 16384 - diff last byte 203.16 ns/op 214.18 ns/op 0.95
byteArrayEquals 123687377 - diff last byte 198.04 ms/op 201.18 ms/op 0.98
Buffer.compare 123687377 - diff last byte 7.1984 ms/op 7.6169 ms/op 0.95
byteArrayEquals 32 - random bytes 5.3110 ns/op 5.4050 ns/op 0.98
Buffer.compare 32 - random bytes 17.790 ns/op 17.872 ns/op 1.00
byteArrayEquals 1024 - random bytes 5.3110 ns/op 5.3590 ns/op 0.99
Buffer.compare 1024 - random bytes 17.780 ns/op 17.855 ns/op 1.00
byteArrayEquals 16384 - random bytes 5.3110 ns/op 5.3740 ns/op 0.99
Buffer.compare 16384 - random bytes 17.807 ns/op 17.864 ns/op 1.00
byteArrayEquals 123687377 - random bytes 6.6300 ns/op 7.5700 ns/op 0.88
Buffer.compare 123687377 - random bytes 18.850 ns/op 20.710 ns/op 0.91
regular array get 100000 times 42.011 us/op 34.993 us/op 1.20
wrappedArray get 100000 times 44.551 us/op 34.917 us/op 1.28
arrayWithProxy get 100000 times 12.952 ms/op 12.669 ms/op 1.02
ssz.Root.equals 47.438 ns/op 48.650 ns/op 0.98
byteArrayEquals 46.467 ns/op 47.546 ns/op 0.98
Buffer.compare 10.706 ns/op 10.797 ns/op 0.99
processSlot - 1 slots 10.281 us/op 13.221 us/op 0.78
processSlot - 32 slots 2.4596 ms/op 2.5074 ms/op 0.98
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 3.0251 ms/op 3.5942 ms/op 0.84
getCommitteeAssignments - req 1 vs - 250000 vc 2.2042 ms/op 2.2277 ms/op 0.99
getCommitteeAssignments - req 100 vs - 250000 vc 4.2592 ms/op 4.3265 ms/op 0.98
getCommitteeAssignments - req 1000 vs - 250000 vc 4.5349 ms/op 4.6500 ms/op 0.98
findModifiedValidators - 10000 modified validators 758.10 ms/op 815.26 ms/op 0.93
findModifiedValidators - 1000 modified validators 700.25 ms/op 748.85 ms/op 0.94
findModifiedValidators - 100 modified validators 249.60 ms/op 292.12 ms/op 0.85
findModifiedValidators - 10 modified validators 183.54 ms/op 155.08 ms/op 1.18
findModifiedValidators - 1 modified validators 172.84 ms/op 166.88 ms/op 1.04
findModifiedValidators - no difference 151.31 ms/op 221.30 ms/op 0.68
compare ViewDUs 6.2100 s/op 7.0604 s/op 0.88
compare each validator Uint8Array 2.1398 s/op 1.7758 s/op 1.21
compare ViewDU to Uint8Array 964.24 ms/op 1.8616 s/op 0.52
migrate state 1000000 validators, 24 modified, 0 new 938.89 ms/op 1.3016 s/op 0.72
migrate state 1000000 validators, 1700 modified, 1000 new 1.2148 s/op 1.7404 s/op 0.70
migrate state 1000000 validators, 3400 modified, 2000 new 1.3175 s/op 1.7966 s/op 0.73
migrate state 1500000 validators, 24 modified, 0 new 985.38 ms/op 1.0733 s/op 0.92
migrate state 1500000 validators, 1700 modified, 1000 new 1.2027 s/op 1.1817 s/op 1.02
migrate state 1500000 validators, 3400 modified, 2000 new 1.7150 s/op 1.3137 s/op 1.31
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 4.7600 ns/op 5.3300 ns/op 0.89
state getBlockRootAtSlot - 250000 vs - 7PWei 610.66 ns/op 621.73 ns/op 0.98
naive computeProposerIndex 100000 validators 58.024 ms/op 65.965 ms/op 0.88
computeProposerIndex 100000 validators 1.5650 ms/op 1.6661 ms/op 0.94
naiveGetNextSyncCommitteeIndices 1000 validators 9.4967 s/op 8.1893 s/op 1.16
getNextSyncCommitteeIndices 1000 validators 133.34 ms/op 140.48 ms/op 0.95
naiveGetNextSyncCommitteeIndices 10000 validators 9.3623 s/op 9.7746 s/op 0.96
getNextSyncCommitteeIndices 10000 validators 129.54 ms/op 129.38 ms/op 1.00
naiveGetNextSyncCommitteeIndices 100000 validators 8.9308 s/op 7.6039 s/op 1.17
getNextSyncCommitteeIndices 100000 validators 137.13 ms/op 116.27 ms/op 1.18
naive computeShuffledIndex 100000 validators 28.737 s/op 22.097 s/op 1.30
cached computeShuffledIndex 100000 validators 618.45 ms/op 568.30 ms/op 1.09
naive computeShuffledIndex 2000000 validators 487.35 s/op 494.71 s/op 0.99
cached computeShuffledIndex 2000000 validators 27.999 s/op 31.878 s/op 0.88
computeProposers - vc 250000 601.99 us/op 630.04 us/op 0.96
computeEpochShuffling - vc 250000 40.967 ms/op 42.299 ms/op 0.97
getNextSyncCommittee - vc 250000 10.156 ms/op 10.599 ms/op 0.96
computeSigningRoot for AttestationData 20.956 us/op 19.173 us/op 1.09
hash AttestationData serialized data then Buffer.toString(base64) 1.5720 us/op 1.6002 us/op 0.98
toHexString serialized data 1.0994 us/op 1.1569 us/op 0.95
Buffer.toString(base64) 155.00 ns/op 157.12 ns/op 0.99
nodejs block root to RootHex using toHex 139.52 ns/op 151.10 ns/op 0.92
nodejs block root to RootHex using toRootHex 86.210 ns/op 99.563 ns/op 0.87
nodejs fromhex(blob) 107.68 ms/op 114.65 ms/op 0.94
nodejs fromHexInto(blob) 94.333 ms/op 97.271 ms/op 0.97
browser block root to RootHex using the deprecated toHexString 206.92 ns/op 213.77 ns/op 0.97
browser block root to RootHex using toHex 166.99 ns/op 173.27 ns/op 0.96
browser block root to RootHex using toRootHex 156.71 ns/op 162.15 ns/op 0.97
browser fromHexInto(blob) 806.49 us/op 830.16 us/op 0.97
browser fromHex(blob) 768.47 ms/op 795.25 ms/op 0.97

by benchmarkbot/action

@nflaig
Copy link
Member

nflaig commented Sep 23, 2025

/gemini review

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 correctly implements the spec requirement to sort cell indices before calling recoverCellsAndKzgProofs. The changes in dataColumnMatrixRecovery ensure that sidecars are sorted by index, guaranteeing that cell indices passed to the KZG function are in ascending order. The corresponding update to the test helper in kzg.ts to validate the sorted order of indices is a good addition for test correctness. The implementation is clean and effectively addresses the issue. No issues found.

function recoverCellsAndKzgProofs(input: RecoverCellsAndKzgProofsInput): [string[], string[]] | null {
const isSorted = input.cell_indices.every((val, i, arr) => i === 0 || arr[i - 1] < val);
// If cell indices are not in ascending order, they are deemed invalid and cannot pass it to kzg
if (!isSorted) 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.

is the spec test invalid, or what happens if you pass them to kzg? I see we already have a try/catch below and would also 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.

The problem is kzg.recoverCellsAndKzgProofs doesn't enforce the order of cell indices. So it will return list of cells without sorting them instead of throwing error.

So it's up to the client to enforce the order before calling kzg

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here's what it looks like if we run the related spec test without validating the order

image

Copy link
Member

Choose a reason for hiding this comment

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

should we create a wrapper function that ensures sorting and call that one instead?

Copy link
Member

Choose a reason for hiding this comment

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

i think that is what jtraglia suggested

Copy link
Contributor Author

Choose a reason for hiding this comment

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

should we create a wrapper function that ensures sorting and call that one instead?

But spec test calls recoverCellsAndKzgProofs where as dataColumnMatrixRecovery calls asyncRecoverCellsAndKzgProofs. So even if we have a wrapper, we would need a flag to indicate async or not, and there will still be two code paths.

Copy link
Member

@matthewkeil matthewkeil Sep 23, 2025

Choose a reason for hiding this comment

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

Copy link
Member

@matthewkeil matthewkeil Sep 23, 2025

Choose a reason for hiding this comment

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

I think its fine to return null like this. We know we are handling the case correctly in the main codebase and short circuiting the spec tests is done elsewhere due to code conditions.

if (pk === G1_POINT_AT_INFINITY) return null;

I think its worth just adding a comment stating that we are doing it for spec compliance and then point to this PR for future reference of where in the actual code we are handling the condition and that should cover us for spirit of intent and correctness with regards to the spec

@codecov
Copy link

codecov bot commented Sep 24, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.22%. Comparing base (c0078a1) to head (ce427ab).
⚠️ Report is 11 commits behind head on unstable.

Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #8450      +/-   ##
============================================
- Coverage     52.24%   52.22%   -0.03%     
============================================
  Files           853      853              
  Lines         64770    64899     +129     
  Branches       4764     4769       +5     
============================================
+ Hits          33841    33894      +53     
- Misses        30859    30935      +76     
  Partials         70       70              
🚀 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.

Copy link
Member

@matthewkeil matthewkeil left a comment

Choose a reason for hiding this comment

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

LGTM 🚀

@ensi321 ensi321 merged commit 643a113 into unstable Sep 24, 2025
24 of 26 checks passed
@ensi321 ensi321 deleted the nc/sort-indices-in-recovery branch September 24, 2025 17:58
@wemeetagain
Copy link
Member

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

6 participants