github.com/Gessiux/neatchain@v1.3.1/chain/core/state/statedb_delegate.go (about) 1 package state 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "math/big" 8 "sort" 9 10 "github.com/Gessiux/neatchain/chain/trie" 11 "github.com/Gessiux/neatchain/utilities/common" 12 "github.com/Gessiux/neatchain/utilities/rlp" 13 ) 14 15 // ----- DelegateBalance 16 17 // GetDelegateBalance Retrieve the delegate balance from the given address or 0 if object not found 18 func (self *StateDB) GetDelegateBalance(addr common.Address) *big.Int { 19 stateObject := self.getStateObject(addr) 20 if stateObject != nil { 21 return stateObject.DelegateBalance() 22 } 23 return common.Big0 24 } 25 26 // AddDelegateBalance adds delegate amount to the account associated with addr 27 func (self *StateDB) AddDelegateBalance(addr common.Address, amount *big.Int) { 28 stateObject := self.GetOrNewStateObject(addr) 29 if stateObject != nil { 30 stateObject.AddDelegateBalance(amount) 31 } 32 } 33 34 // SubDelegateBalance subtracts delegate amount from the account associated with addr 35 func (self *StateDB) SubDelegateBalance(addr common.Address, amount *big.Int) { 36 stateObject := self.GetOrNewStateObject(addr) 37 if stateObject != nil { 38 stateObject.SubDelegateBalance(amount) 39 } 40 } 41 42 // ----- ProxiedBalance (Total) 43 44 // GetTotalProxiedBalance Retrieve the proxied balance from the given address or 0 if object not found 45 func (self *StateDB) GetTotalProxiedBalance(addr common.Address) *big.Int { 46 stateObject := self.getStateObject(addr) 47 if stateObject != nil { 48 return stateObject.ProxiedBalance() 49 } 50 return common.Big0 51 } 52 53 // ----- DepositProxiedBalance (Total) 54 55 // GetTotalDepositProxiedBalance Retrieve the deposit proxied balance from the given address or 0 if object not found 56 func (self *StateDB) GetTotalDepositProxiedBalance(addr common.Address) *big.Int { 57 stateObject := self.getStateObject(addr) 58 if stateObject != nil { 59 return stateObject.DepositProxiedBalance() 60 } 61 return common.Big0 62 } 63 64 // ----- PendingRefundBalance (Total) 65 66 // GetTotalPendingRefundBalance Retrieve the pending refund balance from the given address or 0 if object not found 67 func (self *StateDB) GetTotalPendingRefundBalance(addr common.Address) *big.Int { 68 stateObject := self.getStateObject(addr) 69 if stateObject != nil { 70 return stateObject.PendingRefundBalance() 71 } 72 return common.Big0 73 } 74 75 // ----- Proxied Trie 76 77 // GetProxiedBalanceByUser 78 func (self *StateDB) GetProxiedBalanceByUser(addr, user common.Address) *big.Int { 79 stateObject := self.getStateObject(addr) 80 if stateObject != nil { 81 apb := stateObject.GetAccountProxiedBalance(self.db, user) 82 if apb == nil { 83 return common.Big0 84 } else { 85 return apb.ProxiedBalance 86 } 87 } 88 return common.Big0 89 } 90 91 // AddProxiedBalanceByUser adds proxied amount to the account associated with addr 92 func (self *StateDB) AddProxiedBalanceByUser(addr, user common.Address, amount *big.Int) { 93 stateObject := self.GetOrNewStateObject(addr) 94 if stateObject != nil { 95 // Get AccountProxiedBalance and update ProxiedBalance 96 apb := stateObject.GetAccountProxiedBalance(self.db, user) 97 var dirtyApb *accountProxiedBalance 98 if apb == nil { 99 dirtyApb = NewAccountProxiedBalance() 100 } else { 101 dirtyApb = apb.Copy() 102 } 103 dirtyApb.ProxiedBalance = new(big.Int).Add(dirtyApb.ProxiedBalance, amount) 104 stateObject.SetAccountProxiedBalance(self.db, user, dirtyApb) 105 106 // Add amount to Total Proxied Balance 107 stateObject.AddProxiedBalance(amount) 108 } 109 } 110 111 // SubProxiedBalanceByUser subtracts proxied amount from the account associated with addr 112 func (self *StateDB) SubProxiedBalanceByUser(addr, user common.Address, amount *big.Int) { 113 stateObject := self.GetOrNewStateObject(addr) 114 if stateObject != nil { 115 // Get AccountProxiedBalance and update ProxiedBalance 116 apb := stateObject.GetAccountProxiedBalance(self.db, user) 117 var dirtyApb *accountProxiedBalance 118 if apb == nil { 119 dirtyApb = NewAccountProxiedBalance() 120 } else { 121 dirtyApb = apb.Copy() 122 } 123 dirtyApb.ProxiedBalance = new(big.Int).Sub(dirtyApb.ProxiedBalance, amount) 124 stateObject.SetAccountProxiedBalance(self.db, user, dirtyApb) 125 126 // Sub amount from Total Proxied Balance 127 stateObject.SubProxiedBalance(amount) 128 } 129 } 130 131 // GetDepositProxiedBalanceByUser 132 func (self *StateDB) GetDepositProxiedBalanceByUser(addr, user common.Address) *big.Int { 133 stateObject := self.getStateObject(addr) 134 if stateObject != nil { 135 apb := stateObject.GetAccountProxiedBalance(self.db, user) 136 if apb == nil { 137 return common.Big0 138 } else { 139 return apb.DepositProxiedBalance 140 } 141 } 142 return common.Big0 143 } 144 145 func (self *StateDB) GetProxiedAddressNumber(addr common.Address) int { 146 stateObject := self.getStateObject(addr) 147 if stateObject == nil { 148 return 0 149 } 150 number := 0 151 it := trie.NewIterator(stateObject.getProxiedTrie(self.db).NodeIterator(nil)) 152 for it.Next() { 153 number++ 154 } 155 return number 156 } 157 158 // AddDepositProxiedBalanceByUser adds proxied amount to the account associated with addr 159 func (self *StateDB) AddDepositProxiedBalanceByUser(addr, user common.Address, amount *big.Int) { 160 stateObject := self.GetOrNewStateObject(addr) 161 if stateObject != nil { 162 // Get AccountProxiedBalance and update DepositProxiedBalance 163 apb := stateObject.GetAccountProxiedBalance(self.db, user) 164 var dirtyApb *accountProxiedBalance 165 if apb == nil { 166 dirtyApb = NewAccountProxiedBalance() 167 } else { 168 dirtyApb = apb.Copy() 169 } 170 dirtyApb.DepositProxiedBalance = new(big.Int).Add(dirtyApb.DepositProxiedBalance, amount) 171 stateObject.SetAccountProxiedBalance(self.db, user, dirtyApb) 172 173 // Add amount to Total Proxied Balance 174 stateObject.AddDepositProxiedBalance(amount) 175 } 176 } 177 178 // SubDepositProxiedBalanceByUser subtracts proxied amount from the account associated with addr 179 func (self *StateDB) SubDepositProxiedBalanceByUser(addr, user common.Address, amount *big.Int) { 180 stateObject := self.GetOrNewStateObject(addr) 181 if stateObject != nil { 182 // Get AccountProxiedBalance and update DepositProxiedBalance 183 apb := stateObject.GetAccountProxiedBalance(self.db, user) 184 var dirtyApb *accountProxiedBalance 185 if apb == nil { 186 dirtyApb = NewAccountProxiedBalance() 187 } else { 188 dirtyApb = apb.Copy() 189 } 190 dirtyApb.DepositProxiedBalance = new(big.Int).Sub(dirtyApb.DepositProxiedBalance, amount) 191 stateObject.SetAccountProxiedBalance(self.db, user, dirtyApb) 192 193 // Sub amount from Total Proxied Balance 194 stateObject.SubDepositProxiedBalance(amount) 195 } 196 } 197 198 // GetPendingRefundBalanceByUser 199 func (self *StateDB) GetPendingRefundBalanceByUser(addr, user common.Address) *big.Int { 200 stateObject := self.getStateObject(addr) 201 if stateObject != nil { 202 apb := stateObject.GetAccountProxiedBalance(self.db, user) 203 if apb == nil { 204 return common.Big0 205 } else { 206 return apb.PendingRefundBalance 207 } 208 } 209 return common.Big0 210 } 211 212 // AddPendingRefundBalanceByUser adds pending refund amount to the account associated with addr 213 func (self *StateDB) AddPendingRefundBalanceByUser(addr, user common.Address, amount *big.Int) { 214 stateObject := self.GetOrNewStateObject(addr) 215 if stateObject != nil { 216 // Get AccountProxiedBalance and update PendingRefundBalance 217 apb := stateObject.GetAccountProxiedBalance(self.db, user) 218 var dirtyApb *accountProxiedBalance 219 if apb == nil { 220 dirtyApb = NewAccountProxiedBalance() 221 } else { 222 dirtyApb = apb.Copy() 223 } 224 dirtyApb.PendingRefundBalance = new(big.Int).Add(dirtyApb.PendingRefundBalance, amount) 225 stateObject.SetAccountProxiedBalance(self.db, user, dirtyApb) 226 227 // Add amount to Total Proxied Balance 228 stateObject.AddPendingRefundBalance(amount) 229 } 230 } 231 232 // SubPendingRefundBalanceByUser subtracts pending refund amount from the account associated with addr 233 func (self *StateDB) SubPendingRefundBalanceByUser(addr, user common.Address, amount *big.Int) { 234 stateObject := self.GetOrNewStateObject(addr) 235 if stateObject != nil { 236 // Get AccountProxiedBalance and update PendingRefundBalance 237 apb := stateObject.GetAccountProxiedBalance(self.db, user) 238 var dirtyApb *accountProxiedBalance 239 if apb == nil { 240 dirtyApb = NewAccountProxiedBalance() 241 } else { 242 dirtyApb = apb.Copy() 243 } 244 dirtyApb.PendingRefundBalance = new(big.Int).Sub(dirtyApb.PendingRefundBalance, amount) 245 stateObject.SetAccountProxiedBalance(self.db, user, dirtyApb) 246 247 // Sub amount from Total Proxied Balance 248 stateObject.SubPendingRefundBalance(amount) 249 } 250 } 251 252 // ----- Candidate 253 254 // IsCandidate Retrieve the candidate flag of the given address or false if object not found 255 func (self *StateDB) IsCandidate(addr common.Address) bool { 256 stateObject := self.getStateObject(addr) 257 if stateObject != nil { 258 return stateObject.IsCandidate() 259 } 260 return false 261 } 262 263 func (self *StateDB) IsCleanAddress(addr common.Address) bool { 264 stateObject := self.getStateObject(addr) 265 if stateObject != nil { 266 return !stateObject.IsCandidate() && stateObject.IsEmptyTrie() 267 } 268 return true 269 } 270 271 func (self *StateDB) GetPubkey(addr common.Address) string { 272 stateObject := self.getStateObject(addr) 273 if stateObject != nil { 274 return stateObject.Pubkey() 275 } 276 return "" 277 } 278 279 // GetCommission Retrieve the commission percentage of the given address or 0 if object not found 280 func (self *StateDB) GetCommission(addr common.Address) uint8 { 281 stateObject := self.getStateObject(addr) 282 if stateObject != nil { 283 return stateObject.Commission() 284 } 285 return 0 286 } 287 288 func (self *StateDB) SetCommission(addr common.Address, commission uint8) { 289 stateObject := self.GetOrNewStateObject(addr) 290 if stateObject != nil { 291 stateObject.SetCommission(commission) 292 } 293 } 294 295 // ApplyForCandidate Set the Candidate Flag of the given address to true and commission to given value 296 func (self *StateDB) ApplyForCandidate(addr common.Address, pubkey string, commission uint8) { 297 stateObject := self.GetOrNewStateObject(addr) 298 if stateObject != nil { 299 stateObject.SetCandidate(true) 300 stateObject.SetCommission(commission) 301 stateObject.SetPubkey(pubkey) 302 } 303 } 304 305 // CancelCandidate Set the Candidate Flag of the given address to false and commission to 0 306 func (self *StateDB) CancelCandidate(addr common.Address, allRefund bool) { 307 stateObject := self.GetOrNewStateObject(addr) 308 if stateObject != nil { 309 stateObject.SetCandidate(false) 310 // remove pubkey 311 stateObject.SetPubkey("") 312 313 if allRefund { 314 stateObject.SetCommission(0) 315 } 316 } 317 } 318 319 func (self *StateDB) GetForbidden(addr common.Address) bool { 320 stateObject := self.GetOrNewStateObject(addr) 321 if stateObject != nil { 322 return stateObject.IsForbidden() 323 } 324 return false 325 } 326 327 func (self *StateDB) SetForbidden(addr common.Address, forbidden bool) { 328 stateObject := self.GetOrNewStateObject(addr) 329 if stateObject != nil { 330 stateObject.SetForbidden(forbidden) 331 } 332 } 333 334 func (self *StateDB) GetForbiddenTime(addr common.Address) *big.Int { 335 stateObject := self.GetOrNewStateObject(addr) 336 if stateObject != nil { 337 return stateObject.ForbiddenTime() 338 } 339 return common.Big0 340 } 341 342 func (self *StateDB) SetForbiddenTime(addr common.Address, forbiddenTime *big.Int) { 343 stateObject := self.GetOrNewStateObject(addr) 344 if stateObject != nil { 345 stateObject.SetForbiddenTime(forbiddenTime) 346 } 347 } 348 349 func (self *StateDB) GetMinedBlocks(addr common.Address) *big.Int { 350 stateObject := self.GetOrNewStateObject(addr) 351 if stateObject != nil { 352 return stateObject.BlockTime() 353 } 354 355 return common.Big0 356 } 357 358 func (self *StateDB) SetMinedBlocks(addr common.Address, blocks *big.Int) { 359 stateObject := self.GetOrNewStateObject(addr) 360 if stateObject != nil { 361 stateObject.SetBlockTime(blocks) 362 } 363 } 364 365 // ClearCommission Set the Candidate commission to 0 366 func (self *StateDB) ClearCommission(addr common.Address) { 367 stateObject := self.GetOrNewStateObject(addr) 368 if stateObject != nil { 369 stateObject.SetCommission(0) 370 } 371 } 372 373 // ----- Refund Set 374 375 // MarkDelegateAddressRefund adds the specified object to the dirty map to avoid 376 func (self *StateDB) MarkDelegateAddressRefund(addr common.Address) { 377 if _, exist := self.GetDelegateAddressRefundSet()[addr]; !exist { 378 self.delegateRefundSet[addr] = struct{}{} 379 self.delegateRefundSetDirty = true 380 } 381 } 382 383 func (self *StateDB) GetDelegateAddressRefundSet() DelegateRefundSet { 384 if len(self.delegateRefundSet) != 0 { 385 return self.delegateRefundSet 386 } 387 // Try to get from Trie 388 enc, err := self.trie.TryGet(refundSetKey) 389 if err != nil { 390 self.setError(err) 391 return nil 392 } 393 var value DelegateRefundSet 394 if len(enc) > 0 { 395 err := rlp.DecodeBytes(enc, &value) 396 if err != nil { 397 self.setError(err) 398 } 399 self.delegateRefundSet = value 400 } 401 return value 402 } 403 404 func (self *StateDB) commitDelegateRefundSet() { 405 data, err := rlp.EncodeToBytes(self.delegateRefundSet) 406 if err != nil { 407 panic(fmt.Errorf("can't encode delegate refund set : %v", err)) 408 } 409 self.setError(self.trie.TryUpdate(refundSetKey, data)) 410 } 411 412 func (self *StateDB) ClearDelegateRefundSet() { 413 self.setError(self.trie.TryDelete(refundSetKey)) 414 self.delegateRefundSet = make(DelegateRefundSet) 415 self.delegateRefundSetDirty = false 416 } 417 418 // Store the Delegate Refund Set 419 420 var refundSetKey = []byte("DelegateRefundSet") 421 422 type DelegateRefundSet map[common.Address]struct{} 423 424 func (set DelegateRefundSet) EncodeRLP(w io.Writer) error { 425 var list []common.Address 426 for addr := range set { 427 list = append(list, addr) 428 } 429 sort.Slice(list, func(i, j int) bool { 430 return bytes.Compare(list[i].Bytes(), list[j].Bytes()) == 1 431 }) 432 return rlp.Encode(w, list) 433 } 434 435 func (set *DelegateRefundSet) DecodeRLP(s *rlp.Stream) error { 436 var list []common.Address 437 if err := s.Decode(&list); err != nil { 438 return err 439 } 440 refundSet := make(DelegateRefundSet, len(list)) 441 for _, addr := range list { 442 refundSet[addr] = struct{}{} 443 } 444 *set = refundSet 445 return nil 446 }