github.com/tacshi/go-ethereum@v0.0.0-20230616113857-84a434e20921/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 "bufio" 21 "bytes" 22 "encoding/gob" 23 "errors" 24 "io" 25 "sync" 26 27 "github.com/tacshi/go-ethereum/common" 28 "github.com/tacshi/go-ethereum/core/types" 29 "github.com/tacshi/go-ethereum/log" 30 ) 31 32 var ErrCommitDisabled = errors.New("no database for committing") 33 34 var stPool = sync.Pool{ 35 New: func() interface{} { 36 return NewStackTrie(nil) 37 }, 38 } 39 40 // NodeWriteFunc is used to provide all information of a dirty node for committing 41 // so that callers can flush nodes into database with desired scheme. 42 type NodeWriteFunc = func(owner common.Hash, path []byte, hash common.Hash, blob []byte) 43 44 func stackTrieFromPool(writeFn NodeWriteFunc, owner common.Hash) *StackTrie { 45 st := stPool.Get().(*StackTrie) 46 st.owner = owner 47 st.writeFn = writeFn 48 return st 49 } 50 51 func returnToPool(st *StackTrie) { 52 st.Reset() 53 stPool.Put(st) 54 } 55 56 // StackTrie is a trie implementation that expects keys to be inserted 57 // in order. Once it determines that a subtree will no longer be inserted 58 // into, it will hash it and free up the memory it uses. 59 type StackTrie struct { 60 owner common.Hash // the owner of the trie 61 nodeType uint8 // node type (as in branch, ext, leaf) 62 val []byte // value contained by this node if it's a leaf 63 key []byte // key chunk covered by this (leaf|ext) node 64 children [16]*StackTrie // list of children (for branch and exts) 65 writeFn NodeWriteFunc // function for committing nodes, can be nil 66 } 67 68 // NewStackTrie allocates and initializes an empty trie. 69 func NewStackTrie(writeFn NodeWriteFunc) *StackTrie { 70 return &StackTrie{ 71 nodeType: emptyNode, 72 writeFn: writeFn, 73 } 74 } 75 76 // NewStackTrieWithOwner allocates and initializes an empty trie, but with 77 // the additional owner field. 78 func NewStackTrieWithOwner(writeFn NodeWriteFunc, owner common.Hash) *StackTrie { 79 return &StackTrie{ 80 owner: owner, 81 nodeType: emptyNode, 82 writeFn: writeFn, 83 } 84 } 85 86 // NewFromBinary initialises a serialized stacktrie with the given db. 87 func NewFromBinary(data []byte, writeFn NodeWriteFunc) (*StackTrie, error) { 88 var st StackTrie 89 if err := st.UnmarshalBinary(data); err != nil { 90 return nil, err 91 } 92 // If a database is used, we need to recursively add it to every child 93 if writeFn != nil { 94 st.setWriter(writeFn) 95 } 96 return &st, nil 97 } 98 99 // MarshalBinary implements encoding.BinaryMarshaler 100 func (st *StackTrie) MarshalBinary() (data []byte, err error) { 101 var ( 102 b bytes.Buffer 103 w = bufio.NewWriter(&b) 104 ) 105 if err := gob.NewEncoder(w).Encode(struct { 106 Owner common.Hash 107 NodeType uint8 108 Val []byte 109 Key []byte 110 }{ 111 st.owner, 112 st.nodeType, 113 st.val, 114 st.key, 115 }); err != nil { 116 return nil, err 117 } 118 for _, child := range st.children { 119 if child == nil { 120 w.WriteByte(0) 121 continue 122 } 123 w.WriteByte(1) 124 if childData, err := child.MarshalBinary(); err != nil { 125 return nil, err 126 } else { 127 w.Write(childData) 128 } 129 } 130 w.Flush() 131 return b.Bytes(), nil 132 } 133 134 // UnmarshalBinary implements encoding.BinaryUnmarshaler 135 func (st *StackTrie) UnmarshalBinary(data []byte) error { 136 r := bytes.NewReader(data) 137 return st.unmarshalBinary(r) 138 } 139 140 func (st *StackTrie) unmarshalBinary(r io.Reader) error { 141 var dec struct { 142 Owner common.Hash 143 NodeType uint8 144 Val []byte 145 Key []byte 146 } 147 gob.NewDecoder(r).Decode(&dec) 148 st.owner = dec.Owner 149 st.nodeType = dec.NodeType 150 st.val = dec.Val 151 st.key = dec.Key 152 153 var hasChild = make([]byte, 1) 154 for i := range st.children { 155 if _, err := r.Read(hasChild); err != nil { 156 return err 157 } else if hasChild[0] == 0 { 158 continue 159 } 160 var child StackTrie 161 child.unmarshalBinary(r) 162 st.children[i] = &child 163 } 164 return nil 165 } 166 167 func (st *StackTrie) setWriter(writeFn NodeWriteFunc) { 168 st.writeFn = writeFn 169 for _, child := range st.children { 170 if child != nil { 171 child.setWriter(writeFn) 172 } 173 } 174 } 175 176 func newLeaf(owner common.Hash, key, val []byte, writeFn NodeWriteFunc) *StackTrie { 177 st := stackTrieFromPool(writeFn, owner) 178 st.nodeType = leafNode 179 st.key = append(st.key, key...) 180 st.val = val 181 return st 182 } 183 184 func newExt(owner common.Hash, key []byte, child *StackTrie, writeFn NodeWriteFunc) *StackTrie { 185 st := stackTrieFromPool(writeFn, owner) 186 st.nodeType = extNode 187 st.key = append(st.key, key...) 188 st.children[0] = child 189 return st 190 } 191 192 // List all values that StackTrie#nodeType can hold 193 const ( 194 emptyNode = iota 195 branchNode 196 extNode 197 leafNode 198 hashedNode 199 ) 200 201 // TryUpdate inserts a (key, value) pair into the stack trie 202 func (st *StackTrie) TryUpdate(key, value []byte) error { 203 k := keybytesToHex(key) 204 if len(value) == 0 { 205 panic("deletion not supported") 206 } 207 st.insert(k[:len(k)-1], value, nil) 208 return nil 209 } 210 211 func (st *StackTrie) Update(key, value []byte) { 212 if err := st.TryUpdate(key, value); err != nil { 213 log.Error("Unhandled trie error in StackTrie.Update", "err", err) 214 } 215 } 216 217 func (st *StackTrie) Reset() { 218 st.owner = common.Hash{} 219 st.writeFn = nil 220 st.key = st.key[:0] 221 st.val = nil 222 for i := range st.children { 223 st.children[i] = nil 224 } 225 st.nodeType = emptyNode 226 } 227 228 // Helper function that, given a full key, determines the index 229 // at which the chunk pointed by st.keyOffset is different from 230 // the same chunk in the full key. 231 func (st *StackTrie) getDiffIndex(key []byte) int { 232 for idx, nibble := range st.key { 233 if nibble != key[idx] { 234 return idx 235 } 236 } 237 return len(st.key) 238 } 239 240 // Helper function to that inserts a (key, value) pair into 241 // the trie. 242 func (st *StackTrie) insert(key, value []byte, prefix []byte) { 243 switch st.nodeType { 244 case branchNode: /* Branch */ 245 idx := int(key[0]) 246 247 // Unresolve elder siblings 248 for i := idx - 1; i >= 0; i-- { 249 if st.children[i] != nil { 250 if st.children[i].nodeType != hashedNode { 251 st.children[i].hash(append(prefix, byte(i))) 252 } 253 break 254 } 255 } 256 257 // Add new child 258 if st.children[idx] == nil { 259 st.children[idx] = newLeaf(st.owner, key[1:], value, st.writeFn) 260 } else { 261 st.children[idx].insert(key[1:], value, append(prefix, key[0])) 262 } 263 264 case extNode: /* Ext */ 265 // Compare both key chunks and see where they differ 266 diffidx := st.getDiffIndex(key) 267 268 // Check if chunks are identical. If so, recurse into 269 // the child node. Otherwise, the key has to be split 270 // into 1) an optional common prefix, 2) the fullnode 271 // representing the two differing path, and 3) a leaf 272 // for each of the differentiated subtrees. 273 if diffidx == len(st.key) { 274 // Ext key and key segment are identical, recurse into 275 // the child node. 276 st.children[0].insert(key[diffidx:], value, append(prefix, key[:diffidx]...)) 277 return 278 } 279 // Save the original part. Depending if the break is 280 // at the extension's last byte or not, create an 281 // intermediate extension or use the extension's child 282 // node directly. 283 var n *StackTrie 284 if diffidx < len(st.key)-1 { 285 // Break on the non-last byte, insert an intermediate 286 // extension. The path prefix of the newly-inserted 287 // extension should also contain the different byte. 288 n = newExt(st.owner, st.key[diffidx+1:], st.children[0], st.writeFn) 289 n.hash(append(prefix, st.key[:diffidx+1]...)) 290 } else { 291 // Break on the last byte, no need to insert 292 // an extension node: reuse the current node. 293 // The path prefix of the original part should 294 // still be same. 295 n = st.children[0] 296 n.hash(append(prefix, st.key...)) 297 } 298 var p *StackTrie 299 if diffidx == 0 { 300 // the break is on the first byte, so 301 // the current node is converted into 302 // a branch node. 303 st.children[0] = nil 304 p = st 305 st.nodeType = branchNode 306 } else { 307 // the common prefix is at least one byte 308 // long, insert a new intermediate branch 309 // node. 310 st.children[0] = stackTrieFromPool(st.writeFn, st.owner) 311 st.children[0].nodeType = branchNode 312 p = st.children[0] 313 } 314 // Create a leaf for the inserted part 315 o := newLeaf(st.owner, key[diffidx+1:], value, st.writeFn) 316 317 // Insert both child leaves where they belong: 318 origIdx := st.key[diffidx] 319 newIdx := key[diffidx] 320 p.children[origIdx] = n 321 p.children[newIdx] = o 322 st.key = st.key[:diffidx] 323 324 case leafNode: /* Leaf */ 325 // Compare both key chunks and see where they differ 326 diffidx := st.getDiffIndex(key) 327 328 // Overwriting a key isn't supported, which means that 329 // the current leaf is expected to be split into 1) an 330 // optional extension for the common prefix of these 2 331 // keys, 2) a fullnode selecting the path on which the 332 // keys differ, and 3) one leaf for the differentiated 333 // component of each key. 334 if diffidx >= len(st.key) { 335 panic("Trying to insert into existing key") 336 } 337 338 // Check if the split occurs at the first nibble of the 339 // chunk. In that case, no prefix extnode is necessary. 340 // Otherwise, create that 341 var p *StackTrie 342 if diffidx == 0 { 343 // Convert current leaf into a branch 344 st.nodeType = branchNode 345 p = st 346 st.children[0] = nil 347 } else { 348 // Convert current node into an ext, 349 // and insert a child branch node. 350 st.nodeType = extNode 351 st.children[0] = NewStackTrieWithOwner(st.writeFn, st.owner) 352 st.children[0].nodeType = branchNode 353 p = st.children[0] 354 } 355 356 // Create the two child leaves: one containing the original 357 // value and another containing the new value. The child leaf 358 // is hashed directly in order to free up some memory. 359 origIdx := st.key[diffidx] 360 p.children[origIdx] = newLeaf(st.owner, st.key[diffidx+1:], st.val, st.writeFn) 361 p.children[origIdx].hash(append(prefix, st.key[:diffidx+1]...)) 362 363 newIdx := key[diffidx] 364 p.children[newIdx] = newLeaf(st.owner, key[diffidx+1:], value, st.writeFn) 365 366 // Finally, cut off the key part that has been passed 367 // over to the children. 368 st.key = st.key[:diffidx] 369 st.val = nil 370 371 case emptyNode: /* Empty */ 372 st.nodeType = leafNode 373 st.key = key 374 st.val = value 375 376 case hashedNode: 377 panic("trying to insert into hash") 378 379 default: 380 panic("invalid type") 381 } 382 } 383 384 // hash converts st into a 'hashedNode', if possible. Possible outcomes: 385 // 386 // 1. The rlp-encoded value was >= 32 bytes: 387 // - Then the 32-byte `hash` will be accessible in `st.val`. 388 // - And the 'st.type' will be 'hashedNode' 389 // 390 // 2. The rlp-encoded value was < 32 bytes 391 // - Then the <32 byte rlp-encoded value will be accessible in 'st.val'. 392 // - And the 'st.type' will be 'hashedNode' AGAIN 393 // 394 // This method also sets 'st.type' to hashedNode, and clears 'st.key'. 395 func (st *StackTrie) hash(path []byte) { 396 h := newHasher(false) 397 defer returnHasherToPool(h) 398 399 st.hashRec(h, path) 400 } 401 402 func (st *StackTrie) hashRec(hasher *hasher, path []byte) { 403 // The switch below sets this to the RLP-encoding of this node. 404 var encodedNode []byte 405 406 switch st.nodeType { 407 case hashedNode: 408 return 409 410 case emptyNode: 411 st.val = types.EmptyRootHash.Bytes() 412 st.key = st.key[:0] 413 st.nodeType = hashedNode 414 return 415 416 case branchNode: 417 var nodes rawFullNode 418 for i, child := range st.children { 419 if child == nil { 420 nodes[i] = nilValueNode 421 continue 422 } 423 child.hashRec(hasher, append(path, byte(i))) 424 if len(child.val) < 32 { 425 nodes[i] = rawNode(child.val) 426 } else { 427 nodes[i] = hashNode(child.val) 428 } 429 430 // Release child back to pool. 431 st.children[i] = nil 432 returnToPool(child) 433 } 434 435 nodes.encode(hasher.encbuf) 436 encodedNode = hasher.encodedBytes() 437 438 case extNode: 439 st.children[0].hashRec(hasher, append(path, st.key...)) 440 441 n := rawShortNode{Key: hexToCompact(st.key)} 442 if len(st.children[0].val) < 32 { 443 n.Val = rawNode(st.children[0].val) 444 } else { 445 n.Val = hashNode(st.children[0].val) 446 } 447 448 n.encode(hasher.encbuf) 449 encodedNode = hasher.encodedBytes() 450 451 // Release child back to pool. 452 returnToPool(st.children[0]) 453 st.children[0] = nil 454 455 case leafNode: 456 st.key = append(st.key, byte(16)) 457 n := rawShortNode{Key: hexToCompact(st.key), Val: valueNode(st.val)} 458 459 n.encode(hasher.encbuf) 460 encodedNode = hasher.encodedBytes() 461 462 default: 463 panic("invalid node type") 464 } 465 466 st.nodeType = hashedNode 467 st.key = st.key[:0] 468 if len(encodedNode) < 32 { 469 st.val = common.CopyBytes(encodedNode) 470 return 471 } 472 473 // Write the hash to the 'val'. We allocate a new val here to not mutate 474 // input values 475 st.val = hasher.hashData(encodedNode) 476 if st.writeFn != nil { 477 st.writeFn(st.owner, path, common.BytesToHash(st.val), encodedNode) 478 } 479 } 480 481 // Hash returns the hash of the current node. 482 func (st *StackTrie) Hash() (h common.Hash) { 483 hasher := newHasher(false) 484 defer returnHasherToPool(hasher) 485 486 st.hashRec(hasher, nil) 487 if len(st.val) == 32 { 488 copy(h[:], st.val) 489 return h 490 } 491 // If the node's RLP isn't 32 bytes long, the node will not 492 // be hashed, and instead contain the rlp-encoding of the 493 // node. For the top level node, we need to force the hashing. 494 hasher.sha.Reset() 495 hasher.sha.Write(st.val) 496 hasher.sha.Read(h[:]) 497 return h 498 } 499 500 // Commit will firstly hash the entire trie if it's still not hashed 501 // and then commit all nodes to the associated database. Actually most 502 // of the trie nodes MAY have been committed already. The main purpose 503 // here is to commit the root node. 504 // 505 // The associated database is expected, otherwise the whole commit 506 // functionality should be disabled. 507 func (st *StackTrie) Commit() (h common.Hash, err error) { 508 if st.writeFn == nil { 509 return common.Hash{}, ErrCommitDisabled 510 } 511 hasher := newHasher(false) 512 defer returnHasherToPool(hasher) 513 514 st.hashRec(hasher, nil) 515 if len(st.val) == 32 { 516 copy(h[:], st.val) 517 return h, nil 518 } 519 // If the node's RLP isn't 32 bytes long, the node will not 520 // be hashed (and committed), and instead contain the rlp-encoding of the 521 // node. For the top level node, we need to force the hashing+commit. 522 hasher.sha.Reset() 523 hasher.sha.Write(st.val) 524 hasher.sha.Read(h[:]) 525 526 st.writeFn(st.owner, nil, h, st.val) 527 return h, nil 528 }