Skip to content

feat: state cache for ePBS - #8868

Merged
twoeths merged 25 commits into
unstablefrom
nc/epbs-state-cache
Mar 19, 2026
Merged

feat: state cache for ePBS#8868
twoeths merged 25 commits into
unstablefrom
nc/epbs-state-cache

Conversation

@ensi321

@ensi321 ensi321 commented Feb 6, 2026

Copy link
Copy Markdown
Member

Summary

This PR extends the Gloas ePBS state cache architecture to support dual state variants (block state and payload state) by threading the payloadPresent flag through the state cache layer, regeneration system, and archive store.

Context

Building on the fork choice changes in nc/epbs-fc (which stores checkpoints with payload status), this PR completes the state cache implementation for Gloas ePBS by:

  1. Extending all checkpoint cache operations to track payloadPresent
  2. Updating the regeneration layer to explicitly handle both state variants
  3. Propagating payload status from block import through to checkpoint caching

Key Changes

1. State Cache Type System Updates

packages/beacon-node/src/chain/stateCache/types.ts (+208/-111 lines total across files):

  • Renamed CheckpointHexCheckpointHexPayload with required payloadPresent: boolean field
  • Updated CheckpointStateCache interface methods to accept payloadPresent parameter:
    • add(cp, state, payloadPresent) - explicitly marks state variant when adding to cache
    • getLatest(rootHex, maxEpoch, payloadPresent) - retrieves specific state variant
    • getOrReloadLatest(rootHex, maxEpoch, payloadPresent) - reloads specific state variant from disk
    • updatePreComputedCheckpoint(rootHex, epoch, payloadPresent) - tracks payload status for pre-computed states
  • Kept processState() method signature unchanged (manages both variants internally)

2. PersistentCheckpointStateCache Implementation

packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts (~289 lines modified):

  • Extended cache key format from "epoch-rootHex" to "epoch-rootHex-payloadPresent"
  • Updated toCheckpointHexPayload() helper to include payload status in keys
  • Modified all cache operations (add, get, getLatest, etc.) to handle dual state variants
  • Implemented logic to iterate both payloadPresent variants in processPastEpoch() for memory management
  • Updated cache metrics and debugging utilities to reflect dual state architecture

3. Regeneration Layer - Dual State Support

packages/beacon-node/src/chain/regen/interface.ts & queued.ts & regen.ts:

  • Added processPayloadState(payloadState) method for explicit payload state caching (Gloas-only)
    • Called after processExecutionPayloadEnvelope() when payload is revealed
    • Complements processState() which handles block state caching
  • Updated addCheckpointState(cp, state, payloadPresent) to accept payload flag
  • Extended updatePreComputedCheckpoint() with payloadPresent parameter
  • Modified getCheckpointState() and related methods to pass payloadPresent through cache lookups

4. Block Import - Payload Status Propagation

packages/beacon-node/src/chain/blocks/importBlock.ts:

  • Derive payloadPresent from block type:
    • Pre-Gloas: payloadPresent = true (execution payload embedded in block, always FULL variant)
    • Post-Gloas: payloadPresent = false (block state only, PENDING/EMPTY variant, payload not yet revealed)
  • Thread payloadPresent through checkpoint caching operations:
    • regen.addCheckpointState(cp, checkpointState, payloadPresent)

5. Archive Store - Historical State Management

packages/beacon-node/src/chain/archiveStore/:

  • Updated archiveStore.archiveState() to accept payloadPresent parameter
  • Modified archival strategies (frequencyStateArchiveStrategy) to propagate payload status
  • Ensured historical states maintain proper metadata for state variant tracking

6. API & Validation Layer Updates

packages/beacon-node/src/api/impl/:

  • Updated validator API to retrieve correct state variant with payloadPresent flag
  • Modified beacon state utilities to handle payload-aware checkpoint lookups
  • Ensured API endpoints return appropriate state variant based on block type

Technical Details

Checkpoint Key Format (Post-Gloas)

// Pre-Gloas (always single variant):
"100-0x1234abcd"  // epoch-rootHex

// Post-Gloas (dual variants):
"100-0x1234abcd-false"  // epoch-rootHex-payloadPresent (block state)
"100-0x1234abcd-true"   // epoch-rootHex-payloadPresent (payload state)

State Variant Semantics

  • Block State (payloadPresent = false): State after processing beacon block, before execution payload

    • Only exists for Gloas blocks (PENDING/EMPTY variants)
  • Payload State (payloadPresent = true): State after processing execution payload

    • Exists for all pre-Gloas blocks (single variant)
    • Exists for Gloas blocks after payload revelation

Migration & Compatibility

  • Pre-Gloas blocks: All state cache operations default to payloadPresent = true
  • Backward compatibility: Checkpoint cache can handle mix of pre-Gloas and post-Gloas states
  • Cache key migration: Existing cache entries remain valid (treated as payloadPresent = true)

Depends On


AI Disclosure: This PR was written primarily by Claude Code.

@gemini-code-assist

Copy link
Copy Markdown
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 significantly refactors the beacon node's state caching mechanism to accommodate the requirements of ePBS. By introducing a payloadPresent flag, the system can now differentiate and cache distinct states for a given checkpoint: one representing the beacon block's state and another including the full execution payload. This foundational change enables more flexible and efficient state management in an ePBS context, where block and payload processing can occur independently. The modifications span type definitions, cache key generation, and core state processing logic across various components of the node.

