def init_live_feeds(self) -> None: self.feed_manager.register_feed(EthNewTransactionFeed()) self.feed_manager.register_feed( EthPendingTransactionFeed(self.alarm_queue)) self.feed_manager.register_feed(EthOnBlockFeed(self)) self.feed_manager.register_feed(EthNewBlockFeed(self)) self.feed_manager.register_feed(EthTransactionReceiptsFeed(self))
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_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 setUp(self) -> None: crypto_utils.recover_public_key = MagicMock(return_value=bytes(32)) account_model = BdnAccountModelBase( "account_id", "account_name", "fake_certificate", new_transaction_streaming=BdnServiceModelConfigBase( expire_date=date(2999, 1, 1).isoformat())) self.eth_ws_port = helpers.get_free_port() self.eth_ws_uri = f"ws://127.0.0.1:{self.eth_ws_port}" self.eth_ws_server_message_queue = asyncio.Queue() await self.start_server() gateway_opts = gateway_helpers.get_gateway_opts( 8000, eth_ws_uri=self.eth_ws_uri, ws=True) gateway_opts.set_account_options(account_model) self.gateway_node = MockGatewayNode(gateway_opts) self.gateway_node.transaction_streamer_peer = OutboundPeerModel( "127.0.0.1", 8006, node_type=NodeType.INTERNAL_GATEWAY) self.gateway_node.feed_manager.register_feed( EthPendingTransactionFeed(self.gateway_node.alarm_queue)) self.eth_ws_proxy_publisher = EthWsProxyPublisher( self.eth_ws_uri, self.gateway_node.feed_manager, self.gateway_node.get_tx_service(), self.gateway_node) self.subscriber: Subscriber[ RawTransactionFeedEntry] = self.gateway_node.feed_manager.subscribe_to_feed( FeedKey(EthPendingTransactionFeed.NAME), {}) self.assertIsNotNone(self.subscriber) await self.eth_ws_proxy_publisher.start() await asyncio.sleep(0.01) self.assertEqual(len(self.eth_ws_proxy_publisher.receiving_tasks), 2) self.assertEqual(0, self.subscriber.messages.qsize()) self.sample_transactions = { i: mock_eth_messages.get_dummy_transaction(i) for i in range(10) }
def setUp(self) -> None: self.alarm_queue = AlarmQueue() self.sut = EthPendingTransactionFeed(self.alarm_queue)
class EthPendingTransactionFeedTest(AbstractTestCase): def setUp(self) -> None: self.alarm_queue = AlarmQueue() self.sut = EthPendingTransactionFeed(self.alarm_queue) @async_test 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"]) @async_test 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_test async def test_publish_transaction_no_subscribers(self): self.sut.serialize = MagicMock(wraps=self.sut.serialize) self.sut.publish(mock_eth_messages.generate_eth_raw_transaction()) self.sut.serialize.assert_not_called() @async_test async def test_publish_transaction_duplicate_transaction(self): self.sut.subscribe({}) self.sut.serialize = MagicMock(wraps=self.sut.serialize) raw_transaction = mock_eth_messages.generate_eth_raw_transaction() self.sut.publish(raw_transaction) self.sut.publish(raw_transaction) self.sut.serialize.assert_called_once() @async_test async def test_publish_duplicate_transaction_subscriber_wants_duplicates( self): subscriber = self.sut.subscribe({"duplicates": True}) self.sut.serialize = MagicMock(wraps=self.sut.serialize) subscriber.queue = MagicMock(wraps=subscriber.queue) raw_transaction = mock_eth_messages.generate_eth_raw_transaction() self.sut.publish(raw_transaction) self.sut.serialize.assert_called_once() self.sut.serialize.reset_mock() subscriber.queue.assert_called_once() subscriber.queue.reset_mock() self.sut.publish(raw_transaction) self.sut.serialize.assert_called_once() subscriber.queue.assert_called_once() @async_test 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()) @async_test async def test_publish_transaction_filtered_transaction(self): to = "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" subscriber = self.sut.subscribe({"filters": f"to = {to}"}) self.sut.serialize = MagicMock(wraps=self.sut.serialize) subscriber.queue = MagicMock(wraps=subscriber.queue) raw_transaction = mock_eth_messages.generate_eth_raw_transaction_with_to_address( FeedSource.BLOCKCHAIN_SOCKET, "3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be") self.sut.publish(raw_transaction) received_tx = await subscriber.receive() self.assertTrue(received_tx) self.assertEqual(received_tx["tx_contents"].get("to", None), to) self.sut.serialize.assert_called_once() self.sut.serialize.reset_mock() subscriber.queue.assert_called_once() @async_test async def test_publish_transaction_denied_transaction(self): to = "0x1111111111111111111111111111111111111111" subscriber = self.sut.subscribe({"filters": f"to = {to}"}) self.sut.serialize = MagicMock(wraps=self.sut.serialize) subscriber.queue = MagicMock(wraps=subscriber.queue) raw_transaction = mock_eth_messages.generate_eth_raw_transaction_with_to_address( FeedSource.BLOCKCHAIN_SOCKET, "3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be") self.sut.publish(raw_transaction) subscriber.queue.assert_not_called() @async_test 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() @async_test async def test_validate_and_handle_filters2(self): t2 = "value > 5534673480000000000 or to = 0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" valid = self.sut.validate_filters(t2) self.assertTrue(valid) subscriber = self.sut.subscribe({"filters": t2}) subscriber.queue = MagicMock(wraps=subscriber.queue) logger.error( subscriber.validator({ "value": 10, "from": "0xbd4e113ee68bcbbf768ba1d6c7a14e003362979a" })) raw_transaction = mock_eth_messages.generate_eth_raw_transaction_with_to_address( FeedSource.BLOCKCHAIN_SOCKET, "3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be") logger.error(raw_transaction.tx_contents) self.sut.publish(raw_transaction) subscriber.queue.assert_called_once() @async_test async def test_validate_and_handle_filters3(self): t3 = "value > 5534673480000000000 or (to = 0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be or to = 0xbd4e113ee68bcbbf768ba1d6c7a14e0033629792)" valid = self.sut.validate_filters(t3) self.assertTrue(valid) subscriber = self.sut.subscribe({"filters": t3}) subscriber.queue = MagicMock(wraps=subscriber.queue) logger.error( subscriber.validator({ "value": 10, "from": "0xbd4e113ee68bcbbf768ba1d6c7a14e003362979a" })) raw_transaction = mock_eth_messages.generate_eth_raw_transaction_with_to_address( FeedSource.BLOCKCHAIN_SOCKET, "3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be") logger.error(raw_transaction.tx_contents) self.sut.publish(raw_transaction) subscriber.queue.assert_called_once() @async_test async def test_validate_and_handle_filters4(self): t3 = "to in [0x0000000000000000000000000000000000000001]" valid = self.sut.validate_filters(t3) self.assertTrue(valid) subscriber = self.sut.subscribe({"filters": t3}) subscriber.queue = MagicMock(wraps=subscriber.queue) valid = subscriber.validator({ "value": 10, "to": eth_filter_handlers.reformat_address("0x") }) self.assertFalse(valid) valid = subscriber.validator({"value": 10, "to": "0x"}) self.assertTrue(valid) t4 = "to in [0x0000000000000000000000000000000000000000]" subscriber = self.sut.subscribe({"filters": t4}) valid = subscriber.validator({ "value": 10, "to": eth_filter_handlers.reformat_address("0x") }) self.assertTrue(valid)