initial specifications refactor commit

pull/1555/head
damon 2020-01-03 17:24:43 -08:00
parent 072bf76e1b
commit 52551da5da
13 changed files with 186 additions and 207 deletions

View File

@ -18,6 +18,7 @@ cryptography = ">=2.3"
pysha3="*"
requests = "*"
sqlalchemy = "*"
marshmallow = "*"
maya = "*"
flask = "*"
flask_sqlalchemy = "*"

10
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "2a36b4160cdf1d70dbdb8ae0113c35e7e2f4cf97bff4088c9ca0133c45f592b1"
"sha256": "da7b7364c172c115fa1d88b6e6e35128dfde996366b51b08e2c3b1eacff52387"
},
"pipfile-spec": 6,
"requires": {
@ -483,6 +483,14 @@
],
"version": "==1.1.1"
},
"marshmallow": {
"hashes": [
"sha256:0ba81b6da4ae69eb229b74b3c741ff13fe04fb899824377b1aff5aaa1a9fd46e",
"sha256:3e53dd9e9358977a3929e45cdbe4a671f9eff53a7d6a23f33ed3eab8c1890d8f"
],
"index": "pypi",
"version": "==3.3.0"
},
"maya": {
"hashes": [
"sha256:7f53e06d5a123613dce7c270cbc647643a6942590dba7a19ec36194d0338c3f4",

View File

@ -1,59 +0,0 @@
-i https://pypi.python.org/simple
aafigure==0.6
alabaster==0.7.12
ansible==2.9.2
apipkg==1.5
attrs==19.3.0
babel==2.7.0
bumpversion==0.5.3
certifi==2019.11.28
cffi==1.13.2
chardet==3.0.4
commonmark==0.9.1
coverage==5.0.1
cryptography==2.8
decorator==4.4.1
docutils==0.16rc1
execnet==1.7.1
git+https://github.com/nucypher/py-solc.git@391b8da1a6bac5816877197bda25527c6b0b8c15#egg=py-solc
greenlet==0.4.15
idna==2.8
imagesize==1.1.0
importlib-metadata==1.3.0 ; python_version < '3.8'
jinja2==2.10.3
markupsafe==1.1.1
more-itertools==8.0.2
mypy-extensions==0.4.3
mypy==0.761
packaging==19.2
pluggy==0.13.1
py==1.8.0
pycparser==2.19
pygments==2.5.2
pyparsing==2.4.5
pytest-cov==2.8.1
pytest-forked==1.1.3
pytest-mock==1.13.0
pytest-mypy==0.4.2
pytest-twisted==1.12
pytest-xdist==1.31.0
pytest==5.3.2
pytz==2019.3
pyyaml==5.3b1
recommonmark==0.6.0
requests==2.22.0
six==1.13.0
snowballstemmer==2.0.0
sphinx-rtd-theme==0.4.3
sphinx==2.3.1
sphinxcontrib-applehelp==1.0.1
sphinxcontrib-devhelp==1.0.1
sphinxcontrib-htmlhelp==1.0.2
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.2
sphinxcontrib-serializinghtml==1.1.3
typed-ast==1.4.0
typing-extensions==3.7.4.1
urllib3==1.25.7
wcwidth==0.1.7
zipp==0.6.0

View File

@ -1,3 +1,8 @@
from .bob import specifications as bob
from .alice import specifications as alice
from .enrico import specifications as enrico
from abc import ABC
from collections import namedtuple
@ -33,6 +38,32 @@ class CharacterSpecification(ABC):
k: spec.get(k, ())
for k in ['input', 'optional', 'output']})
@classmethod
def get_spec(cls, interface_name: str) -> tuple:
if cls._specifications is NotImplemented:
raise NotImplementedError("Missing specifications for character")
try:
spec = cls.specifications()[interface_name]
except KeyError:
raise cls.SpecificationError(f"{cls.__class__.__name__} has no such control interface: '{interface_name}'")
return spec
@classmethod
def get_specifications(cls, interface_name: str) -> tuple:
spec = cls.get_spec(interface_name)
if isinstance(spec, dict):
return SpecificationTuple(**{
k: spec.get(k, ())
for k in ['input', 'optional', 'output']})
return SpecificationTuple(
[k for k, f in spec.load_fields.items() if f.required],
[k for k, f in spec.load_fields.items() if not f.required],
list(spec.dump_fields.keys())
)
@classmethod
def specifications(cls):
if cls._specifications is NotImplemented:
@ -65,56 +96,14 @@ class CharacterSpecification(ABC):
_, _, output_specification = self.get_specifications(interface_name=interface_name)
return self.__validate(specification=output_specification, data=response, error_class=self.InvalidInputField)
class AliceSpecification(CharacterSpecification):
__create_policy = {'input': ('bob_encrypting_key', 'bob_verifying_key', 'm', 'n', 'label', 'expiration'),
'optional': ('value', 'rate'),
'output': ('label', 'policy_encrypting_key')}
__derive_policy_encrypting_key = {'input': ('label', ),
'output': ('policy_encrypting_key', 'label')}
__grant = {'input': ('bob_encrypting_key', 'bob_verifying_key', 'm', 'n', 'label', 'expiration'),
'optional': ('value', 'rate'),
'output': ('treasure_map', 'policy_encrypting_key', 'alice_verifying_key')}
__revoke = {'input': ('label', 'bob_verifying_key', ),
'output': ('failed_revocations',)}
__decrypt = {'input': ('label', 'message_kit'),
'output': ('cleartexts', )}
__public_keys = {'input': (),
'output': ('alice_verifying_key',)}
_specifications = {'create_policy': __create_policy, # type: Tuple[Tuple[str]]
'derive_policy_encrypting_key': __derive_policy_encrypting_key,
'grant': __grant,
'revoke': __revoke,
'public_keys': __public_keys,
'decrypt': __decrypt, }
_specifications = alice
class BobSpecification(CharacterSpecification):
__join_policy = {'input': ('label', 'alice_verifying_key'),
'output': ('policy_encrypting_key', )}
__retrieve = {'input': ('label', 'policy_encrypting_key', 'alice_verifying_key', 'message_kit'),
'output': ('cleartexts', )}
__public_keys = {'input': (),
'output': ('bob_encrypting_key', 'bob_verifying_key')}
_specifications = {'join_policy': __join_policy,
'retrieve': __retrieve,
'public_keys': __public_keys}
_specifications = bob
class EnricoSpecification(CharacterSpecification):
__encrypt_message = {'input': ('message', ),
'output': ('message_kit', 'signature')}
_specifications = {'encrypt_message': __encrypt_message}
_specifications = enrico

