github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/core/state/statedb_reward.go (about) 1 package state 2 3 import ( 4 "bytes" 5 "fmt" 6 "github.com/intfoundation/intchain/common" 7 "github.com/intfoundation/intchain/rlp" 8 "github.com/intfoundation/intchain/trie" 9 "io" 10 "math/big" 11 "sort" 12 ) 13 14 // ----- RewardBalance (Total) 15 16 // GetTotalRewardBalance Retrieve the reward balance from the given address or 0 if object not found 17 func (self *StateDB) GetTotalRewardBalance(addr common.Address) *big.Int { 18 stateObject := self.getStateObject(addr) 19 if stateObject != nil { 20 return stateObject.RewardBalance() 21 } 22 return common.Big0 23 } 24 25 func (self *StateDB) AddRewardBalance(addr common.Address, amount *big.Int) { 26 stateObject := self.GetOrNewStateObject(addr) 27 if stateObject != nil { 28 // Add amount to Total Reward Balance 29 stateObject.AddRewardBalance(amount) 30 } 31 } 32 33 func (self *StateDB) SubRewardBalance(addr common.Address, amount *big.Int) { 34 stateObject := self.GetOrNewStateObject(addr) 35 if stateObject != nil { 36 // Sub amount to Total Reward Balance 37 stateObject.SubRewardBalance(amount) 38 } 39 } 40 41 // ----- AvailableRewardBalance (Total) 42 43 // GetTotalAvailableRewardBalance retrieve the available reward balance from the given address or 0 if object not found 44 //func (self *StateDB) GetTotalAvailableRewardBalance(addr common.Address) *big.Int { 45 // stateObject := self.getStateObject(addr) 46 // if stateObject != nil { 47 // return stateObject.AvailableRewardBalance() 48 // } 49 // return common.Big0 50 //} 51 // 52 //func (self *StateDB) AddAvailableRewardBalance(addr common.Address, amount *big.Int) { 53 // stateObject := self.getStateObject(addr) 54 // if stateObject != nil { 55 // stateObject.AddAvailableRewardBalance(amount) 56 // } 57 //} 58 // 59 //func (self *StateDB) SubAvailableRewardBalance(addr common.Address, amount *big.Int) { 60 // stateObject := self.getStateObject(addr) 61 // if stateObject != nil { 62 // stateObject.SubAvailableRewardBalance(amount) 63 // } 64 //} 65 66 // ----- Reward Trie 67 68 func (self *StateDB) GetDelegateRewardAddress(addr common.Address) map[common.Address]struct{} { 69 var deleAddr map[common.Address]struct{} 70 reward := Reward{} 71 72 so := self.getStateObject(addr) 73 if so == nil { 74 return deleAddr 75 } 76 77 it := trie.NewIterator(so.getRewardTrie(self.db).NodeIterator(nil)) 78 for it.Next() { 79 var key common.Address 80 rlp.DecodeBytes(self.trie.GetKey(it.Key), &key) 81 deleAddr[key] = struct{}{} 82 } 83 84 if len(so.dirtyReward) > len(deleAddr) { 85 reward = so.dirtyReward 86 for key := range reward { 87 deleAddr[key] = struct{}{} 88 } 89 } 90 91 if len(so.originReward) > len(deleAddr) { 92 reward = so.originReward 93 for key := range reward { 94 deleAddr[key] = struct{}{} 95 } 96 } 97 98 return deleAddr 99 } 100 101 // GetRewardBalanceByDelegateAddress 102 func (self *StateDB) GetRewardBalanceByDelegateAddress(addr common.Address, deleAddress common.Address) *big.Int { 103 stateObject := self.getStateObject(addr) 104 if stateObject != nil { 105 rewardBalance := stateObject.GetDelegateRewardBalance(self.db, deleAddress) 106 if rewardBalance == nil { 107 return common.Big0 108 } else { 109 return rewardBalance 110 } 111 } 112 return common.Big0 113 } 114 115 // AddRewardBalanceByDelegateAddress adds reward amount to the account associated with delegate address 116 func (self *StateDB) AddRewardBalanceByDelegateAddress(addr common.Address, deleAddress common.Address, amount *big.Int) { 117 stateObject := self.GetOrNewStateObject(addr) 118 if stateObject != nil { 119 // Get EpochRewardBalance and update EpochRewardBalance 120 rewardBalance := stateObject.GetDelegateRewardBalance(self.db, deleAddress) 121 var dirtyRewardBalance *big.Int 122 if rewardBalance == nil { 123 dirtyRewardBalance = amount 124 } else { 125 dirtyRewardBalance = new(big.Int).Add(rewardBalance, amount) 126 } 127 stateObject.SetDelegateRewardBalance(self.db, deleAddress, dirtyRewardBalance) 128 129 // Add amount to Total Reward Balance 130 stateObject.AddRewardBalance(amount) 131 } 132 } 133 134 // AddRewardBalanceByDelegateAddress subtracts reward amount from the account associated with delegate address 135 func (self *StateDB) SubRewardBalanceByDelegateAddress(addr common.Address, deleAddress common.Address, amount *big.Int) { 136 stateObject := self.GetOrNewStateObject(addr) 137 if stateObject != nil { 138 // Get EpochRewardBalance and update EpochRewardBalance 139 rewardBalance := stateObject.GetDelegateRewardBalance(self.db, deleAddress) 140 var dirtyRewardBalance *big.Int 141 if rewardBalance == nil { 142 panic("you can't subtract the amount from nil balance, check the code, this should not happen") 143 } else { 144 dirtyRewardBalance = new(big.Int).Sub(rewardBalance, amount) 145 } 146 stateObject.SetDelegateRewardBalance(self.db, deleAddress, dirtyRewardBalance) 147 148 // Sub amount from Total Reward Balance 149 stateObject.SubRewardBalance(amount) 150 } 151 } 152 153 func (db *StateDB) ForEachReward(addr common.Address, cb func(key common.Address, rewardBalance *big.Int) bool) { 154 so := db.getStateObject(addr) 155 if so == nil { 156 return 157 } 158 it := trie.NewIterator(so.getRewardTrie(db.db).NodeIterator(nil)) 159 for it.Next() { 160 var key common.Address 161 rlp.DecodeBytes(db.trie.GetKey(it.Key), &key) 162 if value, dirty := so.dirtyReward[key]; dirty { 163 cb(key, value) 164 continue 165 } 166 var value big.Int 167 rlp.DecodeBytes(it.Value, &value) 168 cb(key, &value) 169 } 170 } 171 172 // ----- Reward Set 173 174 // MarkAddressReward adds the specified object to the dirty map to avoid 175 func (self *StateDB) MarkAddressReward(addr common.Address) { 176 if _, exist := self.GetRewardSet()[addr]; !exist { 177 self.rewardSet[addr] = struct{}{} 178 self.rewardSetDirty = true 179 } 180 } 181 182 func (self *StateDB) GetRewardSet() RewardSet { 183 if len(self.rewardSet) != 0 { 184 return self.rewardSet 185 } 186 // Try to get from Trie 187 enc, err := self.trie.TryGet(rewardSetKey) 188 if err != nil { 189 self.setError(err) 190 return nil 191 } 192 var value RewardSet 193 if len(enc) > 0 { 194 err := rlp.DecodeBytes(enc, &value) 195 if err != nil { 196 self.setError(err) 197 } 198 self.rewardSet = value 199 } 200 return value 201 } 202 203 func (self *StateDB) commitRewardSet() { 204 data, err := rlp.EncodeToBytes(self.rewardSet) 205 if err != nil { 206 panic(fmt.Errorf("can't encode reward set : %v", err)) 207 } 208 self.setError(self.trie.TryUpdate(rewardSetKey, data)) 209 } 210 211 func (self *StateDB) ClearRewardSetByAddress(addr common.Address) { 212 delete(self.rewardSet, addr) 213 self.rewardSetDirty = true 214 } 215 216 // Store the Reward Address Set 217 218 var rewardSetKey = []byte("RewardSet") 219 220 type RewardSet map[common.Address]struct{} 221 222 func (set RewardSet) EncodeRLP(w io.Writer) error { 223 var list []common.Address 224 for addr := range set { 225 list = append(list, addr) 226 } 227 sort.Slice(list, func(i, j int) bool { 228 return bytes.Compare(list[i].Bytes(), list[j].Bytes()) == 1 229 }) 230 return rlp.Encode(w, list) 231 } 232 233 func (set *RewardSet) DecodeRLP(s *rlp.Stream) error { 234 var list []common.Address 235 if err := s.Decode(&list); err != nil { 236 return err 237 } 238 rewardSet := make(RewardSet, len(list)) 239 for _, addr := range list { 240 rewardSet[addr] = struct{}{} 241 } 242 *set = rewardSet 243 return nil 244 } 245 246 // ----- Child Chain Reward Per Block 247 248 func (self *StateDB) SetChildChainRewardPerBlock(rewardPerBlock *big.Int) { 249 self.childChainRewardPerBlock = rewardPerBlock 250 self.childChainRewardPerBlockDirty = true 251 } 252 253 func (self *StateDB) GetChildChainRewardPerBlock() *big.Int { 254 if self.childChainRewardPerBlock != nil { 255 return self.childChainRewardPerBlock 256 } 257 // Try to get from Trie 258 enc, err := self.trie.TryGet(childChainRewardPerBlockKey) 259 if err != nil { 260 self.setError(err) 261 return nil 262 } 263 value := new(big.Int) 264 if len(enc) > 0 { 265 err := rlp.DecodeBytes(enc, value) 266 if err != nil { 267 self.setError(err) 268 } 269 self.childChainRewardPerBlock = value 270 } 271 return value 272 } 273 274 func (self *StateDB) commitChildChainRewardPerBlock() { 275 data, err := rlp.EncodeToBytes(self.childChainRewardPerBlock) 276 if err != nil { 277 panic(fmt.Errorf("can't encode child chain reward per block : %v", err)) 278 } 279 self.setError(self.trie.TryUpdate(childChainRewardPerBlockKey, data)) 280 } 281 282 // Child Chain Reward Per Block 283 284 var childChainRewardPerBlockKey = []byte("RewardPerBlock") 285 286 func (self *StateDB) MarkProposedInEpoch(address common.Address, epoch uint64) error { 287 288 return self.db.TrieDB().MarkProposedInEpoch(address, epoch) 289 } 290 291 func (self *StateDB) CheckProposedInEpoch(address common.Address, epoch uint64) bool { 292 293 return self.db.TrieDB().CheckProposedInEpoch(address, epoch) 294 }