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