mirror of https://github.com/nucypher/nucypher.git
Making a distinction between blocking until some number of nodes (any nodes) are learned and blocking until some specific set of nodes are learned.
parent
27fce61668
commit
b551067603
|
@ -314,24 +314,58 @@ class Character:
|
||||||
self._node_ids_to_learn_about_immediately.update(canonical_addresses) # hmmmm
|
self._node_ids_to_learn_about_immediately.update(canonical_addresses) # hmmmm
|
||||||
self.learn_about_nodes_now()
|
self.learn_about_nodes_now()
|
||||||
|
|
||||||
def block_until_nodes_are_known(self, canonical_addresses: Set, timeout=10, allow_missing=0,
|
# TODO: Dehydrate these next two methods.
|
||||||
learn_on_this_thread=False):
|
|
||||||
|
def block_until_number_of_known_nodes_is(self, number_of_nodes_to_know: int,
|
||||||
|
timeout=10,
|
||||||
|
learn_on_this_thread=False):
|
||||||
start = maya.now()
|
start = maya.now()
|
||||||
starting_round = self._learning_round
|
starting_round = self._learning_round
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
rounds_undertaken = self._learning_round - starting_round
|
||||||
|
if len(self._known_nodes) >= number_of_nodes_to_know:
|
||||||
|
if rounds_undertaken:
|
||||||
|
self.log.info("Learned about enough nodes after {} rounds.".format(rounds_undertaken))
|
||||||
|
return True
|
||||||
|
|
||||||
if not self._learning_task.running:
|
if not self._learning_task.running:
|
||||||
self.log.warning("Blocking to learn about nodes, but learning loop isn't running.")
|
self.log.warning("Blocking to learn about nodes, but learning loop isn't running.")
|
||||||
if learn_on_this_thread:
|
if learn_on_this_thread:
|
||||||
self.learn_from_teacher_node(eager=True)
|
self.learn_from_teacher_node(eager=True)
|
||||||
rounds_undertaken = self._learning_round - starting_round
|
|
||||||
if (maya.now() - start).seconds < timeout:
|
if (maya.now() - start).seconds > timeout:
|
||||||
if canonical_addresses.issubset(self._known_nodes):
|
if not self._learning_task.running:
|
||||||
self.log.info("Learned about all nodes after {} rounds.".format(rounds_undertaken))
|
raise self.NotEnoughUrsulas(
|
||||||
return True
|
"We didn't discover any nodes because the learning loop isn't running. Start it with start_learning().")
|
||||||
else:
|
else:
|
||||||
time.sleep(.1)
|
raise self.NotEnoughUrsulas("After {} seconds and {} rounds, didn't find {} nodes".format(
|
||||||
|
timeout, rounds_undertaken, number_of_nodes_to_know))
|
||||||
else:
|
else:
|
||||||
|
time.sleep(.1)
|
||||||
|
|
||||||
|
def block_until_specific_nodes_are_known(self,
|
||||||
|
canonical_addresses: Set,
|
||||||
|
timeout=10,
|
||||||
|
allow_missing=0,
|
||||||
|
learn_on_this_thread=False):
|
||||||
|
start = maya.now()
|
||||||
|
starting_round = self._learning_round
|
||||||
|
|
||||||
|
while True:
|
||||||
|
rounds_undertaken = self._learning_round - starting_round
|
||||||
|
if canonical_addresses.issubset(self._known_nodes):
|
||||||
|
if rounds_undertaken:
|
||||||
|
self.log.info("Learned about all nodes after {} rounds.".format(rounds_undertaken))
|
||||||
|
return True
|
||||||
|
|
||||||
|
if not self._learning_task.running:
|
||||||
|
self.log.warning("Blocking to learn about nodes, but learning loop isn't running.")
|
||||||
|
if learn_on_this_thread:
|
||||||
|
self.learn_from_teacher_node(eager=True)
|
||||||
|
|
||||||
|
if (maya.now() - start).seconds > timeout:
|
||||||
|
|
||||||
still_unknown = canonical_addresses.difference(self._known_nodes)
|
still_unknown = canonical_addresses.difference(self._known_nodes)
|
||||||
|
|
||||||
if len(still_unknown) <= allow_missing:
|
if len(still_unknown) <= allow_missing:
|
||||||
|
@ -343,6 +377,9 @@ class Character:
|
||||||
raise self.NotEnoughUrsulas("After {} seconds and {} rounds, didn't find these {} nodes: {}".format(
|
raise self.NotEnoughUrsulas("After {} seconds and {} rounds, didn't find these {} nodes: {}".format(
|
||||||
timeout, rounds_undertaken, len(still_unknown), still_unknown))
|
timeout, rounds_undertaken, len(still_unknown), still_unknown))
|
||||||
|
|
||||||
|
else:
|
||||||
|
time.sleep(.1)
|
||||||
|
|
||||||
def learn_from_teacher_node(self, eager=True):
|
def learn_from_teacher_node(self, eager=True):
|
||||||
"""
|
"""
|
||||||
Sends a request to node_url to find out about known nodes.
|
Sends a request to node_url to find out about known nodes.
|
||||||
|
@ -696,10 +733,26 @@ class Alice(Character, PolicyAuthor):
|
||||||
# Users may decide to inject some market strategies here.
|
# Users may decide to inject some market strategies here.
|
||||||
#
|
#
|
||||||
# TODO: 289
|
# TODO: 289
|
||||||
|
|
||||||
|
# If we're federated only, we need to block to make sure we have enough nodes.
|
||||||
|
if self.federated_only and len(self._known_nodes) < n:
|
||||||
|
good_to_go = self.block_until_number_of_known_nodes_is(n, learn_on_this_thread=True)
|
||||||
|
if not good_to_go:
|
||||||
|
raise ValueError(
|
||||||
|
"To make a Policy in federated mode, you need to know about\
|
||||||
|
all the Ursulas you need (in this case, {}); there's no other way to\
|
||||||
|
know which nodes to use. Either pass them here or when you make\
|
||||||
|
the Policy, or run the learning loop on a network with enough Ursulas.".format(self.n))
|
||||||
|
|
||||||
|
if len(handpicked_ursulas) < n:
|
||||||
|
number_of_ursulas_needed = n - len(handpicked_ursulas)
|
||||||
|
new_ursulas = random.sample(list(self._known_nodes.values()), number_of_ursulas_needed)
|
||||||
|
handpicked_ursulas.update(new_ursulas)
|
||||||
|
|
||||||
policy.make_arrangements(network_middleware=self.network_middleware,
|
policy.make_arrangements(network_middleware=self.network_middleware,
|
||||||
deposit=deposit,
|
deposit=deposit,
|
||||||
expiration=expiration,
|
expiration=expiration,
|
||||||
ursulas=ursulas,
|
handpicked_ursulas=handpicked_ursulas,
|
||||||
)
|
)
|
||||||
|
|
||||||
# REST call happens here, as does population of TreasureMap.
|
# REST call happens here, as does population of TreasureMap.
|
||||||
|
@ -784,14 +837,14 @@ class Bob(Character):
|
||||||
|
|
||||||
if block:
|
if block:
|
||||||
if new_thread:
|
if new_thread:
|
||||||
return threads.deferToThread(self.block_until_nodes_are_known, unknown_ursulas,
|
return threads.deferToThread(self.block_until_specific_nodes_are_known, unknown_ursulas,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
allow_missing=allow_missing)
|
allow_missing=allow_missing)
|
||||||
else:
|
else:
|
||||||
self.block_until_nodes_are_known(unknown_ursulas,
|
self.block_until_specific_nodes_are_known(unknown_ursulas,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
allow_missing=allow_missing,
|
allow_missing=allow_missing,
|
||||||
learn_on_this_thread=True)
|
learn_on_this_thread=True)
|
||||||
|
|
||||||
return unknown_ursulas, known_ursulas
|
return unknown_ursulas, known_ursulas
|
||||||
|
|
||||||
|
@ -913,7 +966,7 @@ class Bob(Character):
|
||||||
verifying=alice_verifying_key)
|
verifying=alice_verifying_key)
|
||||||
|
|
||||||
hrac, map_id = self.construct_hrac_and_map_id(alice_verifying_key, data_source.label)
|
hrac, map_id = self.construct_hrac_and_map_id(alice_verifying_key, data_source.label)
|
||||||
self.follow_treasure_map(map_id=map_id)
|
self.follow_treasure_map(map_id=map_id, block=True)
|
||||||
|
|
||||||
work_orders = self.generate_work_orders(map_id, message_kit.capsule)
|
work_orders = self.generate_work_orders(map_id, message_kit.capsule)
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ def test_bob_can_follow_treasure_map_even_if_he_only_knows_of_one_node(enacted_f
|
||||||
bob.start_learning_loop()
|
bob.start_learning_loop()
|
||||||
|
|
||||||
# ...and block until the unknown_nodes have all been found.
|
# ...and block until the unknown_nodes have all been found.
|
||||||
yield threads.deferToThread(bob.block_until_nodes_are_known, unknown_nodes)
|
yield threads.deferToThread(bob.block_until_specific_nodes_are_known, unknown_nodes)
|
||||||
|
|
||||||
# ...and he now has no more unknown_nodes.
|
# ...and he now has no more unknown_nodes.
|
||||||
print(len(bob._known_nodes))
|
print(len(bob._known_nodes))
|
||||||
|
|
|
@ -81,7 +81,7 @@ def enacted_federated_policy(idle_federated_policy, ursulas):
|
||||||
idle_federated_policy.make_arrangements(network_middleware,
|
idle_federated_policy.make_arrangements(network_middleware,
|
||||||
deposit=deposit,
|
deposit=deposit,
|
||||||
expiration=contract_end_datetime,
|
expiration=contract_end_datetime,
|
||||||
ursulas=ursulas)
|
handpicked_ursulas=ursulas)
|
||||||
idle_federated_policy.enact(network_middleware) # REST call happens here, as does population of TreasureMap.
|
idle_federated_policy.enact(network_middleware) # REST call happens here, as does population of TreasureMap.
|
||||||
|
|
||||||
return idle_federated_policy
|
return idle_federated_policy
|
||||||
|
|
Loading…
Reference in New Issue