github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/store_decided_state.go (about) 1 package gossip 2 3 import ( 4 "github.com/unicornultrafoundation/go-helios/native/idx" 5 "github.com/unicornultrafoundation/go-helios/native/pos" 6 "github.com/unicornultrafoundation/go-u2u/log" 7 ethparams "github.com/unicornultrafoundation/go-u2u/params" 8 "github.com/unicornultrafoundation/go-u2u/rlp" 9 10 "github.com/unicornultrafoundation/go-u2u/native/iblockproc" 11 "github.com/unicornultrafoundation/go-u2u/u2u" 12 ) 13 14 const sKey = "s" 15 16 type BlockEpochState struct { 17 BlockState *iblockproc.BlockState 18 EpochState *iblockproc.EpochState 19 } 20 21 // TODO propose to pass bs, es arguments by pointer 22 func (s *Store) SetHistoryBlockEpochState(epoch idx.Epoch, bs iblockproc.BlockState, es iblockproc.EpochState) { 23 bs, es = bs.Copy(), es.Copy() 24 bes := &BlockEpochState{ 25 BlockState: &bs, 26 EpochState: &es, 27 } 28 // Write to the DB 29 s.rlp.Set(s.table.BlockEpochStateHistory, epoch.Bytes(), bes) 30 // Save to the LRU cache 31 s.cache.BlockEpochStateHistory.Add(epoch, bes, nominalSize) 32 } 33 34 func (s *Store) GetHistoryBlockEpochState(epoch idx.Epoch) (*iblockproc.BlockState, *iblockproc.EpochState) { 35 // Get HistoryBlockEpochState from LRU cache first. 36 if v, ok := s.cache.BlockEpochStateHistory.Get(epoch); ok { 37 bes := v.(*BlockEpochState) 38 if bes.EpochState.Epoch == epoch { 39 bs := bes.BlockState.Copy() 40 es := bes.EpochState.Copy() 41 return &bs, &es 42 } 43 } 44 // read from DB 45 v, ok := s.rlp.Get(s.table.BlockEpochStateHistory, epoch.Bytes(), &BlockEpochState{}).(*BlockEpochState) 46 if !ok { 47 return nil, nil 48 } 49 // Save to the LRU cache 50 s.cache.BlockEpochStateHistory.Add(epoch, v, nominalSize) 51 bs := v.BlockState.Copy() 52 es := v.EpochState.Copy() 53 return &bs, &es 54 } 55 56 func (s *Store) ForEachHistoryBlockEpochState(fn func(iblockproc.BlockState, iblockproc.EpochState) bool) { 57 it := s.table.BlockEpochStateHistory.NewIterator(nil, nil) 58 defer it.Release() 59 for it.Next() { 60 bes := BlockEpochState{} 61 err := rlp.DecodeBytes(it.Value(), &bes) 62 if err != nil { 63 s.Log.Crit("Failed to decode BlockEpochState", "err", err) 64 } 65 if !fn(*bes.BlockState, *bes.EpochState) { 66 break 67 } 68 } 69 } 70 71 func (s *Store) GetHistoryEpochState(epoch idx.Epoch) *iblockproc.EpochState { 72 // check current BlockEpochState as a cache 73 if v := s.cache.BlockEpochState.Load(); v != nil { 74 bes := v.(*BlockEpochState) 75 if bes.EpochState.Epoch == epoch { 76 es := bes.EpochState.Copy() 77 return &es 78 } 79 } 80 _, es := s.GetHistoryBlockEpochState(epoch) 81 return es 82 } 83 84 func (s *Store) HasHistoryBlockEpochState(epoch idx.Epoch) bool { 85 has, _ := s.table.BlockEpochStateHistory.Has(epoch.Bytes()) 86 return has 87 } 88 89 func (s *Store) HasBlockEpochState() bool { 90 has, _ := s.table.BlockEpochState.Has([]byte(sKey)) 91 return has 92 } 93 94 // SetBlockEpochState stores the latest block and epoch state in memory 95 func (s *Store) SetBlockEpochState(bs iblockproc.BlockState, es iblockproc.EpochState) { 96 bs, es = bs.Copy(), es.Copy() 97 s.cache.BlockEpochState.Store(&BlockEpochState{&bs, &es}) 98 } 99 100 func (s *Store) getBlockEpochState() BlockEpochState { 101 if v := s.cache.BlockEpochState.Load(); v != nil { 102 return *v.(*BlockEpochState) 103 } 104 v, ok := s.rlp.Get(s.table.BlockEpochState, []byte(sKey), &BlockEpochState{}).(*BlockEpochState) 105 if !ok { 106 log.Crit("Epoch state reading failed: genesis not applied") 107 } 108 s.cache.BlockEpochState.Store(v) 109 return *v 110 } 111 112 // FlushBlockEpochState stores the latest epoch and block state in DB 113 func (s *Store) FlushBlockEpochState() { 114 s.rlp.Set(s.table.BlockEpochState, []byte(sKey), s.getBlockEpochState()) 115 } 116 117 // GetBlockState retrieves the latest block state 118 func (s *Store) GetBlockState() iblockproc.BlockState { 119 return *s.getBlockEpochState().BlockState 120 } 121 122 // GetEpochState retrieves the latest epoch state 123 func (s *Store) GetEpochState() iblockproc.EpochState { 124 return *s.getBlockEpochState().EpochState 125 } 126 127 func (s *Store) GetBlockEpochState() (iblockproc.BlockState, iblockproc.EpochState) { 128 bes := s.getBlockEpochState() 129 return *bes.BlockState, *bes.EpochState 130 } 131 132 // GetEpoch retrieves the current epoch 133 func (s *Store) GetEpoch() idx.Epoch { 134 return s.GetEpochState().Epoch 135 } 136 137 // GetValidators retrieves current validators 138 func (s *Store) GetValidators() *pos.Validators { 139 return s.GetEpochState().Validators 140 } 141 142 // GetEpochValidators retrieves the current epoch and validators atomically 143 func (s *Store) GetEpochValidators() (*pos.Validators, idx.Epoch) { 144 es := s.GetEpochState() 145 return es.Validators, es.Epoch 146 } 147 148 // GetLatestBlockIndex retrieves the current block number 149 func (s *Store) GetLatestBlockIndex() idx.Block { 150 return s.GetBlockState().LastBlock.Idx 151 } 152 153 // GetRules retrieves current network rules 154 func (s *Store) GetRules() u2u.Rules { 155 return s.GetEpochState().Rules 156 } 157 158 // GetEvmChainConfig retrieves current EVM chain config 159 func (s *Store) GetEvmChainConfig() *ethparams.ChainConfig { 160 return s.GetRules().EvmChainConfig(s.GetUpgradeHeights()) 161 } 162 163 // GetEpochRules retrieves current network rules and epoch atomically 164 func (s *Store) GetEpochRules() (u2u.Rules, idx.Epoch) { 165 es := s.GetEpochState() 166 return es.Rules, es.Epoch 167 }