Integrate cryptoconditions version 02

This commit is contained in:
Sylvain Bellemare 2017-06-14 18:42:07 +02:00 committed by Sylvain Bellemare
parent a175f371b0
commit 02fe712c34
11 changed files with 134 additions and 119 deletions

View File

@ -7,6 +7,6 @@ pip install --upgrade pip
if [[ -n ${TOXENV} ]]; then if [[ -n ${TOXENV} ]]; then
pip install --upgrade tox pip install --upgrade tox
else else
pip install -e .[test] pip install .[test]
pip install --upgrade codecov pip install --upgrade codecov
fi fi

View File

@ -154,7 +154,7 @@ definitions:
additionalProperties: true additionalProperties: true
uri: uri:
type: string type: string
pattern: "^cc:([1-9a-f][0-9a-f]{0,3}|0):[1-9a-f][0-9a-f]{0,15}:[a-zA-Z0-9_-]{0,86}:([1-9][0-9]{0,17}|0)$" pattern: "^ni:///sha-256;([a-zA-Z0-9_-]{0,86})?(.+)$"
public_keys: public_keys:
"$ref": "#/definitions/public_keys" "$ref": "#/definitions/public_keys"
description: | description: |
@ -195,7 +195,7 @@ definitions:
that satisfies the condition of a previous output to prove that the that satisfies the condition of a previous output to prove that the
creator(s) of this transaction have control over the listed asset. creator(s) of this transaction have control over the listed asset.
- type: string - type: string
pattern: "^cf:([1-9a-f][0-9a-f]{0,3}|0):[a-zA-Z0-9_-]*$" pattern: "^[a-zA-Z0-9_-]*$"
fulfills: fulfills:
anyOf: anyOf:
- type: 'object' - type: 'object'

View File

