Add cached PTC window to the state#4979
Merged
jtraglia merged 15 commits intoethereum:masterfrom Mar 25, 2026
Merged
Conversation
jtraglia
reviewed
Mar 6, 2026
Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com>
jtraglia
reviewed
Mar 6, 2026
jtraglia
reviewed
Mar 6, 2026
Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com>
ensi321
reviewed
Mar 6, 2026
4 tasks
Member
|
I'm going to close this one in favor of: |
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>
Member
|
The PTC lookbehind discussion is still ongoing. Reopening this PR to help facilitate discussion. |
specs/gloas/beacon-chain.md
Outdated
| # [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] |
Contributor
There was a problem hiding this comment.
ptc_lookbehind is not entirely accurate right? there's look ahead too.
how about rename it to ptc_window
Member
There was a problem hiding this comment.
I agree that it should be renamed. ptc_window or ptc_cache seem fine to me.
nflaig
reviewed
Mar 24, 2026
nflaig
reviewed
Mar 24, 2026
nflaig
approved these changes
Mar 25, 2026
terencechain
approved these changes
Mar 25, 2026
jtraglia
approved these changes
Mar 25, 2026
Merged
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.
3 tasks
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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_ptcmay 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.,