github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/eth/fetcher/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:37</date>
    10  //</624450088550273024>
    11  
    12  
    13  //包获取器包含基于块通知的同步。
    14  package fetcher
    15  
    16  import (
    17  	"errors"
    18  	"math/rand"
    19  	"time"
    20  
    21  	"github.com/ethereum/go-ethereum/common"
    22  	"github.com/ethereum/go-ethereum/common/prque"
    23  	"github.com/ethereum/go-ethereum/consensus"
    24  	"github.com/ethereum/go-ethereum/core/types"
    25  	"github.com/ethereum/go-ethereum/log"
    26  )
    27  
    28  const (
    29  arriveTimeout = 500 * time.Millisecond //明确请求公告块之前的时间裕度
    30  gatherSlack   = 100 * time.Millisecond //用于整理带有回迁的几乎过期的公告的间隔
    31  fetchTimeout  = 5 * time.Second        //返回显式请求块的最长分配时间
    32  maxUncleDist  = 7                      //距链头的最大允许后退距离
    33  maxQueueDist  = 32                     //链头到队列的最大允许距离
    34  hashLimit     = 256                    //对等机可能已宣布的唯一块的最大数目
    35  blockLimit    = 64                     //对等端传递的唯一块的最大数目
    36  )
    37  
    38  var (
    39  	errTerminated = errors.New("terminated")
    40  )
    41  
    42  //blockretrievalfn是用于从本地链检索块的回调类型。
    43  type blockRetrievalFn func(common.Hash) *types.Block
    44  
    45  //HeaderRequesterFn是用于发送头检索请求的回调类型。
    46  type headerRequesterFn func(common.Hash) error
    47  
    48  //BodyRequesterFn是用于发送正文检索请求的回调类型。
    49  type bodyRequesterFn func([]common.Hash) error
    50  
    51  //headerverifierfn是一种回调类型,用于验证块头的快速传播。
    52  type headerVerifierFn func(header *types.Header) error
    53  
    54  //BlockBroadcasterFn是一种回调类型,用于向连接的对等端广播块。
    55  type blockBroadcasterFn func(block *types.Block, propagate bool)
    56  
    57  //chainheightfn是用于检索当前链高度的回调类型。
    58  type chainHeightFn func() uint64
    59  
    60  //chaininsertfn是一种回调类型,用于将一批块插入本地链。
    61  type chainInsertFn func(types.Blocks) (int, error)
    62  
    63  //peerDropFn是一种回调类型,用于删除被检测为恶意的对等机。
    64  type peerDropFn func(id string)
    65  
    66  //Announce是哈希通知,通知中新块的可用性
    67  //网络。
    68  type announce struct {
    69  hash   common.Hash   //正在公布的块的哈希值
    70  number uint64        //正在公布的块的数目(0=未知旧协议)
    71  header *types.Header //部分重新组装的块头(新协议)
    72  time   time.Time     //公告的时间戳
    73  
    74  origin string //发出通知的对等方的标识符
    75  
    76  fetchHeader headerRequesterFn //获取函数以检索已公告块的头
    77  fetchBodies bodyRequesterFn   //获取函数以检索已公告块的主体
    78  }
    79  
    80  //HeaderFilterTask表示需要获取器筛选的一批头。
    81  type headerFilterTask struct {
    82  peer    string          //块头的源对等
    83  headers []*types.Header //要筛选的标题集合
    84  time    time.Time       //收割台到达时间
    85  }
    86  
    87  //BodyFilterTask表示一批块体(事务和叔叔)
    88  //需要回迁过滤。
    89  type bodyFilterTask struct {
    90  peer         string                 //阻塞体的源对等体
    91  transactions [][]*types.Transaction //Collection of transactions per block bodies
    92  uncles       [][]*types.Header      //每个区块主体的叔叔集合
    93  time         time.Time              //块内容物到达时间
    94  }
    95  
    96  //Inject表示计划导入操作。
    97  type inject struct {
    98  	origin string
    99  	block  *types.Block
   100  }
   101  
   102  //Fetcher负责从不同的对等方收集块通知
   103  //并安排它们进行检索。
   104  type Fetcher struct {
   105  //各种事件通道
   106  	notify chan *announce
   107  	inject chan *inject
   108  
   109  	blockFilter  chan chan []*types.Block
   110  	headerFilter chan chan *headerFilterTask
   111  	bodyFilter   chan chan *bodyFilterTask
   112  
   113  	done chan common.Hash
   114  	quit chan struct{}
   115  
   116  //宣布国
   117  announces  map[string]int              //每对等端宣布计数以防止内存耗尽
   118  announced  map[common.Hash][]*announce //已通知块,计划获取
   119  fetching   map[common.Hash]*announce   //Announced blocks, currently fetching
   120  fetched    map[common.Hash][]*announce //已提取头的块,计划用于正文检索
   121  completing map[common.Hash]*announce   //带有标题的块,当前主体正在完成
   122  
   123  //块缓存
   124  queue  *prque.Prque            //包含导入操作的队列(已排序块号)
   125  queues map[string]int          //每对等块计数以防止内存耗尽
   126  queued map[common.Hash]*inject //已排队的块集(用于消除导入的重复数据)
   127  
   128  //回调
   129  getBlock       blockRetrievalFn   //从本地链中检索块
   130  verifyHeader   headerVerifierFn   //检查块的头是否具有有效的工作证明
   131  broadcastBlock blockBroadcasterFn //向连接的对等端广播块
   132  chainHeight    chainHeightFn      //检索当前链的高度
   133  insertChain    chainInsertFn      //向链中注入一批块
   134  dropPeer       peerDropFn         //因行为不端而丢掉一个同伴
   135  
   136  //测试钩
   137  announceChangeHook func(common.Hash, bool) //方法在从公告列表中添加或删除哈希时调用
   138  queueChangeHook    func(common.Hash, bool) //从导入队列添加或删除块时要调用的方法
   139  fetchingHook       func([]common.Hash)     //启动块(eth/61)或头(eth/62)提取时调用的方法
   140  completingHook     func([]common.Hash)     //启动块体提取时调用的方法(eth/62)
   141  importedHook       func(*types.Block)      //成功块导入时调用的方法(ETH/61和ETH/62)
   142  }
   143  
   144  //新建创建一个块获取器,以基于哈希通知检索块。
   145  func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertChain chainInsertFn, dropPeer peerDropFn) *Fetcher {
   146  	return &Fetcher{
   147  		notify:         make(chan *announce),
   148  		inject:         make(chan *inject),
   149  		blockFilter:    make(chan chan []*types.Block),
   150  		headerFilter:   make(chan chan *headerFilterTask),
   151  		bodyFilter:     make(chan chan *bodyFilterTask),
   152  		done:           make(chan common.Hash),
   153  		quit:           make(chan struct{}),
   154  		announces:      make(map[string]int),
   155  		announced:      make(map[common.Hash][]*announce),
   156  		fetching:       make(map[common.Hash]*announce),
   157  		fetched:        make(map[common.Hash][]*announce),
   158  		completing:     make(map[common.Hash]*announce),
   159  		queue:          prque.New(nil),
   160  		queues:         make(map[string]int),
   161  		queued:         make(map[common.Hash]*inject),
   162  		getBlock:       getBlock,
   163  		verifyHeader:   verifyHeader,
   164  		broadcastBlock: broadcastBlock,
   165  		chainHeight:    chainHeight,
   166  		insertChain:    insertChain,
   167  		dropPeer:       dropPeer,
   168  	}
   169  }
   170  
   171  //启动基于公告的同步器,接受和处理
   172  //哈希通知和块提取,直到请求终止。
   173  func (f *Fetcher) Start() {
   174  	go f.loop()
   175  }
   176  
   177  //停止终止基于公告的同步器,取消所有挂起
   178  //操作。
   179  func (f *Fetcher) Stop() {
   180  	close(f.quit)
   181  }
   182  
   183  //通知将通知获取程序新块的潜在可用性
   184  //网络。
   185  func (f *Fetcher) Notify(peer string, hash common.Hash, number uint64, time time.Time,
   186  	headerFetcher headerRequesterFn, bodyFetcher bodyRequesterFn) error {
   187  	block := &announce{
   188  		hash:        hash,
   189  		number:      number,
   190  		time:        time,
   191  		origin:      peer,
   192  		fetchHeader: headerFetcher,
   193  		fetchBodies: bodyFetcher,
   194  	}
   195  	select {
   196  	case f.notify <- block:
   197  		return nil
   198  	case <-f.quit:
   199  		return errTerminated
   200  	}
   201  }
   202  
   203  //入队试图填补取款人未来导入队列的空白。
   204  func (f *Fetcher) Enqueue(peer string, block *types.Block) error {
   205  	op := &inject{
   206  		origin: peer,
   207  		block:  block,
   208  	}
   209  	select {
   210  	case f.inject <- op:
   211  		return nil
   212  	case <-f.quit:
   213  		return errTerminated
   214  	}
   215  }
   216  
   217  //filterheaders提取提取提取程序显式请求的所有头,
   218  //退回那些应该以不同方式处理的。
   219  func (f *Fetcher) FilterHeaders(peer string, headers []*types.Header, time time.Time) []*types.Header {
   220  	log.Trace("Filtering headers", "peer", peer, "headers", len(headers))
   221  
   222  //将过滤通道发送到获取器
   223  	filter := make(chan *headerFilterTask)
   224  
   225  	select {
   226  	case f.headerFilter <- filter:
   227  	case <-f.quit:
   228  		return nil
   229  	}
   230  //请求筛选头列表
   231  	select {
   232  	case filter <- &headerFilterTask{peer: peer, headers: headers, time: time}:
   233  	case <-f.quit:
   234  		return nil
   235  	}
   236  //检索筛选后剩余的邮件头
   237  	select {
   238  	case task := <-filter:
   239  		return task.headers
   240  	case <-f.quit:
   241  		return nil
   242  	}
   243  }
   244  
   245  //filterbody提取由
   246  //回迁者,返回那些应该以不同方式处理的。
   247  func (f *Fetcher) FilterBodies(peer string, transactions [][]*types.Transaction, uncles [][]*types.Header, time time.Time) ([][]*types.Transaction, [][]*types.Header) {
   248  	log.Trace("Filtering bodies", "peer", peer, "txs", len(transactions), "uncles", len(uncles))
   249  
   250  //将过滤通道发送到获取器
   251  	filter := make(chan *bodyFilterTask)
   252  
   253  	select {
   254  	case f.bodyFilter <- filter:
   255  	case <-f.quit:
   256  		return nil, nil
   257  	}
   258  //请求对身体清单的过滤
   259  	select {
   260  	case filter <- &bodyFilterTask{peer: peer, transactions: transactions, uncles: uncles, time: time}:
   261  	case <-f.quit:
   262  		return nil, nil
   263  	}
   264  //检索过滤后剩余的主体
   265  	select {
   266  	case task := <-filter:
   267  		return task.transactions, task.uncles
   268  	case <-f.quit:
   269  		return nil, nil
   270  	}
   271  }
   272  
   273  //循环是主获取循环,检查和处理各种通知
   274  //事件。
   275  func (f *Fetcher) loop() {
   276  //迭代块提取,直到请求退出
   277  	fetchTimer := time.NewTimer(0)
   278  	completeTimer := time.NewTimer(0)
   279  
   280  	for {
   281  //清除所有过期的块提取
   282  		for hash, announce := range f.fetching {
   283  			if time.Since(announce.time) > fetchTimeout {
   284  				f.forgetHash(hash)
   285  			}
   286  		}
   287  //Import any queued blocks that could potentially fit
   288  		height := f.chainHeight()
   289  		for !f.queue.Empty() {
   290  			op := f.queue.PopItem().(*inject)
   291  			hash := op.block.Hash()
   292  			if f.queueChangeHook != nil {
   293  				f.queueChangeHook(hash, false)
   294  			}
   295  //如果链条或相位过高,请稍后继续
   296  			number := op.block.NumberU64()
   297  			if number > height+1 {
   298  				f.queue.Push(op, -int64(number))
   299  				if f.queueChangeHook != nil {
   300  					f.queueChangeHook(hash, true)
   301  				}
   302  				break
   303  			}
   304  //否则,如果是新鲜的,还是未知的,请尝试导入
   305  			if number+maxUncleDist < height || f.getBlock(hash) != nil {
   306  				f.forgetBlock(hash)
   307  				continue
   308  			}
   309  			f.insert(op.origin, op.block)
   310  		}
   311  //等待外部事件发生
   312  		select {
   313  		case <-f.quit:
   314  //取数器终止,中止所有操作
   315  			return
   316  
   317  		case notification := <-f.notify:
   318  //宣布封锁,确保同伴没有给我们注射药物。
   319  			propAnnounceInMeter.Mark(1)
   320  
   321  			count := f.announces[notification.origin] + 1
   322  			if count > hashLimit {
   323  				log.Debug("Peer exceeded outstanding announces", "peer", notification.origin, "limit", hashLimit)
   324  				propAnnounceDOSMeter.Mark(1)
   325  				break
   326  			}
   327  //如果我们有一个有效的块号,检查它是否有潜在的用处
   328  			if notification.number > 0 {
   329  				if dist := int64(notification.number) - int64(f.chainHeight()); dist < -maxUncleDist || dist > maxQueueDist {
   330  					log.Debug("Peer discarded announcement", "peer", notification.origin, "number", notification.number, "hash", notification.hash, "distance", dist)
   331  					propAnnounceDropMeter.Mark(1)
   332  					break
   333  				}
   334  			}
   335  //一切都很好,如果块尚未下载,请安排公告
   336  			if _, ok := f.fetching[notification.hash]; ok {
   337  				break
   338  			}
   339  			if _, ok := f.completing[notification.hash]; ok {
   340  				break
   341  			}
   342  			f.announces[notification.origin] = count
   343  			f.announced[notification.hash] = append(f.announced[notification.hash], notification)
   344  			if f.announceChangeHook != nil && len(f.announced[notification.hash]) == 1 {
   345  				f.announceChangeHook(notification.hash, true)
   346  			}
   347  			if len(f.announced) == 1 {
   348  				f.rescheduleFetch(fetchTimer)
   349  			}
   350  
   351  		case op := <-f.inject:
   352  //已请求直接插入块,请尝试填充所有挂起的空白。
   353  			propBroadcastInMeter.Mark(1)
   354  			f.enqueue(op.origin, op.block)
   355  
   356  		case hash := <-f.done:
   357  //挂起的导入已完成,请删除通知的所有跟踪
   358  			f.forgetHash(hash)
   359  			f.forgetBlock(hash)
   360  
   361  		case <-fetchTimer.C:
   362  //At least one block's timer ran out, check for needing retrieval
   363  			request := make(map[string][]common.Hash)
   364  
   365  			for hash, announces := range f.announced {
   366  				if time.Since(announces[0].time) > arriveTimeout-gatherSlack {
   367  //选择要检索的随机对等机,重置所有其他对等机
   368  					announce := announces[rand.Intn(len(announces))]
   369  					f.forgetHash(hash)
   370  
   371  //如果块仍未到达,请排队取件
   372  					if f.getBlock(hash) == nil {
   373  						request[announce.origin] = append(request[announce.origin], hash)
   374  						f.fetching[hash] = announce
   375  					}
   376  				}
   377  			}
   378  //Send out all block header requests
   379  			for peer, hashes := range request {
   380  				log.Trace("Fetching scheduled headers", "peer", peer, "list", hashes)
   381  
   382  //在新线程上创建fetch和schedule的闭包
   383  				fetchHeader, hashes := f.fetching[hashes[0]].fetchHeader, hashes
   384  				go func() {
   385  					if f.fetchingHook != nil {
   386  						f.fetchingHook(hashes)
   387  					}
   388  					for _, hash := range hashes {
   389  						headerFetchMeter.Mark(1)
   390  fetchHeader(hash) //次优,但协议不允许批头检索
   391  					}
   392  				}()
   393  			}
   394  //如果块仍处于挂起状态,则计划下一次提取
   395  			f.rescheduleFetch(fetchTimer)
   396  
   397  		case <-completeTimer.C:
   398  //至少有一个头的计时器用完了,检索所有内容
   399  			request := make(map[string][]common.Hash)
   400  
   401  			for hash, announces := range f.fetched {
   402  //选择要检索的随机对等机,重置所有其他对等机
   403  				announce := announces[rand.Intn(len(announces))]
   404  				f.forgetHash(hash)
   405  
   406  //如果块仍未到达,请排队等待完成
   407  				if f.getBlock(hash) == nil {
   408  					request[announce.origin] = append(request[announce.origin], hash)
   409  					f.completing[hash] = announce
   410  				}
   411  			}
   412  //发送所有块体请求
   413  			for peer, hashes := range request {
   414  				log.Trace("Fetching scheduled bodies", "peer", peer, "list", hashes)
   415  
   416  //在新线程上创建fetch和schedule的闭包
   417  				if f.completingHook != nil {
   418  					f.completingHook(hashes)
   419  				}
   420  				bodyFetchMeter.Mark(int64(len(hashes)))
   421  				go f.completing[hashes[0]].fetchBodies(hashes)
   422  			}
   423  //如果块仍处于挂起状态,则计划下一次提取
   424  			f.rescheduleComplete(completeTimer)
   425  
   426  		case filter := <-f.headerFilter:
   427  //Headers arrived from a remote peer. Extract those that were explicitly
   428  //由提取者请求,并返回所有其他内容,以便交付
   429  //系统的其他部分。
   430  			var task *headerFilterTask
   431  			select {
   432  			case task = <-filter:
   433  			case <-f.quit:
   434  				return
   435  			}
   436  			headerFilterInMeter.Mark(int64(len(task.headers)))
   437  
   438  //将一批报头拆分为未知的报文(返回给呼叫者),
   439  //已知的不完整块(需要检索主体)和完整块。
   440  			unknown, incomplete, complete := []*types.Header{}, []*announce{}, []*types.Block{}
   441  			for _, header := range task.headers {
   442  				hash := header.Hash()
   443  
   444  //过滤器从其他同步算法中获取请求的头
   445  				if announce := f.fetching[hash]; announce != nil && announce.origin == task.peer && f.fetched[hash] == nil && f.completing[hash] == nil && f.queued[hash] == nil {
   446  //如果交付的报头与承诺的号码不匹配,请删除播音员
   447  					if header.Number.Uint64() != announce.number {
   448  						log.Trace("Invalid block number fetched", "peer", announce.origin, "hash", header.Hash(), "announced", announce.number, "provided", header.Number)
   449  						f.dropPeer(announce.origin)
   450  						f.forgetHash(hash)
   451  						continue
   452  					}
   453  //仅在不通过其他方式进口时保留
   454  					if f.getBlock(hash) == nil {
   455  						announce.header = header
   456  						announce.time = task.time
   457  
   458  //如果块为空(仅限头段),则对最终导入队列短路
   459  						if header.TxHash == types.DeriveSha(types.Transactions{}) && header.UncleHash == types.CalcUncleHash([]*types.Header{}) {
   460  							log.Trace("Block empty, skipping body retrieval", "peer", announce.origin, "number", header.Number, "hash", header.Hash())
   461  
   462  							block := types.NewBlockWithHeader(header)
   463  							block.ReceivedAt = task.time
   464  
   465  							complete = append(complete, block)
   466  							f.completing[hash] = announce
   467  							continue
   468  						}
   469  //否则添加到需要完成的块列表中
   470  						incomplete = append(incomplete, announce)
   471  					} else {
   472  						log.Trace("Block already imported, discarding header", "peer", announce.origin, "number", header.Number, "hash", header.Hash())
   473  						f.forgetHash(hash)
   474  					}
   475  				} else {
   476  //Fetcher不知道这一点,添加到返回列表
   477  					unknown = append(unknown, header)
   478  				}
   479  			}
   480  			headerFilterOutMeter.Mark(int64(len(unknown)))
   481  			select {
   482  			case filter <- &headerFilterTask{headers: unknown, time: task.time}:
   483  			case <-f.quit:
   484  				return
   485  			}
   486  //安排检索到的邮件头的正文完成时间
   487  			for _, announce := range incomplete {
   488  				hash := announce.header.Hash()
   489  				if _, ok := f.completing[hash]; ok {
   490  					continue
   491  				}
   492  				f.fetched[hash] = append(f.fetched[hash], announce)
   493  				if len(f.fetched) == 1 {
   494  					f.rescheduleComplete(completeTimer)
   495  				}
   496  			}
   497  //为导入计划仅标题块
   498  			for _, block := range complete {
   499  				if announce := f.completing[block.Hash()]; announce != nil {
   500  					f.enqueue(announce.origin, block)
   501  				}
   502  			}
   503  
   504  		case filter := <-f.bodyFilter:
   505  //块体到达,提取任何显式请求的块,返回其余的
   506  			var task *bodyFilterTask
   507  			select {
   508  			case task = <-filter:
   509  			case <-f.quit:
   510  				return
   511  			}
   512  			bodyFilterInMeter.Mark(int64(len(task.transactions)))
   513  
   514  			blocks := []*types.Block{}
   515  			for i := 0; i < len(task.transactions) && i < len(task.uncles); i++ {
   516  //将主体与任何可能的完成请求匹配
   517  				matched := false
   518  
   519  				for hash, announce := range f.completing {
   520  					if f.queued[hash] == nil {
   521  						txnHash := types.DeriveSha(types.Transactions(task.transactions[i]))
   522  						uncleHash := types.CalcUncleHash(task.uncles[i])
   523  
   524  						if txnHash == announce.header.TxHash && uncleHash == announce.header.UncleHash && announce.origin == task.peer {
   525  //标记匹配的车身,如果仍然未知,则重新装配
   526  							matched = true
   527  
   528  							if f.getBlock(hash) == nil {
   529  								block := types.NewBlockWithHeader(announce.header).WithBody(task.transactions[i], task.uncles[i])
   530  								block.ReceivedAt = task.time
   531  
   532  								blocks = append(blocks, block)
   533  							} else {
   534  								f.forgetHash(hash)
   535  							}
   536  						}
   537  					}
   538  				}
   539  				if matched {
   540  					task.transactions = append(task.transactions[:i], task.transactions[i+1:]...)
   541  					task.uncles = append(task.uncles[:i], task.uncles[i+1:]...)
   542  					i--
   543  					continue
   544  				}
   545  			}
   546  
   547  			bodyFilterOutMeter.Mark(int64(len(task.transactions)))
   548  			select {
   549  			case filter <- task:
   550  			case <-f.quit:
   551  				return
   552  			}
   553  //为有序导入计划检索的块
   554  			for _, block := range blocks {
   555  				if announce := f.completing[block.Hash()]; announce != nil {
   556  					f.enqueue(announce.origin, block)
   557  				}
   558  			}
   559  		}
   560  	}
   561  }
   562  
   563  //RescheduleFetch将指定的Fetch计时器重置为下一个公告超时。
   564  func (f *Fetcher) rescheduleFetch(fetch *time.Timer) {
   565  //如果没有公告块,则短路
   566  	if len(f.announced) == 0 {
   567  		return
   568  	}
   569  //否则查找最早的过期通知
   570  	earliest := time.Now()
   571  	for _, announces := range f.announced {
   572  		if earliest.After(announces[0].time) {
   573  			earliest = announces[0].time
   574  		}
   575  	}
   576  	fetch.Reset(arriveTimeout - time.Since(earliest))
   577  }
   578  
   579  //重新安排完成将指定的完成计时器重置为下一个提取超时。
   580  func (f *Fetcher) rescheduleComplete(complete *time.Timer) {
   581  //如果未提取收割台,则短路
   582  	if len(f.fetched) == 0 {
   583  		return
   584  	}
   585  //否则查找最早的过期通知
   586  	earliest := time.Now()
   587  	for _, announces := range f.fetched {
   588  		if earliest.After(announces[0].time) {
   589  			earliest = announces[0].time
   590  		}
   591  	}
   592  	complete.Reset(gatherSlack - time.Since(earliest))
   593  }
   594  
   595  //如果要导入的块
   596  //还没有看到。
   597  func (f *Fetcher) enqueue(peer string, block *types.Block) {
   598  	hash := block.Hash()
   599  
   600  //确保同伴没有给我们剂量
   601  	count := f.queues[peer] + 1
   602  	if count > blockLimit {
   603  		log.Debug("Discarded propagated block, exceeded allowance", "peer", peer, "number", block.Number(), "hash", hash, "limit", blockLimit)
   604  		propBroadcastDOSMeter.Mark(1)
   605  		f.forgetHash(hash)
   606  		return
   607  	}
   608  //丢弃任何过去或太远的块
   609  	if dist := int64(block.NumberU64()) - int64(f.chainHeight()); dist < -maxUncleDist || dist > maxQueueDist {
   610  		log.Debug("Discarded propagated block, too far away", "peer", peer, "number", block.Number(), "hash", hash, "distance", dist)
   611  		propBroadcastDropMeter.Mark(1)
   612  		f.forgetHash(hash)
   613  		return
   614  	}
   615  //为以后的导入计划块
   616  	if _, ok := f.queued[hash]; !ok {
   617  		op := &inject{
   618  			origin: peer,
   619  			block:  block,
   620  		}
   621  		f.queues[peer] = count
   622  		f.queued[hash] = op
   623  		f.queue.Push(op, -int64(block.NumberU64()))
   624  		if f.queueChangeHook != nil {
   625  			f.queueChangeHook(op.block.Hash(), true)
   626  		}
   627  		log.Debug("Queued propagated block", "peer", peer, "number", block.Number(), "hash", hash, "queued", f.queue.Size())
   628  	}
   629  }
   630  
   631  //insert生成新的goroutine以在链中执行块插入。如果
   632  //块的编号与当前导入阶段的高度相同,它将更新
   633  //相应地,相位状态。
   634  func (f *Fetcher) insert(peer string, block *types.Block) {
   635  	hash := block.Hash()
   636  
   637  //在新线程上运行导入
   638  	log.Debug("Importing propagated block", "peer", peer, "number", block.Number(), "hash", hash)
   639  	go func() {
   640  		defer func() { f.done <- hash }()
   641  
   642  //如果父级未知,则中止插入
   643  		parent := f.getBlock(block.ParentHash())
   644  		if parent == nil {
   645  			log.Debug("Unknown parent of propagated block", "peer", peer, "number", block.Number(), "hash", hash, "parent", block.ParentHash())
   646  			return
   647  		}
   648  //快速验证头并在块通过时传播该块
   649  		switch err := f.verifyHeader(block.Header()); err {
   650  		case nil:
   651  //一切正常,迅速传播给我们的同行
   652  			propBroadcastOutTimer.UpdateSince(block.ReceivedAt)
   653  			go f.broadcastBlock(block, true)
   654  
   655  		case consensus.ErrFutureBlock:
   656  //奇怪的未来块,不要失败,但都不会传播
   657  
   658  		default:
   659  //Something went very wrong, drop the peer
   660  			log.Debug("Propagated block verification failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err)
   661  			f.dropPeer(peer)
   662  			return
   663  		}
   664  //运行实际导入并记录所有问题
   665  		if _, err := f.insertChain(types.Blocks{block}); err != nil {
   666  			log.Debug("Propagated block import failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err)
   667  			return
   668  		}
   669  //如果导入成功,则广播块
   670  		propAnnounceOutTimer.UpdateSince(block.ReceivedAt)
   671  		go f.broadcastBlock(block, false)
   672  
   673  //如果需要,调用测试挂钩
   674  		if f.importedHook != nil {
   675  			f.importedHook(block)
   676  		}
   677  	}()
   678  }
   679  
   680  //遗忘哈希从提取程序中删除块通知的所有跟踪
   681  //内部状态。
   682  func (f *Fetcher) forgetHash(hash common.Hash) {
   683  //删除所有挂起的公告和递减DOS计数器
   684  	for _, announce := range f.announced[hash] {
   685  		f.announces[announce.origin]--
   686  		if f.announces[announce.origin] == 0 {
   687  			delete(f.announces, announce.origin)
   688  		}
   689  	}
   690  	delete(f.announced, hash)
   691  	if f.announceChangeHook != nil {
   692  		f.announceChangeHook(hash, false)
   693  	}
   694  //删除所有挂起的提取并减少DOS计数器
   695  	if announce := f.fetching[hash]; announce != nil {
   696  		f.announces[announce.origin]--
   697  		if f.announces[announce.origin] == 0 {
   698  			delete(f.announces, announce.origin)
   699  		}
   700  		delete(f.fetching, hash)
   701  	}
   702  
   703  //删除所有挂起的完成请求并减少DOS计数器
   704  	for _, announce := range f.fetched[hash] {
   705  		f.announces[announce.origin]--
   706  		if f.announces[announce.origin] == 0 {
   707  			delete(f.announces, announce.origin)
   708  		}
   709  	}
   710  	delete(f.fetched, hash)
   711  
   712  //删除所有挂起的完成并减少DOS计数器
   713  	if announce := f.completing[hash]; announce != nil {
   714  		f.announces[announce.origin]--
   715  		if f.announces[announce.origin] == 0 {
   716  			delete(f.announces, announce.origin)
   717  		}
   718  		delete(f.completing, hash)
   719  	}
   720  }
   721  
   722  //CISTION块从取回器的内部移除队列块的所有踪迹。
   723  //状态。
   724  func (f *Fetcher) forgetBlock(hash common.Hash) {
   725  	if insert := f.queued[hash]; insert != nil {
   726  		f.queues[insert.origin]--
   727  		if f.queues[insert.origin] == 0 {
   728  			delete(f.queues, insert.origin)
   729  		}
   730  		delete(f.queued, hash)
   731  	}
   732  }
   733