Esempio n. 1
0
    def test_split(self):
        a = Address('127.0.0.1:80')
        host, port = a.split(':')
        self.assertEqual(host, '127.0.0.1')
        self.assertEqual(port, '80')

        host, port = a.rsplit(':', maxsplit=1)
        self.assertEqual(host, '127.0.0.1')
        self.assertEqual(port, '80')
Esempio n. 2
0
    def test_list_lookup(self):
        a = Address('127.0.0.1:80')
        b = Address('127.0.0.2:80')
        c = Address('127.0.0.1:80')
        d = Address('127.0.0.1:99')

        z = [a, b]
        self.assertTrue(a in z)
        self.assertTrue(b in z)
        # duplicate check, equals to 'a'
        self.assertTrue(c in z)
        self.assertFalse(d in z)
Esempio n. 3
0
 def _check_for_consecutive_disconnects(self, error_name):
     now = datetime.datetime.utcnow().timestamp()
     FIVE_MINUTES = 5 * 60
     if self.address.last_connection != 0 and now - self.address.last_connection < FIVE_MINUTES:
         self.leader.AddDeadAddress(self.address, reason=f"{self.prefix} second {error_name} within 5 minutes")
     else:
         self.address.last_connection = Address.Now()
Esempio n. 4
0
 def buildProtocol(self, addr):
     print(f"building new protocol for addr: {addr}")
     self.leader.AddKnownAddress(
         Address(f"{addr.host}:{addr.port}"))
     p = NeoNode(incoming_client=True)
     p.factory = self
     return p
Esempio n. 5
0
 def RemoteNodePeerReceived(self, host, port, via_node_addr):
     addr = Address("%s:%s" % (host, port))
     if addr not in self.KNOWN_ADDRS and addr not in self.DEAD_ADDRS:
         logger.debug(
             f"Adding new address {addr:>21} to known addresses list, received from {via_node_addr}"
         )
         # we always want to save new addresses in case we lose all active connections before we can request a new list
         self.KNOWN_ADDRS.append(addr)
Esempio n. 6
0
    def test_repr_and_str(self):
        host = '127.0.0.1:80'
        a = Address(host, last_connection_to=0)
        self.assertEqual(host, str(a))

        x = repr(a)
        self.assertIn("Address", x)
        self.assertIn(host, x)
Esempio n. 7
0
        def conn_setup(node: NeoNode):
            with self.assertLogHandler('network', 10) as log:
                # setup last_connection, to indicate we've lost connection before
                node.address.last_connection = Address.Now(
                )  # returns a timestamp of utcnow()

                # setup the heartbeat data to have last happened 25 seconds ago
                # if we disconnect now we should get a premature disconnect
                node.start_outstanding_data_request[
                    HEARTBEAT_BLOCKS] = Address.Now() - 25

                # now lose the connection
                node.connectionLost(failure.Failure(error.ConnectionLost()))

            self.assertIn("Premature disconnect", log.output[-2])
            self.assertIn(str(error.ConnectionLost()), log.output[-1])

            self.assertIn(self.addr, self.leader.DEAD_ADDRS)
            self.assertNotIn(self.addr, self.leader.KNOWN_ADDRS)
            self.assertNotIn(self.addr, self.leader.Peers)

            self.assertFalse(node.has_tasks_running())
