@@ -24,6 +24,7 @@ import (
2424 "sync"
2525
2626 "github.com/ethereum/go-ethereum/common"
27+ "github.com/ethereum/go-ethereum/core/rawdb"
2728 "github.com/ethereum/go-ethereum/core/types"
2829 "github.com/ethereum/go-ethereum/crypto"
2930 "github.com/ethereum/go-ethereum/log"
@@ -62,17 +63,32 @@ type LeafCallback func(paths [][]byte, hexpath []byte, leaf []byte, parent commo
6263type Trie struct {
6364 db * Database
6465 root node
65- // Keep track of the number leafs which have been inserted since the last
66+
67+ // Keep track of the number leaves which have been inserted since the last
6668 // hashing operation. This number will not directly map to the number of
6769 // actually unhashed nodes
6870 unhashed int
71+
72+ // tracer is the state diff tracer can be used to track newly added/deleted
73+ // trie node. It will be reset after each commit operation.
74+ tracer * tracer
6975}
7076
7177// newFlag returns the cache flag value for a newly created node.
7278func (t * Trie ) newFlag () nodeFlag {
7379 return nodeFlag {dirty : true }
7480}
7581
82+ // Copy returns a copy of Trie.
83+ func (t * Trie ) Copy () * Trie {
84+ return & Trie {
85+ db : t .db ,
86+ root : t .root ,
87+ unhashed : t .unhashed ,
88+ tracer : t .tracer .copy (),
89+ }
90+ }
91+
7692// New creates a trie with an existing root node from db.
7793//
7894// If root is the zero hash or the sha3 hash of an empty string, the
@@ -85,6 +101,7 @@ func New(root common.Hash, db *Database) (*Trie, error) {
85101 }
86102 trie := & Trie {
87103 db : db ,
104+ //tracer: newTracer(),
88105 }
89106 if root != (common.Hash {}) && root != emptyRoot {
90107 rootnode , err := trie .resolveHash (root [:], nil )
@@ -96,6 +113,16 @@ func New(root common.Hash, db *Database) (*Trie, error) {
96113 return trie , nil
97114}
98115
116+ // newWithRootNode initializes the trie with the given root node.
117+ // It's only used by range prover.
118+ func newWithRootNode (root node ) * Trie {
119+ return & Trie {
120+ root : root ,
121+ //tracer: newTracer(),
122+ db : NewDatabase (rawdb .NewMemoryDatabase ()),
123+ }
124+ }
125+
99126// NodeIterator returns an iterator that returns nodes of the trie. Iteration starts at
100127// the key after the given start key.
101128func (t * Trie ) NodeIterator (start []byte ) NodeIterator {
@@ -317,7 +344,12 @@ func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error
317344 if matchlen == 0 {
318345 return true , branch , nil
319346 }
320- // Otherwise, replace it with a short node leading up to the branch.
347+ // New branch node is created as a child of the original short node.
348+ // Track the newly inserted node in the tracer. The node identifier
349+ // passed is the path from the root node.
350+ t .tracer .onInsert (append (prefix , key [:matchlen ]... ))
351+
352+ // Replace it with a short node leading up to the branch.
321353 return true , & shortNode {key [:matchlen ], branch , t .newFlag ()}, nil
322354
323355 case * fullNode :
@@ -331,6 +363,11 @@ func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error
331363 return true , n , nil
332364
333365 case nil :
366+ // New short node is created and track it in the tracer. The node identifier
367+ // passed is the path from the root node. Note the valueNode won't be tracked
368+ // since it's always embedded in its parent.
369+ t .tracer .onInsert (prefix )
370+
334371 return true , & shortNode {key , value , t .newFlag ()}, nil
335372
336373 case hashNode :
@@ -383,6 +420,11 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
383420 return false , n , nil // don't replace n on mismatch
384421 }
385422 if matchlen == len (key ) {
423+ // The matched short node is deleted entirely and track
424+ // it in the deletion set. The same the valueNode doesn't
425+ // need to be tracked at all since it's always embedded.
426+ t .tracer .onDelete (prefix )
427+
386428 return true , nil , nil // remove n entirely for whole matches
387429 }
388430 // The key is longer than n.Key. Remove the remaining suffix
@@ -395,6 +437,10 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
395437 }
396438 switch child := child .(type ) {
397439 case * shortNode :
440+ // The child shortNode is merged into its parent, track
441+ // is deleted as well.
442+ t .tracer .onDelete (append (prefix , n .Key ... ))
443+
398444 // Deleting from the subtrie reduced it to another
399445 // short node. Merge the nodes to avoid creating a
400446 // shortNode{..., shortNode{...}}. Use concat (which
@@ -456,6 +502,11 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
456502 return false , nil , err
457503 }
458504 if cnode , ok := cnode .(* shortNode ); ok {
505+ // Replace the entire full node with the short node.
506+ // Mark the original short node as deleted since the
507+ // value is embedded into the parent now.
508+ t .tracer .onDelete (append (prefix , byte (pos )))
509+
459510 k := append ([]byte {byte (pos )}, cnode .Key ... )
460511 return true , & shortNode {k , cnode .Val , t .newFlag ()}, nil
461512 }
@@ -537,6 +588,8 @@ func (t *Trie) Commit(onleaf LeafCallback) (common.Hash, int, error) {
537588 if t .db == nil {
538589 panic ("commit called on trie with nil database" )
539590 }
591+ defer t .tracer .reset ()
592+
540593 if t .root == nil {
541594 return emptyRoot , 0 , nil
542595 }
@@ -595,4 +648,5 @@ func (t *Trie) hashRoot() (node, node, error) {
595648func (t * Trie ) Reset () {
596649 t .root = nil
597650 t .unhashed = 0
651+ t .tracer .reset ()
598652}
0 commit comments