Ejemplo n.º 1
0
    def setUp(self) -> None:
        self.nodemgr._reset_for_test()
        node.NeoNode._reset_for_test()
        settings.reset_settings_to_default()

        fake_protocol = object()
        self.node1 = node.NeoNode(fake_protocol)
        self.node2 = node.NeoNode(fake_protocol)

        self.addr1 = payloads.NetworkAddress(address="127.0.0.1:10333")
        self.addr2 = payloads.NetworkAddress(address="127.0.0.2:20333")
        self.node1.address = self.addr1
        self.node2.address = self.addr2
Ejemplo n.º 2
0
    def test_helpers(self):
        addr1 = payloads.NetworkAddress(address='127.0.0.1:1111')
        addr1.set_state_dead()
        addr2 = payloads.NetworkAddress(address='127.0.0.1:2222')
        node.NeoNode.addresses = [addr1, addr2]
        result = node.NeoNode.get_address_new()
        self.assertEqual(addr2, result)

        n = node.NeoNode(object())
        addr = n._find_address_by_host_port('127.0.0.1:1111')
        self.assertEqual(addr1, addr)
        addr = n._find_address_by_host_port('127.0.0.1:3333')
        self.assertEqual(None, addr)
Ejemplo n.º 3
0
    async def test_fill_open_connection_spots_node_timeout_error(self):
        self.nodemgr.min_clients = 1
        self.nodemgr.max_clients = 2
        addr = payloads.NetworkAddress(address='127.0.0.1:1111')
        node.NeoNode.addresses = [addr]

        call_back_result = None

        def client_connect_done(node_instance, failure):
            nonlocal call_back_result
            call_back_result = failure

        # listen to a connection done event
        msgrouter.on_client_connect_done += client_connect_done

        with self.assertLogs(network_logger, 'DEBUG') as context:
            self.loop.create_connection = AsyncMock()
            self.loop.create_connection.side_effect = asyncio.TimeoutError()
            await self.nodemgr._fill_open_connection_spots()

        # advance loop
        await asyncio.sleep(0.1)
        self.assertEqual("Timed out", call_back_result[1])
        self.assertIn("Found 2 open pool spots, trying to add nodes...",
                      context.output[0])
Ejemplo n.º 4
0
 def _find_address_by_host_port(
         self, host_port) -> Optional[payloads.NetworkAddress]:
     addr = payloads.NetworkAddress(address=host_port)
     try:
         idx = self.addresses.index(addr)
         return self.addresses[idx]
     except ValueError:
         return None
Ejemplo n.º 5
0
 async def _process(seed):
     host, port = seed.split(':')
     if not is_ip_address(host):
         try:
             result = await resolver.query(host, 'A')
             host = result[0].host
         except aiodns.error.DNSError as e:
             logger.debug(f"Skipping {host}, address could not be resolved: {e}.")
     node.NeoNode.addresses.append(payloads.NetworkAddress(address=f"{host}:{port}"))
Ejemplo n.º 6
0
    async def test_send_addr_list(self):
        n = node.NeoNode(object())
        n.send_message = asynctest.CoroutineMock()
        n.addresses = [payloads.NetworkAddress(address='127.0.0.1:1111')]
        await n.send_address_list(n.addresses)

        self.assertIsNotNone(n.send_message.call_args)
        m = n.send_message.call_args[0][0]  # type: message.Message
        self.assertEqual(message.MessageType.ADDR, m.type)
        self.assertIsInstance(m.payload, payloads.AddrPayload)
        self.assertEqual(n.addresses, m.payload.addresses)
Ejemplo n.º 7
0
 async def test_sending_addresses(self):
     n = await node.NeoNode.connect_to('127.0.0.1', 40333)
     await n.send_address_list([
         payloads.NetworkAddress(
             host='127.0.0.1',
             timestamp=0,
             capabilities=[
                 capabilities.FullNodeCapability(start_height=123)
             ])
     ])
     await asyncio.sleep(100)
Ejemplo n.º 8
0
    async def test_fill_open_connection_spots_no_clients(self):
        # create 1 open spot
        self.nodemgr.max_clients = 1
        # ensure we have an address that can be connected to
        node.NeoNode.addresses = [payloads.NetworkAddress(address='127.0.0.1:1111')]

        with self.assertLogs(network_logger, 'DEBUG') as context:
            with mock.patch('asyncio.create_task'):
                await self.nodemgr._fill_open_connection_spots()
        self.assertIn("Found 1 open pool spots", context.output[0])
        self.assertIn("Adding 127.0.0.1:1111 to connection queue", context.output[1])
