github.com/aergoio/aergo@v1.3.1/syncer/blockfetcher.go (about) 1 package syncer 2 3 import ( 4 "bytes" 5 "container/list" 6 "errors" 7 "fmt" 8 "github.com/aergoio/aergo/p2p/p2putil" 9 "sync" 10 "sync/atomic" 11 "time" 12 13 "github.com/aergoio/aergo/internal/enc" 14 "github.com/aergoio/aergo/message" 15 "github.com/aergoio/aergo/pkg/component" 16 "github.com/aergoio/aergo/types" 17 ) 18 19 type BlockFetcher struct { 20 compRequester component.IComponentRequester //for communicate with other service 21 22 ctx *types.SyncContext 23 24 quitCh chan interface{} 25 26 hfCh chan *HashSet 27 28 curHashSet *HashSet 29 30 runningQueue TaskQueue 31 pendingQueue TaskQueue 32 retryQueue SortedTaskQueue 33 34 responseCh chan interface{} //BlockResponse, AddBlockResponse message 35 peers *PeerSet 36 37 blockProcessor *BlockProcessor 38 39 name string 40 41 maxFetchSize int 42 maxFetchTasks int 43 maxPendingConn int 44 45 debug bool 46 47 stat BlockFetcherStat 48 49 waitGroup *sync.WaitGroup 50 isRunning bool 51 52 cfg *SyncerConfig 53 } 54 55 type BlockFetcherStat struct { 56 maxRspBlock atomic.Value 57 lastAddBlock atomic.Value 58 } 59 60 type SyncPeer struct { 61 No int 62 ID types.PeerID 63 FailCnt int 64 IsErr bool 65 } 66 67 type TaskQueue struct { 68 list.List 69 } 70 71 type SortedTaskQueue struct { 72 TaskQueue 73 } 74 75 func (squeue *SortedTaskQueue) Push(task *FetchTask) { 76 var bigElem *list.Element 77 78 for e := squeue.Front(); e != nil; e = e.Next() { 79 // do something with e.Value 80 curTask := e.Value.(*FetchTask) 81 if curTask.startNo > task.startNo { 82 bigElem = e 83 break 84 } 85 } 86 87 if bigElem != nil { 88 squeue.InsertBefore(task, bigElem) 89 } else { 90 squeue.PushBack(task) 91 } 92 93 } 94 95 type FetchTask struct { 96 count int 97 hashes []message.BlockHash 98 startNo types.BlockNo 99 100 syncPeer *SyncPeer 101 102 started time.Time 103 retry int 104 } 105 106 type PeerSet struct { 107 total int 108 free int 109 bad int 110 111 freePeers *list.List 112 badPeers *list.List 113 } 114 115 var ( 116 schedTick = time.Millisecond * 100 117 DfltFetchTimeOut = time.Second * 30 118 DfltBlockFetchSize = 100 119 MaxPeerFailCount = 3 120 DfltBlockFetchTasks = 5 121 MaxBlockPendingTasks = 10 122 ) 123 124 var ( 125 ErrAllPeerBad = errors.New("BlockFetcher: error no avaliable peers") 126 ErrQuitBlockFetcher = errors.New("BlockFetcher quit") 127 ) 128 129 func newBlockFetcher(ctx *types.SyncContext, compRequester component.IComponentRequester, cfg *SyncerConfig) *BlockFetcher { 130 bf := &BlockFetcher{ctx: ctx, compRequester: compRequester, name: NameBlockFetcher, cfg: cfg} 131 132 bf.quitCh = make(chan interface{}) 133 bf.hfCh = make(chan *HashSet) 134 bf.responseCh = make(chan interface{}, cfg.maxBlockReqTasks*2) //for safety. In normal situdation, it should use only one 135 136 bf.peers = newPeerSet() 137 bf.maxFetchSize = cfg.maxBlockReqSize 138 bf.maxFetchTasks = cfg.maxBlockReqTasks 139 bf.maxPendingConn = cfg.maxPendingConn 140 141 bf.blockProcessor = NewBlockProcessor(compRequester, bf, ctx.CommonAncestor, ctx.TargetNo) 142 143 bf.blockProcessor.connQueue = make([]*ConnectTask, 0, 16) 144 145 bf.runningQueue.Init() 146 bf.pendingQueue.Init() 147 bf.retryQueue.Init() 148 149 return bf 150 } 151 152 func (bf *BlockFetcher) Start() { 153 bf.waitGroup = &sync.WaitGroup{} 154 bf.waitGroup.Add(1) 155 156 schedTicker := time.NewTicker(schedTick) 157 158 bf.isRunning = true 159 160 if bf.cfg.debugContext != nil && bf.cfg.debugContext.debugHashFetcher { 161 testRun := func() { 162 logger.Debug().Msg("BlockFetcher dummy mode started") 163 164 defer bf.waitGroup.Done() 165 166 for { 167 if bf.cfg.debugContext.BfWaitTime > 0 { 168 logger.Debug().Msg("BlockFetcher sleep") 169 time.Sleep(bf.cfg.debugContext.BfWaitTime) 170 logger.Debug().Msg("BlockFetcher wakeup") 171 } 172 select { 173 case <-bf.hfCh: 174 case <-bf.quitCh: 175 logger.Debug().Msg("BlockFetcher dummy mode exited") 176 return 177 } 178 } 179 } 180 181 go testRun() 182 return 183 } 184 185 run := func() { 186 defer RecoverSyncer(NameBlockFetcher, bf.GetSeq(), bf.compRequester, func() { bf.waitGroup.Done() }) 187 188 logger.Debug().Msg("start block fetcher") 189 190 if err := bf.init(); err != nil { 191 stopSyncer(bf.compRequester, bf.GetSeq(), bf.name, err) 192 return 193 } 194 195 logger.Debug().Msg("block fetcher loop start") 196 197 for { 198 select { 199 case <-schedTicker.C: 200 if err := bf.checkTaskTimeout(); err != nil { 201 logger.Error().Err(err).Msg("failed checkTaskTimeout") 202 stopSyncer(bf.compRequester, bf.GetSeq(), bf.name, err) 203 return 204 } 205 206 case msg, ok := <-bf.responseCh: 207 if !ok { 208 logger.Info().Msg("BlockFetcher responseCh is closed. Syncer is maybe stopping.") 209 return 210 } 211 212 err := bf.blockProcessor.run(msg) 213 if err != nil { 214 logger.Error().Err(err).Msg("invalid block response message") 215 stopSyncer(bf.compRequester, bf.GetSeq(), bf.name, err) 216 return 217 } 218 219 case <-bf.quitCh: 220 logger.Info().Msg("BlockFetcher quit#1") 221 return 222 } 223 224 //TODO scheduler stop if all tasks have done 225 if err := bf.schedule(); err != nil { 226 if err == ErrQuitBlockFetcher { 227 logger.Info().Msg("BlockFetcher exited while schedule") 228 return 229 } 230 231 logger.Error().Err(err).Msg("BlockFetcher schedule failed & finished") 232 stopSyncer(bf.compRequester, bf.GetSeq(), bf.name, err) 233 return 234 } 235 } 236 } 237 238 go run() 239 } 240 241 func (bf *BlockFetcher) init() error { 242 setPeers := func() error { 243 result, err := bf.compRequester.RequestToFutureResult(message.P2PSvc, &message.GetPeers{}, dfltTimeout, "BlockFetcher init") 244 if err != nil { 245 logger.Error().Err(err).Msg("failed to get peers information") 246 return err 247 } 248 249 msg := result.(*message.GetPeersRsp) 250 251 for _, peerElem := range msg.Peers { 252 state := peerElem.State 253 if state.Get() == types.RUNNING { 254 bf.peers.addNew(types.PeerID(peerElem.Addr.PeerID)) 255 } 256 } 257 258 if bf.peers.freePeers.Len() != bf.peers.free { 259 panic(fmt.Sprintf("free peer len mismatch %d,%d", bf.peers.freePeers.Len(), bf.peers.free)) 260 } 261 262 return nil 263 } 264 265 logger.Debug().Msg("block fetcher init") 266 267 if err := setPeers(); err != nil { 268 logger.Error().Err(err).Msg("failed to set peers") 269 return err 270 } 271 272 return nil 273 } 274 275 func (bf *BlockFetcher) GetSeq() uint64 { 276 return bf.ctx.Seq 277 } 278 279 func (bf *BlockFetcher) schedule() error { 280 for bf.peers.free > 0 { 281 //check max concurrent runing task count 282 curRunning := bf.runningQueue.Len() 283 if curRunning >= bf.maxFetchTasks { 284 //logger.Debug().Int("runnig", curRunning).Int("pending", bf.pendingQueue.Len()).Msg("max running") 285 return nil 286 } 287 288 //check no task 289 candTask, err := bf.searchCandidateTask() 290 if err != nil { 291 logger.Error().Err(err).Msg("failed to search candidate task") 292 return err 293 } 294 if candTask == nil { 295 return nil 296 } 297 298 //check max pending connect 299 // if next task is retry task, must run. it can be next block to connect 300 curPendingConn := len(bf.blockProcessor.connQueue) 301 if curPendingConn >= bf.maxPendingConn && candTask.retry <= 0 { 302 return nil 303 } 304 305 freePeer, err := bf.popFreePeer() 306 if err != nil { 307 logger.Error().Err(err).Msg("error to get free peer") 308 return err 309 } 310 if freePeer == nil { 311 panic("free peer can't be nil") 312 } 313 314 bf.popNextTask(candTask) 315 if candTask == nil { 316 panic("task can't be nil") 317 } 318 319 logger.Debug().Int("pendingConn", curPendingConn).Int("running", curRunning).Msg("schedule") 320 bf.runTask(candTask, freePeer) 321 } 322 323 return nil 324 } 325 326 func (bf *BlockFetcher) checkTaskTimeout() error { 327 now := time.Now() 328 var next *list.Element 329 330 for e := bf.runningQueue.Front(); e != nil; e = next { 331 // do something with e.Value 332 task := e.Value.(*FetchTask) 333 next = e.Next() 334 335 if !task.isTimeOut(now, bf.cfg.fetchTimeOut) { 336 continue 337 } 338 339 bf.runningQueue.Remove(e) 340 341 if err := bf.processFailedTask(task, false); err != nil { 342 return err 343 } 344 345 logger.Error().Uint64("StartNo", task.startNo).Str("start", enc.ToString(task.hashes[0])).Int("cout", task.count).Int("runqueue", bf.runningQueue.Len()).Int("pendingqueue", bf.pendingQueue.Len()). 346 Msg("timeouted task pushed to pending queue") 347 348 //time.Sleep(10000*time.Second) 349 } 350 351 return nil 352 } 353 354 func (bf *BlockFetcher) processFailedTask(task *FetchTask, isErr bool) error { 355 logBadPeer := func(peer *SyncPeer, peers *PeerSet, cfg *SyncerConfig) { 356 if cfg != nil && cfg.debugContext != nil { 357 cfg.debugContext.logBadPeers[peer.No] = true 358 } 359 } 360 361 logger.Error().Int("peerno", task.syncPeer.No).Uint64("StartNo", task.startNo).Str("start", enc.ToString(task.hashes[0])).Msg("task fail, move to retry queue") 362 363 failPeer := task.syncPeer 364 365 logBadPeer(failPeer, bf.peers, bf.cfg) 366 367 bf.peers.processPeerFail(failPeer, isErr) 368 369 task.retry++ 370 task.syncPeer = nil 371 372 //TODO sort by time because deadlock 373 bf.retryQueue.Push(task) 374 375 if bf.peers.isAllBad() { 376 return ErrAllPeerBad 377 } 378 379 return nil 380 } 381 382 func (bf *BlockFetcher) popNextTask(task *FetchTask) { 383 logger.Debug().Int("retry", task.retry).Uint64("StartNo", task.startNo).Str("start", enc.ToString(task.hashes[0])).Str("end", enc.ToString(task.hashes[task.count-1])). 384 Int("tasks retry", bf.retryQueue.Len()).Int("tasks pending", bf.pendingQueue.Len()).Msg("next fetchtask") 385 386 var poppedTask *FetchTask 387 if task.retry > 0 { 388 poppedTask = bf.retryQueue.Pop() 389 } else { 390 poppedTask = bf.pendingQueue.Pop() 391 } 392 393 if poppedTask != task { 394 logger.Panic().Uint64("next task", task.startNo).Uint64("popped task", poppedTask.startNo). 395 Int("retry", task.retry).Msg("peeked task is not popped task") 396 panic("peeked task is not popped task") 397 } 398 } 399 400 func (bf *BlockFetcher) searchCandidateTask() (*FetchTask, error) { 401 getNewHashSet := func() (*HashSet, error) { 402 if bf.curHashSet == nil { //blocking 403 logger.Info().Msg("BlockFetcher waiting first hashset") 404 405 select { 406 case hashSet := <-bf.hfCh: 407 return hashSet, nil 408 case <-bf.quitCh: 409 logger.Debug().Msg("BlockFetcher quitCh#2") 410 return nil, ErrQuitBlockFetcher 411 } 412 } else { 413 select { //nonblocking 414 case hashSet := <-bf.hfCh: 415 return hashSet, nil 416 case <-bf.quitCh: 417 logger.Debug().Msg("BlockFetcher quitCh#3") 418 return nil, ErrQuitBlockFetcher 419 default: 420 //logger.Debug().Msg("BlockFetcher has no input HashSet") 421 return nil, nil 422 } 423 } 424 } 425 426 addNewFetchTasks := func(hashSet *HashSet) { 427 start, end := 0, 0 428 count := hashSet.Count 429 430 logger.Debug().Uint64("startno", hashSet.StartNo).Str("start", enc.ToString(hashSet.Hashes[0])).Int("count", hashSet.Count).Msg("add new fetchtasks from HashSet") 431 432 for start < count { 433 end = start + bf.maxFetchSize 434 if end > count { 435 end = count 436 } 437 438 task := &FetchTask{count: end - start, hashes: hashSet.Hashes[start:end], startNo: hashSet.StartNo + uint64(start), retry: 0} 439 440 logger.Debug().Uint64("StartNo", task.startNo).Int("count", task.count).Msg("add fetchtask") 441 442 bf.pendingQueue.PushBack(task) 443 444 start = end 445 } 446 logger.Debug().Int("pendingqueue", bf.pendingQueue.Len()).Msg("addNewTasks end") 447 } 448 449 var newTask *FetchTask 450 451 if bf.retryQueue.Len() > 0 { 452 newTask = bf.retryQueue.Peek() 453 } else { 454 if bf.pendingQueue.Len() == 0 { 455 logger.Debug().Msg("pendingqueue is empty") 456 457 hashSet, err := getNewHashSet() 458 if err != nil { 459 logger.Debug().Err(err).Msg("failed to get new hashset") 460 return nil, err 461 } 462 if hashSet == nil { 463 logger.Debug().Msg("BlockFetcher no hashSet") 464 return nil, nil 465 } 466 467 logger.Debug().Uint64("startno", hashSet.StartNo).Str("start", enc.ToString(hashSet.Hashes[0])).Int("count", hashSet.Count).Msg("BlockFetcher got hashset") 468 469 bf.curHashSet = hashSet 470 addNewFetchTasks(hashSet) 471 } 472 473 newTask = bf.pendingQueue.Peek() 474 } 475 476 //logger.Debug().Int("retry", newTask.retry).Uint64("StartNo", newTask.startNo).Str("start", enc.ToString(newTask.hashes[0])).Str("end", enc.ToString(newTask.hashes[newTask.count-1])). 477 // Int("tasks retry", bf.retryQueue.Len()).Int("tasks pending", bf.pendingQueue.Len()).Msg("candidate fetchtask") 478 479 return newTask, nil 480 } 481 482 func (bf *BlockFetcher) popFreePeer() (*SyncPeer, error) { 483 setDebugAllPeerBad := func(err error, cfg *SyncerConfig) { 484 if err == ErrAllPeerBad && cfg != nil && cfg.debugContext != nil { 485 debugCtx := cfg.debugContext 486 debugCtx.logAllPeersBad = true 487 } 488 } 489 490 freePeer, err := bf.peers.popFree() 491 if err != nil { 492 setDebugAllPeerBad(err, bf.cfg) 493 logger.Error().Err(err).Msg("pop free peer failed") 494 return nil, err 495 } 496 497 if freePeer != nil { 498 logger.Debug().Int("peerno", freePeer.No).Int("free", bf.peers.free).Int("total", bf.peers.total).Int("bad", bf.peers.bad).Msg("popped free peer") 499 } else { 500 logger.Debug().Int("free", bf.peers.free).Int("total", bf.peers.total).Int("bad", bf.peers.bad).Msg("not exist free peer") 501 } 502 503 return freePeer, nil 504 } 505 506 func (bf *BlockFetcher) pushFreePeer(syncPeer *SyncPeer) { 507 bf.peers.pushFree(syncPeer) 508 509 logger.Debug().Int("peerno", syncPeer.No).Int("free", bf.peers.free).Msg("pushed free peer") 510 } 511 512 func (bf *BlockFetcher) runTask(task *FetchTask, peer *SyncPeer) { 513 task.started = time.Now() 514 task.syncPeer = peer 515 bf.runningQueue.PushBack(task) 516 517 logger.Debug().Int("peerno", task.syncPeer.No).Int("count", task.count).Uint64("StartNo", task.startNo).Str("start", enc.ToString(task.hashes[0])).Int("runqueue", bf.runningQueue.Len()).Msg("send block fetch request") 518 519 bf.compRequester.TellTo(message.P2PSvc, &message.GetBlockChunks{Seq: bf.GetSeq(), GetBlockInfos: message.GetBlockInfos{ToWhom: peer.ID, Hashes: task.hashes}, TTL: DfltFetchTimeOut}) 520 } 521 522 //TODO refactoring matchFunc 523 func (bf *BlockFetcher) findFinished(msg *message.GetBlockChunksRsp, peerMatch bool) (*FetchTask, error) { 524 count := len(msg.Blocks) 525 526 var next *list.Element 527 for e := bf.runningQueue.Front(); e != nil; e = next { 528 // do something with e.Value 529 task := e.Value.(*FetchTask) 530 next = e.Next() 531 532 //find failed peer 533 if peerMatch { 534 if task.isPeerMatched(msg.ToWhom) { 535 bf.runningQueue.Remove(e) 536 537 logger.Debug().Str("peer", p2putil.ShortForm(msg.ToWhom)).Err(msg.Err).Str("start", enc.ToString(task.hashes[0])).Int("count", task.count).Int("runqueue", bf.runningQueue.Len()).Msg("task finished with error") 538 return task, nil 539 } 540 } else { 541 //find finished peer 542 if task.isMatched(msg.ToWhom, msg.Blocks, count) { 543 bf.runningQueue.Remove(e) 544 545 logger.Debug().Uint64("StartNo", task.startNo).Str("start", enc.ToString(task.hashes[0])).Int("count", task.count).Int("runqueue", bf.runningQueue.Len()). 546 Msg("task finished") 547 548 return task, nil 549 } 550 } 551 } 552 553 return nil, &ErrSyncMsg{msg: msg} 554 } 555 556 func (bf *BlockFetcher) handleBlockRsp(msg interface{}) error { 557 if bf == nil { 558 return nil 559 } 560 561 bf.responseCh <- msg 562 return nil 563 } 564 565 func (bf *BlockFetcher) stop() { 566 if bf == nil { 567 return 568 } 569 570 //logger.Info().Bool("isrunning", bf.isRunning).Bool("isnil", bf.quitCh== nil).Msg("BlockFetcher stop") 571 572 if bf.isRunning { 573 logger.Info().Msg("BlockFetcher stop#1") 574 575 close(bf.quitCh) 576 close(bf.hfCh) 577 578 bf.waitGroup.Wait() 579 bf.isRunning = false 580 } 581 logger.Info().Msg("BlockFetcher stopped") 582 } 583 584 func (stat *BlockFetcherStat) setMaxChunkRsp(lastBlock *types.Block) { 585 curMaxRspBlock := stat.getMaxChunkRsp() 586 587 if curMaxRspBlock == nil || curMaxRspBlock.GetHeader().BlockNo < lastBlock.GetHeader().BlockNo { 588 stat.maxRspBlock.Store(lastBlock) 589 logger.Debug().Uint64("no", lastBlock.GetHeader().BlockNo).Msg("last block chunk response") 590 } 591 } 592 593 func (stat *BlockFetcherStat) setLastAddBlock(block *types.Block) { 594 stat.lastAddBlock.Store(block) 595 logger.Debug().Uint64("no", block.GetHeader().BlockNo).Msg("last block add response") 596 } 597 598 func (stat *BlockFetcherStat) getMaxChunkRsp() *types.Block { 599 aopv := stat.maxRspBlock.Load() 600 if aopv != nil { 601 return aopv.(*types.Block) 602 } 603 604 return nil 605 } 606 607 func (stat *BlockFetcherStat) getLastAddBlock() *types.Block { 608 aopv := stat.lastAddBlock.Load() 609 if aopv != nil { 610 return aopv.(*types.Block) 611 } 612 613 return nil 614 } 615 616 func newPeerSet() *PeerSet { 617 ps := &PeerSet{} 618 619 ps.freePeers = list.New() 620 ps.badPeers = list.New() 621 622 return ps 623 } 624 625 func (ps *PeerSet) isAllBad() bool { 626 if ps.total == ps.bad { 627 return true 628 } 629 630 return false 631 } 632 633 func (ps *PeerSet) addNew(peerID types.PeerID) { 634 peerno := ps.total 635 ps.pushFree(&SyncPeer{No: peerno, ID: peerID}) 636 ps.total++ 637 638 logger.Info().Str("peer", p2putil.ShortForm(peerID)).Int("peerno", peerno).Int("no", ps.total).Msg("new peer added") 639 } 640 641 /* 642 func (ps *PeerSet) print() { 643 644 }*/ 645 func (ps *PeerSet) pushFree(freePeer *SyncPeer) { 646 ps.freePeers.PushBack(freePeer) 647 ps.free++ 648 649 logger.Info().Int("no", freePeer.No).Int("free", ps.free).Msg("free peer added") 650 } 651 652 func (ps *PeerSet) popFree() (*SyncPeer, error) { 653 if ps.isAllBad() { 654 logger.Error().Msg("all peers are bad") 655 return nil, ErrAllPeerBad 656 } 657 658 elem := ps.freePeers.Front() 659 if elem == nil { 660 return nil, nil 661 } 662 663 ps.freePeers.Remove(elem) 664 ps.free-- 665 666 if ps.freePeers.Len() != ps.free { 667 panic(fmt.Sprintf("free peer len mismatch %d,%d", ps.freePeers.Len(), ps.free)) 668 } 669 670 freePeer := elem.Value.(*SyncPeer) 671 logger.Debug().Int("peerno", freePeer.No).Int("no", freePeer.No).Msg("free peer poped") 672 return freePeer, nil 673 } 674 675 func (ps *PeerSet) processPeerFail(failPeer *SyncPeer, isErr bool) { 676 //TODO handle connection closed 677 failPeer.FailCnt++ 678 failPeer.IsErr = isErr 679 680 logger.Error().Int("peerno", failPeer.No).Int("failcnt", failPeer.FailCnt).Int("maxfailcnt", MaxPeerFailCount).Bool("iserr", failPeer.IsErr).Msg("peer failed") 681 682 if isErr || failPeer.FailCnt >= MaxPeerFailCount { 683 ps.badPeers.PushBack(failPeer) 684 ps.bad++ 685 686 if ps.badPeers.Len() != ps.bad { 687 panic(fmt.Sprintf("bad peer len mismatch %d,%d", ps.badPeers.Len(), ps.bad)) 688 } 689 690 logger.Error().Int("peerno", failPeer.No).Int("total", ps.total).Int("free", ps.free).Int("bad", ps.bad).Msg("peer move to bad") 691 } else { 692 ps.freePeers.PushBack(failPeer) 693 ps.free++ 694 695 logger.Error().Int("peerno", failPeer.No).Int("total", ps.total).Int("free", ps.free).Int("bad", ps.bad).Msg("peer move to free") 696 } 697 } 698 699 func (tq *TaskQueue) Pop() *FetchTask { 700 elem := tq.Front() 701 if elem == nil { 702 return nil 703 } 704 705 tq.Remove(elem) 706 return elem.Value.(*FetchTask) 707 } 708 709 func (tq *TaskQueue) Peek() *FetchTask { 710 elem := tq.Front() 711 if elem == nil { 712 return nil 713 } 714 715 return elem.Value.(*FetchTask) 716 } 717 718 func (task *FetchTask) isTimeOut(now time.Time, timeout time.Duration) bool { 719 if now.Sub(task.started) > timeout { 720 logger.Info().Int("peerno", task.syncPeer.No).Uint64("startno", task.startNo).Str("start", enc.ToString(task.hashes[0])).Int("cout", task.count).Msg("FetchTask peer timeouted") 721 return true 722 } 723 724 return false 725 } 726 727 func (task *FetchTask) isMatched(peerID types.PeerID, blocks []*types.Block, count int) bool { 728 startHash, endHash := blocks[0].GetHash(), blocks[len(blocks)-1].GetHash() 729 730 if task.count != count || 731 task.syncPeer.ID != peerID || 732 bytes.Compare(task.hashes[0], startHash) != 0 || 733 bytes.Compare(task.hashes[len(task.hashes)-1], endHash) != 0 { 734 return false 735 } 736 737 for i, block := range blocks { 738 if bytes.Compare(task.hashes[i], block.GetHash()) != 0 { 739 logger.Info().Int("peerno", task.syncPeer.No).Str("hash", enc.ToString(task.hashes[0])).Int("idx", i).Msg("task hash mismatch") 740 return false 741 } 742 } 743 744 return true 745 } 746 747 func (task *FetchTask) isPeerMatched(peerID types.PeerID) bool { 748 if task.syncPeer.ID == peerID { 749 return true 750 } 751 752 return false 753 }