Esempio n. 8
0
    def connectionLost(self, reason=None):
        """Callback handler from twisted when a connection was lost."""
        try:
            self.connected = False
            self.stop_block_loop()
            self.stop_peerinfo_loop()
            self.stop_header_loop()

            self.ReleaseBlockRequests()
            self.leader.RemoveConnectedPeer(self)

            time_expired = self.time_expired(HEARTBEAT_BLOCKS)
            # some NEO-cli versions have a 30s timeout to receive block/consensus or tx messages. By default neo-python doesn't respond to these requests
            if time_expired > 20:
                self.address.last_connection = Address.Now()
                self.leader.AddDeadAddress(
                    self.address, reason=f"{self.prefix} Premature disconnect")

            if reason and reason.check(twisted_error.ConnectionDone):
                # this might happen if they close our connection because they've reached max peers or something similar
                logger.debug(
                    f"{self.prefix} disconnected normally with reason:{reason.value}"
                )
                self._check_for_consecutive_disconnects("connection done")

            elif reason and reason.check(twisted_error.ConnectionLost):
                # Can be due to a timeout. Only if this happened again within 5 minutes do we label the node as bad
                # because then it clearly doesn't want to talk to us or we have a bad connection to them.
                # Otherwise allow for the node to be queued again by NodeLeader.
                logger.debug(
                    f"{self.prefix} disconnected with connectionlost reason: {reason.value}"
                )
                self._check_for_consecutive_disconnects("connection lost")

            else:
                logger.debug(
                    f"{self.prefix} disconnected with reason: {reason.value}")
        except Exception as e:
            logger.error("Error with connection lost: %s " % e)

        def try_me(err):
            err.check(error.ConnectionAborted)

        if self.disconnect_deferred:
            d, self.disconnect_deferred = self.disconnect_deferred, None  # type: defer.Deferred
            d.addErrback(try_me)
            if len(d.callbacks) > 0:
                d.callback(reason)
            else:
                print("connLost, disconnect_deferred cancelling!")
                d.cancel()
Esempio n. 9
0
    def test_show_nodes(self):
        # query nodes with no NodeLeader.Instance()
        with patch('neo.Network.NodeLeader.NodeLeader.Instance'):
            args = ['nodes']
            res = CommandShow().execute(args)
            self.assertFalse(res)

        # query nodes with connected peers
        # first make sure we have a predictable state
        NodeLeader.Instance().Reset()
        leader = NodeLeader.Instance()
        addr1 = Address("127.0.0.1:20333")
        addr2 = Address("127.0.0.1:20334")
        leader.ADDRS = [addr1, addr2]
        leader.DEAD_ADDRS = [Address("127.0.0.1:20335")]
        test_node = NeoNode()
        test_node.host = "127.0.0.1"
        test_node.port = 20333
        test_node.address = Address("127.0.0.1:20333")
        leader.Peers = [test_node]

        # now show nodes
        with patch('neo.Network.NeoNode.NeoNode.Name',
                   return_value="test name"):
            args = ['nodes']
            res = CommandShow().execute(args)
            self.assertTrue(res)
            self.assertIn('Total Connected: 1', res)
            self.assertIn('Peer 0', res)

            # now use "node"
            args = ['node']
            res = CommandShow().execute(args)
            self.assertTrue(res)
            self.assertIn('Total Connected: 1', res)
            self.assertIn('Peer 0', res)
Esempio n. 10
0
    def setUp(self):
        self.node = None
        self.leader = NodeLeader.Instance()

        host, port = '127.0.0.1', 8080
        self.addr = Address(f"{host}:{port}")

        # we use a helper class such that we do not have to setup a real TCP connection
        peerAddress = IPv4Address('TCP', host, port)
        self.endpoint = TestTransportEndpoint(
            self.leader.reactor, str(self.addr),
            proto_helpers.StringTransportWithDisconnection(
                peerAddress=peerAddress))

        # store our deferred so we can add callbacks
        self.d = self.leader.SetupConnection(self.addr, self.endpoint)
        # make sure we create a fully running client
        self.d.addCallback(self.do_handshake)
Esempio n. 11
0
        def conn_setup(node: NeoNode):
            # at this point we should have a fully connected node, so lets try to simulate a connection lost by the other side
            with self.assertLogHandler('network', 10) as log:
                # setup last_connection, to indicate we've lost connection before
                node.address.last_connection = Address.Now(
                )  # returns a timestamp of utcnow()

                # now lose the connection
                node.connectionLost(failure.Failure(error.ConnectionLost()))

            self.assertIn("second connection lost within 5 minutes",
                          log.output[-1])
            self.assertIn(str(error.ConnectionLost()), log.output[-2])

            self.assertIn(self.addr, self.leader.DEAD_ADDRS)
            self.assertNotIn(self.addr, self.leader.KNOWN_ADDRS)
            self.assertNotIn(self.addr, self.leader.Peers)

            self.assertFalse(node.has_tasks_running())
