2017-09-28 00:07:36 +00:00
|
|
|
import asyncio
|
2017-09-30 17:32:39 +00:00
|
|
|
|
2017-10-04 04:13:46 +00:00
|
|
|
import pytest
|
2017-11-07 04:42:21 +00:00
|
|
|
from kademlia.utils import digest
|
2018-04-12 03:17:39 +00:00
|
|
|
|
2018-05-08 19:35:34 +00:00
|
|
|
from nucypher.crypto.api import keccak_digest
|
2018-07-02 12:18:31 +00:00
|
|
|
from tests.utilities import MockRestMiddleware
|
2017-12-15 05:21:27 +00:00
|
|
|
|
|
|
|
|
2018-06-23 03:27:15 +00:00
|
|
|
@pytest.mark.usefixtures('testerchain')
|
2018-06-23 20:48:06 +00:00
|
|
|
def test_all_ursulas_know_about_all_other_ursulas(ursulas, three_agents):
|
2017-11-09 21:48:40 +00:00
|
|
|
"""
|
|
|
|
Once launched, all Ursulas know about - and can help locate - all other Ursulas in the network.
|
|
|
|
"""
|
2018-06-23 20:48:06 +00:00
|
|
|
token_agent, miner_agent, policy_agent = three_agents
|
|
|
|
|
2017-11-06 21:35:54 +00:00
|
|
|
ignorance = []
|
2018-06-23 20:48:06 +00:00
|
|
|
for acounter, announcing_ursula in enumerate(miner_agent.swarm()):
|
2017-11-22 06:06:52 +00:00
|
|
|
for counter, propagating_ursula in enumerate(ursulas):
|
2018-06-04 18:00:08 +00:00
|
|
|
announcing_ursula_ether_address, announcing_ursula_id = announcing_ursula
|
|
|
|
if not digest(bytes(announcing_ursula_id)) in propagating_ursula.server.storage:
|
2017-11-06 21:35:54 +00:00
|
|
|
ignorance.append((counter, acounter))
|
|
|
|
if ignorance:
|
|
|
|
pytest.fail(str(["{} didn't know about {}".format(counter, acounter) for counter, acounter in ignorance]))
|
|
|
|
|
|
|
|
|
2017-11-22 06:06:52 +00:00
|
|
|
def test_vladimir_illegal_interface_key_does_not_propagate(ursulas):
|
2017-11-09 21:48:40 +00:00
|
|
|
"""
|
|
|
|
Although Ursulas propagate each other's interface information, as demonstrated above, they do not propagate
|
2018-06-04 18:00:08 +00:00
|
|
|
interface information for Vladimir, an Evil Ursula.
|
2017-11-09 21:48:40 +00:00
|
|
|
"""
|
2018-06-23 03:27:15 +00:00
|
|
|
ursulas = list(ursulas)
|
2018-06-04 18:00:08 +00:00
|
|
|
vladimir, ursula = ursulas[0], ursulas[1]
|
2017-11-06 03:28:13 +00:00
|
|
|
|
|
|
|
# Ursula hasn't seen any illegal keys.
|
2018-06-04 18:00:08 +00:00
|
|
|
assert ursula.dht_server.protocol.illegal_keys_seen == []
|
2017-11-06 03:28:13 +00:00
|
|
|
|
|
|
|
# Vladimir does almost everything right....
|
2018-04-17 08:46:13 +00:00
|
|
|
value = vladimir.interface_info_with_metadata()
|
2017-11-06 03:28:13 +00:00
|
|
|
|
|
|
|
# Except he sets an illegal key for his interface.
|
2018-02-19 01:34:38 +00:00
|
|
|
illegal_key = b"Not allowed to set arbitrary key for this."
|
2018-06-04 18:00:08 +00:00
|
|
|
setter = vladimir.dht_server.set(key=illegal_key, value=value)
|
2017-11-06 03:28:13 +00:00
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
loop.run_until_complete(setter)
|
|
|
|
|
|
|
|
# Now Ursula has seen an illegal key.
|
2018-06-04 22:10:55 +00:00
|
|
|
assert digest(illegal_key) in ursula.dht_server.protocol.illegal_keys_seen
|
2017-10-18 08:52:01 +00:00
|
|
|
|
2017-10-28 02:26:23 +00:00
|
|
|
|
2018-06-30 03:25:36 +00:00
|
|
|
@pytest.mark.skip("What do we want this test to do now?")
|
2018-04-14 16:05:11 +00:00
|
|
|
def test_alice_finds_ursula_via_rest(alice, ursulas):
|
2018-04-17 08:46:13 +00:00
|
|
|
# Imagine alice knows of nobody.
|
2018-06-23 01:57:14 +00:00
|
|
|
alice._known_nodes = {}
|
2018-04-17 08:46:13 +00:00
|
|
|
|
2018-06-23 20:48:06 +00:00
|
|
|
some_ursula_interface = ursulas.pop().rest_interface
|
|
|
|
|
2018-06-30 02:15:56 +00:00
|
|
|
new_nodes = alice.learn_from_teacher_node()
|
2018-06-30 03:25:36 +00:00
|
|
|
|
2018-04-14 16:05:11 +00:00
|
|
|
assert len(new_nodes) == len(ursulas)
|
|
|
|
|
|
|
|
for ursula in ursulas:
|
|
|
|
assert ursula.stamp.as_umbral_pubkey() in new_nodes
|
|
|
|
|
|
|
|
|
2018-07-02 12:18:31 +00:00
|
|
|
def test_alice_creates_policy_with_correct_hrac(idle_federated_policy):
|
2017-11-09 22:28:11 +00:00
|
|
|
"""
|
2018-07-02 12:18:31 +00:00
|
|
|
Alice creates a Policy. It has the proper HRAC, unique per her, Bob, and the uri (resource_id).
|
2017-11-09 22:28:11 +00:00
|
|
|
"""
|
2018-06-30 03:25:36 +00:00
|
|
|
alice = idle_federated_policy.alice
|
|
|
|
bob = idle_federated_policy.bob
|
2017-11-09 22:28:11 +00:00
|
|
|
|
2018-06-30 03:25:36 +00:00
|
|
|
assert idle_federated_policy.hrac() == keccak_digest(
|
2018-07-02 12:18:31 +00:00
|
|
|
bytes(alice.stamp) + bytes(bob.stamp) + idle_federated_policy.label)
|
2017-11-21 03:24:03 +00:00
|
|
|
|
2017-11-21 03:50:38 +00:00
|
|
|
|
2018-06-30 02:25:42 +00:00
|
|
|
def test_alice_sets_treasure_map(enacted_federated_policy, ursulas):
|
2017-10-04 04:13:46 +00:00
|
|
|
"""
|
2017-11-21 03:50:38 +00:00
|
|
|
Having enacted all the policies of a PolicyGroup, Alice creates a TreasureMap and sends it to Ursula via the DHT.
|
2017-10-04 04:13:46 +00:00
|
|
|
"""
|
2018-06-06 08:32:25 +00:00
|
|
|
networky_stuff = MockRestMiddleware()
|
2018-06-30 03:25:36 +00:00
|
|
|
enacted_federated_policy.publish_treasure_map(network_middleare=networky_stuff)
|
2017-10-03 15:43:12 +00:00
|
|
|
|
2018-07-02 12:18:31 +00:00
|
|
|
treasure_map_as_set_on_network = list(ursulas)[0].treasure_maps[
|
|
|
|
digest(enacted_federated_policy.treasure_map.public_id())]
|
|
|
|
assert treasure_map_as_set_on_network == enacted_federated_policy.treasure_map
|
2017-10-24 00:28:10 +00:00
|
|
|
|
|
|
|
|
2018-06-30 02:25:42 +00:00
|
|
|
@pytest.mark.skip("Needs cleanup.")
|
|
|
|
def test_treasure_map_with_bad_id_does_not_propagate(idle_federated_policy, ursulas):
|
2017-11-10 00:07:25 +00:00
|
|
|
"""
|
|
|
|
In order to prevent spam attacks, Ursula refuses to propagate a TreasureMap whose PolicyGroup ID does not comport to convention.
|
|
|
|
"""
|
2018-02-19 01:34:38 +00:00
|
|
|
illegal_policygroup_id = b"This is not a conventional policygroup id"
|
2018-06-30 02:25:42 +00:00
|
|
|
alice = idle_federated_policy.alice
|
|
|
|
bob = idle_federated_policy.bob
|
|
|
|
treasure_map = idle_federated_policy.treasure_map
|
2017-11-10 00:07:25 +00:00
|
|
|
|
2018-02-13 19:13:07 +00:00
|
|
|
message_kit, signature = alice.encrypt_for(bob, treasure_map.packed_payload())
|
2017-11-10 00:07:25 +00:00
|
|
|
|
2018-06-30 03:25:36 +00:00
|
|
|
alice.network_middleware.put_treasure_map_on_node(node=ursulas[1],
|
2018-07-02 12:18:31 +00:00
|
|
|
map_id=illegal_policygroup_id,
|
|
|
|
map_payload=message_kit.to_bytes())
|
2017-11-10 00:07:25 +00:00
|
|
|
|
2018-06-06 08:33:42 +00:00
|
|
|
# setter = alice.server.set(illegal_policygroup_id, message_kit.to_bytes())
|
|
|
|
# _set_event = TEST_EVENT_LOOP.run_until_complete(setter)
|
|
|
|
|
|
|
|
# with pytest.raises(KeyError):
|
|
|
|
# _ = ursulas_on_network[0].server.storage[digest(illegal_policygroup_id)]
|
|
|
|
assert False
|
2017-11-10 00:07:25 +00:00
|
|
|
|
|
|
|
|
2018-06-30 03:25:36 +00:00
|
|
|
def test_treasure_map_stored_by_ursula_is_the_correct_one_for_bob(alice, bob, ursulas, enacted_federated_policy):
|
2017-11-09 22:28:11 +00:00
|
|
|
"""
|
|
|
|
The TreasureMap given by Alice to Ursula is the correct one for Bob; he can decrypt and read it.
|
|
|
|
"""
|
2018-07-02 12:18:31 +00:00
|
|
|
treasure_map_as_set_on_network = list(ursulas)[0].treasure_maps[
|
|
|
|
digest(enacted_federated_policy.treasure_map.public_id())]
|
2018-02-14 08:19:26 +00:00
|
|
|
|
2018-07-02 12:18:31 +00:00
|
|
|
hrac_by_bob = bob.construct_policy_hrac(alice.stamp, enacted_federated_policy.label)
|
|
|
|
assert enacted_federated_policy.hrac() == hrac_by_bob
|
2017-11-22 06:03:31 +00:00
|
|
|
|
2018-07-02 12:18:31 +00:00
|
|
|
map_id_by_bob = bob.construct_map_id(alice.stamp, enacted_federated_policy.label)
|
|
|
|
assert map_id_by_bob == treasure_map_as_set_on_network.public_id()
|
2017-10-03 15:43:12 +00:00
|
|
|
|
|
|
|
|
2018-06-30 03:25:36 +00:00
|
|
|
def test_bob_can_retreive_the_treasure_map_and_decrypt_it(enacted_federated_policy, ursulas):
|
2017-10-24 00:28:10 +00:00
|
|
|
"""
|
2017-11-09 22:28:11 +00:00
|
|
|
Above, we showed that the TreasureMap saved on the network is the correct one for Bob. Here, we show
|
|
|
|
that Bob can retrieve it with only the information about which he is privy pursuant to the PolicyGroup.
|
2017-10-24 00:28:10 +00:00
|
|
|
"""
|
2018-06-30 03:25:36 +00:00
|
|
|
bob = enacted_federated_policy.bob
|
2017-10-28 02:26:23 +00:00
|
|
|
|
2017-11-10 10:04:01 +00:00
|
|
|
# Of course, in the real world, Bob has sufficient information to reconstitute a PolicyGroup, gleaned, we presume,
|
|
|
|
# through a side-channel with Alice.
|
2018-02-25 23:37:14 +00:00
|
|
|
|
|
|
|
# If Bob doesn't know about any Ursulas, he can't find the TreasureMap via the REST swarm:
|
|
|
|
with pytest.raises(bob.NotEnoughUrsulas):
|
2018-07-02 12:18:31 +00:00
|
|
|
treasure_map_from_wire = bob.get_treasure_map(enacted_federated_policy.alice.stamp,
|
|
|
|
enacted_federated_policy.label)
|
2018-02-25 23:37:14 +00:00
|
|
|
|
|
|
|
# Let's imagine he has learned about some - say, from the blockchain.
|
2018-07-02 12:18:31 +00:00
|
|
|
bob._known_nodes = {u.canonical_public_address: u for u in ursulas}
|
2018-02-25 23:37:14 +00:00
|
|
|
|
|
|
|
# Now try.
|
2018-07-02 12:18:31 +00:00
|
|
|
treasure_map_from_wire = bob.get_treasure_map(enacted_federated_policy.alice.stamp,
|
|
|
|
enacted_federated_policy.label)
|
2017-10-27 02:46:34 +00:00
|
|
|
|
2018-06-30 03:25:36 +00:00
|
|
|
assert enacted_federated_policy.treasure_map == treasure_map_from_wire
|
2017-10-24 00:28:10 +00:00
|
|
|
|
|
|
|
|
2018-06-30 03:25:36 +00:00
|
|
|
def test_treaure_map_is_legit(enacted_federated_policy):
|
2017-11-09 22:28:11 +00:00
|
|
|
"""
|
|
|
|
Sure, the TreasureMap can get to Bob, but we also need to know that each Ursula in the TreasureMap is on the network.
|
|
|
|
"""
|
2018-07-02 12:18:31 +00:00
|
|
|
for ursula_address in enacted_federated_policy.treasure_map:
|
|
|
|
assert ursula_address in enacted_federated_policy.bob._known_nodes
|