Highlights

  • Enhanced State Caching for ePBS: Introduced a payloadPresent flag to checkpoint state types (CheckpointHexPayload, CheckpointWithPayload), allowing the state cache to distinguish and store both beacon block states and full execution payload states. This is crucial for supporting the decoupled block and payload processing in ePBS (Ethereum Proposer-Builder Separation).
  • Dynamic Cache Sizing: The FIFOBlockStateCache now dynamically adjusts its maximum capacity, doubling it when the Gloas (ePBS) fork is reached. This ensures adequate space to cache both block and payload states, maintaining effective block depth.
  • Comprehensive Integration: The payloadPresent flag and related logic have been integrated across numerous modules, including API resolvers, archive store, block import, state regenerator, and chain event handlers, ensuring consistent handling of state variants throughout the beacon node.

🧠 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/api/impl/beacon/state/utils.ts
    • Updated resolveStateId to use CheckpointWithPayload instead of CheckpointWithHex.
  • packages/beacon-node/src/api/impl/validator/index.ts
    • Imported PayloadStatus for determining payload presence.
    • Replaced CheckpointHex with CheckpointHexPayload in waitForCheckpointState signature.
    • Modified waitForCheckpointState call to pass payloadPresent based on head.payloadStatus.
  • packages/beacon-node/src/chain/archiveStore/archiveStore.ts
    • Replaced CheckpointWithHex with CheckpointWithPayload in JobItemQueue and onFinalizedCheckpoint.
  • packages/beacon-node/src/chain/archiveStore/interface.ts
    • Updated StateArchiveStrategy interface methods to use CheckpointWithPayload.
  • packages/beacon-node/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts
    • Replaced CheckpointWithHex with CheckpointWithPayload in method signatures.
    • Added fcCheckpointToHexPayload conversion when archiving states to include payloadPresent.
  • packages/beacon-node/src/chain/blocks/importBlock.ts
    • Replaced toCheckpointHex with toCheckpointHexPayload.
    • Added logic to determine payloadPresent based on isGloasBlock and blockSummary.payloadStatus when processing states and emitting checkpoint events.
  • packages/beacon-node/src/chain/chain.ts
    • Updated imports and method signatures (getStateByCheckpoint, getStateOrBytesByCheckpoint, justifiedBalancesGetter, closestJustifiedBalancesStateToCheckpoint, onForkChoiceJustified, onForkChoiceFinalized, updateValidatorsCustodyRequirement) to use CheckpointWithPayload.
    • Modified addCheckpointState to accept a payloadPresent argument.
  • packages/beacon-node/src/chain/interface.ts
    • Added CheckpointWithPayload to imports.
    • Updated getStateOrBytesByCheckpoint signature to use CheckpointWithPayload.
  • packages/beacon-node/src/chain/prepareNextSlot.ts
    • Imported PayloadStatus.
    • Updated updatePreComputedCheckpoint to pass payloadPresent based on headBlock.payloadStatus.
  • packages/beacon-node/src/chain/regen/interface.ts
    • Replaced CheckpointHex with CheckpointHexPayload in method signatures.
    • Added processPayloadState method.
    • Modified addCheckpointState and updatePreComputedCheckpoint to include a payloadPresent parameter.
  • packages/beacon-node/src/chain/regen/queued.ts
    • Replaced CheckpointHex with CheckpointHexPayload and imported PayloadStatus.
    • Updated getPreStateSync, getClosestHeadState, addCheckpointState, and updatePreComputedCheckpoint to handle payloadPresent.
    • Implemented processPayloadState to add payload states to the block state cache.
  • packages/beacon-node/src/chain/regen/regen.ts
    • Imported PayloadStatus and ForkSeq.
    • Updated getPreState and processSlotsToNearestCheckpoint to determine and use payloadPresent based on PayloadStatus or ForkSeq.
  • packages/beacon-node/src/chain/stateCache/fifoBlockStateCache.ts
    • Imported ForkSeq.
    • Introduced DEFAULT_MAX_BLOCK_STATES_GLOAS and logic to dynamically increase maxStates when the Gloas fork is reached.
  • packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts
    • Imported CheckpointWithPayload.
    • Replaced CheckpointHex with CheckpointHexPayload throughout the file.
    • Updated toCacheKey and fromCacheKey functions to incorporate the payloadPresent flag into cache keys.
    • Added fcCheckpointToHexPayload utility for converting fork-choice checkpoints.
    • Modified add, getLatest, getOrReloadLatest, updatePreComputedCheckpoint, findSeedStateToReload, processState, and pruneFinalized to correctly utilize the payloadPresent flag.
  • packages/beacon-node/src/chain/stateCache/types.ts
    • Defined CheckpointHexPayload type to include payloadPresent: boolean.
    • Updated CheckpointStateCache interface methods to use CheckpointHexPayload and accept the payloadPresent parameter where appropriate.
  • packages/beacon-node/test/unit-minimal/chain/stateCache/persistentCheckpointsCache.test.ts
    • Updated imports and test variables to reflect the new CheckpointHexPayload type.
    • Modified calls to add, getLatest, getOrReloadLatest, getStateOrBytes, and findSeedStateToReload to pass the payloadPresent argument.
  • packages/beacon-node/test/unit/chain/regen/regen.test.ts
    • Updated cache.add calls to include the payloadPresent argument.
  • packages/beacon-node/test/utils/node/simTest.ts
    • Modified getCheckpointStateSync call to explicitly set payloadPresent: true for pre-Gloas simulation in tests.
Activity
  • The pull request introduces a new feature (feat: state cache for ePBS).
  • It is noted that this PR depends on another PR (nc/epbs-fc) to be merged first.
  • The branch will point to unstable after issue feat: implement epbs fork choice #8739 is merged, indicating a planned integration into a larger feature rollout.
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 significant refactoring to the state caching mechanism to support ePBS, where a block can have two distinct states: one with a payload and one without. The core of the changes is the introduction of a payloadPresent flag to differentiate these states, which is propagated through various types and functions related to state management. Key updates include modifying the in-memory cache key to incorporate this flag, adjusting state retrieval logic to handle both variants, and dynamically increasing cache sizes for the Gloas fork. The implementation is largely consistent and well-structured. However, I've identified a critical issue in the persistence logic where the datastore key for checkpoint states does not distinguish between the two state variants, potentially leading to data loss when both variants are persisted for the same block. This needs to be addressed to ensure the integrity of the state cache.

