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);
        }
Esempio n. 2
0
        private void EnqueueBlock(IPeer peer, BlockWithTransactions blockWithTransactions)
        {
            try
            {
                var blockHash = blockWithTransactions.GetHash();

                if (peer.KnowsBlock(blockHash))
                {
                    return; // block already known to this peer
                }
                peer.EnqueueBlock(blockWithTransactions, async ex =>
                {
                    peer.TryAddKnownBlock(blockHash);

                    if (ex != null)
                    {
                        Logger.LogError(ex, $"Error while broadcasting block to {peer}.");
                        await HandleNetworkException(peer, ex);
                    }
                });
            }
            catch (NetworkException ex)
            {
                Logger.LogError(ex, $"Error while broadcasting block to {peer}.");
            }
        }
Esempio n. 3
0
        public async Task BroadcastBlock_OnePeerKnowsBlock_Test()
        {
            var blockHeader           = OsCoreTestHelper.CreateFakeBlockHeader(1, 2);
            var blockWithTransactions = new BlockWithTransactions {
                Header = blockHeader
            };

            _peerPool.FindPeerByPublicKey("Pubkey0").TryAddKnownBlock(blockWithTransactions.GetHash());

            await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTransactions);

            foreach (var peer in _testContext.MockedPeers)
            {
                peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once());
            }

            _testContext.MockedPeers[0].Verify(
                p => p.EnqueueBlock(blockWithTransactions, It.IsAny <Action <NetworkException> >()),
                Times.Never);
            _testContext.MockedPeers[1].Verify(
                p => p.EnqueueBlock(blockWithTransactions, It.IsAny <Action <NetworkException> >()),
                Times.Once());
            _testContext.MockedPeers[2].Verify(
                p => p.EnqueueBlock(blockWithTransactions, It.IsAny <Action <NetworkException> >()),
                Times.Once());
        }
