Tx ID as Asset ID (#926)

* Allow AssetLinks to be used in place of Assets in the Transaction Model and enforce `Transaction.transfer()` to only take an AssetLink

* Remove AssetLink's inheritance from Asset

* Remove id from the Asset model

* Fix get_txids_by_asset_id query for rethinkdb after removing asset's uuid

Because `CREATE` transactions don't have an asset that contains an id
anymore, one way to find all the transactions related to an asset is to
query the database twice: once for the `CREATE` transaction and another
for the `TRANSFER` transactions.

* Add TODO notice for vote test utils to be fixtures

* Update asset model documentation to reflect usage of transaction id

* Fix outdated asset description in transaction schema
This commit is contained in:
libscott 2016-12-20 17:28:15 +01:00 committed by Brett Sun
parent 1d7a8e3369
commit 7e33f2bd52
19 changed files with 316 additions and 259 deletions

View File

@ -111,12 +111,12 @@ def get_blocks_status_from_transaction(connection, transaction_id):
def get_txids_by_asset_id(connection, asset_id): def get_txids_by_asset_id(connection, asset_id):
"""Retrieves transactions ids related to a particular asset. """Retrieves transactions ids related to a particular asset.
A digital asset in bigchaindb is identified by an uuid. This allows us A digital asset in bigchaindb is identified by its ``CREATE``
to query all the transactions related to a particular digital asset, transaction's ID. Knowing this ID allows us to query all the
knowing the id. transactions related to a particular digital asset.
Args: Args:
asset_id (str): the id for this particular metadata. asset_id (str): the ID of the asset.
Returns: Returns:
A list of transactions ids related to the asset. If no transaction A list of transactions ids related to the asset. If no transaction

View File

@ -1,3 +1,4 @@
from itertools import chain
from time import time from time import time
import rethinkdb as r import rethinkdb as r
@ -75,23 +76,32 @@ def get_blocks_status_from_transaction(connection, transaction_id):
def get_txids_by_asset_id(connection, asset_id): def get_txids_by_asset_id(connection, asset_id):
# here we only want to return the transaction ids since later on when # here we only want to return the transaction ids since later on when
# we are going to retrieve the transaction with status validation # we are going to retrieve the transaction with status validation
return connection.run(
# First find the asset's CREATE transaction
create_tx_cursor = connection.run(
_get_asset_create_tx_query(asset_id).get_field('id'))
# Then find any TRANSFER transactions related to the asset
transfer_tx_cursor = connection.run(
r.table('bigchain') r.table('bigchain')
.get_all(asset_id, index='asset_id') .get_all(asset_id, index='asset_id')
.concat_map(lambda block: block['block']['transactions']) .concat_map(lambda block: block['block']['transactions'])
.filter(lambda transaction: transaction['asset']['id'] == asset_id) .filter(lambda transaction: transaction['asset']['id'] == asset_id)
.get_field('id')) .get_field('id'))
return chain(create_tx_cursor, transfer_tx_cursor)
@register_query(RethinkDBConnection) @register_query(RethinkDBConnection)
def get_asset_by_id(connection, asset_id): def get_asset_by_id(connection, asset_id):
return connection.run( return connection.run(_get_asset_create_tx_query(asset_id).pluck('asset'))
r.table('bigchain', read_mode=READ_MODE)
.get_all(asset_id, index='asset_id')
.concat_map(lambda block: block['block']['transactions']) def _get_asset_create_tx_query(asset_id):
.filter(lambda transaction: transaction['asset']['id'] == asset_id) return r.table('bigchain', read_mode=READ_MODE) \
.filter(lambda transaction: transaction['operation'] == 'CREATE') .get_all(asset_id, index='transaction_id') \
.pluck('asset')) .concat_map(lambda block: block['block']['transactions']) \
.filter(lambda transaction: transaction['id'] == asset_id)
@register_query(RethinkDBConnection) @register_query(RethinkDBConnection)

View File

@ -60,7 +60,7 @@ def create_bigchain_secondary_index(connection, dbname):
.table('bigchain') .table('bigchain')
.index_create('transaction_id', r.row['block']['transactions']['id'], multi=True)) .index_create('transaction_id', r.row['block']['transactions']['id'], multi=True))
# secondary index for asset uuid # secondary index for asset links (in TRANSFER transactions)
connection.run( connection.run(
r.db(dbname) r.db(dbname)
.table('bigchain') .table('bigchain')

View File

@ -105,13 +105,14 @@ definitions:
description: | description: |
Description of the asset being transacted. In the case of a ``TRANSFER`` Description of the asset being transacted. In the case of a ``TRANSFER``
transaction, this field contains only the ID of asset. In the case transaction, this field contains only the ID of asset. In the case
of a ``CREATE`` transaction, this field may contain properties: of a ``CREATE`` transaction, this field contains only the user-defined
payload.
additionalProperties: false additionalProperties: false
required:
- id
properties: properties:
id: id:
"$ref": "#/definitions/uuid4" "$ref": "#/definitions/sha3_hexdigest"
description: |
ID of the transaction that created the asset.
data: data:
description: | description: |
User provided metadata associated with the asset. May also be ``null``. User provided metadata associated with the asset. May also be ``null``.

View File

@ -1,6 +1,5 @@
from copy import deepcopy from copy import deepcopy
from functools import reduce from functools import reduce
from uuid import uuid4
from cryptoconditions import (Fulfillment as CCFulfillment, from cryptoconditions import (Fulfillment as CCFulfillment,
ThresholdSha256Fulfillment, Ed25519Fulfillment) ThresholdSha256Fulfillment, Ed25519Fulfillment)
@ -384,14 +383,11 @@ class Asset(object):
Attributes: Attributes:
data (dict): A dictionary of data that can be added to an Asset. data (dict): A dictionary of data that can be added to an Asset.
data_id (str): A unique identifier of `data`'s content.
""" """
def __init__(self, data=None, data_id=None): def __init__(self, data=None):
"""An Asset is not required to contain any extra data from outside.""" """An Asset is not required to contain any extra data from outside."""
self.data = data self.data = data
self.data_id = data_id if data_id is not None else self.to_hash()
self.validate_asset() self.validate_asset()
def __eq__(self, other): def __eq__(self, other):
@ -409,7 +405,6 @@ class Asset(object):
format. format.
""" """
return { return {
'id': self.data_id,
'data': self.data, 'data': self.data,
} }
@ -423,38 +418,37 @@ class Asset(object):
Returns: Returns:
:class:`~bigchaindb.common.transaction.Asset` :class:`~bigchaindb.common.transaction.Asset`
""" """
return cls(asset.get('data'), asset['id']) return cls(asset.get('data'))
def to_hash(self):
"""Generates a unqiue uuid for an Asset"""
return str(uuid4())
@staticmethod @staticmethod
def get_asset_id(transactions): def get_asset_id(transactions):
"""Get the asset id from a list of transaction ids. """Get the asset id from a list of :class:`~.Transactions`.
This is useful when we want to check if the multiple inputs of a This is useful when we want to check if the multiple inputs of a
transaction are related to the same asset id. transaction are related to the same asset id.
Args: Args:
transactions (:obj:`list` of :class:`~bigchaindb.common. transactions (:obj:`list` of :class:`~bigchaindb.common.
transaction.Transaction`): list of transaction usually inputs transaction.Transaction`): A list of Transactions.
that should have a matching asset_id Usually input Transactions that should have a matching
asset ID.
Returns: Returns:
str: uuid of the asset. str: ID of the asset.
Raises: Raises:
AssetIdMismatch: If the inputs are related to different assets. :exc:`AssetIdMismatch`: If the inputs are related to different
assets.
""" """
if not isinstance(transactions, list): if not isinstance(transactions, list):
transactions = [transactions] transactions = [transactions]
# create a set of asset_ids # create a set of the transactions' asset ids
asset_ids = {tx.asset.data_id for tx in transactions} 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 # check that all the transasctions have the same asset id
if len(asset_ids) > 1: if len(asset_ids) > 1:
raise AssetIdMismatch(('All inputs of all transactions passed' raise AssetIdMismatch(('All inputs of all transactions passed'
' need to have the same asset id')) ' need to have the same asset id'))
@ -475,20 +469,20 @@ class Asset(object):
raise AmountError('`amount` must be greater than 0') raise AmountError('`amount` must be greater than 0')
class AssetLink(Asset): class AssetLink(object):
"""An object for unidirectional linking to a Asset. """An object for unidirectional linking to a Asset.
""" """
def __init__(self, data_id=None): def __init__(self, asset_id=None):
"""Used to point to a specific Asset. """Used to point to a specific Asset.
Args: Args:
data_id (str): A Asset to link to. asset_id (str): The ID of an asset to link to.
""" """
self.data_id = data_id self.id = asset_id
def __bool__(self): def __bool__(self):
return self.data_id is not None return self.id is not None
def __eq__(self, other): def __eq__(self, other):
return isinstance(other, AssetLink) and \ return isinstance(other, AssetLink) and \
@ -514,12 +508,14 @@ class AssetLink(Asset):
Returns: Returns:
(dict|None): The link as an alternative serialization format. (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.data_id is None: if self.id is None:
return None return None
else: else:
return { return {
'id': self.data_id 'id': self.id
} }
@ -537,6 +533,10 @@ class Transaction(object):
spend. spend.
conditions (:obj:`list` of :class:`~bigchaindb.common. conditions (:obj:`list` of :class:`~bigchaindb.common.
transaction.Condition`, optional): Define the assets to lock. 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.
metadata (dict): metadata (dict):
Metadata to be stored along with the Transaction. Metadata to be stored along with the Transaction.
version (int): Defines the version number of a Transaction. version (int): Defines the version number of a Transaction.
@ -557,8 +557,8 @@ class Transaction(object):
Args: Args:
operation (str): Defines the operation of the Transaction. operation (str): Defines the operation of the Transaction.
asset (:class:`~bigchaindb.common.transaction.Asset`): An Asset asset (:class:`~.Asset`|:class:`~.AssetLink`): An Asset to be
to be transferred or created in a Transaction. created or an AssetLink linking an asset to be transferred.
fulfillments (:obj:`list` of :class:`~bigchaindb.common. fulfillments (:obj:`list` of :class:`~bigchaindb.common.
transaction.Fulfillment`, optional): Define the assets to transaction.Fulfillment`, optional): Define the assets to
spend. spend.
@ -575,10 +575,17 @@ class Transaction(object):
raise ValueError('`operation` must be one of {}' raise ValueError('`operation` must be one of {}'
.format(allowed_ops)) .format(allowed_ops))
# Only assets for 'CREATE' operations can be un-defined. # Assets for 'CREATE' and 'GENESIS' operations must be None or of Asset
if (asset and not isinstance(asset, Asset) or # type and Assets for 'TRANSFER' operations must be of AssetLink type.
not asset and operation != Transaction.CREATE): if (operation in [Transaction.CREATE, Transaction.GENESIS] and
raise TypeError('`asset` must be an Asset instance') asset is not None and
not isinstance(asset, Asset)):
raise TypeError(("`asset` must be an Asset 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)))
if conditions and not isinstance(conditions, list): if conditions and not isinstance(conditions, list):
raise TypeError('`conditions` must be a list instance or None') raise TypeError('`conditions` must be a list instance or None')
@ -591,9 +598,9 @@ class Transaction(object):
self.version = version if version is not None else self.VERSION self.version = version if version is not None else self.VERSION
self.operation = operation self.operation = operation
self.asset = asset if asset else Asset() self.asset = asset or Asset()
self.conditions = conditions if conditions else [] self.conditions = conditions or []
self.fulfillments = fulfillments if fulfillments else [] self.fulfillments = fulfillments or []
self.metadata = metadata self.metadata = metadata
# validate asset # validate asset
@ -659,7 +666,7 @@ class Transaction(object):
return cls(cls.CREATE, asset, fulfillments, conditions, metadata) return cls(cls.CREATE, asset, fulfillments, conditions, metadata)
@classmethod @classmethod
def transfer(cls, inputs, owners_after, asset, metadata=None): def transfer(cls, inputs, owners_after, asset_link, metadata=None):
"""A simple way to generate a `TRANSFER` transaction. """A simple way to generate a `TRANSFER` transaction.
Note: Note:
@ -689,8 +696,9 @@ class Transaction(object):
generate. generate.
owners_after (:obj:`list` of :obj:`str`): A list of keys that owners_after (:obj:`list` of :obj:`str`): A list of keys that
represent the receivers of this Transaction. represent the receivers of this Transaction.
asset (:class:`~bigchaindb.common.transaction.Asset`): An Asset asset_link (:class:`~bigchaindb.common.transaction.AssetLink`):
to be transferred in this Transaction. An AssetLink linking an asset to be transferred in this
Transaction.
metadata (dict): Python dictionary to be stored along with the metadata (dict): Python dictionary to be stored along with the
Transaction. Transaction.
@ -716,7 +724,7 @@ class Transaction(object):
conditions.append(Condition.generate(pub_keys, amount)) conditions.append(Condition.generate(pub_keys, amount))
inputs = deepcopy(inputs) inputs = deepcopy(inputs)
return cls(cls.TRANSFER, asset, inputs, conditions, metadata) return cls(cls.TRANSFER, asset_link, inputs, conditions, metadata)
def __eq__(self, other): def __eq__(self, other):
try: try:
@ -1056,12 +1064,6 @@ class Transaction(object):
Returns: Returns:
dict: The Transaction as an alternative serialization format. dict: The Transaction as an alternative serialization format.
""" """
if self.operation in (self.__class__.GENESIS, self.__class__.CREATE):
asset = self.asset.to_dict()
else:
# NOTE: An `asset` in a `TRANSFER` only contains the asset's id
asset = {'id': self.asset.data_id}
tx = { tx = {
'fulfillments': [fulfillment.to_dict() for fulfillment 'fulfillments': [fulfillment.to_dict() for fulfillment
in self.fulfillments], in self.fulfillments],
@ -1069,7 +1071,7 @@ class Transaction(object):
in self.conditions], in self.conditions],
'operation': str(self.operation), 'operation': str(self.operation),
'metadata': self.metadata, 'metadata': self.metadata,
'asset': asset, 'asset': self.asset.to_dict(),
'version': self.version, 'version': self.version,
} }

View File

@ -82,7 +82,7 @@ class Transaction(Transaction):
# validate asset id # validate asset id
asset_id = Asset.get_asset_id(input_txs) asset_id = Asset.get_asset_id(input_txs)
if asset_id != self.asset.data_id: if asset_id != self.asset.id:
raise AssetIdMismatch(('The asset id of the input does not' raise AssetIdMismatch(('The asset id of the input does not'
' match the asset id of the' ' match the asset id of the'
' transaction')) ' transaction'))

View File

@ -62,7 +62,7 @@ def main():
""" Main function """ """ Main function """
privkey = 'CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z' privkey = 'CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z'
pubkey = '4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD' pubkey = '4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD'
asset = Asset(None, 'e6969f87-4fc9-4467-b62a-f0dfa1c85002') asset = Asset(None)
tx = Transaction.create([pubkey], [([pubkey], 1)], asset=asset) tx = Transaction.create([pubkey], [([pubkey], 1)], asset=asset)
tx = tx.sign([privkey]) tx = tx.sign([privkey])
tx_json = json.dumps(tx.to_dict(), indent=2, sort_keys=True) tx_json = json.dumps(tx.to_dict(), indent=2, sort_keys=True)

View File

@ -5,18 +5,17 @@ To avoid redundant data in transactions, the digital asset model is different fo
A digital asset's properties are defined in a `CREATE` transaction with the following model: A digital asset's properties are defined in a `CREATE` transaction with the following model:
```json ```json
{ {
"id": "<uuid>",
"data": "<json document>" "data": "<json document>"
} }
``` ```
For `TRANSFER` transactions we only keep the asset id. For `TRANSFER` transactions we only keep the asset ID:
```json ```json
{ {
"id": "<uuid>" "id": "<asset's CREATE transaction ID (sha3-256 hash)>"
} }
``` ```
- `id`: UUID version 4 (random) converted to a string of hex digits in standard form. Added server side. - `id`: The ID of the `CREATE` transaction that created the asset.
- `data`: A user supplied JSON document with custom information about the asset. Defaults to null. - `data`: A user supplied JSON document with custom information about the asset. Defaults to null.

View File

@ -1,20 +1,22 @@
import pytest import pytest
import random
from unittest.mock import patch from unittest.mock import patch
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_asset_transfer(b, user_pk, user_sk): def test_asset_transfer(b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
tx_input = b.get_owned_ids(user_pk).pop() tx_input = b.get_owned_ids(user_pk).pop()
tx_create = b.get_transaction(tx_input.txid) tx_create = b.get_transaction(tx_input.txid)
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed assert tx_transfer_signed.validate(b) == tx_transfer_signed
assert tx_transfer_signed.asset.data_id == tx_create.asset.data_id assert tx_transfer_signed.asset.id == tx_create.id
def test_validate_bad_asset_creation(b, user_pk): def test_validate_bad_asset_creation(b, user_pk):
@ -32,13 +34,14 @@ def test_validate_bad_asset_creation(b, user_pk):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_validate_transfer_asset_id_mismatch(b, user_pk, user_sk): def test_validate_transfer_asset_id_mismatch(b, user_pk, user_sk):
from bigchaindb.common.exceptions import AssetIdMismatch from bigchaindb.common.exceptions import AssetIdMismatch
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
tx_create = b.get_owned_ids(user_pk).pop() tx_create = b.get_owned_ids(user_pk).pop()
tx_create = b.get_transaction(tx_create.txid) tx_create = b.get_transaction(tx_create.txid)
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
tx_create.asset) AssetLink(tx_create.id))
tx_transfer.asset.data_id = 'aaa' tx_transfer.asset.id = 'aaa'
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
with pytest.raises(AssetIdMismatch): with pytest.raises(AssetIdMismatch):
tx_transfer_signed.validate(b) tx_transfer_signed.validate(b)
@ -50,18 +53,19 @@ def test_get_asset_id_create_transaction(b, user_pk):
tx_create = Transaction.create([b.me], [([user_pk], 1)]) tx_create = Transaction.create([b.me], [([user_pk], 1)])
asset_id = Asset.get_asset_id(tx_create) asset_id = Asset.get_asset_id(tx_create)
assert asset_id == tx_create.asset.data_id assert asset_id == tx_create.id
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_get_asset_id_transfer_transaction(b, user_pk, user_sk): 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, Asset
tx_create = b.get_owned_ids(user_pk).pop() tx_create = b.get_owned_ids(user_pk).pop()
tx_create = b.get_transaction(tx_create.txid) tx_create = b.get_transaction(tx_create.txid)
# create a transfer transaction # create a transfer transaction
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
# create a block # create a block
block = b.create_block([tx_transfer_signed]) block = b.create_block([tx_transfer_signed])
@ -71,15 +75,17 @@ def test_get_asset_id_transfer_transaction(b, user_pk, user_sk):
b.write_vote(vote) b.write_vote(vote)
asset_id = Asset.get_asset_id(tx_transfer) asset_id = Asset.get_asset_id(tx_transfer)
assert asset_id == tx_transfer.asset.data_id assert asset_id == tx_transfer.asset.id
def test_asset_id_mismatch(b, user_pk): def test_asset_id_mismatch(b, user_pk):
from bigchaindb.models import Transaction, Asset from bigchaindb.models import Transaction, Asset
from bigchaindb.common.exceptions import AssetIdMismatch from bigchaindb.common.exceptions import AssetIdMismatch
tx1 = Transaction.create([b.me], [([user_pk], 1)]) tx1 = Transaction.create([b.me], [([user_pk], 1)],
tx2 = Transaction.create([b.me], [([user_pk], 1)]) metadata={'msg': random.random()})
tx2 = Transaction.create([b.me], [([user_pk], 1)],
metadata={'msg': random.random()})
with pytest.raises(AssetIdMismatch): with pytest.raises(AssetIdMismatch):
Asset.get_asset_id([tx1, tx2]) Asset.get_asset_id([tx1, tx2])
@ -87,20 +93,21 @@ def test_asset_id_mismatch(b, user_pk):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_get_transactions_by_asset_id(b, user_pk, user_sk): def test_get_transactions_by_asset_id(b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
tx_create = b.get_owned_ids(user_pk).pop() tx_create = b.get_owned_ids(user_pk).pop()
tx_create = b.get_transaction(tx_create.txid) tx_create = b.get_transaction(tx_create.txid)
asset_id = tx_create.asset.data_id asset_id = tx_create.id
txs = b.get_transactions_by_asset_id(asset_id) txs = b.get_transactions_by_asset_id(asset_id)
assert len(txs) == 1 assert len(txs) == 1
assert txs[0].id == tx_create.id assert txs[0].id == tx_create.id
assert txs[0].asset.data_id == asset_id assert txs[0].id == asset_id
# create a transfer transaction # create a transfer transaction
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
# create the block # create the block
block = b.create_block([tx_transfer_signed]) block = b.create_block([tx_transfer_signed])
@ -114,26 +121,28 @@ def test_get_transactions_by_asset_id(b, user_pk, user_sk):
assert len(txs) == 2 assert len(txs) == 2
assert tx_create.id in [t.id for t in txs] assert tx_create.id in [t.id for t in txs]
assert tx_transfer.id in [t.id for t in txs] assert tx_transfer.id in [t.id for t in txs]
assert asset_id == txs[0].asset.data_id # FIXME: can I rely on the ordering here?
assert asset_id == txs[1].asset.data_id assert asset_id == txs[0].id
assert asset_id == txs[1].asset.id
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_get_transactions_by_asset_id_with_invalid_block(b, user_pk, user_sk): 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 from bigchaindb.models import Transaction
tx_create = b.get_owned_ids(user_pk).pop() tx_create = b.get_owned_ids(user_pk).pop()
tx_create = b.get_transaction(tx_create.txid) tx_create = b.get_transaction(tx_create.txid)
asset_id = tx_create.asset.data_id asset_id = tx_create.id
txs = b.get_transactions_by_asset_id(asset_id) txs = b.get_transactions_by_asset_id(asset_id)
assert len(txs) == 1 assert len(txs) == 1
assert txs[0].id == tx_create.id assert txs[0].id == tx_create.id
assert txs[0].asset.data_id == asset_id assert txs[0].id == asset_id
# create a transfer transaction # create a transfer transaction
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
# create the block # create the block
block = b.create_block([tx_transfer_signed]) block = b.create_block([tx_transfer_signed])
@ -149,15 +158,15 @@ def test_get_transactions_by_asset_id_with_invalid_block(b, user_pk, user_sk):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_get_asset_by_id(b, user_pk, user_sk): def test_get_asset_by_id(b, user_pk, user_sk):
from bigchaindb.models import Transaction from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Asset, Transaction
tx_create = b.get_owned_ids(user_pk).pop() tx_create = b.get_owned_ids(user_pk).pop()
tx_create = b.get_transaction(tx_create.txid) tx_create = b.get_transaction(tx_create.txid)
asset_id = tx_create.asset.data_id
# create a transfer transaction # create a transfer transaction
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
# create the block # create the block
block = b.create_block([tx_transfer_signed]) block = b.create_block([tx_transfer_signed])
@ -166,6 +175,7 @@ def test_get_asset_by_id(b, user_pk, user_sk):
vote = b.vote(block.id, b.get_last_voted_block().id, True) vote = b.vote(block.id, b.get_last_voted_block().id, True)
b.write_vote(vote) b.write_vote(vote)
asset_id = Asset.get_asset_id([tx_create, tx_transfer])
txs = b.get_transactions_by_asset_id(asset_id) txs = b.get_transactions_by_asset_id(asset_id)
assert len(txs) == 2 assert len(txs) == 2

View File

@ -130,7 +130,7 @@ 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, def test_single_in_single_own_single_out_single_own_transfer(b, user_pk,
user_sk): user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset # CREATE divisible asset
asset = Asset() asset = Asset()
@ -146,7 +146,7 @@ def test_single_in_single_own_single_out_single_own_transfer(b, user_pk,
# TRANSFER # TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) assert tx_transfer_signed.validate(b)
@ -164,7 +164,7 @@ 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, def test_single_in_single_own_multiple_out_single_own_transfer(b, user_pk,
user_sk): user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset # CREATE divisible asset
asset = Asset() asset = Asset()
@ -181,7 +181,7 @@ def test_single_in_single_own_multiple_out_single_own_transfer(b, user_pk,
# TRANSFER # TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 50), ([b.me], 50)], [([b.me], 50), ([b.me], 50)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -200,7 +200,7 @@ 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, def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk,
user_sk): user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset # CREATE divisible asset
asset = Asset() asset = Asset()
@ -217,7 +217,7 @@ def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk,
# TRANSFER # TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me, b.me], 100)], [([b.me, b.me], 100)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -241,7 +241,7 @@ 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, def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_pk,
user_sk): user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset # CREATE divisible asset
asset = Asset() asset = Asset()
@ -258,7 +258,7 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_pk,
# TRANSFER # TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 50), ([b.me, b.me], 50)], [([b.me], 50), ([b.me, b.me], 50)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -282,7 +282,7 @@ 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, def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk,
user_sk): user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset # CREATE divisible asset
asset = Asset() asset = Asset()
@ -299,7 +299,7 @@ def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk,
# TRANSFER # TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk]) tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -321,7 +321,7 @@ 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, def test_multiple_in_single_own_single_out_single_own_transfer(b, user_pk,
user_sk): user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset # CREATE divisible asset
asset = Asset() asset = Asset()
@ -338,7 +338,7 @@ def test_multiple_in_single_own_single_out_single_own_transfer(b, user_pk,
# TRANSFER # TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) assert tx_transfer_signed.validate(b)
@ -356,7 +356,7 @@ 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, def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_pk,
user_sk): user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset # CREATE divisible asset
asset = Asset() asset = Asset()
@ -375,7 +375,7 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_pk,
# TRANSFER # TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk]) tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
assert tx_transfer_signed.validate(b) assert tx_transfer_signed.validate(b)
@ -401,7 +401,7 @@ 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, def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(b, user_pk,
user_sk): user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset # CREATE divisible asset
asset = Asset() asset = Asset()
@ -420,7 +420,7 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(b, user_pk,
# TRANSFER # TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk]) tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -446,7 +446,7 @@ 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, def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk,
user_sk): user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset # CREATE divisible asset
asset = Asset() asset = Asset()
@ -466,7 +466,7 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk,
# TRANSFER # TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 50), ([b.me, user_pk], 50)], [([b.me], 50), ([b.me, user_pk], 50)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk]) tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -496,7 +496,7 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk,
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_multiple_in_different_transactions(b, user_pk, user_sk): def test_multiple_in_different_transactions(b, user_pk, user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset # CREATE divisible asset
# `b` creates a divisible asset and assigns 50 shares to `b` and # `b` creates a divisible asset and assigns 50 shares to `b` and
@ -521,7 +521,7 @@ def test_multiple_in_different_transactions(b, user_pk, user_sk):
# split across two different transactions # split across two different transactions
tx_transfer1 = Transaction.transfer(tx_create.to_inputs([1]), tx_transfer1 = Transaction.transfer(tx_create.to_inputs([1]),
[([user_pk], 50)], [([user_pk], 50)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer1_signed = tx_transfer1.sign([b.me_private]) tx_transfer1_signed = tx_transfer1.sign([b.me_private])
# create block # create block
block = b.create_block([tx_transfer1_signed]) block = b.create_block([tx_transfer1_signed])
@ -537,7 +537,7 @@ def test_multiple_in_different_transactions(b, user_pk, user_sk):
tx_transfer2 = Transaction.transfer(tx_create.to_inputs([0]) + tx_transfer2 = Transaction.transfer(tx_create.to_inputs([0]) +
tx_transfer1.to_inputs([0]), tx_transfer1.to_inputs([0]),
[([b.me], 100)], [([b.me], 100)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer2_signed = tx_transfer2.sign([user_sk]) tx_transfer2_signed = tx_transfer2.sign([user_sk])
assert tx_transfer2_signed.validate(b) == tx_transfer2_signed assert tx_transfer2_signed.validate(b) == tx_transfer2_signed
@ -557,7 +557,7 @@ def test_multiple_in_different_transactions(b, user_pk, user_sk):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_amount_error_transfer(b, user_pk, user_sk): def test_amount_error_transfer(b, user_pk, user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
from bigchaindb.common.exceptions import AmountError from bigchaindb.common.exceptions import AmountError
# CREATE divisible asset # CREATE divisible asset
@ -575,7 +575,7 @@ def test_amount_error_transfer(b, user_pk, user_sk):
# TRANSFER # TRANSFER
# output amount less than input amount # output amount less than input amount
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 50)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 50)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
with pytest.raises(AmountError): with pytest.raises(AmountError):
tx_transfer_signed.validate(b) tx_transfer_signed.validate(b)
@ -583,7 +583,7 @@ def test_amount_error_transfer(b, user_pk, user_sk):
# TRANSFER # TRANSFER
# output amount greater than input amount # output amount greater than input amount
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 101)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 101)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
with pytest.raises(AmountError): with pytest.raises(AmountError):
tx_transfer_signed.validate(b) tx_transfer_signed.validate(b)
@ -600,7 +600,7 @@ def test_threshold_same_public_key(b, user_pk, user_sk):
# that does not mean that the code shouldn't work. # that does not mean that the code shouldn't work.
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset # CREATE divisible asset
asset = Asset() asset = Asset()
@ -617,7 +617,7 @@ def test_threshold_same_public_key(b, user_pk, user_sk):
# TRANSFER # TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk, user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk, user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -626,7 +626,7 @@ def test_threshold_same_public_key(b, user_pk, user_sk):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_sum_amount(b, user_pk, user_sk): def test_sum_amount(b, user_pk, user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset with 3 outputs with amount 1 # CREATE divisible asset with 3 outputs with amount 1
asset = Asset() asset = Asset()
@ -647,7 +647,7 @@ def test_sum_amount(b, user_pk, user_sk):
# create a transfer transaction with one output and check if the amount # create a transfer transaction with one output and check if the amount
# is 3 # is 3
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 3)], tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 3)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -658,7 +658,7 @@ def test_sum_amount(b, user_pk, user_sk):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_divide(b, user_pk, user_sk): def test_divide(b, user_pk, user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset with 1 output with amount 3 # CREATE divisible asset with 1 output with amount 3
asset = Asset() asset = Asset()
@ -677,7 +677,7 @@ def test_divide(b, user_pk, user_sk):
# of each output is 1 # of each output is 1
tx_transfer = Transaction.transfer(tx_create.to_inputs(), tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 1), ([b.me], 1), ([b.me], 1)], [([b.me], 1), ([b.me], 1), ([b.me], 1)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -690,7 +690,7 @@ def test_divide(b, user_pk, user_sk):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_non_positive_amounts_on_transfer(b, user_pk): def test_non_positive_amounts_on_transfer(b, user_pk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
from bigchaindb.common.exceptions import AmountError from bigchaindb.common.exceptions import AmountError
# CREATE divisible asset with 1 output with amount 3 # CREATE divisible asset with 1 output with amount 3
@ -709,14 +709,14 @@ def test_non_positive_amounts_on_transfer(b, user_pk):
with pytest.raises(AmountError): with pytest.raises(AmountError):
Transaction.transfer(tx_create.to_inputs(), Transaction.transfer(tx_create.to_inputs(),
[([b.me], 4), ([b.me], -1)], [([b.me], 4), ([b.me], -1)],
asset=tx_create.asset) AssetLink(tx_create.id))
# Check that negative inputs are caught when validating a TRANSFER transaction # Check that negative inputs are caught when validating a TRANSFER transaction
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_non_positive_amounts_on_transfer_validate(b, user_pk, user_sk): def test_non_positive_amounts_on_transfer_validate(b, user_pk, user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset, AssetLink
from bigchaindb.common.exceptions import AmountError from bigchaindb.common.exceptions import AmountError
# CREATE divisible asset with 1 output with amount 3 # CREATE divisible asset with 1 output with amount 3
@ -736,7 +736,7 @@ def test_non_positive_amounts_on_transfer_validate(b, user_pk, user_sk):
# of each output is 1 # of each output is 1
tx_transfer = Transaction.transfer(tx_create.to_inputs(), tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 4), ([b.me], 1)], [([b.me], 4), ([b.me], 1)],
asset=tx_create.asset) AssetLink(tx_create.id))
tx_transfer.conditions[1].amount = -1 tx_transfer.conditions[1].amount = -1
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])

View File

@ -17,9 +17,6 @@ CC_CONDITION_URI = 'cc:0:3:47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU:0'
DATA = { DATA = {
'msg': 'Hello BigchainDB!' 'msg': 'Hello BigchainDB!'
} }
DATA_ID = '872fa6e6f46246cd44afdb2ee9cfae0e72885fb0910e2bcf9a5a2a4eadb417b8'
UUID4 = 'dc568f27-a113-46b4-9bd4-43015859e3e3'
@pytest.fixture @pytest.fixture
@ -126,16 +123,6 @@ def data():
return DATA return DATA
@pytest.fixture
def data_id():
return DATA_ID
@pytest.fixture
def uuid4():
return UUID4
@pytest.fixture @pytest.fixture
def utx(user_ffill, user_cond): def utx(user_ffill, user_cond):
from bigchaindb.common.transaction import Transaction, Asset from bigchaindb.common.transaction import Transaction, Asset
@ -150,12 +137,12 @@ def tx(utx, user_priv):
@pytest.fixture @pytest.fixture
def transfer_utx(user_cond, user2_cond, utx): def transfer_utx(user_cond, user2_cond, utx):
from bigchaindb.common.transaction import (Fulfillment, TransactionLink, from bigchaindb.common.transaction import (Fulfillment, TransactionLink,
Transaction, Asset) Transaction, AssetLink)
user_cond = user_cond.to_dict() user_cond = user_cond.to_dict()
ffill = Fulfillment(utx.conditions[0].fulfillment, ffill = Fulfillment(utx.conditions[0].fulfillment,
user_cond['owners_after'], user_cond['owners_after'],
TransactionLink(utx.id, 0)) TransactionLink(utx.id, 0))
return Transaction('TRANSFER', Asset(), [ffill], [user2_cond]) return Transaction('TRANSFER', AssetLink(utx.id), [ffill], [user2_cond])
@pytest.fixture @pytest.fixture

View File

@ -6,7 +6,6 @@ def test_asset_default_values():
asset = Asset() asset = Asset()
assert asset.data is None assert asset.data is None
assert asset.data_id
def test_asset_creation_with_data(data): def test_asset_creation_with_data(data):
@ -24,32 +23,30 @@ def test_asset_invalid_asset_initialization():
Asset(data='some wrong type') Asset(data='some wrong type')
def test_invalid_asset_comparison(data, data_id): def test_invalid_asset_comparison(data):
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset
assert Asset(data, data_id) != 'invalid comparison' assert Asset(data) != 'invalid comparison'
def test_asset_serialization(data, data_id): def test_asset_serialization(data):
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset
expected = { expected = {
'id': data_id,
'data': data, 'data': data,
} }
asset = Asset(data, data_id) asset = Asset(data)
assert asset.to_dict() == expected assert asset.to_dict() == expected
def test_asset_deserialization(data, data_id): def test_asset_deserialization(data):
from bigchaindb.common.transaction import Asset from bigchaindb.common.transaction import Asset
asset_dict = { asset_dict = {
'id': data_id,
'data': data, 'data': data,
} }
asset = Asset.from_dict(asset_dict) asset = Asset.from_dict(asset_dict)
expected = Asset(data, data_id) expected = Asset(data)
assert asset == expected assert asset == expected

View File

@ -274,27 +274,17 @@ def test_invalid_transaction_initialization():
def test_create_default_asset_on_tx_initialization(): def test_create_default_asset_on_tx_initialization():
from bigchaindb.common.transaction import Transaction, Asset from bigchaindb.common.transaction import Transaction, Asset
from bigchaindb.common.exceptions import ValidationError
from .util import validate_transaction_model
with patch.object(Asset, 'validate_asset', return_value=None): with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, None) tx = Transaction(Transaction.CREATE, None)
expected = Asset() expected = Asset()
asset = tx.asset asset = tx.asset
expected.data_id = None
asset.data_id = None
assert asset == expected assert asset == expected
# Fails because no asset hash
with raises(ValidationError):
validate_transaction_model(tx)
def test_transaction_serialization(user_ffill, user_cond, data):
def test_transaction_serialization(user_ffill, user_cond, data, data_id):
from bigchaindb.common.transaction import Transaction, Asset from bigchaindb.common.transaction import Transaction, Asset
from bigchaindb.common.exceptions import ValidationError
from .util import validate_transaction_model
tx_id = 'l0l' tx_id = 'l0l'
@ -308,30 +298,23 @@ def test_transaction_serialization(user_ffill, user_cond, data, data_id):
'operation': Transaction.CREATE, 'operation': Transaction.CREATE,
'metadata': None, 'metadata': None,
'asset': { 'asset': {
'id': data_id,
'data': data, 'data': data,
} }
} }
tx = Transaction(Transaction.CREATE, Asset(data, data_id), [user_ffill], tx = Transaction(Transaction.CREATE, Asset(data), [user_ffill],
[user_cond]) [user_cond])
tx_dict = tx.to_dict() tx_dict = tx.to_dict()
tx_dict['id'] = tx_id tx_dict['id'] = tx_id
tx_dict['asset']['id'] = data_id
assert tx_dict == expected assert tx_dict == expected
# Fails because asset id is not a uuid4
with raises(ValidationError):
validate_transaction_model(tx)
def test_transaction_deserialization(user_ffill, user_cond, data):
def test_transaction_deserialization(user_ffill, user_cond, data, uuid4):
from bigchaindb.common.transaction import Transaction, Asset from bigchaindb.common.transaction import Transaction, Asset
from .util import validate_transaction_model from .util import validate_transaction_model
expected_asset = Asset(data)
expected_asset = Asset(data, uuid4)
expected = Transaction(Transaction.CREATE, expected_asset, [user_ffill], expected = Transaction(Transaction.CREATE, expected_asset, [user_ffill],
[user_cond], None, Transaction.VERSION) [user_cond], None, Transaction.VERSION)
@ -344,7 +327,6 @@ def test_transaction_deserialization(user_ffill, user_cond, data, uuid4):
'operation': Transaction.CREATE, 'operation': Transaction.CREATE,
'metadata': None, 'metadata': None,
'asset': { 'asset': {
'id': uuid4,
'data': data, 'data': data,
} }
} }
@ -453,11 +435,11 @@ def test_cast_transaction_link_to_boolean():
def test_asset_link_serialization(): def test_asset_link_serialization():
from bigchaindb.common.transaction import AssetLink from bigchaindb.common.transaction import AssetLink
data_id = 'a asset id' asset_id = 'a asset id'
expected = { expected = {
'id': data_id, 'id': asset_id,
} }
asset_link = AssetLink(data_id) asset_link = AssetLink(asset_id)
assert asset_link.to_dict() == expected assert asset_link.to_dict() == expected
@ -474,10 +456,10 @@ def test_asset_link_serialization_with_empty_payload():
def test_asset_link_deserialization(): def test_asset_link_deserialization():
from bigchaindb.common.transaction import AssetLink from bigchaindb.common.transaction import AssetLink
data_id = 'a asset id' asset_id = 'a asset id'
expected = AssetLink(data_id) expected = AssetLink(asset_id)
asset_link = { asset_link = {
'id': data_id 'id': asset_id
} }
asset_link = AssetLink.from_dict(asset_link) asset_link = AssetLink.from_dict(asset_link)
@ -686,7 +668,8 @@ def test_multiple_fulfillment_validation_of_transfer_tx(user_ffill, user_cond,
user3_priv): user3_priv):
from copy import deepcopy from copy import deepcopy
from bigchaindb.common.transaction import (Transaction, TransactionLink, from bigchaindb.common.transaction import (Transaction, TransactionLink,
Fulfillment, Condition, Asset) Fulfillment, Condition, Asset,
AssetLink)
from cryptoconditions import Ed25519Fulfillment from cryptoconditions import Ed25519Fulfillment
from .util import validate_transaction_model from .util import validate_transaction_model
@ -702,7 +685,8 @@ def test_multiple_fulfillment_validation_of_transfer_tx(user_ffill, user_cond,
[user3_pub]), [user3_pub]),
Condition(Ed25519Fulfillment(public_key=user3_pub), Condition(Ed25519Fulfillment(public_key=user3_pub),
[user3_pub])] [user3_pub])]
transfer_tx = Transaction('TRANSFER', tx.asset, fulfillments, conditions) transfer_tx = Transaction('TRANSFER', AssetLink(tx.id),
fulfillments, conditions)
transfer_tx = transfer_tx.sign([user_priv]) transfer_tx = transfer_tx.sign([user_priv])
assert transfer_tx.fulfillments_valid(tx.conditions) is True assert transfer_tx.fulfillments_valid(tx.conditions) is True
@ -735,7 +719,7 @@ def test_validate_fulfillments_of_transfer_tx_with_invalid_params(transfer_tx,
transfer_tx.fulfillments_valid([utx.conditions[0]]) transfer_tx.fulfillments_valid([utx.conditions[0]])
def test_create_create_transaction_single_io(user_cond, user_pub, data, uuid4): 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, Asset
from .util import validate_transaction_model from .util import validate_transaction_model
@ -743,7 +727,6 @@ def test_create_create_transaction_single_io(user_cond, user_pub, data, uuid4):
'conditions': [user_cond.to_dict()], 'conditions': [user_cond.to_dict()],
'metadata': data, 'metadata': data,
'asset': { 'asset': {
'id': uuid4,
'data': data, 'data': data,
}, },
'fulfillments': [ 'fulfillments': [
@ -759,7 +742,7 @@ def test_create_create_transaction_single_io(user_cond, user_pub, data, uuid4):
'version': 1, 'version': 1,
} }
asset = Asset(data, uuid4) asset = Asset(data)
tx = Transaction.create([user_pub], [([user_pub], 1)], data, asset) tx = Transaction.create([user_pub], [([user_pub], 1)], data, asset)
tx_dict = tx.to_dict() tx_dict = tx.to_dict()
tx_dict['fulfillments'][0]['fulfillment'] = None tx_dict['fulfillments'][0]['fulfillment'] = None
@ -823,15 +806,13 @@ def test_validate_multiple_io_create_transaction(user_pub, user_priv,
def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub, def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub,
user_user2_threshold_cond, user_user2_threshold_cond,
user_user2_threshold_ffill, data, user_user2_threshold_ffill, data):
uuid4):
from bigchaindb.common.transaction import Transaction, Asset from bigchaindb.common.transaction import Transaction, Asset
expected = { expected = {
'conditions': [user_user2_threshold_cond.to_dict()], 'conditions': [user_user2_threshold_cond.to_dict()],
'metadata': data, 'metadata': data,
'asset': { 'asset': {
'id': uuid4,
'data': data, 'data': data,
}, },
'fulfillments': [ 'fulfillments': [
@ -846,7 +827,7 @@ def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub,
'operation': 'CREATE', 'operation': 'CREATE',
'version': 1 'version': 1
} }
asset = Asset(data, uuid4) asset = Asset(data)
tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)], tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)],
data, asset) data, asset)
tx_dict = tx.to_dict() tx_dict = tx.to_dict()
@ -870,7 +851,7 @@ def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub,
def test_create_create_transaction_with_invalid_parameters(user_pub): def test_create_create_transaction_with_invalid_parameters(user_pub):
from bigchaindb.common.transaction import Transaction from bigchaindb.common.transaction import Transaction, AssetLink
with raises(TypeError): with raises(TypeError):
Transaction.create('not a list') Transaction.create('not a list')
@ -884,6 +865,13 @@ def test_create_create_transaction_with_invalid_parameters(user_pub):
Transaction.create([user_pub], [user_pub]) Transaction.create([user_pub], [user_pub])
with raises(ValueError): with raises(ValueError):
Transaction.create([user_pub], [([user_pub],)]) Transaction.create([user_pub], [([user_pub],)])
with raises(TypeError):
Transaction.create([user_pub], [([user_pub], 1)], metadata=[])
with raises(TypeError):
Transaction.create([user_pub],
[([user_pub], 1)],
metadata=None,
asset=AssetLink('mock_asset_link'))
def test_conditions_to_inputs(tx): def test_conditions_to_inputs(tx):
@ -897,10 +885,10 @@ def test_conditions_to_inputs(tx):
def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
user2_cond, user_priv, uuid4): user2_cond, user_priv):
from copy import deepcopy from copy import deepcopy
from bigchaindb.common.crypto import PrivateKey from bigchaindb.common.crypto import PrivateKey
from bigchaindb.common.transaction import Transaction, Asset from bigchaindb.common.transaction import Transaction, AssetLink
from bigchaindb.common.util import serialize from bigchaindb.common.util import serialize
from .util import validate_transaction_model from .util import validate_transaction_model
@ -908,7 +896,7 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
'conditions': [user2_cond.to_dict()], 'conditions': [user2_cond.to_dict()],
'metadata': None, 'metadata': None,
'asset': { 'asset': {
'id': uuid4, 'id': tx.id,
}, },
'fulfillments': [ 'fulfillments': [
{ {
@ -926,8 +914,8 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
'version': 1 'version': 1
} }
inputs = tx.to_inputs([0]) inputs = tx.to_inputs([0])
asset = Asset(None, uuid4) transfer_tx = Transaction.transfer(inputs, [([user2_pub], 1)],
transfer_tx = Transaction.transfer(inputs, [([user2_pub], 1)], asset=asset) asset_link=AssetLink(tx.id))
transfer_tx = transfer_tx.sign([user_priv]) transfer_tx = transfer_tx.sign([user_priv])
transfer_tx = transfer_tx.to_dict() transfer_tx = transfer_tx.to_dict()
@ -949,7 +937,7 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
def test_create_transfer_transaction_multiple_io(user_pub, user_priv, def test_create_transfer_transaction_multiple_io(user_pub, user_priv,
user2_pub, user2_priv, user2_pub, user2_priv,
user3_pub, user2_cond): user3_pub, user2_cond):
from bigchaindb.common.transaction import Transaction, Asset from bigchaindb.common.transaction import Transaction, Asset, AssetLink
asset = Asset() asset = Asset()
tx = Transaction.create([user_pub], [([user_pub], 1), ([user2_pub], 1)], tx = Transaction.create([user_pub], [([user_pub], 1), ([user2_pub], 1)],
@ -986,7 +974,7 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv,
transfer_tx = Transaction.transfer(tx.to_inputs(), transfer_tx = Transaction.transfer(tx.to_inputs(),
[([user2_pub], 1), ([user2_pub], 1)], [([user2_pub], 1), ([user2_pub], 1)],
asset=tx.asset) asset_link=AssetLink(tx.id))
transfer_tx = transfer_tx.sign([user_priv, user2_priv]) transfer_tx = transfer_tx.sign([user_priv, user2_priv])
assert len(transfer_tx.fulfillments) == 2 assert len(transfer_tx.fulfillments) == 2
@ -1003,21 +991,27 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv,
assert expected == transfer_tx assert expected == transfer_tx
def test_create_transfer_with_invalid_parameters(user_pub): def test_create_transfer_with_invalid_parameters(tx, user_pub):
from bigchaindb.common.transaction import Transaction, Asset from bigchaindb.common.transaction import Transaction, Asset, AssetLink
mock_asset_link = AssetLink(tx.id)
with raises(TypeError): with raises(TypeError):
Transaction.transfer({}, [], Asset()) Transaction.transfer({}, [], mock_asset_link)
with raises(ValueError): with raises(ValueError):
Transaction.transfer([], [], Asset()) Transaction.transfer([], [], mock_asset_link)
with raises(TypeError): with raises(TypeError):
Transaction.transfer(['fulfillment'], {}, Asset()) Transaction.transfer(['fulfillment'], {}, mock_asset_link)
with raises(ValueError): with raises(ValueError):
Transaction.transfer(['fulfillment'], [], Asset()) Transaction.transfer(['fulfillment'], [], mock_asset_link)
with raises(ValueError): with raises(ValueError):
Transaction.transfer(['fulfillment'], [user_pub], Asset()) Transaction.transfer(['fulfillment'], [user_pub], mock_asset_link)
with raises(ValueError): with raises(ValueError):
Transaction.transfer(['fulfillment'], [([user_pub],)], Asset()) Transaction.transfer(['fulfillment'], [([user_pub],)], mock_asset_link)
with raises(TypeError):
Transaction.transfer(['fulfillment'], [([user_pub], 1)],
mock_asset_link, metadata=[])
with raises(TypeError):
Transaction.transfer(['fulfillment'], [([user_pub], 1)], Asset())
def test_cant_add_empty_condition(): def test_cant_add_empty_condition():

View File

@ -8,6 +8,7 @@ Tasks:
import os import os
import copy import copy
import random
import pytest import pytest
@ -123,9 +124,12 @@ def signed_create_tx(b, create_tx):
@pytest.fixture @pytest.fixture
def signed_transfer_tx(signed_create_tx, user_pk, user_sk): def signed_transfer_tx(signed_create_tx, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
inputs = signed_create_tx.to_inputs() inputs = signed_create_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)], signed_create_tx.asset) tx = Transaction.transfer(inputs,
[([user_pk], 1)],
AssetLink(signed_create_tx.id))
return tx.sign([user_sk]) return tx.sign([user_sk])
@ -188,8 +192,10 @@ def inputs(user_pk, setup_database):
prev_block_id = g.id prev_block_id = g.id
for block in range(4): for block in range(4):
transactions = [ transactions = [
Transaction.create([b.me], [([user_pk], 1)]).sign([b.me_private]) Transaction.create([b.me], [([user_pk], 1)],
for i in range(10) metadata={'msg': random.random()})
.sign([b.me_private])
for _ in range(10)
] ]
block = b.create_block(transactions) block = b.create_block(transactions)
b.write_block(block) b.write_block(block)
@ -216,9 +222,10 @@ def inputs_shared(user_pk, user2_pk, setup_database):
prev_block_id = g.id prev_block_id = g.id
for block in range(4): for block in range(4):
transactions = [ transactions = [
Transaction.create( Transaction.create([b.me], [user_pk, user2_pk],
[b.me], [user_pk, user2_pk], payload={'i': i}).sign([b.me_private]) metadata={'msg': random.random()})
for i in range(10) .sign([b.me_private])
for _ in range(10)
] ]
block = b.create_block(transactions) block = b.create_block(transactions)
b.write_block(block) b.write_block(block)

View File

@ -1,6 +1,7 @@
from time import sleep from time import sleep
import pytest import pytest
import random
@pytest.mark.skipif(reason='Some tests throw a ResourceWarning that might result in some weird ' @pytest.mark.skipif(reason='Some tests throw a ResourceWarning that might result in some weird '
@ -91,6 +92,7 @@ class TestBigchainApi(object):
def test_get_spent_with_double_spend(self, b, monkeypatch): def test_get_spent_with_double_spend(self, b, monkeypatch):
from bigchaindb.common.exceptions import DoubleSpend from bigchaindb.common.exceptions import DoubleSpend
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
b.create_genesis_block() b.create_genesis_block()
@ -104,14 +106,14 @@ class TestBigchainApi(object):
monkeypatch.setattr('time.time', lambda: 2) monkeypatch.setattr('time.time', lambda: 2)
transfer_tx = Transaction.transfer(tx.to_inputs(), [([b.me], 1)], transfer_tx = Transaction.transfer(tx.to_inputs(), [([b.me], 1)],
tx.asset) AssetLink(tx.id))
transfer_tx = transfer_tx.sign([b.me_private]) transfer_tx = transfer_tx.sign([b.me_private])
block2 = b.create_block([transfer_tx]) block2 = b.create_block([transfer_tx])
b.write_block(block2) b.write_block(block2)
monkeypatch.setattr('time.time', lambda: 3333333333) monkeypatch.setattr('time.time', lambda: 3333333333)
transfer_tx2 = Transaction.transfer(tx.to_inputs(), [([b.me], 1)], transfer_tx2 = Transaction.transfer(tx.to_inputs(), [([b.me], 1)],
tx.asset) AssetLink(tx.id))
transfer_tx2 = transfer_tx2.sign([b.me_private]) transfer_tx2 = transfer_tx2.sign([b.me_private])
block3 = b.create_block([transfer_tx2]) block3 = b.create_block([transfer_tx2])
b.write_block(block3) b.write_block(block3)
@ -157,13 +159,15 @@ class TestBigchainApi(object):
b.create_genesis_block() b.create_genesis_block()
monkeypatch.setattr('time.time', lambda: 1) monkeypatch.setattr('time.time', lambda: 1)
tx1 = Transaction.create([b.me], [([b.me], 1)]) tx1 = Transaction.create([b.me], [([b.me], 1)],
metadata={'msg': random.random()})
tx1 = tx1.sign([b.me_private]) tx1 = tx1.sign([b.me_private])
block1 = b.create_block([tx1]) block1 = b.create_block([tx1])
b.write_block(block1) b.write_block(block1)
monkeypatch.setattr('time.time', lambda: 2222222222) monkeypatch.setattr('time.time', lambda: 2222222222)
tx2 = Transaction.create([b.me], [([b.me], 1)]) tx2 = Transaction.create([b.me], [([b.me], 1)],
metadata={'msg': random.random()})
tx2 = tx2.sign([b.me_private]) tx2 = tx2.sign([b.me_private])
block2 = b.create_block([tx2]) block2 = b.create_block([tx2])
b.write_block(block2) b.write_block(block2)
@ -181,12 +185,14 @@ class TestBigchainApi(object):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_write_transaction(self, b, user_pk, user_sk): def test_write_transaction(self, b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid) input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs() inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)], input_tx.asset) tx = Transaction.transfer(inputs, [([user_pk], 1)],
AssetLink(input_tx.id))
tx = tx.sign([user_sk]) tx = tx.sign([user_sk])
response = b.write_transaction(tx) response = b.write_transaction(tx)
@ -199,12 +205,14 @@ class TestBigchainApi(object):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_read_transaction(self, b, user_pk, user_sk): def test_read_transaction(self, b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid) input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs() inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)], input_tx.asset) tx = Transaction.transfer(inputs, [([user_pk], 1)],
AssetLink(input_tx.id))
tx = tx.sign([user_sk]) tx = tx.sign([user_sk])
b.write_transaction(tx) b.write_transaction(tx)
@ -219,12 +227,14 @@ class TestBigchainApi(object):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_read_transaction_invalid_block(self, b, user_pk, user_sk): def test_read_transaction_invalid_block(self, b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid) input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs() inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)], input_tx.asset) tx = Transaction.transfer(inputs, [([user_pk], 1)],
AssetLink(input_tx.id))
tx = tx.sign([user_sk]) tx = tx.sign([user_sk])
# There's no need to b.write_transaction(tx) to the backlog # There's no need to b.write_transaction(tx) to the backlog
@ -243,12 +253,14 @@ class TestBigchainApi(object):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_read_transaction_invalid_block_and_backlog(self, b, user_pk, user_sk): 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 from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid) input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs() inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)], input_tx.asset) tx = Transaction.transfer(inputs, [([user_pk], 1)],
AssetLink(input_tx.id))
tx = tx.sign([user_sk]) tx = tx.sign([user_sk])
# Make sure there's a copy of tx in the backlog # Make sure there's a copy of tx in the backlog
@ -482,12 +494,14 @@ class TestBigchainApi(object):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_assign_transaction_one_node(self, b, user_pk, user_sk): def test_assign_transaction_one_node(self, b, user_pk, user_sk):
from bigchaindb.backend import query from bigchaindb.backend import query
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid) input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs() inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)], input_tx.asset) tx = Transaction.transfer(inputs, [([user_pk], 1)],
AssetLink(input_tx.id))
tx = tx.sign([user_sk]) tx = tx.sign([user_sk])
b.write_transaction(tx) b.write_transaction(tx)
@ -501,6 +515,7 @@ class TestBigchainApi(object):
def test_assign_transaction_multiple_nodes(self, b, user_pk, user_sk): def test_assign_transaction_multiple_nodes(self, b, user_pk, user_sk):
from bigchaindb.backend import query from bigchaindb.backend import query
from bigchaindb.common.crypto import generate_key_pair from bigchaindb.common.crypto import generate_key_pair
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
# create 5 federation nodes # create 5 federation nodes
@ -512,7 +527,9 @@ class TestBigchainApi(object):
input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid) input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs() inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)], input_tx.asset) tx = Transaction.transfer(inputs, [([user_pk], 1)],
asset_link=AssetLink(input_tx.id),
metadata={'msg': random.random()})
tx = tx.sign([user_sk]) tx = tx.sign([user_sk])
b.write_transaction(tx) b.write_transaction(tx)
@ -527,7 +544,7 @@ class TestBigchainApi(object):
def test_non_create_input_not_found(self, b, user_pk): def test_non_create_input_not_found(self, b, user_pk):
from cryptoconditions import Ed25519Fulfillment from cryptoconditions import Ed25519Fulfillment
from bigchaindb.common.exceptions import TransactionDoesNotExist from bigchaindb.common.exceptions import TransactionDoesNotExist
from bigchaindb.common.transaction import (Fulfillment, Asset, from bigchaindb.common.transaction import (AssetLink, Fulfillment,
TransactionLink) TransactionLink)
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb import Bigchain from bigchaindb import Bigchain
@ -536,7 +553,8 @@ class TestBigchainApi(object):
fulfillment = Fulfillment(Ed25519Fulfillment(public_key=user_pk), fulfillment = Fulfillment(Ed25519Fulfillment(public_key=user_pk),
[user_pk], [user_pk],
TransactionLink('somethingsomething', 0)) TransactionLink('somethingsomething', 0))
tx = Transaction.transfer([fulfillment], [([user_pk], 1)], Asset()) tx = Transaction.transfer([fulfillment], [([user_pk], 1)],
AssetLink('mock_asset_link'))
with pytest.raises(TransactionDoesNotExist): with pytest.raises(TransactionDoesNotExist):
tx.validate(Bigchain()) tx.validate(Bigchain())
@ -546,8 +564,9 @@ class TestBigchainApi(object):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
for _ in range(4): for _ in range(4):
tx = Transaction.create([b.me], tx = Transaction.create([b.me], [([user_pk], 1)],
[([user_pk], 1)]).sign([b.me_private]) metadata={'msg': random.random()}) \
.sign([b.me_private])
b.write_transaction(tx) b.write_transaction(tx)
assert query.count_backlog(b.connection) == 4 assert query.count_backlog(b.connection) == 4
@ -585,6 +604,7 @@ class TestTransactionValidation(object):
def test_non_create_valid_input_wrong_owner(self, b, user_pk): def test_non_create_valid_input_wrong_owner(self, b, user_pk):
from bigchaindb.common.crypto import generate_key_pair from bigchaindb.common.crypto import generate_key_pair
from bigchaindb.common.exceptions import InvalidSignature from bigchaindb.common.exceptions import InvalidSignature
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_owned_ids(user_pk).pop()
@ -592,7 +612,7 @@ class TestTransactionValidation(object):
sk, pk = generate_key_pair() sk, pk = generate_key_pair()
tx = Transaction.create([pk], [([user_pk], 1)]) tx = Transaction.create([pk], [([user_pk], 1)])
tx.operation = 'TRANSFER' tx.operation = 'TRANSFER'
tx.asset = input_transaction.asset tx.asset = AssetLink(input_transaction.id)
tx.fulfillments[0].tx_input = input_tx tx.fulfillments[0].tx_input = input_tx
with pytest.raises(InvalidSignature): with pytest.raises(InvalidSignature):
@ -629,13 +649,14 @@ class TestTransactionValidation(object):
def test_valid_non_create_transaction_after_block_creation(self, b, def test_valid_non_create_transaction_after_block_creation(self, b,
user_pk, user_pk,
user_sk): user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop() input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid) input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs() inputs = input_tx.to_inputs()
transfer_tx = Transaction.transfer(inputs, [([user_pk], 1)], transfer_tx = Transaction.transfer(inputs, [([user_pk], 1)],
input_tx.asset) AssetLink(input_tx.id))
transfer_tx = transfer_tx.sign([user_sk]) transfer_tx = transfer_tx.sign([user_sk])
assert transfer_tx == b.validate_transaction(transfer_tx) assert transfer_tx == b.validate_transaction(transfer_tx)
@ -653,6 +674,7 @@ class TestTransactionValidation(object):
def test_transaction_not_in_valid_block(self, b, user_pk, user_sk): def test_transaction_not_in_valid_block(self, b, user_pk, user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.exceptions import TransactionNotInValidBlock 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_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid) input_tx = b.get_transaction(input_tx.txid)
@ -660,7 +682,7 @@ class TestTransactionValidation(object):
# create a transaction that's valid but not in a voted valid block # create a transaction that's valid but not in a voted valid block
transfer_tx = Transaction.transfer(inputs, [([user_pk], 1)], transfer_tx = Transaction.transfer(inputs, [([user_pk], 1)],
input_tx.asset) AssetLink(input_tx.id))
transfer_tx = transfer_tx.sign([user_sk]) transfer_tx = transfer_tx.sign([user_sk])
assert transfer_tx == b.validate_transaction(transfer_tx) assert transfer_tx == b.validate_transaction(transfer_tx)
@ -672,7 +694,7 @@ class TestTransactionValidation(object):
# create transaction with the undecided input # create transaction with the undecided input
tx_invalid = Transaction.transfer(transfer_tx.to_inputs(), tx_invalid = Transaction.transfer(transfer_tx.to_inputs(),
[([user_pk], 1)], [([user_pk], 1)],
transfer_tx.asset) AssetLink(transfer_tx.asset.id))
tx_invalid = tx_invalid.sign([user_sk]) tx_invalid = tx_invalid.sign([user_sk])
with pytest.raises(TransactionNotInValidBlock): with pytest.raises(TransactionNotInValidBlock):
@ -766,13 +788,15 @@ class TestMultipleInputs(object):
def test_transfer_single_owner_single_input(self, b, inputs, user_pk, def test_transfer_single_owner_single_input(self, b, inputs, user_pk,
user_sk): user_sk):
from bigchaindb.common import crypto from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair() user2_sk, user2_pk = crypto.generate_key_pair()
tx_link = b.get_owned_ids(user_pk).pop() tx_link = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(tx_link.txid) input_tx = b.get_transaction(tx_link.txid)
inputs = input_tx.to_inputs() inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user2_pk], 1)], input_tx.asset) tx = Transaction.transfer(inputs, [([user2_pk], 1)],
AssetLink(input_tx.id))
tx = tx.sign([user_sk]) tx = tx.sign([user_sk])
# validate transaction # validate transaction
@ -785,6 +809,7 @@ class TestMultipleInputs(object):
user_pk, user_pk,
inputs): inputs):
from bigchaindb.common import crypto from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair() user2_sk, user2_pk = crypto.generate_key_pair()
@ -794,7 +819,8 @@ class TestMultipleInputs(object):
tx_link = owned_inputs.pop() tx_link = owned_inputs.pop()
input_tx = b.get_transaction(tx_link.txid) input_tx = b.get_transaction(tx_link.txid)
tx = Transaction.transfer(input_tx.to_inputs(), tx = Transaction.transfer(input_tx.to_inputs(),
[([user2_pk, user3_pk], 1)], input_tx.asset) [([user2_pk, user3_pk], 1)],
AssetLink(input_tx.id))
tx = tx.sign([user_sk]) tx = tx.sign([user_sk])
assert b.is_valid_transaction(tx) == tx assert b.is_valid_transaction(tx) == tx
@ -806,6 +832,7 @@ class TestMultipleInputs(object):
user_sk, user_sk,
user_pk): user_pk):
from bigchaindb.common import crypto from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair() user2_sk, user2_pk = crypto.generate_key_pair()
@ -825,7 +852,7 @@ class TestMultipleInputs(object):
inputs = input_tx.to_inputs() inputs = input_tx.to_inputs()
transfer_tx = Transaction.transfer(inputs, [([user3_pk], 1)], transfer_tx = Transaction.transfer(inputs, [([user3_pk], 1)],
input_tx.asset) AssetLink(input_tx.id))
transfer_tx = transfer_tx.sign([user_sk, user2_sk]) transfer_tx = transfer_tx.sign([user_sk, user2_sk])
# validate transaction # validate transaction
@ -838,6 +865,7 @@ class TestMultipleInputs(object):
user_sk, user_sk,
user_pk): user_pk):
from bigchaindb.common import crypto from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair() user2_sk, user2_pk = crypto.generate_key_pair()
@ -858,7 +886,8 @@ class TestMultipleInputs(object):
tx_input = b.get_transaction(tx_link.txid) tx_input = b.get_transaction(tx_link.txid)
tx = Transaction.transfer(tx_input.to_inputs(), tx = Transaction.transfer(tx_input.to_inputs(),
[([user3_pk, user4_pk], 1)], tx_input.asset) [([user3_pk, user4_pk], 1)],
AssetLink(tx_input.id))
tx = tx.sign([user_sk, user2_sk]) tx = tx.sign([user_sk, user2_sk])
assert b.is_valid_transaction(tx) == tx assert b.is_valid_transaction(tx) == tx
@ -868,7 +897,7 @@ class TestMultipleInputs(object):
@pytest.mark.usefixtures('setup_database') @pytest.mark.usefixtures('setup_database')
def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_pk): def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_pk):
from bigchaindb.common import crypto from bigchaindb.common import crypto
from bigchaindb.common.transaction import TransactionLink from bigchaindb.common.transaction import AssetLink, TransactionLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair() user2_sk, user2_pk = crypto.generate_key_pair()
@ -883,7 +912,8 @@ class TestMultipleInputs(object):
assert owned_inputs_user1 == [TransactionLink(tx.id, 0)] assert owned_inputs_user1 == [TransactionLink(tx.id, 0)]
assert owned_inputs_user2 == [] assert owned_inputs_user2 == []
tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)], tx.asset) tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
AssetLink(tx.id))
tx = tx.sign([user_sk]) tx = tx.sign([user_sk])
block = b.create_block([tx]) block = b.create_block([tx])
b.write_block(block) b.write_block(block)
@ -898,7 +928,7 @@ class TestMultipleInputs(object):
user_sk, user_sk,
user_pk): user_pk):
from bigchaindb.common import crypto from bigchaindb.common import crypto
from bigchaindb.common.transaction import TransactionLink from bigchaindb.common.transaction import AssetLink, TransactionLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
genesis = b.create_genesis_block() genesis = b.create_genesis_block()
@ -921,7 +951,7 @@ class TestMultipleInputs(object):
# NOTE: The transaction itself is valid, still will mark the block # NOTE: The transaction itself is valid, still will mark the block
# as invalid to mock the behavior. # as invalid to mock the behavior.
tx_invalid = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)], tx_invalid = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
tx.asset) AssetLink(tx.id))
tx_invalid = tx_invalid.sign([user_sk]) tx_invalid = tx_invalid.sign([user_sk])
block = b.create_block([tx_invalid]) block = b.create_block([tx_invalid])
b.write_block(block) b.write_block(block)
@ -941,7 +971,8 @@ class TestMultipleInputs(object):
def test_get_owned_ids_single_tx_multiple_outputs(self, b, user_sk, def test_get_owned_ids_single_tx_multiple_outputs(self, b, user_sk,
user_pk): user_pk):
from bigchaindb.common import crypto from bigchaindb.common import crypto
from bigchaindb.common.transaction import TransactionLink, Asset from bigchaindb.common.transaction import (TransactionLink, Asset,
AssetLink)
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair() user2_sk, user2_pk = crypto.generate_key_pair()
@ -967,7 +998,7 @@ class TestMultipleInputs(object):
# transfer divisible asset divided in two outputs # transfer divisible asset divided in two outputs
tx_transfer = Transaction.transfer(tx_create.to_inputs(), tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([user2_pk], 1), ([user2_pk], 1)], [([user2_pk], 1), ([user2_pk], 1)],
asset=tx_create.asset) asset_link=AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
block = b.create_block([tx_transfer_signed]) block = b.create_block([tx_transfer_signed])
b.write_block(block) b.write_block(block)
@ -981,7 +1012,7 @@ class TestMultipleInputs(object):
@pytest.mark.usefixtures('setup_database') @pytest.mark.usefixtures('setup_database')
def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk): def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk):
from bigchaindb.common import crypto from bigchaindb.common import crypto
from bigchaindb.common.transaction import TransactionLink from bigchaindb.common.transaction import AssetLink, TransactionLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair() user2_sk, user2_pk = crypto.generate_key_pair()
@ -999,7 +1030,8 @@ class TestMultipleInputs(object):
assert owned_inputs_user1 == owned_inputs_user2 assert owned_inputs_user1 == owned_inputs_user2
assert owned_inputs_user1 == expected_owned_inputs_user1 assert owned_inputs_user1 == expected_owned_inputs_user1
tx = Transaction.transfer(tx.to_inputs(), [([user3_pk], 1)], tx.asset) tx = Transaction.transfer(tx.to_inputs(), [([user3_pk], 1)],
AssetLink(tx.id))
tx = tx.sign([user_sk, user2_sk]) tx = tx.sign([user_sk, user2_sk])
block = b.create_block([tx]) block = b.create_block([tx])
b.write_block(block) b.write_block(block)
@ -1012,6 +1044,7 @@ class TestMultipleInputs(object):
@pytest.mark.usefixtures('setup_database') @pytest.mark.usefixtures('setup_database')
def test_get_spent_single_tx_single_output(self, b, user_sk, user_pk): def test_get_spent_single_tx_single_output(self, b, user_sk, user_pk):
from bigchaindb.common import crypto from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair() user2_sk, user2_pk = crypto.generate_key_pair()
@ -1030,7 +1063,8 @@ class TestMultipleInputs(object):
assert spent_inputs_user1 is None assert spent_inputs_user1 is None
# create a transaction and block # create a transaction and block
tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)], tx.asset) tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
AssetLink(tx.id))
tx = tx.sign([user_sk]) tx = tx.sign([user_sk])
block = b.create_block([tx]) block = b.create_block([tx])
b.write_block(block) b.write_block(block)
@ -1041,6 +1075,7 @@ class TestMultipleInputs(object):
@pytest.mark.usefixtures('setup_database') @pytest.mark.usefixtures('setup_database')
def test_get_spent_single_tx_single_output_invalid_block(self, b, user_sk, user_pk): def test_get_spent_single_tx_single_output_invalid_block(self, b, user_sk, user_pk):
from bigchaindb.common import crypto from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
genesis = b.create_genesis_block() genesis = b.create_genesis_block()
@ -1066,7 +1101,8 @@ class TestMultipleInputs(object):
assert spent_inputs_user1 is None assert spent_inputs_user1 is None
# create a transaction and block # create a transaction and block
tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)], tx.asset) tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
AssetLink(tx.id))
tx = tx.sign([user_sk]) tx = tx.sign([user_sk])
block = b.create_block([tx]) block = b.create_block([tx])
b.write_block(block) b.write_block(block)
@ -1084,8 +1120,8 @@ class TestMultipleInputs(object):
@pytest.mark.usefixtures('setup_database') @pytest.mark.usefixtures('setup_database')
def test_get_spent_single_tx_multiple_outputs(self, b, user_sk, user_pk): def test_get_spent_single_tx_multiple_outputs(self, b, user_sk, user_pk):
from bigchaindb.common import crypto from bigchaindb.common import crypto
from bigchaindb.common.transaction import Asset, AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset
# create a new users # create a new users
user2_sk, user2_pk = crypto.generate_key_pair() user2_sk, user2_pk = crypto.generate_key_pair()
@ -1110,7 +1146,7 @@ class TestMultipleInputs(object):
# transfer the first 2 inputs # transfer the first 2 inputs
tx_transfer = Transaction.transfer(tx_create.to_inputs()[:2], tx_transfer = Transaction.transfer(tx_create.to_inputs()[:2],
[([user2_pk], 1), ([user2_pk], 1)], [([user2_pk], 1), ([user2_pk], 1)],
asset=tx_create.asset) asset_link=AssetLink(tx_create.id))
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
block = b.create_block([tx_transfer_signed]) block = b.create_block([tx_transfer_signed])
b.write_block(block) b.write_block(block)
@ -1126,8 +1162,8 @@ class TestMultipleInputs(object):
@pytest.mark.usefixtures('setup_database') @pytest.mark.usefixtures('setup_database')
def test_get_spent_multiple_owners(self, b, user_sk, user_pk): def test_get_spent_multiple_owners(self, b, user_sk, user_pk):
import random
from bigchaindb.common import crypto from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair() user2_sk, user2_pk = crypto.generate_key_pair()
@ -1151,7 +1187,8 @@ class TestMultipleInputs(object):
# create a transaction # create a transaction
tx = Transaction.transfer(transactions[0].to_inputs(), tx = Transaction.transfer(transactions[0].to_inputs(),
[([user3_pk], 1)], transactions[0].asset) [([user3_pk], 1)],
AssetLink(transactions[0].id))
tx = tx.sign([user_sk, user2_sk]) tx = tx.sign([user_sk, user2_sk])
block = b.create_block([tx]) block = b.create_block([tx])
b.write_block(block) b.write_block(block)

View File

@ -1,3 +1,4 @@
import random
import time import time
from unittest.mock import patch from unittest.mock import patch
@ -44,8 +45,9 @@ def test_create_block(b, user_pk):
block_maker = BlockPipeline() block_maker = BlockPipeline()
for i in range(100): for _ in range(100):
tx = Transaction.create([b.me], [([user_pk], 1)]) tx = Transaction.create([b.me], [([user_pk], 1)],
metadata={'msg': random.random()})
tx = tx.sign([b.me_private]) tx = tx.sign([b.me_private])
block_maker.create(tx) block_maker.create(tx)
@ -63,8 +65,9 @@ def test_write_block(b, user_pk):
block_maker = BlockPipeline() block_maker = BlockPipeline()
txs = [] txs = []
for i in range(100): for _ in range(100):
tx = Transaction.create([b.me], [([user_pk], 1)]) tx = Transaction.create([b.me], [([user_pk], 1)],
metadata={'msg': random.random()})
tx = tx.sign([b.me_private]) tx = tx.sign([b.me_private])
txs.append(tx) txs.append(tx)
@ -83,8 +86,9 @@ def test_duplicate_transaction(b, user_pk):
block_maker = block.BlockPipeline() block_maker = block.BlockPipeline()
txs = [] txs = []
for i in range(10): for _ in range(10):
tx = Transaction.create([b.me], [([user_pk], 1)]) tx = Transaction.create([b.me], [([user_pk], 1)],
metadata={'msg': random.random()})
tx = tx.sign([b.me_private]) tx = tx.sign([b.me_private])
txs.append(tx) txs.append(tx)
@ -114,7 +118,8 @@ def test_delete_tx(b, user_pk):
from bigchaindb.pipelines.block import BlockPipeline from bigchaindb.pipelines.block import BlockPipeline
block_maker = BlockPipeline() block_maker = BlockPipeline()
for i in range(100): for i in range(100):
tx = Transaction.create([b.me], [([user_pk], 1)]) tx = Transaction.create([b.me], [([user_pk], 1)],
metadata={'msg': random.random()})
tx = tx.sign([b.me_private]) tx = tx.sign([b.me_private])
block_maker.create(tx) block_maker.create(tx)
# make sure the tx appears in the backlog # make sure the tx appears in the backlog
@ -150,10 +155,8 @@ def test_start(create_pipeline):
@pytest.mark.usefixtures('setup_database') @pytest.mark.usefixtures('setup_database')
def test_full_pipeline(b, user_pk): def test_full_pipeline(b, user_pk):
import random
from bigchaindb.backend import query
from bigchaindb.models import Block, Transaction from bigchaindb.models import Block, Transaction
from bigchaindb.pipelines.block import create_pipeline, get_changefeed from bigchaindb.pipelines.block import create_pipeline
outpipe = Pipe() outpipe = Pipe()
@ -166,7 +169,7 @@ def test_full_pipeline(b, user_pk):
number_assigned_to_others = 0 number_assigned_to_others = 0
for i in range(100): for i in range(100):
tx = Transaction.create([b.me], [([user_pk], 1)], tx = Transaction.create([b.me], [([user_pk], 1)],
{'msg': random.random()}) metadata={'msg': random.random()})
tx = tx.sign([b.me_private]) tx = tx.sign([b.me_private])
tx = tx.to_dict() tx = tx.to_dict()

View File

@ -1,9 +1,10 @@
import os
import random
from bigchaindb import Bigchain from bigchaindb import Bigchain
from bigchaindb.pipelines import stale from bigchaindb.pipelines import stale
from multipipes import Pipe, Pipeline from multipipes import Pipe, Pipeline
from unittest.mock import patch from unittest.mock import patch
from bigchaindb import config_utils from bigchaindb import config_utils
import os
import pytest import pytest
@ -89,7 +90,8 @@ def test_full_pipeline(monkeypatch, user_pk):
monkeypatch.setattr('time.time', lambda: 1) monkeypatch.setattr('time.time', lambda: 1)
for i in range(100): for i in range(100):
tx = Transaction.create([b.me], [([user_pk], 1)]) tx = Transaction.create([b.me], [([user_pk], 1)],
metadata={'msg': random.random()})
tx = tx.sign([b.me_private]) tx = tx.sign([b.me_private])
original_txc.append(tx.to_dict()) original_txc.append(tx.to_dict())

View File

@ -1,3 +1,4 @@
import random
import time import time
from unittest.mock import patch from unittest.mock import patch
@ -5,9 +6,11 @@ from multipipes import Pipe, Pipeline
import pytest import pytest
# TODO: dummy_tx and dummy_block could be fixtures
def dummy_tx(b): def dummy_tx(b):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
tx = Transaction.create([b.me], [([b.me], 1)]) tx = Transaction.create([b.me], [([b.me], 1)],
metadata={'msg': random.random()})
tx = tx.sign([b.me_private]) tx = tx.sign([b.me_private])
return tx return tx
@ -275,6 +278,7 @@ def test_valid_block_voting_with_create_transaction(b, monkeypatch):
def test_valid_block_voting_with_transfer_transactions(monkeypatch, b): def test_valid_block_voting_with_transfer_transactions(monkeypatch, b):
from bigchaindb.backend import query from bigchaindb.backend import query
from bigchaindb.common import crypto, util from bigchaindb.common import crypto, util
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.pipelines import vote from bigchaindb.pipelines import vote
@ -292,7 +296,7 @@ def test_valid_block_voting_with_transfer_transactions(monkeypatch, b):
# create a `TRANSFER` transaction # create a `TRANSFER` transaction
test_user2_priv, test_user2_pub = crypto.generate_key_pair() test_user2_priv, test_user2_pub = crypto.generate_key_pair()
tx2 = Transaction.transfer(tx.to_inputs(), [([test_user2_pub], 1)], tx2 = Transaction.transfer(tx.to_inputs(), [([test_user2_pub], 1)],
tx.asset) AssetLink(tx.id))
tx2 = tx2.sign([test_user_priv]) tx2 = tx2.sign([test_user_priv])
monkeypatch.setattr('time.time', lambda: 2222222222) monkeypatch.setattr('time.time', lambda: 2222222222)

View File

@ -124,13 +124,15 @@ def test_post_invalid_transaction(client, exc, msg, monkeypatch):
def test_post_transfer_transaction_endpoint(b, client, user_pk, user_sk): def test_post_transfer_transaction_endpoint(b, client, user_pk, user_sk):
sk, pk = crypto.generate_key_pair() sk, pk = crypto.generate_key_pair()
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import AssetLink
user_priv, user_pub = crypto.generate_key_pair() user_priv, user_pub = crypto.generate_key_pair()
input_valid = b.get_owned_ids(user_pk).pop() input_valid = b.get_owned_ids(user_pk).pop()
create_tx = b.get_transaction(input_valid.txid) create_tx = b.get_transaction(input_valid.txid)
transfer_tx = Transaction.transfer(create_tx.to_inputs(), transfer_tx = Transaction.transfer(create_tx.to_inputs(),
[([user_pub], 1)], create_tx.asset) [([user_pub], 1)],
AssetLink(create_tx.id))
transfer_tx = transfer_tx.sign([user_sk]) transfer_tx = transfer_tx.sign([user_sk])
res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict())) res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict()))
@ -142,13 +144,15 @@ def test_post_transfer_transaction_endpoint(b, client, user_pk, user_sk):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_post_invalid_transfer_transaction_returns_400(b, client, user_pk, user_sk): def test_post_invalid_transfer_transaction_returns_400(b, client, user_pk, user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.transaction import AssetLink
user_priv, user_pub = crypto.generate_key_pair() user_priv, user_pub = crypto.generate_key_pair()
input_valid = b.get_owned_ids(user_pk).pop() input_valid = b.get_owned_ids(user_pk).pop()
create_tx = b.get_transaction(input_valid.txid) create_tx = b.get_transaction(input_valid.txid)
transfer_tx = Transaction.transfer(create_tx.to_inputs(), transfer_tx = Transaction.transfer(create_tx.to_inputs(),
[([user_pub], 1)], create_tx.asset) [([user_pub], 1)],
AssetLink(create_tx.id))
res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict())) res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict()))
assert res.status_code == 400 assert res.status_code == 400