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