From c623ca56d0ea0308d9a1d6af5df6f40e661ec841 Mon Sep 17 00:00:00 2001 From: diminator Date: Wed, 11 May 2016 19:02:37 +0200 Subject: [PATCH] fulfillment_message with output_condition added tests --- bigchaindb/util.py | 5 +- tests/db/test_bigchain_api.py | 92 +++++++++++++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 6 deletions(-) diff --git a/bigchaindb/util.py b/bigchaindb/util.py index 9d318485..68d97eab 100644 --- a/bigchaindb/util.py +++ b/bigchaindb/util.py @@ -480,7 +480,8 @@ def get_fulfillment_message(transaction, fulfillment, serialized=False): # or created on the fly it this is a `CREATE` transaction fulfillment_message.update({ 'input': fulfillment['input'], - 'condition': None, + 'input_condition': None, + 'output_condition': None }) # if `TRANSFER` transaction @@ -489,12 +490,14 @@ def get_fulfillment_message(transaction, fulfillment, serialized=False): previous_tx = b.get_transaction(fulfillment['input']['txid']) conditions = sorted(previous_tx['transaction']['conditions'], key=lambda d: d['cid']) fulfillment_message['input_condition'] = conditions[fulfillment['input']['cid']] + fulfillment_message['output_condition'] = transaction['transaction']['conditions'][fulfillment['input']['cid']] # if `CREATE` transaction # there is no previous transaction so we need to create one on the fly else: current_owner = transaction['transaction']['fulfillments'][0]['current_owners'][0] condition = json.loads(cc.Ed25519Fulfillment(public_key=current_owner).serialize_json()) fulfillment_message['input_condition'] = {'condition': {'details': condition}} + fulfillment_message['output_condition'] = transaction['transaction']['conditions'][0] if serialized: return serialize(fulfillment_message) return fulfillment_message diff --git a/tests/db/test_bigchain_api.py b/tests/db/test_bigchain_api.py index 0537e9ca..4b7d77c4 100644 --- a/tests/db/test_bigchain_api.py +++ b/tests/db/test_bigchain_api.py @@ -1202,6 +1202,86 @@ class TestMultipleInputs(object): assert b.get_spent(inp) is None +class TestFulfillmentMessage(object): + def test_fulfillment_message_create(self, b, user_vk): + tx = b.create_transaction(b.me, user_vk, None, 'CREATE', payload={'pay': 'load'}) + original_fulfillment = tx['transaction']['fulfillments'][0] + fulfillment_message = util.get_fulfillment_message(tx, original_fulfillment) + + assert sorted(fulfillment_message) == ['data', 'id', 'input', 'input_condition', + 'operation', 'output_condition', 'timestamp', 'version'] + + assert fulfillment_message['data']['payload'] == tx['transaction']['data']['payload'] + assert fulfillment_message['id'] == tx['id'] + assert fulfillment_message['input'] == original_fulfillment['input'] + assert fulfillment_message['input_condition']['condition']['details']['public_key'] == \ + original_fulfillment['current_owners'][0] + assert fulfillment_message['operation'] == tx['transaction']['operation'] + assert fulfillment_message['timestamp'] == tx['transaction']['timestamp'] + assert fulfillment_message['version'] == tx['version'] + assert fulfillment_message['output_condition'] == tx['transaction']['conditions'][0] + + @pytest.mark.usefixtures('inputs') + def test_fulfillment_message_transfer(self, b, user_vk): + input_tx = b.get_owned_ids(user_vk).pop() + assert b.validate_fulfillments(b.get_transaction(input_tx['txid'])) == True + + tx = b.create_transaction(user_vk, b.me, input_tx, 'TRANSFER', payload={'pay': 'load'}) + + original_fulfillment = tx['transaction']['fulfillments'][0] + fulfillment_message = util.get_fulfillment_message(tx, original_fulfillment) + + assert sorted(fulfillment_message) == ['data', 'id', 'input', 'input_condition', + 'operation', 'output_condition', 'timestamp', 'version'] + + assert fulfillment_message['data']['payload'] == tx['transaction']['data']['payload'] + assert fulfillment_message['id'] == tx['id'] + assert fulfillment_message['input'] == original_fulfillment['input'] + assert fulfillment_message['input_condition']['new_owners'] == original_fulfillment['current_owners'] + assert fulfillment_message['operation'] == tx['transaction']['operation'] + assert fulfillment_message['timestamp'] == tx['transaction']['timestamp'] + assert fulfillment_message['version'] == tx['version'] + assert fulfillment_message['output_condition'] == tx['transaction']['conditions'][0] + + def test_fulfillment_message_multiple_current_owners_multiple_new_owners_multiple_inputs(self, b, user_vk): + # create a new users + user2_sk, user2_vk = crypto.generate_key_pair() + user3_sk, user3_vk = crypto.generate_key_pair() + user4_sk, user4_vk = crypto.generate_key_pair() + + # create inputs to spend + transactions = [] + for i in range(5): + tx = b.create_transaction(b.me, [user_vk, user2_vk], None, 'CREATE') + tx_signed = b.sign_transaction(tx, b.me_private) + transactions.append(tx_signed) + block = b.create_block(transactions) + b.write_block(block, durability='hard') + + # get input + owned_inputs = b.get_owned_ids(user_vk) + inp = owned_inputs[:3] + + # create a transaction + tx = b.create_transaction([user_vk, user2_vk], [user3_vk, user4_vk], inp, 'TRANSFER', payload={'pay': 'load'}) + + for original_fulfillment in tx['transaction']['fulfillments']: + fulfillment_message = util.get_fulfillment_message(tx, original_fulfillment) + + assert sorted(fulfillment_message) == ['data', 'id', 'input', 'input_condition', + 'operation', 'output_condition', 'timestamp', 'version'] + + assert fulfillment_message['data']['payload'] == tx['transaction']['data']['payload'] + assert fulfillment_message['id'] == tx['id'] + assert fulfillment_message['input'] == original_fulfillment['input'] + assert fulfillment_message['input_condition']['new_owners'] == original_fulfillment['current_owners'] + assert fulfillment_message['operation'] == tx['transaction']['operation'] + assert fulfillment_message['timestamp'] == tx['transaction']['timestamp'] + assert fulfillment_message['version'] == tx['version'] + assert fulfillment_message['output_condition'] == \ + tx['transaction']['conditions'][original_fulfillment['input']['cid']] + + class TestCryptoconditions(object): def test_fulfillment_transaction_create(self, b, user_vk): tx = b.create_transaction(b.me, user_vk, None, 'CREATE') @@ -1306,7 +1386,7 @@ class TestCryptoconditions(object): assert b.is_valid_transaction(tx) == tx @pytest.mark.usefixtures('inputs') - def test_override_fulfillment_transfer(self, b, user_vk, user_sk): + def test_override_fulfillment_transfer(self, b, user_vk, user_sk): # create valid transaction other_sk, other_vk = crypto.generate_key_pair() prev_tx_id = b.get_owned_ids(user_vk).pop() @@ -1323,7 +1403,7 @@ class TestCryptoconditions(object): assert b.is_valid_transaction(tx) == tx @pytest.mark.usefixtures('inputs') - def test_override_condition_and_fulfillment_transfer(self, b, user_vk, user_sk): + def test_override_condition_and_fulfillment_transfer(self, b, user_vk, user_sk): other_sk, other_vk = crypto.generate_key_pair() first_input_tx = b.get_owned_ids(user_vk).pop() first_tx = b.create_transaction(user_vk, other_vk, first_input_tx, 'TRANSFER') @@ -1560,7 +1640,8 @@ class TestCryptoconditions(object): tx_transfer_signed = b.sign_transaction(tx_transfer, [user_sk, user2_sk]) # expected fulfillment - expected_fulfillment = cc.Fulfillment.from_json(tx_create['transaction']['conditions'][0]['condition']['details']) + expected_fulfillment = cc.Fulfillment.from_json( + tx_create['transaction']['conditions'][0]['condition']['details']) subfulfillment1 = expected_fulfillment.subconditions[0]['body'] subfulfillment2 = expected_fulfillment.subconditions[1]['body'] @@ -1571,7 +1652,7 @@ class TestCryptoconditions(object): subfulfillment2.sign(util.serialize(expected_fulfillment_message), crypto.SigningKey(user2_sk)) assert tx_transfer_signed['transaction']['fulfillments'][0]['fulfillment'] \ - == expected_fulfillment.serialize_uri() + == expected_fulfillment.serialize_uri() assert b.validate_fulfillments(tx_transfer_signed) is True @@ -1696,7 +1777,8 @@ class TestCryptoconditions(object): # try doublespending user2_sk, user2_vk = crypto.generate_key_pair() - hashlock_doublespend_tx = b.create_transaction(None, user2_vk, {'txid': hashlock_tx['id'], 'cid': 0}, 'TRANSFER') + hashlock_doublespend_tx = b.create_transaction(None, user2_vk, {'txid': hashlock_tx['id'], 'cid': 0}, + 'TRANSFER') hashlock_doublespend_tx_fulfillment = cc.PreimageSha256Fulfillment(preimage=secret) hashlock_doublespend_tx['transaction']['fulfillments'][0]['fulfillment'] = \