github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/store_last_ev.go (about)

     1  package gossip
     2  
     3  import (
     4  	"bytes"
     5  	"sort"
     6  
     7  	"github.com/unicornultrafoundation/go-helios/native/idx"
     8  
     9  	"github.com/unicornultrafoundation/go-u2u/utils/concurrent"
    10  )
    11  
    12  type sortedLastEV []byte
    13  
    14  func (s *Store) getCachedLastEV() (*concurrent.ValidatorEpochsSet, bool) {
    15  	cache := s.cache.LastEV.Load()
    16  	if cache != nil {
    17  		return cache.(*concurrent.ValidatorEpochsSet), true
    18  	}
    19  	return nil, false
    20  }
    21  
    22  func (s *Store) loadLastEV() *concurrent.ValidatorEpochsSet {
    23  	res := make(map[idx.ValidatorID]idx.Epoch, 100)
    24  
    25  	b, err := s.table.LlrLastEpochVote.Get([]byte{})
    26  	if err != nil {
    27  		s.Log.Crit("Failed to get key-value", "err", err)
    28  	}
    29  	if b == nil {
    30  		return concurrent.WrapValidatorEpochsSet(res)
    31  	}
    32  	for i := 0; i < len(b); i += 4 + 4 {
    33  		res[idx.BytesToValidatorID(b[i:i+4])] = idx.BytesToEpoch(b[i+4 : i+4+4])
    34  	}
    35  
    36  	return concurrent.WrapValidatorEpochsSet(res)
    37  }
    38  
    39  func (s *Store) GetLastEVs() *concurrent.ValidatorEpochsSet {
    40  	cached, ok := s.getCachedLastEV()
    41  	if ok {
    42  		return cached
    43  	}
    44  	heads := s.loadLastEV()
    45  	if heads == nil {
    46  		heads = &concurrent.ValidatorEpochsSet{}
    47  	}
    48  	s.cache.LastEV.Store(heads)
    49  	return heads
    50  }
    51  
    52  func (s *Store) SetLastEVs(ids *concurrent.ValidatorEpochsSet) {
    53  	s.cache.LastEV.Store(ids)
    54  }
    55  
    56  func (s *Store) FlushLastEV() {
    57  	lasts, ok := s.getCachedLastEV()
    58  	if !ok {
    59  		return
    60  	}
    61  
    62  	// sort values for determinism
    63  	sortedLastEV := make([]sortedLastEV, 0, len(lasts.Val))
    64  	for vid, val := range lasts.Val {
    65  		b := append(vid.Bytes(), val.Bytes()...)
    66  		sortedLastEV = append(sortedLastEV, b)
    67  	}
    68  	sort.Slice(sortedLastEV, func(i, j int) bool {
    69  		a, b := sortedLastEV[i], sortedLastEV[j]
    70  		return bytes.Compare(a, b) < 0
    71  	})
    72  
    73  	b := make([]byte, 0, len(sortedLastEV)*(4+4))
    74  	for _, head := range sortedLastEV {
    75  		b = append(b, head...)
    76  	}
    77  
    78  	if err := s.table.LlrLastEpochVote.Put([]byte{}, b); err != nil {
    79  		s.Log.Crit("Failed to put key-value", "err", err)
    80  	}
    81  }
    82  
    83  // GetLastEV returns latest connected LLR epoch vote from specified validator
    84  func (s *Store) GetLastEV(vid idx.ValidatorID) *idx.Epoch {
    85  	lasts := s.GetLastEVs()
    86  	lasts.RLock()
    87  	defer lasts.RUnlock()
    88  	last, ok := lasts.Val[vid]
    89  	if !ok {
    90  		return nil
    91  	}
    92  	return &last
    93  }