@@ -19,6 +19,7 @@ package trie
1919import (
2020 "errors"
2121 "fmt"
22+ "sync"
2223
2324 "github.com/ethereum/go-ethereum/common"
2425 "github.com/ethereum/go-ethereum/common/prque"
@@ -381,26 +382,26 @@ func (s *Sync) scheduleCodeRequest(req *codeRequest) {
381382// retrieval scheduling.
382383func (s * Sync ) children (req * nodeRequest , object node ) ([]* nodeRequest , error ) {
383384 // Gather all the children of the node, irrelevant whether known or not
384- type child struct {
385+ type childNode struct {
385386 path []byte
386387 node node
387388 }
388- var children []child
389+ var children []childNode
389390
390391 switch node := (object ).(type ) {
391392 case * shortNode :
392393 key := node .Key
393394 if hasTerm (key ) {
394395 key = key [:len (key )- 1 ]
395396 }
396- children = []child {{
397+ children = []childNode {{
397398 node : node .Val ,
398399 path : append (append ([]byte (nil ), req .path ... ), key ... ),
399400 }}
400401 case * fullNode :
401402 for i := 0 ; i < 17 ; i ++ {
402403 if node .Children [i ] != nil {
403- children = append (children , child {
404+ children = append (children , childNode {
404405 node : node .Children [i ],
405406 path : append (append ([]byte (nil ), req .path ... ), byte (i )),
406407 })
@@ -410,7 +411,10 @@ func (s *Sync) children(req *nodeRequest, object node) ([]*nodeRequest, error) {
410411 panic (fmt .Sprintf ("unknown node: %+v" , node ))
411412 }
412413 // Iterate over the children, and request all unknown ones
413- requests := make ([]* nodeRequest , 0 , len (children ))
414+ var (
415+ missing = make (chan * nodeRequest , len (children ))
416+ pending sync.WaitGroup
417+ )
414418 for _ , child := range children {
415419 // Notify any external watcher of a new key/value node
416420 if req .callback != nil {
@@ -433,19 +437,36 @@ func (s *Sync) children(req *nodeRequest, object node) ([]*nodeRequest, error) {
433437 if s .membatch .hasNode (child .path ) {
434438 continue
435439 }
436- // If database says duplicate, then at least the trie node is present
437- // and we hold the assumption that it's NOT legacy contract code.
438- chash := common .BytesToHash (node )
439- if rawdb .HasTrieNode (s .database , chash ) {
440- continue
441- }
442- // Locally unknown node, schedule for retrieval
443- requests = append (requests , & nodeRequest {
444- path : child .path ,
445- hash : chash ,
446- parent : req ,
447- callback : req .callback ,
448- })
440+ // Check the presence of children concurrently
441+ pending .Add (1 )
442+ go func (child childNode ) {
443+ defer pending .Done ()
444+
445+ // If database says duplicate, then at least the trie node is present
446+ // and we hold the assumption that it's NOT legacy contract code.
447+ chash := common .BytesToHash (node )
448+ if rawdb .HasTrieNode (s .database , chash ) {
449+ return
450+ }
451+ // Locally unknown node, schedule for retrieval
452+ missing <- & nodeRequest {
453+ path : child .path ,
454+ hash : chash ,
455+ parent : req ,
456+ callback : req .callback ,
457+ }
458+ }(child )
459+ }
460+ }
461+ pending .Wait ()
462+
463+ requests := make ([]* nodeRequest , 0 , len (children ))
464+ for done := false ; ! done ; {
465+ select {
466+ case miss := <- missing :
467+ requests = append (requests , miss )
468+ default :
469+ done = true
449470 }
450471 }
451472 return requests , nil
0 commit comments