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  }