Exemple #1
0
    async def setUp(self) -> None:
        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        opts = gateway_helpers.get_gateway_opts(
            8000,
            include_default_eth_args=True,
            pub_key=pub_key,
        )
        if opts.use_extensions:
            helpers.set_extensions_parallelism()
        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE,
                                              MagicMock())
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.feed_manager = FeedManager(self.node)
        self.node.feed_manager = self.feed_manager
        self.rpc = SubscriptionRpcHandler(self.node, self.feed_manager,
                                          Case.SNAKE)
        self.feed_name = NewTransactionFeed.NAME
        self.node.init_live_feeds()

        self.feed_service_model = FeedServiceModelBase(
            allow_filtering=True, available_fields=["all"])
        self.base_feed_service_model = BdnFeedServiceModelConfigBase(
            expire_date="2999-01-01", feed=self.feed_service_model)
        self.node.account_model = BdnAccountModelBase(
            account_id="account_id",
            certificate="",
            logical_account_name="test",
            new_transaction_streaming=self.base_feed_service_model,
        )
    def setUp(self) -> None:
        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        opts = gateway_helpers.get_gateway_opts(8000, pub_key=pub_key)

        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE,
                                              MagicMock())
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.relay_1 = MockNode(
            helpers.get_common_opts(8000, region="us-east-1"))
        self.relay_connection_1 = helpers.create_connection(
            EthRelayConnection,
            self.node,
            node_opts=self.relay_1.opts,
            file_no=1,
            ip="1.2.3.4")

        self.relay_2 = MockNode(
            helpers.get_common_opts(8001, region="eu-west-1"))
        self.relay_connection_2 = helpers.create_connection(
            EthRelayConnection,
            self.node,
            node_opts=self.relay_2.opts,
            file_no=1,
            ip="1.2.3.5")
        self.node.broadcast = MagicMock()
        self.node.has_active_blockchain_peer = MagicMock(return_value=True)
Exemple #3
0
    def setUp(self) -> None:
        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        opts = gateway_helpers.get_gateway_opts(8000, pub_key=pub_key)

        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE,
                                              MagicMock())
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.connection = helpers.create_connection(EthRelayConnection,
                                                    self.node)
        self.node.broadcast = MagicMock()
        self.node.has_active_blockchain_peer = MagicMock(return_value=True)
Exemple #4
0
    def setUp(self) -> None:
        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE, MagicMock())
        opts = gateway_helpers.get_gateway_opts(
            8000,
            include_default_eth_args=True,
            blockchain_protocol=BlockchainProtocol.ETHEREUM.name,
            blockchain_network_num=5,
            pub_key=pub_key,
        )
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.enqueued_messages = []
        self.broadcast_to_node_messages = []
        self.broadcast_messages = []
        self.node.opts.has_fully_updated_tx_service = True
        self.node.init_live_feeds()

        self.connection = helpers.create_connection(
            EthNodeConnection, self.node, opts, port=opts.blockchain_port
        )

        gateway_helpers.add_blockchain_peer(self.node, self.connection)
        self.block_queuing_service = self.node.block_queuing_service_manager.get_designated_block_queuing_service()

        self.connection.on_connection_established()
        self.node.node_conn = self.connection
        gateway_bdn_performance_stats_service.set_node(self.node)

        def mocked_enqueue_msg(msg, prepend=False):
            self.enqueued_messages.append(msg)

        self.connection.enqueue_msg = mocked_enqueue_msg

        def mocked_broadcast(msg, broadcasting_conn=None, prepend_to_queue=False, connection_types=None):
            if connection_types is None:
                connection_types = [ConnectionType.RELAY_ALL]
            if len(connection_types) == 1 and connection_types[0] == ConnectionType.BLOCKCHAIN_NODE:
                self.broadcast_to_node_messages.append(msg)
            else:
                self.broadcast_messages.append(msg)

        self.node.broadcast = mocked_broadcast

        self.cleanup_service = self.node.block_cleanup_service
        self.node.block_processing_service.queue_block_for_processing = MagicMock()

        self.sut = self.connection.connection_protocol
        self.sut._waiting_checkpoint_headers_request = False
        self.node.opts.ws = True
        self.node.publish_block = MagicMock()
    def setUp(self) -> None:

        crypto_utils.recover_public_key = MagicMock(
            return_value=bytes(32))

        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        opts = gateway_helpers.get_gateway_opts(8000, include_default_eth_args=True, pub_key=pub_key,
                                                                  track_detailed_sent_messages=True)
        if opts.use_extensions:
            helpers.set_extensions_parallelism()
        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE, MagicMock())
        self.node = EthGatewayNode(opts, node_ssl_service)

        self.sut = EthNewBlockFeed(self.node)
Exemple #6
0
    def setUp(self) -> None:
        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        opts = gateway_helpers.get_gateway_opts(
            8000,
            include_default_eth_args=True,
            pub_key=pub_key,
            track_detailed_sent_messages=True)
        if opts.use_extensions:
            helpers.set_extensions_parallelism()
        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE,
                                              MagicMock())
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.connection_fileno = 1
        self.connection = helpers.create_connection(
            EthNodeConnection, node=self.node, file_no=self.connection_fileno)

        cipher1, cipher2 = AbstractRLPxCipherTest().setup_ciphers()
        self.connection.connection_protocol.rlpx_cipher = cipher1
class EthNodeConnectionTest(AbstractTestCase):
    def setUp(self) -> None:
        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        opts = gateway_helpers.get_gateway_opts(
            8000,
            include_default_eth_args=True,
            pub_key=pub_key,
            track_detailed_sent_messages=True)
        if opts.use_extensions:
            helpers.set_extensions_parallelism()
        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE,
                                              MagicMock())
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.connection_fileno = 1
        self.connection = helpers.create_connection(
            EthNodeConnection,
            node=self.node,
            file_no=self.connection_fileno,
            port=opts.blockchain_port)

        cipher1, cipher2 = AbstractRLPxCipherTest().setup_ciphers()
        self.connection.connection_protocol.rlpx_cipher = cipher1

    def test_message_tracked_correctly_when_framed(self):
        block_stats.add_block_event_by_block_hash = MagicMock()

        # send the handshake message
        self.node.on_bytes_sent(self.connection_fileno, 307)
        self.node.on_bytes_written_to_socket(self.connection_fileno, 307)

        block_message = NewBlockEthProtocolMessage(
            None,
            mock_eth_messages.get_dummy_block(
                1,
                mock_eth_messages.get_dummy_block_header(5, int(time.time()))),
            10)
        block_message.serialize()

        self.connection.enqueue_msg(block_message)
        message_length = self.connection.outputbuf.length
        for message in self.connection.message_tracker.messages:
            print(message.length)
        block_stats.add_block_event_by_block_hash.assert_not_called()
        self.assertEqual(message_length,
                         self.connection.message_tracker.messages[0].length)

        self.node.on_bytes_sent(self.connection_fileno, message_length)
        self.node.on_bytes_written_to_socket(self.connection_fileno,
                                             message_length)
        block_stats.add_block_event_by_block_hash.assert_called_once()
