github.com/calmw/ethereum@v0.1.1/trie/trienode/node.go (about)

     1  // Copyright 2023 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 trienode
    18  
    19  import (
    20  	"fmt"
    21  	"sort"
    22  	"strings"
    23  
    24  	"github.com/calmw/ethereum/common"
    25  )
    26  
    27  // Node is a wrapper which contains the encoded blob of the trie node and its
    28  // unique hash identifier. It is general enough that can be used to represent
    29  // trie nodes corresponding to different trie implementations.
    30  type Node struct {
    31  	Hash common.Hash // Node hash, empty for deleted node
    32  	Blob []byte      // Encoded node blob, nil for the deleted node
    33  }
    34  
    35  // Size returns the total memory size used by this node.
    36  func (n *Node) Size() int {
    37  	return len(n.Blob) + common.HashLength
    38  }
    39  
    40  // IsDeleted returns the indicator if the node is marked as deleted.
    41  func (n *Node) IsDeleted() bool {
    42  	return n.Hash == (common.Hash{})
    43  }
    44  
    45  // WithPrev wraps the Node with the previous node value attached.
    46  type WithPrev struct {
    47  	*Node
    48  	Prev []byte // Encoded original value, nil means it's non-existent
    49  }
    50  
    51  // Unwrap returns the internal Node object.
    52  func (n *WithPrev) Unwrap() *Node {
    53  	return n.Node
    54  }
    55  
    56  // Size returns the total memory size used by this node. It overloads
    57  // the function in Node by counting the size of previous value as well.
    58  func (n *WithPrev) Size() int {
    59  	return n.Node.Size() + len(n.Prev)
    60  }
    61  
    62  // New constructs a node with provided node information.
    63  func New(hash common.Hash, blob []byte) *Node {
    64  	return &Node{Hash: hash, Blob: blob}
    65  }
    66  
    67  // NewWithPrev constructs a node with provided node information.
    68  func NewWithPrev(hash common.Hash, blob []byte, prev []byte) *WithPrev {
    69  	return &WithPrev{
    70  		Node: New(hash, blob),
    71  		Prev: prev,
    72  	}
    73  }
    74  
    75  // leaf represents a trie leaf node
    76  type leaf struct {
    77  	Blob   []byte      // raw blob of leaf
    78  	Parent common.Hash // the hash of parent node
    79  }
    80  
    81  // NodeSet contains a set of nodes collected during the commit operation.
    82  // Each node is keyed by path. It's not thread-safe to use.
    83  type NodeSet struct {
    84  	Owner   common.Hash
    85  	Leaves  []*leaf
    86  	Nodes   map[string]*WithPrev
    87  	updates int // the count of updated and inserted nodes
    88  	deletes int // the count of deleted nodes
    89  }
    90  
    91  // NewNodeSet initializes a node set. The owner is zero for the account trie and
    92  // the owning account address hash for storage tries.
    93  func NewNodeSet(owner common.Hash) *NodeSet {
    94  	return &NodeSet{
    95  		Owner: owner,
    96  		Nodes: make(map[string]*WithPrev),
    97  	}
    98  }
    99  
   100  // ForEachWithOrder iterates the nodes with the order from bottom to top,
   101  // right to left, nodes with the longest path will be iterated first.
   102  func (set *NodeSet) ForEachWithOrder(callback func(path string, n *Node)) {
   103  	var paths sort.StringSlice
   104  	for path := range set.Nodes {
   105  		paths = append(paths, path)
   106  	}
   107  	// Bottom-up, longest path first
   108  	sort.Sort(sort.Reverse(paths))
   109  	for _, path := range paths {
   110  		callback(path, set.Nodes[path].Unwrap())
   111  	}
   112  }
   113  
   114  // AddNode adds the provided node into set.
   115  func (set *NodeSet) AddNode(path []byte, n *WithPrev) {
   116  	if n.IsDeleted() {
   117  		set.deletes += 1
   118  	} else {
   119  		set.updates += 1
   120  	}
   121  	set.Nodes[string(path)] = n
   122  }
   123  
   124  // AddLeaf adds the provided leaf node into set. TODO(rjl493456442) how can
   125  // we get rid of it?
   126  func (set *NodeSet) AddLeaf(parent common.Hash, blob []byte) {
   127  	set.Leaves = append(set.Leaves, &leaf{Blob: blob, Parent: parent})
   128  }
   129  
   130  // Size returns the number of dirty nodes in set.
   131  func (set *NodeSet) Size() (int, int) {
   132  	return set.updates, set.deletes
   133  }
   134  
   135  // Hashes returns the hashes of all updated nodes. TODO(rjl493456442) how can
   136  // we get rid of it?
   137  func (set *NodeSet) Hashes() []common.Hash {
   138  	var ret []common.Hash
   139  	for _, node := range set.Nodes {
   140  		ret = append(ret, node.Hash)
   141  	}
   142  	return ret
   143  }
   144  
   145  // Summary returns a string-representation of the NodeSet.
   146  func (set *NodeSet) Summary() string {
   147  	var out = new(strings.Builder)
   148  	fmt.Fprintf(out, "nodeset owner: %v\n", set.Owner)
   149  	if set.Nodes != nil {
   150  		for path, n := range set.Nodes {
   151  			// Deletion
   152  			if n.IsDeleted() {
   153  				fmt.Fprintf(out, "  [-]: %x prev: %x\n", path, n.Prev)
   154  				continue
   155  			}
   156  			// Insertion
   157  			if len(n.Prev) == 0 {
   158  				fmt.Fprintf(out, "  [+]: %x -> %v\n", path, n.Hash)
   159  				continue
   160  			}
   161  			// Update
   162  			fmt.Fprintf(out, "  [*]: %x -> %v prev: %x\n", path, n.Hash, n.Prev)
   163  		}
   164  	}
   165  	for _, n := range set.Leaves {
   166  		fmt.Fprintf(out, "[leaf]: %v\n", n)
   167  	}
   168  	return out.String()
   169  }
   170  
   171  // MergedNodeSet represents a merged node set for a group of tries.
   172  type MergedNodeSet struct {
   173  	Sets map[common.Hash]*NodeSet
   174  }
   175  
   176  // NewMergedNodeSet initializes an empty merged set.
   177  func NewMergedNodeSet() *MergedNodeSet {
   178  	return &MergedNodeSet{Sets: make(map[common.Hash]*NodeSet)}
   179  }
   180  
   181  // NewWithNodeSet constructs a merged nodeset with the provided single set.
   182  func NewWithNodeSet(set *NodeSet) *MergedNodeSet {
   183  	merged := NewMergedNodeSet()
   184  	merged.Merge(set)
   185  	return merged
   186  }
   187  
   188  // Merge merges the provided dirty nodes of a trie into the set. The assumption
   189  // is held that no duplicated set belonging to the same trie will be merged twice.
   190  func (set *MergedNodeSet) Merge(other *NodeSet) error {
   191  	_, present := set.Sets[other.Owner]
   192  	if present {
   193  		return fmt.Errorf("duplicate trie for owner %#x", other.Owner)
   194  	}
   195  	set.Sets[other.Owner] = other
   196  	return nil
   197  }