@@ -24,6 +24,7 @@ import (
24
24
"sync"
25
25
26
26
"github.com/ethereum/go-ethereum/common"
27
+ "github.com/ethereum/go-ethereum/core/rawdb"
27
28
"github.com/ethereum/go-ethereum/core/types"
28
29
"github.com/ethereum/go-ethereum/crypto"
29
30
"github.com/ethereum/go-ethereum/log"
@@ -62,17 +63,32 @@ type LeafCallback func(paths [][]byte, hexpath []byte, leaf []byte, parent commo
62
63
type Trie struct {
63
64
db * Database
64
65
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
66
68
// hashing operation. This number will not directly map to the number of
67
69
// actually unhashed nodes
68
70
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
69
75
}
70
76
71
77
// newFlag returns the cache flag value for a newly created node.
72
78
func (t * Trie ) newFlag () nodeFlag {
73
79
return nodeFlag {dirty : true }
74
80
}
75
81
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
+
76
92
// New creates a trie with an existing root node from db.
77
93
//
78
94
// 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) {
85
101
}
86
102
trie := & Trie {
87
103
db : db ,
104
+ //tracer: newTracer(),
88
105
}
89
106
if root != (common.Hash {}) && root != emptyRoot {
90
107
rootnode , err := trie .resolveHash (root [:], nil )
@@ -96,6 +113,16 @@ func New(root common.Hash, db *Database) (*Trie, error) {
96
113
return trie , nil
97
114
}
98
115
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
+
99
126
// NodeIterator returns an iterator that returns nodes of the trie. Iteration starts at
100
127
// the key after the given start key.
101
128
func (t * Trie ) NodeIterator (start []byte ) NodeIterator {
@@ -317,7 +344,12 @@ func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error
317
344
if matchlen == 0 {
318
345
return true , branch , nil
319
346
}
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.
321
353
return true , & shortNode {key [:matchlen ], branch , t .newFlag ()}, nil
322
354
323
355
case * fullNode :
@@ -331,6 +363,11 @@ func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error
331
363
return true , n , nil
332
364
333
365
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
+
334
371
return true , & shortNode {key , value , t .newFlag ()}, nil
335
372
336
373
case hashNode :
@@ -383,6 +420,11 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
383
420
return false , n , nil // don't replace n on mismatch
384
421
}
385
422
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
+
386
428
return true , nil , nil // remove n entirely for whole matches
387
429
}
388
430
// 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) {
395
437
}
396
438
switch child := child .(type ) {
397
439
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
+
398
444
// Deleting from the subtrie reduced it to another
399
445
// short node. Merge the nodes to avoid creating a
400
446
// shortNode{..., shortNode{...}}. Use concat (which
@@ -456,6 +502,11 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
456
502
return false , nil , err
457
503
}
458
504
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
+
459
510
k := append ([]byte {byte (pos )}, cnode .Key ... )
460
511
return true , & shortNode {k , cnode .Val , t .newFlag ()}, nil
461
512
}
@@ -537,6 +588,8 @@ func (t *Trie) Commit(onleaf LeafCallback) (common.Hash, int, error) {
537
588
if t .db == nil {
538
589
panic ("commit called on trie with nil database" )
539
590
}
591
+ defer t .tracer .reset ()
592
+
540
593
if t .root == nil {
541
594
return emptyRoot , 0 , nil
542
595
}
@@ -595,4 +648,5 @@ func (t *Trie) hashRoot() (node, node, error) {
595
648
func (t * Trie ) Reset () {
596
649
t .root = nil
597
650
t .unhashed = 0
651
+ t .tracer .reset ()
598
652
}
0 commit comments