Skip to content

feat: add payload envelope reqresp - #9050

Merged
nflaig merged 15 commits into
unstablefrom
nc/epbs-reqresp
Mar 25, 2026
Merged

feat: add payload envelope reqresp#9050
nflaig merged 15 commits into
unstablefrom
nc/epbs-reqresp

Conversation

@ensi321

@ensi321 ensi321 commented Mar 17, 2026

Copy link
Copy Markdown
Member

No description provided.

@ensi321
ensi321 requested a review from a team as a code owner March 17, 2026 00:20
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

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

This pull request introduces new peer-to-peer (P2P) protocols to enable the retrieval of execution payload envelopes within the beacon node network. These additions are critical for supporting upcoming network requirements, likely associated with a new Ethereum fork, by allowing nodes to efficiently request and serve execution payload data either by block root or by a specified slot range.

Highlights

  • New P2P Protocols: Introduced two new P2P request/response protocols: ExecutionPayloadEnvelopesByRoot and ExecutionPayloadEnvelopesByRange to facilitate the retrieval of execution payload envelopes.
  • Handler Implementation: Implemented dedicated handlers for these new protocols, enabling the beacon node to fetch execution payload envelopes from its database based on either block root or a specified slot range, covering both finalized and unfinalized data.
  • Fork Integration: Integrated the new protocols into the ReqRespBeaconNode, activating them conditionally when the gloas fork is active.
  • Network Health Management: Established rate limiting configurations and updated peer scoring mechanisms for the newly introduced protocols to ensure network stability and prevent abuse.
  • Type Definitions: Defined necessary SSZ (Simple Serialize) types and updated request/response structures across various modules to support the new payload envelope data and protocols.

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

Changelog
  • packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts
    • Enabled ExecutionPayloadEnvelopesByRoot and ExecutionPayloadEnvelopesByRange protocols for the gloas fork.
  • packages/beacon-node/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts
    • Added a new handler for ExecutionPayloadEnvelopesByRange requests, fetching payload envelopes by slot range from both finalized and unfinalized databases.
  • packages/beacon-node/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts
    • Added a new handler for ExecutionPayloadEnvelopesByRoot requests, fetching payload envelopes by block root.
  • packages/beacon-node/src/network/reqresp/handlers/index.ts
    • Imported and registered the new ExecutionPayloadEnvelopesByRoot and ExecutionPayloadEnvelopesByRange handlers.
  • packages/beacon-node/src/network/reqresp/protocols.ts
    • Defined ExecutionPayloadEnvelopesByRoot and ExecutionPayloadEnvelopesByRange protocols.
  • packages/beacon-node/src/network/reqresp/rateLimit.ts
    • Configured rate limits for the new ExecutionPayloadEnvelopesByRoot and ExecutionPayloadEnvelopesByRange methods.
  • packages/beacon-node/src/network/reqresp/score.ts
    • Updated peer scoring logic to include ExecutionPayloadEnvelopesByRange in mid-tolerance error handling.
  • packages/beacon-node/src/network/reqresp/types.ts
    • Expanded ReqRespMethod enum, request/response body types, and SSZ type mappings to include the new payload envelope protocols.
    • Imported gloas types.
  • packages/beacon-node/src/util/types.ts
    • Defined ExecutionPayloadEnvelopesByRootRequestType and its corresponding TypeScript type.
  • packages/types/src/gloas/sszTypes.ts
    • Added SSZ type definition for ExecutionPayloadEnvelopesByRangeRequest.
  • packages/types/src/gloas/types.ts
    • Added TypeScript type definition for ExecutionPayloadEnvelopesByRangeRequest.
Activity
  • No specific activity (comments, reviews, progress) was provided in the context for this pull request.
Using Gemini Code Assist

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

Invoking Gemini

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

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

Customization

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

Limitations & Feedback

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

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

Footnotes

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

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for ExecutionPayloadEnvelopes request-response protocols, which is a key feature for the upcoming gloas fork. The changes are well-structured and follow the existing patterns for adding new network protocols. I've identified one minor omission related to peer scoring on request timeouts that should be addressed for consistency.

Comment thread packages/beacon-node/src/network/reqresp/score.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2e20f2b08a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

}

// TODO GLOAS: Use chain.getSerializedExecutionPayloadEnvelope() to check in-memory caches before hitting the db when the method is available
const envelopeBytes = await db.executionPayloadEnvelope.getBinary(root);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Read finalized envelopes when serving by-root requests

