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 }