Comment thread packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts Outdated
Comment thread packages/beacon-node/src/chain/stateCache/fifoBlockStateCache.ts
Comment thread packages/beacon-node/src/chain/stateCache/fifoBlockStateCache.ts Outdated
Comment thread packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts Outdated
Comment thread packages/beacon-node/src/chain/chain.ts Outdated
nflaig added a commit that referenced this pull request Feb 20, 2026
nflaig added a commit that referenced this pull request Feb 20, 2026
nflaig added a commit that referenced this pull request Feb 20, 2026
Comment thread packages/beacon-node/src/chain/regen/regen.ts Outdated
Base automatically changed from nc/epbs-fc to unstable March 4, 2026 00:41
@ensi321
ensi321 force-pushed the nc/epbs-state-cache branch from 3d88a87 to 26595a7 Compare March 4, 2026 01:18
@github-actions

github-actions Bot commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: a0fc163 Previous: 9939b12 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 1.0386 ms/op 1.1102 ms/op 0.94
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 37.997 us/op 37.249 us/op 1.02
BLS verify - blst 885.80 us/op 993.19 us/op 0.89
BLS verifyMultipleSignatures 3 - blst 1.2755 ms/op 1.2519 ms/op 1.02
BLS verifyMultipleSignatures 8 - blst 1.8409 ms/op 1.8789 ms/op 0.98
BLS verifyMultipleSignatures 32 - blst 5.5004 ms/op 5.7428 ms/op 0.96
BLS verifyMultipleSignatures 64 - blst 10.636 ms/op 11.007 ms/op 0.97
BLS verifyMultipleSignatures 128 - blst 17.313 ms/op 17.732 ms/op 0.98
BLS deserializing 10000 signatures 687.40 ms/op 694.17 ms/op 0.99
BLS deserializing 100000 signatures 6.8672 s/op 6.8886 s/op 1.00
BLS verifyMultipleSignatures - same message - 3 - blst 893.03 us/op 914.80 us/op 0.98
BLS verifyMultipleSignatures - same message - 8 - blst 1.0705 ms/op 1.1068 ms/op 0.97
BLS verifyMultipleSignatures - same message - 32 - blst 1.6699 ms/op 1.8466 ms/op 0.90
BLS verifyMultipleSignatures - same message - 64 - blst 2.5627 ms/op 2.6007 ms/op 0.99
BLS verifyMultipleSignatures - same message - 128 - blst 4.3163 ms/op 4.4034 ms/op 0.98
BLS aggregatePubkeys 32 - blst 19.131 us/op 19.167 us/op 1.00
BLS aggregatePubkeys 128 - blst 70.222 us/op 68.308 us/op 1.03
getSlashingsAndExits - default max 72.621 us/op 71.162 us/op 1.02
getSlashingsAndExits - 2k 334.54 us/op 332.59 us/op 1.01
isKnown best case - 1 super set check 211.00 ns/op 208.00 ns/op 1.01
isKnown normal case - 2 super set checks 207.00 ns/op 204.00 ns/op 1.01
isKnown worse case - 16 super set checks 210.00 ns/op 205.00 ns/op 1.02
validate api signedAggregateAndProof - struct 1.6292 ms/op 1.4043 ms/op 1.16
validate gossip signedAggregateAndProof - struct 1.5145 ms/op 1.4135 ms/op 1.07
batch validate gossip attestation - vc 640000 - chunk 32 121.96 us/op 119.68 us/op 1.02
batch validate gossip attestation - vc 640000 - chunk 64 104.83 us/op 105.26 us/op 1.00
batch validate gossip attestation - vc 640000 - chunk 128 97.634 us/op 110.30 us/op 0.89
batch validate gossip attestation - vc 640000 - chunk 256 94.100 us/op 93.371 us/op 1.01
bytes32 toHexString 404.00 ns/op 348.00 ns/op 1.16
bytes32 Buffer.toString(hex) 226.00 ns/op 259.00 ns/op 0.87
bytes32 Buffer.toString(hex) from Uint8Array 347.00 ns/op 336.00 ns/op 1.03
bytes32 Buffer.toString(hex) + 0x 250.00 ns/op 266.00 ns/op 0.94
Return object 10000 times 0.22910 ns/op 0.25200 ns/op 0.91
Throw Error 10000 times 4.2673 us/op 4.2617 us/op 1.00
toHex 131.19 ns/op 131.41 ns/op 1.00
Buffer.from 124.61 ns/op 125.56 ns/op 0.99
shared Buffer 76.681 ns/op 81.535 ns/op 0.94
fastMsgIdFn sha256 / 200 bytes 1.9390 us/op 1.9190 us/op 1.01
fastMsgIdFn h32 xxhash / 200 bytes 192.00 ns/op 209.00 ns/op 0.92
fastMsgIdFn h64 xxhash / 200 bytes 372.00 ns/op 294.00 ns/op 1.27
fastMsgIdFn sha256 / 1000 bytes 6.0840 us/op 5.8970 us/op 1.03
fastMsgIdFn h32 xxhash / 1000 bytes 282.00 ns/op 281.00 ns/op 1.00
fastMsgIdFn h64 xxhash / 1000 bytes 346.00 ns/op 361.00 ns/op 0.96
fastMsgIdFn sha256 / 10000 bytes 53.500 us/op 51.682 us/op 1.04
fastMsgIdFn h32 xxhash / 10000 bytes 1.3960 us/op 1.3670 us/op 1.02
fastMsgIdFn h64 xxhash / 10000 bytes 1.2490 us/op 1.0330 us/op 1.21
send data - 1000 256B messages 5.4889 ms/op 4.7412 ms/op 1.16
send data - 1000 512B messages 4.9615 ms/op 4.8255 ms/op 1.03
send data - 1000 1024B messages 4.8947 ms/op 5.8467 ms/op 0.84
send data - 1000 1200B messages 4.9951 ms/op 5.3323 ms/op 0.94
send data - 1000 2048B messages 6.0554 ms/op 5.7764 ms/op 1.05
send data - 1000 4096B messages 7.6756 ms/op 6.5051 ms/op 1.18
send data - 1000 16384B messages 42.201 ms/op 32.521 ms/op 1.30
send data - 1000 65536B messages 98.719 ms/op 103.65 ms/op 0.95
enrSubnets - fastDeserialize 64 bits 932.00 ns/op 2.1100 us/op 0.44
enrSubnets - ssz BitVector 64 bits 393.00 ns/op 329.00 ns/op 1.19
enrSubnets - fastDeserialize 4 bits 147.00 ns/op 148.00 ns/op 0.99
enrSubnets - ssz BitVector 4 bits 339.00 ns/op 333.00 ns/op 1.02
prioritizePeers score -10:0 att 32-0.1 sync 2-0 275.59 us/op 262.76 us/op 1.05
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 259.63 us/op 273.04 us/op 0.95
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 414.00 us/op 453.11 us/op 0.91
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 813.94 us/op 713.52 us/op 1.14
prioritizePeers score 0:0 att 64-1 sync 4-1 1.0859 ms/op 849.36 us/op 1.28
array of 16000 items push then shift 1.5897 us/op 1.6102 us/op 0.99
LinkedList of 16000 items push then shift 7.2690 ns/op 8.0620 ns/op 0.90
array of 16000 items push then pop 75.180 ns/op 78.013 ns/op 0.96
LinkedList of 16000 items push then pop 7.4130 ns/op 7.2860 ns/op 1.02
array of 24000 items push then shift 2.4270 us/op 2.3678 us/op 1.02
LinkedList of 24000 items push then shift 7.5610 ns/op 7.7080 ns/op 0.98
array of 24000 items push then pop 107.39 ns/op 107.98 ns/op 0.99
LinkedList of 24000 items push then pop 7.2240 ns/op 7.4130 ns/op 0.97
intersect bitArray bitLen 8 5.8060 ns/op 5.6760 ns/op 1.02
intersect array and set length 8 33.863 ns/op 33.457 ns/op 1.01
intersect bitArray bitLen 128 29.183 ns/op 29.696 ns/op 0.98
intersect array and set length 128 558.55 ns/op 547.47 ns/op 1.02
bitArray.getTrueBitIndexes() bitLen 128 1.1580 us/op 1.0110 us/op 1.15
bitArray.getTrueBitIndexes() bitLen 248 1.8770 us/op 1.8090 us/op 1.04
bitArray.getTrueBitIndexes() bitLen 512 3.8970 us/op 3.6930 us/op 1.06
Full columns - reconstruct all 6 blobs 278.31 us/op 225.90 us/op 1.23
Full columns - reconstruct half of the blobs out of 6 129.02 us/op 111.59 us/op 1.16
Full columns - reconstruct single blob out of 6 30.717 us/op 34.001 us/op 0.90
Half columns - reconstruct all 6 blobs 267.03 ms/op 272.24 ms/op 0.98
Half columns - reconstruct half of the blobs out of 6 134.80 ms/op 138.22 ms/op 0.98
Half columns - reconstruct single blob out of 6 50.626 ms/op 51.280 ms/op 0.99
Full columns - reconstruct all 10 blobs 449.19 us/op 613.63 us/op 0.73
Full columns - reconstruct half of the blobs out of 10 228.82 us/op 208.57 us/op 1.10
Full columns - reconstruct single blob out of 10 29.602 us/op 31.929 us/op 0.93
Half columns - reconstruct all 10 blobs 435.86 ms/op 454.61 ms/op 0.96
Half columns - reconstruct half of the blobs out of 10 220.26 ms/op 231.76 ms/op 0.95
Half columns - reconstruct single blob out of 10 48.266 ms/op 52.316 ms/op 0.92
Full columns - reconstruct all 20 blobs 880.43 us/op 678.88 us/op 1.30
Full columns - reconstruct half of the blobs out of 20 339.33 us/op 346.88 us/op 0.98
Full columns - reconstruct single blob out of 20 30.249 us/op 32.759 us/op 0.92
Half columns - reconstruct all 20 blobs 875.35 ms/op 908.47 ms/op 0.96
Half columns - reconstruct half of the blobs out of 20 445.26 ms/op 450.49 ms/op 0.99
Half columns - reconstruct single blob out of 20 48.961 ms/op 51.060 ms/op 0.96
Set add up to 64 items then delete first 2.0580 us/op 2.0447 us/op 1.01
OrderedSet add up to 64 items then delete first 2.9921 us/op 3.0330 us/op 0.99
Set add up to 64 items then delete last 2.2801 us/op 2.2697 us/op 1.00
OrderedSet add up to 64 items then delete last 3.4438 us/op 3.2690 us/op 1.05
Set add up to 64 items then delete middle 2.2993 us/op 2.3343 us/op 0.98
OrderedSet add up to 64 items then delete middle 4.9413 us/op 5.2975 us/op 0.93
Set add up to 128 items then delete first 4.6720 us/op 5.0391 us/op 0.93
OrderedSet add up to 128 items then delete first 6.7418 us/op 7.7313 us/op 0.87
Set add up to 128 items then delete last 4.5694 us/op 4.9603 us/op 0.92
OrderedSet add up to 128 items then delete last 6.8112 us/op 7.0511 us/op 0.97
Set add up to 128 items then delete middle 4.5573 us/op 4.9453 us/op 0.92
OrderedSet add up to 128 items then delete middle 13.285 us/op 13.940 us/op 0.95
Set add up to 256 items then delete first 10.108 us/op 10.634 us/op 0.95
OrderedSet add up to 256 items then delete first 14.095 us/op 16.421 us/op 0.86
Set add up to 256 items then delete last 9.4458 us/op 10.036 us/op 0.94
OrderedSet add up to 256 items then delete last 14.084 us/op 14.981 us/op 0.94
Set add up to 256 items then delete middle 9.1016 us/op 9.7512 us/op 0.93
OrderedSet add up to 256 items then delete middle 40.125 us/op 42.986 us/op 0.93
pass gossip attestations to forkchoice per slot 481.88 us/op 492.87 us/op 0.98
computeDeltas 1400000 validators 0% inactive 14.109 ms/op 14.317 ms/op 0.99
computeDeltas 1400000 validators 10% inactive 13.545 ms/op 13.571 ms/op 1.00
computeDeltas 1400000 validators 20% inactive 12.466 ms/op 12.434 ms/op 1.00
computeDeltas 1400000 validators 50% inactive 9.6441 ms/op 9.8426 ms/op 0.98
computeDeltas 2100000 validators 0% inactive 21.550 ms/op 22.301 ms/op 0.97
computeDeltas 2100000 validators 10% inactive 20.319 ms/op 20.458 ms/op 0.99
computeDeltas 2100000 validators 20% inactive 18.679 ms/op 19.034 ms/op 0.98
computeDeltas 2100000 validators 50% inactive 14.495 ms/op 14.763 ms/op 0.98
altair processAttestation - setStatus - 1/6 committees join 567.00 ns/op 564.00 ns/op 1.01
altair processAttestation - setStatus - 1/3 committees join 889.00 ns/op 981.00 ns/op 0.91
altair processAttestation - setStatus - 1/2 committees join 1.2630 us/op 1.3690 us/op 0.92
altair processAttestation - setStatus - 2/3 committees join 1.4560 us/op 1.5300 us/op 0.95
altair processAttestation - setStatus - 4/5 committees join 1.6580 us/op 1.7460 us/op 0.95
altair processAttestation - setStatus - 100% committees join 1.9440 us/op 2.2510 us/op 0.86
phase0 processBlock - 250000 vs - 7PWei normalcase 2.0801 ms/op 1.7047 ms/op 1.22
phase0 processBlock - 250000 vs - 7PWei worstcase 22.330 ms/op 21.688 ms/op 1.03
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:16 9.1160 us/op 7.0040 us/op 1.30
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:220 52.720 us/op 44.883 us/op 1.17
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:43 10.470 us/op 12.460 us/op 0.84
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:19 8.0960 us/op 7.8800 us/op 1.03
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1021 179.22 us/op 210.65 us/op 0.85
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11778 1.7434 ms/op 2.6573 ms/op 0.66
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 2.1757 ms/op 2.8236 ms/op 0.77
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 2.1683 ms/op 2.2409 ms/op 0.97
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 5.2861 ms/op 4.4385 ms/op 1.19
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.5952 ms/op 2.7017 ms/op 0.96
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.9639 ms/op 4.9080 ms/op 1.01
Tree 40 250000 create 395.13 ms/op 391.26 ms/op 1.01
Tree 40 250000 get(125000) 129.55 ns/op 133.95 ns/op 0.97
Tree 40 250000 set(125000) 1.2246 us/op 1.4857 us/op 0.82
Tree 40 250000 toArray() 12.787 ms/op 18.076 ms/op 0.71
Tree 40 250000 iterate all - toArray() + loop 12.688 ms/op 18.801 ms/op 0.67
Tree 40 250000 iterate all - get(i) 46.276 ms/op 45.719 ms/op 1.01
Array 250000 create 2.4742 ms/op 2.5251 ms/op 0.98
Array 250000 clone - spread 806.63 us/op 832.18 us/op 0.97
Array 250000 get(125000) 0.34700 ns/op 0.35500 ns/op 0.98
Array 250000 set(125000) 0.38000 ns/op 0.36400 ns/op 1.04
Array 250000 iterate all - loop 62.014 us/op 61.700 us/op 1.01
phase0 afterProcessEpoch - 250000 vs - 7PWei 41.906 ms/op 42.244 ms/op 0.99
Array.fill - length 1000000 3.0797 ms/op 2.8670 ms/op 1.07
Array push - length 1000000 11.735 ms/op 10.004 ms/op 1.17
Array.get 0.22094 ns/op 0.21974 ns/op 1.01
Uint8Array.get 0.22257 ns/op 0.22201 ns/op 1.00
phase0 beforeProcessEpoch - 250000 vs - 7PWei 23.335 ms/op 16.135 ms/op 1.45
altair processEpoch - mainnet_e81889 266.22 ms/op 276.40 ms/op 0.96
mainnet_e81889 - altair beforeProcessEpoch 16.014 ms/op 23.012 ms/op 0.70
mainnet_e81889 - altair processJustificationAndFinalization 5.4400 us/op 6.8280 us/op 0.80
mainnet_e81889 - altair processInactivityUpdates 3.9688 ms/op 5.0955 ms/op 0.78
mainnet_e81889 - altair processRewardsAndPenalties 22.158 ms/op 19.889 ms/op 1.11
mainnet_e81889 - altair processRegistryUpdates 633.00 ns/op 632.00 ns/op 1.00
mainnet_e81889 - altair processSlashings 169.00 ns/op 172.00 ns/op 0.98
mainnet_e81889 - altair processEth1DataReset 178.00 ns/op 170.00 ns/op 1.05
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.7198 ms/op 1.7397 ms/op 0.99
mainnet_e81889 - altair processSlashingsReset 811.00 ns/op 1.0630 us/op 0.76
mainnet_e81889 - altair processRandaoMixesReset 1.1020 us/op 1.6380 us/op 0.67
mainnet_e81889 - altair processHistoricalRootsUpdate 175.00 ns/op 173.00 ns/op 1.01
mainnet_e81889 - altair processParticipationFlagUpdates 558.00 ns/op 539.00 ns/op 1.04
mainnet_e81889 - altair processSyncCommitteeUpdates 133.00 ns/op 137.00 ns/op 0.97
mainnet_e81889 - altair afterProcessEpoch 43.513 ms/op 43.927 ms/op 0.99
capella processEpoch - mainnet_e217614 803.84 ms/op 889.23 ms/op 0.90
mainnet_e217614 - capella beforeProcessEpoch 59.492 ms/op 66.453 ms/op 0.90
mainnet_e217614 - capella processJustificationAndFinalization 5.7280 us/op 5.8980 us/op 0.97
mainnet_e217614 - capella processInactivityUpdates 17.540 ms/op 18.346 ms/op 0.96
mainnet_e217614 - capella processRewardsAndPenalties 103.48 ms/op 105.98 ms/op 0.98
mainnet_e217614 - capella processRegistryUpdates 6.3070 us/op 6.0830 us/op 1.04
mainnet_e217614 - capella processSlashings 163.00 ns/op 141.00 ns/op 1.16
mainnet_e217614 - capella processEth1DataReset 160.00 ns/op 169.00 ns/op 0.95
mainnet_e217614 - capella processEffectiveBalanceUpdates 12.426 ms/op 14.866 ms/op 0.84
mainnet_e217614 - capella processSlashingsReset 977.00 ns/op 1.1530 us/op 0.85
mainnet_e217614 - capella processRandaoMixesReset 1.1240 us/op 1.2020 us/op 0.94
mainnet_e217614 - capella processHistoricalRootsUpdate 157.00 ns/op 187.00 ns/op 0.84
mainnet_e217614 - capella processParticipationFlagUpdates 571.00 ns/op 574.00 ns/op 0.99
mainnet_e217614 - capella afterProcessEpoch 117.03 ms/op 117.14 ms/op 1.00
phase0 processEpoch - mainnet_e58758 263.46 ms/op 250.98 ms/op 1.05
mainnet_e58758 - phase0 beforeProcessEpoch 58.504 ms/op 59.082 ms/op 0.99
mainnet_e58758 - phase0 processJustificationAndFinalization 5.4580 us/op 5.8020 us/op 0.94
mainnet_e58758 - phase0 processRewardsAndPenalties 19.007 ms/op 21.144 ms/op 0.90
mainnet_e58758 - phase0 processRegistryUpdates 2.8070 us/op 3.8960 us/op 0.72
mainnet_e58758 - phase0 processSlashings 148.00 ns/op 226.00 ns/op 0.65
mainnet_e58758 - phase0 processEth1DataReset 161.00 ns/op 180.00 ns/op 0.89
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.4140 ms/op 1.1258 ms/op 1.26
mainnet_e58758 - phase0 processSlashingsReset 886.00 ns/op 910.00 ns/op 0.97
mainnet_e58758 - phase0 processRandaoMixesReset 1.0980 us/op 1.1100 us/op 0.99
mainnet_e58758 - phase0 processHistoricalRootsUpdate 173.00 ns/op 207.00 ns/op 0.84
mainnet_e58758 - phase0 processParticipationRecordUpdates 2.7070 us/op 874.00 ns/op 3.10
mainnet_e58758 - phase0 afterProcessEpoch 35.434 ms/op 35.616 ms/op 0.99
phase0 processEffectiveBalanceUpdates - 250000 normalcase 2.4713 ms/op 2.1637 ms/op 1.14
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 2.1713 ms/op 3.8929 ms/op 0.56
altair processInactivityUpdates - 250000 normalcase 105.83 us/op 86.094 us/op 1.23
altair processInactivityUpdates - 250000 worstcase 60.745 us/op 98.184 us/op 0.62
phase0 processRegistryUpdates - 250000 normalcase 4.5090 us/op 5.8890 us/op 0.77
phase0 processRegistryUpdates - 250000 badcase_full_deposits 291.08 us/op 290.10 us/op 1.00
phase0 processRegistryUpdates - 250000 worstcase 0.5 70.490 ms/op 81.049 ms/op 0.87
altair processRewardsAndPenalties - 250000 normalcase 150.69 us/op 118.85 us/op 1.27
altair processRewardsAndPenalties - 250000 worstcase 103.03 us/op 112.12 us/op 0.92
phase0 getAttestationDeltas - 250000 normalcase 7.0553 ms/op 7.0508 ms/op 1.00
phase0 getAttestationDeltas - 250000 worstcase 6.8122 ms/op 7.0248 ms/op 0.97
phase0 processSlashings - 250000 worstcase 127.14 us/op 117.71 us/op 1.08
altair processSyncCommitteeUpdates - 250000 8.7370 ms/op 8.4933 ms/op 1.03
BeaconState.hashTreeRoot - No change 230.00 ns/op 196.00 ns/op 1.17
BeaconState.hashTreeRoot - 1 full validator 91.896 us/op 105.27 us/op 0.87
BeaconState.hashTreeRoot - 32 full validator 1.1171 ms/op 824.97 us/op 1.35
BeaconState.hashTreeRoot - 512 full validator 8.9213 ms/op 7.5863 ms/op 1.18
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 92.122 us/op 92.199 us/op 1.00
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.6416 ms/op 1.6902 ms/op 0.97
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 18.093 ms/op 25.049 ms/op 0.72
BeaconState.hashTreeRoot - 1 balances 68.829 us/op 93.819 us/op 0.73
BeaconState.hashTreeRoot - 32 balances 799.49 us/op 954.50 us/op 0.84
BeaconState.hashTreeRoot - 512 balances 5.7866 ms/op 6.8252 ms/op 0.85
BeaconState.hashTreeRoot - 250000 balances 182.73 ms/op 171.93 ms/op 1.06
aggregationBits - 2048 els - zipIndexesInBitList 21.922 us/op 17.979 us/op 1.22
regular array get 100000 times 25.614 us/op 24.645 us/op 1.04
wrappedArray get 100000 times 25.585 us/op 24.613 us/op 1.04
arrayWithProxy get 100000 times 15.619 ms/op 14.789 ms/op 1.06
ssz.Root.equals 24.838 ns/op 23.673 ns/op 1.05
byteArrayEquals 24.424 ns/op 23.230 ns/op 1.05
Buffer.compare 10.480 ns/op 9.8500 ns/op 1.06
processSlot - 1 slots 9.9230 us/op 14.282 us/op 0.69
processSlot - 32 slots 2.1373 ms/op 2.4421 ms/op 0.88
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 4.5467 ms/op 3.8485 ms/op 1.18
getCommitteeAssignments - req 1 vs - 250000 vc 1.8876 ms/op 1.8965 ms/op 1.00
getCommitteeAssignments - req 100 vs - 250000 vc 3.7604 ms/op 3.7372 ms/op 1.01
getCommitteeAssignments - req 1000 vs - 250000 vc 4.1424 ms/op 4.0342 ms/op 1.03
findModifiedValidators - 10000 modified validators 432.00 ms/op 501.03 ms/op 0.86
findModifiedValidators - 1000 modified validators 361.89 ms/op 337.89 ms/op 1.07
findModifiedValidators - 100 modified validators 188.89 ms/op 246.78 ms/op 0.77
findModifiedValidators - 10 modified validators 253.15 ms/op 145.69 ms/op 1.74
findModifiedValidators - 1 modified validators 167.91 ms/op 146.89 ms/op 1.14
findModifiedValidators - no difference 137.10 ms/op 150.20 ms/op 0.91
migrate state 1500000 validators, 3400 modified, 2000 new 366.50 ms/op 376.40 ms/op 0.97
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 4.9700 ns/op 4.1000 ns/op 1.21
state getBlockRootAtSlot - 250000 vs - 7PWei 538.27 ns/op 486.70 ns/op 1.11
computeProposerIndex 100000 validators 1.5124 ms/op 1.5004 ms/op 1.01
getNextSyncCommitteeIndices 1000 validators 3.3705 ms/op 3.3361 ms/op 1.01
getNextSyncCommitteeIndices 10000 validators 3.3404 ms/op 3.3187 ms/op 1.01
getNextSyncCommitteeIndices 100000 validators 3.3451 ms/op 3.3192 ms/op 1.01
computeProposers - vc 250000 697.12 us/op 617.85 us/op 1.13
computeEpochShuffling - vc 250000 41.660 ms/op 41.752 ms/op 1.00
getNextSyncCommittee - vc 250000 10.517 ms/op 10.388 ms/op 1.01
nodejs block root to RootHex using toHex 145.68 ns/op 140.02 ns/op 1.04
nodejs block root to RootHex using toRootHex 90.215 ns/op 90.855 ns/op 0.99
nodejs fromHex(blob) 379.07 us/op 395.52 us/op 0.96
nodejs fromHexInto(blob) 716.04 us/op 696.78 us/op 1.03
nodejs block root to RootHex using the deprecated toHexString 408.74 ns/op 437.02 ns/op 0.94
nodejs byteArrayEquals 32 bytes (block root) 28.517 ns/op 28.887 ns/op 0.99
nodejs byteArrayEquals 48 bytes (pubkey) 40.918 ns/op 41.079 ns/op 1.00
nodejs byteArrayEquals 96 bytes (signature) 40.780 ns/op 41.131 ns/op 0.99
nodejs byteArrayEquals 1024 bytes 46.649 ns/op 46.070 ns/op 1.01
nodejs byteArrayEquals 131072 bytes (blob) 1.8879 us/op 1.8653 us/op 1.01
browser block root to RootHex using toHex 162.64 ns/op 160.58 ns/op 1.01
browser block root to RootHex using toRootHex 154.60 ns/op 153.82 ns/op 1.01
browser fromHex(blob) 1.2099 ms/op 1.1198 ms/op 1.08
browser fromHexInto(blob) 695.62 us/op 711.50 us/op 0.98
browser block root to RootHex using the deprecated toHexString 380.43 ns/op 402.69 ns/op 0.94
browser byteArrayEquals 32 bytes (block root) 30.958 ns/op 31.352 ns/op 0.99
browser byteArrayEquals 48 bytes (pubkey) 43.056 ns/op 43.651 ns/op 0.99
browser byteArrayEquals 96 bytes (signature) 84.249 ns/op 85.772 ns/op 0.98
browser byteArrayEquals 1024 bytes 792.33 ns/op 826.76 ns/op 0.96
browser byteArrayEquals 131072 bytes (blob) 100.91 us/op 100.21 us/op 1.01

