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