Exemple #8
0
    def setUp(self) -> None:

        crypto_utils.recover_public_key = MagicMock(return_value=bytes(32))

        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        opts = gateway_helpers.get_gateway_opts(8000,
                                                include_default_eth_args=True,
                                                pub_key=pub_key)
        if opts.use_extensions:
            helpers.set_extensions_parallelism()
        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE,
                                              MagicMock())
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.node_conn = MockConnection(
            MockSocketConnection(1, self.node, ip_address=LOCALHOST,
                                 port=8002), self.node)
        self.node.connection_pool.add(1, LOCALHOST, 8002, self.node_conn)
        gateway_helpers.add_blockchain_peer(self.node, self.node_conn)
        self.block_queuing_service = self.node.block_queuing_service_manager.get_designated_block_queuing_service(
        )

        self.sut = EthNewBlockFeed(self.node)
    def _set_up_test_node(self, initialize_handshake, generate_pub_key=False):
        # Dummy address
        self.server_ip = "127.0.0.1"
        self.server_port = 1234

        self.blockchain_ip = "0.0.0.0"
        self.blockchain_port = 30303

        # Setting up dummy server addresses
        self.servers = [
            OutboundPeerModel("172.0.0.1", 2222, node_type=NodeType.GATEWAY),
            OutboundPeerModel("172.0.0.2", 3333, node_type=NodeType.GATEWAY),
            OutboundPeerModel("172.0.0.3", 4444, node_type=NodeType.GATEWAY)
        ]
        if generate_pub_key:
            pub_key = convert.bytes_to_hex(self._get_dummy_public_key())
        else:
            pub_key = None
        opts = gateway_helpers.get_gateway_opts(
            self.server_port,
            sid_expire_time=0,
            external_ip=self.server_ip,
            test_mode=[],
            peer_gateways=[],
            peer_relays=self.servers,
            blockchain_address=(self.blockchain_ip, self.blockchain_port),
            include_default_eth_args=True,
            pub_key=pub_key,
            no_discovery=not initialize_handshake)
        if opts.use_extensions:
            helpers.set_extensions_parallelism()
        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE,
                                              MagicMock())
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.node.requester = MagicMock()
        self.assertTrue(self.node)

        return self.node
Exemple #10
0
class EthNewBlockFeedPublishTest(AbstractTestCase):
    def setUp(self) -> None:

        crypto_utils.recover_public_key = MagicMock(return_value=bytes(32))

        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        opts = gateway_helpers.get_gateway_opts(
            8000,
            include_default_eth_args=True,
            pub_key=pub_key,
            track_detailed_sent_messages=True)
        if opts.use_extensions:
            helpers.set_extensions_parallelism()
        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE,
                                              MagicMock())
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.node_conn = MockConnection(
            MockSocketConnection(1, self.node, ip_address=LOCALHOST,
                                 port=8002), self.node)
        self.node.connection_pool.add(1, LOCALHOST, 8002, self.node_conn)
        gateway_helpers.add_blockchain_peer(self.node, self.node_conn)
        self.block_queuing_service = self.node.block_queuing_service_manager.get_designated_block_queuing_service(
        )

        self.sut = EthNewBlockFeed(self.node)

    def generate_new_eth_block(self, block_number=10) -> InternalEthBlockInfo:
        block_message = NewBlockEthProtocolMessage(
            None,
            mock_eth_messages.get_dummy_block(
                1,
                mock_eth_messages.get_dummy_block_header(
                    5, int(time.time()), block_number=block_number)), 10)
        block_message.serialize()
        internal_block_message = InternalEthBlockInfo.from_new_block_msg(
            block_message)
        return internal_block_message

    def generate_raw_block_msg(self,
                               block_number=10,
                               source=FeedSource.BLOCKCHAIN_SOCKET):
        block_msg = self.generate_new_eth_block(block_number)
        return EthRawBlock(block_msg.block_number(), block_msg.block_hash(),
                           source,
                           self.node._get_block_message_lazy(block_msg, None))

    def tearDown(self) -> None:
        crypto_utils.recover_public_key = _recover_public_key

    def test_lazy_get_block(self):
        block_msg = self.generate_new_eth_block()
        block_hash = block_msg.block_hash()

        # raises when block is absent from block queueing service
        lazy_block = self.node._get_block_message_lazy(None, block_hash)
        with self.assertRaises(StopIteration):
            block = next(lazy_block)
            self.assertIsNone(block)

        # returns block
        self.node.block_parts_storage[
            block_hash] = block_msg.to_new_block_parts()
        lazy_block = self.node._get_block_message_lazy(None, block_hash)
        block = next(lazy_block)
        self.assertEqual(block.block_hash(), block_hash)

        # returns block
        lazy_block = self.node._get_block_message_lazy(block_msg, None)
        next(lazy_block)
        self.assertEqual(block.block_hash(), block_hash)

    def test_block_seen_from_node(self):
        self.node.publish_block = MagicMock()
        block_msg = self.generate_new_eth_block()
        block_hash = block_msg.block_hash()
        block_number = block_msg.block_number()

        # called without block_msg
        self.block_queuing_service.mark_block_seen_by_blockchain_node(
            block_hash,
            None,
            block_number,
        )
        # called once with block
        self.node.publish_block.assert_not_called()

        # called for same block with message
        self.node.publish_block = MagicMock()
        self.block_queuing_service.mark_block_seen_by_blockchain_node(
            block_hash,
            block_msg,
            block_number,
        )
        self.node.publish_block.assert_called_with(
            block_number, block_hash, block_msg, FeedSource.BLOCKCHAIN_SOCKET)

        # call for stale block
        stale_block_msg = self.generate_new_eth_block(9)
        stale_block_hash = stale_block_msg.block_hash()
        stale_block_number = stale_block_msg.block_number()
        self.node.publish_block = MagicMock()

        self.block_queuing_service.mark_block_seen_by_blockchain_node(
            stale_block_hash,
            stale_block_msg,
            stale_block_number,
        )
        self.node.publish_block.assert_not_called()

    def test_push_block(self):
        self.node.publish_block = MagicMock()
        block_msg = self.generate_new_eth_block()
        block_hash = block_msg.block_hash()
        block_number = block_msg.block_number()

        self.node.block_queuing_service_manager.push(block_hash, block_msg)
        self.node.publish_block.assert_called_once()
        self.node.publish_block.assert_called_with(block_number, block_hash,
                                                   block_msg,
                                                   FeedSource.BDN_SOCKET)

    def test_publish_fork(self):
        # in case of a fork publish current block,
        # and attempt to publish all following blocks from the queueing service

        self.sut.subscriber_count = MagicMock(return_value=10)
        self.sut.publish_blocks_from_queue = MagicMock()

        self.sut.publish(self.generate_raw_block_msg(10))
        self.sut.publish(self.generate_raw_block_msg(11))
        self.sut.publish(self.generate_raw_block_msg(12))

        fork_msg = self.generate_raw_block_msg(10)
        self.sut.publish(fork_msg)

        self.assertIn(fork_msg.block_hash, self.sut.published_blocks.contents)
        self.sut.publish_blocks_from_queue.assert_called_with(11, 12)

    def test_publish_gap(self):
        # in case of a gap attempt to publish all intermediate blocks from the queueing service
        # and publish current block

        self.sut.subscriber_count = MagicMock(return_value=10)
        self.sut.publish_blocks_from_queue = MagicMock()

        self.sut.publish(self.generate_raw_block_msg(10))
        msg = self.generate_raw_block_msg(20)
        self.sut.publish(msg)

        self.assertIn(msg.block_hash, self.sut.published_blocks.contents)
        self.sut.publish_blocks_from_queue.assert_called_once()
        self.sut.publish_blocks_from_queue.assert_called_with(11, 19)

    def test_publish_from_queue(self):
        self.sut.subscriber_count = MagicMock(return_value=10)
        self.sut.publish = MagicMock()

        self.sut.publish_blocks_from_queue(10, 20)
        # no blocks in queueing service
        self.sut.publish.assert_not_called()
        self.block_queuing_service.accepted_block_hash_at_height[11] = "11"
        self.sut.publish_blocks_from_queue(10, 20)
        # only one block in queueing service
        self.sut.publish.assert_called_once()
        self.sut.publish = MagicMock()
        for i in range(10, 20):
            self.block_queuing_service.accepted_block_hash_at_height[i] = str(
                i)
        self.sut.publish_blocks_from_queue(10, 20)
        # only one block in queueing service
        call_args = self.sut.publish.call_args_list
        self.assertTrue(10, len(call_args))
        published_blocks = set({})
        for _call in call_args:
            published_blocks.add(_call[0][0].block_number)
        self.assertEqual(set(range(10, 20)), published_blocks)
