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 }