github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/trie/tracer.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 "maps" 21 22 "github.com/ethereum/go-ethereum/common" 23 ) 24 25 // tracer tracks the changes of trie nodes. During the trie operations, 26 // some nodes can be deleted from the trie, while these deleted nodes 27 // won't be captured by trie.Hasher or trie.Committer. Thus, these deleted 28 // nodes won't be removed from the disk at all. Tracer is an auxiliary tool 29 // used to track all insert and delete operations of trie and capture all 30 // deleted nodes eventually. 31 // 32 // The changed nodes can be mainly divided into two categories: the leaf 33 // node and intermediate node. The former is inserted/deleted by callers 34 // while the latter is inserted/deleted in order to follow the rule of trie. 35 // This tool can track all of them no matter the node is embedded in its 36 // parent or not, but valueNode is never tracked. 37 // 38 // Besides, it's also used for recording the original value of the nodes 39 // when they are resolved from the disk. The pre-value of the nodes will 40 // be used to construct trie history in the future. 41 // 42 // Note tracer is not thread-safe, callers should be responsible for handling 43 // the concurrency issues by themselves. 44 type tracer struct { 45 inserts map[string]struct{} 46 deletes map[string]struct{} 47 accessList map[string][]byte 48 } 49 50 // newTracer initializes the tracer for capturing trie changes. 51 func newTracer() *tracer { 52 return &tracer{ 53 inserts: make(map[string]struct{}), 54 deletes: make(map[string]struct{}), 55 accessList: make(map[string][]byte), 56 } 57 } 58 59 // onRead tracks the newly loaded trie node and caches the rlp-encoded 60 // blob internally. Don't change the value outside of function since 61 // it's not deep-copied. 62 func (t *tracer) onRead(path []byte, val []byte) { 63 t.accessList[string(path)] = val 64 } 65 66 // onInsert tracks the newly inserted trie node. If it's already 67 // in the deletion set (resurrected node), then just wipe it from 68 // the deletion set as it's "untouched". 69 func (t *tracer) onInsert(path []byte) { 70 if _, present := t.deletes[string(path)]; present { 71 delete(t.deletes, string(path)) 72 return 73 } 74 t.inserts[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 if _, present := t.inserts[string(path)]; present { 82 delete(t.inserts, string(path)) 83 return 84 } 85 t.deletes[string(path)] = struct{}{} 86 } 87 88 // reset clears the content tracked by tracer. 89 func (t *tracer) reset() { 90 t.inserts = make(map[string]struct{}) 91 t.deletes = make(map[string]struct{}) 92 t.accessList = make(map[string][]byte) 93 } 94 95 // copy returns a deep copied tracer instance. 96 func (t *tracer) copy() *tracer { 97 accessList := make(map[string][]byte, len(t.accessList)) 98 for path, blob := range t.accessList { 99 accessList[path] = common.CopyBytes(blob) 100 } 101 return &tracer{ 102 inserts: maps.Clone(t.inserts), 103 deletes: maps.Clone(t.deletes), 104 accessList: accessList, 105 } 106 } 107 108 // deletedNodes returns a list of node paths which are deleted from the trie. 109 func (t *tracer) deletedNodes() []string { 110 var paths []string 111 for path := range t.deletes { 112 // It's possible a few deleted nodes were embedded 113 // in their parent before, the deletions can be no 114 // effect by deleting nothing, filter them out. 115 _, ok := t.accessList[path] 116 if !ok { 117 continue 118 } 119 paths = append(paths, path) 120 } 121 return paths 122 }