private async Task <DownloadBlocksResult> DownloadBlocksAsync(Chain chain, BlockDownloadJobInfo jobInfo) { var downloadResult = new DownloadBlocksResult(); if (jobInfo.CurrentTargetBlockHeight > 0) { if (jobInfo.CurrentTargetBlockHeight <= chain.BestChainHeight || await BlockIsInBestChain(chain, jobInfo.CurrentTargetBlockHash, jobInfo.CurrentTargetBlockHeight)) { downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { PreviousBlockHash = jobInfo.CurrentTargetBlockHash, PreviousBlockHeight = jobInfo.CurrentTargetBlockHeight, BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount }); } } else { // Download blocks from longest chain downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { PreviousBlockHash = chain.LongestChainHash, PreviousBlockHeight = chain.LongestChainHeight, BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount }); // Download blocks from best chain if (downloadResult.DownloadBlockCount == 0) { downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { PreviousBlockHash = chain.BestChainHash, PreviousBlockHeight = chain.BestChainHeight, BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount }); } // Download blocks from LIB if (downloadResult.DownloadBlockCount == 0) { Logger.LogDebug($"Resynchronize from lib, lib height: {chain.LastIrreversibleBlockHeight}."); downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { PreviousBlockHash = chain.LastIrreversibleBlockHash, PreviousBlockHeight = chain.LastIrreversibleBlockHeight, BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount }); } } return(downloadResult); }
/// <summary> /// Download and attach blocks /// UseSuggestedPeer == true: Download blocks from suggested peer directly; /// Target download height > peer lib height, download blocks from suggested peer; /// Target download height <= peer lib height, select a random peer to download. /// </summary> /// <param name="downloadBlockDto"></param> /// <returns></returns> public async Task <DownloadBlocksResult> DownloadBlocksAsync(DownloadBlockDto downloadBlockDto) { var downloadResult = new DownloadBlocksResult(); var peerPubkey = downloadBlockDto.SuggestedPeerPubkey; try { if (UseSuggestedPeer(downloadBlockDto)) { downloadResult = await DownloadBlocksAsync(peerPubkey, downloadBlockDto); } else { // If cannot get the blocks, there should be network problems or bad peer, // because we have selected peer with lib height greater than or equal to the target height. // 1. network problems, need to retry from other peer. // 2. not network problems, this peer or the last peer is bad peer, we need to remove it. var downloadTargetHeight = downloadBlockDto.PreviousBlockHeight + downloadBlockDto.MaxBlockDownloadCount; var exceptedPeers = new List <string> { _blockSyncStateProvider.LastRequestPeerPubkey }; var retryTimes = 2; while (true) { peerPubkey = GetRandomPeerPubkey(downloadBlockDto.SuggestedPeerPubkey, downloadTargetHeight, exceptedPeers); downloadResult = await DownloadBlocksAsync(peerPubkey, downloadBlockDto); if (downloadResult.Success || retryTimes <= 0) { break; } exceptedPeers.Add(peerPubkey); retryTimes--; } if (downloadResult.Success && downloadResult.DownloadBlockCount == 0) { await CheckBadPeerAsync(peerPubkey, downloadBlockDto.PreviousBlockHash, downloadBlockDto.PreviousBlockHeight); } } } catch (BlockDownloadException e) { await LocalEventBus.PublishAsync(new BadPeerFoundEventData { BlockHash = e.BlockHash, BlockHeight = e.BlockHeight, PeerPubkey = e.PeerPubkey }); } return(downloadResult); }
private async Task <DownloadBlocksResult> DownloadBlocksAsync(Chain chain, BlockDownloadJobInfo jobInfo) { var downloadResult = new DownloadBlocksResult(); if (jobInfo.CurrentTargetBlockHeight == 0) { // Download blocks from longest chain downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { PreviousBlockHash = chain.LongestChainHash, PreviousBlockHeight = chain.LongestChainHeight, BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, UseSuggestedPeer = true }); // Download blocks from best chain if (downloadResult.Success && downloadResult.DownloadBlockCount == 0) { downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { PreviousBlockHash = chain.BestChainHash, PreviousBlockHeight = chain.BestChainHeight, BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, UseSuggestedPeer = true }); } // Download blocks from LIB if (downloadResult.Success && downloadResult.DownloadBlockCount == 0) { Logger.LogDebug($"Resynchronize from lib, lib height: {chain.LastIrreversibleBlockHeight}."); downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { PreviousBlockHash = chain.LastIrreversibleBlockHash, PreviousBlockHeight = chain.LastIrreversibleBlockHeight, BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, UseSuggestedPeer = true }); } } // If last target block didn't become the longest chain, stop this job. else if (jobInfo.CurrentTargetBlockHeight <= chain.LongestChainHeight + 8) { downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { PreviousBlockHash = jobInfo.CurrentTargetBlockHash, PreviousBlockHeight = jobInfo.CurrentTargetBlockHeight, BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, UseSuggestedPeer = false }); } return(downloadResult); }