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