@@ -36,24 +36,26 @@ const (
3636 maxNodeCount = 20 // maximum number of fetcherTreeNode entries remembered for each peer
3737)
3838
39- // lightFetcher
39+ // lightFetcher implements retrieval of newly announced headers. It also provides a peerHasBlock function for the
40+ // ODR system to ensure that we only request data related to a certain block from peers who have already processed
41+ // and announced that block.
4042type lightFetcher struct {
4143 pm * ProtocolManager
4244 odr * LesOdr
4345 chain * light.LightChain
4446
47+ lock sync.Mutex // lock protects access to the fetcher's internal state variables except sent requests
4548 maxConfirmedTd * big.Int
4649 peers map [* peer ]* fetcherPeerInfo
4750 lastUpdateStats * updateStatsEntry
51+ syncing bool
52+ syncDone chan * peer
4853
49- lock sync.Mutex // qwerqwerqwe
50- deliverChn chan fetchResponse
51- reqMu sync.RWMutex
54+ reqMu sync.RWMutex // reqMu protects access to sent header fetch requests
5255 requested map [uint64 ]fetchRequest
56+ deliverChn chan fetchResponse
5357 timeoutChn chan uint64
5458 requestChn chan bool // true if initiated from outside
55- syncing bool
56- syncDone chan * peer
5759}
5860
5961// fetcherPeerInfo holds fetcher-specific information about each active peer
@@ -560,8 +562,13 @@ func (f *lightFetcher) checkAnnouncedHeaders(fp *fetcherPeerInfo, headers []*typ
560562 return true
561563 }
562564 // we ran out of recently delivered headers but have not reached a node known by this peer yet, continue matching
563- td = f .chain .GetTd (header .ParentHash , header .Number .Uint64 ()- 1 )
564- header = f .chain .GetHeader (header .ParentHash , header .Number .Uint64 ()- 1 )
565+ hash , number := header .ParentHash , header .Number .Uint64 ()- 1
566+ td = f .chain .GetTd (hash , number )
567+ header = f .chain .GetHeader (hash , number )
568+ if header == nil || td == nil {
569+ log .Error ("Missing parent of validated header" , "hash" , hash , "number" , number )
570+ return false
571+ }
565572 } else {
566573 header = headers [i ]
567574 td = tds [i ]
@@ -645,13 +652,18 @@ func (f *lightFetcher) checkKnownNode(p *peer, n *fetcherTreeNode) bool {
645652 if td == nil {
646653 return false
647654 }
655+ header := f .chain .GetHeader (n .hash , n .number )
656+ // check the availability of both header and td because reads are not protected by chain db mutex
657+ // Note: returning false is always safe here
658+ if header == nil {
659+ return false
660+ }
648661
649662 fp := f .peers [p ]
650663 if fp == nil {
651664 p .Log ().Debug ("Unknown peer to check known nodes" )
652665 return false
653666 }
654- header := f .chain .GetHeader (n .hash , n .number )
655667 if ! f .checkAnnouncedHeaders (fp , []* types.Header {header }, []* big.Int {td }) {
656668 p .Log ().Debug ("Inconsistent announcement" )
657669 go f .pm .removePeer (p .id )
0 commit comments