This handler accepts roots from the MIN_EPOCHS_FOR_BLOCK_REQUESTS window but only reads from db.executionPayloadEnvelope (hot/unfinalized storage), so valid finalized roots in that window are silently skipped once data is archived/pruned from hot DB. In practice, peers requesting older-but-still-allowed roots will get empty responses even when the node has the envelope in archive, so this needs a finalized fallback path before continuing.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We probably can. But onBeaconBlocksByRoot currently doesn't serve blocks from cold db. A TODO was added in #8784. We probably want to wait until that is resolved before we serve finalized payloads

@nflaig nflaig Mar 25, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this looks like a regression to me, I am pretty sure we previously served these, and it's now also required by spec ethereum/consensus-specs#4950

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@ensi321 can you add a TODO for this, or even better, address this for payloads in this PR, this is just a bug and not compliant with the spec

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We probably can. But onBeaconBlocksByRoot currently doesn't serve blocks from cold db. A TODO was added in #8784. We probably want to wait until that is resolved before we serve finalized payloads

@ensi321 this doesn't seem true, I looked at the code today and it seems good to me, the TODO is something else and I am not even sure it's real (or at most just a very unlikely race condition)

see #9108 (comment)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@ensi321 can you add a TODO for this, or even better, address this for payloads in this PR, this is just a bug and not compliant with the spec

also already resolved, see #9111 (comment)

@github-actions

