github.com/nitinawathare/ethereumassignment3@v0.0.0-20211021213010-f07344c2b868/go-ethereum/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
    18  
    19  import (
    20  	"math/big"
    21  	"sync"
    22  	"time"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/common/mclock"
    26  	"github.com/ethereum/go-ethereum/consensus"
    27  	"github.com/ethereum/go-ethereum/core/rawdb"
    28  	"github.com/ethereum/go-ethereum/core/types"
    29  	"github.com/ethereum/go-ethereum/light"
    30  	"github.com/ethereum/go-ethereum/log"
    31  )
    32  
    33  const (
    34  	blockDelayTimeout    = time.Second * 10 // timeout for a peer to announce a head that has already been confirmed by others
    35  	maxNodeCount         = 20               // maximum number of fetcherTreeNode entries remembered for each peer
    36  	serverStateAvailable = 100              // number of recent blocks where state availability is assumed
    37  )
    38  
    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.
    42  type lightFetcher struct {
    43  	pm    *ProtocolManager
    44  	odr   *LesOdr
    45  	chain lightChain
    46  
    47  	lock            sync.Mutex // lock protects access to the fetcher's internal state variables except sent requests
    48  	maxConfirmedTd  *big.Int
    49  	peers           map[*peer]*fetcherPeerInfo
    50  	lastUpdateStats *updateStatsEntry
    51  	syncing         bool
    52  	syncDone        chan *peer
    53  
    54  	reqMu             sync.RWMutex // reqMu protects access to sent header fetch requests
    55  	requested         map[uint64]fetchRequest
    56  	deliverChn        chan fetchResponse
    57  	timeoutChn        chan uint64
    58  	requestChn        chan bool // true if initiated from outside
    59  	lastTrustedHeader *types.Header
    60  }
    61  
    62  // lightChain extends the BlockChain interface by locking.
    63  type lightChain interface {
    64  	BlockChain
    65  	LockChain()
    66  	UnlockChain()
    67  }
    68  
    69  // fetcherPeerInfo holds fetcher-specific information about each active peer
    70  type fetcherPeerInfo struct {
    71  	root, lastAnnounced *fetcherTreeNode
    72  	nodeCnt             int
    73  	confirmedTd         *big.Int
    74  	bestConfirmed       *fetcherTreeNode
    75  	nodeByHash          map[common.Hash]*fetcherTreeNode
    76  	firstUpdateStats    *updateStatsEntry
    77  }
    78  
    79  // fetcherTreeNode is a node of a tree that holds information about blocks recently
    80  // announced and confirmed by a certain peer. Each new announce message from a peer
    81  // adds nodes to the tree, based on the previous announced head and the reorg depth.
    82  // There are three possible states for a tree node:
    83  // - announced: not downloaded (known) yet, but we know its head, number and td
    84  // - intermediate: not known, hash and td are empty, they are filled out when it becomes known
    85  // - known: both announced by this peer and downloaded (from any peer).
    86  // This structure makes it possible to always know which peer has a certain block,
    87  // which is necessary for selecting a suitable peer for ODR requests and also for
    88  // canonizing new heads. It also helps to always download the minimum necessary
    89  // amount of headers with a single request.
    90  type fetcherTreeNode struct {
    91  	hash             common.Hash
    92  	number           uint64
    93  	td               *big.Int
    94  	known, requested bool
    95  	parent           *fetcherTreeNode
    96  	children         []*fetcherTreeNode
    97  }
    98  
    99  // fetchRequest represents a header download request
   100  type fetchRequest struct {
   101  	hash    common.Hash
   102  	amount  uint64
   103  	peer    *peer
   104  	sent    mclock.AbsTime
   105  	timeout bool
   106  }
   107  
   108  // fetchResponse represents a header download response
   109  type fetchResponse struct {
   110  	reqID   uint64
   111  	headers []*types.Header
   112  	peer    *peer
   113  }
   114  
   115  // newLightFetcher creates a new light fetcher
   116  func newLightFetcher(pm *ProtocolManager) *lightFetcher {
   117  	f := &lightFetcher{
   118  		pm:             pm,
   119  		chain:          pm.blockchain.(*light.LightChain),
   120  		odr:            pm.odr,
   121  		peers:          make(map[*peer]*fetcherPeerInfo),
   122  		deliverChn:     make(chan fetchResponse, 100),
   123  		requested:      make(map[uint64]fetchRequest),
   124  		timeoutChn:     make(chan uint64),
   125  		requestChn:     make(chan bool, 100),
   126  		syncDone:       make(chan *peer),
   127  		maxConfirmedTd: big.NewInt(0),
   128  	}
   129  	pm.peers.notify(f)
   130  
   131  	f.pm.wg.Add(1)
   132  	go f.syncLoop()
   133  	return f
   134  }
   135  
   136  // syncLoop is the main event loop of the light fetcher
   137  func (f *lightFetcher) syncLoop() {
   138  	requesting := false
   139  	defer f.pm.wg.Done()
   140  	for {
   141  		select {
   142  		case <-f.pm.quitSync:
   143  			return
   144  		// when a new announce is received, request loop keeps running until
   145  		// no further requests are necessary or possible
   146  		case newAnnounce := <-f.requestChn:
   147  			f.lock.Lock()
   148  			s := requesting
   149  			requesting = false
   150  			var (
   151  				rq      *distReq
   152  				reqID   uint64
   153  				syncing bool
   154  			)
   155  
   156  			if !f.syncing && !(newAnnounce && s) {
   157  				rq, reqID, syncing = f.nextRequest()
   158  			}
   159  			f.lock.Unlock()
   160  
   161  			if rq != nil {
   162  				requesting = true
   163  				if _, ok := <-f.pm.reqDist.queue(rq); ok {
   164  					if syncing {
   165  						f.lock.Lock()
   166  						f.syncing = true
   167  						f.lock.Unlock()
   168  					} else {
   169  						go func() {
   170  							time.Sleep(softRequestTimeout)
   171  							f.reqMu.Lock()
   172  							req, ok := f.requested[reqID]
   173  							if ok {
   174  								req.timeout = true
   175  								f.requested[reqID] = req
   176  							}
   177  							f.reqMu.Unlock()
   178  							// keep starting new requests while possible
   179  							f.requestChn <- false
   180  						}()
   181  					}
   182  				} else {
   183  					f.requestChn <- false
   184  				}
   185  			}
   186  		case reqID := <-f.timeoutChn:
   187  			f.reqMu.Lock()
   188  			req, ok := f.requested[reqID]
   189  			if ok {
   190  				delete(f.requested, reqID)
   191  			}
   192  			f.reqMu.Unlock()
   193  			if ok {
   194  				f.pm.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), true)
   195  				req.peer.Log().Debug("Fetching data timed out hard")
   196  				go f.pm.removePeer(req.peer.id)
   197  			}
   198  		case resp := <-f.deliverChn:
   199  			f.reqMu.Lock()
   200  			req, ok := f.requested[resp.reqID]
   201  			if ok && req.peer != resp.peer {
   202  				ok = false
   203  			}
   204  			if ok {
   205  				delete(f.requested, resp.reqID)
   206  			}
   207  			f.reqMu.Unlock()
   208  			if ok {
   209  				f.pm.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), req.timeout)
   210  			}
   211  			f.lock.Lock()
   212  			if !ok || !(f.syncing || f.processResponse(req, resp)) {
   213  				resp.peer.Log().Debug("Failed processing response")
   214  				go f.pm.removePeer(resp.peer.id)
   215  			}
   216  			f.lock.Unlock()
   217  		case p := <-f.syncDone:
   218  			f.lock.Lock()
   219  			p.Log().Debug("Done synchronising with peer")
   220  			f.checkSyncedHeaders(p)
   221  			f.syncing = false
   222  			f.lock.Unlock()
   223  			f.requestChn <- false
   224  		}
   225  	}
   226  }
   227  
   228  // registerPeer adds a new peer to the fetcher's peer set
   229  func (f *lightFetcher) registerPeer(p *peer) {
   230  	p.lock.Lock()
   231  	p.hasBlock = func(hash common.Hash, number uint64, hasState bool) bool {
   232  		return f.peerHasBlock(p, hash, number, hasState)
   233  	}
   234  	p.lock.Unlock()
   235  
   236  	f.lock.Lock()
   237  	defer f.lock.Unlock()
   238  	f.peers[p] = &fetcherPeerInfo{nodeByHash: make(map[common.Hash]*fetcherTreeNode)}
   239  }
   240  
   241  // unregisterPeer removes a new peer from the fetcher's peer set
   242  func (f *lightFetcher) unregisterPeer(p *peer) {
   243  	p.lock.Lock()
   244  	p.hasBlock = nil
   245  	p.lock.Unlock()
   246  
   247  	f.lock.Lock()
   248  	defer f.lock.Unlock()
   249  
   250  	// check for potential timed out block delay statistics
   251  	f.checkUpdateStats(p, nil)
   252  	delete(f.peers, p)
   253  }
   254  
   255  // announce processes a new announcement message received from a peer, adding new
   256  // nodes to the peer's block tree and removing old nodes if necessary
   257  func (f *lightFetcher) announce(p *peer, head *announceData) {
   258  	f.lock.Lock()
   259  	defer f.lock.Unlock()
   260  	p.Log().Debug("Received new announcement", "number", head.Number, "hash", head.Hash, "reorg", head.ReorgDepth)
   261  
   262  	fp := f.peers[p]
   263  	if fp == nil {
   264  		p.Log().Debug("Announcement from unknown peer")
   265  		return
   266  	}
   267  
   268  	if fp.lastAnnounced != nil && head.Td.Cmp(fp.lastAnnounced.td) <= 0 {
   269  		// announced tds should be strictly monotonic
   270  		p.Log().Debug("Received non-monotonic td", "current", head.Td, "previous", fp.lastAnnounced.td)
   271  		go f.pm.removePeer(p.id)
   272  		return
   273  	}
   274  
   275  	n := fp.lastAnnounced
   276  	for i := uint64(0); i < head.ReorgDepth; i++ {
   277  		if n == nil {
   278  			break
   279  		}
   280  		n = n.parent
   281  	}
   282  	// n is now the reorg common ancestor, add a new branch of nodes
   283  	if n != nil && (head.Number >= n.number+maxNodeCount || head.Number <= n.number) {
   284  		// if announced head block height is lower or same as n or too far from it to add
   285  		// intermediate nodes then discard previous announcement info and trigger a resync
   286  		n = nil
   287  		fp.nodeCnt = 0
   288  		fp.nodeByHash = make(map[common.Hash]*fetcherTreeNode)
   289  	}
   290  	// check if the node count is too high to add new nodes, discard oldest ones if necessary
   291  	if n != nil {
   292  		// n is now the reorg common ancestor, add a new branch of nodes
   293  		// check if the node count is too high to add new nodes
   294  		locked := false
   295  		for uint64(fp.nodeCnt)+head.Number-n.number > maxNodeCount && fp.root != nil {
   296  			if !locked {
   297  				f.chain.LockChain()
   298  				defer f.chain.UnlockChain()
   299  				locked = true
   300  			}
   301  			// if one of root's children is canonical, keep it, delete other branches and root itself
   302  			var newRoot *fetcherTreeNode
   303  			for i, nn := range fp.root.children {
   304  				if rawdb.ReadCanonicalHash(f.pm.chainDb, nn.number) == nn.hash {
   305  					fp.root.children = append(fp.root.children[:i], fp.root.children[i+1:]...)
   306  					nn.parent = nil
   307  					newRoot = nn
   308  					break
   309  				}
   310  			}
   311  			fp.deleteNode(fp.root)
   312  			if n == fp.root {
   313  				n = newRoot
   314  			}
   315  			fp.root = newRoot
   316  			if newRoot == nil || !f.checkKnownNode(p, newRoot) {
   317  				fp.bestConfirmed = nil
   318  				fp.confirmedTd = nil
   319  			}
   320  
   321  			if n == nil {
   322  				break
   323  			}
   324  		}
   325  		if n != nil {
   326  			for n.number < head.Number {
   327  				nn := &fetcherTreeNode{number: n.number + 1, parent: n}
   328  				n.children = append(n.children, nn)
   329  				n = nn
   330  				fp.nodeCnt++
   331  			}
   332  			n.hash = head.Hash
   333  			n.td = head.Td
   334  			fp.nodeByHash[n.hash] = n
   335  		}
   336  	}
   337  
   338  	if n == nil {
   339  		// could not find reorg common ancestor or had to delete entire tree, a new root and a resync is needed
   340  		if fp.root != nil {
   341  			fp.deleteNode(fp.root)
   342  		}
   343  		n = &fetcherTreeNode{hash: head.Hash, number: head.Number, td: head.Td}
   344  		fp.root = n
   345  		fp.nodeCnt++
   346  		fp.nodeByHash[n.hash] = n
   347  		fp.bestConfirmed = nil
   348  		fp.confirmedTd = nil
   349  	}
   350  
   351  	f.checkKnownNode(p, n)
   352  	p.lock.Lock()
   353  	p.headInfo = head
   354  	fp.lastAnnounced = n
   355  	p.lock.Unlock()
   356  	f.checkUpdateStats(p, nil)
   357  	f.requestChn <- true
   358  }
   359  
   360  // peerHasBlock returns true if we can assume the peer knows the given block
   361  // based on its announcements
   362  func (f *lightFetcher) peerHasBlock(p *peer, hash common.Hash, number uint64, hasState bool) bool {
   363  	f.lock.Lock()
   364  	defer f.lock.Unlock()
   365  
   366  	fp := f.peers[p]
   367  	if fp == nil || fp.root == nil {
   368  		return false
   369  	}
   370  
   371  	if hasState {
   372  		if fp.lastAnnounced == nil || fp.lastAnnounced.number > number+serverStateAvailable {
   373  			return false
   374  		}
   375  	}
   376  
   377  	if f.syncing {
   378  		// always return true when syncing
   379  		// false positives are acceptable, a more sophisticated condition can be implemented later
   380  		return true
   381  	}
   382  
   383  	if number >= fp.root.number {
   384  		// it is recent enough that if it is known, is should be in the peer's block tree
   385  		return fp.nodeByHash[hash] != nil
   386  	}
   387  	f.chain.LockChain()
   388  	defer f.chain.UnlockChain()
   389  	// if it's older than the peer's block tree root but it's in the same canonical chain
   390  	// as the root, we can still be sure the peer knows it
   391  	//
   392  	// when syncing, just check if it is part of the known chain, there is nothing better we
   393  	// can do since we do not know the most recent block hash yet
   394  	return rawdb.ReadCanonicalHash(f.pm.chainDb, fp.root.number) == fp.root.hash && rawdb.ReadCanonicalHash(f.pm.chainDb, number) == hash
   395  }
   396  
   397  // requestAmount calculates the amount of headers to be downloaded starting
   398  // from a certain head backwards
   399  func (f *lightFetcher) requestAmount(p *peer, n *fetcherTreeNode) uint64 {
   400  	amount := uint64(0)
   401  	nn := n
   402  	for nn != nil && !f.checkKnownNode(p, nn) {
   403  		nn = nn.parent
   404  		amount++
   405  	}
   406  	if nn == nil {
   407  		amount = n.number
   408  	}
   409  	return amount
   410  }
   411  
   412  // requestedID tells if a certain reqID has been requested by the fetcher
   413  func (f *lightFetcher) requestedID(reqID uint64) bool {
   414  	f.reqMu.RLock()
   415  	_, ok := f.requested[reqID]
   416  	f.reqMu.RUnlock()
   417  	return ok
   418  }
   419  
   420  // nextRequest selects the peer and announced head to be requested next, amount
   421  // to be downloaded starting from the head backwards is also returned
   422  func (f *lightFetcher) nextRequest() (*distReq, uint64, bool) {
   423  	var (
   424  		bestHash    common.Hash
   425  		bestAmount  uint64
   426  		bestTd      *big.Int
   427  		bestSyncing bool
   428  	)
   429  	bestHash, bestAmount, bestTd, bestSyncing = f.findBestRequest()
   430  
   431  	if bestTd == f.maxConfirmedTd {
   432  		return nil, 0, false
   433  	}
   434  
   435  	var rq *distReq
   436  	reqID := genReqID()
   437  	if bestSyncing {
   438  		rq = f.newFetcherDistReqForSync(bestHash)
   439  	} else {
   440  		rq = f.newFetcherDistReq(bestHash, reqID, bestAmount)
   441  	}
   442  	return rq, reqID, bestSyncing
   443  }
   444  
   445  // findBestRequest finds the best head to request that has been announced by but not yet requested from a known peer.
   446  // It also returns the announced Td (which should be verified after fetching the head),
   447  // the necessary amount to request and whether a downloader sync is necessary instead of a normal header request.
   448  func (f *lightFetcher) findBestRequest() (bestHash common.Hash, bestAmount uint64, bestTd *big.Int, bestSyncing bool) {
   449  	bestTd = f.maxConfirmedTd
   450  	bestSyncing = false
   451  
   452  	for p, fp := range f.peers {
   453  		for hash, n := range fp.nodeByHash {
   454  			if f.checkKnownNode(p, n) || n.requested {
   455  				continue
   456  			}
   457  
   458  			//if ulc mode is disabled, isTrustedHash returns true
   459  			amount := f.requestAmount(p, n)
   460  			if (bestTd == nil || n.td.Cmp(bestTd) > 0 || amount < bestAmount) && (f.isTrustedHash(hash) || f.maxConfirmedTd.Int64() == 0) {
   461  				bestHash = hash
   462  				bestTd = n.td
   463  				bestAmount = amount
   464  				bestSyncing = fp.bestConfirmed == nil || fp.root == nil || !f.checkKnownNode(p, fp.root)
   465  			}
   466  		}
   467  	}
   468  	return
   469  }
   470  
   471  // isTrustedHash checks if the block can be trusted by the minimum trusted fraction.
   472  func (f *lightFetcher) isTrustedHash(hash common.Hash) bool {
   473  	if !f.pm.isULCEnabled() {
   474  		return true
   475  	}
   476  
   477  	var numAgreed int
   478  	for p, fp := range f.peers {
   479  		if !p.isTrusted {
   480  			continue
   481  		}
   482  		if _, ok := fp.nodeByHash[hash]; !ok {
   483  			continue
   484  		}
   485  
   486  		numAgreed++
   487  	}
   488  
   489  	return 100*numAgreed/len(f.pm.ulc.trustedKeys) >= f.pm.ulc.minTrustedFraction
   490  }
   491  
   492  func (f *lightFetcher) newFetcherDistReqForSync(bestHash common.Hash) *distReq {
   493  	return &distReq{
   494  		getCost: func(dp distPeer) uint64 {
   495  			return 0
   496  		},
   497  		canSend: func(dp distPeer) bool {
   498  			p := dp.(*peer)
   499  			f.lock.Lock()
   500  			defer f.lock.Unlock()
   501  
   502  			if p.isOnlyAnnounce {
   503  				return false
   504  			}
   505  
   506  			fp := f.peers[p]
   507  			return fp != nil && fp.nodeByHash[bestHash] != nil
   508  		},
   509  		request: func(dp distPeer) func() {
   510  			if f.pm.isULCEnabled() {
   511  				//keep last trusted header before sync
   512  				f.setLastTrustedHeader(f.chain.CurrentHeader())
   513  			}
   514  			go func() {
   515  				p := dp.(*peer)
   516  				p.Log().Debug("Synchronisation started")
   517  				f.pm.synchronise(p)
   518  				f.syncDone <- p
   519  			}()
   520  			return nil
   521  		},
   522  	}
   523  }
   524  
   525  // newFetcherDistReq creates a new request for the distributor.
   526  func (f *lightFetcher) newFetcherDistReq(bestHash common.Hash, reqID uint64, bestAmount uint64) *distReq {
   527  	return &distReq{
   528  		getCost: func(dp distPeer) uint64 {
   529  			p := dp.(*peer)
   530  			return p.GetRequestCost(GetBlockHeadersMsg, int(bestAmount))
   531  		},
   532  		canSend: func(dp distPeer) bool {
   533  			p := dp.(*peer)
   534  			f.lock.Lock()
   535  			defer f.lock.Unlock()
   536  
   537  			if p.isOnlyAnnounce {
   538  				return false
   539  			}
   540  
   541  			fp := f.peers[p]
   542  			if fp == nil {
   543  				return false
   544  			}
   545  			n := fp.nodeByHash[bestHash]
   546  			return n != nil && !n.requested
   547  		},
   548  		request: func(dp distPeer) func() {
   549  			p := dp.(*peer)
   550  			f.lock.Lock()
   551  			fp := f.peers[p]
   552  			if fp != nil {
   553  				n := fp.nodeByHash[bestHash]
   554  				if n != nil {
   555  					n.requested = true
   556  				}
   557  			}
   558  			f.lock.Unlock()
   559  
   560  			cost := p.GetRequestCost(GetBlockHeadersMsg, int(bestAmount))
   561  			p.fcServer.QueuedRequest(reqID, cost)
   562  			f.reqMu.Lock()
   563  			f.requested[reqID] = fetchRequest{hash: bestHash, amount: bestAmount, peer: p, sent: mclock.Now()}
   564  			f.reqMu.Unlock()
   565  			go func() {
   566  				time.Sleep(hardRequestTimeout)
   567  				f.timeoutChn <- reqID
   568  			}()
   569  			return func() { p.RequestHeadersByHash(reqID, cost, bestHash, int(bestAmount), 0, true) }
   570  		},
   571  	}
   572  }
   573  
   574  // deliverHeaders delivers header download request responses for processing
   575  func (f *lightFetcher) deliverHeaders(peer *peer, reqID uint64, headers []*types.Header) {
   576  	f.deliverChn <- fetchResponse{reqID: reqID, headers: headers, peer: peer}
   577  }
   578  
   579  // processResponse processes header download request responses, returns true if successful
   580  func (f *lightFetcher) processResponse(req fetchRequest, resp fetchResponse) bool {
   581  	if uint64(len(resp.headers)) != req.amount || resp.headers[0].Hash() != req.hash {
   582  		req.peer.Log().Debug("Response content mismatch", "requested", len(resp.headers), "reqfrom", resp.headers[0], "delivered", req.amount, "delfrom", req.hash)
   583  		return false
   584  	}
   585  	headers := make([]*types.Header, req.amount)
   586  	for i, header := range resp.headers {
   587  		headers[int(req.amount)-1-i] = header
   588  	}
   589  
   590  	if _, err := f.chain.InsertHeaderChain(headers, 1); err != nil {
   591  		if err == consensus.ErrFutureBlock {
   592  			return true
   593  		}
   594  		log.Debug("Failed to insert header chain", "err", err)
   595  		return false
   596  	}
   597  	tds := make([]*big.Int, len(headers))
   598  	for i, header := range headers {
   599  		td := f.chain.GetTd(header.Hash(), header.Number.Uint64())
   600  		if td == nil {
   601  			log.Debug("Total difficulty not found for header", "index", i+1, "number", header.Number, "hash", header.Hash())
   602  			return false
   603  		}
   604  		tds[i] = td
   605  	}
   606  	f.newHeaders(headers, tds)
   607  	return true
   608  }
   609  
   610  // newHeaders updates the block trees of all active peers according to a newly
   611  // downloaded and validated batch or headers
   612  func (f *lightFetcher) newHeaders(headers []*types.Header, tds []*big.Int) {
   613  	var maxTd *big.Int
   614  
   615  	for p, fp := range f.peers {
   616  		if !f.checkAnnouncedHeaders(fp, headers, tds) {
   617  			p.Log().Debug("Inconsistent announcement")
   618  			go f.pm.removePeer(p.id)
   619  		}
   620  		if fp.confirmedTd != nil && (maxTd == nil || maxTd.Cmp(fp.confirmedTd) > 0) {
   621  			maxTd = fp.confirmedTd
   622  		}
   623  	}
   624  
   625  	if maxTd != nil {
   626  		f.updateMaxConfirmedTd(maxTd)
   627  	}
   628  }
   629  
   630  // checkAnnouncedHeaders updates peer's block tree if necessary after validating
   631  // a batch of headers. It searches for the latest header in the batch that has a
   632  // matching tree node (if any), and if it has not been marked as known already,
   633  // sets it and its parents to known (even those which are older than the currently
   634  // validated ones). Return value shows if all hashes, numbers and Tds matched
   635  // correctly to the announced values (otherwise the peer should be dropped).
   636  func (f *lightFetcher) checkAnnouncedHeaders(fp *fetcherPeerInfo, headers []*types.Header, tds []*big.Int) bool {
   637  	var (
   638  		n      *fetcherTreeNode
   639  		header *types.Header
   640  		td     *big.Int
   641  	)
   642  
   643  	for i := len(headers) - 1; ; i-- {
   644  		if i < 0 {
   645  			if n == nil {
   646  				// no more headers and nothing to match
   647  				return true
   648  			}
   649  			// we ran out of recently delivered headers but have not reached a node known by this peer yet, continue matching
   650  			hash, number := header.ParentHash, header.Number.Uint64()-1
   651  			td = f.chain.GetTd(hash, number)
   652  			header = f.chain.GetHeader(hash, number)
   653  			if header == nil || td == nil {
   654  				log.Error("Missing parent of validated header", "hash", hash, "number", number)
   655  				return false
   656  			}
   657  		} else {
   658  			header = headers[i]
   659  			td = tds[i]
   660  		}
   661  		hash := header.Hash()
   662  		number := header.Number.Uint64()
   663  		if n == nil {
   664  			n = fp.nodeByHash[hash]
   665  		}
   666  		if n != nil {
   667  			if n.td == nil {
   668  				// node was unannounced
   669  				if nn := fp.nodeByHash[hash]; nn != nil {
   670  					// if there was already a node with the same hash, continue there and drop this one
   671  					nn.children = append(nn.children, n.children...)
   672  					n.children = nil
   673  					fp.deleteNode(n)
   674  					n = nn
   675  				} else {
   676  					n.hash = hash
   677  					n.td = td
   678  					fp.nodeByHash[hash] = n
   679  				}
   680  			}
   681  			// check if it matches the header
   682  			if n.hash != hash || n.number != number || n.td.Cmp(td) != 0 {
   683  				// peer has previously made an invalid announcement
   684  				return false
   685  			}
   686  			if n.known {
   687  				// we reached a known node that matched our expectations, return with success
   688  				return true
   689  			}
   690  			n.known = true
   691  			if fp.confirmedTd == nil || td.Cmp(fp.confirmedTd) > 0 {
   692  				fp.confirmedTd = td
   693  				fp.bestConfirmed = n
   694  			}
   695  			n = n.parent
   696  			if n == nil {
   697  				return true
   698  			}
   699  		}
   700  	}
   701  }
   702  
   703  // checkSyncedHeaders updates peer's block tree after synchronisation by marking
   704  // downloaded headers as known. If none of the announced headers are found after
   705  // syncing, the peer is dropped.
   706  func (f *lightFetcher) checkSyncedHeaders(p *peer) {
   707  	fp := f.peers[p]
   708  	if fp == nil {
   709  		p.Log().Debug("Unknown peer to check sync headers")
   710  		return
   711  	}
   712  
   713  	n := fp.lastAnnounced
   714  	var td *big.Int
   715  
   716  	var h *types.Header
   717  	if f.pm.isULCEnabled() {
   718  		var unapprovedHashes []common.Hash
   719  		// Overwrite last announced for ULC mode
   720  		h, unapprovedHashes = f.lastTrustedTreeNode(p)
   721  		//rollback untrusted blocks
   722  		f.chain.Rollback(unapprovedHashes)
   723  		//overwrite to last trusted
   724  		n = fp.nodeByHash[h.Hash()]
   725  	}
   726  
   727  	//find last valid block
   728  	for n != nil {
   729  		if td = f.chain.GetTd(n.hash, n.number); td != nil {
   730  			break
   731  		}
   732  		n = n.parent
   733  	}
   734  
   735  	// Now n is the latest downloaded/approved header after syncing
   736  	if n == nil {
   737  		p.Log().Debug("Synchronisation failed")
   738  		go f.pm.removePeer(p.id)
   739  		return
   740  	}
   741  	header := f.chain.GetHeader(n.hash, n.number)
   742  	f.newHeaders([]*types.Header{header}, []*big.Int{td})
   743  }
   744  
   745  // lastTrustedTreeNode return last approved treeNode and a list of unapproved hashes
   746  func (f *lightFetcher) lastTrustedTreeNode(p *peer) (*types.Header, []common.Hash) {
   747  	unapprovedHashes := make([]common.Hash, 0)
   748  	current := f.chain.CurrentHeader()
   749  
   750  	if f.lastTrustedHeader == nil {
   751  		return current, unapprovedHashes
   752  	}
   753  
   754  	canonical := f.chain.CurrentHeader()
   755  	if canonical.Number.Uint64() > f.lastTrustedHeader.Number.Uint64() {
   756  		canonical = f.chain.GetHeaderByNumber(f.lastTrustedHeader.Number.Uint64())
   757  	}
   758  	commonAncestor := rawdb.FindCommonAncestor(f.pm.chainDb, canonical, f.lastTrustedHeader)
   759  	if commonAncestor == nil {
   760  		log.Error("Common ancestor of last trusted header and canonical header is nil", "canonical hash", canonical.Hash(), "trusted hash", f.lastTrustedHeader.Hash())
   761  		return current, unapprovedHashes
   762  	}
   763  
   764  	for current.Hash() == commonAncestor.Hash() {
   765  		if f.isTrustedHash(current.Hash()) {
   766  			break
   767  		}
   768  		unapprovedHashes = append(unapprovedHashes, current.Hash())
   769  		current = f.chain.GetHeader(current.ParentHash, current.Number.Uint64()-1)
   770  	}
   771  	return current, unapprovedHashes
   772  }
   773  
   774  func (f *lightFetcher) setLastTrustedHeader(h *types.Header) {
   775  	f.lock.Lock()
   776  	defer f.lock.Unlock()
   777  	f.lastTrustedHeader = h
   778  }
   779  
   780  // checkKnownNode checks if a block tree node is known (downloaded and validated)
   781  // If it was not known previously but found in the database, sets its known flag
   782  func (f *lightFetcher) checkKnownNode(p *peer, n *fetcherTreeNode) bool {
   783  	if n.known {
   784  		return true
   785  	}
   786  	td := f.chain.GetTd(n.hash, n.number)
   787  	if td == nil {
   788  		return false
   789  	}
   790  	header := f.chain.GetHeader(n.hash, n.number)
   791  	// check the availability of both header and td because reads are not protected by chain db mutex
   792  	// Note: returning false is always safe here
   793  	if header == nil {
   794  		return false
   795  	}
   796  
   797  	fp := f.peers[p]
   798  	if fp == nil {
   799  		p.Log().Debug("Unknown peer to check known nodes")
   800  		return false
   801  	}
   802  	if !f.checkAnnouncedHeaders(fp, []*types.Header{header}, []*big.Int{td}) {
   803  		p.Log().Debug("Inconsistent announcement")
   804  		go f.pm.removePeer(p.id)
   805  	}
   806  	if fp.confirmedTd != nil {
   807  		f.updateMaxConfirmedTd(fp.confirmedTd)
   808  	}
   809  	return n.known
   810  }
   811  
   812  // deleteNode deletes a node and its child subtrees from a peer's block tree
   813  func (fp *fetcherPeerInfo) deleteNode(n *fetcherTreeNode) {
   814  	if n.parent != nil {
   815  		for i, nn := range n.parent.children {
   816  			if nn == n {
   817  				n.parent.children = append(n.parent.children[:i], n.parent.children[i+1:]...)
   818  				break
   819  			}
   820  		}
   821  	}
   822  	for {
   823  		if n.td != nil {
   824  			delete(fp.nodeByHash, n.hash)
   825  		}
   826  		fp.nodeCnt--
   827  		if len(n.children) == 0 {
   828  			return
   829  		}
   830  		for i, nn := range n.children {
   831  			if i == 0 {
   832  				n = nn
   833  			} else {
   834  				fp.deleteNode(nn)
   835  			}
   836  		}
   837  	}
   838  }
   839  
   840  // updateStatsEntry items form a linked list that is expanded with a new item every time a new head with a higher Td
   841  // than the previous one has been downloaded and validated. The list contains a series of maximum confirmed Td values
   842  // and the time these values have been confirmed, both increasing monotonically. A maximum confirmed Td is calculated
   843  // both globally for all peers and also for each individual peer (meaning that the given peer has announced the head
   844  // and it has also been downloaded from any peer, either before or after the given announcement).
   845  // The linked list has a global tail where new confirmed Td entries are added and a separate head for each peer,
   846  // pointing to the next Td entry that is higher than the peer's max confirmed Td (nil if it has already confirmed
   847  // the current global head).
   848  type updateStatsEntry struct {
   849  	time mclock.AbsTime
   850  	td   *big.Int
   851  	next *updateStatsEntry
   852  }
   853  
   854  // updateMaxConfirmedTd updates the block delay statistics of active peers. Whenever a new highest Td is confirmed,
   855  // adds it to the end of a linked list together with the time it has been confirmed. Then checks which peers have
   856  // already confirmed a head with the same or higher Td (which counts as zero block delay) and updates their statistics.
   857  // Those who have not confirmed such a head by now will be updated by a subsequent checkUpdateStats call with a
   858  // positive block delay value.
   859  func (f *lightFetcher) updateMaxConfirmedTd(td *big.Int) {
   860  	if f.maxConfirmedTd == nil || td.Cmp(f.maxConfirmedTd) > 0 {
   861  		f.maxConfirmedTd = td
   862  		newEntry := &updateStatsEntry{
   863  			time: mclock.Now(),
   864  			td:   td,
   865  		}
   866  		if f.lastUpdateStats != nil {
   867  			f.lastUpdateStats.next = newEntry
   868  		}
   869  
   870  		f.lastUpdateStats = newEntry
   871  		for p := range f.peers {
   872  			f.checkUpdateStats(p, newEntry)
   873  		}
   874  	}
   875  }
   876  
   877  // checkUpdateStats checks those peers who have not confirmed a certain highest Td (or a larger one) by the time it
   878  // has been confirmed by another peer. If they have confirmed such a head by now, their stats are updated with the
   879  // block delay which is (this peer's confirmation time)-(first confirmation time). After blockDelayTimeout has passed,
   880  // the stats are updated with blockDelayTimeout value. In either case, the confirmed or timed out updateStatsEntry
   881  // items are removed from the head of the linked list.
   882  // If a new entry has been added to the global tail, it is passed as a parameter here even though this function
   883  // assumes that it has already been added, so that if the peer's list is empty (all heads confirmed, head is nil),
   884  // it can set the new head to newEntry.
   885  func (f *lightFetcher) checkUpdateStats(p *peer, newEntry *updateStatsEntry) {
   886  	now := mclock.Now()
   887  	fp := f.peers[p]
   888  	if fp == nil {
   889  		p.Log().Debug("Unknown peer to check update stats")
   890  		return
   891  	}
   892  
   893  	if newEntry != nil && fp.firstUpdateStats == nil {
   894  		fp.firstUpdateStats = newEntry
   895  	}
   896  	for fp.firstUpdateStats != nil && fp.firstUpdateStats.time <= now-mclock.AbsTime(blockDelayTimeout) {
   897  		f.pm.serverPool.adjustBlockDelay(p.poolEntry, blockDelayTimeout)
   898  		fp.firstUpdateStats = fp.firstUpdateStats.next
   899  	}
   900  	if fp.confirmedTd != nil {
   901  		for fp.firstUpdateStats != nil && fp.firstUpdateStats.td.Cmp(fp.confirmedTd) <= 0 {
   902  			f.pm.serverPool.adjustBlockDelay(p.poolEntry, time.Duration(now-fp.firstUpdateStats.time))
   903  			fp.firstUpdateStats = fp.firstUpdateStats.next
   904  		}
   905  	}
   906  }