mirror of https://github.com/nucypher/nucypher.git
191 lines
7.7 KiB
Python
191 lines
7.7 KiB
Python
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from nucypher.acumen.perception import FleetSensor
|
|
from nucypher.characters.lawful import Ursula
|
|
from nucypher.config.storages import LocalFileBasedNodeStorage
|
|
from nucypher.network.nodes import TEACHER_NODES
|
|
from tests.utils.ursula import make_ursulas
|
|
|
|
|
|
@pytest.mark.skip
|
|
def test_learner_learns_about_domains_separately(lonely_ursula_maker, caplog):
|
|
hero_learner, other_first_domain_learner = lonely_ursula_maker(
|
|
domain="nucypher1.test_suite", quantity=2
|
|
)
|
|
_nobody = lonely_ursula_maker(domain="nucypher1.test_suite", quantity=1).pop()
|
|
other_first_domain_learner.remember_node(_nobody)
|
|
|
|
second_domain_learners = lonely_ursula_maker(domain="nucypher2.test_suite", know_each_other=True, quantity=3)
|
|
|
|
assert len(hero_learner.known_nodes) == 0
|
|
|
|
# Learn from a teacher in our domain.
|
|
hero_learner.remember_node(other_first_domain_learner)
|
|
hero_learner.start_learning_loop(now=True)
|
|
hero_learner.learn_from_teacher_node()
|
|
|
|
# All domain 1 nodes
|
|
assert len(hero_learner.known_nodes) == 2
|
|
|
|
# Learn about the second domain.
|
|
hero_learner._current_teacher_node = second_domain_learners.pop()
|
|
hero_learner.learn_from_teacher_node()
|
|
|
|
# All domain 1 nodes
|
|
assert len(hero_learner.known_nodes) == 2
|
|
|
|
new_first_domain_learner = lonely_ursula_maker(domain="nucypher1.test_suite", quantity=1).pop()
|
|
_new_second_domain_learner = lonely_ursula_maker(domain="nucypher2.test_suite", quantity=1).pop()
|
|
|
|
new_first_domain_learner.remember_node(hero_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(new_first_domain_learner.known_nodes)
|
|
|
|
# However, it learned about *all* of the nodes in its own domain.
|
|
assert hero_learner in new_first_domain_learner.known_nodes
|
|
assert other_first_domain_learner in new_first_domain_learner.known_nodes
|
|
assert _nobody in new_first_domain_learner.known_nodes
|
|
|
|
|
|
@pytest.mark.skip
|
|
def test_learner_restores_metadata_from_storage(lonely_ursula_maker, tmpdir):
|
|
# Create a local file-based node storage
|
|
root = tmpdir.mkdir("known_nodes")
|
|
metadata = root.mkdir("metadata")
|
|
certs = root.mkdir("certs")
|
|
old_storage = LocalFileBasedNodeStorage(metadata_dir=Path(metadata),
|
|
certificates_dir=Path(certs),
|
|
storage_root=Path(root))
|
|
|
|
# Use the ursula maker with this storage so it's populated with nodes from one domain
|
|
_some_ursulas = lonely_ursula_maker(domain="fistro",
|
|
node_storage=old_storage,
|
|
know_each_other=True,
|
|
quantity=3,
|
|
save_metadata=True)
|
|
|
|
# Create a pair of new learners in a different domain, using the previous storage, and learn from it
|
|
new_learners = lonely_ursula_maker(domain="duodenal",
|
|
node_storage=old_storage,
|
|
quantity=2,
|
|
know_each_other=True,
|
|
save_metadata=False)
|
|
learner, buddy = new_learners
|
|
buddy._Learner__known_nodes = FleetSensor(domain="fistro")
|
|
|
|
# The learner shouldn't learn about any node from the first domain, since it's different.
|
|
learner.learn_from_teacher_node()
|
|
for restored_node in learner.known_nodes:
|
|
assert restored_node.mature().domain == learner.domain
|
|
|
|
# In fact, since the storage only contains nodes from a different domain,
|
|
# the learner should only know its buddy from the second domain.
|
|
assert set(learner.known_nodes) == {buddy}
|
|
|
|
|
|
@pytest.mark.skip
|
|
def test_learner_ignores_stored_nodes_from_other_domains(
|
|
lonely_ursula_maker, tmpdir, testerchain, ursula_test_config
|
|
):
|
|
learner, other_staker = make_ursulas(
|
|
ursula_test_config,
|
|
domain="call-it-mainnet",
|
|
quantity=2,
|
|
know_each_other=True,
|
|
staking_provider_addresses=testerchain.stake_providers_accounts[:2],
|
|
operator_addresses=testerchain.ursulas_accounts[:2],
|
|
)
|
|
|
|
pest, *other_ursulas_from_the_wrong_side_of_the_tracks = make_ursulas(
|
|
ursula_test_config,
|
|
domain="i-dunno-testt-maybe",
|
|
quantity=5,
|
|
know_each_other=True,
|
|
staking_provider_addresses=testerchain.stake_providers_accounts[2:],
|
|
operator_addresses=testerchain.ursulas_accounts[2:],
|
|
)
|
|
|
|
assert pest not in other_staker.known_nodes
|
|
assert pest not in learner.known_nodes
|
|
pest._current_teacher_node = learner
|
|
pest.learn_from_teacher_node()
|
|
assert pest not in other_staker.known_nodes
|
|
|
|
##################################
|
|
# Prior to #2423, learner remembered pest because POSTed node metadata was not domain-checked.
|
|
# This is how ibex nodes initially made their way into mainnet fleet states.
|
|
assert pest not in learner.known_nodes # But not anymore.
|
|
|
|
# Once pest made its way into learner, learner taught passed it to other mainnet nodes.
|
|
assert pest not in learner.known_nodes # But not anymore.
|
|
|
|
learner.known_nodes.record_node(pest) # This used to happen anyway.
|
|
|
|
other_staker._current_teacher_node = learner
|
|
other_staker.learn_from_teacher_node() # And once it did, the node from the wrong domain spread.
|
|
assert pest not in other_staker.known_nodes # But not anymore.
|
|
|
|
|
|
@pytest.mark.skip
|
|
def test_learner_with_empty_storage_uses_fallback_nodes(lonely_ursula_maker, mocker):
|
|
domain = "learner-domain"
|
|
mocker.patch.dict(TEACHER_NODES, {domain: ("teacher-uri",)}, clear=True)
|
|
|
|
# Create a learner and a teacher
|
|
learner, teacher = lonely_ursula_maker(domain=domain, quantity=2, save_metadata=False)
|
|
mocker.patch.object(Ursula, 'from_teacher_uri', return_value=teacher)
|
|
|
|
# Since there are no nodes in local node storage, the learner should only learn about the teacher
|
|
learner.learn_from_teacher_node()
|
|
assert set(learner.known_nodes) == {teacher}
|
|
|
|
|
|
@pytest.mark.skip
|
|
def test_learner_uses_both_nodes_from_storage_and_fallback_nodes(
|
|
lonely_ursula_maker, tmpdir, mocker, test_registry, ursula_test_config, testerchain
|
|
):
|
|
domain = "learner-domain"
|
|
mocker.patch.dict(TEACHER_NODES, {domain: ("teacher-uri",)}, clear=True)
|
|
|
|
# Create a local file-based node storage
|
|
root = tmpdir.mkdir("known_nodes")
|
|
metadata = root.mkdir("metadata")
|
|
certs = root.mkdir("certs")
|
|
node_storage = LocalFileBasedNodeStorage(metadata_dir=Path(metadata),
|
|
certificates_dir=Path(certs),
|
|
storage_root=Path(root))
|
|
|
|
# Create some nodes and persist them to local storage
|
|
other_nodes = make_ursulas(
|
|
ursula_test_config,
|
|
domain=domain,
|
|
node_storage=node_storage,
|
|
know_each_other=True,
|
|
quantity=3,
|
|
save_metadata=True,
|
|
staking_provider_addresses=testerchain.stake_providers_accounts[:3],
|
|
operator_addresses=testerchain.ursulas_accounts[:3],
|
|
)
|
|
|
|
# Create a teacher and a learner using existing node storage
|
|
learner, teacher = lonely_ursula_maker(
|
|
domain=domain,
|
|
node_storage=node_storage,
|
|
quantity=2,
|
|
know_each_other=True,
|
|
staking_provider_addresses=testerchain.stake_providers_accounts[3:],
|
|
operator_addresses=testerchain.ursulas_accounts[3:],
|
|
)
|
|
mocker.patch.object(Ursula, 'from_teacher_uri', return_value=teacher)
|
|
|
|
# The learner should learn about all nodes
|
|
learner.learn_from_teacher_node()
|
|
all_nodes = {teacher}
|
|
all_nodes.update(other_nodes)
|
|
assert set(learner.known_nodes) == all_nodes
|