class GatewayTransactionStatsServiceTest(AbstractTestCase):
    def setUp(self):
        self.node = MockGatewayNode(
            gateway_helpers.get_gateway_opts(8000,
                                             include_default_btc_args=True,
                                             include_default_eth_args=True))

        self.relay_connection = AbstractRelayConnection(
            MockSocketConnection(node=self.node,
                                 ip_address="127.0.0.1",
                                 port=12345), self.node)
        self.blockchain_connection = EthBaseConnection(
            MockSocketConnection(node=self.node,
                                 ip_address="127.0.0.1",
                                 port=12345), self.node)
        self.node.message_converter = converter_factory.create_eth_message_converter(
            self.node.opts)

        dummy_private_key = crypto_utils.make_private_key(
            helpers.generate_bytearray(111))
        dummy_public_key = crypto_utils.private_to_public_key(
            dummy_private_key)
        self.blockchain_connection_protocol = EthNodeConnectionProtocol(
            self.blockchain_connection, True, dummy_private_key,
            dummy_public_key)
        self.blockchain_connection.network_num = 0
        self.blockchain_connection_protocol.publish_transaction = MagicMock()

        self.relay_connection.state = ConnectionState.INITIALIZED
        gateway_transaction_stats_service.set_node(self.node)

    def test_tx_stats_new_full_from_relay(self):
        short_id = 123
        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(
            1, gateway_transaction_stats_service.interval_data.
            new_full_transactions_received_from_relays)
        self.assertEqual(
            0, 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)

    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)

    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)

    def test_tx_stats_duplicate_compact_from_relay(self):
        short_id = 1
        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.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(
            1, gateway_transaction_stats_service.interval_data.
            new_compact_transactions_received_from_relays)
        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            duplicate_compact_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)

    def test_tx_stats_duplicate_compact_after_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)
        compact_message = TxMessage(message_hash=tx_hash,
                                    network_num=1,
                                    short_id=short_id)

        self.relay_connection.msg_tx(full_message)
        self.relay_connection.msg_tx(compact_message)

        self.assertEqual(
            1, 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(
            0, gateway_transaction_stats_service.interval_data.
            new_compact_transactions_received_from_relays)
        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            duplicate_compact_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)

    def test_tx_stats_new_full_after_new_compact_from_relay(self):
        short_id = 1
        tx_hash = helpers.generate_object_hash()
        tx_content = helpers.generate_bytearray(250)

        compact_message = TxMessage(message_hash=tx_hash,
                                    network_num=1,
                                    short_id=short_id)
        full_message = TxMessage(message_hash=tx_hash,
                                 network_num=1,
                                 short_id=short_id,
                                 tx_val=tx_content)

        self.relay_connection.msg_tx(compact_message)
        self.relay_connection.msg_tx(full_message)

        self.assertEqual(
            1, 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(
            1, 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.
            short_id_assignments_processed)
        self.assertEqual(
            0, gateway_transaction_stats_service.interval_data.
            redundant_transaction_content_messages)

    def test_tx_stats_redundant_tx_contents_from_relay(self):
        tx_hash = helpers.generate_object_hash()
        tx_content = helpers.generate_bytearray(250)

        short_id = 1
        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)

        short_id = 2
        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(
            2, 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(
            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(
            2, gateway_transaction_stats_service.interval_data.
            short_id_assignments_processed)
        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            redundant_transaction_content_messages)

    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 test_tx_stats_new_from_blockchain_node(self):
        txs = [
            mock_eth_messages.get_dummy_transaction(1),
        ]
        tx_msg = TransactionsEthProtocolMessage(None, txs)

        self.blockchain_connection_protocol.msg_tx(tx_msg)

        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            new_transactions_received_from_blockchain)
        self.assertEqual(
            0, gateway_transaction_stats_service.interval_data.
            duplicate_transactions_received_from_blockchain)

    def test_tx_stats_duplicate_from_blockchain_node(self):
        txs = [
            mock_eth_messages.get_dummy_transaction(7),
        ]
        tx_msg = TransactionsEthProtocolMessage(None, txs)

        self.blockchain_connection_protocol.msg_tx(tx_msg)
        self.blockchain_connection_protocol.msg_tx(tx_msg)

        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            new_transactions_received_from_blockchain)
        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            duplicate_transactions_received_from_blockchain)

    def test_tx_stats_new_full_relay_duplicate_blockchain_node(self):
        blockchain_node_txs = [
            mock_eth_messages.get_dummy_transaction(7),
        ]
        blockchain_node_tx_msg = TransactionsEthProtocolMessage(
            None, blockchain_node_txs)
        bx_tx_message = self.node.message_converter.tx_to_bx_txs(
            blockchain_node_tx_msg, 1)
        for (msg, tx_hash, tx_bytes) in bx_tx_message:
            relay_full_message = TxMessage(message_hash=tx_hash,
                                           network_num=1,
                                           short_id=1,
                                           tx_val=tx_bytes)
            self.relay_connection.msg_tx(relay_full_message)

        self.blockchain_connection_protocol.msg_tx(blockchain_node_tx_msg)

        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            new_full_transactions_received_from_relays)
        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            short_id_assignments_processed)
        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            duplicate_transactions_received_from_blockchain)

    def test_tx_stats_new_compact_relay_new_blockchain_node(self):
        blockchain_node_txs = [
            mock_eth_messages.get_dummy_transaction(7),
        ]
        blockchain_node_tx_msg = TransactionsEthProtocolMessage(
            None, blockchain_node_txs)
        bx_tx_message = self.node.message_converter.tx_to_bx_txs(
            blockchain_node_tx_msg, 1)
        for (msg, tx_hash, tx_bytes) in bx_tx_message:
            relay_compact_message = TxMessage(message_hash=tx_hash,
                                              network_num=1,
                                              short_id=1)
            self.relay_connection.msg_tx(relay_compact_message)

        self.blockchain_connection_protocol.msg_tx(blockchain_node_tx_msg)

        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)
        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            new_transactions_received_from_blockchain)

    def test_tx_stats_new_blockchain_node_redundant_full_relay(self):
        blockchain_node_txs = [
            mock_eth_messages.get_dummy_transaction(7),
        ]
        blockchain_node_tx_msg = TransactionsEthProtocolMessage(
            None, blockchain_node_txs)

        self.blockchain_connection_protocol.msg_tx(blockchain_node_tx_msg)

        time.time = MagicMock(return_value=time.time() + 1)
        self.node.alarm_queue.fire_alarms()

        bx_tx_message = self.node.message_converter.tx_to_bx_txs(
            blockchain_node_tx_msg, 1)
        for (msg, tx_hash, tx_bytes) in bx_tx_message:
            relay_full_message = TxMessage(message_hash=tx_hash,
                                           network_num=1,
                                           short_id=1,
                                           tx_val=tx_bytes)
            self.relay_connection.msg_tx(relay_full_message)

        self.assertEqual(
            1, 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(
            1, gateway_transaction_stats_service.interval_data.
            new_transactions_received_from_blockchain)
        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            short_id_assignments_processed)
        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            redundant_transaction_content_messages)

    def test_tx_stats_new_blockchain_node_new_compact_relay(self):
        blockchain_node_txs = [
            mock_eth_messages.get_dummy_transaction(7),
        ]
        blockchain_node_tx_msg = TransactionsEthProtocolMessage(
            None, blockchain_node_txs)

        self.blockchain_connection_protocol.msg_tx(blockchain_node_tx_msg)

        bx_tx_message = self.node.message_converter.tx_to_bx_txs(
            blockchain_node_tx_msg, 1)
        for (msg, tx_hash, tx_bytes) in bx_tx_message:
            relay_compact_message = TxMessage(message_hash=tx_hash,
                                              network_num=1,
                                              short_id=1)
            self.relay_connection.msg_tx(relay_compact_message)

        self.assertEqual(
            1, gateway_transaction_stats_service.interval_data.
            new_transactions_received_from_blockchain)
        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)
        self.assertEqual(
            0, gateway_transaction_stats_service.interval_data.
            redundant_transaction_content_messages)
