예제 #1
0
    def __init__(
            self,

            # Ursula
            rest_host: str,
            rest_port: int,
            domains: Set = (
                GLOBAL_DOMAIN,
            ),  # For now, serving and learning domains will be the same.
            certificate: Certificate = None,
            certificate_filepath: str = None,
            db_filepath: str = None,
            is_me: bool = True,
            interface_signature=None,
            timestamp=None,

            # Blockchain
            identity_evidence: bytes = constants.NOT_SIGNED,
            checksum_public_address: str = None,

            # Character
            password: str = None,
            abort_on_learning_error: bool = False,
            federated_only: bool = False,
            start_learning_now: bool = None,
            crypto_power=None,
            tls_curve: EllipticCurve = None,
            known_nodes: Iterable = None,
            **character_kwargs) -> None:

        #
        # Character
        #
        self._work_orders = list()
        Character.__init__(self,
                           is_me=is_me,
                           checksum_public_address=checksum_public_address,
                           start_learning_now=start_learning_now,
                           federated_only=federated_only,
                           crypto_power=crypto_power,
                           abort_on_learning_error=abort_on_learning_error,
                           known_nodes=known_nodes,
                           domains=domains,
                           **character_kwargs)

        #
        # Self-Ursula
        #
        if is_me is True:  # TODO: 340
            self._stored_treasure_maps = dict()

            #
            # Staking Ursula
            #
            if not federated_only:
                Miner.__init__(self,
                               is_me=is_me,
                               checksum_address=checksum_public_address)

                # Access staking node via node's transacting keys  TODO: Better handle ephemeral staking self ursula
                blockchain_power = BlockchainPower(
                    blockchain=self.blockchain,
                    account=self.checksum_public_address)
                self._crypto_power.consume_power_up(blockchain_power)

                # Use blockchain power to substantiate stamp, instead of signing key
                self.substantiate_stamp(
                    password=password)  # TODO: Derive from keyring

        #
        # ProxyRESTServer and TLSHostingPower # TODO: Maybe we want _power_ups to be public after all?
        #
        if not crypto_power or (TLSHostingPower
                                not in crypto_power._power_ups):

            #
            # Ephemeral Self-Ursula
            #
            if is_me:
                self.suspicious_activities_witnessed = {
                    'vladimirs': [],
                    'bad_treasure_maps': []
                }

                #
                # REST Server (Ephemeral Self-Ursula)
                #
                rest_app, datastore = make_rest_app(
                    db_filepath=db_filepath,
                    network_middleware=self.network_middleware,
                    federated_only=self.federated_only,  # TODO: 466
                    treasure_map_tracker=self.treasure_maps,
                    node_tracker=self.known_nodes,
                    node_bytes_caster=self.__bytes__,
                    work_order_tracker=self._work_orders,
                    node_recorder=self.remember_node,
                    stamp=self.stamp,
                    verifier=self.verify_from,
                    suspicious_activity_tracker=self.
                    suspicious_activities_witnessed,
                    serving_domains=domains,
                )

                #
                # TLSHostingPower (Ephemeral Self-Ursula)
                #
                tls_hosting_keypair = HostingKeypair(
                    curve=tls_curve,
                    host=rest_host,
                    checksum_public_address=self.checksum_public_address)
                tls_hosting_power = TLSHostingPower(
                    keypair=tls_hosting_keypair, host=rest_host)
                self.rest_server = ProxyRESTServer(
                    rest_host=rest_host,
                    rest_port=rest_port,
                    rest_app=rest_app,
                    datastore=datastore,
                    hosting_power=tls_hosting_power)

            #
            # Stranger-Ursula
            #
            else:

                # TLSHostingPower
                if certificate or certificate_filepath:
                    tls_hosting_power = TLSHostingPower(
                        host=rest_host,
                        public_certificate_filepath=certificate_filepath,
                        public_certificate=certificate)
                else:
                    tls_hosting_keypair = HostingKeypair(
                        curve=tls_curve,
                        host=rest_host,
                        generate_certificate=False)
                    tls_hosting_power = TLSHostingPower(
                        host=rest_host, keypair=tls_hosting_keypair)

                # REST Server
                # Unless the caller passed a crypto power we'll make our own TLSHostingPower for this stranger.
                self.rest_server = ProxyRESTServer(
                    rest_host=rest_host,
                    rest_port=rest_port,
                    hosting_power=tls_hosting_power)

            #
            # OK - Now we have a ProxyRestServer and a TLSHostingPower for some Ursula
            #
            self._crypto_power.consume_power_up(tls_hosting_power)  # Consume!

        #
        # Verifiable Node
        #
        certificate_filepath = self._crypto_power.power_ups(
            TLSHostingPower).keypair.certificate_filepath
        certificate = self._crypto_power.power_ups(
            TLSHostingPower).keypair.certificate
        Teacher.__init__(
            self,
            domains=domains,
            certificate=certificate,
            certificate_filepath=certificate_filepath,
            interface_signature=interface_signature,
            timestamp=timestamp,
            identity_evidence=identity_evidence,
            substantiate_immediately=is_me and not federated_only,
        )

        #
        # Logging / Updating
        #
        if is_me:
            self.known_nodes.record_fleet_state(
                additional_nodes_to_track=[self])
            message = "THIS IS YOU: {}: {}".format(self.__class__.__name__,
                                                   self)
            self.log.info(message)
        else:
            message = "Initialized Stranger {} | {}".format(
                self.__class__.__name__, self)
            self.log.debug(message)
