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  }