class AbstractRelayConnectionTest(AbstractTestCase):
    def setUp(self):
        self.node = MockGatewayNode(
            gateway_helpers.get_gateway_opts(8000,
                                             include_default_btc_args=True,
                                             include_default_eth_args=True))

        self.connection = AbstractRelayConnection(
            MockSocketConnection(node=self.node,
                                 ip_address="127.0.0.1",
                                 port=12345), self.node)
        self.connection.state = ConnectionState.INITIALIZED

        self.blockchain_connecton = AbstractGatewayBlockchainConnection(
            MockSocketConnection(node=self.node,
                                 ip_address="127.0.0.1",
                                 port=333), self.node)
        self.blockchain_connecton.state = ConnectionState.ESTABLISHED

        self.node.node_conn = self.blockchain_connecton

    @patch(
        "bxgateway.services.block_processing_service.BlockProcessingService._handle_decrypted_block"
    )
    def test_msg_broadcast_encrypted(self, mock_handle_decrypted_block):
        msg_bytes = helpers.generate_bytearray(50)
        msg_hash = Sha256Hash(crypto.double_sha256(msg_bytes))

        broadcast_msg = BroadcastMessage(message_hash=msg_hash,
                                         network_num=1,
                                         is_encrypted=True,
                                         blob=msg_bytes)

        self.connection.msg_broadcast(broadcast_msg)

        self.assertTrue(
            self.node.in_progress_blocks.has_ciphertext_for_hash(msg_hash))
        self.assertEqual(1, len(self.node.broadcast_messages))
        self.assertIsInstance(self.node.broadcast_messages[0][0],
                              BlockReceivedMessage)
        mock_handle_decrypted_block.assert_not_called()

    @patch(
        "bxgateway.services.block_processing_service.BlockProcessingService._handle_decrypted_block"
    )
    def test_msg_broadcast_unencrypted(self, mock_handle_decrypted_block):
        msg_bytes = helpers.generate_bytearray(50)
        msg_hash = Sha256Hash(crypto.double_sha256(msg_bytes))

        broadcast_msg = BroadcastMessage(message_hash=msg_hash,
                                         network_num=1,
                                         is_encrypted=False,
                                         blob=msg_bytes)

        self.connection.msg_broadcast(broadcast_msg)

        self.assertFalse(
            self.node.in_progress_blocks.has_ciphertext_for_hash(msg_hash))
        self.assertEqual(0, len(self.node.broadcast_messages))

        mock_handle_decrypted_block.assert_called_once()

    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_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)

        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(tx_hash))
        self.assertEqual(tx_content,
                         tx_service.get_transaction_by_hash(tx_hash))

    def test_ping_pong(self):
        hello_msg = HelloMessage(
            protocol_version=protocol_version.PROTOCOL_VERSION, network_num=1)
        self.connection.add_received_bytes(hello_msg.rawbytes())
        self.connection.process_message()

        hello_msg_bytes = self.connection.get_bytes_to_send()
        self.assertTrue(len(hello_msg_bytes) > 0)
        self.connection.advance_sent_bytes(len(hello_msg_bytes))

        ack_msg = AckMessage()
        self.connection.add_received_bytes(ack_msg.rawbytes())
        self.connection.process_message()

        ack_msg_bytes = self.connection.get_bytes_to_send()
        self.assertTrue(len(ack_msg_bytes) > 0)
        self.connection.advance_sent_bytes(len(ack_msg_bytes))

        ping_msg = PingMessage(nonce=12345)
        self.connection.add_received_bytes(ping_msg.rawbytes())
        self.connection.process_message()

        pong_msg_bytes = self.connection.get_bytes_to_send()
        self.assertTrue(len(pong_msg_bytes) > 0)

        msg_type, payload_len = AbstractBloxrouteMessage.unpack(
            pong_msg_bytes[:AbstractBloxrouteMessage.HEADER_LENGTH])
        self.assertEqual(BloxrouteMessageType.PONG, msg_type)
        self.connection.advance_sent_bytes(len(pong_msg_bytes))

        time.time = MagicMock(return_value=time.time() +
                              constants.PING_INTERVAL_S)
        self.node.alarm_queue.fire_alarms()

        ping_msg_bytes = self.connection.get_bytes_to_send()
        self.assertTrue(len(ping_msg_bytes) > 0)
        msg_type, payload_len = AbstractBloxrouteMessage.unpack(
            ping_msg_bytes[:AbstractBloxrouteMessage.HEADER_LENGTH])
        self.assertEqual(BloxrouteMessageType.PING, msg_type)

    @patch(
        "bxgateway.connections.abstract_relay_connection.AbstractRelayConnection.log"
    )
    def test_msg_notification(self, log):
        args_list = [
            "10",
            str(QuotaType.FREE_DAILY_QUOTA.value),
            str(EntityType.TRANSACTION.value), "100"
        ]
        args = ",".join(args_list)
        notification_msg = NotificationMessage(
            NotificationCode.QUOTA_FILL_STATUS, args)
        log.assert_not_called()
        self.connection.msg_notify(notification_msg)
        log.assert_called_once()
