mirror of https://github.com/nucypher/nucypher.git
OK, fixtures are implemented in the tests that need them.
parent
2f0b483ba3
commit
0084b14a3d
|
@ -122,4 +122,4 @@ def test_character_with_encrypting_power_can_encrypt():
|
|||
ciphertext, signature = can_sign_and_encrypt.encrypt_for(ursula, cleartext, sign=False)
|
||||
assert signature == NOT_SIGNED
|
||||
|
||||
assert ciphertext is not None # annnd fail.
|
||||
assert ciphertext is not None
|
||||
|
|
|
@ -1,38 +1,36 @@
|
|||
import asyncio
|
||||
import datetime
|
||||
|
||||
import msgpack
|
||||
import pytest
|
||||
|
||||
from kademlia.utils import digest
|
||||
from nkms.characters import Ursula, Character
|
||||
from nkms.network.blockchain_client import list_all_ursulas
|
||||
from nkms.network import blockchain_client
|
||||
from nkms.network.protocols import dht_value_splitter
|
||||
from nkms.policy.constants import NON_PAYMENT
|
||||
from nkms.policy.models import PolicyOffer, Policy
|
||||
from tests.utilities import MockNetworkyStuff, ALICE
|
||||
from nkms.policy.models import Policy
|
||||
from tests.utilities import MockNetworkyStuff, EVENT_LOOP, URSULA_PORT, NUMBER_OF_URSULAS_IN_NETWORK
|
||||
|
||||
|
||||
def test_all_ursulas_know_about_all_other_ursulas():
|
||||
def test_all_ursulas_know_about_all_other_ursulas(fake_ursulas):
|
||||
"""
|
||||
Once launched, all Ursulas know about - and can help locate - all other Ursulas in the network.
|
||||
"""
|
||||
ignorance = []
|
||||
for acounter, announcing_ursula in enumerate(list_all_ursulas()):
|
||||
for counter, propagating_ursula in enumerate(URSULAS):
|
||||
for acounter, announcing_ursula in enumerate(blockchain_client._ursulas_on_blockchain):
|
||||
for counter, propagating_ursula in enumerate(fake_ursulas):
|
||||
if not digest(announcing_ursula) in propagating_ursula.server.storage:
|
||||
ignorance.append((counter, acounter))
|
||||
if ignorance:
|
||||
pytest.fail(str(["{} didn't know about {}".format(counter, acounter) for counter, acounter in ignorance]))
|
||||
|
||||
|
||||
def test_vladimir_illegal_interface_key_does_not_propagate():
|
||||
def test_vladimir_illegal_interface_key_does_not_propagate(fake_ursulas):
|
||||
"""
|
||||
Although Ursulas propagate each other's interface information, as demonstrated above, they do not propagate
|
||||
interface information for Vladimir, an Evil Ursula.
|
||||
"""
|
||||
vladimir = URSULAS[0]
|
||||
ursula = URSULAS[1]
|
||||
vladimir = fake_ursulas[0]
|
||||
ursula = fake_ursulas[1]
|
||||
|
||||
# Ursula hasn't seen any illegal keys.
|
||||
assert ursula.server.protocol.illegal_keys_seen == []
|
||||
|
@ -50,44 +48,44 @@ def test_vladimir_illegal_interface_key_does_not_propagate():
|
|||
assert digest(illegal_key) in ursula.server.protocol.illegal_keys_seen
|
||||
|
||||
|
||||
def test_alice_cannot_offer_policy_without_first_finding_ursula():
|
||||
def test_alice_cannot_offer_policy_without_first_finding_ursula(alice, bob, fake_ursulas):
|
||||
"""
|
||||
Alice can't just offer a Policy if she doesn't know whether any Ursulas are available (she gets Ursula.NotFound).
|
||||
"""
|
||||
networky_stuff = MockNetworkyStuff(URSULAS)
|
||||
policy = Policy(ALICE, BOB)
|
||||
networky_stuff = MockNetworkyStuff(fake_ursulas)
|
||||
policy = Policy(alice, bob)
|
||||
|
||||
with pytest.raises(Ursula.NotFound):
|
||||
policy_offer = policy.encrypt_payload_for_ursula()
|
||||
|
||||
|
||||
def test_trying_to_find_unknown_actor_raises_not_found():
|
||||
def test_trying_to_find_unknown_actor_raises_not_found(alice):
|
||||
"""
|
||||
Tony the test character can't make reference to a character he doesn't know about yet.
|
||||
"""
|
||||
tony_clifton = Character()
|
||||
|
||||
message = b"some_message"
|
||||
signature = ALICE.seal(message)
|
||||
signature = alice.seal(message)
|
||||
|
||||
# Tony can't reference Alice...
|
||||
with pytest.raises(Character.NotFound):
|
||||
verification = tony_clifton.verify_from(ALICE, signature, message)
|
||||
verification = tony_clifton.verify_from(alice, signature, message)
|
||||
|
||||
# ...before learning about Alice.
|
||||
tony_clifton.learn_about_actor(ALICE)
|
||||
verification, NO_DECRYPTION_PERFORMED = tony_clifton.verify_from(ALICE, signature, message)
|
||||
tony_clifton.learn_about_actor(alice)
|
||||
verification, NO_DECRYPTION_PERFORMED = tony_clifton.verify_from(alice, signature, message)
|
||||
|
||||
assert verification is True
|
||||
|
||||
|
||||
def test_alice_finds_ursula():
|
||||
def test_alice_finds_ursula(alice, fake_ursulas):
|
||||
"""
|
||||
With the help of any Ursula, Alice can find a specific Ursula.
|
||||
"""
|
||||
ursula_index = 1
|
||||
all_ursulas = list_all_ursulas()
|
||||
getter = ALICE.server.get(all_ursulas[ursula_index])
|
||||
all_ursulas = blockchain_client._ursulas_on_blockchain
|
||||
getter = alice.server.get(all_ursulas[ursula_index])
|
||||
loop = asyncio.get_event_loop()
|
||||
value = loop.run_until_complete(getter)
|
||||
_signature, _ursula_pubkey_sig, _hrac, interface_info = dht_value_splitter(value.lstrip(b"uaddr-"),
|
||||
|
@ -100,76 +98,68 @@ def test_alice_creates_policy_group_with_correct_hrac(alices_policy_group):
|
|||
"""
|
||||
Alice creates a PolicyGroup. It has the proper HRAC, unique per her, Bob, and the uri (resource_id).
|
||||
"""
|
||||
alice = alices_policy_group.alice
|
||||
bob = alices_policy_group.bob
|
||||
|
||||
assert policy_group.hrac() == policy_group.hash(bytes(ALICE.seal) + bytes(BOB.seal) + ALICE.__resource_id)
|
||||
return policy_group
|
||||
assert alices_policy_group.hrac() == alices_policy_group.hash(
|
||||
bytes(alice.seal) + bytes(bob.seal) + alice.__resource_id)
|
||||
|
||||
|
||||
def test_alice_enacts_policies_in_policy_group_via_rest():
|
||||
def test_alice_enacts_policies_in_policy_group_via_rest(enacted_policy_group):
|
||||
"""
|
||||
Now that Alice has made a PolicyGroup, she can enact its policies, using Ursula's Public Key to encrypt each offer
|
||||
and transmitting them via REST.
|
||||
"""
|
||||
policy_group = test_alice_creates_policy_group_with_correct_hrac()
|
||||
|
||||
# Alice has a policy in mind and knows of enough qualifies Ursulas; she crafts an offer for them.
|
||||
deposit = NON_PAYMENT
|
||||
contract_end_datetime = datetime.datetime.now() + datetime.timedelta(days=5)
|
||||
offer = PolicyOffer(policy_group.n, deposit, contract_end_datetime)
|
||||
|
||||
networky_stuff = MockNetworkyStuff(URSULAS)
|
||||
policy_group.find_n_ursulas(networky_stuff, offer)
|
||||
policy_group.enact_policies(networky_stuff)
|
||||
|
||||
kfrag_that_was_set = policy_group.policies[0].ursula.keystore.get_kfrag(policy_group.hrac())
|
||||
assert bool(kfrag_that_was_set)
|
||||
return policy_group
|
||||
ursula = enacted_policy_group.policies[0].ursula
|
||||
kfrag_that_was_set = ursula.keystore.get_kfrag(enacted_policy_group.hrac())
|
||||
assert bool(kfrag_that_was_set) # TODO: This can be a more poignant assertion.
|
||||
|
||||
|
||||
def test_alice_sets_treasure_map_on_network():
|
||||
def test_alice_sets_treasure_map_on_network(enacted_policy_group, fake_ursulas):
|
||||
"""
|
||||
Having enacted all the policies of a PolicyGroup, Alice creates a TreasureMap and sends it to Ursula via the DHT.
|
||||
"""
|
||||
policy_group = test_alice_enacts_policies_in_policy_group_via_rest()
|
||||
|
||||
setter, encrypted_treasure_map, packed_encrypted_treasure_map, signature_for_bob, signature_for_ursula = ALICE.publish_treasure_map(
|
||||
policy_group)
|
||||
alice = enacted_policy_group.alice
|
||||
setter, encrypted_treasure_map, packed_encrypted_treasure_map, signature_for_bob, signature_for_ursula = alice.publish_treasure_map(
|
||||
enacted_policy_group)
|
||||
_set_event = EVENT_LOOP.run_until_complete(setter)
|
||||
|
||||
treasure_map_as_set_on_network = URSULAS[0].server.storage[
|
||||
digest(policy_group.treasure_map_dht_key())]
|
||||
treasure_map_as_set_on_network = fake_ursulas[0].server.storage[
|
||||
digest(enacted_policy_group.treasure_map_dht_key())]
|
||||
assert treasure_map_as_set_on_network == b"trmap" + packed_encrypted_treasure_map
|
||||
return treasure_map_as_set_on_network, signature_for_bob, policy_group
|
||||
|
||||
|
||||
def test_treasure_map_with_bad_id_does_not_propagate():
|
||||
def test_treasure_map_with_bad_id_does_not_propagate(alices_policy_group, fake_ursulas):
|
||||
"""
|
||||
In order to prevent spam attacks, Ursula refuses to propagate a TreasureMap whose PolicyGroup ID does not comport to convention.
|
||||
"""
|
||||
illegal_policygroup_id = "This is not a conventional policygroup id"
|
||||
policy_group = test_alice_creates_policy_group_with_correct_hrac()
|
||||
alice = alices_policy_group.alice
|
||||
bob = alices_policy_group.bob
|
||||
treasure_map = alices_policy_group.treasure_map
|
||||
|
||||
treasure_map = policy_group.treasure_map
|
||||
|
||||
encrypted_treasure_map, signature = ALICE.encrypt_for(BOB, treasure_map.packed_payload())
|
||||
encrypted_treasure_map, signature = alice.encrypt_for(bob, treasure_map.packed_payload())
|
||||
packed_encrypted_treasure_map = msgpack.dumps(encrypted_treasure_map) # TODO: #114? Do we even need to pack here?
|
||||
|
||||
setter = ALICE.server.set(illegal_policygroup_id, packed_encrypted_treasure_map)
|
||||
setter = alice.server.set(illegal_policygroup_id, packed_encrypted_treasure_map)
|
||||
_set_event = EVENT_LOOP.run_until_complete(setter)
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
URSULAS[0].server.storage[digest(illegal_policygroup_id)]
|
||||
fake_ursulas[0].server.storage[digest(illegal_policygroup_id)]
|
||||
|
||||
|
||||
def test_treasure_map_stored_by_ursula_is_the_correct_one_for_bob():
|
||||
def test_treasure_map_stored_by_ursula_is_the_correct_one_for_bob(fake_ursulas, enacted_policy_group):
|
||||
"""
|
||||
The TreasureMap given by Alice to Ursula is the correct one for Bob; he can decrypt and read it.
|
||||
"""
|
||||
treasure_map_as_set_on_network = fake_ursulas[0].server.storage[
|
||||
digest(enacted_policy_group.treasure_map_dht_key())]
|
||||
|
||||
treasure_map_as_set_on_network, signature, policy_group = test_alice_sets_treasure_map_on_network()
|
||||
_signature_for_ursula, pubkey_sig_alice, hrac, encrypted_treasure_map = dht_value_splitter(
|
||||
treasure_map_as_set_on_network[5::], msgpack_remainder=True) # 5:: to account for prepended "trmap"
|
||||
|
||||
assert False # TODO: Get Alice's signature to Bob.
|
||||
|
||||
verified, treasure_map_as_decrypted_by_bob = BOB.verify_from(ALICE, signature,
|
||||
encrypted_treasure_map,
|
||||
decrypt=True,
|
||||
|
@ -179,32 +169,33 @@ def test_treasure_map_stored_by_ursula_is_the_correct_one_for_bob():
|
|||
assert verified is True
|
||||
|
||||
|
||||
def test_bob_can_retreive_the_treasure_map_and_decrypt_it():
|
||||
def test_bob_can_retreive_the_treasure_map_and_decrypt_it(enacted_policy_group, fake_ursulas):
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
treasure_map_as_set_on_network, signature, policy_group = test_alice_sets_treasure_map_on_network()
|
||||
networky_stuff = MockNetworkyStuff(URSULAS)
|
||||
bob = enacted_policy_group.bob
|
||||
networky_stuff = MockNetworkyStuff(fake_ursulas)
|
||||
|
||||
# Of course, in the real world, Bob has sufficient information to reconstitute a PolicyGroup, gleaned, we presume,
|
||||
# through a side-channel with Alice.
|
||||
treasure_map_from_wire = BOB.get_treasure_map(policy_group, signature)
|
||||
assert False # TODO: Get Alice's signature to Bob.
|
||||
treasure_map_from_wire = BOB.get_treasure_map(enacted_policy_group, signature)
|
||||
|
||||
assert policy_group.treasure_map == treasure_map_from_wire
|
||||
assert enacted_policy_group.treasure_map == treasure_map_from_wire
|
||||
|
||||
|
||||
def test_treaure_map_is_legit():
|
||||
def test_treaure_map_is_legit(enacted_policy_group):
|
||||
"""
|
||||
Sure, the TreasureMap can get to Bob, but we also need to know that each Ursula in the TreasureMap is on the network.
|
||||
"""
|
||||
treasure_map_as_set_on_network, signature, policy_group = test_alice_sets_treasure_map_on_network()
|
||||
|
||||
for ursula_interface_id in policy_group.treasure_map:
|
||||
getter = ALICE.server.get(ursula_interface_id)
|
||||
alice = enacted_policy_group.alice
|
||||
for ursula_interface_id in enacted_policy_group.treasure_map:
|
||||
getter = alice.server.get(ursula_interface_id)
|
||||
loop = asyncio.get_event_loop()
|
||||
value = loop.run_until_complete(getter)
|
||||
signature, ursula_pubkey_sig, hrac, interface_info = dht_value_splitter(value.lstrip(b"uaddr-"),
|
||||
return_remainder=True)
|
||||
port = msgpack.loads(interface_info)[0]
|
||||
assert port in URSULA_PORTS
|
||||
legal_ports = range(NUMBER_OF_URSULAS_IN_NETWORK, NUMBER_OF_URSULAS_IN_NETWORK + URSULA_PORT)
|
||||
assert port in legal_ports
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
from tests.utilities import BOB, URSULAS
|
||||
from tests.utilities import EVENT_LOOP
|
||||
|
||||
|
||||
def test_bob_can_follow_treasure_map():
|
||||
def test_bob_can_follow_treasure_map(enacted_policy_group, fake_ursulas):
|
||||
"""
|
||||
Upon receiving a TreasureMap, Bob populates his list of Ursulas with the correct number.
|
||||
"""
|
||||
assert len(BOB._ursulas) == 0
|
||||
_treasure_map_as_set_on_network, _signature, policy_group = test_alice_sets_treasure_map_on_network()
|
||||
BOB.follow_treasure_map(policy_group.treasure_map)
|
||||
assert len(BOB._ursulas) == len(URSULAS)
|
||||
alice = enacted_policy_group.alice
|
||||
bob = enacted_policy_group.bob
|
||||
assert len(bob._ursulas) == 0
|
||||
|
||||
setter, encrypted_treasure_map, packed_encrypted_treasure_map, signature_for_bob, signature_for_ursula = alice.publish_treasure_map(
|
||||
enacted_policy_group)
|
||||
_set_event = EVENT_LOOP.run_until_complete(setter)
|
||||
|
||||
bob.follow_treasure_map(enacted_policy_group.treasure_map)
|
||||
assert len(bob._ursulas) == len(fake_ursulas)
|
||||
|
|
|
@ -3,15 +3,12 @@ import asyncio
|
|||
from apistar.test import TestClient
|
||||
from sqlalchemy.engine import create_engine
|
||||
|
||||
from nkms.characters import Ursula, Alice, congregate, Bob
|
||||
from nkms.characters import Ursula, Alice, Bob
|
||||
from nkms.keystore import keystore
|
||||
from nkms.keystore.db import Base
|
||||
from nkms.network.node import NetworkyStuff
|
||||
|
||||
ALICE = Alice()
|
||||
ALICE.attach_server()
|
||||
ALICE.server.listen(8471)
|
||||
ALICE.__resource_id = b"some_resource_id"
|
||||
|
||||
|
||||
NUMBER_OF_URSULAS_IN_NETWORK = 6
|
||||
|
||||
|
@ -21,13 +18,6 @@ asyncio.set_event_loop(EVENT_LOOP)
|
|||
URSULA_PORT = 7468
|
||||
NUMBER_OF_URSULAS_IN_NETWORK = 6
|
||||
|
||||
EVENT_LOOP.run_until_complete(ALICE.server.bootstrap([("127.0.0.1", URSULA_PORT)]))
|
||||
|
||||
BOB = Bob(alice=ALICE)
|
||||
BOB.attach_server()
|
||||
BOB.server.listen(8475)
|
||||
EVENT_LOOP.run_until_complete(BOB.server.bootstrap([("127.0.0.1", URSULA_PORT)]))
|
||||
|
||||
|
||||
def make_fake_ursulas(how_many_ursulas: int, ursula_starting_port: int) -> list:
|
||||
"""
|
||||
|
@ -35,7 +25,6 @@ def make_fake_ursulas(how_many_ursulas: int, ursula_starting_port: int) -> list:
|
|||
:param ursula_starting_port: The port of the first created Ursula; subsequent Ursulas will increment the port number by 1.
|
||||
:return: A list of created Ursulas
|
||||
"""
|
||||
|
||||
event_loop = asyncio.get_event_loop()
|
||||
|
||||
URSULAS = []
|
||||
|
@ -54,7 +43,7 @@ def make_fake_ursulas(how_many_ursulas: int, ursula_starting_port: int) -> list:
|
|||
ursula.server.bootstrap([("127.0.0.1", ursula_starting_port + _c) for _c in range(how_many_ursulas)]))
|
||||
ursula.publish_interface_information()
|
||||
|
||||
return URSULAS, range(ursula_starting_port, ursula_starting_port + len(URSULAS))
|
||||
return URSULAS # , range(ursula_starting_port, ursula_starting_port + len(URSULAS))
|
||||
|
||||
|
||||
class MockPolicyOfferResponse(object):
|
||||
|
@ -81,7 +70,3 @@ class MockNetworkyStuff(NetworkyStuff):
|
|||
mock_client = TestClient(ursula.rest_app)
|
||||
response = mock_client.post('http://localhost/kFrag/{}'.format(hrac.hex()), payload)
|
||||
return True, ursula.interface_dht_key()
|
||||
|
||||
|
||||
URSULAS, URSULA_PORTS = make_fake_ursulas(NUMBER_OF_URSULAS_IN_NETWORK, URSULA_PORT)
|
||||
congregate(ALICE, BOB, URSULAS[0])
|
||||
|
|
Loading…
Reference in New Issue