diff --git a/beacon-chain/cache/BUILD.bazel b/beacon-chain/cache/BUILD.bazel index 52256c419379..8a0b9d7a99f0 100644 --- a/beacon-chain/cache/BUILD.bazel +++ b/beacon-chain/cache/BUILD.bazel @@ -6,6 +6,7 @@ go_library( "active_balance.go", "active_balance_disabled.go", # keep "attestation_data.go", + "balance_cache_key.go", "checkpoint_state.go", "committee.go", "committee_disabled.go", # keep @@ -70,6 +71,7 @@ go_test( "committee_fuzz_test.go", "committee_test.go", "payload_id_test.go", + "private_access_test.go", "proposer_indices_test.go", "registration_test.go", "skip_slot_cache_test.go", @@ -93,6 +95,7 @@ go_test( "//testing/util:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_google_gofuzz//:go_default_library", + "@com_github_hashicorp_golang_lru//:go_default_library", "@com_github_stretchr_testify//require:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], diff --git a/beacon-chain/cache/active_balance.go b/beacon-chain/cache/active_balance.go index f79f5e896131..fb1bb50b9576 100644 --- a/beacon-chain/cache/active_balance.go +++ b/beacon-chain/cache/active_balance.go @@ -3,17 +3,13 @@ package cache import ( - "encoding/binary" "sync" lru "github.com/hashicorp/golang-lru" - "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" lruwrpr "github.com/prysmaticlabs/prysm/v5/cache/lru" - "github.com/prysmaticlabs/prysm/v5/config/params" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ) const ( @@ -86,36 +82,3 @@ func (c *BalanceCache) Get(st state.ReadOnlyBeaconState) (uint64, error) { balanceCacheHit.Inc() return value.(uint64), nil } - -// Given input state `st`, balance key is constructed as: -// (block_root in `st` at epoch_start_slot - 1) + current_epoch + validator_count -func balanceCacheKey(st state.ReadOnlyBeaconState) (string, error) { - slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch - currentEpoch := st.Slot().DivSlot(slotsPerEpoch) - epochStartSlot, err := slotsPerEpoch.SafeMul(uint64(currentEpoch)) - if err != nil { - // impossible condition due to early division - return "", errors.Errorf("start slot calculation overflows: %v", err) - } - prevSlot := primitives.Slot(0) - if epochStartSlot > 1 { - prevSlot = epochStartSlot - 1 - } - r, err := st.BlockRootAtIndex(uint64(prevSlot % params.BeaconConfig().SlotsPerHistoricalRoot)) - if err != nil { - // impossible condition because index is always constrained within state - return "", err - } - - // Mix in current epoch - b := make([]byte, 8) - binary.LittleEndian.PutUint64(b, uint64(currentEpoch)) - key := append(r, b...) - - // Mix in validator count - b = make([]byte, 8) - binary.LittleEndian.PutUint64(b, uint64(st.NumValidators())) - key = append(key, b...) - - return string(key), nil -} diff --git a/beacon-chain/cache/active_balance_test.go b/beacon-chain/cache/active_balance_test.go index b821a6d1550a..e70315ca1361 100644 --- a/beacon-chain/cache/active_balance_test.go +++ b/beacon-chain/cache/active_balance_test.go @@ -1,12 +1,13 @@ //go:build !fuzz -package cache +package cache_test import ( "encoding/binary" "math" "testing" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" @@ -27,33 +28,33 @@ func TestBalanceCache_AddGetBalance(t *testing.T) { st, err := state_native.InitializeFromProtoPhase0(raw) require.NoError(t, err) - cache := NewEffectiveBalanceCache() - _, err = cache.Get(st) - require.ErrorContains(t, ErrNotFound.Error(), err) + cc := cache.NewEffectiveBalanceCache() + _, err = cc.Get(st) + require.ErrorContains(t, cache.ErrNotFound.Error(), err) b := uint64(100) - require.NoError(t, cache.AddTotalEffectiveBalance(st, b)) - cachedB, err := cache.Get(st) + require.NoError(t, cc.AddTotalEffectiveBalance(st, b)) + cachedB, err := cc.Get(st) require.NoError(t, err) require.Equal(t, b, cachedB) require.NoError(t, st.SetSlot(1000)) - _, err = cache.Get(st) - require.ErrorContains(t, ErrNotFound.Error(), err) + _, err = cc.Get(st) + require.ErrorContains(t, cache.ErrNotFound.Error(), err) b = uint64(200) - require.NoError(t, cache.AddTotalEffectiveBalance(st, b)) - cachedB, err = cache.Get(st) + require.NoError(t, cc.AddTotalEffectiveBalance(st, b)) + cachedB, err = cc.Get(st) require.NoError(t, err) require.Equal(t, b, cachedB) require.NoError(t, st.SetSlot(1000+params.BeaconConfig().SlotsPerHistoricalRoot)) - _, err = cache.Get(st) - require.ErrorContains(t, ErrNotFound.Error(), err) + _, err = cc.Get(st) + require.ErrorContains(t, cache.ErrNotFound.Error(), err) b = uint64(300) - require.NoError(t, cache.AddTotalEffectiveBalance(st, b)) - cachedB, err = cache.Get(st) + require.NoError(t, cc.AddTotalEffectiveBalance(st, b)) + cachedB, err = cc.Get(st) require.NoError(t, err) require.Equal(t, b, cachedB) } @@ -72,6 +73,6 @@ func TestBalanceCache_BalanceKey(t *testing.T) { require.NoError(t, err) require.NoError(t, st.SetSlot(primitives.Slot(math.MaxUint64))) - _, err = balanceCacheKey(st) + _, err = cache.BalanceCacheKey(st) require.NoError(t, err) } diff --git a/beacon-chain/cache/balance_cache_key.go b/beacon-chain/cache/balance_cache_key.go new file mode 100644 index 000000000000..9c83d54a2a17 --- /dev/null +++ b/beacon-chain/cache/balance_cache_key.go @@ -0,0 +1,43 @@ +package cache + +import ( + "encoding/binary" + "fmt" + + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" +) + +// Given input state `st`, balance key is constructed as: +// (block_root in `st` at epoch_start_slot - 1) + current_epoch + validator_count +func balanceCacheKey(st state.ReadOnlyBeaconState) (string, error) { + slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch + currentEpoch := st.Slot().DivSlot(slotsPerEpoch) + epochStartSlot, err := slotsPerEpoch.SafeMul(uint64(currentEpoch)) + if err != nil { + // impossible condition due to early division + return "", fmt.Errorf("start slot calculation overflows: %w", err) + } + prevSlot := primitives.Slot(0) + if epochStartSlot > 1 { + prevSlot = epochStartSlot - 1 + } + r, err := st.BlockRootAtIndex(uint64(prevSlot % params.BeaconConfig().SlotsPerHistoricalRoot)) + if err != nil { + // impossible condition because index is always constrained within state + return "", err + } + + // Mix in current epoch + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, uint64(currentEpoch)) + key := append(r, b...) + + // Mix in validator count + b = make([]byte, 8) + binary.LittleEndian.PutUint64(b, uint64(st.NumValidators())) + key = append(key, b...) + + return string(key), nil +} diff --git a/beacon-chain/cache/checkpoint_state_test.go b/beacon-chain/cache/checkpoint_state_test.go index 13647b5f54f4..6426d7bc8997 100644 --- a/beacon-chain/cache/checkpoint_state_test.go +++ b/beacon-chain/cache/checkpoint_state_test.go @@ -1,8 +1,9 @@ -package cache +package cache_test import ( "testing" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/config/params" @@ -15,7 +16,7 @@ import ( ) func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) { - cache := NewCheckpointStateCache() + cache := cache.NewCheckpointStateCache() cp1 := ðpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'A'}, 32)} st, err := state_native.InitializeFromProtoPhase0(ðpb.BeaconState{ @@ -58,16 +59,16 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) { } func TestCheckpointStateCache_MaxSize(t *testing.T) { - c := NewCheckpointStateCache() + c := cache.NewCheckpointStateCache() st, err := state_native.InitializeFromProtoPhase0(ðpb.BeaconState{ Slot: 0, }) require.NoError(t, err) - for i := uint64(0); i < uint64(maxCheckpointStateSize+100); i++ { + for i := uint64(0); i < uint64(cache.MaxCheckpointStateSize()+100); i++ { require.NoError(t, st.SetSlot(primitives.Slot(i))) require.NoError(t, c.AddCheckpointState(ðpb.Checkpoint{Epoch: primitives.Epoch(i), Root: make([]byte, 32)}, st)) } - assert.Equal(t, maxCheckpointStateSize, len(c.cache.Keys())) + assert.Equal(t, cache.MaxCheckpointStateSize(), len(c.Cache().Keys())) } diff --git a/beacon-chain/cache/private_access_test.go b/beacon-chain/cache/private_access_test.go new file mode 100644 index 000000000000..673fe9a3c75b --- /dev/null +++ b/beacon-chain/cache/private_access_test.go @@ -0,0 +1,18 @@ +package cache + +import ( + lru "github.com/hashicorp/golang-lru" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" +) + +func BalanceCacheKey(st state.ReadOnlyBeaconState) (string, error) { + return balanceCacheKey(st) +} + +func MaxCheckpointStateSize() int { + return maxCheckpointStateSize +} + +func (c *CheckpointStateCache) Cache() *lru.Cache { + return c.cache +} diff --git a/beacon-chain/cache/sync_committee_head_state_test.go b/beacon-chain/cache/sync_committee_head_state_test.go index 073e174946c2..fcb2202ed55c 100644 --- a/beacon-chain/cache/sync_committee_head_state_test.go +++ b/beacon-chain/cache/sync_committee_head_state_test.go @@ -1,8 +1,9 @@ -package cache +package cache_test import ( "testing" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/config/params" @@ -125,7 +126,7 @@ func TestSyncCommitteeHeadState(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - c := NewSyncCommitteeHeadState() + c := cache.NewSyncCommitteeHeadState() if tt.put != nil { err := c.Put(tt.put.slot, tt.put.state) if (err != nil) != tt.wantPutErr {