Code cleanup after rebase over retrieval protocol work in #2730.

pull/2768/head
derekpierre 2021-08-23 14:09:49 -04:00
parent 57bfba6d4e
commit dfa65a2976
23 changed files with 120 additions and 181 deletions

View File

@ -475,8 +475,8 @@ Parameters
+-------------------------------------------+---------------+----------------------------------------+
| **Parameter** | **Type** | **Description** |
+===========================================+===============+========================================+
| ``treasure_map`` | String | | Decrypted treasure map bytes encoded |
| | | | as base64. |
| ``treasure_map`` | String | | Unencrypted treasure map bytes |
| | | | encoded as base64. |
+-------------------------------------------+---------------+----------------------------------------+
| ``retrieval_kits`` | List[String] | | List of retrieval kits bytes encoded |
| | | | as base64. |

View File

@ -20,8 +20,8 @@ import click
import nucypher.control.specifications.fields as base_fields
from nucypher.characters.control.specifications import fields as character_fields
from nucypher.characters.control.specifications.fields.treasuremap import EncryptedTreasureMap
from nucypher.control.specifications.base import BaseSchema
from nucypher.cli import options
from nucypher.control.specifications.base import BaseSchema
class RetrieveAndDecrypt(BaseSchema):
@ -46,17 +46,6 @@ class RetrieveAndDecrypt(BaseSchema):
load_only=True,
click=options.option_message_kit(required=True)
)
# optional
treasure_map = character_fields.TreasureMap(
required=False,
load_only=True,
click=click.option(
'--treasure-map',
'-t',
help="Treasure Map for retrieve",
type=click.STRING,
required=False))
encrypted_treasure_map = EncryptedTreasureMap(required=True,
load_only=True,
click=options.option_treasure_map)

View File

@ -1,22 +0,0 @@
"""
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/>.
"""
from bytestring_splitter import BytestringSplittingError
from cryptography.exceptions import InternalError
# TODO: catch cryptography.exceptions.InternalError in PyUmbral
InvalidNativeDataTypes = (ValueError, TypeError, BytestringSplittingError, InternalError)

View File

@ -17,8 +17,7 @@
from marshmallow import fields
from nucypher.characters.control.specifications.exceptions import InvalidNativeDataTypes
from nucypher.control.specifications.exceptions import InvalidInputData
from nucypher.control.specifications.exceptions import InvalidInputData, InvalidNativeDataTypes
from nucypher.control.specifications.fields.base import BaseField
from nucypher.crypto.umbral_adapter import PublicKey

View File

@ -19,8 +19,7 @@ from base64 import b64decode, b64encode
from marshmallow import fields
from nucypher.characters.control.specifications.exceptions import InvalidNativeDataTypes
from nucypher.control.specifications.exceptions import InvalidInputData
from nucypher.control.specifications.exceptions import InvalidInputData, InvalidNativeDataTypes
from nucypher.control.specifications.fields.base import BaseField
from nucypher.policy.kits import MessageKit as MessageKitClass

View File

@ -19,8 +19,7 @@ from base64 import b64decode, b64encode
from marshmallow import fields
from nucypher.characters.control.specifications.exceptions import InvalidNativeDataTypes
from nucypher.control.specifications.exceptions import InvalidInputData
from nucypher.control.specifications.exceptions import InvalidInputData, InvalidNativeDataTypes
from nucypher.control.specifications.fields.base import BaseField
from nucypher.crypto.umbral_adapter import Signature

View File

