github.com/FUSIONFoundation/efsn@v3.6.2-0.20200916075423-dbb5dd5d2cc7+incompatible/core/state/state_object.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package state 18 19 import ( 20 "bytes" 21 "fmt" 22 "io" 23 "math/big" 24 25 "github.com/FusionFoundation/efsn/common" 26 "github.com/FusionFoundation/efsn/crypto" 27 "github.com/FusionFoundation/efsn/rlp" 28 ) 29 30 var emptyCodeHash = crypto.Keccak256(nil) 31 32 type Code []byte 33 34 func (self Code) String() string { 35 return string(self) //strings.Join(Disassemble(self), " ") 36 } 37 38 type Storage map[common.Hash]common.Hash 39 40 func (self Storage) String() (str string) { 41 for key, value := range self { 42 str += fmt.Sprintf("%X : %X\n", key, value) 43 } 44 45 return 46 } 47 48 func (self Storage) Copy() Storage { 49 cpy := make(Storage) 50 for key, value := range self { 51 cpy[key] = value 52 } 53 54 return cpy 55 } 56 57 // stateObject represents an Ethereum account which is being modified. 58 // 59 // The usage pattern is as follows: 60 // First you need to obtain a state object. 61 // Account values can be accessed and modified through the object. 62 // Finally, call CommitTrie to write the modified storage trie into a database. 63 type stateObject struct { 64 address common.Address 65 addrHash common.Hash // hash of ethereum address of the account 66 data Account 67 db *StateDB 68 69 // DB error. 70 // State objects are used by the consensus core and VM which are 71 // unable to deal with database-level errors. Any error that occurs 72 // during a database read is memoized here and will eventually be returned 73 // by StateDB.Commit. 74 dbErr error 75 76 // Write caches. 77 trie Trie // storage trie, which becomes non-nil on first access 78 code Code // contract bytecode, which gets set when code is loaded 79 80 originStorage Storage // Storage cache of original entries to dedup rewrites 81 dirtyStorage Storage // Storage entries that need to be flushed to disk 82 83 // Cache flags. 84 // When an object is marked suicided it will be delete from the trie 85 // during the "update" phase of the state transition. 86 dirtyCode bool // true if the code was updated 87 suicided bool 88 deleted bool 89 } 90 91 // empty returns whether the account is considered empty. 92 func (s *stateObject) empty() bool { 93 if s.data.Nonce != 0 { 94 return false 95 } 96 if len(s.data.BalancesVal) > 0 { 97 return false 98 } 99 if len(s.data.TimeLockBalancesVal) > 0 { 100 return false 101 } 102 if bytes.Equal(s.data.CodeHash, emptyCodeHash) == false { 103 return false 104 } 105 if s.address.IsSpecialKeyAddress() == true { 106 return false 107 } 108 return true 109 } 110 111 func (s *stateObject) deepCopyBalancesHash() []common.Hash { 112 ret := make([]common.Hash, 0) 113 if len(s.data.BalancesHash) == 0 { 114 return ret 115 } 116 117 for _, v := range s.data.BalancesHash { 118 ret = append(ret, v) 119 } 120 121 return ret 122 } 123 124 func (s *stateObject) deepCopyBalancesVal() []*big.Int { 125 ret := make([]*big.Int, 0) 126 if len(s.data.BalancesVal) == 0 { 127 return ret 128 } 129 130 for _, v := range s.data.BalancesVal { 131 a := new(big.Int).SetBytes(v.Bytes()) 132 ret = append(ret, a) 133 } 134 135 return ret 136 } 137 138 func (s *stateObject) deepCopyTimeLockBalancesHash() []common.Hash { 139 ret := make([]common.Hash, 0) 140 if len(s.data.TimeLockBalancesHash) == 0 { 141 return ret 142 } 143 144 for _, v := range s.data.TimeLockBalancesHash { 145 ret = append(ret, v) 146 } 147 148 return ret 149 } 150 151 func (s *stateObject) deepCopyTimeLockBalancesVal() []*common.TimeLock { 152 ret := make([]*common.TimeLock, 0) 153 if len(s.data.TimeLockBalancesVal) == 0 { 154 return ret 155 } 156 157 for _, v := range s.data.TimeLockBalancesVal { 158 t := v.Clone() 159 ret = append(ret, t) 160 } 161 162 return ret 163 } 164 165 // Account is the Ethereum consensus representation of accounts. 166 // These objects are stored in the main account trie. 167 type Account struct { 168 Nonce uint64 169 Notaion uint64 170 171 // Balances map[common.Hash]*big.Int 172 // TimeLockBalances map[common.Hash]*common.TimeLock 173 174 BalancesHash []common.Hash 175 BalancesVal []*big.Int 176 177 TimeLockBalancesHash []common.Hash 178 TimeLockBalancesVal []*common.TimeLock 179 180 Root common.Hash // merkle root of the storage trie 181 CodeHash []byte 182 } 183 184 // newObject creates a state object. 185 func newObject(db *StateDB, address common.Address, data Account) *stateObject { 186 // if data.Balances == nil { 187 // data.Balances = make(map[common.Hash]*big.Int) 188 // } 189 // if data.TimeLockBalances == nil { 190 // data.TimeLockBalances = make(map[common.Hash]*common.TimeLock) 191 // } 192 193 if data.BalancesHash == nil { 194 data.BalancesHash = make([]common.Hash, 0) 195 } 196 if data.BalancesVal == nil { 197 data.BalancesVal = make([]*big.Int, 0) 198 } 199 if data.TimeLockBalancesHash == nil { 200 data.TimeLockBalancesHash = make([]common.Hash, 0) 201 } 202 if data.TimeLockBalancesVal == nil { 203 data.TimeLockBalancesVal = make([]*common.TimeLock, 0) 204 } 205 206 if data.CodeHash == nil { 207 data.CodeHash = emptyCodeHash 208 } 209 return &stateObject{ 210 db: db, 211 address: address, 212 addrHash: crypto.Keccak256Hash(address[:]), 213 data: data, 214 originStorage: make(Storage), 215 dirtyStorage: make(Storage), 216 } 217 } 218 219 // EncodeRLP implements rlp.Encoder. 220 func (c *stateObject) EncodeRLP(w io.Writer) error { 221 return rlp.Encode(w, c.data) 222 } 223 224 // setError remembers the first non-nil error it is called with. 225 func (self *stateObject) setError(err error) { 226 if self.dbErr == nil { 227 self.dbErr = err 228 } 229 } 230 231 func (self *stateObject) markSuicided() { 232 self.suicided = true 233 } 234 235 func (c *stateObject) touch() { 236 c.db.journal.append(touchChange{ 237 account: &c.address, 238 }) 239 if c.address == ripemd { 240 // Explicitly put it in the dirty-cache, which is otherwise generated from 241 // flattened journals. 242 c.db.journal.dirty(c.address) 243 } 244 } 245 246 func (c *stateObject) getTrie(db Database) Trie { 247 if c.trie == nil { 248 var err error 249 c.trie, err = db.OpenStorageTrie(c.addrHash, c.data.Root) 250 if err != nil { 251 c.trie, _ = db.OpenStorageTrie(c.addrHash, common.Hash{}) 252 c.setError(fmt.Errorf("can't create storage trie: %v", err)) 253 } 254 } 255 return c.trie 256 } 257 258 // GetState returns a value in account storage. 259 // GetState retrieves a value from the account storage trie. 260 func (self *stateObject) GetState(db Database, key common.Hash) common.Hash { 261 // If we have a dirty value for this state entry, return it 262 value, dirty := self.dirtyStorage[key] 263 if dirty { 264 return value 265 } 266 // Otherwise return the entry's original value 267 return self.GetCommittedState(db, key) 268 } 269 270 // GetCommittedState retrieves a value from the committed account storage trie. 271 func (self *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash { 272 // If we have the original value cached, return that 273 value, cached := self.originStorage[key] 274 if cached { 275 return value 276 } 277 // Otherwise load the value from the database 278 enc, err := self.getTrie(db).TryGet(key[:]) 279 if err != nil { 280 self.setError(err) 281 return common.Hash{} 282 } 283 if len(enc) > 0 { 284 _, content, _, err := rlp.Split(enc) 285 if err != nil { 286 self.setError(err) 287 } 288 value.SetBytes(content) 289 } 290 self.originStorage[key] = value 291 return value 292 } 293 294 // SetState updates a value in account storage. 295 func (self *stateObject) SetState(db Database, key, value common.Hash) { 296 // If the new value is the same as old, don't set 297 prev := self.GetState(db, key) 298 if prev == value { 299 return 300 } 301 // New value is different, update and journal the change 302 self.db.journal.append(storageChange{ 303 account: &self.address, 304 key: key, 305 prevalue: prev, 306 }) 307 self.setState(key, value) 308 } 309 310 func (self *stateObject) setState(key, value common.Hash) { 311 self.dirtyStorage[key] = value 312 } 313 314 // updateTrie writes cached storage modifications into the object's storage trie. 315 func (self *stateObject) updateTrie(db Database) Trie { 316 tr := self.getTrie(db) 317 for key, value := range self.dirtyStorage { 318 delete(self.dirtyStorage, key) 319 320 // Skip noop changes, persist actual changes 321 if value == self.originStorage[key] { 322 continue 323 } 324 self.originStorage[key] = value 325 326 if (value == common.Hash{}) { 327 self.setError(tr.TryDelete(key[:])) 328 continue 329 } 330 // Encoding []byte cannot fail, ok to ignore the error. 331 v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) 332 self.setError(tr.TryUpdate(key[:], v)) 333 } 334 return tr 335 } 336 337 // UpdateRoot sets the trie root to the current root hash of 338 func (self *stateObject) updateRoot(db Database) { 339 self.updateTrie(db) 340 self.data.Root = self.trie.Hash() 341 } 342 343 // CommitTrie the storage trie of the object to db. 344 // This updates the trie root. 345 func (self *stateObject) CommitTrie(db Database) error { 346 self.updateTrie(db) 347 if self.dbErr != nil { 348 return self.dbErr 349 } 350 root, err := self.trie.Commit(nil) 351 if err == nil { 352 self.data.Root = root 353 } 354 return err 355 } 356 357 func (c *stateObject) balanceAssetIndex(assetID common.Hash) int { 358 359 for i, v := range c.data.BalancesHash { 360 if v == assetID { 361 return i 362 } 363 } 364 365 c.data.BalancesHash = append(c.data.BalancesHash, assetID) 366 c.data.BalancesVal = append(c.data.BalancesVal, new(big.Int)) 367 368 return len(c.data.BalancesVal) - 1 369 } 370 371 // AddBalance removes amount from c's balance. 372 // It is used to add funds to the destination account of a transfer. 373 func (c *stateObject) AddBalance(assetID common.Hash, amount *big.Int) { 374 // EIP158: We must check emptiness for the objects such that the account 375 // clearing (0,0,0 objects) can take effect. 376 if amount.Sign() == 0 { 377 if c.empty() { 378 c.touch() 379 } 380 return 381 } 382 index := c.balanceAssetIndex(assetID) 383 384 c.SetBalance(assetID, new(big.Int).Add(c.data.BalancesVal[index], amount)) 385 } 386 387 // SubBalance removes amount from c's balance. 388 // It is used to remove funds from the origin account of a transfer. 389 func (c *stateObject) SubBalance(assetID common.Hash, amount *big.Int) { 390 if amount.Sign() == 0 { 391 return 392 } 393 index := c.balanceAssetIndex(assetID) 394 c.SetBalance(assetID, new(big.Int).Sub(c.data.BalancesVal[index], amount)) 395 } 396 397 func (self *stateObject) SetBalance(assetID common.Hash, amount *big.Int) { 398 index := self.balanceAssetIndex(assetID) 399 400 self.db.journal.append(balanceChange{ 401 account: &self.address, 402 assetID: assetID, 403 prev: new(big.Int).Set(self.data.BalancesVal[index]), 404 }) 405 self.setBalance(assetID, amount) 406 } 407 408 func (self *stateObject) setBalance(assetID common.Hash, amount *big.Int) { 409 index := self.balanceAssetIndex(assetID) 410 self.data.BalancesVal[index] = amount 411 } 412 413 func (c *stateObject) timeLockAssetIndex(assetID common.Hash) int { 414 415 for i, v := range c.data.TimeLockBalancesHash { 416 if v == assetID { 417 return i 418 } 419 } 420 421 c.data.TimeLockBalancesHash = append(c.data.TimeLockBalancesHash, assetID) 422 c.data.TimeLockBalancesVal = append(c.data.TimeLockBalancesVal, new(common.TimeLock)) 423 424 return len(c.data.TimeLockBalancesVal) - 1 425 } 426 427 // AddTimeLockBalance wacom 428 func (s *stateObject) AddTimeLockBalance(assetID common.Hash, amount *common.TimeLock, blockNumber *big.Int, timestamp uint64) { 429 if amount.IsEmpty() { 430 if s.empty() { 431 s.touch() 432 } 433 return 434 } 435 436 index := s.timeLockAssetIndex(assetID) 437 res := s.data.TimeLockBalancesVal[index] 438 res = new(common.TimeLock).Add(res, amount) 439 if res != nil { 440 res = res.ClearExpired(timestamp) 441 } 442 443 s.SetTimeLockBalance(assetID, res) 444 } 445 446 // SubTimeLockBalance wacom 447 func (s *stateObject) SubTimeLockBalance(assetID common.Hash, amount *common.TimeLock, blockNumber *big.Int, timestamp uint64) { 448 if amount.IsEmpty() { 449 return 450 } 451 452 index := s.timeLockAssetIndex(assetID) 453 res := s.data.TimeLockBalancesVal[index] 454 res = new(common.TimeLock).Sub(res, amount) 455 if res != nil { 456 res = res.ClearExpired(timestamp) 457 } 458 459 s.SetTimeLockBalance(assetID, res) 460 } 461 462 func (s *stateObject) SetTimeLockBalance(assetID common.Hash, amount *common.TimeLock) { 463 index := s.timeLockAssetIndex(assetID) 464 465 s.db.journal.append(timeLockBalanceChange{ 466 account: &s.address, 467 assetID: assetID, 468 prev: new(common.TimeLock).Set(s.data.TimeLockBalancesVal[index]), 469 }) 470 s.setTimeLockBalance(assetID, amount) 471 } 472 473 func (s *stateObject) setTimeLockBalance(assetID common.Hash, amount *common.TimeLock) { 474 index := s.timeLockAssetIndex(assetID) 475 s.data.TimeLockBalancesVal[index] = amount 476 } 477 478 // Return the gas back to the origin. Used by the Virtual machine or Closures 479 func (c *stateObject) ReturnGas(gas *big.Int) {} 480 481 func (self *stateObject) deepCopy(db *StateDB) *stateObject { 482 stateObject := newObject(db, self.address, self.data) 483 if self.trie != nil { 484 stateObject.trie = db.db.CopyTrie(self.trie) 485 } 486 stateObject.code = self.code 487 stateObject.dirtyStorage = self.dirtyStorage.Copy() 488 stateObject.originStorage = self.originStorage.Copy() 489 stateObject.suicided = self.suicided 490 stateObject.dirtyCode = self.dirtyCode 491 stateObject.deleted = self.deleted 492 stateObject.data.BalancesHash = self.deepCopyBalancesHash() 493 stateObject.data.BalancesVal = self.deepCopyBalancesVal() 494 stateObject.data.TimeLockBalancesHash = self.deepCopyTimeLockBalancesHash() 495 stateObject.data.TimeLockBalancesVal = self.deepCopyTimeLockBalancesVal() 496 return stateObject 497 } 498 499 // 500 // Attribute accessors 501 // 502 503 // Returns the address of the contract/account 504 func (c *stateObject) Address() common.Address { 505 return c.address 506 } 507 508 // Code returns the contract code associated with this object, if any. 509 func (self *stateObject) Code(db Database) []byte { 510 if self.code != nil { 511 return self.code 512 } 513 if bytes.Equal(self.CodeHash(), emptyCodeHash) { 514 return nil 515 } 516 code, err := db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash())) 517 if err != nil { 518 self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err)) 519 } 520 self.code = code 521 return code 522 } 523 524 func (self *stateObject) SetCode(codeHash common.Hash, code []byte) { 525 prevcode := self.Code(self.db.db) 526 self.db.journal.append(codeChange{ 527 account: &self.address, 528 prevhash: self.CodeHash(), 529 prevcode: prevcode, 530 }) 531 self.setCode(codeHash, code) 532 } 533 534 func (self *stateObject) setCode(codeHash common.Hash, code []byte) { 535 self.code = code 536 self.data.CodeHash = codeHash[:] 537 self.dirtyCode = true 538 } 539 540 func (self *stateObject) SetNonce(nonce uint64) { 541 self.db.journal.append(nonceChange{ 542 account: &self.address, 543 prev: self.data.Nonce, 544 }) 545 self.setNonce(nonce) 546 } 547 548 func (self *stateObject) setNonce(nonce uint64) { 549 self.data.Nonce = nonce 550 } 551 552 func (self *stateObject) SetNotation(notation uint64) { 553 self.db.journal.append(notationChange{ 554 account: &self.address, 555 prev: self.data.Notaion, 556 }) 557 self.setNotation(notation) 558 } 559 560 func (self *stateObject) setNotation(notation uint64) { 561 self.data.Notaion = notation 562 } 563 564 func (self *stateObject) CodeHash() []byte { 565 return self.data.CodeHash 566 } 567 568 func (self *stateObject) CopyBalances() map[common.Hash]string { 569 retBalances := make(map[common.Hash]string) 570 for i, v := range self.data.BalancesHash { 571 if self.data.BalancesVal[i].Sign() != 0 { 572 retBalances[v] = self.data.BalancesVal[i].String() 573 } 574 } 575 return retBalances 576 } 577 578 func (self *stateObject) Balance(assetID common.Hash) *big.Int { 579 index := self.balanceAssetIndex(assetID) 580 return self.data.BalancesVal[index] 581 } 582 583 func (self *stateObject) CopyTimeLockBalances() map[common.Hash]*common.TimeLock { 584 retBalances := make(map[common.Hash]*common.TimeLock) 585 for i, v := range self.data.TimeLockBalancesHash { 586 if !self.data.TimeLockBalancesVal[i].IsEmpty() { 587 retBalances[v] = self.data.TimeLockBalancesVal[i] 588 } 589 } 590 return retBalances 591 } 592 593 func (self *stateObject) TimeLockBalance(assetID common.Hash) *common.TimeLock { 594 index := self.timeLockAssetIndex(assetID) 595 return self.data.TimeLockBalancesVal[index] 596 } 597 598 func (self *stateObject) Nonce() uint64 { 599 return self.data.Nonce 600 } 601 602 func (self *stateObject) Notation() uint64 { 603 return self.data.Notaion 604 } 605 606 // Never called, but must be present to allow stateObject to be used 607 // as a vm.Account interface that also satisfies the vm.ContractRef 608 // interface. Interfaces are awesome. 609 func (self *stateObject) Value() *big.Int { 610 panic("Value on stateObject should never be called") 611 }