def test_msg_tx(self): self.node.feed_manager.publish_to_feed = MagicMock() self.node.opts.ws = True self.node.opts.transaction_validation = False 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( FeedKey(EthNewTransactionFeed.NAME), EthRawTransaction( transaction_hash, transaction_contents, FeedSource.BLOCKCHAIN_SOCKET, local_region=True ) ), call( FeedKey(EthPendingTransactionFeed.NAME), EthRawTransaction( transaction_hash, transaction_contents, FeedSource.BLOCKCHAIN_SOCKET, local_region=True ) ), ] ) # broadcast transactions self.assertEqual(1, len(self.broadcast_messages)) self.assertEqual(1, len(self.broadcast_to_node_messages))
async def test_eth_pending_transactions_feed_subscribe_filters4(self): self.gateway_node.feed_manager.feeds.clear() self.gateway_node.feed_manager.register_feed( EthPendingTransactionFeed(self.gateway_node.alarm_queue) ) to = "0x" eth_tx_message = generate_new_eth_with_to_transaction(to[2:]) eth_transaction = EthRawTransaction( eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BLOCKCHAIN_SOCKET, local_region=True ) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" logger.error(expected_tx_hash) to2 = "0x0000000000000000000000000000000000000000" eth_tx_message2 = generate_new_eth_with_to_transaction(to2[2:]) eth_transaction2 = EthRawTransaction( eth_tx_message2.tx_hash(), eth_tx_message2.tx_val(), FeedSource.BLOCKCHAIN_SOCKET, local_region=True ) expected_tx_hash2 = f"0x{str(eth_transaction2.tx_hash)}" logger.error(expected_tx_hash2) async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe( "pendingTxs", options={ "filters": f"to in [0x0000000000000000000000000000000000000000]" }, ) self.gateway_node.feed_manager.publish_to_feed( FeedKey("pendingTxs"), eth_transaction ) self.gateway_node.feed_manager.publish_to_feed( FeedKey("pendingTxs"), eth_transaction2 ) 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"] ) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id ) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual( expected_tx_hash2, subscription_message.notification["txHash"] )
async def test_eth_new_transactions_feed_subscribe_filters(self): self.gateway_node.feed_manager.feeds.clear() self.gateway_node.feed_manager.register_feed(EthNewTransactionFeed()) to = "0x1111111111111111111111111111111111111111" eth_tx_message = generate_new_eth_with_to_transaction(to[2:]) eth_transaction = EthRawTransaction(eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BLOCKCHAIN_SOCKET, local_region=True) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" logger.error(expected_tx_hash) async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe( "newTxs", options={"filters": f"to = {to} or to = aaaa"}) self.gateway_node.feed_manager.publish_to_feed( FeedKey("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"])
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, local_region=True)
def msg_confirmed_tx(self, msg: ConfirmedTxMessage) -> None: tx_hash = msg.tx_hash() transaction_key = self.node.get_tx_service().get_transaction_key( tx_hash) tx_contents = msg.tx_val() # shouldn't ever happen, but just in case if tx_contents == ConfirmedTxMessage.EMPTY_TX_VAL: tx_contents = cast( Optional[memoryview], self.node.get_tx_service().get_transaction_by_key( transaction_key)) if tx_contents is None: transaction_feed_stats_service.log_pending_transaction_missing_contents( ) return self.node.feed_manager.publish_to_feed( FeedKey(EthPendingTransactionFeed.NAME), EthRawTransaction(tx_hash, tx_contents, FeedSource.BDN_SOCKET, local_region=True)) transaction_feed_stats_service.log_pending_transaction_from_internal( tx_hash)
async def test_eth_pending_tx_feed_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(), FeedSource.BDN_SOCKET, local_region=True) 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( FeedKey("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 publish twice self.gateway_node.feed_manager.publish_to_feed( FeedKey("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"])
async def test_eth_new_tx_feed_subscribe_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.BLOCKCHAIN_SOCKET, local_region=True) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe( "newTxs", {"include_from_blockchain": True}) self.gateway_node.feed_manager.publish_to_feed( FeedKey("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"]) self.assertTrue(subscription_message.notification["localRegion"])
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, local_region=True)) 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"])
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, local_region=True)) 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 publish_transaction(self, tx_hash: Sha256Hash, tx_contents: memoryview, local_region: bool = True) -> None: transaction_feed_stats_service.log_new_transaction(tx_hash) self.node.feed_manager.publish_to_feed( FeedKey(EthNewTransactionFeed.NAME), EthRawTransaction(tx_hash, tx_contents, FeedSource.BLOCKCHAIN_SOCKET, local_region=local_region)) transaction_feed_stats_service.log_pending_transaction_from_local( tx_hash) self.node.feed_manager.publish_to_feed( FeedKey(EthPendingTransactionFeed.NAME), EthRawTransaction(tx_hash, tx_contents, FeedSource.BLOCKCHAIN_SOCKET, local_region=local_region))
def publish_new_transaction(self, tx_hash: Sha256Hash, tx_contents: memoryview, local_region: bool) -> 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( FeedKey(EthNewTransactionFeed.NAME), EthRawTransaction(tx_hash, tx_contents, FeedSource.BDN_SOCKET, local_region=local_region))
def process_transaction_with_contents(self, transaction_key: TransactionKey, tx_contents: memoryview) -> None: transaction_feed_stats_service.log_pending_transaction_from_local( transaction_key.transaction_hash) self.feed_manager.publish_to_feed( FeedKey(EthPendingTransactionFeed.NAME), EthRawTransaction(transaction_key.transaction_hash, tx_contents, FeedSource.BLOCKCHAIN_RPC, local_region=True))
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, local_region=True ) 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, local_region=True ) 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(FeedKey("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( FeedKey("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 test_publish_new_tx_from_different_location(self): # relay from different region bx_tx_message_2 = self._convert_to_bx_message( mock_eth_messages.EIP_155_TRANSACTIONS_MESSAGE) self.node.feed_manager.publish_to_feed = MagicMock() self.relay_connection_2.msg_tx(bx_tx_message_2) expected_publication = EthRawTransaction(bx_tx_message_2.tx_hash(), bx_tx_message_2.tx_val(), FeedSource.BDN_SOCKET, local_region=False) self.node.feed_manager.publish_to_feed.assert_called_once_with( FeedKey(NewTransactionFeed.NAME), expected_publication)
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, local_region=True)
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, local_region=True)) self.assertEqual(0, subscriber.messages.qsize())
def test_publish_new_transaction(self): bx_tx_message = self._convert_to_bx_message( mock_eth_messages.EIP_155_TRANSACTIONS_MESSAGE) bx_tx_message.set_transaction_flag(TransactionFlag.LOCAL_REGION) self.node.feed_manager.publish_to_feed = MagicMock() self.relay_connection_1.msg_tx(bx_tx_message) expected_publication = EthRawTransaction(bx_tx_message.tx_hash(), bx_tx_message.tx_val(), FeedSource.BDN_SOCKET, local_region=True) self.node.feed_manager.publish_to_feed.assert_called_once_with( FeedKey(NewTransactionFeed.NAME), expected_publication)
async def test_validate_and_handle_filters1(self): t1 = "to == dai or to == eth" valid = self.sut.validate_filters(t1) self.assertTrue(valid) subscriber = self.sut.subscribe({"filters": t1}) subscriber.queue = MagicMock(wraps=subscriber.queue) 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, local_region=True)) subscriber.queue.assert_not_called()
def process_transaction_with_parsed_contents( self, transaction_key: TransactionKey, parsed_tx: Optional[Dict[str, Any]] ) -> None: transaction_feed_stats_service.log_pending_transaction_from_local(transaction_key.transaction_hash) if parsed_tx is None: logger.debug(log_messages.TRANSACTION_NOT_FOUND_IN_MEMPOOL, transaction_key.transaction_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( FeedKey(EthPendingTransactionFeed.NAME), EthRawTransaction( transaction_key.transaction_hash, parsed_tx, FeedSource.BLOCKCHAIN_RPC, local_region=True, ) )