github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/cache/checkpoint_state.go (about) 1 package cache 2 3 import ( 4 "sync" 5 6 lru "github.com/hashicorp/golang-lru" 7 "github.com/prometheus/client_golang/prometheus" 8 "github.com/prometheus/client_golang/prometheus/promauto" 9 iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface" 10 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 11 "github.com/prysmaticlabs/prysm/shared/hashutil" 12 ) 13 14 var ( 15 // maxCheckpointStateSize defines the max number of entries check point to state cache can contain. 16 // Choosing 10 to account for multiple forks, this allows 5 forks per epoch boundary with 2 epochs 17 // window to accept attestation based on latest spec. 18 maxCheckpointStateSize = 10 19 20 // Metrics. 21 checkpointStateMiss = promauto.NewCounter(prometheus.CounterOpts{ 22 Name: "check_point_state_cache_miss", 23 Help: "The number of check point state requests that aren't present in the cache.", 24 }) 25 checkpointStateHit = promauto.NewCounter(prometheus.CounterOpts{ 26 Name: "check_point_state_cache_hit", 27 Help: "The number of check point state requests that are present in the cache.", 28 }) 29 ) 30 31 // CheckpointStateCache is a struct with 1 queue for looking up state by checkpoint. 32 type CheckpointStateCache struct { 33 cache *lru.Cache 34 lock sync.RWMutex 35 } 36 37 // NewCheckpointStateCache creates a new checkpoint state cache for storing/accessing processed state. 38 func NewCheckpointStateCache() *CheckpointStateCache { 39 cache, err := lru.New(maxCheckpointStateSize) 40 if err != nil { 41 panic(err) 42 } 43 return &CheckpointStateCache{ 44 cache: cache, 45 } 46 } 47 48 // StateByCheckpoint fetches state by checkpoint. Returns true with a 49 // reference to the CheckpointState info, if exists. Otherwise returns false, nil. 50 func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (iface.BeaconState, error) { 51 c.lock.RLock() 52 defer c.lock.RUnlock() 53 h, err := hashutil.HashProto(cp) 54 if err != nil { 55 return nil, err 56 } 57 58 item, exists := c.cache.Get(h) 59 60 if exists && item != nil { 61 checkpointStateHit.Inc() 62 // Copy here is unnecessary since the return will only be used to verify attestation signature. 63 return item.(iface.BeaconState), nil 64 } 65 66 checkpointStateMiss.Inc() 67 return nil, nil 68 } 69 70 // AddCheckpointState adds CheckpointState object to the cache. This method also trims the least 71 // recently added CheckpointState object if the cache size has ready the max cache size limit. 72 func (c *CheckpointStateCache) AddCheckpointState(cp *ethpb.Checkpoint, s iface.ReadOnlyBeaconState) error { 73 c.lock.Lock() 74 defer c.lock.Unlock() 75 h, err := hashutil.HashProto(cp) 76 if err != nil { 77 return err 78 } 79 c.cache.Add(h, s) 80 return nil 81 }