Ejemplo n.º 9
0
    async def test_fill_open_connection_spots_no_addresses_to_fill_spots(self):
        # we first test that no errors occur if we have open spots, but we still meet our minimum required clients
        # this should not cause any error count increases
        self.nodemgr.min_clients = 1
        self.nodemgr.max_clients = 2
        # just a place holder to have a count matching min_clients
        self.nodemgr.nodes = [object()]
        node.NeoNode.addresses = []

        with self.assertLogs(network_logger, 'DEBUG') as context:
            await self.nodemgr._fill_open_connection_spots()
        self.assertIn("Found 1 open pool spots, trying to add nodes...",
                      context.output[0])
        self.assertIn(
            "No addresses available to fill spots. However, minimum clients still satisfied",
            context.output[1])

        # next we clear the nodes and start inducing errors for not being able to fill the open spots
        self.nodemgr.nodes = []
        with self.assertLogs(network_logger, 'DEBUG') as context:
            await self.nodemgr._fill_open_connection_spots()
        self.assertIn("Found 2 open pool spots, trying to add nodes...",
                      context.output[0])
        self.assertIn("Increasing pool spot error count to 1",
                      context.output[1])

        with self.assertLogs(network_logger, 'DEBUG') as context:
            await self.nodemgr._fill_open_connection_spots()
        self.assertIn("Found 2 open pool spots, trying to add nodes...",
                      context.output[0])
        self.assertIn("Increasing pool spot error count to 2",
                      context.output[1])

        # 3rd time we reached our threshold
        # let's also setup an address in POOR state that should be reset to NEW
        addr = payloads.NetworkAddress(address='127.0.0.1:1111')
        addr.set_state_poor()
        node.NeoNode.addresses = [addr]
        with self.assertLogs(network_logger, 'DEBUG') as context:
            await self.nodemgr._fill_open_connection_spots()
        self.assertIn("Found 2 open pool spots, trying to add nodes...",
                      context.output[0])
        self.assertIn("Recycling old addresses", context.output[1])
        self.assertEqual(0, self.nodemgr.MAX_NODE_POOL_ERROR_COUNT)
        self.assertTrue(node.NeoNode.addresses[0].is_state_new)
Ejemplo n.º 10
0
    async def test_fill_open_connection_spots_dont_queue_addr_that_is_already_queued(self):
        fake_protocol = object()
        self.node1 = node.NeoNode(fake_protocol)

        # ensure we have an address that can be connected to
        addr = payloads.NetworkAddress(address='127.0.0.1:1111')
        # create 1 open spot
        self.nodemgr.max_clients = 2
        node.NeoNode.addresses = [addr]
        # and ensure we pretend we have already queued this address
        self.nodemgr.queued_addresses = [addr]

        with self.assertLogs(network_logger, 'DEBUG') as context:
            with mock.patch('asyncio.create_task'):
                await self.nodemgr._fill_open_connection_spots()
        self.assertIn("Found 1 open pool spots", context.output[0])
        # context.output length should only contain the above debug message, nothing more
        self.assertEqual(1, len(context.output))
Ejemplo n.º 11
0
    def _connect_done_cb(self, future) -> None:
        node_instance, failure = future.result()
        # failures here are hard failures from asyncio's loop.create_connection()
        if failure:
            logger.debug(f"Failed to connect to {failure[0]} reason: {failure[1]}.")
            tmp_addr = payloads.NetworkAddress(address=failure[0])

            with suppress(ValueError):
                idx = node.NeoNode.addresses.index(tmp_addr)
                addr = node.NeoNode.addresses[idx]
                addr.set_state_dead()
                self.queued_addresses.remove(tmp_addr)

            msgrouter.on_client_connect_done(None, failure)
        else:
            msgrouter.on_client_connect_done(node_instance, None)
            node_instance.start_message_handler()

        self.tasks.remove(future)
Ejemplo n.º 12
0
    def __init__(self, protocol):
        self.protocol = protocol
        #: payloads.NetworkAddress: Address of the remote endpoint.
        self.address = payloads.NetworkAddress(
            state=payloads.AddressState.DEAD)
        self.nodeid: int = id(self)  #: int: Unique identifier.
        self.nodeid_human: str = encode_base62(
            self.nodeid)  #: str: Human readable id.
        self.version = None
        self.tasks = []
        self.nodeweight = nodeweight.NodeWeight(self.nodeid)
        self.best_height: int = 0  #: int: Best block height of node.
        self.best_height_last_update = datetime.utcnow().timestamp()

        self._read_task = None  # type: asyncio.Task
        #: bool: Whether the node is in the process of disconnecting and shutting down its tasks.
        self.disconnecting: bool = False

        #: Dict[message.MessageType, Callable[[message.Message], None]]: A table matching message types to handler
        #: functions.
        self.dispatch_table: Dict[message.MessageType, Callable[
            [message.Message], None]] = {
                message.MessageType.ADDR: self.handler_addr,
                message.MessageType.BLOCK: self.handler_block,
                message.MessageType.CONSENSUS: self.handler_consensus,
                message.MessageType.INV: self.handler_inv,
                message.MessageType.FILTERADD: self.handler_filteradd,
                message.MessageType.FILTERCLEAR: self.handler_filterclear,
                message.MessageType.FILTERLOAD: self.handler_filterload,
                message.MessageType.GETADDR: self.handler_getaddr,
                message.MessageType.GETBLOCKS: self.handler_getblocks,
                message.MessageType.GETBLOCKDATA: self.handler_getblockdata,
                message.MessageType.GETDATA: self.handler_getdata,
                message.MessageType.GETHEADERS: self.handler_getheaders,
                message.MessageType.HEADERS: self.handler_headers,
                message.MessageType.MEMPOOL: self.handler_mempool,
                message.MessageType.MERKLEBLOCK: self.handler_merkleblock,
                message.MessageType.PING: self.handler_ping,
                message.MessageType.PONG: self.handler_pong,
                message.MessageType.TRANSACTION: self.handler_transaction
            }