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  }