github.com/MetalBlockchain/subnet-evm@v0.4.9/core/state/database.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2017 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package state 28 29 import ( 30 "errors" 31 "fmt" 32 33 "github.com/MetalBlockchain/subnet-evm/core/rawdb" 34 "github.com/MetalBlockchain/subnet-evm/core/types" 35 "github.com/MetalBlockchain/subnet-evm/ethdb" 36 "github.com/MetalBlockchain/subnet-evm/trie" 37 "github.com/VictoriaMetrics/fastcache" 38 "github.com/ethereum/go-ethereum/common" 39 lru "github.com/hashicorp/golang-lru" 40 ) 41 42 const ( 43 // Number of codehash->size associations to keep. 44 codeSizeCacheSize = 100000 45 46 // Cache size granted for caching clean code. 47 codeCacheSize = 64 * 1024 * 1024 48 ) 49 50 // Database wraps access to tries and contract code. 51 type Database interface { 52 // OpenTrie opens the main account trie. 53 OpenTrie(root common.Hash) (Trie, error) 54 55 // OpenStorageTrie opens the storage trie of an account. 56 OpenStorageTrie(addrHash, root common.Hash) (Trie, error) 57 58 // CopyTrie returns an independent copy of the given trie. 59 CopyTrie(Trie) Trie 60 61 // ContractCode retrieves a particular contract's code. 62 ContractCode(addrHash, codeHash common.Hash) ([]byte, error) 63 64 // ContractCodeSize retrieves a particular contracts code's size. 65 ContractCodeSize(addrHash, codeHash common.Hash) (int, error) 66 67 // TrieDB retrieves the low level trie database used for data storage. 68 TrieDB() *trie.Database 69 } 70 71 // Trie is a Ethereum Merkle Patricia trie. 72 type Trie interface { 73 // GetKey returns the sha3 preimage of a hashed key that was previously used 74 // to store a value. 75 // 76 // TODO(fjl): remove this when StateTrie is removed 77 GetKey([]byte) []byte 78 79 // TryGet returns the value for key stored in the trie. The value bytes must 80 // not be modified by the caller. If a node was not found in the database, a 81 // trie.MissingNodeError is returned. 82 TryGet(key []byte) ([]byte, error) 83 84 // TryGetAccount abstract an account read from the trie. 85 TryGetAccount(key []byte) (*types.StateAccount, error) 86 87 // TryUpdate associates key with value in the trie. If value has length zero, any 88 // existing value is deleted from the trie. The value bytes must not be modified 89 // by the caller while they are stored in the trie. If a node was not found in the 90 // database, a trie.MissingNodeError is returned. 91 TryUpdate(key, value []byte) error 92 93 // TryUpdateAccount abstract an account write to the trie. 94 TryUpdateAccount(key []byte, account *types.StateAccount) error 95 96 // TryDelete removes any existing value for key from the trie. If a node was not 97 // found in the database, a trie.MissingNodeError is returned. 98 TryDelete(key []byte) error 99 100 // TryDeleteAccount abstracts an account deletion from the trie. 101 TryDeleteAccount(key []byte) error 102 103 // Hash returns the root hash of the trie. It does not write to the database and 104 // can be used even if the trie doesn't have one. 105 Hash() common.Hash 106 107 // Commit collects all dirty nodes in the trie and replace them with the 108 // corresponding node hash. All collected nodes(including dirty leaves if 109 // collectLeaf is true) will be encapsulated into a nodeset for return. 110 // The returned nodeset can be nil if the trie is clean(nothing to commit). 111 // Once the trie is committed, it's not usable anymore. A new trie must 112 // be created with new root and updated trie database for following usage 113 Commit(collectLeaf bool) (common.Hash, *trie.NodeSet, error) 114 115 // NodeIterator returns an iterator that returns nodes of the trie. Iteration 116 // starts at the key after the given start key. 117 NodeIterator(startKey []byte) trie.NodeIterator 118 119 // Prove constructs a Merkle proof for key. The result contains all encoded nodes 120 // on the path to the value at key. The value itself is also included in the last 121 // node and can be retrieved by verifying the proof. 122 // 123 // If the trie does not contain a value for key, the returned proof contains all 124 // nodes of the longest existing prefix of the key (at least the root), ending 125 // with the node that proves the absence of the key. 126 Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) error 127 } 128 129 // NewDatabase creates a backing store for state. The returned database is safe for 130 // concurrent use, but does not retain any recent trie nodes in memory. To keep some 131 // historical state in memory, use the NewDatabaseWithConfig constructor. 132 func NewDatabase(db ethdb.Database) Database { 133 return NewDatabaseWithConfig(db, nil) 134 } 135 136 // NewDatabaseWithConfig creates a backing store for state. The returned database 137 // is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a 138 // large memory cache. 139 func NewDatabaseWithConfig(db ethdb.Database, config *trie.Config) Database { 140 csc, _ := lru.New(codeSizeCacheSize) 141 return &cachingDB{ 142 db: trie.NewDatabaseWithConfig(db, config), 143 codeSizeCache: csc, 144 codeCache: fastcache.New(codeCacheSize), 145 } 146 } 147 148 type cachingDB struct { 149 db *trie.Database 150 codeSizeCache *lru.Cache 151 codeCache *fastcache.Cache 152 } 153 154 // OpenTrie opens the main account trie at a specific root hash. 155 func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { 156 tr, err := trie.NewStateTrie(common.Hash{}, root, db.db) 157 if err != nil { 158 return nil, err 159 } 160 return tr, nil 161 } 162 163 // OpenStorageTrie opens the storage trie of an account. 164 func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) { 165 tr, err := trie.NewStateTrie(addrHash, root, db.db) 166 if err != nil { 167 return nil, err 168 } 169 return tr, nil 170 } 171 172 // CopyTrie returns an independent copy of the given trie. 173 func (db *cachingDB) CopyTrie(t Trie) Trie { 174 switch t := t.(type) { 175 case *trie.StateTrie: 176 return t.Copy() 177 default: 178 panic(fmt.Errorf("unknown trie type %T", t)) 179 } 180 } 181 182 // ContractCode retrieves a particular contract's code. 183 func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) { 184 if code := db.codeCache.Get(nil, codeHash.Bytes()); len(code) > 0 { 185 return code, nil 186 } 187 code := rawdb.ReadCode(db.db.DiskDB(), codeHash) 188 if len(code) > 0 { 189 db.codeCache.Set(codeHash.Bytes(), code) 190 db.codeSizeCache.Add(codeHash, len(code)) 191 return code, nil 192 } 193 return nil, errors.New("not found") 194 } 195 196 // ContractCodeSize retrieves a particular contracts code's size. 197 func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) { 198 if cached, ok := db.codeSizeCache.Get(codeHash); ok { 199 return cached.(int), nil 200 } 201 code, err := db.ContractCode(addrHash, codeHash) 202 return len(code), err 203 } 204 205 // TrieDB retrieves any intermediate trie-node caching layer. 206 func (db *cachingDB) TrieDB() *trie.Database { 207 return db.db 208 }