github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/les/fetcher.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:38</date>
    10  //</624450093579243520>
    11  
    12  
    13  //包les实现轻以太坊子协议。
    14  package les
    15  
    16  import (
    17  	"math/big"
    18  	"sync"
    19  	"time"
    20  
    21  	"github.com/ethereum/go-ethereum/common"
    22  	"github.com/ethereum/go-ethereum/common/mclock"
    23  	"github.com/ethereum/go-ethereum/consensus"
    24  	"github.com/ethereum/go-ethereum/core/rawdb"
    25  	"github.com/ethereum/go-ethereum/core/types"
    26  	"github.com/ethereum/go-ethereum/light"
    27  	"github.com/ethereum/go-ethereum/log"
    28  )
    29  
    30  const (
    31  blockDelayTimeout    = time.Second * 10 //对等机宣布已被其他人确认的头的超时
    32  maxNodeCount         = 20               //为每个对等机记住的最大fetchertreenode条目数
    33  serverStateAvailable = 100              //假定状态可用性的最近块数
    34  )
    35  
    36  //LightFetcher实现对新公布的头的检索。它还为
    37  //ODR系统确保我们只向已经处理过的对等方请求与某个块相关的数据
    38  //并宣布封锁。
    39  type lightFetcher struct {
    40  	pm    *ProtocolManager
    41  	odr   *LesOdr
    42  	chain *light.LightChain
    43  
    44  lock            sync.Mutex //锁保护对提取程序内部状态变量(发送的请求除外)的访问
    45  	maxConfirmedTd  *big.Int
    46  	peers           map[*peer]*fetcherPeerInfo
    47  	lastUpdateStats *updateStatsEntry
    48  	syncing         bool
    49  	syncDone        chan *peer
    50  
    51  reqMu      sync.RWMutex //reqmu保护对发送的头提取请求的访问
    52  	requested  map[uint64]fetchRequest
    53  	deliverChn chan fetchResponse
    54  	timeoutChn chan uint64
    55  requestChn chan bool //如果从外部启动,则为真
    56  }
    57  
    58  //FETCHEPERIVENT保存关于每个活动对等点的特定的信息
    59  type fetcherPeerInfo struct {
    60  	root, lastAnnounced *fetcherTreeNode
    61  	nodeCnt             int
    62  	confirmedTd         *big.Int
    63  	bestConfirmed       *fetcherTreeNode
    64  	nodeByHash          map[common.Hash]*fetcherTreeNode
    65  	firstUpdateStats    *updateStatsEntry
    66  }
    67  
    68  //fetchergreenode是树的一个节点,最近保存了关于块的信息。
    69  //announced and confirmed by a certain peer. Each new announce message from a peer
    70  //将节点添加到树中,基于先前公布的头部和重新排列深度。
    71  //树节点有三种可能的状态:
    72  //-已宣布:尚未下载(已知),但我们知道它的头、编号和td
    73  //-中间:不知道,散列和td为空,当已知时填写。
    74  //-已知:由该对等方宣布并下载(从任何对等方)。
    75  //这种结构可以始终知道哪个对等机具有某个块,
    76  //这对于为ODR请求以及
    77  //将新的头封为圣徒。它也有助于始终下载所需的最少数量
    78  //具有单个请求的头的数量。
    79  type fetcherTreeNode struct {
    80  	hash             common.Hash
    81  	number           uint64
    82  	td               *big.Int
    83  	known, requested bool
    84  	parent           *fetcherTreeNode
    85  	children         []*fetcherTreeNode
    86  }
    87  
    88  //fetchRequest表示头下载请求
    89  type fetchRequest struct {
    90  	hash    common.Hash
    91  	amount  uint64
    92  	peer    *peer
    93  	sent    mclock.AbsTime
    94  	timeout bool
    95  }
    96  
    97  //fetchResponse表示头下载响应
    98  type fetchResponse struct {
    99  	reqID   uint64
   100  	headers []*types.Header
   101  	peer    *peer
   102  }
   103  
   104  //new light fetcher创建新的light fetcher
   105  func newLightFetcher(pm *ProtocolManager) *lightFetcher {
   106  	f := &lightFetcher{
   107  		pm:             pm,
   108  		chain:          pm.blockchain.(*light.LightChain),
   109  		odr:            pm.odr,
   110  		peers:          make(map[*peer]*fetcherPeerInfo),
   111  		deliverChn:     make(chan fetchResponse, 100),
   112  		requested:      make(map[uint64]fetchRequest),
   113  		timeoutChn:     make(chan uint64),
   114  		requestChn:     make(chan bool, 100),
   115  		syncDone:       make(chan *peer),
   116  		maxConfirmedTd: big.NewInt(0),
   117  	}
   118  	pm.peers.notify(f)
   119  
   120  	f.pm.wg.Add(1)
   121  	go f.syncLoop()
   122  	return f
   123  }
   124  
   125  //同步循环是取光器的主事件循环
   126  func (f *lightFetcher) syncLoop() {
   127  	requesting := false
   128  	defer f.pm.wg.Done()
   129  	for {
   130  		select {
   131  		case <-f.pm.quitSync:
   132  			return
   133  //当接收到新的公告时,请求循环将一直运行,直到
   134  //无需或可能进一步请求
   135  		case newAnnounce := <-f.requestChn:
   136  			f.lock.Lock()
   137  			s := requesting
   138  			requesting = false
   139  			var (
   140  				rq      *distReq
   141  				reqID   uint64
   142  				syncing bool
   143  			)
   144  			if !f.syncing && !(newAnnounce && s) {
   145  				rq, reqID, syncing = f.nextRequest()
   146  			}
   147  			f.lock.Unlock()
   148  
   149  			if rq != nil {
   150  				requesting = true
   151  				if _, ok := <-f.pm.reqDist.queue(rq); ok {
   152  					if syncing {
   153  						f.lock.Lock()
   154  						f.syncing = true
   155  						f.lock.Unlock()
   156  					} else {
   157  						go func() {
   158  							time.Sleep(softRequestTimeout)
   159  							f.reqMu.Lock()
   160  							req, ok := f.requested[reqID]
   161  							if ok {
   162  								req.timeout = true
   163  								f.requested[reqID] = req
   164  							}
   165  							f.reqMu.Unlock()
   166  //尽可能继续启动新请求
   167  							f.requestChn <- false
   168  						}()
   169  					}
   170  				} else {
   171  					f.requestChn <- false
   172  				}
   173  			}
   174  		case reqID := <-f.timeoutChn:
   175  			f.reqMu.Lock()
   176  			req, ok := f.requested[reqID]
   177  			if ok {
   178  				delete(f.requested, reqID)
   179  			}
   180  			f.reqMu.Unlock()
   181  			if ok {
   182  				f.pm.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), true)
   183  				req.peer.Log().Debug("Fetching data timed out hard")
   184  				go f.pm.removePeer(req.peer.id)
   185  			}
   186  		case resp := <-f.deliverChn:
   187  			f.reqMu.Lock()
   188  			req, ok := f.requested[resp.reqID]
   189  			if ok && req.peer != resp.peer {
   190  				ok = false
   191  			}
   192  			if ok {
   193  				delete(f.requested, resp.reqID)
   194  			}
   195  			f.reqMu.Unlock()
   196  			if ok {
   197  				f.pm.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), req.timeout)
   198  			}
   199  			f.lock.Lock()
   200  			if !ok || !(f.syncing || f.processResponse(req, resp)) {
   201  				resp.peer.Log().Debug("Failed processing response")
   202  				go f.pm.removePeer(resp.peer.id)
   203  			}
   204  			f.lock.Unlock()
   205  		case p := <-f.syncDone:
   206  			f.lock.Lock()
   207  			p.Log().Debug("Done synchronising with peer")
   208  			f.checkSyncedHeaders(p)
   209  			f.syncing = false
   210  			f.lock.Unlock()
   211  			f.requestChn <- false
   212  		}
   213  	}
   214  }
   215  
   216  //registerpeer将新的对等添加到提取程序的对等集
   217  func (f *lightFetcher) registerPeer(p *peer) {
   218  	p.lock.Lock()
   219  	p.hasBlock = func(hash common.Hash, number uint64, hasState bool) bool {
   220  		return f.peerHasBlock(p, hash, number, hasState)
   221  	}
   222  	p.lock.Unlock()
   223  
   224  	f.lock.Lock()
   225  	defer f.lock.Unlock()
   226  
   227  	f.peers[p] = &fetcherPeerInfo{nodeByHash: make(map[common.Hash]*fetcherTreeNode)}
   228  }
   229  
   230  //UnregisterPeer从提取程序的对等集中删除一个新对等。
   231  func (f *lightFetcher) unregisterPeer(p *peer) {
   232  	p.lock.Lock()
   233  	p.hasBlock = nil
   234  	p.lock.Unlock()
   235  
   236  	f.lock.Lock()
   237  	defer f.lock.Unlock()
   238  
   239  //检查潜在的超时块延迟统计信息
   240  	f.checkUpdateStats(p, nil)
   241  	delete(f.peers, p)
   242  }
   243  
   244  //公告处理从对等端接收的新公告消息,添加新的
   245  //节点到对等机的块树,并在必要时删除旧节点
   246  func (f *lightFetcher) announce(p *peer, head *announceData) {
   247  	f.lock.Lock()
   248  	defer f.lock.Unlock()
   249  	p.Log().Debug("Received new announcement", "number", head.Number, "hash", head.Hash, "reorg", head.ReorgDepth)
   250  
   251  	fp := f.peers[p]
   252  	if fp == nil {
   253  		p.Log().Debug("Announcement from unknown peer")
   254  		return
   255  	}
   256  
   257  	if fp.lastAnnounced != nil && head.Td.Cmp(fp.lastAnnounced.td) <= 0 {
   258  //公布的技术数据应该严格单调
   259  		p.Log().Debug("Received non-monotonic td", "current", head.Td, "previous", fp.lastAnnounced.td)
   260  		go f.pm.removePeer(p.id)
   261  		return
   262  	}
   263  
   264  	n := fp.lastAnnounced
   265  	for i := uint64(0); i < head.ReorgDepth; i++ {
   266  		if n == nil {
   267  			break
   268  		}
   269  		n = n.parent
   270  	}
   271  //n现在是reorg的共同祖先,添加一个新的节点分支
   272  	if n != nil && (head.Number >= n.number+maxNodeCount || head.Number <= n.number) {
   273  //如果公布的头块高度低于或等于N或太远无法添加
   274  //中间节点然后放弃先前的通知信息并触发重新同步
   275  		n = nil
   276  		fp.nodeCnt = 0
   277  		fp.nodeByHash = make(map[common.Hash]*fetcherTreeNode)
   278  	}
   279  	if n != nil {
   280  //检查节点计数是否太高,无法添加新节点,必要时丢弃最旧的节点
   281  		locked := false
   282  		for uint64(fp.nodeCnt)+head.Number-n.number > maxNodeCount && fp.root != nil {
   283  			if !locked {
   284  				f.chain.LockChain()
   285  				defer f.chain.UnlockChain()
   286  				locked = true
   287  			}
   288  //如果根的一个子级是规范的,请保留它,删除其他分支和根本身。
   289  			var newRoot *fetcherTreeNode
   290  			for i, nn := range fp.root.children {
   291  				if rawdb.ReadCanonicalHash(f.pm.chainDb, nn.number) == nn.hash {
   292  					fp.root.children = append(fp.root.children[:i], fp.root.children[i+1:]...)
   293  					nn.parent = nil
   294  					newRoot = nn
   295  					break
   296  				}
   297  			}
   298  			fp.deleteNode(fp.root)
   299  			if n == fp.root {
   300  				n = newRoot
   301  			}
   302  			fp.root = newRoot
   303  			if newRoot == nil || !f.checkKnownNode(p, newRoot) {
   304  				fp.bestConfirmed = nil
   305  				fp.confirmedTd = nil
   306  			}
   307  
   308  			if n == nil {
   309  				break
   310  			}
   311  		}
   312  		if n != nil {
   313  			for n.number < head.Number {
   314  				nn := &fetcherTreeNode{number: n.number + 1, parent: n}
   315  				n.children = append(n.children, nn)
   316  				n = nn
   317  				fp.nodeCnt++
   318  			}
   319  			n.hash = head.Hash
   320  			n.td = head.Td
   321  			fp.nodeByHash[n.hash] = n
   322  		}
   323  	}
   324  	if n == nil {
   325  //找不到REORG公共祖先或必须删除整个树,需要新的根目录和重新同步
   326  		if fp.root != nil {
   327  			fp.deleteNode(fp.root)
   328  		}
   329  		n = &fetcherTreeNode{hash: head.Hash, number: head.Number, td: head.Td}
   330  		fp.root = n
   331  		fp.nodeCnt++
   332  		fp.nodeByHash[n.hash] = n
   333  		fp.bestConfirmed = nil
   334  		fp.confirmedTd = nil
   335  	}
   336  
   337  	f.checkKnownNode(p, n)
   338  	p.lock.Lock()
   339  	p.headInfo = head
   340  	fp.lastAnnounced = n
   341  	p.lock.Unlock()
   342  	f.checkUpdateStats(p, nil)
   343  	f.requestChn <- true
   344  }
   345  
   346  //如果我们可以假设对等方知道给定的块,那么peerhassblock返回true。
   347  //根据它的公告
   348  func (f *lightFetcher) peerHasBlock(p *peer, hash common.Hash, number uint64, hasState bool) bool {
   349  	f.lock.Lock()
   350  	defer f.lock.Unlock()
   351  
   352  	fp := f.peers[p]
   353  	if fp == nil || fp.root == nil {
   354  		return false
   355  	}
   356  
   357  	if hasState {
   358  		if fp.lastAnnounced == nil || fp.lastAnnounced.number > number+serverStateAvailable {
   359  			return false
   360  		}
   361  	}
   362  
   363  	if f.syncing {
   364  //同步时始终返回true
   365  //误报是可以接受的,一个更复杂的条件可以稍后实现。
   366  		return true
   367  	}
   368  
   369  	if number >= fp.root.number {
   370  //如果知道它,它应该在对等机的块树中,这已经足够新了。
   371  		return fp.nodeByHash[hash] != nil
   372  	}
   373  	f.chain.LockChain()
   374  	defer f.chain.UnlockChain()
   375  //如果它比对等的块树根还老,但它在同一个规范链中
   376  //作为根,我们仍然可以确定同伴知道它。
   377  //
   378  //同步时,只要检查它是否是已知链的一部分,就没有比我们更好的了
   379  //可以,因为我们还不知道最新的块哈希
   380  	return rawdb.ReadCanonicalHash(f.pm.chainDb, fp.root.number) == fp.root.hash && rawdb.ReadCanonicalHash(f.pm.chainDb, number) == hash
   381  }
   382  
   383  //RequestAmount从开始计算要下载的头的数量
   384  //从某个头向后
   385  func (f *lightFetcher) requestAmount(p *peer, n *fetcherTreeNode) uint64 {
   386  	amount := uint64(0)
   387  	nn := n
   388  	for nn != nil && !f.checkKnownNode(p, nn) {
   389  		nn = nn.parent
   390  		amount++
   391  	}
   392  	if nn == nil {
   393  		amount = n.number
   394  	}
   395  	return amount
   396  }
   397  
   398  //REQUESTEDID指示获取程序是否已请求某个REQID
   399  func (f *lightFetcher) requestedID(reqID uint64) bool {
   400  	f.reqMu.RLock()
   401  	_, ok := f.requested[reqID]
   402  	f.reqMu.RUnlock()
   403  	return ok
   404  }
   405  
   406  //nextrequest选择要请求的对等端和公告头,下一个,amount
   407  //从头部开始向后下载也会返回
   408  func (f *lightFetcher) nextRequest() (*distReq, uint64, bool) {
   409  	var (
   410  		bestHash   common.Hash
   411  		bestAmount uint64
   412  	)
   413  	bestTd := f.maxConfirmedTd
   414  	bestSyncing := false
   415  
   416  	for p, fp := range f.peers {
   417  		for hash, n := range fp.nodeByHash {
   418  			if !f.checkKnownNode(p, n) && !n.requested && (bestTd == nil || n.td.Cmp(bestTd) >= 0) {
   419  				amount := f.requestAmount(p, n)
   420  				if bestTd == nil || n.td.Cmp(bestTd) > 0 || amount < bestAmount {
   421  					bestHash = hash
   422  					bestAmount = amount
   423  					bestTd = n.td
   424  					bestSyncing = fp.bestConfirmed == nil || fp.root == nil || !f.checkKnownNode(p, fp.root)
   425  				}
   426  			}
   427  		}
   428  	}
   429  	if bestTd == f.maxConfirmedTd {
   430  		return nil, 0, false
   431  	}
   432  
   433  	var rq *distReq
   434  	reqID := genReqID()
   435  	if bestSyncing {
   436  		rq = &distReq{
   437  			getCost: func(dp distPeer) uint64 {
   438  				return 0
   439  			},
   440  			canSend: func(dp distPeer) bool {
   441  				p := dp.(*peer)
   442  				f.lock.Lock()
   443  				defer f.lock.Unlock()
   444  
   445  				fp := f.peers[p]
   446  				return fp != nil && fp.nodeByHash[bestHash] != nil
   447  			},
   448  			request: func(dp distPeer) func() {
   449  				go func() {
   450  					p := dp.(*peer)
   451  					p.Log().Debug("Synchronisation started")
   452  					f.pm.synchronise(p)
   453  					f.syncDone <- p
   454  				}()
   455  				return nil
   456  			},
   457  		}
   458  	} else {
   459  		rq = &distReq{
   460  			getCost: func(dp distPeer) uint64 {
   461  				p := dp.(*peer)
   462  				return p.GetRequestCost(GetBlockHeadersMsg, int(bestAmount))
   463  			},
   464  			canSend: func(dp distPeer) bool {
   465  				p := dp.(*peer)
   466  				f.lock.Lock()
   467  				defer f.lock.Unlock()
   468  
   469  				fp := f.peers[p]
   470  				if fp == nil {
   471  					return false
   472  				}
   473  				n := fp.nodeByHash[bestHash]
   474  				return n != nil && !n.requested
   475  			},
   476  			request: func(dp distPeer) func() {
   477  				p := dp.(*peer)
   478  				f.lock.Lock()
   479  				fp := f.peers[p]
   480  				if fp != nil {
   481  					n := fp.nodeByHash[bestHash]
   482  					if n != nil {
   483  						n.requested = true
   484  					}
   485  				}
   486  				f.lock.Unlock()
   487  
   488  				cost := p.GetRequestCost(GetBlockHeadersMsg, int(bestAmount))
   489  				p.fcServer.QueueRequest(reqID, cost)
   490  				f.reqMu.Lock()
   491  				f.requested[reqID] = fetchRequest{hash: bestHash, amount: bestAmount, peer: p, sent: mclock.Now()}
   492  				f.reqMu.Unlock()
   493  				go func() {
   494  					time.Sleep(hardRequestTimeout)
   495  					f.timeoutChn <- reqID
   496  				}()
   497  				return func() { p.RequestHeadersByHash(reqID, cost, bestHash, int(bestAmount), 0, true) }
   498  			},
   499  		}
   500  	}
   501  	return rq, reqID, bestSyncing
   502  }
   503  
   504  //DeliverHeaders传递要处理的头下载请求响应
   505  func (f *lightFetcher) deliverHeaders(peer *peer, reqID uint64, headers []*types.Header) {
   506  	f.deliverChn <- fetchResponse{reqID: reqID, headers: headers, peer: peer}
   507  }
   508  
   509  //processResponse处理头下载请求响应,如果成功,则返回true
   510  func (f *lightFetcher) processResponse(req fetchRequest, resp fetchResponse) bool {
   511  	if uint64(len(resp.headers)) != req.amount || resp.headers[0].Hash() != req.hash {
   512  		req.peer.Log().Debug("Response content mismatch", "requested", len(resp.headers), "reqfrom", resp.headers[0], "delivered", req.amount, "delfrom", req.hash)
   513  		return false
   514  	}
   515  	headers := make([]*types.Header, req.amount)
   516  	for i, header := range resp.headers {
   517  		headers[int(req.amount)-1-i] = header
   518  	}
   519  	if _, err := f.chain.InsertHeaderChain(headers, 1); err != nil {
   520  		if err == consensus.ErrFutureBlock {
   521  			return true
   522  		}
   523  		log.Debug("Failed to insert header chain", "err", err)
   524  		return false
   525  	}
   526  	tds := make([]*big.Int, len(headers))
   527  	for i, header := range headers {
   528  		td := f.chain.GetTd(header.Hash(), header.Number.Uint64())
   529  		if td == nil {
   530  			log.Debug("Total difficulty not found for header", "index", i+1, "number", header.Number, "hash", header.Hash())
   531  			return false
   532  		}
   533  		tds[i] = td
   534  	}
   535  	f.newHeaders(headers, tds)
   536  	return true
   537  }
   538  
   539  //newheaders根据
   540  //下载并验证批或头
   541  func (f *lightFetcher) newHeaders(headers []*types.Header, tds []*big.Int) {
   542  	var maxTd *big.Int
   543  	for p, fp := range f.peers {
   544  		if !f.checkAnnouncedHeaders(fp, headers, tds) {
   545  			p.Log().Debug("Inconsistent announcement")
   546  			go f.pm.removePeer(p.id)
   547  		}
   548  		if fp.confirmedTd != nil && (maxTd == nil || maxTd.Cmp(fp.confirmedTd) > 0) {
   549  			maxTd = fp.confirmedTd
   550  		}
   551  	}
   552  	if maxTd != nil {
   553  		f.updateMaxConfirmedTd(maxTd)
   554  	}
   555  }
   556  
   557  //如果验证后需要,checkAnnouncedHeaders会更新对等方的块树
   558  //一批头文件。它搜索具有
   559  //matching tree node (if any), and if it has not been marked as known already,
   560  //将其及其父级设置为已知(甚至那些比当前
   561  //已验证)。返回值显示所有哈希、数字和TDS是否匹配
   562  //正确到公布的值(否则应删除对等机)。
   563  func (f *lightFetcher) checkAnnouncedHeaders(fp *fetcherPeerInfo, headers []*types.Header, tds []*big.Int) bool {
   564  	var (
   565  		n      *fetcherTreeNode
   566  		header *types.Header
   567  		td     *big.Int
   568  	)
   569  
   570  	for i := len(headers) - 1; ; i-- {
   571  		if i < 0 {
   572  			if n == nil {
   573  //没有更多的标题,也没有要匹配的内容
   574  				return true
   575  			}
   576  //最近传递的头已用完,但尚未到达此对等方已知的节点,请继续匹配
   577  			hash, number := header.ParentHash, header.Number.Uint64()-1
   578  			td = f.chain.GetTd(hash, number)
   579  			header = f.chain.GetHeader(hash, number)
   580  			if header == nil || td == nil {
   581  				log.Error("Missing parent of validated header", "hash", hash, "number", number)
   582  				return false
   583  			}
   584  		} else {
   585  			header = headers[i]
   586  			td = tds[i]
   587  		}
   588  		hash := header.Hash()
   589  		number := header.Number.Uint64()
   590  		if n == nil {
   591  			n = fp.nodeByHash[hash]
   592  		}
   593  		if n != nil {
   594  			if n.td == nil {
   595  //节点未通知
   596  				if nn := fp.nodeByHash[hash]; nn != nil {
   597  //如果已经有一个具有相同哈希的节点,请继续执行该操作并删除该节点。
   598  					nn.children = append(nn.children, n.children...)
   599  					n.children = nil
   600  					fp.deleteNode(n)
   601  					n = nn
   602  				} else {
   603  					n.hash = hash
   604  					n.td = td
   605  					fp.nodeByHash[hash] = n
   606  				}
   607  			}
   608  //检查它是否与标题匹配
   609  			if n.hash != hash || n.number != number || n.td.Cmp(td) != 0 {
   610  //对等机以前发出了无效的通知
   611  				return false
   612  			}
   613  			if n.known {
   614  //我们到达了一个与我们的期望相符的已知节点,成功地返回
   615  				return true
   616  			}
   617  			n.known = true
   618  			if fp.confirmedTd == nil || td.Cmp(fp.confirmedTd) > 0 {
   619  				fp.confirmedTd = td
   620  				fp.bestConfirmed = n
   621  			}
   622  			n = n.parent
   623  			if n == nil {
   624  				return true
   625  			}
   626  		}
   627  	}
   628  }
   629  
   630  //checkSyncedHeaders通过标记在同步后更新对等方的块树
   631  //下载了已知的邮件头。如果在
   632  //syncing, the peer is dropped.
   633  func (f *lightFetcher) checkSyncedHeaders(p *peer) {
   634  	fp := f.peers[p]
   635  	if fp == nil {
   636  		p.Log().Debug("Unknown peer to check sync headers")
   637  		return
   638  	}
   639  	n := fp.lastAnnounced
   640  	var td *big.Int
   641  	for n != nil {
   642  		if td = f.chain.GetTd(n.hash, n.number); td != nil {
   643  			break
   644  		}
   645  		n = n.parent
   646  	}
   647  //现在n是同步后最新下载的头文件
   648  	if n == nil {
   649  		p.Log().Debug("Synchronisation failed")
   650  		go f.pm.removePeer(p.id)
   651  	} else {
   652  		header := f.chain.GetHeader(n.hash, n.number)
   653  		f.newHeaders([]*types.Header{header}, []*big.Int{td})
   654  	}
   655  }
   656  
   657  //checkknownnode检查是否已知块树节点(已下载并验证)
   658  //如果以前不知道,但在数据库中找到,则设置其已知标志
   659  func (f *lightFetcher) checkKnownNode(p *peer, n *fetcherTreeNode) bool {
   660  	if n.known {
   661  		return true
   662  	}
   663  	td := f.chain.GetTd(n.hash, n.number)
   664  	if td == nil {
   665  		return false
   666  	}
   667  	header := f.chain.GetHeader(n.hash, n.number)
   668  //检查header和td的可用性,因为chain db mutex不保护读操作
   669  //注意:返回false在这里总是安全的
   670  	if header == nil {
   671  		return false
   672  	}
   673  
   674  	fp := f.peers[p]
   675  	if fp == nil {
   676  		p.Log().Debug("Unknown peer to check known nodes")
   677  		return false
   678  	}
   679  	if !f.checkAnnouncedHeaders(fp, []*types.Header{header}, []*big.Int{td}) {
   680  		p.Log().Debug("Inconsistent announcement")
   681  		go f.pm.removePeer(p.id)
   682  	}
   683  	if fp.confirmedTd != nil {
   684  		f.updateMaxConfirmedTd(fp.confirmedTd)
   685  	}
   686  	return n.known
   687  }
   688  
   689  //删除节点从对等块树中删除节点及其子树
   690  func (fp *fetcherPeerInfo) deleteNode(n *fetcherTreeNode) {
   691  	if n.parent != nil {
   692  		for i, nn := range n.parent.children {
   693  			if nn == n {
   694  				n.parent.children = append(n.parent.children[:i], n.parent.children[i+1:]...)
   695  				break
   696  			}
   697  		}
   698  	}
   699  	for {
   700  		if n.td != nil {
   701  			delete(fp.nodeByHash, n.hash)
   702  		}
   703  		fp.nodeCnt--
   704  		if len(n.children) == 0 {
   705  			return
   706  		}
   707  		for i, nn := range n.children {
   708  			if i == 0 {
   709  				n = nn
   710  			} else {
   711  				fp.deleteNode(nn)
   712  			}
   713  		}
   714  	}
   715  }
   716  
   717  //updateStatentEntry项形成一个链接列表,每次具有更高TD的新头时,都会使用新项展开该列表。
   718  //已下载并验证。该列表包含一系列已确认的最大td值
   719  //这些值被确认的时间,都是单调增加的。计算最大确认td
   720  //无论是全球范围内的所有同行,还是每个单独的同行(也就是说,给定的同行已经宣布了领导
   721  //它也已经从任何一个对等机上下载,无论是在发布之前还是之后)。
   722  //链接列表有一个全局尾部,其中添加了新的已确认TD条目,并为每个对等端分别添加了一个头部,
   723  //pointing to the next Td entry that is higher than the peer's max confirmed Td (nil if it has already confirmed
   724  //目前的全球负责人)。
   725  type updateStatsEntry struct {
   726  	time mclock.AbsTime
   727  	td   *big.Int
   728  	next *updateStatsEntry
   729  }
   730  
   731  //updateMaxConfirmedtd更新活动对等机的块延迟统计信息。一旦确定了新的最高TD,
   732  //将其与确认时间一起添加到链接列表的末尾。然后检查哪些同行
   733  //已经确认了一个具有相同或更高TD(计算为零块延迟)的头,并更新了他们的统计数据。
   734  //现在还没有确认该头的人将通过随后的checkupdatestats调用更新
   735  //positive block delay value.
   736  func (f *lightFetcher) updateMaxConfirmedTd(td *big.Int) {
   737  	if f.maxConfirmedTd == nil || td.Cmp(f.maxConfirmedTd) > 0 {
   738  		f.maxConfirmedTd = td
   739  		newEntry := &updateStatsEntry{
   740  			time: mclock.Now(),
   741  			td:   td,
   742  		}
   743  		if f.lastUpdateStats != nil {
   744  			f.lastUpdateStats.next = newEntry
   745  		}
   746  		f.lastUpdateStats = newEntry
   747  		for p := range f.peers {
   748  			f.checkUpdateStats(p, newEntry)
   749  		}
   750  	}
   751  }
   752  
   753  //CheckUpdateStats检查那些在确认某个最高TD(或更大TD)时还没有确认的同行。
   754  //已被另一个对等方确认。如果他们现在已经确认了这样一个头部,他们的统计数据将更新为
   755  //阻塞延迟,即(此对等方的确认时间)-(第一次确认时间)。BlockDelayTimeout通过后,
   756  //统计信息将用BlockDelayTimeout值更新。在这两种情况下,已确认或超时的更新StatsEntry
   757  //项目将从链接列表的标题中删除。
   758  //如果新条目已添加到全局尾部,则在此处作为参数传递,即使此函数
   759  //假设它已经被添加,这样如果对等方的列表是空的(所有头都已确认,头为零)。
   760  //它可以将新头设置为newentry。
   761  func (f *lightFetcher) checkUpdateStats(p *peer, newEntry *updateStatsEntry) {
   762  	now := mclock.Now()
   763  	fp := f.peers[p]
   764  	if fp == nil {
   765  		p.Log().Debug("Unknown peer to check update stats")
   766  		return
   767  	}
   768  	if newEntry != nil && fp.firstUpdateStats == nil {
   769  		fp.firstUpdateStats = newEntry
   770  	}
   771  	for fp.firstUpdateStats != nil && fp.firstUpdateStats.time <= now-mclock.AbsTime(blockDelayTimeout) {
   772  		f.pm.serverPool.adjustBlockDelay(p.poolEntry, blockDelayTimeout)
   773  		fp.firstUpdateStats = fp.firstUpdateStats.next
   774  	}
   775  	if fp.confirmedTd != nil {
   776  		for fp.firstUpdateStats != nil && fp.firstUpdateStats.td.Cmp(fp.confirmedTd) <= 0 {
   777  			f.pm.serverPool.adjustBlockDelay(p.poolEntry, time.Duration(now-fp.firstUpdateStats.time))
   778  			fp.firstUpdateStats = fp.firstUpdateStats.next
   779  		}
   780  	}
   781  }
   782