github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/core/state/state_object_delegate.go (about) 1 package state 2 3 import ( 4 "fmt" 5 "github.com/intfoundation/intchain/common" 6 "github.com/intfoundation/intchain/core/types" 7 "github.com/intfoundation/intchain/rlp" 8 "math/big" 9 ) 10 11 // ----- Type 12 type accountProxiedBalance struct { 13 ProxiedBalance *big.Int 14 DepositProxiedBalance *big.Int 15 PendingRefundBalance *big.Int 16 } 17 18 func (a *accountProxiedBalance) String() (str string) { 19 return fmt.Sprintf("pb: %v, dpb: %v, rb: %v", a.ProxiedBalance, a.DepositProxiedBalance, a.PendingRefundBalance) 20 } 21 22 func (a *accountProxiedBalance) Copy() *accountProxiedBalance { 23 cpy := *a 24 return &cpy 25 } 26 27 func (a *accountProxiedBalance) Equal(b *accountProxiedBalance) bool { 28 if b == nil { 29 return false 30 } 31 return a.ProxiedBalance.Cmp(b.ProxiedBalance) == 0 && a.DepositProxiedBalance.Cmp(b.DepositProxiedBalance) == 0 && a.PendingRefundBalance.Cmp(b.PendingRefundBalance) == 0 32 } 33 34 func (a *accountProxiedBalance) IsEmpty() bool { 35 return a.ProxiedBalance.Sign() == 0 && a.DepositProxiedBalance.Sign() == 0 && a.PendingRefundBalance.Sign() == 0 36 } 37 38 func NewAccountProxiedBalance() *accountProxiedBalance { 39 return &accountProxiedBalance{ 40 ProxiedBalance: big.NewInt(0), 41 DepositProxiedBalance: big.NewInt(0), 42 PendingRefundBalance: big.NewInt(0), 43 } 44 } 45 46 type Proxied map[common.Address]*accountProxiedBalance 47 48 func (p Proxied) String() (str string) { 49 for key, value := range p { 50 str += fmt.Sprintf("%v : %X\n", key.String(), value) 51 } 52 return 53 } 54 55 func (p Proxied) Copy() Proxied { 56 cpy := make(Proxied) 57 for key, value := range p { 58 cpy[key] = value.Copy() 59 } 60 return cpy 61 } 62 63 // ----- DelegateBalance 64 65 // AddDelegateBalance add amount to c's DelegateBalance. 66 func (c *stateObject) AddDelegateBalance(amount *big.Int) { 67 // EIP158: We must check emptiness for the objects such that the account 68 // clearing (0,0,0 objects) can take effect. 69 if amount.Sign() == 0 { 70 if c.empty() { 71 c.touch() 72 } 73 return 74 } 75 c.SetDelegateBalance(new(big.Int).Add(c.DelegateBalance(), amount)) 76 } 77 78 // SubDelegateBalance removes amount from c's DelegateBalance. 79 func (c *stateObject) SubDelegateBalance(amount *big.Int) { 80 if amount.Sign() == 0 { 81 return 82 } 83 c.SetDelegateBalance(new(big.Int).Sub(c.DelegateBalance(), amount)) 84 } 85 86 func (self *stateObject) SetDelegateBalance(amount *big.Int) { 87 self.db.journal = append(self.db.journal, delegateBalanceChange{ 88 account: &self.address, 89 prev: new(big.Int).Set(self.data.DelegateBalance), 90 }) 91 self.setDelegateBalance(amount) 92 } 93 94 func (self *stateObject) setDelegateBalance(amount *big.Int) { 95 self.data.DelegateBalance = amount 96 if self.onDirty != nil { 97 self.onDirty(self.Address()) 98 self.onDirty = nil 99 } 100 } 101 102 func (self *stateObject) DelegateBalance() *big.Int { 103 return self.data.DelegateBalance 104 } 105 106 // ----- ProxiedBalance 107 108 // AddProxiedBalance add amount to c's ProxiedBalance. 109 func (c *stateObject) AddProxiedBalance(amount *big.Int) { 110 // EIP158: We must check emptiness for the objects such that the account 111 // clearing (0,0,0 objects) can take effect. 112 if amount.Sign() == 0 { 113 if c.empty() { 114 c.touch() 115 } 116 return 117 } 118 c.SetProxiedBalance(new(big.Int).Add(c.ProxiedBalance(), amount)) 119 } 120 121 // SubProxiedBalance removes amount from c's ProxiedBalance. 122 func (c *stateObject) SubProxiedBalance(amount *big.Int) { 123 if amount.Sign() == 0 { 124 return 125 } 126 c.SetProxiedBalance(new(big.Int).Sub(c.ProxiedBalance(), amount)) 127 } 128 129 func (self *stateObject) SetProxiedBalance(amount *big.Int) { 130 self.db.journal = append(self.db.journal, proxiedBalanceChange{ 131 account: &self.address, 132 prev: new(big.Int).Set(self.data.ProxiedBalance), 133 }) 134 self.setProxiedBalance(amount) 135 } 136 137 func (self *stateObject) setProxiedBalance(amount *big.Int) { 138 self.data.ProxiedBalance = amount 139 if self.onDirty != nil { 140 self.onDirty(self.Address()) 141 self.onDirty = nil 142 } 143 } 144 145 func (self *stateObject) ProxiedBalance() *big.Int { 146 return self.data.ProxiedBalance 147 } 148 149 // ----- DepositProxiedBalance 150 151 // AddDepositProxiedBalance add amount to c's DepositProxiedBalance. 152 func (c *stateObject) AddDepositProxiedBalance(amount *big.Int) { 153 // EIP158: We must check emptiness for the objects such that the account 154 // clearing (0,0,0 objects) can take effect. 155 if amount.Sign() == 0 { 156 if c.empty() { 157 c.touch() 158 } 159 return 160 } 161 c.SetDepositProxiedBalance(new(big.Int).Add(c.DepositProxiedBalance(), amount)) 162 } 163 164 // SubDepositProxiedBalance removes amount from c's DepositProxiedBalance. 165 func (c *stateObject) SubDepositProxiedBalance(amount *big.Int) { 166 if amount.Sign() == 0 { 167 return 168 } 169 c.SetDepositProxiedBalance(new(big.Int).Sub(c.DepositProxiedBalance(), amount)) 170 } 171 172 func (self *stateObject) SetDepositProxiedBalance(amount *big.Int) { 173 self.db.journal = append(self.db.journal, depositProxiedBalanceChange{ 174 account: &self.address, 175 prev: new(big.Int).Set(self.data.DepositProxiedBalance), 176 }) 177 self.setDepositProxiedBalance(amount) 178 } 179 180 func (self *stateObject) setDepositProxiedBalance(amount *big.Int) { 181 self.data.DepositProxiedBalance = amount 182 if self.onDirty != nil { 183 self.onDirty(self.Address()) 184 self.onDirty = nil 185 } 186 } 187 188 func (self *stateObject) DepositProxiedBalance() *big.Int { 189 return self.data.DepositProxiedBalance 190 } 191 192 // ----- PendingRefundBalance 193 194 // AddPendingRefundBalance add amount to c's PendingRefundBalance. 195 func (c *stateObject) AddPendingRefundBalance(amount *big.Int) { 196 // EIP158: We must check emptiness for the objects such that the account 197 // clearing (0,0,0 objects) can take effect. 198 if amount.Sign() == 0 { 199 if c.empty() { 200 c.touch() 201 } 202 return 203 } 204 c.SetPendingRefundBalance(new(big.Int).Add(c.PendingRefundBalance(), amount)) 205 } 206 207 // SubPendingRefundBalance removes amount from c's PendingRefundBalance. 208 func (c *stateObject) SubPendingRefundBalance(amount *big.Int) { 209 if amount.Sign() == 0 { 210 return 211 } 212 c.SetPendingRefundBalance(new(big.Int).Sub(c.PendingRefundBalance(), amount)) 213 } 214 215 func (self *stateObject) SetPendingRefundBalance(amount *big.Int) { 216 self.db.journal = append(self.db.journal, pendingRefundBalanceChange{ 217 account: &self.address, 218 prev: new(big.Int).Set(self.data.PendingRefundBalance), 219 }) 220 self.setPendingRefundBalance(amount) 221 } 222 223 func (self *stateObject) setPendingRefundBalance(amount *big.Int) { 224 self.data.PendingRefundBalance = amount 225 if self.onDirty != nil { 226 self.onDirty(self.Address()) 227 self.onDirty = nil 228 } 229 } 230 231 func (self *stateObject) PendingRefundBalance() *big.Int { 232 return self.data.PendingRefundBalance 233 } 234 235 // ----- Delegate Trie 236 237 func (c *stateObject) getProxiedTrie(db Database) Trie { 238 if c.proxiedTrie == nil { 239 var err error 240 c.proxiedTrie, err = db.OpenProxiedTrie(c.addrHash, c.data.ProxiedRoot) 241 if err != nil { 242 c.proxiedTrie, _ = db.OpenProxiedTrie(c.addrHash, common.Hash{}) 243 c.setError(fmt.Errorf("can't create proxied trie: %v", err)) 244 } 245 } 246 return c.proxiedTrie 247 } 248 249 // GetAccountProxiedBalance returns a value in proxied trie 250 func (self *stateObject) GetAccountProxiedBalance(db Database, key common.Address) *accountProxiedBalance { 251 // If we have a dirty value for this state entry, return it 252 value, dirty := self.dirtyProxied[key] 253 if dirty { 254 return value 255 } 256 // If we have the original value cached, return that 257 value, cached := self.originProxied[key] 258 if cached { 259 return value 260 } 261 // Otherwise load the value from the database 262 enc, err := self.getProxiedTrie(db).TryGet(key[:]) 263 if err != nil { 264 self.setError(err) 265 return nil 266 } 267 if len(enc) > 0 { 268 value = new(accountProxiedBalance) 269 err := rlp.DecodeBytes(enc, value) 270 if err != nil { 271 self.setError(err) 272 } 273 } 274 self.originProxied[key] = value 275 return value 276 } 277 278 // SetAccountProxiedBalance updates a value in account storage. 279 func (self *stateObject) SetAccountProxiedBalance(db Database, key common.Address, proxiedBalance *accountProxiedBalance) { 280 self.db.journal = append(self.db.journal, accountProxiedBalanceChange{ 281 account: &self.address, 282 key: key, 283 prevalue: self.GetAccountProxiedBalance(db, key), 284 }) 285 self.setAccountProxiedBalance(key, proxiedBalance) 286 } 287 288 func (self *stateObject) setAccountProxiedBalance(key common.Address, proxiedBalance *accountProxiedBalance) { 289 self.dirtyProxied[key] = proxiedBalance 290 291 if self.onDirty != nil { 292 self.onDirty(self.Address()) 293 self.onDirty = nil 294 } 295 } 296 297 // updateProxiedTrie writes cached proxied modifications into the object's proxied trie. 298 func (self *stateObject) updateProxiedTrie(db Database) Trie { 299 tr := self.getProxiedTrie(db) 300 for key, value := range self.dirtyProxied { 301 delete(self.dirtyProxied, key) 302 303 // Skip noop changes, persist actual changes 304 if value.Equal(self.originProxied[key]) { 305 continue 306 } 307 self.originProxied[key] = value 308 309 if value.IsEmpty() { 310 self.setError(tr.TryDelete(key[:])) 311 continue 312 } 313 // Encoding []byte cannot fail, ok to ignore the error. 314 v, _ := rlp.EncodeToBytes(value) 315 self.setError(tr.TryUpdate(key[:], v)) 316 } 317 return tr 318 } 319 320 // updateProxiedRoot sets the proxiedTrie root to the current root hash of 321 func (self *stateObject) updateProxiedRoot(db Database) { 322 self.updateProxiedTrie(db) 323 self.data.ProxiedRoot = self.proxiedTrie.Hash() 324 } 325 326 // CommitProxiedTrie the proxied trie of the object to dwb. 327 // This updates the proxied trie root. 328 func (self *stateObject) CommitProxiedTrie(db Database) error { 329 self.updateProxiedTrie(db) 330 if self.dbErr != nil { 331 return self.dbErr 332 } 333 root, err := self.proxiedTrie.Commit(nil) 334 if err == nil { 335 self.data.ProxiedRoot = root 336 } 337 return err 338 } 339 340 func (self *stateObject) IsEmptyTrie() bool { 341 return self.data.ProxiedRoot == types.EmptyRootHash 342 } 343 344 // ----- Candidate 345 346 func (self *stateObject) IsCandidate() bool { 347 return self.data.Candidate 348 } 349 350 func (self *stateObject) SetCandidate(isCandidate bool) { 351 self.db.journal = append(self.db.journal, candidateChange{ 352 account: &self.address, 353 prev: self.data.Candidate, 354 }) 355 self.setCandidate(isCandidate) 356 } 357 358 func (self *stateObject) setCandidate(isCandidate bool) { 359 self.data.Candidate = isCandidate 360 361 if self.onDirty != nil { 362 self.onDirty(self.Address()) 363 self.onDirty = nil 364 } 365 } 366 367 func (self *stateObject) Pubkey() string { 368 return self.data.Pubkey 369 } 370 371 func (self *stateObject) SetPubkey(pubkey string) { 372 self.db.journal = append(self.db.journal, pubkeyChange{ 373 account: &self.address, 374 prev: self.data.Pubkey, 375 }) 376 377 self.setPubkey(pubkey) 378 } 379 380 func (self *stateObject) setPubkey(pubkey string) { 381 self.data.Pubkey = pubkey 382 383 if self.onDirty != nil { 384 self.onDirty(self.Address()) 385 self.onDirty = nil 386 } 387 } 388 389 func (self *stateObject) Commission() uint8 { 390 return self.data.Commission 391 } 392 393 func (self *stateObject) SetCommission(commission uint8) { 394 self.db.journal = append(self.db.journal, commissionChange{ 395 account: &self.address, 396 prev: self.data.Commission, 397 }) 398 self.setCommission(commission) 399 } 400 401 func (self *stateObject) setCommission(commission uint8) { 402 self.data.Commission = commission 403 404 if self.onDirty != nil { 405 self.onDirty(self.Address()) 406 self.onDirty = nil 407 } 408 } 409 410 //func (self *stateObject) IsForbidden() bool { 411 // return self.data.IsForbidden 412 //} 413 // 414 //func (self *stateObject) SetForbidden(forbidden bool) { 415 // self.db.journal = append(self.db.journal, forbiddenChange{ 416 // account: &self.address, 417 // prev: self.data.IsForbidden, 418 // }) 419 // self.setForbidden(forbidden) 420 //} 421 // 422 //func (self *stateObject) setForbidden(forbidden bool) { 423 // self.data.IsForbidden = forbidden 424 // 425 // if self.onDirty != nil { 426 // self.onDirty(self.Address()) 427 // self.onDirty = nil 428 // } 429 //} 430 431 //func (self *stateObject) BlockTime() *big.Int { 432 // return self.data.BlockTime 433 //} 434 // 435 //func (self *stateObject) SetBlockTime(blockTime *big.Int) { 436 // self.db.journal = append(self.db.journal, blockTimeChange{ 437 // account: &self.address, 438 // prev: self.data.BlockTime, 439 // }) 440 // self.setBlockTime(blockTime) 441 //} 442 // 443 //func (self *stateObject) setBlockTime(blockTime *big.Int) { 444 // self.data.BlockTime = blockTime 445 // 446 // if self.onDirty != nil { 447 // self.onDirty(self.Address()) 448 // self.onDirty = nil 449 // } 450 //} 451 452 //func (self *stateObject) ForbiddenTime() *big.Int { 453 // return self.data.ForbiddenTime 454 //} 455 // 456 //func (self *stateObject) SetForbiddenTime(forbiddenTime *big.Int) { 457 // self.db.journal = append(self.db.journal, forbiddenTimeChange{ 458 // account: &self.address, 459 // prev: self.data.ForbiddenTime, 460 // }) 461 // self.setForbiddenTime(forbiddenTime) 462 //} 463 // 464 //func (self *stateObject) setForbiddenTime(forbiddenTime *big.Int) { 465 // self.data.ForbiddenTime = forbiddenTime 466 // 467 // if self.onDirty != nil { 468 // self.onDirty(self.Address()) 469 // self.onDirty = nil 470 // } 471 //}