Esempio n. 12
0
    def connectionMade(self):
        """Callback handler from twisted when establishing a new connection."""
        self.endpoint = self.transport.getPeer()
        # get the reference to the Address object in NodeLeader so we can manipulate it properly.
        tmp_addr = Address(f"{self.endpoint.host}:{self.endpoint.port}")
        try:
            known_idx = self.leader.KNOWN_ADDRS.index(tmp_addr)
            self.address = self.leader.KNOWN_ADDRS[known_idx]
        except ValueError:
            # Not found.
            self.leader.AddKnownAddress(tmp_addr)
            self.address = tmp_addr

        self.address.address = "%s:%s" % (self.endpoint.host, self.endpoint.port)
        self.host = self.endpoint.host
        self.port = int(self.endpoint.port)
        self.leader.AddConnectedPeer(self)
        self.leader.RemoveFromQueue(self.address)
        self.leader.peers_connecting -= 1
        logger.debug(f"{self.address} connection established")
        if self.incoming_client:
            # start protocol
            self.SendVersion()
Esempio n. 13
0
    def test_equality(self):
        """
        Only the host:port matters in equality
        """
        a = Address('127.0.0.1:80', last_connection_to=0)
        b = Address('127.0.0.1:80', last_connection_to=0)
        c = Address('127.0.0.1:99', last_connection_to=0)
        self.assertEqual(a, b)
        self.assertNotEqual(a, c)

        # last connected does not influence equality
        b.last_connection = 123
        self.assertEqual(a, b)

        # different port does change equality
        b.address = "127.0.0.1:99"
        self.assertNotEqual(a, b)

        # test diff types
        self.assertNotEqual(int(1), a)
        self.assertNotEqual("127.0.0.1:80", a)
Esempio n. 14
0
    def Start(self,
              seed_list: List[str] = None,
              skip_seeds: bool = False) -> None:
        """
        Start connecting to the seed list.

        Args:
            seed_list: a list of host:port strings if not supplied use list from `protocol.xxx.json`
            skip_seeds: skip connecting to seed list
        """
        if not seed_list:
            seed_list = settings.SEED_LIST

        logger.debug("Starting up nodeleader")
        if not skip_seeds:
            logger.debug("Attempting to connect to seed list...")
            for bootstrap in seed_list:
                if not is_ip_address(bootstrap):
                    host, port = bootstrap.split(':')
                    bootstrap = f"{hostname_to_ip(host)}:{port}"
                addr = Address(bootstrap)
                self.KNOWN_ADDRS.append(addr)
                self.SetupConnection(addr)

        logger.debug(
            "Starting up nodeleader: starting peer, mempool, and blockheight check loops"
        )
        # check in on peers every 10 seconds
        self.start_peer_check_loop()
        self.start_memcheck_loop()
        self.start_blockheight_loop()

        if settings.ACCEPT_INCOMING_PEERS and not self.incoming_server_running:

            class OneShotFactory(Factory):
                def __init__(self, leader):
                    self.leader = leader

                def buildProtocol(self, addr):
                    print(f"building new protocol for addr: {addr}")
                    self.leader.AddKnownAddress(
                        Address(f"{addr.host}:{addr.port}"))
                    p = NeoNode(incoming_client=True)
                    p.factory = self
                    return p

            def listen_err(err):
                print(f"Failed start listening server for reason: {err.value}")

            def listen_ok(value):
                self.incoming_server_running = True

            logger.debug(
                f"Starting up nodeleader: setting up listen server on port: {settings.NODE_PORT}"
            )
            server_endpoint = TCP4ServerEndpoint(self.reactor,
                                                 settings.NODE_PORT)
            listenport_deferred = server_endpoint.listen(
                OneShotFactory(leader=self))
            listenport_deferred.addCallback(listen_ok)
            listenport_deferred.addErrback(listen_err)
