diff --git a/bigchaindb/common/transaction.py b/bigchaindb/common/transaction.py index 9b423902..245b89c7 100644 --- a/bigchaindb/common/transaction.py +++ b/bigchaindb/common/transaction.py @@ -221,9 +221,12 @@ class Condition(object): """ if not isinstance(owners_after, list) and owners_after is not None: raise TypeError('`owners_after` must be a list instance or None') + if not isinstance(amount, int): + raise TypeError('`amount` must be an int') + if amount < 1: + raise AmountError('`amount` must be greater than 0') self.fulfillment = fulfillment - # TODO: Not sure if we should validate for value here self.amount = amount self.owners_after = owners_after @@ -378,147 +381,6 @@ class Condition(object): return cls(fulfillment, cond['owners_after'], cond['amount']) -class Asset(object): - """An Asset is a fungible unit to spend and lock with Transactions. - - Attributes: - data (dict): A dictionary of data that can be added to an Asset. - """ - - def __init__(self, data=None): - """An Asset is not required to contain any extra data from outside.""" - self.data = data - self.validate_asset() - - def __eq__(self, other): - try: - other_dict = other.to_dict() - except AttributeError: - return False - return self.to_dict() == other_dict - - def to_dict(self): - """Transforms the object to a Python dictionary. - - Returns: - (dict): The Asset object as an alternative serialization - format. - """ - return { - 'data': self.data, - } - - @classmethod - def from_dict(cls, asset): - """Transforms a Python dictionary to an Asset object. - - Args: - asset (dict): The dictionary to be serialized. - - Returns: - :class:`~bigchaindb.common.transaction.Asset` - """ - return cls(asset.get('data')) - - @staticmethod - def get_asset_id(transactions): - """Get the asset id from a list of :class:`~.Transactions`. - - This is useful when we want to check if the multiple inputs of a - transaction are related to the same asset id. - - Args: - transactions (:obj:`list` of :class:`~bigchaindb.common. - transaction.Transaction`): A list of Transactions. - Usually input Transactions that should have a matching - asset ID. - - Returns: - str: ID of the asset. - - Raises: - :exc:`AssetIdMismatch`: If the inputs are related to different - assets. - """ - - if not isinstance(transactions, list): - transactions = [transactions] - - # create a set of the transactions' asset ids - asset_ids = {tx.id if tx.operation == Transaction.CREATE else tx.asset.id - for tx in transactions} - - # check that all the transasctions have the same asset id - if len(asset_ids) > 1: - raise AssetIdMismatch(('All inputs of all transactions passed' - ' need to have the same asset id')) - return asset_ids.pop() - - def validate_asset(self, amount=None): - """Validates the asset""" - if self.data is not None and not isinstance(self.data, dict): - raise TypeError('`data` must be a dict instance or None') - - # If the amount is supplied we can perform extra validations to - # the asset - if amount is not None: - if not isinstance(amount, int): - raise TypeError('`amount` must be an int') - - if amount < 1: - raise AmountError('`amount` must be greater than 0') - - -class AssetLink(object): - """An object for unidirectional linking to a Asset. - """ - - def __init__(self, asset_id=None): - """Used to point to a specific Asset. - - Args: - asset_id (str): The ID of an asset to link to. - """ - self.id = asset_id - - def __bool__(self): - return self.id is not None - - def __eq__(self, other): - return isinstance(other, AssetLink) and \ - self.to_dict() == other.to_dict() - - @classmethod - def from_dict(cls, link): - """Transforms a Python dictionary to a AssetLink object. - - Args: - link (dict): The link to be transformed. - - Returns: - :class:`~bigchaindb.common.transaction.AssetLink` - """ - try: - return cls(link['id']) - except TypeError: - return cls() - - def to_dict(self): - """Transforms the object to a Python dictionary. - - Returns: - (dict|None): The link as an alternative serialization format. - Returns None if the link is empty (i.e. is not linking to - an asset). - """ - if self.id is None: - return None - else: - return { - 'id': self.id - } - - class Transaction(object): """A Transaction is used to create and transfer assets. @@ -533,10 +395,10 @@ class Transaction(object): spend. conditions (:obj:`list` of :class:`~bigchaindb.common. transaction.Condition`, optional): Define the assets to lock. - asset (:class:`~.Asset`|:class:`~.AssetLink`): Asset or Asset link - associated with this Transaction. ``CREATE`` and ``GENESIS`` - Transactions require an Asset while ``TRANSFER`` Transactions - require an AssetLink. + asset (dict): Asset payload for this Transaction. ``CREATE`` and + ``GENESIS`` Transactions require a dict with a ``data`` + property while ``TRANSFER`` Transactions require a dict with a + ``id`` property. metadata (dict): Metadata to be stored along with the Transaction. version (int): Defines the version number of a Transaction. @@ -557,35 +419,33 @@ class Transaction(object): Args: operation (str): Defines the operation of the Transaction. - asset (:class:`~.Asset`|:class:`~.AssetLink`): An Asset to be - created or an AssetLink linking an asset to be transferred. + asset (dict): Asset payload for this Transaction. fulfillments (:obj:`list` of :class:`~bigchaindb.common. transaction.Fulfillment`, optional): Define the assets to spend. conditions (:obj:`list` of :class:`~bigchaindb.common. transaction.Condition`, optional): Define the assets to lock. - metadata (dict): - Metadata to be stored along with the Transaction. + metadata (dict): Metadata to be stored along with the + Transaction. version (int): Defines the version number of a Transaction. - """ if operation not in Transaction.ALLOWED_OPERATIONS: allowed_ops = ', '.join(self.__class__.ALLOWED_OPERATIONS) raise ValueError('`operation` must be one of {}' .format(allowed_ops)) - # Assets for 'CREATE' and 'GENESIS' operations must be None or of Asset - # type and Assets for 'TRANSFER' operations must be of AssetLink type. + # Asset payloads for 'CREATE' and 'GENESIS' operations must be None or + # dicts holding a `data` property. Asset payloads for 'TRANSFER' + # operations must be dicts holding an `id` property. if (operation in [Transaction.CREATE, Transaction.GENESIS] and - asset is not None and - not isinstance(asset, Asset)): - raise TypeError(("`asset` must be an Asset instance for " - "'{}' Transactions".format(operation))) + asset is not None and not (isinstance(asset, dict) and 'data' in asset)): + raise TypeError(('`asset` must be None or a dict holding a `data` ' + " property instance for '{}' Transactions".format(operation))) elif (operation == Transaction.TRANSFER and - not (asset and isinstance(asset, AssetLink))): - raise TypeError(("`asset` must be an valid AssetLink instance for " - "'TRANSFER' Transactions".format(operation))) + not (isinstance(asset, dict) and 'id' in asset)): + raise TypeError(('`asset` must be a dict holding an `id` property ' + "for 'TRANSFER' Transactions".format(operation))) if conditions and not isinstance(conditions, list): raise TypeError('`conditions` must be a list instance or None') @@ -598,20 +458,11 @@ class Transaction(object): self.version = version if version is not None else self.VERSION self.operation = operation - self.asset = asset or Asset() + self.asset = asset self.conditions = conditions or [] self.fulfillments = fulfillments or [] self.metadata = metadata - # validate asset - # we know that each transaction relates to a single asset - # we can sum the amount of all the conditions - # for transactions other then CREATE we only have an id so there is - # nothing we can validate - if self.operation == self.CREATE: - amount = sum([condition.amount for condition in self.conditions]) - self.asset.validate_asset(amount=amount) - @classmethod def create(cls, owners_before, owners_after, metadata=None, asset=None): """A simple way to generate a `CREATE` transaction. @@ -631,10 +482,10 @@ class Transaction(object): represent the creators of this asset. owners_after (:obj:`list` of :obj:`str`): A list of keys that represent the receivers of this Transaction. - metadata (dict): Python dictionary to be stored along with the + metadata (dict): The metadata to be stored along with the Transaction. - asset (:class:`~bigchaindb.common.transaction.Asset`): An Asset - to be created in this Transaction. + asset (dict): The metadata associated with the asset that will + be created in this Transaction. Returns: :class:`~bigchaindb.common.transaction.Transaction` @@ -647,6 +498,8 @@ class Transaction(object): raise ValueError('`owners_before` list cannot be empty') if len(owners_after) == 0: raise ValueError('`owners_after` list cannot be empty') + if not (asset is None or isinstance(asset, dict)): + raise TypeError('`asset` must be a dict or None') fulfillments = [] conditions = [] @@ -663,10 +516,10 @@ class Transaction(object): # generate fulfillments fulfillments.append(Fulfillment.generate(owners_before)) - return cls(cls.CREATE, asset, fulfillments, conditions, metadata) + return cls(cls.CREATE, {'data': asset}, fulfillments, conditions, metadata) @classmethod - def transfer(cls, inputs, owners_after, asset_link, metadata=None): + def transfer(cls, inputs, owners_after, asset_id, metadata=None): """A simple way to generate a `TRANSFER` transaction. Note: @@ -696,9 +549,8 @@ class Transaction(object): generate. owners_after (:obj:`list` of :obj:`str`): A list of keys that represent the receivers of this Transaction. - asset_link (:class:`~bigchaindb.common.transaction.AssetLink`): - An AssetLink linking an asset to be transferred in this - Transaction. + asset_id (str): The asset ID of the asset to be transferred in + this Transaction. metadata (dict): Python dictionary to be stored along with the Transaction. @@ -713,6 +565,8 @@ class Transaction(object): raise TypeError('`owners_after` must be a list instance') if len(owners_after) == 0: raise ValueError('`owners_after` list cannot be empty') + if not isinstance(asset_id, str): + raise TypeError('`asset_id` must be a string') conditions = [] for owner_after in owners_after: @@ -724,7 +578,7 @@ class Transaction(object): conditions.append(Condition.generate(pub_keys, amount)) inputs = deepcopy(inputs) - return cls(cls.TRANSFER, asset_link, inputs, conditions, metadata) + return cls(cls.TRANSFER, {'id': asset_id}, inputs, conditions, metadata) def __eq__(self, other): try: @@ -1071,7 +925,7 @@ class Transaction(object): in self.conditions], 'operation': str(self.operation), 'metadata': self.metadata, - 'asset': self.asset.to_dict(), + 'asset': self.asset, 'version': self.version, } @@ -1125,6 +979,40 @@ class Transaction(object): tx = Transaction._remove_signatures(self.to_dict()) return Transaction._to_str(tx) + @staticmethod + def get_asset_id(transactions): + """Get the asset id from a list of :class:`~.Transactions`. + + This is useful when we want to check if the multiple inputs of a + transaction are related to the same asset id. + + Args: + transactions (:obj:`list` of :class:`~bigchaindb.common. + transaction.Transaction`): A list of Transactions. + Usually input Transactions that should have a matching + asset ID. + + Returns: + str: ID of the asset. + + Raises: + :exc:`AssetIdMismatch`: If the inputs are related to different + assets. + """ + + if not isinstance(transactions, list): + transactions = [transactions] + + # create a set of the transactions' asset ids + asset_ids = {tx.id if tx.operation == Transaction.CREATE else tx.asset['id'] + for tx in transactions} + + # check that all the transasctions have the same asset id + if len(asset_ids) > 1: + raise AssetIdMismatch(('All inputs of all transactions passed' + ' need to have the same asset id')) + return asset_ids.pop() + @staticmethod def validate_structure(tx_body): """Validate the transaction ID of a transaction @@ -1163,10 +1051,6 @@ class Transaction(object): in tx['fulfillments']] conditions = [Condition.from_dict(condition) for condition in tx['conditions']] - if tx['operation'] in [cls.CREATE, cls.GENESIS]: - asset = Asset.from_dict(tx['asset']) - else: - asset = AssetLink.from_dict(tx['asset']) - return cls(tx['operation'], asset, fulfillments, conditions, + return cls(tx['operation'], tx['asset'], fulfillments, conditions, tx['metadata'], tx['version']) diff --git a/bigchaindb/core.py b/bigchaindb/core.py index 8fb0df5c..b1e87e00 100644 --- a/bigchaindb/core.py +++ b/bigchaindb/core.py @@ -6,7 +6,7 @@ from time import time from itertools import compress from bigchaindb.common import crypto, exceptions from bigchaindb.common.util import gen_timestamp, serialize -from bigchaindb.common.transaction import TransactionLink, Asset +from bigchaindb.common.transaction import TransactionLink import bigchaindb @@ -348,13 +348,12 @@ class Bigchain(object): asset_id (str): The asset id. Returns: - :class:`~bigchaindb.common.transaction.Asset` if the asset - exists else None. + dict if the asset exists else None. """ cursor = backend.query.get_asset_by_id(self.connection, asset_id) cursor = list(cursor) if cursor: - return Asset.from_dict(cursor[0]['asset']) + return cursor[0]['asset'] def get_spent(self, txid, cid): """Check if a `txid` was already used as an input. diff --git a/bigchaindb/models.py b/bigchaindb/models.py index 8917c1e2..3f04682c 100644 --- a/bigchaindb/models.py +++ b/bigchaindb/models.py @@ -4,7 +4,7 @@ from bigchaindb.common.exceptions import (InvalidHash, InvalidSignature, TransactionDoesNotExist, TransactionNotInValidBlock, AssetIdMismatch, AmountError) -from bigchaindb.common.transaction import Transaction, Asset +from bigchaindb.common.transaction import Transaction from bigchaindb.common.util import gen_timestamp, serialize from bigchaindb.common.schema import validate_transaction_schema @@ -39,21 +39,30 @@ class Transaction(Transaction): input_conditions = [] inputs_defined = all([ffill.tx_input for ffill in self.fulfillments]) + # validate amounts + if any(condition.amount < 1 for condition in self.conditions): + raise AmountError('`amount` needs to be greater than zero') + if self.operation in (Transaction.CREATE, Transaction.GENESIS): + # validate asset + if self.asset['data'] is not None and not isinstance(self.asset['data'], dict): + raise TypeError(('`asset.data` must be a dict instance or ' + 'None for `CREATE` transactions')) # validate inputs if inputs_defined: raise ValueError('A CREATE operation has no inputs') - # validate asset - amount = sum([condition.amount for condition in self.conditions]) - self.asset.validate_asset(amount=amount) elif self.operation == Transaction.TRANSFER: + # validate asset + if not isinstance(self.asset['id'], str): + raise ValueError(('`asset.id` must be a string for ' + '`TRANSFER` transations')) + # check inputs if not inputs_defined: raise ValueError('Only `CREATE` transactions can have null ' 'inputs') - # check inputs + # store the inputs so that we can check if the asset ids match input_txs = [] - input_amount = 0 for ffill in self.fulfillments: input_txid = ffill.tx_input.txid input_cid = ffill.tx_input.cid @@ -74,29 +83,20 @@ class Transaction(Transaction): raise DoubleSpend('input `{}` was already spent' .format(input_txid)) - input_conditions.append(input_tx.conditions[input_cid]) + input_condition = input_tx.conditions[input_cid] + input_conditions.append(input_condition) + input_txs.append(input_tx) - if input_tx.conditions[input_cid].amount < 1: - raise AmountError('`amount` needs to be greater than zero') - input_amount += input_tx.conditions[input_cid].amount # validate asset id - asset_id = Asset.get_asset_id(input_txs) - if asset_id != self.asset.id: + asset_id = Transaction.get_asset_id(input_txs) + if asset_id != self.asset['id']: raise AssetIdMismatch(('The asset id of the input does not' ' match the asset id of the' ' transaction')) - # get the asset creation - asset = bigchain.get_asset_by_id(asset_id) - # validate the asset - asset.validate_asset(amount=input_amount) - # validate the amounts - output_amount = 0 - for condition in self.conditions: - if condition.amount < 1: - raise AmountError('`amount` needs to be greater than zero') - output_amount += condition.amount + input_amount = sum([input_condition.amount for input_condition in input_conditions]) + output_amount = sum([output_condition.amount for output_condition in self.conditions]) if output_amount != input_amount: raise AmountError(('The amount used in the inputs `{}`' @@ -111,8 +111,8 @@ class Transaction(Transaction): if not self.fulfillments_valid(input_conditions): raise InvalidSignature() - else: - return self + + return self @classmethod def from_dict(cls, tx_body): diff --git a/docs/server/generate_http_server_api_documentation.py b/docs/server/generate_http_server_api_documentation.py index 43fd5f4b..7c7c4b97 100644 --- a/docs/server/generate_http_server_api_documentation.py +++ b/docs/server/generate_http_server_api_documentation.py @@ -4,7 +4,7 @@ import json import os import os.path -from bigchaindb.common.transaction import Asset, Transaction +from bigchaindb.common.transaction import Transaction TPLS = {} @@ -62,8 +62,7 @@ def main(): """ Main function """ privkey = 'CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z' pubkey = '4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD' - asset = Asset(None) - tx = Transaction.create([pubkey], [([pubkey], 1)], asset=asset) + tx = Transaction.create([pubkey], [([pubkey], 1)]) tx = tx.sign([privkey]) tx_json = json.dumps(tx.to_dict(), indent=2, sort_keys=True) diff --git a/tests/assets/test_digital_assets.py b/tests/assets/test_digital_assets.py index 66db993e..0ef1572d 100644 --- a/tests/assets/test_digital_assets.py +++ b/tests/assets/test_digital_assets.py @@ -1,33 +1,31 @@ import pytest import random -from unittest.mock import patch @pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_asset_transfer(b, user_pk, user_sk): - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction tx_input = b.get_owned_ids(user_pk).pop() tx_create = b.get_transaction(tx_input.txid) tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], - AssetLink(tx_create.id)) + tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) assert tx_transfer_signed.validate(b) == tx_transfer_signed - assert tx_transfer_signed.asset.id == tx_create.id + assert tx_transfer_signed.asset['id'] == tx_create.id def test_validate_bad_asset_creation(b, user_pk): - from bigchaindb.models import Transaction, Asset + from bigchaindb.models import Transaction # `data` needs to be a dictionary tx = Transaction.create([b.me], [([user_pk], 1)]) - tx.asset.data = 'a' - with patch.object(Asset, 'validate_asset', return_value=None): - tx_signed = tx.sign([b.me_private]) + tx.asset['data'] = 'a' + tx_signed = tx.sign([b.me_private]) + with pytest.raises(TypeError): b.validate_transaction(tx_signed) @@ -36,24 +34,23 @@ def test_validate_bad_asset_creation(b, user_pk): @pytest.mark.usefixtures('inputs') def test_validate_transfer_asset_id_mismatch(b, user_pk, user_sk): from bigchaindb.common.exceptions import AssetIdMismatch - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction tx_create = b.get_owned_ids(user_pk).pop() tx_create = b.get_transaction(tx_create.txid) tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], - AssetLink(tx_create.id)) - tx_transfer.asset.id = 'aaa' + tx_create.id) + tx_transfer.asset['id'] = 'aaa' tx_transfer_signed = tx_transfer.sign([user_sk]) with pytest.raises(AssetIdMismatch): tx_transfer_signed.validate(b) def test_get_asset_id_create_transaction(b, user_pk): - from bigchaindb.models import Transaction, Asset + from bigchaindb.models import Transaction tx_create = Transaction.create([b.me], [([user_pk], 1)]) - asset_id = Asset.get_asset_id(tx_create) + asset_id = Transaction.get_asset_id(tx_create) assert asset_id == tx_create.id @@ -61,14 +58,13 @@ def test_get_asset_id_create_transaction(b, user_pk): @pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_asset_id_transfer_transaction(b, user_pk, user_sk): - from bigchaindb.common.transaction import AssetLink - from bigchaindb.models import Transaction, Asset + from bigchaindb.models import Transaction tx_create = b.get_owned_ids(user_pk).pop() tx_create = b.get_transaction(tx_create.txid) # create a transfer transaction tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], - AssetLink(tx_create.id)) + tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) # create a block block = b.create_block([tx_transfer_signed]) @@ -76,13 +72,13 @@ def test_get_asset_id_transfer_transaction(b, user_pk, user_sk): # vote the block valid vote = b.vote(block.id, b.get_last_voted_block().id, True) b.write_vote(vote) - asset_id = Asset.get_asset_id(tx_transfer) + asset_id = Transaction.get_asset_id(tx_transfer) - assert asset_id == tx_transfer.asset.id + assert asset_id == tx_transfer.asset['id'] def test_asset_id_mismatch(b, user_pk): - from bigchaindb.models import Transaction, Asset + from bigchaindb.models import Transaction from bigchaindb.common.exceptions import AssetIdMismatch tx1 = Transaction.create([b.me], [([user_pk], 1)], @@ -91,13 +87,12 @@ def test_asset_id_mismatch(b, user_pk): metadata={'msg': random.random()}) with pytest.raises(AssetIdMismatch): - Asset.get_asset_id([tx1, tx2]) + Transaction.get_asset_id([tx1, tx2]) @pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_transactions_by_asset_id(b, user_pk, user_sk): - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction tx_create = b.get_owned_ids(user_pk).pop() @@ -111,7 +106,7 @@ def test_get_transactions_by_asset_id(b, user_pk, user_sk): # create a transfer transaction tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], - AssetLink(tx_create.id)) + tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) # create the block block = b.create_block([tx_transfer_signed]) @@ -127,13 +122,12 @@ def test_get_transactions_by_asset_id(b, user_pk, user_sk): assert tx_transfer.id in [t.id for t in txs] # FIXME: can I rely on the ordering here? assert asset_id == txs[0].id - assert asset_id == txs[1].asset.id + assert asset_id == txs[1].asset['id'] @pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_transactions_by_asset_id_with_invalid_block(b, user_pk, user_sk): - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction tx_create = b.get_owned_ids(user_pk).pop() @@ -147,7 +141,7 @@ def test_get_transactions_by_asset_id_with_invalid_block(b, user_pk, user_sk): # create a transfer transaction tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], - AssetLink(tx_create.id)) + tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) # create the block block = b.create_block([tx_transfer_signed]) @@ -164,15 +158,14 @@ def test_get_transactions_by_asset_id_with_invalid_block(b, user_pk, user_sk): @pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_asset_by_id(b, user_pk, user_sk): - from bigchaindb.common.transaction import AssetLink - from bigchaindb.models import Asset, Transaction + from bigchaindb.models import Transaction tx_create = b.get_owned_ids(user_pk).pop() tx_create = b.get_transaction(tx_create.txid) # create a transfer transaction tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], - AssetLink(tx_create.id)) + tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) # create the block block = b.create_block([tx_transfer_signed]) @@ -181,7 +174,7 @@ def test_get_asset_by_id(b, user_pk, user_sk): vote = b.vote(block.id, b.get_last_voted_block().id, True) b.write_vote(vote) - asset_id = Asset.get_asset_id([tx_create, tx_transfer]) + asset_id = Transaction.get_asset_id([tx_create, tx_transfer]) txs = b.get_transactions_by_asset_id(asset_id) assert len(txs) == 2 @@ -190,32 +183,21 @@ def test_get_asset_by_id(b, user_pk, user_sk): def test_create_invalid_divisible_asset(b, user_pk, user_sk): - from bigchaindb.models import Transaction, Asset + from bigchaindb.models import Transaction from bigchaindb.common.exceptions import AmountError # Asset amount must be more than 0 - asset = Asset() - tx = Transaction.create([user_pk], [([user_pk], 1)], asset=asset) + tx = Transaction.create([user_pk], [([user_pk], 1)]) tx.conditions[0].amount = 0 - with pytest.raises(AmountError): - tx.sign([user_sk]) + tx.sign([user_sk]) - # even if a transaction is badly constructed the server should raise the - # exception - asset = Asset() - tx = Transaction.create([user_pk], [([user_pk], 1)], asset=asset) - tx.conditions[0].amount = 0 - with patch.object(Asset, 'validate_asset', return_value=None): - tx_signed = tx.sign([user_sk]) with pytest.raises(AmountError): - tx_signed.validate(b) - assert b.is_valid_transaction(tx_signed) is False + b.validate_transaction(tx) def test_create_valid_divisible_asset(b, user_pk, user_sk): - from bigchaindb.models import Transaction, Asset + from bigchaindb.models import Transaction - asset = Asset() - tx = Transaction.create([user_pk], [([user_pk], 2)], asset=asset) + tx = Transaction.create([user_pk], [([user_pk], 2)]) tx_signed = tx.sign([user_sk]) assert b.is_valid_transaction(tx_signed) diff --git a/tests/assets/test_divisible_assets.py b/tests/assets/test_divisible_assets.py index 79235362..1a2993c8 100644 --- a/tests/assets/test_divisible_assets.py +++ b/tests/assets/test_divisible_assets.py @@ -1,7 +1,5 @@ import pytest -from unittest.mock import patch - # CREATE divisible asset # Single input @@ -10,10 +8,8 @@ from unittest.mock import patch # Single owners_after def test_single_in_single_own_single_out_single_own_create(b, user_pk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset - asset = Asset() - tx = Transaction.create([b.me], [([user_pk], 100)], asset=asset) + tx = Transaction.create([b.me], [([user_pk], 100)]) tx_signed = tx.sign([b.me_private]) assert tx_signed.validate(b) == tx_signed @@ -29,11 +25,8 @@ def test_single_in_single_own_single_out_single_own_create(b, user_pk): # Single owners_after per output def test_single_in_single_own_multiple_out_single_own_create(b, user_pk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset - asset = Asset() - tx = Transaction.create([b.me], [([user_pk], 50), ([user_pk], 50)], - asset=asset) + tx = Transaction.create([b.me], [([user_pk], 50), ([user_pk], 50)]) tx_signed = tx.sign([b.me_private]) assert tx_signed.validate(b) == tx_signed @@ -50,10 +43,8 @@ def test_single_in_single_own_multiple_out_single_own_create(b, user_pk): # Multiple owners_after def test_single_in_single_own_single_out_multiple_own_create(b, user_pk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset - asset = Asset() - tx = Transaction.create([b.me], [([user_pk, user_pk], 100)], asset=asset) + tx = Transaction.create([b.me], [([user_pk, user_pk], 100)]) tx_signed = tx.sign([b.me_private]) assert tx_signed.validate(b) == tx_signed @@ -75,12 +66,8 @@ def test_single_in_single_own_single_out_multiple_own_create(b, user_pk): # owners_after def test_single_in_single_own_multiple_out_mix_own_create(b, user_pk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset - asset = Asset() - tx = Transaction.create([b.me], - [([user_pk], 50), ([user_pk, user_pk], 50)], - asset=asset) + tx = Transaction.create([b.me], [([user_pk], 50), ([user_pk, user_pk], 50)]) tx_signed = tx.sign([b.me_private]) assert tx_signed.validate(b) == tx_signed @@ -102,10 +89,8 @@ def test_single_in_single_own_multiple_out_mix_own_create(b, user_pk): def test_single_in_multiple_own_single_out_single_own_create(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset - asset = Asset() - tx = Transaction.create([b.me, user_pk], [([user_pk], 100)], asset=asset) + tx = Transaction.create([b.me, user_pk], [([user_pk], 100)]) tx_signed = tx.sign([b.me_private, user_sk]) assert tx_signed.validate(b) == tx_signed assert len(tx_signed.conditions) == 1 @@ -131,11 +116,9 @@ def test_single_in_multiple_own_single_out_single_own_create(b, user_pk, def test_single_in_single_own_single_out_single_own_transfer(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset - asset = Asset() - tx_create = Transaction.create([b.me], [([user_pk], 100)], asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 100)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -147,7 +130,7 @@ def test_single_in_single_own_single_out_single_own_transfer(b, user_pk, # TRANSFER tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) assert tx_transfer_signed.validate(b) @@ -166,11 +149,9 @@ def test_single_in_single_own_single_out_single_own_transfer(b, user_pk, def test_single_in_single_own_multiple_out_single_own_transfer(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset - asset = Asset() - tx_create = Transaction.create([b.me], [([user_pk], 100)], asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 100)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -183,7 +164,7 @@ def test_single_in_single_own_multiple_out_single_own_transfer(b, user_pk, # TRANSFER tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 50), ([b.me], 50)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) assert tx_transfer_signed.validate(b) == tx_transfer_signed @@ -203,11 +184,9 @@ def test_single_in_single_own_multiple_out_single_own_transfer(b, user_pk, def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset - asset = Asset() - tx_create = Transaction.create([b.me], [([user_pk], 100)], asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 100)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -220,7 +199,7 @@ def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk, # TRANSFER tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me, b.me], 100)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) assert tx_transfer_signed.validate(b) == tx_transfer_signed @@ -245,11 +224,9 @@ def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk, def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset - asset = Asset() - tx_create = Transaction.create([b.me], [([user_pk], 100)], asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 100)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -262,7 +239,7 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_pk, # TRANSFER tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 50), ([b.me, b.me], 50)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) assert tx_transfer_signed.validate(b) == tx_transfer_signed @@ -287,12 +264,9 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_pk, def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset - asset = Asset() - tx_create = Transaction.create([b.me], [([b.me, user_pk], 100)], - asset=asset) + tx_create = Transaction.create([b.me], [([b.me, user_pk], 100)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -304,7 +278,7 @@ def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk, # TRANSFER tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk]) assert tx_transfer_signed.validate(b) == tx_transfer_signed @@ -327,12 +301,9 @@ def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk, def test_multiple_in_single_own_single_out_single_own_transfer(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset - asset = Asset() - tx_create = Transaction.create([b.me], [([user_pk], 50), ([user_pk], 50)], - asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 50), ([user_pk], 50)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -344,7 +315,7 @@ def test_multiple_in_single_own_single_out_single_own_transfer(b, user_pk, # TRANSFER tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) assert tx_transfer_signed.validate(b) @@ -363,14 +334,9 @@ def test_multiple_in_single_own_single_out_single_own_transfer(b, user_pk, def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset - asset = Asset() - tx_create = Transaction.create([b.me], - [([user_pk, b.me], 50), - ([user_pk, b.me], 50)], - asset=asset) + tx_create = Transaction.create([b.me], [([user_pk, b.me], 50), ([user_pk, b.me], 50)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -382,7 +348,7 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_pk, # TRANSFER tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk]) assert tx_transfer_signed.validate(b) @@ -409,14 +375,9 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_pk, def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset - asset = Asset() - tx_create = Transaction.create([b.me], - [([user_pk], 50), - ([user_pk, b.me], 50)], - asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 50), ([user_pk, b.me], 50)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -428,7 +389,7 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(b, user_pk, # TRANSFER tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk]) assert tx_transfer_signed.validate(b) == tx_transfer_signed @@ -455,14 +416,9 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(b, user_pk, def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset - asset = Asset() - tx_create = Transaction.create([b.me], - [([user_pk], 50), - ([user_pk, b.me], 50)], - asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 50), ([user_pk, b.me], 50)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -475,7 +431,7 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk, # TRANSFER tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 50), ([b.me, user_pk], 50)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk]) assert tx_transfer_signed.validate(b) == tx_transfer_signed @@ -506,16 +462,11 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk, @pytest.mark.usefixtures('inputs') def test_multiple_in_different_transactions(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset # `b` creates a divisible asset and assigns 50 shares to `b` and # 50 shares to `user_pk` - asset = Asset() - tx_create = Transaction.create([b.me], - [([user_pk], 50), - ([b.me], 50)], - asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 50), ([b.me], 50)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -531,7 +482,7 @@ def test_multiple_in_different_transactions(b, user_pk, user_sk): # split across two different transactions tx_transfer1 = Transaction.transfer(tx_create.to_inputs([1]), [([user_pk], 50)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer1_signed = tx_transfer1.sign([b.me_private]) # create block block = b.create_block([tx_transfer1_signed]) @@ -547,7 +498,7 @@ def test_multiple_in_different_transactions(b, user_pk, user_sk): tx_transfer2 = Transaction.transfer(tx_create.to_inputs([0]) + tx_transfer1.to_inputs([0]), [([b.me], 100)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer2_signed = tx_transfer2.sign([user_sk]) assert tx_transfer2_signed.validate(b) == tx_transfer2_signed @@ -568,12 +519,10 @@ def test_multiple_in_different_transactions(b, user_pk, user_sk): @pytest.mark.usefixtures('inputs') def test_amount_error_transfer(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink from bigchaindb.common.exceptions import AmountError # CREATE divisible asset - asset = Asset() - tx_create = Transaction.create([b.me], [([user_pk], 100)], asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 100)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -586,7 +535,7 @@ def test_amount_error_transfer(b, user_pk, user_sk): # TRANSFER # output amount less than input amount tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 50)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) with pytest.raises(AmountError): tx_transfer_signed.validate(b) @@ -594,7 +543,7 @@ def test_amount_error_transfer(b, user_pk, user_sk): # TRANSFER # output amount greater than input amount tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 101)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) with pytest.raises(AmountError): tx_transfer_signed.validate(b) @@ -612,12 +561,9 @@ def test_threshold_same_public_key(b, user_pk, user_sk): # that does not mean that the code shouldn't work. from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset - asset = Asset() - tx_create = Transaction.create([b.me], [([user_pk, user_pk], 100)], - asset=asset) + tx_create = Transaction.create([b.me], [([user_pk, user_pk], 100)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -629,7 +575,7 @@ def test_threshold_same_public_key(b, user_pk, user_sk): # TRANSFER tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk, user_sk]) assert tx_transfer_signed.validate(b) == tx_transfer_signed @@ -639,15 +585,9 @@ def test_threshold_same_public_key(b, user_pk, user_sk): @pytest.mark.usefixtures('inputs') def test_sum_amount(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset with 3 outputs with amount 1 - asset = Asset() - tx_create = Transaction.create([b.me], - [([user_pk], 1), - ([user_pk], 1), - ([user_pk], 1)], - asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 1), ([user_pk], 1), ([user_pk], 1)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -660,7 +600,7 @@ def test_sum_amount(b, user_pk, user_sk): # 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)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) assert tx_transfer_signed.validate(b) == tx_transfer_signed @@ -672,12 +612,9 @@ def test_sum_amount(b, user_pk, user_sk): @pytest.mark.usefixtures('inputs') def test_divide(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink # CREATE divisible asset with 1 output with amount 3 - asset = Asset() - tx_create = Transaction.create([b.me], [([user_pk], 3)], - asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 3)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -691,7 +628,7 @@ def test_divide(b, user_pk, user_sk): # of each output is 1 tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 1), ([b.me], 1), ([b.me], 1)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) assert tx_transfer_signed.validate(b) == tx_transfer_signed @@ -705,13 +642,10 @@ def test_divide(b, user_pk, user_sk): @pytest.mark.usefixtures('inputs') def test_non_positive_amounts_on_transfer(b, user_pk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink from bigchaindb.common.exceptions import AmountError # CREATE divisible asset with 1 output with amount 3 - asset = Asset() - tx_create = Transaction.create([b.me], [([user_pk], 3)], - asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 3)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -724,7 +658,7 @@ def test_non_positive_amounts_on_transfer(b, user_pk): with pytest.raises(AmountError): Transaction.transfer(tx_create.to_inputs(), [([b.me], 4), ([b.me], -1)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) # Check that negative inputs are caught when validating a TRANSFER transaction @@ -732,13 +666,10 @@ def test_non_positive_amounts_on_transfer(b, user_pk): @pytest.mark.usefixtures('inputs') def test_non_positive_amounts_on_transfer_validate(b, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset, AssetLink from bigchaindb.common.exceptions import AmountError # CREATE divisible asset with 1 output with amount 3 - asset = Asset() - tx_create = Transaction.create([b.me], [([user_pk], 3)], - asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 3)]) tx_create_signed = tx_create.sign([b.me_private]) # create block block = b.create_block([tx_create_signed]) @@ -752,7 +683,7 @@ def test_non_positive_amounts_on_transfer_validate(b, user_pk, user_sk): # of each output is 1 tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 4), ([b.me], 1)], - AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer.conditions[1].amount = -1 tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -765,14 +696,11 @@ def test_non_positive_amounts_on_transfer_validate(b, user_pk, user_sk): @pytest.mark.usefixtures('inputs') def test_non_positive_amounts_on_create(b, user_pk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset from bigchaindb.common.exceptions import AmountError # CREATE divisible asset with 1 output with amount 3 - asset = Asset() with pytest.raises(AmountError): - Transaction.create([b.me], [([user_pk], -3)], - asset=asset) + Transaction.create([b.me], [([user_pk], -3)]) # Check that negative inputs are caught when validating a CREATE transaction @@ -780,16 +708,12 @@ def test_non_positive_amounts_on_create(b, user_pk): @pytest.mark.usefixtures('inputs') def test_non_positive_amounts_on_create_validate(b, user_pk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import Asset from bigchaindb.common.exceptions import AmountError # CREATE divisible asset with 1 output with amount 3 - asset = Asset() - tx_create = Transaction.create([b.me], [([user_pk], 3)], - asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 3)]) tx_create.conditions[0].amount = -3 - with patch.object(Asset, 'validate_asset', return_value=None): - tx_create_signed = tx_create.sign([b.me_private]) + tx_create_signed = tx_create.sign([b.me_private]) with pytest.raises(AmountError): tx_create_signed.validate(b) diff --git a/tests/common/conftest.py b/tests/common/conftest.py index ca3194f9..77cf6264 100644 --- a/tests/common/conftest.py +++ b/tests/common/conftest.py @@ -14,6 +14,16 @@ USER3_PUBLIC_KEY = 'Gbrg7JtxdjedQRmr81ZZbh1BozS7fBW88ZyxNDy7WLNC' CC_FULFILLMENT_URI = 'cf:0:' CC_CONDITION_URI = 'cc:0:3:47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU:0' +ASSET_DEFINITION = { + 'data': { + 'definition': 'Asset definition' + } +} + +ASSET_LINK = { + 'id': 'a' * 64 +} + DATA = { 'msg': 'Hello BigchainDB!' } @@ -118,6 +128,16 @@ def user2_cond(user2_Ed25519, user2_pub): return Condition(user2_Ed25519, [user2_pub]) +@pytest.fixture +def asset_definition(): + return ASSET_DEFINITION + + +@pytest.fixture +def asset_link(): + return ASSET_LINK + + @pytest.fixture def data(): return DATA @@ -125,8 +145,8 @@ def data(): @pytest.fixture def utx(user_ffill, user_cond): - from bigchaindb.common.transaction import Transaction, Asset - return Transaction(Transaction.CREATE, Asset(), [user_ffill], [user_cond]) + from bigchaindb.common.transaction import Transaction + return Transaction(Transaction.CREATE, {'data': None}, [user_ffill], [user_cond]) @pytest.fixture @@ -137,12 +157,12 @@ def tx(utx, user_priv): @pytest.fixture def transfer_utx(user_cond, user2_cond, utx): from bigchaindb.common.transaction import (Fulfillment, TransactionLink, - Transaction, AssetLink) + Transaction) user_cond = user_cond.to_dict() ffill = Fulfillment(utx.conditions[0].fulfillment, user_cond['owners_after'], TransactionLink(utx.id, 0)) - return Transaction('TRANSFER', AssetLink(utx.id), [ffill], [user2_cond]) + return Transaction('TRANSFER', {'id': utx.id}, [ffill], [user2_cond]) @pytest.fixture diff --git a/tests/common/test_asset.py b/tests/common/test_asset.py deleted file mode 100644 index 12951bf3..00000000 --- a/tests/common/test_asset.py +++ /dev/null @@ -1,59 +0,0 @@ -from pytest import raises - - -def test_asset_default_values(): - from bigchaindb.common.transaction import Asset - - asset = Asset() - assert asset.data is None - - -def test_asset_creation_with_data(data): - from bigchaindb.common.transaction import Asset - - asset = Asset(data) - assert asset.data == data - - -def test_asset_invalid_asset_initialization(): - from bigchaindb.common.transaction import Asset - - # check types - with raises(TypeError): - Asset(data='some wrong type') - - -def test_invalid_asset_comparison(data): - from bigchaindb.common.transaction import Asset - - assert Asset(data) != 'invalid comparison' - - -def test_asset_serialization(data): - from bigchaindb.common.transaction import Asset - - expected = { - 'data': data, - } - asset = Asset(data) - assert asset.to_dict() == expected - - -def test_asset_deserialization(data): - from bigchaindb.common.transaction import Asset - - asset_dict = { - 'data': data, - } - asset = Asset.from_dict(asset_dict) - expected = Asset(data) - assert asset == expected - - -def test_validate_asset(): - from bigchaindb.common.transaction import Asset - - # test amount errors - asset = Asset() - with raises(TypeError): - asset.validate_asset(amount='a') diff --git a/tests/common/test_transaction.py b/tests/common/test_transaction.py index dc8a7784..4acd8f0e 100644 --- a/tests/common/test_transaction.py +++ b/tests/common/test_transaction.py @@ -1,5 +1,4 @@ from pytest import raises -from unittest.mock import patch def test_fulfillment_serialization(ffill_uri, user_pub): @@ -146,9 +145,14 @@ def test_condition_hashlock_deserialization(): def test_invalid_condition_initialization(cond_uri, user_pub): from bigchaindb.common.transaction import Condition + from bigchaindb.common.exceptions import AmountError with raises(TypeError): Condition(cond_uri, user_pub) + with raises(TypeError): + Condition(cond_uri, [user_pub], 'amount') + with raises(AmountError): + Condition(cond_uri, [user_pub], 0) def test_generate_conditions_split_half_recursive(user_pub, user2_pub, @@ -242,49 +246,50 @@ def test_generate_conditions_invalid_parameters(user_pub, user2_pub, Condition.generate([[user_pub]], 1) -def test_invalid_transaction_initialization(): - from bigchaindb.common.transaction import Transaction, Asset +def test_invalid_transaction_initialization(asset_definition): + from bigchaindb.common.transaction import Transaction with raises(ValueError): - Transaction(operation='invalid operation', asset=Asset()) + Transaction(operation='invalid operation', asset=asset_definition) with raises(TypeError): Transaction(operation='CREATE', asset='invalid asset') + with raises(TypeError): + Transaction(operation='TRANSFER', asset={}) with raises(TypeError): Transaction( operation='CREATE', - asset=Asset(), + asset=asset_definition, conditions='invalid conditions' ) with raises(TypeError): Transaction( operation='CREATE', - asset=Asset(), + asset=asset_definition, conditions=[], fulfillments='invalid fulfillments' ) with raises(TypeError): Transaction( operation='CREATE', - asset=Asset(), + asset=asset_definition, conditions=[], fulfillments=[], metadata='invalid metadata' ) -def test_create_default_asset_on_tx_initialization(): - from bigchaindb.common.transaction import Transaction, Asset +def test_create_default_asset_on_tx_initialization(asset_definition): + from bigchaindb.common.transaction import Transaction - with patch.object(Asset, 'validate_asset', return_value=None): - tx = Transaction(Transaction.CREATE, None) - expected = Asset() + expected = {'data': None} + tx = Transaction(Transaction.CREATE, asset=expected) asset = tx.asset assert asset == expected def test_transaction_serialization(user_ffill, user_cond, data): - from bigchaindb.common.transaction import Transaction, Asset + from bigchaindb.common.transaction import Transaction tx_id = 'l0l' @@ -302,7 +307,7 @@ def test_transaction_serialization(user_ffill, user_cond, data): } } - tx = Transaction(Transaction.CREATE, Asset(data), [user_ffill], + tx = Transaction(Transaction.CREATE, {'data': data}, [user_ffill], [user_cond]) tx_dict = tx.to_dict() tx_dict['id'] = tx_id @@ -311,10 +316,10 @@ def test_transaction_serialization(user_ffill, user_cond, data): def test_transaction_deserialization(user_ffill, user_cond, data): - from bigchaindb.common.transaction import Transaction, Asset + from bigchaindb.common.transaction import Transaction from .util import validate_transaction_model - expected_asset = Asset(data) + expected_asset = {'data': data} expected = Transaction(Transaction.CREATE, expected_asset, [user_ffill], [user_cond], None, Transaction.VERSION) @@ -432,92 +437,28 @@ def test_cast_transaction_link_to_boolean(): assert bool(TransactionLink(False, False)) is True -def test_asset_link_serialization(): - from bigchaindb.common.transaction import AssetLink +def test_add_fulfillment_to_tx(user_ffill, asset_definition): + from bigchaindb.common.transaction import Transaction - asset_id = 'a asset id' - expected = { - 'id': asset_id, - } - asset_link = AssetLink(asset_id) - - assert asset_link.to_dict() == expected - - -def test_asset_link_serialization_with_empty_payload(): - from bigchaindb.common.transaction import AssetLink - - expected = None - asset_link = AssetLink() - - assert asset_link.to_dict() == expected - - -def test_asset_link_deserialization(): - from bigchaindb.common.transaction import AssetLink - - asset_id = 'a asset id' - expected = AssetLink(asset_id) - asset_link = { - 'id': asset_id - } - asset_link = AssetLink.from_dict(asset_link) - - assert asset_link == expected - - -def test_asset_link_deserialization_with_empty_payload(): - from bigchaindb.common.transaction import AssetLink - - expected = AssetLink() - asset_link = AssetLink.from_dict(None) - - assert asset_link == expected - - -def test_cast_asset_link_to_boolean(): - from bigchaindb.common.transaction import AssetLink - - assert bool(AssetLink()) is False - assert bool(AssetLink('a')) is True - assert bool(AssetLink(False)) is True - - -def test_eq_asset_link(): - from bigchaindb.common.transaction import AssetLink - - asset_id_1 = 'asset_1' - asset_id_2 = 'asset_2' - - assert AssetLink(asset_id_1) == AssetLink(asset_id_1) - assert AssetLink(asset_id_1) != AssetLink(asset_id_2) - - -def test_add_fulfillment_to_tx(user_ffill): - from bigchaindb.common.transaction import Transaction, Asset - - with patch.object(Asset, 'validate_asset', return_value=None): - tx = Transaction(Transaction.CREATE, Asset(), [], []) + tx = Transaction(Transaction.CREATE, asset_definition, [], []) tx.add_fulfillment(user_ffill) assert len(tx.fulfillments) == 1 -def test_add_fulfillment_to_tx_with_invalid_parameters(): - from bigchaindb.common.transaction import Transaction, Asset +def test_add_fulfillment_to_tx_with_invalid_parameters(asset_definition): + from bigchaindb.common.transaction import Transaction + tx = Transaction(Transaction.CREATE, asset_definition) - with patch.object(Asset, 'validate_asset', return_value=None): - tx = Transaction(Transaction.CREATE, Asset()) with raises(TypeError): tx.add_fulfillment('somewronginput') -def test_add_condition_to_tx(user_cond): - from bigchaindb.common.transaction import Transaction, Asset +def test_add_condition_to_tx(user_cond, asset_definition): + from bigchaindb.common.transaction import Transaction from .util import validate_transaction_model - with patch.object(Asset, 'validate_asset', return_value=None): - tx = Transaction(Transaction.CREATE, Asset()) + tx = Transaction(Transaction.CREATE, asset_definition) tx.add_condition(user_cond) assert len(tx.conditions) == 1 @@ -525,11 +466,10 @@ def test_add_condition_to_tx(user_cond): validate_transaction_model(tx) -def test_add_condition_to_tx_with_invalid_parameters(): - from bigchaindb.common.transaction import Transaction, Asset +def test_add_condition_to_tx_with_invalid_parameters(asset_definition): + from bigchaindb.common.transaction import Transaction + tx = Transaction(Transaction.CREATE, asset_definition, [], []) - with patch.object(Asset, 'validate_asset', return_value=None): - tx = Transaction(Transaction.CREATE, Asset(), [], []) with raises(TypeError): tx.add_condition('somewronginput') @@ -541,13 +481,14 @@ def test_sign_with_invalid_parameters(utx, user_priv): utx.sign(user_priv) -def test_validate_tx_simple_create_signature(user_ffill, user_cond, user_priv): +def test_validate_tx_simple_create_signature(user_ffill, user_cond, user_priv, + asset_definition): from copy import deepcopy from bigchaindb.common.crypto import PrivateKey - from bigchaindb.common.transaction import Transaction, Asset + from bigchaindb.common.transaction import Transaction from .util import validate_transaction_model - tx = Transaction(Transaction.CREATE, Asset(), [user_ffill], [user_cond]) + tx = Transaction(Transaction.CREATE, asset_definition, [user_ffill], [user_cond]) expected = deepcopy(user_cond) expected.fulfillment.sign(str(tx).encode(), PrivateKey(user_priv)) tx.sign([user_priv]) @@ -601,14 +542,15 @@ def test_validate_fulfillment_with_invalid_parameters(utx): input_conditions) is False -def test_validate_multiple_fulfillments(user_ffill, user_cond, user_priv): +def test_validate_multiple_fulfillments(user_ffill, user_cond, user_priv, + asset_definition): from copy import deepcopy from bigchaindb.common.crypto import PrivateKey - from bigchaindb.common.transaction import Transaction, Asset + from bigchaindb.common.transaction import Transaction from .util import validate_transaction_model - tx = Transaction(Transaction.CREATE, Asset(), + tx = Transaction(Transaction.CREATE, asset_definition, [user_ffill, deepcopy(user_ffill)], [user_cond, deepcopy(user_cond)]) @@ -639,14 +581,16 @@ def test_validate_tx_threshold_create_signature(user_user2_threshold_ffill, user_pub, user2_pub, user_priv, - user2_priv): + user2_priv, + asset_definition): from copy import deepcopy from bigchaindb.common.crypto import PrivateKey - from bigchaindb.common.transaction import Transaction, Asset + from bigchaindb.common.transaction import Transaction from .util import validate_transaction_model - tx = Transaction(Transaction.CREATE, Asset(), [user_user2_threshold_ffill], + tx = Transaction(Transaction.CREATE, asset_definition, + [user_user2_threshold_ffill], [user_user2_threshold_cond]) expected = deepcopy(user_user2_threshold_cond) expected.fulfillment.subconditions[0]['body'].sign(str(tx).encode(), @@ -665,15 +609,15 @@ def test_validate_tx_threshold_create_signature(user_user2_threshold_ffill, def test_multiple_fulfillment_validation_of_transfer_tx(user_ffill, user_cond, user_priv, user2_pub, user2_priv, user3_pub, - user3_priv): + user3_priv, + asset_definition): from copy import deepcopy from bigchaindb.common.transaction import (Transaction, TransactionLink, - Fulfillment, Condition, Asset, - AssetLink) + Fulfillment, Condition) from cryptoconditions import Ed25519Fulfillment from .util import validate_transaction_model - tx = Transaction(Transaction.CREATE, Asset(), + tx = Transaction(Transaction.CREATE, asset_definition, [user_ffill, deepcopy(user_ffill)], [user_cond, deepcopy(user_cond)]) tx.sign([user_priv]) @@ -685,7 +629,7 @@ def test_multiple_fulfillment_validation_of_transfer_tx(user_ffill, user_cond, [user3_pub]), Condition(Ed25519Fulfillment(public_key=user3_pub), [user3_pub])] - transfer_tx = Transaction('TRANSFER', AssetLink(tx.id), + transfer_tx = Transaction('TRANSFER', {'id': tx.id}, fulfillments, conditions) transfer_tx = transfer_tx.sign([user_priv]) @@ -720,7 +664,7 @@ def test_validate_fulfillments_of_transfer_tx_with_invalid_params(transfer_tx, def test_create_create_transaction_single_io(user_cond, user_pub, data): - from bigchaindb.common.transaction import Transaction, Asset + from bigchaindb.common.transaction import Transaction from .util import validate_transaction_model expected = { @@ -742,8 +686,8 @@ def test_create_create_transaction_single_io(user_cond, user_pub, data): 'version': 1, } - asset = Asset(data) - tx = Transaction.create([user_pub], [([user_pub], 1)], data, asset) + tx = Transaction.create([user_pub], [([user_pub], 1)], metadata=data, + asset=data) tx_dict = tx.to_dict() tx_dict['fulfillments'][0]['fulfillment'] = None tx_dict.pop('id') @@ -753,17 +697,18 @@ def test_create_create_transaction_single_io(user_cond, user_pub, data): validate_transaction_model(tx) -def test_validate_single_io_create_transaction(user_pub, user_priv, data): - from bigchaindb.common.transaction import Transaction, Asset +def test_validate_single_io_create_transaction(user_pub, user_priv, data, + asset_definition): + from bigchaindb.common.transaction import Transaction - tx = Transaction.create([user_pub], [([user_pub], 1)], data, Asset()) + tx = Transaction.create([user_pub], [([user_pub], 1)], metadata=data) tx = tx.sign([user_priv]) assert tx.fulfillments_valid() is True def test_create_create_transaction_multiple_io(user_cond, user2_cond, user_pub, - user2_pub): - from bigchaindb.common.transaction import Transaction, Asset, Fulfillment + user2_pub, asset_definition): + from bigchaindb.common.transaction import Transaction, Fulfillment # a fulfillment for a create transaction with multiple `owners_before` # is a fulfillment for an implicit threshold condition with @@ -778,10 +723,8 @@ def test_create_create_transaction_multiple_io(user_cond, user2_cond, user_pub, 'operation': 'CREATE', 'version': 1 } - asset = Asset() tx = Transaction.create([user_pub, user2_pub], [([user_pub], 1), ([user2_pub], 1)], - asset=asset, metadata={'message': 'hello'}).to_dict() tx.pop('id') tx.pop('asset') @@ -790,14 +733,14 @@ def test_create_create_transaction_multiple_io(user_cond, user2_cond, user_pub, def test_validate_multiple_io_create_transaction(user_pub, user_priv, - user2_pub, user2_priv): - from bigchaindb.common.transaction import Transaction, Asset + user2_pub, user2_priv, + asset_definition): + from bigchaindb.common.transaction import Transaction from .util import validate_transaction_model tx = Transaction.create([user_pub, user2_pub], [([user_pub], 1), ([user2_pub], 1)], - metadata={'message': 'hello'}, - asset=Asset()) + metadata={'message': 'hello'}) tx = tx.sign([user_priv, user2_priv]) assert tx.fulfillments_valid() is True @@ -807,7 +750,7 @@ def test_validate_multiple_io_create_transaction(user_pub, user_priv, def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub, user_user2_threshold_cond, user_user2_threshold_ffill, data): - from bigchaindb.common.transaction import Transaction, Asset + from bigchaindb.common.transaction import Transaction expected = { 'conditions': [user_user2_threshold_cond.to_dict()], @@ -827,9 +770,8 @@ def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub, 'operation': 'CREATE', 'version': 1 } - asset = Asset(data) tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)], - data, asset) + metadata=data, asset=data) tx_dict = tx.to_dict() tx_dict.pop('id') tx_dict['fulfillments'][0]['fulfillment'] = None @@ -838,12 +780,12 @@ def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub, def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub, - data): - from bigchaindb.common.transaction import Transaction, Asset + data, asset_definition): + from bigchaindb.common.transaction import Transaction from .util import validate_transaction_model tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)], - data, Asset()) + metadata=data) tx = tx.sign([user_priv]) assert tx.fulfillments_valid() is True @@ -851,7 +793,7 @@ def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub, def test_create_create_transaction_with_invalid_parameters(user_pub): - from bigchaindb.common.transaction import Transaction, AssetLink + from bigchaindb.common.transaction import Transaction with raises(TypeError): Transaction.create('not a list') @@ -866,12 +808,12 @@ def test_create_create_transaction_with_invalid_parameters(user_pub): with raises(ValueError): Transaction.create([user_pub], [([user_pub],)]) with raises(TypeError): - Transaction.create([user_pub], [([user_pub], 1)], metadata=[]) + Transaction.create([user_pub], [([user_pub], 1)], + metadata='not a dict or none') with raises(TypeError): Transaction.create([user_pub], [([user_pub], 1)], - metadata=None, - asset=AssetLink('mock_asset_link')) + asset='not a dict or none') def test_conditions_to_inputs(tx): @@ -888,7 +830,7 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, user2_cond, user_priv): from copy import deepcopy from bigchaindb.common.crypto import PrivateKey - from bigchaindb.common.transaction import Transaction, AssetLink + from bigchaindb.common.transaction import Transaction from bigchaindb.common.util import serialize from .util import validate_transaction_model @@ -915,7 +857,7 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, } inputs = tx.to_inputs([0]) transfer_tx = Transaction.transfer(inputs, [([user2_pub], 1)], - asset_link=AssetLink(tx.id)) + asset_id=tx.id) transfer_tx = transfer_tx.sign([user_priv]) transfer_tx = transfer_tx.to_dict() @@ -936,12 +878,12 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, 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, Asset, AssetLink + user3_pub, user2_cond, + asset_definition): + from bigchaindb.common.transaction import Transaction - asset = Asset() tx = Transaction.create([user_pub], [([user_pub], 1), ([user2_pub], 1)], - asset=asset, metadata={'message': 'hello'}) + metadata={'message': 'hello'}) tx = tx.sign([user_priv]) expected = { @@ -974,7 +916,7 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv, transfer_tx = Transaction.transfer(tx.to_inputs(), [([user2_pub], 1), ([user2_pub], 1)], - asset_link=AssetLink(tx.id)) + asset_id=tx.id) transfer_tx = transfer_tx.sign([user_priv, user2_priv]) assert len(transfer_tx.fulfillments) == 2 @@ -992,41 +934,39 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv, def test_create_transfer_with_invalid_parameters(tx, user_pub): - from bigchaindb.common.transaction import Transaction, Asset, AssetLink - mock_asset_link = AssetLink(tx.id) + from bigchaindb.common.transaction import Transaction with raises(TypeError): - Transaction.transfer({}, [], mock_asset_link) + Transaction.transfer({}, [], tx.id) with raises(ValueError): - Transaction.transfer([], [], mock_asset_link) + Transaction.transfer([], [], tx.id) with raises(TypeError): - Transaction.transfer(['fulfillment'], {}, mock_asset_link) + Transaction.transfer(['fulfillment'], {}, tx.id) with raises(ValueError): - Transaction.transfer(['fulfillment'], [], mock_asset_link) + Transaction.transfer(['fulfillment'], [], tx.id) with raises(ValueError): - Transaction.transfer(['fulfillment'], [user_pub], mock_asset_link) + Transaction.transfer(['fulfillment'], [user_pub], tx.id) with raises(ValueError): - Transaction.transfer(['fulfillment'], [([user_pub],)], mock_asset_link) + Transaction.transfer(['fulfillment'], [([user_pub],)], tx.id) with raises(TypeError): Transaction.transfer(['fulfillment'], [([user_pub], 1)], - mock_asset_link, metadata=[]) + tx.id, metadata='not a dict or none') with raises(TypeError): - Transaction.transfer(['fulfillment'], [([user_pub], 1)], Asset()) + Transaction.transfer(['fulfillment'], [([user_pub], 1)], + ['not a string']) def test_cant_add_empty_condition(): - from bigchaindb.common.transaction import Transaction, Asset + from bigchaindb.common.transaction import Transaction + tx = Transaction(Transaction.CREATE, None) - with patch.object(Asset, 'validate_asset', return_value=None): - tx = Transaction(Transaction.CREATE, None) with raises(TypeError): tx.add_condition(None) def test_cant_add_empty_fulfillment(): - from bigchaindb.common.transaction import Transaction, Asset + from bigchaindb.common.transaction import Transaction + tx = Transaction(Transaction.CREATE, None) - with patch.object(Asset, 'validate_asset', return_value=None): - tx = Transaction(Transaction.CREATE, None) with raises(TypeError): tx.add_fulfillment(None) diff --git a/tests/conftest.py b/tests/conftest.py index 82c6b3fe..9a6b7a73 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -234,12 +234,9 @@ def signed_create_tx(b, create_tx): @pytest.fixture def signed_transfer_tx(signed_create_tx, user_pk, user_sk): - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction inputs = signed_create_tx.to_inputs() - tx = Transaction.transfer(inputs, - [([user_pk], 1)], - AssetLink(signed_create_tx.id)) + tx = Transaction.transfer(inputs, [([user_pk], 1)], asset_id=signed_create_tx.id) return tx.sign([user_sk]) diff --git a/tests/db/test_bigchain_api.py b/tests/db/test_bigchain_api.py index c9b3ec5f..1d8cfd74 100644 --- a/tests/db/test_bigchain_api.py +++ b/tests/db/test_bigchain_api.py @@ -92,7 +92,6 @@ class TestBigchainApi(object): @pytest.mark.genesis def test_get_spent_with_double_spend(self, b, monkeypatch): from bigchaindb.common.exceptions import DoubleSpend - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction tx = Transaction.create([b.me], [([b.me], 1)]) @@ -104,14 +103,14 @@ class TestBigchainApi(object): monkeypatch.setattr('time.time', lambda: 2) transfer_tx = Transaction.transfer(tx.to_inputs(), [([b.me], 1)], - AssetLink(tx.id)) + asset_id=tx.id) transfer_tx = transfer_tx.sign([b.me_private]) block2 = b.create_block([transfer_tx]) b.write_block(block2) monkeypatch.setattr('time.time', lambda: 3333333333) transfer_tx2 = Transaction.transfer(tx.to_inputs(), [([b.me], 1)], - AssetLink(tx.id)) + asset_id=tx.id) transfer_tx2 = transfer_tx2.sign([b.me_private]) block3 = b.create_block([transfer_tx2]) b.write_block(block3) @@ -181,14 +180,13 @@ class TestBigchainApi(object): @pytest.mark.usefixtures('inputs') def test_write_transaction(self, b, user_pk, user_sk): - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() tx = Transaction.transfer(inputs, [([user_pk], 1)], - AssetLink(input_tx.id)) + asset_id=input_tx.id) tx = tx.sign([user_sk]) response = b.write_transaction(tx) @@ -201,14 +199,13 @@ class TestBigchainApi(object): @pytest.mark.usefixtures('inputs') def test_read_transaction(self, b, user_pk, user_sk): - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() tx = Transaction.transfer(inputs, [([user_pk], 1)], - AssetLink(input_tx.id)) + asset_id=input_tx.id) tx = tx.sign([user_sk]) b.write_transaction(tx) @@ -223,14 +220,13 @@ class TestBigchainApi(object): @pytest.mark.usefixtures('inputs') def test_read_transaction_invalid_block(self, b, user_pk, user_sk): - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() tx = Transaction.transfer(inputs, [([user_pk], 1)], - AssetLink(input_tx.id)) + asset_id=input_tx.id) tx = tx.sign([user_sk]) # There's no need to b.write_transaction(tx) to the backlog @@ -249,14 +245,13 @@ class TestBigchainApi(object): @pytest.mark.usefixtures('inputs') def test_read_transaction_invalid_block_and_backlog(self, b, user_pk, user_sk): - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() tx = Transaction.transfer(inputs, [([user_pk], 1)], - AssetLink(input_tx.id)) + asset_id=input_tx.id) tx = tx.sign([user_sk]) # Make sure there's a copy of tx in the backlog @@ -489,14 +484,13 @@ class TestBigchainApi(object): @pytest.mark.usefixtures('inputs') def test_assign_transaction_one_node(self, b, user_pk, user_sk): from bigchaindb.backend import query - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() tx = Transaction.transfer(inputs, [([user_pk], 1)], - AssetLink(input_tx.id)) + asset_id=input_tx.id) tx = tx.sign([user_sk]) b.write_transaction(tx) @@ -510,7 +504,6 @@ class TestBigchainApi(object): def test_assign_transaction_multiple_nodes(self, b, user_pk, user_sk): from bigchaindb.backend import query from bigchaindb.common.crypto import generate_key_pair - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction # create 5 federation nodes @@ -523,7 +516,7 @@ class TestBigchainApi(object): input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() tx = Transaction.transfer(inputs, [([user_pk], 1)], - asset_link=AssetLink(input_tx.id), + asset_id=input_tx.id, metadata={'msg': random.random()}) tx = tx.sign([user_sk]) b.write_transaction(tx) @@ -539,8 +532,7 @@ class TestBigchainApi(object): def test_non_create_input_not_found(self, b, user_pk): from cryptoconditions import Ed25519Fulfillment from bigchaindb.common.exceptions import TransactionDoesNotExist - from bigchaindb.common.transaction import (AssetLink, Fulfillment, - TransactionLink) + from bigchaindb.common.transaction import Fulfillment, TransactionLink from bigchaindb.models import Transaction from bigchaindb import Bigchain @@ -549,7 +541,7 @@ class TestBigchainApi(object): [user_pk], TransactionLink('somethingsomething', 0)) tx = Transaction.transfer([fulfillment], [([user_pk], 1)], - AssetLink('mock_asset_link')) + asset_id='mock_asset_link') with pytest.raises(TransactionDoesNotExist): tx.validate(Bigchain()) @@ -599,7 +591,6 @@ class TestTransactionValidation(object): def test_non_create_valid_input_wrong_owner(self, b, user_pk): from bigchaindb.common.crypto import generate_key_pair from bigchaindb.common.exceptions import InvalidSignature - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction input_tx = b.get_owned_ids(user_pk).pop() @@ -607,7 +598,7 @@ class TestTransactionValidation(object): sk, pk = generate_key_pair() tx = Transaction.create([pk], [([user_pk], 1)]) tx.operation = 'TRANSFER' - tx.asset = AssetLink(input_transaction.id) + tx.asset = {'id': input_transaction.id} tx.fulfillments[0].tx_input = input_tx with pytest.raises(InvalidSignature): @@ -644,14 +635,13 @@ class TestTransactionValidation(object): def test_valid_non_create_transaction_after_block_creation(self, b, user_pk, user_sk): - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_transaction(input_tx.txid) inputs = input_tx.to_inputs() transfer_tx = Transaction.transfer(inputs, [([user_pk], 1)], - AssetLink(input_tx.id)) + asset_id=input_tx.id) transfer_tx = transfer_tx.sign([user_sk]) assert transfer_tx == b.validate_transaction(transfer_tx) @@ -669,7 +659,6 @@ class TestTransactionValidation(object): def test_transaction_not_in_valid_block(self, b, user_pk, user_sk): from bigchaindb.models import Transaction from bigchaindb.common.exceptions import TransactionNotInValidBlock - from bigchaindb.common.transaction import AssetLink input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_transaction(input_tx.txid) @@ -677,7 +666,7 @@ class TestTransactionValidation(object): # create a transaction that's valid but not in a voted valid block transfer_tx = Transaction.transfer(inputs, [([user_pk], 1)], - AssetLink(input_tx.id)) + asset_id=input_tx.id) transfer_tx = transfer_tx.sign([user_sk]) assert transfer_tx == b.validate_transaction(transfer_tx) @@ -689,7 +678,7 @@ class TestTransactionValidation(object): # create transaction with the undecided input tx_invalid = Transaction.transfer(transfer_tx.to_inputs(), [([user_pk], 1)], - AssetLink(transfer_tx.asset.id)) + asset_id=transfer_tx.asset['id']) tx_invalid = tx_invalid.sign([user_sk]) with pytest.raises(TransactionNotInValidBlock): @@ -783,7 +772,6 @@ class TestMultipleInputs(object): def test_transfer_single_owner_single_input(self, b, inputs, user_pk, user_sk): from bigchaindb.common import crypto - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -791,7 +779,7 @@ class TestMultipleInputs(object): input_tx = b.get_transaction(tx_link.txid) inputs = input_tx.to_inputs() tx = Transaction.transfer(inputs, [([user2_pk], 1)], - AssetLink(input_tx.id)) + asset_id=input_tx.id) tx = tx.sign([user_sk]) # validate transaction @@ -804,7 +792,6 @@ class TestMultipleInputs(object): user_pk, inputs): from bigchaindb.common import crypto - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -815,7 +802,7 @@ class TestMultipleInputs(object): input_tx = b.get_transaction(tx_link.txid) tx = Transaction.transfer(input_tx.to_inputs(), [([user2_pk, user3_pk], 1)], - AssetLink(input_tx.id)) + asset_id=input_tx.id) tx = tx.sign([user_sk]) assert b.is_valid_transaction(tx) == tx @@ -827,7 +814,6 @@ class TestMultipleInputs(object): user_sk, user_pk): from bigchaindb.common import crypto - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -847,7 +833,7 @@ class TestMultipleInputs(object): inputs = input_tx.to_inputs() transfer_tx = Transaction.transfer(inputs, [([user3_pk], 1)], - AssetLink(input_tx.id)) + asset_id=input_tx.id) transfer_tx = transfer_tx.sign([user_sk, user2_sk]) # validate transaction @@ -860,7 +846,6 @@ class TestMultipleInputs(object): user_sk, user_pk): from bigchaindb.common import crypto - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -882,7 +867,7 @@ class TestMultipleInputs(object): tx = Transaction.transfer(tx_input.to_inputs(), [([user3_pk, user4_pk], 1)], - AssetLink(tx_input.id)) + asset_id=tx_input.id) tx = tx.sign([user_sk, user2_sk]) assert b.is_valid_transaction(tx) == tx @@ -891,7 +876,7 @@ class TestMultipleInputs(object): def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_pk): from bigchaindb.common import crypto - from bigchaindb.common.transaction import AssetLink, TransactionLink + from bigchaindb.common.transaction import TransactionLink from bigchaindb.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -907,7 +892,7 @@ class TestMultipleInputs(object): assert owned_inputs_user2 == [] tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)], - AssetLink(tx.id)) + asset_id=tx.id) tx = tx.sign([user_sk]) block = b.create_block([tx]) b.write_block(block) @@ -922,7 +907,7 @@ class TestMultipleInputs(object): user_pk, genesis_block): from bigchaindb.common import crypto - from bigchaindb.common.transaction import AssetLink, TransactionLink + from bigchaindb.common.transaction import TransactionLink from bigchaindb.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -944,7 +929,7 @@ 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_pk], 1)], - AssetLink(tx.id)) + asset_id=tx.id) tx_invalid = tx_invalid.sign([user_sk]) block = b.create_block([tx_invalid]) b.write_block(block) @@ -963,17 +948,13 @@ class TestMultipleInputs(object): def test_get_owned_ids_single_tx_multiple_outputs(self, b, user_sk, user_pk): from bigchaindb.common import crypto - from bigchaindb.common.transaction import (TransactionLink, Asset, - AssetLink) + from bigchaindb.common.transaction import TransactionLink from bigchaindb.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() # create divisible asset - asset = Asset() - tx_create = Transaction.create([b.me], - [([user_pk], 1), ([user_pk], 1)], - asset=asset) + tx_create = Transaction.create([b.me], [([user_pk], 1), ([user_pk], 1)]) tx_create_signed = tx_create.sign([b.me_private]) block = b.create_block([tx_create_signed]) b.write_block(block) @@ -990,7 +971,7 @@ class TestMultipleInputs(object): # transfer divisible asset divided in two outputs tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user2_pk], 1), ([user2_pk], 1)], - asset_link=AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) block = b.create_block([tx_transfer_signed]) b.write_block(block) @@ -1003,7 +984,7 @@ class TestMultipleInputs(object): def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk): from bigchaindb.common import crypto - from bigchaindb.common.transaction import AssetLink, TransactionLink + from bigchaindb.common.transaction import TransactionLink from bigchaindb.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -1022,7 +1003,7 @@ class TestMultipleInputs(object): assert owned_inputs_user1 == expected_owned_inputs_user1 tx = Transaction.transfer(tx.to_inputs(), [([user3_pk], 1)], - AssetLink(tx.id)) + asset_id=tx.id) tx = tx.sign([user_sk, user2_sk]) block = b.create_block([tx]) b.write_block(block) @@ -1034,7 +1015,6 @@ class TestMultipleInputs(object): def test_get_spent_single_tx_single_output(self, b, user_sk, user_pk): from bigchaindb.common import crypto - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -1054,7 +1034,7 @@ class TestMultipleInputs(object): # create a transaction and block tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)], - AssetLink(tx.id)) + asset_id=tx.id) tx = tx.sign([user_sk]) block = b.create_block([tx]) b.write_block(block) @@ -1067,7 +1047,6 @@ class TestMultipleInputs(object): user_pk, genesis_block): from bigchaindb.common import crypto - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction # create a new users @@ -1092,7 +1071,7 @@ class TestMultipleInputs(object): # create a transaction and block tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)], - AssetLink(tx.id)) + asset_id=tx.id) tx = tx.sign([user_sk]) block = b.create_block([tx]) b.write_block(block) @@ -1109,19 +1088,16 @@ class TestMultipleInputs(object): def test_get_spent_single_tx_multiple_outputs(self, b, user_sk, user_pk): from bigchaindb.common import crypto - from bigchaindb.common.transaction import Asset, AssetLink from bigchaindb.models import Transaction # create a new users user2_sk, user2_pk = crypto.generate_key_pair() # create a divisible asset with 3 outputs - asset = Asset() tx_create = Transaction.create([b.me], [([user_pk], 1), ([user_pk], 1), - ([user_pk], 1)], - asset=asset) + ([user_pk], 1)]) tx_create_signed = tx_create.sign([b.me_private]) block = b.create_block([tx_create_signed]) b.write_block(block) @@ -1135,7 +1111,7 @@ class TestMultipleInputs(object): # transfer the first 2 inputs tx_transfer = Transaction.transfer(tx_create.to_inputs()[:2], [([user2_pk], 1), ([user2_pk], 1)], - asset_link=AssetLink(tx_create.id)) + asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) block = b.create_block([tx_transfer_signed]) b.write_block(block) @@ -1151,7 +1127,6 @@ class TestMultipleInputs(object): def test_get_spent_multiple_owners(self, b, user_sk, user_pk): from bigchaindb.common import crypto - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -1176,7 +1151,7 @@ class TestMultipleInputs(object): # create a transaction tx = Transaction.transfer(transactions[0].to_inputs(), [([user3_pk], 1)], - AssetLink(transactions[0].id)) + asset_id=transactions[0].id) tx = tx.sign([user_sk, user2_sk]) block = b.create_block([tx]) b.write_block(block) diff --git a/tests/pipelines/test_vote.py b/tests/pipelines/test_vote.py index 0d1f673c..8eae0755 100644 --- a/tests/pipelines/test_vote.py +++ b/tests/pipelines/test_vote.py @@ -271,7 +271,6 @@ def test_valid_block_voting_with_transfer_transactions(monkeypatch, b, genesis_block): from bigchaindb.backend import query from bigchaindb.common import crypto, util - from bigchaindb.common.transaction import AssetLink from bigchaindb.models import Transaction from bigchaindb.pipelines import vote @@ -287,7 +286,7 @@ def test_valid_block_voting_with_transfer_transactions(monkeypatch, # create a `TRANSFER` transaction test_user2_priv, test_user2_pub = crypto.generate_key_pair() tx2 = Transaction.transfer(tx.to_inputs(), [([test_user2_pub], 1)], - AssetLink(tx.id)) + asset_id=tx.id) tx2 = tx2.sign([test_user_priv]) monkeypatch.setattr('time.time', lambda: 2222222222) diff --git a/tests/web/test_transactions.py b/tests/web/test_transactions.py index 45c94181..304dcce2 100644 --- a/tests/web/test_transactions.py +++ b/tests/web/test_transactions.py @@ -127,7 +127,6 @@ def test_post_invalid_transaction(client, exc, msg, monkeypatch): def test_post_transfer_transaction_endpoint(b, client, user_pk, user_sk): sk, pk = crypto.generate_key_pair() from bigchaindb.models import Transaction - from bigchaindb.common.transaction import AssetLink user_priv, user_pub = crypto.generate_key_pair() @@ -135,7 +134,7 @@ def test_post_transfer_transaction_endpoint(b, client, user_pk, user_sk): create_tx = b.get_transaction(input_valid.txid) transfer_tx = Transaction.transfer(create_tx.to_inputs(), [([user_pub], 1)], - AssetLink(create_tx.id)) + asset_id=create_tx.id) transfer_tx = transfer_tx.sign([user_sk]) res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict())) @@ -148,7 +147,6 @@ def test_post_transfer_transaction_endpoint(b, client, user_pk, user_sk): @pytest.mark.usefixtures('inputs') def test_post_invalid_transfer_transaction_returns_400(b, client, user_pk, user_sk): from bigchaindb.models import Transaction - from bigchaindb.common.transaction import AssetLink user_priv, user_pub = crypto.generate_key_pair() @@ -156,7 +154,7 @@ def test_post_invalid_transfer_transaction_returns_400(b, client, user_pk, user_ create_tx = b.get_transaction(input_valid.txid) transfer_tx = Transaction.transfer(create_tx.to_inputs(), [([user_pub], 1)], - AssetLink(create_tx.id)) + asset_id=create_tx.id) res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict())) assert res.status_code == 400