@ -1,15 +1,16 @@
from copy import deepcopy from copy import deepcopy
from functools import reduce from functools import reduce
from cryptoconditions import (Fulfillment, ThresholdSha256Fulfillment, import base58
Ed25519Fulfillment) from cryptoconditions import Fulfillment, ThresholdSha256, Ed25519Sha256
from cryptoconditions.exceptions import ParsingError from cryptoconditions.exceptions import (
ParsingError, ASN1DecodeError, ASN1EncodeError)
from bigchaindb.common.crypto import PrivateKey, hash_data from bigchaindb.common.crypto import PrivateKey, hash_data
from bigchaindb.common.exceptions import (KeypairMismatchException, from bigchaindb.common.exceptions import (KeypairMismatchException,
InvalidHash, InvalidSignature, InvalidHash, InvalidSignature,
AmountError, AssetIdMismatch) AmountError, AssetIdMismatch)
from bigchaindb.common.utils import serialize, gen_timestamp from bigchaindb.common.utils import serialize
import bigchaindb.version import bigchaindb.version
@ -65,7 +66,7 @@ class Input(object):
""" """
try: try:
fulfillment = self.fulfillment.serialize_uri() fulfillment = self.fulfillment.serialize_uri()
except (TypeError, AttributeError): except (TypeError, AttributeError, ASN1EncodeError):
# NOTE: When a non-signed transaction is casted to a dict, # NOTE: When a non-signed transaction is casted to a dict,
# `self.inputs` value is lost, as in the node's # `self.inputs` value is lost, as in the node's
# transaction model that is saved to the database, does not # transaction model that is saved to the database, does not
@ -114,15 +115,18 @@ class Input(object):
Raises: Raises:
InvalidSignature: If an Input's URI couldn't be parsed. InvalidSignature: If an Input's URI couldn't be parsed.
""" """
try: fulfillment = data['fulfillment']
fulfillment = Fulfillment.from_uri(data['fulfillment']) if not isinstance(fulfillment, Fulfillment):
except ValueError: try:
# TODO FOR CC: Throw an `InvalidSignature` error in this case. fulfillment = Fulfillment.from_uri(data['fulfillment'])
raise InvalidSignature("Fulfillment URI couldn't been parsed") except ASN1DecodeError:
except TypeError: # TODO Remove as it is legacy code, and simply fall back on
# NOTE: See comment about this special case in # ASN1DecodeError
# `Input.to_dict` raise InvalidSignature("Fulfillment URI couldn't been parsed")
fulfillment = Fulfillment.from_dict(data['fulfillment']) except TypeError:
# NOTE: See comment about this special case in
# `Input.to_dict`
fulfillment = Fulfillment.from_dict(data['fulfillment'])
fulfills = TransactionLink.from_dict(data['fulfills']) fulfills = TransactionLink.from_dict(data['fulfills'])
return cls(fulfillment, data['owners_before'], fulfills) return cls(fulfillment, data['owners_before'], fulfills)
@ -310,13 +314,14 @@ class Output(object):
raise ValueError('`public_keys` needs to contain at least one' raise ValueError('`public_keys` needs to contain at least one'
'owner') 'owner')
elif len(public_keys) == 1 and not isinstance(public_keys[0], list): elif len(public_keys) == 1 and not isinstance(public_keys[0], list):
try: if isinstance(public_keys[0], Fulfillment):
ffill = Ed25519Fulfillment(public_key=public_keys[0])
except TypeError:
ffill = public_keys[0] ffill = public_keys[0]
else:
ffill = Ed25519Sha256(
public_key=base58.b58decode(public_keys[0]))
return cls(ffill, public_keys, amount=amount) return cls(ffill, public_keys, amount=amount)
else: else:
initial_cond = ThresholdSha256Fulfillment(threshold=threshold) initial_cond = ThresholdSha256(threshold=threshold)
threshold_cond = reduce(cls._gen_condition, public_keys, threshold_cond = reduce(cls._gen_condition, public_keys,
initial_cond) initial_cond)
return cls(threshold_cond, public_keys, amount=amount) return cls(threshold_cond, public_keys, amount=amount)
@ -331,13 +336,13 @@ class Output(object):
:meth:`~.Output.generate`. :meth:`~.Output.generate`.
Args: Args:
initial (:class:`cryptoconditions.ThresholdSha256Fulfillment`): initial (:class:`cryptoconditions.ThresholdSha256`):
A Condition representing the overall root. A Condition representing the overall root.
new_public_keys (:obj:`list` of :obj:`str`|str): A list of new new_public_keys (:obj:`list` of :obj:`str`|str): A list of new
owners or a single new owner. owners or a single new owner.
Returns: Returns:
:class:`cryptoconditions.ThresholdSha256Fulfillment`: :class:`cryptoconditions.ThresholdSha256`:
""" """
try: try:
threshold = len(new_public_keys) threshold = len(new_public_keys)
@ -345,7 +350,7 @@ class Output(object):
threshold = None threshold = None
if isinstance(new_public_keys, list) and len(new_public_keys) > 1: if isinstance(new_public_keys, list) and len(new_public_keys) > 1:
ffill = ThresholdSha256Fulfillment(threshold=threshold) ffill = ThresholdSha256(threshold=threshold)
reduce(cls._gen_condition, new_public_keys, ffill) reduce(cls._gen_condition, new_public_keys, ffill)
elif isinstance(new_public_keys, list) and len(new_public_keys) <= 1: elif isinstance(new_public_keys, list) and len(new_public_keys) <= 1:
raise ValueError('Sublist cannot contain single owner') raise ValueError('Sublist cannot contain single owner')
@ -354,16 +359,17 @@ class Output(object):
new_public_keys = new_public_keys.pop() new_public_keys = new_public_keys.pop()
except AttributeError: except AttributeError:
pass pass
try: # NOTE: Instead of submitting base58 encoded addresses, a user
ffill = Ed25519Fulfillment(public_key=new_public_keys) # of this class can also submit fully instantiated
except TypeError: # Cryptoconditions. In the case of casting
# NOTE: Instead of submitting base58 encoded addresses, a user # `new_public_keys` to a Ed25519Fulfillment with the
# of this class can also submit fully instantiated # result of a `TypeError`, we're assuming that
# Cryptoconditions. In the case of casting # `new_public_keys` is a Cryptocondition then.
# `new_public_keys` to a Ed25519Fulfillment with the if isinstance(new_public_keys, Fulfillment):
# result of a `TypeError`, we're assuming that
# `new_public_keys` is a Cryptocondition then.
ffill = new_public_keys ffill = new_public_keys
else:
ffill = Ed25519Sha256(
public_key=base58.b58decode(new_public_keys))
initial.add_subfulfillment(ffill) initial.add_subfulfillment(ffill)
return initial return initial
@ -661,7 +667,7 @@ class Transaction(object):
This method works only for the following Cryptoconditions This method works only for the following Cryptoconditions
currently: currently:
- Ed25519Fulfillment - Ed25519Fulfillment
- ThresholdSha256Fulfillment - ThresholdSha256
Furthermore, note that all keys required to fully sign the Furthermore, note that all keys required to fully sign the
Transaction have to be passed to this method. A subset of all Transaction have to be passed to this method. A subset of all
will cause this method to fail. will cause this method to fail.
@ -712,7 +718,7 @@ class Transaction(object):
This method works only for the following Cryptoconditions This method works only for the following Cryptoconditions
currently: currently:
- Ed25519Fulfillment - Ed25519Fulfillment
- ThresholdSha256Fulfillment. - ThresholdSha256.
Args: Args:
input_ (:class:`~bigchaindb.common.transaction. input_ (:class:`~bigchaindb.common.transaction.
@ -720,10 +726,10 @@ class Transaction(object):
message (str): The message to be signed message (str): The message to be signed
key_pairs (dict): The keys to sign the Transaction with. key_pairs (dict): The keys to sign the Transaction with.
""" """
if isinstance(input_.fulfillment, Ed25519Fulfillment): if isinstance(input_.fulfillment, Ed25519Sha256):
return cls._sign_simple_signature_fulfillment(input_, message, return cls._sign_simple_signature_fulfillment(input_, message,
key_pairs) key_pairs)
elif isinstance(input_.fulfillment, ThresholdSha256Fulfillment): elif isinstance(input_.fulfillment, ThresholdSha256):
return cls._sign_threshold_signature_fulfillment(input_, message, return cls._sign_threshold_signature_fulfillment(input_, message,
key_pairs) key_pairs)
else: else:
@ -749,7 +755,10 @@ class Transaction(object):
try: try:
# cryptoconditions makes no assumptions of the encoding of the # cryptoconditions makes no assumptions of the encoding of the
# message to sign or verify. It only accepts bytestrings # message to sign or verify. It only accepts bytestrings
input_.fulfillment.sign(message.encode(), key_pairs[public_key]) input_.fulfillment.sign(
message.encode(),
base58.b58decode(key_pairs[public_key].encode()),
)
except KeyError: except KeyError:
raise KeypairMismatchException('Public key {} is not a pair to ' raise KeypairMismatchException('Public key {} is not a pair to '
'any of the private keys' 'any of the private keys'
@ -758,7 +767,7 @@ class Transaction(object):
@classmethod @classmethod
def _sign_threshold_signature_fulfillment(cls, input_, message, key_pairs): def _sign_threshold_signature_fulfillment(cls, input_, message, key_pairs):
"""Signs a ThresholdSha256Fulfillment. """Signs a ThresholdSha256.
Args: Args:
input_ (:class:`~bigchaindb.common.transaction. input_ (:class:`~bigchaindb.common.transaction.
@ -778,7 +787,8 @@ class Transaction(object):
# TODO FOR CC: `get_subcondition` is singular. One would not # TODO FOR CC: `get_subcondition` is singular. One would not
# expect to get a list back. # expect to get a list back.
ccffill = input_.fulfillment ccffill = input_.fulfillment
subffills = ccffill.get_subcondition_from_vk(owner_before) subffills = ccffill.get_subcondition_from_vk(
base58.b58decode(owner_before))
if not subffills: if not subffills:
raise KeypairMismatchException('Public key {} cannot be found ' raise KeypairMismatchException('Public key {} cannot be found '
'in the fulfillment' 'in the fulfillment'
@ -793,7 +803,7 @@ class Transaction(object):
# cryptoconditions makes no assumptions of the encoding of the # cryptoconditions makes no assumptions of the encoding of the
# message to sign or verify. It only accepts bytestrings # message to sign or verify. It only accepts bytestrings
for subffill in subffills: for subffill in subffills:
subffill.sign(message.encode(), private_key) subffill.sign(message.encode(), base58.b58decode(private_key.encode()))
return input_ return input_
def inputs_valid(self, outputs=None): def inputs_valid(self, outputs=None):
@ -882,7 +892,8 @@ class Transaction(object):
ccffill = input_.fulfillment ccffill = input_.fulfillment
try: try:
parsed_ffill = Fulfillment.from_uri(ccffill.serialize_uri()) parsed_ffill = Fulfillment.from_uri(ccffill.serialize_uri())
except (TypeError, ValueError, ParsingError): except (TypeError, ValueError,
ParsingError, ASN1DecodeError, ASN1EncodeError):
return False return False
if operation in (Transaction.CREATE, Transaction.GENESIS): if operation in (Transaction.CREATE, Transaction.GENESIS):
@ -897,8 +908,7 @@ class Transaction(object):
# cryptoconditions makes no assumptions of the encoding of the # cryptoconditions makes no assumptions of the encoding of the
# message to sign or verify. It only accepts bytestrings # message to sign or verify. It only accepts bytestrings
ffill_valid = parsed_ffill.validate(message=tx_serialized.encode(), ffill_valid = parsed_ffill.validate(message=tx_serialized.encode())
now=gen_timestamp())
return output_valid and ffill_valid return output_valid and ffill_valid
def to_dict(self): def to_dict(self):
@ -940,7 +950,7 @@ class Transaction(object):
tx_dict = deepcopy(tx_dict) tx_dict = deepcopy(tx_dict)
for input_ in tx_dict['inputs']: for input_ in tx_dict['inputs']:
# NOTE: Not all Cryptoconditions return a `signature` key (e.g. # NOTE: Not all Cryptoconditions return a `signature` key (e.g.
# ThresholdSha256Fulfillment), so setting it to `None` in any # ThresholdSha256), so setting it to `None` in any
# case could yield incorrect signatures. This is why we only # case could yield incorrect signatures. This is why we only
# set it to `None` if it's set in the dict. # set it to `None` if it's set in the dict.
input_['fulfillment'] = None input_['fulfillment'] = None

View File

@ -22,6 +22,7 @@ services:
- ./setup.cfg:/usr/src/app/setup.cfg - ./setup.cfg:/usr/src/app/setup.cfg
- ./pytest.ini:/usr/src/app/pytest.ini - ./pytest.ini:/usr/src/app/pytest.ini
- ./tox.ini:/usr/src/app/tox.ini - ./tox.ini:/usr/src/app/tox.ini
- ../cryptoconditions:/usr/src/app/cryptoconditions
environment: environment:
BIGCHAINDB_DATABASE_BACKEND: mongodb BIGCHAINDB_DATABASE_BACKEND: mongodb
BIGCHAINDB_DATABASE_HOST: mdb BIGCHAINDB_DATABASE_HOST: mdb

View File

@ -67,7 +67,7 @@ install_requires = [
'rethinkdb~=2.3', # i.e. a version between 2.3 and 3.0 'rethinkdb~=2.3', # i.e. a version between 2.3 and 3.0
'pymongo~=3.4', 'pymongo~=3.4',
'pysha3~=1.0.2', 'pysha3~=1.0.2',
'cryptoconditions>=0.5.0', 'cryptoconditions>=0.6.0.dev',
'python-rapidjson==0.0.11', 'python-rapidjson==0.0.11',
'logstats>=0.2.1', 'logstats>=0.2.1',
'flask>=0.10.1', 'flask>=0.10.1',
@ -126,7 +126,7 @@ setup(
], ],
}, },
install_requires=install_requires, install_requires=install_requires,
setup_requires=['pytest-runner'], setup_requires=['pytest-runner', 'cryptoconditions'],
tests_require=tests_require, tests_require=tests_require,
extras_require={ extras_require={
'test': tests_require, 'test': tests_require,

View File

@ -1,3 +1,4 @@
from base58 import b58decode
import pytest import pytest
@ -11,8 +12,13 @@ USER3_PRIVATE_KEY = '4rNQFzWQbVwuTiDVxwuFMvLG5zd8AhrQKCtVovBvcYsB'
USER3_PUBLIC_KEY = 'Gbrg7JtxdjedQRmr81ZZbh1BozS7fBW88ZyxNDy7WLNC' USER3_PUBLIC_KEY = 'Gbrg7JtxdjedQRmr81ZZbh1BozS7fBW88ZyxNDy7WLNC'
CC_FULFILLMENT_URI = 'cf:0:' CC_FULFILLMENT_URI = (
CC_CONDITION_URI = 'cc:0:3:47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU:0' 'pGSAINdamAGCsQq31Uv-08lkBzoO4XLz2qYjJa8CGmj3B1EagUDlVkMAw2CscpCG4syAboKKh'
'Id_Hrjl2XTYc-BlIkkBVV-4ghWQozusxh45cBz5tGvSW_XwWVu-JGVRQUOOehAL'
)
CC_CONDITION_URI = ('ni:///sha-256;'
'eZI5q6j8T_fqv7xMROaei9_tmTMk4S7WR5Kr4onPHV8'
'?fpt=ed25519-sha-256&cost=131072')
ASSET_DEFINITION = { ASSET_DEFINITION = {
'data': { 'data': {
@ -71,25 +77,25 @@ def cond_uri():
@pytest.fixture @pytest.fixture
def user_Ed25519(user_pub): def user_Ed25519(user_pub):
from cryptoconditions import Ed25519Fulfillment from cryptoconditions import Ed25519Sha256
return Ed25519Fulfillment(public_key=user_pub) return Ed25519Sha256(public_key=b58decode(user_pub))
@pytest.fixture @pytest.fixture
def user_user2_threshold(user_pub, user2_pub): def user_user2_threshold(user_pub, user2_pub):
from cryptoconditions import (ThresholdSha256Fulfillment, from cryptoconditions import ThresholdSha256, Ed25519Sha256
Ed25519Fulfillment)
user_pub_keys = [user_pub, user2_pub] user_pub_keys = [user_pub, user2_pub]
threshold = ThresholdSha256Fulfillment(threshold=len(user_pub_keys)) threshold = ThresholdSha256(threshold=len(user_pub_keys))
for user_pub in user_pub_keys: for user_pub in user_pub_keys:
threshold.add_subfulfillment(Ed25519Fulfillment(public_key=user_pub)) threshold.add_subfulfillment(
Ed25519Sha256(public_key=b58decode(user_pub)))
return threshold return threshold
@pytest.fixture @pytest.fixture
def user2_Ed25519(user2_pub): def user2_Ed25519(user2_pub):
from cryptoconditions import Ed25519Fulfillment from cryptoconditions import Ed25519Sha256
return Ed25519Fulfillment(public_key=user2_pub) return Ed25519Sha256(public_key=b58decode(user2_pub))
@pytest.fixture @pytest.fixture

View File

@ -2,7 +2,9 @@
These are tests of the API of the Transaction class and associated classes. These are tests of the API of the Transaction class and associated classes.
Tests for transaction validation are separate. Tests for transaction validation are separate.
""" """
from copy import deepcopy
from base58 import b58decode
from pytest import raises from pytest import raises
@ -110,10 +112,10 @@ def test_output_deserialization(user_Ed25519, user_pub):
def test_output_hashlock_serialization(): def test_output_hashlock_serialization():
from bigchaindb.common.transaction import Output from bigchaindb.common.transaction import Output
from cryptoconditions import PreimageSha256Fulfillment from cryptoconditions import PreimageSha256
secret = b'wow much secret' secret = b'wow much secret'
hashlock = PreimageSha256Fulfillment(preimage=secret).condition_uri hashlock = PreimageSha256(preimage=secret).condition_uri
expected = { expected = {
'condition': { 'condition': {
@ -129,10 +131,10 @@ def test_output_hashlock_serialization():
def test_output_hashlock_deserialization(): def test_output_hashlock_deserialization():
from bigchaindb.common.transaction import Output from bigchaindb.common.transaction import Output
from cryptoconditions import PreimageSha256Fulfillment from cryptoconditions import PreimageSha256
secret = b'wow much secret' secret = b'wow much secret'
hashlock = PreimageSha256Fulfillment(preimage=secret).condition_uri hashlock = PreimageSha256(preimage=secret).condition_uri
expected = Output(hashlock, amount=1) expected = Output(hashlock, amount=1)
cond = { cond = {
@ -161,15 +163,15 @@ def test_invalid_output_initialization(cond_uri, user_pub):
def test_generate_output_split_half_recursive(user_pub, user2_pub, user3_pub): def test_generate_output_split_half_recursive(user_pub, user2_pub, user3_pub):
from bigchaindb.common.transaction import Output from bigchaindb.common.transaction import Output
from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment from cryptoconditions import Ed25519Sha256, ThresholdSha256
expected_simple1 = Ed25519Fulfillment(public_key=user_pub) expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub))
expected_simple2 = Ed25519Fulfillment(public_key=user2_pub) expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub))
expected_simple3 = Ed25519Fulfillment(public_key=user3_pub) expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub))
expected = ThresholdSha256Fulfillment(threshold=2) expected = ThresholdSha256(threshold=2)
expected.add_subfulfillment(expected_simple1) expected.add_subfulfillment(expected_simple1)
expected_threshold = ThresholdSha256Fulfillment(threshold=2) expected_threshold = ThresholdSha256(threshold=2)
expected_threshold.add_subfulfillment(expected_simple2) expected_threshold.add_subfulfillment(expected_simple2)
expected_threshold.add_subfulfillment(expected_simple3) expected_threshold.add_subfulfillment(expected_simple3)
expected.add_subfulfillment(expected_threshold) expected.add_subfulfillment(expected_threshold)
@ -181,14 +183,14 @@ def test_generate_output_split_half_recursive(user_pub, user2_pub, user3_pub):
def test_generate_outputs_split_half_single_owner(user_pub, def test_generate_outputs_split_half_single_owner(user_pub,
user2_pub, user3_pub): user2_pub, user3_pub):
from bigchaindb.common.transaction import Output from bigchaindb.common.transaction import Output
from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment from cryptoconditions import Ed25519Sha256, ThresholdSha256
expected_simple1 = Ed25519Fulfillment(public_key=user_pub) expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub))
expected_simple2 = Ed25519Fulfillment(public_key=user2_pub) expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub))
expected_simple3 = Ed25519Fulfillment(public_key=user3_pub) expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub))
expected = ThresholdSha256Fulfillment(threshold=2) expected = ThresholdSha256(threshold=2)
expected_threshold = ThresholdSha256Fulfillment(threshold=2) expected_threshold = ThresholdSha256(threshold=2)
expected_threshold.add_subfulfillment(expected_simple2) expected_threshold.add_subfulfillment(expected_simple2)
expected_threshold.add_subfulfillment(expected_simple3) expected_threshold.add_subfulfillment(expected_simple3)
expected.add_subfulfillment(expected_threshold) expected.add_subfulfillment(expected_threshold)
@ -200,13 +202,13 @@ def test_generate_outputs_split_half_single_owner(user_pub,
def test_generate_outputs_flat_ownage(user_pub, user2_pub, user3_pub): def test_generate_outputs_flat_ownage(user_pub, user2_pub, user3_pub):
from bigchaindb.common.transaction import Output from bigchaindb.common.transaction import Output
from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment from cryptoconditions import Ed25519Sha256, ThresholdSha256
expected_simple1 = Ed25519Fulfillment(public_key=user_pub) expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub))
expected_simple2 = Ed25519Fulfillment(public_key=user2_pub) expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub))
expected_simple3 = Ed25519Fulfillment(public_key=user3_pub) expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub))
expected = ThresholdSha256Fulfillment(threshold=3) expected = ThresholdSha256(threshold=3)
expected.add_subfulfillment(expected_simple1) expected.add_subfulfillment(expected_simple1)
expected.add_subfulfillment(expected_simple2) expected.add_subfulfillment(expected_simple2)
expected.add_subfulfillment(expected_simple3) expected.add_subfulfillment(expected_simple3)
@ -217,9 +219,9 @@ def test_generate_outputs_flat_ownage(user_pub, user2_pub, user3_pub):
def test_generate_output_single_owner(user_pub): def test_generate_output_single_owner(user_pub):
from bigchaindb.common.transaction import Output from bigchaindb.common.transaction import Output
from cryptoconditions import Ed25519Fulfillment from cryptoconditions import Ed25519Sha256
expected = Ed25519Fulfillment(public_key=user_pub) expected = Ed25519Sha256(public_key=b58decode(user_pub))
cond = Output.generate([user_pub], 1) cond = Output.generate([user_pub], 1)
assert cond.fulfillment.to_dict() == expected.to_dict() assert cond.fulfillment.to_dict() == expected.to_dict()
@ -227,9 +229,9 @@ def test_generate_output_single_owner(user_pub):
def test_generate_output_single_owner_with_output(user_pub): def test_generate_output_single_owner_with_output(user_pub):
from bigchaindb.common.transaction import Output from bigchaindb.common.transaction import Output
from cryptoconditions import Ed25519Fulfillment from cryptoconditions import Ed25519Sha256
expected = Ed25519Fulfillment(public_key=user_pub) expected = Ed25519Sha256(public_key=b58decode(user_pub))
cond = Output.generate([expected], 1) cond = Output.generate([expected], 1)
assert cond.fulfillment.to_dict() == expected.to_dict() assert cond.fulfillment.to_dict() == expected.to_dict()
@ -489,15 +491,13 @@ def test_sign_with_invalid_parameters(utx, user_priv):
def test_validate_tx_simple_create_signature(user_input, user_output, user_priv, def test_validate_tx_simple_create_signature(user_input, user_output, user_priv,
asset_definition): asset_definition):
from copy import deepcopy
from bigchaindb.common.crypto import PrivateKey
from bigchaindb.common.transaction import Transaction from bigchaindb.common.transaction import Transaction
from .utils import validate_transaction_model from .utils import validate_transaction_model
tx = Transaction(Transaction.CREATE, asset_definition, [user_input], [user_output]) tx = Transaction(Transaction.CREATE, asset_definition, [user_input], [user_output])
expected = deepcopy(user_output) expected = deepcopy(user_output)
message = str(tx).encode() message = str(tx).encode()
expected.fulfillment.sign(message, PrivateKey(user_priv)) expected.fulfillment.sign(message, b58decode(user_priv))
tx.sign([user_priv]) tx.sign([user_priv])
assert tx.inputs[0].to_dict()['fulfillment'] == \ assert tx.inputs[0].to_dict()['fulfillment'] == \
@ -527,7 +527,7 @@ def test_sign_threshold_with_invalid_params(utx, user_user2_threshold_input,
'somemessage', 'somemessage',
{user3_pub: user3_priv}) {user3_pub: user3_priv})
with raises(KeypairMismatchException): with raises(KeypairMismatchException):
user_user2_threshold_input.owners_before = ['somewrongvalue'] user_user2_threshold_input.owners_before = [58 * 'a']
utx._sign_threshold_signature_fulfillment(user_user2_threshold_input, utx._sign_threshold_signature_fulfillment(user_user2_threshold_input,
'somemessage', 'somemessage',
None) None)
@ -551,9 +551,6 @@ def test_validate_tx_threshold_create_signature(user_user2_threshold_input,
user_priv, user_priv,
user2_priv, user2_priv,
asset_definition): asset_definition):
from copy import deepcopy
from bigchaindb.common.crypto import PrivateKey
from bigchaindb.common.transaction import Transaction from bigchaindb.common.transaction import Transaction
from .utils import validate_transaction_model from .utils import validate_transaction_model
@ -562,10 +559,10 @@ def test_validate_tx_threshold_create_signature(user_user2_threshold_input,
[user_user2_threshold_output]) [user_user2_threshold_output])
message = str(tx).encode() message = str(tx).encode()
expected = deepcopy(user_user2_threshold_output) expected = deepcopy(user_user2_threshold_output)
expected.fulfillment.subconditions[0]['body'].sign(message, expected.fulfillment.subconditions[0]['body'].sign(
PrivateKey(user_priv)) message, b58decode(user_priv))
expected.fulfillment.subconditions[1]['body'].sign(message, expected.fulfillment.subconditions[1]['body'].sign(
PrivateKey(user2_priv)) message, b58decode(user2_priv))
tx.sign([user_priv, user2_priv]) tx.sign([user_priv, user2_priv])
assert tx.inputs[0].to_dict()['fulfillment'] == \ assert tx.inputs[0].to_dict()['fulfillment'] == \
@ -577,14 +574,14 @@ def test_validate_tx_threshold_create_signature(user_user2_threshold_input,
def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv, def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv,
asset_definition): asset_definition):
from copy import deepcopy from cryptoconditions import Ed25519Sha256, ThresholdSha256
from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment
from bigchaindb.common.transaction import Input, Output, Transaction from bigchaindb.common.transaction import Input, Output, Transaction
from bigchaindb.common.crypto import PrivateKey
threshold = ThresholdSha256Fulfillment(threshold=2) threshold = ThresholdSha256(threshold=2)
threshold.add_subfulfillment(Ed25519Fulfillment(public_key=user_pub)) threshold.add_subfulfillment(
threshold.add_subfulfillment(Ed25519Fulfillment(public_key=user_pub)) Ed25519Sha256(public_key=b58decode(user_pub)))
threshold.add_subfulfillment(
Ed25519Sha256(public_key=b58decode(user_pub)))
threshold_input = Input(threshold, [user_pub, user_pub]) threshold_input = Input(threshold, [user_pub, user_pub])
threshold_output = Output(threshold, [user_pub, user_pub]) threshold_output = Output(threshold, [user_pub, user_pub])
@ -592,10 +589,10 @@ def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv,
tx = Transaction(Transaction.CREATE, asset_definition, tx = Transaction(Transaction.CREATE, asset_definition,
[threshold_input], [threshold_output]) [threshold_input], [threshold_output])
expected = deepcopy(threshold_input) expected = deepcopy(threshold_input)
expected.fulfillment.subconditions[0]['body'].sign(str(tx).encode(), expected.fulfillment.subconditions[0]['body'].sign(
PrivateKey(user_priv)) str(tx).encode(), b58decode(user_priv))
expected.fulfillment.subconditions[1]['body'].sign(str(tx).encode(), expected.fulfillment.subconditions[1]['body'].sign(
PrivateKey(user_priv)) str(tx).encode(), b58decode(user_priv))
tx.sign([user_priv, user_priv]) tx.sign([user_priv, user_priv])
@ -616,10 +613,9 @@ def test_multiple_input_validation_of_transfer_tx(user_input, user_output,
user2_priv, user3_pub, user2_priv, user3_pub,
user3_priv, user3_priv,
asset_definition): asset_definition):
from copy import deepcopy
from bigchaindb.common.transaction import (Transaction, TransactionLink, from bigchaindb.common.transaction import (Transaction, TransactionLink,
Input, Output) Input, Output)
from cryptoconditions import Ed25519Fulfillment from cryptoconditions import Ed25519Sha256
from .utils import validate_transaction_model from .utils import validate_transaction_model
tx = Transaction(Transaction.CREATE, asset_definition, [user_input], tx = Transaction(Transaction.CREATE, asset_definition, [user_input],
@ -629,8 +625,10 @@ def test_multiple_input_validation_of_transfer_tx(user_input, user_output,
inputs = [Input(cond.fulfillment, cond.public_keys, inputs = [Input(cond.fulfillment, cond.public_keys,
TransactionLink(tx.id, index)) TransactionLink(tx.id, index))
for index, cond in enumerate(tx.outputs)] for index, cond in enumerate(tx.outputs)]
outputs = [Output(Ed25519Fulfillment(public_key=user3_pub), [user3_pub]), outputs = [Output(Ed25519Sha256(public_key=b58decode(user3_pub)),
Output(Ed25519Fulfillment(public_key=user3_pub), [user3_pub])] [user3_pub]),
Output(Ed25519Sha256(public_key=b58decode(user3_pub)),
[user3_pub])]
transfer_tx = Transaction('TRANSFER', {'id': tx.id}, inputs, outputs) transfer_tx = Transaction('TRANSFER', {'id': tx.id}, inputs, outputs)
transfer_tx = transfer_tx.sign([user_priv]) transfer_tx = transfer_tx.sign([user_priv])
@ -640,11 +638,11 @@ def test_multiple_input_validation_of_transfer_tx(user_input, user_output,
def test_validate_inputs_of_transfer_tx_with_invalid_params( def test_validate_inputs_of_transfer_tx_with_invalid_params(
transfer_tx, cond_uri, utx, user2_pub, user_priv): transfer_tx, cond_uri, utx, user2_pub, user_priv, ffill_uri):
from bigchaindb.common.transaction import Output from bigchaindb.common.transaction import Output
from cryptoconditions import Ed25519Fulfillment from cryptoconditions import Ed25519Sha256
invalid_out = Output(Ed25519Fulfillment.from_uri('cf:0:'), ['invalid']) invalid_out = Output(Ed25519Sha256.from_uri(ffill_uri), ['invalid'])
assert transfer_tx.inputs_valid([invalid_out]) is False assert transfer_tx.inputs_valid([invalid_out]) is False
invalid_out = utx.outputs[0] invalid_out = utx.outputs[0]
invalid_out.public_key = 'invalid' invalid_out.public_key = 'invalid'
@ -826,8 +824,6 @@ def test_outputs_to_inputs(tx):
def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
user2_output, user_priv): user2_output, user_priv):
from copy import deepcopy
from bigchaindb.common.crypto import PrivateKey
from bigchaindb.common.transaction import Transaction from bigchaindb.common.transaction import Transaction
from bigchaindb.common.utils import serialize from bigchaindb.common.utils import serialize
from .utils import validate_transaction_model from .utils import validate_transaction_model
@ -861,8 +857,8 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
expected_input = deepcopy(inputs[0]) expected_input = deepcopy(inputs[0])
expected['id'] = transfer_tx['id'] expected['id'] = transfer_tx['id']
expected_input.fulfillment.sign(serialize(expected).encode(), expected_input.fulfillment.sign(
PrivateKey(user_priv)) serialize(expected).encode(), b58decode(user_priv))
expected_ffill = expected_input.fulfillment.serialize_uri() expected_ffill = expected_input.fulfillment.serialize_uri()
transfer_ffill = transfer_tx['inputs'][0]['fulfillment'] transfer_ffill = transfer_tx['inputs'][0]['fulfillment']

View File

@ -1,7 +1,8 @@
from time import sleep from time import sleep
from unittest.mock import patch
import pytest import pytest
from unittest.mock import patch from base58 import b58decode
pytestmark = pytest.mark.bdb pytestmark = pytest.mark.bdb
@ -577,14 +578,14 @@ class TestBigchainApi(object):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_non_create_input_not_found(self, b, user_pk): def test_non_create_input_not_found(self, b, user_pk):
from cryptoconditions import Ed25519Fulfillment from cryptoconditions import Ed25519Sha256
from bigchaindb.common.exceptions import InputDoesNotExist from bigchaindb.common.exceptions import InputDoesNotExist
from bigchaindb.common.transaction import Input, TransactionLink from bigchaindb.common.transaction import Input, TransactionLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb import Bigchain from bigchaindb import Bigchain
# Create an input for a non existing transaction # Create an input for a non existing transaction
input = Input(Ed25519Fulfillment(public_key=user_pk), input = Input(Ed25519Sha256(public_key=b58decode(user_pk)),
[user_pk], [user_pk],
TransactionLink('somethingsomething', 0)) TransactionLink('somethingsomething', 0))
tx = Transaction.transfer([input], [([user_pk], 1)], tx = Transaction.transfer([input], [([user_pk], 1)],

View File

@ -180,7 +180,7 @@ def test_vote_accumulates_transactions(b):
validation = vote_obj.validate_tx(tx.to_dict(), 123, 1) validation = vote_obj.validate_tx(tx.to_dict(), 123, 1)
assert validation == (True, 123, 1) assert validation == (True, 123, 1)
tx.inputs[0].fulfillment.signature = None tx.inputs[0].fulfillment.signature = 64*b'z'
validation = vote_obj.validate_tx(tx.to_dict(), 456, 10) validation = vote_obj.validate_tx(tx.to_dict(), 456, 10)
assert validation == (False, 456, 10) assert validation == (False, 456, 10)

View File

@ -89,7 +89,7 @@ def test_post_create_transaction_with_invalid_signature(mock_logger,
tx = Transaction.create([user_pub], [([user_pub], 1)]) tx = Transaction.create([user_pub], [([user_pub], 1)])
tx = tx.sign([user_priv]).to_dict() tx = tx.sign([user_priv]).to_dict()
tx['inputs'][0]['fulfillment'] = 'cf:0:0' tx['inputs'][0]['fulfillment'] = 64 * '0'
res = client.post(TX_ENDPOINT, data=json.dumps(tx)) res = client.post(TX_ENDPOINT, data=json.dumps(tx))
expected_status_code = 400 expected_status_code = 400

View File

@ -13,6 +13,7 @@ setenv =
rethinkdb: BIGCHAINDB_DATABASE_BACKEND=rethinkdb rethinkdb: BIGCHAINDB_DATABASE_BACKEND=rethinkdb
mongodb: BIGCHAINDB_DATABASE_BACKEND=mongodb mongodb: BIGCHAINDB_DATABASE_BACKEND=mongodb
deps = {[base]deps} deps = {[base]deps}
install_command = pip install {opts} {packages}
extras = test extras = test
commands = pytest -v -n auto --cov=bigchaindb --basetemp={envtmpdir} commands = pytest -v -n auto --cov=bigchaindb --basetemp={envtmpdir}