Domains are now sets.

pull/574/head
jMyles 2018-12-01 13:45:23 -05:00
parent ece4bf2808
commit c6b63d641a
4 changed files with 60 additions and 8 deletions

View File

@ -16,17 +16,17 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
""" """
from contextlib import suppress from contextlib import suppress
from typing import Dict, ClassVar, Set
from typing import Optional
from typing import Tuple
from typing import Union, List
from eth_keys import KeyAPI as EthKeyAPI
from eth_utils import to_checksum_address, to_canonical_address
from typing import Dict, ClassVar, Tuple, Union, List, Optional
from constant_sorrow import constants, default_constant_splitter
from eth_keys import KeyAPI as EthKeyAPI from eth_keys import KeyAPI as EthKeyAPI
from eth_utils import to_checksum_address, to_canonical_address from eth_utils import to_checksum_address, to_canonical_address
from umbral.keys import UmbralPublicKey from umbral.keys import UmbralPublicKey
from umbral.signing import Signature from umbral.signing import Signature
from constant_sorrow import constants, default_constant_splitter
from nucypher.blockchain.eth.chains import Blockchain from nucypher.blockchain.eth.chains import Blockchain
from nucypher.crypto.api import encrypt_and_sign from nucypher.crypto.api import encrypt_and_sign
from nucypher.crypto.kits import UmbralMessageKit from nucypher.crypto.kits import UmbralMessageKit
@ -57,6 +57,7 @@ class Character(Learner):
from nucypher.crypto.signing import InvalidSignature from nucypher.crypto.signing import InvalidSignature
def __init__(self, def __init__(self,
domains: Set = (constants.GLOBAL_DOMAIN,),
is_me: bool = True, is_me: bool = True,
federated_only: bool = False, federated_only: bool = False,
blockchain: Blockchain = None, blockchain: Blockchain = None,
@ -133,6 +134,7 @@ class Character(Learner):
# Learner # Learner
# #
Learner.__init__(self, Learner.__init__(self,
domains=domains,
network_middleware=network_middleware, network_middleware=network_middleware,
*args, **kwargs) *args, **kwargs)
@ -146,7 +148,6 @@ class Character(Learner):
self.keyring_dir = constants.STRANGER self.keyring_dir = constants.STRANGER
self.network_middleware = constants.STRANGER self.network_middleware = constants.STRANGER
# #
# Decentralized # Decentralized
# #

View File

@ -20,6 +20,7 @@ from collections import OrderedDict
from functools import partial from functools import partial
from typing import Iterable from typing import Iterable
from typing import List, Dict from typing import List, Dict
from typing import Set
import maya import maya
import requests import requests
@ -32,7 +33,8 @@ from twisted.internet import threads
from umbral.keys import UmbralPublicKey from umbral.keys import UmbralPublicKey
from umbral.signing import Signature from umbral.signing import Signature
from bytestring_splitter import VariableLengthBytestring, BytestringSplittingFabricator from bytestring_splitter import BytestringSplittingFabricator
from bytestring_splitter import VariableLengthBytestring, BytestringSplitter
from constant_sorrow import constants from constant_sorrow import constants
from constant_sorrow.constants import INCLUDED_IN_BYTESTRING from constant_sorrow.constants import INCLUDED_IN_BYTESTRING
from nucypher.blockchain.eth.actors import PolicyAuthor, Miner from nucypher.blockchain.eth.actors import PolicyAuthor, Miner
@ -439,6 +441,7 @@ class Ursula(Teacher, Character, Miner):
# Ursula # Ursula
rest_host: str, rest_host: str,
rest_port: int, rest_port: int,
domains: Set = (constants.GLOBAL_DOMAIN,), # For now, serving and learning domains will be the same.
certificate: Certificate = None, certificate: Certificate = None,
certificate_filepath: str = None, certificate_filepath: str = None,
@ -476,6 +479,7 @@ class Ursula(Teacher, Character, Miner):
crypto_power=crypto_power, crypto_power=crypto_power,
abort_on_learning_error=abort_on_learning_error, abort_on_learning_error=abort_on_learning_error,
known_nodes=known_nodes, known_nodes=known_nodes,
domains=domains,
**character_kwargs) **character_kwargs)
# #
@ -565,6 +569,7 @@ class Ursula(Teacher, Character, Miner):
certificate_filepath = self._crypto_power.power_ups(TLSHostingPower).keypair.certificate_filepath certificate_filepath = self._crypto_power.power_ups(TLSHostingPower).keypair.certificate_filepath
certificate = self._crypto_power.power_ups(TLSHostingPower).keypair.certificate certificate = self._crypto_power.power_ups(TLSHostingPower).keypair.certificate
Teacher.__init__(self, Teacher.__init__(self,
domains=domains,
certificate=certificate, certificate=certificate,
certificate_filepath=certificate_filepath, certificate_filepath=certificate_filepath,
interface_signature=interface_signature, interface_signature=interface_signature,
@ -693,7 +698,8 @@ class Ursula(Teacher, Character, Miner):
nickname = nickname_from_seed(checksum_address) nickname = nickname_from_seed(checksum_address)
display_name = "{}↽ ({})".format(nickname, checksum_address) display_name = "{}↽ ({})".format(nickname, checksum_address)
message = "{} purported to be of version {}, but we're only version {}. Is there a new version of NuCypher?" message = "{} purported to be of version {}, but we're only version {}. Is there a new version of NuCypher?"
cls.log.warn(message.format(display_name, version, cls.LEARNER_VERSION)) # TODO: Some auto-updater logic? cls.log.warn(
message.format(display_name, version, cls.LEARNER_VERSION)) # TODO: Some auto-updater logic?
except ValueError as e: except ValueError as e:
message = "Unable to glean address from node that purported to be version {}. We're only version {}." message = "Unable to glean address from node that purported to be version {}. We're only version {}."
cls.log.warn(message.format(version, cls.LEARNER_VERSION)) cls.log.warn(message.format(version, cls.LEARNER_VERSION))

View File

@ -215,6 +215,7 @@ class Learner:
pass pass
def __init__(self, def __init__(self,
domains: Set,
network_middleware: RestMiddleware = __DEFAULT_MIDDLEWARE_CLASS(), network_middleware: RestMiddleware = __DEFAULT_MIDDLEWARE_CLASS(),
start_learning_now: bool = False, start_learning_now: bool = False,
learn_on_same_thread: bool = False, learn_on_same_thread: bool = False,
@ -657,6 +658,9 @@ class Learner:
new_nodes = [] new_nodes = []
for node in node_list: for node in node_list:
if GLOBAL_DOMAIN not in self.learning_domains:
if not self.learning_domains.intersection(node.serving_domains):
continue # This node is not serving any of our domains.
try: try:
if eager: if eager:
certificate_filepath = current_teacher.get_certificate_filepath( certificate_filepath = current_teacher.get_certificate_filepath(
@ -706,6 +710,7 @@ class Teacher:
invalid_metadata_message = "{} has invalid metadata. Maybe its stake is over? Or maybe it is transitioning to a new interface. Ignoring." invalid_metadata_message = "{} has invalid metadata. Maybe its stake is over? Or maybe it is transitioning to a new interface. Ignoring."
def __init__(self, def __init__(self,
domains: Set,
certificate: Certificate, certificate: Certificate,
certificate_filepath: str, certificate_filepath: str,
interface_signature=constants.NOT_SIGNED.bool_value(False), interface_signature=constants.NOT_SIGNED.bool_value(False),
@ -715,6 +720,7 @@ class Teacher:
passphrase=None, passphrase=None,
) -> None: ) -> None:
self.serving_domains = domains
self.certificate = certificate self.certificate = certificate
self.certificate_filepath = certificate_filepath self.certificate_filepath = certificate_filepath
self._interface_signature_object = interface_signature self._interface_signature_object = interface_signature

View File

@ -0,0 +1,39 @@
from functools import partial
from nucypher.utilities.sandbox.ursula import make_federated_ursulas
def test_learner_learns_about_domains_separately(ursula_federated_test_config, caplog):
lonely_ursula_maker = partial(make_federated_ursulas,
ursula_config=ursula_federated_test_config,
quantity=3,
know_each_other=True)
global_learners = lonely_ursula_maker()
first_domain_learners = lonely_ursula_maker(domains=set([b"nucypher1.test_suite"]))
second_domain_learners = lonely_ursula_maker(domains=set([b"nucypher2.test_suite"]))
big_learner = global_learners.pop()
assert len(big_learner.known_nodes) == 2
# Learn about the fist domain.
big_learner._current_teacher_node = first_domain_learners.pop()
big_learner.learn_from_teacher_node()
# Learn about the second domain.
big_learner._current_teacher_node = second_domain_learners.pop()
big_learner.learn_from_teacher_node()
assert len(big_learner.known_nodes) == 8
new_first_domain_learner = lonely_ursula_maker(domains=set([b"nucypher1.test_suite"])).pop()
new_second_domain_learner = lonely_ursula_maker(domains=set([b"nucypher2.test_suite"]))
new_first_domain_learner._current_teacher_node = big_learner
new_first_domain_learner.learn_from_teacher_node()
# This node, in the first domain, didn't learn about the second domain.
assert not set(second_domain_learners).intersection(set(new_first_domain_learner.known_nodes))
# However, it learned about *all* of the nodes in its own domain.
assert set(first_domain_learners).intersection(set(new_first_domain_learner.known_nodes)) == first_domain_learners