@ -15,40 +15,30 @@
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from base64 import b64decode, b64encode
from marshmallow import fields
from nucypher.control.specifications.exceptions import InvalidInputData
from nucypher.control.specifications.fields.base import BaseField
from nucypher.policy.maps import EncryptedTreasureMap as EncryptedTreasureMapClass, TreasureMap as TreaureMapClass
from nucypher.control.specifications.fields.base import Base64BytesRepresentation
from nucypher.policy.maps import EncryptedTreasureMap as EncryptedTreasureMapClass, TreasureMap as TreasureMapClass
class EncryptedTreasureMap(BaseField, fields.Field):
class EncryptedTreasureMap(Base64BytesRepresentation):
"""
JSON Parameter representation of EncryptedTreasureMap.
"""
def _serialize(self, value, attr, obj, **kwargs):
return b64encode(bytes(value)).decode()
def _deserialize(self, value, attr, data, **kwargs):
try:
treasure_map_bytes = b64decode(value)
return EncryptedTreasureMapClass.from_bytes(treasure_map_bytes)
encrypted_treasure_map_bytes = super()._deserialize(value, attr, data, **kwargs)
return EncryptedTreasureMapClass.from_bytes(encrypted_treasure_map_bytes)
except Exception as e:
raise InvalidInputData(f"Could not convert input for {self.name} to an EncryptedTreasureMap: {e}") from e
class TreasureMap(BaseField, fields.Field):
class TreasureMap(Base64BytesRepresentation):
"""
JSON Parameter representation of (decrypted) TreasureMap.
JSON Parameter representation of (unencrypted) TreasureMap.
"""
def _serialize(self, value, attr, obj, **kwargs):
return b64encode(bytes(value)).decode()
def _deserialize(self, value, attr, data, **kwargs):
try:
treasure_map_bytes = b64decode(value)
return TreaureMapClass.from_bytes(treasure_map_bytes)
treasure_map_bytes = super()._deserialize(value, attr, data, **kwargs)
return TreasureMapClass.from_bytes(treasure_map_bytes)
except Exception as e:
raise InvalidInputData(f"Could not convert input for {self.name} to a TreaureMap: {e}") from e
raise InvalidInputData(f"Could not convert input for {self.name} to a TreasureMap: {e}") from e

View File

@ -14,6 +14,8 @@
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from bytestring_splitter import BytestringSplittingError
from cryptography.exceptions import InternalError
class SpecificationError(ValueError):
@ -34,3 +36,6 @@ class InvalidOutputData(SpecificationError):
class InvalidArgumentCombo(SpecificationError):
"""Arguments specified are incompatible"""
InvalidNativeDataTypes = (ValueError, TypeError, BytestringSplittingError, InternalError)

View File

@ -16,23 +16,22 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from typing import Optional, Callable, Union, Sequence, Dict
from typing import Optional, Callable, Sequence, Dict
from bytestring_splitter import (
BytestringSplitter,
VariableLengthBytestring,
BytestringSplittingError,
)
from constant_sorrow.constants import NO_DECRYPTION_PERFORMED, NOT_SIGNED
from eth_utils.address import to_checksum_address, to_canonical_address
from eth_typing.evm import ChecksumAddress
from eth_utils.address import to_checksum_address, to_canonical_address
from nucypher.blockchain.eth.constants import ETH_ADDRESS_BYTE_LENGTH
from nucypher.crypto.constants import EIP712_MESSAGE_SIGNATURE_SIZE
from nucypher.crypto.powers import DecryptingPower, SigningPower
from nucypher.crypto.powers import DecryptingPower
from nucypher.crypto.signing import SignatureStamp, InvalidSignature
from nucypher.crypto.splitters import signature_splitter, kfrag_splitter
from nucypher.crypto.umbral_adapter import KeyFrag, VerifiedKeyFrag, PublicKey, Signature
from nucypher.crypto.umbral_adapter import KeyFrag, VerifiedKeyFrag, Signature
from nucypher.crypto.utils import keccak_digest, verify_eip_191
from nucypher.network.middleware import RestMiddleware
from nucypher.policy.hrac import HRAC, hrac_splitter
@ -131,6 +130,9 @@ class TreasureMap:
destinations = {u: k for u, k in ursula_and_kfrags}
return cls(threshold, hrac, destinations)
def __eq__(self, other):
return bytes(self) == bytes(other)
def __iter__(self):
return iter(self.destinations.items())
@ -313,3 +315,6 @@ class EncryptedTreasureMap:
result = cls(hrac, public_signature, message_kit, blockchain_signature=blockchain_signature)
result._public_verify()
return result
def __eq__(self, other):
return bytes(self) == bytes(other)

View File

@ -21,6 +21,7 @@ from eth_typing import ChecksumAddress
from nucypher.control.interfaces import ControlInterface, attach_schema
from nucypher.crypto.umbral_adapter import PublicKey
from nucypher.policy.kits import RetrievalKit
from nucypher.policy.maps import TreasureMap
from nucypher.utilities.porter.control.specifications import porter_schema
@ -55,7 +56,7 @@ class PorterInterface(ControlInterface):
@attach_schema(porter_schema.BobRetrieveCFrags)
def retrieve_cfrags(self,
treasure_map: 'TreasureMap',
treasure_map: TreasureMap,
retrieval_kits: List[RetrievalKit],
alice_verifying_key: PublicKey,
bob_encrypting_key: PublicKey,
@ -70,6 +71,6 @@ class PorterInterface(ControlInterface):
bob_verifying_key=bob_verifying_key,
policy_encrypting_key=policy_encrypting_key,
publisher_verifying_key=publisher_verifying_key)
results = retrieval_results.results # list of RetrievalResult objects
results = retrieval_results # list of RetrievalResult objects
response_data = {'retrieval_results': results}
return response_data