Exemple #11
0
class EthNodeConnectionProtocolTest(AbstractTestCase):
    def setUp(self) -> None:
        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE, MagicMock())
        opts = gateway_helpers.get_gateway_opts(
            8000,
            include_default_eth_args=True,
            blockchain_protocol=BlockchainProtocol.ETHEREUM.name,
            blockchain_network_num=5,
            pub_key=pub_key,
        )
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.enqueued_messages = []
        self.broadcast_to_node_messages = []
        self.broadcast_messages = []
        self.node.opts.has_fully_updated_tx_service = True
        self.node.init_live_feeds()

        self.connection = helpers.create_connection(
            EthNodeConnection, self.node, opts, port=opts.blockchain_port
        )

        gateway_helpers.add_blockchain_peer(self.node, self.connection)
        self.block_queuing_service = self.node.block_queuing_service_manager.get_designated_block_queuing_service()

        self.connection.on_connection_established()
        self.node.node_conn = self.connection
        gateway_bdn_performance_stats_service.set_node(self.node)

        def mocked_enqueue_msg(msg, prepend=False):
            self.enqueued_messages.append(msg)

        self.connection.enqueue_msg = mocked_enqueue_msg

        def mocked_broadcast(msg, broadcasting_conn=None, prepend_to_queue=False, connection_types=None):
            if connection_types is None:
                connection_types = [ConnectionType.RELAY_ALL]
            if len(connection_types) == 1 and connection_types[0] == ConnectionType.BLOCKCHAIN_NODE:
                self.broadcast_to_node_messages.append(msg)
            else:
                self.broadcast_messages.append(msg)

        self.node.broadcast = mocked_broadcast

        self.cleanup_service = self.node.block_cleanup_service
        self.node.block_processing_service.queue_block_for_processing = MagicMock()

        self.sut = self.connection.connection_protocol
        self.sut._waiting_checkpoint_headers_request = False
        self.node.opts.ws = True
        self.node.publish_block = MagicMock()

    def test_request_block_bodies(self):
        self.cleanup_service.clean_block_transactions_by_block_components = (
            MagicMock()
        )

        block_hashes_sets = [
            [helpers.generate_object_hash(), helpers.generate_object_hash()],
            [helpers.generate_object_hash()],
            [helpers.generate_object_hash()],
        ]

        block_bodies_messages = [
            BlockBodiesEthProtocolMessage(
                None,
                [
                    mock_eth_messages.get_dummy_transient_block_body(1),
                    mock_eth_messages.get_dummy_transient_block_body(2),
                ],
            ),
            BlockBodiesEthProtocolMessage(
                None, [mock_eth_messages.get_dummy_transient_block_body(3)]
            ),
            BlockBodiesEthProtocolMessage(
                None, [mock_eth_messages.get_dummy_transient_block_body(4)]
            ),
        ]

        transactions = [
            [
                [
                    tx.hash()
                    for tx in BlockBodiesEthProtocolMessage.from_body_bytes(
                        block_body_bytes
                    )
                    .get_blocks()[0]
                    .transactions
                ]
                for block_body_bytes in msg.get_block_bodies_bytes()
            ]
            for msg in block_bodies_messages
        ]

        for block_bodies_message in block_bodies_messages:
            block_bodies_message.serialize()

        for block_hashes_set in block_hashes_sets:
            for block_hash in block_hashes_set:
                self.node.block_cleanup_service._block_hash_marked_for_cleanup.add(
                    block_hash
                )
            self.sut.request_block_body(block_hashes_set)

        self.sut.msg_block_bodies(block_bodies_messages[0])
        call_args_list = (
            self.cleanup_service.clean_block_transactions_by_block_components.call_args_list
        )

        first_call = call_args_list[0]
        first_kwargs = first_call[1]
        self.assertEqual(
            first_kwargs["transaction_service"], self.node.get_tx_service()
        )
        self.assertEqual(first_kwargs["block_hash"], block_hashes_sets[0][0])
        self.assertEqual(
            list(first_kwargs["transactions_list"]), transactions[0][0]
        )

        second_call = call_args_list[1]
        second_kwargs = second_call[1]
        self.assertEqual(
            second_kwargs["transaction_service"], self.node.get_tx_service()
        )
        self.assertEqual(second_kwargs["block_hash"], block_hashes_sets[0][1])
        self.assertEqual(
            list(second_kwargs["transactions_list"]), transactions[0][1]
        )

        self.cleanup_service.clean_block_transactions_by_block_components.reset_mock()
        self.sut.msg_block_bodies(block_bodies_messages[1])
        call_args_list = (
            self.cleanup_service.clean_block_transactions_by_block_components.call_args_list
        )

        first_call = call_args_list[0]
        first_kwargs = first_call[1]
        self.assertEqual(
            first_kwargs["transaction_service"], self.node.get_tx_service()
        )
        self.assertEqual(first_kwargs["block_hash"], block_hashes_sets[1][0])
        self.assertEqual(
            list(first_kwargs["transactions_list"]), transactions[1][0]
        )

        self.cleanup_service.clean_block_transactions_by_block_components.reset_mock()
        self.sut.msg_block_bodies(block_bodies_messages[2])
        call_args_list = (
            self.cleanup_service.clean_block_transactions_by_block_components.call_args_list
        )

        first_call = call_args_list[0]
        first_kwargs = first_call[1]
        self.assertEqual(
            first_kwargs["transaction_service"], self.node.get_tx_service()
        )
        self.assertEqual(first_kwargs["block_hash"], block_hashes_sets[2][0])
        self.assertEqual(
            list(first_kwargs["transactions_list"]), transactions[2][0]
        )

    def test_msg_get_block_headers_unknown(self):
        block_hash = helpers.generate_hash()
        self.sut.msg_proxy_request = MagicMock()
        message = GetBlockHeadersEthProtocolMessage(None, block_hash, 1, 0, 0)

        self.sut.msg_get_block_headers(message)
        self.sut.msg_proxy_request.assert_called_once()

    def test_msg_get_block_headers_known_single(self):
        header = mock_eth_messages.get_dummy_block_header(12)
        block = mock_eth_messages.get_dummy_block(1, header)
        raw_hash = header.hash()
        block_hash = header.hash_object()
        new_block_message = NewBlockEthProtocolMessage(None, block, 10)
        eth_block_info = InternalEthBlockInfo.from_new_block_msg(
            new_block_message
        )

        self.node.block_queuing_service_manager.push(block_hash, eth_block_info)
        self.enqueued_messages.clear()

        self.sut.msg_proxy_request = MagicMock()
        message = GetBlockHeadersEthProtocolMessage(None, raw_hash, 1, 0, 0)
        self.sut.msg_get_block_headers(message)

        self.sut.msg_proxy_request.assert_not_called()
        self.assertEqual(1, len(self.enqueued_messages))

        headers_sent = self.enqueued_messages[0]
        self.assertIsInstance(headers_sent, BlockHeadersEthProtocolMessage)
        self.assertEqual(1, len(headers_sent.get_block_headers()))
        self.assertEqual(
            block_hash, headers_sent.get_block_headers()[0].hash_object()
        )

        self.block_queuing_service.mark_block_seen_by_blockchain_node(
            block_hash, eth_block_info
        )
        self.sut.msg_get_block_headers(message)
        self.sut.msg_proxy_request.assert_not_called()
        self.assertEqual(2, len(self.enqueued_messages))

    def test_msg_get_block_headers_block_number(self):
        block_number = 123456
        header = mock_eth_messages.get_dummy_block_header(
            12, block_number=block_number
        )
        block = mock_eth_messages.get_dummy_block(1, header)
        block_hash = header.hash_object()
        new_block_message = NewBlockEthProtocolMessage(None, block, 10)
        eth_block_info = InternalEthBlockInfo.from_new_block_msg(
            new_block_message
        )

        self.node.block_queuing_service_manager.push(block_hash, eth_block_info)
        self.enqueued_messages.clear()

        self.sut.msg_proxy_request = MagicMock()

        block_number_bytes = struct.pack(">I", block_number)
        message = GetBlockHeadersEthProtocolMessage(
            None, block_number_bytes, 1, 0, 0
        )

        self.sut.msg_get_block_headers(message)
        self.sut.msg_proxy_request.assert_not_called()
        self.assertEqual(1, len(self.enqueued_messages))

        headers_sent = self.enqueued_messages[0]
        self.assertIsInstance(headers_sent, BlockHeadersEthProtocolMessage)
        self.assertEqual(1, len(headers_sent.get_block_headers()))
        self.assertEqual(
            block_hash, headers_sent.get_block_headers()[0].hash_object()
        )

    def test_msg_get_block_headers_known_many(self):
        self.node.opts.max_block_interval_s = 0

        block_hashes = []
        block_hash = None
        for i in range(20):
            block_message = InternalEthBlockInfo.from_new_block_msg(
                mock_eth_messages.new_block_eth_protocol_message(
                    i, i + 1000, block_hash
                )
            )
            block_hash = block_message.block_hash()
            block_hashes.append(block_hash)
            self.node.block_queuing_service_manager.push(block_hash, block_message)
        self.block_queuing_service.best_sent_block = (1019, block_hashes[-1], 0)

        self.enqueued_messages.clear()

        self.sut.msg_proxy_request = MagicMock()
        message = GetBlockHeadersEthProtocolMessage(
            None, block_hashes[10].binary, 10, 0, 0
        )
        self.sut.msg_get_block_headers(message)

        self.sut.msg_proxy_request.assert_not_called()
        self.assertEqual(1, len(self.enqueued_messages))

        headers_sent = self.enqueued_messages[0]
        self.assertIsInstance(headers_sent, BlockHeadersEthProtocolMessage)
        self.assertEqual(10, len(headers_sent.get_block_headers()))

        for i in range(10):
            self.assertEqual(
                block_hashes[i + 10],
                headers_sent.get_block_headers()[i].hash_object(),
            )

    def test_msg_get_block_headers_fork(self):
        self.node.opts.max_block_interval_s = 0

        block_hashes = []
        for i in range(20):
            block_message = InternalEthBlockInfo.from_new_block_msg(
                mock_eth_messages.new_block_eth_protocol_message(i, i + 1000)
            )
            block_hash = block_message.block_hash()
            block_hashes.append(block_hash)
            self.node.block_queuing_service_manager.push(block_hash, block_message)

        # create fork
        block_message = InternalEthBlockInfo.from_new_block_msg(
            mock_eth_messages.new_block_eth_protocol_message(34, 1017)
        )
        block_hash = block_message.block_hash()
        block_hashes.append(block_hash)
        self.node.block_queuing_service_manager.push(block_hash, block_message)

        self.enqueued_messages.clear()

        self.sut.msg_proxy_request = MagicMock()
        message = GetBlockHeadersEthProtocolMessage(
            None, block_hashes[-1].binary, 10, 0, 1
        )
        self.sut.msg_get_block_headers(message)

        self.sut.msg_proxy_request.assert_called_once()
        self.assertEqual(0, len(self.enqueued_messages))

    def test_msg_get_block_headers_missing_block(self):
        self.node.opts.max_block_interval_s = 0

        block_hashes = []
        for i in (j for j in range(20) if j != 17):
            block_message = InternalEthBlockInfo.from_new_block_msg(
                mock_eth_messages.new_block_eth_protocol_message(i, i + 1000)
            )
            block_hash = block_message.block_hash()
            block_hashes.append(block_hash)
            self.node.block_queuing_service_manager.push(block_hash, block_message)

        self.enqueued_messages.clear()

        self.sut.msg_proxy_request = MagicMock()
        message = GetBlockHeadersEthProtocolMessage(
            None, block_hashes[-1].binary, 10, 0, 1
        )
        self.sut.msg_get_block_headers(message)

        self.sut.msg_proxy_request.assert_called_once()
        self.assertEqual(0, len(self.enqueued_messages))

    def test_msg_get_block_headers_future_block(self):
        self.node.opts.max_block_interval_s = 0

        block_hashes = []
        block_heights = []
        for i in range(20):
            block_message = InternalEthBlockInfo.from_new_block_msg(
                mock_eth_messages.new_block_eth_protocol_message(i, i + 1000)
            )
            block_hash = block_message.block_hash()
            block_heights.append(block_message.block_number())
            block_hashes.append(block_hash)
            self.node.block_queuing_service_manager.push(block_hash, block_message)

        self.enqueued_messages.clear()
        self.sut.msg_proxy_request = MagicMock()

        block_height_bytes = block_heights[-1] + 4
        block_height_bytes = block_height_bytes.to_bytes(8, "big")

        message = GetBlockHeadersEthProtocolMessage(
            None, block_height_bytes, 1, 0, 0
        )
        self.sut.msg_get_block_headers(message)

        self.sut.msg_proxy_request.assert_not_called()
        self.assertEqual(1, len(self.enqueued_messages))
        headers_sent = self.enqueued_messages[0]
        self.assertIsInstance(headers_sent, BlockHeadersEthProtocolMessage)
        self.assertEqual(0, len(headers_sent.get_block_headers()))

    def test_msg_block_adds_headers_and_bodies(self):
        self.node.opts.max_block_interval_s = 0
        self.sut.is_valid_block_timestamp = MagicMock(return_value=True)

        block_hashes = []
        block_messages = []
        block_hash = None
        for i in range(20):
            block_message = InternalEthBlockInfo.from_new_block_msg(
                mock_eth_messages.new_block_eth_protocol_message(i, i + 1000, block_hash)
            )
            block_hash = block_message.block_hash()
            block_hashes.append(block_hash)
            block_messages.append(block_message)

        # push all blocks, except for # 17
        for i in (j for j in range(20) if j != 17):
            self.node.block_queuing_service_manager.push(
                block_hashes[i], block_messages[i]
            )
            self.block_queuing_service.remove_from_queue(block_hashes[i])
        self.block_queuing_service.best_sent_block = (1019, block_hashes[-1], 0)

        self.enqueued_messages.clear()
        self.sut.msg_proxy_request = MagicMock()
        message = GetBlockHeadersEthProtocolMessage(
            None, block_hashes[10].binary, 10, 0, 0
        )
        self.sut.msg_get_block_headers(message)

        self.sut.msg_proxy_request.assert_called_once()
        self.sut.msg_proxy_request.reset_mock()

        self.sut.msg_block(block_messages[17].to_new_block_msg())
        self.node.publish_block.assert_called()

        self.sut.msg_get_block_headers(message)
        self.sut.msg_proxy_request.assert_not_called()
        self.assertEqual(1, len(self.enqueued_messages))

        headers_sent = self.enqueued_messages[0]
        self.assertIsInstance(headers_sent, BlockHeadersEthProtocolMessage)
        self.assertEqual(10, len(headers_sent.get_block_headers()))

        for i in range(10):
            self.assertEqual(
                block_hashes[i + 10],
                headers_sent.get_block_headers()[i].hash_object(),
            )

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

    def test_handle_tx_with_an_invalid_signature(self):
        tx_bytes = \
            b"\xf8k" \
            b"!" \
            b"\x85\x0b\xdf\xd6>\x00" \
            b"\x82R\x08\x94" \
            b"\xf8\x04O\xf8$\xc2\xdc\xe1t\xb4\xee\x9f\x95\x8c*s\x84\x83\x18\x9e" \
            b"\x87\t<\xaf\xacj\x80\x00\x80" \
            b"!" \
            b"\xa0-\xbf,\xa9+\xae\xabJ\x03\xcd\xfa\xe3<\xbf$\x00e\xe2N|\xc9\xf7\xe2\xa9\x9c>\xdfn\x0cO\xc0\x16" \
            b"\xa0)\x11K=;\x96X}a\xd5\x00\x06eSz\xd1,\xe4>\xa1\x8c\xf8\x7f>\x0e:\xd1\xcd\x00?'?"

        result = transaction_validation.validate_transaction(
            tx_bytes,
            BlockchainProtocol(self.node.network.protocol.lower()),
            self.node.get_network_min_transaction_fee()
        )

        self.assertEqual(TxValidationStatus.INVALID_SIGNATURE, result)

    def test_handle_tx_with_an_invalid_format(self):
        tx_bytes = \
            b"\xf8k" \
            b"!" \
            b"\x85\x0b\xdf\xd6>\x00\x82R\x08\x94\xf8\x04O\xf8$\xc2\xdc\xe1t\xb4\xee\x9f\x95\x8c*s\x84\x83" \
            b"\x18\x9e\x87\t<\xaf\xacj\x80\x00\x80&\xa0-\xbf,\xa9+\xae\xabJ\x03\xcd\xfa\xe3<\xbf$\x00e\xe2N|\xc9" \
            b"\xf7\xe2\xa9\x9c>\xdfn\x0cO\xc0\x16"

        result = transaction_validation.validate_transaction(
            tx_bytes,
            BlockchainProtocol(self.node.network.protocol.lower()),
            self.node.get_network_min_transaction_fee()
        )

        self.assertEqual(TxValidationStatus.INVALID_FORMAT, result)

    def test_handle_tx_with_low_fee(self):
        self.node.feed_manager.publish_to_feed = MagicMock()
        self.node.opts.ws = False

        tx_bytes = \
            b"\xf8k" \
            b"!" \
            b"\x85\x0b\xdf\xd6>\x00\x82R\x08\x94\xf8\x04O\xf8$\xc2\xdc\xe1t\xb4\xee\x9f\x95\x8c*s\x84\x83" \
            b"\x18\x9e\x87\t<\xaf\xacj\x80\x00\x80" \
            b"&" \
            b"\xa0" \
            b"-\xbf,\xa9+\xae\xabJ\x03\xcd\xfa\xe3<\xbf$\x00e\xe2N|\xc9\xf7\xe2\xa9\x9c>\xdfn\x0cO\xc0\x16" \
            b"\xa0)\x11K=;\x96X}a\xd5\x00\x06eSz\xd1,\xe4>\xa1\x8c\xf8\x7f>\x0e:\xd1\xcd\x00?'\x15"

        result = transaction_validation.validate_transaction(
            tx_bytes,
            BlockchainProtocol(self.node.network.protocol.lower()),
            510000000000
        )
        self.assertEqual(TxValidationStatus.LOW_FEE, result)

    def test_complete_header_body_fetch(self):
        self.node.block_processing_service.queue_block_for_processing = MagicMock()
        self.node.block_queuing_service_manager.push = MagicMock()
        self.node.on_block_seen_by_blockchain_node = MagicMock(return_value=False)
        self.sut.is_valid_block_timestamp = MagicMock(return_value=True)

        header = mock_eth_messages.get_dummy_block_header(1)
        block = mock_eth_messages.get_dummy_block(1, header)
        block_hash = header.hash_object()
        new_block_hashes_message = NewBlockHashesEthProtocolMessage.from_block_hash_number_pair(
            block_hash, 1
        )
        header_message = BlockHeadersEthProtocolMessage(None, [header])
        bodies_message = BlockBodiesEthProtocolMessage(None, [TransientBlockBody(block.transactions, block.uncles)])

        self.sut.msg_new_block_hashes(new_block_hashes_message)
        self.node.on_block_seen_by_blockchain_node.assert_called_once()

        self.assertEqual(1, len(self.sut.pending_new_block_parts.contents))
        self.assertEqual(2, len(self.enqueued_messages))

        self.node.on_block_seen_by_blockchain_node.reset_mock()
        self.sut.msg_block_headers(header_message)
        self.sut.msg_block_bodies(bodies_message)

        self.node.block_queuing_service_manager.push.assert_called_once()
        self.node.on_block_seen_by_blockchain_node.assert_called_once()
        self.node.block_processing_service.queue_block_for_processing.assert_called_once()

    def test_complete_header_body_fetch_already_seen(self):
        self.node.block_processing_service.queue_block_for_processing = MagicMock()
        self.node.block_queuing_service_manager.push = MagicMock()
        self.node.on_block_seen_by_blockchain_node = MagicMock()
        self.sut.is_valid_block_timestamp = MagicMock(return_value=True)

        header = mock_eth_messages.get_dummy_block_header(1)
        block = mock_eth_messages.get_dummy_block(1, header)
        block_hash = header.hash_object()
        new_block_hashes_message = NewBlockHashesEthProtocolMessage.from_block_hash_number_pair(
            block_hash, 1
        )
        header_message = BlockHeadersEthProtocolMessage(None, [header])
        bodies_message = BlockBodiesEthProtocolMessage(None, [TransientBlockBody(block.transactions, block.uncles)])

        self.sut.msg_new_block_hashes(new_block_hashes_message)
        self.node.on_block_seen_by_blockchain_node.assert_called_once()

        self.assertEqual(1, len(self.sut.pending_new_block_parts.contents))
        self.assertEqual(2, len(self.enqueued_messages))

        self.node.on_block_seen_by_blockchain_node.reset_mock()
        self.node.blocks_seen.add(block_hash)
        self.sut.msg_block_headers(header_message)
        self.sut.msg_block_bodies(bodies_message)

        self.node.block_queuing_service_manager.push.assert_not_called()
        self.node.on_block_seen_by_blockchain_node.assert_called_once()
        self.node.block_processing_service.queue_block_for_processing.assert_not_called()

    def test_complete_header_body_recovery(self):
        self.node.block_processing_service.queue_block_for_processing = MagicMock()
        self.node.block_queuing_service_manager.push = MagicMock()
        self.node.on_block_seen_by_blockchain_node = MagicMock(return_value=False)
        self.sut.is_valid_block_timestamp = MagicMock(return_value=True)

        header = mock_eth_messages.get_dummy_block_header(1)
        block = mock_eth_messages.get_dummy_block(1, header)
        block_hash = header.hash_object()
        new_block_hashes_message = NewBlockHashesEthProtocolMessage.from_block_hash_number_pair(
            block_hash, 1
        )
        header_message = BlockHeadersEthProtocolMessage(None, [header])
        bodies_message = BlockBodiesEthProtocolMessage(None, [TransientBlockBody(block.transactions, block.uncles)])

        self.sut.msg_new_block_hashes(new_block_hashes_message)
        self.node.on_block_seen_by_blockchain_node.assert_called_once()

        self.assertEqual(1, len(self.sut.pending_new_block_parts.contents))
        self.assertEqual(2, len(self.enqueued_messages))

        self.node.on_block_seen_by_blockchain_node.reset_mock()
        self.node.on_block_seen_by_blockchain_node = MagicMock(return_value=True)
        self.sut.msg_block_headers(header_message)
        self.sut.msg_block_bodies(bodies_message)

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

        self.node.on_block_seen_by_blockchain_node.assert_called_once()
        self.node.block_queuing_service_manager.push.assert_not_called()
        self.node.block_processing_service.queue_block_for_processing.assert_not_called()

    def test_header_body_fetch_abort_from_bdn(self):
        self.node.block_processing_service.queue_block_for_processing = MagicMock()
        self.sut.is_valid_block_timestamp = MagicMock(return_value=True)

        header = mock_eth_messages.get_dummy_block_header(1)
        block = mock_eth_messages.get_dummy_block(1, header)
        block_hash = header.hash_object()
        new_block_hashes_message = NewBlockHashesEthProtocolMessage.from_block_hash_number_pair(
            block_hash, 1
        )
        header_message = BlockHeadersEthProtocolMessage(None, [header])
        bodies_message = BlockBodiesEthProtocolMessage(None, [TransientBlockBody(block.transactions, block.uncles)])
        internal_block_info = InternalEthBlockInfo.from_new_block_msg(NewBlockEthProtocolMessage(None, block, 1))

        self.sut.msg_new_block_hashes(new_block_hashes_message)
        self.assertEqual(1, len(self.sut.pending_new_block_parts.contents))
        self.assertEqual(2, len(self.enqueued_messages))

        self.node.on_block_received_from_bdn(block_hash, internal_block_info)

        self.sut.msg_block_headers(header_message)
        self.sut.msg_block_bodies(bodies_message)

        self.node.block_processing_service.queue_block_for_processing.assert_not_called()
