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