diff --git a/cmd/erigon-cl/cache/attestation_indicies_cache.go b/cmd/erigon-cl/cache/attestation_indicies_cache.go new file mode 100644 index 00000000000..36b8b6d03ad --- /dev/null +++ b/cmd/erigon-cl/cache/attestation_indicies_cache.go @@ -0,0 +1,18 @@ +package cache + +import ( + "github.com/ledgerwatch/erigon/cl/cltypes" + "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/lru" +) + +var attestationIndiciesCache *lru.Cache[*cltypes.AttestationData, []uint64] + +const attestationIndiciesCacheSize = 256 + +func LoadAttestatingIndicies(attestation *cltypes.AttestationData) ([]uint64, bool) { + return attestationIndiciesCache.Get(attestation) +} + +func StoreAttestation(attestation *cltypes.AttestationData, indicies []uint64) { + attestationIndiciesCache.Add(attestation, indicies) +} diff --git a/cmd/erigon-cl/cache/init.go b/cmd/erigon-cl/cache/init.go new file mode 100644 index 00000000000..d0f51cd31b5 --- /dev/null +++ b/cmd/erigon-cl/cache/init.go @@ -0,0 +1,13 @@ +package cache + +import ( + "github.com/ledgerwatch/erigon/cl/cltypes" + "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/lru" +) + +func init() { + var err error + if attestationIndiciesCache, err = lru.New[*cltypes.AttestationData, []uint64]("attestationIndiciesCacheSize", attestationIndiciesCacheSize); err != nil { + panic(err) + } +} diff --git a/cmd/erigon-cl/core/state/cache.go b/cmd/erigon-cl/core/state/cache.go index 583b410206f..8fc21bbe42c 100644 --- a/cmd/erigon-cl/core/state/cache.go +++ b/cmd/erigon-cl/core/state/cache.go @@ -27,7 +27,6 @@ type BeaconState struct { publicKeyIndicies map[[48]byte]uint64 // Caches activeValidatorsCache *lru.Cache[uint64, []uint64] - committeeCache *lru.Cache[[16]byte, []uint64] shuffledSetsCache *lru.Cache[common.Hash, []uint64] totalActiveBalanceCache *uint64 totalActiveBalanceRootCache uint64 @@ -200,9 +199,6 @@ func (b *BeaconState) initCaches() error { if b.shuffledSetsCache, err = lru.New[common.Hash, []uint64]("beacon_shuffled_sets_cache", 5); err != nil { return err } - if b.committeeCache, err = lru.New[[16]byte, []uint64]("beacon_committee_cache", 256); err != nil { - return err - } return nil } diff --git a/cmd/erigon-cl/core/state/cache_accessors.go b/cmd/erigon-cl/core/state/cache_accessors.go index de4e3c2dc18..8f887113472 100644 --- a/cmd/erigon-cl/core/state/cache_accessors.go +++ b/cmd/erigon-cl/core/state/cache_accessors.go @@ -9,6 +9,7 @@ import ( "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/cltypes" "github.com/ledgerwatch/erigon/cl/utils" + "github.com/ledgerwatch/erigon/cmd/erigon-cl/cache" "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/shuffling" ) @@ -160,9 +161,6 @@ func (b *BeaconState) GetBeaconCommitee(slot, committeeIndex uint64) ([]uint64, binary.BigEndian.PutUint64(cacheKey[:], slot) binary.BigEndian.PutUint64(cacheKey[8:], committeeIndex) - if cachedCommittee, ok := b.committeeCache.Get(cacheKey); ok { - return cachedCommittee, nil - } epoch := GetEpochAtSlot(b.BeaconConfig(), slot) committeesPerSlot := b.CommitteeCount(epoch) committee, err := b.ComputeCommittee( @@ -174,7 +172,6 @@ func (b *BeaconState) GetBeaconCommitee(slot, committeeIndex uint64) ([]uint64, if err != nil { return nil, err } - b.committeeCache.Add(cacheKey, committee) return committee, nil } @@ -238,6 +235,9 @@ func (b *BeaconState) ComputeNextSyncCommittee() (*cltypes.SyncCommittee, error) // GetAttestingIndicies retrieves attesting indicies for a specific attestation. however some tests will not expect the aggregation bits check. // thus, it is a flag now. func (b *BeaconState) GetAttestingIndicies(attestation *cltypes.AttestationData, aggregationBits []byte, checkBitsLength bool) ([]uint64, error) { + if cached, ok := cache.LoadAttestatingIndicies(attestation); ok { + return cached, nil + } committee, err := b.GetBeaconCommitee(attestation.Slot, attestation.Index) if err != nil { return nil, err @@ -246,6 +246,7 @@ func (b *BeaconState) GetAttestingIndicies(attestation *cltypes.AttestationData, if checkBitsLength && utils.GetBitlistLength(aggregationBits) != len(committee) { return nil, fmt.Errorf("GetAttestingIndicies: invalid aggregation bits. agg bits size: %d, expect: %d", aggregationBitsLen, len(committee)) } + attestingIndices := []uint64{} for i, member := range committee { bitIndex := i % 8 @@ -257,6 +258,7 @@ func (b *BeaconState) GetAttestingIndicies(attestation *cltypes.AttestationData, attestingIndices = append(attestingIndices, member) } } + cache.StoreAttestation(attestation, attestingIndices) return attestingIndices, nil } diff --git a/cmd/erigon-cl/core/state/copy.go b/cmd/erigon-cl/core/state/copy.go index 0a7cf9d1c7d..d70ae2a0f91 100644 --- a/cmd/erigon-cl/core/state/copy.go +++ b/cmd/erigon-cl/core/state/copy.go @@ -36,7 +36,6 @@ func (b *BeaconState) copyCachesInto(bs *BeaconState) error { // Sync caches bs.activeValidatorsCache = copyLRU(bs.activeValidatorsCache, b.activeValidatorsCache) bs.shuffledSetsCache = copyLRU(bs.shuffledSetsCache, b.shuffledSetsCache) - bs.committeeCache = copyLRU(bs.committeeCache, b.committeeCache) if b.totalActiveBalanceCache != nil { bs.totalActiveBalanceCache = new(uint64) diff --git a/cmd/erigon-cl/core/transition/process_attestations.go b/cmd/erigon-cl/core/transition/process_attestations.go index 294c9802750..ed2d97f935a 100644 --- a/cmd/erigon-cl/core/transition/process_attestations.go +++ b/cmd/erigon-cl/core/transition/process_attestations.go @@ -56,10 +56,12 @@ func processAttestationPostAltair(s *state.BeaconState, attestation *cltypes.Att c.PutSince() c = h.Tag("step", "get_attesting_indices") + attestingIndicies, err := s.GetAttestingIndicies(attestation.Data, attestation.AggregationBits, true) if err != nil { return nil, err } + c.PutSince() var proposerRewardNumerator uint64 diff --git a/cmd/erigon-cl/forkchoice/on_attestation.go b/cmd/erigon-cl/forkchoice/on_attestation.go index ac4b438754c..128b96b5192 100644 --- a/cmd/erigon-cl/forkchoice/on_attestation.go +++ b/cmd/erigon-cl/forkchoice/on_attestation.go @@ -5,6 +5,7 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/cl/cltypes" + "github.com/ledgerwatch/erigon/cmd/erigon-cl/cache" "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state" ) @@ -16,7 +17,10 @@ func (f *ForkChoiceStore) OnAttestation(attestation *cltypes.Attestation, fromBl return err } target := attestation.Data.Target - + if cachedIndicies, ok := cache.LoadAttestatingIndicies(attestation.Data); ok { + f.processAttestingIndicies(attestation, cachedIndicies) + return nil + } targetState, err := f.getCheckpointState(*target) if err != nil { return nil @@ -26,13 +30,11 @@ func (f *ForkChoiceStore) OnAttestation(attestation *cltypes.Attestation, fromBl return fmt.Errorf("target state does not exist") } // Now we need to find the attesting indicies. - attestationIndicies, err := targetState.getAttestingIndicies(attestation.Data, attestation.AggregationBits) if err != nil { return err } if !fromBlock { - indexedAttestation := state.GetIndexedAttestation(attestation, attestationIndicies) if err != nil { return err @@ -47,8 +49,15 @@ func (f *ForkChoiceStore) OnAttestation(attestation *cltypes.Attestation, fromBl } } // Lastly update latest messages. + f.processAttestingIndicies(attestation, attestationIndicies) + return nil +} + +func (f *ForkChoiceStore) processAttestingIndicies(attestation *cltypes.Attestation, indicies []uint64) { beaconBlockRoot := attestation.Data.BeaconBlockHash - for _, index := range attestationIndicies { + target := attestation.Data.Target + + for _, index := range indicies { if _, ok := f.equivocatingIndicies[index]; ok { continue } @@ -60,7 +69,6 @@ func (f *ForkChoiceStore) OnAttestation(attestation *cltypes.Attestation, fromBl } } } - return nil } func (f *ForkChoiceStore) validateOnAttestation(attestation *cltypes.Attestation, fromBlock bool) error {