Esempio n. 15
0
 def test_str_formatting(self):
     a = Address('127.0.0.1:80')
     expected = "   127.0.0.1:80"
     out = f"{a:>15}"
     self.assertEqual(expected, out)
Esempio n. 16
0
    def test_config_maxpeers(self):
        # test no input and verify output confirming current maxpeers
        with patch('sys.stdout', new=StringIO()) as mock_print:
            args = ['maxpeers']
            res = CommandConfig().execute(args)
            self.assertFalse(res)
            self.assertIn(
                f"Maintaining maxpeers at {settings.CONNECTED_PEER_MAX}",
                mock_print.getvalue())

        # test changing the number of maxpeers
        with patch('sys.stdout', new=StringIO()) as mock_print:
            args = ['maxpeers', "6"]
            res = CommandConfig().execute(args)
            self.assertTrue(res)
            self.assertEqual(int(res), settings.CONNECTED_PEER_MAX)
            self.assertIn(f"Maxpeers set to {settings.CONNECTED_PEER_MAX}",
                          mock_print.getvalue())

        # test bad input
        with patch('sys.stdout', new=StringIO()) as mock_print:
            args = ['maxpeers', "blah"]
            res = CommandConfig().execute(args)
            self.assertFalse(res)
            self.assertIn("Please supply a positive integer for maxpeers",
                          mock_print.getvalue())

        # test negative number
        with patch('sys.stdout', new=StringIO()) as mock_print:
            args = ['maxpeers', "-1"]
            res = CommandConfig().execute(args)
            self.assertFalse(res)
            self.assertIn("Please supply a positive integer for maxpeers",
                          mock_print.getvalue())

        # test if the new maxpeers < settings.CONNECTED_PEER_MAX
        # first make sure we have a predictable state
        NodeLeader.Instance().Reset()
        leader = NodeLeader.Instance()
        addr1 = Address("127.0.0.1:20333")
        addr2 = Address("127.0.0.1:20334")
        leader.ADDRS = [addr1, addr2]
        leader.DEAD_ADDRS = [Address("127.0.0.1:20335")]
        test_node = NeoNode()
        test_node.host = "127.0.0.1"
        test_node.port = 20333
        test_node.address = Address("127.0.0.1:20333")
        test_node2 = NeoNode()
        test_node2.host = "127.0.0.1"
        test_node2.port = 20333
        test_node2.address = Address("127.0.0.1:20334")
        leader.Peers = [test_node, test_node2]

        with patch(
                "neo.Network.NeoNode.NeoNode.Disconnect") as mock_disconnect:
            # first test if the number of connected peers !< new maxpeers
            with patch('sys.stdout', new=StringIO()) as mock_print:
                args = ['maxpeers', "4"]
                res = CommandConfig().execute(args)
                self.assertTrue(res)
                self.assertEqual(len(leader.Peers), 2)
                self.assertFalse(mock_disconnect.called)
                self.assertIn(f"Maxpeers set to {settings.CONNECTED_PEER_MAX}",
                              mock_print.getvalue())

            # now test if the number of connected peers < new maxpeers
            with patch('sys.stdout', new=StringIO()) as mock_print:
                args = ['maxpeers', "1"]
                res = CommandConfig().execute(args)
                self.assertTrue(res)
                self.assertEqual(len(leader.Peers), 1)
                self.assertEqual(leader.Peers[0].address, test_node.address)
                self.assertTrue(mock_disconnect.called)
                self.assertIn(f"Maxpeers set to {settings.CONNECTED_PEER_MAX}",
                              mock_print.getvalue())
Esempio n. 17
0
 def test_now_helper(self):
     n = Address.Now()
     delta = datetime.now().utcnow().timestamp() - n
     self.assertTrue(delta < 2)