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 }