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