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