github-actions Bot commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: 7b83a39 Previous: 7e96447 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 1.1615 ms/op 874.68 us/op 1.33
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 42.471 us/op 38.895 us/op 1.09
BLS verify - blst 815.97 us/op 889.54 us/op 0.92
BLS verifyMultipleSignatures 3 - blst 1.1491 ms/op 1.3727 ms/op 0.84
BLS verifyMultipleSignatures 8 - blst 1.6542 ms/op 2.3773 ms/op 0.70
BLS verifyMultipleSignatures 32 - blst 4.9602 ms/op 4.6486 ms/op 1.07
BLS verifyMultipleSignatures 64 - blst 8.9863 ms/op 8.8483 ms/op 1.02
BLS verifyMultipleSignatures 128 - blst 17.170 ms/op 16.222 ms/op 1.06
BLS deserializing 10000 signatures 722.64 ms/op 617.12 ms/op 1.17
BLS deserializing 100000 signatures 7.2116 s/op 6.1424 s/op 1.17
BLS verifyMultipleSignatures - same message - 3 - blst 903.61 us/op 928.60 us/op 0.97
BLS verifyMultipleSignatures - same message - 8 - blst 1.0056 ms/op 1.0635 ms/op 0.95
BLS verifyMultipleSignatures - same message - 32 - blst 1.6852 ms/op 1.7209 ms/op 0.98
BLS verifyMultipleSignatures - same message - 64 - blst 2.5687 ms/op 2.5940 ms/op 0.99
BLS verifyMultipleSignatures - same message - 128 - blst 4.3880 ms/op 4.2530 ms/op 1.03
BLS aggregatePubkeys 32 - blst 19.420 us/op 17.972 us/op 1.08
BLS aggregatePubkeys 128 - blst 69.082 us/op 63.310 us/op 1.09
getSlashingsAndExits - default max 61.759 us/op 39.104 us/op 1.58
getSlashingsAndExits - 2k 297.90 us/op 317.96 us/op 0.94
isKnown best case - 1 super set check 207.00 ns/op 421.00 ns/op 0.49
isKnown normal case - 2 super set checks 205.00 ns/op 409.00 ns/op 0.50
isKnown worse case - 16 super set checks 201.00 ns/op 409.00 ns/op 0.49
validate api signedAggregateAndProof - struct 1.3315 ms/op 1.4710 ms/op 0.91
validate gossip signedAggregateAndProof - struct 1.3551 ms/op 1.9329 ms/op 0.70
batch validate gossip attestation - vc 640000 - chunk 32 117.09 us/op 109.84 us/op 1.07
batch validate gossip attestation - vc 640000 - chunk 64 103.54 us/op 95.385 us/op 1.09
batch validate gossip attestation - vc 640000 - chunk 128 96.056 us/op 87.544 us/op 1.10
batch validate gossip attestation - vc 640000 - chunk 256 93.838 us/op 83.055 us/op 1.13
bytes32 toHexString 360.00 ns/op 547.00 ns/op 0.66
bytes32 Buffer.toString(hex) 238.00 ns/op 409.00 ns/op 0.58
bytes32 Buffer.toString(hex) from Uint8Array 325.00 ns/op 491.00 ns/op 0.66
bytes32 Buffer.toString(hex) + 0x 244.00 ns/op 396.00 ns/op 0.62
Return object 10000 times 0.25140 ns/op 0.23530 ns/op 1.07
Throw Error 10000 times 4.0154 us/op 3.3900 us/op 1.18
toHex 136.63 ns/op 101.77 ns/op 1.34
Buffer.from 125.49 ns/op 94.790 ns/op 1.32
shared Buffer 76.345 ns/op 67.366 ns/op 1.13
fastMsgIdFn sha256 / 200 bytes 1.7870 us/op 1.7430 us/op 1.03
fastMsgIdFn h32 xxhash / 200 bytes 195.00 ns/op 384.00 ns/op 0.51
fastMsgIdFn h64 xxhash / 200 bytes 265.00 ns/op 429.00 ns/op 0.62
fastMsgIdFn sha256 / 1000 bytes 5.8940 us/op 5.3100 us/op 1.11
fastMsgIdFn h32 xxhash / 1000 bytes 288.00 ns/op 485.00 ns/op 0.59
fastMsgIdFn h64 xxhash / 1000 bytes 311.00 ns/op 488.00 ns/op 0.64
fastMsgIdFn sha256 / 10000 bytes 52.055 us/op 42.454 us/op 1.23
fastMsgIdFn h32 xxhash / 10000 bytes 1.3500 us/op 1.5240 us/op 0.89
fastMsgIdFn h64 xxhash / 10000 bytes 923.00 ns/op 1.0800 us/op 0.85
send data - 1000 256B messages 4.5269 ms/op 4.1919 ms/op 1.08
send data - 1000 512B messages 4.6397 ms/op 4.2167 ms/op 1.10
send data - 1000 1024B messages 5.0452 ms/op 4.3049 ms/op 1.17
send data - 1000 1200B messages 4.9371 ms/op 4.8521 ms/op 1.02
send data - 1000 2048B messages 4.7217 ms/op 5.1791 ms/op 0.91
send data - 1000 4096B messages 6.3715 ms/op 5.5341 ms/op 1.15
send data - 1000 16384B messages 50.432 ms/op 47.954 ms/op 1.05
send data - 1000 65536B messages 155.98 ms/op 117.15 ms/op 1.33
enrSubnets - fastDeserialize 64 bits 905.00 ns/op 1.1780 us/op 0.77
enrSubnets - ssz BitVector 64 bits 325.00 ns/op 498.00 ns/op 0.65
enrSubnets - fastDeserialize 4 bits 137.00 ns/op 328.00 ns/op 0.42
enrSubnets - ssz BitVector 4 bits 326.00 ns/op 508.00 ns/op 0.64
prioritizePeers score -10:0 att 32-0.1 sync 2-0 229.69 us/op 261.17 us/op 0.88
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 254.61 us/op 235.83 us/op 1.08
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 384.17 us/op 342.71 us/op 1.12
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 702.05 us/op 595.22 us/op 1.18
prioritizePeers score 0:0 att 64-1 sync 4-1 859.23 us/op 730.11 us/op 1.18
array of 16000 items push then shift 1.6127 us/op 1.2452 us/op 1.30
LinkedList of 16000 items push then shift 7.4160 ns/op 8.6320 ns/op 0.86
array of 16000 items push then pop 73.422 ns/op 69.058 ns/op 1.06
LinkedList of 16000 items push then pop 7.0030 ns/op 6.4720 ns/op 1.08
array of 24000 items push then shift 2.3554 us/op 2.0370 us/op 1.16
LinkedList of 24000 items push then shift 7.3480 ns/op 7.6210 ns/op 0.96
array of 24000 items push then pop 103.83 ns/op 96.044 ns/op 1.08
LinkedList of 24000 items push then pop 7.0060 ns/op 6.4700 ns/op 1.08
intersect bitArray bitLen 8 5.5650 ns/op 4.9250 ns/op 1.13
intersect array and set length 8 31.802 ns/op 31.470 ns/op 1.01
intersect bitArray bitLen 128 28.061 ns/op 26.440 ns/op 1.06
intersect array and set length 128 535.60 ns/op 502.57 ns/op 1.07
bitArray.getTrueBitIndexes() bitLen 128 1.1030 us/op 1.2050 us/op 0.92
bitArray.getTrueBitIndexes() bitLen 248 1.9580 us/op 1.9580 us/op 1.00
bitArray.getTrueBitIndexes() bitLen 512 3.7040 us/op 3.8770 us/op 0.96
Full columns - reconstruct all 6 blobs 319.64 us/op 202.20 us/op 1.58
Full columns - reconstruct half of the blobs out of 6 100.15 us/op 107.15 us/op 0.93
Full columns - reconstruct single blob out of 6 31.065 us/op 33.227 us/op 0.93
Half columns - reconstruct all 6 blobs 264.65 ms/op 253.31 ms/op 1.04
Half columns - reconstruct half of the blobs out of 6 132.12 ms/op 130.09 ms/op 1.02
Half columns - reconstruct single blob out of 6 49.170 ms/op 47.855 ms/op 1.03
Full columns - reconstruct all 10 blobs 335.99 us/op 416.88 us/op 0.81
Full columns - reconstruct half of the blobs out of 10 223.60 us/op 180.65 us/op 1.24
Full columns - reconstruct single blob out of 10 31.336 us/op 26.931 us/op 1.16
Half columns - reconstruct all 10 blobs 436.72 ms/op 419.11 ms/op 1.04
Half columns - reconstruct half of the blobs out of 10 221.06 ms/op 222.16 ms/op 1.00
Half columns - reconstruct single blob out of 10 48.582 ms/op 48.732 ms/op 1.00
Full columns - reconstruct all 20 blobs 929.34 us/op 815.93 us/op 1.14
Full columns - reconstruct half of the blobs out of 20 362.90 us/op 351.12 us/op 1.03
Full columns - reconstruct single blob out of 20 33.185 us/op 26.858 us/op 1.24
Half columns - reconstruct all 20 blobs 880.46 ms/op 836.41 ms/op 1.05
Half columns - reconstruct half of the blobs out of 20 457.08 ms/op 419.56 ms/op 1.09
Half columns - reconstruct single blob out of 20 51.838 ms/op 47.086 ms/op 1.10
Set add up to 64 items then delete first 2.0555 us/op 1.6618 us/op 1.24
OrderedSet add up to 64 items then delete first 3.0409 us/op 2.5536 us/op 1.19
Set add up to 64 items then delete last 2.3153 us/op 1.9034 us/op 1.22
OrderedSet add up to 64 items then delete last 3.4716 us/op 2.8280 us/op 1.23
Set add up to 64 items then delete middle 2.3140 us/op 1.9713 us/op 1.17
OrderedSet add up to 64 items then delete middle 5.0474 us/op 4.2977 us/op 1.17
Set add up to 128 items then delete first 4.8180 us/op 3.7431 us/op 1.29
OrderedSet add up to 128 items then delete first 8.0166 us/op 5.7682 us/op 1.39
Set add up to 128 items then delete last 4.6063 us/op 3.6152 us/op 1.27
OrderedSet add up to 128 items then delete last 6.8588 us/op 5.4104 us/op 1.27
Set add up to 128 items then delete middle 4.5109 us/op 3.6226 us/op 1.25
OrderedSet add up to 128 items then delete middle 13.734 us/op 11.345 us/op 1.21
Set add up to 256 items then delete first 10.007 us/op 7.4081 us/op 1.35
OrderedSet add up to 256 items then delete first 14.472 us/op 12.508 us/op 1.16
Set add up to 256 items then delete last 9.5894 us/op 7.3776 us/op 1.30
OrderedSet add up to 256 items then delete last 15.021 us/op 11.521 us/op 1.30
Set add up to 256 items then delete middle 9.4502 us/op 6.9093 us/op 1.37
OrderedSet add up to 256 items then delete middle 40.906 us/op 37.020 us/op 1.10
pass gossip attestations to forkchoice per slot 486.69 us/op 395.32 us/op 1.23
computeDeltas 1400000 validators 0% inactive 14.271 ms/op 12.332 ms/op 1.16
computeDeltas 1400000 validators 10% inactive 14.276 ms/op 11.105 ms/op 1.29
computeDeltas 1400000 validators 20% inactive 12.454 ms/op 10.396 ms/op 1.20
computeDeltas 1400000 validators 50% inactive 9.8037 ms/op 7.9768 ms/op 1.23
computeDeltas 2100000 validators 0% inactive 21.231 ms/op 17.862 ms/op 1.19
computeDeltas 2100000 validators 10% inactive 19.423 ms/op 16.734 ms/op 1.16
computeDeltas 2100000 validators 20% inactive 17.753 ms/op 15.565 ms/op 1.14
computeDeltas 2100000 validators 50% inactive 14.072 ms/op 8.9982 ms/op 1.56
altair processAttestation - setStatus - 1/6 committees join 508.00 ns/op 1.3560 us/op 0.37
altair processAttestation - setStatus - 1/3 committees join 857.00 ns/op 1.0590 us/op 0.81
altair processAttestation - setStatus - 1/2 committees join 1.2060 us/op 1.2940 us/op 0.93
altair processAttestation - setStatus - 2/3 committees join 1.4000 us/op 1.4260 us/op 0.98
altair processAttestation - setStatus - 4/5 committees join 1.6040 us/op 1.5780 us/op 1.02
altair processAttestation - setStatus - 100% committees join 1.8620 us/op 1.8360 us/op 1.01
phase0 processBlock - 250000 vs - 7PWei normalcase 1.4786 ms/op 1.6090 ms/op 0.92
phase0 processBlock - 250000 vs - 7PWei worstcase 19.248 ms/op 20.637 ms/op 0.93
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:16 6.0400 us/op 3.2060 us/op 1.88
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:220 34.737 us/op 34.455 us/op 1.01
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:43 10.724 us/op 8.5530 us/op 1.25
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:19 7.2530 us/op 3.6950 us/op 1.96
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1021 133.70 us/op 89.915 us/op 1.49
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11778 1.7300 ms/op 1.3850 ms/op 1.25
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 2.2315 ms/op 1.8494 ms/op 1.21
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 2.1687 ms/op 1.7200 ms/op 1.26
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 4.5333 ms/op 3.7825 ms/op 1.20
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.6971 ms/op 2.0362 ms/op 1.32
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.8866 ms/op 4.2199 ms/op 1.16
Tree 40 250000 create 367.33 ms/op 317.49 ms/op 1.16
Tree 40 250000 get(125000) 124.71 ns/op 96.236 ns/op 1.30
Tree 40 250000 set(125000) 1.2120 us/op 1.0273 us/op 1.18
Tree 40 250000 toArray() 13.596 ms/op 9.0991 ms/op 1.49
Tree 40 250000 iterate all - toArray() + loop 14.330 ms/op 17.120 ms/op 0.84
Tree 40 250000 iterate all - get(i) 43.970 ms/op 38.259 ms/op 1.15
Array 250000 create 2.5321 ms/op 2.0894 ms/op 1.21
Array 250000 clone - spread 821.40 us/op 641.80 us/op 1.28
Array 250000 get(125000) 0.34800 ns/op 0.52500 ns/op 0.66
Array 250000 set(125000) 0.36300 ns/op 0.52800 ns/op 0.69
Array 250000 iterate all - loop 62.006 us/op 57.946 us/op 1.07
phase0 afterProcessEpoch - 250000 vs - 7PWei 41.082 ms/op 38.753 ms/op 1.06
Array.fill - length 1000000 2.9283 ms/op 1.9843 ms/op 1.48
Array push - length 1000000 11.177 ms/op 7.1091 ms/op 1.57
Array.get 0.21952 ns/op 0.20661 ns/op 1.06
Uint8Array.get 0.21979 ns/op 0.20315 ns/op 1.08
phase0 beforeProcessEpoch - 250000 vs - 7PWei 17.578 ms/op 11.960 ms/op 1.47
altair processEpoch - mainnet_e81889 301.57 ms/op 241.55 ms/op 1.25
mainnet_e81889 - altair beforeProcessEpoch 17.592 ms/op 17.178 ms/op 1.02
mainnet_e81889 - altair processJustificationAndFinalization 7.4200 us/op 5.4800 us/op 1.35
mainnet_e81889 - altair processInactivityUpdates 3.8427 ms/op 4.3605 ms/op 0.88
mainnet_e81889 - altair processRewardsAndPenalties 20.226 ms/op 19.190 ms/op 1.05
mainnet_e81889 - altair processRegistryUpdates 627.00 ns/op 820.00 ns/op 0.76
mainnet_e81889 - altair processSlashings 158.00 ns/op 379.00 ns/op 0.42
mainnet_e81889 - altair processEth1DataReset 159.00 ns/op 370.00 ns/op 0.43
mainnet_e81889 - altair processEffectiveBalanceUpdates 2.4026 ms/op 2.3362 ms/op 1.03
mainnet_e81889 - altair processSlashingsReset 790.00 ns/op 995.00 ns/op 0.79
mainnet_e81889 - altair processRandaoMixesReset 1.1310 us/op 1.6550 us/op 0.68
mainnet_e81889 - altair processHistoricalRootsUpdate 154.00 ns/op 398.00 ns/op 0.39
mainnet_e81889 - altair processParticipationFlagUpdates 483.00 ns/op 713.00 ns/op 0.68
mainnet_e81889 - altair processSyncCommitteeUpdates 126.00 ns/op 348.00 ns/op 0.36
mainnet_e81889 - altair afterProcessEpoch 43.054 ms/op 39.649 ms/op 1.09
capella processEpoch - mainnet_e217614 785.15 ms/op 749.91 ms/op 1.05
mainnet_e217614 - capella beforeProcessEpoch 58.744 ms/op 60.893 ms/op 0.96
mainnet_e217614 - capella processJustificationAndFinalization 5.4380 us/op 4.8670 us/op 1.12
mainnet_e217614 - capella processInactivityUpdates 15.200 ms/op 10.948 ms/op 1.39
mainnet_e217614 - capella processRewardsAndPenalties 97.929 ms/op 96.279 ms/op 1.02
mainnet_e217614 - capella processRegistryUpdates 5.5780 us/op 4.8160 us/op 1.16
mainnet_e217614 - capella processSlashings 158.00 ns/op 380.00 ns/op 0.42
mainnet_e217614 - capella processEth1DataReset 154.00 ns/op 376.00 ns/op 0.41
mainnet_e217614 - capella processEffectiveBalanceUpdates 12.129 ms/op 15.273 ms/op 0.79
mainnet_e217614 - capella processSlashingsReset 1.5000 us/op 962.00 ns/op 1.56
mainnet_e217614 - capella processRandaoMixesReset 1.0980 us/op 1.1860 us/op 0.93
mainnet_e217614 - capella processHistoricalRootsUpdate 155.00 ns/op 390.00 ns/op 0.40
mainnet_e217614 - capella processParticipationFlagUpdates 494.00 ns/op 738.00 ns/op 0.67
mainnet_e217614 - capella afterProcessEpoch 113.86 ms/op 111.82 ms/op 1.02
phase0 processEpoch - mainnet_e58758 241.51 ms/op 202.56 ms/op 1.19
mainnet_e58758 - phase0 beforeProcessEpoch 48.431 ms/op 53.264 ms/op 0.91
mainnet_e58758 - phase0 processJustificationAndFinalization 5.3360 us/op 4.8380 us/op 1.10
mainnet_e58758 - phase0 processRewardsAndPenalties 18.921 ms/op 16.505 ms/op 1.15
mainnet_e58758 - phase0 processRegistryUpdates 2.7550 us/op 3.2040 us/op 0.86
mainnet_e58758 - phase0 processSlashings 162.00 ns/op 398.00 ns/op 0.41
mainnet_e58758 - phase0 processEth1DataReset 157.00 ns/op 390.00 ns/op 0.40
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.2794 ms/op 962.30 us/op 1.33
mainnet_e58758 - phase0 processSlashingsReset 930.00 ns/op 1.0240 us/op 0.91
mainnet_e58758 - phase0 processRandaoMixesReset 1.0710 us/op 1.2450 us/op 0.86
mainnet_e58758 - phase0 processHistoricalRootsUpdate 222.00 ns/op 383.00 ns/op 0.58
mainnet_e58758 - phase0 processParticipationRecordUpdates 816.00 ns/op 1.1950 us/op 0.68
mainnet_e58758 - phase0 afterProcessEpoch 35.172 ms/op 34.321 ms/op 1.02
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.6943 ms/op 957.27 us/op 1.77
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 2.7935 ms/op 1.5227 ms/op 1.83
altair processInactivityUpdates - 250000 normalcase 55.670 us/op 55.672 us/op 1.00
altair processInactivityUpdates - 250000 worstcase 54.975 us/op 54.302 us/op 1.01
phase0 processRegistryUpdates - 250000 normalcase 4.9410 us/op 5.9850 us/op 0.83
phase0 processRegistryUpdates - 250000 badcase_full_deposits 192.44 us/op 243.95 us/op 0.79
phase0 processRegistryUpdates - 250000 worstcase 0.5 67.631 ms/op 62.513 ms/op 1.08
altair processRewardsAndPenalties - 250000 normalcase 98.640 us/op 83.797 us/op 1.18
altair processRewardsAndPenalties - 250000 worstcase 88.791 us/op 81.993 us/op 1.08
phase0 getAttestationDeltas - 250000 normalcase 6.5922 ms/op 4.6965 ms/op 1.40
phase0 getAttestationDeltas - 250000 worstcase 6.8689 ms/op 4.7573 ms/op 1.44
phase0 processSlashings - 250000 worstcase 78.666 us/op 89.218 us/op 0.88
altair processSyncCommitteeUpdates - 250000 8.5269 ms/op 7.8630 ms/op 1.08
BeaconState.hashTreeRoot - No change 193.00 ns/op 431.00 ns/op 0.45
BeaconState.hashTreeRoot - 1 full validator 87.032 us/op 74.691 us/op 1.17
BeaconState.hashTreeRoot - 32 full validator 727.89 us/op 1.0124 ms/op 0.72
BeaconState.hashTreeRoot - 512 full validator 7.1889 ms/op 7.6708 ms/op 0.94
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 86.153 us/op 120.89 us/op 0.71
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.3549 ms/op 2.5256 ms/op 0.54
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 14.596 ms/op 15.951 ms/op 0.92
BeaconState.hashTreeRoot - 1 balances 70.268 us/op 92.369 us/op 0.76
BeaconState.hashTreeRoot - 32 balances 767.95 us/op 799.39 us/op 0.96
BeaconState.hashTreeRoot - 512 balances 5.8863 ms/op 6.1408 ms/op 0.96
BeaconState.hashTreeRoot - 250000 balances 123.33 ms/op 133.65 ms/op 0.92
aggregationBits - 2048 els - zipIndexesInBitList 20.776 us/op 19.078 us/op 1.09
regular array get 100000 times 24.413 us/op 23.474 us/op 1.04
wrappedArray get 100000 times 24.256 us/op 23.708 us/op 1.02
arrayWithProxy get 100000 times 13.667 ms/op 10.578 ms/op 1.29
ssz.Root.equals 23.383 ns/op 21.889 ns/op 1.07
byteArrayEquals 23.003 ns/op 23.878 ns/op 0.96
Buffer.compare 9.8020 ns/op 9.1340 ns/op 1.07
processSlot - 1 slots 10.405 us/op 12.212 us/op 0.85
processSlot - 32 slots 1.9635 ms/op 2.6943 ms/op 0.73
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 4.6090 ms/op 1.0258 ms/op 4.49
getCommitteeAssignments - req 1 vs - 250000 vc 1.8256 ms/op 1.6817 ms/op 1.09
getCommitteeAssignments - req 100 vs - 250000 vc 3.6009 ms/op 3.4202 ms/op 1.05
getCommitteeAssignments - req 1000 vs - 250000 vc 3.8618 ms/op 3.7213 ms/op 1.04
findModifiedValidators - 10000 modified validators 475.72 ms/op 463.82 ms/op 1.03
findModifiedValidators - 1000 modified validators 317.17 ms/op 440.26 ms/op 0.72
findModifiedValidators - 100 modified validators 242.21 ms/op 236.15 ms/op 1.03
findModifiedValidators - 10 modified validators 130.01 ms/op 155.67 ms/op 0.84
findModifiedValidators - 1 modified validators 143.19 ms/op 138.60 ms/op 1.03
findModifiedValidators - no difference 155.54 ms/op 141.78 ms/op 1.10
migrate state 1500000 validators, 3400 modified, 2000 new 360.46 ms/op 337.73 ms/op 1.07
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 4.0600 ns/op 5.9300 ns/op 0.68
state getBlockRootAtSlot - 250000 vs - 7PWei 347.23 ns/op 395.71 ns/op 0.88
computeProposerIndex 100000 validators 1.5022 ms/op 1.3780 ms/op 1.09
getNextSyncCommitteeIndices 1000 validators 3.2743 ms/op 2.8917 ms/op 1.13
getNextSyncCommitteeIndices 10000 validators 3.2877 ms/op 2.9065 ms/op 1.13
getNextSyncCommitteeIndices 100000 validators 3.2816 ms/op 2.8994 ms/op 1.13
computeProposers - vc 250000 607.73 us/op 558.95 us/op 1.09
computeEpochShuffling - vc 250000 41.294 ms/op 38.789 ms/op 1.06
getNextSyncCommittee - vc 250000 10.404 ms/op 9.6412 ms/op 1.08
nodejs block root to RootHex using toHex 145.24 ns/op 110.21 ns/op 1.32
nodejs block root to RootHex using toRootHex 79.882 ns/op 71.782 ns/op 1.11
nodejs fromHex(blob) 361.91 us/op 417.62 us/op 0.87
nodejs fromHexInto(blob) 676.09 us/op 641.81 us/op 1.05
nodejs block root to RootHex using the deprecated toHexString 543.16 ns/op 549.51 ns/op 0.99
nodejs byteArrayEquals 32 bytes (block root) 27.117 ns/op 27.215 ns/op 1.00
nodejs byteArrayEquals 48 bytes (pubkey) 38.824 ns/op 42.134 ns/op 0.92
nodejs byteArrayEquals 96 bytes (signature) 37.712 ns/op 34.912 ns/op 1.08
nodejs byteArrayEquals 1024 bytes 43.358 ns/op 41.161 ns/op 1.05
nodejs byteArrayEquals 131072 bytes (blob) 1.8176 us/op 1.7716 us/op 1.03
browser block root to RootHex using toHex 156.31 ns/op 149.42 ns/op 1.05
browser block root to RootHex using toRootHex 147.61 ns/op 135.13 ns/op 1.09
browser fromHex(blob) 1.0670 ms/op 917.21 us/op 1.16
browser fromHexInto(blob) 711.34 us/op 598.22 us/op 1.19
browser block root to RootHex using the deprecated toHexString 383.66 ns/op 348.14 ns/op 1.10
browser byteArrayEquals 32 bytes (block root) 30.393 ns/op 29.086 ns/op 1.04
browser byteArrayEquals 48 bytes (pubkey) 42.440 ns/op 38.043 ns/op 1.12
browser byteArrayEquals 96 bytes (signature) 83.354 ns/op 74.126 ns/op 1.12
browser byteArrayEquals 1024 bytes 781.29 ns/op 723.31 ns/op 1.08
browser byteArrayEquals 131072 bytes (blob) 98.999 us/op 91.199 us/op 1.09