class EthRelayConnectionTest(AbstractTestCase):
    def setUp(self) -> None:
        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        opts = gateway_helpers.get_gateway_opts(8000, pub_key=pub_key)

        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE,
                                              MagicMock())
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.relay_1 = MockNode(
            helpers.get_common_opts(8000, region="us-east-1"))
        self.relay_connection_1 = helpers.create_connection(
            EthRelayConnection,
            self.node,
            node_opts=self.relay_1.opts,
            file_no=1,
            ip="1.2.3.4")

        self.relay_2 = MockNode(
            helpers.get_common_opts(8001, region="eu-west-1"))
        self.relay_connection_2 = helpers.create_connection(
            EthRelayConnection,
            self.node,
            node_opts=self.relay_2.opts,
            file_no=1,
            ip="1.2.3.5")
        self.node.broadcast = MagicMock()
        self.node.has_active_blockchain_peer = MagicMock(return_value=True)

    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)

    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 test_publish_new_transaction_low_gas(self):
        bx_tx_message = self._convert_to_bx_message(
            mock_eth_messages.EIP_155_TRANSACTIONS_MESSAGE)

        self.node.feed_manager.publish_to_feed = MagicMock()
        self.node.get_blockchain_network().min_tx_network_fee = (
            mock_eth_messages.EIP_155_TRANSACTION_GAS_PRICE + 10)
        self.relay_connection_1.msg_tx(bx_tx_message)

        self.node.feed_manager.publish_to_feed.assert_not_called()

    def test_transaction_updates_filters_based_on_factor(self):
        self.node.opts.filter_txs_factor = 1
        self._set_bc_connection()

        transactions = [
            mock_eth_messages.get_dummy_transaction(i, 10) for i in range(100)
        ]
        self.node.on_transactions_in_block(transactions)

        cheap_tx = self._convert_to_bx_message(
            TransactionsEthProtocolMessage(
                None, [mock_eth_messages.get_dummy_transaction(1, 5)]))
        self.relay_connection_1.msg_tx(cheap_tx)
        self.node.broadcast.assert_not_called()

        expensive_tx = self._convert_to_bx_message(
            TransactionsEthProtocolMessage(
                None, [mock_eth_messages.get_dummy_transaction(1, 15)]))
        self.relay_connection_1.msg_tx(expensive_tx)
        self._assert_tx_sent()

    def _convert_to_bx_message(
            self,
            transactions_eth_msg: TransactionsEthProtocolMessage) -> TxMessage:
        bx_tx_message, _, _ = self.node.message_converter.tx_to_bx_txs(
            transactions_eth_msg, 5)[0]
        return bx_tx_message

    def _set_bc_connection(self) -> None:
        self.node.on_connection_added(
            MockSocketConnection(1, self.node, ip_address=LOCALHOST,
                                 port=7000))
        self.assertEqual(
            1,
            len(
                list(
                    self.node.connection_pool.get_by_connection_types(
                        [ConnectionType.BLOCKCHAIN_NODE]))))
        self.assertEqual(1, len(self.node.blockchain_peers))
        blockchain_conn = next(
            iter(
                self.node.connection_pool.get_by_connection_types(
                    [ConnectionType.BLOCKCHAIN_NODE])))
        self.node.requester.send_threaded_request = MagicMock()
        self.node.on_blockchain_connection_ready(blockchain_conn)
        self.assertIsNone(self.node._blockchain_liveliness_alarm)

    def _assert_tx_sent(self):
        self.node.broadcast.assert_called_once()
        calls = self.node.broadcast.call_args_list

        ((sent_tx_msg, ), connection_info) = calls[0]
        self.assertIsInstance(sent_tx_msg, TransactionsEthProtocolMessage)
        connection_types = connection_info["connection_types"]
        self.assertEqual(len(connection_types), 1)
        connection_type = connection_types[0]
        self.assertEqual(connection_type, ConnectionType.BLOCKCHAIN_NODE)
