Skip to content

core: implement cached PTC window in state#16573

Merged
prestonvanloon merged 11 commits intodevelopfrom
update-ptc
Apr 2, 2026
Merged

core: implement cached PTC window in state#16573
prestonvanloon merged 11 commits intodevelopfrom
update-ptc

Conversation

@terencechain
Copy link
Copy Markdown
Collaborator

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

@terencechain terencechain force-pushed the update-ptc branch 3 times, most recently from d10f188 to b73e843 Compare March 30, 2026 08:52
Comment on lines +43 to +47
// if is_builder or (
// is_builder_withdrawal_credential(deposit_request.withdrawal_credentials)
// and not is_validator
// and not is_pending_validator(state, deposit_request.pubkey)
// ):
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Because update spec test, i have to change this, this is implemented in #16532

Copy link
Copy Markdown
Contributor

@potuz potuz left a comment

Choose a reason for hiding this comment

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

I'm worried about the committee cache usage of the same seed to get epoch+2 and epoch+1 committees.


func ptcSlotFromValidatorIndices(indices []primitives.ValidatorIndex) *eth.PTCs {
result := &eth.PTCs{
ValidatorIndices: make([]uint64, len(indices)),
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.

Shouldn't these be always PTCSize?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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


newSlots := make([]*eth.PTCs, slotsPerEpoch)
for i := range slotsPerEpoch {
ptc, err := computePTC(ctx, st, startSlot+primitives.Slot(i))
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.

Something that worries me here is that we are now calling to get a committee 2 epochs ago from now, with the current state's seed (we add 2 in line 385 and then subtract 2 in Seed). This is guaranteed not to be in the cache, so BeaconCommitteeFromState will fail in the committeeCache. This will then call ActiveValidatorIndices that will also fail the cache and then recompute the cache with the current state's seed but for epoch e+2. The problem is if we use the seed for e+1 in a few places like Attester Duties but the cache in only keyed by seed. This means that either we will be getting a false seed on some cache hits, or we will be overriding them with some other committees depending on whether we call with e+1 or e+2.

roots := make([][32]byte, len(slice))

for i, slot := range slice {
r, err := slot.HashTreeRoot()
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.

Unlikely, but it is possible for a slot to be nil. Having a nil check may prevent a panic.

Suggested change
r, err := slot.HashTreeRoot()
if slot == nil {
return [32]byte{}, fmt.Errorf("invalid PTC at position %d", i)
}
r, err := slot.HashTreeRoot()

This suggestion probably needs gofmt

// Vector[ValidatorIndex, PTC_SIZE]
message PTCs {
repeated uint64 validator_indices = 1
[ (ethereum.eth.ext.ssz_size) = "ptc_committee_indices.size" ];
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.

Could you cast this to a ValidatorIndex? Then you could avoid casting/copying with methods like validatorIndicesFromUint64

Comment on lines +766 to +772
func validatorIndicesFromUint64(indices []uint64) []primitives.ValidatorIndex {
result := make([]primitives.ValidatorIndex, len(indices))
for i, index := range indices {
result[i] = primitives.ValidatorIndex(index)
}
return result
}
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.

Commented on this in the proto file, but shouldn't you just make the PTCs message have ValidatorIndices be type []primitive.ValidatorIndex?

prestonvanloon
prestonvanloon previously approved these changes Apr 1, 2026
@terencechain terencechain added this pull request to the merge queue Apr 1, 2026
@potuz potuz removed this pull request from the merge queue due to a manual request Apr 1, 2026
Copy link
Copy Markdown
Contributor

@potuz potuz left a comment

Choose a reason for hiding this comment

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

On every single call to process a payload attestation message, we inconditionally call PayloadCommittee that will copy 2KB and allocate them on the heap. This happens in validatorIndicesFromUint64. I think we want to return the original slice as a read only object.

This is funny in processing the block since we call in a loop indexedPayloadAttestation that will get a committee that should be guaranteed to be the same on each round, although in this case the number of copies will be smaller (just 4 instead of 512).

@terencechain terencechain enabled auto-merge April 2, 2026 14:30
@terencechain terencechain added this pull request to the merge queue Apr 2, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Apr 2, 2026
@prestonvanloon prestonvanloon added this pull request to the merge queue Apr 2, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Apr 2, 2026
@prestonvanloon prestonvanloon added this pull request to the merge queue Apr 2, 2026
Merged via the queue into develop with commit c02c057 Apr 2, 2026
19 checks passed
@prestonvanloon prestonvanloon deleted the update-ptc branch April 2, 2026 18:24
@github-project-automation github-project-automation bot moved this from Unassigned to Done in Gloas Apr 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants