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 }