View File

@ -0,0 +1,68 @@
from marshmallow import Schema
from .fields import fields
class PolicyBaseSchema(Schema):
#required input fields
bob_encrypting_key = fields.Key(required=True, load_only=True)
bob_verifying_key = fields.Key(required=True, load_only=True)
m = fields.Integer(required=True, load_only=True)
n = fields.Integer(required=True, load_only=True)
expiration = fields.Date(required=True, load_only=True)
# optional input
value = fields.Integer(load_only=True)
first_period_reward = fields.Integer(load_only=True)
rate = fields.Integer(load_only=True)
#output
policy_encrypting_key = fields.Key(dump_only=True)
class CreatePolicy(PolicyBaseSchema):
label = fields.Str(required=True)
class GrantPolicy(PolicyBaseSchema):
treasure_map = fields.TreasureMap(dump_only=True)
alice_verifying_key = fields.Key(dump_only=True)
label = fields.Str(load_only=True, required=True)
class DerivePolicyEncryptionKey(Schema):
label = fields.Str(required=True)
policy_encrypting_key = fields.Key(dump_only=True)
class Revoke(Schema):
label = fields.Str(required=True, load_only=True)
bob_verifying_key = fields.Key(required=True, load_only=True)
failed_revocations = fields.List(fields.Str(), dump_only=True)
class Decrypt(Schema):
label = fields.Str(required=True, load_only=True)
message_kit = fields.MessageKit(load_only=True)
cleartexts = fields.List(fields.Str(), dump_only=True)
class PublicKeys(Schema):
alice_verifying_key = fields.Key(dump_only=True)
specifications = {
'create_policy': CreatePolicy(),
'derive_policy_encrypting_key': DerivePolicyEncryptionKey(),
'grant': GrantPolicy(),
'revoke': Revoke(),
'public_keys': PublicKeys(),
'decrypt': Decrypt(),
}

View File

@ -0,0 +1,13 @@
__join_policy = {'input': ('label', 'alice_verifying_key'),
'output': ('policy_encrypting_key', )}
__retrieve = {'input': ('label', 'policy_encrypting_key', 'alice_verifying_key', 'message_kit'),
'output': ('cleartexts', )}
__public_keys = {'input': (),
'output': ('bob_encrypting_key', 'bob_verifying_key')}
specifications = {'join_policy': __join_policy,
'retrieve': __retrieve,
'public_keys': __public_keys}

View File

