github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/les/fetcher.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package les implements the Light Ethereum Subprotocol.
    18  package les
    19  
    20  import (
    21  	"math/big"
    22  	"sync"
    23  	"time"
    24  
    25  	"github.com/atheioschain/go-atheios/common"
    26  	"github.com/atheioschain/go-atheios/common/mclock"
    27  	"github.com/atheioschain/go-atheios/core"
    28  	"github.com/atheioschain/go-atheios/core/types"
    29  	"github.com/atheioschain/go-atheios/light"
    30  	"github.com/atheioschain/go-atheios/logger"
    31  	"github.com/atheioschain/go-atheios/logger/glog"
    32  )
    33  
    34  const (
    35  	blockDelayTimeout = time.Second * 10 // timeout for a peer to announce a head that has already been confirmed by others
    36  	maxNodeCount      = 20               // maximum number of fetcherTreeNode entries remembered for each peer
    37  )
    38  
    39  // lightFetcher
    40  type lightFetcher struct {
    41  	pm    *ProtocolManager
    42  	odr   *LesOdr
    43  	chain *light.LightChain
    44  
    45  	maxConfirmedTd  *big.Int
    46  	peers           map[*peer]*fetcherPeerInfo
    47  	lastUpdateStats *updateStatsEntry
    48  
    49  	lock       sync.Mutex // qwerqwerqwe
    50  	deliverChn chan fetchResponse
    51  	reqMu      sync.RWMutex
    52  	requested  map[uint64]fetchRequest
    53  	timeoutChn chan uint64
    54  	requestChn chan bool // true if initiated from outside
    55  	syncing    bool
    56  	syncDone   chan *peer
    57  }
    58  
    59  // fetcherPeerInfo holds fetcher-specific information about each active peer
    60  type fetcherPeerInfo struct {
    61  	root, lastAnnounced *fetcherTreeNode
    62  	nodeCnt             int
    63  	confirmedTd         *big.Int
    64  	bestConfirmed       *fetcherTreeNode
    65  	nodeByHash          map[common.Hash]*fetcherTreeNode
    66  	firstUpdateStats    *updateStatsEntry
    67  }
    68  
    69  // fetcherTreeNode is a node of a tree that holds information about blocks recently
    70  // announced and confirmed by a certain peer. Each new announce message from a peer
    71  // adds nodes to the tree, based on the previous announced head and the reorg depth.
    72  // There are three possible states for a tree node:
    73  // - announced: not downloaded (known) yet, but we know its head, number and td
    74  // - intermediate: not known, hash and td are empty, they are filled out when it becomes known
    75  // - known: both announced by this peer and downloaded (from any peer).
    76  // This structure makes it possible to always know which peer has a certain block,
    77  // which is necessary for selecting a suitable peer for ODR requests and also for
    78  // canonizing new heads. It also helps to always download the minimum necessary
    79  // amount of headers with a single request.
    80  type fetcherTreeNode struct {
    81  	hash             common.Hash
    82  	number           uint64
    83  	td               *big.Int
    84  	known, requested bool
    85  	parent           *fetcherTreeNode
    86  	children         []*fetcherTreeNode
    87  }
    88  
    89  // fetchRequest represents a header download request
    90  type fetchRequest struct {
    91  	hash    common.Hash
    92  	amount  uint64
    93  	peer    *peer
    94  	sent    mclock.AbsTime
    95  	timeout bool
    96  }
    97  
    98  // fetchResponse represents a header download response
    99  type fetchResponse struct {
   100  	reqID   uint64
   101  	headers []*types.Header
   102  	peer    *peer
   103  }
   104  
   105  // newLightFetcher creates a new light fetcher
   106  func newLightFetcher(pm *ProtocolManager) *lightFetcher {
   107  	f := &lightFetcher{
   108  		pm:             pm,
   109  		chain:          pm.blockchain.(*light.LightChain),
   110  		odr:            pm.odr,
   111  		peers:          make(map[*peer]*fetcherPeerInfo),
   112  		deliverChn:     make(chan fetchResponse, 100),
   113  		requested:      make(map[uint64]fetchRequest),
   114  		timeoutChn:     make(chan uint64),
   115  		requestChn:     make(chan bool, 100),
   116  		syncDone:       make(chan *peer),
   117  		maxConfirmedTd: big.NewInt(0),
   118  	}
   119  	go f.syncLoop()
   120  	return f
   121  }
   122  
   123  // syncLoop is the main event loop of the light fetcher
   124  func (f *lightFetcher) syncLoop() {
   125  	f.pm.wg.Add(1)
   126  	defer f.pm.wg.Done()
   127  
   128  	requesting := false
   129  	for {
   130  		select {
   131  		case <-f.pm.quitSync:
   132  			return
   133  		// when a new announce is received, request loop keeps running until
   134  		// no further requests are necessary or possible
   135  		case newAnnounce := <-f.requestChn:
   136  			f.lock.Lock()
   137  			s := requesting
   138  			requesting = false
   139  			if !f.syncing && !(newAnnounce && s) {
   140  				reqID := getNextReqID()
   141  				if peer, node, amount, retry := f.nextRequest(reqID); node != nil {
   142  					requesting = true
   143  					if reqID, ok := f.request(peer, reqID, node, amount); ok {
   144  						go func() {
   145  							time.Sleep(softRequestTimeout)
   146  							f.reqMu.Lock()
   147  							req, ok := f.requested[reqID]
   148  							if ok {
   149  								req.timeout = true
   150  								f.requested[reqID] = req
   151  							}
   152  							f.reqMu.Unlock()
   153  							// keep starting new requests while possible
   154  							f.requestChn <- false
   155  						}()
   156  					}
   157  				} else {
   158  					if retry {
   159  						requesting = true
   160  						go func() {
   161  							time.Sleep(time.Millisecond * 100)
   162  							f.requestChn <- false
   163  						}()
   164  					}
   165  				}
   166  			}
   167  			f.lock.Unlock()
   168  		case reqID := <-f.timeoutChn:
   169  			f.reqMu.Lock()
   170  			req, ok := f.requested[reqID]
   171  			if ok {
   172  				delete(f.requested, reqID)
   173  			}
   174  			f.reqMu.Unlock()
   175  			if ok {
   176  				f.pm.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), true)
   177  				glog.V(logger.Debug).Infof("hard timeout by peer %v", req.peer.id)
   178  				go f.pm.removePeer(req.peer.id)
   179  			}
   180  		case resp := <-f.deliverChn:
   181  			f.reqMu.Lock()
   182  			req, ok := f.requested[resp.reqID]
   183  			if ok && req.peer != resp.peer {
   184  				ok = false
   185  			}
   186  			if ok {
   187  				delete(f.requested, resp.reqID)
   188  			}
   189  			f.reqMu.Unlock()
   190  			if ok {
   191  				f.pm.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), req.timeout)
   192  			}
   193  			f.lock.Lock()
   194  			if !ok || !(f.syncing || f.processResponse(req, resp)) {
   195  				glog.V(logger.Debug).Infof("failed processing response by peer %v", resp.peer.id)
   196  				go f.pm.removePeer(resp.peer.id)
   197  			}
   198  			f.lock.Unlock()
   199  		case p := <-f.syncDone:
   200  			f.lock.Lock()
   201  			glog.V(logger.Debug).Infof("done synchronising with peer %v", p.id)
   202  			f.checkSyncedHeaders(p)
   203  			f.syncing = false
   204  			f.lock.Unlock()
   205  		}
   206  	}
   207  }
   208  
   209  // addPeer adds a new peer to the fetcher's peer set
   210  func (f *lightFetcher) addPeer(p *peer) {
   211  	p.lock.Lock()
   212  	p.hasBlock = func(hash common.Hash, number uint64) bool {
   213  		return f.peerHasBlock(p, hash, number)
   214  	}
   215  	p.lock.Unlock()
   216  
   217  	f.lock.Lock()
   218  	defer f.lock.Unlock()
   219  
   220  	f.peers[p] = &fetcherPeerInfo{nodeByHash: make(map[common.Hash]*fetcherTreeNode)}
   221  }
   222  
   223  // removePeer removes a new peer from the fetcher's peer set
   224  func (f *lightFetcher) removePeer(p *peer) {
   225  	p.lock.Lock()
   226  	p.hasBlock = nil
   227  	p.lock.Unlock()
   228  
   229  	f.lock.Lock()
   230  	defer f.lock.Unlock()
   231  
   232  	// check for potential timed out block delay statistics
   233  	f.checkUpdateStats(p, nil)
   234  	delete(f.peers, p)
   235  }
   236  
   237  // announce processes a new announcement message received from a peer, adding new
   238  // nodes to the peer's block tree and removing old nodes if necessary
   239  func (f *lightFetcher) announce(p *peer, head *announceData) {
   240  	f.lock.Lock()
   241  	defer f.lock.Unlock()
   242  	glog.V(logger.Debug).Infof("received announce from peer %v  #%d  %016x  reorg: %d", p.id, head.Number, head.Hash[:8], head.ReorgDepth)
   243  
   244  	fp := f.peers[p]
   245  	if fp == nil {
   246  		glog.V(logger.Debug).Infof("announce: unknown peer")
   247  		return
   248  	}
   249  
   250  	if fp.lastAnnounced != nil && head.Td.Cmp(fp.lastAnnounced.td) <= 0 {
   251  		// announced tds should be strictly monotonic
   252  		glog.V(logger.Debug).Infof("non-monotonic Td from peer %v", p.id)
   253  		go f.pm.removePeer(p.id)
   254  		return
   255  	}
   256  
   257  	n := fp.lastAnnounced
   258  	for i := uint64(0); i < head.ReorgDepth; i++ {
   259  		if n == nil {
   260  			break
   261  		}
   262  		n = n.parent
   263  	}
   264  	if n != nil {
   265  		// n is now the reorg common ancestor, add a new branch of nodes
   266  		// check if the node count is too high to add new nodes
   267  		locked := false
   268  		for uint64(fp.nodeCnt)+head.Number-n.number > maxNodeCount && fp.root != nil {
   269  			if !locked {
   270  				f.chain.LockChain()
   271  				defer f.chain.UnlockChain()
   272  				locked = true
   273  			}
   274  			// if one of root's children is canonical, keep it, delete other branches and root itself
   275  			var newRoot *fetcherTreeNode
   276  			for i, nn := range fp.root.children {
   277  				if core.GetCanonicalHash(f.pm.chainDb, nn.number) == nn.hash {
   278  					fp.root.children = append(fp.root.children[:i], fp.root.children[i+1:]...)
   279  					nn.parent = nil
   280  					newRoot = nn
   281  					break
   282  				}
   283  			}
   284  			fp.deleteNode(fp.root)
   285  			if n == fp.root {
   286  				n = newRoot
   287  			}
   288  			fp.root = newRoot
   289  			if newRoot == nil || !f.checkKnownNode(p, newRoot) {
   290  				fp.bestConfirmed = nil
   291  				fp.confirmedTd = nil
   292  			}
   293  
   294  			if n == nil {
   295  				break
   296  			}
   297  		}
   298  		if n != nil {
   299  			for n.number < head.Number {
   300  				nn := &fetcherTreeNode{number: n.number + 1, parent: n}
   301  				n.children = append(n.children, nn)
   302  				n = nn
   303  				fp.nodeCnt++
   304  			}
   305  			n.hash = head.Hash
   306  			n.td = head.Td
   307  			fp.nodeByHash[n.hash] = n
   308  		}
   309  	}
   310  	if n == nil {
   311  		// could not find reorg common ancestor or had to delete entire tree, a new root and a resync is needed
   312  		if fp.root != nil {
   313  			fp.deleteNode(fp.root)
   314  		}
   315  		n = &fetcherTreeNode{hash: head.Hash, number: head.Number, td: head.Td}
   316  		fp.root = n
   317  		fp.nodeCnt++
   318  		fp.nodeByHash[n.hash] = n
   319  		fp.bestConfirmed = nil
   320  		fp.confirmedTd = nil
   321  	}
   322  
   323  	f.checkKnownNode(p, n)
   324  	p.lock.Lock()
   325  	p.headInfo = head
   326  	fp.lastAnnounced = n
   327  	p.lock.Unlock()
   328  	f.checkUpdateStats(p, nil)
   329  	f.requestChn <- true
   330  }
   331  
   332  // peerHasBlock returns true if we can assume the peer knows the given block
   333  // based on its announcements
   334  func (f *lightFetcher) peerHasBlock(p *peer, hash common.Hash, number uint64) bool {
   335  	f.lock.Lock()
   336  	defer f.lock.Unlock()
   337  
   338  	fp := f.peers[p]
   339  	if fp == nil || fp.root == nil {
   340  		return false
   341  	}
   342  
   343  	if number >= fp.root.number {
   344  		// it is recent enough that if it is known, is should be in the peer's block tree
   345  		return fp.nodeByHash[hash] != nil
   346  	}
   347  	f.chain.LockChain()
   348  	defer f.chain.UnlockChain()
   349  	// if it's older than the peer's block tree root but it's in the same canonical chain
   350  	// than the root, we can still be sure the peer knows it
   351  	return core.GetCanonicalHash(f.pm.chainDb, fp.root.number) == fp.root.hash && core.GetCanonicalHash(f.pm.chainDb, number) == hash
   352  }
   353  
   354  // request initiates a header download request from a certain peer
   355  func (f *lightFetcher) request(p *peer, reqID uint64, n *fetcherTreeNode, amount uint64) (uint64, bool) {
   356  	fp := f.peers[p]
   357  	if fp == nil {
   358  		glog.V(logger.Debug).Infof("request: unknown peer")
   359  		p.fcServer.DeassignRequest(reqID)
   360  		return 0, false
   361  	}
   362  	if fp.bestConfirmed == nil || fp.root == nil || !f.checkKnownNode(p, fp.root) {
   363  		f.syncing = true
   364  		go func() {
   365  			glog.V(logger.Debug).Infof("synchronising with peer %v", p.id)
   366  			f.pm.synchronise(p)
   367  			f.syncDone <- p
   368  		}()
   369  		p.fcServer.DeassignRequest(reqID)
   370  		return 0, false
   371  	}
   372  
   373  	n.requested = true
   374  	cost := p.GetRequestCost(GetBlockHeadersMsg, int(amount))
   375  	p.fcServer.SendRequest(reqID, cost)
   376  	f.reqMu.Lock()
   377  	f.requested[reqID] = fetchRequest{hash: n.hash, amount: amount, peer: p, sent: mclock.Now()}
   378  	f.reqMu.Unlock()
   379  	go p.RequestHeadersByHash(reqID, cost, n.hash, int(amount), 0, true)
   380  	go func() {
   381  		time.Sleep(hardRequestTimeout)
   382  		f.timeoutChn <- reqID
   383  	}()
   384  	return reqID, true
   385  }
   386  
   387  // requestAmount calculates the amount of headers to be downloaded starting
   388  // from a certain head backwards
   389  func (f *lightFetcher) requestAmount(p *peer, n *fetcherTreeNode) uint64 {
   390  	amount := uint64(0)
   391  	nn := n
   392  	for nn != nil && !f.checkKnownNode(p, nn) {
   393  		nn = nn.parent
   394  		amount++
   395  	}
   396  	if nn == nil {
   397  		amount = n.number
   398  	}
   399  	return amount
   400  }
   401  
   402  // requestedID tells if a certain reqID has been requested by the fetcher
   403  func (f *lightFetcher) requestedID(reqID uint64) bool {
   404  	f.reqMu.RLock()
   405  	_, ok := f.requested[reqID]
   406  	f.reqMu.RUnlock()
   407  	return ok
   408  }
   409  
   410  // nextRequest selects the peer and announced head to be requested next, amount
   411  // to be downloaded starting from the head backwards is also returned
   412  func (f *lightFetcher) nextRequest(reqID uint64) (*peer, *fetcherTreeNode, uint64, bool) {
   413  	var (
   414  		bestHash   common.Hash
   415  		bestAmount uint64
   416  	)
   417  	bestTd := f.maxConfirmedTd
   418  
   419  	for p, fp := range f.peers {
   420  		for hash, n := range fp.nodeByHash {
   421  			if !f.checkKnownNode(p, n) && !n.requested && (bestTd == nil || n.td.Cmp(bestTd) >= 0) {
   422  				amount := f.requestAmount(p, n)
   423  				if bestTd == nil || n.td.Cmp(bestTd) > 0 || amount < bestAmount {
   424  					bestHash = hash
   425  					bestAmount = amount
   426  					bestTd = n.td
   427  				}
   428  			}
   429  		}
   430  	}
   431  	if bestTd == f.maxConfirmedTd {
   432  		return nil, nil, 0, false
   433  	}
   434  
   435  	peer, _, locked := f.pm.serverPool.selectPeer(reqID, func(p *peer) (bool, time.Duration) {
   436  		fp := f.peers[p]
   437  		if fp == nil || fp.nodeByHash[bestHash] == nil {
   438  			return false, 0
   439  		}
   440  		return true, p.fcServer.CanSend(p.GetRequestCost(GetBlockHeadersMsg, int(bestAmount)))
   441  	})
   442  	if !locked {
   443  		return nil, nil, 0, true
   444  	}
   445  	var node *fetcherTreeNode
   446  	if peer != nil {
   447  		node = f.peers[peer].nodeByHash[bestHash]
   448  	}
   449  	return peer, node, bestAmount, false
   450  }
   451  
   452  // deliverHeaders delivers header download request responses for processing
   453  func (f *lightFetcher) deliverHeaders(peer *peer, reqID uint64, headers []*types.Header) {
   454  	f.deliverChn <- fetchResponse{reqID: reqID, headers: headers, peer: peer}
   455  }
   456  
   457  // processResponse processes header download request responses, returns true if successful
   458  func (f *lightFetcher) processResponse(req fetchRequest, resp fetchResponse) bool {
   459  	if uint64(len(resp.headers)) != req.amount || resp.headers[0].Hash() != req.hash {
   460  		glog.V(logger.Debug).Infof("response mismatch %v %016x != %v %016x", len(resp.headers), resp.headers[0].Hash().Bytes()[:8], req.amount, req.hash[:8])
   461  		return false
   462  	}
   463  	headers := make([]*types.Header, req.amount)
   464  	for i, header := range resp.headers {
   465  		headers[int(req.amount)-1-i] = header
   466  	}
   467  	if _, err := f.chain.InsertHeaderChain(headers, 1); err != nil {
   468  		if err == core.BlockFutureErr {
   469  			return true
   470  		}
   471  		glog.V(logger.Debug).Infof("InsertHeaderChain error: %v", err)
   472  		return false
   473  	}
   474  	tds := make([]*big.Int, len(headers))
   475  	for i, header := range headers {
   476  		td := f.chain.GetTd(header.Hash(), header.Number.Uint64())
   477  		if td == nil {
   478  			glog.V(logger.Debug).Infof("TD not found for header %v of %v", i+1, len(headers))
   479  			return false
   480  		}
   481  		tds[i] = td
   482  	}
   483  	f.newHeaders(headers, tds)
   484  	return true
   485  }
   486  
   487  // newHeaders updates the block trees of all active peers according to a newly
   488  // downloaded and validated batch or headers
   489  func (f *lightFetcher) newHeaders(headers []*types.Header, tds []*big.Int) {
   490  	var maxTd *big.Int
   491  	for p, fp := range f.peers {
   492  		if !f.checkAnnouncedHeaders(fp, headers, tds) {
   493  			glog.V(logger.Debug).Infof("announce inconsistency by peer %v", p.id)
   494  			go f.pm.removePeer(p.id)
   495  		}
   496  		if fp.confirmedTd != nil && (maxTd == nil || maxTd.Cmp(fp.confirmedTd) > 0) {
   497  			maxTd = fp.confirmedTd
   498  		}
   499  	}
   500  	if maxTd != nil {
   501  		f.updateMaxConfirmedTd(maxTd)
   502  	}
   503  }
   504  
   505  // checkAnnouncedHeaders updates peer's block tree if necessary after validating
   506  // a batch of headers. It searches for the latest header in the batch that has a
   507  // matching tree node (if any), and if it has not been marked as known already,
   508  // sets it and its parents to known (even those which are older than the currently
   509  // validated ones). Return value shows if all hashes, numbers and Tds matched
   510  // correctly to the announced values (otherwise the peer should be dropped).
   511  func (f *lightFetcher) checkAnnouncedHeaders(fp *fetcherPeerInfo, headers []*types.Header, tds []*big.Int) bool {
   512  	var (
   513  		n      *fetcherTreeNode
   514  		header *types.Header
   515  		td     *big.Int
   516  	)
   517  
   518  	for i := len(headers) - 1; ; i-- {
   519  		if i < 0 {
   520  			if n == nil {
   521  				// no more headers and nothing to match
   522  				return true
   523  			}
   524  			// we ran out of recently delivered headers but have not reached a node known by this peer yet, continue matching
   525  			td = f.chain.GetTd(header.ParentHash, header.Number.Uint64()-1)
   526  			header = f.chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
   527  		} else {
   528  			header = headers[i]
   529  			td = tds[i]
   530  		}
   531  		hash := header.Hash()
   532  		number := header.Number.Uint64()
   533  		if n == nil {
   534  			n = fp.nodeByHash[hash]
   535  		}
   536  		if n != nil {
   537  			if n.td == nil {
   538  				// node was unannounced
   539  				if nn := fp.nodeByHash[hash]; nn != nil {
   540  					// if there was already a node with the same hash, continue there and drop this one
   541  					nn.children = append(nn.children, n.children...)
   542  					n.children = nil
   543  					fp.deleteNode(n)
   544  					n = nn
   545  				} else {
   546  					n.hash = hash
   547  					n.td = td
   548  					fp.nodeByHash[hash] = n
   549  				}
   550  			}
   551  			// check if it matches the header
   552  			if n.hash != hash || n.number != number || n.td.Cmp(td) != 0 {
   553  				// peer has previously made an invalid announcement
   554  				return false
   555  			}
   556  			if n.known {
   557  				// we reached a known node that matched our expectations, return with success
   558  				return true
   559  			}
   560  			n.known = true
   561  			if fp.confirmedTd == nil || td.Cmp(fp.confirmedTd) > 0 {
   562  				fp.confirmedTd = td
   563  				fp.bestConfirmed = n
   564  			}
   565  			n = n.parent
   566  			if n == nil {
   567  				return true
   568  			}
   569  		}
   570  	}
   571  }
   572  
   573  // checkSyncedHeaders updates peer's block tree after synchronisation by marking
   574  // downloaded headers as known. If none of the announced headers are found after
   575  // syncing, the peer is dropped.
   576  func (f *lightFetcher) checkSyncedHeaders(p *peer) {
   577  	fp := f.peers[p]
   578  	if fp == nil {
   579  		glog.V(logger.Debug).Infof("checkSyncedHeaders: unknown peer")
   580  		return
   581  	}
   582  	n := fp.lastAnnounced
   583  	var td *big.Int
   584  	for n != nil {
   585  		if td = f.chain.GetTd(n.hash, n.number); td != nil {
   586  			break
   587  		}
   588  		n = n.parent
   589  	}
   590  	// now n is the latest downloaded header after syncing
   591  	if n == nil {
   592  		glog.V(logger.Debug).Infof("synchronisation failed with peer %v", p.id)
   593  		go f.pm.removePeer(p.id)
   594  	} else {
   595  		header := f.chain.GetHeader(n.hash, n.number)
   596  		f.newHeaders([]*types.Header{header}, []*big.Int{td})
   597  	}
   598  }
   599  
   600  // checkKnownNode checks if a block tree node is known (downloaded and validated)
   601  // If it was not known previously but found in the database, sets its known flag
   602  func (f *lightFetcher) checkKnownNode(p *peer, n *fetcherTreeNode) bool {
   603  	if n.known {
   604  		return true
   605  	}
   606  	td := f.chain.GetTd(n.hash, n.number)
   607  	if td == nil {
   608  		return false
   609  	}
   610  
   611  	fp := f.peers[p]
   612  	if fp == nil {
   613  		glog.V(logger.Debug).Infof("checkKnownNode: unknown peer")
   614  		return false
   615  	}
   616  	header := f.chain.GetHeader(n.hash, n.number)
   617  	if !f.checkAnnouncedHeaders(fp, []*types.Header{header}, []*big.Int{td}) {
   618  		glog.V(logger.Debug).Infof("announce inconsistency by peer %v", p.id)
   619  		go f.pm.removePeer(p.id)
   620  	}
   621  	if fp.confirmedTd != nil {
   622  		f.updateMaxConfirmedTd(fp.confirmedTd)
   623  	}
   624  	return n.known
   625  }
   626  
   627  // deleteNode deletes a node and its child subtrees from a peer's block tree
   628  func (fp *fetcherPeerInfo) deleteNode(n *fetcherTreeNode) {
   629  	if n.parent != nil {
   630  		for i, nn := range n.parent.children {
   631  			if nn == n {
   632  				n.parent.children = append(n.parent.children[:i], n.parent.children[i+1:]...)
   633  				break
   634  			}
   635  		}
   636  	}
   637  	for {
   638  		if n.td != nil {
   639  			delete(fp.nodeByHash, n.hash)
   640  		}
   641  		fp.nodeCnt--
   642  		if len(n.children) == 0 {
   643  			return
   644  		}
   645  		for i, nn := range n.children {
   646  			if i == 0 {
   647  				n = nn
   648  			} else {
   649  				fp.deleteNode(nn)
   650  			}
   651  		}
   652  	}
   653  }
   654  
   655  // updateStatsEntry items form a linked list that is expanded with a new item every time a new head with a higher Td
   656  // than the previous one has been downloaded and validated. The list contains a series of maximum confirmed Td values
   657  // and the time these values have been confirmed, both increasing monotonically. A maximum confirmed Td is calculated
   658  // both globally for all peers and also for each individual peer (meaning that the given peer has announced the head
   659  // and it has also been downloaded from any peer, either before or after the given announcement).
   660  // The linked list has a global tail where new confirmed Td entries are added and a separate head for each peer,
   661  // pointing to the next Td entry that is higher than the peer's max confirmed Td (nil if it has already confirmed
   662  // the current global head).
   663  type updateStatsEntry struct {
   664  	time mclock.AbsTime
   665  	td   *big.Int
   666  	next *updateStatsEntry
   667  }
   668  
   669  // updateMaxConfirmedTd updates the block delay statistics of active peers. Whenever a new highest Td is confirmed,
   670  // adds it to the end of a linked list together with the time it has been confirmed. Then checks which peers have
   671  // already confirmed a head with the same or higher Td (which counts as zero block delay) and updates their statistics.
   672  // Those who have not confirmed such a head by now will be updated by a subsequent checkUpdateStats call with a
   673  // positive block delay value.
   674  func (f *lightFetcher) updateMaxConfirmedTd(td *big.Int) {
   675  	if f.maxConfirmedTd == nil || td.Cmp(f.maxConfirmedTd) > 0 {
   676  		f.maxConfirmedTd = td
   677  		newEntry := &updateStatsEntry{
   678  			time: mclock.Now(),
   679  			td:   td,
   680  		}
   681  		if f.lastUpdateStats != nil {
   682  			f.lastUpdateStats.next = newEntry
   683  		}
   684  		f.lastUpdateStats = newEntry
   685  		for p := range f.peers {
   686  			f.checkUpdateStats(p, newEntry)
   687  		}
   688  	}
   689  }
   690  
   691  // checkUpdateStats checks those peers who have not confirmed a certain highest Td (or a larger one) by the time it
   692  // has been confirmed by another peer. If they have confirmed such a head by now, their stats are updated with the
   693  // block delay which is (this peer's confirmation time)-(first confirmation time). After blockDelayTimeout has passed,
   694  // the stats are updated with blockDelayTimeout value. In either case, the confirmed or timed out updateStatsEntry
   695  // items are removed from the head of the linked list.
   696  // If a new entry has been added to the global tail, it is passed as a parameter here even though this function
   697  // assumes that it has already been added, so that if the peer's list is empty (all heads confirmed, head is nil),
   698  // it can set the new head to newEntry.
   699  func (f *lightFetcher) checkUpdateStats(p *peer, newEntry *updateStatsEntry) {
   700  	now := mclock.Now()
   701  	fp := f.peers[p]
   702  	if fp == nil {
   703  		glog.V(logger.Debug).Infof("checkUpdateStats: unknown peer")
   704  		return
   705  	}
   706  	if newEntry != nil && fp.firstUpdateStats == nil {
   707  		fp.firstUpdateStats = newEntry
   708  	}
   709  	for fp.firstUpdateStats != nil && fp.firstUpdateStats.time <= now-mclock.AbsTime(blockDelayTimeout) {
   710  		f.pm.serverPool.adjustBlockDelay(p.poolEntry, blockDelayTimeout)
   711  		fp.firstUpdateStats = fp.firstUpdateStats.next
   712  	}
   713  	if fp.confirmedTd != nil {
   714  		for fp.firstUpdateStats != nil && fp.firstUpdateStats.td.Cmp(fp.confirmedTd) <= 0 {
   715  			f.pm.serverPool.adjustBlockDelay(p.poolEntry, time.Duration(now-fp.firstUpdateStats.time))
   716  			fp.firstUpdateStats = fp.firstUpdateStats.next
   717  		}
   718  	}
   719  }