Exemple #1
0
        public async Task ProcessDownloadJob_Success()
        {
            var response = await _networkService.GetBlockByHashAsync(Hash.FromString("PeerBlock"), null);

            var peerBlock = response.Payload;

            await _blockDownloadJobManager.EnqueueAsync(peerBlock.GetHash(), peerBlock.Height,
                                                        _blockSyncOptions.MaxBatchRequestBlockCount,
                                                        null);

            await _blockDownloadWorker.ProcessDownloadJobAsync();

            var chain = await _blockchainService.GetChainAsync();

            chain.BestChainHeight.ShouldBe(31);

            var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync();

            jobInfo.JobId.ShouldBe(peerBlock.GetHash());
            _blockSyncStateProvider.TryGetDownloadJobTargetState(chain.BestChainHash, out var state).ShouldBeTrue();
            state.ShouldBeFalse();

            _blockSyncStateProvider.SetDownloadJobTargetState(chain.BestChainHash, true);

            await _blockDownloadWorker.ProcessDownloadJobAsync();

            jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync();

            jobInfo.ShouldBeNull();
            _blockSyncStateProvider.TryGetDownloadJobTargetState(chain.BestChainHash, out state).ShouldBeFalse();
        }
Exemple #2
0
        public void RemoveDownloadJobTargetState_Test()
        {
            var targetHash = HashHelper.ComputeFrom("TargetHash");

            _blockSyncStateProvider.SetDownloadJobTargetState(targetHash, true);

            _blockDownloadService.RemoveDownloadJobTargetState(null);
            _blockSyncStateProvider.TryGetDownloadJobTargetState(targetHash, out _).ShouldBeTrue();

            _blockDownloadService.RemoveDownloadJobTargetState(targetHash);
            _blockSyncStateProvider.TryGetDownloadJobTargetState(targetHash, out _).ShouldBeFalse();
        }
Exemple #3
0
        public async Task ProcessDownloadJob_ValidateFailed()
        {
            var chain = await _blockchainService.GetChainAsync();

            var peerBlock = await _networkService.GetBlockByHashAsync(Hash.FromString("PeerBlock"));

            var bestChainHash   = chain.BestChainHash;
            var bestChainHeight = chain.BestChainHeight;

            // no job
            await _blockDownloadWorker.ProcessDownloadJobAsync();

            chain = await _blockchainService.GetChainAsync();

            chain.BestChainHash.ShouldBe(bestChainHash);
            chain.BestChainHeight.ShouldBe(bestChainHeight);

            await _blockDownloadJobManager.EnqueueAsync(peerBlock.GetHash(), peerBlock.Height,
                                                        _blockSyncOptions.MaxBatchRequestBlockCount, null);

            // attach queue is too busy
            _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName,
                                                   TimestampHelper.GetUtcNow().AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachBlockAgeLimit + 100)));
            await _blockDownloadWorker.ProcessDownloadJobAsync();

            chain = await _blockchainService.GetChainAsync();

            chain.BestChainHash.ShouldBe(bestChainHash);
            chain.BestChainHeight.ShouldBe(bestChainHeight);

            _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, null);

            // update queue is too busy
            _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, TimestampHelper.GetUtcNow()
                                                   .AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachAndExecuteBlockAgeLimit + 100)));
            await _blockDownloadWorker.ProcessDownloadJobAsync();

            chain = await _blockchainService.GetChainAsync();

            chain.BestChainHash.ShouldBe(bestChainHash);
            chain.BestChainHeight.ShouldBe(bestChainHeight);

            // not reached the download target and less then deadline
            var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync();

            jobInfo.CurrentTargetBlockHash   = jobInfo.TargetBlockHash;
            jobInfo.CurrentTargetBlockHeight = jobInfo.TargetBlockHeight;
            jobInfo.Deadline = TimestampHelper.GetUtcNow().AddSeconds(4);
            _blockSyncStateProvider.SetDownloadJobTargetState(jobInfo.TargetBlockHash, false);

            await _blockDownloadWorker.ProcessDownloadJobAsync();

            chain = await _blockchainService.GetChainAsync();

            chain.BestChainHash.ShouldBe(bestChainHash);
            chain.BestChainHeight.ShouldBe(bestChainHeight);
        }
        public void DownloadJobTargetState_Test()
        {
            var targetHash = HashHelper.ComputeFrom("TargetHash");
            var result     = _blockSyncStateProvider.TryUpdateDownloadJobTargetState(targetHash, false);

            result.ShouldBeFalse();

            _blockSyncStateProvider.SetDownloadJobTargetState(targetHash, false);
            result = _blockSyncStateProvider.TryGetDownloadJobTargetState(targetHash, out var value);
            result.ShouldBeTrue();
            value.ShouldBeFalse();

            result = _blockSyncStateProvider.TryUpdateDownloadJobTargetState(targetHash, false);
            result.ShouldBeFalse();

            result = _blockSyncStateProvider.TryUpdateDownloadJobTargetState(targetHash, true);
            result.ShouldBeTrue();

            _blockSyncStateProvider.TryRemoveDownloadJobTargetState(targetHash);
            result = _blockSyncStateProvider.TryGetDownloadJobTargetState(targetHash, out value);
            result.ShouldBeFalse();
        }
