github.com/tdcblockchain/tdcblockchain@v0.0.0-20191111034745-805c65ade158/core/state/statedb.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 provides a caching layer atop the Ethereum state trie. 18 package state 19 20 import ( 21 "errors" 22 "fmt" 23 "math/big" 24 "sort" 25 "time" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/core/types" 29 "github.com/ethereum/go-ethereum/crypto" 30 "github.com/ethereum/go-ethereum/log" 31 "github.com/ethereum/go-ethereum/metrics" 32 "github.com/ethereum/go-ethereum/rlp" 33 "github.com/ethereum/go-ethereum/trie" 34 ) 35 36 type revision struct { 37 id int 38 journalIndex int 39 } 40 41 var ( 42 // emptyRoot is the known root hash of an empty trie. 43 emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") 44 45 // emptyCode is the known hash of the empty EVM bytecode. 46 emptyCode = crypto.Keccak256Hash(nil) 47 ) 48 49 type proofList [][]byte 50 51 func (n *proofList) Put(key []byte, value []byte) error { 52 *n = append(*n, value) 53 return nil 54 } 55 56 func (n *proofList) Delete(key []byte) error { 57 panic("not supported") 58 } 59 60 // StateDBs within the ethereum protocol are used to store anything 61 // within the merkle trie. StateDBs take care of caching and storing 62 // nested states. It's the general query interface to retrieve: 63 // * Contracts 64 // * Accounts 65 type StateDB struct { 66 db Database 67 trie Trie 68 69 // This map holds 'live' objects, which will get modified while processing a state transition. 70 stateObjects map[common.Address]*stateObject 71 stateObjectsDirty map[common.Address]struct{} 72 73 // DB error. 74 // State objects are used by the consensus core and VM which are 75 // unable to deal with database-level errors. Any error that occurs 76 // during a database read is memoized here and will eventually be returned 77 // by StateDB.Commit. 78 dbErr error 79 80 // The refund counter, also used by state transitioning. 81 refund uint64 82 83 thash, bhash common.Hash 84 txIndex int 85 logs map[common.Hash][]*types.Log 86 logSize uint 87 88 preimages map[common.Hash][]byte 89 90 // Journal of state modifications. This is the backbone of 91 // Snapshot and RevertToSnapshot. 92 journal *journal 93 validRevisions []revision 94 nextRevisionId int 95 96 // Measurements gathered during execution for debugging purposes 97 AccountReads time.Duration 98 AccountHashes time.Duration 99 AccountUpdates time.Duration 100 AccountCommits time.Duration 101 StorageReads time.Duration 102 StorageHashes time.Duration 103 StorageUpdates time.Duration 104 StorageCommits time.Duration 105 } 106 107 // Create a new state from a given trie. 108 func New(root common.Hash, db Database) (*StateDB, error) { 109 tr, err := db.OpenTrie(root) 110 if err != nil { 111 return nil, err 112 } 113 return &StateDB{ 114 db: db, 115 trie: tr, 116 stateObjects: make(map[common.Address]*stateObject), 117 stateObjectsDirty: make(map[common.Address]struct{}), 118 logs: make(map[common.Hash][]*types.Log), 119 preimages: make(map[common.Hash][]byte), 120 journal: newJournal(), 121 }, nil 122 } 123 124 // setError remembers the first non-nil error it is called with. 125 func (self *StateDB) setError(err error) { 126 if self.dbErr == nil { 127 self.dbErr = err 128 } 129 } 130 131 func (self *StateDB) Error() error { 132 return self.dbErr 133 } 134 135 // Reset clears out all ephemeral state objects from the state db, but keeps 136 // the underlying state trie to avoid reloading data for the next operations. 137 func (self *StateDB) Reset(root common.Hash) error { 138 tr, err := self.db.OpenTrie(root) 139 if err != nil { 140 return err 141 } 142 self.trie = tr 143 self.stateObjects = make(map[common.Address]*stateObject) 144 self.stateObjectsDirty = make(map[common.Address]struct{}) 145 self.thash = common.Hash{} 146 self.bhash = common.Hash{} 147 self.txIndex = 0 148 self.logs = make(map[common.Hash][]*types.Log) 149 self.logSize = 0 150 self.preimages = make(map[common.Hash][]byte) 151 self.clearJournalAndRefund() 152 return nil 153 } 154 155 func (self *StateDB) AddLog(log *types.Log) { 156 self.journal.append(addLogChange{txhash: self.thash}) 157 158 log.TxHash = self.thash 159 log.BlockHash = self.bhash 160 log.TxIndex = uint(self.txIndex) 161 log.Index = self.logSize 162 self.logs[self.thash] = append(self.logs[self.thash], log) 163 self.logSize++ 164 } 165 166 func (self *StateDB) GetLogs(hash common.Hash) []*types.Log { 167 return self.logs[hash] 168 } 169 170 func (self *StateDB) Logs() []*types.Log { 171 var logs []*types.Log 172 for _, lgs := range self.logs { 173 logs = append(logs, lgs...) 174 } 175 return logs 176 } 177 178 // AddPreimage records a SHA3 preimage seen by the VM. 179 func (self *StateDB) AddPreimage(hash common.Hash, preimage []byte) { 180 if _, ok := self.preimages[hash]; !ok { 181 self.journal.append(addPreimageChange{hash: hash}) 182 pi := make([]byte, len(preimage)) 183 copy(pi, preimage) 184 self.preimages[hash] = pi 185 } 186 } 187 188 // Preimages returns a list of SHA3 preimages that have been submitted. 189 func (self *StateDB) Preimages() map[common.Hash][]byte { 190 return self.preimages 191 } 192 193 // AddRefund adds gas to the refund counter 194 func (self *StateDB) AddRefund(gas uint64) { 195 self.journal.append(refundChange{prev: self.refund}) 196 self.refund += gas 197 } 198 199 // SubRefund removes gas from the refund counter. 200 // This method will panic if the refund counter goes below zero 201 func (self *StateDB) SubRefund(gas uint64) { 202 self.journal.append(refundChange{prev: self.refund}) 203 if gas > self.refund { 204 panic("Refund counter below zero") 205 } 206 self.refund -= gas 207 } 208 209 // Exist reports whether the given account address exists in the state. 210 // Notably this also returns true for suicided accounts. 211 func (self *StateDB) Exist(addr common.Address) bool { 212 return self.getStateObject(addr) != nil 213 } 214 215 // Empty returns whether the state object is either non-existent 216 // or empty according to the EIP161 specification (balance = nonce = code = 0) 217 func (self *StateDB) Empty(addr common.Address) bool { 218 so := self.getStateObject(addr) 219 return so == nil || so.empty() 220 } 221 222 // Retrieve the balance from the given address or 0 if object not found 223 func (self *StateDB) GetBalance(addr common.Address) *big.Int { 224 stateObject := self.getStateObject(addr) 225 if stateObject != nil { 226 return stateObject.Balance() 227 } 228 return common.Big0 229 } 230 231 func (self *StateDB) GetNonce(addr common.Address) uint64 { 232 stateObject := self.getStateObject(addr) 233 if stateObject != nil { 234 return stateObject.Nonce() 235 } 236 237 return 0 238 } 239 240 // TxIndex returns the current transaction index set by Prepare. 241 func (self *StateDB) TxIndex() int { 242 return self.txIndex 243 } 244 245 // BlockHash returns the current block hash set by Prepare. 246 func (self *StateDB) BlockHash() common.Hash { 247 return self.bhash 248 } 249 250 func (self *StateDB) GetCode(addr common.Address) []byte { 251 stateObject := self.getStateObject(addr) 252 if stateObject != nil { 253 return stateObject.Code(self.db) 254 } 255 return nil 256 } 257 258 func (self *StateDB) GetCodeSize(addr common.Address) int { 259 stateObject := self.getStateObject(addr) 260 if stateObject == nil { 261 return 0 262 } 263 if stateObject.code != nil { 264 return len(stateObject.code) 265 } 266 size, err := self.db.ContractCodeSize(stateObject.addrHash, common.BytesToHash(stateObject.CodeHash())) 267 if err != nil { 268 self.setError(err) 269 } 270 return size 271 } 272 273 func (self *StateDB) GetCodeHash(addr common.Address) common.Hash { 274 stateObject := self.getStateObject(addr) 275 if stateObject == nil { 276 return common.Hash{} 277 } 278 return common.BytesToHash(stateObject.CodeHash()) 279 } 280 281 // GetState retrieves a value from the given account's storage trie. 282 func (self *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash { 283 stateObject := self.getStateObject(addr) 284 if stateObject != nil { 285 return stateObject.GetState(self.db, hash) 286 } 287 return common.Hash{} 288 } 289 290 // GetProof returns the MerkleProof for a given Account 291 func (self *StateDB) GetProof(a common.Address) ([][]byte, error) { 292 var proof proofList 293 err := self.trie.Prove(crypto.Keccak256(a.Bytes()), 0, &proof) 294 return [][]byte(proof), err 295 } 296 297 // GetProof returns the StorageProof for given key 298 func (self *StateDB) GetStorageProof(a common.Address, key common.Hash) ([][]byte, error) { 299 var proof proofList 300 trie := self.StorageTrie(a) 301 if trie == nil { 302 return proof, errors.New("storage trie for requested address does not exist") 303 } 304 err := trie.Prove(crypto.Keccak256(key.Bytes()), 0, &proof) 305 return [][]byte(proof), err 306 } 307 308 // GetCommittedState retrieves a value from the given account's committed storage trie. 309 func (self *StateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash { 310 stateObject := self.getStateObject(addr) 311 if stateObject != nil { 312 return stateObject.GetCommittedState(self.db, hash) 313 } 314 return common.Hash{} 315 } 316 317 // Database retrieves the low level database supporting the lower level trie ops. 318 func (self *StateDB) Database() Database { 319 return self.db 320 } 321 322 // StorageTrie returns the storage trie of an account. 323 // The return value is a copy and is nil for non-existent accounts. 324 func (self *StateDB) StorageTrie(addr common.Address) Trie { 325 stateObject := self.getStateObject(addr) 326 if stateObject == nil { 327 return nil 328 } 329 cpy := stateObject.deepCopy(self) 330 return cpy.updateTrie(self.db) 331 } 332 333 func (self *StateDB) HasSuicided(addr common.Address) bool { 334 stateObject := self.getStateObject(addr) 335 if stateObject != nil { 336 return stateObject.suicided 337 } 338 return false 339 } 340 341 /* 342 * SETTERS 343 */ 344 345 // AddBalance adds amount to the account associated with addr. 346 func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) { 347 stateObject := self.GetOrNewStateObject(addr) 348 if stateObject != nil { 349 stateObject.AddBalance(amount) 350 } 351 } 352 353 // SubBalance subtracts amount from the account associated with addr. 354 func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) { 355 stateObject := self.GetOrNewStateObject(addr) 356 if stateObject != nil { 357 stateObject.SubBalance(amount) 358 } 359 } 360 361 func (self *StateDB) SetBalance(addr common.Address, amount *big.Int) { 362 stateObject := self.GetOrNewStateObject(addr) 363 if stateObject != nil { 364 stateObject.SetBalance(amount) 365 } 366 } 367 368 func (self *StateDB) SetNonce(addr common.Address, nonce uint64) { 369 stateObject := self.GetOrNewStateObject(addr) 370 if stateObject != nil { 371 stateObject.SetNonce(nonce) 372 } 373 } 374 375 func (self *StateDB) SetCode(addr common.Address, code []byte) { 376 stateObject := self.GetOrNewStateObject(addr) 377 if stateObject != nil { 378 stateObject.SetCode(crypto.Keccak256Hash(code), code) 379 } 380 } 381 382 func (self *StateDB) SetState(addr common.Address, key, value common.Hash) { 383 stateObject := self.GetOrNewStateObject(addr) 384 if stateObject != nil { 385 stateObject.SetState(self.db, key, value) 386 } 387 } 388 389 // SetStorage replaces the entire storage for the specified account with given 390 // storage. This function should only be used for debugging. 391 func (self *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) { 392 stateObject := self.GetOrNewStateObject(addr) 393 if stateObject != nil { 394 stateObject.SetStorage(storage) 395 } 396 } 397 398 // Suicide marks the given account as suicided. 399 // This clears the account balance. 400 // 401 // The account's state object is still available until the state is committed, 402 // getStateObject will return a non-nil account after Suicide. 403 func (self *StateDB) Suicide(addr common.Address) bool { 404 stateObject := self.getStateObject(addr) 405 if stateObject == nil { 406 return false 407 } 408 self.journal.append(suicideChange{ 409 account: &addr, 410 prev: stateObject.suicided, 411 prevbalance: new(big.Int).Set(stateObject.Balance()), 412 }) 413 stateObject.markSuicided() 414 stateObject.data.Balance = new(big.Int) 415 416 return true 417 } 418 419 // 420 // Setting, updating & deleting state object methods. 421 // 422 423 // updateStateObject writes the given object to the trie. 424 func (s *StateDB) updateStateObject(stateObject *stateObject) { 425 // Track the amount of time wasted on updating the account from the trie 426 if metrics.EnabledExpensive { 427 defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) 428 } 429 // Encode the account and update the account trie 430 addr := stateObject.Address() 431 432 data, err := rlp.EncodeToBytes(stateObject) 433 if err != nil { 434 panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err)) 435 } 436 s.setError(s.trie.TryUpdate(addr[:], data)) 437 } 438 439 // deleteStateObject removes the given object from the state trie. 440 func (s *StateDB) deleteStateObject(stateObject *stateObject) { 441 // Track the amount of time wasted on deleting the account from the trie 442 if metrics.EnabledExpensive { 443 defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) 444 } 445 // Delete the account from the trie 446 stateObject.deleted = true 447 448 addr := stateObject.Address() 449 s.setError(s.trie.TryDelete(addr[:])) 450 } 451 452 // Retrieve a state object given by the address. Returns nil if not found. 453 func (s *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) { 454 // Prefer live objects 455 if obj := s.stateObjects[addr]; obj != nil { 456 if obj.deleted { 457 return nil 458 } 459 return obj 460 } 461 // Track the amount of time wasted on loading the object from the database 462 if metrics.EnabledExpensive { 463 defer func(start time.Time) { s.AccountReads += time.Since(start) }(time.Now()) 464 } 465 // Load the object from the database 466 enc, err := s.trie.TryGet(addr[:]) 467 if len(enc) == 0 { 468 s.setError(err) 469 return nil 470 } 471 var data Account 472 if err := rlp.DecodeBytes(enc, &data); err != nil { 473 log.Error("Failed to decode state object", "addr", addr, "err", err) 474 return nil 475 } 476 // Insert into the live set 477 obj := newObject(s, addr, data) 478 s.setStateObject(obj) 479 return obj 480 } 481 482 func (self *StateDB) setStateObject(object *stateObject) { 483 self.stateObjects[object.Address()] = object 484 } 485 486 // Retrieve a state object or create a new state object if nil. 487 func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { 488 stateObject := self.getStateObject(addr) 489 if stateObject == nil || stateObject.deleted { 490 stateObject, _ = self.createObject(addr) 491 } 492 return stateObject 493 } 494 495 // createObject creates a new state object. If there is an existing account with 496 // the given address, it is overwritten and returned as the second return value. 497 func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { 498 prev = self.getStateObject(addr) 499 newobj = newObject(self, addr, Account{}) 500 newobj.setNonce(0) // sets the object to dirty 501 if prev == nil { 502 self.journal.append(createObjectChange{account: &addr}) 503 } else { 504 self.journal.append(resetObjectChange{prev: prev}) 505 } 506 self.setStateObject(newobj) 507 return newobj, prev 508 } 509 510 // CreateAccount explicitly creates a state object. If a state object with the address 511 // already exists the balance is carried over to the new account. 512 // 513 // CreateAccount is called during the EVM CREATE operation. The situation might arise that 514 // a contract does the following: 515 // 516 // 1. sends funds to sha(account ++ (nonce + 1)) 517 // 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) 518 // 519 // Carrying over the balance ensures that Ether doesn't disappear. 520 func (self *StateDB) CreateAccount(addr common.Address) { 521 newObj, prev := self.createObject(addr) 522 if prev != nil { 523 newObj.setBalance(prev.data.Balance) 524 } 525 } 526 527 func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error { 528 so := db.getStateObject(addr) 529 if so == nil { 530 return nil 531 } 532 it := trie.NewIterator(so.getTrie(db.db).NodeIterator(nil)) 533 534 for it.Next() { 535 key := common.BytesToHash(db.trie.GetKey(it.Key)) 536 if value, dirty := so.dirtyStorage[key]; dirty { 537 if !cb(key, value) { 538 return nil 539 } 540 continue 541 } 542 543 if len(it.Value) > 0 { 544 _, content, _, err := rlp.Split(it.Value) 545 if err != nil { 546 return err 547 } 548 if !cb(key, common.BytesToHash(content)) { 549 return nil 550 } 551 } 552 } 553 return nil 554 } 555 556 // Copy creates a deep, independent copy of the state. 557 // Snapshots of the copied state cannot be applied to the copy. 558 func (self *StateDB) Copy() *StateDB { 559 // Copy all the basic fields, initialize the memory ones 560 state := &StateDB{ 561 db: self.db, 562 trie: self.db.CopyTrie(self.trie), 563 stateObjects: make(map[common.Address]*stateObject, len(self.journal.dirties)), 564 stateObjectsDirty: make(map[common.Address]struct{}, len(self.journal.dirties)), 565 refund: self.refund, 566 logs: make(map[common.Hash][]*types.Log, len(self.logs)), 567 logSize: self.logSize, 568 preimages: make(map[common.Hash][]byte, len(self.preimages)), 569 journal: newJournal(), 570 } 571 // Copy the dirty states, logs, and preimages 572 for addr := range self.journal.dirties { 573 // As documented [here](https://github.com/ethereum/go-ethereum/pull/16485#issuecomment-380438527), 574 // and in the Finalise-method, there is a case where an object is in the journal but not 575 // in the stateObjects: OOG after touch on ripeMD prior to Byzantium. Thus, we need to check for 576 // nil 577 if object, exist := self.stateObjects[addr]; exist { 578 state.stateObjects[addr] = object.deepCopy(state) 579 state.stateObjectsDirty[addr] = struct{}{} 580 } 581 } 582 // Above, we don't copy the actual journal. This means that if the copy is copied, the 583 // loop above will be a no-op, since the copy's journal is empty. 584 // Thus, here we iterate over stateObjects, to enable copies of copies 585 for addr := range self.stateObjectsDirty { 586 if _, exist := state.stateObjects[addr]; !exist { 587 state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state) 588 state.stateObjectsDirty[addr] = struct{}{} 589 } 590 } 591 for hash, logs := range self.logs { 592 cpy := make([]*types.Log, len(logs)) 593 for i, l := range logs { 594 cpy[i] = new(types.Log) 595 *cpy[i] = *l 596 } 597 state.logs[hash] = cpy 598 } 599 for hash, preimage := range self.preimages { 600 state.preimages[hash] = preimage 601 } 602 return state 603 } 604 605 // Snapshot returns an identifier for the current revision of the state. 606 func (self *StateDB) Snapshot() int { 607 id := self.nextRevisionId 608 self.nextRevisionId++ 609 self.validRevisions = append(self.validRevisions, revision{id, self.journal.length()}) 610 return id 611 } 612 613 // RevertToSnapshot reverts all state changes made since the given revision. 614 func (self *StateDB) RevertToSnapshot(revid int) { 615 // Find the snapshot in the stack of valid snapshots. 616 idx := sort.Search(len(self.validRevisions), func(i int) bool { 617 return self.validRevisions[i].id >= revid 618 }) 619 if idx == len(self.validRevisions) || self.validRevisions[idx].id != revid { 620 panic(fmt.Errorf("revision id %v cannot be reverted", revid)) 621 } 622 snapshot := self.validRevisions[idx].journalIndex 623 624 // Replay the journal to undo changes and remove invalidated snapshots 625 self.journal.revert(self, snapshot) 626 self.validRevisions = self.validRevisions[:idx] 627 } 628 629 // GetRefund returns the current value of the refund counter. 630 func (self *StateDB) GetRefund() uint64 { 631 return self.refund 632 } 633 634 // Finalise finalises the state by removing the self destructed objects 635 // and clears the journal as well as the refunds. 636 func (s *StateDB) Finalise(deleteEmptyObjects bool) { 637 for addr := range s.journal.dirties { 638 stateObject, exist := s.stateObjects[addr] 639 if !exist { 640 // ripeMD is 'touched' at block 1714175, in tx 0x1237f737031e40bcde4a8b7e717b2d15e3ecadfe49bb1bbc71ee9deb09c6fcf2 641 // That tx goes out of gas, and although the notion of 'touched' does not exist there, the 642 // touch-event will still be recorded in the journal. Since ripeMD is a special snowflake, 643 // it will persist in the journal even though the journal is reverted. In this special circumstance, 644 // it may exist in `s.journal.dirties` but not in `s.stateObjects`. 645 // Thus, we can safely ignore it here 646 continue 647 } 648 649 if stateObject.suicided || (deleteEmptyObjects && stateObject.empty()) { 650 s.deleteStateObject(stateObject) 651 } else { 652 stateObject.updateRoot(s.db) 653 s.updateStateObject(stateObject) 654 } 655 s.stateObjectsDirty[addr] = struct{}{} 656 } 657 // Invalidate journal because reverting across transactions is not allowed. 658 s.clearJournalAndRefund() 659 } 660 661 // IntermediateRoot computes the current root hash of the state trie. 662 // It is called in between transactions to get the root hash that 663 // goes into transaction receipts. 664 func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { 665 s.Finalise(deleteEmptyObjects) 666 667 // Track the amount of time wasted on hashing the account trie 668 if metrics.EnabledExpensive { 669 defer func(start time.Time) { s.AccountHashes += time.Since(start) }(time.Now()) 670 } 671 return s.trie.Hash() 672 } 673 674 // Prepare sets the current transaction hash and index and block hash which is 675 // used when the EVM emits new state logs. 676 func (self *StateDB) Prepare(thash, bhash common.Hash, ti int) { 677 self.thash = thash 678 self.bhash = bhash 679 self.txIndex = ti 680 } 681 682 func (s *StateDB) clearJournalAndRefund() { 683 s.journal = newJournal() 684 s.validRevisions = s.validRevisions[:0] 685 s.refund = 0 686 } 687 688 // Commit writes the state to the underlying in-memory trie database. 689 func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) { 690 defer s.clearJournalAndRefund() 691 692 for addr := range s.journal.dirties { 693 s.stateObjectsDirty[addr] = struct{}{} 694 } 695 // Commit objects to the trie, measuring the elapsed time 696 for addr, stateObject := range s.stateObjects { 697 _, isDirty := s.stateObjectsDirty[addr] 698 switch { 699 case stateObject.suicided || (isDirty && deleteEmptyObjects && stateObject.empty()): 700 // If the object has been removed, don't bother syncing it 701 // and just mark it for deletion in the trie. 702 s.deleteStateObject(stateObject) 703 case isDirty: 704 // Write any contract code associated with the state object 705 if stateObject.code != nil && stateObject.dirtyCode { 706 s.db.TrieDB().InsertBlob(common.BytesToHash(stateObject.CodeHash()), stateObject.code) 707 stateObject.dirtyCode = false 708 } 709 // Write any storage changes in the state object to its storage trie. 710 if err := stateObject.CommitTrie(s.db); err != nil { 711 return common.Hash{}, err 712 } 713 // Update the object in the main account trie. 714 s.updateStateObject(stateObject) 715 } 716 delete(s.stateObjectsDirty, addr) 717 } 718 // Write the account trie changes, measuing the amount of wasted time 719 if metrics.EnabledExpensive { 720 defer func(start time.Time) { s.AccountCommits += time.Since(start) }(time.Now()) 721 } 722 root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error { 723 var account Account 724 if err := rlp.DecodeBytes(leaf, &account); err != nil { 725 return nil 726 } 727 if account.Root != emptyRoot { 728 s.db.TrieDB().Reference(account.Root, parent) 729 } 730 code := common.BytesToHash(account.CodeHash) 731 if code != emptyCode { 732 s.db.TrieDB().Reference(code, parent) 733 } 734 return nil 735 }) 736 return root, err 737 }