by benchmarkbot/action

@ensi321
ensi321 marked this pull request as ready for review March 5, 2026 02:08
@ensi321
ensi321 requested a review from a team as a code owner March 5, 2026 02:08

@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

.filter((fileName) => fileName.startsWith("0x") && fileName.length === CHECKPOINT_FILE_NAME_LENGTH)

P2 Badge Accept legacy checkpoint filenames in file datastore

readKeys() now filters strictly to 84-char filenames, so legacy 82-char checkpoint files (old 40-byte key format) are silently ignored. That breaks upgrade compatibility for nodes using the file CP datastore because previously persisted checkpoint states are no longer discoverable by readLatestSafe(), despite compatibility handling existing on the DB-key deserialization path.

ℹ️ 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".

Comment thread packages/beacon-node/src/chain/regen/queued.ts
Comment thread packages/beacon-node/src/chain/stateCache/datastore/db.ts
@nflaig

nflaig commented Mar 6, 2026

Copy link
Copy Markdown
Member

relevant discussion on discord here, seems like we can't properly serve states yet, well at least on the epbs-devnet-0 branch, not sure if that's still the case with this PR, or if we need further tweaks after this

Comment thread packages/beacon-node/src/chain/blocks/importBlock.ts Outdated
Comment thread packages/beacon-node/src/chain/archiveStore/utils/archiveBlocks.ts Outdated
Comment thread packages/beacon-node/src/chain/regen/queued.ts Outdated
Comment thread packages/beacon-node/src/chain/regen/regen.ts Outdated
Comment thread packages/beacon-node/src/chain/regen/queued.ts Outdated
…dStatus

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@nflaig