Exemple #5
0
        private async Task <DownloadBlocksResult> DownloadBlocksAsync(Hash previousBlockHash, string peerPubkey, int
                                                                      batchRequestBlockCount, int maxBlockDownloadCount)
        {
            var downloadBlockCount      = 0;
            var lastDownloadBlockHash   = previousBlockHash;
            var lastDownloadBlockHeight = 0L;

            Logger.LogDebug(
                $"Download blocks start with block hash: {lastDownloadBlockHash}, PeerPubkey: {peerPubkey}");

            while (downloadBlockCount < maxBlockDownloadCount)
            {
                var getBlocksResult = await _networkService.GetBlocksAsync(lastDownloadBlockHash,
                                                                           batchRequestBlockCount, peerPubkey);

                if (!getBlocksResult.Success)
                {
                    return(new DownloadBlocksResult
                    {
                        Success = false
                    });
                }

                var blocksWithTransactions = getBlocksResult.Payload;
                if (blocksWithTransactions == null || !blocksWithTransactions.Any())
                {
                    Logger.LogWarning("No blocks returned.");
                    break;
                }

                if (blocksWithTransactions.First().Header.PreviousBlockHash != lastDownloadBlockHash)
                {
                    throw new InvalidOperationException(
                              $"Previous block not match previous {lastDownloadBlockHash}, network back {blocksWithTransactions.First().Header.PreviousBlockHash}");
                }

                foreach (var blockWithTransactions in blocksWithTransactions)
                {
                    Logger.LogDebug($"Processing block {blockWithTransactions}.");
                    EnqueueAttachBlockJob(blockWithTransactions, peerPubkey);
                    downloadBlockCount++;
                }

                var lastBlock = blocksWithTransactions.Last();
                lastDownloadBlockHash   = lastBlock.GetHash();
                lastDownloadBlockHeight = lastBlock.Height;
            }

            if (downloadBlockCount != 0)
            {
                _blockSyncStateProvider.SetDownloadJobTargetState(lastDownloadBlockHash, false);
                _blockSyncStateProvider.LastRequestPeerPubkey = peerPubkey;
            }

            return(new DownloadBlocksResult
            {
                Success = true,
                DownloadBlockCount = downloadBlockCount,
                LastDownloadBlockHash = lastDownloadBlockHash,
                LastDownloadBlockHeight = lastDownloadBlockHeight
            });
        }
