Esempio n. 1
0
        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));
        }
Esempio n. 2
0
        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();
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
        }