nflaig commented Mar 10, 2026

Copy link
Copy Markdown
Member

relevant discussion on discord here, seems like we can't properly serve states yet, well at least on the epbs-devnet-0 branch, not sure if that's still the case with this PR, or if we need further tweaks after this

this state cache enhancement should be straightforward enough what missing could be to populate checkpointStateCache, see this TODO

it's mostly fixed now on our epbs-devnet-0 branch in this commit 0daf882

wemeetagain and others added 8 commits March 10, 2026 19:54
…tracking (#9019)

Replace `Set<boolean>` with a numeric bitmask in the epochIndex of
PersistentCheckpointStateCache. Since payloadPresent is boolean, the Set
could only ever hold {true}, {false}, or {true, false} — at most 2
elements. A full Set object with hash table internals is significant
overhead for tracking 1-2 bits per root per epoch.

The bitmask uses PayloadAvailability (NOT_PRESENT=1, PRESENT=2) as bit
flags with standard bitwise ops: OR to set, AND to check, AND-NOT to
clear. This eliminates one Set allocation per root while keeping the
optimization entirely internal to the class — no public API changes.

Follow-up of
#9006 (comment)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
twoeths
twoeths previously approved these changes Mar 17, 2026
meta: ExecutionOptimisticFinalizedAndVersionCodec,
},
},
// TODO GLOAS: this endpoint needs to be updated because post-gloas there could be two variants of the persisted checkpoint state (empty or full).

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.

