@@ -83,7 +83,7 @@ type BlockChain interface {
83
83
InsertHeaderChain (chain []* types.Header , checkFreq int ) (int , error )
84
84
Rollback (chain []common.Hash )
85
85
GetHeaderByNumber (number uint64 ) * types.Header
86
- GetBlockHashesFromHash (hash common.Hash , max uint64 ) [] common.Hash
86
+ GetAncestor (hash common.Hash , number , ancestor uint64 , maxNonCanonical * uint64 ) ( common.Hash , uint64 )
87
87
Genesis () * types.Block
88
88
SubscribeChainHeadEvent (ch chan <- core.ChainHeadEvent ) event.Subscription
89
89
}
@@ -419,6 +419,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
419
419
}
420
420
421
421
hashMode := query .Origin .Hash != (common.Hash {})
422
+ first := true
423
+ maxNonCanonical := uint64 (100 )
422
424
423
425
// Gather headers until the fetch or network limits is reached
424
426
var (
@@ -430,29 +432,34 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
430
432
// Retrieve the next header satisfying the query
431
433
var origin * types.Header
432
434
if hashMode {
433
- origin = pm .blockchain .GetHeaderByHash (query .Origin .Hash )
435
+ if first {
436
+ first = false
437
+ origin = pm .blockchain .GetHeaderByHash (query .Origin .Hash )
438
+ if origin != nil {
439
+ query .Origin .Number = origin .Number .Uint64 ()
440
+ }
441
+ } else {
442
+ origin = pm .blockchain .GetHeader (query .Origin .Hash , query .Origin .Number )
443
+ }
434
444
} else {
435
445
origin = pm .blockchain .GetHeaderByNumber (query .Origin .Number )
436
446
}
437
447
if origin == nil {
438
448
break
439
449
}
440
- number := origin .Number .Uint64 ()
441
450
headers = append (headers , origin )
442
451
bytes += estHeaderRlpSize
443
452
444
453
// Advance to the next header of the query
445
454
switch {
446
455
case hashMode && query .Reverse :
447
456
// Hash based traversal towards the genesis block
448
- for i := 0 ; i < int (query .Skip )+ 1 ; i ++ {
449
- if header := pm .blockchain .GetHeader (query .Origin .Hash , number ); header != nil {
450
- query .Origin .Hash = header .ParentHash
451
- number --
452
- } else {
453
- unknown = true
454
- break
455
- }
457
+ ancestor := query .Skip + 1
458
+ if ancestor == 0 {
459
+ unknown = true
460
+ } else {
461
+ query .Origin .Hash , query .Origin .Number = pm .blockchain .GetAncestor (query .Origin .Hash , query .Origin .Number , ancestor , & maxNonCanonical )
462
+ unknown = (query .Origin .Hash == common.Hash {})
456
463
}
457
464
case hashMode && ! query .Reverse :
458
465
// Hash based traversal towards the leaf block
@@ -466,8 +473,10 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
466
473
unknown = true
467
474
} else {
468
475
if header := pm .blockchain .GetHeaderByNumber (next ); header != nil {
469
- if pm .blockchain .GetBlockHashesFromHash (header .Hash (), query .Skip + 1 )[query .Skip ] == query .Origin .Hash {
470
- query .Origin .Hash = header .Hash ()
476
+ nextHash := header .Hash ()
477
+ expOldHash , _ := pm .blockchain .GetAncestor (nextHash , next , query .Skip + 1 , & maxNonCanonical )
478
+ if expOldHash == query .Origin .Hash {
479
+ query .Origin .Hash , query .Origin .Number = nextHash , next
471
480
} else {
472
481
unknown = true
473
482
}
0 commit comments