github.com/tacshi/go-ethereum@v0.0.0-20230616113857-84a434e20921/trie/nodeset.go (about)

     1  // Copyright 2022 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  	"fmt"
    21  	"reflect"
    22  	"strings"
    23  
    24  	"github.com/tacshi/go-ethereum/common"
    25  )
    26  
    27  // memoryNode is all the information we know about a single cached trie node
    28  // in the memory.
    29  type memoryNode struct {
    30  	hash common.Hash // Node hash, computed by hashing rlp value, empty for deleted nodes
    31  	size uint16      // Byte size of the useful cached data, 0 for deleted nodes
    32  	node node        // Cached collapsed trie node, or raw rlp data, nil for deleted nodes
    33  }
    34  
    35  // memoryNodeSize is the raw size of a memoryNode data structure without any
    36  // node data included. It's an approximate size, but should be a lot better
    37  // than not counting them.
    38  // nolint:unused
    39  var memoryNodeSize = int(reflect.TypeOf(memoryNode{}).Size())
    40  
    41  // memorySize returns the total memory size used by this node.
    42  // nolint:unused
    43  func (n *memoryNode) memorySize(key int) int {
    44  	return int(n.size) + memoryNodeSize + key
    45  }
    46  
    47  // rlp returns the raw rlp encoded blob of the cached trie node, either directly
    48  // from the cache, or by regenerating it from the collapsed node.
    49  // nolint:unused
    50  func (n *memoryNode) rlp() []byte {
    51  	if node, ok := n.node.(rawNode); ok {
    52  		return node
    53  	}
    54  	return nodeToBytes(n.node)
    55  }
    56  
    57  // obj returns the decoded and expanded trie node, either directly from the cache,
    58  // or by regenerating it from the rlp encoded blob.
    59  // nolint:unused
    60  func (n *memoryNode) obj() node {
    61  	if node, ok := n.node.(rawNode); ok {
    62  		return mustDecodeNode(n.hash[:], node)
    63  	}
    64  	return expandNode(n.hash[:], n.node)
    65  }
    66  
    67  // nodeWithPrev wraps the memoryNode with the previous node value.
    68  type nodeWithPrev struct {
    69  	*memoryNode
    70  	prev []byte // RLP-encoded previous value, nil means it's non-existent
    71  }
    72  
    73  // unwrap returns the internal memoryNode object.
    74  // nolint:unused
    75  func (n *nodeWithPrev) unwrap() *memoryNode {
    76  	return n.memoryNode
    77  }
    78  
    79  // memorySize returns the total memory size used by this node. It overloads
    80  // the function in memoryNode by counting the size of previous value as well.
    81  // nolint: unused
    82  func (n *nodeWithPrev) memorySize(key int) int {
    83  	return n.memoryNode.memorySize(key) + len(n.prev)
    84  }
    85  
    86  // nodesWithOrder represents a collection of dirty nodes which includes
    87  // newly-inserted and updated nodes. The modification order of all nodes
    88  // is represented by order list.
    89  type nodesWithOrder struct {
    90  	order []string                 // the path list of dirty nodes, sort by insertion order
    91  	nodes map[string]*nodeWithPrev // the map of dirty nodes, keyed by node path
    92  }
    93  
    94  // NodeSet contains all dirty nodes collected during the commit operation.
    95  // Each node is keyed by path. It's not thread-safe to use.
    96  type NodeSet struct {
    97  	owner   common.Hash       // the identifier of the trie
    98  	updates *nodesWithOrder   // the set of updated nodes(newly inserted, updated)
    99  	deletes map[string][]byte // the map of deleted nodes, keyed by node
   100  	leaves  []*leaf           // the list of dirty leaves
   101  }
   102  
   103  // NewNodeSet initializes an empty node set to be used for tracking dirty nodes
   104  // from a specific account or storage trie. The owner is zero for the account
   105  // trie and the owning account address hash for storage tries.
   106  func NewNodeSet(owner common.Hash) *NodeSet {
   107  	return &NodeSet{
   108  		owner: owner,
   109  		updates: &nodesWithOrder{
   110  			nodes: make(map[string]*nodeWithPrev),
   111  		},
   112  		deletes: make(map[string][]byte),
   113  	}
   114  }
   115  
   116  /*
   117  // NewNodeSetWithDeletion initializes the nodeset with provided deletion set.
   118  func NewNodeSetWithDeletion(owner common.Hash, paths [][]byte, prev [][]byte) *NodeSet {
   119  	set := NewNodeSet(owner)
   120  	for i, path := range paths {
   121  		set.markDeleted(path, prev[i])
   122  	}
   123  	return set
   124  }
   125  */
   126  
   127  // markUpdated marks the node as dirty(newly-inserted or updated) with provided
   128  // node path, node object along with its previous value.
   129  func (set *NodeSet) markUpdated(path []byte, node *memoryNode, prev []byte) {
   130  	set.updates.order = append(set.updates.order, string(path))
   131  	set.updates.nodes[string(path)] = &nodeWithPrev{
   132  		memoryNode: node,
   133  		prev:       prev,
   134  	}
   135  }
   136  
   137  // markDeleted marks the node as deleted with provided path and previous value.
   138  func (set *NodeSet) markDeleted(path []byte, prev []byte) {
   139  	set.deletes[string(path)] = prev
   140  }
   141  
   142  // addLeaf collects the provided leaf node into set.
   143  func (set *NodeSet) addLeaf(node *leaf) {
   144  	set.leaves = append(set.leaves, node)
   145  }
   146  
   147  // Size returns the number of updated and deleted nodes contained in the set.
   148  func (set *NodeSet) Size() (int, int) {
   149  	return len(set.updates.order), len(set.deletes)
   150  }
   151  
   152  // Hashes returns the hashes of all updated nodes. TODO(rjl493456442) how can
   153  // we get rid of it?
   154  func (set *NodeSet) Hashes() []common.Hash {
   155  	var ret []common.Hash
   156  	for _, node := range set.updates.nodes {
   157  		ret = append(ret, node.hash)
   158  	}
   159  	return ret
   160  }
   161  
   162  // Summary returns a string-representation of the NodeSet.
   163  func (set *NodeSet) Summary() string {
   164  	var out = new(strings.Builder)
   165  	fmt.Fprintf(out, "nodeset owner: %v\n", set.owner)
   166  	if set.updates != nil {
   167  		for _, key := range set.updates.order {
   168  			updated := set.updates.nodes[key]
   169  			if updated.prev != nil {
   170  				fmt.Fprintf(out, "  [*]: %x -> %v prev: %x\n", key, updated.hash, updated.prev)
   171  			} else {
   172  				fmt.Fprintf(out, "  [+]: %x -> %v\n", key, updated.hash)
   173  			}
   174  		}
   175  	}
   176  	for k, n := range set.deletes {
   177  		fmt.Fprintf(out, "  [-]: %x -> %x\n", k, n)
   178  	}
   179  	for _, n := range set.leaves {
   180  		fmt.Fprintf(out, "[leaf]: %v\n", n)
   181  	}
   182  	return out.String()
   183  }
   184  
   185  // MergedNodeSet represents a merged dirty node set for a group of tries.
   186  type MergedNodeSet struct {
   187  	sets map[common.Hash]*NodeSet
   188  }
   189  
   190  // NewMergedNodeSet initializes an empty merged set.
   191  func NewMergedNodeSet() *MergedNodeSet {
   192  	return &MergedNodeSet{sets: make(map[common.Hash]*NodeSet)}
   193  }
   194  
   195  // NewWithNodeSet constructs a merged nodeset with the provided single set.
   196  func NewWithNodeSet(set *NodeSet) *MergedNodeSet {
   197  	merged := NewMergedNodeSet()
   198  	merged.Merge(set)
   199  	return merged
   200  }
   201  
   202  // Merge merges the provided dirty nodes of a trie into the set. The assumption
   203  // is held that no duplicated set belonging to the same trie will be merged twice.
   204  func (set *MergedNodeSet) Merge(other *NodeSet) error {
   205  	_, present := set.sets[other.owner]
   206  	if present {
   207  		return fmt.Errorf("duplicate trie for owner %#x", other.owner)
   208  	}
   209  	set.sets[other.owner] = other
   210  	return nil
   211  }