github.com/theQRL/go-zond@v0.1.1/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/theQRL/go-zond/common" 28 "github.com/theQRL/go-zond/core/types" 29 "github.com/theQRL/go-zond/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 if err := gob.NewDecoder(r).Decode(&dec); err != nil { 148 return err 149 } 150 st.owner = dec.Owner 151 st.nodeType = dec.NodeType 152 st.val = dec.Val 153 st.key = dec.Key 154 155 var hasChild = make([]byte, 1) 156 for i := range st.children { 157 if _, err := r.Read(hasChild); err != nil { 158 return err 159 } else if hasChild[0] == 0 { 160 continue 161 } 162 var child StackTrie 163 if err := child.unmarshalBinary(r); err != nil { 164 return err 165 } 166 st.children[i] = &child 167 } 168 return nil 169 } 170 171 func (st *StackTrie) setWriter(writeFn NodeWriteFunc) { 172 st.writeFn = writeFn 173 for _, child := range st.children { 174 if child != nil { 175 child.setWriter(writeFn) 176 } 177 } 178 } 179 180 func newLeaf(owner common.Hash, key, val []byte, writeFn NodeWriteFunc) *StackTrie { 181 st := stackTrieFromPool(writeFn, owner) 182 st.nodeType = leafNode 183 st.key = append(st.key, key...) 184 st.val = val 185 return st 186 } 187 188 func newExt(owner common.Hash, key []byte, child *StackTrie, writeFn NodeWriteFunc) *StackTrie { 189 st := stackTrieFromPool(writeFn, owner) 190 st.nodeType = extNode 191 st.key = append(st.key, key...) 192 st.children[0] = child 193 return st 194 } 195 196 // List all values that StackTrie#nodeType can hold 197 const ( 198 emptyNode = iota 199 branchNode 200 extNode 201 leafNode 202 hashedNode 203 ) 204 205 // Update inserts a (key, value) pair into the stack trie. 206 func (st *StackTrie) Update(key, value []byte) error { 207 k := keybytesToHex(key) 208 if len(value) == 0 { 209 panic("deletion not supported") 210 } 211 st.insert(k[:len(k)-1], value, nil) 212 return nil 213 } 214 215 // MustUpdate is a wrapper of Update and will omit any encountered error but 216 // just print out an error message. 217 func (st *StackTrie) MustUpdate(key, value []byte) { 218 if err := st.Update(key, value); err != nil { 219 log.Error("Unhandled trie error in StackTrie.Update", "err", err) 220 } 221 } 222 223 func (st *StackTrie) Reset() { 224 st.owner = common.Hash{} 225 st.writeFn = nil 226 st.key = st.key[:0] 227 st.val = nil 228 for i := range st.children { 229 st.children[i] = nil 230 } 231 st.nodeType = emptyNode 232 } 233 234 // Helper function that, given a full key, determines the index 235 // at which the chunk pointed by st.keyOffset is different from 236 // the same chunk in the full key. 237 func (st *StackTrie) getDiffIndex(key []byte) int { 238 for idx, nibble := range st.key { 239 if nibble != key[idx] { 240 return idx 241 } 242 } 243 return len(st.key) 244 } 245 246 // Helper function to that inserts a (key, value) pair into 247 // the trie. 248 func (st *StackTrie) insert(key, value []byte, prefix []byte) { 249 switch st.nodeType { 250 case branchNode: /* Branch */ 251 idx := int(key[0]) 252 253 // Unresolve elder siblings 254 for i := idx - 1; i >= 0; i-- { 255 if st.children[i] != nil { 256 if st.children[i].nodeType != hashedNode { 257 st.children[i].hash(append(prefix, byte(i))) 258 } 259 break 260 } 261 } 262 263 // Add new child 264 if st.children[idx] == nil { 265 st.children[idx] = newLeaf(st.owner, key[1:], value, st.writeFn) 266 } else { 267 st.children[idx].insert(key[1:], value, append(prefix, key[0])) 268 } 269 270 case extNode: /* Ext */ 271 // Compare both key chunks and see where they differ 272 diffidx := st.getDiffIndex(key) 273 274 // Check if chunks are identical. If so, recurse into 275 // the child node. Otherwise, the key has to be split 276 // into 1) an optional common prefix, 2) the fullnode 277 // representing the two differing path, and 3) a leaf 278 // for each of the differentiated subtrees. 279 if diffidx == len(st.key) { 280 // Ext key and key segment are identical, recurse into 281 // the child node. 282 st.children[0].insert(key[diffidx:], value, append(prefix, key[:diffidx]...)) 283 return 284 } 285 // Save the original part. Depending if the break is 286 // at the extension's last byte or not, create an 287 // intermediate extension or use the extension's child 288 // node directly. 289 var n *StackTrie 290 if diffidx < len(st.key)-1 { 291 // Break on the non-last byte, insert an intermediate 292 // extension. The path prefix of the newly-inserted 293 // extension should also contain the different byte. 294 n = newExt(st.owner, st.key[diffidx+1:], st.children[0], st.writeFn) 295 n.hash(append(prefix, st.key[:diffidx+1]...)) 296 } else { 297 // Break on the last byte, no need to insert 298 // an extension node: reuse the current node. 299 // The path prefix of the original part should 300 // still be same. 301 n = st.children[0] 302 n.hash(append(prefix, st.key...)) 303 } 304 var p *StackTrie 305 if diffidx == 0 { 306 // the break is on the first byte, so 307 // the current node is converted into 308 // a branch node. 309 st.children[0] = nil 310 p = st 311 st.nodeType = branchNode 312 } else { 313 // the common prefix is at least one byte 314 // long, insert a new intermediate branch 315 // node. 316 st.children[0] = stackTrieFromPool(st.writeFn, st.owner) 317 st.children[0].nodeType = branchNode 318 p = st.children[0] 319 } 320 // Create a leaf for the inserted part 321 o := newLeaf(st.owner, key[diffidx+1:], value, st.writeFn) 322 323 // Insert both child leaves where they belong: 324 origIdx := st.key[diffidx] 325 newIdx := key[diffidx] 326 p.children[origIdx] = n 327 p.children[newIdx] = o 328 st.key = st.key[:diffidx] 329 330 case leafNode: /* Leaf */ 331 // Compare both key chunks and see where they differ 332 diffidx := st.getDiffIndex(key) 333 334 // Overwriting a key isn't supported, which means that 335 // the current leaf is expected to be split into 1) an 336 // optional extension for the common prefix of these 2 337 // keys, 2) a fullnode selecting the path on which the 338 // keys differ, and 3) one leaf for the differentiated 339 // component of each key. 340 if diffidx >= len(st.key) { 341 panic("Trying to insert into existing key") 342 } 343 344 // Check if the split occurs at the first nibble of the 345 // chunk. In that case, no prefix extnode is necessary. 346 // Otherwise, create that 347 var p *StackTrie 348 if diffidx == 0 { 349 // Convert current leaf into a branch 350 st.nodeType = branchNode 351 p = st 352 st.children[0] = nil 353 } else { 354 // Convert current node into an ext, 355 // and insert a child branch node. 356 st.nodeType = extNode 357 st.children[0] = NewStackTrieWithOwner(st.writeFn, st.owner) 358 st.children[0].nodeType = branchNode 359 p = st.children[0] 360 } 361 362 // Create the two child leaves: one containing the original 363 // value and another containing the new value. The child leaf 364 // is hashed directly in order to free up some memory. 365 origIdx := st.key[diffidx] 366 p.children[origIdx] = newLeaf(st.owner, st.key[diffidx+1:], st.val, st.writeFn) 367 p.children[origIdx].hash(append(prefix, st.key[:diffidx+1]...)) 368 369 newIdx := key[diffidx] 370 p.children[newIdx] = newLeaf(st.owner, key[diffidx+1:], value, st.writeFn) 371 372 // Finally, cut off the key part that has been passed 373 // over to the children. 374 st.key = st.key[:diffidx] 375 st.val = nil 376 377 case emptyNode: /* Empty */ 378 st.nodeType = leafNode 379 st.key = key 380 st.val = value 381 382 case hashedNode: 383 panic("trying to insert into hash") 384 385 default: 386 panic("invalid type") 387 } 388 } 389 390 // hash converts st into a 'hashedNode', if possible. Possible outcomes: 391 // 392 // 1. The rlp-encoded value was >= 32 bytes: 393 // - Then the 32-byte `hash` will be accessible in `st.val`. 394 // - And the 'st.type' will be 'hashedNode' 395 // 396 // 2. The rlp-encoded value was < 32 bytes 397 // - Then the <32 byte rlp-encoded value will be accessible in 'st.val'. 398 // - And the 'st.type' will be 'hashedNode' AGAIN 399 // 400 // This method also sets 'st.type' to hashedNode, and clears 'st.key'. 401 func (st *StackTrie) hash(path []byte) { 402 h := newHasher(false) 403 defer returnHasherToPool(h) 404 405 st.hashRec(h, path) 406 } 407 408 func (st *StackTrie) hashRec(hasher *hasher, path []byte) { 409 // The switch below sets this to the RLP-encoding of this node. 410 var encodedNode []byte 411 412 switch st.nodeType { 413 case hashedNode: 414 return 415 416 case emptyNode: 417 st.val = types.EmptyRootHash.Bytes() 418 st.key = st.key[:0] 419 st.nodeType = hashedNode 420 return 421 422 case branchNode: 423 var nodes fullNode 424 for i, child := range st.children { 425 if child == nil { 426 nodes.Children[i] = nilValueNode 427 continue 428 } 429 child.hashRec(hasher, append(path, byte(i))) 430 if len(child.val) < 32 { 431 nodes.Children[i] = rawNode(child.val) 432 } else { 433 nodes.Children[i] = hashNode(child.val) 434 } 435 436 // Release child back to pool. 437 st.children[i] = nil 438 returnToPool(child) 439 } 440 441 nodes.encode(hasher.encbuf) 442 encodedNode = hasher.encodedBytes() 443 444 case extNode: 445 st.children[0].hashRec(hasher, append(path, st.key...)) 446 447 n := shortNode{Key: hexToCompactInPlace(st.key)} 448 if len(st.children[0].val) < 32 { 449 n.Val = rawNode(st.children[0].val) 450 } else { 451 n.Val = hashNode(st.children[0].val) 452 } 453 454 n.encode(hasher.encbuf) 455 encodedNode = hasher.encodedBytes() 456 457 // Release child back to pool. 458 returnToPool(st.children[0]) 459 st.children[0] = nil 460 461 case leafNode: 462 st.key = append(st.key, byte(16)) 463 n := shortNode{Key: hexToCompactInPlace(st.key), Val: valueNode(st.val)} 464 465 n.encode(hasher.encbuf) 466 encodedNode = hasher.encodedBytes() 467 468 default: 469 panic("invalid node type") 470 } 471 472 st.nodeType = hashedNode 473 st.key = st.key[:0] 474 if len(encodedNode) < 32 { 475 st.val = common.CopyBytes(encodedNode) 476 return 477 } 478 479 // Write the hash to the 'val'. We allocate a new val here to not mutate 480 // input values 481 st.val = hasher.hashData(encodedNode) 482 if st.writeFn != nil { 483 st.writeFn(st.owner, path, common.BytesToHash(st.val), encodedNode) 484 } 485 } 486 487 // Hash returns the hash of the current node. 488 func (st *StackTrie) Hash() (h common.Hash) { 489 hasher := newHasher(false) 490 defer returnHasherToPool(hasher) 491 492 st.hashRec(hasher, nil) 493 if len(st.val) == 32 { 494 copy(h[:], st.val) 495 return h 496 } 497 // If the node's RLP isn't 32 bytes long, the node will not 498 // be hashed, and instead contain the rlp-encoding of the 499 // node. For the top level node, we need to force the hashing. 500 hasher.sha.Reset() 501 hasher.sha.Write(st.val) 502 hasher.sha.Read(h[:]) 503 return h 504 } 505 506 // Commit will firstly hash the entire trie if it's still not hashed 507 // and then commit all nodes to the associated database. Actually most 508 // of the trie nodes MAY have been committed already. The main purpose 509 // here is to commit the root node. 510 // 511 // The associated database is expected, otherwise the whole commit 512 // functionality should be disabled. 513 func (st *StackTrie) Commit() (h common.Hash, err error) { 514 if st.writeFn == nil { 515 return common.Hash{}, ErrCommitDisabled 516 } 517 hasher := newHasher(false) 518 defer returnHasherToPool(hasher) 519 520 st.hashRec(hasher, nil) 521 if len(st.val) == 32 { 522 copy(h[:], st.val) 523 return h, nil 524 } 525 // If the node's RLP isn't 32 bytes long, the node will not 526 // be hashed (and committed), and instead contain the rlp-encoding of the 527 // node. For the top level node, we need to force the hashing+commit. 528 hasher.sha.Reset() 529 hasher.sha.Write(st.val) 530 hasher.sha.Read(h[:]) 531 532 st.writeFn(st.owner, nil, h, st.val) 533 return h, nil 534 }