github.com/ethereum/go-ethereum@v1.14.4-0.20240516095835-473ee8fc07a3/core/state/state_object.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package state 18 19 import ( 20 "bytes" 21 "fmt" 22 "io" 23 "maps" 24 "sync" 25 "time" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/core/tracing" 29 "github.com/ethereum/go-ethereum/core/types" 30 "github.com/ethereum/go-ethereum/crypto" 31 "github.com/ethereum/go-ethereum/log" 32 "github.com/ethereum/go-ethereum/rlp" 33 "github.com/ethereum/go-ethereum/trie/trienode" 34 "github.com/holiman/uint256" 35 ) 36 37 // hasherPool holds a pool of hashers used by state objects during concurrent 38 // trie updates. 39 var hasherPool = sync.Pool{ 40 New: func() interface{} { 41 return crypto.NewKeccakState() 42 }, 43 } 44 45 type Storage map[common.Hash]common.Hash 46 47 func (s Storage) Copy() Storage { 48 return maps.Clone(s) 49 } 50 51 // stateObject represents an Ethereum account which is being modified. 52 // 53 // The usage pattern is as follows: 54 // - First you need to obtain a state object. 55 // - Account values as well as storages can be accessed and modified through the object. 56 // - Finally, call commit to return the changes of storage trie and update account data. 57 type stateObject struct { 58 db *StateDB 59 address common.Address // address of ethereum account 60 addrHash common.Hash // hash of ethereum address of the account 61 origin *types.StateAccount // Account original data without any change applied, nil means it was not existent 62 data types.StateAccount // Account data with all mutations applied in the scope of block 63 64 // Write caches. 65 trie Trie // storage trie, which becomes non-nil on first access 66 code []byte // contract bytecode, which gets set when code is loaded 67 68 originStorage Storage // Storage cache of original entries to dedup rewrites 69 pendingStorage Storage // Storage entries that need to be flushed to disk, at the end of an entire block 70 dirtyStorage Storage // Storage entries that have been modified in the current transaction execution, reset for every transaction 71 72 // Cache flags. 73 dirtyCode bool // true if the code was updated 74 75 // Flag whether the account was marked as self-destructed. The self-destructed 76 // account is still accessible in the scope of same transaction. 77 selfDestructed bool 78 79 // This is an EIP-6780 flag indicating whether the object is eligible for 80 // self-destruct according to EIP-6780. The flag could be set either when 81 // the contract is just created within the current transaction, or when the 82 // object was previously existent and is being deployed as a contract within 83 // the current transaction. 84 newContract bool 85 } 86 87 // empty returns whether the account is considered empty. 88 func (s *stateObject) empty() bool { 89 return s.data.Nonce == 0 && s.data.Balance.IsZero() && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes()) 90 } 91 92 // newObject creates a state object. 93 func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *stateObject { 94 origin := acct 95 if acct == nil { 96 acct = types.NewEmptyStateAccount() 97 } 98 return &stateObject{ 99 db: db, 100 address: address, 101 addrHash: crypto.Keccak256Hash(address[:]), 102 origin: origin, 103 data: *acct, 104 originStorage: make(Storage), 105 pendingStorage: make(Storage), 106 dirtyStorage: make(Storage), 107 } 108 } 109 110 // EncodeRLP implements rlp.Encoder. 111 func (s *stateObject) EncodeRLP(w io.Writer) error { 112 return rlp.Encode(w, &s.data) 113 } 114 115 func (s *stateObject) markSelfdestructed() { 116 s.selfDestructed = true 117 } 118 119 func (s *stateObject) touch() { 120 s.db.journal.append(touchChange{ 121 account: &s.address, 122 }) 123 if s.address == ripemd { 124 // Explicitly put it in the dirty-cache, which is otherwise generated from 125 // flattened journals. 126 s.db.journal.dirty(s.address) 127 } 128 } 129 130 // getTrie returns the associated storage trie. The trie will be opened if it' 131 // not loaded previously. An error will be returned if trie can't be loaded. 132 // 133 // If a new trie is opened, it will be cached within the state object to allow 134 // subsequent reads to expand the same trie instead of reloading from disk. 135 func (s *stateObject) getTrie() (Trie, error) { 136 if s.trie == nil { 137 tr, err := s.db.db.OpenStorageTrie(s.db.originalRoot, s.address, s.data.Root, s.db.trie) 138 if err != nil { 139 return nil, err 140 } 141 s.trie = tr 142 } 143 return s.trie, nil 144 } 145 146 // getPrefetchedTrie returns the associated trie, as populated by the prefetcher 147 // if it's available. 148 // 149 // Note, opposed to getTrie, this method will *NOT* blindly cache the resulting 150 // trie in the state object. The caller might want to do that, but it's cleaner 151 // to break the hidden interdependency between retrieving tries from the db or 152 // from the prefetcher. 153 func (s *stateObject) getPrefetchedTrie() (Trie, error) { 154 // If there's nothing to meaningfully return, let the user figure it out by 155 // pulling the trie from disk. 156 if s.data.Root == types.EmptyRootHash || s.db.prefetcher == nil { 157 return nil, nil 158 } 159 // Attempt to retrieve the trie from the pretecher 160 return s.db.prefetcher.trie(s.addrHash, s.data.Root) 161 } 162 163 // GetState retrieves a value from the account storage trie. 164 func (s *stateObject) GetState(key common.Hash) common.Hash { 165 value, _ := s.getState(key) 166 return value 167 } 168 169 // getState retrieves a value associated with the given storage key, along with 170 // its original value. 171 func (s *stateObject) getState(key common.Hash) (common.Hash, common.Hash) { 172 origin := s.GetCommittedState(key) 173 value, dirty := s.dirtyStorage[key] 174 if dirty { 175 return value, origin 176 } 177 return origin, origin 178 } 179 180 // GetCommittedState retrieves a value from the committed account storage trie. 181 func (s *stateObject) GetCommittedState(key common.Hash) common.Hash { 182 // If we have a pending write or clean cached, return that 183 if value, pending := s.pendingStorage[key]; pending { 184 return value 185 } 186 if value, cached := s.originStorage[key]; cached { 187 return value 188 } 189 // If the object was destructed in *this* block (and potentially resurrected), 190 // the storage has been cleared out, and we should *not* consult the previous 191 // database about any storage values. The only possible alternatives are: 192 // 1) resurrect happened, and new slot values were set -- those should 193 // have been handles via pendingStorage above. 194 // 2) we don't have new values, and can deliver empty response back 195 if _, destructed := s.db.stateObjectsDestruct[s.address]; destructed { 196 return common.Hash{} 197 } 198 // If no live objects are available, attempt to use snapshots 199 var ( 200 enc []byte 201 err error 202 value common.Hash 203 ) 204 if s.db.snap != nil { 205 start := time.Now() 206 enc, err = s.db.snap.Storage(s.addrHash, crypto.Keccak256Hash(key.Bytes())) 207 s.db.SnapshotStorageReads += time.Since(start) 208 209 if len(enc) > 0 { 210 _, content, _, err := rlp.Split(enc) 211 if err != nil { 212 s.db.setError(err) 213 } 214 value.SetBytes(content) 215 } 216 } 217 // If the snapshot is unavailable or reading from it fails, load from the database. 218 if s.db.snap == nil || err != nil { 219 start := time.Now() 220 tr, err := s.getTrie() 221 if err != nil { 222 s.db.setError(err) 223 return common.Hash{} 224 } 225 val, err := tr.GetStorage(s.address, key.Bytes()) 226 s.db.StorageReads += time.Since(start) 227 228 if err != nil { 229 s.db.setError(err) 230 return common.Hash{} 231 } 232 value.SetBytes(val) 233 } 234 s.originStorage[key] = value 235 return value 236 } 237 238 // SetState updates a value in account storage. 239 func (s *stateObject) SetState(key, value common.Hash) { 240 // If the new value is the same as old, don't set. Otherwise, track only the 241 // dirty changes, supporting reverting all of it back to no change. 242 prev, origin := s.getState(key) 243 if prev == value { 244 return 245 } 246 // New value is different, update and journal the change 247 s.db.journal.append(storageChange{ 248 account: &s.address, 249 key: key, 250 prevvalue: prev, 251 origvalue: origin, 252 }) 253 if s.db.logger != nil && s.db.logger.OnStorageChange != nil { 254 s.db.logger.OnStorageChange(s.address, key, prev, value) 255 } 256 s.setState(key, value, origin) 257 } 258 259 // setState updates a value in account dirty storage. The dirtiness will be 260 // removed if the value being set equals to the original value. 261 func (s *stateObject) setState(key common.Hash, value common.Hash, origin common.Hash) { 262 // Storage slot is set back to its original value, undo the dirty marker 263 if value == origin { 264 delete(s.dirtyStorage, key) 265 return 266 } 267 s.dirtyStorage[key] = value 268 } 269 270 // finalise moves all dirty storage slots into the pending area to be hashed or 271 // committed later. It is invoked at the end of every transaction. 272 func (s *stateObject) finalise() { 273 slotsToPrefetch := make([][]byte, 0, len(s.dirtyStorage)) 274 for key, value := range s.dirtyStorage { 275 // If the slot is different from its original value, move it into the 276 // pending area to be committed at the end of the block (and prefetch 277 // the pathways). 278 if value != s.originStorage[key] { 279 s.pendingStorage[key] = value 280 slotsToPrefetch = append(slotsToPrefetch, common.CopyBytes(key[:])) // Copy needed for closure 281 } else { 282 // Otherwise, the slot was reverted to its original value, remove it 283 // from the pending area to avoid thrashing the data structure. 284 delete(s.pendingStorage, key) 285 } 286 } 287 if s.db.prefetcher != nil && len(slotsToPrefetch) > 0 && s.data.Root != types.EmptyRootHash { 288 if err := s.db.prefetcher.prefetch(s.addrHash, s.data.Root, s.address, slotsToPrefetch); err != nil { 289 log.Error("Failed to prefetch slots", "addr", s.address, "slots", len(slotsToPrefetch), "err", err) 290 } 291 } 292 if len(s.dirtyStorage) > 0 { 293 s.dirtyStorage = make(Storage) 294 } 295 // Revoke the flag at the end of the transaction. It finalizes the status 296 // of the newly-created object as it's no longer eligible for self-destruct 297 // by EIP-6780. For non-newly-created objects, it's a no-op. 298 s.newContract = false 299 } 300 301 // updateTrie is responsible for persisting cached storage changes into the 302 // object's storage trie. In case the storage trie is not yet loaded, this 303 // function will load the trie automatically. If any issues arise during the 304 // loading or updating of the trie, an error will be returned. Furthermore, 305 // this function will return the mutated storage trie, or nil if there is no 306 // storage change at all. 307 // 308 // It assumes all the dirty storage slots have been finalized before. 309 func (s *stateObject) updateTrie() (Trie, error) { 310 // Short circuit if nothing changed, don't bother with hashing anything 311 if len(s.pendingStorage) == 0 { 312 return s.trie, nil 313 } 314 // Retrieve a pretecher populated trie, or fall back to the database 315 tr, err := s.getPrefetchedTrie() 316 switch { 317 case err != nil: 318 // Fetcher retrieval failed, something's very wrong, abort 319 s.db.setError(err) 320 return nil, err 321 322 case tr == nil: 323 // Fetcher not running or empty trie, fallback to the database trie 324 tr, err = s.getTrie() 325 if err != nil { 326 s.db.setError(err) 327 return nil, err 328 } 329 330 default: 331 // Prefetcher returned a live trie, swap it out for the current one 332 s.trie = tr 333 } 334 // The snapshot storage map for the object 335 var ( 336 storage map[common.Hash][]byte 337 origin map[common.Hash][]byte 338 ) 339 // Insert all the pending storage updates into the trie 340 usedStorage := make([][]byte, 0, len(s.pendingStorage)) 341 342 hasher := hasherPool.Get().(crypto.KeccakState) 343 defer hasherPool.Put(hasher) 344 345 // Perform trie updates before deletions. This prevents resolution of unnecessary trie nodes 346 // in circumstances similar to the following: 347 // 348 // Consider nodes `A` and `B` who share the same full node parent `P` and have no other siblings. 349 // During the execution of a block: 350 // - `A` is deleted, 351 // - `C` is created, and also shares the parent `P`. 352 // If the deletion is handled first, then `P` would be left with only one child, thus collapsed 353 // into a shortnode. This requires `B` to be resolved from disk. 354 // Whereas if the created node is handled first, then the collapse is avoided, and `B` is not resolved. 355 var deletions []common.Hash 356 for key, value := range s.pendingStorage { 357 // Skip noop changes, persist actual changes 358 if value == s.originStorage[key] { 359 continue 360 } 361 prev := s.originStorage[key] 362 s.originStorage[key] = value 363 364 var encoded []byte // rlp-encoded value to be used by the snapshot 365 if (value != common.Hash{}) { 366 // Encoding []byte cannot fail, ok to ignore the error. 367 trimmed := common.TrimLeftZeroes(value[:]) 368 encoded, _ = rlp.EncodeToBytes(trimmed) 369 if err := tr.UpdateStorage(s.address, key[:], trimmed); err != nil { 370 s.db.setError(err) 371 return nil, err 372 } 373 s.db.StorageUpdated.Add(1) 374 } else { 375 deletions = append(deletions, key) 376 } 377 // Cache the mutated storage slots until commit 378 if storage == nil { 379 s.db.storagesLock.Lock() 380 if storage = s.db.storages[s.addrHash]; storage == nil { 381 storage = make(map[common.Hash][]byte) 382 s.db.storages[s.addrHash] = storage 383 } 384 s.db.storagesLock.Unlock() 385 } 386 khash := crypto.HashData(hasher, key[:]) 387 storage[khash] = encoded // encoded will be nil if it's deleted 388 389 // Cache the original value of mutated storage slots 390 if origin == nil { 391 s.db.storagesLock.Lock() 392 if origin = s.db.storagesOrigin[s.address]; origin == nil { 393 origin = make(map[common.Hash][]byte) 394 s.db.storagesOrigin[s.address] = origin 395 } 396 s.db.storagesLock.Unlock() 397 } 398 // Track the original value of slot only if it's mutated first time 399 if _, ok := origin[khash]; !ok { 400 if prev == (common.Hash{}) { 401 origin[khash] = nil // nil if it was not present previously 402 } else { 403 // Encoding []byte cannot fail, ok to ignore the error. 404 b, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(prev[:])) 405 origin[khash] = b 406 } 407 } 408 // Cache the items for preloading 409 usedStorage = append(usedStorage, common.CopyBytes(key[:])) // Copy needed for closure 410 } 411 for _, key := range deletions { 412 if err := tr.DeleteStorage(s.address, key[:]); err != nil { 413 s.db.setError(err) 414 return nil, err 415 } 416 s.db.StorageDeleted.Add(1) 417 } 418 // If no slots were touched, issue a warning as we shouldn't have done all 419 // the above work in the first place 420 if len(usedStorage) == 0 { 421 log.Error("State object update was noop", "addr", s.address, "slots", len(s.pendingStorage)) 422 } 423 if s.db.prefetcher != nil { 424 s.db.prefetcher.used(s.addrHash, s.data.Root, usedStorage) 425 } 426 s.pendingStorage = make(Storage) // reset pending map 427 return tr, nil 428 } 429 430 // updateRoot flushes all cached storage mutations to trie, recalculating the 431 // new storage trie root. 432 func (s *stateObject) updateRoot() { 433 // Flush cached storage mutations into trie, short circuit if any error 434 // is occurred or there is no change in the trie. 435 tr, err := s.updateTrie() 436 if err != nil || tr == nil { 437 return 438 } 439 s.data.Root = tr.Hash() 440 } 441 442 // commit obtains a set of dirty storage trie nodes and updates the account data. 443 // The returned set can be nil if nothing to commit. This function assumes all 444 // storage mutations have already been flushed into trie by updateRoot. 445 // 446 // Note, commit may run concurrently across all the state objects. Do not assume 447 // thread-safe access to the statedb. 448 func (s *stateObject) commit() (*trienode.NodeSet, error) { 449 // Short circuit if trie is not even loaded, don't bother with committing anything 450 if s.trie == nil { 451 s.origin = s.data.Copy() 452 return nil, nil 453 } 454 // The trie is currently in an open state and could potentially contain 455 // cached mutations. Call commit to acquire a set of nodes that have been 456 // modified, the set can be nil if nothing to commit. 457 root, nodes, err := s.trie.Commit(false) 458 if err != nil { 459 return nil, err 460 } 461 s.data.Root = root 462 463 // Update original account data after commit 464 s.origin = s.data.Copy() 465 return nodes, nil 466 } 467 468 // AddBalance adds amount to s's balance. 469 // It is used to add funds to the destination account of a transfer. 470 func (s *stateObject) AddBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) { 471 // EIP161: We must check emptiness for the objects such that the account 472 // clearing (0,0,0 objects) can take effect. 473 if amount.IsZero() { 474 if s.empty() { 475 s.touch() 476 } 477 return 478 } 479 s.SetBalance(new(uint256.Int).Add(s.Balance(), amount), reason) 480 } 481 482 // SubBalance removes amount from s's balance. 483 // It is used to remove funds from the origin account of a transfer. 484 func (s *stateObject) SubBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) { 485 if amount.IsZero() { 486 return 487 } 488 s.SetBalance(new(uint256.Int).Sub(s.Balance(), amount), reason) 489 } 490 491 func (s *stateObject) SetBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) { 492 s.db.journal.append(balanceChange{ 493 account: &s.address, 494 prev: new(uint256.Int).Set(s.data.Balance), 495 }) 496 if s.db.logger != nil && s.db.logger.OnBalanceChange != nil { 497 s.db.logger.OnBalanceChange(s.address, s.Balance().ToBig(), amount.ToBig(), reason) 498 } 499 s.setBalance(amount) 500 } 501 502 func (s *stateObject) setBalance(amount *uint256.Int) { 503 s.data.Balance = amount 504 } 505 506 func (s *stateObject) deepCopy(db *StateDB) *stateObject { 507 obj := &stateObject{ 508 db: db, 509 address: s.address, 510 addrHash: s.addrHash, 511 origin: s.origin, 512 data: s.data, 513 code: s.code, 514 originStorage: s.originStorage.Copy(), 515 pendingStorage: s.pendingStorage.Copy(), 516 dirtyStorage: s.dirtyStorage.Copy(), 517 dirtyCode: s.dirtyCode, 518 selfDestructed: s.selfDestructed, 519 newContract: s.newContract, 520 } 521 if s.trie != nil { 522 obj.trie = db.db.CopyTrie(s.trie) 523 } 524 return obj 525 } 526 527 // 528 // Attribute accessors 529 // 530 531 // Address returns the address of the contract/account 532 func (s *stateObject) Address() common.Address { 533 return s.address 534 } 535 536 // Code returns the contract code associated with this object, if any. 537 func (s *stateObject) Code() []byte { 538 if len(s.code) != 0 { 539 return s.code 540 } 541 if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) { 542 return nil 543 } 544 code, err := s.db.db.ContractCode(s.address, common.BytesToHash(s.CodeHash())) 545 if err != nil { 546 s.db.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err)) 547 } 548 s.code = code 549 return code 550 } 551 552 // CodeSize returns the size of the contract code associated with this object, 553 // or zero if none. This method is an almost mirror of Code, but uses a cache 554 // inside the database to avoid loading codes seen recently. 555 func (s *stateObject) CodeSize() int { 556 if len(s.code) != 0 { 557 return len(s.code) 558 } 559 if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) { 560 return 0 561 } 562 size, err := s.db.db.ContractCodeSize(s.address, common.BytesToHash(s.CodeHash())) 563 if err != nil { 564 s.db.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err)) 565 } 566 return size 567 } 568 569 func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { 570 prevcode := s.Code() 571 s.db.journal.append(codeChange{ 572 account: &s.address, 573 prevhash: s.CodeHash(), 574 prevcode: prevcode, 575 }) 576 if s.db.logger != nil && s.db.logger.OnCodeChange != nil { 577 s.db.logger.OnCodeChange(s.address, common.BytesToHash(s.CodeHash()), prevcode, codeHash, code) 578 } 579 s.setCode(codeHash, code) 580 } 581 582 func (s *stateObject) setCode(codeHash common.Hash, code []byte) { 583 s.code = code 584 s.data.CodeHash = codeHash[:] 585 s.dirtyCode = true 586 } 587 588 func (s *stateObject) SetNonce(nonce uint64) { 589 s.db.journal.append(nonceChange{ 590 account: &s.address, 591 prev: s.data.Nonce, 592 }) 593 if s.db.logger != nil && s.db.logger.OnNonceChange != nil { 594 s.db.logger.OnNonceChange(s.address, s.data.Nonce, nonce) 595 } 596 s.setNonce(nonce) 597 } 598 599 func (s *stateObject) setNonce(nonce uint64) { 600 s.data.Nonce = nonce 601 } 602 603 func (s *stateObject) CodeHash() []byte { 604 return s.data.CodeHash 605 } 606 607 func (s *stateObject) Balance() *uint256.Int { 608 return s.data.Balance 609 } 610 611 func (s *stateObject) Nonce() uint64 { 612 return s.data.Nonce 613 } 614 615 func (s *stateObject) Root() common.Hash { 616 return s.data.Root 617 }