Exemple #13
0
class EthRelayConnectionTest(AbstractTestCase):
    def setUp(self) -> None:
        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        opts = gateway_helpers.get_gateway_opts(8000, pub_key=pub_key)

        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE,
                                              MagicMock())
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.connection = helpers.create_connection(EthRelayConnection,
                                                    self.node)
        self.node.broadcast = MagicMock()
        self.node.has_active_blockchain_peer = MagicMock(return_value=True)

    def test_publish_new_transaction(self):
        bx_tx_message = self._convert_to_bx_message(
            mock_eth_messages.EIP_155_TRANSACTIONS_MESSAGE)

        self.node.feed_manager.publish_to_feed = MagicMock()
        self.connection.msg_tx(bx_tx_message)

        expected_publication = EthRawTransaction(bx_tx_message.tx_hash(),
                                                 bx_tx_message.tx_val(),
                                                 FeedSource.BDN_SOCKET)
        self.node.feed_manager.publish_to_feed.assert_called_once_with(
            NewTransactionFeed.NAME, expected_publication)

    def test_transaction_updates_filters_based_on_factor(self):
        self.node.opts.filter_txs_factor = 1
        self._set_bc_connection()

        transactions = [
            mock_eth_messages.get_dummy_transaction(i, 10) for i in range(100)
        ]
        self.node.on_transactions_in_block(transactions)

        cheap_tx = self._convert_to_bx_message(
            TransactionsEthProtocolMessage(
                None, [mock_eth_messages.get_dummy_transaction(1, 5)]))
        self.connection.msg_tx(cheap_tx)
        self.node.broadcast.assert_not_called()

        expensive_tx = self._convert_to_bx_message(
            TransactionsEthProtocolMessage(
                None, [mock_eth_messages.get_dummy_transaction(1, 15)]))
        self.connection.msg_tx(expensive_tx)
        self.node.broadcast.assert_called_once()

    def _convert_to_bx_message(
            self,
            transactions_eth_msg: TransactionsEthProtocolMessage) -> TxMessage:
        bx_tx_message, _, _ = self.node.message_converter.tx_to_bx_txs(
            transactions_eth_msg, 5)[0]
        return bx_tx_message

    def _set_bc_connection(self) -> None:
        self.node.on_connection_added(
            MockSocketConnection(1, self.node, ip_address=LOCALHOST,
                                 port=7000))
        self.assertEqual(
            1,
            len(
                list(
                    self.node.connection_pool.get_by_connection_types(
                        [ConnectionType.BLOCKCHAIN_NODE]))))
        self.assertEqual(1, len(self.node.blockchain_peers))
        blockchain_conn = next(
            iter(
                self.node.connection_pool.get_by_connection_types(
                    [ConnectionType.BLOCKCHAIN_NODE])))
        self.node.requester.send_threaded_request = MagicMock()
        self.node.on_blockchain_connection_ready(blockchain_conn)
        self.assertIsNone(self.node._blockchain_liveliness_alarm)