by benchmarkbot/action

@nflaig nflaig left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this PR needs to be reworked once payload input PR is merged, let's hold off on it for now

Comment thread packages/beacon-node/src/network/reqresp/score.ts
Comment thread packages/beacon-node/src/chain/chain.ts Outdated
Comment thread packages/beacon-node/src/chain/chain.ts Outdated
Comment thread packages/beacon-node/src/network/network.ts
@nflaig

nflaig commented Mar 24, 2026

Copy link
Copy Markdown
Member

to quickly summarize how I think we should deal with orphaned payloads

by range

  • never serve orphaned payloads
  • for unfinalized data, serve only envelopes that match our current fork choice view
  • for finalized data, do not serve them either, already handled since we prune orphaned payloads before archiving

by root

  • for unfinalized data, serve payloads irrespective of fork choice view since it's a single item lookup
  • for finalized data, do not serve them, already handled by archiving (same as by range)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@nflaig
nflaig merged commit b10dfac into unstable Mar 25, 2026
25 of 27 checks passed
@nflaig
nflaig deleted the nc/epbs-reqresp branch March 25, 2026 14:25
@codecov

codecov Bot commented Mar 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.42%. Comparing base (7e96447) to head (22149ba).
⚠️ Report is 1 commits behind head on unstable.

