github.com/ethereum/go-ethereum@v1.16.1/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 "github.com/ethereum/go-ethereum/common" 21 "github.com/ethereum/go-ethereum/core/types" 22 "github.com/ethereum/go-ethereum/crypto" 23 "github.com/ethereum/go-ethereum/rlp" 24 "github.com/ethereum/go-ethereum/trie/trienode" 25 "github.com/ethereum/go-ethereum/triedb/database" 26 ) 27 28 // preimageStore wraps the methods of a backing store for reading and writing 29 // trie node preimages. 30 type preimageStore interface { 31 // Preimage retrieves the preimage of the specified hash. 32 Preimage(hash common.Hash) []byte 33 34 // InsertPreimage commits a set of preimages along with their hashes. 35 InsertPreimage(preimages map[common.Hash][]byte) 36 37 // PreimageEnabled returns true if the preimage store is enabled. 38 PreimageEnabled() bool 39 } 40 41 // SecureTrie is the old name of StateTrie. 42 // Deprecated: use StateTrie. 43 type SecureTrie = StateTrie 44 45 // NewSecure creates a new StateTrie. 46 // Deprecated: use NewStateTrie. 47 func NewSecure(stateRoot common.Hash, owner common.Hash, root common.Hash, db database.NodeDatabase) (*SecureTrie, error) { 48 id := &ID{ 49 StateRoot: stateRoot, 50 Owner: owner, 51 Root: root, 52 } 53 return NewStateTrie(id, db) 54 } 55 56 // StateTrie wraps a trie with key hashing. In a stateTrie trie, all 57 // access operations hash the key using keccak256. This prevents 58 // calling code from creating long chains of nodes that 59 // increase the access time. 60 // 61 // Contrary to a regular trie, a StateTrie can only be created with 62 // New and must have an attached database. The database also stores 63 // the preimage of each key if preimage recording is enabled. 64 // 65 // StateTrie is not safe for concurrent use. 66 type StateTrie struct { 67 trie Trie 68 db database.NodeDatabase 69 preimages preimageStore 70 secKeyCache map[common.Hash][]byte 71 } 72 73 // NewStateTrie creates a trie with an existing root node from a backing database. 74 // 75 // If root is the zero hash or the sha3 hash of an empty string, the 76 // trie is initially empty. Otherwise, New will panic if db is nil 77 // and returns MissingNodeError if the root node cannot be found. 78 func NewStateTrie(id *ID, db database.NodeDatabase) (*StateTrie, error) { 79 if db == nil { 80 panic("trie.NewStateTrie called without a database") 81 } 82 trie, err := New(id, db) 83 if err != nil { 84 return nil, err 85 } 86 tr := &StateTrie{ 87 trie: *trie, 88 db: db, 89 secKeyCache: make(map[common.Hash][]byte), 90 } 91 92 // link the preimage store if it's supported 93 if preimages, ok := db.(preimageStore); ok && preimages.PreimageEnabled() { 94 tr.preimages = preimages 95 } 96 return tr, nil 97 } 98 99 // MustGet returns the value for key stored in the trie. 100 // The value bytes must not be modified by the caller. 101 // 102 // This function will omit any encountered error but just 103 // print out an error message. 104 func (t *StateTrie) MustGet(key []byte) []byte { 105 return t.trie.MustGet(crypto.Keccak256(key)) 106 } 107 108 // GetStorage attempts to retrieve a storage slot with provided account address 109 // and slot key. The value bytes must not be modified by the caller. 110 // If the specified storage slot is not in the trie, nil will be returned. 111 // If a trie node is not found in the database, a MissingNodeError is returned. 112 func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) { 113 enc, err := t.trie.Get(crypto.Keccak256(key)) 114 if err != nil || len(enc) == 0 { 115 return nil, err 116 } 117 _, content, _, err := rlp.Split(enc) 118 return content, err 119 } 120 121 // GetAccount attempts to retrieve an account with provided account address. 122 // If the specified account is not in the trie, nil will be returned. 123 // If a trie node is not found in the database, a MissingNodeError is returned. 124 func (t *StateTrie) GetAccount(address common.Address) (*types.StateAccount, error) { 125 res, err := t.trie.Get(crypto.Keccak256(address.Bytes())) 126 if res == nil || err != nil { 127 return nil, err 128 } 129 ret := new(types.StateAccount) 130 err = rlp.DecodeBytes(res, ret) 131 return ret, err 132 } 133 134 // GetAccountByHash does the same thing as GetAccount, however it expects an 135 // account hash that is the hash of address. This constitutes an abstraction 136 // leak, since the client code needs to know the key format. 137 func (t *StateTrie) GetAccountByHash(addrHash common.Hash) (*types.StateAccount, error) { 138 res, err := t.trie.Get(addrHash.Bytes()) 139 if res == nil || err != nil { 140 return nil, err 141 } 142 ret := new(types.StateAccount) 143 err = rlp.DecodeBytes(res, ret) 144 return ret, err 145 } 146 147 // GetNode attempts to retrieve a trie node by compact-encoded path. It is not 148 // possible to use keybyte-encoding as the path might contain odd nibbles. 149 // If the specified trie node is not in the trie, nil will be returned. 150 // If a trie node is not found in the database, a MissingNodeError is returned. 151 func (t *StateTrie) GetNode(path []byte) ([]byte, int, error) { 152 return t.trie.GetNode(path) 153 } 154 155 // MustUpdate associates key with value in the trie. Subsequent calls to 156 // Get will return value. If value has length zero, any existing value 157 // is deleted from the trie and calls to Get will return nil. 158 // 159 // The value bytes must not be modified by the caller while they are 160 // stored in the trie. 161 // 162 // This function will omit any encountered error but just print out an 163 // error message. 164 func (t *StateTrie) MustUpdate(key, value []byte) { 165 hk := crypto.Keccak256(key) 166 t.trie.MustUpdate(hk, value) 167 if t.preimages != nil { 168 t.secKeyCache[common.Hash(hk)] = common.CopyBytes(key) 169 } 170 } 171 172 // UpdateStorage associates key with value in the trie. Subsequent calls to 173 // Get will return value. If value has length zero, any existing value 174 // is deleted from the trie and calls to Get will return nil. 175 // 176 // The value bytes must not be modified by the caller while they are 177 // stored in the trie. 178 // 179 // If a node is not found in the database, a MissingNodeError is returned. 180 func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error { 181 hk := crypto.Keccak256(key) 182 v, _ := rlp.EncodeToBytes(value) 183 err := t.trie.Update(hk, v) 184 if err != nil { 185 return err 186 } 187 if t.preimages != nil { 188 t.secKeyCache[common.Hash(hk)] = common.CopyBytes(key) 189 } 190 return nil 191 } 192 193 // UpdateAccount will abstract the write of an account to the secure trie. 194 func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccount, _ int) error { 195 hk := crypto.Keccak256(address.Bytes()) 196 data, err := rlp.EncodeToBytes(acc) 197 if err != nil { 198 return err 199 } 200 if err := t.trie.Update(hk, data); err != nil { 201 return err 202 } 203 if t.preimages != nil { 204 t.secKeyCache[common.Hash(hk)] = address.Bytes() 205 } 206 return nil 207 } 208 209 func (t *StateTrie) UpdateContractCode(_ common.Address, _ common.Hash, _ []byte) error { 210 return nil 211 } 212 213 // MustDelete removes any existing value for key from the trie. This function 214 // will omit any encountered error but just print out an error message. 215 func (t *StateTrie) MustDelete(key []byte) { 216 hk := crypto.Keccak256(key) 217 if t.preimages != nil { 218 delete(t.secKeyCache, common.Hash(hk)) 219 } 220 t.trie.MustDelete(hk) 221 } 222 223 // DeleteStorage removes any existing storage slot from the trie. 224 // If the specified trie node is not in the trie, nothing will be changed. 225 // If a node is not found in the database, a MissingNodeError is returned. 226 func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error { 227 hk := crypto.Keccak256(key) 228 if t.preimages != nil { 229 delete(t.secKeyCache, common.Hash(hk)) 230 } 231 return t.trie.Delete(hk) 232 } 233 234 // DeleteAccount abstracts an account deletion from the trie. 235 func (t *StateTrie) DeleteAccount(address common.Address) error { 236 hk := crypto.Keccak256(address.Bytes()) 237 if t.preimages != nil { 238 delete(t.secKeyCache, common.Hash(hk)) 239 } 240 return t.trie.Delete(hk) 241 } 242 243 // GetKey returns the sha3 preimage of a hashed key that was 244 // previously used to store a value. 245 func (t *StateTrie) GetKey(shaKey []byte) []byte { 246 if t.preimages == nil { 247 return nil 248 } 249 if key, ok := t.secKeyCache[common.BytesToHash(shaKey)]; ok { 250 return key 251 } 252 return t.preimages.Preimage(common.BytesToHash(shaKey)) 253 } 254 255 // Witness returns a set containing all trie nodes that have been accessed. 256 func (t *StateTrie) Witness() map[string]struct{} { 257 return t.trie.Witness() 258 } 259 260 // Commit collects all dirty nodes in the trie and replaces them with the 261 // corresponding node hash. All collected nodes (including dirty leaves if 262 // collectLeaf is true) will be encapsulated into a nodeset for return. 263 // The returned nodeset can be nil if the trie is clean (nothing to commit). 264 // All cached preimages will be also flushed if preimages recording is enabled. 265 // Once the trie is committed, it's not usable anymore. A new trie must 266 // be created with new root and updated trie database for following usage 267 func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) { 268 // Write all the pre-images to the actual disk database 269 if len(t.secKeyCache) > 0 { 270 if t.preimages != nil { 271 t.preimages.InsertPreimage(t.secKeyCache) 272 } 273 clear(t.secKeyCache) 274 } 275 // Commit the trie and return its modified nodeset. 276 return t.trie.Commit(collectLeaf) 277 } 278 279 // Hash returns the root hash of StateTrie. It does not write to the 280 // database and can be used even if the trie doesn't have one. 281 func (t *StateTrie) Hash() common.Hash { 282 return t.trie.Hash() 283 } 284 285 // Copy returns a copy of StateTrie. 286 func (t *StateTrie) Copy() *StateTrie { 287 return &StateTrie{ 288 trie: *t.trie.Copy(), 289 db: t.db, 290 secKeyCache: make(map[common.Hash][]byte), 291 preimages: t.preimages, 292 } 293 } 294 295 // NodeIterator returns an iterator that returns nodes of the underlying trie. 296 // Iteration starts at the key after the given start key. 297 func (t *StateTrie) NodeIterator(start []byte) (NodeIterator, error) { 298 return t.trie.NodeIterator(start) 299 } 300 301 // MustNodeIterator is a wrapper of NodeIterator and will omit any encountered 302 // error but just print out an error message. 303 func (t *StateTrie) MustNodeIterator(start []byte) NodeIterator { 304 return t.trie.MustNodeIterator(start) 305 } 306 307 func (t *StateTrie) IsVerkle() bool { 308 return false 309 }