Exemple #6
0
        private async Task <DownloadBlocksResult> DownloadBlocksAsync(string peerPubkey,
                                                                      DownloadBlockDto downloadBlockDto)
        {
            var downloadBlockCount      = 0;
            var lastDownloadBlockHash   = downloadBlockDto.PreviousBlockHash;
            var lastDownloadBlockHeight = downloadBlockDto.PreviousBlockHeight;

            Logger.LogDebug(
                $"Download blocks start with block height: {lastDownloadBlockHeight}, hash: {lastDownloadBlockHash}, PeerPubkey: {peerPubkey}");

            while (downloadBlockCount < downloadBlockDto.MaxBlockDownloadCount)
            {
                var getBlocksResult = await _networkService.GetBlocksAsync(lastDownloadBlockHash,
                                                                           downloadBlockDto.BatchRequestBlockCount, peerPubkey);

                if (!getBlocksResult.Success)
                {
                    return(new DownloadBlocksResult
                    {
                        Success = false
                    });
                }

                var blocksWithTransactions = getBlocksResult.Payload;
                if (blocksWithTransactions == null || !blocksWithTransactions.Any())
                {
                    Logger.LogDebug(
                        $"No blocks returned from peer: {peerPubkey}, Previous block height: {lastDownloadBlockHeight}, hash: {lastDownloadBlockHash}.");
                    break;
                }

                foreach (var blockWithTransactions in blocksWithTransactions)
                {
                    Logger.LogDebug($"Processing block {blockWithTransactions}.");

                    if (blockWithTransactions.Height != lastDownloadBlockHeight + 1 ||
                        blockWithTransactions.Header.PreviousBlockHash != lastDownloadBlockHash)
                    {
                        Logger.LogWarning(
                            $"Received invalid block, peer: {peerPubkey}, block hash: {blockWithTransactions.GetHash()}, block height: {blockWithTransactions.Height}");
                        throw new BlockDownloadException(blockWithTransactions.GetHash(), blockWithTransactions.Height,
                                                         peerPubkey);
                    }

                    lastDownloadBlockHash   = blockWithTransactions.GetHash();
                    lastDownloadBlockHeight = blockWithTransactions.Height;

                    EnqueueAttachBlockJob(blockWithTransactions, peerPubkey);
                    downloadBlockCount++;
                }

                var lastBlock = blocksWithTransactions.Last();
                lastDownloadBlockHash   = lastBlock.GetHash();
                lastDownloadBlockHeight = lastBlock.Height;
            }

            if (downloadBlockCount != 0)
            {
                _blockSyncStateProvider.SetDownloadJobTargetState(lastDownloadBlockHash, false);
                _blockSyncStateProvider.LastRequestPeerPubkey = peerPubkey;
            }

            return(new DownloadBlocksResult
            {
                Success = true,
                DownloadBlockCount = downloadBlockCount,
                LastDownloadBlockHash = lastDownloadBlockHash,
                LastDownloadBlockHeight = lastDownloadBlockHeight
            });
        }
Exemple #7
0
        public async Task <DownloadBlocksResult> DownloadBlocksAsync(DownloadBlockDto downloadBlockDto)
        {
            var downloadBlockCount      = 0;
            var lastDownloadBlockHash   = downloadBlockDto.PreviousBlockHash;
            var lastDownloadBlockHeight = downloadBlockDto.PreviousBlockHeight;

            while (downloadBlockCount < downloadBlockDto.MaxBlockDownloadCount)
            {
                Logger.LogDebug(
                    $"Request blocks start with block hash: {lastDownloadBlockHash}, block height: {lastDownloadBlockHeight}");

                var blocksWithTransactions = await _networkService.GetBlocksAsync(lastDownloadBlockHash,
                                                                                  downloadBlockDto.BatchRequestBlockCount, downloadBlockDto.SuggestedPeerPubkey);

                if (blocksWithTransactions == null || !blocksWithTransactions.Any())
                {
                    Logger.LogWarning("No blocks returned.");
                    break;
                }

                if (blocksWithTransactions.First().Header.PreviousBlockHash != lastDownloadBlockHash)
                {
                    throw new InvalidOperationException(
                              $"Previous block not match previous {lastDownloadBlockHash}, network back {blocksWithTransactions.First().Header.PreviousBlockHash}");
                }

                foreach (var blockWithTransactions in blocksWithTransactions)
                {
                    Logger.LogDebug($"Processing block {blockWithTransactions}.");

                    _blockSyncQueueService.Enqueue(
                        async() =>
                    {
                        await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions,
                                                                                       async() =>
                        {
                            _blockSyncStateProvider.TryUpdateDownloadJobTargetState(blockWithTransactions.GetHash(), true);
                        });
                    },
                        OSConstants.BlockSyncAttachQueueName);

                    downloadBlockCount++;
                }

                var lastBlock = blocksWithTransactions.Last();
                lastDownloadBlockHash   = lastBlock.GetHash();
                lastDownloadBlockHeight = lastBlock.Height;
            }

            if (lastDownloadBlockHash != null)
            {
                _blockSyncStateProvider.SetDownloadJobTargetState(lastDownloadBlockHash, false);
            }

            return(new DownloadBlocksResult
            {
                DownloadBlockCount = downloadBlockCount,
                LastDownloadBlockHash = lastDownloadBlockHash,
                LastDownloadBlockHeight = lastDownloadBlockHeight
            });
        }