github.com/ethereum/go-ethereum@v1.16.1/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 "maps" 23 "slices" 24 "time" 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/trienode" 32 "github.com/holiman/uint256" 33 ) 34 35 type Storage map[common.Hash]common.Hash 36 37 func (s Storage) Copy() Storage { 38 return maps.Clone(s) 39 } 40 41 // stateObject represents an Ethereum account which is being modified. 42 // 43 // The usage pattern is as follows: 44 // - First you need to obtain a state object. 45 // - Account values as well as storages can be accessed and modified through the object. 46 // - Finally, call commit to return the changes of storage trie and update account data. 47 type stateObject struct { 48 db *StateDB 49 address common.Address // address of ethereum account 50 addrHash common.Hash // hash of ethereum address of the account 51 origin *types.StateAccount // Account original data without any change applied, nil means it was not existent 52 data types.StateAccount // Account data with all mutations applied in the scope of block 53 54 // Write caches. 55 trie Trie // storage trie, which becomes non-nil on first access 56 code []byte // contract bytecode, which gets set when code is loaded 57 58 originStorage Storage // Storage entries that have been accessed within the current block 59 dirtyStorage Storage // Storage entries that have been modified within the current transaction 60 pendingStorage Storage // Storage entries that have been modified within the current block 61 62 // uncommittedStorage tracks a set of storage entries that have been modified 63 // but not yet committed since the "last commit operation", along with their 64 // original values before mutation. 65 // 66 // Specifically, the commit will be performed after each transaction before 67 // the byzantium fork, therefore the map is already reset at the transaction 68 // boundary; however post the byzantium fork, the commit will only be performed 69 // at the end of block, this set essentially tracks all the modifications 70 // made within the block. 71 uncommittedStorage Storage 72 73 // Cache flags. 74 dirtyCode bool // true if the code was updated 75 76 // Flag whether the account was marked as self-destructed. The self-destructed 77 // account is still accessible in the scope of same transaction. 78 selfDestructed bool 79 80 // This is an EIP-6780 flag indicating whether the object is eligible for 81 // self-destruct according to EIP-6780. The flag could be set either when 82 // the contract is just created within the current transaction, or when the 83 // object was previously existent and is being deployed as a contract within 84 // the current transaction. 85 newContract bool 86 } 87 88 // empty returns whether the account is considered empty. 89 func (s *stateObject) empty() bool { 90 return s.data.Nonce == 0 && s.data.Balance.IsZero() && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes()) 91 } 92 93 // newObject creates a state object. 94 func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *stateObject { 95 origin := acct 96 if acct == nil { 97 acct = types.NewEmptyStateAccount() 98 } 99 return &stateObject{ 100 db: db, 101 address: address, 102 addrHash: crypto.Keccak256Hash(address[:]), 103 origin: origin, 104 data: *acct, 105 originStorage: make(Storage), 106 dirtyStorage: make(Storage), 107 pendingStorage: make(Storage), 108 uncommittedStorage: make(Storage), 109 } 110 } 111 112 func (s *stateObject) markSelfdestructed() { 113 s.selfDestructed = true 114 } 115 116 func (s *stateObject) touch() { 117 s.db.journal.touchChange(s.address) 118 } 119 120 // getTrie returns the associated storage trie. The trie will be opened if it's 121 // not loaded previously. An error will be returned if trie can't be loaded. 122 // 123 // If a new trie is opened, it will be cached within the state object to allow 124 // subsequent reads to expand the same trie instead of reloading from disk. 125 func (s *stateObject) getTrie() (Trie, error) { 126 if s.trie == nil { 127 // Assumes the primary account trie is already loaded 128 tr, err := s.db.db.OpenStorageTrie(s.db.originalRoot, s.address, s.data.Root, s.db.trie) 129 if err != nil { 130 return nil, err 131 } 132 s.trie = tr 133 } 134 return s.trie, nil 135 } 136 137 // getPrefetchedTrie returns the associated trie, as populated by the prefetcher 138 // if it's available. 139 // 140 // Note, opposed to getTrie, this method will *NOT* blindly cache the resulting 141 // trie in the state object. The caller might want to do that, but it's cleaner 142 // to break the hidden interdependency between retrieving tries from the db or 143 // from the prefetcher. 144 func (s *stateObject) getPrefetchedTrie() Trie { 145 // If there's nothing to meaningfully return, let the user figure it out by 146 // pulling the trie from disk. 147 if (s.data.Root == types.EmptyRootHash && !s.db.db.TrieDB().IsVerkle()) || s.db.prefetcher == nil { 148 return nil 149 } 150 // Attempt to retrieve the trie from the prefetcher 151 return s.db.prefetcher.trie(s.addrHash, s.data.Root) 152 } 153 154 // GetState retrieves a value associated with the given storage key. 155 func (s *stateObject) GetState(key common.Hash) common.Hash { 156 value, _ := s.getState(key) 157 return value 158 } 159 160 // getState retrieves a value associated with the given storage key, along with 161 // its original value. 162 func (s *stateObject) getState(key common.Hash) (common.Hash, common.Hash) { 163 origin := s.GetCommittedState(key) 164 value, dirty := s.dirtyStorage[key] 165 if dirty { 166 return value, origin 167 } 168 return origin, origin 169 } 170 171 // GetCommittedState retrieves the value associated with the specific key 172 // without any mutations caused in the current execution. 173 func (s *stateObject) GetCommittedState(key common.Hash) common.Hash { 174 // If we have a pending write or clean cached, return that 175 if value, pending := s.pendingStorage[key]; pending { 176 return value 177 } 178 if value, cached := s.originStorage[key]; cached { 179 return value 180 } 181 // If the object was destructed in *this* block (and potentially resurrected), 182 // the storage has been cleared out, and we should *not* consult the previous 183 // database about any storage values. The only possible alternatives are: 184 // 1) resurrect happened, and new slot values were set -- those should 185 // have been handles via pendingStorage above. 186 // 2) we don't have new values, and can deliver empty response back 187 if _, destructed := s.db.stateObjectsDestruct[s.address]; destructed { 188 s.originStorage[key] = common.Hash{} // track the empty slot as origin value 189 return common.Hash{} 190 } 191 s.db.StorageLoaded++ 192 193 start := time.Now() 194 value, err := s.db.reader.Storage(s.address, key) 195 if err != nil { 196 s.db.setError(err) 197 return common.Hash{} 198 } 199 s.db.StorageReads += time.Since(start) 200 201 // Schedule the resolved storage slots for prefetching if it's enabled. 202 if s.db.prefetcher != nil && s.data.Root != types.EmptyRootHash { 203 if err = s.db.prefetcher.prefetch(s.addrHash, s.origin.Root, s.address, nil, []common.Hash{key}, true); err != nil { 204 log.Error("Failed to prefetch storage slot", "addr", s.address, "key", key, "err", err) 205 } 206 } 207 s.originStorage[key] = value 208 return value 209 } 210 211 // SetState updates a value in account storage. 212 // It returns the previous value 213 func (s *stateObject) SetState(key, value common.Hash) common.Hash { 214 // If the new value is the same as old, don't set. Otherwise, track only the 215 // dirty changes, supporting reverting all of it back to no change. 216 prev, origin := s.getState(key) 217 if prev == value { 218 return prev 219 } 220 // New value is different, update and journal the change 221 s.db.journal.storageChange(s.address, key, prev, origin) 222 s.setState(key, value, origin) 223 return prev 224 } 225 226 // setState updates a value in account dirty storage. The dirtiness will be 227 // removed if the value being set equals to the original value. 228 func (s *stateObject) setState(key common.Hash, value common.Hash, origin common.Hash) { 229 // Storage slot is set back to its original value, undo the dirty marker 230 if value == origin { 231 delete(s.dirtyStorage, key) 232 return 233 } 234 s.dirtyStorage[key] = value 235 } 236 237 // finalise moves all dirty storage slots into the pending area to be hashed or 238 // committed later. It is invoked at the end of every transaction. 239 func (s *stateObject) finalise() { 240 slotsToPrefetch := make([]common.Hash, 0, len(s.dirtyStorage)) 241 for key, value := range s.dirtyStorage { 242 if origin, exist := s.uncommittedStorage[key]; exist && origin == value { 243 // The slot is reverted to its original value, delete the entry 244 // to avoid thrashing the data structures. 245 delete(s.uncommittedStorage, key) 246 } else if exist { 247 // The slot is modified to another value and the slot has been 248 // tracked for commit, do nothing here. 249 } else { 250 // The slot is different from its original value and hasn't been 251 // tracked for commit yet. 252 s.uncommittedStorage[key] = s.GetCommittedState(key) 253 slotsToPrefetch = append(slotsToPrefetch, key) // Copy needed for closure 254 } 255 // Aggregate the dirty storage slots into the pending area. It might 256 // be possible that the value of tracked slot here is same with the 257 // one in originStorage (e.g. the slot was modified in tx_a and then 258 // modified back in tx_b). We can't blindly remove it from pending 259 // map as the dirty slot might have been committed already (before the 260 // byzantium fork) and entry is necessary to modify the value back. 261 s.pendingStorage[key] = value 262 } 263 if s.db.prefetcher != nil && len(slotsToPrefetch) > 0 && s.data.Root != types.EmptyRootHash { 264 if err := s.db.prefetcher.prefetch(s.addrHash, s.data.Root, s.address, nil, slotsToPrefetch, false); err != nil { 265 log.Error("Failed to prefetch slots", "addr", s.address, "slots", len(slotsToPrefetch), "err", err) 266 } 267 } 268 if len(s.dirtyStorage) > 0 { 269 s.dirtyStorage = make(Storage) 270 } 271 // Revoke the flag at the end of the transaction. It finalizes the status 272 // of the newly-created object as it's no longer eligible for self-destruct 273 // by EIP-6780. For non-newly-created objects, it's a no-op. 274 s.newContract = false 275 } 276 277 // updateTrie is responsible for persisting cached storage changes into the 278 // object's storage trie. In case the storage trie is not yet loaded, this 279 // function will load the trie automatically. If any issues arise during the 280 // loading or updating of the trie, an error will be returned. Furthermore, 281 // this function will return the mutated storage trie, or nil if there is no 282 // storage change at all. 283 // 284 // It assumes all the dirty storage slots have been finalized before. 285 func (s *stateObject) updateTrie() (Trie, error) { 286 // Short circuit if nothing was accessed, don't trigger a prefetcher warning 287 if len(s.uncommittedStorage) == 0 { 288 // Nothing was written, so we could stop early. Unless we have both reads 289 // and witness collection enabled, in which case we need to fetch the trie. 290 if s.db.witness == nil || len(s.originStorage) == 0 { 291 return s.trie, nil 292 } 293 } 294 // Retrieve a pretecher populated trie, or fall back to the database. This will 295 // block until all prefetch tasks are done, which are needed for witnesses even 296 // for unmodified state objects. 297 tr := s.getPrefetchedTrie() 298 if tr != nil { 299 // Prefetcher returned a live trie, swap it out for the current one 300 s.trie = tr 301 } else { 302 // Fetcher not running or empty trie, fallback to the database trie 303 var err error 304 tr, err = s.getTrie() 305 if err != nil { 306 s.db.setError(err) 307 return nil, err 308 } 309 } 310 // Short circuit if nothing changed, don't bother with hashing anything 311 if len(s.uncommittedStorage) == 0 { 312 return s.trie, nil 313 } 314 // Perform trie updates before deletions. This prevents resolution of unnecessary trie nodes 315 // in circumstances similar to the following: 316 // 317 // Consider nodes `A` and `B` who share the same full node parent `P` and have no other siblings. 318 // During the execution of a block: 319 // - `A` is deleted, 320 // - `C` is created, and also shares the parent `P`. 321 // If the deletion is handled first, then `P` would be left with only one child, thus collapsed 322 // into a shortnode. This requires `B` to be resolved from disk. 323 // Whereas if the created node is handled first, then the collapse is avoided, and `B` is not resolved. 324 var ( 325 deletions []common.Hash 326 used = make([]common.Hash, 0, len(s.uncommittedStorage)) 327 ) 328 for key, origin := range s.uncommittedStorage { 329 // Skip noop changes, persist actual changes 330 value, exist := s.pendingStorage[key] 331 if value == origin { 332 log.Error("Storage update was noop", "address", s.address, "slot", key) 333 continue 334 } 335 if !exist { 336 log.Error("Storage slot is not found in pending area", s.address, "slot", key) 337 continue 338 } 339 if (value != common.Hash{}) { 340 if err := tr.UpdateStorage(s.address, key[:], common.TrimLeftZeroes(value[:])); err != nil { 341 s.db.setError(err) 342 return nil, err 343 } 344 s.db.StorageUpdated.Add(1) 345 } else { 346 deletions = append(deletions, key) 347 } 348 // Cache the items for preloading 349 used = append(used, key) // Copy needed for closure 350 } 351 for _, key := range deletions { 352 if err := tr.DeleteStorage(s.address, key[:]); err != nil { 353 s.db.setError(err) 354 return nil, err 355 } 356 s.db.StorageDeleted.Add(1) 357 } 358 if s.db.prefetcher != nil { 359 s.db.prefetcher.used(s.addrHash, s.data.Root, nil, used) 360 } 361 s.uncommittedStorage = make(Storage) // empties the commit markers 362 return tr, nil 363 } 364 365 // updateRoot flushes all cached storage mutations to trie, recalculating the 366 // new storage trie root. 367 func (s *stateObject) updateRoot() { 368 // Flush cached storage mutations into trie, short circuit if any error 369 // is occurred or there is no change in the trie. 370 tr, err := s.updateTrie() 371 if err != nil || tr == nil { 372 return 373 } 374 s.data.Root = tr.Hash() 375 } 376 377 // commitStorage overwrites the clean storage with the storage changes and 378 // fulfills the storage diffs into the given accountUpdate struct. 379 func (s *stateObject) commitStorage(op *accountUpdate) { 380 var ( 381 encode = func(val common.Hash) []byte { 382 if val == (common.Hash{}) { 383 return nil 384 } 385 blob, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(val[:])) 386 return blob 387 } 388 ) 389 for key, val := range s.pendingStorage { 390 // Skip the noop storage changes, it might be possible the value 391 // of tracked slot is same in originStorage and pendingStorage 392 // map, e.g. the storage slot is modified in tx_a and then reset 393 // back in tx_b. 394 if val == s.originStorage[key] { 395 continue 396 } 397 hash := crypto.Keccak256Hash(key[:]) 398 if op.storages == nil { 399 op.storages = make(map[common.Hash][]byte) 400 } 401 op.storages[hash] = encode(val) 402 403 if op.storagesOriginByKey == nil { 404 op.storagesOriginByKey = make(map[common.Hash][]byte) 405 } 406 if op.storagesOriginByHash == nil { 407 op.storagesOriginByHash = make(map[common.Hash][]byte) 408 } 409 origin := encode(s.originStorage[key]) 410 op.storagesOriginByKey[key] = origin 411 op.storagesOriginByHash[hash] = origin 412 413 // Overwrite the clean value of storage slots 414 s.originStorage[key] = val 415 } 416 s.pendingStorage = make(Storage) 417 } 418 419 // commit obtains the account changes (metadata, storage slots, code) caused by 420 // state execution along with the dirty storage trie nodes. 421 // 422 // Note, commit may run concurrently across all the state objects. Do not assume 423 // thread-safe access to the statedb. 424 func (s *stateObject) commit() (*accountUpdate, *trienode.NodeSet, error) { 425 // commit the account metadata changes 426 op := &accountUpdate{ 427 address: s.address, 428 data: types.SlimAccountRLP(s.data), 429 } 430 if s.origin != nil { 431 op.origin = types.SlimAccountRLP(*s.origin) 432 } 433 // commit the contract code if it's modified 434 if s.dirtyCode { 435 op.code = &contractCode{ 436 hash: common.BytesToHash(s.CodeHash()), 437 blob: s.code, 438 } 439 s.dirtyCode = false // reset the dirty flag 440 } 441 // Commit storage changes and the associated storage trie 442 s.commitStorage(op) 443 if len(op.storages) == 0 { 444 // nothing changed, don't bother to commit the trie 445 s.origin = s.data.Copy() 446 return op, nil, nil 447 } 448 root, nodes := s.trie.Commit(false) 449 s.data.Root = root 450 s.origin = s.data.Copy() 451 return op, nodes, nil 452 } 453 454 // AddBalance adds amount to s's balance. 455 // It is used to add funds to the destination account of a transfer. 456 // returns the previous balance 457 func (s *stateObject) AddBalance(amount *uint256.Int) uint256.Int { 458 // EIP161: We must check emptiness for the objects such that the account 459 // clearing (0,0,0 objects) can take effect. 460 if amount.IsZero() { 461 if s.empty() { 462 s.touch() 463 } 464 return *(s.Balance()) 465 } 466 return s.SetBalance(new(uint256.Int).Add(s.Balance(), amount)) 467 } 468 469 // SetBalance sets the balance for the object, and returns the previous balance. 470 func (s *stateObject) SetBalance(amount *uint256.Int) uint256.Int { 471 prev := *s.data.Balance 472 s.db.journal.balanceChange(s.address, s.data.Balance) 473 s.setBalance(amount) 474 return prev 475 } 476 477 func (s *stateObject) setBalance(amount *uint256.Int) { 478 s.data.Balance = amount 479 } 480 481 func (s *stateObject) deepCopy(db *StateDB) *stateObject { 482 obj := &stateObject{ 483 db: db, 484 address: s.address, 485 addrHash: s.addrHash, 486 origin: s.origin, 487 data: s.data, 488 code: s.code, 489 originStorage: s.originStorage.Copy(), 490 pendingStorage: s.pendingStorage.Copy(), 491 dirtyStorage: s.dirtyStorage.Copy(), 492 uncommittedStorage: s.uncommittedStorage.Copy(), 493 dirtyCode: s.dirtyCode, 494 selfDestructed: s.selfDestructed, 495 newContract: s.newContract, 496 } 497 if s.trie != nil { 498 obj.trie = mustCopyTrie(s.trie) 499 } 500 return obj 501 } 502 503 // 504 // Attribute accessors 505 // 506 507 // Address returns the address of the contract/account 508 func (s *stateObject) Address() common.Address { 509 return s.address 510 } 511 512 // Code returns the contract code associated with this object, if any. 513 func (s *stateObject) Code() []byte { 514 if len(s.code) != 0 { 515 return s.code 516 } 517 if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) { 518 return nil 519 } 520 code, err := s.db.reader.Code(s.address, common.BytesToHash(s.CodeHash())) 521 if err != nil { 522 s.db.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err)) 523 } 524 if len(code) == 0 { 525 s.db.setError(fmt.Errorf("code is not found %x", s.CodeHash())) 526 } 527 s.code = code 528 return code 529 } 530 531 // CodeSize returns the size of the contract code associated with this object, 532 // or zero if none. This method is an almost mirror of Code, but uses a cache 533 // inside the database to avoid loading codes seen recently. 534 func (s *stateObject) CodeSize() int { 535 if len(s.code) != 0 { 536 return len(s.code) 537 } 538 if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) { 539 return 0 540 } 541 size, err := s.db.reader.CodeSize(s.address, common.BytesToHash(s.CodeHash())) 542 if err != nil { 543 s.db.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err)) 544 } 545 if size == 0 { 546 s.db.setError(fmt.Errorf("code is not found %x", s.CodeHash())) 547 } 548 return size 549 } 550 551 func (s *stateObject) SetCode(codeHash common.Hash, code []byte) (prev []byte) { 552 prev = slices.Clone(s.code) 553 s.db.journal.setCode(s.address, prev) 554 s.setCode(codeHash, code) 555 return prev 556 } 557 558 func (s *stateObject) setCode(codeHash common.Hash, code []byte) { 559 s.code = code 560 s.data.CodeHash = codeHash[:] 561 s.dirtyCode = true 562 } 563 564 func (s *stateObject) SetNonce(nonce uint64) { 565 s.db.journal.nonceChange(s.address, s.data.Nonce) 566 s.setNonce(nonce) 567 } 568 569 func (s *stateObject) setNonce(nonce uint64) { 570 s.data.Nonce = nonce 571 } 572 573 func (s *stateObject) CodeHash() []byte { 574 return s.data.CodeHash 575 } 576 577 func (s *stateObject) Balance() *uint256.Int { 578 return s.data.Balance 579 } 580 581 func (s *stateObject) Nonce() uint64 { 582 return s.data.Nonce 583 } 584 585 func (s *stateObject) Root() common.Hash { 586 return s.data.Root 587 }