View File

@ -17,8 +17,7 @@
from marshmallow import fields
from nucypher.characters.control.specifications.exceptions import InvalidNativeDataTypes
from nucypher.control.specifications.exceptions import InvalidInputData
from nucypher.control.specifications.exceptions import InvalidInputData, InvalidNativeDataTypes
from nucypher.control.specifications.fields.base import BaseField
from nucypher.policy.hrac import HRAC as HRACClass
@ -30,12 +29,7 @@ class HRAC(BaseField, fields.String):
def _deserialize(self, value, attr, data, **kwargs):
try:
return bytes.fromhex(value)
except InvalidNativeDataTypes as e:
raise InvalidInputData(f"Could not convert input for {self.name} to a valid HRAC serialization: {e}")
def _validate(self, value):
try:
HRACClass.from_bytes(value)
hrac_bytes = bytes.fromhex(value)
return HRACClass.from_bytes(hrac_bytes)
except InvalidNativeDataTypes as e:
raise InvalidInputData(f"Could not convert input for {self.name} to a valid HRAC: {e}")

View File

@ -15,11 +15,12 @@
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from marshmallow import fields
from nucypher.control.specifications.base import BaseSchema
from nucypher.control.specifications.exceptions import InvalidInputData
from nucypher.control.specifications.fields import Base64BytesRepresentation
from nucypher.crypto.kits import RetrievalKit as RetrievalKitClass
from nucypher.crypto.umbral_adapter import Capsule as CapsuleClass, CapsuleFrag as CapsuleFragClass
from nucypher.crypto.umbral_adapter import CapsuleFrag as CapsuleFragClass
from nucypher.policy.kits import RetrievalKit as RetrievalKitClass
from nucypher.utilities.porter.control.specifications.fields import UrsulaChecksumAddress
@ -34,16 +35,7 @@ class RetrievalKit(Base64BytesRepresentation):
raise InvalidInputData(f"Could not convert input for {self.name} to a valid checksum address: {e}")
class Capsule(Base64BytesRepresentation):
def _deserialize(self, value, attr, data, **kwargs):
try:
capsule_bytes = super()._deserialize(value, attr, data, **kwargs)
return CapsuleClass.from_bytes(capsule_bytes)
except Exception as e:
raise InvalidInputData(f"Could not parse {self.name}: {e}")
class CapsuleFrag(Base64BytesRepresentation):
class VerifiedCapsuleFrag(Base64BytesRepresentation):
def _deserialize(self, value, attr, data, **kwargs):
try:
capsule_frag_bytes = super()._deserialize(value, attr, data, **kwargs)
@ -54,8 +46,7 @@ class CapsuleFrag(Base64BytesRepresentation):
class RetrievalResultSchema(BaseSchema):
"""Schema for the result of retrieve_cfrags."""
capsule = Capsule()
cfrags = fields.Dict(keys=UrsulaChecksumAddress(), values=CapsuleFrag())
cfrags = fields.Dict(keys=UrsulaChecksumAddress(), values=VerifiedCapsuleFrag())
# maintain field declaration ordering
class Meta:

View File

@ -17,15 +17,15 @@
import click
from marshmallow import validates_schema
from marshmallow import fields as marshmallow_fields
from marshmallow import validates_schema
from nucypher.control.specifications.base import BaseSchema
from nucypher.control.specifications import fields as base_fields
from nucypher.control.specifications.exceptions import InvalidArgumentCombo
from nucypher.utilities.porter.control.specifications import fields
from nucypher.characters.control.specifications import fields as character_fields
from nucypher.cli import types
from nucypher.control.specifications import fields as base_fields
from nucypher.control.specifications.base import BaseSchema
from nucypher.control.specifications.exceptions import InvalidArgumentCombo
from nucypher.utilities.porter.control.specifications import fields
def option_ursula():

View File