more of a question, do we actually wanna persist full states? since for checkpoint sync we always wanna use post block state (without payload applied) what's the use case for this?

instead of storing 2 states we could also just load post block state and apply payload if needed

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.

yes that could be a good improvement
right now in in checkpoint state cache it has no context of payload
whenever it goes out of memory windows (of 3 epochs), it persists whatever it has

the down side of not persisting payload state is when we have a finalized checkpoint of > 3 epochs ago, we may not have the state, we have to load post block Uint8Array state, deserialize and apply payload

Comment thread packages/beacon-node/src/api/impl/validator/index.ts
Comment thread packages/beacon-node/src/chain/archiveStore/utils/archiveBlocks.ts
Comment thread packages/beacon-node/src/chain/regen/queued.ts Outdated
Comment thread packages/beacon-node/src/chain/stateCache/datastore/db.ts Outdated
* For Gloas (ePBS), each block can have two states: block state and payload state.
* Double the cache size to maintain the same effective block depth.
*/
export const DEFAULT_MAX_BLOCK_STATES_GLOAS = 128;

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.

something feels off to me here bu would have to explore this more myself, I don't think it's necessary to store payload state, where do we use payload state if we have post block state of the next slot?

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.

whenever we run state-transition with block/payload, we need to store BeaconState in this cache
in forky condition, next blocks may build on either block or payload of this block
and we need to be able to get BeaconState from this cache given a state root, to run the state-transition later

