public async Task <TransactionVerifierResult> VerifyAsync(NdmTransaction transaction) { int confirmations = 0; Block?latestBlock = await _blockchainBridge.GetLatestBlockAsync(); if (latestBlock is null) { return(new TransactionVerifierResult(false, 0, _requiredBlockConfirmations)); } do { confirmations++; if (latestBlock.Hash == transaction.BlockHash) { break; } latestBlock = await _blockchainBridge.FindBlockAsync(latestBlock.ParentHash); if (latestBlock is null) { confirmations = 0; break; } if (confirmations == _requiredBlockConfirmations) { break; } } while (confirmations < _requiredBlockConfirmations); return(new TransactionVerifierResult(true, confirmations, _requiredBlockConfirmations)); }
public async Task verify_async_should_return_result_with_confirmed_property_equal_to_false_if_latest_block_is_null() { NdmTransaction transaction = GetTransaction(); TransactionVerifierResult result = await _transactionVerifier.VerifyAsync(transaction); result.BlockFound.Should().BeFalse(); result.Confirmed.Should().BeFalse(); await _blockchainBridge.Received().GetLatestBlockAsync(); }
public async Task verify_async_should_return_result_with_confirmed_property_equal_to_false_if_block_was_not_found_and_required_number_of_confirmations_was_not_achieved() { Block block = GetBlock(); NdmTransaction transaction = GetTransaction(); _blockchainBridge.GetLatestBlockAsync().Returns(block); TransactionVerifierResult result = await _transactionVerifier.VerifyAsync(transaction); result.BlockFound.Should().BeTrue(); result.Confirmed.Should().BeFalse(); await _blockchainBridge.Received().GetLatestBlockAsync(); await _blockchainBridge.Received().FindBlockAsync(block.ParentHash); }
public async Task will_not_claim_without_enough_confirmations() { PaymentClaim claim = GenerateTestClaim(PaymentClaimStatus.Sent, "will_not_claim_without_enough_confirmations"); await paymentClaimRepository.AddAsync(claim); var testTransaction = new NdmTransaction(new Transaction(), false, 1, Keccak.OfAnEmptyString, 5); blockchainBridge.GetTransactionAsync(claim.Transaction.Hash).Returns(Task.FromResult(testTransaction)); transactionVerifier.VerifyAsync(testTransaction).Returns(Task.FromResult(new TransactionVerifierResult(true, 2, 5))); WaitForPaymentClaimsProcessing(); var addedClaim = await paymentClaimRepository.GetAsync(claim.Id); Assert.IsTrue(addedClaim.Status != PaymentClaimStatus.Claimed); }
public async Task can_claim_payment() { PaymentClaim claim = GenerateTestClaim(PaymentClaimStatus.Sent, "can_claim_payment"); await paymentClaimRepository.AddAsync(claim); var testTransaction = new NdmTransaction(new Transaction(), false, 5, Keccak.OfAnEmptyString, 1); blockchainBridge.GetTransactionAsync(claim.Transaction.Hash).Returns(Task.FromResult(testTransaction)); transactionVerifier.VerifyAsync(testTransaction).Returns(Task.FromResult(new TransactionVerifierResult(true, 10, 2))); WaitForPaymentClaimsProcessing(); var addedClaim = await paymentClaimRepository.GetAsync(claim.Id); Assert.IsTrue(addedClaim.Status == PaymentClaimStatus.Claimed); }
private async Task <(uint confirmations, bool rejected)> VerifyDepositConfirmationsAsync(DepositDetails deposit, NdmTransaction transaction, long headNumber) { if (headNumber <= transaction.BlockNumber) { return(0, false); } Keccak?transactionHash = deposit.Transaction?.Hash; uint confirmations = 0u; Block? block = await _blockchainBridge.FindBlockAsync(headNumber); do { if (block is null) { if (_logger.IsWarn) { _logger.Warn("Block was not found."); } return(0, false); } uint confirmationTimestamp = await _depositService.VerifyDepositAsync(deposit.Consumer, deposit.Id, block.Header.Number); if (confirmationTimestamp > 0) { confirmations++; if (_logger.IsInfo) { _logger.Info($"Deposit: '{deposit.Id}' has been confirmed in block number: {block.Number}, hash: '{block.Hash}', transaction hash: '{transactionHash}', timestamp: {confirmationTimestamp}."); } if (deposit.ConfirmationTimestamp == 0) { deposit.SetConfirmationTimestamp(confirmationTimestamp); await _depositRepository.UpdateAsync(deposit); } } else { if (_logger.IsInfo) { _logger.Info($"Deposit with id: '{deposit.Id}' has not returned confirmation timestamp from the contract call yet.'"); } return(0, false); } if (confirmations == _requiredBlockConfirmations) { break; } if (transaction.BlockHash == block.Hash || block.Number <= transaction.BlockNumber) { break; } if (block.ParentHash is null) { break; } block = await _blockchainBridge.FindBlockAsync(block.ParentHash); } while (confirmations < _requiredBlockConfirmations); long latestBlockNumber = await _blockchainBridge.GetLatestBlockNumberAsync(); long?blocksDifference = latestBlockNumber - transaction.BlockNumber; if (blocksDifference >= _requiredBlockConfirmations && confirmations < _requiredBlockConfirmations) { if (_logger.IsError) { _logger.Error($"Deposit: '{deposit.Id}' has been rejected - missing confirmation in block number: {block!.Number}, hash: {block!.Hash}' (transaction hash: '{transactionHash}')."); } return(confirmations, true); } return(confirmations, false); }