github.com/cryptotooltop/go-ethereum@v0.0.0-20231103184714-151d1922f3e5/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 "errors" 21 "fmt" 22 23 "github.com/VictoriaMetrics/fastcache" 24 lru "github.com/hashicorp/golang-lru" 25 26 "github.com/scroll-tech/go-ethereum/common" 27 "github.com/scroll-tech/go-ethereum/core/rawdb" 28 "github.com/scroll-tech/go-ethereum/core/types" 29 "github.com/scroll-tech/go-ethereum/ethdb" 30 "github.com/scroll-tech/go-ethereum/trie" 31 ) 32 33 const ( 34 // Number of codehash->size associations to keep. 35 codeSizeCacheSize = 100000 36 37 // Cache size granted for caching clean code. 38 codeCacheSize = 64 * 1024 * 1024 39 ) 40 41 // Database wraps access to tries and contract code. 42 type Database interface { 43 // OpenTrie opens the main account trie. 44 OpenTrie(root common.Hash) (Trie, error) 45 46 // OpenStorageTrie opens the storage trie of an account. 47 OpenStorageTrie(addrHash, root common.Hash) (Trie, error) 48 49 // CopyTrie returns an independent copy of the given trie. 50 CopyTrie(Trie) Trie 51 52 // ContractCode retrieves a particular contract's code. 53 ContractCode(addrHash, codeHash common.Hash) ([]byte, error) 54 55 // ContractCodeSize retrieves a particular contracts code's size. 56 ContractCodeSize(addrHash, codeHash common.Hash) (int, error) 57 58 // TrieDB retrieves the low level trie database used for data storage. 59 TrieDB() *trie.Database 60 } 61 62 // Trie is a Ethereum Merkle Patricia trie. 63 type Trie interface { 64 // GetKey returns the sha3 preimage of a hashed key that was previously used 65 // to store a value. 66 // 67 // TODO(fjl): remove this when SecureTrie is removed 68 GetKey([]byte) []byte 69 70 // TryGet returns the value for key stored in the trie. The value bytes must 71 // not be modified by the caller. If a node was not found in the database, a 72 // trie.MissingNodeError is returned. 73 TryGet(key []byte) ([]byte, error) 74 75 // TryUpdateAccount abstract an account write in the trie. 76 TryUpdateAccount(key []byte, account *types.StateAccount) error 77 78 // TryUpdate associates key with value in the trie. If value has length zero, any 79 // existing value is deleted from the trie. The value bytes must not be modified 80 // by the caller while they are stored in the trie. If a node was not found in the 81 // database, a trie.MissingNodeError is returned. 82 TryUpdate(key, value []byte) error 83 84 // TryDelete removes any existing value for key from the trie. If a node was not 85 // found in the database, a trie.MissingNodeError is returned. 86 TryDelete(key []byte) error 87 88 // Hash returns the root hash of the trie. It does not write to the database and 89 // can be used even if the trie doesn't have one. 90 Hash() common.Hash 91 92 // Commit writes all nodes to the trie's memory database, tracking the internal 93 // and external (for account tries) references. 94 Commit(onleaf trie.LeafCallback) (common.Hash, int, error) 95 96 // NodeIterator returns an iterator that returns nodes of the trie. Iteration 97 // starts at the key after the given start key. 98 NodeIterator(startKey []byte) trie.NodeIterator 99 100 // Prove constructs a Merkle proof for key. The result contains all encoded nodes 101 // on the path to the value at key. The value itself is also included in the last 102 // node and can be retrieved by verifying the proof. 103 // 104 // If the trie does not contain a value for key, the returned proof contains all 105 // nodes of the longest existing prefix of the key (at least the root), ending 106 // with the node that proves the absence of the key. 107 Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) error 108 } 109 110 // NewDatabase creates a backing store for state. The returned database is safe for 111 // concurrent use, but does not retain any recent trie nodes in memory. To keep some 112 // historical state in memory, use the NewDatabaseWithConfig constructor. 113 func NewDatabase(db ethdb.Database) Database { 114 return NewDatabaseWithConfig(db, nil) 115 } 116 117 // NewDatabaseWithConfig creates a backing store for state. The returned database 118 // is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a 119 // large memory cache. 120 func NewDatabaseWithConfig(db ethdb.Database, config *trie.Config) Database { 121 csc, _ := lru.New(codeSizeCacheSize) 122 return &cachingDB{ 123 zktrie: config != nil && config.Zktrie, 124 db: trie.NewDatabaseWithConfig(db, config), 125 codeSizeCache: csc, 126 codeCache: fastcache.New(codeCacheSize), 127 } 128 } 129 130 type cachingDB struct { 131 db *trie.Database 132 codeSizeCache *lru.Cache 133 codeCache *fastcache.Cache 134 zktrie bool 135 } 136 137 // OpenTrie opens the main account trie at a specific root hash. 138 func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { 139 if db.zktrie { 140 tr, err := trie.NewZkTrie(root, trie.NewZktrieDatabaseFromTriedb(db.db)) 141 if err != nil { 142 return nil, err 143 } 144 return tr, nil 145 } 146 tr, err := trie.NewSecure(root, db.db) 147 if err != nil { 148 return nil, err 149 } 150 return tr, nil 151 } 152 153 // OpenStorageTrie opens the storage trie of an account. 154 func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) { 155 if db.zktrie { 156 tr, err := trie.NewZkTrie(root, trie.NewZktrieDatabaseFromTriedb(db.db)) 157 if err != nil { 158 return nil, err 159 } 160 return tr, nil 161 } 162 tr, err := trie.NewSecure(root, db.db) 163 if err != nil { 164 return nil, err 165 } 166 return tr, nil 167 } 168 169 // CopyTrie returns an independent copy of the given trie. 170 func (db *cachingDB) CopyTrie(t Trie) Trie { 171 switch t := t.(type) { 172 case *trie.SecureTrie: 173 return t.Copy() 174 case *trie.ZkTrie: 175 return t.Copy() 176 default: 177 panic(fmt.Errorf("unknown trie type %T", t)) 178 } 179 } 180 181 // ContractCode retrieves a particular contract's code. 182 func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) { 183 if code := db.codeCache.Get(nil, codeHash.Bytes()); len(code) > 0 { 184 return code, nil 185 } 186 code := rawdb.ReadCode(db.db.DiskDB(), codeHash) 187 if len(code) > 0 { 188 db.codeCache.Set(codeHash.Bytes(), code) 189 db.codeSizeCache.Add(codeHash, len(code)) 190 return code, nil 191 } 192 return nil, errors.New("not found") 193 } 194 195 // ContractCodeWithPrefix retrieves a particular contract's code. If the 196 // code can't be found in the cache, then check the existence with **new** 197 // db scheme. 198 func (db *cachingDB) ContractCodeWithPrefix(addrHash, codeHash common.Hash) ([]byte, error) { 199 if code := db.codeCache.Get(nil, codeHash.Bytes()); len(code) > 0 { 200 return code, nil 201 } 202 code := rawdb.ReadCodeWithPrefix(db.db.DiskDB(), codeHash) 203 if len(code) > 0 { 204 db.codeCache.Set(codeHash.Bytes(), code) 205 db.codeSizeCache.Add(codeHash, len(code)) 206 return code, nil 207 } 208 return nil, errors.New("not found") 209 } 210 211 // ContractCodeSize retrieves a particular contracts code's size. 212 func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) { 213 if cached, ok := db.codeSizeCache.Get(codeHash); ok { 214 return cached.(int), nil 215 } 216 code, err := db.ContractCode(addrHash, codeHash) 217 return len(code), err 218 } 219 220 // TrieDB retrieves any intermediate trie-node caching layer. 221 func (db *cachingDB) TrieDB() *trie.Database { 222 return db.db 223 }