@ -14,8 +14,6 @@
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from base64 import b64encode
import pytest
@ -34,10 +32,10 @@ def test_enrico_rpc_character_control_encrypt_message(enrico_rpc_controller_test
interface=EnricoInterface)
def test_bob_rpc_character_control_retrieve_with_tmap(
enacted_blockchain_policy, blockchain_bob, blockchain_alice,
bob_rpc_controller, retrieve_control_request):
def test_bob_rpc_character_control_retrieve_with_tmap(enacted_blockchain_policy,
blockchain_bob,
bob_rpc_controller,
retrieve_control_request):
# So that this test can run even independently.
if not blockchain_bob.done_seeding:
blockchain_bob.learn_from_teacher_node()

View File

@ -21,7 +21,6 @@ import pytest
from nucypher.control.specifications.exceptions import InvalidInputData
from nucypher.network.nodes import Learner
from nucypher.utilities.porter.control.specifications.fields import Capsule
from tests.utils.middleware import MockRestMiddleware
from tests.utils.policy import retrieval_request_setup, retrieval_params_decode_from_rest
@ -100,15 +99,10 @@ def test_retrieve_cfrags(blockchain_porter,
retrieval_results = response.data['result']['retrieval_results']
assert retrieval_results
# expected results - can only compare capsules, ursulas are randomized to obtain cfrags
# expected results - can only compare length of results, ursulas are randomized to obtain cfrags
retrieve_args = retrieval_params_decode_from_rest(retrieve_cfrags_params)
expected_results = blockchain_porter.retrieve_cfrags(**retrieve_args).results
capsule_field = Capsule()
expected_results = blockchain_porter.retrieve_cfrags(**retrieve_args)
assert len(retrieval_results) == len(expected_results)
for i, result in enumerate(retrieval_results):
# compare capsule
capsule = capsule_field._deserialize(value=result['capsule'], attr=None, data=None)
assert capsule == expected_results[i].capsule
# Failure - use encrypted treasure map
failure_retrieve_cfrags_params = dict(retrieve_cfrags_params)

View File

@ -18,8 +18,8 @@
import json
import os
from base64 import b64encode
from urllib.parse import urlencode
from nucypher.utilities.porter.control.specifications.fields import Capsule
from tests.utils.middleware import MockRestMiddleware
from tests.utils.policy import retrieval_request_setup, retrieval_params_decode_from_rest
@ -110,15 +110,10 @@ def test_retrieve_cfrags(blockchain_porter,
retrieval_results = response_data['result']['retrieval_results']
assert retrieval_results
# expected results - can only compare capsules, ursulas are randomized to obtain cfrags
# expected results - can only compare length of results, ursulas are randomized to obtain cfrags
retrieve_args = retrieval_params_decode_from_rest(retrieve_cfrags_params)
expected_results = blockchain_porter.retrieve_cfrags(**retrieve_args).results
capsule_field = Capsule()
expected_results = blockchain_porter.retrieve_cfrags(**retrieve_args)
assert len(retrieval_results) == len(expected_results)
for i, result in enumerate(retrieval_results):
# compare capsule
capsule = capsule_field._deserialize(value=result['capsule'], attr=None, data=None)
assert capsule == expected_results[i].capsule
# try same retrieval using query parameters
url_retrieve_params = dict(retrieve_cfrags_params)

View File

@ -22,14 +22,14 @@ from base64 import b64encode
import maya
import pytest
from nucypher.policy.maps import TreasureMap as TreasureMapClass
from nucypher.characters.control.specifications import fields
from nucypher.characters.control.specifications.alice import GrantPolicy
from nucypher.characters.control.specifications.fields.treasuremap import EncryptedTreasureMap
from nucypher.characters.control.specifications.fields.treasuremap import EncryptedTreasureMap, TreasureMap
from nucypher.control.specifications.base import BaseSchema
from nucypher.control.specifications.exceptions import SpecificationError, InvalidInputData, InvalidArgumentCombo
from nucypher.crypto.powers import DecryptingPower
from nucypher.crypto.umbral_adapter import PublicKey
from nucypher.policy.maps import EncryptedTreasureMap as EncryptedTreasureMapClass, TreasureMap as TreasureMapClass
def test_various_field_validations_by_way_of_alice_grant(federated_bob):
@ -52,7 +52,7 @@ def test_various_field_validations_by_way_of_alice_grant(federated_bob):
}
# validate data with both rate and value fails validation
with pytest.raises(InvalidArgumentCombo) as e:
with pytest.raises(InvalidArgumentCombo):
GrantPolicy().load(data)
# remove value and now it works
@ -62,24 +62,27 @@ def test_various_field_validations_by_way_of_alice_grant(federated_bob):
# validate that negative "m" value fails
data['threshold'] = -5
with pytest.raises(SpecificationError) as e:
with pytest.raises(SpecificationError):
GrantPolicy().load(data)
# validate that m > n fails validation
data['threshold'] = data['shares'] + 19
with pytest.raises(SpecificationError) as e:
with pytest.raises(SpecificationError):
GrantPolicy().load(data)
def test_treasuremap_validation(enacted_federated_policy):
def test_treasure_map_validation(enacted_federated_policy,
federated_bob):
"""Tell people exactly what's wrong with their treasuremaps"""
class TreasureMapsOnly(BaseSchema):
#
# encrypted treasure map
#
class EncryptedTreasureMapsOnly(BaseSchema):
tmap = EncryptedTreasureMap()
# this will raise a base64 error
with pytest.raises(SpecificationError) as e:
TreasureMapsOnly().load({'tmap': "your face looks like a treasure map"})
EncryptedTreasureMapsOnly().load({'tmap': "your face looks like a treasure map"})
# assert that field name is in the error message
assert "Could not parse tmap" in str(e)
@ -87,7 +90,7 @@ def test_treasuremap_validation(enacted_federated_policy):
# valid base64 but invalid treasuremap
with pytest.raises(InvalidInputData) as e:
TreasureMapsOnly().load({'tmap': "VGhpcyBpcyB0b3RhbGx5IG5vdCBhIHRyZWFzdXJlbWFwLg=="})
EncryptedTreasureMapsOnly().load({'tmap': "VGhpcyBpcyB0b3RhbGx5IG5vdCBhIHRyZWFzdXJlbWFwLg=="})
assert "Could not convert input for tmap to an EncryptedTreasureMap" in str(e)
assert "Invalid encrypted treasure map contents." in str(e)
@ -95,7 +98,36 @@ def test_treasuremap_validation(enacted_federated_policy):
# a valid treasuremap for once...
tmap_bytes = bytes(enacted_federated_policy.treasure_map)
tmap_b64 = b64encode(tmap_bytes)
result = TreasureMapsOnly().load({'tmap': tmap_b64.decode()})
result = EncryptedTreasureMapsOnly().load({'tmap': tmap_b64.decode()})
assert isinstance(result['tmap'], EncryptedTreasureMapClass)
#
# unencrypted treasure map
#
class UnenncryptedTreasureMapsOnly(BaseSchema):
tmap = TreasureMap()
# this will raise a base64 error
with pytest.raises(SpecificationError) as e:
UnenncryptedTreasureMapsOnly().load({'tmap': "your face looks like a treasure map"})
# assert that field name is in the error message
assert "Could not parse tmap" in str(e)
assert "Invalid base64-encoded string" in str(e)
# valid base64 but invalid treasuremap
with pytest.raises(InvalidInputData) as e:
UnenncryptedTreasureMapsOnly().load({'tmap': "VGhpcyBpcyB0b3RhbGx5IG5vdCBhIHRyZWFzdXJlbWFwLg=="})
assert "Could not convert input for tmap to a TreasureMap" in str(e)
assert "Invalid treasure map contents." in str(e)
# a valid treasuremap
decrypted_treasure_map = federated_bob._decrypt_treasure_map(enacted_federated_policy.treasure_map,
enacted_federated_policy.publisher_verifying_key)
tmap_bytes = bytes(decrypted_treasure_map)
tmap_b64 = b64encode(tmap_bytes).decode()
result = UnenncryptedTreasureMapsOnly().load({'tmap': tmap_b64})
assert isinstance(result['tmap'], TreasureMapClass)

View File

@ -21,7 +21,6 @@ import pytest
from nucypher.control.specifications.exceptions import InvalidInputData
from nucypher.network.nodes import Learner
from nucypher.utilities.porter.control.specifications.fields import Capsule
from tests.utils.policy import retrieval_request_setup, retrieval_params_decode_from_rest
@ -95,19 +94,14 @@ def test_retrieve_cfrags(federated_porter,
retrieval_results = response.data['result']['retrieval_results']
assert retrieval_results
# expected results - can only compare capsules, ursulas are randomized to obtain cfrags
# expected results - can only compare length of results, ursulas are randomized to obtain cfrags
retrieve_args = retrieval_params_decode_from_rest(retrieve_cfrags_params)
expected_results = federated_porter.retrieve_cfrags(**retrieve_args).results
capsule_field = Capsule()
expected_results = federated_porter.retrieve_cfrags(**retrieve_args)
assert len(retrieval_results) == len(expected_results)
for i, result in enumerate(retrieval_results):
# compare capsule
capsule = capsule_field._deserialize(value=result['capsule'], attr=None, data=None)
assert capsule == expected_results[i].capsule
# Failure - use encrypted treasure map
failure_retrieve_cfrags_params = dict(retrieve_cfrags_params)
_, _, random_treasure_map = random_federated_treasure_map_data
_, random_treasure_map = random_federated_treasure_map_data
failure_retrieve_cfrags_params['treasure_map'] = b64encode(bytes(random_treasure_map)).decode()
request_data = {'method': method, 'params': failure_retrieve_cfrags_params}
with pytest.raises(InvalidInputData):

View File

@ -18,8 +18,8 @@
import json
from base64 import b64encode
from urllib.parse import urlencode
from nucypher.utilities.porter.control.specifications.fields import Capsule
from tests.utils.policy import retrieval_request_setup, retrieval_params_decode_from_rest
@ -106,15 +106,10 @@ def test_retrieve_cfrags(federated_porter,
retrieval_results = response_data['result']['retrieval_results']
assert retrieval_results
# expected results - can only compare capsules, ursulas are randomized to obtain cfrags
# expected results - can only compare length of results, ursulas are randomized to obtain cfrags
retrieve_args = retrieval_params_decode_from_rest(retrieve_cfrags_params)
expected_results = federated_porter.retrieve_cfrags(**retrieve_args).results
capsule_field = Capsule()
expected_results = federated_porter.retrieve_cfrags(**retrieve_args)
assert len(retrieval_results) == len(expected_results)
for i, result in enumerate(retrieval_results):
# compare capsule
capsule = capsule_field._deserialize(value=result['capsule'], attr=None, data=None)
assert capsule == expected_results[i].capsule
# try same retrieval using query parameters
url_retrieve_params = dict(retrieve_cfrags_params)
@ -127,7 +122,7 @@ def test_retrieve_cfrags(federated_porter,
failure_retrieve_cfrags_params = dict(retrieve_cfrags_params)
# use encrypted treasure map
_, _, random_treasure_map = random_federated_treasure_map_data
_, random_treasure_map = random_federated_treasure_map_data
failure_retrieve_cfrags_params['treasure_map'] = b64encode(bytes(random_treasure_map)).decode()
response = federated_porter_web_controller.post('/retrieve_cfrags', data=json.dumps(failure_retrieve_cfrags_params))
assert response.status_code == 400 # invalid treasure map provided

View File

@ -73,4 +73,4 @@ def test_retrieve_cfrags(federated_porter,
result = federated_porter.retrieve_cfrags(**retrieval_args)
assert result, "valid result returned"
assert result, "valid result returned"

View File

@ -205,9 +205,9 @@ def test_bob_retrieve_cfrags(federated_porter,
retrieval_results = federated_porter.retrieve_cfrags(**non_encoded_retrieval_args)
expected_retrieval_results_json = []
retrieval_result_schema = RetrievalResultSchema()
for result in retrieval_results.results:
for result in retrieval_results:
data = retrieval_result_schema.dump(result)
expected_retrieval_results_json.append(data)
output = bob_retrieve_cfrags_schema.dump(obj={'retrieval_results': retrieval_results.results})
output = bob_retrieve_cfrags_schema.dump(obj={'retrieval_results': retrieval_results})
assert output == {"retrieval_results": expected_retrieval_results_json}

View File

@ -20,13 +20,10 @@ import pytest
from nucypher.control.specifications.exceptions import InvalidInputData
from nucypher.control.specifications.fields import StringList
from nucypher.crypto.kits import RetrievalKit as RetrievalKitClass
from nucypher.crypto.umbral_adapter import SecretKey, encrypt, Capsule as CapsuleClass
from nucypher.utilities.porter.control.specifications.fields import (
HRAC,
UrsulaChecksumAddress,
)
from nucypher.utilities.porter.control.specifications.fields.retrieve import RetrievalKit, Capsule
from nucypher.crypto.umbral_adapter import SecretKey, encrypt
from nucypher.policy.kits import RetrievalKit as RetrievalKitClass
from nucypher.utilities.porter.control.specifications.fields import HRAC, UrsulaChecksumAddress
from nucypher.utilities.porter.control.specifications.fields.retrieve import RetrievalKit
def test_hrac_field(enacted_federated_policy):
@ -37,11 +34,10 @@ def test_hrac_field(enacted_federated_policy):
assert serialized == bytes(hrac).hex()
deserialized = field._deserialize(value=serialized, attr=None, data=None)
assert deserialized == bytes(hrac)
assert deserialized == hrac
field._validate(value=bytes(hrac))
with pytest.raises(InvalidInputData):
field._validate(value=b'not hrac')
field._deserialize(value=b'not hrac', attr=None, data=None)
def test_ursula_checksum_address_field(get_random_checksum_address):
@ -124,19 +120,3 @@ def test_retrieval_kit_field():
with pytest.raises(InvalidInputData):
field.deserialize(value=b64encode(b"invalid_retrieval_kit_bytes").decode(), attr=None, data=None)
def test_capsule_field():
encrypting_key = SecretKey.random().public_key()
capsule, _ = encrypt(encrypting_key, b'testing_retrieval_kit')
field = Capsule()
serialized = field._serialize(value=capsule, attr=None, obj=None)
assert serialized == b64encode(bytes(capsule)).decode()
deserialized = field._deserialize(value=serialized, attr=None, data=None)
assert isinstance(deserialized, CapsuleClass)
assert deserialized == capsule
with pytest.raises(InvalidInputData):
field._deserialize(value=b64encode(b"faux_capsule").decode(), attr=None, data=None)

View File

@ -20,7 +20,7 @@ import random
import string
from typing import Dict
from nucypher.characters.control.specifications.fields import Key, DecryptedTreasureMap
from nucypher.characters.control.specifications.fields import Key, TreasureMap
from nucypher.characters.lawful import Enrico
from nucypher.crypto.powers import DecryptingPower
from nucypher.utilities.porter.control.specifications.fields import RetrievalKit
@ -47,7 +47,8 @@ def retrieval_request_setup(enacted_policy, bob, alice, encode_for_rest=False) -
bob.start_learning_loop()
bob.follow_treasure_map(treasure_map=treasure_map, block=True, timeout=1)
decrypted_map = treasure_map.as_decrypted_map()
decrypted_treasure_map = bob._decrypt_treasure_map(enacted_policy.treasure_map,
enacted_policy.publisher_verifying_key)
# We'll test against just a single Ursula - here, we make a WorkOrder for just one.
# We can pass any number of capsules as args; here we pass just one.
@ -57,7 +58,7 @@ def retrieval_request_setup(enacted_policy, bob, alice, encode_for_rest=False) -
encode_bytes = (lambda field, obj: field()._serialize(value=obj, attr=None, obj=None)) if encode_for_rest else (lambda field, obj: obj)
return dict(treasure_map=encode_bytes(DecryptedTreasureMap, decrypted_map),
return dict(treasure_map=encode_bytes(TreasureMap, decrypted_treasure_map),
retrieval_kits=[encode_bytes(RetrievalKit, message_kit.as_retrieval_kit())],
alice_verifying_key=encode_bytes(Key, alice.stamp.as_umbral_pubkey()),
bob_encrypting_key=encode_bytes(Key, bob.public_keys(DecryptingPower)),
@ -67,7 +68,7 @@ def retrieval_request_setup(enacted_policy, bob, alice, encode_for_rest=False) -
def retrieval_params_decode_from_rest(retrieval_params: Dict) -> Dict:
decode_bytes = (lambda field, data: field()._deserialize(value=data, attr=None, data=None))
return dict(treasure_map=decode_bytes(DecryptedTreasureMap, retrieval_params['treasure_map']),
return dict(treasure_map=decode_bytes(TreasureMap, retrieval_params['treasure_map']),
retrieval_kits=[decode_bytes(RetrievalKit, kit) for kit in retrieval_params['retrieval_kits']],
alice_verifying_key=decode_bytes(Key, retrieval_params['alice_verifying_key']),
bob_encrypting_key=decode_bytes(Key, retrieval_params['bob_encrypting_key']),