@@ -23,6 +23,7 @@ import (
23
23
24
24
"github.com/XinFinOrg/XDPoSChain/common"
25
25
"github.com/XinFinOrg/XDPoSChain/core/types"
26
+ "github.com/XinFinOrg/XDPoSChain/ethdb"
26
27
)
27
28
28
29
// Iterator is a key-value trie iterator that traverses a Trie.
@@ -102,6 +103,19 @@ type NodeIterator interface {
102
103
// iterator is not positioned at a leaf. Callers must not retain references
103
104
// to the value after calling Next.
104
105
LeafProof () [][]byte
106
+
107
+ // AddResolver sets an intermediate database to use for looking up trie nodes
108
+ // before reaching into the real persistent layer.
109
+ //
110
+ // This is not required for normal operation, rather is an optimization for
111
+ // cases where trie nodes can be recovered from some external mechanism without
112
+ // reading from disk. In those cases, this resolver allows short circuiting
113
+ // accesses and returning them from memory.
114
+ //
115
+ // Before adding a similar mechanism to any other place in Geth, consider
116
+ // making trie.Database an interface and wrapping at that level. It's a huge
117
+ // refactor, but it could be worth it if another occurrence arises.
118
+ AddResolver (ethdb.KeyValueStore )
105
119
}
106
120
107
121
// nodeIteratorState represents the iteration state at one particular Node of the
@@ -119,6 +133,8 @@ type nodeIterator struct {
119
133
stack []* nodeIteratorState // Hierarchy of trie nodes persisting the iteration state
120
134
path []byte // Path to the current Node
121
135
err error // Failure set in case of an internal error in the iterator
136
+
137
+ resolver ethdb.KeyValueStore // Optional intermediate resolver above the disk layer
122
138
}
123
139
124
140
// errIteratorEnd is stored in nodeIterator.err when iteration is done.
@@ -143,6 +159,10 @@ func newNodeIterator(trie *Trie, start []byte) NodeIterator {
143
159
return it
144
160
}
145
161
162
+ func (it * nodeIterator ) AddResolver (resolver ethdb.KeyValueStore ) {
163
+ it .resolver = resolver
164
+ }
165
+
146
166
func (it * nodeIterator ) Hash () common.Hash {
147
167
if len (it .stack ) == 0 {
148
168
return common.Hash {}
@@ -261,7 +281,7 @@ func (it *nodeIterator) init() (*nodeIteratorState, error) {
261
281
if root != types .EmptyRootHash {
262
282
state .hash = root
263
283
}
264
- return state , state .resolve (it . trie , nil )
284
+ return state , state .resolve (it , nil )
265
285
}
266
286
267
287
// peek creates the next state of the iterator.
@@ -285,7 +305,7 @@ func (it *nodeIterator) peek(descend bool) (*nodeIteratorState, *int, []byte, er
285
305
}
286
306
state , path , ok := it .nextChild (parent , ancestor )
287
307
if ok {
288
- if err := state .resolve (it . trie , path ); err != nil {
308
+ if err := state .resolve (it , path ); err != nil {
289
309
return parent , & parent .index , path , err
290
310
}
291
311
return state , & parent .index , path , nil
@@ -318,7 +338,7 @@ func (it *nodeIterator) peekSeek(seekKey []byte) (*nodeIteratorState, *int, []by
318
338
}
319
339
state , path , ok := it .nextChildAt (parent , ancestor , seekKey )
320
340
if ok {
321
- if err := state .resolve (it . trie , path ); err != nil {
341
+ if err := state .resolve (it , path ); err != nil {
322
342
return parent , & parent .index , path , err
323
343
}
324
344
return state , & parent .index , path , nil
@@ -329,9 +349,21 @@ func (it *nodeIterator) peekSeek(seekKey []byte) (*nodeIteratorState, *int, []by
329
349
return nil , nil , nil , errIteratorEnd
330
350
}
331
351
332
- func (st * nodeIteratorState ) resolve (tr * Trie , path []byte ) error {
352
+ func (it * nodeIterator ) resolveHash (hash hashNode , path []byte ) (node , error ) {
353
+ if it .resolver != nil {
354
+ if blob , err := it .resolver .Get (hash ); err == nil && len (blob ) > 0 {
355
+ if resolved , err := decodeNode (hash , blob ); err == nil {
356
+ return resolved , nil
357
+ }
358
+ }
359
+ }
360
+ resolved , err := it .trie .resolveHash (hash , path )
361
+ return resolved , err
362
+ }
363
+
364
+ func (st * nodeIteratorState ) resolve (it * nodeIterator , path []byte ) error {
333
365
if hash , ok := st .node .(hashNode ); ok {
334
- resolved , err := tr .resolveHash (hash , path )
366
+ resolved , err := it .resolveHash (hash , path )
335
367
if err != nil {
336
368
return err
337
369
}
@@ -516,6 +548,10 @@ func (it *differenceIterator) Path() []byte {
516
548
return it .b .Path ()
517
549
}
518
550
551
+ func (it * differenceIterator ) AddResolver (resolver ethdb.KeyValueStore ) {
552
+ panic ("not implemented" )
553
+ }
554
+
519
555
func (it * differenceIterator ) Next (bool ) bool {
520
556
// Invariants:
521
557
// - We always advance at least one element in b.
@@ -623,7 +659,11 @@ func (it *unionIterator) Path() []byte {
623
659
return (* it .items )[0 ].Path ()
624
660
}
625
661
626
- // Next returns the next Node in the union of tries being iterated over.
662
+ func (it * unionIterator ) AddResolver (resolver ethdb.KeyValueStore ) {
663
+ panic ("not implemented" )
664
+ }
665
+
666
+ // Next returns the next node in the union of tries being iterated over.
627
667
//
628
668
// It does this by maintaining a heap of iterators, sorted by the iteration
629
669
// order of their next elements, with one entry for each source trie. Each
0 commit comments