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