From 22823ee88c1d9b11ad3c7cec48288382b3ac3b2f Mon Sep 17 00:00:00 2001 From: "Kieran R. Prasch" Date: Fri, 7 Sep 2018 05:49:34 -0700 Subject: [PATCH] Executes node learning from CLI --- cli/main.py | 30 +++++++++++++++++++++++------- nucypher/characters.py | 12 +++++++----- nucypher/network/middleware.py | 4 ++-- nucypher/utilities/sandbox.py | 2 +- tests/cli/test_run_ursula.py | 13 +++++++++++-- 5 files changed, 44 insertions(+), 17 deletions(-) diff --git a/cli/main.py b/cli/main.py index 6f23b0d07..5d19e0f11 100755 --- a/cli/main.py +++ b/cli/main.py @@ -6,6 +6,8 @@ import random import sys import subprocess +from urllib.parse import urlparse + from constant_sorrow import constants from nucypher.blockchain.eth.actors import Miner @@ -17,6 +19,7 @@ from nucypher.config.constants import DEFAULT_CONFIG_ROOT, DEFAULT_SIMULATION_PO BASE_DIR from nucypher.config.metadata import write_node_metadata, collect_stored_nodes from nucypher.config.parsers import parse_nucypher_ini_config, parse_running_modes +from nucypher.utilities.sandbox import UrsulaProcessProtocol __version__ = '0.1.0-alpha.0' @@ -662,6 +665,7 @@ def status(config, provider, contracts, network): @cli.command() @click.option('--federated-only', is_flag=True, default=False) +@click.option('--teacher-uri', type=str) @click.option('--seed-node', is_flag=True, default=False) @click.option('--rest-port', type=int, default=DEFAULT_REST_PORT) @click.option('--dht-port', type=int, default=DEFAULT_DHT_PORT) @@ -670,8 +674,12 @@ def status(config, provider, contracts, network): @click.option('--data-dir', type=click.Path(), default=DEFAULT_CONFIG_ROOT) @click.option('--config-file', type=click.Path(), default=DEFAULT_INI_FILEPATH) def run_ursula(rest_port, dht_port, db_name, - checksum_address, federated_only, - seed_node, data_dir, config_file) -> None: + teacher_uri, + checksum_address, + federated_only, + seed_node, + data_dir, + config_file) -> None: """ The following procedure is required to "spin-up" an Ursula node. @@ -703,16 +711,24 @@ def run_ursula(rest_port, dht_port, db_name, asyncio.set_event_loop(asyncio.new_event_loop()) # 2. Init DHT async loop + if teacher_uri: + host, port = teacher_uri.split(':') + teacher = Ursula(rest_host=host, + rest_port=port, + db_name='ursula-{}.db'.format(rest_port), + federated_only=federated_only) + + overrides['known_nodes'] = (teacher, ) + # 3. Initialize Ursula (includes overrides) - ursula = Ursula.from_config(filepath=config_file, overrides=overrides) + ursula = Ursula.from_config(filepath=config_file, + overrides=overrides) ursula.dht_listen() # 4. Start DHT - write_node_metadata(seed_node=seed_node, node=ursula, node_metadata_dir=data_dir) - - if not seed_node: - ursula.start_learning_loop() # 5. Enter learning loop + # write_node_metadata(seed_node=seed_node, node=ursula, node_metadata_dir=data_dir) + ursula.start_learning_loop() # 5. Enter learning loop ursula.get_deployer().run() # 6. Run TLS Deployer if not federated_only: diff --git a/nucypher/characters.py b/nucypher/characters.py index 66eb4533b..582c099a5 100644 --- a/nucypher/characters.py +++ b/nucypher/characters.py @@ -136,30 +136,32 @@ class Character: # Identity and Network # if is_me is True: - self._known_nodes = {} # type: dict + self._known_nodes = {} # type: dict self.treasure_maps = {} # type: dict self.network_middleware = network_middleware or RestMiddleware() ##### LEARNING STUFF (Maybe move to a different class?) ##### + self._learning_listeners = defaultdict(list) # type: DefaultDict self._node_ids_to_learn_about_immediately = set() # type: set for node in known_nodes: self.remember_node(node) - self.teacher_nodes = deque() # type: deque - self._current_teacher_node = None # type: Ursula + self.teacher_nodes = deque() # type: deque + self._current_teacher_node = None # type: Ursula self._learning_task = task.LoopingCall(self.keep_learning_about_nodes) - self._learning_round = 0 # type: int + self._learning_round = 0 # type: int self._rounds_without_new_nodes = 0 # type: int if always_be_learning: self.start_learning_loop(now=start_learning_on_same_thread) + ##### try: signing_power = self._crypto_power.power_ups(SigningPower) # type: SigningPower - self._stamp = signing_power.get_signature_stamp() # type: SignatureStamp + self._stamp = signing_power.get_signature_stamp() # type: SignatureStamp except NoSigningPower: self._stamp = constants.NO_SIGNING_POWER diff --git a/nucypher/network/middleware.py b/nucypher/network/middleware.py index 043c68b85..2f5630d36 100644 --- a/nucypher/network/middleware.py +++ b/nucypher/network/middleware.py @@ -62,10 +62,10 @@ class RestMiddleware: # nodes matching these ids, then it will ask other nodes via the DHT or whatever. pass if announce_nodes: - response = requests.post("https://{}/node_metadata".format(address), + response = requests.post("https://{}/node_metadata".format(url), verify=False, data=bytes().join(bytes(n) for n in announce_nodes)) # TODO: TLS-only. else: - response = requests.get("https://{}node_metadata".format(address), + response = requests.get("https://{}node_metadata".format(url), verify=False) # TODO: TLS-only. return response diff --git a/nucypher/utilities/sandbox.py b/nucypher/utilities/sandbox.py index f193d6a52..da403d7f0 100644 --- a/nucypher/utilities/sandbox.py +++ b/nucypher/utilities/sandbox.py @@ -132,7 +132,7 @@ def make_ursulas(ether_addresses: list, event_loop.run_until_complete( ursula.dht_server.bootstrap( [("localhost", starting_port + _c) for _c in range(len(ursulas))])) - ursula.publish_dht_information() + # ursula.publish_dht_information() return ursulas diff --git a/tests/cli/test_run_ursula.py b/tests/cli/test_run_ursula.py index 2eb39bd4e..df3fc366a 100644 --- a/tests/cli/test_run_ursula.py +++ b/tests/cli/test_run_ursula.py @@ -3,6 +3,15 @@ from click.testing import CliRunner from cli.main import cli -def test_run_ursula(): +def test_run_federated_ursulas(): runner = CliRunner() - result = runner.invoke(cli, ['run_ursula'], catch_exceptions=False) + # result = runner.invoke(cli, + # ['run_ursula', '--federated-only', '--rest-port', '5431'], + # catch_exceptions=False) + + result_with_teacher = runner.invoke(cli, + ['run_ursula', '--federated-only', + '--teacher-uri', 'localhost:5556'], + catch_exceptions=False) + +