mirror of https://github.com/nucypher/nucypher.git
128 lines
6.2 KiB
Python
128 lines
6.2 KiB
Python
"""
|
|
This file is part of nucypher.
|
|
|
|
nucypher is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
nucypher is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|
"""
|
|
|
|
|
|
import maya
|
|
import pytest
|
|
import time
|
|
from flask import Response
|
|
from umbral.keys import UmbralPublicKey
|
|
from unittest.mock import patch
|
|
|
|
from nucypher.characters.lawful import Ursula
|
|
from tests.utils.ursula import MOCK_KNOWN_URSULAS_CACHE
|
|
from umbral.keys import UmbralPublicKey
|
|
from nucypher.datastore.base import RecordField
|
|
from tests.mock.performance_mocks import (
|
|
NotAPublicKey,
|
|
NotARestApp,
|
|
VerificationTracker,
|
|
mock_cert_loading,
|
|
mock_cert_storage,
|
|
mock_message_verification,
|
|
mock_metadata_validation,
|
|
mock_pubkey_from_bytes,
|
|
mock_secret_source,
|
|
mock_signature_bytes,
|
|
mock_stamp_call,
|
|
mock_verify_node
|
|
)
|
|
|
|
"""
|
|
Node Discovery happens in phases. The first step is for a network actor to learn about the mere existence of a Node.
|
|
This is a straightforward step which we currently do with our own logic, but which may someday be replaced by something
|
|
like libp2p, depending on the course of development of those sorts of tools. The introduction of hamming distance
|
|
in particular is useful when wanting to learn about a small number (~500) of nodes among a much larger (25,000+) swarm.
|
|
This toolchain is not built for that scenario at this time, although it is not a stated nongoal.
|
|
|
|
After this, our "Learning Loop" does four other things in sequence which are not part of the offering of node discovery tooling alone:
|
|
|
|
* Instantiation of an actual Node object (currently, an Ursula object) from node metadata.
|
|
* Validation of the node's metadata (non-interactive; shows that the Node's public material is indeed signed by the wallet holder of its Staker).
|
|
* Verification of the Node itself (interactive; shows that the REST server operating at the Node's interface matches the node's metadata).
|
|
* Verification of the Stake (reads the blockchain; shows that the Node is sponsored by a Staker with sufficient Stake to support a Policy).
|
|
|
|
These tests show that each phase of this process is done correctly, and in some cases, with attention to specific
|
|
performance bottlenecks.
|
|
"""
|
|
|
|
|
|
def test_alice_can_learn_about_a_whole_bunch_of_ursulas(highperf_mocked_alice):
|
|
# During the fixture execution, Alice verified one node.
|
|
# TODO: Consider changing this - #1449
|
|
assert VerificationTracker.node_verifications == 1
|
|
|
|
# A quick setup so that the bytes casting of Ursulas (on what in the real world will be the remote node)
|
|
# doesn't take up all the time.
|
|
_teacher = highperf_mocked_alice.current_teacher_node()
|
|
_teacher_known_nodes_bytestring = _teacher.bytestring_of_known_nodes()
|
|
_teacher.bytestring_of_known_nodes = lambda *args, **kwargs: _teacher_known_nodes_bytestring # TODO: Formalize this? #1537
|
|
|
|
with mock_cert_storage, mock_cert_loading, mock_verify_node, mock_message_verification, mock_metadata_validation:
|
|
with mock_pubkey_from_bytes(), mock_stamp_call, mock_signature_bytes:
|
|
started = time.time()
|
|
highperf_mocked_alice.block_until_number_of_known_nodes_is(4000, learn_on_this_thread=True)
|
|
ended = time.time()
|
|
elapsed = ended - started
|
|
|
|
assert elapsed < 6 # 6 seconds is still a little long to discover 4000 out of 5000 nodes, but before starting the optimization that went with this test, this operation took about 18 minutes on jMyles' laptop.
|
|
assert VerificationTracker.node_verifications == 1 # We have only verified the first Ursula.
|
|
assert sum(
|
|
isinstance(u, Ursula) for u in highperf_mocked_alice.known_nodes) < 20 # We haven't instantiated many Ursulas.
|
|
VerificationTracker.node_verifications = 0 # Cleanup
|
|
|
|
|
|
@pytest.mark.parametrize('fleet_of_highperf_mocked_ursulas', [100], indirect=True)
|
|
def test_alice_verifies_ursula_just_in_time(fleet_of_highperf_mocked_ursulas,
|
|
highperf_mocked_alice,
|
|
highperf_mocked_bob):
|
|
# Patch the Datastore PolicyArrangement model with the highperf
|
|
# NotAPublicKey
|
|
not_public_key_record_field = RecordField(NotAPublicKey, encode=bytes,
|
|
decode=NotAPublicKey.from_bytes)
|
|
|
|
_umbral_pubkey_from_bytes = UmbralPublicKey.from_bytes
|
|
|
|
def actual_random_key_instead(*args, **kwargs):
|
|
_previous_bytes = args[0]
|
|
serial = _previous_bytes[-5:]
|
|
pubkey = NotAPublicKey(serial=serial)
|
|
return pubkey
|
|
|
|
def mock_set_policy(id_as_hex):
|
|
return ""
|
|
|
|
def mock_receive_treasure_map(treasure_map_id):
|
|
return Response(bytes(), status=202)
|
|
|
|
with NotARestApp.replace_route("receive_treasure_map", mock_receive_treasure_map):
|
|
with NotARestApp.replace_route("set_policy", mock_set_policy):
|
|
with patch('umbral.keys.UmbralPublicKey.__eq__', lambda *args, **kwargs: True):
|
|
with patch('umbral.keys.UmbralPublicKey.from_bytes',
|
|
new=actual_random_key_instead):
|
|
with patch("nucypher.datastore.models.PolicyArrangement._alice_verifying_key",
|
|
new=not_public_key_record_field):
|
|
with mock_cert_loading, mock_metadata_validation, mock_message_verification:
|
|
with mock_secret_source():
|
|
policy = highperf_mocked_alice.grant(
|
|
highperf_mocked_bob, b"any label", m=20, n=30,
|
|
expiration=maya.when('next week'),
|
|
publish_treasure_map=False)
|
|
# TODO: Make some assertions about policy.
|
|
total_verified = sum(node.verified_node for node in highperf_mocked_alice.known_nodes)
|
|
assert total_verified == 30
|