diff --git a/bigchaindb/common/transaction.py b/bigchaindb/common/transaction.py index e1aa8245..fc364bf7 100644 --- a/bigchaindb/common/transaction.py +++ b/bigchaindb/common/transaction.py @@ -346,14 +346,11 @@ class Condition(object): Returns: :class:`cryptoconditions.ThresholdSha256Fulfillment`: """ - if isinstance(current, tuple): - owners_after, threshold = current - else: - owners_after = current - try: - threshold = len(owners_after) - except TypeError: - threshold = None + owners_after = current + try: + threshold = len(owners_after) + except TypeError: + threshold = None if isinstance(owners_after, list) and len(owners_after) > 1: ffill = ThresholdSha256Fulfillment(threshold=threshold) @@ -764,7 +761,6 @@ class Transaction(object): # generate_conditions for owner_after in owners_after: - # TODO: Check types so this doesn't fail unpacking if not isinstance(owner_after, tuple) or len(owner_after) != 2: raise ValueError(('Each `owner_after` in the list is a tuple' ' of `([], )`')) @@ -821,21 +817,14 @@ class Transaction(object): raise ValueError('`inputs` must contain at least one item') if not isinstance(owners_after, list): raise TypeError('`owners_after` must be a list instance') - - # # NOTE: See doc strings `Note` for description. - # if len(inputs) == len(owners_after): - # if len(owners_after) == 1: - # conditions = [Condition.generate(owners_after)] - # elif len(owners_after) > 1: - # conditions = [Condition.generate(owners) for owners - # in owners_after] - # else: - # # TODO: Why?? - # raise ValueError("`inputs` and `owners_after`'s count must be the " - # "same") + if len(owners_after) == 0: + raise ValueError('`owners_after` list cannot be empty') conds = [] for owner_after in owners_after: + if not isinstance(owner_after, tuple) or len(owner_after) != 2: + raise ValueError(('Each `owner_after` in the list is a tuple' + ' of `([], )`')) pub_keys, amount = owner_after conds.append(Condition.generate(pub_keys, amount)) diff --git a/bigchaindb/pipelines/vote.py b/bigchaindb/pipelines/vote.py index 6b12f55b..3d30de35 100644 --- a/bigchaindb/pipelines/vote.py +++ b/bigchaindb/pipelines/vote.py @@ -40,7 +40,7 @@ class Vote: self.validity = {} self.invalid_dummy_tx = Transaction.create([self.bigchain.me], - [self.bigchain.me]) + [([self.bigchain.me], 1)]) def validate_block(self, block): if not self.bigchain.has_previous_vote(block['id'], block['block']['voters']): diff --git a/tests/assets/test_divisible_assets.py b/tests/assets/test_divisible_assets.py index aeed19e6..d808008c 100644 --- a/tests/assets/test_divisible_assets.py +++ b/tests/assets/test_divisible_assets.py @@ -32,7 +32,8 @@ def test_single_in_single_own_multiple_out_single_own_create(b, user_vk): from bigchaindb.common.transaction import Asset asset = Asset(divisible=True) - tx = Transaction.create([b.me], [([user_vk], 50), ([user_vk], 50)], asset=asset) + tx = Transaction.create([b.me], [([user_vk], 50), ([user_vk], 50)], + asset=asset) tx_signed = tx.sign([b.me_private]) assert tx_signed.validate(b) == tx_signed @@ -161,7 +162,7 @@ def test_single_in_single_own_single_out_single_own_transfer(b, user_vk, # Single owners_after @pytest.mark.usefixtures('inputs') def test_single_in_single_own_multiple_out_single_own_transfer(b, user_vk, - user_sk): + user_sk): from bigchaindb.models import Transaction from bigchaindb.common.transaction import Asset @@ -197,7 +198,7 @@ def test_single_in_single_own_multiple_out_single_own_transfer(b, user_vk, # Multiple owners_after @pytest.mark.usefixtures('inputs') def test_single_in_single_own_single_out_multiple_own_transfer(b, user_vk, - user_sk): + user_sk): from bigchaindb.models import Transaction from bigchaindb.common.transaction import Asset @@ -238,7 +239,7 @@ def test_single_in_single_own_single_out_multiple_own_transfer(b, user_vk, # owners_after @pytest.mark.usefixtures('inputs') def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_vk, - user_sk): + user_sk): from bigchaindb.models import Transaction from bigchaindb.common.transaction import Asset @@ -390,7 +391,6 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_vk, assert len(ffill_fid1['subfulfillments']) == 2 - # TRANSFER divisible asset # Multiple inputs # Mix: one input with a single owners_before, one input with multiple @@ -589,46 +589,15 @@ def test_amount_error_transfer(b, user_vk, user_sk): tx_transfer_signed.validate(b) -@pytest.mark.skip -@pytest.mark.usefixtures('inputs') -def test_transaction_unfulfilled_fulfillments(b, user_vk, - user_sk): - from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset - - # CREATE divisible asset - asset = Asset(divisible=True) - tx_create = Transaction.create([b.me], - [([user_vk, b.me], 50), - ([user_vk, b.me], 50)], - asset=asset) - tx_create_signed = tx_create.sign([b.me_private]) - # create block - block = b.create_block([tx_create_signed]) - assert block.validate(b) == block - b.write_block(block, durability='hard') - # vote - vote = b.vote(block.id, b.get_last_voted_block().id, True) - b.write_vote(vote) - - # TRANSFER - tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], - asset=tx_create.asset) - tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk]) - - # TODO: This transaction has unfulfilled fulfillments and should be - # invalid. Somehow the validation passes - assert b.is_valid_transaction(tx_transfer_signed) == False - - -@pytest.mark.skip(reason=('get_subcondition_from_vk does not always work' - ' as expected')) +@pytest.mark.skip(reason='Figure out how to handle this case') @pytest.mark.usefixtures('inputs') def test_threshold_same_public_key(b, user_vk, user_sk): # If we try to fulfill a threshold condition where each subcondition has # the same key get_subcondition_from_vk will always return the first # subcondition. This means that only the 1st subfulfillment will be # generated + # Creating threshold conditions with the same key does not make sense but + # that does not mean that the code shouldn't work. from bigchaindb.models import Transaction from bigchaindb.common.transaction import Asset @@ -652,3 +621,66 @@ def test_threshold_same_public_key(b, user_vk, user_sk): tx_transfer_signed = tx_transfer.sign([user_sk, user_sk]) assert tx_transfer_signed.validate(b) == tx_transfer_signed + + +@pytest.mark.usefixtures('inputs') +def test_sum_amount(b, user_vk, user_sk): + from bigchaindb.models import Transaction + from bigchaindb.common.transaction import Asset + + # CREATE divisible asset with 3 outputs with amount 1 + asset = Asset(divisible=True) + tx_create = Transaction.create([b.me], + [([user_vk], 1), + ([user_vk], 1), + ([user_vk], 1)], + asset=asset) + tx_create_signed = tx_create.sign([b.me_private]) + # create block + block = b.create_block([tx_create_signed]) + assert block.validate(b) == block + b.write_block(block, durability='hard') + # vote + vote = b.vote(block.id, b.get_last_voted_block().id, True) + b.write_vote(vote) + + # create a transfer transaction with one output and check if the amount + # is 3 + tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 3)], + asset=tx_create.asset) + tx_transfer_signed = tx_transfer.sign([user_sk]) + + assert tx_transfer_signed.validate(b) == tx_transfer_signed + assert len(tx_transfer_signed.conditions) == 1 + assert tx_transfer_signed.conditions[0].amount == 3 + + +@pytest.mark.usefixtures('inputs') +def test_divide(b, user_vk, user_sk): + from bigchaindb.models import Transaction + from bigchaindb.common.transaction import Asset + + # CREATE divisible asset with 1 output with amount 3 + asset = Asset(divisible=True) + tx_create = Transaction.create([b.me], [([user_vk], 3)], + asset=asset) + tx_create_signed = tx_create.sign([b.me_private]) + # create block + block = b.create_block([tx_create_signed]) + assert block.validate(b) == block + b.write_block(block, durability='hard') + # vote + vote = b.vote(block.id, b.get_last_voted_block().id, True) + b.write_vote(vote) + + # create a transfer transaction with 3 outputs and check if the amount + # of each output is 1 + tx_transfer = Transaction.transfer(tx_create.to_inputs(), + [([b.me], 1), ([b.me], 1), ([b.me], 1)], + asset=tx_create.asset) + tx_transfer_signed = tx_transfer.sign([user_sk]) + + assert tx_transfer_signed.validate(b) == tx_transfer_signed + assert len(tx_transfer_signed.conditions) == 3 + for condition in tx_transfer_signed.conditions: + assert condition.amount == 1 diff --git a/tests/common/test_transaction.py b/tests/common/test_transaction.py index d5754b47..50e26c21 100644 --- a/tests/common/test_transaction.py +++ b/tests/common/test_transaction.py @@ -171,28 +171,6 @@ def test_generate_conditions_split_half_recursive(user_pub, user2_pub, assert cond.fulfillment.to_dict() == expected.to_dict() -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), 1) - assert cond.fulfillment.to_dict() == expected.to_dict() - - def test_generate_conditions_split_half_single_owner(user_pub, user2_pub, user3_pub): from bigchaindb.common.transaction import Condition @@ -614,24 +592,23 @@ def test_validate_fulfillment_with_invalid_parameters(utx): input_conditions) is False -@mark.skip(reason='Talk to @TimDaub') def test_validate_multiple_fulfillments(user_ffill, user_cond, user_priv): from copy import deepcopy from bigchaindb.common.crypto import SigningKey - from bigchaindb.common.transaction import Transaction, Asset + from bigchaindb.common.transaction import Transaction, Asset, Condition # TODO: Why is there a fulfillment in the conditions list - tx = Transaction(Transaction.CREATE, Asset(), + tx = Transaction(Transaction.CREATE, Asset(divisible=True), [user_ffill, deepcopy(user_ffill)], - [user_ffill, deepcopy(user_cond)]) + [user_cond, deepcopy(user_cond)]) expected_first = deepcopy(tx) expected_second = deepcopy(tx) expected_first.fulfillments = [expected_first.fulfillments[0]] - expected_first.conditions = [expected_first.conditions[0]] + expected_first.conditions = expected_first.conditions expected_second.fulfillments = [expected_second.fulfillments[1]] - expected_second.conditions = [expected_second.conditions[1]] + expected_second.conditions = expected_second.conditions expected_first_bytes = str(expected_first).encode() expected_first.fulfillments[0].fulfillment.sign(expected_first_bytes, @@ -700,7 +677,6 @@ def test_multiple_fulfillment_validation_of_transfer_tx(user_ffill, user_cond, assert transfer_tx.fulfillments_valid(tx.conditions) is True -@mark.skip(reason='Ask @TimDaub') def test_validate_fulfillments_of_transfer_tx_with_invalid_params(transfer_tx, cond_uri, utx, @@ -724,11 +700,6 @@ def test_validate_fulfillments_of_transfer_tx_with_invalid_params(transfer_tx, with raises(TypeError): transfer_tx.operation = "Operation that doesn't exist" transfer_tx.fulfillments_valid([utx.conditions[0]]) - # TODO: Why should this raise a ValueError? - with raises(ValueError): - tx = utx.sign([user_priv]) - tx.conditions = [] - tx.fulfillments_valid() def test_create_create_transaction_single_io(user_cond, user_pub, data, @@ -782,12 +753,15 @@ def test_validate_single_io_create_transaction(user_pub, user_priv, data): assert tx.fulfillments_valid() is True -@mark.skip(reason='Multiple inputs and outputs in CREATE not supported') -# TODO: Add digital assets def test_create_create_transaction_multiple_io(user_cond, user2_cond, user_pub, user2_pub): - from bigchaindb.common.transaction import Transaction + from bigchaindb.common.transaction import Transaction, Asset, Fulfillment + # a fulfillment for a create transaction with multiple `owners_before` + # is a fulfillment for an implicit threshold condition with + # weight = len(owners_before) + ffill = Fulfillment.generate([user_pub, user2_pub]).to_dict() + ffill.update({'fid': 0}) expected = { 'transaction': { 'conditions': [user_cond.to_dict(0), user2_cond.to_dict(1)], @@ -796,33 +770,20 @@ def test_create_create_transaction_multiple_io(user_cond, user2_cond, user_pub, 'message': 'hello' } }, - 'fulfillments': [ - { - 'owners_before': [ - user_pub, - ], - 'fid': 0, - 'fulfillment': None, - 'input': None - }, - { - 'owners_before': [ - user2_pub, - ], - 'fid': 1, - 'fulfillment': None, - 'input': None - } - ], + 'fulfillments': [ffill], 'operation': 'CREATE', }, 'version': 1 } - tx = Transaction.create([user_pub, user2_pub], [user_pub, user2_pub], - {'message': 'hello'}).to_dict() + asset = Asset(divisible=True) + tx = Transaction.create([user_pub, user2_pub], + [([user_pub], 1), ([user2_pub], 1)], + asset=asset, + metadata={'message': 'hello'}).to_dict() tx.pop('id') tx['transaction']['metadata'].pop('id') tx['transaction'].pop('timestamp') + tx['transaction'].pop('asset') assert tx == expected @@ -951,21 +912,21 @@ def test_validate_hashlock_create_transaction(user_pub, user_priv, data): assert tx.fulfillments_valid() is True -def test_create_create_transaction_with_invalid_parameters(): +def test_create_create_transaction_with_invalid_parameters(user_pub): 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) + Transaction.create([],[user_pub]) with raises(ValueError): - Transaction.create([], [], secret='wow, much secret') + Transaction.create([user_pub],[]) + with raises(ValueError): + Transaction.create([user_pub], [user_pub]) + with raises(ValueError): + Transaction.create([user_pub], [([user_pub],)]) def test_conditions_to_inputs(tx): @@ -1030,16 +991,15 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, assert transfer_tx.fulfillments_valid([tx.conditions[0]]) is True -@mark.skip(reason='FIXME: When divisible assets land') 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 + from bigchaindb.common.transaction import Transaction, Asset - 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]) + asset = Asset(divisible=True) + tx = Transaction.create([user_pub], [([user_pub], 1), ([user2_pub], 1)], + asset=asset, metadata={'message': 'hello'}) + tx = tx.sign([user_priv]) expected = { 'transaction': { @@ -1053,7 +1013,7 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv, 'fid': 0, 'fulfillment': None, 'input': { - 'txid': tx1.id, + 'txid': tx.id, 'cid': 0 } }, { @@ -1063,8 +1023,8 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv, 'fid': 1, 'fulfillment': None, 'input': { - 'txid': tx2.id, - 'cid': 0 + 'txid': tx.id, + 'cid': 1 } } ], @@ -1072,30 +1032,29 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv, }, 'version': 1 } - tx1_inputs = tx1.to_inputs() - tx2_inputs = tx2.to_inputs() - tx_inputs = tx1_inputs + tx2_inputs + tx_inputs = tx.to_inputs() - transfer_tx = Transaction.transfer(tx_inputs, [[user2_pub], [user2_pub]]) + transfer_tx = Transaction.transfer(tx.to_inputs(), + [([user2_pub], 1), ([user2_pub], 1)], + asset=tx.asset) 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 - combined_conditions = tx1.conditions + tx2.conditions - assert transfer_tx.fulfillments_valid(combined_conditions) is True + assert transfer_tx.fulfillments_valid(tx.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') + transfer_tx['transaction'].pop('asset') assert expected == transfer_tx -def test_create_transfer_with_invalid_parameters(): +def test_create_transfer_with_invalid_parameters(user_pub): from bigchaindb.common.transaction import Transaction, Asset with raises(TypeError): @@ -1106,6 +1065,10 @@ def test_create_transfer_with_invalid_parameters(): Transaction.transfer(['fulfillment'], {}, Asset()) with raises(ValueError): Transaction.transfer(['fulfillment'], [], Asset()) + with raises(ValueError): + Transaction.transfer(['fulfillment'], [user_pub], Asset()) + with raises(ValueError): + Transaction.transfer(['fulfillment'], [([user_pub],)], Asset()) def test_cant_add_empty_condition(): diff --git a/tests/conftest.py b/tests/conftest.py index 58178b7f..fcb6b318 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -72,7 +72,7 @@ def b(request, node_config): @pytest.fixture def create_tx(b, user_vk): from bigchaindb.models import Transaction - return Transaction.create([b.me], [user_vk]) + return Transaction.create([b.me], [([user_vk], 1)]) @pytest.fixture @@ -84,5 +84,5 @@ def signed_create_tx(b, create_tx): def signed_transfer_tx(signed_create_tx, user_vk, user_sk): from bigchaindb.models import Transaction inputs = signed_create_tx.to_inputs() - tx = Transaction.transfer(inputs, [user_vk], signed_create_tx.asset) + tx = Transaction.transfer(inputs, [([user_vk], 1)], signed_create_tx.asset) return tx.sign([user_sk]) diff --git a/tests/db/test_bigchain_api.py b/tests/db/test_bigchain_api.py index f0a88c44..74b875c7 100644 --- a/tests/db/test_bigchain_api.py +++ b/tests/db/test_bigchain_api.py @@ -15,7 +15,7 @@ def dummy_tx(): import bigchaindb from bigchaindb.models import Transaction b = bigchaindb.Bigchain() - tx = Transaction.create([b.me], [b.me]) + tx = Transaction.create([b.me], [([b.me], 1)]) tx = tx.sign([b.me_private]) return tx @@ -37,7 +37,7 @@ class TestBigchainApi(object): b.create_genesis_block() - tx = Transaction.create([b.me], [b.me]) + tx = Transaction.create([b.me], [([b.me], 1)]) tx = tx.sign([b.me_private]) monkeypatch.setattr('time.time', lambda: 1) block1 = b.create_block([tx]) @@ -60,7 +60,7 @@ class TestBigchainApi(object): b.create_genesis_block() - tx = Transaction.create([b.me], [b.me]) + tx = Transaction.create([b.me], [([b.me], 1)]) tx = tx.sign([b.me_private]) block1 = b.create_block([tx]) @@ -74,7 +74,7 @@ class TestBigchainApi(object): b.create_genesis_block() - tx = Transaction.create([b.me], [b.me]) + tx = Transaction.create([b.me], [([b.me], 1)]) tx = tx.sign([b.me_private]) monkeypatch.setattr('time.time', lambda: 1) @@ -99,7 +99,7 @@ class TestBigchainApi(object): b.create_genesis_block() - tx = Transaction.create([b.me], [b.me]) + tx = Transaction.create([b.me], [([b.me], 1)]) tx = tx.sign([b.me_private]) monkeypatch.setattr('time.time', lambda: 1) @@ -107,13 +107,15 @@ class TestBigchainApi(object): b.write_block(block1, durability='hard') monkeypatch.setattr('time.time', lambda: 2) - transfer_tx = Transaction.transfer(tx.to_inputs(), [b.me], tx.asset) + transfer_tx = Transaction.transfer(tx.to_inputs(), [([b.me], 1)], + tx.asset) transfer_tx = transfer_tx.sign([b.me_private]) block2 = b.create_block([transfer_tx]) b.write_block(block2, durability='hard') monkeypatch.setattr('time.time', lambda: 3) - transfer_tx2 = Transaction.transfer(tx.to_inputs(), [b.me], tx.asset) + transfer_tx2 = Transaction.transfer(tx.to_inputs(), [([b.me], 1)], + tx.asset) transfer_tx2 = transfer_tx2.sign([b.me_private]) block3 = b.create_block([transfer_tx2]) b.write_block(block3, durability='hard') @@ -133,7 +135,7 @@ class TestBigchainApi(object): b.create_genesis_block() - tx = Transaction.create([b.me], [b.me]) + tx = Transaction.create([b.me], [([b.me], 1)]) tx = tx.sign([b.me_private]) monkeypatch.setattr('time.time', lambda: 1) @@ -159,13 +161,13 @@ class TestBigchainApi(object): b.create_genesis_block() monkeypatch.setattr('time.time', lambda: 1) - tx1 = Transaction.create([b.me], [b.me]) + tx1 = Transaction.create([b.me], [([b.me], 1)]) tx1 = tx1.sign([b.me_private]) block1 = b.create_block([tx1]) b.write_block(block1, durability='hard') monkeypatch.setattr('time.time', lambda: 2) - tx2 = Transaction.create([b.me], [b.me]) + tx2 = Transaction.create([b.me], [([b.me], 1)]) tx2 = tx2.sign([b.me_private]) block2 = b.create_block([tx2]) b.write_block(block2, durability='hard') @@ -185,7 +187,7 @@ class TestBigchainApi(object): from bigchaindb.models import Transaction metadata = {'msg': 'Hello BigchainDB!'} - tx = Transaction.create([b.me], [user_vk], metadata=metadata) + tx = Transaction.create([b.me], [([user_vk], 1)], metadata=metadata) block = b.create_block([tx]) b.write_block(block, durability='hard') @@ -205,7 +207,7 @@ class TestBigchainApi(object): input_tx = b.get_owned_ids(user_vk).pop() input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() - tx = Transaction.transfer(inputs, [user_vk], input_tx.asset) + tx = Transaction.transfer(inputs, [([user_vk], 1)], input_tx.asset) tx = tx.sign([user_sk]) response = b.write_transaction(tx) @@ -223,7 +225,7 @@ class TestBigchainApi(object): input_tx = b.get_owned_ids(user_vk).pop() input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() - tx = Transaction.transfer(inputs, [user_vk], input_tx.asset) + tx = Transaction.transfer(inputs, [([user_vk], 1)], input_tx.asset) tx = tx.sign([user_sk]) b.write_transaction(tx) @@ -243,7 +245,7 @@ class TestBigchainApi(object): input_tx = b.get_owned_ids(user_vk).pop() input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() - tx = Transaction.transfer(inputs, [user_vk], input_tx.asset) + tx = Transaction.transfer(inputs, [([user_vk], 1)], input_tx.asset) tx = tx.sign([user_sk]) b.write_transaction(tx) @@ -499,7 +501,7 @@ class TestBigchainApi(object): input_tx = b.get_owned_ids(user_vk).pop() input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() - tx = Transaction.transfer(inputs, [user_vk], input_tx.asset) + tx = Transaction.transfer(inputs, [([user_vk], 1)], input_tx.asset) tx = tx.sign([user_sk]) b.write_transaction(tx) @@ -525,7 +527,7 @@ class TestBigchainApi(object): input_tx = b.get_owned_ids(user_vk).pop() input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() - tx = Transaction.transfer(inputs, [user_vk], input_tx.asset) + tx = Transaction.transfer(inputs, [([user_vk], 1)], input_tx.asset) tx = tx.sign([user_sk]) b.write_transaction(tx) @@ -549,7 +551,7 @@ class TestBigchainApi(object): fulfillment = Fulfillment(Ed25519Fulfillment(public_key=user_vk), [user_vk], TransactionLink('somethingsomething', 0)) - tx = Transaction.transfer([fulfillment], [user_vk], Asset()) + tx = Transaction.transfer([fulfillment], [([user_vk], 1)], Asset()) with pytest.raises(TransactionDoesNotExist) as excinfo: tx.validate(Bigchain()) @@ -591,7 +593,7 @@ class TestTransactionValidation(object): input_tx = b.get_owned_ids(user_vk).pop() input_transaction = b.get_transaction(input_tx.txid) sk, vk = generate_key_pair() - tx = Transaction.create([vk], [user_vk]) + tx = Transaction.create([vk], [([user_vk], 1)]) tx.operation = 'TRANSFER' tx.asset = input_transaction.asset tx.fulfillments[0].tx_input = input_tx @@ -635,7 +637,7 @@ class TestTransactionValidation(object): input_tx = b.get_owned_ids(user_vk).pop() input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() - transfer_tx = Transaction.transfer(inputs, [user_vk], input_tx.asset) + transfer_tx = Transaction.transfer(inputs, [([user_vk], 1)], input_tx.asset) transfer_tx = transfer_tx.sign([user_sk]) assert transfer_tx == b.validate_transaction(transfer_tx) @@ -659,7 +661,7 @@ class TestTransactionValidation(object): inputs = input_tx.to_inputs() # create a transaction that's valid but not in a voted valid block - transfer_tx = Transaction.transfer(inputs, [user_vk], input_tx.asset) + transfer_tx = Transaction.transfer(inputs, [([user_vk], 1)], input_tx.asset) transfer_tx = transfer_tx.sign([user_sk]) assert transfer_tx == b.validate_transaction(transfer_tx) @@ -669,8 +671,9 @@ class TestTransactionValidation(object): b.write_block(block, durability='hard') # create transaction with the undecided input - tx_invalid = Transaction.transfer(transfer_tx.to_inputs(), [user_vk], - transfer_tx.asset) + tx_invalid = Transaction.transfer(transfer_tx.to_inputs(), + [([user_vk], 1)], + transfer_tx.asset) tx_invalid = tx_invalid.sign([user_sk]) with pytest.raises(FulfillmentNotInValidBlock): @@ -768,7 +771,7 @@ class TestMultipleInputs(object): tx_link = b.get_owned_ids(user_vk).pop() input_tx = b.get_transaction(tx_link.txid) inputs = input_tx.to_inputs() - tx = Transaction.transfer(inputs, [user2_vk], input_tx.asset) + tx = Transaction.transfer(inputs, [([user2_vk], 1)], input_tx.asset) tx = tx.sign([user_sk]) # validate transaction @@ -776,69 +779,6 @@ class TestMultipleInputs(object): assert len(tx.fulfillments) == 1 assert len(tx.conditions) == 1 - @pytest.mark.skipif(reason=('Multiple inputs are only allowed for the ' - 'same asset. Remove this after implementing ', - 'multiple assets')) - @pytest.mark.usefixtures('inputs') - def test_transfer_single_owners_multiple_inputs(self, b, user_sk, user_vk): - from bigchaindb.common import crypto - from bigchaindb.models import Transaction - - user2_sk, user2_vk = crypto.generate_key_pair() - - # get inputs - owned_inputs = b.get_owned_ids(user_vk) - input_txs = [b.get_transaction(tx_link.txid) for tx_link - in owned_inputs] - inputs = sum([input_tx.to_inputs() for input_tx in input_txs], []) - tx = Transaction.transfer(inputs, len(inputs) * [[user_vk]]) - tx = tx.sign([user_sk]) - assert b.validate_transaction(tx) == tx - assert len(tx.fulfillments) == len(inputs) - assert len(tx.conditions) == len(inputs) - - @pytest.mark.skipif(reason=('Multiple inputs are only allowed for the ' - 'same asset. Remove this after implementing ', - 'multiple assets')) - @pytest.mark.usefixtures('inputs') - def test_transfer_single_owners_single_input_from_multiple_outputs(self, b, - user_sk, - user_vk): - from bigchaindb.common import crypto - from bigchaindb.models import Transaction - - user2_sk, user2_vk = crypto.generate_key_pair() - - # get inputs - owned_inputs = b.get_owned_ids(user_vk) - input_txs = [b.get_transaction(tx_link.txid) for tx_link - in owned_inputs] - inputs = sum([input_tx.to_inputs() for input_tx in input_txs], []) - tx = Transaction.transfer(inputs, len(inputs) * [[user2_vk]]) - tx = tx.sign([user_sk]) - - # create block with the transaction - block = b.create_block([tx]) - b.write_block(block, durability='hard') - - # vote block valid - vote = b.vote(block.id, b.get_last_voted_block().id, True) - b.write_vote(vote) - - # get inputs from user2 - owned_inputs = b.get_owned_ids(user2_vk) - assert len(owned_inputs) == len(inputs) - - # create a transaction with a single input from a multiple output transaction - tx_link = owned_inputs.pop() - inputs = b.get_transaction(tx_link.txid).to_inputs([0]) - tx = Transaction.transfer(inputs, [user_vk]) - tx = tx.sign([user2_sk]) - - assert b.is_valid_transaction(tx) == tx - assert len(tx.fulfillments) == 1 - assert len(tx.conditions) == 1 - def test_single_owner_before_multiple_owners_after_single_input(self, b, user_sk, user_vk, @@ -852,47 +792,14 @@ class TestMultipleInputs(object): owned_inputs = b.get_owned_ids(user_vk) tx_link = owned_inputs.pop() input_tx = b.get_transaction(tx_link.txid) - tx = Transaction.transfer(input_tx.to_inputs(), [[user2_vk, user3_vk]], input_tx.asset) + tx = Transaction.transfer(input_tx.to_inputs(), + [([user2_vk, user3_vk], 1)], input_tx.asset) tx = tx.sign([user_sk]) assert b.is_valid_transaction(tx) == tx assert len(tx.fulfillments) == 1 assert len(tx.conditions) == 1 - @pytest.mark.skipif(reason=('Multiple inputs are only allowed for the ' - 'same asset. Remove this after implementing ', - 'multiple assets')) - @pytest.mark.usefixtures('inputs') - def test_single_owner_before_multiple_owners_after_multiple_inputs(self, b, - user_sk, - user_vk): - from bigchaindb.common import crypto - from bigchaindb.models import Transaction - - user2_sk, user2_vk = crypto.generate_key_pair() - user3_sk, user3_vk = crypto.generate_key_pair() - - owned_inputs = b.get_owned_ids(user_vk) - input_txs = [b.get_transaction(tx_link.txid) for tx_link - in owned_inputs] - inputs = sum([input_tx.to_inputs() for input_tx in input_txs], []) - - tx = Transaction.transfer(inputs, len(inputs) * [[user2_vk, user3_vk]]) - tx = tx.sign([user_sk]) - - # create block with the transaction - block = b.create_block([tx]) - b.write_block(block, durability='hard') - - # vote block valid - vote = b.vote(block.id, b.get_last_voted_block().id, True) - b.write_vote(vote) - - # validate transaction - assert b.is_valid_transaction(tx) == tx - assert len(tx.fulfillments) == len(inputs) - assert len(tx.conditions) == len(inputs) - @pytest.mark.usefixtures('inputs') def test_multiple_owners_before_single_owner_after_single_input(self, b, user_sk, @@ -903,7 +810,7 @@ class TestMultipleInputs(object): user2_sk, user2_vk = crypto.generate_key_pair() user3_sk, user3_vk = crypto.generate_key_pair() - tx = Transaction.create([b.me], [user_vk, user2_vk]) + tx = Transaction.create([b.me], [([user_vk, user2_vk], 1)]) tx = tx.sign([b.me_private]) block = b.create_block([tx]) b.write_block(block, durability='hard') @@ -916,7 +823,8 @@ class TestMultipleInputs(object): input_tx = b.get_transaction(owned_input.txid) inputs = input_tx.to_inputs() - transfer_tx = Transaction.transfer(inputs, [user3_vk], input_tx.asset) + transfer_tx = Transaction.transfer(inputs, [([user3_vk], 1)], + input_tx.asset) transfer_tx = transfer_tx.sign([user_sk, user2_sk]) # validate transaction @@ -924,29 +832,6 @@ class TestMultipleInputs(object): assert len(transfer_tx.fulfillments) == 1 assert len(transfer_tx.conditions) == 1 - @pytest.mark.skipif(reason=('Multiple inputs are only allowed for the ' - 'same asset. Remove this after implementing ', - 'multiple assets')) - @pytest.mark.usefixtures('inputs_shared') - def test_multiple_owners_before_single_owner_after_multiple_inputs(self, b, - user_sk, user_vk, user2_vk, user2_sk): - from bigchaindb.common import crypto - from bigchaindb.models import Transaction - - # create a new users - user3_sk, user3_vk = crypto.generate_key_pair() - - tx_links = b.get_owned_ids(user_vk) - inputs = sum([b.get_transaction(tx_link.txid).to_inputs() for tx_link - in tx_links], []) - - tx = Transaction.transfer(inputs, len(inputs) * [[user3_vk]]) - tx = tx.sign([user_sk, user2_sk]) - - assert b.is_valid_transaction(tx) == tx - assert len(tx.fulfillments) == len(inputs) - assert len(tx.conditions) == len(inputs) - @pytest.mark.usefixtures('inputs') def test_multiple_owners_before_multiple_owners_after_single_input(self, b, user_sk, @@ -958,7 +843,7 @@ class TestMultipleInputs(object): user3_sk, user3_vk = crypto.generate_key_pair() user4_sk, user4_vk = crypto.generate_key_pair() - tx = Transaction.create([b.me], [user_vk, user2_vk]) + tx = Transaction.create([b.me], [([user_vk, user2_vk], 1)]) tx = tx.sign([b.me_private]) block = b.create_block([tx]) b.write_block(block, durability='hard') @@ -971,38 +856,14 @@ class TestMultipleInputs(object): tx_link = b.get_owned_ids(user_vk).pop() tx_input = b.get_transaction(tx_link.txid) - tx = Transaction.transfer(tx_input.to_inputs(), [[user3_vk, user4_vk]], tx_input.asset) + tx = Transaction.transfer(tx_input.to_inputs(), + [([user3_vk, user4_vk], 1)], tx_input.asset) tx = tx.sign([user_sk, user2_sk]) assert b.is_valid_transaction(tx) == tx assert len(tx.fulfillments) == 1 assert len(tx.conditions) == 1 - @pytest.mark.skipif(reason=('Multiple inputs are only allowed for the ' - 'same asset. Remove this after implementing ', - 'multiple assets')) - @pytest.mark.usefixtures('inputs_shared') - def test_multiple_owners_before_multiple_owners_after_multiple_inputs(self, b, - user_sk, user_vk, - user2_sk, user2_vk): - from bigchaindb.common import crypto - from bigchaindb.models import Transaction - - # create a new users - user3_sk, user3_vk = crypto.generate_key_pair() - user4_sk, user4_vk = crypto.generate_key_pair() - - tx_links = b.get_owned_ids(user_vk) - inputs = sum([b.get_transaction(tx_link.txid).to_inputs() for tx_link - in tx_links], []) - - tx = Transaction.transfer(inputs, len(inputs) * [[user3_vk, user4_vk]]) - tx = tx.sign([user_sk, user2_sk]) - - assert b.is_valid_transaction(tx) == tx - assert len(tx.fulfillments) == len(inputs) - assert len(tx.conditions) == len(inputs) - def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_vk): from bigchaindb.common import crypto from bigchaindb.common.transaction import TransactionLink @@ -1010,7 +871,7 @@ class TestMultipleInputs(object): user2_sk, user2_vk = crypto.generate_key_pair() - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]) block = b.create_block([tx]) b.write_block(block, durability='hard') @@ -1020,7 +881,7 @@ class TestMultipleInputs(object): assert owned_inputs_user1 == [TransactionLink(tx.id, 0)] assert owned_inputs_user2 == [] - tx = Transaction.transfer(tx.to_inputs(), [user2_vk], tx.asset) + tx = Transaction.transfer(tx.to_inputs(), [([user2_vk], 1)], tx.asset) tx = tx.sign([user_sk]) block = b.create_block([tx]) b.write_block(block, durability='hard') @@ -1040,7 +901,7 @@ class TestMultipleInputs(object): genesis = b.create_genesis_block() user2_sk, user2_vk = crypto.generate_key_pair() - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]) block = b.create_block([tx]) b.write_block(block, durability='hard') @@ -1056,7 +917,8 @@ class TestMultipleInputs(object): # NOTE: The transaction itself is valid, still will mark the block # as invalid to mock the behavior. - tx_invalid = Transaction.transfer(tx.to_inputs(), [user2_vk], tx.asset) + tx_invalid = Transaction.transfer(tx.to_inputs(), [([user2_vk], 1)], + tx.asset) tx_invalid = tx_invalid.sign([user_sk]) block = b.create_block([tx_invalid]) b.write_block(block, durability='hard') @@ -1072,47 +934,46 @@ class TestMultipleInputs(object): assert owned_inputs_user1 == [TransactionLink(tx.id, 0)] assert owned_inputs_user2 == [] - @pytest.mark.skipif(reason=('Multiple inputs are only allowed for the ' - 'same asset. Remove this after implementing ', - 'multiple assets')) def test_get_owned_ids_single_tx_multiple_outputs(self, b, user_sk, user_vk): import random from bigchaindb.common import crypto - from bigchaindb.common.transaction import TransactionLink + from bigchaindb.common.transaction import TransactionLink, Asset from bigchaindb.models import Transaction user2_sk, user2_vk = crypto.generate_key_pair() - transactions = [] - for i in range(2): - payload = {'somedata': random.randint(0, 255)} - tx = Transaction.create([b.me], [user_vk], payload) - tx = tx.sign([b.me_private]) - transactions.append(tx) - block = b.create_block(transactions) + # create divisible asset + asset = Asset(divisible=True) + tx_create = Transaction.create([b.me], + [([user_vk], 1), ([user_vk], 1)], + asset=asset) + tx_create_signed = tx_create.sign([b.me_private]) + block = b.create_block([tx_create_signed]) b.write_block(block, durability='hard') # get input owned_inputs_user1 = b.get_owned_ids(user_vk) owned_inputs_user2 = b.get_owned_ids(user2_vk) - expected_owned_inputs_user1 = [TransactionLink(tx.id, 0) for tx - in transactions] + expected_owned_inputs_user1 = [TransactionLink(tx_create.id, 0), + TransactionLink(tx_create.id, 1)] assert owned_inputs_user1 == expected_owned_inputs_user1 assert owned_inputs_user2 == [] - inputs = sum([tx.to_inputs() for tx in transactions], []) - tx = Transaction.transfer(inputs, len(inputs) * [[user2_vk]]) - tx = tx.sign([user_sk]) - block = b.create_block([tx]) + # transfer divisible asset divided in two outputs + tx_transfer = Transaction.transfer(tx_create.to_inputs(), + [([user2_vk], 1), ([user2_vk], 1)], + asset=tx_create.asset) + tx_transfer_signed = tx_transfer.sign([user_sk]) + block = b.create_block([tx_transfer_signed]) b.write_block(block, durability='hard') owned_inputs_user1 = b.get_owned_ids(user_vk) owned_inputs_user2 = b.get_owned_ids(user2_vk) assert owned_inputs_user1 == [] - assert owned_inputs_user2 == [TransactionLink(tx.id, 0), - TransactionLink(tx.id, 1)] + assert owned_inputs_user2 == [TransactionLink(tx_transfer.id, 0), + TransactionLink(tx_transfer.id, 1)] def test_get_owned_ids_multiple_owners(self, b, user_sk, user_vk): from bigchaindb.common import crypto @@ -1122,7 +983,7 @@ class TestMultipleInputs(object): user2_sk, user2_vk = crypto.generate_key_pair() user3_sk, user3_vk = crypto.generate_key_pair() - tx = Transaction.create([b.me], [user_vk, user2_vk]) + tx = Transaction.create([b.me], [([user_vk, user2_vk],1)]) tx = tx.sign([b.me_private]) block = b.create_block([tx]) b.write_block(block, durability='hard') @@ -1134,7 +995,7 @@ class TestMultipleInputs(object): assert owned_inputs_user1 == owned_inputs_user2 assert owned_inputs_user1 == expected_owned_inputs_user1 - tx = Transaction.transfer(tx.to_inputs(), [user3_vk], tx.asset) + tx = Transaction.transfer(tx.to_inputs(), [([user3_vk], 1)], tx.asset) tx = tx.sign([user_sk, user2_sk]) block = b.create_block([tx]) b.write_block(block, durability='hard') @@ -1150,7 +1011,7 @@ class TestMultipleInputs(object): user2_sk, user2_vk = crypto.generate_key_pair() - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]) block = b.create_block([tx]) b.write_block(block, durability='hard') @@ -1164,7 +1025,7 @@ class TestMultipleInputs(object): assert spent_inputs_user1 is None # create a transaction and block - tx = Transaction.transfer(tx.to_inputs(), [user2_vk], tx.asset) + tx = Transaction.transfer(tx.to_inputs(), [([user2_vk], 1)], tx.asset) tx = tx.sign([user_sk]) block = b.create_block([tx]) b.write_block(block, durability='hard') @@ -1181,7 +1042,7 @@ class TestMultipleInputs(object): # create a new users user2_sk, user2_vk = crypto.generate_key_pair() - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]) block = b.create_block([tx]) b.write_block(block, durability='hard') @@ -1199,7 +1060,7 @@ class TestMultipleInputs(object): assert spent_inputs_user1 is None # create a transaction and block - tx = Transaction.transfer(tx.to_inputs(), [user2_vk], tx.asset) + tx = Transaction.transfer(tx.to_inputs(), [([user2_vk], 1)], tx.asset) tx = tx.sign([user_sk]) block = b.create_block([tx]) b.write_block(block, durability='hard') @@ -1214,24 +1075,24 @@ class TestMultipleInputs(object): # Now there should be no spents (the block is invalid) assert spent_inputs_user1 is None - @pytest.mark.skipif(reason=('Multiple inputs are only allowed for the ' - 'same asset. Remove this after implementing ', - 'multiple assets')) def test_get_spent_single_tx_multiple_outputs(self, b, user_sk, user_vk): import random from bigchaindb.common import crypto from bigchaindb.models import Transaction + from bigchaindb.common.transaction import Asset # create a new users user2_sk, user2_vk = crypto.generate_key_pair() - transactions = [] - for i in range(3): - payload = {'somedata': random.randint(0, 255)} - tx = Transaction.create([b.me], [user_vk], payload) - tx = tx.sign([b.me_private]) - transactions.append(tx) - block = b.create_block(transactions) + # create a divisible asset with 3 outputs + asset = Asset(divisible=True) + tx_create = Transaction.create([b.me], + [([user_vk], 1), + ([user_vk], 1), + ([user_vk], 1)], + asset=asset) + tx_create_signed = tx_create.sign([b.me_private]) + block = b.create_block([tx_create_signed]) b.write_block(block, durability='hard') owned_inputs_user1 = b.get_owned_ids(user_vk) @@ -1240,22 +1101,22 @@ class TestMultipleInputs(object): for input_tx in owned_inputs_user1: assert b.get_spent(input_tx.txid, input_tx.cid) is None - # select inputs to use - inputs = sum([tx.to_inputs() for tx in transactions[:2]], []) - - # create a transaction and block - tx = Transaction.transfer(inputs, len(inputs) * [[user2_vk]]) - tx = tx.sign([user_sk]) - block = b.create_block([tx]) + # transfer the first 2 inputs + tx_transfer = Transaction.transfer(tx_create.to_inputs()[:2], + [([user2_vk], 1), ([user2_vk], 1)], + asset=tx_create.asset) + tx_transfer_signed = tx_transfer.sign([user_sk]) + block = b.create_block([tx_transfer_signed]) b.write_block(block, durability='hard') # check that used inputs are marked as spent - for ffill in inputs: - assert b.get_spent(ffill.tx_input.txid, ffill.tx_input.cid) == tx + for ffill in tx_create.to_inputs()[:2]: + spent_tx = b.get_spent(ffill.tx_input.txid, ffill.tx_input.cid) + assert spent_tx == tx_transfer_signed # check if remaining transaction that was unspent is also perceived # spendable by BigchainDB - assert b.get_spent(transactions[2].id, 0) is None + assert b.get_spent(tx_create.to_inputs()[2].tx_input.txid, 2) is None def test_get_spent_multiple_owners(self, b, user_sk, user_vk): import random @@ -1268,7 +1129,7 @@ class TestMultipleInputs(object): transactions = [] for i in range(3): payload = {'somedata': random.randint(0, 255)} - tx = Transaction.create([b.me], [user_vk, user2_vk], payload) + tx = Transaction.create([b.me], [([user_vk, user2_vk], 1)], payload) tx = tx.sign([b.me_private]) transactions.append(tx) block = b.create_block(transactions) @@ -1281,7 +1142,8 @@ class TestMultipleInputs(object): assert b.get_spent(input_tx.txid, input_tx.cid) is None # create a transaction - tx = Transaction.transfer(transactions[0].to_inputs(), [user3_vk], transactions[0].asset) + tx = Transaction.transfer(transactions[0].to_inputs(), + [([user3_vk], 1)], transactions[0].asset) tx = tx.sign([user_sk, user2_sk]) block = b.create_block([tx]) b.write_block(block, durability='hard') diff --git a/tests/pipelines/test_block_creation.py b/tests/pipelines/test_block_creation.py index c2403a08..5396ebc3 100644 --- a/tests/pipelines/test_block_creation.py +++ b/tests/pipelines/test_block_creation.py @@ -45,7 +45,7 @@ def test_create_block(b, user_vk): block_maker = BlockPipeline() for i in range(100): - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]) block_maker.create(tx) @@ -63,7 +63,7 @@ def test_write_block(b, user_vk): txs = [] for i in range(100): - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]) txs.append(tx) @@ -82,7 +82,7 @@ def test_duplicate_transaction(b, user_vk): txs = [] for i in range(10): - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]) txs.append(tx) @@ -110,7 +110,7 @@ def test_delete_tx(b, user_vk): from bigchaindb.pipelines.block import BlockPipeline block_maker = BlockPipeline() for i in range(100): - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]) block_maker.create(tx) # make sure the tx appears in the backlog @@ -139,7 +139,8 @@ def test_prefeed(b, user_vk): from bigchaindb.pipelines.block import initial for i in range(100): - tx = Transaction.create([b.me], [user_vk], {'msg': random.random()}) + tx = Transaction.create([b.me], [([user_vk], 1)], + {'msg': random.random()}) tx = tx.sign([b.me_private]) b.write_transaction(tx) @@ -168,7 +169,8 @@ def test_full_pipeline(b, user_vk): count_assigned_to_me = 0 for i in range(100): - tx = Transaction.create([b.me], [user_vk], {'msg': random.random()}) + tx = Transaction.create([b.me], [([user_vk], 1)], + {'msg': random.random()}) tx = tx.sign([b.me_private]).to_dict() assignee = random.choice([b.me, 'aaa', 'bbb', 'ccc']) tx['assignee'] = assignee diff --git a/tests/pipelines/test_election.py b/tests/pipelines/test_election.py index 669a75cb..d62869f5 100644 --- a/tests/pipelines/test_election.py +++ b/tests/pipelines/test_election.py @@ -15,7 +15,7 @@ def test_check_for_quorum_invalid(b, user_vk): e = election.Election() # create blocks with transactions - tx1 = Transaction.create([b.me], [user_vk]) + tx1 = Transaction.create([b.me], [([user_vk], 1)]) test_block = b.create_block([tx1]) # simulate a federation with four voters @@ -44,7 +44,7 @@ def test_check_for_quorum_invalid_prev_node(b, user_vk): e = election.Election() # create blocks with transactions - tx1 = Transaction.create([b.me], [user_vk]) + tx1 = Transaction.create([b.me], [([user_vk], 1)]) test_block = b.create_block([tx1]) # simulate a federation with four voters @@ -74,7 +74,7 @@ def test_check_for_quorum_valid(b, user_vk): e = election.Election() # create blocks with transactions - tx1 = Transaction.create([b.me], [user_vk]) + tx1 = Transaction.create([b.me], [([user_vk], 1)]) test_block = b.create_block([tx1]) # simulate a federation with four voters @@ -103,7 +103,7 @@ def test_check_requeue_transaction(b, user_vk): e = election.Election() # create blocks with transactions - tx1 = Transaction.create([b.me], [user_vk]) + tx1 = Transaction.create([b.me], [([user_vk], 1)]) test_block = b.create_block([tx1]) e.requeue_transactions(test_block) @@ -131,7 +131,8 @@ def test_full_pipeline(b, user_vk): # write two blocks txs = [] for i in range(100): - tx = Transaction.create([b.me], [user_vk], {'msg': random.random()}) + tx = Transaction.create([b.me], [([user_vk], 1)], + {'msg': random.random()}) tx = tx.sign([b.me_private]) txs.append(tx) @@ -140,7 +141,8 @@ def test_full_pipeline(b, user_vk): txs = [] for i in range(100): - tx = Transaction.create([b.me], [user_vk], {'msg': random.random()}) + tx = Transaction.create([b.me], [([user_vk], 1)], + {'msg': random.random()}) tx = tx.sign([b.me_private]) txs.append(tx) diff --git a/tests/pipelines/test_stale_monitor.py b/tests/pipelines/test_stale_monitor.py index 3a3e6ffe..95f298c5 100644 --- a/tests/pipelines/test_stale_monitor.py +++ b/tests/pipelines/test_stale_monitor.py @@ -10,7 +10,7 @@ import os def test_get_stale(b, user_vk): from bigchaindb.models import Transaction - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]) b.write_transaction(tx, durability='hard') @@ -27,7 +27,7 @@ def test_get_stale(b, user_vk): def test_reassign_transactions(b, user_vk): from bigchaindb.models import Transaction # test with single node - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]) b.write_transaction(tx, durability='hard') @@ -36,7 +36,7 @@ def test_reassign_transactions(b, user_vk): stm.reassign_transactions(tx.to_dict()) # test with federation - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]) b.write_transaction(tx, durability='hard') @@ -51,7 +51,7 @@ def test_reassign_transactions(b, user_vk): assert reassigned_tx['assignee'] != tx['assignee'] # test with node not in federation - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]).to_dict() tx.update({'assignee': 'lol'}) tx.update({'assignment_timestamp': time.time()}) @@ -85,7 +85,7 @@ def test_full_pipeline(monkeypatch, user_vk): monkeypatch.setattr('time.time', lambda: 1) for i in range(100): - tx = Transaction.create([b.me], [user_vk]) + tx = Transaction.create([b.me], [([user_vk], 1)]) tx = tx.sign([b.me_private]) original_txc.append(tx.to_dict()) diff --git a/tests/pipelines/test_vote.py b/tests/pipelines/test_vote.py index 5bd0eb52..ec2f6204 100644 --- a/tests/pipelines/test_vote.py +++ b/tests/pipelines/test_vote.py @@ -8,7 +8,7 @@ from multipipes import Pipe, Pipeline def dummy_tx(b): from bigchaindb.models import Transaction - tx = Transaction.create([b.me], [b.me]) + tx = Transaction.create([b.me], [([b.me], 1)]) tx = tx.sign([b.me_private]) return tx @@ -130,7 +130,7 @@ def test_vote_validate_transaction(b): assert validation == (True, 123, 1) # NOTE: Submit unsigned transaction to `validate_tx` yields `False`. - tx = Transaction.create([b.me], [b.me]) + tx = Transaction.create([b.me], [([b.me], 1)]) validation = vote_obj.validate_tx(tx, 456, 10) assert validation == (False, 456, 10) @@ -224,7 +224,7 @@ def test_valid_block_voting_with_create_transaction(b, monkeypatch): # create a `CREATE` transaction test_user_priv, test_user_pub = crypto.generate_key_pair() - tx = Transaction.create([b.me], [test_user_pub]) + tx = Transaction.create([b.me], [([test_user_pub], 1)]) tx = tx.sign([b.me_private]) monkeypatch.setattr('time.time', lambda: 1) @@ -265,7 +265,7 @@ def test_valid_block_voting_with_transfer_transactions(monkeypatch, b): # create a `CREATE` transaction test_user_priv, test_user_pub = crypto.generate_key_pair() - tx = Transaction.create([b.me], [test_user_pub]) + tx = Transaction.create([b.me], [([test_user_pub], 1)]) tx = tx.sign([b.me_private]) monkeypatch.setattr('time.time', lambda: 1) @@ -274,7 +274,8 @@ def test_valid_block_voting_with_transfer_transactions(monkeypatch, b): # create a `TRANSFER` transaction test_user2_priv, test_user2_pub = crypto.generate_key_pair() - tx2 = Transaction.transfer(tx.to_inputs(), [test_user2_pub], tx.asset) + tx2 = Transaction.transfer(tx.to_inputs(), [([test_user2_pub], 1)], + tx.asset) tx2 = tx2.sign([test_user_priv]) monkeypatch.setattr('time.time', lambda: 2) @@ -338,7 +339,7 @@ def test_unsigned_tx_in_block_voting(monkeypatch, b, user_vk): vote_pipeline.setup(indata=inpipe, outdata=outpipe) # NOTE: `tx` is invalid, because it wasn't signed. - tx = Transaction.create([b.me], [b.me]) + tx = Transaction.create([b.me], [([b.me], 1)]) block = b.create_block([tx]) inpipe.put(block.to_dict()) @@ -375,7 +376,7 @@ def test_invalid_id_tx_in_block_voting(monkeypatch, b, user_vk): vote_pipeline.setup(indata=inpipe, outdata=outpipe) # NOTE: `tx` is invalid, because its id is not corresponding to its content - tx = Transaction.create([b.me], [b.me]) + tx = Transaction.create([b.me], [([b.me], 1)]) tx = tx.sign([b.me_private]) block = b.create_block([tx]).to_dict() block['block']['transactions'][0]['id'] = 'an invalid tx id' @@ -414,7 +415,7 @@ def test_invalid_content_in_tx_in_block_voting(monkeypatch, b, user_vk): vote_pipeline.setup(indata=inpipe, outdata=outpipe) # NOTE: `tx` is invalid, because its content is not corresponding to its id - tx = Transaction.create([b.me], [b.me]) + tx = Transaction.create([b.me], [([b.me], 1)]) tx = tx.sign([b.me_private]) block = b.create_block([tx]).to_dict() block['block']['transactions'][0]['id'] = 'an invalid tx id' diff --git a/tests/web/test_basic_views.py b/tests/web/test_basic_views.py index 00e40a37..7d382ca5 100644 --- a/tests/web/test_basic_views.py +++ b/tests/web/test_basic_views.py @@ -36,7 +36,7 @@ def test_post_create_transaction_endpoint(b, client): from bigchaindb.models import Transaction user_priv, user_pub = crypto.generate_key_pair() - tx = Transaction.create([user_pub], [user_pub]) + tx = Transaction.create([user_pub], [([user_pub], 1)]) tx = tx.sign([user_priv]) res = client.post(TX_ENDPOINT, data=json.dumps(tx.to_dict())) @@ -48,7 +48,7 @@ def test_post_create_transaction_with_invalid_id(b, client): from bigchaindb.models import Transaction user_priv, user_pub = crypto.generate_key_pair() - tx = Transaction.create([user_pub], [user_pub]) + tx = Transaction.create([user_pub], [([user_pub], 1)]) tx = tx.sign([user_priv]).to_dict() tx['id'] = 'invalid id' @@ -60,7 +60,7 @@ def test_post_create_transaction_with_invalid_signature(b, client): from bigchaindb.models import Transaction user_priv, user_pub = crypto.generate_key_pair() - tx = Transaction.create([user_pub], [user_pub]) + tx = Transaction.create([user_pub], [([user_pub], 1)]) tx = tx.sign([user_priv]).to_dict() tx['transaction']['fulfillments'][0]['fulfillment'] = 'invalid signature' @@ -77,7 +77,8 @@ def test_post_transfer_transaction_endpoint(b, client, user_vk, user_sk): input_valid = b.get_owned_ids(user_vk).pop() create_tx = b.get_transaction(input_valid.txid) - transfer_tx = Transaction.transfer(create_tx.to_inputs(), [user_pub], create_tx.asset) + transfer_tx = Transaction.transfer(create_tx.to_inputs(), + [([user_pub], 1)], create_tx.asset) transfer_tx = transfer_tx.sign([user_sk]) res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict())) @@ -94,7 +95,8 @@ def test_post_invalid_transfer_transaction_returns_400(b, client, user_vk, user_ input_valid = b.get_owned_ids(user_vk).pop() create_tx = b.get_transaction(input_valid.txid) - transfer_tx = Transaction.transfer(create_tx.to_inputs(), [user_pub], create_tx.asset) + transfer_tx = Transaction.transfer(create_tx.to_inputs(), + [([user_pub], 1)], create_tx.asset) res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict())) assert res.status_code == 400