github.com/tirogen/go-ethereum@v1.10.12-0.20221226051715-250cfede41b6/trie/utils.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 // tracer tracks the changes of trie nodes. During the trie operations, 20 // some nodes can be deleted from the trie, while these deleted nodes 21 // won't be captured by trie.Hasher or trie.Committer. Thus, these deleted 22 // nodes won't be removed from the disk at all. Tracer is an auxiliary tool 23 // used to track all insert and delete operations of trie and capture all 24 // deleted nodes eventually. 25 // 26 // The changed nodes can be mainly divided into two categories: the leaf 27 // node and intermediate node. The former is inserted/deleted by callers 28 // while the latter is inserted/deleted in order to follow the rule of trie. 29 // This tool can track all of them no matter the node is embedded in its 30 // parent or not, but valueNode is never tracked. 31 // 32 // Besides, it's also used for recording the original value of the nodes 33 // when they are resolved from the disk. The pre-value of the nodes will 34 // be used to construct reverse-diffs in the future. 35 // 36 // Note tracer is not thread-safe, callers should be responsible for handling 37 // the concurrency issues by themselves. 38 type tracer struct { 39 insert map[string]struct{} 40 delete map[string]struct{} 41 origin map[string][]byte 42 } 43 44 // newTracer initializes the tracer for capturing trie changes. 45 func newTracer() *tracer { 46 return &tracer{ 47 insert: make(map[string]struct{}), 48 delete: make(map[string]struct{}), 49 origin: make(map[string][]byte), 50 } 51 } 52 53 // onRead tracks the newly loaded trie node and caches the rlp-encoded blob internally. 54 // Don't change the value outside of function since it's not deep-copied. 55 func (t *tracer) onRead(path []byte, val []byte) { 56 // Tracer isn't used right now, remove this check later. 57 if t == nil { 58 return 59 } 60 t.origin[string(path)] = val 61 } 62 63 // onInsert tracks the newly inserted trie node. If it's already in the deletion set 64 // (resurrected node), then just wipe it from the deletion set as the "untouched". 65 func (t *tracer) onInsert(path []byte) { 66 // Tracer isn't used right now, remove this check later. 67 if t == nil { 68 return 69 } 70 if _, present := t.delete[string(path)]; present { 71 delete(t.delete, string(path)) 72 return 73 } 74 t.insert[string(path)] = struct{}{} 75 } 76 77 // onDelete tracks the newly deleted trie node. If it's already 78 // in the addition set, then just wipe it from the addition set 79 // as it's untouched. 80 func (t *tracer) onDelete(path []byte) { 81 // Tracer isn't used right now, remove this check later. 82 if t == nil { 83 return 84 } 85 if _, present := t.insert[string(path)]; present { 86 delete(t.insert, string(path)) 87 return 88 } 89 t.delete[string(path)] = struct{}{} 90 } 91 92 // insertList returns the tracked inserted trie nodes in list format. 93 func (t *tracer) insertList() [][]byte { 94 // Tracer isn't used right now, remove this check later. 95 if t == nil { 96 return nil 97 } 98 var ret [][]byte 99 for path := range t.insert { 100 ret = append(ret, []byte(path)) 101 } 102 return ret 103 } 104 105 // deleteList returns the tracked deleted trie nodes in list format. 106 func (t *tracer) deleteList() [][]byte { 107 // Tracer isn't used right now, remove this check later. 108 if t == nil { 109 return nil 110 } 111 var ret [][]byte 112 for path := range t.delete { 113 ret = append(ret, []byte(path)) 114 } 115 return ret 116 } 117 118 // prevList returns the tracked node blobs in list format. 119 func (t *tracer) prevList() ([][]byte, [][]byte) { 120 // Tracer isn't used right now, remove this check later. 121 if t == nil { 122 return nil, nil 123 } 124 var ( 125 paths [][]byte 126 blobs [][]byte 127 ) 128 for path, blob := range t.origin { 129 paths = append(paths, []byte(path)) 130 blobs = append(blobs, blob) 131 } 132 return paths, blobs 133 } 134 135 // getPrev returns the cached original value of the specified node. 136 func (t *tracer) getPrev(path []byte) []byte { 137 // Tracer isn't used right now, remove this check later. 138 if t == nil { 139 return nil 140 } 141 return t.origin[string(path)] 142 } 143 144 // reset clears the content tracked by tracer. 145 func (t *tracer) reset() { 146 // Tracer isn't used right now, remove this check later. 147 if t == nil { 148 return 149 } 150 t.insert = make(map[string]struct{}) 151 t.delete = make(map[string]struct{}) 152 t.origin = make(map[string][]byte) 153 } 154 155 // copy returns a deep copied tracer instance. 156 func (t *tracer) copy() *tracer { 157 // Tracer isn't used right now, remove this check later. 158 if t == nil { 159 return nil 160 } 161 var ( 162 insert = make(map[string]struct{}) 163 delete = make(map[string]struct{}) 164 origin = make(map[string][]byte) 165 ) 166 for key := range t.insert { 167 insert[key] = struct{}{} 168 } 169 for key := range t.delete { 170 delete[key] = struct{}{} 171 } 172 for key, val := range t.origin { 173 origin[key] = val 174 } 175 return &tracer{ 176 insert: insert, 177 delete: delete, 178 origin: origin, 179 } 180 } 181 182 // markDeletions puts all tracked deletions into the provided nodeset. 183 func (t *tracer) markDeletions(set *NodeSet) { 184 // Tracer isn't used right now, remove this check later. 185 if t == nil { 186 return 187 } 188 for _, path := range t.deleteList() { 189 // There are a few possibilities for this scenario(the node is deleted 190 // but not present in database previously), for example the node was 191 // embedded in the parent and now deleted from the trie. In this case 192 // it's noop from database's perspective. 193 val := t.getPrev(path) 194 if len(val) == 0 { 195 continue 196 } 197 set.markDeleted(path, val) 198 } 199 }