예제 #3
0
class GatewayBdnPerformanceStatsTest(AbstractTestCase):
    def setUp(self):
        self.node = MockGatewayNode(gateway_helpers.get_gateway_opts(
            8000, include_default_eth_args=True, use_extensions=True),
                                    block_queueing_cls=MagicMock())
        self.node.message_converter = converter_factory.create_eth_message_converter(
            self.node.opts)
        self.node.block_processing_service = BlockProcessingService(self.node)

        is_handshake_initiator = True
        dummy_private_key = crypto_utils.make_private_key(
            helpers.generate_bytearray(111))
        dummy_public_key = crypto_utils.private_to_public_key(
            dummy_private_key)
        rlpx_cipher = RLPxCipher(is_handshake_initiator, dummy_private_key,
                                 dummy_public_key)

        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE,
                                              MagicMock())
        local_ip = "127.0.0.1"
        eth_port = 30303
        eth_opts = gateway_helpers.get_gateway_opts(
            1234,
            include_default_eth_args=True,
            blockchain_address=(local_ip, eth_port),
            pub_key=convert.bytes_to_hex(dummy_public_key))
        self.eth_node = EthGatewayNode(eth_opts, node_ssl_service)
        self.blockchain_connection = EthNodeConnection(
            MockSocketConnection(1,
                                 node=self.node,
                                 ip_address=local_ip,
                                 port=30303), self.node)
        self.blockchain_connection.on_connection_established()
        self.node.connection_pool.add(19, local_ip, eth_port,
                                      self.blockchain_connection)

        self.blockchain_connection_1 = EthNodeConnection(
            MockSocketConnection(1,
                                 node=self.node,
                                 ip_address=local_ip,
                                 port=333), self.node)
        self.blockchain_connection_1.on_connection_established()
        self.node.mock_add_blockchain_peer(self.blockchain_connection_1)
        self.node_1_endpoint = IpEndpoint(local_ip, 333)
        self.node.connection_pool.add(20, self.node_1_endpoint.ip_address,
                                      self.node_1_endpoint.port,
                                      self.blockchain_connection_1)

        self.blockchain_connection_2 = EthNodeConnection(
            MockSocketConnection(1,
                                 node=self.node,
                                 ip_address=local_ip,
                                 port=444), self.node)
        self.blockchain_connection_2.on_connection_established()
        self.node.mock_add_blockchain_peer(self.blockchain_connection_2)
        self.node_2_endpoint = IpEndpoint(local_ip, 444)
        self.node.connection_pool.add(21, self.node_2_endpoint.ip_address,
                                      self.node_2_endpoint.port,
                                      self.blockchain_connection_2)

        self.blockchain_connection_1.network_num = 0

        self.tx_blockchain_connection_protocol = EthNodeConnectionProtocol(
            self.blockchain_connection_1, is_handshake_initiator, rlpx_cipher)
        self.block_blockchain_connection_protocol = EthNodeConnectionProtocol(
            self.blockchain_connection_1, is_handshake_initiator, rlpx_cipher)
        self.tx_blockchain_connection_protocol.publish_transaction = MagicMock(
        )
        self.block_blockchain_connection_protocol.publish_transaction = MagicMock(
        )

        self.tx_blockchain_connection_protocol_2 = EthNodeConnectionProtocol(
            self.blockchain_connection_2, is_handshake_initiator, rlpx_cipher)
        self.block_blockchain_connection_protocol_2 = EthNodeConnectionProtocol(
            self.blockchain_connection_2, is_handshake_initiator, rlpx_cipher)
        self.tx_blockchain_connection_protocol_2.publish_transaction = MagicMock(
        )
        self.block_blockchain_connection_protocol_2.publish_transaction = MagicMock(
        )

        self.relay_connection = AbstractRelayConnection(
            MockSocketConnection(1,
                                 node=self.node,
                                 ip_address=local_ip,
                                 port=12345), self.node)
        self.relay_connection.state = ConnectionState.INITIALIZED

        gateway_bdn_performance_stats_service.set_node(self.node)
        self.node.account_id = "12345"

    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_bdn_stats_tx_new_full_from_bdn_ignore_duplicate(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(
            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_bdn_stats_tx_new_from_node_low_fee(self):
        self.node.opts.blockchain_networks[
            self.node.network_num].min_tx_network_fee = 500
        blockchain_network = self.tx_blockchain_connection_protocol.connection.node.get_blockchain_network(
        )
        blockchain_network.protocol = "ethereum"

        txs = [
            mock_eth_messages.get_dummy_transaction(1, gas_price=5),
        ]

        tx_msg = TransactionsEthProtocolMessage(None, txs)
        self.assertEqual(1, len(tx_msg.get_transactions()))
        self.tx_blockchain_connection_protocol.msg_tx(tx_msg)

        self.assertEqual(
            3,
            len(gateway_bdn_performance_stats_service.interval_data.
                blockchain_node_to_bdn_stats))
        node_1_stats = gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats[
            self.node_1_endpoint]
        for endpoint, stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.items(
        ):
            if endpoint == self.node_1_endpoint:
                continue
            self.assertEqual(0, stats.new_tx_received_from_bdn)

        self.assertEqual(0, node_1_stats.new_tx_received_from_blockchain_node)
        self.assertEqual(
            1, node_1_stats.new_tx_received_from_blockchain_node_low_fee)

    def test_bdn_stats_tx_new_from_node(self):
        txs = [
            mock_eth_messages.get_dummy_transaction(1),
        ]
        tx_msg = TransactionsEthProtocolMessage(None, txs)

        self.tx_blockchain_connection_protocol.msg_tx(tx_msg)

        self.assertEqual(
            3,
            len(gateway_bdn_performance_stats_service.interval_data.
                blockchain_node_to_bdn_stats))
        node_1_stats = gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats[
            self.node_1_endpoint]
        for endpoint, stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.items(
        ):
            if endpoint == self.node_1_endpoint:
                continue
            self.assertEqual(1, stats.new_tx_received_from_bdn)

        self.assertEqual(1, node_1_stats.new_tx_received_from_blockchain_node)

    def test_bdn_stats_tx_new_from_node_ignore_duplicate(self):
        txs = [
            mock_eth_messages.get_dummy_transaction(1),
        ]
        tx_msg = TransactionsEthProtocolMessage(None, txs)

        self.tx_blockchain_connection_protocol.msg_tx(tx_msg)
        self.tx_blockchain_connection_protocol.msg_tx(tx_msg)

        self.assertEqual(
            3,
            len(gateway_bdn_performance_stats_service.interval_data.
                blockchain_node_to_bdn_stats))
        node_1_stats = gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats[
            self.node_1_endpoint]
        for endpoint, stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.items(
        ):
            if endpoint == self.node_1_endpoint:
                continue
            self.assertEqual(1, stats.new_tx_received_from_bdn)

        self.assertEqual(1, node_1_stats.new_tx_received_from_blockchain_node)

    def test_bdn_stats_tx_new_from_node_ignore_duplicate_from_second_node(
            self):
        txs = [
            mock_eth_messages.get_dummy_transaction(1),
        ]
        tx_msg = TransactionsEthProtocolMessage(None, txs)

        self.tx_blockchain_connection_protocol.msg_tx(tx_msg)
        self.tx_blockchain_connection_protocol_2.msg_tx(tx_msg)

        self.assertEqual(
            3,
            len(gateway_bdn_performance_stats_service.interval_data.
                blockchain_node_to_bdn_stats))
        node_1_stats = gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats[
            self.node_1_endpoint]
        for endpoint, stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.items(
        ):
            if endpoint == self.node_1_endpoint:
                continue
            self.assertEqual(1, stats.new_tx_received_from_bdn)

        self.assertEqual(1, node_1_stats.new_tx_received_from_blockchain_node)

    def test_bdn_stats_tx_new_full_from_bdn_ignore_from_node(self):
        blockchain_node_txs = [
            mock_eth_messages.get_dummy_transaction(7),
        ]
        blockchain_node_tx_msg = TransactionsEthProtocolMessage(
            None, blockchain_node_txs)
        bx_tx_message = self.node.message_converter.tx_to_bx_txs(
            blockchain_node_tx_msg, 1)
        for (msg, tx_hash, tx_bytes) in bx_tx_message:
            relay_full_message = TxMessage(message_hash=tx_hash,
                                           network_num=1,
                                           short_id=1,
                                           tx_val=tx_bytes)
            self.relay_connection.msg_tx(relay_full_message)

        self.tx_blockchain_connection_protocol.msg_tx(blockchain_node_tx_msg)

        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)
            self.assertEqual(0, stats.new_tx_received_from_blockchain_node)

    def test_bdn_stats_tx_new_from_node_ignore_from_bdn(self):
        blockchain_node_txs = [
            mock_eth_messages.get_dummy_transaction(7),
        ]
        blockchain_node_tx_msg = TransactionsEthProtocolMessage(
            None, blockchain_node_txs)

        self.tx_blockchain_connection_protocol.msg_tx(blockchain_node_tx_msg)
        time.time = MagicMock(return_value=time.time() + 1)
        self.node.alarm_queue.fire_alarms()
        bx_tx_message = self.node.message_converter.tx_to_bx_txs(
            blockchain_node_tx_msg, 1)
        for (msg, tx_hash, tx_bytes) in bx_tx_message:
            relay_full_message = TxMessage(message_hash=tx_hash,
                                           network_num=1,
                                           short_id=1,
                                           tx_val=tx_bytes)
            self.relay_connection.msg_tx(relay_full_message)

        self.assertEqual(
            3,
            len(gateway_bdn_performance_stats_service.interval_data.
                blockchain_node_to_bdn_stats))
        node_1_stats = gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats[
            self.node_1_endpoint]
        for endpoint, stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.items(
        ):
            if endpoint == self.node_1_endpoint:
                continue
            self.assertEqual(1, stats.new_tx_received_from_bdn)
            self.assertEqual(0, stats.new_tx_received_from_blockchain_node)
        self.assertEqual(1, node_1_stats.new_tx_received_from_blockchain_node)
        self.assertEqual(0, node_1_stats.new_tx_received_from_bdn)

    def test_bdn_stats_tx_ignore_new_compact_from_bdn_log_new_from_node(self):
        blockchain_node_txs = [
            mock_eth_messages.get_dummy_transaction(7),
        ]
        blockchain_node_tx_msg = TransactionsEthProtocolMessage(
            None, blockchain_node_txs)
        bx_tx_message = self.node.message_converter.tx_to_bx_txs(
            blockchain_node_tx_msg, 1)
        for (msg, tx_hash, tx_bytes) in bx_tx_message:
            relay_compact_message = TxMessage(message_hash=tx_hash,
                                              network_num=1,
                                              short_id=1)
            self.relay_connection.msg_tx(relay_compact_message)

        self.tx_blockchain_connection_protocol.msg_tx(blockchain_node_tx_msg)

        self.assertEqual(
            3,
            len(gateway_bdn_performance_stats_service.interval_data.
                blockchain_node_to_bdn_stats))
        node_1_stats = gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats[
            self.node_1_endpoint]
        for endpoint, stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.items(
        ):
            if endpoint == self.node_1_endpoint:
                continue
            self.assertEqual(1, stats.new_tx_received_from_bdn)

        self.assertEqual(1, node_1_stats.new_tx_received_from_blockchain_node)
        self.assertEqual(0, node_1_stats.new_tx_received_from_bdn)

    def test_bdn_stats_block_new_from_node(self):
        block_msg = NewBlockEthProtocolMessage(
            None,
            _block_with_timestamp(
                time.time() + 1 -
                self.node.opts.blockchain_ignore_block_interval_count *
                self.node.opts.blockchain_block_interval), 10)
        block_msg.serialize()
        self.block_blockchain_connection_protocol.msg_block(block_msg)

        self.assertEqual(
            3,
            len(gateway_bdn_performance_stats_service.interval_data.
                blockchain_node_to_bdn_stats))
        node_1_stats = gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats[
            self.node_1_endpoint]
        for endpoint, stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.items(
        ):
            if endpoint == self.node_1_endpoint:
                continue
            self.assertEqual(1, stats.new_blocks_received_from_bdn)

        self.assertEqual(1,
                         node_1_stats.new_blocks_received_from_blockchain_node)

    def test_bdn_stats_block_new_from_node_ignore_duplicate(self):
        block_msg = NewBlockEthProtocolMessage(
            None,
            _block_with_timestamp(
                time.time() + 1 -
                self.node.opts.blockchain_ignore_block_interval_count *
                self.node.opts.blockchain_block_interval), 10)
        block_msg.serialize()
        self.block_blockchain_connection_protocol.msg_block(block_msg)
        self.block_blockchain_connection_protocol.msg_block(block_msg)

        self.assertEqual(
            3,
            len(gateway_bdn_performance_stats_service.interval_data.
                blockchain_node_to_bdn_stats))
        node_1_stats = gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats[
            self.node_1_endpoint]
        for endpoint, stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.items(
        ):
            if endpoint == self.node_1_endpoint:
                continue
            self.assertEqual(1, stats.new_blocks_received_from_bdn)

        self.assertEqual(1,
                         node_1_stats.new_blocks_received_from_blockchain_node)

    def test_bdn_stats_block_new_from_bdn(self):
        block_msg = mock_eth_messages.new_block_eth_protocol_message(21, 1017)
        internal_new_block_msg = InternalEthBlockInfo.from_new_block_msg(
            block_msg)
        msg_bytes, block_info = self.node.message_converter.block_to_bx_block(
            internal_new_block_msg, self.node._tx_service, True,
            self.node.network.min_tx_age_seconds)
        msg_hash = Sha256Hash(crypto.double_sha256(msg_bytes))

        broadcast_msg = BroadcastMessage(message_hash=msg_hash,
                                         network_num=1,
                                         is_encrypted=False,
                                         blob=msg_bytes)
        self.relay_connection.msg_broadcast(broadcast_msg)

        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_blocks_received_from_bdn)

    def test_bdn_stats_block_new_from_bdn_ignore_duplicate(self):
        block_msg = mock_eth_messages.new_block_eth_protocol_message(21, 1017)
        internal_new_block_msg = InternalEthBlockInfo.from_new_block_msg(
            block_msg)
        msg_bytes, block_info = self.node.message_converter.block_to_bx_block(
            internal_new_block_msg, self.node._tx_service, True,
            self.node.network.min_tx_age_seconds)
        msg_hash = Sha256Hash(crypto.double_sha256(msg_bytes))

        broadcast_msg = BroadcastMessage(message_hash=msg_hash,
                                         network_num=1,
                                         is_encrypted=False,
                                         blob=msg_bytes)
        self.relay_connection.msg_broadcast(broadcast_msg)
        self.relay_connection.msg_broadcast(broadcast_msg)

        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_blocks_received_from_bdn)

    def test_bdn_stats_block_new_from_bdn_ignore_from_node(self):
        block_msg = NewBlockEthProtocolMessage(
            None,
            _block_with_timestamp(time.time() + 1 - (
                self.node.opts.blockchain_ignore_block_interval_count *
                self.node.opts.blockchain_block_interval)), 10)

        internal_new_block_msg = InternalEthBlockInfo.from_new_block_msg(
            block_msg)
        msg_bytes, block_info = self.node.message_converter.block_to_bx_block(
            internal_new_block_msg, self.node._tx_service, True,
            self.node.network.min_tx_age_seconds)
        msg_hash = Sha256Hash(crypto.double_sha256(msg_bytes))
        broadcast_msg = BroadcastMessage(message_hash=msg_hash,
                                         network_num=1,
                                         is_encrypted=False,
                                         blob=msg_bytes)
        self.relay_connection.msg_broadcast(broadcast_msg)

        block_msg.serialize()
        self.block_blockchain_connection_protocol.msg_block(block_msg)

        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_blocks_received_from_bdn)
            self.assertEqual(0, stats.new_blocks_received_from_blockchain_node)

    def test_bdn_stats_block_new_from_node_ignore_from_bdn(self):
        block_msg = NewBlockEthProtocolMessage(
            None,
            _block_with_timestamp(
                time.time() + 1 -
                self.node.opts.blockchain_ignore_block_interval_count *
                self.node.opts.blockchain_block_interval), 10)

        block_msg.serialize()
        self.block_blockchain_connection_protocol.msg_block(block_msg)

        internal_new_block_msg = InternalEthBlockInfo.from_new_block_msg(
            block_msg)
        msg_bytes, block_info = self.node.message_converter.block_to_bx_block(
            internal_new_block_msg, self.node._tx_service, True,
            self.node.network.min_tx_age_seconds)
        msg_hash = Sha256Hash(crypto.double_sha256(msg_bytes))
        broadcast_msg = BroadcastMessage(message_hash=msg_hash,
                                         network_num=1,
                                         is_encrypted=False,
                                         blob=msg_bytes)
        self.relay_connection.msg_broadcast(broadcast_msg)

        self.assertEqual(
            3,
            len(gateway_bdn_performance_stats_service.interval_data.
                blockchain_node_to_bdn_stats))
        node_1_stats = gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats[
            self.node_1_endpoint]
        for endpoint, stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.items(
        ):
            if endpoint == self.node_1_endpoint:
                continue
            self.assertEqual(1, stats.new_blocks_received_from_bdn)

        self.assertEqual(1,
                         node_1_stats.new_blocks_received_from_blockchain_node)
        self.assertEqual(0, node_1_stats.new_blocks_received_from_bdn)