@nflaig nflaig Mar 19, 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.

right, that makes sense, we could still only cache block state and apply the payload but there are definitely trade-offs of each approach

in the happy case we need the state with the payload applied so it makes sense to cache it

Comment thread packages/beacon-node/src/chain/chain.ts
twoeths
twoeths previously approved these changes Mar 19, 2026
envelopeEntries.push({key: blocks[i].slot, value: bytes});
migratedRoots.push(blocks[i].root);
} else {
logger.debug("Payload in forkchoice but missing in db", {slot: blocks[i].slot, root: toRootHex(blocks[i].root)});

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.

If we have a FULL node in fork choice but we don't have payload in db.executionPayloadEnvelope, it sounds like an error not debug to me?

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 have a convention to make it debug to improve UX, users don't care this much

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.

agree, this doesn't need to be logged at error, there isn't much a user can do in this case, it's also an invariant that should not happen

@twoeths
twoeths merged commit 274a991 into unstable Mar 19, 2026
19 checks passed
@twoeths
twoeths deleted the nc/epbs-state-cache branch March 19, 2026 06:17
@codecov

codecov Bot commented Mar 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.27%. Comparing base (9939b12) to head (3deb79d).
⚠️ Report is 1 commits behind head on unstable.

Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #8868      +/-   ##
============================================
- Coverage     52.32%   52.27%   -0.05%     
============================================
  Files           848      848              
  Lines         62326    62175     -151     
  Branches       4572     4545      -27     
============================================
- Hits          32612    32505     -107     
+ Misses        29649    29605      -44     
  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 🎉

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