@@ -160,9 +160,6 @@ type LightChain interface {
160160 // GetHeaderByHash retrieves a header from the local chain.
161161 GetHeaderByHash (common.Hash ) * types.Header
162162
163- // GetHeaderByNumber retrieves a block header from the local chain by number.
164- GetHeaderByNumber (number uint64 ) * types.Header
165-
166163 // CurrentHeader retrieves the head header from the local chain.
167164 CurrentHeader () * types.Header
168165
@@ -493,7 +490,15 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd *
493490 // Retrieve the pivot header from the skeleton chain segment but
494491 // fallback to local chain if it's not found in skeleton space.
495492 if pivot = d .skeleton .Header (number ); pivot == nil {
496- pivot = d .lightchain .GetHeaderByNumber (number )
493+ _ , oldest , _ := d .skeleton .Bounds () // error is already checked
494+ if number < oldest .Number .Uint64 () {
495+ count := int (oldest .Number .Uint64 () - number ) // it's capped by fsMinFullBlocks
496+ headers := d .readHeaderRange (oldest , count )
497+ if len (headers ) == count {
498+ pivot = headers [len (headers )- 1 ]
499+ log .Warn ("Retrieved pivot header from local" , "number" , pivot .Number , "hash" , pivot .Hash (), "latest" , latest .Number , "oldest" , oldest .Number )
500+ }
501+ }
497502 }
498503 // Print an error log and return directly in case the pivot header
499504 // is still not found. It means the skeleton chain is not linked
@@ -1779,3 +1784,25 @@ func (d *Downloader) DeliverSnapPacket(peer *snap.Peer, packet snap.Packet) erro
17791784 return fmt .Errorf ("unexpected snap packet type: %T" , packet )
17801785 }
17811786}
1787+
1788+ // readHeaderRange returns a list of headers, using the given last header as the base,
1789+ // and going backwards towards genesis. This method assumes that the caller already has
1790+ // placed a reasonable cap on count.
1791+ func (d * Downloader ) readHeaderRange (last * types.Header , count int ) []* types.Header {
1792+ var (
1793+ current = last
1794+ headers []* types.Header
1795+ )
1796+ for {
1797+ parent := d .lightchain .GetHeaderByHash (current .ParentHash )
1798+ if parent == nil {
1799+ break // The chain is not continuous, or the chain is exhausted
1800+ }
1801+ headers = append (headers , parent )
1802+ if len (headers ) >= count {
1803+ break
1804+ }
1805+ current = parent
1806+ }
1807+ return headers
1808+ }
0 commit comments