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