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