Beispiel #1
0
    def from_teacher_uri(
        cls,
        federated_only: bool,
        teacher_uri: str,
        min_stake: int,
    ) -> 'Ursula':

        hostname, port, checksum_address = parse_node_uri(uri=teacher_uri)

        def __attempt(round=1, interval=10) -> Ursula:
            if round > 3:
                raise ConnectionRefusedError(
                    "Host {} Refused Connection".format(teacher_uri))

            try:
                teacher = cls.from_seed_and_stake_info(
                    seed_uri='{host}:{port}'.format(host=hostname, port=port),
                    federated_only=federated_only,
                    checksum_address=checksum_address,
                    minimum_stake=min_stake)

            except (socket.gaierror, requests.exceptions.ConnectionError,
                    ConnectionRefusedError):
                log = Logger(cls.__name__)
                log.warn(
                    "Can't connect to seed node (attempt {}).  Will retry in {} seconds."
                    .format(round, interval))
                time.sleep(interval)
                return __attempt(round=round + 1)
            else:
                return teacher

        return __attempt()
Beispiel #2
0
    def from_seed_and_stake_info(
            cls,
            seed_uri: str,
            federated_only: bool,
            minimum_stake: int = 0,
            checksum_address: str = None,  # TODO: Why is this unused?
            network_middleware: RestMiddleware = None,
            *args,
            **kwargs) -> 'Ursula':

        #
        # WARNING: xxx Poison xxx
        # Let's learn what we can about the ... "seednode".
        #

        if network_middleware is None:
            network_middleware = RestMiddleware()

        host, port, checksum_address = parse_node_uri(seed_uri)

        # Fetch the hosts TLS certificate and read the common name
        certificate = network_middleware.get_certificate(host=host, port=port)
        real_host = certificate.subject.get_attributes_for_oid(
            NameOID.COMMON_NAME)[0].value
        temp_node_storage = ForgetfulNodeStorage(federated_only=federated_only)
        certificate_filepath = temp_node_storage.store_node_certificate(
            certificate=certificate)
        # Load the host as a potential seed node
        potential_seed_node = cls.from_rest_url(
            host=real_host,
            port=port,
            network_middleware=network_middleware,
            certificate_filepath=certificate_filepath,
            federated_only=True,
            *args,
            **kwargs)  # TODO: 466

        potential_seed_node.certificate_filepath = certificate_filepath

        if checksum_address:
            # Ensure this is the specific node we expected
            if not checksum_address == potential_seed_node.checksum_public_address:
                template = "This seed node has a different wallet address: {} (expected {}).  Are you sure this is a seednode?"
                raise potential_seed_node.SuspiciousActivity(
                    template.format(
                        potential_seed_node.checksum_public_address,
                        checksum_address))

        # Check the node's stake (optional)
        if minimum_stake > 0:
            # TODO: check the blockchain to verify that address has more then minimum_stake. #511
            raise NotImplementedError("Stake checking is not implemented yet.")

        # Verify the node's TLS certificate
        try:
            potential_seed_node.verify_node(
                network_middleware=network_middleware,
                accept_federated_only=federated_only,
                certificate_filepath=certificate_filepath)

        except potential_seed_node.InvalidNode:
            raise  # TODO: What if our seed node fails verification?

        # OK - everyone get out
        temp_node_storage.forget()

        return potential_seed_node