github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/trie/stacktrie.go (about) 1 // Copyright 2020 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 "bytes" 21 "errors" 22 "sync" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/core/types" 26 ) 27 28 var ( 29 stPool = sync.Pool{New: func() any { return new(stNode) }} 30 _ = types.TrieHasher((*StackTrie)(nil)) 31 ) 32 33 // OnTrieNode is a callback method invoked when a trie node is committed 34 // by the stack trie. The node is only committed if it's considered complete. 35 // 36 // The caller should not modify the contents of the returned path and blob 37 // slice, and their contents may be changed after the call. It is up to the 38 // `onTrieNode` receiver function to deep-copy the data if it wants to retain 39 // it after the call ends. 40 type OnTrieNode func(path []byte, hash common.Hash, blob []byte) 41 42 // StackTrie is a trie implementation that expects keys to be inserted 43 // in order. Once it determines that a subtree will no longer be inserted 44 // into, it will hash it and free up the memory it uses. 45 type StackTrie struct { 46 root *stNode 47 h *hasher 48 last []byte 49 onTrieNode OnTrieNode 50 } 51 52 // NewStackTrie allocates and initializes an empty trie. The committed nodes 53 // will be discarded immediately if no callback is configured. 54 func NewStackTrie(onTrieNode OnTrieNode) *StackTrie { 55 return &StackTrie{ 56 root: stPool.Get().(*stNode), 57 h: newHasher(false), 58 onTrieNode: onTrieNode, 59 } 60 } 61 62 // Update inserts a (key, value) pair into the stack trie. 63 func (t *StackTrie) Update(key, value []byte) error { 64 if len(value) == 0 { 65 return errors.New("trying to insert empty (deletion)") 66 } 67 k := keybytesToHex(key) 68 k = k[:len(k)-1] // chop the termination flag 69 if bytes.Compare(t.last, k) >= 0 { 70 return errors.New("non-ascending key order") 71 } 72 if t.last == nil { 73 t.last = append([]byte{}, k...) // allocate key slice 74 } else { 75 t.last = append(t.last[:0], k...) // reuse key slice 76 } 77 t.insert(t.root, k, value, nil) 78 return nil 79 } 80 81 // Reset resets the stack trie object to empty state. 82 func (t *StackTrie) Reset() { 83 t.root = stPool.Get().(*stNode) 84 t.last = nil 85 } 86 87 // stNode represents a node within a StackTrie 88 type stNode struct { 89 typ uint8 // node type (as in branch, ext, leaf) 90 key []byte // key chunk covered by this (leaf|ext) node 91 val []byte // value contained by this node if it's a leaf 92 children [16]*stNode // list of children (for branch and exts) 93 } 94 95 // newLeaf constructs a leaf node with provided node key and value. The key 96 // will be deep-copied in the function and safe to modify afterwards, but 97 // value is not. 98 func newLeaf(key, val []byte) *stNode { 99 st := stPool.Get().(*stNode) 100 st.typ = leafNode 101 st.key = append(st.key, key...) 102 st.val = val 103 return st 104 } 105 106 // newExt constructs an extension node with provided node key and child. The 107 // key will be deep-copied in the function and safe to modify afterwards. 108 func newExt(key []byte, child *stNode) *stNode { 109 st := stPool.Get().(*stNode) 110 st.typ = extNode 111 st.key = append(st.key, key...) 112 st.children[0] = child 113 return st 114 } 115 116 // List all values that stNode#nodeType can hold 117 const ( 118 emptyNode = iota 119 branchNode 120 extNode 121 leafNode 122 hashedNode 123 ) 124 125 func (n *stNode) reset() *stNode { 126 n.key = n.key[:0] 127 n.val = nil 128 for i := range n.children { 129 n.children[i] = nil 130 } 131 n.typ = emptyNode 132 return n 133 } 134 135 // Helper function that, given a full key, determines the index 136 // at which the chunk pointed by st.keyOffset is different from 137 // the same chunk in the full key. 138 func (n *stNode) getDiffIndex(key []byte) int { 139 for idx, nibble := range n.key { 140 if nibble != key[idx] { 141 return idx 142 } 143 } 144 return len(n.key) 145 } 146 147 // Helper function to that inserts a (key, value) pair into 148 // the trie. 149 func (t *StackTrie) insert(st *stNode, key, value []byte, path []byte) { 150 switch st.typ { 151 case branchNode: /* Branch */ 152 idx := int(key[0]) 153 154 // Unresolve elder siblings 155 for i := idx - 1; i >= 0; i-- { 156 if st.children[i] != nil { 157 if st.children[i].typ != hashedNode { 158 t.hash(st.children[i], append(path, byte(i))) 159 } 160 break 161 } 162 } 163 164 // Add new child 165 if st.children[idx] == nil { 166 st.children[idx] = newLeaf(key[1:], value) 167 } else { 168 t.insert(st.children[idx], key[1:], value, append(path, key[0])) 169 } 170 171 case extNode: /* Ext */ 172 // Compare both key chunks and see where they differ 173 diffidx := st.getDiffIndex(key) 174 175 // Check if chunks are identical. If so, recurse into 176 // the child node. Otherwise, the key has to be split 177 // into 1) an optional common prefix, 2) the fullnode 178 // representing the two differing path, and 3) a leaf 179 // for each of the differentiated subtrees. 180 if diffidx == len(st.key) { 181 // Ext key and key segment are identical, recurse into 182 // the child node. 183 t.insert(st.children[0], key[diffidx:], value, append(path, key[:diffidx]...)) 184 return 185 } 186 // Save the original part. Depending if the break is 187 // at the extension's last byte or not, create an 188 // intermediate extension or use the extension's child 189 // node directly. 190 var n *stNode 191 if diffidx < len(st.key)-1 { 192 // Break on the non-last byte, insert an intermediate 193 // extension. The path prefix of the newly-inserted 194 // extension should also contain the different byte. 195 n = newExt(st.key[diffidx+1:], st.children[0]) 196 t.hash(n, append(path, st.key[:diffidx+1]...)) 197 } else { 198 // Break on the last byte, no need to insert 199 // an extension node: reuse the current node. 200 // The path prefix of the original part should 201 // still be same. 202 n = st.children[0] 203 t.hash(n, append(path, st.key...)) 204 } 205 var p *stNode 206 if diffidx == 0 { 207 // the break is on the first byte, so 208 // the current node is converted into 209 // a branch node. 210 st.children[0] = nil 211 p = st 212 st.typ = branchNode 213 } else { 214 // the common prefix is at least one byte 215 // long, insert a new intermediate branch 216 // node. 217 st.children[0] = stPool.Get().(*stNode) 218 st.children[0].typ = branchNode 219 p = st.children[0] 220 } 221 // Create a leaf for the inserted part 222 o := newLeaf(key[diffidx+1:], value) 223 224 // Insert both child leaves where they belong: 225 origIdx := st.key[diffidx] 226 newIdx := key[diffidx] 227 p.children[origIdx] = n 228 p.children[newIdx] = o 229 st.key = st.key[:diffidx] 230 231 case leafNode: /* Leaf */ 232 // Compare both key chunks and see where they differ 233 diffidx := st.getDiffIndex(key) 234 235 // Overwriting a key isn't supported, which means that 236 // the current leaf is expected to be split into 1) an 237 // optional extension for the common prefix of these 2 238 // keys, 2) a fullnode selecting the path on which the 239 // keys differ, and 3) one leaf for the differentiated 240 // component of each key. 241 if diffidx >= len(st.key) { 242 panic("Trying to insert into existing key") 243 } 244 245 // Check if the split occurs at the first nibble of the 246 // chunk. In that case, no prefix extnode is necessary. 247 // Otherwise, create that 248 var p *stNode 249 if diffidx == 0 { 250 // Convert current leaf into a branch 251 st.typ = branchNode 252 p = st 253 st.children[0] = nil 254 } else { 255 // Convert current node into an ext, 256 // and insert a child branch node. 257 st.typ = extNode 258 st.children[0] = stPool.Get().(*stNode) 259 st.children[0].typ = branchNode 260 p = st.children[0] 261 } 262 263 // Create the two child leaves: one containing the original 264 // value and another containing the new value. The child leaf 265 // is hashed directly in order to free up some memory. 266 origIdx := st.key[diffidx] 267 p.children[origIdx] = newLeaf(st.key[diffidx+1:], st.val) 268 t.hash(p.children[origIdx], append(path, st.key[:diffidx+1]...)) 269 270 newIdx := key[diffidx] 271 p.children[newIdx] = newLeaf(key[diffidx+1:], value) 272 273 // Finally, cut off the key part that has been passed 274 // over to the children. 275 st.key = st.key[:diffidx] 276 st.val = nil 277 278 case emptyNode: /* Empty */ 279 st.typ = leafNode 280 st.key = key 281 st.val = value 282 283 case hashedNode: 284 panic("trying to insert into hash") 285 286 default: 287 panic("invalid type") 288 } 289 } 290 291 // hash converts st into a 'hashedNode', if possible. Possible outcomes: 292 // 293 // 1. The rlp-encoded value was >= 32 bytes: 294 // - Then the 32-byte `hash` will be accessible in `st.val`. 295 // - And the 'st.type' will be 'hashedNode' 296 // 297 // 2. The rlp-encoded value was < 32 bytes 298 // - Then the <32 byte rlp-encoded value will be accessible in 'st.val'. 299 // - And the 'st.type' will be 'hashedNode' AGAIN 300 // 301 // This method also sets 'st.type' to hashedNode, and clears 'st.key'. 302 func (t *StackTrie) hash(st *stNode, path []byte) { 303 var blob []byte // RLP-encoded node blob 304 switch st.typ { 305 case hashedNode: 306 return 307 308 case emptyNode: 309 st.val = types.EmptyRootHash.Bytes() 310 st.key = st.key[:0] 311 st.typ = hashedNode 312 return 313 314 case branchNode: 315 var nodes fullNode 316 for i, child := range st.children { 317 if child == nil { 318 nodes.Children[i] = nilValueNode 319 continue 320 } 321 t.hash(child, append(path, byte(i))) 322 323 if len(child.val) < 32 { 324 nodes.Children[i] = rawNode(child.val) 325 } else { 326 nodes.Children[i] = hashNode(child.val) 327 } 328 st.children[i] = nil 329 stPool.Put(child.reset()) // Release child back to pool. 330 } 331 nodes.encode(t.h.encbuf) 332 blob = t.h.encodedBytes() 333 334 case extNode: 335 // recursively hash and commit child as the first step 336 t.hash(st.children[0], append(path, st.key...)) 337 338 // encode the extension node 339 n := shortNode{Key: hexToCompactInPlace(st.key)} 340 if len(st.children[0].val) < 32 { 341 n.Val = rawNode(st.children[0].val) 342 } else { 343 n.Val = hashNode(st.children[0].val) 344 } 345 n.encode(t.h.encbuf) 346 blob = t.h.encodedBytes() 347 348 stPool.Put(st.children[0].reset()) // Release child back to pool. 349 st.children[0] = nil 350 351 case leafNode: 352 st.key = append(st.key, byte(16)) 353 n := shortNode{Key: hexToCompactInPlace(st.key), Val: valueNode(st.val)} 354 355 n.encode(t.h.encbuf) 356 blob = t.h.encodedBytes() 357 358 default: 359 panic("invalid node type") 360 } 361 // Convert the node type to hashNode and reset the key slice. 362 st.typ = hashedNode 363 st.key = st.key[:0] 364 365 // Skip committing the non-root node if the size is smaller than 32 bytes 366 // as tiny nodes are always embedded in their parent except root node. 367 if len(blob) < 32 && len(path) > 0 { 368 st.val = common.CopyBytes(blob) 369 return 370 } 371 // Write the hash to the 'val'. We allocate a new val here to not mutate 372 // input values. 373 st.val = t.h.hashData(blob) 374 375 // Invoke the callback it's provided. Notably, the path and blob slices are 376 // volatile, please deep-copy the slices in callback if the contents need 377 // to be retained. 378 if t.onTrieNode != nil { 379 t.onTrieNode(path, common.BytesToHash(st.val), blob) 380 } 381 } 382 383 // Hash will firstly hash the entire trie if it's still not hashed and then commit 384 // all leftover nodes to the associated database. Actually most of the trie nodes 385 // have been committed already. The main purpose here is to commit the nodes on 386 // right boundary. 387 func (t *StackTrie) Hash() common.Hash { 388 n := t.root 389 t.hash(n, nil) 390 return common.BytesToHash(n.val) 391 }