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); }
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}."); } }
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()); }
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); }
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"); }
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); }
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); }
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); }