github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/store_llr_block.go (about) 1 package gossip 2 3 import ( 4 "github.com/unicornultrafoundation/go-helios/common/bigendian" 5 "github.com/unicornultrafoundation/go-helios/hash" 6 "github.com/unicornultrafoundation/go-helios/native/idx" 7 "github.com/unicornultrafoundation/go-helios/native/pos" 8 "github.com/unicornultrafoundation/go-helios/u2udb" 9 "github.com/unicornultrafoundation/go-helios/utils/simplewlru" 10 "github.com/unicornultrafoundation/go-u2u/core/types" 11 "github.com/unicornultrafoundation/go-u2u/rlp" 12 13 "github.com/unicornultrafoundation/go-u2u/native" 14 "github.com/unicornultrafoundation/go-u2u/native/ibr" 15 "github.com/unicornultrafoundation/go-u2u/native/ier" 16 "github.com/unicornultrafoundation/go-u2u/utils/bitmap" 17 ) 18 19 func (s *Store) SetBlockVotes(bvs native.LlrSignedBlockVotes) { 20 s.rlp.Set(s.table.LlrBlockVotes, append(bvs.Val.Epoch.Bytes(), append(bvs.Val.LastBlock().Bytes(), bvs.Signed.Locator.ID().Bytes()...)...), &bvs) 21 } 22 23 func (s *Store) HasBlockVotes(epoch idx.Epoch, lastBlock idx.Block, id hash.Event) bool { 24 ok, _ := s.table.LlrBlockVotes.Has(append(epoch.Bytes(), append(lastBlock.Bytes(), id.Bytes()...)...)) 25 return ok 26 } 27 28 func (s *Store) IterateOverlappingBlockVotesRLP(start []byte, f func(key []byte, bvs rlp.RawValue) bool) { 29 it := s.table.LlrBlockVotes.NewIterator(nil, start) 30 defer it.Release() 31 for it.Next() { 32 if !f(it.Key(), it.Value()) { 33 break 34 } 35 } 36 } 37 38 func (s *Store) getLlrVoteWeight(cache *VotesCache, reader u2udb.Reader, cKey VotesCacheID, key []byte) (pos.Weight, bitmap.Set) { 39 if cached := cache.Get(cKey); cached != nil { 40 return cached.weight, cached.set 41 } 42 weightB, err := reader.Get(key) 43 if err != nil { 44 s.Log.Crit("Failed to get key-value", "err", err) 45 } 46 if weightB == nil { 47 return 0, nil 48 } 49 weight, set := pos.Weight(bigendian.BytesToUint32(weightB[:4])), weightB[4:] 50 cache.Add(cKey, VotesCacheValue{ 51 weight: weight, 52 set: set, 53 mutated: false, 54 }) 55 return weight, set 56 } 57 58 func (s *Store) flushLlrVoteWeight(table u2udb.Writer, key []byte, weight pos.Weight, set bitmap.Set) { 59 err := table.Put(key, append(bigendian.Uint32ToBytes(uint32(weight)), set...)) 60 if err != nil { 61 s.Log.Crit("Failed to put key-value", "err", err) 62 } 63 } 64 65 func (s *Store) flushLlrBlockVoteWeight(cKey VotesCacheID, value VotesCacheValue) { 66 key := append(cKey.Block.Bytes(), append(cKey.Epoch.Bytes(), cKey.V[:]...)...) 67 s.flushLlrVoteWeight(s.table.LlrBlockVotesIndex, key, value.weight, value.set) 68 } 69 70 func (s *Store) addLlrVoteWeight(cache *VotesCache, reader u2udb.Reader, cKey VotesCacheID, key []byte, validator idx.Validator, validatorsNum idx.Validator, diff pos.Weight) pos.Weight { 71 weight, set := s.getLlrVoteWeight(cache, reader, cKey, key) 72 if set != nil && set.Has(int(validator)) { 73 // don't count the vote if validator already voted 74 return weight 75 } 76 if set == nil { 77 set = bitmap.New(int(validatorsNum)) 78 } 79 set.Put(int(validator)) 80 weight += diff 81 // save to cache which will be later flushed to the DB 82 cache.Add(cKey, VotesCacheValue{ 83 weight: weight, 84 set: set, 85 mutated: true, 86 }) 87 return weight 88 } 89 90 func (s *Store) AddLlrBlockVoteWeight(block idx.Block, epoch idx.Epoch, bv hash.Hash, val idx.Validator, vals idx.Validator, diff pos.Weight) pos.Weight { 91 key := append(block.Bytes(), append(epoch.Bytes(), bv[:]...)...) 92 cKey := VotesCacheID{ 93 Block: block, 94 Epoch: epoch, 95 V: bv, 96 } 97 return s.addLlrVoteWeight(s.cache.LlrBlockVotesIndex, s.table.LlrBlockVotesIndex, cKey, key, val, vals, diff) 98 } 99 100 func (s *Store) SetLlrBlockResult(block idx.Block, bv hash.Hash) { 101 err := s.table.LlrBlockResults.Put(block.Bytes(), bv.Bytes()) 102 if err != nil { 103 s.Log.Crit("Failed to put key-value", "err", err) 104 } 105 } 106 107 func (s *Store) GetLlrBlockResult(block idx.Block) *hash.Hash { 108 bvB, err := s.table.LlrBlockResults.Get(block.Bytes()) 109 if err != nil { 110 s.Log.Crit("Failed to get key-value", "err", err) 111 } 112 if bvB == nil { 113 return nil 114 } 115 bv := hash.BytesToHash(bvB) 116 return &bv 117 } 118 119 func (s *Store) GetFullBlockRecord(n idx.Block) *ibr.LlrFullBlockRecord { 120 block := s.GetBlock(n) 121 if block == nil { 122 return nil 123 } 124 txs := s.GetBlockTxs(n, block) 125 receipts, _ := s.EvmStore().GetRawReceipts(n) 126 if receipts == nil { 127 receipts = []*types.ReceiptForStorage{} 128 } 129 return &ibr.LlrFullBlockRecord{ 130 Atropos: block.Atropos, 131 Root: block.Root, 132 Txs: txs, 133 Receipts: receipts, 134 Time: block.Time, 135 GasUsed: block.GasUsed, 136 } 137 } 138 139 func (s *Store) GetBlockRecordHash(n idx.Block) *hash.Hash { 140 // Get data from LRU cache first. 141 if s.cache.BlockRecordHashes != nil { 142 if c, ok := s.cache.BlockRecordHashes.Get(n); ok { 143 h := c.(hash.Hash) 144 return &h 145 } 146 } 147 blockRecord := s.GetFullBlockRecord(n) 148 if blockRecord == nil { 149 return nil 150 } 151 blockRecordHash := blockRecord.Hash() 152 // Add to LRU cache. 153 s.cache.BlockRecordHashes.Add(n, blockRecordHash, nominalSize) 154 return &blockRecordHash 155 } 156 157 func (s *Store) GetFullEpochRecord(epoch idx.Epoch) *ier.LlrFullEpochRecord { 158 hbs, hes := s.GetHistoryBlockEpochState(epoch) 159 if hbs == nil || hes == nil { 160 return nil 161 } 162 return &ier.LlrFullEpochRecord{ 163 BlockState: *hbs, 164 EpochState: *hes, 165 } 166 } 167 168 type LlrFullBlockRecordRLP struct { 169 Atropos hash.Event 170 Root hash.Hash 171 Txs types.Transactions 172 ReceiptsRLP rlp.RawValue 173 Time native.Timestamp 174 GasUsed uint64 175 } 176 177 type LlrIdxFullBlockRecordRLP struct { 178 LlrFullBlockRecordRLP 179 Idx idx.Block 180 } 181 182 var emptyReceiptsRLP, _ = rlp.EncodeToBytes([]*types.ReceiptForStorage{}) 183 184 func (s *Store) IterateFullBlockRecordsRLP(start idx.Block, f func(b idx.Block, br rlp.RawValue) bool) { 185 it := s.table.Blocks.NewIterator(nil, start.Bytes()) 186 defer it.Release() 187 for it.Next() { 188 block := &native.Block{} 189 err := rlp.DecodeBytes(it.Value(), block) 190 if err != nil { 191 s.Log.Crit("Failed to decode block", "err", err) 192 } 193 n := idx.BytesToBlock(it.Key()) 194 txs := s.GetBlockTxs(n, block) 195 receiptsRLP := s.EvmStore().GetRawReceiptsRLP(n) 196 if receiptsRLP == nil { 197 receiptsRLP = emptyReceiptsRLP 198 } 199 br := LlrIdxFullBlockRecordRLP{ 200 LlrFullBlockRecordRLP: LlrFullBlockRecordRLP{ 201 Atropos: block.Atropos, 202 Root: block.Root, 203 Txs: txs, 204 ReceiptsRLP: receiptsRLP, 205 Time: block.Time, 206 GasUsed: block.GasUsed, 207 }, 208 Idx: n, 209 } 210 encoded, err := rlp.EncodeToBytes(br) 211 if err != nil { 212 s.Log.Crit("Failed to encode BR", "err", err) 213 } 214 215 if !f(n, encoded) { 216 break 217 } 218 } 219 } 220 221 type VotesCacheID struct { 222 Block idx.Block 223 Epoch idx.Epoch 224 V hash.Hash 225 } 226 227 type VotesCacheValue struct { 228 weight pos.Weight 229 set bitmap.Set 230 mutated bool 231 } 232 233 type VotesCache struct { 234 votes *simplewlru.Cache 235 } 236 237 func NewVotesCache(maxSize int, evictedFn func(VotesCacheID, VotesCacheValue)) *VotesCache { 238 votes, _ := simplewlru.NewWithEvict(uint(maxSize), maxSize, func(key interface{}, _value interface{}) { 239 value := _value.(*VotesCacheValue) 240 if value.mutated { 241 evictedFn(key.(VotesCacheID), *value) 242 } 243 }) 244 return &VotesCache{ 245 votes: votes, 246 } 247 } 248 249 func (c *VotesCache) FlushMutated(write func(VotesCacheID, VotesCacheValue)) { 250 keys := c.votes.Keys() 251 for _, k := range keys { 252 val_, _ := c.votes.Peek(k) 253 val := val_.(*VotesCacheValue) 254 if val.mutated { 255 write(k.(VotesCacheID), *val) 256 val.mutated = false 257 } 258 } 259 } 260 261 func (c *VotesCache) Get(key VotesCacheID) *VotesCacheValue { 262 if v, ok := c.votes.Get(key); ok { 263 return v.(*VotesCacheValue) 264 } 265 return nil 266 } 267 268 func (c *VotesCache) Add(key VotesCacheID, val VotesCacheValue) { 269 c.votes.Add(key, &val, nominalSize) 270 }