async def test_subscription(self): tx_hash = helpers.generate_object_hash() tx_contents = mock_eth_messages.get_dummy_transaction(1) transaction_key = self.gateway_node.get_tx_service( ).get_transaction_key(tx_hash) self.gateway_node.get_tx_service().set_transaction_contents_by_key( transaction_key, rlp.encode(tx_contents)) tx_hash_2 = helpers.generate_object_hash() tx_contents_2 = mock_eth_messages.get_dummy_transaction(2) transaction_key_2 = self.gateway_node.get_tx_service( ).get_transaction_key(tx_hash_2) self.gateway_node.get_tx_service().set_transaction_contents_by_key( transaction_key_2, rlp.encode(tx_contents_2)) await self.eth_ws_server_message_queue.put( (TX_SUB_ID, f"0x{convert.bytes_to_hex(tx_hash.binary)}")) await self.eth_ws_server_message_queue.put( (TX_SUB_ID, f"0x{convert.bytes_to_hex(tx_hash_2.binary)}")) await asyncio.sleep(0.01) self.assertEqual(2, self.subscriber.messages.qsize()) tx_message_1 = await self.subscriber.receive() self.assertEqual(f"0x{convert.bytes_to_hex(tx_hash.binary)}", tx_message_1["tx_hash"]) self.assertEqual(tx_contents.to_json(), tx_message_1["tx_contents"]) tx_message_2 = await self.subscriber.receive() self.assertEqual(f"0x{convert.bytes_to_hex(tx_hash_2.binary)}", tx_message_2["tx_hash"]) self.assertEqual(tx_contents_2.to_json(), tx_message_2["tx_contents"])
def test_block_queue_continues_after_timeout(self): block_hash_1 = helpers.generate_object_hash() block_msg_1 = create_block_message(block_hash_1) block_hash_2 = helpers.generate_object_hash() block_msg_2 = create_block_message(block_hash_2, block_hash_1) block_hash_3 = helpers.generate_object_hash() block_msg_3 = create_block_message(block_hash_3, block_hash_2) self.node.has_active_blockchain_peer = MagicMock(return_value=False) self.block_queuing_service.push(block_hash_1, block_msg_1) time.time = MagicMock(return_value=time.time() + 150) self.block_queuing_service.push(block_hash_2, block_msg_2) self.block_queuing_service.push(block_hash_3, block_msg_3) time.time = MagicMock(return_value=time.time() + TTL - 150 + 1) # too much time has elapsed for the first message self.node.has_active_blockchain_peer = MagicMock(return_value=True) self.node.alarm_queue.fire_alarms() self.assertEqual(1, len(self.node.broadcast_to_nodes_messages)) self.assertEqual(block_msg_2, self.node.broadcast_to_nodes_messages[0])
def test_block_queue_continues_after_timeout(self): block_hash_1 = helpers.generate_object_hash() block_msg_1 = helpers.create_block_message(block_hash_1) block_hash_2 = helpers.generate_object_hash() block_msg_2 = helpers.create_block_message(block_hash_2, block_hash_1) block_hash_3 = helpers.generate_object_hash() block_msg_3 = helpers.create_block_message(block_hash_3, block_hash_2) self.node.has_active_blockchain_peer = MagicMock(return_value=False) self.node.block_queuing_service_manager.push(block_hash_1, block_msg_1) time.time = MagicMock(return_value=time.time() + 150) self.node.block_queuing_service_manager.push(block_hash_2, block_msg_2) self.node.block_queuing_service_manager.push(block_hash_3, block_msg_3) time.time = MagicMock(return_value=time.time() + TTL - 150 + 1) # too much time has elapsed for the first message self.node.has_active_blockchain_peer = MagicMock(return_value=True) self.node.alarm_queue.fire_alarms() self._assert_length_of_enqueued_messages(1) self._assert_block_in_enqueued_messages_index(block_msg_2, 0)
def test_routing_message(self): origin_node_id = helpers.generate_node_id() forwarding_node_id = helpers.generate_node_id() node_id_2 = helpers.generate_node_id() node_id_3 = helpers.generate_node_id() routing_update_id = helpers.generate_object_hash() routing_update = [node_id_2, node_id_3] expected_length = (RoutingUpdateMessage.PAYLOAD_LENGTH + 2 * constants.NODE_ID_SIZE_IN_BYTES) self.get_message_preview_successfully( RoutingUpdateMessage(helpers.generate_object_hash(), "", origin_node_id, forwarding_node_id, routing_update_id, routing_update), RoutingUpdateMessage.MESSAGE_TYPE, expected_length) routing_update_message = self.create_message_successfully( RoutingUpdateMessage(helpers.generate_object_hash(), "", origin_node_id, forwarding_node_id, routing_update_id, routing_update), RoutingUpdateMessage) self.assertEqual(origin_node_id, routing_update_message.origin_node_id()) self.assertEqual(forwarding_node_id, routing_update_message.forwarding_node_id()) self.assertEqual(routing_update, routing_update_message.routing_update()) self.assertEqual(routing_update_id, routing_update_message.routing_update_id())
def blkcnfrm_message(self) -> BlockConfirmationMessage: return BlockConfirmationMessage( helpers.generate_object_hash(), self.NETWORK_NUMBER, self.NODE_ID, list(range(100, 200)), [helpers.generate_object_hash() for _ in range(100)], )
def test_msg_confirmed_tx(self): self.node.feed_manager.publish_to_feed = MagicMock() tx_hash = helpers.generate_object_hash() message = ConfirmedTxMessage(tx_hash) self.connection.msg_confirmed_tx(message) self.node.feed_manager.publish_to_feed.assert_not_called() tx_hash = helpers.generate_object_hash() message = ConfirmedTxMessage( tx_hash, rlp.encode(mock_eth_messages.get_dummy_transaction(1))) self.connection.msg_confirmed_tx(message) self.node.feed_manager.publish_to_feed.assert_called_once()
def tx_message( network_num: int = 1, source_id: str = "", short_id: int = constants.NULL_TX_SID ) -> TxMessage: return TxMessage( helpers.generate_object_hash(), network_num, source_id, short_id, helpers.generate_bytearray(250), account_id=helpers.generate_object_hash().to_string() )
async def test_transaction_status(self): time.time = MagicMock(return_value=time.time()) expected_assignment_time = datetime.datetime.fromtimestamp( time.time()).isoformat() short_id = 123 transaction_hash = helpers.generate_object_hash() transaction_contents = helpers.generate_bytearray(250) tx_service = self.gateway_node.get_tx_service() transaction_key = tx_service.get_transaction_key(transaction_hash) tx_service.set_transaction_contents_by_key(transaction_key, transaction_contents) tx_service.assign_short_id_by_key(transaction_key, short_id) result = await self.request( BxJsonRpcRequest("7", RpcRequestType.TX_STATUS, { "transaction_hash": convert.bytes_to_hex(transaction_hash.binary) })) self.assertEqual("7", result.id) self.assertIsNone(result.error) self.assertEqual( { "status": "assigned short ID", "short_ids": [123], "assignment_time": expected_assignment_time }, result.result)
def key_message(self) -> KeyMessage: return KeyMessage( helpers.generate_object_hash(), self.NETWORK_NUMBER, self.NODE_ID, helpers.generate_bytearray(32), )
async def test_connection_and_close_while_receiving_subscriptions(self): async with WsProvider(self.ws_uri) as ws: self.assertEqual(1, len(self.server._connections)) connection_handler = self.server._connections[0] self.assertTrue(ws.running) subscription_id = await ws.subscribe("newTxs") tx_contents = helpers.generate_bytes(250) raw_published_message = RawTransaction( helpers.generate_object_hash(), memoryview(tx_contents)) serialized_published_message = RawTransactionFeedEntry( raw_published_message.tx_hash, raw_published_message.tx_contents) self.gateway_node.feed_manager.publish_to_feed( "newTxs", raw_published_message) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(serialized_published_message.tx_hash, subscription_message.notification["tx_hash"]) self.assertEqual(serialized_published_message.tx_contents, subscription_message.notification["tx_contents"]) task = asyncio.create_task( ws.get_next_subscription_notification_by_id(subscription_id)) await connection_handler.close() await asyncio.sleep(0.01) exception = task.exception() self.assertIsInstance(exception, WsException)
def test_tx_stats_duplicate_full_from_relay(self): short_id = 1 tx_hash = helpers.generate_object_hash() tx_content = helpers.generate_bytearray(250) full_message = TxMessage(message_hash=tx_hash, network_num=1, short_id=short_id, tx_val=tx_content) self.relay_connection.msg_tx(full_message) self.relay_connection.msg_tx(full_message) self.assertEqual( 0, gateway_transaction_stats_service.interval_data. new_compact_transactions_received_from_relays) self.assertEqual( 0, gateway_transaction_stats_service.interval_data. duplicate_compact_transactions_received_from_relays) self.assertEqual( 1, gateway_transaction_stats_service.interval_data. new_full_transactions_received_from_relays) self.assertEqual( 1, gateway_transaction_stats_service.interval_data. duplicate_full_transactions_received_from_relays) self.assertEqual( 1, gateway_transaction_stats_service.interval_data. short_id_assignments_processed) self.assertEqual( 0, gateway_transaction_stats_service.interval_data. redundant_transaction_content_messages)
async def test_disconnect_server_reconnect(self): tx_hash = helpers.generate_object_hash() tx_contents = mock_eth_messages.get_dummy_transaction(1) self.gateway_node.get_tx_service().set_transaction_contents( tx_hash, rlp.encode(tx_contents)) self.eth_test_ws_server.close() await self.eth_test_ws_server.wait_closed() await self.eth_ws_server_message_queue.put( (TX_SUB_ID, f"0x{convert.bytes_to_hex(tx_hash.binary)}")) await asyncio.sleep(0.02) self.assertEqual(0, self.subscriber.messages.qsize()) self.assertTrue(self.eth_ws_proxy_publisher.running) self.assertFalse(self.eth_ws_proxy_publisher.connected_event.is_set()) await self.start_server() await asyncio.sleep(0.1) self.assertTrue(self.eth_ws_proxy_publisher.connected_event.is_set()) self.assertEqual(0, self.subscriber.messages.qsize()) await self.eth_ws_server_message_queue.put( (TX_SUB_ID, f"0x{convert.bytes_to_hex(tx_hash.binary)}")) await asyncio.sleep(0.01) self.assertEqual(1, self.subscriber.messages.qsize())
def test_tx_stats_multiple_new_compact_from_relay(self): tx_hash = helpers.generate_object_hash() short_id = 1 compact_message = TxMessage(message_hash=tx_hash, network_num=1, short_id=short_id) self.relay_connection.msg_tx(compact_message) short_id = 2 compact_message = TxMessage(message_hash=tx_hash, network_num=1, short_id=short_id) self.relay_connection.msg_tx(compact_message) self.assertEqual( 0, gateway_transaction_stats_service.interval_data. new_full_transactions_received_from_relays) self.assertEqual( 0, gateway_transaction_stats_service.interval_data. duplicate_full_transactions_received_from_relays) self.assertEqual( 2, gateway_transaction_stats_service.interval_data. new_compact_transactions_received_from_relays) self.assertEqual( 0, gateway_transaction_stats_service.interval_data. duplicate_compact_transactions_received_from_relays) self.assertEqual( 2, gateway_transaction_stats_service.interval_data. short_id_assignments_processed) self.assertEqual( 0, gateway_transaction_stats_service.interval_data. redundant_transaction_content_messages)
def txclnup_message(self) -> TransactionCleanupMessage: return TransactionCleanupMessage( self.NETWORK_NUMBER, self.NODE_ID, list(range(50, 150)), [helpers.generate_object_hash() for _ in range(10)], )
def test_try_send_headers_to_node_unknown_block(self): self.node.broadcast = MagicMock() result = self.block_queuing_service.try_send_headers_to_node( [self.block_hashes[0], helpers.generate_object_hash()]) self.assertFalse(result) self.node.broadcast.assert_not_called()
def test_try_send_bodies_to_node_unknown_block(self): self.node_conn.enqueue_msg.reset_mock() result = self.block_queuing_service.try_send_bodies_to_node( [self.block_hashes[0], helpers.generate_object_hash()]) self.assertFalse(result) self.node_conn.enqueue_msg.assert_not_called()
def txs_message(self) -> TxsMessage: return TxsMessage([ TransactionInfo( helpers.generate_object_hash(), helpers.generate_bytearray(250), i, ) for i in range(1, 10) ])
def broadcast_message(self) -> BroadcastMessage: return BroadcastMessage( helpers.generate_object_hash(), self.NETWORK_NUMBER, self.NODE_ID, self.BROADCAST_TYPE, False, helpers.generate_bytearray(500), )
def txblock_message(self) -> TxServiceSyncBlocksShortIdsMessage: return TxServiceSyncBlocksShortIdsMessage( self.NETWORK_NUMBER, [ BlockShortIds( helpers.generate_object_hash(), list(range(j * 10, j * 15)), ) for j in range(2, 20) ], )
def tx_message(self) -> TxMessage: return TxMessage( helpers.generate_object_hash(), self.NETWORK_NUMBER, self.NODE_ID, 50, helpers.generate_bytearray(250), TransactionFlag.PAID_TX, time.time(), )
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())
def txtxs_message(self) -> TxServiceSyncTxsMessage: return TxServiceSyncTxsMessage( self.NETWORK_NUMBER, [ TxContentShortIds( helpers.generate_object_hash(), helpers.generate_bytearray(250), [2, 3], [TransactionFlag.NO_FLAGS, TransactionFlag.PAID_TX], ) ], )
def test_msg_tx__full_message(self): tx_service = self.connection.node.get_tx_service() short_id = 1 tx_hash = helpers.generate_object_hash() tx_content = helpers.generate_bytearray(250) full_message = TxMessage(message_hash=tx_hash, network_num=1, short_id=short_id, tx_val=tx_content) self.connection.msg_tx(full_message) self.assertEqual(short_id, tx_service.get_short_id(tx_hash)) self.assertEqual(tx_content, tx_service.get_transaction_by_hash(tx_hash))
def test_empty_bytes(self): message1 = TxMessage( helpers.generate_object_hash(), 5, tx_val=helpers.generate_bytearray(250), ) message2 = TxMessage( helpers.generate_object_hash(), 5, tx_val=helpers.generate_bytearray(250), ) message3 = TxMessage( helpers.generate_object_hash(), 5, tx_val=helpers.generate_bytearray(250), ) message_length = len(message1.rawbytes()) self.output_buffer.enqueue_msgbytes(message1.rawbytes()) self.output_buffer.flush() self.output_buffer.enqueue_msgbytes(message2.rawbytes()) self.output_buffer.enqueue_msgbytes(message3.rawbytes()) self.tracker.append_message(message_length, message1) self.tracker.append_message(message_length, message2) self.tracker.append_message(message_length, message3) self.output_buffer.advance_buffer(120) self.tracker.advance_bytes(120) self.output_buffer.safe_empty() self.assertEqual(message_length - 120, self.output_buffer.length) self.tracker.empty_bytes(self.output_buffer.length) self.assertEqual(1, len(self.tracker.messages)) self.assertEqual(message_length - 120, self.tracker.bytes_remaining) self.assertEqual(120, self.tracker.messages[0].sent_bytes)
def test_msg_tx__compact_then_full(self): tx_service = self.connection.node.get_tx_service() short_id = 1 tx_hash = helpers.generate_object_hash() tx_content = helpers.generate_bytearray(250) transaction_key = tx_service.get_transaction_key(tx_hash) compact_tx_msg = TxMessage(message_hash=tx_hash, network_num=1, short_id=short_id) no_short_id_tx_msg = TxMessage(message_hash=tx_hash, network_num=1, tx_val=tx_content) self.connection.msg_tx(compact_tx_msg) self.connection.msg_tx(no_short_id_tx_msg) self.assertEqual(short_id, tx_service.get_short_id_by_key(transaction_key)) self.assertEqual(tx_content, tx_service.get_transaction_by_key(transaction_key))
async def test_disconnect_server(self): tx_hash = helpers.generate_object_hash() tx_contents = mock_eth_messages.get_dummy_transaction(1) self.gateway_node.get_tx_service().set_transaction_contents( tx_hash, rlp.encode(tx_contents) ) self.eth_test_ws_server.close() await self.eth_test_ws_server.wait_closed() await self.eth_ws_server_message_queue.put(f"0x{convert.bytes_to_hex(tx_hash.binary)}") await asyncio.sleep(0.05) self.assertEqual(0, self.subscriber.messages.qsize()) self.assertFalse(self.eth_ws_subscriber.running)
def test_empty_bytes_no_bytes_sent(self): message = TxMessage( helpers.generate_object_hash(), 5, tx_val=helpers.generate_bytearray(250), ) message_length = len(message.rawbytes()) self.output_buffer.enqueue_msgbytes(message.rawbytes()) self.output_buffer.flush() self.tracker.append_message(message_length, message) self.output_buffer.safe_empty() self.tracker.empty_bytes(self.output_buffer.length) self.assertEqual(0, self.output_buffer.length) self.assertEqual(0, self.tracker.bytes_remaining) self.assertEqual(0, len(self.tracker.messages))
def test_set_transaction_flag(self): tx_message = TxMessage(helpers.generate_object_hash(), 1, "", tx_val=helpers.generate_bytearray(250), transaction_flag=TransactionFlag.PAID_TX) tx_message.set_transaction_flag(TransactionFlag.PAID_TX | TransactionFlag.CEN_ENABLED | TransactionFlag.LOCAL_REGION | TransactionFlag.TBD_2) reserialized_message = self._serialize_deserialize_message(tx_message) self.assertTrue(TransactionFlag.CEN_ENABLED in reserialized_message.transaction_flag()) self.assertTrue(TransactionFlag.LOCAL_REGION in reserialized_message.transaction_flag()) self.assertTrue( TransactionFlag.TBD_2 in reserialized_message.transaction_flag())
def test_bdn_stats_tx_new_full_from_bdn(self): short_id = 1 tx_hash = helpers.generate_object_hash() tx_content = helpers.generate_bytearray(250) full_message = TxMessage(message_hash=tx_hash, network_num=1, short_id=short_id, tx_val=tx_content) self.relay_connection.msg_tx(full_message) self.assertEqual( 3, len(gateway_bdn_performance_stats_service.interval_data. blockchain_node_to_bdn_stats)) for stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.values( ): self.assertEqual(1, stats.new_tx_received_from_bdn)
def test_tx_stats_new_compact_from_relay(self): short_id = 321 tx_hash = helpers.generate_object_hash() compact_message = TxMessage(message_hash=tx_hash, network_num=1, short_id=short_id) self.relay_connection.msg_tx(compact_message) self.assertEqual( 0, gateway_transaction_stats_service.interval_data. new_full_transactions_received_from_relays) self.assertEqual( 1, gateway_transaction_stats_service.interval_data. new_compact_transactions_received_from_relays) self.assertEqual( 1, gateway_transaction_stats_service.interval_data. short_id_assignments_processed)