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 }