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