@ -0,0 +1,5 @@
__encrypt_message = {'input': ('message', ),
'output': ('message_kit', 'signature')}
specifications = {'encrypt_message': __encrypt_message}

View File

@ -0,0 +1,7 @@
from marshmallow import fields
from .key import *
from .treasuremap import *
from .messagekit import *

View File

@ -0,0 +1,12 @@
from marshmallow import fields
class KeyField(fields.Field):
def _serialize(self, value, attr, obj, **kwargs):
return value
def _deserialize(self, value, attr, data, **kwargs):
return value
fields.Key = KeyField

View File

@ -0,0 +1,12 @@
from marshmallow import fields
class MessageKitField(fields.Field):
def _serialize(self, value, attr, obj, **kwargs):
return value
def _deserialize(self, value, attr, data, **kwargs):
return value
fields.MessageKit = MessageKitField

View File

@ -0,0 +1,12 @@
from marshmallow import fields
class TreasureMapField(fields.Field):
def _serialize(self, value, attr, obj, **kwargs):
return value
def _deserialize(self, value, attr, data, **kwargs):
return value
fields.TreasureMap = TreasureMapField

View File

@ -1,102 +0,0 @@
-i https://pypi.python.org/simple
appdirs==1.4.3
argh==0.26.2
asn1crypto==1.2.0
attrdict==2.0.1
attrs==19.3.0
autobahn==19.11.1
automat==0.8.0
base58==1.0.3
blake2b-py==0.1.3
bytestring-splitter==1.3.0
cached-property==1.5.1
certifi==2019.11.28
cffi==1.13.2
chardet==3.0.4
click==7.0
coincurve==13.0.0
colorama==0.4.3
constant-sorrow==0.1.0a8
constantly==15.1.0
cryptography==2.8
cytoolz==0.10.1 ; implementation_name == 'cpython'
dateparser==0.7.2
eth-abi==2.1.0
eth-account==0.4.0
eth-bloom==1.0.3
eth-hash[pycryptodome]==0.2.0
eth-keyfile==0.5.1
eth-keys==0.2.4
eth-rlp==0.1.2
eth-tester==0.4.0b1
eth-typing==2.2.1
eth-utils==1.8.4
flask-limiter==1.1.0
flask-sqlalchemy==2.4.1
flask==1.1.1
hendrix==3.2.5
hexbytes==0.2.0
humanize==0.5.1
hyperlink==19.0.0
idna==2.8
importlib-metadata==1.3.0 ; python_version < '3.8'
incremental==17.5.0
ipfshttpclient==0.4.12
itsdangerous==1.1.0
jinja2==2.10.3
jsonschema==3.2.0
limits==1.4.1
lru-dict==1.1.6
markupsafe==1.1.1
maya==0.6.1
more-itertools==8.0.2
msgpack-python==0.5.6
multiaddr==0.0.9
mypy-extensions==0.4.3
netaddr==0.7.19
parsimonious==0.8.1
pathtools==0.1.2
pendulum==2.0.5
protobuf==3.11.2
py-ecc==1.7.1
py-evm==0.3.0a12
py-geth==2.2.0
pyasn1-modules==0.2.7
pyasn1==0.4.8
pychalk==2.0.1
pycparser==2.19
pycryptodome==3.9.4
pyethash==0.1.27
pyhamcrest==1.9.0
pynacl==1.3.0
pyopenssl==19.1.0
pyrsistent==0.15.6
pysha3==1.0.2
python-dateutil==2.8.1
pytz==2019.3
pytzdata==2019.3
pyyaml==5.3b1
regex==2019.12.20
requests==2.22.0
rlp==1.2.0
semantic-version==2.8.4
sentry-sdk==0.9.0
service-identity==18.1.0
six==1.13.0
snaptime==0.2.4
sqlalchemy==1.3.12
toolz==0.10.0
trie==1.4.0
twisted==19.10.0
txaio==18.8.1
typing-extensions==3.7.4.1
tzlocal==2.0.0
umbral==0.1.3a2
urllib3==1.25.7
varint==1.0.2
watchdog==0.9.0
web3==5.4.0
websockets==8.1
werkzeug==0.16.0
zipp==0.6.0
zope.interface==4.7.1

View File

@ -0,0 +1,13 @@
import pytest
from marshmallow.exceptions import ValidationError
from nucypher.characters.control.specifications import AliceSpecification
def test_alice_spec_validate(federated_alice, federated_bob):
createPolicy = AliceSpecification.get_spec('create_policy')
specs = AliceSpecification.get_specifications('create_policy')
with pytest.raises(ValidationError) as e:
result = createPolicy.load({})