github.com/jimmyx0x/go-ethereum@v1.10.28/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  }