github.com/ethereum/go-ethereum@v1.16.1/core/state/database.go (about)

     1  // Copyright 2017 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  	"fmt"
    21  
    22  	"github.com/ethereum/go-ethereum/common"
    23  	"github.com/ethereum/go-ethereum/common/lru"
    24  	"github.com/ethereum/go-ethereum/core/rawdb"
    25  	"github.com/ethereum/go-ethereum/core/state/snapshot"
    26  	"github.com/ethereum/go-ethereum/core/types"
    27  	"github.com/ethereum/go-ethereum/crypto"
    28  	"github.com/ethereum/go-ethereum/ethdb"
    29  	"github.com/ethereum/go-ethereum/trie"
    30  	"github.com/ethereum/go-ethereum/trie/trienode"
    31  	"github.com/ethereum/go-ethereum/trie/utils"
    32  	"github.com/ethereum/go-ethereum/triedb"
    33  )
    34  
    35  const (
    36  	// Number of codehash->size associations to keep.
    37  	codeSizeCacheSize = 1_000_000 // 4 megabytes in total
    38  
    39  	// Cache size granted for caching clean code.
    40  	codeCacheSize = 256 * 1024 * 1024
    41  
    42  	// Number of address->curve point associations to keep.
    43  	pointCacheSize = 4096
    44  )
    45  
    46  // Database wraps access to tries and contract code.
    47  type Database interface {
    48  	// Reader returns a state reader associated with the specified state root.
    49  	Reader(root common.Hash) (Reader, error)
    50  
    51  	// OpenTrie opens the main account trie.
    52  	OpenTrie(root common.Hash) (Trie, error)
    53  
    54  	// OpenStorageTrie opens the storage trie of an account.
    55  	OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, trie Trie) (Trie, error)
    56  
    57  	// PointCache returns the cache holding points used in verkle tree key computation
    58  	PointCache() *utils.PointCache
    59  
    60  	// TrieDB returns the underlying trie database for managing trie nodes.
    61  	TrieDB() *triedb.Database
    62  
    63  	// Snapshot returns the underlying state snapshot.
    64  	Snapshot() *snapshot.Tree
    65  }
    66  
    67  // Trie is a Ethereum Merkle Patricia trie.
    68  type Trie interface {
    69  	// GetKey returns the sha3 preimage of a hashed key that was previously used
    70  	// to store a value.
    71  	//
    72  	// TODO(fjl): remove this when StateTrie is removed
    73  	GetKey([]byte) []byte
    74  
    75  	// GetAccount abstracts an account read from the trie. It retrieves the
    76  	// account blob from the trie with provided account address and decodes it
    77  	// with associated decoding algorithm. If the specified account is not in
    78  	// the trie, nil will be returned. If the trie is corrupted(e.g. some nodes
    79  	// are missing or the account blob is incorrect for decoding), an error will
    80  	// be returned.
    81  	GetAccount(address common.Address) (*types.StateAccount, error)
    82  
    83  	// GetStorage returns the value for key stored in the trie. The value bytes
    84  	// must not be modified by the caller. If a node was not found in the database,
    85  	// a trie.MissingNodeError is returned.
    86  	GetStorage(addr common.Address, key []byte) ([]byte, error)
    87  
    88  	// UpdateAccount abstracts an account write to the trie. It encodes the
    89  	// provided account object with associated algorithm and then updates it
    90  	// in the trie with provided address.
    91  	UpdateAccount(address common.Address, account *types.StateAccount, codeLen int) error
    92  
    93  	// UpdateStorage associates key with value in the trie. If value has length zero,
    94  	// any existing value is deleted from the trie. The value bytes must not be modified
    95  	// by the caller while they are stored in the trie. If a node was not found in the
    96  	// database, a trie.MissingNodeError is returned.
    97  	UpdateStorage(addr common.Address, key, value []byte) error
    98  
    99  	// DeleteAccount abstracts an account deletion from the trie.
   100  	DeleteAccount(address common.Address) error
   101  
   102  	// DeleteStorage removes any existing value for key from the trie. If a node
   103  	// was not found in the database, a trie.MissingNodeError is returned.
   104  	DeleteStorage(addr common.Address, key []byte) error
   105  
   106  	// UpdateContractCode abstracts code write to the trie. It is expected
   107  	// to be moved to the stateWriter interface when the latter is ready.
   108  	UpdateContractCode(address common.Address, codeHash common.Hash, code []byte) error
   109  
   110  	// Hash returns the root hash of the trie. It does not write to the database and
   111  	// can be used even if the trie doesn't have one.
   112  	Hash() common.Hash
   113  
   114  	// Commit collects all dirty nodes in the trie and replace them with the
   115  	// corresponding node hash. All collected nodes(including dirty leaves if
   116  	// collectLeaf is true) will be encapsulated into a nodeset for return.
   117  	// The returned nodeset can be nil if the trie is clean(nothing to commit).
   118  	// Once the trie is committed, it's not usable anymore. A new trie must
   119  	// be created with new root and updated trie database for following usage
   120  	Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet)
   121  
   122  	// Witness returns a set containing all trie nodes that have been accessed.
   123  	// The returned map could be nil if the witness is empty.
   124  	Witness() map[string]struct{}
   125  
   126  	// NodeIterator returns an iterator that returns nodes of the trie. Iteration
   127  	// starts at the key after the given start key. And error will be returned
   128  	// if fails to create node iterator.
   129  	NodeIterator(startKey []byte) (trie.NodeIterator, error)
   130  
   131  	// Prove constructs a Merkle proof for key. The result contains all encoded nodes
   132  	// on the path to the value at key. The value itself is also included in the last
   133  	// node and can be retrieved by verifying the proof.
   134  	//
   135  	// If the trie does not contain a value for key, the returned proof contains all
   136  	// nodes of the longest existing prefix of the key (at least the root), ending
   137  	// with the node that proves the absence of the key.
   138  	Prove(key []byte, proofDb ethdb.KeyValueWriter) error
   139  
   140  	// IsVerkle returns true if the trie is verkle-tree based
   141  	IsVerkle() bool
   142  }
   143  
   144  // CachingDB is an implementation of Database interface. It leverages both trie and
   145  // state snapshot to provide functionalities for state access. It's meant to be a
   146  // long-live object and has a few caches inside for sharing between blocks.
   147  type CachingDB struct {
   148  	disk          ethdb.KeyValueStore
   149  	triedb        *triedb.Database
   150  	snap          *snapshot.Tree
   151  	codeCache     *lru.SizeConstrainedCache[common.Hash, []byte]
   152  	codeSizeCache *lru.Cache[common.Hash, int]
   153  	pointCache    *utils.PointCache
   154  }
   155  
   156  // NewDatabase creates a state database with the provided data sources.
   157  func NewDatabase(triedb *triedb.Database, snap *snapshot.Tree) *CachingDB {
   158  	return &CachingDB{
   159  		disk:          triedb.Disk(),
   160  		triedb:        triedb,
   161  		snap:          snap,
   162  		codeCache:     lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
   163  		codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
   164  		pointCache:    utils.NewPointCache(pointCacheSize),
   165  	}
   166  }
   167  
   168  // NewDatabaseForTesting is similar to NewDatabase, but it initializes the caching
   169  // db by using an ephemeral memory db with default config for testing.
   170  func NewDatabaseForTesting() *CachingDB {
   171  	return NewDatabase(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil), nil)
   172  }
   173  
   174  // Reader returns a state reader associated with the specified state root.
   175  func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) {
   176  	var readers []StateReader
   177  
   178  	// Configure the state reader using the standalone snapshot in hash mode.
   179  	// This reader offers improved performance but is optional and only
   180  	// partially useful if the snapshot is not fully generated.
   181  	if db.TrieDB().Scheme() == rawdb.HashScheme && db.snap != nil {
   182  		snap := db.snap.Snapshot(stateRoot)
   183  		if snap != nil {
   184  			readers = append(readers, newFlatReader(snap))
   185  		}
   186  	}
   187  	// Configure the state reader using the path database in path mode.
   188  	// This reader offers improved performance but is optional and only
   189  	// partially useful if the snapshot data in path database is not
   190  	// fully generated.
   191  	if db.TrieDB().Scheme() == rawdb.PathScheme {
   192  		reader, err := db.triedb.StateReader(stateRoot)
   193  		if err == nil {
   194  			readers = append(readers, newFlatReader(reader))
   195  		}
   196  	}
   197  	// Configure the trie reader, which is expected to be available as the
   198  	// gatekeeper unless the state is corrupted.
   199  	tr, err := newTrieReader(stateRoot, db.triedb, db.pointCache)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  	readers = append(readers, tr)
   204  
   205  	combined, err := newMultiStateReader(readers...)
   206  	if err != nil {
   207  		return nil, err
   208  	}
   209  	return newReader(newCachingCodeReader(db.disk, db.codeCache, db.codeSizeCache), combined), nil
   210  }
   211  
   212  // ReadersWithCacheStats creates a pair of state readers sharing the same internal cache and
   213  // same backing Reader, but exposing separate statistics.
   214  // and statistics.
   215  func (db *CachingDB) ReadersWithCacheStats(stateRoot common.Hash) (ReaderWithStats, ReaderWithStats, error) {
   216  	reader, err := db.Reader(stateRoot)
   217  	if err != nil {
   218  		return nil, nil, err
   219  	}
   220  	shared := newReaderWithCache(reader)
   221  	return newReaderWithCacheStats(shared), newReaderWithCacheStats(shared), nil
   222  }
   223  
   224  // OpenTrie opens the main account trie at a specific root hash.
   225  func (db *CachingDB) OpenTrie(root common.Hash) (Trie, error) {
   226  	if db.triedb.IsVerkle() {
   227  		return trie.NewVerkleTrie(root, db.triedb, db.pointCache)
   228  	}
   229  	tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb)
   230  	if err != nil {
   231  		return nil, err
   232  	}
   233  	return tr, nil
   234  }
   235  
   236  // OpenStorageTrie opens the storage trie of an account.
   237  func (db *CachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) {
   238  	// In the verkle case, there is only one tree. But the two-tree structure
   239  	// is hardcoded in the codebase. So we need to return the same trie in this
   240  	// case.
   241  	if db.triedb.IsVerkle() {
   242  		return self, nil
   243  	}
   244  	tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb)
   245  	if err != nil {
   246  		return nil, err
   247  	}
   248  	return tr, nil
   249  }
   250  
   251  // ContractCodeWithPrefix retrieves a particular contract's code. If the
   252  // code can't be found in the cache, then check the existence with **new**
   253  // db scheme.
   254  func (db *CachingDB) ContractCodeWithPrefix(address common.Address, codeHash common.Hash) []byte {
   255  	code, _ := db.codeCache.Get(codeHash)
   256  	if len(code) > 0 {
   257  		return code
   258  	}
   259  	code = rawdb.ReadCodeWithPrefix(db.disk, codeHash)
   260  	if len(code) > 0 {
   261  		db.codeCache.Add(codeHash, code)
   262  		db.codeSizeCache.Add(codeHash, len(code))
   263  	}
   264  	return code
   265  }
   266  
   267  // TrieDB retrieves any intermediate trie-node caching layer.
   268  func (db *CachingDB) TrieDB() *triedb.Database {
   269  	return db.triedb
   270  }
   271  
   272  // PointCache returns the cache of evaluated curve points.
   273  func (db *CachingDB) PointCache() *utils.PointCache {
   274  	return db.pointCache
   275  }
   276  
   277  // Snapshot returns the underlying state snapshot.
   278  func (db *CachingDB) Snapshot() *snapshot.Tree {
   279  	return db.snap
   280  }
   281  
   282  // mustCopyTrie returns a deep-copied trie.
   283  func mustCopyTrie(t Trie) Trie {
   284  	switch t := t.(type) {
   285  	case *trie.StateTrie:
   286  		return t.Copy()
   287  	case *trie.VerkleTrie:
   288  		return t.Copy()
   289  	default:
   290  		panic(fmt.Errorf("unknown trie type %T", t))
   291  	}
   292  }