Esempio n. 4
0
        private async Task <bool> ValidateTransactionAsync(BlockWithTransactions blockWithTransactions)
        {
            foreach (var transaction in blockWithTransactions.Transactions)
            {
                if (!transaction.VerifyExpiration(blockWithTransactions.Height - 1))
                {
                    Logger.LogWarning($"Transaction {transaction.GetHash()} expired.");
                    return(false);
                }

                // No need to validate again if this tx already in local database.
                if (await _blockchainService.HasTransactionAsync(transaction.GetHash()))
                {
                    continue;
                }

                if (!await _transactionValidationService.ValidateTransactionAsync(transaction))
                {
                    return(false);
                }

                var constrainedTransactionValidationResult =
                    _transactionValidationService.ValidateConstrainedTransaction(transaction,
                                                                                 blockWithTransactions.GetHash());
                _transactionValidationService.ClearConstrainedTransactionValidationProvider(blockWithTransactions
                                                                                            .GetHash());
                if (!constrainedTransactionValidationResult)
                {
                    Logger.LogWarning($"Transaction {transaction} validation failed for constraint.");
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 5
0
        private async Task <bool> ValidateTransactionAsync(BlockWithTransactions blockWithTransactions)
        {
            foreach (var transaction in blockWithTransactions.Transactions)
            {
                // No need to validate again if this tx already in local database.
                var tx = await _transactionManager.GetTransactionAsync(transaction.GetHash());

                if (tx != null)
                {
                    continue;
                }

                if (!await _transactionValidationService.ValidateTransactionAsync(transaction))
                {
                    return(false);
                }

                var constrainedTransactionValidationResult =
                    _transactionValidationService.ValidateConstrainedTransaction(transaction,
                                                                                 blockWithTransactions.GetHash());
                _transactionValidationService.ClearConstrainedTransactionValidationProvider(blockWithTransactions
                                                                                            .GetHash());
                if (!constrainedTransactionValidationResult)
                {
                    return(false);
                }
            }

            return(true);
        }
        private void EnqueueBlock(IPeer peer, BlockWithTransactions blockWithTransactions)
        {
            try
            {
                var blockHash = blockWithTransactions.GetHash();

                if (peer.KnowsBlock(blockHash))
                {
                    return; // block already known to this peer
                }
                peer.EnqueueBlock(blockWithTransactions, async ex =>
                {
                    peer.TryAddKnownBlock(blockHash);

                    if (ex != null)
                    {
                        Logger.LogWarning(ex, $"Could not broadcast block to {peer} - status {peer.ConnectionStatus}.");
                        await HandleNetworkException(peer, ex);
                    }
                });
            }
            catch (NetworkException ex)
            {
                Logger.LogWarning(ex, $"Could not enqueue block to {peer} - status {peer.ConnectionStatus}.");
            }
        }
        public async Task GetBlockByHash_Test()
        {
            var block = new BlockWithTransactions
            {
                Header = _osTestHelper.GenerateBlock(HashHelper.ComputeFrom("PreBlockHash"), 100).Header
            };

            var mockClient = new Mock <PeerService.PeerServiceClient>();

            mockClient.Setup(c =>
                             c.RequestBlockAsync(It.IsAny <BlockRequest>(), It.IsAny <Metadata>(), null,
                                                 CancellationToken.None))
            .Returns(MockAsyncUnaryCall(new BlockReply {
                Block = block
            }));
            var grpcPeer = CreatePeer(mockClient.Object);

            var result = await grpcPeer.GetBlockByHashAsync(block.GetHash());

            result.ShouldBe(block);

            var metrics = grpcPeer.GetRequestMetrics();

            metrics["GetBlock"].Count.ShouldBe(1);
            metrics["GetBlock"][0].MethodName.ShouldContain("GetBlock");
            metrics["GetBlock"][0].Info.ShouldContain("Block request for");
        }
Esempio n. 8
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);
 }
Esempio n. 9
0
        private Task ProcessBlockAsync(BlockWithTransactions block, string peerPubkey)
        {
            var peer = TryGetPeerByPubkey(peerPubkey);

            if (peer.SyncState != SyncState.Finished)
            {
                peer.SyncState = SyncState.Finished;
            }

            if (!peer.TryAddKnownBlock(block.GetHash()))
            {
                return(Task.CompletedTask);
            }

            _ = EventBus.PublishAsync(new BlockReceivedEvent(block, peerPubkey));
            return(Task.CompletedTask);
        }
        public async Task AttachBlockWithTransactionsAsync(BlockWithTransactions blockWithTransactions,
                                                           string senderPubkey, Func <Task> attachFinishedCallback = null)
        {
            var blockValid = await _blockSyncValidationService.ValidateBlockBeforeAttachAsync(blockWithTransactions);

            if (!blockValid)
            {
                Logger.LogDebug(
                    $"Sync block validation failed, peer: {senderPubkey}, block hash: {blockWithTransactions.GetHash()}, block height: {blockWithTransactions.Height}");
                await LocalEventBus.PublishAsync(new AbnormalPeerFoundEventData
                {
                    BlockHash   = blockWithTransactions.GetHash(),
                    BlockHeight = blockWithTransactions.Height,
                    PeerPubkey  = senderPubkey
                });

                return;
            }

            await _blockchainService.AddTransactionsAsync(blockWithTransactions.Transactions);

            var block = blockWithTransactions.ToBlock();
            await _blockchainService.AddBlockAsync(block);

            _blockSyncQueueService.Enqueue(async() =>
            {
                try
                {
                    await _blockAttachService.AttachBlockAsync(block);
                }
                finally
                {
                    if (attachFinishedCallback != null)
                    {
                        await attachFinishedCallback();
                    }
                }
            },
                                           KernelConstants.UpdateChainQueueName);
        }
Esempio n. 11
0
        public async Task RecordMetric_Test()
        {
            var block = new BlockWithTransactions
            {
                Header = _osTestHelper.GenerateBlock(HashHelper.ComputeFrom("PreBlockHash"), 100).Header
            };

            var mockClient = new Mock <PeerService.PeerServiceClient>();

            mockClient.Setup(c =>
                             c.RequestBlockAsync(It.IsAny <BlockRequest>(), It.IsAny <Metadata>(), null,
                                                 CancellationToken.None))
            .Returns(MockAsyncUnaryCall(new BlockReply {
                Block = block
            }));

            var blockList = new BlockList();

            blockList.Blocks.Add(block);

            mockClient.Setup(c =>
                             c.RequestBlocksAsync(It.IsAny <BlocksRequest>(), It.IsAny <Metadata>(), null,
                                                  CancellationToken.None))
            .Returns(MockAsyncUnaryCall(blockList));
            var grpcPeer = CreatePeer(mockClient.Object);

            for (var i = 0; i < 101; i++)
            {
                await grpcPeer.GetBlockByHashAsync(block.GetHash());

                await grpcPeer.GetBlocksAsync(block.Header.PreviousBlockHash, 1);
            }

            var metrics = grpcPeer.GetRequestMetrics();

            metrics["GetBlocks"].Count.ShouldBe(100);
            metrics["GetBlock"].Count.ShouldBe(100);
        }