public async Task AttachBlockWithTransactions_Test()
        {
            var chain = await _blockchainService.GetChainAsync();

            var transactions = await _osTestHelper.GenerateTransferTransactions(2);

            var block                 = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions);
            var executedBlock         = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block;
            var blockWithTransactions = new BlockWithTransactions
            {
                Header = executedBlock.Header, Transactions = { transactions }
            };

            var attachFinished = false;

            await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions, "pubkey",
                                                                           () =>
            {
                attachFinished = true;
                return(Task.CompletedTask);
            });

            chain = await _blockchainService.GetChainAsync();

            chain.BestChainHash.ShouldBe(blockWithTransactions.GetHash());
            chain.BestChainHeight.ShouldBe(blockWithTransactions.Height);
            attachFinished.ShouldBeTrue();

            var txs = await _blockchainService.GetTransactionsAsync(transactions.Select(t => t.GetHash()));

            txs.Count.ShouldBe(2);
        }
Beispiel #2
0
        public async Task <bool> FetchBlockAsync(Hash blockHash, long blockHeight, string suggestedPeerPubKey)
        {
            var localBlock = await _blockchainService.GetBlockByHashAsync(blockHash);

            if (localBlock != null)
            {
                Logger.LogDebug($"Block {localBlock} already know.");
                return(true);
            }

            var response = await _networkService.GetBlockByHashAsync(blockHash, suggestedPeerPubKey);

            var blockWithTransactions = response.Payload;

            if (blockWithTransactions == null)
            {
                return(false);
            }

            _blockSyncQueueService.Enqueue(
                async() =>
            {
                await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions,
                                                                               suggestedPeerPubKey);
            },
                OSConstants.BlockSyncAttachQueueName);

            return(true);
        }
Beispiel #3
0
 private void EnqueueSyncBlockJob(BlockWithTransactions blockWithTransactions)
 {
     _blockSyncQueueService.Enqueue(async() =>
     {
         Logger.LogTrace($"Block sync: sync block, block: {blockWithTransactions}.");
         await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions);
     }, OSConstants.BlockSyncAttachQueueName);
 }
Beispiel #4
0
 private void EnqueueAttachBlockJob(BlockWithTransactions blockWithTransactions, string senderPubkey)
 {
     _blockSyncQueueService.Enqueue(async() =>
     {
         Logger.LogDebug($"Block sync: sync block, block: {blockWithTransactions}.");
         await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions, senderPubkey);
     }, OSConstants.BlockSyncAttachQueueName);
 }
        public async Task Attach_InvalidBlock()
        {
            var badPeerPubkey = "BadPeerPubkey";
            var badBlock      = _osTestHelper.GenerateBlockWithTransactions(Hash.FromString("BadBlock"), 10000);

            var badPeer = _networkService.GetPeerByPubkey(badPeerPubkey);

            badPeer.ShouldNotBeNull();

            await _blockSyncAttachService.AttachBlockWithTransactionsAsync(badBlock, badPeerPubkey);

            badPeer = _networkService.GetPeerByPubkey(badPeerPubkey);
            badPeer.ShouldBeNull();
        }
Beispiel #6
0
        public async Task Attach_InvalidBlock()
        {
            var abnormalPeerPubkey = "AbnormalPeerPubkey";
            var badBlock           = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("BadBlock"), 10000);

            var abnormalPeer = _networkService.GetPeerByPubkey(abnormalPeerPubkey);

            abnormalPeer.ShouldNotBeNull();

            await _blockSyncAttachService.AttachBlockWithTransactionsAsync(badBlock, abnormalPeerPubkey);

            abnormalPeer = _networkService.GetPeerByPubkey(abnormalPeerPubkey);
            abnormalPeer.ShouldBeNull();
        }
Beispiel #7
0
 private void EnqueueAttachBlockJob(BlockWithTransactions blockWithTransactions, string senderPubkey)
 {
     _blockSyncQueueService.Enqueue(
         async() =>
     {
         await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions, senderPubkey,
                                                                        () =>
         {
             _blockSyncStateProvider.TryUpdateDownloadJobTargetState(
                 blockWithTransactions.GetHash(), true);
             return(Task.CompletedTask);
         });
     },
         OSConstants.BlockSyncAttachQueueName);
 }
Beispiel #8
0
        public async Task <bool> FetchBlockAsync(Hash blockHash, long blockHeight, string suggestedPeerPubKey)
        {
            var hasBlock = await _blockchainService.HasBlockAsync(blockHash);

            if (hasBlock)
            {
                Logger.LogDebug($"Block {blockHash} already know.");
                return(true);
            }

            var response = await _networkService.GetBlockByHashAsync(blockHash, suggestedPeerPubKey);

            if (!response.Success || response.Payload == null)
            {
                return(false);
            }

            var blockWithTransactions = response.Payload;

            if (blockWithTransactions.GetHash() != blockHash || blockWithTransactions.Height != blockHeight)
            {
                Logger.LogWarning(
                    $"Fetched invalid block, peer: {suggestedPeerPubKey}, block hash: {blockWithTransactions.GetHash()}, block height: {blockWithTransactions.Height}");
                await LocalEventBus.PublishAsync(new BadPeerFoundEventData
                {
                    BlockHash   = blockWithTransactions.GetHash(),
                    BlockHeight = blockWithTransactions.Height,
                    PeerPubkey  = suggestedPeerPubKey
                });

                return(false);
            }

            _blockSyncQueueService.Enqueue(
                async() =>
            {
                await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions,
                                                                               suggestedPeerPubKey);
            },
                OSConstants.BlockSyncAttachQueueName);

            return(true);
        }
Beispiel #9
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
            });
        }