github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/cache/proposer_indices.go (about)

     1  // +build !libfuzzer
     2  
     3  package cache
     4  
     5  import (
     6  	"sync"
     7  
     8  	"github.com/prometheus/client_golang/prometheus"
     9  	"github.com/prometheus/client_golang/prometheus/promauto"
    10  	types "github.com/prysmaticlabs/eth2-types"
    11  	"k8s.io/client-go/tools/cache"
    12  )
    13  
    14  var (
    15  	// maxProposerIndicesCacheSize defines the max number of proposer indices on per block root basis can cache.
    16  	// Due to reorgs and long finality, it's good to keep the old cache around for quickly switch over.
    17  	maxProposerIndicesCacheSize = uint64(8)
    18  
    19  	// ProposerIndicesCacheMiss tracks the number of proposerIndices requests that aren't present in the cache.
    20  	ProposerIndicesCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
    21  		Name: "proposer_indices_cache_miss",
    22  		Help: "The number of proposer indices requests that aren't present in the cache.",
    23  	})
    24  	// ProposerIndicesCacheHit tracks the number of proposerIndices requests that are in the cache.
    25  	ProposerIndicesCacheHit = promauto.NewCounter(prometheus.CounterOpts{
    26  		Name: "proposer_indices_cache_hit",
    27  		Help: "The number of proposer indices requests that are present in the cache.",
    28  	})
    29  )
    30  
    31  // ProposerIndicesCache is a struct with 1 queue for looking up proposer indices by root.
    32  type ProposerIndicesCache struct {
    33  	ProposerIndicesCache *cache.FIFO
    34  	lock                 sync.RWMutex
    35  }
    36  
    37  // proposerIndicesKeyFn takes the block root as the key to retrieve proposer indices in a given epoch.
    38  func proposerIndicesKeyFn(obj interface{}) (string, error) {
    39  	info, ok := obj.(*ProposerIndices)
    40  	if !ok {
    41  		return "", ErrNotProposerIndices
    42  	}
    43  
    44  	return key(info.BlockRoot), nil
    45  }
    46  
    47  // NewProposerIndicesCache creates a new proposer indices cache for storing/accessing proposer index assignments of an epoch.
    48  func NewProposerIndicesCache() *ProposerIndicesCache {
    49  	return &ProposerIndicesCache{
    50  		ProposerIndicesCache: cache.NewFIFO(proposerIndicesKeyFn),
    51  	}
    52  }
    53  
    54  // AddProposerIndices adds ProposerIndices object to the cache.
    55  // This method also trims the least recently list if the cache size has ready the max cache size limit.
    56  func (c *ProposerIndicesCache) AddProposerIndices(p *ProposerIndices) error {
    57  	c.lock.Lock()
    58  	defer c.lock.Unlock()
    59  
    60  	if err := c.ProposerIndicesCache.AddIfNotPresent(p); err != nil {
    61  		return err
    62  	}
    63  	trim(c.ProposerIndicesCache, maxProposerIndicesCacheSize)
    64  	return nil
    65  }
    66  
    67  // HasProposerIndices returns the proposer indices of a block root seed.
    68  func (c *ProposerIndicesCache) HasProposerIndices(r [32]byte) (bool, error) {
    69  	c.lock.RLock()
    70  	defer c.lock.RUnlock()
    71  	_, exists, err := c.ProposerIndicesCache.GetByKey(key(r))
    72  	if err != nil {
    73  		return false, err
    74  	}
    75  	return exists, nil
    76  }
    77  
    78  // ProposerIndices returns the proposer indices of a block root seed.
    79  func (c *ProposerIndicesCache) ProposerIndices(r [32]byte) ([]types.ValidatorIndex, error) {
    80  	c.lock.RLock()
    81  	defer c.lock.RUnlock()
    82  	obj, exists, err := c.ProposerIndicesCache.GetByKey(key(r))
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  
    87  	if exists {
    88  		ProposerIndicesCacheHit.Inc()
    89  	} else {
    90  		ProposerIndicesCacheMiss.Inc()
    91  		return nil, nil
    92  	}
    93  
    94  	item, ok := obj.(*ProposerIndices)
    95  	if !ok {
    96  		return nil, ErrNotProposerIndices
    97  	}
    98  
    99  	return item.ProposerIndices, nil
   100  }