mirror of https://github.com/nucypher/nucypher.git
Merge pull request #1523 from KPrasch/carlin
Excavate Re-encryption logic; WorkOrder Datastore Modelspull/1543/head
commit
881a8cfd22
|
@ -17,7 +17,6 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import time
|
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
@ -26,6 +25,7 @@ from typing import Dict, Iterable, List, Set, Tuple, Union
|
||||||
|
|
||||||
import maya
|
import maya
|
||||||
import requests
|
import requests
|
||||||
|
import time
|
||||||
from bytestring_splitter import BytestringKwargifier, BytestringSplittingError
|
from bytestring_splitter import BytestringKwargifier, BytestringSplittingError
|
||||||
from bytestring_splitter import BytestringSplitter, VariableLengthBytestring
|
from bytestring_splitter import BytestringSplitter, VariableLengthBytestring
|
||||||
from constant_sorrow import constants
|
from constant_sorrow import constants
|
||||||
|
@ -38,7 +38,9 @@ from eth_utils import to_checksum_address
|
||||||
from flask import request, Response
|
from flask import request, Response
|
||||||
from twisted.internet import threads
|
from twisted.internet import threads
|
||||||
from twisted.logger import Logger
|
from twisted.logger import Logger
|
||||||
|
from umbral import pre
|
||||||
from umbral.keys import UmbralPublicKey
|
from umbral.keys import UmbralPublicKey
|
||||||
|
from umbral.kfrags import KFrag
|
||||||
from umbral.pre import UmbralCorrectnessError
|
from umbral.pre import UmbralCorrectnessError
|
||||||
from umbral.signing import Signature
|
from umbral.signing import Signature
|
||||||
|
|
||||||
|
@ -62,13 +64,13 @@ from nucypher.crypto.kits import UmbralMessageKit
|
||||||
from nucypher.crypto.powers import SigningPower, DecryptingPower, DelegatingPower, TransactingPower, PowerUpError
|
from nucypher.crypto.powers import SigningPower, DecryptingPower, DelegatingPower, TransactingPower, PowerUpError
|
||||||
from nucypher.crypto.signing import InvalidSignature
|
from nucypher.crypto.signing import InvalidSignature
|
||||||
from nucypher.keystore.keypairs import HostingKeypair
|
from nucypher.keystore.keypairs import HostingKeypair
|
||||||
|
from nucypher.keystore.threading import ThreadedSession
|
||||||
from nucypher.network.exceptions import NodeSeemsToBeDown
|
from nucypher.network.exceptions import NodeSeemsToBeDown
|
||||||
from nucypher.network.middleware import RestMiddleware, UnexpectedResponse, NotFound
|
from nucypher.network.middleware import RestMiddleware, UnexpectedResponse, NotFound
|
||||||
from nucypher.network.nicknames import nickname_from_seed
|
from nucypher.network.nicknames import nickname_from_seed
|
||||||
from nucypher.network.nodes import Teacher
|
from nucypher.network.nodes import Teacher
|
||||||
from nucypher.network.protocols import InterfaceInfo, parse_node_uri
|
from nucypher.network.protocols import InterfaceInfo, parse_node_uri
|
||||||
from nucypher.network.server import ProxyRESTServer, TLSHostingPower, make_rest_app
|
from nucypher.network.server import ProxyRESTServer, TLSHostingPower, make_rest_app
|
||||||
from nucypher.blockchain.eth.decorators import validate_checksum_address
|
|
||||||
|
|
||||||
|
|
||||||
class Alice(Character, BlockchainPolicyAuthor):
|
class Alice(Character, BlockchainPolicyAuthor):
|
||||||
|
@ -820,7 +822,6 @@ class Ursula(Teacher, Character, Worker):
|
||||||
from nucypher.config.node import CharacterConfiguration
|
from nucypher.config.node import CharacterConfiguration
|
||||||
domains = (CharacterConfiguration.DEFAULT_DOMAIN,)
|
domains = (CharacterConfiguration.DEFAULT_DOMAIN,)
|
||||||
|
|
||||||
self._work_orders = list()
|
|
||||||
Character.__init__(self,
|
Character.__init__(self,
|
||||||
is_me=is_me,
|
is_me=is_me,
|
||||||
checksum_address=checksum_address,
|
checksum_address=checksum_address,
|
||||||
|
@ -1251,21 +1252,42 @@ class Ursula(Teacher, Character, Worker):
|
||||||
return constants.BYTESTRING_IS_URSULA_IFACE_INFO + bytes(self)
|
return constants.BYTESTRING_IS_URSULA_IFACE_INFO + bytes(self)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Utilities
|
# Work Orders & Re-Encryption
|
||||||
#
|
#
|
||||||
|
|
||||||
def work_orders(self, bob=None):
|
def work_orders(self, bob=None) -> List['WorkOrder']:
|
||||||
"""
|
with ThreadedSession(self.datastore.engine):
|
||||||
TODO: This is better written as a model method for Ursula's datastore.
|
if not bob: # All
|
||||||
"""
|
return self.datastore.get_workorders()
|
||||||
if not bob:
|
else: # Filter
|
||||||
return self._work_orders
|
work_orders_from_bob = self.datastore.get_workorders(bob_verifying_key=bytes(bob.stamp))
|
||||||
else:
|
return work_orders_from_bob
|
||||||
work_orders_from_bob = []
|
|
||||||
for work_order in self._work_orders:
|
def _reencrypt(self, kfrag: KFrag, work_order: 'WorkOrder', alice_verifying_key: UmbralPublicKey):
|
||||||
if work_order.bob == bob:
|
|
||||||
work_orders_from_bob.append(work_order)
|
# Prepare a bytestring for concatenating re-encrypted
|
||||||
return work_orders_from_bob
|
# capsule data for each work order task.
|
||||||
|
cfrag_byte_stream = bytes()
|
||||||
|
for task in work_order.tasks:
|
||||||
|
|
||||||
|
# Ursula signs on top of Bob's signature of each task.
|
||||||
|
# Now both are committed to the same task. See #259.
|
||||||
|
reencryption_metadata = bytes(self.stamp(bytes(task.signature)))
|
||||||
|
|
||||||
|
# Ursula sets Alice's verifying key for capsule correctness verification.
|
||||||
|
capsule = task.capsule
|
||||||
|
capsule.set_correctness_keys(verifying=alice_verifying_key)
|
||||||
|
|
||||||
|
# Then re-encrypts the fragment.
|
||||||
|
cfrag = pre.reencrypt(kfrag, capsule, metadata=reencryption_metadata) # <--- pyUmbral
|
||||||
|
self.log.info(f"Re-encrypted capsule {capsule} -> made {cfrag}.")
|
||||||
|
|
||||||
|
# Next, Ursula signs to commit to her results.
|
||||||
|
reencryption_signature = self.stamp(bytes(cfrag))
|
||||||
|
cfrag_byte_stream += VariableLengthBytestring(cfrag) + reencryption_signature
|
||||||
|
|
||||||
|
# ... and finally returns all the re-encrypted bytes
|
||||||
|
return cfrag_byte_stream
|
||||||
|
|
||||||
|
|
||||||
class Enrico(Character):
|
class Enrico(Character):
|
||||||
|
|
|
@ -124,7 +124,7 @@ def paint_node_status(emitter, ursula, start_time):
|
||||||
'Rest Interface ...... {}'.format(ursula.rest_url()),
|
'Rest Interface ...... {}'.format(ursula.rest_url()),
|
||||||
'Node Storage Type ... {}'.format(ursula.node_storage._name.capitalize()),
|
'Node Storage Type ... {}'.format(ursula.node_storage._name.capitalize()),
|
||||||
'Known Nodes ......... {}'.format(len(ursula.known_nodes)),
|
'Known Nodes ......... {}'.format(len(ursula.known_nodes)),
|
||||||
'Work Orders ......... {}'.format(len(ursula._work_orders)),
|
'Work Orders ......... {}'.format(len(ursula.work_orders())),
|
||||||
teacher]
|
teacher]
|
||||||
|
|
||||||
if not ursula.federated_only:
|
if not ursula.federated_only:
|
||||||
|
|
|
@ -15,10 +15,10 @@ You should have received a copy of the GNU Affero General Public License
|
||||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from coincurve import PublicKey
|
|
||||||
from eth_keys import KeyAPI as EthKeyAPI
|
|
||||||
from typing import Any, Union
|
from typing import Any, Union
|
||||||
|
|
||||||
|
from coincurve import PublicKey
|
||||||
|
from eth_keys import KeyAPI as EthKeyAPI
|
||||||
from umbral.keys import UmbralPublicKey
|
from umbral.keys import UmbralPublicKey
|
||||||
from umbral.point import Point
|
from umbral.point import Point
|
||||||
from umbral.signing import Signature
|
from umbral.signing import Signature
|
||||||
|
|
|
@ -15,6 +15,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from sqlalchemy import (
|
from sqlalchemy import (
|
||||||
Column, Integer, LargeBinary, ForeignKey, Boolean, DateTime
|
Column, Integer, LargeBinary, ForeignKey, Boolean, DateTime
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,11 +14,12 @@ GNU Affero General Public License for more details.
|
||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
from typing import Union, List
|
||||||
|
|
||||||
from bytestring_splitter import BytestringSplitter
|
from bytestring_splitter import BytestringSplitter
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
from typing import Union
|
|
||||||
from umbral.kfrags import KFrag
|
|
||||||
from umbral.keys import UmbralPublicKey
|
from umbral.keys import UmbralPublicKey
|
||||||
|
from umbral.kfrags import KFrag
|
||||||
|
|
||||||
from nucypher.crypto.signing import Signature
|
from nucypher.crypto.signing import Signature
|
||||||
from nucypher.crypto.utils import fingerprint_from_key
|
from nucypher.crypto.utils import fingerprint_from_key
|
||||||
|
@ -79,10 +80,8 @@ class KeyStore(object):
|
||||||
session = session or self._session_on_init_thread
|
session = session or self._session_on_init_thread
|
||||||
|
|
||||||
key = session.query(Key).filter_by(fingerprint=fingerprint).first()
|
key = session.query(Key).filter_by(fingerprint=fingerprint).first()
|
||||||
|
|
||||||
if not key:
|
if not key:
|
||||||
raise NotFound(
|
raise NotFound("No key with fingerprint {} found.".format(fingerprint))
|
||||||
"No key with fingerprint {} found.".format(fingerprint))
|
|
||||||
|
|
||||||
pubkey = UmbralPublicKey.from_bytes(key.key_data)
|
pubkey = UmbralPublicKey.from_bytes(key.key_data)
|
||||||
return pubkey
|
return pubkey
|
||||||
|
@ -160,30 +159,56 @@ class KeyStore(object):
|
||||||
policy_arrangement.kfrag = bytes(kfrag)
|
policy_arrangement.kfrag = bytes(kfrag)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
def add_workorder(self, bob_verifying_key, bob_signature, arrangement_id, session=None) -> Workorder:
|
def save_workorder(self, bob_verifying_key, bob_signature, arrangement_id, session=None) -> Workorder:
|
||||||
"""
|
"""
|
||||||
Adds a Workorder to the keystore.
|
Adds a Workorder to the keystore.
|
||||||
"""
|
"""
|
||||||
session = session or self._session_on_init_thread
|
session = session or self._session_on_init_thread
|
||||||
bob_verifying_key = self.add_key(bob_verifying_key)
|
|
||||||
new_workorder = Workorder(bob_verifying_key.id, bob_signature, arrangement_id)
|
# Get or Create Bob Verifying Key
|
||||||
|
fingerprint = fingerprint_from_key(bob_verifying_key)
|
||||||
|
key = session.query(Key).filter_by(fingerprint=fingerprint).first()
|
||||||
|
if not key:
|
||||||
|
key = self.add_key(key=bob_verifying_key)
|
||||||
|
|
||||||
|
new_workorder = Workorder(bob_verifying_key_id=key.id,
|
||||||
|
bob_signature=bob_signature,
|
||||||
|
arrangement_id=arrangement_id)
|
||||||
|
|
||||||
session.add(new_workorder)
|
session.add(new_workorder)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
return new_workorder
|
return new_workorder
|
||||||
|
|
||||||
def get_workorders(self, arrangement_id: bytes, session=None) -> Workorder:
|
def get_workorders(self,
|
||||||
|
arrangement_id: bytes = None,
|
||||||
|
bob_verifying_key: bytes = None,
|
||||||
|
session=None
|
||||||
|
) -> List[Workorder]:
|
||||||
"""
|
"""
|
||||||
Returns a list of Workorders by HRAC.
|
Returns a list of Workorders by HRAC.
|
||||||
"""
|
"""
|
||||||
session = session or self._session_on_init_thread
|
session = session or self._session_on_init_thread
|
||||||
|
query = session.query(Workorder)
|
||||||
|
|
||||||
workorders = session.query(Workorder).filter_by(arrangement_id=arrangement_id)
|
if not arrangement_id and not bob_verifying_key:
|
||||||
|
workorders = query.all() # Return all records
|
||||||
|
|
||||||
if not workorders:
|
else:
|
||||||
raise NotFound("No Workorders with {} HRAC found.".format(arrangement_id))
|
|
||||||
return workorders
|
# Return arrangement records
|
||||||
|
if arrangement_id:
|
||||||
|
workorders = query.filter_by(arrangement_id=arrangement_id)
|
||||||
|
|
||||||
|
# Return records for Bob
|
||||||
|
else:
|
||||||
|
fingerprint = fingerprint_from_key(bob_verifying_key)
|
||||||
|
key = session.query(Key).filter_by(fingerprint=fingerprint).first()
|
||||||
|
workorders = query.filter_by(bob_verifying_key_id=key.id)
|
||||||
|
|
||||||
|
if not workorders:
|
||||||
|
raise NotFound
|
||||||
|
|
||||||
|
return list(workorders)
|
||||||
|
|
||||||
def del_workorders(self, arrangement_id: bytes, session=None):
|
def del_workorders(self, arrangement_id: bytes, session=None):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -19,14 +19,13 @@ import ssl
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import time
|
import time
|
||||||
|
from bytestring_splitter import BytestringSplitter, VariableLengthBytestring
|
||||||
|
from constant_sorrow.constants import CERTIFICATE_NOT_SAVED
|
||||||
from cryptography import x509
|
from cryptography import x509
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
from twisted.logger import Logger
|
from twisted.logger import Logger
|
||||||
from umbral.cfrags import CapsuleFrag
|
from umbral.cfrags import CapsuleFrag
|
||||||
from umbral.signing import Signature
|
from umbral.signing import Signature
|
||||||
from constant_sorrow.constants import CERTIFICATE_NOT_SAVED
|
|
||||||
|
|
||||||
from bytestring_splitter import BytestringSplitter, VariableLengthBytestring
|
|
||||||
|
|
||||||
|
|
||||||
class UnexpectedResponse(Exception):
|
class UnexpectedResponse(Exception):
|
||||||
|
|
|
@ -19,18 +19,16 @@ import binascii
|
||||||
import os
|
import os
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
from flask import Flask, Response
|
|
||||||
from flask import request
|
|
||||||
from jinja2 import Template, TemplateError
|
|
||||||
from twisted.logger import Logger
|
|
||||||
from umbral import pre
|
|
||||||
from umbral.keys import UmbralPublicKey
|
|
||||||
from umbral.kfrags import KFrag
|
|
||||||
|
|
||||||
from bytestring_splitter import VariableLengthBytestring
|
from bytestring_splitter import VariableLengthBytestring
|
||||||
from constant_sorrow import constants
|
from constant_sorrow import constants
|
||||||
from constant_sorrow.constants import FLEET_STATES_MATCH, NO_KNOWN_NODES
|
from constant_sorrow.constants import FLEET_STATES_MATCH, NO_KNOWN_NODES
|
||||||
|
from flask import Flask, Response
|
||||||
|
from flask import request
|
||||||
from hendrix.experience import crosstown_traffic
|
from hendrix.experience import crosstown_traffic
|
||||||
|
from jinja2 import Template, TemplateError
|
||||||
|
from twisted.logger import Logger
|
||||||
|
from umbral.keys import UmbralPublicKey
|
||||||
|
from umbral.kfrags import KFrag
|
||||||
|
|
||||||
import nucypher
|
import nucypher
|
||||||
from nucypher.config.storages import ForgetfulNodeStorage
|
from nucypher.config.storages import ForgetfulNodeStorage
|
||||||
|
@ -293,51 +291,46 @@ def make_rest_app(
|
||||||
|
|
||||||
@rest_app.route('/kFrag/<id_as_hex>/reencrypt', methods=["POST"])
|
@rest_app.route('/kFrag/<id_as_hex>/reencrypt', methods=["POST"])
|
||||||
def reencrypt_via_rest(id_as_hex):
|
def reencrypt_via_rest(id_as_hex):
|
||||||
from nucypher.policy.collections import WorkOrder # Avoid circular import
|
|
||||||
arrangement_id = binascii.unhexlify(id_as_hex)
|
# Get Policy Arrangement
|
||||||
|
try:
|
||||||
|
arrangement_id = binascii.unhexlify(id_as_hex)
|
||||||
|
except (binascii.Error, TypeError):
|
||||||
|
return Response(response=b'Invalid arrangement ID', status=405)
|
||||||
try:
|
try:
|
||||||
with ThreadedSession(db_engine) as session:
|
with ThreadedSession(db_engine) as session:
|
||||||
policy_arrangement = datastore.get_policy_arrangement(arrangement_id=id_as_hex.encode(),
|
arrangement = datastore.get_policy_arrangement(arrangement_id=id_as_hex.encode(), session=session)
|
||||||
session=session)
|
|
||||||
except NotFound:
|
except NotFound:
|
||||||
return Response(response=arrangement_id, status=404)
|
return Response(response=arrangement_id, status=404)
|
||||||
kfrag_bytes = policy_arrangement.kfrag # Careful! :-)
|
|
||||||
verifying_key_bytes = policy_arrangement.alice_verifying_key.key_data
|
|
||||||
|
|
||||||
# TODO: Push this to a lower level. Perhaps to Ursula character? #619
|
# Get KFrag
|
||||||
kfrag = KFrag.from_bytes(kfrag_bytes)
|
kfrag = KFrag.from_bytes(arrangement.kfrag)
|
||||||
alices_verifying_key = UmbralPublicKey.from_bytes(verifying_key_bytes)
|
|
||||||
alices_address = canonical_address_from_umbral_key(alices_verifying_key)
|
|
||||||
|
|
||||||
|
# Get Work Order
|
||||||
|
from nucypher.policy.collections import WorkOrder # Avoid circular import
|
||||||
|
alice_verifying_key_bytes = arrangement.alice_verifying_key.key_data
|
||||||
|
alice_verifying_key = UmbralPublicKey.from_bytes(alice_verifying_key_bytes)
|
||||||
|
alice_address = canonical_address_from_umbral_key(alice_verifying_key)
|
||||||
|
work_order_payload = request.data
|
||||||
work_order = WorkOrder.from_rest_payload(arrangement_id=arrangement_id,
|
work_order = WorkOrder.from_rest_payload(arrangement_id=arrangement_id,
|
||||||
rest_payload=request.data,
|
rest_payload=work_order_payload,
|
||||||
ursula=this_node,
|
ursula=this_node,
|
||||||
alice_address=alices_address)
|
alice_address=alice_address)
|
||||||
|
|
||||||
log.info(f"Work Order from {work_order.bob}, signed {work_order.receipt_signature}")
|
log.info(f"Work Order from {work_order.bob}, signed {work_order.receipt_signature}")
|
||||||
|
|
||||||
cfrag_byte_stream = b""
|
# Re-encrypt
|
||||||
|
response = this_node._reencrypt(kfrag=kfrag,
|
||||||
|
work_order=work_order,
|
||||||
|
alice_verifying_key=alice_verifying_key)
|
||||||
|
|
||||||
for task in work_order.tasks:
|
# Now, Ursula saves this workorder to her database...
|
||||||
# Ursula signs on top of Bob's signature of each task.
|
with ThreadedSession(db_engine):
|
||||||
# Now both are committed to the same task. See #259.
|
this_node.datastore.save_workorder(bob_verifying_key=bytes(work_order.bob.stamp),
|
||||||
reencryption_metadata = bytes(this_node.stamp(bytes(task.signature)))
|
bob_signature=bytes(work_order.receipt_signature),
|
||||||
|
arrangement_id=work_order.arrangement_id)
|
||||||
capsule = task.capsule
|
|
||||||
capsule.set_correctness_keys(verifying=alices_verifying_key)
|
|
||||||
cfrag = pre.reencrypt(kfrag, capsule, metadata=reencryption_metadata)
|
|
||||||
log.info(f"Re-encrypting for {capsule}, made {cfrag}.")
|
|
||||||
|
|
||||||
# Finally, Ursula commits to her result
|
|
||||||
reencryption_signature = this_node.stamp(bytes(cfrag))
|
|
||||||
cfrag_byte_stream += VariableLengthBytestring(cfrag) + reencryption_signature
|
|
||||||
|
|
||||||
# TODO: Put this in Ursula's datastore
|
|
||||||
this_node._work_orders.append(work_order)
|
|
||||||
|
|
||||||
headers = {'Content-Type': 'application/octet-stream'}
|
headers = {'Content-Type': 'application/octet-stream'}
|
||||||
|
return Response(headers=headers, response=response)
|
||||||
return Response(response=cfrag_byte_stream, headers=headers)
|
|
||||||
|
|
||||||
@rest_app.route('/treasure_map/<treasure_map_id>')
|
@rest_app.route('/treasure_map/<treasure_map_id>')
|
||||||
def provide_treasure_map(treasure_map_id):
|
def provide_treasure_map(treasure_map_id):
|
||||||
|
|
|
@ -15,6 +15,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
import binascii
|
import binascii
|
||||||
|
from typing import List, Optional, Tuple
|
||||||
|
|
||||||
import maya
|
import maya
|
||||||
import msgpack
|
import msgpack
|
||||||
|
@ -23,8 +24,6 @@ from constant_sorrow.constants import NO_DECRYPTION_PERFORMED
|
||||||
from cryptography.hazmat.backends.openssl import backend
|
from cryptography.hazmat.backends.openssl import backend
|
||||||
from cryptography.hazmat.primitives import hashes
|
from cryptography.hazmat.primitives import hashes
|
||||||
from eth_utils import to_canonical_address, to_checksum_address
|
from eth_utils import to_canonical_address, to_checksum_address
|
||||||
from typing import List, Optional, Tuple
|
|
||||||
|
|
||||||
from umbral.cfrags import CapsuleFrag
|
from umbral.cfrags import CapsuleFrag
|
||||||
from umbral.config import default_params
|
from umbral.config import default_params
|
||||||
from umbral.curvebn import CurveBN
|
from umbral.curvebn import CurveBN
|
||||||
|
|
|
@ -215,7 +215,7 @@ def test_bob_can_issue_a_work_order_to_a_specific_ursula(enacted_federated_polic
|
||||||
# Now we'll show that Ursula saved the correct WorkOrder.
|
# Now we'll show that Ursula saved the correct WorkOrder.
|
||||||
work_orders_from_bob = ursula.work_orders(bob=federated_bob)
|
work_orders_from_bob = ursula.work_orders(bob=federated_bob)
|
||||||
assert len(work_orders_from_bob) == 1
|
assert len(work_orders_from_bob) == 1
|
||||||
assert work_orders_from_bob[0] == work_order
|
assert work_orders_from_bob[0].bob_signature == work_order.receipt_signature
|
||||||
|
|
||||||
|
|
||||||
def test_bob_remembers_that_he_has_cfrags_for_a_particular_capsule(enacted_federated_policy, federated_bob,
|
def test_bob_remembers_that_he_has_cfrags_for_a_particular_capsule(enacted_federated_policy, federated_bob,
|
||||||
|
|
|
@ -64,8 +64,8 @@ def test_workorder_sqlite_keystore(test_keystore):
|
||||||
arrangement_id = b'test'
|
arrangement_id = b'test'
|
||||||
|
|
||||||
# Test add workorder
|
# Test add workorder
|
||||||
new_workorder1 = test_keystore.add_workorder(bob_keypair_sig1.pubkey, b'test0', arrangement_id)
|
new_workorder1 = test_keystore.save_workorder(bob_keypair_sig1.pubkey, b'test0', arrangement_id)
|
||||||
new_workorder2 = test_keystore.add_workorder(bob_keypair_sig2.pubkey, b'test1', arrangement_id)
|
new_workorder2 = test_keystore.save_workorder(bob_keypair_sig2.pubkey, b'test1', arrangement_id)
|
||||||
|
|
||||||
# Test get workorder
|
# Test get workorder
|
||||||
query_workorders = test_keystore.get_workorders(arrangement_id)
|
query_workorders = test_keystore.get_workorders(arrangement_id)
|
||||||
|
@ -74,4 +74,4 @@ def test_workorder_sqlite_keystore(test_keystore):
|
||||||
# Test del workorder
|
# Test del workorder
|
||||||
deleted = test_keystore.del_workorders(arrangement_id)
|
deleted = test_keystore.del_workorders(arrangement_id)
|
||||||
assert deleted > 0
|
assert deleted > 0
|
||||||
assert test_keystore.get_workorders(arrangement_id).count() == 0
|
assert len(test_keystore.get_workorders(arrangement_id)) == 0
|
||||||
|
|
Loading…
Reference in New Issue