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 }