github.com/MetalBlockchain/subnet-evm@v0.4.9/trie/secure_trie.go (about) 1 // (c) 2020-2021, 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 2015 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 trie 28 29 import ( 30 "fmt" 31 32 "github.com/MetalBlockchain/subnet-evm/core/types" 33 "github.com/ethereum/go-ethereum/common" 34 "github.com/ethereum/go-ethereum/log" 35 "github.com/ethereum/go-ethereum/rlp" 36 ) 37 38 // SecureTrie is the old name of StateTrie. 39 // Deprecated: use StateTrie. 40 type SecureTrie = StateTrie 41 42 // NewSecure creates a new StateTrie. 43 // Deprecated: use NewStateTrie. 44 func NewSecure(owner common.Hash, root common.Hash, db *Database) (*SecureTrie, error) { 45 return NewStateTrie(owner, root, db) 46 } 47 48 // StateTrie wraps a trie with key hashing. In a secure trie, all 49 // access operations hash the key using keccak256. This prevents 50 // calling code from creating long chains of nodes that 51 // increase the access time. 52 // 53 // Contrary to a regular trie, a StateTrie can only be created with 54 // New and must have an attached database. The database also stores 55 // the preimage of each key. 56 // 57 // StateTrie is not safe for concurrent use. 58 type StateTrie struct { 59 trie Trie 60 preimages *preimageStore 61 hashKeyBuf [common.HashLength]byte 62 secKeyCache map[string][]byte 63 secKeyCacheOwner *StateTrie // Pointer to self, replace the key cache on mismatch 64 } 65 66 // NewStateTrie creates a trie with an existing root node from a backing database 67 // and optional intermediate in-memory node pool. 68 // 69 // If root is the zero hash or the sha3 hash of an empty string, the 70 // trie is initially empty. Otherwise, New will panic if db is nil 71 // and returns MissingNodeError if the root node cannot be found. 72 // 73 // Accessing the trie loads nodes from the database or node pool on demand. 74 // Loaded nodes are kept around until their 'cache generation' expires. 75 // A new cache generation is created by each call to Commit. 76 // cachelimit sets the number of past cache generations to keep. 77 func NewStateTrie(owner common.Hash, root common.Hash, db *Database) (*StateTrie, error) { 78 if db == nil { 79 panic("trie.NewSecure called without a database") 80 } 81 trie, err := New(owner, root, db) 82 if err != nil { 83 return nil, err 84 } 85 return &StateTrie{trie: *trie, preimages: db.preimages}, nil 86 } 87 88 // Get returns the value for key stored in the trie. 89 // The value bytes must not be modified by the caller. 90 func (t *StateTrie) Get(key []byte) []byte { 91 res, err := t.TryGet(key) 92 if err != nil { 93 log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) 94 } 95 return res 96 } 97 98 // TryGet returns the value for key stored in the trie. 99 // The value bytes must not be modified by the caller. 100 // If a node was not found in the database, a MissingNodeError is returned. 101 func (t *StateTrie) TryGet(key []byte) ([]byte, error) { 102 return t.trie.TryGet(t.hashKey(key)) 103 } 104 105 func (t *StateTrie) TryGetAccount(key []byte) (*types.StateAccount, error) { 106 var ret types.StateAccount 107 res, err := t.trie.TryGet(t.hashKey(key)) 108 if err != nil { 109 log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) 110 return &ret, err 111 } 112 if res == nil { 113 return nil, nil 114 } 115 err = rlp.DecodeBytes(res, &ret) 116 return &ret, err 117 } 118 119 // TryGetAccountWithPreHashedKey does the same thing as TryGetAccount, however 120 // it expects a key that is already hashed. This constitutes an abstraction leak, 121 // since the client code needs to know the key format. 122 func (t *StateTrie) TryGetAccountWithPreHashedKey(key []byte) (*types.StateAccount, error) { 123 var ret types.StateAccount 124 res, err := t.trie.TryGet(key) 125 if err != nil { 126 log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) 127 return &ret, err 128 } 129 if res == nil { 130 return nil, nil 131 } 132 err = rlp.DecodeBytes(res, &ret) 133 return &ret, err 134 } 135 136 // TryGetNode attempts to retrieve a trie node by compact-encoded path. It is not 137 // possible to use keybyte-encoding as the path might contain odd nibbles. 138 func (t *StateTrie) TryGetNode(path []byte) ([]byte, int, error) { 139 return t.trie.TryGetNode(path) 140 } 141 142 // TryUpdateAccount account will abstract the write of an account to the 143 // secure trie. 144 func (t *StateTrie) TryUpdateAccount(key []byte, acc *types.StateAccount) error { 145 hk := t.hashKey(key) 146 data, err := rlp.EncodeToBytes(acc) 147 if err != nil { 148 return err 149 } 150 if err := t.trie.TryUpdate(hk, data); err != nil { 151 return err 152 } 153 t.getSecKeyCache()[string(hk)] = common.CopyBytes(key) 154 return nil 155 } 156 157 // Update associates key with value in the trie. Subsequent calls to 158 // Get will return value. If value has length zero, any existing value 159 // is deleted from the trie and calls to Get will return nil. 160 // 161 // The value bytes must not be modified by the caller while they are 162 // stored in the trie. 163 func (t *StateTrie) Update(key, value []byte) { 164 if err := t.TryUpdate(key, value); err != nil { 165 log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) 166 } 167 } 168 169 // TryUpdate associates key with value in the trie. Subsequent calls to 170 // Get will return value. If value has length zero, any existing value 171 // is deleted from the trie and calls to Get will return nil. 172 // 173 // The value bytes must not be modified by the caller while they are 174 // stored in the trie. 175 // 176 // If a node was not found in the database, a MissingNodeError is returned. 177 func (t *StateTrie) TryUpdate(key, value []byte) error { 178 hk := t.hashKey(key) 179 err := t.trie.TryUpdate(hk, value) 180 if err != nil { 181 return err 182 } 183 t.getSecKeyCache()[string(hk)] = common.CopyBytes(key) 184 return nil 185 } 186 187 // Delete removes any existing value for key from the trie. 188 func (t *StateTrie) Delete(key []byte) { 189 if err := t.TryDelete(key); err != nil { 190 log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) 191 } 192 } 193 194 // TryDelete removes any existing value for key from the trie. 195 // If a node was not found in the database, a MissingNodeError is returned. 196 func (t *StateTrie) TryDelete(key []byte) error { 197 hk := t.hashKey(key) 198 delete(t.getSecKeyCache(), string(hk)) 199 return t.trie.TryDelete(hk) 200 } 201 202 // TryDeleteAccount abstracts an account deletion from the trie. 203 func (t *StateTrie) TryDeleteAccount(key []byte) error { 204 hk := t.hashKey(key) 205 delete(t.getSecKeyCache(), string(hk)) 206 return t.trie.TryDelete(hk) 207 } 208 209 // GetKey returns the sha3 preimage of a hashed key that was 210 // previously used to store a value. 211 func (t *StateTrie) GetKey(shaKey []byte) []byte { 212 if key, ok := t.getSecKeyCache()[string(shaKey)]; ok { 213 return key 214 } 215 if t.preimages == nil { 216 return nil 217 } 218 return t.preimages.preimage(common.BytesToHash(shaKey)) 219 } 220 221 // Commit collects all dirty nodes in the trie and replace them with the 222 // corresponding node hash. All collected nodes(including dirty leaves if 223 // collectLeaf is true) will be encapsulated into a nodeset for return. 224 // The returned nodeset can be nil if the trie is clean(nothing to commit). 225 // All cached preimages will be also flushed if preimages recording is enabled. 226 // Once the trie is committed, it's not usable anymore. A new trie must 227 // be created with new root and updated trie database for following usage 228 func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *NodeSet, error) { 229 // Write all the pre-images to the actual disk database 230 if len(t.getSecKeyCache()) > 0 { 231 if t.preimages != nil { 232 preimages := make(map[common.Hash][]byte) 233 for hk, key := range t.secKeyCache { 234 preimages[common.BytesToHash([]byte(hk))] = key 235 } 236 t.preimages.insertPreimage(preimages) 237 } 238 t.secKeyCache = make(map[string][]byte) 239 } 240 // Commit the trie to its intermediate node database 241 return t.trie.Commit(collectLeaf) 242 } 243 244 // Hash returns the root hash of StateTrie. It does not write to the 245 // database and can be used even if the trie doesn't have one. 246 func (t *StateTrie) Hash() common.Hash { 247 return t.trie.Hash() 248 } 249 250 // Copy returns a copy of StateTrie. 251 func (t *StateTrie) Copy() *StateTrie { 252 return &StateTrie{ 253 trie: *t.trie.Copy(), 254 preimages: t.preimages, 255 secKeyCache: t.secKeyCache, 256 } 257 } 258 259 // NodeIterator returns an iterator that returns nodes of the underlying trie. Iteration 260 // starts at the key after the given start key. 261 func (t *StateTrie) NodeIterator(start []byte) NodeIterator { 262 return t.trie.NodeIterator(start) 263 } 264 265 // hashKey returns the hash of key as an ephemeral buffer. 266 // The caller must not hold onto the return value because it will become 267 // invalid on the next call to hashKey or secKey. 268 func (t *StateTrie) hashKey(key []byte) []byte { 269 h := newHasher(false) 270 h.sha.Reset() 271 h.sha.Write(key) 272 h.sha.Read(t.hashKeyBuf[:]) 273 returnHasherToPool(h) 274 return t.hashKeyBuf[:] 275 } 276 277 // getSecKeyCache returns the current secure key cache, creating a new one if 278 // ownership changed (i.e. the current secure trie is a copy of another owning 279 // the actual cache). 280 func (t *StateTrie) getSecKeyCache() map[string][]byte { 281 if t != t.secKeyCacheOwner { 282 t.secKeyCacheOwner = t 283 t.secKeyCache = make(map[string][]byte) 284 } 285 return t.secKeyCache 286 }