예제 #2
0
    def __init__(self,
                 influx_host: str,
                 influx_port: int,
                 crawler_http_port: int = DEFAULT_CRAWLER_HTTP_PORT,
                 registry: BaseContractRegistry = None,
                 node_storage_filepath: str = CrawlerNodeStorage.
                 DEFAULT_DB_FILEPATH,
                 refresh_rate=DEFAULT_REFRESH_RATE,
                 restart_on_error=True,
                 *args,
                 **kwargs):

        # Settings
        self.federated_only = False  # Nope - for compatibility with Learner TODO # nucypher/466
        Teacher.set_federated_mode(False)

        self.registry = registry or InMemoryContractRegistry.from_latest_publication(
        )
        self._refresh_rate = refresh_rate
        self._restart_on_error = restart_on_error

        # TODO: Needs cleanup
        # Tracking
        node_storage = CrawlerNodeStorage(
            storage_filepath=node_storage_filepath)

        class MonitoringTracker(FleetStateTracker):
            def record_fleet_state(self, *args, **kwargs):
                new_state_or_none = super().record_fleet_state(*args, **kwargs)
                if new_state_or_none:
                    _, new_state = new_state_or_none
                    state = self.abridged_state_details(new_state)
                    node_storage.store_state_metadata(state)

        self.tracker_class = MonitoringTracker

        super().__init__(save_metadata=True,
                         node_storage=node_storage,
                         *args,
                         **kwargs)
        self.log = Logger(self.__class__.__name__)
        self.log.info(
            f"Storing node metadata in DB: {node_storage.db_filepath}")
        self.log.info(
            f"Storing blockchain metadata in DB: {influx_host}:{influx_port}")

        # In-memory Metrics
        self._stats = {'status': 'initializing'}
        self._crawler_client = None

        # Initialize InfluxDB
        self._db_host = influx_host
        self._db_port = influx_port
        self._influx_client = None

        # Agency
        self.staking_agent = ContractAgency.get_agent(StakingEscrowAgent,
                                                      registry=self.registry)

        # Crawler Tasks
        self.__collection_round = 0
        self.__collecting_nodes = False  # thread tracking
        self.__collecting_stats = False
        self.__events_from_block = 0  # from the beginning
        self.__collecting_events = False

        self._node_details_task = task.LoopingCall(self._learn_about_nodes)
        self._stats_collection_task = task.LoopingCall(self._collect_stats,
                                                       threaded=True)
        self._events_collection_task = task.LoopingCall(self._collect_events)

        # JSON Endpoint
        self._crawler_http_port = crawler_http_port
        self._flask = None