Skip to content

Add cached PTC window to the state#4979

Merged
jtraglia merged 15 commits intoethereum:masterfrom
potuz:ptc_lookbehind
Mar 25, 2026
Merged

Add cached PTC window to the state#4979
jtraglia merged 15 commits intoethereum:masterfrom
potuz:ptc_lookbehind

Conversation

@potuz
Copy link
Copy Markdown
Contributor

@potuz potuz commented Mar 6, 2026

h/t to @nflaig for finding the issue.

When processing the block at slot 32 we validate payload attestations with the PTC of slot 31. However, the result of get_ptc may be different at this slot than in the previous one as it uses the effective balance at different epochs.

This PR adds the most brutal way of caching everything for the current epoch in the beacon state, and keeping the previous epoch's PTC in the same slice. This way a beacon state always contains the full PTC for the current epoch and the previous one.

This is a lot of overkill and it's rather ugly to waste 256KB in the state for this purpose. We could do this by keeping only one PTC, that of the last slot of the previous epoch, in the state, but that's even uglier. Since clients are caching anyway the full committees for the epoch (or even two epochs in advance) then perhaps this feature is not that bad.,

@github-actions github-actions bot added the gloas label Mar 6, 2026
Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com>
potuz and others added 3 commits March 6, 2026 15:25
Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com>
@github-actions github-actions bot added the testing CI, actions, tests, testing infra label Mar 6, 2026
@github-actions github-actions bot added the heze label Mar 6, 2026
@jtraglia
Copy link
Copy Markdown
Member

I'm going to close this one in favor of:

@jtraglia jtraglia closed this Mar 13, 2026
lodekeeper added a commit to lodekeeper/consensus-specs that referenced this pull request Mar 18, 2026
Alternative to ethereum#4992 that addresses ethereum#4979's epoch-boundary PTC bug
with minimal state changes:

