github.com/RobustRoundRobin/quorum@v20.10.0+incompatible/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/core/rawdb" 24 "github.com/ethereum/go-ethereum/ethdb" 25 "github.com/ethereum/go-ethereum/trie" 26 lru "github.com/hashicorp/golang-lru" 27 ) 28 29 const ( 30 // Number of codehash->size associations to keep. 31 codeSizeCacheSize = 100000 32 ) 33 34 // Database wraps access to tries and contract code. 35 type Database interface { 36 // OpenTrie opens the main account trie. 37 OpenTrie(root common.Hash) (Trie, error) 38 39 // OpenStorageTrie opens the storage trie of an account. 40 OpenStorageTrie(addrHash, root common.Hash) (Trie, error) 41 42 // CopyTrie returns an independent copy of the given trie. 43 CopyTrie(Trie) Trie 44 45 // ContractCode retrieves a particular contract's code. 46 ContractCode(addrHash, codeHash common.Hash) ([]byte, error) 47 48 // ContractCodeSize retrieves a particular contracts code's size. 49 ContractCodeSize(addrHash, codeHash common.Hash) (int, error) 50 51 // TrieDB retrieves the low level trie database used for data storage. 52 TrieDB() *trie.Database 53 54 // Privacy metadata linker 55 PrivacyMetadataLinker() rawdb.PrivacyMetadataLinker 56 } 57 58 // Trie is a Ethereum Merkle Patricia trie. 59 type Trie interface { 60 // GetKey returns the sha3 preimage of a hashed key that was previously used 61 // to store a value. 62 // 63 // TODO(fjl): remove this when SecureTrie is removed 64 GetKey([]byte) []byte 65 66 // TryGet returns the value for key stored in the trie. The value bytes must 67 // not be modified by the caller. If a node was not found in the database, a 68 // trie.MissingNodeError is returned. 69 TryGet(key []byte) ([]byte, error) 70 71 // TryUpdate associates key with value in the trie. If value has length zero, any 72 // existing value is deleted from the trie. The value bytes must not be modified 73 // by the caller while they are stored in the trie. If a node was not found in the 74 // database, a trie.MissingNodeError is returned. 75 TryUpdate(key, value []byte) error 76 77 // TryDelete removes any existing value for key from the trie. If a node was not 78 // found in the database, a trie.MissingNodeError is returned. 79 TryDelete(key []byte) error 80 81 // Hash returns the root hash of the trie. It does not write to the database and 82 // can be used even if the trie doesn't have one. 83 Hash() common.Hash 84 85 // Commit writes all nodes to the trie's memory database, tracking the internal 86 // and external (for account tries) references. 87 Commit(onleaf trie.LeafCallback) (common.Hash, error) 88 89 // NodeIterator returns an iterator that returns nodes of the trie. Iteration 90 // starts at the key after the given start key. 91 NodeIterator(startKey []byte) trie.NodeIterator 92 93 // Prove constructs a Merkle proof for key. The result contains all encoded nodes 94 // on the path to the value at key. The value itself is also included in the last 95 // node and can be retrieved by verifying the proof. 96 // 97 // If the trie does not contain a value for key, the returned proof contains all 98 // nodes of the longest existing prefix of the key (at least the root), ending 99 // with the node that proves the absence of the key. 100 Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) error 101 } 102 103 // NewDatabase creates a backing store for state. The returned database is safe for 104 // concurrent use, but does not retain any recent trie nodes in memory. To keep some 105 // historical state in memory, use the NewDatabaseWithCache constructor. 106 func NewDatabase(db ethdb.Database) Database { 107 return NewDatabaseWithCache(db, 0) 108 } 109 110 // NewDatabaseWithCache creates a backing store for state. The returned database 111 // is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a 112 // large memory cache. 113 func NewDatabaseWithCache(db ethdb.Database, cache int) Database { 114 csc, _ := lru.New(codeSizeCacheSize) 115 return &cachingDB{ 116 db: trie.NewDatabaseWithCache(db, cache), 117 // Quorum - Privacy Enhancements 118 privacyMetadataLinker: rawdb.NewPrivacyMetadataLinker(db), 119 codeSizeCache: csc, 120 } 121 } 122 123 type cachingDB struct { 124 db *trie.Database 125 // Quorum: Privacy enhacements introducing privacyMetadataLinker which maintains mapping between private state root and privacy metadata root. As this struct is the backing store for state, this gives the reference to the linker when needed. 126 privacyMetadataLinker rawdb.PrivacyMetadataLinker 127 codeSizeCache *lru.Cache 128 } 129 130 // Quorum - Privacy Enhancements 131 func (db *cachingDB) PrivacyMetadataLinker() rawdb.PrivacyMetadataLinker { 132 return db.privacyMetadataLinker 133 } 134 135 // OpenTrie opens the main account trie at a specific root hash. 136 func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { 137 return trie.NewSecure(root, db.db) 138 } 139 140 // OpenStorageTrie opens the storage trie of an account. 141 func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) { 142 return trie.NewSecure(root, db.db) 143 } 144 145 // CopyTrie returns an independent copy of the given trie. 146 func (db *cachingDB) CopyTrie(t Trie) Trie { 147 switch t := t.(type) { 148 case *trie.SecureTrie: 149 return t.Copy() 150 default: 151 panic(fmt.Errorf("unknown trie type %T", t)) 152 } 153 } 154 155 // ContractCode retrieves a particular contract's code. 156 func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) { 157 code, err := db.db.Node(codeHash) 158 if err == nil { 159 db.codeSizeCache.Add(codeHash, len(code)) 160 } 161 return code, err 162 } 163 164 // ContractCodeSize retrieves a particular contracts code's size. 165 func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) { 166 if cached, ok := db.codeSizeCache.Get(codeHash); ok { 167 return cached.(int), nil 168 } 169 code, err := db.ContractCode(addrHash, codeHash) 170 return len(code), err 171 } 172 173 // TrieDB retrieves any intermediate trie-node caching layer. 174 func (db *cachingDB) TrieDB() *trie.Database { 175 return db.db 176 }