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