github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/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  	"bytes"
    21  	"errors"
    22  	"sync"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/core/types"
    26  )
    27  
    28  var (
    29  	stPool = sync.Pool{New: func() any { return new(stNode) }}
    30  	_      = types.TrieHasher((*StackTrie)(nil))
    31  )
    32  
    33  // OnTrieNode is a callback method invoked when a trie node is committed
    34  // by the stack trie. The node is only committed if it's considered complete.
    35  //
    36  // The caller should not modify the contents of the returned path and blob
    37  // slice, and their contents may be changed after the call. It is up to the
    38  // `onTrieNode` receiver function to deep-copy the data if it wants to retain
    39  // it after the call ends.
    40  type OnTrieNode func(path []byte, hash common.Hash, blob []byte)
    41  
    42  // StackTrie is a trie implementation that expects keys to be inserted
    43  // in order. Once it determines that a subtree will no longer be inserted
    44  // into, it will hash it and free up the memory it uses.
    45  type StackTrie struct {
    46  	root       *stNode
    47  	h          *hasher
    48  	last       []byte
    49  	onTrieNode OnTrieNode
    50  }
    51  
    52  // NewStackTrie allocates and initializes an empty trie. The committed nodes
    53  // will be discarded immediately if no callback is configured.
    54  func NewStackTrie(onTrieNode OnTrieNode) *StackTrie {
    55  	return &StackTrie{
    56  		root:       stPool.Get().(*stNode),
    57  		h:          newHasher(false),
    58  		onTrieNode: onTrieNode,
    59  	}
    60  }
    61  
    62  // Update inserts a (key, value) pair into the stack trie.
    63  func (t *StackTrie) Update(key, value []byte) error {
    64  	if len(value) == 0 {
    65  		return errors.New("trying to insert empty (deletion)")
    66  	}
    67  	k := keybytesToHex(key)
    68  	k = k[:len(k)-1] // chop the termination flag
    69  	if bytes.Compare(t.last, k) >= 0 {
    70  		return errors.New("non-ascending key order")
    71  	}
    72  	if t.last == nil {
    73  		t.last = append([]byte{}, k...) // allocate key slice
    74  	} else {
    75  		t.last = append(t.last[:0], k...) // reuse key slice
    76  	}
    77  	t.insert(t.root, k, value, nil)
    78  	return nil
    79  }
    80  
    81  // Reset resets the stack trie object to empty state.
    82  func (t *StackTrie) Reset() {
    83  	t.root = stPool.Get().(*stNode)
    84  	t.last = nil
    85  }
    86  
    87  // stNode represents a node within a StackTrie
    88  type stNode struct {
    89  	typ      uint8       // node type (as in branch, ext, leaf)
    90  	key      []byte      // key chunk covered by this (leaf|ext) node
    91  	val      []byte      // value contained by this node if it's a leaf
    92  	children [16]*stNode // list of children (for branch and exts)
    93  }
    94  
    95  // newLeaf constructs a leaf node with provided node key and value. The key
    96  // will be deep-copied in the function and safe to modify afterwards, but
    97  // value is not.
    98  func newLeaf(key, val []byte) *stNode {
    99  	st := stPool.Get().(*stNode)
   100  	st.typ = leafNode
   101  	st.key = append(st.key, key...)
   102  	st.val = val
   103  	return st
   104  }
   105  
   106  // newExt constructs an extension node with provided node key and child. The
   107  // key will be deep-copied in the function and safe to modify afterwards.
   108  func newExt(key []byte, child *stNode) *stNode {
   109  	st := stPool.Get().(*stNode)
   110  	st.typ = extNode
   111  	st.key = append(st.key, key...)
   112  	st.children[0] = child
   113  	return st
   114  }
   115  
   116  // List all values that stNode#nodeType can hold
   117  const (
   118  	emptyNode = iota
   119  	branchNode
   120  	extNode
   121  	leafNode
   122  	hashedNode
   123  )
   124  
   125  func (n *stNode) reset() *stNode {
   126  	n.key = n.key[:0]
   127  	n.val = nil
   128  	for i := range n.children {
   129  		n.children[i] = nil
   130  	}
   131  	n.typ = emptyNode
   132  	return n
   133  }
   134  
   135  // Helper function that, given a full key, determines the index
   136  // at which the chunk pointed by st.keyOffset is different from
   137  // the same chunk in the full key.
   138  func (n *stNode) getDiffIndex(key []byte) int {
   139  	for idx, nibble := range n.key {
   140  		if nibble != key[idx] {
   141  			return idx
   142  		}
   143  	}
   144  	return len(n.key)
   145  }
   146  
   147  // Helper function to that inserts a (key, value) pair into
   148  // the trie.
   149  func (t *StackTrie) insert(st *stNode, key, value []byte, path []byte) {
   150  	switch st.typ {
   151  	case branchNode: /* Branch */
   152  		idx := int(key[0])
   153  
   154  		// Unresolve elder siblings
   155  		for i := idx - 1; i >= 0; i-- {
   156  			if st.children[i] != nil {
   157  				if st.children[i].typ != hashedNode {
   158  					t.hash(st.children[i], append(path, byte(i)))
   159  				}
   160  				break
   161  			}
   162  		}
   163  
   164  		// Add new child
   165  		if st.children[idx] == nil {
   166  			st.children[idx] = newLeaf(key[1:], value)
   167  		} else {
   168  			t.insert(st.children[idx], key[1:], value, append(path, key[0]))
   169  		}
   170  
   171  	case extNode: /* Ext */
   172  		// Compare both key chunks and see where they differ
   173  		diffidx := st.getDiffIndex(key)
   174  
   175  		// Check if chunks are identical. If so, recurse into
   176  		// the child node. Otherwise, the key has to be split
   177  		// into 1) an optional common prefix, 2) the fullnode
   178  		// representing the two differing path, and 3) a leaf
   179  		// for each of the differentiated subtrees.
   180  		if diffidx == len(st.key) {
   181  			// Ext key and key segment are identical, recurse into
   182  			// the child node.
   183  			t.insert(st.children[0], key[diffidx:], value, append(path, key[:diffidx]...))
   184  			return
   185  		}
   186  		// Save the original part. Depending if the break is
   187  		// at the extension's last byte or not, create an
   188  		// intermediate extension or use the extension's child
   189  		// node directly.
   190  		var n *stNode
   191  		if diffidx < len(st.key)-1 {
   192  			// Break on the non-last byte, insert an intermediate
   193  			// extension. The path prefix of the newly-inserted
   194  			// extension should also contain the different byte.
   195  			n = newExt(st.key[diffidx+1:], st.children[0])
   196  			t.hash(n, append(path, st.key[:diffidx+1]...))
   197  		} else {
   198  			// Break on the last byte, no need to insert
   199  			// an extension node: reuse the current node.
   200  			// The path prefix of the original part should
   201  			// still be same.
   202  			n = st.children[0]
   203  			t.hash(n, append(path, st.key...))
   204  		}
   205  		var p *stNode
   206  		if diffidx == 0 {
   207  			// the break is on the first byte, so
   208  			// the current node is converted into
   209  			// a branch node.
   210  			st.children[0] = nil
   211  			p = st
   212  			st.typ = branchNode
   213  		} else {
   214  			// the common prefix is at least one byte
   215  			// long, insert a new intermediate branch
   216  			// node.
   217  			st.children[0] = stPool.Get().(*stNode)
   218  			st.children[0].typ = branchNode
   219  			p = st.children[0]
   220  		}
   221  		// Create a leaf for the inserted part
   222  		o := newLeaf(key[diffidx+1:], value)
   223  
   224  		// Insert both child leaves where they belong:
   225  		origIdx := st.key[diffidx]
   226  		newIdx := key[diffidx]
   227  		p.children[origIdx] = n
   228  		p.children[newIdx] = o
   229  		st.key = st.key[:diffidx]
   230  
   231  	case leafNode: /* Leaf */
   232  		// Compare both key chunks and see where they differ
   233  		diffidx := st.getDiffIndex(key)
   234  
   235  		// Overwriting a key isn't supported, which means that
   236  		// the current leaf is expected to be split into 1) an
   237  		// optional extension for the common prefix of these 2
   238  		// keys, 2) a fullnode selecting the path on which the
   239  		// keys differ, and 3) one leaf for the differentiated
   240  		// component of each key.
   241  		if diffidx >= len(st.key) {
   242  			panic("Trying to insert into existing key")
   243  		}
   244  
   245  		// Check if the split occurs at the first nibble of the
   246  		// chunk. In that case, no prefix extnode is necessary.
   247  		// Otherwise, create that
   248  		var p *stNode
   249  		if diffidx == 0 {
   250  			// Convert current leaf into a branch
   251  			st.typ = branchNode
   252  			p = st
   253  			st.children[0] = nil
   254  		} else {
   255  			// Convert current node into an ext,
   256  			// and insert a child branch node.
   257  			st.typ = extNode
   258  			st.children[0] = stPool.Get().(*stNode)
   259  			st.children[0].typ = branchNode
   260  			p = st.children[0]
   261  		}
   262  
   263  		// Create the two child leaves: one containing the original
   264  		// value and another containing the new value. The child leaf
   265  		// is hashed directly in order to free up some memory.
   266  		origIdx := st.key[diffidx]
   267  		p.children[origIdx] = newLeaf(st.key[diffidx+1:], st.val)
   268  		t.hash(p.children[origIdx], append(path, st.key[:diffidx+1]...))
   269  
   270  		newIdx := key[diffidx]
   271  		p.children[newIdx] = newLeaf(key[diffidx+1:], value)
   272  
   273  		// Finally, cut off the key part that has been passed
   274  		// over to the children.
   275  		st.key = st.key[:diffidx]
   276  		st.val = nil
   277  
   278  	case emptyNode: /* Empty */
   279  		st.typ = leafNode
   280  		st.key = key
   281  		st.val = value
   282  
   283  	case hashedNode:
   284  		panic("trying to insert into hash")
   285  
   286  	default:
   287  		panic("invalid type")
   288  	}
   289  }
   290  
   291  // hash converts st into a 'hashedNode', if possible. Possible outcomes:
   292  //
   293  // 1. The rlp-encoded value was >= 32 bytes:
   294  //   - Then the 32-byte `hash` will be accessible in `st.val`.
   295  //   - And the 'st.type' will be 'hashedNode'
   296  //
   297  // 2. The rlp-encoded value was < 32 bytes
   298  //   - Then the <32 byte rlp-encoded value will be accessible in 'st.val'.
   299  //   - And the 'st.type' will be 'hashedNode' AGAIN
   300  //
   301  // This method also sets 'st.type' to hashedNode, and clears 'st.key'.
   302  func (t *StackTrie) hash(st *stNode, path []byte) {
   303  	var blob []byte // RLP-encoded node blob
   304  	switch st.typ {
   305  	case hashedNode:
   306  		return
   307  
   308  	case emptyNode:
   309  		st.val = types.EmptyRootHash.Bytes()
   310  		st.key = st.key[:0]
   311  		st.typ = hashedNode
   312  		return
   313  
   314  	case branchNode:
   315  		var nodes fullNode
   316  		for i, child := range st.children {
   317  			if child == nil {
   318  				nodes.Children[i] = nilValueNode
   319  				continue
   320  			}
   321  			t.hash(child, append(path, byte(i)))
   322  
   323  			if len(child.val) < 32 {
   324  				nodes.Children[i] = rawNode(child.val)
   325  			} else {
   326  				nodes.Children[i] = hashNode(child.val)
   327  			}
   328  			st.children[i] = nil
   329  			stPool.Put(child.reset()) // Release child back to pool.
   330  		}
   331  		nodes.encode(t.h.encbuf)
   332  		blob = t.h.encodedBytes()
   333  
   334  	case extNode:
   335  		// recursively hash and commit child as the first step
   336  		t.hash(st.children[0], append(path, st.key...))
   337  
   338  		// encode the extension node
   339  		n := shortNode{Key: hexToCompactInPlace(st.key)}
   340  		if len(st.children[0].val) < 32 {
   341  			n.Val = rawNode(st.children[0].val)
   342  		} else {
   343  			n.Val = hashNode(st.children[0].val)
   344  		}
   345  		n.encode(t.h.encbuf)
   346  		blob = t.h.encodedBytes()
   347  
   348  		stPool.Put(st.children[0].reset()) // Release child back to pool.
   349  		st.children[0] = nil
   350  
   351  	case leafNode:
   352  		st.key = append(st.key, byte(16))
   353  		n := shortNode{Key: hexToCompactInPlace(st.key), Val: valueNode(st.val)}
   354  
   355  		n.encode(t.h.encbuf)
   356  		blob = t.h.encodedBytes()
   357  
   358  	default:
   359  		panic("invalid node type")
   360  	}
   361  	// Convert the node type to hashNode and reset the key slice.
   362  	st.typ = hashedNode
   363  	st.key = st.key[:0]
   364  
   365  	// Skip committing the non-root node if the size is smaller than 32 bytes
   366  	// as tiny nodes are always embedded in their parent except root node.
   367  	if len(blob) < 32 && len(path) > 0 {
   368  		st.val = common.CopyBytes(blob)
   369  		return
   370  	}
   371  	// Write the hash to the 'val'. We allocate a new val here to not mutate
   372  	// input values.
   373  	st.val = t.h.hashData(blob)
   374  
   375  	// Invoke the callback it's provided. Notably, the path and blob slices are
   376  	// volatile, please deep-copy the slices in callback if the contents need
   377  	// to be retained.
   378  	if t.onTrieNode != nil {
   379  		t.onTrieNode(path, common.BytesToHash(st.val), blob)
   380  	}
   381  }
   382  
   383  // Hash will firstly hash the entire trie if it's still not hashed and then commit
   384  // all leftover nodes to the associated database. Actually most of the trie nodes
   385  // have been committed already. The main purpose here is to commit the nodes on
   386  // right boundary.
   387  func (t *StackTrie) Hash() common.Hash {
   388  	n := t.root
   389  	t.hash(n, nil)
   390  	return common.BytesToHash(n.val)
   391  }