github.com/newbtp/btp@v0.0.0-20190709081714-e4aafa07224e/core/state/statedb.go (about) 1 // Copyright 2014 The go-btpereum Authors 2 // This file is part of the go-btpereum library. 3 // 4 // The go-btpereum 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-btpereum 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-btpereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package state provides a caching layer atop the btpereum state trie. 18 package state 19 20 import ( 21 "errors" 22 "fmt" 23 "math/big" 24 "sort" 25 "time" 26 27 "github.com/btpereum/go-btpereum/common" 28 "github.com/btpereum/go-btpereum/core/types" 29 "github.com/btpereum/go-btpereum/crypto" 30 "github.com/btpereum/go-btpereum/log" 31 "github.com/btpereum/go-btpereum/metrics" 32 "github.com/btpereum/go-btpereum/rlp" 33 "github.com/btpereum/go-btpereum/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 btpereum 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 mbtpod 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 whbtper 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 whbtper 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 // Suicide marks the given account as suicided. 390 // This clears the account balance. 391 // 392 // The account's state object is still available until the state is committed, 393 // getStateObject will return a non-nil account after Suicide. 394 func (self *StateDB) Suicide(addr common.Address) bool { 395 stateObject := self.getStateObject(addr) 396 if stateObject == nil { 397 return false 398 } 399 self.journal.append(suicideChange{ 400 account: &addr, 401 prev: stateObject.suicided, 402 prevbalance: new(big.Int).Set(stateObject.Balance()), 403 }) 404 stateObject.markSuicided() 405 stateObject.data.Balance = new(big.Int) 406 407 return true 408 } 409 410 // 411 // Setting, updating & deleting state object mbtpods. 412 // 413 414 // updateStateObject writes the given object to the trie. 415 func (s *StateDB) updateStateObject(stateObject *stateObject) { 416 // Track the amount of time wasted on updating the account from the trie 417 if metrics.EnabledExpensive { 418 defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) 419 } 420 // Encode the account and update the account trie 421 addr := stateObject.Address() 422 423 data, err := rlp.EncodeToBytes(stateObject) 424 if err != nil { 425 panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err)) 426 } 427 s.setError(s.trie.TryUpdate(addr[:], data)) 428 } 429 430 // deleteStateObject removes the given object from the state trie. 431 func (s *StateDB) deleteStateObject(stateObject *stateObject) { 432 // Track the amount of time wasted on deleting the account from the trie 433 if metrics.EnabledExpensive { 434 defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) 435 } 436 // Delete the account from the trie 437 stateObject.deleted = true 438 439 addr := stateObject.Address() 440 s.setError(s.trie.TryDelete(addr[:])) 441 } 442 443 // Retrieve a state object given by the address. Returns nil if not found. 444 func (s *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) { 445 // Prefer live objects 446 if obj := s.stateObjects[addr]; obj != nil { 447 if obj.deleted { 448 return nil 449 } 450 return obj 451 } 452 // Track the amount of time wasted on loading the object from the database 453 if metrics.EnabledExpensive { 454 defer func(start time.Time) { s.AccountReads += time.Since(start) }(time.Now()) 455 } 456 // Load the object from the database 457 enc, err := s.trie.TryGet(addr[:]) 458 if len(enc) == 0 { 459 s.setError(err) 460 return nil 461 } 462 var data Account 463 if err := rlp.DecodeBytes(enc, &data); err != nil { 464 log.Error("Failed to decode state object", "addr", addr, "err", err) 465 return nil 466 } 467 // Insert into the live set 468 obj := newObject(s, addr, data) 469 s.setStateObject(obj) 470 return obj 471 } 472 473 func (self *StateDB) setStateObject(object *stateObject) { 474 self.stateObjects[object.Address()] = object 475 } 476 477 // Retrieve a state object or create a new state object if nil. 478 func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { 479 stateObject := self.getStateObject(addr) 480 if stateObject == nil || stateObject.deleted { 481 stateObject, _ = self.createObject(addr) 482 } 483 return stateObject 484 } 485 486 // createObject creates a new state object. If there is an existing account with 487 // the given address, it is overwritten and returned as the second return value. 488 func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { 489 prev = self.getStateObject(addr) 490 newobj = newObject(self, addr, Account{}) 491 newobj.setNonce(0) // sets the object to dirty 492 if prev == nil { 493 self.journal.append(createObjectChange{account: &addr}) 494 } else { 495 self.journal.append(resetObjectChange{prev: prev}) 496 } 497 self.setStateObject(newobj) 498 return newobj, prev 499 } 500 501 // CreateAccount explicitly creates a state object. If a state object with the address 502 // already exists the balance is carried over to the new account. 503 // 504 // CreateAccount is called during the EVM CREATE operation. The situation might arise that 505 // a contract does the following: 506 // 507 // 1. sends funds to sha(account ++ (nonce + 1)) 508 // 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) 509 // 510 // Carrying over the balance ensures that btper doesn't disappear. 511 func (self *StateDB) CreateAccount(addr common.Address) { 512 newObj, prev := self.createObject(addr) 513 if prev != nil { 514 newObj.setBalance(prev.data.Balance) 515 } 516 } 517 518 func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error { 519 so := db.getStateObject(addr) 520 if so == nil { 521 return nil 522 } 523 it := trie.NewIterator(so.getTrie(db.db).NodeIterator(nil)) 524 525 for it.Next() { 526 key := common.BytesToHash(db.trie.GetKey(it.Key)) 527 if value, dirty := so.dirtyStorage[key]; dirty { 528 if !cb(key, value) { 529 return nil 530 } 531 continue 532 } 533 534 if len(it.Value) > 0 { 535 _, content, _, err := rlp.Split(it.Value) 536 if err != nil { 537 return err 538 } 539 if !cb(key, common.BytesToHash(content)) { 540 return nil 541 } 542 } 543 } 544 return nil 545 } 546 547 // Copy creates a deep, independent copy of the state. 548 // Snapshots of the copied state cannot be applied to the copy. 549 func (self *StateDB) Copy() *StateDB { 550 // Copy all the basic fields, initialize the memory ones 551 state := &StateDB{ 552 db: self.db, 553 trie: self.db.CopyTrie(self.trie), 554 stateObjects: make(map[common.Address]*stateObject, len(self.journal.dirties)), 555 stateObjectsDirty: make(map[common.Address]struct{}, len(self.journal.dirties)), 556 refund: self.refund, 557 logs: make(map[common.Hash][]*types.Log, len(self.logs)), 558 logSize: self.logSize, 559 preimages: make(map[common.Hash][]byte, len(self.preimages)), 560 journal: newJournal(), 561 } 562 // Copy the dirty states, logs, and preimages 563 for addr := range self.journal.dirties { 564 // As documented [here](https://github.com/btpereum/go-btpereum/pull/16485#issuecomment-380438527), 565 // and in the Finalise-mbtpod, there is a case where an object is in the journal but not 566 // in the stateObjects: OOG after touch on ripeMD prior to Byzantium. Thus, we need to check for 567 // nil 568 if object, exist := self.stateObjects[addr]; exist { 569 state.stateObjects[addr] = object.deepCopy(state) 570 state.stateObjectsDirty[addr] = struct{}{} 571 } 572 } 573 // Above, we don't copy the actual journal. This means that if the copy is copied, the 574 // loop above will be a no-op, since the copy's journal is empty. 575 // Thus, here we iterate over stateObjects, to enable copies of copies 576 for addr := range self.stateObjectsDirty { 577 if _, exist := state.stateObjects[addr]; !exist { 578 state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state) 579 state.stateObjectsDirty[addr] = struct{}{} 580 } 581 } 582 for hash, logs := range self.logs { 583 cpy := make([]*types.Log, len(logs)) 584 for i, l := range logs { 585 cpy[i] = new(types.Log) 586 *cpy[i] = *l 587 } 588 state.logs[hash] = cpy 589 } 590 for hash, preimage := range self.preimages { 591 state.preimages[hash] = preimage 592 } 593 return state 594 } 595 596 // Snapshot returns an identifier for the current revision of the state. 597 func (self *StateDB) Snapshot() int { 598 id := self.nextRevisionId 599 self.nextRevisionId++ 600 self.validRevisions = append(self.validRevisions, revision{id, self.journal.length()}) 601 return id 602 } 603 604 // RevertToSnapshot reverts all state changes made since the given revision. 605 func (self *StateDB) RevertToSnapshot(revid int) { 606 // Find the snapshot in the stack of valid snapshots. 607 idx := sort.Search(len(self.validRevisions), func(i int) bool { 608 return self.validRevisions[i].id >= revid 609 }) 610 if idx == len(self.validRevisions) || self.validRevisions[idx].id != revid { 611 panic(fmt.Errorf("revision id %v cannot be reverted", revid)) 612 } 613 snapshot := self.validRevisions[idx].journalIndex 614 615 // Replay the journal to undo changes and remove invalidated snapshots 616 self.journal.revert(self, snapshot) 617 self.validRevisions = self.validRevisions[:idx] 618 } 619 620 // GetRefund returns the current value of the refund counter. 621 func (self *StateDB) GetRefund() uint64 { 622 return self.refund 623 } 624 625 // Finalise finalises the state by removing the self destructed objects 626 // and clears the journal as well as the refunds. 627 func (s *StateDB) Finalise(deleteEmptyObjects bool) { 628 for addr := range s.journal.dirties { 629 stateObject, exist := s.stateObjects[addr] 630 if !exist { 631 // ripeMD is 'touched' at block 1714175, in tx 0x1237f737031e40bcde4a8b7e717b2d15e3ecadfe49bb1bbc71ee9deb09c6fcf2 632 // That tx goes out of gas, and although the notion of 'touched' does not exist there, the 633 // touch-event will still be recorded in the journal. Since ripeMD is a special snowflake, 634 // it will persist in the journal even though the journal is reverted. In this special circumstance, 635 // it may exist in `s.journal.dirties` but not in `s.stateObjects`. 636 // Thus, we can safely ignore it here 637 continue 638 } 639 640 if stateObject.suicided || (deleteEmptyObjects && stateObject.empty()) { 641 s.deleteStateObject(stateObject) 642 } else { 643 stateObject.updateRoot(s.db) 644 s.updateStateObject(stateObject) 645 } 646 s.stateObjectsDirty[addr] = struct{}{} 647 } 648 // Invalidate journal because reverting across transactions is not allowed. 649 s.clearJournalAndRefund() 650 } 651 652 // IntermediateRoot computes the current root hash of the state trie. 653 // It is called in between transactions to get the root hash that 654 // goes into transaction receipts. 655 func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { 656 s.Finalise(deleteEmptyObjects) 657 658 // Track the amount of time wasted on hashing the account trie 659 if metrics.EnabledExpensive { 660 defer func(start time.Time) { s.AccountHashes += time.Since(start) }(time.Now()) 661 } 662 return s.trie.Hash() 663 } 664 665 // Prepare sets the current transaction hash and index and block hash which is 666 // used when the EVM emits new state logs. 667 func (self *StateDB) Prepare(thash, bhash common.Hash, ti int) { 668 self.thash = thash 669 self.bhash = bhash 670 self.txIndex = ti 671 } 672 673 func (s *StateDB) clearJournalAndRefund() { 674 s.journal = newJournal() 675 s.validRevisions = s.validRevisions[:0] 676 s.refund = 0 677 } 678 679 // Commit writes the state to the underlying in-memory trie database. 680 func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) { 681 defer s.clearJournalAndRefund() 682 683 for addr := range s.journal.dirties { 684 s.stateObjectsDirty[addr] = struct{}{} 685 } 686 // Commit objects to the trie, measuring the elapsed time 687 for addr, stateObject := range s.stateObjects { 688 _, isDirty := s.stateObjectsDirty[addr] 689 switch { 690 case stateObject.suicided || (isDirty && deleteEmptyObjects && stateObject.empty()): 691 // If the object has been removed, don't bother syncing it 692 // and just mark it for deletion in the trie. 693 s.deleteStateObject(stateObject) 694 case isDirty: 695 // Write any contract code associated with the state object 696 if stateObject.code != nil && stateObject.dirtyCode { 697 s.db.TrieDB().InsertBlob(common.BytesToHash(stateObject.CodeHash()), stateObject.code) 698 stateObject.dirtyCode = false 699 } 700 // Write any storage changes in the state object to its storage trie. 701 if err := stateObject.CommitTrie(s.db); err != nil { 702 return common.Hash{}, err 703 } 704 // Update the object in the main account trie. 705 s.updateStateObject(stateObject) 706 } 707 delete(s.stateObjectsDirty, addr) 708 } 709 // Write the account trie changes, measuing the amount of wasted time 710 if metrics.EnabledExpensive { 711 defer func(start time.Time) { s.AccountCommits += time.Since(start) }(time.Now()) 712 } 713 root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error { 714 var account Account 715 if err := rlp.DecodeBytes(leaf, &account); err != nil { 716 return nil 717 } 718 if account.Root != emptyRoot { 719 s.db.TrieDB().Reference(account.Root, parent) 720 } 721 code := common.BytesToHash(account.CodeHash) 722 if code != emptyCode { 723 s.db.TrieDB().Reference(code, parent) 724 } 725 return nil 726 }) 727 return root, err 728 }