@@ -371,6 +371,11 @@ func dumpRawTrieDescendants(db ethdb.Database, root common.Hash, output *stateBl
371
371
for i := 0 ; i < threads ; i ++ {
372
372
results <- nil
373
373
}
374
+ // We also create a semaphore for the storage trie traversal, to limit the number of goroutines
375
+ resultsPerAccount := make (chan error , threads )
376
+ for i := 0 ; i < threads ; i ++ {
377
+ resultsPerAccount <- nil
378
+ }
374
379
var threadsRunning atomic.Int32
375
380
376
381
for accountIt .Next (true ) {
@@ -424,38 +429,33 @@ func dumpRawTrieDescendants(db ethdb.Database, root common.Hash, output *stateBl
424
429
threadLastLog := time .Now ()
425
430
426
431
var processedNodes uint64
427
- var startStorageIt trie.NodeIterator
428
- startStorageIt , err = storageTr .NodeIterator (nil )
429
- if err != nil {
430
- return
431
- }
432
432
for i := int64 (1 ); i <= 32 ; i ++ {
433
- // Split the storage trie into 32 parts to parallelize the traversal
434
- var nextStorageIt trie.NodeIterator
435
- var nextStorageItHash common.Hash
436
- // For the last iteration, we don't need to create a new iterator, as it will be till the end, so just let it be nil
437
- if i != 32 {
438
- nextStorageIt , err = storageTr .NodeIterator (big .NewInt ((i ) << 3 ).Bytes ())
439
- nextStorageItHash = nextStorageIt .Hash ()
440
- if err != nil {
441
- return
442
- }
443
- }
444
- err = <- results
433
+ err = <- resultsPerAccount
445
434
if err != nil {
446
435
return
447
436
}
448
- go func (startIt trie. NodeIterator , endHash common. Hash ) {
437
+ go func (iteration int64 ) {
449
438
threadsRunning .Add (1 )
450
439
defer threadsRunning .Add (- 1 )
451
440
var err error
452
441
defer func () {
453
- results <- err
442
+ resultsPerAccount <- err
454
443
}()
444
+ var startIt trie.NodeIterator
445
+ startIt , err = storageTr .NodeIterator (big .NewInt ((i - 1 ) << 3 ).Bytes ())
446
+ if err != nil {
447
+ return
448
+ }
449
+
455
450
// Traverse the storage trie, and stop if we reach the end of the trie or the end of the current part
456
451
var startItPath , endItPath []byte
457
452
458
- for startIt .Next (true ) && (endHash == common.Hash {} || endHash .Cmp (startIt .Hash ()) != 0 ) {
453
+ key := keybytesToHex (big .NewInt ((iteration ) << 3 ).Bytes ())
454
+ key = key [:len (key )- 1 ]
455
+ for startIt .Next (true ) {
456
+ if iteration != 32 && bytes .Compare (startIt .Path (), key ) >= 0 {
457
+ break
458
+ }
459
459
if startItPath == nil {
460
460
startItPath = startIt .Path ()
461
461
}
@@ -481,8 +481,7 @@ func dumpRawTrieDescendants(db ethdb.Database, root common.Hash, output *stateBl
481
481
return
482
482
}
483
483
log .Trace ("Finished traversing storage trie" , "key" , key , "startPath" , startItPath , "endPath" , endItPath )
484
- }(startStorageIt , nextStorageItHash )
485
- startStorageIt = nextStorageIt
484
+ }(i )
486
485
}
487
486
}()
488
487
}
@@ -497,9 +496,26 @@ func dumpRawTrieDescendants(db ethdb.Database, root common.Hash, output *stateBl
497
496
return err
498
497
}
499
498
}
499
+ for i := 0 ; i < threads ; i ++ {
500
+ err = <- resultsPerAccount
501
+ if err != nil {
502
+ return err
503
+ }
504
+ }
500
505
return nil
501
506
}
502
507
508
+ func keybytesToHex (str []byte ) []byte {
509
+ l := len (str )* 2 + 1
510
+ var nibbles = make ([]byte , l )
511
+ for i , b := range str {
512
+ nibbles [i * 2 ] = b / 16
513
+ nibbles [i * 2 + 1 ] = b % 16
514
+ }
515
+ nibbles [l - 1 ] = 16
516
+ return nibbles
517
+ }
518
+
503
519
// Prune deletes all historical state nodes except the nodes belong to the
504
520
// specified state version. If user doesn't specify the state version, use
505
521
// the bottom-most snapshot diff layer as the target.
0 commit comments