github.com/ethw3/go-ethereuma@v0.0.0-20221013053120-c14602a4c23c/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 "fmt" 25 "io" 26 "sync" 27 28 "github.com/ethw3/go-ethereuma/common" 29 "github.com/ethw3/go-ethereuma/ethdb" 30 "github.com/ethw3/go-ethereuma/log" 31 ) 32 33 var ErrCommitDisabled = errors.New("no database for committing") 34 35 var stPool = sync.Pool{ 36 New: func() interface{} { 37 return NewStackTrie(nil) 38 }, 39 } 40 41 func stackTrieFromPool(db ethdb.KeyValueWriter, owner common.Hash) *StackTrie { 42 st := stPool.Get().(*StackTrie) 43 st.db = db 44 st.owner = owner 45 return st 46 } 47 48 func returnToPool(st *StackTrie) { 49 st.Reset() 50 stPool.Put(st) 51 } 52 53 // StackTrie is a trie implementation that expects keys to be inserted 54 // in order. Once it determines that a subtree will no longer be inserted 55 // into, it will hash it and free up the memory it uses. 56 type StackTrie struct { 57 owner common.Hash // the owner of the trie 58 nodeType uint8 // node type (as in branch, ext, leaf) 59 val []byte // value contained by this node if it's a leaf 60 key []byte // key chunk covered by this (leaf|ext) node 61 children [16]*StackTrie // list of children (for branch and exts) 62 db ethdb.KeyValueWriter // Pointer to the commit db, can be nil 63 } 64 65 // NewStackTrie allocates and initializes an empty trie. 66 func NewStackTrie(db ethdb.KeyValueWriter) *StackTrie { 67 return &StackTrie{ 68 nodeType: emptyNode, 69 db: db, 70 } 71 } 72 73 // NewStackTrieWithOwner allocates and initializes an empty trie, but with 74 // the additional owner field. 75 func NewStackTrieWithOwner(db ethdb.KeyValueWriter, owner common.Hash) *StackTrie { 76 return &StackTrie{ 77 owner: owner, 78 nodeType: emptyNode, 79 db: db, 80 } 81 } 82 83 // NewFromBinary initialises a serialized stacktrie with the given db. 84 func NewFromBinary(data []byte, db ethdb.KeyValueWriter) (*StackTrie, error) { 85 var st StackTrie 86 if err := st.UnmarshalBinary(data); err != nil { 87 return nil, err 88 } 89 // If a database is used, we need to recursively add it to every child 90 if db != nil { 91 st.setDb(db) 92 } 93 return &st, nil 94 } 95 96 // MarshalBinary implements encoding.BinaryMarshaler 97 func (st *StackTrie) MarshalBinary() (data []byte, err error) { 98 var ( 99 b bytes.Buffer 100 w = bufio.NewWriter(&b) 101 ) 102 if err := gob.NewEncoder(w).Encode(struct { 103 Owner common.Hash 104 NodeType uint8 105 Val []byte 106 Key []byte 107 }{ 108 st.owner, 109 st.nodeType, 110 st.val, 111 st.key, 112 }); err != nil { 113 return nil, err 114 } 115 for _, child := range st.children { 116 if child == nil { 117 w.WriteByte(0) 118 continue 119 } 120 w.WriteByte(1) 121 if childData, err := child.MarshalBinary(); err != nil { 122 return nil, err 123 } else { 124 w.Write(childData) 125 } 126 } 127 w.Flush() 128 return b.Bytes(), nil 129 } 130 131 // UnmarshalBinary implements encoding.BinaryUnmarshaler 132 func (st *StackTrie) UnmarshalBinary(data []byte) error { 133 r := bytes.NewReader(data) 134 return st.unmarshalBinary(r) 135 } 136 137 func (st *StackTrie) unmarshalBinary(r io.Reader) error { 138 var dec struct { 139 Owner common.Hash 140 NodeType uint8 141 Val []byte 142 Key []byte 143 } 144 gob.NewDecoder(r).Decode(&dec) 145 st.owner = dec.Owner 146 st.nodeType = dec.NodeType 147 st.val = dec.Val 148 st.key = dec.Key 149 150 var hasChild = make([]byte, 1) 151 for i := range st.children { 152 if _, err := r.Read(hasChild); err != nil { 153 return err 154 } else if hasChild[0] == 0 { 155 continue 156 } 157 var child StackTrie 158 child.unmarshalBinary(r) 159 st.children[i] = &child 160 } 161 return nil 162 } 163 164 func (st *StackTrie) setDb(db ethdb.KeyValueWriter) { 165 st.db = db 166 for _, child := range st.children { 167 if child != nil { 168 child.setDb(db) 169 } 170 } 171 } 172 173 func newLeaf(owner common.Hash, key, val []byte, db ethdb.KeyValueWriter) *StackTrie { 174 st := stackTrieFromPool(db, owner) 175 st.nodeType = leafNode 176 st.key = append(st.key, key...) 177 st.val = val 178 return st 179 } 180 181 func newExt(owner common.Hash, key []byte, child *StackTrie, db ethdb.KeyValueWriter) *StackTrie { 182 st := stackTrieFromPool(db, owner) 183 st.nodeType = extNode 184 st.key = append(st.key, key...) 185 st.children[0] = child 186 return st 187 } 188 189 // List all values that StackTrie#nodeType can hold 190 const ( 191 emptyNode = iota 192 branchNode 193 extNode 194 leafNode 195 hashedNode 196 ) 197 198 // TryUpdate inserts a (key, value) pair into the stack trie 199 func (st *StackTrie) TryUpdate(key, value []byte) error { 200 k := keybytesToHex(key) 201 if len(value) == 0 { 202 panic("deletion not supported") 203 } 204 st.insert(k[:len(k)-1], value) 205 return nil 206 } 207 208 func (st *StackTrie) Update(key, value []byte) { 209 if err := st.TryUpdate(key, value); err != nil { 210 log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) 211 } 212 } 213 214 func (st *StackTrie) Reset() { 215 st.owner = common.Hash{} 216 st.db = nil 217 st.key = st.key[:0] 218 st.val = nil 219 for i := range st.children { 220 st.children[i] = nil 221 } 222 st.nodeType = emptyNode 223 } 224 225 // Helper function that, given a full key, determines the index 226 // at which the chunk pointed by st.keyOffset is different from 227 // the same chunk in the full key. 228 func (st *StackTrie) getDiffIndex(key []byte) int { 229 for idx, nibble := range st.key { 230 if nibble != key[idx] { 231 return idx 232 } 233 } 234 return len(st.key) 235 } 236 237 // Helper function to that inserts a (key, value) pair into 238 // the trie. 239 func (st *StackTrie) insert(key, value []byte) { 240 switch st.nodeType { 241 case branchNode: /* Branch */ 242 idx := int(key[0]) 243 244 // Unresolve elder siblings 245 for i := idx - 1; i >= 0; i-- { 246 if st.children[i] != nil { 247 if st.children[i].nodeType != hashedNode { 248 st.children[i].hash() 249 } 250 break 251 } 252 } 253 254 // Add new child 255 if st.children[idx] == nil { 256 st.children[idx] = newLeaf(st.owner, key[1:], value, st.db) 257 } else { 258 st.children[idx].insert(key[1:], value) 259 } 260 261 case extNode: /* Ext */ 262 // Compare both key chunks and see where they differ 263 diffidx := st.getDiffIndex(key) 264 265 // Check if chunks are identical. If so, recurse into 266 // the child node. Otherwise, the key has to be split 267 // into 1) an optional common prefix, 2) the fullnode 268 // representing the two differing path, and 3) a leaf 269 // for each of the differentiated subtrees. 270 if diffidx == len(st.key) { 271 // Ext key and key segment are identical, recurse into 272 // the child node. 273 st.children[0].insert(key[diffidx:], value) 274 return 275 } 276 // Save the original part. Depending if the break is 277 // at the extension's last byte or not, create an 278 // intermediate extension or use the extension's child 279 // node directly. 280 var n *StackTrie 281 if diffidx < len(st.key)-1 { 282 n = newExt(st.owner, st.key[diffidx+1:], st.children[0], st.db) 283 } else { 284 // Break on the last byte, no need to insert 285 // an extension node: reuse the current node 286 n = st.children[0] 287 } 288 // Convert to hash 289 n.hash() 290 var p *StackTrie 291 if diffidx == 0 { 292 // the break is on the first byte, so 293 // the current node is converted into 294 // a branch node. 295 st.children[0] = nil 296 p = st 297 st.nodeType = branchNode 298 } else { 299 // the common prefix is at least one byte 300 // long, insert a new intermediate branch 301 // node. 302 st.children[0] = stackTrieFromPool(st.db, st.owner) 303 st.children[0].nodeType = branchNode 304 p = st.children[0] 305 } 306 // Create a leaf for the inserted part 307 o := newLeaf(st.owner, key[diffidx+1:], value, st.db) 308 309 // Insert both child leaves where they belong: 310 origIdx := st.key[diffidx] 311 newIdx := key[diffidx] 312 p.children[origIdx] = n 313 p.children[newIdx] = o 314 st.key = st.key[:diffidx] 315 316 case leafNode: /* Leaf */ 317 // Compare both key chunks and see where they differ 318 diffidx := st.getDiffIndex(key) 319 320 // Overwriting a key isn't supported, which means that 321 // the current leaf is expected to be split into 1) an 322 // optional extension for the common prefix of these 2 323 // keys, 2) a fullnode selecting the path on which the 324 // keys differ, and 3) one leaf for the differentiated 325 // component of each key. 326 if diffidx >= len(st.key) { 327 panic("Trying to insert into existing key") 328 } 329 330 // Check if the split occurs at the first nibble of the 331 // chunk. In that case, no prefix extnode is necessary. 332 // Otherwise, create that 333 var p *StackTrie 334 if diffidx == 0 { 335 // Convert current leaf into a branch 336 st.nodeType = branchNode 337 p = st 338 st.children[0] = nil 339 } else { 340 // Convert current node into an ext, 341 // and insert a child branch node. 342 st.nodeType = extNode 343 st.children[0] = NewStackTrieWithOwner(st.db, st.owner) 344 st.children[0].nodeType = branchNode 345 p = st.children[0] 346 } 347 348 // Create the two child leaves: one containing the original 349 // value and another containing the new value. The child leaf 350 // is hashed directly in order to free up some memory. 351 origIdx := st.key[diffidx] 352 p.children[origIdx] = newLeaf(st.owner, st.key[diffidx+1:], st.val, st.db) 353 p.children[origIdx].hash() 354 355 newIdx := key[diffidx] 356 p.children[newIdx] = newLeaf(st.owner, key[diffidx+1:], value, st.db) 357 358 // Finally, cut off the key part that has been passed 359 // over to the children. 360 st.key = st.key[:diffidx] 361 st.val = nil 362 363 case emptyNode: /* Empty */ 364 st.nodeType = leafNode 365 st.key = key 366 st.val = value 367 368 case hashedNode: 369 panic("trying to insert into hash") 370 371 default: 372 panic("invalid type") 373 } 374 } 375 376 // hash converts st into a 'hashedNode', if possible. Possible outcomes: 377 // 378 // 1. The rlp-encoded value was >= 32 bytes: 379 // - Then the 32-byte `hash` will be accessible in `st.val`. 380 // - And the 'st.type' will be 'hashedNode' 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 }