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