public TransactionVerifierResult Verify(TxReceipt receipt) { var confirmations = 0; var block = _blockchainBridge.FindBlock(_blockchainBridge.Head.Hash); if (block is null) { return(new TransactionVerifierResult(false, 0, _requiredBlockConfirmations)); } while (block.Number >= receipt.BlockNumber) { confirmations++; if (block.Hash == receipt.BlockHash) { break; } block = _blockchainBridge.FindBlock(block.ParentHash); if (block is null) { break; } } return(new TransactionVerifierResult(true, confirmations, _requiredBlockConfirmations)); }
public async Task find_block_by_hash_should_invoke_blockchain_bridge_find_block_by_hash() { var block = Build.A.Block.TestObject; _blockchainBridge.FindBlock(block.Hash).Returns(block); var result = await _ndmBridge.FindBlockAsync(block.Hash); _blockchainBridge.Received().FindBlock(block.Hash); result.Should().Be(block); }
public void Eth_get_block_by_hash() { IBlockchainBridge bridge = Substitute.For <IBlockchainBridge>(); bridge.FindBlock(Arg.Any <Keccak>(), Arg.Any <bool>()).Returns(Build.A.Block.WithTotalDifficulty(0).WithTransactions(Build.A.Transaction.TestObject).TestObject); IEthModule module = new EthModule(NullLogManager.Instance, bridge); string serialized = RpcTest.TestSerializedRequest(module, "eth_getBlockByHash", TestItem.KeccakA.ToString(), "true"); Assert.AreEqual("{\"id\":\"0x43\",\"jsonrpc\":\"2.0\",\"result\":{\"number\":\"0x0\",\"hash\":\"0xa2a9f03b9493046696099d27b2612b99497aa1f392ec966716ab393c715a5bb6\",\"parentHash\":\"0xff483e972a04a9a62bb4b7d04ae403c615604e4090521ecc5bb7af67f71be09c\",\"nonce\":\"0x3e8\",\"mixHash\":\"0x2ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e2\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"transactionsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"stateRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"totalDifficulty\":\"0x0\",\"extraData\":\"0x010203\",\"size\":\"0x0\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"timestamp\":\"0xf4240\",\"transactions\":[{\"hash\":null,\"nonce\":\"0x0\",\"blockHash\":\"0xa2a9f03b9493046696099d27b2612b99497aa1f392ec966716ab393c715a5bb6\",\"blockNumber\":\"0x0\",\"transactionIndex\":\"0x0\",\"from\":null,\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\"}],\"transactionHashes\":null,\"uncles\":[]}}", serialized); }
public ResultWrapper <UInt256?> eth_getBlockTransactionCountByHash(Keccak blockHash) { Block block = _blockchainBridge.FindBlock(blockHash); if (block == null) { return(ResultWrapper <UInt256?> .Fail($"Cannot find block for hash: {blockHash}", ErrorType.NotFound, null)); } return(ResultWrapper <UInt256?> .Success((UInt256)block.Transactions.Length)); }
public static Block GetBlock(this IBlockchainBridge blockchainBridge, BlockParameter blockParameter, bool allowNulls = false, bool recoverTxSenders = false) { Block block; switch (blockParameter.Type) { case BlockParameterType.Pending: { block = blockchainBridge.FindPendingBlock(); break; } case BlockParameterType.Latest: { block = blockchainBridge.FindLatestBlock(); break; } case BlockParameterType.Earliest: { block = blockchainBridge.FindEarliestBlock(); break; } case BlockParameterType.BlockId: { if (blockParameter.BlockId == null) { throw new JsonRpcException(ErrorType.InvalidParams, $"Block number is required for {BlockParameterType.BlockId}"); } block = blockchainBridge.FindBlock(blockParameter.BlockId.Value); break; } default: throw new Exception($"{nameof(BlockParameterType)} not supported: {blockParameter.Type}"); } if (block == null && !allowNulls) { throw new JsonRpcException(ErrorType.NotFound, $"Cannot find block {blockParameter}"); } if (block != null && recoverTxSenders) { blockchainBridge.RecoverTxSenders(block); } return(block); }
public void Eth_get_balance() { IBlockchainBridge bridge = Substitute.For <IBlockchainBridge>(); bridge.FindBlock(Arg.Any <long>()).Returns(Build.A.Block.TestObject); bridge.GetAccount(Arg.Any <Address>(), Arg.Any <Keccak>()).Returns(Build.A.Account.WithBalance(1.Ether()).TestObject); bridge.Head.Returns(Build.A.BlockHeader.TestObject); IEthModule module = new EthModule(NullLogManager.Instance, bridge); string serialized = RpcTest.TestSerializedRequest(module, "eth_getBalance", TestItem.AddressA.Bytes.ToHexString(true), "0x01"); Assert.AreEqual("{\"id\":\"0x43\",\"jsonrpc\":\"2.0\",\"result\":\"0xde0b6b3a7640000\"}", serialized); }
public void Eth_get_block_by_number_empty_param() { IBlockchainBridge bridge = Substitute.For <IBlockchainBridge>(); bridge.FindBlock(Arg.Any <Keccak>(), Arg.Any <bool>()).Returns(Build.A.Block.WithTotalDifficulty(0).WithTransactions(Build.A.Transaction.TestObject).TestObject); bridge.RetrieveHeadBlock().Returns(Build.A.Block.WithTotalDifficulty(0).WithTransactions(Build.A.Transaction.TestObject).TestObject); bridge.Head.Returns(Build.A.BlockHeader.TestObject); IEthModule module = new EthModule(NullLogManager.Instance, bridge); string serialized = RpcTest.TestSerializedRequest(module, "eth_getBlockByNumber", "", "true"); Assert.AreEqual("{\"id\":\"0x43\",\"jsonrpc\":\"2.0\",\"result\":null,\"error\":{\"code\":-32602,\"message\":\"Incorrect parameters count, expected: 2, actual: 1\",\"data\":null}}", serialized); }
public void Eth_get_block_by_number_with_number_bad_number() { IBlockchainBridge bridge = Substitute.For <IBlockchainBridge>(); bridge.FindBlock(Arg.Any <UInt256>()).Returns(Build.A.Block.WithTotalDifficulty(0).WithTransactions(Build.A.Transaction.TestObject).TestObject); bridge.RetrieveHeadBlock().Returns(Build.A.Block.WithTotalDifficulty(0).WithTransactions(Build.A.Transaction.TestObject).TestObject); bridge.Head.Returns(Build.A.BlockHeader.TestObject); IEthModule module = new EthModule(new EthereumJsonSerializer(), Substitute.For <IConfigProvider>(), NullLogManager.Instance, bridge); string serialized = RpcTest.TestSerializedRequest(module, "eth_getBlockByNumber", "'0x1234567890123456789012345678901234567890123456789012345678901234567890'", "true"); Assert.AreEqual("{\"id\":67,\"jsonrpc\":\"2.0\",\"result\":null}", serialized); }
public ResultWrapper <BigInteger?> eth_getBlockTransactionCountByHash(Keccak blockHash) { try { _readerWriterLockSlim.EnterReadLock(); Block block = _blockchainBridge.FindBlock(blockHash); if (block == null) { return(ResultWrapper <BigInteger?> .Fail($"Cannot find block for hash: {blockHash}", ErrorType.NotFound, null)); } return(ResultWrapper <BigInteger?> .Success(block.Transactions.Length)); } finally { _readerWriterLockSlim.ExitReadLock(); } }
public ResultWrapper <Quantity> eth_getBlockTransactionCountByHash(Data blockHash) { var block = _blockchainBridge.FindBlock(new Keccak(blockHash.Value), false); if (block == null) { return(ResultWrapper <Quantity> .Fail($"Cannot find block for hash: {blockHash.Value}", ErrorType.NotFound)); } if (Logger.IsTrace) { Logger.Trace($"eth_getBlockTransactionCountByHash request {blockHash.ToJson()}, result: {block.Transactions.Length}"); } return(ResultWrapper <Quantity> .Success(new Quantity(block.Transactions.Length))); }
public Task <Block> FindBlockAsync(Keccak blockHash) => Task.FromResult(_blockchainBridge.FindBlock(blockHash));
private async Task <(uint confirmations, bool rejected)> VerifyDepositConfirmationsAsync(DepositDetails deposit, TxReceipt receipt, Keccak headHash) { var confirmations = 0u; var block = _blockchainBridge.FindBlock(headHash); do { if (block is null) { if (_logger.IsWarn) { _logger.Warn("Block was not found."); } return(0, false); } var confirmationTimestamp = _depositService.VerifyDeposit(deposit.Consumer, deposit.Id, block.Header); 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: '{deposit.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 (receipt.BlockHash == block.Hash || block.Number <= receipt.BlockNumber) { break; } block = _blockchainBridge.FindBlock(block.ParentHash); } while (confirmations < _requiredBlockConfirmations); var blocksDifference = _blockchainBridge.Head.Number - receipt.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: '{deposit.TransactionHash}')."); } return(confirmations, true); } return(confirmations, false); }