- Add single `previous_ptc` field to BeaconState (~4KB vs 8KB/ethereum#4992, 256KB/ethereum#4979)
- New `compute_ptc(state, slot)` extracted from `get_ptc` for on-demand computation
- New `process_ptc_update` at START of `process_epoch` (before balance updates)
- Modified `get_ptc` returns cached `previous_ptc` for epoch boundary case
- No per-slot rotation in `process_slots` (unlike ethereum#4992)
- Preserves `get_ptc_assignment` validator duties API (unlike ethereum#4992)
- Tightened `get_ptc_assignment` assert to `current_epoch <= epoch <= next_epoch`

Key insight: only the PTC for the last slot of the previous epoch needs
caching because `process_payload_attestation` enforces
`data.slot + 1 == state.slot` and effective balances only change at
epoch boundaries.

Co-authored-by: Nico Flaig <nflaig@users.noreply.github.com>
lodekeeper added a commit to lodekeeper/consensus-specs that referenced this pull request Mar 18, 2026
Alternative to ethereum#4992 that addresses ethereum#4979's epoch-boundary PTC bug
with minimal state changes:

- Add single `previous_ptc` field to BeaconState (~4KB vs 8KB/ethereum#4992, 256KB/ethereum#4979)
- New `compute_ptc(state, slot)` extracted from `get_ptc` for on-demand computation
- New `process_ptc_update` at START of `process_epoch` (before balance updates)
- Modified `get_ptc` returns cached `previous_ptc` for epoch boundary case
- No per-slot rotation in `process_slots` (unlike ethereum#4992)
- Preserves `get_ptc_assignment` validator duties API (unlike ethereum#4992)
- Tightened `get_ptc_assignment` assert to `current_epoch <= epoch <= next_epoch`

Key insight: only the PTC for the last slot of the previous epoch needs
caching because `process_payload_attestation` enforces
`data.slot + 1 == state.slot` and effective balances only change at
epoch boundaries.

Co-authored-by: Nico Flaig <nflaig@users.noreply.github.com>
@jihoonsong
Copy link
Copy Markdown
Member

The PTC lookbehind discussion is still ongoing. Reopening this PR to help facilitate discussion.

# [New in Gloas:EIP7732]
payload_expected_withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
# [New in Gloas:EIP7732]
ptc_lookbehind: Vector[Vector[ValidatorIndex, PTC_SIZE], (2 + MIN_SEED_LOOKAHEAD)* SLOTS_PER_EPOCH]
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.

ptc_lookbehind is not entirely accurate right? there's look ahead too.
how about rename it to ptc_window

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.

I agree that it should be renamed. ptc_window or ptc_cache seem fine 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.

what about ptc_assignments?

@jtraglia jtraglia changed the title Add a PTC Lookbehind slice in the state Add cached PTC window with prev/curr/next epochs to the state Mar 23, 2026
@jtraglia jtraglia changed the title Add cached PTC window with prev/curr/next epochs to the state Add cached PTC window to the state Mar 23, 2026
@jtraglia jtraglia merged commit a196ff3 into ethereum:master Mar 25, 2026
16 checks passed
@jtraglia jtraglia mentioned this pull request Mar 26, 2026
jtraglia added a commit that referenced this pull request Mar 26, 2026
With #4979 merged, the
testing framework generates an input state for each test and calls
`initialize_ptc_window`. This is computing two epochs worth of PTCs
which is causing the mainnet tests to take considerably longer; ~5 hours
before the change and 12+ hours after the change. On my system, it takes
~30 seconds to compute PTCs for a single epoch. This PR's goal is to
speed this up. For details on each optimization, please refer to the
extended description for each commit.

*Note*: This PR is necessary to make the upcoming release. We triggered
the release action yesterday but it timed out (12 hours per fork/preset
combo) in the Gloas/Heze tests.
github-merge-queue bot pushed a commit to OffchainLabs/prysm that referenced this pull request Apr 1, 2026
This adds the PTC cache to the Gloas proto and native beacon state,
updates SSZ/hash-tree-root handling, initializes the cache on Gloas
upgrade, rotates it during epoch processing, and switches payload
committee lookups to read from the cached window instead of recomputing
PTC assignments on demand

Reference: ethereum/consensus-specs#4979
github-merge-queue bot pushed a commit to OffchainLabs/prysm that referenced this pull request Apr 2, 2026
This adds the PTC cache to the Gloas proto and native beacon state,
updates SSZ/hash-tree-root handling, initializes the cache on Gloas
upgrade, rotates it during epoch processing, and switches payload
committee lookups to read from the cached window instead of recomputing
PTC assignments on demand

Reference: ethereum/consensus-specs#4979
github-merge-queue bot pushed a commit to OffchainLabs/prysm that referenced this pull request Apr 2, 2026
This adds the PTC cache to the Gloas proto and native beacon state,
updates SSZ/hash-tree-root handling, initializes the cache on Gloas
upgrade, rotates it during epoch processing, and switches payload
committee lookups to read from the cached window instead of recomputing
PTC assignments on demand

Reference: ethereum/consensus-specs#4979
github-merge-queue bot pushed a commit to OffchainLabs/prysm that referenced this pull request Apr 2, 2026
This adds the PTC cache to the Gloas proto and native beacon state,
updates SSZ/hash-tree-root handling, initializes the cache on Gloas
upgrade, rotates it during epoch processing, and switches payload
committee lookups to read from the cached window instead of recomputing
PTC assignments on demand

Reference: ethereum/consensus-specs#4979
github-merge-queue bot pushed a commit to OffchainLabs/prysm that referenced this pull request Apr 2, 2026
This adds the PTC cache to the Gloas proto and native beacon state,
updates SSZ/hash-tree-root handling, initializes the cache on Gloas
upgrade, rotates it during epoch processing, and switches payload
committee lookups to read from the cached window instead of recomputing
PTC assignments on demand

Reference: ethereum/consensus-specs#4979
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gloas heze testing CI, actions, tests, testing infra

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants