diff --git a/beacon-chain/core/state/BUILD.bazel b/beacon-chain/core/state/BUILD.bazel index 50c69c903..96d4bbbae 100644 --- a/beacon-chain/core/state/BUILD.bazel +++ b/beacon-chain/core/state/BUILD.bazel @@ -23,7 +23,9 @@ go_library( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/state/interop:go_default_library", "//proto/beacon/p2p/v1:go_default_library", + "//shared/bytesutil:go_default_library", "//shared/featureconfig:go_default_library", + "//shared/hashutil:go_default_library", "//shared/mathutil:go_default_library", "//shared/params:go_default_library", "//shared/stateutil:go_default_library", diff --git a/beacon-chain/core/state/skip_slot_cache.go b/beacon-chain/core/state/skip_slot_cache.go index 4382d7275..69d9fe6e9 100644 --- a/beacon-chain/core/state/skip_slot_cache.go +++ b/beacon-chain/core/state/skip_slot_cache.go @@ -4,6 +4,10 @@ import ( lru "github.com/hashicorp/golang-lru" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" + "github.com/prysmaticlabs/go-ssz" + pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" + "github.com/prysmaticlabs/prysm/shared/bytesutil" + "github.com/prysmaticlabs/prysm/shared/hashutil" ) // skipSlotCache exists for the unlikely scenario that is a large gap between the head state and @@ -22,3 +26,14 @@ var ( Help: "The total number of cache misses on the skip slot cache.", }) ) + +func cacheKey(bState *pb.BeaconState) ([32]byte, error) { + // the latest header has a zeroed 32 byte hash as the state root, + // which isnt necessary for the purposes of making the cache key. As + // the parent root and body root are sufficient to prevent any collisions. + blockRoot, err := ssz.HashTreeRoot(bState.LatestBlockHeader) + if err != nil { + return [32]byte{}, err + } + return hashutil.FastSum256(append(bytesutil.Bytes8(bState.Slot), blockRoot[:]...)), nil +} diff --git a/beacon-chain/core/state/transition.go b/beacon-chain/core/state/transition.go index 1b97c7f00..bb375535a 100644 --- a/beacon-chain/core/state/transition.go +++ b/beacon-chain/core/state/transition.go @@ -268,24 +268,17 @@ func ProcessSlots(ctx context.Context, state *pb.BeaconState, slot uint64) (*pb. } highestSlot := state.Slot - var root [32]byte + var key [32]byte var writeToCache bool var err error if featureconfig.Get().EnableSkipSlotsCache { // Restart from cached value, if one exists. - if featureconfig.Get().EnableCustomStateSSZ { - root, err = stateutil.HashTreeRootState(state) - if err != nil { - return nil, errors.Wrap(err, "could not HashTreeRoot(state)") - } - } else { - root, err = ssz.HashTreeRoot(state) - if err != nil { - return nil, errors.Wrap(err, "could not HashTreeRoot(state)") - } + key, err = cacheKey(state) + if err != nil { + return nil, errors.Wrap(err, "could not create cache key") } - cached, ok := skipSlotCache.Get(root) + cached, ok := skipSlotCache.Get(key) // if cache key does not exist, we write it to the cache. writeToCache = !ok if ok { @@ -307,7 +300,7 @@ func ProcessSlots(ctx context.Context, state *pb.BeaconState, slot uint64) (*pb. if featureconfig.Get().EnableSkipSlotsCache { // Cache last best value. if highestSlot < state.Slot && writeToCache { - skipSlotCache.Add(root, proto.Clone(state).(*pb.BeaconState)) + skipSlotCache.Add(key, proto.Clone(state).(*pb.BeaconState)) } } return nil, ctx.Err() @@ -330,7 +323,7 @@ func ProcessSlots(ctx context.Context, state *pb.BeaconState, slot uint64) (*pb. if featureconfig.Get().EnableSkipSlotsCache { // Clone result state so that caches are not mutated. if highestSlot < state.Slot && writeToCache { - skipSlotCache.Add(root, proto.Clone(state).(*pb.BeaconState)) + skipSlotCache.Add(key, proto.Clone(state).(*pb.BeaconState)) } }