@@ -16,7 +16,7 @@ import (
16
16
func TestEmptyTrie (t * testing.T ) {
17
17
emptyTrie := trie .NewEmptyMTrie ()
18
18
19
- itr := flattener .NewNodeIterator (emptyTrie )
19
+ itr := flattener .NewNodeIterator (emptyTrie . RootNode () )
20
20
require .True (t , nil == itr .Value ()) // initial iterator should return nil
21
21
22
22
require .False (t , itr .Next ())
@@ -30,7 +30,7 @@ func TestPopulatedTrie(t *testing.T) {
30
30
emptyTrie := trie .NewEmptyMTrie ()
31
31
32
32
// key: 0000...
33
- p1 := testutils .PathByUint8 (1 )
33
+ p1 := testutils .PathByUint8 (0 )
34
34
v1 := testutils .LightPayload8 ('A' , 'a' )
35
35
36
36
// key: 0100....
@@ -43,12 +43,12 @@ func TestPopulatedTrie(t *testing.T) {
43
43
testTrie , _ , err := trie .NewTrieWithUpdatedRegisters (emptyTrie , paths , payloads , true )
44
44
require .NoError (t , err )
45
45
46
- for itr := flattener .NewNodeIterator (testTrie ); itr .Next (); {
46
+ for itr := flattener .NewNodeIterator (testTrie . RootNode () ); itr .Next (); {
47
47
fmt .Println (itr .Value ().FmtStr ("" , "" ))
48
48
fmt .Println ()
49
49
}
50
50
51
- itr := flattener .NewNodeIterator (testTrie )
51
+ itr := flattener .NewNodeIterator (testTrie . RootNode () )
52
52
53
53
require .True (t , itr .Next ())
54
54
p1_leaf := itr .Value ()
@@ -80,13 +80,13 @@ func TestUniqueNodeIterator(t *testing.T) {
80
80
emptyTrie := trie .NewEmptyMTrie ()
81
81
82
82
// visitedNodes is nil
83
- itr := flattener .NewUniqueNodeIterator (emptyTrie , nil )
83
+ itr := flattener .NewUniqueNodeIterator (emptyTrie . RootNode () , nil )
84
84
require .False (t , itr .Next ())
85
85
require .True (t , nil == itr .Value ()) // initial iterator should return nil
86
86
87
87
// visitedNodes is empty map
88
88
visitedNodes := make (map [* node.Node ]uint64 )
89
- itr = flattener .NewUniqueNodeIterator (emptyTrie , visitedNodes )
89
+ itr = flattener .NewUniqueNodeIterator (emptyTrie . RootNode () , visitedNodes )
90
90
require .False (t , itr .Next ())
91
91
require .True (t , nil == itr .Value ()) // initial iterator should return nil
92
92
})
@@ -95,7 +95,7 @@ func TestUniqueNodeIterator(t *testing.T) {
95
95
emptyTrie := trie .NewEmptyMTrie ()
96
96
97
97
// key: 0000...
98
- p1 := testutils .PathByUint8 (1 )
98
+ p1 := testutils .PathByUint8 (0 )
99
99
v1 := testutils .LightPayload8 ('A' , 'a' )
100
100
101
101
// key: 0100....
@@ -126,7 +126,7 @@ func TestUniqueNodeIterator(t *testing.T) {
126
126
127
127
// visitedNodes is nil
128
128
i := 0
129
- for itr := flattener .NewUniqueNodeIterator (updatedTrie , nil ); itr .Next (); {
129
+ for itr := flattener .NewUniqueNodeIterator (updatedTrie . RootNode () , nil ); itr .Next (); {
130
130
n := itr .Value ()
131
131
require .True (t , i < len (expectedNodes ))
132
132
require .Equal (t , expectedNodes [i ], n )
@@ -138,7 +138,7 @@ func TestUniqueNodeIterator(t *testing.T) {
138
138
// there isn't any shared sub-trie.
139
139
visitedNodes := make (map [* node.Node ]uint64 )
140
140
i = 0
141
- for itr := flattener .NewUniqueNodeIterator (updatedTrie , visitedNodes ); itr .Next (); {
141
+ for itr := flattener .NewUniqueNodeIterator (updatedTrie . RootNode () , visitedNodes ); itr .Next (); {
142
142
n := itr .Value ()
143
143
visitedNodes [n ] = uint64 (i )
144
144
@@ -157,7 +157,7 @@ func TestUniqueNodeIterator(t *testing.T) {
157
157
emptyTrie := trie .NewEmptyMTrie ()
158
158
159
159
// key: 0000...
160
- p1 := testutils .PathByUint8 (1 )
160
+ p1 := testutils .PathByUint8 (0 )
161
161
v1 := testutils .LightPayload8 ('A' , 'a' )
162
162
163
163
// key: 0100....
@@ -254,7 +254,7 @@ func TestUniqueNodeIterator(t *testing.T) {
254
254
visitedNodes := make (map [* node.Node ]uint64 )
255
255
i := 0
256
256
for _ , trie := range tries {
257
- for itr := flattener .NewUniqueNodeIterator (trie , visitedNodes ); itr .Next (); {
257
+ for itr := flattener .NewUniqueNodeIterator (trie . RootNode () , visitedNodes ); itr .Next (); {
258
258
n := itr .Value ()
259
259
visitedNodes [n ] = uint64 (i )
260
260
@@ -265,4 +265,133 @@ func TestUniqueNodeIterator(t *testing.T) {
265
265
}
266
266
require .Equal (t , i , len (expectedNodes ))
267
267
})
268
+
269
+ t .Run ("subtries" , func (t * testing.T ) {
270
+
271
+ emptyTrie := trie .NewEmptyMTrie ()
272
+
273
+ // key: 0000...
274
+ p1 := testutils .PathByUint8 (0 )
275
+ v1 := testutils .LightPayload8 ('A' , 'a' )
276
+
277
+ // key: 0100....
278
+ p2 := testutils .PathByUint8 (64 )
279
+ v2 := testutils .LightPayload8 ('B' , 'b' )
280
+
281
+ paths := []ledger.Path {p1 , p2 }
282
+ payloads := []ledger.Payload {* v1 , * v2 }
283
+
284
+ trie1 , _ , err := trie .NewTrieWithUpdatedRegisters (emptyTrie , paths , payloads , true )
285
+ require .NoError (t , err )
286
+
287
+ // trie1
288
+ // n4
289
+ // /
290
+ // /
291
+ // n3
292
+ // / \
293
+ // / \
294
+ // n1 (p1/v1) n2 (p2/v2)
295
+ //
296
+
297
+ // New trie reuses its parent's left sub-trie.
298
+
299
+ // key: 1000...
300
+ p3 := testutils .PathByUint8 (128 )
301
+ v3 := testutils .LightPayload8 ('C' , 'c' )
302
+
303
+ // key: 1100....
304
+ p4 := testutils .PathByUint8 (192 )
305
+ v4 := testutils .LightPayload8 ('D' , 'd' )
306
+
307
+ paths = []ledger.Path {p3 , p4 }
308
+ payloads = []ledger.Payload {* v3 , * v4 }
309
+
310
+ trie2 , _ , err := trie .NewTrieWithUpdatedRegisters (trie1 , paths , payloads , true )
311
+ require .NoError (t , err )
312
+
313
+ // trie2
314
+ // n8
315
+ // / \
316
+ // / \
317
+ // n3 n7
318
+ // (shared) / \
319
+ // / \
320
+ // n5 n6
321
+ // (p3/v3) (p4/v4)
322
+
323
+ // New trie reuses its parent's right sub-trie, and left sub-trie's leaf node.
324
+
325
+ // key: 0000...
326
+ v5 := testutils .LightPayload8 ('E' , 'e' )
327
+
328
+ paths = []ledger.Path {p1 }
329
+ payloads = []ledger.Payload {* v5 }
330
+
331
+ trie3 , _ , err := trie .NewTrieWithUpdatedRegisters (trie2 , paths , payloads , true )
332
+ require .NoError (t , err )
333
+
334
+ // trie3
335
+ // n11
336
+ // / \
337
+ // / \
338
+ // n10 n7
339
+ // / \ (shared)
340
+ // / \
341
+ // n9 n2
342
+ // (p1/v5) (shared)
343
+
344
+ leftSubtries := []* node.Node {
345
+ trie1 .RootNode ().LeftChild (),
346
+ trie2 .RootNode ().LeftChild (),
347
+ trie3 .RootNode ().LeftChild (),
348
+ }
349
+
350
+ expectedNodesInLeftSubtries := []* node.Node {
351
+ // unique nodes from trie1
352
+ trie1 .RootNode ().LeftChild ().LeftChild (), // n1
353
+ trie1 .RootNode ().LeftChild ().RightChild (), // n2
354
+ trie1 .RootNode ().LeftChild (), // n3
355
+ // unique nodes from trie3
356
+ trie3 .RootNode ().LeftChild ().LeftChild (), // n9
357
+ trie3 .RootNode ().LeftChild (), // n10
358
+ }
359
+
360
+ rightSubtries := []* node.Node {
361
+ trie1 .RootNode ().RightChild (),
362
+ trie2 .RootNode ().RightChild (),
363
+ trie3 .RootNode ().RightChild (),
364
+ }
365
+
366
+ expectedNodesInRightSubtries := []* node.Node {
367
+ // unique nodes from trie2
368
+ trie2 .RootNode ().RightChild ().LeftChild (), // n5
369
+ trie2 .RootNode ().RightChild ().RightChild (), // n6
370
+ trie2 .RootNode ().RightChild (), // n7
371
+ }
372
+
373
+ testcases := []struct {
374
+ roots []* node.Node
375
+ expectedNodes []* node.Node
376
+ }{
377
+ {leftSubtries , expectedNodesInLeftSubtries },
378
+ {rightSubtries , expectedNodesInRightSubtries },
379
+ }
380
+
381
+ for _ , tc := range testcases {
382
+ visitedNodes := make (map [* node.Node ]uint64 )
383
+ i := 0
384
+ for _ , n := range tc .roots {
385
+ for itr := flattener .NewUniqueNodeIterator (n , visitedNodes ); itr .Next (); {
386
+ n := itr .Value ()
387
+ visitedNodes [n ] = uint64 (i )
388
+
389
+ require .True (t , i < len (tc .expectedNodes ))
390
+ require .Equal (t , tc .expectedNodes [i ], n )
391
+ i ++
392
+ }
393
+ }
394
+ require .Equal (t , i , len (tc .expectedNodes ))
395
+ }
396
+ })
268
397
}
0 commit comments