bigchaindb/test_transaction.py

991 lines
34 KiB
Python
Raw Normal View History

2016-09-02 13:55:54 +02:00
from pytest import raises, mark
2016-08-18 14:54:44 +02:00
def test_fulfillment_serialization(ffill_uri, user_pub):
2016-08-17 15:29:13 +02:00
from bigchaindb_common.transaction import Fulfillment
2016-08-05 10:13:34 +02:00
from cryptoconditions import Fulfillment as CCFulfillment
2016-08-05 10:13:34 +02:00
expected = {
2016-08-18 14:54:44 +02:00
'owners_before': [user_pub],
2016-08-05 10:13:34 +02:00
'fulfillment': ffill_uri,
'input': None,
}
2016-08-18 14:54:44 +02:00
ffill = Fulfillment(CCFulfillment.from_uri(ffill_uri), [user_pub])
2016-08-05 10:13:34 +02:00
assert ffill.to_dict() == expected
2016-08-18 14:54:44 +02:00
def test_fulfillment_deserialization_with_uri(ffill_uri, user_pub):
2016-08-17 15:05:16 +02:00
from bigchaindb_common.transaction import Fulfillment
2016-08-05 10:13:34 +02:00
from cryptoconditions import Fulfillment as CCFulfillment
2016-07-27 15:30:21 +02:00
2016-08-18 14:54:44 +02:00
expected = Fulfillment(CCFulfillment.from_uri(ffill_uri), [user_pub])
2016-08-05 10:13:34 +02:00
ffill = {
2016-08-18 14:54:44 +02:00
'owners_before': [user_pub],
'fulfillment': ffill_uri,
2016-08-05 10:13:34 +02:00
'input': None,
}
ffill = Fulfillment.from_dict(ffill)
2016-08-24 19:12:32 +02:00
assert ffill == expected
2016-08-05 10:13:34 +02:00
2016-09-14 13:46:17 +02:00
def test_fulfillment_deserialization_with_invalid_fulfillment(user_pub):
2016-08-17 15:05:16 +02:00
from bigchaindb_common.transaction import Fulfillment
2016-08-05 10:13:34 +02:00
ffill = {
2016-08-18 14:54:44 +02:00
'owners_before': [user_pub],
2016-08-05 10:13:34 +02:00
'fulfillment': None,
'input': None,
}
2016-09-14 13:46:17 +02:00
with raises(TypeError):
Fulfillment.from_dict(ffill)
2016-09-16 11:12:55 +02:00
def test_fulfillment_deserialization_with_invalid_fulfillment_uri(user_pub):
from bigchaindb_common.exceptions import InvalidSignature
from bigchaindb_common.transaction import Fulfillment
ffill = {
'owners_before': [user_pub],
'fulfillment': 'an invalid fulfillment',
'input': None,
}
with raises(InvalidSignature):
Fulfillment.from_dict(ffill)
2016-09-14 13:46:17 +02:00
def test_fulfillment_deserialization_with_unsigned_fulfillment(ffill_uri,
user_pub):
from bigchaindb_common.transaction import Fulfillment
from cryptoconditions import Fulfillment as CCFulfillment
expected = Fulfillment(CCFulfillment.from_uri(ffill_uri), [user_pub])
ffill = {
'owners_before': [user_pub],
'fulfillment': CCFulfillment.from_uri(ffill_uri),
'input': None,
}
2016-08-05 10:13:34 +02:00
ffill = Fulfillment.from_dict(ffill)
2016-07-27 15:30:21 +02:00
2016-08-24 19:12:32 +02:00
assert ffill == expected
2016-07-27 15:30:21 +02:00
def test_condition_serialization(user_Ed25519, user_pub):
2016-08-17 15:05:16 +02:00
from bigchaindb_common.transaction import Condition
2016-08-05 10:13:34 +02:00
expected = {
'condition': {
'uri': user_Ed25519.condition_uri,
'details': user_Ed25519.to_dict(),
},
2016-08-18 14:54:44 +02:00
'owners_after': [user_pub],
}
cond = Condition(user_Ed25519, [user_pub])
2016-08-05 10:13:34 +02:00
assert cond.to_dict() == expected
def test_condition_deserialization(user_Ed25519, user_pub):
2016-08-17 15:05:16 +02:00
from bigchaindb_common.transaction import Condition
2016-08-05 10:13:34 +02:00
expected = Condition(user_Ed25519, [user_pub])
2016-08-05 10:13:34 +02:00
cond = {
'condition': {
'uri': user_Ed25519.condition_uri,
'details': user_Ed25519.to_dict()
},
2016-08-18 14:54:44 +02:00
'owners_after': [user_pub],
2016-08-05 10:13:34 +02:00
}
cond = Condition.from_dict(cond)
2016-08-24 19:12:32 +02:00
assert cond == expected
2016-08-05 10:13:34 +02:00
2016-08-25 23:27:57 +02:00
def test_condition_hashlock_serialization():
from bigchaindb_common.transaction import Condition
from cryptoconditions import PreimageSha256Fulfillment
secret = b'wow much secret'
hashlock = PreimageSha256Fulfillment(preimage=secret).condition_uri
expected = {
'condition': {
'uri': hashlock,
},
'owners_after': None,
}
cond = Condition(hashlock)
assert cond.to_dict() == expected
def test_condition_hashlock_deserialization():
from bigchaindb_common.transaction import Condition
from cryptoconditions import PreimageSha256Fulfillment
secret = b'wow much secret'
hashlock = PreimageSha256Fulfillment(preimage=secret).condition_uri
expected = Condition(hashlock)
cond = {
'condition': {
'uri': hashlock
},
'owners_after': None,
}
cond = Condition.from_dict(cond)
assert cond == expected
2016-08-18 14:54:44 +02:00
def test_invalid_condition_initialization(cond_uri, user_pub):
2016-08-17 15:05:16 +02:00
from bigchaindb_common.transaction import Condition
2016-08-05 10:13:34 +02:00
with raises(TypeError):
2016-08-18 14:54:44 +02:00
Condition(cond_uri, user_pub)
2016-09-02 13:55:54 +02:00
def test_generate_conditions_split_half_recursive(user_pub, user2_pub,
user3_pub):
from bigchaindb_common.transaction import Condition
from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment
expected_simple1 = Ed25519Fulfillment(public_key=user_pub)
expected_simple2 = Ed25519Fulfillment(public_key=user2_pub)
expected_simple3 = Ed25519Fulfillment(public_key=user3_pub)
expected = ThresholdSha256Fulfillment(threshold=2)
expected.add_subfulfillment(expected_simple1)
expected_threshold = ThresholdSha256Fulfillment(threshold=2)
expected_threshold.add_subfulfillment(expected_simple2)
expected_threshold.add_subfulfillment(expected_simple3)
expected.add_subfulfillment(expected_threshold)
cond = Condition.generate([user_pub, [user2_pub, expected_simple3]])
assert cond.fulfillment.to_dict() == expected.to_dict()
2016-09-20 18:31:38 +02:00
def test_generate_conditions_split_half_recursive_custom_threshold(user_pub,
user2_pub,
user3_pub):
from bigchaindb_common.transaction import Condition
from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment
expected_simple1 = Ed25519Fulfillment(public_key=user_pub)
expected_simple2 = Ed25519Fulfillment(public_key=user2_pub)
expected_simple3 = Ed25519Fulfillment(public_key=user3_pub)
expected = ThresholdSha256Fulfillment(threshold=1)
expected.add_subfulfillment(expected_simple1)
expected_threshold = ThresholdSha256Fulfillment(threshold=1)
expected_threshold.add_subfulfillment(expected_simple2)
expected_threshold.add_subfulfillment(expected_simple3)
expected.add_subfulfillment(expected_threshold)
cond = Condition.generate(([user_pub, ([user2_pub, expected_simple3], 1)], 1))
assert cond.fulfillment.to_dict() == expected.to_dict()
2016-09-02 13:55:54 +02:00
def test_generate_conditions_split_half_single_owner(user_pub, user2_pub,
user3_pub):
from bigchaindb_common.transaction import Condition
from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment
expected_simple1 = Ed25519Fulfillment(public_key=user_pub)
expected_simple2 = Ed25519Fulfillment(public_key=user2_pub)
expected_simple3 = Ed25519Fulfillment(public_key=user3_pub)
expected = ThresholdSha256Fulfillment(threshold=2)
expected_threshold = ThresholdSha256Fulfillment(threshold=2)
expected_threshold.add_subfulfillment(expected_simple2)
expected_threshold.add_subfulfillment(expected_simple3)
expected.add_subfulfillment(expected_threshold)
expected.add_subfulfillment(expected_simple1)
cond = Condition.generate([[expected_simple2, user3_pub], user_pub])
assert cond.fulfillment.to_dict() == expected.to_dict()
def test_generate_conditions_flat_ownage(user_pub, user2_pub, user3_pub):
from bigchaindb_common.transaction import Condition
from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment
expected_simple1 = Ed25519Fulfillment(public_key=user_pub)
expected_simple2 = Ed25519Fulfillment(public_key=user2_pub)
expected_simple3 = Ed25519Fulfillment(public_key=user3_pub)
expected = ThresholdSha256Fulfillment(threshold=3)
expected.add_subfulfillment(expected_simple1)
expected.add_subfulfillment(expected_simple2)
expected.add_subfulfillment(expected_simple3)
cond = Condition.generate([user_pub, user2_pub, expected_simple3])
assert cond.fulfillment.to_dict() == expected.to_dict()
def test_generate_conditions_single_owner(user_pub):
from bigchaindb_common.transaction import Condition
from cryptoconditions import Ed25519Fulfillment
expected = Ed25519Fulfillment(public_key=user_pub)
cond = Condition.generate([user_pub])
assert cond.fulfillment.to_dict() == expected.to_dict()
def test_generate_conditions_single_owner_with_condition(user_pub):
from bigchaindb_common.transaction import Condition
from cryptoconditions import Ed25519Fulfillment
expected = Ed25519Fulfillment(public_key=user_pub)
cond = Condition.generate([expected])
assert cond.fulfillment.to_dict() == expected.to_dict()
# TODO FOR CC: see skip reason
@mark.skip(reason='threshold(hashlock).to_dict() exposes secret')
def test_generate_threshold_condition_with_hashlock(user_pub, user2_pub,
user3_pub):
from bigchaindb_common.transaction import Condition
from cryptoconditions import (PreimageSha256Fulfillment,
Ed25519Fulfillment,
ThresholdSha256Fulfillment)
secret = b'much secret, wow'
hashlock = PreimageSha256Fulfillment(preimage=secret)
expected_simple1 = Ed25519Fulfillment(public_key=user_pub)
expected_simple3 = Ed25519Fulfillment(public_key=user3_pub)
expected = ThresholdSha256Fulfillment(threshold=2)
expected_sub = ThresholdSha256Fulfillment(threshold=2)
expected_sub.add_subfulfillment(expected_simple1)
expected_sub.add_subfulfillment(hashlock)
expected.add_subfulfillment(expected_simple3)
cond = Condition.generate([[user_pub, hashlock], expected_simple3])
assert cond.fulfillment.to_dict() == expected.to_dict()
def test_generate_conditions_invalid_parameters(user_pub, user2_pub,
user3_pub):
from bigchaindb_common.transaction import Condition
with raises(ValueError):
Condition.generate([])
with raises(TypeError):
2016-09-02 14:51:33 +02:00
Condition.generate('not a list')
2016-09-02 13:55:54 +02:00
with raises(ValueError):
Condition.generate([[user_pub, [user2_pub, [user3_pub]]]])
with raises(ValueError):
Condition.generate([[user_pub]])
def test_transaction_serialization(user_ffill, user_cond):
2016-08-17 15:05:16 +02:00
from bigchaindb_common.transaction import Transaction
2016-08-05 10:13:34 +02:00
tx_id = 'l0l'
timestamp = '66666666666'
expected = {
'id': tx_id,
'version': Transaction.VERSION,
'transaction': {
# NOTE: This test assumes that Fulfillments and Conditions can successfully be serialized
'fulfillments': [user_ffill.to_dict(0)],
'conditions': [user_cond.to_dict(0)],
2016-08-05 10:13:34 +02:00
'operation': Transaction.CREATE,
'timestamp': timestamp,
'data': None,
}
}
tx_dict = Transaction(Transaction.CREATE, [user_ffill], [user_cond]).to_dict()
2016-08-05 10:13:34 +02:00
tx_dict['id'] = tx_id
tx_dict['transaction']['timestamp'] = timestamp
assert tx_dict == expected
def test_transaction_deserialization(user_ffill, user_cond):
2016-08-17 15:05:16 +02:00
from bigchaindb_common.transaction import Transaction
2016-08-05 10:13:34 +02:00
timestamp = '66666666666'
expected = Transaction(Transaction.CREATE, [user_ffill], [user_cond], None, timestamp,
2016-08-18 14:54:44 +02:00
Transaction.VERSION)
2016-08-05 10:13:34 +02:00
tx = {
'version': Transaction.VERSION,
'transaction': {
# NOTE: This test assumes that Fulfillments and Conditions can successfully be serialized
'fulfillments': [user_ffill.to_dict()],
'conditions': [user_cond.to_dict()],
2016-08-05 10:13:34 +02:00
'operation': Transaction.CREATE,
'timestamp': timestamp,
'data': None,
}
}
2016-08-24 18:29:20 +02:00
tx['id'] = Transaction._to_hash(Transaction._to_str(Transaction._remove_signatures(tx)))
2016-08-05 10:13:34 +02:00
tx = Transaction.from_dict(tx)
2016-08-24 19:12:32 +02:00
assert tx == expected
2016-08-05 10:13:34 +02:00
2016-08-24 18:29:20 +02:00
def test_tx_serialization_with_incorrect_hash(utx):
from bigchaindb_common.transaction import Transaction
from bigchaindb_common.exceptions import InvalidHash
utx_dict = utx.to_dict()
utx_dict['id'] = 'abc'
with raises(InvalidHash):
Transaction.from_dict(utx_dict)
utx_dict.pop('id')
with raises(InvalidHash):
Transaction.from_dict(utx_dict)
utx_dict['id'] = []
with raises(InvalidHash):
Transaction.from_dict(utx_dict)
2016-08-05 10:13:34 +02:00
def test_invalid_tx_initialization():
2016-08-17 15:05:16 +02:00
from bigchaindb_common.transaction import Transaction
2016-08-05 10:13:34 +02:00
wrong_data_type = {'payload': 'a totally wrong datatype'}
with raises(TypeError):
Transaction(Transaction.CREATE, wrong_data_type)
with raises(TypeError):
Transaction(Transaction.CREATE, [], wrong_data_type)
with raises(TypeError):
Transaction(Transaction.CREATE, [], [], wrong_data_type)
2016-08-08 15:06:00 +02:00
with raises(TypeError):
Transaction('RANSFER', [], [])
def test_invalid_fulfillment_initialization(user_ffill, user_pub):
from bigchaindb_common.transaction import Fulfillment
with raises(TypeError):
Fulfillment(user_ffill, user_pub)
with raises(TypeError):
Fulfillment(user_ffill, [], tx_input='somethingthatiswrong')
def test_invalid_data_initialization():
from bigchaindb_common.transaction import Data
with raises(TypeError):
Data([])
def test_data_serialization(payload, payload_id):
from bigchaindb_common.transaction import Data
expected = {
'payload': payload,
'uuid': payload_id
}
data = Data(payload, payload_id)
assert data.to_dict() == expected
def test_data_deserialization(payload, payload_id):
from bigchaindb_common.transaction import Data
expected = Data(payload, payload_id)
data = Data.from_dict({'payload': payload, 'uuid': payload_id})
assert data == expected
2016-08-17 09:58:20 +02:00
def test_transaction_link_serialization():
2016-08-18 10:44:05 +02:00
from bigchaindb_common.transaction import TransactionLink
tx_id = 'a transaction id'
expected = {
2016-08-23 20:08:51 +02:00
'txid': tx_id,
'cid': 0,
2016-08-18 10:44:05 +02:00
}
tx_link = TransactionLink(tx_id, 0)
assert tx_link.to_dict() == expected
def test_transaction_link_serialization_with_empty_payload():
from bigchaindb_common.transaction import TransactionLink
expected = None
tx_link = TransactionLink()
assert tx_link.to_dict() == expected
2016-08-17 09:58:20 +02:00
def test_transaction_link_deserialization():
2016-08-18 10:44:05 +02:00
from bigchaindb_common.transaction import TransactionLink
tx_id = 'a transaction id'
expected = TransactionLink(tx_id, 0)
tx_link = {
2016-08-23 20:08:51 +02:00
'txid': tx_id,
'cid': 0,
2016-08-18 10:44:05 +02:00
}
tx_link = TransactionLink.from_dict(tx_link)
2016-08-24 19:12:32 +02:00
assert tx_link == expected
2016-08-18 10:44:05 +02:00
def test_transaction_link_deserialization_with_empty_payload():
from bigchaindb_common.transaction import TransactionLink
expected = TransactionLink()
tx_link = TransactionLink.from_dict(None)
2016-08-17 09:58:20 +02:00
2016-08-24 19:12:32 +02:00
assert tx_link == expected
2016-08-17 09:58:20 +02:00
2016-08-18 10:44:05 +02:00
2016-09-02 14:51:33 +02:00
def test_cast_transaction_link_to_boolean():
from bigchaindb_common.transaction import TransactionLink
assert bool(TransactionLink()) is False
assert bool(TransactionLink('a', None)) is False
assert bool(TransactionLink(None, 'b')) is False
assert bool(TransactionLink('a', 'b')) is True
assert bool(TransactionLink(False, False)) is True
def test_add_fulfillment_to_tx(user_ffill):
2016-08-18 14:54:44 +02:00
from bigchaindb_common.transaction import Transaction
tx = Transaction(Transaction.CREATE, [], [])
tx.add_fulfillment(user_ffill)
2016-08-18 14:54:44 +02:00
assert len(tx.fulfillments) == 1
def test_add_fulfillment_to_tx_with_invalid_parameters():
from bigchaindb_common.transaction import Transaction
tx = Transaction(Transaction.CREATE)
with raises(TypeError):
tx.add_fulfillment('somewronginput')
def test_add_condition_to_tx(user_cond):
2016-08-18 14:54:44 +02:00
from bigchaindb_common.transaction import Transaction
tx = Transaction(Transaction.CREATE)
tx.add_condition(user_cond)
2016-08-18 14:54:44 +02:00
assert len(tx.conditions) == 1
def test_add_condition_to_tx_with_invalid_parameters():
from bigchaindb_common.transaction import Transaction
tx = Transaction(Transaction.CREATE, [], [])
with raises(TypeError):
tx.add_condition('somewronginput')
2016-08-19 10:42:20 +02:00
def test_sign_with_invalid_parameters(utx, user_priv):
2016-08-18 10:44:05 +02:00
with raises(TypeError):
2016-08-19 10:42:20 +02:00
utx.sign(None)
2016-08-18 10:44:05 +02:00
with raises(TypeError):
2016-08-19 10:42:20 +02:00
utx.sign(user_priv)
2016-08-18 10:44:05 +02:00
def test_validate_tx_simple_create_signature(user_ffill, user_cond, user_priv):
2016-08-08 15:06:00 +02:00
from copy import deepcopy
2016-08-17 15:05:16 +02:00
from bigchaindb_common.crypto import SigningKey
from bigchaindb_common.transaction import Transaction
2016-08-08 15:06:00 +02:00
tx = Transaction(Transaction.CREATE, [user_ffill], [user_cond])
expected = deepcopy(user_cond)
2016-08-18 14:54:44 +02:00
expected.fulfillment.sign(str(tx), SigningKey(user_priv))
tx.sign([user_priv])
2016-08-15 15:29:20 +02:00
assert tx.fulfillments[0].to_dict()['fulfillment'] == expected.fulfillment.serialize_uri()
2016-08-08 15:06:00 +02:00
assert tx.fulfillments_valid() is True
2016-08-15 15:29:20 +02:00
def test_invoke_simple_signature_fulfillment_with_invalid_parameters(utx, user_ffill):
2016-08-18 14:54:44 +02:00
from bigchaindb_common.exceptions import KeypairMismatchException
with raises(KeypairMismatchException):
utx._sign_simple_signature_fulfillment(user_ffill,
0,
2016-08-19 10:42:20 +02:00
'somemessage',
{'wrong_pub_key': 'wrong_priv_key'})
2016-08-18 14:54:44 +02:00
def test_invoke_threshold_signature_fulfillment_with_invalid_parameters(utx,
user_user2_threshold_ffill,
user3_pub,
user3_priv):
2016-08-18 14:54:44 +02:00
from bigchaindb_common.exceptions import KeypairMismatchException
2016-08-19 14:14:47 +02:00
with raises(KeypairMismatchException):
utx._sign_threshold_signature_fulfillment(user_user2_threshold_ffill,
0,
'somemessage',
{user3_pub: user3_priv})
2016-08-18 14:54:44 +02:00
with raises(KeypairMismatchException):
user_user2_threshold_ffill.owners_before = ['somewrongvalue']
utx._sign_threshold_signature_fulfillment(user_user2_threshold_ffill,
0,
'somemessage',
None)
2016-08-18 14:54:44 +02:00
2016-08-19 10:42:20 +02:00
def test_validate_fulfillment_with_invalid_parameters(utx):
from bigchaindb_common.transaction import Transaction
input_conditions = [cond.fulfillment.condition_uri for cond
in utx.conditions]
tx_serialized = Transaction._to_str(Transaction._remove_signatures(utx.to_dict()))
assert utx._fulfillment_valid(utx.fulfillments[0],
tx_serialized,
input_conditions) == False
2016-08-18 14:54:44 +02:00
def test_validate_multiple_fulfillments(user_ffill, user_cond, user_priv):
2016-08-18 10:44:05 +02:00
from copy import deepcopy
from bigchaindb_common.crypto import SigningKey
from bigchaindb_common.transaction import Transaction
tx = Transaction(Transaction.CREATE,
[user_ffill, deepcopy(user_ffill)],
[user_ffill, deepcopy(user_cond)])
2016-08-18 10:44:05 +02:00
expected_first = deepcopy(tx)
expected_second = deepcopy(tx)
2016-08-18 10:44:05 +02:00
expected_first.fulfillments = [expected_first.fulfillments[0]]
expected_first.conditions = [expected_first.conditions[0]]
2016-08-18 10:44:05 +02:00
expected_second.fulfillments = [expected_second.fulfillments[1]]
expected_second.conditions = [expected_second.conditions[1]]
2016-08-18 10:44:05 +02:00
2016-08-18 14:54:44 +02:00
expected_first.fulfillments[0].fulfillment.sign(str(expected_first), SigningKey(user_priv))
expected_second.fulfillments[0].fulfillment.sign(str(expected_second), SigningKey(user_priv))
tx.sign([user_priv])
2016-08-18 10:44:05 +02:00
assert tx.fulfillments[0].to_dict()['fulfillment'] == expected_first.fulfillments[0].fulfillment.serialize_uri()
assert tx.fulfillments[1].to_dict()['fulfillment'] == expected_second.fulfillments[0].fulfillment.serialize_uri()
2016-08-18 10:44:05 +02:00
assert tx.fulfillments_valid() is True
def test_validate_tx_threshold_create_signature(user_user2_threshold_ffill,
user_user2_threshold_cond,
user_pub,
user2_pub,
user_priv,
user2_priv):
2016-08-15 15:29:20 +02:00
from copy import deepcopy
2016-08-17 15:05:16 +02:00
from bigchaindb_common.crypto import SigningKey
from bigchaindb_common.transaction import Transaction
2016-08-15 15:29:20 +02:00
tx = Transaction(Transaction.CREATE, [user_user2_threshold_ffill], [user_user2_threshold_cond])
expected = deepcopy(user_user2_threshold_cond)
expected.fulfillment.subconditions[0]['body'].sign(str(tx), SigningKey(user_priv))
expected.fulfillment.subconditions[1]['body'].sign(str(tx), SigningKey(user2_priv))
tx.sign([user_priv, user2_priv])
2016-08-15 15:29:20 +02:00
assert tx.fulfillments[0].to_dict()['fulfillment'] == expected.fulfillment.serialize_uri()
2016-08-15 15:29:20 +02:00
assert tx.fulfillments_valid() is True
2016-08-17 09:58:20 +02:00
def test_multiple_fulfillment_validation_of_transfer_tx(user_ffill, user_cond,
user_priv, user2_pub,
user2_priv, user3_pub,
user3_priv):
from copy import deepcopy
from bigchaindb_common.transaction import (Transaction, TransactionLink,
Fulfillment, Condition)
from cryptoconditions import Ed25519Fulfillment
tx = Transaction(Transaction.CREATE,
[user_ffill, deepcopy(user_ffill)],
[user_cond, deepcopy(user_cond)])
tx.sign([user_priv])
fulfillments = [Fulfillment(cond.fulfillment, cond.owners_after,
TransactionLink(tx.id, index))
for index, cond in enumerate(tx.conditions)]
conditions = [Condition(Ed25519Fulfillment(public_key=user3_pub), [user3_pub]),
Condition(Ed25519Fulfillment(public_key=user3_pub), [user3_pub])]
transfer_tx = Transaction('TRANSFER', fulfillments, conditions)
transfer_tx = transfer_tx.sign([user_priv])
assert transfer_tx.fulfillments_valid(tx.conditions) is True
def test_validate_fulfillments_of_transfer_tx_with_invalid_parameters(transfer_tx,
cond_uri,
utx,
user2_pub,
user_priv):
from bigchaindb_common.transaction import Condition
from cryptoconditions import Ed25519Fulfillment
assert transfer_tx.fulfillments_valid([Condition(Ed25519Fulfillment.from_uri('cf:0:'),
['invalid'])]) is False
invalid_cond = utx.conditions[0]
invalid_cond.owners_after = 'invalid'
assert transfer_tx.fulfillments_valid([invalid_cond]) is True
2016-08-19 10:42:20 +02:00
with raises(TypeError):
assert transfer_tx.fulfillments_valid(None) is False
with raises(AttributeError):
transfer_tx.fulfillments_valid('not a list')
2016-08-19 10:42:20 +02:00
with raises(ValueError):
transfer_tx.fulfillments_valid([])
with raises(TypeError):
transfer_tx.operation = "Operation that doesn't exist"
transfer_tx.fulfillments_valid([utx.conditions[0]])
2016-08-19 10:42:20 +02:00
with raises(ValueError):
tx = utx.sign([user_priv])
tx.conditions = []
tx.fulfillments_valid()
2016-08-25 21:29:08 +02:00
def test_create_create_transaction_single_io(user_cond, user_pub):
from bigchaindb_common.transaction import Transaction
expected = {
'transaction': {
'conditions': [user_cond.to_dict(0)],
'data': {
'payload': {
'message': 'hello'
}
},
'fulfillments': [
{
'owners_before': [
user_pub
],
'fid': 0,
'fulfillment': None,
'input': None
}
],
'operation': 'CREATE',
},
'version': 1
}
2016-09-14 13:46:17 +02:00
payload = {'message': 'hello'}
tx = Transaction.create([user_pub], [user_pub], payload).to_dict()
2016-08-25 21:29:08 +02:00
tx.pop('id')
tx['transaction']['data'].pop('uuid')
tx['transaction'].pop('timestamp')
2016-09-14 13:46:17 +02:00
tx['transaction']['fulfillments'][0]['fulfillment'] = None
2016-08-25 21:29:08 +02:00
assert tx == expected
def test_validate_single_io_create_transaction(user_pub, user_priv):
2016-08-25 21:57:20 +02:00
from bigchaindb_common.transaction import Transaction
tx = Transaction.create([user_pub], [user_pub], {'message': 'hello'})
tx = tx.sign([user_priv])
assert tx.fulfillments_valid() is True
2016-09-02 13:55:54 +02:00
@mark.skip(reason='Multiple inputs and outputs in CREATE not supported')
2016-08-25 21:29:08 +02:00
def test_create_create_transaction_multiple_io(user_cond, user2_cond, user_pub,
user2_pub):
from bigchaindb_common.transaction import Transaction
expected = {
'transaction': {
'conditions': [user_cond.to_dict(0), user2_cond.to_dict(1)],
'data': {
'payload': {
'message': 'hello'
}
},
'fulfillments': [
{
'owners_before': [
user_pub,
],
'fid': 0,
'fulfillment': None,
'input': None
},
{
'owners_before': [
user2_pub,
],
'fid': 1,
'fulfillment': None,
'input': None
}
],
'operation': 'CREATE',
},
'version': 1
}
tx = Transaction.create([user_pub, user2_pub], [user_pub, user2_pub],
{'message': 'hello'}).to_dict()
tx.pop('id')
tx['transaction']['data'].pop('uuid')
tx['transaction'].pop('timestamp')
assert tx == expected
2016-09-02 13:55:54 +02:00
@mark.skip(reason='Multiple inputs and outputs in CREATE not supported')
def test_validate_multiple_io_create_transaction(user_pub, user_priv,
2016-08-25 21:57:20 +02:00
user2_pub, user2_priv):
from bigchaindb_common.transaction import Transaction
tx = Transaction.create([user_pub, user2_pub], [user_pub, user2_pub],
{'message': 'hello'})
tx = tx.sign([user_priv, user2_priv])
assert tx.fulfillments_valid() is True
2016-08-25 21:29:08 +02:00
def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub,
user_user2_threshold_cond,
user_user2_threshold_ffill):
from bigchaindb_common.transaction import Transaction
expected = {
'transaction': {
'conditions': [user_user2_threshold_cond.to_dict(0)],
'data': {
'payload': {
'message': 'hello'
}
},
'fulfillments': [
{
'owners_before': [
user_pub,
],
'fid': 0,
'fulfillment': None,
'input': None
},
],
'operation': 'CREATE',
},
'version': 1
}
tx = Transaction.create([user_pub], [user_pub, user2_pub],
{'message': 'hello'}).to_dict()
tx.pop('id')
tx['transaction']['data'].pop('uuid')
tx['transaction'].pop('timestamp')
2016-09-14 13:46:17 +02:00
tx['transaction']['fulfillments'][0]['fulfillment'] = None
2016-08-25 21:29:08 +02:00
assert tx == expected
2016-08-25 21:57:20 +02:00
def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub):
2016-08-25 21:57:20 +02:00
from bigchaindb_common.transaction import Transaction
tx = Transaction.create([user_pub], [user_pub, user2_pub],
{'message': 'hello'})
tx = tx.sign([user_priv])
assert tx.fulfillments_valid() is True
def test_create_create_transaction_hashlock(user_pub):
from bigchaindb_common.transaction import Transaction, Condition
from cryptoconditions import PreimageSha256Fulfillment
secret = b'much secret, wow'
2016-08-25 23:27:57 +02:00
hashlock = PreimageSha256Fulfillment(preimage=secret).condition_uri
cond = Condition(hashlock)
expected = {
'transaction': {
'conditions': [cond.to_dict(0)],
'data': {
'payload': {
'message': 'hello'
}
},
'fulfillments': [
{
'owners_before': [
user_pub,
],
'fid': 0,
'fulfillment': None,
'input': None
},
],
'operation': 'CREATE',
},
'version': 1
}
tx = Transaction.create([user_pub], [], {'message': 'hello'},
secret).to_dict()
tx.pop('id')
tx['transaction']['data'].pop('uuid')
tx['transaction'].pop('timestamp')
2016-09-14 13:46:17 +02:00
tx['transaction']['fulfillments'][0]['fulfillment'] = None
assert tx == expected
def test_validate_hashlock_create_transaction(user_pub, user_priv):
from bigchaindb_common.transaction import Transaction
tx = Transaction.create([user_pub], [], {'message': 'hello'},
b'much secret, wow')
tx = tx.sign([user_priv])
assert tx.fulfillments_valid() is True
2016-09-02 14:51:33 +02:00
def test_create_create_transaction_with_invalid_parameters():
from bigchaindb_common.transaction import Transaction
with raises(TypeError):
Transaction.create('not a list')
with raises(TypeError):
Transaction.create([], 'not a list')
with raises(NotImplementedError):
Transaction.create(['a', 'b'], ['c', 'd'])
with raises(NotImplementedError):
Transaction.create(['a'], [], time_expire=123)
with raises(ValueError):
Transaction.create(['a'], [], secret=None)
with raises(ValueError):
Transaction.create([], [], secret='wow, much secret')
def test_conditions_to_inputs(tx):
ffills = tx.to_inputs([0])
assert len(ffills) == 1
2016-09-02 13:55:54 +02:00
ffill = ffills.pop()
assert ffill.fulfillment == tx.conditions[0].fulfillment
assert ffill.owners_before == tx.conditions[0].owners_after
assert ffill.tx_input.txid == tx.id
assert ffill.tx_input.cid == 0
def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
user2_cond, user_priv):
from copy import deepcopy
2016-09-02 13:55:54 +02:00
from bigchaindb_common.crypto import SigningKey
from bigchaindb_common.transaction import Transaction
from bigchaindb_common.util import serialize
expected = {
'transaction': {
'conditions': [user2_cond.to_dict(0)],
'data': None,
'fulfillments': [
{
'owners_before': [
user_pub
],
'fid': 0,
'fulfillment': None,
'input': {
'txid': tx.id,
'cid': 0
}
}
],
'operation': 'TRANSFER',
},
'version': 1
}
inputs = tx.to_inputs([0])
transfer_tx = Transaction.transfer(inputs, [user2_pub])
transfer_tx = transfer_tx.sign([user_priv])
transfer_tx = transfer_tx.to_dict()
expected_input = deepcopy(inputs[0])
expected['id'] = transfer_tx['id']
expected['transaction']['timestamp'] = transfer_tx['transaction']['timestamp']
expected_input.fulfillment.sign(serialize(expected), SigningKey(user_priv))
expected_ffill = expected_input.fulfillment.serialize_uri()
transfer_ffill = transfer_tx['transaction']['fulfillments'][0]['fulfillment']
assert transfer_ffill == expected_ffill
assert Transaction.from_dict(transfer_tx).fulfillments_valid([tx.conditions[0]]) is True
2016-09-02 13:55:54 +02:00
def test_create_transfer_transaction_multiple_io(user_pub, user_priv,
user2_pub, user2_priv,
user3_pub, user2_cond):
from bigchaindb_common.transaction import Transaction
tx1 = Transaction.create([user_pub], [user_pub], {'message': 'hello'})
tx1 = tx1.sign([user_priv])
tx2 = Transaction.create([user2_pub], [user2_pub], {'message': 'hello'})
tx2 = tx2.sign([user2_priv])
expected = {
'transaction': {
'conditions': [user2_cond.to_dict(0), user2_cond.to_dict(1)],
'data': None,
'fulfillments': [
{
'owners_before': [
user_pub
],
'fid': 0,
'fulfillment': None,
'input': {
'txid': tx1.id,
'cid': 0
}
}, {
'owners_before': [
user2_pub
],
'fid': 1,
'fulfillment': None,
'input': {
'txid': tx2.id,
'cid': 0
}
}
],
'operation': 'TRANSFER',
},
'version': 1
}
tx1_inputs = tx1.to_inputs()
tx2_inputs = tx2.to_inputs()
tx_inputs = tx1_inputs + tx2_inputs
transfer_tx = Transaction.transfer(tx_inputs, [[user2_pub], [user2_pub]])
transfer_tx = transfer_tx.sign([user_priv, user2_priv])
transfer_tx = transfer_tx
assert len(transfer_tx.fulfillments) == 2
assert len(transfer_tx.conditions) == 2
assert transfer_tx.fulfillments_valid(tx1.conditions + tx2.conditions) is True
transfer_tx = transfer_tx.to_dict()
transfer_tx['transaction']['fulfillments'][0]['fulfillment'] = None
transfer_tx['transaction']['fulfillments'][1]['fulfillment'] = None
transfer_tx['transaction'].pop('timestamp')
transfer_tx.pop('id')
assert expected == transfer_tx
def test_create_transfer_with_invalid_parameters():
from bigchaindb_common.transaction import Transaction
with raises(TypeError):
Transaction.transfer({}, [])
with raises(ValueError):
Transaction.transfer([], [])
with raises(TypeError):
Transaction.transfer(['fulfillment'], {})
with raises(ValueError):
Transaction.transfer(['fulfillment'], [])