def test_msg_tx(self): self.node.feed_manager.publish_to_feed = MagicMock() self.node.opts.ws = True transaction = mock_eth_messages.get_dummy_transaction(1) transaction_hash = transaction.hash() transaction_contents = transaction.contents() messages = TransactionsEthProtocolMessage(None, [transaction]) self.sut.msg_tx(messages) # published to both feeds self.node.feed_manager.publish_to_feed.assert_has_calls( [ call( EthNewTransactionFeed.NAME, EthRawTransaction(transaction_hash, transaction_contents) ), call( EthPendingTransactionFeed.NAME, EthRawTransaction(transaction_hash, transaction_contents) ), ] ) # broadcast transactions self.assertEqual(1, len(self.node.broadcast_messages))
async def test_eth_new_tx_feed_subscribe_not_include_from_blockchain(self): self.gateway_node.feed_manager.feeds.clear() self.gateway_node.feed_manager.register_feed(EthNewTransactionFeed()) eth_tx_message = generate_new_eth_transaction() eth_transaction = EthRawTransaction(eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BDN_SOCKET) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" eth_tx_message_blockchain = generate_new_eth_transaction() eth_transaction_blockchain = EthRawTransaction( eth_tx_message_blockchain.tx_hash(), eth_tx_message_blockchain.tx_val(), FeedSource.BLOCKCHAIN_SOCKET) async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe( "newTxs", {"include_from_blockchain": False}) self.gateway_node.feed_manager.publish_to_feed( "newTxs", eth_transaction) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(expected_tx_hash, subscription_message.notification["txHash"]) self.gateway_node.feed_manager.publish_to_feed( "newTxs", eth_transaction_blockchain) with self.assertRaises(asyncio.TimeoutError): await asyncio.wait_for( ws.get_next_subscription_notification_by_id( subscription_id), 0.1)
def publish_transaction( self, tx_hash: Sha256Hash, tx_contents: memoryview ) -> None: self.node.feed_manager.publish_to_feed( EthNewTransactionFeed.NAME, EthRawTransaction(tx_hash, tx_contents) ) self.node.feed_manager.publish_to_feed( EthPendingTransactionFeed.NAME, EthRawTransaction(tx_hash, tx_contents) )
def publish_transaction(self, tx_hash: Sha256Hash, tx_contents: memoryview) -> None: transaction_feed_stats_service.log_new_transaction(tx_hash) self.node.feed_manager.publish_to_feed( EthNewTransactionFeed.NAME, EthRawTransaction(tx_hash, tx_contents, FeedSource.BLOCKCHAIN_SOCKET)) transaction_feed_stats_service.log_pending_transaction_from_local( tx_hash) self.node.feed_manager.publish_to_feed( EthPendingTransactionFeed.NAME, EthRawTransaction(tx_hash, tx_contents, FeedSource.BLOCKCHAIN_SOCKET))
async def test_eth_new_transactions_feed_default_subscribe(self): self.gateway_node.feed_manager.feeds.clear() self.gateway_node.feed_manager.register_feed(EthNewTransactionFeed()) eth_tx_message = generate_new_eth_transaction() eth_transaction = EthRawTransaction(eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BDN_SOCKET) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe("newTxs") self.gateway_node.feed_manager.publish_to_feed( "newTxs", eth_transaction) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(expected_tx_hash, subscription_message.notification["txHash"]) expected_tx_contents = get_expected_eth_tx_contents(eth_tx_message) self.assertEqual(expected_tx_contents, subscription_message.notification["txContents"])
async def test_subscribe_with_duplicates(self): self.gateway_node.feed_manager.register_feed( EthPendingTransactionFeed(self.gateway_node.alarm_queue)) eth_tx_message = generate_new_eth_transaction() eth_transaction = EthRawTransaction(eth_tx_message.tx_hash(), eth_tx_message.tx_val()) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe("pendingTxs", {"duplicates": True}) self.gateway_node.feed_manager.publish_to_feed( "pendingTxs", eth_transaction) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(expected_tx_hash, subscription_message.notification["tx_hash"]) # will publish twice self.gateway_node.feed_manager.publish_to_feed( "pendingTxs", eth_transaction) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(expected_tx_hash, subscription_message.notification["tx_hash"])
async def test_eth_pending_tx_feed_subscribe_handles_no_duplicates(self): self.gateway_node.feed_manager.register_feed( EthPendingTransactionFeed(self.gateway_node.alarm_queue)) eth_tx_message = generate_new_eth_transaction() eth_transaction = EthRawTransaction(eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BDN_SOCKET) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe("pendingTxs", {"duplicates": False}) self.gateway_node.feed_manager.publish_to_feed( "pendingTxs", eth_transaction) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(expected_tx_hash, subscription_message.notification["txHash"]) # will not publish twice self.gateway_node.feed_manager.publish_to_feed( "pendingTxs", eth_transaction) with self.assertRaises(asyncio.TimeoutError): await asyncio.wait_for( ws.get_next_subscription_notification_by_id( subscription_id), 0.1)
def publish_new_transaction(self, tx_hash: Sha256Hash, tx_contents: memoryview) -> None: gas_price = eth_common_utils.raw_tx_gas_price(tx_contents, 0) if gas_price >= self.node.get_network_min_transaction_fee(): self.node.feed_manager.publish_to_feed( EthNewTransactionFeed.NAME, EthRawTransaction(tx_hash, tx_contents, FeedSource.BDN_SOCKET))
async def test_publish_transaction_dictionary(self): subscriber = self.sut.subscribe({}) transaction_hash_str = SAMPLE_TRANSACTION_FROM_WS["hash"] transaction_hash = Sha256Hash( convert.hex_to_bytes(transaction_hash_str[2:])) self.sut.publish( EthRawTransaction(transaction_hash, SAMPLE_TRANSACTION_FROM_WS, FeedSource.BLOCKCHAIN_RPC)) received_tx = await subscriber.receive() self.assertEqual(transaction_hash_str, received_tx["tx_hash"]) self.assertEqual(transaction_hash_str, received_tx["tx_contents"]["hash"]) self.assertIn("from", received_tx["tx_contents"]) self.assertIn("gas", received_tx["tx_contents"]) self.assertIn("gas_price", received_tx["tx_contents"]) self.assertIn("input", received_tx["tx_contents"]) self.assertIn("value", received_tx["tx_contents"]) self.assertIn("to", received_tx["tx_contents"]) self.assertIn("nonce", received_tx["tx_contents"]) self.assertIn("v", received_tx["tx_contents"]) self.assertIn("r", received_tx["tx_contents"]) self.assertIn("s", received_tx["tx_contents"])
def process_transaction_with_contents(self, tx_hash: Sha256Hash, tx_contents: memoryview) -> None: transaction_feed_stats_service.log_pending_transaction_from_local( tx_hash) self.feed_manager.publish_to_feed( EthPendingTransactionFeed.NAME, EthRawTransaction(tx_hash, tx_contents, FeedSource.BLOCKCHAIN_RPC))
def generate_eth_raw_transaction_with_to_address( source: FeedSource = FeedSource.BDN_SOCKET, to_address: str = helpers.generate_bytes(eth_common_constants.ADDRESS_LEN) ) -> EthRawTransaction: transaction = get_dummy_transaction(1, to_address_str=to_address) transactions_eth_message = TransactionsEthProtocolMessage( None, [transaction]) tx_message = EthNormalMessageConverter().tx_to_bx_txs( transactions_eth_message, 5)[0][0] return EthRawTransaction(tx_message.tx_hash(), tx_message.tx_val(), source)
def test_publish_new_transaction(self): bx_tx_message, _, _ = self.node.message_converter.tx_to_bx_txs( mock_eth_messages.EIP_155_TRANSACTIONS_MESSAGE, 5)[0] self.node.feed_manager.publish_to_feed = MagicMock() self.connection.msg_tx(bx_tx_message) expected_publication = EthRawTransaction(bx_tx_message.tx_hash(), bx_tx_message.tx_val()) self.node.feed_manager.publish_to_feed.assert_called_once_with( NewTransactionFeed.NAME, expected_publication)
async def test_publish_invalid_transaction(self): subscriber = self.sut.subscribe({}) transaction_hash = helpers.generate_object_hash() transaction_contents = helpers.generate_bytearray(250) self.sut.publish( EthRawTransaction(transaction_hash, transaction_contents, FeedSource.BLOCKCHAIN_SOCKET)) self.assertEqual(0, subscriber.messages.qsize())
async def send_duplicate_tx_to_pending_txs_feed(self): eth_tx_message = generate_new_eth_transaction() eth_transaction = EthRawTransaction( eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BDN_SOCKET ) await asyncio.sleep(1) for _ in range(20): self.gateway_node.feed_manager.publish_to_feed( "pendingTxs", eth_transaction ) await asyncio.sleep(0.03)
async def send_tx_to_new_txs_feed(self, feed_source: Optional[FeedSource] = FeedSource.BDN_SOCKET): await asyncio.sleep(1) for _ in range(20): eth_tx_message = generate_new_eth_transaction() eth_transaction = EthRawTransaction( eth_tx_message.tx_hash(), eth_tx_message.tx_val(), feed_source ) self.gateway_node.feed_manager.publish_to_feed( "newTxs", eth_transaction ) await asyncio.sleep(0.03)
def process_transaction_with_parsed_contents( self, tx_hash: Sha256Hash, parsed_tx: Optional[Dict[str, Any]]) -> None: transaction_feed_stats_service.log_pending_transaction_from_local( tx_hash) if parsed_tx is None: logger.debug(log_messages.TRANSACTION_NOT_FOUND_IN_MEMPOOL, tx_hash) transaction_feed_stats_service.log_pending_transaction_missing_contents( ) else: self.feed_manager.publish_to_feed( EthPendingTransactionFeed.NAME, EthRawTransaction(tx_hash, parsed_tx))
def process_transaction_with_parsed_contents( self, tx_hash: Sha256Hash, parsed_tx: Optional[Dict[str, Any]]) -> None: transaction_feed_stats_service.log_pending_transaction_from_local( tx_hash) if parsed_tx is None: logger.debug(log_messages.TRANSACTION_NOT_FOUND_IN_MEMPOOL, tx_hash) transaction_feed_stats_service.log_pending_transaction_missing_contents( ) else: gas_price = int(parsed_tx["gasPrice"], 16) if gas_price >= self.node.get_network_min_transaction_fee(): self.feed_manager.publish_to_feed( EthPendingTransactionFeed.NAME, EthRawTransaction(tx_hash, parsed_tx, FeedSource.BLOCKCHAIN_RPC))
async def test_publish_transaction_bytes(self): subscriber = self.sut.subscribe({}) tx_message = mock_eth_messages.generate_eth_tx_message() tx_hash_str = f"0x{str(tx_message.tx_hash())}" self.sut.publish( EthRawTransaction(tx_message.tx_hash(), tx_message.tx_val(), FeedSource.BDN_SOCKET)) received_tx = await subscriber.receive() self.assertEqual(tx_hash_str, received_tx["tx_hash"]) self.assertEqual(tx_hash_str, received_tx["tx_contents"]["hash"]) self.assertIn("from", received_tx["tx_contents"]) self.assertIn("gas", received_tx["tx_contents"]) self.assertIn("gas_price", received_tx["tx_contents"]) self.assertIn("input", received_tx["tx_contents"]) self.assertIn("value", received_tx["tx_contents"]) self.assertIn("to", received_tx["tx_contents"]) self.assertIn("nonce", received_tx["tx_contents"]) self.assertIn("v", received_tx["tx_contents"]) self.assertIn("r", received_tx["tx_contents"]) self.assertIn("s", received_tx["tx_contents"])
def generate_eth_raw_transaction( source: FeedSource = FeedSource.BDN_SOCKET) -> EthRawTransaction: tx_message = generate_eth_tx_message() return EthRawTransaction(tx_message.tx_hash(), tx_message.tx_val(), source)
def publish_new_transaction(self, tx_hash: Sha256Hash, tx_contents: memoryview) -> None: self.node.feed_manager.publish_to_feed( EthNewTransactionFeed.NAME, EthRawTransaction(tx_hash, tx_contents, FeedSource.BDN_SOCKET))
def generate_eth_raw_transaction(self) -> EthRawTransaction: tx_message = self.generate_new_eth_transaction() return EthRawTransaction(tx_message.tx_hash(), tx_message.tx_val())