Exemple #14
0
class GatewaySubscribeRpcRequestTest(AbstractTestCase):
    @async_test
    async def setUp(self) -> None:
        pub_key = "a04f30a45aae413d0ca0f219b4dcb7049857bc3f91a6351288cce603a2c9646294a02b987bf6586b370b2c22d74662355677007a14238bb037aedf41c2d08866"
        opts = gateway_helpers.get_gateway_opts(
            8000,
            include_default_eth_args=True,
            pub_key=pub_key,
        )
        if opts.use_extensions:
            helpers.set_extensions_parallelism()
        node_ssl_service = MockNodeSSLService(EthGatewayNode.NODE_TYPE,
                                              MagicMock())
        self.node = EthGatewayNode(opts, node_ssl_service)
        self.feed_manager = FeedManager(self.node)
        self.node.feed_manager = self.feed_manager
        self.rpc = SubscriptionRpcHandler(self.node, self.feed_manager,
                                          Case.SNAKE)
        self.feed_name = NewTransactionFeed.NAME
        self.node.init_live_feeds()

        self.feed_service_model = FeedServiceModelBase(
            allow_filtering=True, available_fields=["all"])
        self.base_feed_service_model = BdnFeedServiceModelConfigBase(
            expire_date="2999-01-01", feed=self.feed_service_model)
        self.node.account_model = BdnAccountModelBase(
            account_id="account_id",
            certificate="",
            logical_account_name="test",
            new_transaction_streaming=self.base_feed_service_model,
        )

    @async_test
    async def tearDown(self) -> None:
        pass

    @async_test
    async def test_subscribe_to_feed_with_no_includes_specified(self):
        subscribe_request1 = BxJsonRpcRequest(
            "1",
            RpcRequestType.SUBSCRIBE,
            [self.feed_name, {}],
        )

        rpc_handler = self.rpc.get_request_handler(subscribe_request1)
        result = await rpc_handler.process_request()
        self.assertTrue(result)

    @async_test
    async def test_subscribe_to_feed_with_all_available_fields(self):
        subscribe_request1 = BxJsonRpcRequest(
            "1",
            RpcRequestType.SUBSCRIBE,
            [
                self.feed_name, {
                    "include": ["tx_hash", "tx_contents.gas_price"]
                }
            ],
        )

        rpc_handler = self.rpc.get_request_handler(subscribe_request1)
        result = await rpc_handler.process_request()
        self.assertTrue(result)

    @async_test
    async def test_subscribe_to_feed_with_specific_available_field(self):
        feed_service_model = FeedServiceModelBase(
            allow_filtering=True, available_fields=["tx_contents.nonce"])
        base_feed_service_model = BdnFeedServiceModelConfigBase(
            expire_date="2999-01-01", feed=feed_service_model)
        self.node.account_model.new_transaction_streaming = base_feed_service_model

        subscribe_request1 = BxJsonRpcRequest(
            "1",
            RpcRequestType.SUBSCRIBE,
            [self.feed_name, {
                "include": ["tx_contents.nonce"]
            }],
        )

        rpc_handler = self.rpc.get_request_handler(subscribe_request1)
        result = await rpc_handler.process_request()
        self.assertTrue(result)

    @async_test
    async def test_subscribe_to_feed_with_unavailable_field(self):
        feed_service_model = FeedServiceModelBase(
            allow_filtering=True,
            available_fields=["tx_hash", "tx_contents.nonce"])
        base_feed_service_model = BdnFeedServiceModelConfigBase(
            expire_date="2999-01-01", feed=feed_service_model)
        self.node.account_model.new_transaction_streaming = base_feed_service_model

        subscribe_request1 = BxJsonRpcRequest(
            "1",
            RpcRequestType.SUBSCRIBE,
            [
                self.feed_name, {
                    "include": ["tx_hash", "tx_contents.gas_price"]
                }
            ],
        )

        with self.assertRaises(RpcInvalidParams):
            rpc_handler = self.rpc.get_request_handler(subscribe_request1)
            await rpc_handler.process_request()

    @async_test
    async def test_subscribe_to_feed_with_feed_not_set_in_account(self):
        subscribe_request1 = BxJsonRpcRequest(
            "1",
            RpcRequestType.SUBSCRIBE,
            ["pendingTxs", {}],
        )

        with self.assertRaises(RpcAccountIdError):
            rpc_handler = self.rpc.get_request_handler(subscribe_request1)
            await rpc_handler.process_request()

    @async_test
    async def test_subscribe_to_feed_no_feed_service(self):
        # allow feed if service is not defined (old account)
        self.node.account_model.new_transaction_streaming = BdnFeedServiceModelConfigBase(
            expire_date="2999-01-01")

        subscribe_request1 = BxJsonRpcRequest(
            "1",
            RpcRequestType.SUBSCRIBE,
            [self.feed_name, {}],
        )
        subscribe_request2 = BxJsonRpcRequest(
            "1",
            RpcRequestType.SUBSCRIBE,
            [
                self.feed_name, {
                    "include": ["tx_hash", "tx_contents.gas_price"]
                }
            ],
        )

        rpc_handler = self.rpc.get_request_handler(subscribe_request1)
        result = await rpc_handler.process_request()
        self.assertTrue(result)
        rpc_handler = self.rpc.get_request_handler(subscribe_request2)
        result = await rpc_handler.process_request()
        self.assertTrue(result)
 def _get_gateway_node(self) -> AbstractGatewayNode:
     mock_ssl_service = MagicMock()
     return EthGatewayNode(self.opts, mock_ssl_service)
Exemple #16
0
    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"