github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/eth/downloader/downloader.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2015 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  //软件包下载器包含手动全链同步。
    26  package downloader
    27  
    28  import (
    29  	"errors"
    30  	"fmt"
    31  	"math/big"
    32  	"sync"
    33  	"sync/atomic"
    34  	"time"
    35  
    36  	ethereum "github.com/ethereum/go-ethereum"
    37  	"github.com/ethereum/go-ethereum/common"
    38  	"github.com/ethereum/go-ethereum/core/rawdb"
    39  	"github.com/ethereum/go-ethereum/core/types"
    40  	"github.com/ethereum/go-ethereum/ethdb"
    41  	"github.com/ethereum/go-ethereum/event"
    42  	"github.com/ethereum/go-ethereum/log"
    43  	"github.com/ethereum/go-ethereum/metrics"
    44  	"github.com/ethereum/go-ethereum/params"
    45  )
    46  
    47  var (
    48  MaxHashFetch    = 512 //每个检索请求要获取的哈希数
    49  MaxBlockFetch   = 128 //每个检索请求要获取的块的数量
    50  MaxHeaderFetch  = 192 //每个检索请求要获取的块头的数量
    51  MaxSkeletonSize = 128 //骨架程序集所需的头提取数
    52  MaxBodyFetch    = 128 //每个检索请求要获取的块体数量
    53  MaxReceiptFetch = 256 //允许每个请求提取的事务处理收据的数量
    54  MaxStateFetch   = 384 //允许每个请求提取的节点状态值的数量
    55  
    56  MaxForkAncestry  = 3 * params.EpochDuration //最大链重组
    57  rttMinEstimate   = 2 * time.Second          //下载请求到目标的最短往返时间
    58  rttMaxEstimate   = 20 * time.Second         //下载请求到达目标的最大往返时间
    59  rttMinConfidence = 0.1                      //估计的RTT值的置信系数更差
    60  ttlScaling       = 3                        //RTT->TTL转换的恒定比例因子
    61  ttlLimit         = time.Minute              //防止达到疯狂超时的最大TTL允许值
    62  
    63  qosTuningPeers   = 5    //要基于的对等数(最佳对等数)
    64  qosConfidenceCap = 10   //不修改RTT置信度的对等数
    65  qosTuningImpact  = 0.25 //新的优化目标对上一个值的影响
    66  
    67  maxQueuedHeaders  = 32 * 1024 //[ETH/62]要排队导入的头的最大数目(DOS保护)
    68  maxHeadersProcess = 2048      //一次导入到链中的头下载结果数
    69  maxResultsProcess = 2048      //一次导入到链中的内容下载结果数
    70  
    71  fsHeaderCheckFrequency = 100             //快速同步期间下载邮件头的验证频率
    72  fsHeaderSafetyNet      = 2048            //检测到链冲突时要丢弃的头数
    73  fsHeaderForceVerify    = 24              //要在接受透视之前和之后验证的标题数
    74  fsHeaderContCheck      = 3 * time.Second //状态下载期间检查头继续的时间间隔
    75  fsMinFullBlocks        = 64              //即使在快速同步中也要完全检索的块数
    76  )
    77  
    78  var (
    79  	errBusy                    = errors.New("busy")
    80  	errUnknownPeer             = errors.New("peer is unknown or unhealthy")
    81  	errBadPeer                 = errors.New("action from bad peer ignored")
    82  	errStallingPeer            = errors.New("peer is stalling")
    83  	errNoPeers                 = errors.New("no peers to keep download active")
    84  	errTimeout                 = errors.New("timeout")
    85  	errEmptyHeaderSet          = errors.New("empty header set by peer")
    86  	errPeersUnavailable        = errors.New("no peers available or all tried for download")
    87  	errInvalidAncestor         = errors.New("retrieved ancestor is invalid")
    88  	errInvalidChain            = errors.New("retrieved hash chain is invalid")
    89  	errInvalidBlock            = errors.New("retrieved block is invalid")
    90  	errInvalidBody             = errors.New("retrieved block body is invalid")
    91  	errInvalidReceipt          = errors.New("retrieved receipt is invalid")
    92  	errCancelBlockFetch        = errors.New("block download canceled (requested)")
    93  	errCancelHeaderFetch       = errors.New("block header download canceled (requested)")
    94  	errCancelBodyFetch         = errors.New("block body download canceled (requested)")
    95  	errCancelReceiptFetch      = errors.New("receipt download canceled (requested)")
    96  	errCancelStateFetch        = errors.New("state data download canceled (requested)")
    97  	errCancelHeaderProcessing  = errors.New("header processing canceled (requested)")
    98  	errCancelContentProcessing = errors.New("content processing canceled (requested)")
    99  	errNoSyncActive            = errors.New("no sync active")
   100  	errTooOld                  = errors.New("peer doesn't speak recent enough protocol version (need version >= 62)")
   101  )
   102  
   103  type Downloader struct {
   104  mode SyncMode       //定义所用策略的同步模式(每个同步周期)
   105  mux  *event.TypeMux //事件同步器宣布同步操作事件
   106  
   107  queue   *queue   //用于选择要下载的哈希的计划程序
   108  peers   *peerSet //可从中继续下载的活动对等点集
   109  	stateDB ethdb.Database
   110  
   111  rttEstimate   uint64 //目标下载请求的往返时间
   112  rttConfidence uint64 //估计RTT的置信度(单位:百万分之一允许原子操作)
   113  
   114  //统计
   115  syncStatsChainOrigin uint64 //开始同步的起始块编号
   116  syncStatsChainHeight uint64 //开始同步时已知的最高块号
   117  	syncStatsState       stateSyncStats
   118  syncStatsLock        sync.RWMutex //锁定保护同步状态字段
   119  
   120  	lightchain LightChain
   121  	blockchain BlockChain
   122  
   123  //回调
   124  dropPeer peerDropFn //因行为不端而丢掉一个同伴
   125  
   126  //状态
   127  synchroniseMock func(id string, hash common.Hash) error //测试过程中的同步替换
   128  	synchronising   int32
   129  	notified        int32
   130  	committed       int32
   131  
   132  //渠道
   133  headerCh      chan dataPack        //[ETH/62]接收入站数据块头的通道
   134  bodyCh        chan dataPack        //[ETH/62]接收入站闭塞体的信道
   135  receiptCh     chan dataPack        //[ETH/63]接收入站收据的通道
   136  bodyWakeCh    chan bool            //[ETH/62]向新任务的块体获取器发送信号的通道
   137  receiptWakeCh chan bool            //[ETH/63]向接收新任务的接收者发送信号的通道
   138  headerProcCh  chan []*types.Header //[ETH/62]为头处理器提供新任务的通道
   139  
   140  //用于StateFetcher
   141  	stateSyncStart chan *stateSync
   142  	trackStateReq  chan *stateReq
   143  stateCh        chan dataPack //[ETH/63]接收入站节点状态数据的通道
   144  
   145  //取消和终止
   146  cancelPeer string         //当前用作主机的对等机的标识符(删除时取消)
   147  cancelCh   chan struct{}  //取消飞行中同步的频道
   148  cancelLock sync.RWMutex   //锁定以保护取消通道和对等端传递
   149  cancelWg   sync.WaitGroup //确保所有取出器Goroutine都已退出。
   150  
   151  quitCh   chan struct{} //退出通道至信号终止
   152  quitLock sync.RWMutex  //锁定以防止双重关闭
   153  
   154  //测试钩
   155  syncInitHook     func(uint64, uint64)  //启动新同步运行时调用的方法
   156  bodyFetchHook    func([]*types.Header) //启动块体提取时要调用的方法
   157  receiptFetchHook func([]*types.Header) //开始获取收据时调用的方法
   158  chainInsertHook  func([]*fetchResult)  //在插入块链时调用的方法(可能在多个调用中)
   159  }
   160  
   161  //LightChain封装了同步轻链所需的功能。
   162  type LightChain interface {
   163  //hasheader验证头在本地链中的存在。
   164  	HasHeader(common.Hash, uint64) bool
   165  
   166  //GetHeaderByHash从本地链检索头。
   167  	GetHeaderByHash(common.Hash) *types.Header
   168  
   169  //currentHeader从本地链中检索头标头。
   170  	CurrentHeader() *types.Header
   171  
   172  //gettd返回本地块的总难度。
   173  	GetTd(common.Hash, uint64) *big.Int
   174  
   175  //InsertHeaderChain将一批头插入本地链。
   176  	InsertHeaderChain([]*types.Header, int) (int, error)
   177  
   178  //回滚从本地链中删除一些最近添加的元素。
   179  	Rollback([]common.Hash)
   180  }
   181  
   182  //区块链封装了同步(完整或快速)区块链所需的功能。
   183  type BlockChain interface {
   184  	LightChain
   185  
   186  //hasblock验证块在本地链中的存在。
   187  	HasBlock(common.Hash, uint64) bool
   188  
   189  //GetBlockByHash从本地链中检索块。
   190  	GetBlockByHash(common.Hash) *types.Block
   191  
   192  //currentBlock从本地链检索头块。
   193  	CurrentBlock() *types.Block
   194  
   195  //currentFastBlock从本地链检索头快速块。
   196  	CurrentFastBlock() *types.Block
   197  
   198  //fastsynccommithead直接将头块提交给某个实体。
   199  	FastSyncCommitHead(common.Hash) error
   200  
   201  //插入链将一批块插入到本地链中。
   202  	InsertChain(types.Blocks) (int, error)
   203  
   204  //InsertReceiptChain将一批收据插入本地链。
   205  	InsertReceiptChain(types.Blocks, []types.Receipts) (int, error)
   206  }
   207  
   208  //新建创建一个新的下载程序,从远程对等端获取哈希和块。
   209  func New(mode SyncMode, stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn) *Downloader {
   210  	if lightchain == nil {
   211  		lightchain = chain
   212  	}
   213  
   214  	dl := &Downloader{
   215  		mode:           mode,
   216  		stateDB:        stateDb,
   217  		mux:            mux,
   218  		queue:          newQueue(),
   219  		peers:          newPeerSet(),
   220  		rttEstimate:    uint64(rttMaxEstimate),
   221  		rttConfidence:  uint64(1000000),
   222  		blockchain:     chain,
   223  		lightchain:     lightchain,
   224  		dropPeer:       dropPeer,
   225  		headerCh:       make(chan dataPack, 1),
   226  		bodyCh:         make(chan dataPack, 1),
   227  		receiptCh:      make(chan dataPack, 1),
   228  		bodyWakeCh:     make(chan bool, 1),
   229  		receiptWakeCh:  make(chan bool, 1),
   230  		headerProcCh:   make(chan []*types.Header, 1),
   231  		quitCh:         make(chan struct{}),
   232  		stateCh:        make(chan dataPack),
   233  		stateSyncStart: make(chan *stateSync),
   234  		syncStatsState: stateSyncStats{
   235  			processed: rawdb.ReadFastTrieProgress(stateDb),
   236  		},
   237  		trackStateReq: make(chan *stateReq),
   238  	}
   239  	go dl.qosTuner()
   240  	go dl.stateFetcher()
   241  	return dl
   242  }
   243  
   244  //进程检索同步边界,特别是起源。
   245  //同步开始于的块(可能已失败/暂停);块
   246  //或头同步当前位于;以及同步目标的最新已知块。
   247  //
   248  //此外,在快速同步的状态下载阶段,
   249  //同时返回已处理状态和已知状态总数。否则
   250  //这些都是零。
   251  func (d *Downloader) Progress() ethereum.SyncProgress {
   252  //锁定当前状态并返回进度
   253  	d.syncStatsLock.RLock()
   254  	defer d.syncStatsLock.RUnlock()
   255  
   256  	current := uint64(0)
   257  	switch d.mode {
   258  	case FullSync:
   259  		current = d.blockchain.CurrentBlock().NumberU64()
   260  	case FastSync:
   261  		current = d.blockchain.CurrentFastBlock().NumberU64()
   262  	case LightSync:
   263  		current = d.lightchain.CurrentHeader().Number.Uint64()
   264  	}
   265  	return ethereum.SyncProgress{
   266  		StartingBlock: d.syncStatsChainOrigin,
   267  		CurrentBlock:  current,
   268  		HighestBlock:  d.syncStatsChainHeight,
   269  		PulledStates:  d.syncStatsState.processed,
   270  		KnownStates:   d.syncStatsState.processed + d.syncStatsState.pending,
   271  	}
   272  }
   273  
   274  //同步返回下载程序当前是否正在检索块。
   275  func (d *Downloader) Synchronising() bool {
   276  	return atomic.LoadInt32(&d.synchronising) > 0
   277  }
   278  
   279  //registerpeer将一个新的下载对等注入到要
   280  //用于从获取哈希和块。
   281  func (d *Downloader) RegisterPeer(id string, version int, peer Peer) error {
   282  	logger := log.New("peer", id)
   283  	logger.Trace("Registering sync peer")
   284  	if err := d.peers.Register(newPeerConnection(id, version, peer, logger)); err != nil {
   285  		logger.Error("Failed to register sync peer", "err", err)
   286  		return err
   287  	}
   288  	d.qosReduceConfidence()
   289  
   290  	return nil
   291  }
   292  
   293  //Regiterlightpeer注入一个轻量级客户端对等端,将其包装起来,使其看起来像一个普通对等端。
   294  func (d *Downloader) RegisterLightPeer(id string, version int, peer LightPeer) error {
   295  	return d.RegisterPeer(id, version, &lightPeerWrapper{peer})
   296  }
   297  
   298  //注销对等机从已知列表中删除对等机,以阻止
   299  //指定的对等机。还将努力将任何挂起的回迁返回到
   300  //排队。
   301  func (d *Downloader) UnregisterPeer(id string) error {
   302  //从活动对等机集中注销对等机并撤消任何获取任务
   303  	logger := log.New("peer", id)
   304  	logger.Trace("Unregistering sync peer")
   305  	if err := d.peers.Unregister(id); err != nil {
   306  		logger.Error("Failed to unregister sync peer", "err", err)
   307  		return err
   308  	}
   309  	d.queue.Revoke(id)
   310  
   311  //如果此对等是主对等,则立即中止同步
   312  	d.cancelLock.RLock()
   313  	master := id == d.cancelPeer
   314  	d.cancelLock.RUnlock()
   315  
   316  	if master {
   317  		d.cancel()
   318  	}
   319  	return nil
   320  }
   321  
   322  //Synchronise尝试将本地区块链与远程对等机同步,两者都是
   323  //添加各种健全性检查,并用各种日志条目包装它。
   324  func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode SyncMode) error {
   325  	err := d.synchronise(id, head, td, mode)
   326  	switch err {
   327  	case nil:
   328  	case errBusy:
   329  
   330  	case errTimeout, errBadPeer, errStallingPeer,
   331  		errEmptyHeaderSet, errPeersUnavailable, errTooOld,
   332  		errInvalidAncestor, errInvalidChain:
   333  		log.Warn("Synchronisation failed, dropping peer", "peer", id, "err", err)
   334  		if d.dropPeer == nil {
   335  //当对本地副本使用“--copydb”时,droppeer方法为nil。
   336  //如果压缩在错误的时间命中,则可能发生超时,并且可以忽略。
   337  			log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", id)
   338  		} else {
   339  			d.dropPeer(id)
   340  		}
   341  	default:
   342  		log.Warn("Synchronisation failed, retrying", "err", err)
   343  	}
   344  	return err
   345  }
   346  
   347  //同步将选择对等机并使用它进行同步。如果给出空字符串
   348  //如果它的td比我们自己的高,它将使用尽可能最好的对等机并进行同步。如果有
   349  //检查失败,将返回错误。此方法是同步的
   350  func (d *Downloader) synchronise(id string, hash common.Hash, td *big.Int, mode SyncMode) error {
   351  //模拟同步如果测试
   352  	if d.synchroniseMock != nil {
   353  		return d.synchroniseMock(id, hash)
   354  	}
   355  //确保一次只允许一个Goroutine通过此点
   356  	if !atomic.CompareAndSwapInt32(&d.synchronising, 0, 1) {
   357  		return errBusy
   358  	}
   359  	defer atomic.StoreInt32(&d.synchronising, 0)
   360  
   361  //发布同步的用户通知(每个会话仅一次)
   362  	if atomic.CompareAndSwapInt32(&d.notified, 0, 1) {
   363  		log.Info("Block synchronisation started")
   364  	}
   365  //重置队列、对等设置和唤醒通道以清除任何内部剩余状态
   366  	d.queue.Reset()
   367  	d.peers.Reset()
   368  
   369  	for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} {
   370  		select {
   371  		case <-ch:
   372  		default:
   373  		}
   374  	}
   375  	for _, ch := range []chan dataPack{d.headerCh, d.bodyCh, d.receiptCh} {
   376  		for empty := false; !empty; {
   377  			select {
   378  			case <-ch:
   379  			default:
   380  				empty = true
   381  			}
   382  		}
   383  	}
   384  	for empty := false; !empty; {
   385  		select {
   386  		case <-d.headerProcCh:
   387  		default:
   388  			empty = true
   389  		}
   390  	}
   391  //为中途中止创建取消频道并标记主对等机
   392  	d.cancelLock.Lock()
   393  	d.cancelCh = make(chan struct{})
   394  	d.cancelPeer = id
   395  	d.cancelLock.Unlock()
   396  
   397  defer d.Cancel() //不管怎样,我们不能让取消频道一直开着
   398  
   399  //设置请求的同步模式,除非被禁止
   400  	d.mode = mode
   401  
   402  //检索源对等机并启动下载过程
   403  	p := d.peers.Peer(id)
   404  	if p == nil {
   405  		return errUnknownPeer
   406  	}
   407  	return d.syncWithPeer(p, hash, td)
   408  }
   409  
   410  //SyncWithPeer根据来自
   411  //指定的对等和头哈希。
   412  func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.Int) (err error) {
   413  	d.mux.Post(StartEvent{})
   414  	defer func() {
   415  //错误重置
   416  		if err != nil {
   417  			d.mux.Post(FailedEvent{err})
   418  		} else {
   419  			d.mux.Post(DoneEvent{})
   420  		}
   421  	}()
   422  	if p.version < 62 {
   423  		return errTooOld
   424  	}
   425  
   426  	log.Debug("Synchronising with the network", "peer", p.id, "eth", p.version, "head", hash, "td", td, "mode", d.mode)
   427  	defer func(start time.Time) {
   428  		log.Debug("Synchronisation terminated", "elapsed", time.Since(start))
   429  	}(time.Now())
   430  
   431  //查找同步边界:共同祖先和目标块
   432  	latest, err := d.fetchHeight(p)
   433  	if err != nil {
   434  		return err
   435  	}
   436  	height := latest.Number.Uint64()
   437  
   438  	origin, err := d.findAncestor(p, height)
   439  	if err != nil {
   440  		return err
   441  	}
   442  	d.syncStatsLock.Lock()
   443  	if d.syncStatsChainHeight <= origin || d.syncStatsChainOrigin > origin {
   444  		d.syncStatsChainOrigin = origin
   445  	}
   446  	d.syncStatsChainHeight = height
   447  	d.syncStatsLock.Unlock()
   448  
   449  //确保我们的原点在任何快速同步轴点之下
   450  	pivot := uint64(0)
   451  	if d.mode == FastSync {
   452  		if height <= uint64(fsMinFullBlocks) {
   453  			origin = 0
   454  		} else {
   455  			pivot = height - uint64(fsMinFullBlocks)
   456  			if pivot <= origin {
   457  				origin = pivot - 1
   458  			}
   459  		}
   460  	}
   461  	d.committed = 1
   462  	if d.mode == FastSync && pivot != 0 {
   463  		d.committed = 0
   464  	}
   465  //使用并发头和内容检索算法启动同步
   466  	d.queue.Prepare(origin+1, d.mode)
   467  	if d.syncInitHook != nil {
   468  		d.syncInitHook(origin, height)
   469  	}
   470  
   471  	fetchers := []func() error{
   472  func() error { return d.fetchHeaders(p, origin+1, pivot) }, //始终检索邮件头
   473  func() error { return d.fetchBodies(origin + 1) },          //在正常和快速同步期间检索主体
   474  func() error { return d.fetchReceipts(origin + 1) },        //在快速同步过程中检索收据
   475  		func() error { return d.processHeaders(origin+1, pivot, td) },
   476  	}
   477  	if d.mode == FastSync {
   478  		fetchers = append(fetchers, func() error { return d.processFastSyncContent(latest) })
   479  	} else if d.mode == FullSync {
   480  		fetchers = append(fetchers, d.processFullSyncContent)
   481  	}
   482  	return d.spawnSync(fetchers)
   483  }
   484  
   485  //产卵同步运行d.process和所有给定的提取函数以在中完成
   486  //分离goroutine,返回出现的第一个错误。
   487  func (d *Downloader) spawnSync(fetchers []func() error) error {
   488  	errc := make(chan error, len(fetchers))
   489  	d.cancelWg.Add(len(fetchers))
   490  	for _, fn := range fetchers {
   491  		fn := fn
   492  		go func() { defer d.cancelWg.Done(); errc <- fn() }()
   493  	}
   494  //等待第一个错误,然后终止其他错误。
   495  	var err error
   496  	for i := 0; i < len(fetchers); i++ {
   497  		if i == len(fetchers)-1 {
   498  //当所有提取程序退出时关闭队列。
   499  //这将导致块处理器在
   500  //它已经处理了队列。
   501  			d.queue.Close()
   502  		}
   503  		if err = <-errc; err != nil {
   504  			break
   505  		}
   506  	}
   507  	d.queue.Close()
   508  	d.Cancel()
   509  	return err
   510  }
   511  
   512  //取消中止所有操作并重置队列。但是,取消是
   513  //不要等待正在运行的下载Goroutines完成。这个方法应该是
   514  //从下载程序内部取消下载时使用。
   515  func (d *Downloader) cancel() {
   516  //关闭当前取消频道
   517  	d.cancelLock.Lock()
   518  	if d.cancelCh != nil {
   519  		select {
   520  		case <-d.cancelCh:
   521  //频道已关闭
   522  		default:
   523  			close(d.cancelCh)
   524  		}
   525  	}
   526  	d.cancelLock.Unlock()
   527  }
   528  
   529  //取消中止所有操作,并等待所有下载Goroutines到
   530  //返回前完成。
   531  func (d *Downloader) Cancel() {
   532  	d.cancel()
   533  	d.cancelWg.Wait()
   534  }
   535  
   536  //终止中断下载程序,取消所有挂起的操作。
   537  //调用terminate后,下载程序不能再使用。
   538  func (d *Downloader) Terminate() {
   539  //关闭终端通道(确保允许双重关闭)
   540  	d.quitLock.Lock()
   541  	select {
   542  	case <-d.quitCh:
   543  	default:
   544  		close(d.quitCh)
   545  	}
   546  	d.quitLock.Unlock()
   547  
   548  //取消任何挂起的下载请求
   549  	d.Cancel()
   550  }
   551  
   552  //fetchheight检索远程对等端的头段以帮助估计
   553  //等待同步所需的总时间。
   554  func (d *Downloader) fetchHeight(p *peerConnection) (*types.Header, error) {
   555  	p.log.Debug("Retrieving remote chain height")
   556  
   557  //请求公布的远程头块并等待响应
   558  	head, _ := p.peer.Head()
   559  	go p.peer.RequestHeadersByHash(head, 1, 0, false)
   560  
   561  	ttl := d.requestTTL()
   562  	timeout := time.After(ttl)
   563  	for {
   564  		select {
   565  		case <-d.cancelCh:
   566  			return nil, errCancelBlockFetch
   567  
   568  		case packet := <-d.headerCh:
   569  //丢弃源对等机以外的任何内容
   570  			if packet.PeerId() != p.id {
   571  				log.Debug("Received headers from incorrect peer", "peer", packet.PeerId())
   572  				break
   573  			}
   574  //确保对方给出了有效的信息
   575  			headers := packet.(*headerPack).headers
   576  			if len(headers) != 1 {
   577  				p.log.Debug("Multiple headers for single request", "headers", len(headers))
   578  				return nil, errBadPeer
   579  			}
   580  			head := headers[0]
   581  			p.log.Debug("Remote head header identified", "number", head.Number, "hash", head.Hash())
   582  			return head, nil
   583  
   584  		case <-timeout:
   585  			p.log.Debug("Waiting for head header timed out", "elapsed", ttl)
   586  			return nil, errTimeout
   587  
   588  		case <-d.bodyCh:
   589  		case <-d.receiptCh:
   590  //越界交货,忽略
   591  		}
   592  	}
   593  }
   594  
   595  //findancestor试图定位本地链的共同祖先链接,并且
   596  //远程对等区块链。在一般情况下,当我们的节点处于同步状态时,
   597  //在正确的链条上,检查顶部的N个链环应该已经得到了匹配。
   598  //在罕见的情况下,当我们结束了长期的重组(即没有
   599  //头部链接匹配),我们进行二进制搜索以找到共同的祖先。
   600  func (d *Downloader) findAncestor(p *peerConnection, height uint64) (uint64, error) {
   601  //找出有效的祖先范围以防止重写攻击
   602  	floor, ceil := int64(-1), d.lightchain.CurrentHeader().Number.Uint64()
   603  
   604  	if d.mode == FullSync {
   605  		ceil = d.blockchain.CurrentBlock().NumberU64()
   606  	} else if d.mode == FastSync {
   607  		ceil = d.blockchain.CurrentFastBlock().NumberU64()
   608  	}
   609  	if ceil >= MaxForkAncestry {
   610  		floor = int64(ceil - MaxForkAncestry)
   611  	}
   612  	p.log.Debug("Looking for common ancestor", "local", ceil, "remote", height)
   613  
   614  //请求最上面的块短路二进制祖先查找
   615  	head := ceil
   616  	if head > height {
   617  		head = height
   618  	}
   619  	from := int64(head) - int64(MaxHeaderFetch)
   620  	if from < 0 {
   621  		from = 0
   622  	}
   623  //跨越15个区块,以捕捉坏的头报告
   624  	limit := 2 * MaxHeaderFetch / 16
   625  	count := 1 + int((int64(ceil)-from)/16)
   626  	if count > limit {
   627  		count = limit
   628  	}
   629  	go p.peer.RequestHeadersByNumber(uint64(from), count, 15, false)
   630  
   631  //等待对头提取的远程响应
   632  	number, hash := uint64(0), common.Hash{}
   633  
   634  	ttl := d.requestTTL()
   635  	timeout := time.After(ttl)
   636  
   637  	for finished := false; !finished; {
   638  		select {
   639  		case <-d.cancelCh:
   640  			return 0, errCancelHeaderFetch
   641  
   642  		case packet := <-d.headerCh:
   643  //丢弃源对等机以外的任何内容
   644  			if packet.PeerId() != p.id {
   645  				log.Debug("Received headers from incorrect peer", "peer", packet.PeerId())
   646  				break
   647  			}
   648  //确保对方给出了有效的信息
   649  			headers := packet.(*headerPack).headers
   650  			if len(headers) == 0 {
   651  				p.log.Warn("Empty head header set")
   652  				return 0, errEmptyHeaderSet
   653  			}
   654  //确保对等方的答复符合请求
   655  			for i := 0; i < len(headers); i++ {
   656  				if number := headers[i].Number.Int64(); number != from+int64(i)*16 {
   657  					p.log.Warn("Head headers broke chain ordering", "index", i, "requested", from+int64(i)*16, "received", number)
   658  					return 0, errInvalidChain
   659  				}
   660  			}
   661  //检查是否找到共同祖先
   662  			finished = true
   663  			for i := len(headers) - 1; i >= 0; i-- {
   664  //跳过任何下溢/溢出请求集的头
   665  				if headers[i].Number.Int64() < from || headers[i].Number.Uint64() > ceil {
   666  					continue
   667  				}
   668  //否则检查我们是否已经知道标题
   669  				if (d.mode == FullSync && d.blockchain.HasBlock(headers[i].Hash(), headers[i].Number.Uint64())) || (d.mode != FullSync && d.lightchain.HasHeader(headers[i].Hash(), headers[i].Number.Uint64())) {
   670  					number, hash = headers[i].Number.Uint64(), headers[i].Hash()
   671  
   672  //如果每一个标题都是已知的,甚至是未来的标题,那么同行们就会直接说谎。
   673  					if number > height && i == limit-1 {
   674  						p.log.Warn("Lied about chain head", "reported", height, "found", number)
   675  						return 0, errStallingPeer
   676  					}
   677  					break
   678  				}
   679  			}
   680  
   681  		case <-timeout:
   682  			p.log.Debug("Waiting for head header timed out", "elapsed", ttl)
   683  			return 0, errTimeout
   684  
   685  		case <-d.bodyCh:
   686  		case <-d.receiptCh:
   687  //越界交货,忽略
   688  		}
   689  	}
   690  //如果head fetch已经找到祖先,则返回
   691  	if hash != (common.Hash{}) {
   692  		if int64(number) <= floor {
   693  			p.log.Warn("Ancestor below allowance", "number", number, "hash", hash, "allowance", floor)
   694  			return 0, errInvalidAncestor
   695  		}
   696  		p.log.Debug("Found common ancestor", "number", number, "hash", hash)
   697  		return number, nil
   698  	}
   699  //找不到祖先,我们需要在链上进行二进制搜索
   700  	start, end := uint64(0), head
   701  	if floor > 0 {
   702  		start = uint64(floor)
   703  	}
   704  	for start+1 < end {
   705  //将链间隔拆分为两个,并请求哈希进行交叉检查
   706  		check := (start + end) / 2
   707  
   708  		ttl := d.requestTTL()
   709  		timeout := time.After(ttl)
   710  
   711  		go p.peer.RequestHeadersByNumber(check, 1, 0, false)
   712  
   713  //等待答复到达此请求
   714  		for arrived := false; !arrived; {
   715  			select {
   716  			case <-d.cancelCh:
   717  				return 0, errCancelHeaderFetch
   718  
   719  			case packer := <-d.headerCh:
   720  //丢弃源对等机以外的任何内容
   721  				if packer.PeerId() != p.id {
   722  					log.Debug("Received headers from incorrect peer", "peer", packer.PeerId())
   723  					break
   724  				}
   725  //确保对方给出了有效的信息
   726  				headers := packer.(*headerPack).headers
   727  				if len(headers) != 1 {
   728  					p.log.Debug("Multiple headers for single request", "headers", len(headers))
   729  					return 0, errBadPeer
   730  				}
   731  				arrived = true
   732  
   733  //根据响应修改搜索间隔
   734  				if (d.mode == FullSync && !d.blockchain.HasBlock(headers[0].Hash(), headers[0].Number.Uint64())) || (d.mode != FullSync && !d.lightchain.HasHeader(headers[0].Hash(), headers[0].Number.Uint64())) {
   735  					end = check
   736  					break
   737  				}
   738  header := d.lightchain.GetHeaderByHash(headers[0].Hash()) //独立于同步模式,头文件肯定存在
   739  				if header.Number.Uint64() != check {
   740  					p.log.Debug("Received non requested header", "number", header.Number, "hash", header.Hash(), "request", check)
   741  					return 0, errBadPeer
   742  				}
   743  				start = check
   744  
   745  			case <-timeout:
   746  				p.log.Debug("Waiting for search header timed out", "elapsed", ttl)
   747  				return 0, errTimeout
   748  
   749  			case <-d.bodyCh:
   750  			case <-d.receiptCh:
   751  //越界交货,忽略
   752  			}
   753  		}
   754  	}
   755  //确保有效的祖传和回归
   756  	if int64(start) <= floor {
   757  		p.log.Warn("Ancestor below allowance", "number", start, "hash", hash, "allowance", floor)
   758  		return 0, errInvalidAncestor
   759  	}
   760  	p.log.Debug("Found common ancestor", "number", start, "hash", hash)
   761  	return start, nil
   762  }
   763  
   764  //FetchHeaders始终从数字中同时检索头
   765  //请求,直到不再返回,可能会在途中限制。到
   766  //方便并发,但仍能防止恶意节点发送错误
   767  //headers,我们使用“origin”对等体构造一个header链骨架。
   768  //正在与同步,并使用其他人填写丢失的邮件头。报头
   769  //只有当其他对等点干净地映射到骨架时,才接受它们。如果没有人
   770  //可以填充骨架-甚至不是源节点-它被假定为无效和
   771  //原点被删除。
   772  func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64) error {
   773  	p.log.Debug("Directing header downloads", "origin", from)
   774  	defer p.log.Debug("Header download terminated")
   775  
   776  //创建超时计时器和相关联的头提取程序
   777  skeleton := true            //骨架装配阶段或完成
   778  request := time.Now()       //最后一个骨架获取请求的时间
   779  timeout := time.NewTimer(0) //转储非响应活动对等机的计时器
   780  <-timeout.C                 //超时通道最初应为空
   781  	defer timeout.Stop()
   782  
   783  	var ttl time.Duration
   784  	getHeaders := func(from uint64) {
   785  		request = time.Now()
   786  
   787  		ttl = d.requestTTL()
   788  		timeout.Reset(ttl)
   789  
   790  		if skeleton {
   791  			p.log.Trace("Fetching skeleton headers", "count", MaxHeaderFetch, "from", from)
   792  			go p.peer.RequestHeadersByNumber(from+uint64(MaxHeaderFetch)-1, MaxSkeletonSize, MaxHeaderFetch-1, false)
   793  		} else {
   794  			p.log.Trace("Fetching full headers", "count", MaxHeaderFetch, "from", from)
   795  			go p.peer.RequestHeadersByNumber(from, MaxHeaderFetch, 0, false)
   796  		}
   797  	}
   798  //开始拉动收割台链条骨架,直到全部完成。
   799  	getHeaders(from)
   800  
   801  	for {
   802  		select {
   803  		case <-d.cancelCh:
   804  			return errCancelHeaderFetch
   805  
   806  		case packet := <-d.headerCh:
   807  //确保活动对等端正在向我们提供骨架头
   808  			if packet.PeerId() != p.id {
   809  				log.Debug("Received skeleton from incorrect peer", "peer", packet.PeerId())
   810  				break
   811  			}
   812  			headerReqTimer.UpdateSince(request)
   813  			timeout.Stop()
   814  
   815  //如果骨架已完成,则直接从原点拉出任何剩余的头部标题。
   816  			if packet.Items() == 0 && skeleton {
   817  				skeleton = false
   818  				getHeaders(from)
   819  				continue
   820  			}
   821  //如果没有更多的头是入站的,通知内容提取程序并返回
   822  			if packet.Items() == 0 {
   823  //下载数据透视时不要中止头提取
   824  				if atomic.LoadInt32(&d.committed) == 0 && pivot <= from {
   825  					p.log.Debug("No headers, waiting for pivot commit")
   826  					select {
   827  					case <-time.After(fsHeaderContCheck):
   828  						getHeaders(from)
   829  						continue
   830  					case <-d.cancelCh:
   831  						return errCancelHeaderFetch
   832  					}
   833  				}
   834  //透视完成(或不快速同步)并且没有更多的头,终止进程
   835  				p.log.Debug("No more headers available")
   836  				select {
   837  				case d.headerProcCh <- nil:
   838  					return nil
   839  				case <-d.cancelCh:
   840  					return errCancelHeaderFetch
   841  				}
   842  			}
   843  			headers := packet.(*headerPack).headers
   844  
   845  //如果我们接收到一个框架批处理,那么同时解析内部构件
   846  			if skeleton {
   847  				filled, proced, err := d.fillHeaderSkeleton(from, headers)
   848  				if err != nil {
   849  					p.log.Debug("Skeleton chain invalid", "err", err)
   850  					return errInvalidChain
   851  				}
   852  				headers = filled[proced:]
   853  				from += uint64(proced)
   854  			}
   855  //插入所有新标题并获取下一批
   856  			if len(headers) > 0 {
   857  				p.log.Trace("Scheduling new headers", "count", len(headers), "from", from)
   858  				select {
   859  				case d.headerProcCh <- headers:
   860  				case <-d.cancelCh:
   861  					return errCancelHeaderFetch
   862  				}
   863  				from += uint64(len(headers))
   864  			}
   865  			getHeaders(from)
   866  
   867  		case <-timeout.C:
   868  			if d.dropPeer == nil {
   869  //当对本地副本使用“--copydb”时,droppeer方法为nil。
   870  //如果压缩在错误的时间命中,则可能发生超时,并且可以忽略。
   871  				p.log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", p.id)
   872  				break
   873  			}
   874  //头检索超时,考虑对等机错误并丢弃
   875  			p.log.Debug("Header request timed out", "elapsed", ttl)
   876  			headerTimeoutMeter.Mark(1)
   877  			d.dropPeer(p.id)
   878  
   879  //但是,请优雅地完成同步,而不是转储收集的数据
   880  			for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} {
   881  				select {
   882  				case ch <- false:
   883  				case <-d.cancelCh:
   884  				}
   885  			}
   886  			select {
   887  			case d.headerProcCh <- nil:
   888  			case <-d.cancelCh:
   889  			}
   890  			return errBadPeer
   891  		}
   892  	}
   893  }
   894  
   895  //FillHeaderskeleton同时从所有可用的对等端检索头
   896  //并将它们映射到提供的骨架头链。
   897  //
   898  //从骨架开始的任何部分结果(如果可能)都将被转发
   899  //立即发送到头处理器,以保持管道的其余部分保持平衡
   900  //如果收割台失速。
   901  //
   902  //该方法返回整个填充骨架以及头的数量。
   903  //已转发进行处理。
   904  func (d *Downloader) fillHeaderSkeleton(from uint64, skeleton []*types.Header) ([]*types.Header, int, error) {
   905  	log.Debug("Filling up skeleton", "from", from)
   906  	d.queue.ScheduleSkeleton(from, skeleton)
   907  
   908  	var (
   909  		deliver = func(packet dataPack) (int, error) {
   910  			pack := packet.(*headerPack)
   911  			return d.queue.DeliverHeaders(pack.peerID, pack.headers, d.headerProcCh)
   912  		}
   913  		expire   = func() map[string]int { return d.queue.ExpireHeaders(d.requestTTL()) }
   914  		throttle = func() bool { return false }
   915  		reserve  = func(p *peerConnection, count int) (*fetchRequest, bool, error) {
   916  			return d.queue.ReserveHeaders(p, count), false, nil
   917  		}
   918  		fetch    = func(p *peerConnection, req *fetchRequest) error { return p.FetchHeaders(req.From, MaxHeaderFetch) }
   919  		capacity = func(p *peerConnection) int { return p.HeaderCapacity(d.requestRTT()) }
   920  		setIdle  = func(p *peerConnection, accepted int) { p.SetHeadersIdle(accepted) }
   921  	)
   922  	err := d.fetchParts(errCancelHeaderFetch, d.headerCh, deliver, d.queue.headerContCh, expire,
   923  		d.queue.PendingHeaders, d.queue.InFlightHeaders, throttle, reserve,
   924  		nil, fetch, d.queue.CancelHeaders, capacity, d.peers.HeaderIdlePeers, setIdle, "headers")
   925  
   926  	log.Debug("Skeleton fill terminated", "err", err)
   927  
   928  	filled, proced := d.queue.RetrieveHeaders()
   929  	return filled, proced, err
   930  }
   931  
   932  //fetchbodies迭代下载计划的块体,获取
   933  //可用对等机,为每个对等机保留一大块数据块,等待传递
   934  //并定期检查超时情况。
   935  func (d *Downloader) fetchBodies(from uint64) error {
   936  	log.Debug("Downloading block bodies", "origin", from)
   937  
   938  	var (
   939  		deliver = func(packet dataPack) (int, error) {
   940  			pack := packet.(*bodyPack)
   941  			return d.queue.DeliverBodies(pack.peerID, pack.transactions, pack.uncles)
   942  		}
   943  		expire   = func() map[string]int { return d.queue.ExpireBodies(d.requestTTL()) }
   944  		fetch    = func(p *peerConnection, req *fetchRequest) error { return p.FetchBodies(req) }
   945  		capacity = func(p *peerConnection) int { return p.BlockCapacity(d.requestRTT()) }
   946  		setIdle  = func(p *peerConnection, accepted int) { p.SetBodiesIdle(accepted) }
   947  	)
   948  	err := d.fetchParts(errCancelBodyFetch, d.bodyCh, deliver, d.bodyWakeCh, expire,
   949  		d.queue.PendingBlocks, d.queue.InFlightBlocks, d.queue.ShouldThrottleBlocks, d.queue.ReserveBodies,
   950  		d.bodyFetchHook, fetch, d.queue.CancelBodies, capacity, d.peers.BodyIdlePeers, setIdle, "bodies")
   951  
   952  	log.Debug("Block body download terminated", "err", err)
   953  	return err
   954  }
   955  
   956  //fetchreceipts迭代地下载计划的块接收,获取
   957  //可用的对等方,为每个对等方保留一大块收据,等待传递
   958  //并定期检查超时情况。
   959  func (d *Downloader) fetchReceipts(from uint64) error {
   960  	log.Debug("Downloading transaction receipts", "origin", from)
   961  
   962  	var (
   963  		deliver = func(packet dataPack) (int, error) {
   964  			pack := packet.(*receiptPack)
   965  			return d.queue.DeliverReceipts(pack.peerID, pack.receipts)
   966  		}
   967  		expire   = func() map[string]int { return d.queue.ExpireReceipts(d.requestTTL()) }
   968  		fetch    = func(p *peerConnection, req *fetchRequest) error { return p.FetchReceipts(req) }
   969  		capacity = func(p *peerConnection) int { return p.ReceiptCapacity(d.requestRTT()) }
   970  		setIdle  = func(p *peerConnection, accepted int) { p.SetReceiptsIdle(accepted) }
   971  	)
   972  	err := d.fetchParts(errCancelReceiptFetch, d.receiptCh, deliver, d.receiptWakeCh, expire,
   973  		d.queue.PendingReceipts, d.queue.InFlightReceipts, d.queue.ShouldThrottleReceipts, d.queue.ReserveReceipts,
   974  		d.receiptFetchHook, fetch, d.queue.CancelReceipts, capacity, d.peers.ReceiptIdlePeers, setIdle, "receipts")
   975  
   976  	log.Debug("Transaction receipt download terminated", "err", err)
   977  	return err
   978  }
   979  
   980  //fetchparts迭代地下载计划的块部件,获取任何可用的
   981  //对等机,为每个对等机保留一大块获取请求,等待传递和
   982  //还要定期检查超时情况。
   983  //
   984  //由于所有下载的数据的调度/超时逻辑基本相同
   985  //类型,此方法由每个方法用于数据收集,并使用
   986  //处理它们之间的细微差别的各种回调。
   987  //
   988  //仪器参数:
   989  //-errCancel:取消提取操作时返回的错误类型(主要使日志记录更好)
   990  //-deliverych:从中检索下载数据包的通道(从所有并发对等机合并)
   991  //-deliver:处理回调以将数据包传递到特定于类型的下载队列(通常在“queue”内)
   992  //-wakech:通知通道,用于在新任务可用(或同步完成)时唤醒提取程序。
   993  //-expire:任务回调方法,用于中止耗时太长的请求并返回故障对等端(流量形成)
   994  //-挂起:对仍需要下载的请求数的任务回调(检测完成/不可完成性)
   995  //-机上:正在进行的请求数的任务回调(等待所有活动下载完成)
   996  //-限制:任务回调以检查处理队列是否已满并激活限制(绑定内存使用)
   997  //-reserve:任务回调,将新的下载任务保留给特定的对等方(也表示部分完成)
   998  //-fetchhook:tester回调,通知正在启动的新任务(允许测试调度逻辑)
   999  //-fetch:网络回调,实际向物理远程对等端发送特定下载请求
  1000  //-取消:任务回调,以中止飞行中的下载请求并允许重新安排(如果对等机丢失)
  1001  //-容量:网络回调以检索对等机的估计类型特定带宽容量(流量形成)
  1002  //-idle:网络回调以检索当前(特定类型)可分配任务的空闲对等机
  1003  //-set idle:网络回调,将对等机设置回空闲状态,并更新其估计容量(流量形成)
  1004  //-kind:下载类型的文本标签,显示在日志消息中
  1005  func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliver func(dataPack) (int, error), wakeCh chan bool,
  1006  	expire func() map[string]int, pending func() int, inFlight func() bool, throttle func() bool, reserve func(*peerConnection, int) (*fetchRequest, bool, error),
  1007  	fetchHook func([]*types.Header), fetch func(*peerConnection, *fetchRequest) error, cancel func(*fetchRequest), capacity func(*peerConnection) int,
  1008  	idle func() ([]*peerConnection, int), setIdle func(*peerConnection, int), kind string) error {
  1009  
  1010  //创建一个标记器以检测过期的检索任务
  1011  	ticker := time.NewTicker(100 * time.Millisecond)
  1012  	defer ticker.Stop()
  1013  
  1014  	update := make(chan struct{}, 1)
  1015  
  1016  //准备队列并获取块部件,直到块头获取器完成
  1017  	finished := false
  1018  	for {
  1019  		select {
  1020  		case <-d.cancelCh:
  1021  			return errCancel
  1022  
  1023  		case packet := <-deliveryCh:
  1024  //如果之前同伴被禁止并且未能递送包裹
  1025  //在合理的时间范围内,忽略其消息。
  1026  			if peer := d.peers.Peer(packet.PeerId()); peer != nil {
  1027  //传递接收到的数据块并检查链的有效性
  1028  				accepted, err := deliver(packet)
  1029  				if err == errInvalidChain {
  1030  					return err
  1031  				}
  1032  //除非一个同伴提供了完全不需要的东西(通常
  1033  //由最后通过的超时请求引起),将其设置为
  1034  //空闲的如果传递已过时,则对等端应该已经空闲。
  1035  				if err != errStaleDelivery {
  1036  					setIdle(peer, accepted)
  1037  				}
  1038  //向用户发布日志以查看发生了什么
  1039  				switch {
  1040  				case err == nil && packet.Items() == 0:
  1041  					peer.log.Trace("Requested data not delivered", "type", kind)
  1042  				case err == nil:
  1043  					peer.log.Trace("Delivered new batch of data", "type", kind, "count", packet.Stats())
  1044  				default:
  1045  					peer.log.Trace("Failed to deliver retrieved data", "type", kind, "err", err)
  1046  				}
  1047  			}
  1048  //组装块,尝试更新进度
  1049  			select {
  1050  			case update <- struct{}{}:
  1051  			default:
  1052  			}
  1053  
  1054  		case cont := <-wakeCh:
  1055  //头提取程序发送了一个继续标志,检查是否已完成
  1056  			if !cont {
  1057  				finished = true
  1058  			}
  1059  //邮件头到达,请尝试更新进度
  1060  			select {
  1061  			case update <- struct{}{}:
  1062  			default:
  1063  			}
  1064  
  1065  		case <-ticker.C:
  1066  //健全检查更新进度
  1067  			select {
  1068  			case update <- struct{}{}:
  1069  			default:
  1070  			}
  1071  
  1072  		case <-update:
  1073  //如果我们失去所有同龄人,就会短路
  1074  			if d.peers.Len() == 0 {
  1075  				return errNoPeers
  1076  			}
  1077  //检查获取请求超时并降级负责的对等方
  1078  			for pid, fails := range expire() {
  1079  				if peer := d.peers.Peer(pid); peer != nil {
  1080  //如果许多检索元素过期,我们可能高估了远程对等机,或者
  1081  //我们自己。只重置为最小吞吐量,但不要立即下降。即使是最短的时间
  1082  //在同步方面,我们需要摆脱同龄人。
  1083  //
  1084  //最小阈值为2的原因是下载程序试图估计带宽
  1085  //以及对等端的延迟,这需要稍微推一下度量容量并查看
  1086  //响应时间如何反应,对它总是要求一个以上的最小值(即最小2)。
  1087  					if fails > 2 {
  1088  						peer.log.Trace("Data delivery timed out", "type", kind)
  1089  						setIdle(peer, 0)
  1090  					} else {
  1091  						peer.log.Debug("Stalling delivery, dropping", "type", kind)
  1092  						if d.dropPeer == nil {
  1093  //当对本地副本使用“--copydb”时,droppeer方法为nil。
  1094  //如果压缩在错误的时间命中,则可能发生超时,并且可以忽略。
  1095  							peer.log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", pid)
  1096  						} else {
  1097  							d.dropPeer(pid)
  1098  						}
  1099  					}
  1100  				}
  1101  			}
  1102  //如果没有其他东西可以获取,请等待或终止
  1103  			if pending() == 0 {
  1104  				if !inFlight() && finished {
  1105  					log.Debug("Data fetching completed", "type", kind)
  1106  					return nil
  1107  				}
  1108  				break
  1109  			}
  1110  //向所有空闲对等端发送下载请求,直到被阻止
  1111  			progressed, throttled, running := false, false, inFlight()
  1112  			idles, total := idle()
  1113  
  1114  			for _, peer := range idles {
  1115  //节流启动时短路
  1116  				if throttle() {
  1117  					throttled = true
  1118  					break
  1119  				}
  1120  //如果没有更多可用任务,则短路。
  1121  				if pending() == 0 {
  1122  					break
  1123  				}
  1124  //为对等机保留一大块获取。一个零可以意味着
  1125  //没有更多的头可用,或者对等端已知不可用
  1126  //拥有它们。
  1127  				request, progress, err := reserve(peer, capacity(peer))
  1128  				if err != nil {
  1129  					return err
  1130  				}
  1131  				if progress {
  1132  					progressed = true
  1133  				}
  1134  				if request == nil {
  1135  					continue
  1136  				}
  1137  				if request.From > 0 {
  1138  					peer.log.Trace("Requesting new batch of data", "type", kind, "from", request.From)
  1139  				} else {
  1140  					peer.log.Trace("Requesting new batch of data", "type", kind, "count", len(request.Headers), "from", request.Headers[0].Number)
  1141  				}
  1142  //获取块并确保任何错误都将哈希返回到队列
  1143  				if fetchHook != nil {
  1144  					fetchHook(request.Headers)
  1145  				}
  1146  				if err := fetch(peer, request); err != nil {
  1147  //虽然我们可以尝试修复此错误,但实际上
  1148  //意味着我们已经将一个获取任务双重分配给了一个对等方。如果那是
  1149  //案例,下载器和队列的内部状态是非常错误的,所以
  1150  //更好的硬崩溃和注意错误,而不是默默地累积到
  1151  //更大的问题。
  1152  					panic(fmt.Sprintf("%v: %s fetch assignment failed", peer, kind))
  1153  				}
  1154  				running = true
  1155  			}
  1156  //确保我们有可供提取的对等点。如果所有同龄人都被试过
  1157  //所有的失败都会引发一个错误
  1158  			if !progressed && !throttled && !running && len(idles) == total && pending() > 0 {
  1159  				return errPeersUnavailable
  1160  			}
  1161  		}
  1162  	}
  1163  }
  1164  
  1165  //processHeaders从输入通道获取一批检索到的头,并且
  1166  //继续处理并将它们调度到头链和下载程序中
  1167  //排队直到流结束或发生故障。
  1168  func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) error {
  1169  //保留不确定的头数以回滚
  1170  	rollback := []*types.Header{}
  1171  	defer func() {
  1172  		if len(rollback) > 0 {
  1173  //压平收割台并将其回滚
  1174  			hashes := make([]common.Hash, len(rollback))
  1175  			for i, header := range rollback {
  1176  				hashes[i] = header.Hash()
  1177  			}
  1178  			lastHeader, lastFastBlock, lastBlock := d.lightchain.CurrentHeader().Number, common.Big0, common.Big0
  1179  			if d.mode != LightSync {
  1180  				lastFastBlock = d.blockchain.CurrentFastBlock().Number()
  1181  				lastBlock = d.blockchain.CurrentBlock().Number()
  1182  			}
  1183  			d.lightchain.Rollback(hashes)
  1184  			curFastBlock, curBlock := common.Big0, common.Big0
  1185  			if d.mode != LightSync {
  1186  				curFastBlock = d.blockchain.CurrentFastBlock().Number()
  1187  				curBlock = d.blockchain.CurrentBlock().Number()
  1188  			}
  1189  			log.Warn("Rolled back headers", "count", len(hashes),
  1190  				"header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number),
  1191  				"fast", fmt.Sprintf("%d->%d", lastFastBlock, curFastBlock),
  1192  				"block", fmt.Sprintf("%d->%d", lastBlock, curBlock))
  1193  		}
  1194  	}()
  1195  
  1196  //等待处理成批的邮件头
  1197  	gotHeaders := false
  1198  
  1199  	for {
  1200  		select {
  1201  		case <-d.cancelCh:
  1202  			return errCancelHeaderProcessing
  1203  
  1204  		case headers := <-d.headerProcCh:
  1205  //如果同步,则终止头处理
  1206  			if len(headers) == 0 {
  1207  //通知所有人邮件头已完全处理
  1208  				for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} {
  1209  					select {
  1210  					case ch <- false:
  1211  					case <-d.cancelCh:
  1212  					}
  1213  				}
  1214  //如果没有检索到任何头,则对等端违反了其td承诺,即
  1215  //链条比我们的好。唯一的例外是如果它承诺的块
  1216  //已通过其他方式进口(如fecher):
  1217  //
  1218  //R<remote peer>,L<local node>:都在数据块10上
  1219  //R:我的11号区,然后传播到L
  1220  //L:队列块11用于导入
  1221  //L:注意R的头和TD比我们的要高,开始同步。
  1222  //L:11号块饰面的进口
  1223  //L:Sync开始,在11找到共同祖先
  1224  //L:从11点开始请求新的标题(R的td更高,它必须有一些东西)
  1225  //R:没什么可以给的
  1226  				if d.mode != LightSync {
  1227  					head := d.blockchain.CurrentBlock()
  1228  					if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.NumberU64())) > 0 {
  1229  						return errStallingPeer
  1230  					}
  1231  				}
  1232  //如果同步速度快或很轻,请确保确实交付了承诺的头文件。这是
  1233  //需要检测攻击者输入错误的轴然后诱饵离开的场景
  1234  //传递将标记无效内容的post-pivot块。
  1235  //
  1236  //由于块可能仍然是
  1237  //头下载完成后排队等待处理。但是,只要
  1238  //同行给了我们一些有用的东西,我们已经很高兴/进步了(上面的检查)。
  1239  				if d.mode == FastSync || d.mode == LightSync {
  1240  					head := d.lightchain.CurrentHeader()
  1241  					if td.Cmp(d.lightchain.GetTd(head.Hash(), head.Number.Uint64())) > 0 {
  1242  						return errStallingPeer
  1243  					}
  1244  				}
  1245  //禁用任何回滚并返回
  1246  				rollback = nil
  1247  				return nil
  1248  			}
  1249  //否则,将头块分割成批并处理它们
  1250  			gotHeaders = true
  1251  
  1252  			for len(headers) > 0 {
  1253  //在处理块之间发生故障时终止
  1254  				select {
  1255  				case <-d.cancelCh:
  1256  					return errCancelHeaderProcessing
  1257  				default:
  1258  				}
  1259  //选择要导入的下一个标题块
  1260  				limit := maxHeadersProcess
  1261  				if limit > len(headers) {
  1262  					limit = len(headers)
  1263  				}
  1264  				chunk := headers[:limit]
  1265  
  1266  //如果只同步头,请立即验证块。
  1267  				if d.mode == FastSync || d.mode == LightSync {
  1268  //收集尚未确定的邮件头,将其标记为不确定邮件头
  1269  					unknown := make([]*types.Header, 0, len(headers))
  1270  					for _, header := range chunk {
  1271  						if !d.lightchain.HasHeader(header.Hash(), header.Number.Uint64()) {
  1272  							unknown = append(unknown, header)
  1273  						}
  1274  					}
  1275  //如果我们要导入纯头,请根据它们的最近性进行验证。
  1276  					frequency := fsHeaderCheckFrequency
  1277  					if chunk[len(chunk)-1].Number.Uint64()+uint64(fsHeaderForceVerify) > pivot {
  1278  						frequency = 1
  1279  					}
  1280  					if n, err := d.lightchain.InsertHeaderChain(chunk, frequency); err != nil {
  1281  //如果插入了一些头,请将它们也添加到回滚列表中。
  1282  						if n > 0 {
  1283  							rollback = append(rollback, chunk[:n]...)
  1284  						}
  1285  						log.Debug("Invalid header encountered", "number", chunk[n].Number, "hash", chunk[n].Hash(), "err", err)
  1286  						return errInvalidChain
  1287  					}
  1288  //所有验证通过,存储新发现的不确定头
  1289  					rollback = append(rollback, unknown...)
  1290  					if len(rollback) > fsHeaderSafetyNet {
  1291  						rollback = append(rollback[:0], rollback[len(rollback)-fsHeaderSafetyNet:]...)
  1292  					}
  1293  				}
  1294  //除非我们在做轻链,否则请为相关的内容检索安排标题。
  1295  				if d.mode == FullSync || d.mode == FastSync {
  1296  //如果达到了允许的挂起头的数目,请暂停一点。
  1297  					for d.queue.PendingBlocks() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders {
  1298  						select {
  1299  						case <-d.cancelCh:
  1300  							return errCancelHeaderProcessing
  1301  						case <-time.After(time.Second):
  1302  						}
  1303  					}
  1304  //否则插入标题进行内容检索
  1305  					inserts := d.queue.Schedule(chunk, origin)
  1306  					if len(inserts) != len(chunk) {
  1307  						log.Debug("Stale headers")
  1308  						return errBadPeer
  1309  					}
  1310  				}
  1311  				headers = headers[limit:]
  1312  				origin += uint64(limit)
  1313  			}
  1314  
  1315  //更新我们知道的最高块号,如果找到更高的块号。
  1316  			d.syncStatsLock.Lock()
  1317  			if d.syncStatsChainHeight < origin {
  1318  				d.syncStatsChainHeight = origin - 1
  1319  			}
  1320  			d.syncStatsLock.Unlock()
  1321  
  1322  //向内容下载者发出新任务可用性的信号
  1323  			for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} {
  1324  				select {
  1325  				case ch <- true:
  1326  				default:
  1327  				}
  1328  			}
  1329  		}
  1330  	}
  1331  }
  1332  
  1333  //processfullsyncContent从队列中获取结果并将其导入到链中。
  1334  func (d *Downloader) processFullSyncContent() error {
  1335  	for {
  1336  		results := d.queue.Results(true)
  1337  		if len(results) == 0 {
  1338  			return nil
  1339  		}
  1340  		if d.chainInsertHook != nil {
  1341  			d.chainInsertHook(results)
  1342  		}
  1343  		if err := d.importBlockResults(results); err != nil {
  1344  			return err
  1345  		}
  1346  	}
  1347  }
  1348  
  1349  func (d *Downloader) importBlockResults(results []*fetchResult) error {
  1350  //检查是否有任何提前终止请求
  1351  	if len(results) == 0 {
  1352  		return nil
  1353  	}
  1354  	select {
  1355  	case <-d.quitCh:
  1356  		return errCancelContentProcessing
  1357  	default:
  1358  	}
  1359  //检索要导入的一批结果
  1360  	first, last := results[0].Header, results[len(results)-1].Header
  1361  	log.Debug("Inserting downloaded chain", "items", len(results),
  1362  		"firstnum", first.Number, "firsthash", first.Hash(),
  1363  		"lastnum", last.Number, "lasthash", last.Hash(),
  1364  	)
  1365  	blocks := make([]*types.Block, len(results))
  1366  	for i, result := range results {
  1367  		blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles)
  1368  	}
  1369  	if index, err := d.blockchain.InsertChain(blocks); err != nil {
  1370  		log.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err)
  1371  		return errInvalidChain
  1372  	}
  1373  	return nil
  1374  }
  1375  
  1376  //processFastSyncContent从队列获取结果并将其写入
  1377  //数据库。它还控制枢轴块状态节点的同步。
  1378  func (d *Downloader) processFastSyncContent(latest *types.Header) error {
  1379  //开始同步报告的头块的状态。这应该让我们
  1380  //透视图块的状态。
  1381  	stateSync := d.syncState(latest.Root)
  1382  	defer stateSync.Cancel()
  1383  	go func() {
  1384  		if err := stateSync.Wait(); err != nil && err != errCancelStateFetch {
  1385  d.queue.Close() //唤醒等待结果
  1386  		}
  1387  	}()
  1388  //找出理想的轴块。注意,如果
  1389  //同步需要足够长的时间,链头才能显著移动。
  1390  	pivot := uint64(0)
  1391  	if height := latest.Number.Uint64(); height > uint64(fsMinFullBlocks) {
  1392  		pivot = height - uint64(fsMinFullBlocks)
  1393  	}
  1394  //为了适应移动的轴点,跟踪轴块,然后
  1395  //单独累计下载结果。
  1396  	var (
  1397  oldPivot *fetchResult   //锁定在轴块中,可能最终更改
  1398  oldTail  []*fetchResult //在透视之后下载的内容
  1399  	)
  1400  	for {
  1401  //等待下一批下载的数据可用,如果
  1402  //布洛克变僵了,移动门柱
  1403  results := d.queue.Results(oldPivot == nil) //如果我们不监视数据透视过时,请阻止
  1404  		if len(results) == 0 {
  1405  //如果透视同步完成,则停止
  1406  			if oldPivot == nil {
  1407  				return stateSync.Cancel()
  1408  			}
  1409  //如果同步失败,请停止
  1410  			select {
  1411  			case <-d.cancelCh:
  1412  				return stateSync.Cancel()
  1413  			default:
  1414  			}
  1415  		}
  1416  		if d.chainInsertHook != nil {
  1417  			d.chainInsertHook(results)
  1418  		}
  1419  		if oldPivot != nil {
  1420  			results = append(append([]*fetchResult{oldPivot}, oldTail...), results...)
  1421  		}
  1422  //围绕轴块拆分并通过快速/完全同步处理两侧
  1423  		if atomic.LoadInt32(&d.committed) == 0 {
  1424  			latest = results[len(results)-1].Header
  1425  			if height := latest.Number.Uint64(); height > pivot+2*uint64(fsMinFullBlocks) {
  1426  				log.Warn("Pivot became stale, moving", "old", pivot, "new", height-uint64(fsMinFullBlocks))
  1427  				pivot = height - uint64(fsMinFullBlocks)
  1428  			}
  1429  		}
  1430  		P, beforeP, afterP := splitAroundPivot(pivot, results)
  1431  		if err := d.commitFastSyncData(beforeP, stateSync); err != nil {
  1432  			return err
  1433  		}
  1434  		if P != nil {
  1435  //如果找到新的数据透视块,请取消旧的状态检索并重新启动
  1436  			if oldPivot != P {
  1437  				stateSync.Cancel()
  1438  
  1439  				stateSync = d.syncState(P.Header.Root)
  1440  				defer stateSync.Cancel()
  1441  				go func() {
  1442  					if err := stateSync.Wait(); err != nil && err != errCancelStateFetch {
  1443  d.queue.Close() //唤醒等待结果
  1444  					}
  1445  				}()
  1446  				oldPivot = P
  1447  			}
  1448  //等待完成,偶尔检查数据透视是否过时
  1449  			select {
  1450  			case <-stateSync.done:
  1451  				if stateSync.err != nil {
  1452  					return stateSync.err
  1453  				}
  1454  				if err := d.commitPivotBlock(P); err != nil {
  1455  					return err
  1456  				}
  1457  				oldPivot = nil
  1458  
  1459  			case <-time.After(time.Second):
  1460  				oldTail = afterP
  1461  				continue
  1462  			}
  1463  		}
  1464  //快速同步完成,透视提交完成,完全导入
  1465  		if err := d.importBlockResults(afterP); err != nil {
  1466  			return err
  1467  		}
  1468  	}
  1469  }
  1470  
  1471  func splitAroundPivot(pivot uint64, results []*fetchResult) (p *fetchResult, before, after []*fetchResult) {
  1472  	for _, result := range results {
  1473  		num := result.Header.Number.Uint64()
  1474  		switch {
  1475  		case num < pivot:
  1476  			before = append(before, result)
  1477  		case num == pivot:
  1478  			p = result
  1479  		default:
  1480  			after = append(after, result)
  1481  		}
  1482  	}
  1483  	return p, before, after
  1484  }
  1485  
  1486  func (d *Downloader) commitFastSyncData(results []*fetchResult, stateSync *stateSync) error {
  1487  //检查是否有任何提前终止请求
  1488  	if len(results) == 0 {
  1489  		return nil
  1490  	}
  1491  	select {
  1492  	case <-d.quitCh:
  1493  		return errCancelContentProcessing
  1494  	case <-stateSync.done:
  1495  		if err := stateSync.Wait(); err != nil {
  1496  			return err
  1497  		}
  1498  	default:
  1499  	}
  1500  //检索要导入的一批结果
  1501  	first, last := results[0].Header, results[len(results)-1].Header
  1502  	log.Debug("Inserting fast-sync blocks", "items", len(results),
  1503  		"firstnum", first.Number, "firsthash", first.Hash(),
  1504  		"lastnumn", last.Number, "lasthash", last.Hash(),
  1505  	)
  1506  	blocks := make([]*types.Block, len(results))
  1507  	receipts := make([]types.Receipts, len(results))
  1508  	for i, result := range results {
  1509  		blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles)
  1510  		receipts[i] = result.Receipts
  1511  	}
  1512  	if index, err := d.blockchain.InsertReceiptChain(blocks, receipts); err != nil {
  1513  		log.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err)
  1514  		return errInvalidChain
  1515  	}
  1516  	return nil
  1517  }
  1518  
  1519  func (d *Downloader) commitPivotBlock(result *fetchResult) error {
  1520  	block := types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles)
  1521  	log.Debug("Committing fast sync pivot as new head", "number", block.Number(), "hash", block.Hash())
  1522  	if _, err := d.blockchain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{result.Receipts}); err != nil {
  1523  		return err
  1524  	}
  1525  	if err := d.blockchain.FastSyncCommitHead(block.Hash()); err != nil {
  1526  		return err
  1527  	}
  1528  	atomic.StoreInt32(&d.committed, 1)
  1529  	return nil
  1530  }
  1531  
  1532  //DeliverHeaders插入从远程服务器接收的新批块头
  1533  //进入下载计划。
  1534  func (d *Downloader) DeliverHeaders(id string, headers []*types.Header) (err error) {
  1535  	return d.deliver(id, d.headerCh, &headerPack{id, headers}, headerInMeter, headerDropMeter)
  1536  }
  1537  
  1538  //deliverbodies注入从远程节点接收的新批块体。
  1539  func (d *Downloader) DeliverBodies(id string, transactions [][]*types.Transaction, uncles [][]*types.Header) (err error) {
  1540  	return d.deliver(id, d.bodyCh, &bodyPack{id, transactions, uncles}, bodyInMeter, bodyDropMeter)
  1541  }
  1542  
  1543  //DeliverReceipts插入从远程节点接收的新一批收据。
  1544  func (d *Downloader) DeliverReceipts(id string, receipts [][]*types.Receipt) (err error) {
  1545  	return d.deliver(id, d.receiptCh, &receiptPack{id, receipts}, receiptInMeter, receiptDropMeter)
  1546  }
  1547  
  1548  //DeliverNodeData注入从远程节点接收到的新一批节点状态数据。
  1549  func (d *Downloader) DeliverNodeData(id string, data [][]byte) (err error) {
  1550  	return d.deliver(id, d.stateCh, &statePack{id, data}, stateInMeter, stateDropMeter)
  1551  }
  1552  
  1553  //deliver注入从远程节点接收的新批数据。
  1554  func (d *Downloader) deliver(id string, destCh chan dataPack, packet dataPack, inMeter, dropMeter metrics.Meter) (err error) {
  1555  //更新好交付和失败交付的交付指标
  1556  	inMeter.Mark(int64(packet.Items()))
  1557  	defer func() {
  1558  		if err != nil {
  1559  			dropMeter.Mark(int64(packet.Items()))
  1560  		}
  1561  	}()
  1562  //如果在排队时取消同步,则传递或中止
  1563  	d.cancelLock.RLock()
  1564  	cancel := d.cancelCh
  1565  	d.cancelLock.RUnlock()
  1566  	if cancel == nil {
  1567  		return errNoSyncActive
  1568  	}
  1569  	select {
  1570  	case destCh <- packet:
  1571  		return nil
  1572  	case <-cancel:
  1573  		return errNoSyncActive
  1574  	}
  1575  }
  1576  
  1577  //Qostener是服务质量优化循环,偶尔收集
  1578  //对等延迟统计并更新估计的请求往返时间。
  1579  func (d *Downloader) qosTuner() {
  1580  	for {
  1581  //检索当前中间RTT并集成到以前的目标RTT中
  1582  		rtt := time.Duration((1-qosTuningImpact)*float64(atomic.LoadUint64(&d.rttEstimate)) + qosTuningImpact*float64(d.peers.medianRTT()))
  1583  		atomic.StoreUint64(&d.rttEstimate, uint64(rtt))
  1584  
  1585  //通过了一个新的RTT周期,增加了我们对估计的RTT的信心。
  1586  		conf := atomic.LoadUint64(&d.rttConfidence)
  1587  		conf = conf + (1000000-conf)/2
  1588  		atomic.StoreUint64(&d.rttConfidence, conf)
  1589  
  1590  //记录新的QoS值并休眠到下一个RTT
  1591  		log.Debug("Recalculated downloader QoS values", "rtt", rtt, "confidence", float64(conf)/1000000.0, "ttl", d.requestTTL())
  1592  		select {
  1593  		case <-d.quitCh:
  1594  			return
  1595  		case <-time.After(rtt):
  1596  		}
  1597  	}
  1598  }
  1599  
  1600  //QosReduceConfidence是指当新对等加入下载程序时调用的。
  1601  //对等集,需要降低我们对QoS估计的信心。
  1602  func (d *Downloader) qosReduceConfidence() {
  1603  //如果我们只有一个同伴,那么信心总是1
  1604  	peers := uint64(d.peers.Len())
  1605  	if peers == 0 {
  1606  //确保对等连接竞赛不会让我们措手不及
  1607  		return
  1608  	}
  1609  	if peers == 1 {
  1610  		atomic.StoreUint64(&d.rttConfidence, 1000000)
  1611  		return
  1612  	}
  1613  //如果我们有很多同龄人,不要放弃信心)
  1614  	if peers >= uint64(qosConfidenceCap) {
  1615  		return
  1616  	}
  1617  //否则,降低置信系数
  1618  	conf := atomic.LoadUint64(&d.rttConfidence) * (peers - 1) / peers
  1619  	if float64(conf)/1000000 < rttMinConfidence {
  1620  		conf = uint64(rttMinConfidence * 1000000)
  1621  	}
  1622  	atomic.StoreUint64(&d.rttConfidence, conf)
  1623  
  1624  	rtt := time.Duration(atomic.LoadUint64(&d.rttEstimate))
  1625  	log.Debug("Relaxed downloader QoS values", "rtt", rtt, "confidence", float64(conf)/1000000.0, "ttl", d.requestTTL())
  1626  }
  1627  
  1628  //requestrtt返回下载请求的当前目标往返时间
  1629  //完成。
  1630  //
  1631  //注意,返回的RTT是实际估计RTT的.9。原因是
  1632  //下载程序尝试使查询适应RTT,因此多个RTT值可以
  1633  //适应,但较小的是首选(更稳定的下载流)。
  1634  func (d *Downloader) requestRTT() time.Duration {
  1635  	return time.Duration(atomic.LoadUint64(&d.rttEstimate)) * 9 / 10
  1636  }
  1637  
  1638  //REQUESTTL返回单个下载请求的当前超时允许值
  1639  //在…之下完成。
  1640  func (d *Downloader) requestTTL() time.Duration {
  1641  	var (
  1642  		rtt  = time.Duration(atomic.LoadUint64(&d.rttEstimate))
  1643  		conf = float64(atomic.LoadUint64(&d.rttConfidence)) / 1000000.0
  1644  	)
  1645  	ttl := time.Duration(ttlScaling) * time.Duration(float64(rtt)/conf)
  1646  	if ttl > ttlLimit {
  1647  		ttl = ttlLimit
  1648  	}
  1649  	return ttl
  1650  }