github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/store_last_bv.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 sortedLastBV []byte
    13  
    14  func (s *Store) getCachedLastBVs() (*concurrent.ValidatorBlocksSet, bool) {
    15  	cache := s.cache.LastBVs.Load()
    16  	if cache != nil {
    17  		return cache.(*concurrent.ValidatorBlocksSet), true
    18  	}
    19  	return nil, false
    20  }
    21  
    22  func (s *Store) loadLastBVs() *concurrent.ValidatorBlocksSet {
    23  	res := make(map[idx.ValidatorID]idx.Block, 100)
    24  
    25  	b, err := s.table.LlrLastBlockVotes.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.WrapValidatorBlocksSet(res)
    31  	}
    32  	for i := 0; i < len(b); i += 8 + 4 {
    33  		res[idx.BytesToValidatorID(b[i:i+4])] = idx.BytesToBlock(b[i+4 : i+4+8])
    34  	}
    35  
    36  	return concurrent.WrapValidatorBlocksSet(res)
    37  }
    38  
    39  func (s *Store) GetLastBVs() *concurrent.ValidatorBlocksSet {
    40  	cached, ok := s.getCachedLastBVs()
    41  	if ok {
    42  		return cached
    43  	}
    44  	heads := s.loadLastBVs()
    45  	if heads == nil {
    46  		heads = &concurrent.ValidatorBlocksSet{}
    47  	}
    48  	s.cache.LastBVs.Store(heads)
    49  	return heads
    50  }
    51  
    52  func (s *Store) SetLastBVs(ids *concurrent.ValidatorBlocksSet) {
    53  	s.cache.LastBVs.Store(ids)
    54  }
    55  
    56  func (s *Store) FlushLastBVs() {
    57  	lasts, ok := s.getCachedLastBVs()
    58  	if !ok {
    59  		return
    60  	}
    61  
    62  	// sort values for determinism
    63  	sortedLastBVs := make([]sortedLastBV, 0, len(lasts.Val))
    64  	for vid, val := range lasts.Val {
    65  		b := append(vid.Bytes(), val.Bytes()...)
    66  		sortedLastBVs = append(sortedLastBVs, b)
    67  	}
    68  	sort.Slice(sortedLastBVs, func(i, j int) bool {
    69  		a, b := sortedLastBVs[i], sortedLastBVs[j]
    70  		return bytes.Compare(a, b) < 0
    71  	})
    72  
    73  	b := make([]byte, 0, len(sortedLastBVs)*(8+4))
    74  	for _, head := range sortedLastBVs {
    75  		b = append(b, head...)
    76  	}
    77  
    78  	if err := s.table.LlrLastBlockVotes.Put([]byte{}, b); err != nil {
    79  		s.Log.Crit("Failed to put key-value", "err", err)
    80  	}
    81  }
    82  
    83  // GetLastBV returns latest connected LLR block votes from specified validator
    84  func (s *Store) GetLastBV(vid idx.ValidatorID) *idx.Block {
    85  	lasts := s.GetLastBVs()
    86  	lasts.RLock()
    87  	defer lasts.RUnlock()
    88  	last, ok := lasts.Val[vid]
    89  	if !ok {
    90  		return nil
    91  	}
    92  	return &last
    93  }