Additional details and impacted files
@@            Coverage Diff            @@
##           unstable    #9050   +/-   ##
=========================================
  Coverage     52.42%   52.42%           
=========================================
  Files           848      848           
  Lines         61674    61674           
  Branches       4529     4529           
=========================================
  Hits          32334    32334           
  Misses        29275    29275           
  Partials         65       65           
🚀 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.

@wemeetagain

Copy link
Copy Markdown
Member

🎉 This PR is included in v1.42.0 🎉

nflaig pushed a commit that referenced this pull request Aug 4, 2026
**Motivation**

Port of an outstanding fix from the `glamsterdam-devnet-7` branch
(#9587) that never landed on `unstable`.

#9050 added the `ExecutionPayloadEnvelopesByRange` req/resp method with
a `byPeer` quota of `MAX_REQUEST_BLOCKS_DENEB` (128), while the spec
caps envelope range requests at `MAX_REQUEST_PAYLOADS` per
https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.12/specs/gloas/p2p-interface.md#executionpayloadenvelopesbyrange-v1.
The `getRequestCount` side already uses `MAX_REQUEST_PAYLOADS`; the
`byPeer` quota was left inconsistent.

**Description**

- Use `config.MAX_REQUEST_PAYLOADS` for the
`ExecutionPayloadEnvelopesByRange` `byPeer` quota
- Add a unit test asserting the quota matches `MAX_REQUEST_PAYLOADS`

Cherry-picked from `glamsterdam-devnet-7` (88b8052, original author
@nflaig); applied without conflicts.

**AI Assistance Disclosure**

- [x] I have read the [contributor
guidelines](https://github.com/ChainSafe/lodestar/blob/unstable/CONTRIBUTING.md#ai-assistance-notice)
and disclosed my usage of AI below.

Cherry-pick selection and verification done with AI assistance (Claude
Code); original commit authored by @nflaig on the devnet-7 branch.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants