Remove Asset and AssetLink (#982)

* Remove asset.validate_asset and move its validation checks to other areas

* Move Asset.get_asset_id to Transaction

* Remove Asset and AssetLink models

* Add test against creating TRANSFER transactions with bad asset
This commit is contained in:
Brett Sun 2016-12-22 10:19:21 +01:00 committed by GitHub
parent 44391da94a
commit 9319583ab4
13 changed files with 322 additions and 664 deletions

View File

@ -221,9 +221,12 @@ class Condition(object):
"""
if not isinstance(owners_after, list) and owners_after is not None:
raise TypeError('`owners_after` must be a list instance or None')
if not isinstance(amount, int):
raise TypeError('`amount` must be an int')
if amount < 1:
raise AmountError('`amount` must be greater than 0')
self.fulfillment = fulfillment
# TODO: Not sure if we should validate for value here
self.amount = amount
self.owners_after = owners_after
@ -378,147 +381,6 @@ class Condition(object):
return cls(fulfillment, cond['owners_after'], cond['amount'])
class Asset(object):
"""An Asset is a fungible unit to spend and lock with Transactions.
Attributes:
data (dict): A dictionary of data that can be added to an Asset.
"""
def __init__(self, data=None):
"""An Asset is not required to contain any extra data from outside."""
self.data = data
self.validate_asset()
def __eq__(self, other):
try:
other_dict = other.to_dict()
except AttributeError:
return False
return self.to_dict() == other_dict
def to_dict(self):
"""Transforms the object to a Python dictionary.
Returns:
(dict): The Asset object as an alternative serialization
format.
"""
return {
'data': self.data,
}
@classmethod
def from_dict(cls, asset):
"""Transforms a Python dictionary to an Asset object.
Args:
asset (dict): The dictionary to be serialized.
Returns:
:class:`~bigchaindb.common.transaction.Asset`
"""
return cls(asset.get('data'))
@staticmethod
def get_asset_id(transactions):
"""Get the asset id from a list of :class:`~.Transactions`.
This is useful when we want to check if the multiple inputs of a
transaction are related to the same asset id.
Args:
transactions (:obj:`list` of :class:`~bigchaindb.common.
transaction.Transaction`): A list of Transactions.
Usually input Transactions that should have a matching
asset ID.
Returns:
str: ID of the asset.
Raises:
:exc:`AssetIdMismatch`: If the inputs are related to different
assets.
"""
if not isinstance(transactions, list):
transactions = [transactions]
# create a set of the transactions' asset ids
asset_ids = {tx.id if tx.operation == Transaction.CREATE else tx.asset.id
for tx in transactions}
# check that all the transasctions have the same asset id
if len(asset_ids) > 1:
raise AssetIdMismatch(('All inputs of all transactions passed'
' need to have the same asset id'))
return asset_ids.pop()
def validate_asset(self, amount=None):
"""Validates the asset"""
if self.data is not None and not isinstance(self.data, dict):
raise TypeError('`data` must be a dict instance or None')
# If the amount is supplied we can perform extra validations to
# the asset
if amount is not None:
if not isinstance(amount, int):
raise TypeError('`amount` must be an int')
if amount < 1:
raise AmountError('`amount` must be greater than 0')
class AssetLink(object):
"""An object for unidirectional linking to a Asset.
"""
def __init__(self, asset_id=None):
"""Used to point to a specific Asset.
Args:
asset_id (str): The ID of an asset to link to.
"""
self.id = asset_id
def __bool__(self):
return self.id is not None
def __eq__(self, other):
return isinstance(other, AssetLink) and \
self.to_dict() == other.to_dict()
@classmethod
def from_dict(cls, link):
"""Transforms a Python dictionary to a AssetLink object.
Args:
link (dict): The link to be transformed.
Returns:
:class:`~bigchaindb.common.transaction.AssetLink`
"""
try:
return cls(link['id'])
except TypeError:
return cls()
def to_dict(self):
"""Transforms the object to a Python dictionary.
Returns:
(dict|None): The link as an alternative serialization format.
Returns None if the link is empty (i.e. is not linking to
an asset).
"""
if self.id is None:
return None
else:
return {
'id': self.id
}
class Transaction(object):
"""A Transaction is used to create and transfer assets.
@ -533,10 +395,10 @@ class Transaction(object):
spend.
conditions (:obj:`list` of :class:`~bigchaindb.common.
transaction.Condition`, optional): Define the assets to lock.
asset (:class:`~.Asset`|:class:`~.AssetLink`): Asset or Asset link
associated with this Transaction. ``CREATE`` and ``GENESIS``
Transactions require an Asset while ``TRANSFER`` Transactions
require an AssetLink.
asset (dict): Asset payload for this Transaction. ``CREATE`` and
``GENESIS`` Transactions require a dict with a ``data``
property while ``TRANSFER`` Transactions require a dict with a
``id`` property.
metadata (dict):
Metadata to be stored along with the Transaction.
version (int): Defines the version number of a Transaction.
@ -557,35 +419,33 @@ class Transaction(object):
Args:
operation (str): Defines the operation of the Transaction.
asset (:class:`~.Asset`|:class:`~.AssetLink`): An Asset to be
created or an AssetLink linking an asset to be transferred.
asset (dict): Asset payload for this Transaction.
fulfillments (:obj:`list` of :class:`~bigchaindb.common.
transaction.Fulfillment`, optional): Define the assets to
spend.
conditions (:obj:`list` of :class:`~bigchaindb.common.
transaction.Condition`, optional): Define the assets to
lock.
metadata (dict):
Metadata to be stored along with the Transaction.
metadata (dict): Metadata to be stored along with the
Transaction.
version (int): Defines the version number of a Transaction.
"""
if operation not in Transaction.ALLOWED_OPERATIONS:
allowed_ops = ', '.join(self.__class__.ALLOWED_OPERATIONS)
raise ValueError('`operation` must be one of {}'
.format(allowed_ops))
# Assets for 'CREATE' and 'GENESIS' operations must be None or of Asset
# type and Assets for 'TRANSFER' operations must be of AssetLink type.
# Asset payloads for 'CREATE' and 'GENESIS' operations must be None or
# dicts holding a `data` property. Asset payloads for 'TRANSFER'
# operations must be dicts holding an `id` property.
if (operation in [Transaction.CREATE, Transaction.GENESIS] and
asset is not None and
not isinstance(asset, Asset)):
raise TypeError(("`asset` must be an Asset instance for "
"'{}' Transactions".format(operation)))
asset is not None and not (isinstance(asset, dict) and 'data' in asset)):
raise TypeError(('`asset` must be None or a dict holding a `data` '
" property instance for '{}' Transactions".format(operation)))
elif (operation == Transaction.TRANSFER and
not (asset and isinstance(asset, AssetLink))):
raise TypeError(("`asset` must be an valid AssetLink instance for "
"'TRANSFER' Transactions".format(operation)))
not (isinstance(asset, dict) and 'id' in asset)):
raise TypeError(('`asset` must be a dict holding an `id` property '
"for 'TRANSFER' Transactions".format(operation)))
if conditions and not isinstance(conditions, list):
raise TypeError('`conditions` must be a list instance or None')
@ -598,20 +458,11 @@ class Transaction(object):
self.version = version if version is not None else self.VERSION
self.operation = operation
self.asset = asset or Asset()
self.asset = asset
self.conditions = conditions or []
self.fulfillments = fulfillments or []
self.metadata = metadata
# validate asset
# we know that each transaction relates to a single asset
# we can sum the amount of all the conditions
# for transactions other then CREATE we only have an id so there is
# nothing we can validate
if self.operation == self.CREATE:
amount = sum([condition.amount for condition in self.conditions])
self.asset.validate_asset(amount=amount)
@classmethod
def create(cls, owners_before, owners_after, metadata=None, asset=None):
"""A simple way to generate a `CREATE` transaction.
@ -631,10 +482,10 @@ class Transaction(object):
represent the creators of this asset.
owners_after (:obj:`list` of :obj:`str`): A list of keys that
represent the receivers of this Transaction.
metadata (dict): Python dictionary to be stored along with the
metadata (dict): The metadata to be stored along with the
Transaction.
asset (:class:`~bigchaindb.common.transaction.Asset`): An Asset
to be created in this Transaction.
asset (dict): The metadata associated with the asset that will
be created in this Transaction.
Returns:
:class:`~bigchaindb.common.transaction.Transaction`
@ -647,6 +498,8 @@ class Transaction(object):
raise ValueError('`owners_before` list cannot be empty')
if len(owners_after) == 0:
raise ValueError('`owners_after` list cannot be empty')
if not (asset is None or isinstance(asset, dict)):
raise TypeError('`asset` must be a dict or None')
fulfillments = []
conditions = []
@ -663,10 +516,10 @@ class Transaction(object):
# generate fulfillments
fulfillments.append(Fulfillment.generate(owners_before))
return cls(cls.CREATE, asset, fulfillments, conditions, metadata)
return cls(cls.CREATE, {'data': asset}, fulfillments, conditions, metadata)
@classmethod
def transfer(cls, inputs, owners_after, asset_link, metadata=None):
def transfer(cls, inputs, owners_after, asset_id, metadata=None):
"""A simple way to generate a `TRANSFER` transaction.
Note:
@ -696,9 +549,8 @@ class Transaction(object):
generate.
owners_after (:obj:`list` of :obj:`str`): A list of keys that
represent the receivers of this Transaction.
asset_link (:class:`~bigchaindb.common.transaction.AssetLink`):
An AssetLink linking an asset to be transferred in this
Transaction.
asset_id (str): The asset ID of the asset to be transferred in
this Transaction.
metadata (dict): Python dictionary to be stored along with the
Transaction.
@ -713,6 +565,8 @@ class Transaction(object):
raise TypeError('`owners_after` must be a list instance')
if len(owners_after) == 0:
raise ValueError('`owners_after` list cannot be empty')
if not isinstance(asset_id, str):
raise TypeError('`asset_id` must be a string')
conditions = []
for owner_after in owners_after:
@ -724,7 +578,7 @@ class Transaction(object):
conditions.append(Condition.generate(pub_keys, amount))
inputs = deepcopy(inputs)
return cls(cls.TRANSFER, asset_link, inputs, conditions, metadata)
return cls(cls.TRANSFER, {'id': asset_id}, inputs, conditions, metadata)
def __eq__(self, other):
try:
@ -1071,7 +925,7 @@ class Transaction(object):
in self.conditions],
'operation': str(self.operation),
'metadata': self.metadata,
'asset': self.asset.to_dict(),
'asset': self.asset,
'version': self.version,
}
@ -1125,6 +979,40 @@ class Transaction(object):
tx = Transaction._remove_signatures(self.to_dict())
return Transaction._to_str(tx)
@staticmethod
def get_asset_id(transactions):
"""Get the asset id from a list of :class:`~.Transactions`.
This is useful when we want to check if the multiple inputs of a
transaction are related to the same asset id.
Args:
transactions (:obj:`list` of :class:`~bigchaindb.common.
transaction.Transaction`): A list of Transactions.
Usually input Transactions that should have a matching
asset ID.
Returns:
str: ID of the asset.
Raises:
:exc:`AssetIdMismatch`: If the inputs are related to different
assets.
"""
if not isinstance(transactions, list):
transactions = [transactions]
# create a set of the transactions' asset ids
asset_ids = {tx.id if tx.operation == Transaction.CREATE else tx.asset['id']
for tx in transactions}
# check that all the transasctions have the same asset id
if len(asset_ids) > 1:
raise AssetIdMismatch(('All inputs of all transactions passed'
' need to have the same asset id'))
return asset_ids.pop()
@staticmethod
def validate_structure(tx_body):
"""Validate the transaction ID of a transaction
@ -1163,10 +1051,6 @@ class Transaction(object):
in tx['fulfillments']]
conditions = [Condition.from_dict(condition) for condition
in tx['conditions']]
if tx['operation'] in [cls.CREATE, cls.GENESIS]:
asset = Asset.from_dict(tx['asset'])
else:
asset = AssetLink.from_dict(tx['asset'])
return cls(tx['operation'], asset, fulfillments, conditions,
return cls(tx['operation'], tx['asset'], fulfillments, conditions,
tx['metadata'], tx['version'])

View File

@ -6,7 +6,7 @@ from time import time
from itertools import compress
from bigchaindb.common import crypto, exceptions
from bigchaindb.common.util import gen_timestamp, serialize
from bigchaindb.common.transaction import TransactionLink, Asset
from bigchaindb.common.transaction import TransactionLink
import bigchaindb
@ -348,13 +348,12 @@ class Bigchain(object):
asset_id (str): The asset id.
Returns:
:class:`~bigchaindb.common.transaction.Asset` if the asset
exists else None.
dict if the asset exists else None.
"""
cursor = backend.query.get_asset_by_id(self.connection, asset_id)
cursor = list(cursor)
if cursor:
return Asset.from_dict(cursor[0]['asset'])
return cursor[0]['asset']
def get_spent(self, txid, cid):
"""Check if a `txid` was already used as an input.

View File

@ -4,7 +4,7 @@ from bigchaindb.common.exceptions import (InvalidHash, InvalidSignature,
TransactionDoesNotExist,
TransactionNotInValidBlock,
AssetIdMismatch, AmountError)
from bigchaindb.common.transaction import Transaction, Asset
from bigchaindb.common.transaction import Transaction
from bigchaindb.common.util import gen_timestamp, serialize
from bigchaindb.common.schema import validate_transaction_schema
@ -39,21 +39,30 @@ class Transaction(Transaction):
input_conditions = []
inputs_defined = all([ffill.tx_input for ffill in self.fulfillments])
# validate amounts
if any(condition.amount < 1 for condition in self.conditions):
raise AmountError('`amount` needs to be greater than zero')
if self.operation in (Transaction.CREATE, Transaction.GENESIS):
# validate asset
if self.asset['data'] is not None and not isinstance(self.asset['data'], dict):
raise TypeError(('`asset.data` must be a dict instance or '
'None for `CREATE` transactions'))
# validate inputs
if inputs_defined:
raise ValueError('A CREATE operation has no inputs')
# validate asset
amount = sum([condition.amount for condition in self.conditions])
self.asset.validate_asset(amount=amount)
elif self.operation == Transaction.TRANSFER:
# validate asset
if not isinstance(self.asset['id'], str):
raise ValueError(('`asset.id` must be a string for '
'`TRANSFER` transations'))
# check inputs
if not inputs_defined:
raise ValueError('Only `CREATE` transactions can have null '
'inputs')
# check inputs
# store the inputs so that we can check if the asset ids match
input_txs = []
input_amount = 0
for ffill in self.fulfillments:
input_txid = ffill.tx_input.txid
input_cid = ffill.tx_input.cid
@ -74,29 +83,20 @@ class Transaction(Transaction):
raise DoubleSpend('input `{}` was already spent'
.format(input_txid))
input_conditions.append(input_tx.conditions[input_cid])
input_condition = input_tx.conditions[input_cid]
input_conditions.append(input_condition)
input_txs.append(input_tx)
if input_tx.conditions[input_cid].amount < 1:
raise AmountError('`amount` needs to be greater than zero')
input_amount += input_tx.conditions[input_cid].amount
# validate asset id
asset_id = Asset.get_asset_id(input_txs)
if asset_id != self.asset.id:
asset_id = Transaction.get_asset_id(input_txs)
if asset_id != self.asset['id']:
raise AssetIdMismatch(('The asset id of the input does not'
' match the asset id of the'
' transaction'))
# get the asset creation
asset = bigchain.get_asset_by_id(asset_id)
# validate the asset
asset.validate_asset(amount=input_amount)
# validate the amounts
output_amount = 0
for condition in self.conditions:
if condition.amount < 1:
raise AmountError('`amount` needs to be greater than zero')
output_amount += condition.amount
input_amount = sum([input_condition.amount for input_condition in input_conditions])
output_amount = sum([output_condition.amount for output_condition in self.conditions])
if output_amount != input_amount:
raise AmountError(('The amount used in the inputs `{}`'
@ -111,8 +111,8 @@ class Transaction(Transaction):
if not self.fulfillments_valid(input_conditions):
raise InvalidSignature()
else:
return self
return self
@classmethod
def from_dict(cls, tx_body):

View File

@ -4,7 +4,7 @@ import json
import os
import os.path
from bigchaindb.common.transaction import Asset, Transaction
from bigchaindb.common.transaction import Transaction
TPLS = {}
@ -62,8 +62,7 @@ def main():
""" Main function """
privkey = 'CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z'
pubkey = '4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD'
asset = Asset(None)
tx = Transaction.create([pubkey], [([pubkey], 1)], asset=asset)
tx = Transaction.create([pubkey], [([pubkey], 1)])
tx = tx.sign([privkey])
tx_json = json.dumps(tx.to_dict(), indent=2, sort_keys=True)

View File

@ -1,33 +1,31 @@
import pytest
import random
from unittest.mock import patch
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_asset_transfer(b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
tx_input = b.get_owned_ids(user_pk).pop()
tx_create = b.get_transaction(tx_input.txid)
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
AssetLink(tx_create.id))
tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed
assert tx_transfer_signed.asset.id == tx_create.id
assert tx_transfer_signed.asset['id'] == tx_create.id
def test_validate_bad_asset_creation(b, user_pk):
from bigchaindb.models import Transaction, Asset
from bigchaindb.models import Transaction
# `data` needs to be a dictionary
tx = Transaction.create([b.me], [([user_pk], 1)])
tx.asset.data = 'a'
with patch.object(Asset, 'validate_asset', return_value=None):
tx_signed = tx.sign([b.me_private])
tx.asset['data'] = 'a'
tx_signed = tx.sign([b.me_private])
with pytest.raises(TypeError):
b.validate_transaction(tx_signed)
@ -36,24 +34,23 @@ def test_validate_bad_asset_creation(b, user_pk):
@pytest.mark.usefixtures('inputs')
def test_validate_transfer_asset_id_mismatch(b, user_pk, user_sk):
from bigchaindb.common.exceptions import AssetIdMismatch
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
tx_create = b.get_owned_ids(user_pk).pop()
tx_create = b.get_transaction(tx_create.txid)
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
AssetLink(tx_create.id))
tx_transfer.asset.id = 'aaa'
tx_create.id)
tx_transfer.asset['id'] = 'aaa'
tx_transfer_signed = tx_transfer.sign([user_sk])
with pytest.raises(AssetIdMismatch):
tx_transfer_signed.validate(b)
def test_get_asset_id_create_transaction(b, user_pk):
from bigchaindb.models import Transaction, Asset
from bigchaindb.models import Transaction
tx_create = Transaction.create([b.me], [([user_pk], 1)])
asset_id = Asset.get_asset_id(tx_create)
asset_id = Transaction.get_asset_id(tx_create)
assert asset_id == tx_create.id
@ -61,14 +58,13 @@ def test_get_asset_id_create_transaction(b, user_pk):
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_asset_id_transfer_transaction(b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction, Asset
from bigchaindb.models import Transaction
tx_create = b.get_owned_ids(user_pk).pop()
tx_create = b.get_transaction(tx_create.txid)
# create a transfer transaction
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
AssetLink(tx_create.id))
tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
# create a block
block = b.create_block([tx_transfer_signed])
@ -76,13 +72,13 @@ def test_get_asset_id_transfer_transaction(b, user_pk, user_sk):
# vote the block valid
vote = b.vote(block.id, b.get_last_voted_block().id, True)
b.write_vote(vote)
asset_id = Asset.get_asset_id(tx_transfer)
asset_id = Transaction.get_asset_id(tx_transfer)
assert asset_id == tx_transfer.asset.id
assert asset_id == tx_transfer.asset['id']
def test_asset_id_mismatch(b, user_pk):
from bigchaindb.models import Transaction, Asset
from bigchaindb.models import Transaction
from bigchaindb.common.exceptions import AssetIdMismatch
tx1 = Transaction.create([b.me], [([user_pk], 1)],
@ -91,13 +87,12 @@ def test_asset_id_mismatch(b, user_pk):
metadata={'msg': random.random()})
with pytest.raises(AssetIdMismatch):
Asset.get_asset_id([tx1, tx2])
Transaction.get_asset_id([tx1, tx2])
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_transactions_by_asset_id(b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
tx_create = b.get_owned_ids(user_pk).pop()
@ -111,7 +106,7 @@ def test_get_transactions_by_asset_id(b, user_pk, user_sk):
# create a transfer transaction
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
AssetLink(tx_create.id))
tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
# create the block
block = b.create_block([tx_transfer_signed])
@ -127,13 +122,12 @@ def test_get_transactions_by_asset_id(b, user_pk, user_sk):
assert tx_transfer.id in [t.id for t in txs]
# FIXME: can I rely on the ordering here?
assert asset_id == txs[0].id
assert asset_id == txs[1].asset.id
assert asset_id == txs[1].asset['id']
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_transactions_by_asset_id_with_invalid_block(b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
tx_create = b.get_owned_ids(user_pk).pop()
@ -147,7 +141,7 @@ def test_get_transactions_by_asset_id_with_invalid_block(b, user_pk, user_sk):
# create a transfer transaction
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
AssetLink(tx_create.id))
tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
# create the block
block = b.create_block([tx_transfer_signed])
@ -164,15 +158,14 @@ def test_get_transactions_by_asset_id_with_invalid_block(b, user_pk, user_sk):
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_asset_by_id(b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Asset, Transaction
from bigchaindb.models import Transaction
tx_create = b.get_owned_ids(user_pk).pop()
tx_create = b.get_transaction(tx_create.txid)
# create a transfer transaction
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
AssetLink(tx_create.id))
tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
# create the block
block = b.create_block([tx_transfer_signed])
@ -181,7 +174,7 @@ def test_get_asset_by_id(b, user_pk, user_sk):
vote = b.vote(block.id, b.get_last_voted_block().id, True)
b.write_vote(vote)
asset_id = Asset.get_asset_id([tx_create, tx_transfer])
asset_id = Transaction.get_asset_id([tx_create, tx_transfer])
txs = b.get_transactions_by_asset_id(asset_id)
assert len(txs) == 2
@ -190,32 +183,21 @@ def test_get_asset_by_id(b, user_pk, user_sk):
def test_create_invalid_divisible_asset(b, user_pk, user_sk):
from bigchaindb.models import Transaction, Asset
from bigchaindb.models import Transaction
from bigchaindb.common.exceptions import AmountError
# Asset amount must be more than 0
asset = Asset()
tx = Transaction.create([user_pk], [([user_pk], 1)], asset=asset)
tx = Transaction.create([user_pk], [([user_pk], 1)])
tx.conditions[0].amount = 0
with pytest.raises(AmountError):
tx.sign([user_sk])
tx.sign([user_sk])
# even if a transaction is badly constructed the server should raise the
# exception
asset = Asset()
tx = Transaction.create([user_pk], [([user_pk], 1)], asset=asset)
tx.conditions[0].amount = 0
with patch.object(Asset, 'validate_asset', return_value=None):
tx_signed = tx.sign([user_sk])
with pytest.raises(AmountError):
tx_signed.validate(b)
assert b.is_valid_transaction(tx_signed) is False
b.validate_transaction(tx)
def test_create_valid_divisible_asset(b, user_pk, user_sk):
from bigchaindb.models import Transaction, Asset
from bigchaindb.models import Transaction
asset = Asset()
tx = Transaction.create([user_pk], [([user_pk], 2)], asset=asset)
tx = Transaction.create([user_pk], [([user_pk], 2)])
tx_signed = tx.sign([user_sk])
assert b.is_valid_transaction(tx_signed)

View File

@ -1,7 +1,5 @@
import pytest
from unittest.mock import patch
# CREATE divisible asset
# Single input
@ -10,10 +8,8 @@ from unittest.mock import patch
# Single owners_after
def test_single_in_single_own_single_out_single_own_create(b, user_pk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset
asset = Asset()
tx = Transaction.create([b.me], [([user_pk], 100)], asset=asset)
tx = Transaction.create([b.me], [([user_pk], 100)])
tx_signed = tx.sign([b.me_private])
assert tx_signed.validate(b) == tx_signed
@ -29,11 +25,8 @@ def test_single_in_single_own_single_out_single_own_create(b, user_pk):
# Single owners_after per output
def test_single_in_single_own_multiple_out_single_own_create(b, user_pk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset
asset = Asset()
tx = Transaction.create([b.me], [([user_pk], 50), ([user_pk], 50)],
asset=asset)
tx = Transaction.create([b.me], [([user_pk], 50), ([user_pk], 50)])
tx_signed = tx.sign([b.me_private])
assert tx_signed.validate(b) == tx_signed
@ -50,10 +43,8 @@ def test_single_in_single_own_multiple_out_single_own_create(b, user_pk):
# Multiple owners_after
def test_single_in_single_own_single_out_multiple_own_create(b, user_pk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset
asset = Asset()
tx = Transaction.create([b.me], [([user_pk, user_pk], 100)], asset=asset)
tx = Transaction.create([b.me], [([user_pk, user_pk], 100)])
tx_signed = tx.sign([b.me_private])
assert tx_signed.validate(b) == tx_signed
@ -75,12 +66,8 @@ def test_single_in_single_own_single_out_multiple_own_create(b, user_pk):
# owners_after
def test_single_in_single_own_multiple_out_mix_own_create(b, user_pk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset
asset = Asset()
tx = Transaction.create([b.me],
[([user_pk], 50), ([user_pk, user_pk], 50)],
asset=asset)
tx = Transaction.create([b.me], [([user_pk], 50), ([user_pk, user_pk], 50)])
tx_signed = tx.sign([b.me_private])
assert tx_signed.validate(b) == tx_signed
@ -102,10 +89,8 @@ def test_single_in_single_own_multiple_out_mix_own_create(b, user_pk):
def test_single_in_multiple_own_single_out_single_own_create(b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset
asset = Asset()
tx = Transaction.create([b.me, user_pk], [([user_pk], 100)], asset=asset)
tx = Transaction.create([b.me, user_pk], [([user_pk], 100)])
tx_signed = tx.sign([b.me_private, user_sk])
assert tx_signed.validate(b) == tx_signed
assert len(tx_signed.conditions) == 1
@ -131,11 +116,9 @@ def test_single_in_multiple_own_single_out_single_own_create(b, user_pk,
def test_single_in_single_own_single_out_single_own_transfer(b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset
asset = Asset()
tx_create = Transaction.create([b.me], [([user_pk], 100)], asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 100)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -147,7 +130,7 @@ def test_single_in_single_own_single_out_single_own_transfer(b, user_pk,
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b)
@ -166,11 +149,9 @@ def test_single_in_single_own_single_out_single_own_transfer(b, user_pk,
def test_single_in_single_own_multiple_out_single_own_transfer(b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset
asset = Asset()
tx_create = Transaction.create([b.me], [([user_pk], 100)], asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 100)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -183,7 +164,7 @@ def test_single_in_single_own_multiple_out_single_own_transfer(b, user_pk,
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 50), ([b.me], 50)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -203,11 +184,9 @@ def test_single_in_single_own_multiple_out_single_own_transfer(b, user_pk,
def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset
asset = Asset()
tx_create = Transaction.create([b.me], [([user_pk], 100)], asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 100)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -220,7 +199,7 @@ def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk,
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me, b.me], 100)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -245,11 +224,9 @@ def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk,
def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset
asset = Asset()
tx_create = Transaction.create([b.me], [([user_pk], 100)], asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 100)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -262,7 +239,7 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_pk,
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 50), ([b.me, b.me], 50)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -287,12 +264,9 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_pk,
def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset
asset = Asset()
tx_create = Transaction.create([b.me], [([b.me, user_pk], 100)],
asset=asset)
tx_create = Transaction.create([b.me], [([b.me, user_pk], 100)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -304,7 +278,7 @@ def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk,
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -327,12 +301,9 @@ def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk,
def test_multiple_in_single_own_single_out_single_own_transfer(b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset
asset = Asset()
tx_create = Transaction.create([b.me], [([user_pk], 50), ([user_pk], 50)],
asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 50), ([user_pk], 50)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -344,7 +315,7 @@ def test_multiple_in_single_own_single_out_single_own_transfer(b, user_pk,
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b)
@ -363,14 +334,9 @@ def test_multiple_in_single_own_single_out_single_own_transfer(b, user_pk,
def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset
asset = Asset()
tx_create = Transaction.create([b.me],
[([user_pk, b.me], 50),
([user_pk, b.me], 50)],
asset=asset)
tx_create = Transaction.create([b.me], [([user_pk, b.me], 50), ([user_pk, b.me], 50)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -382,7 +348,7 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_pk,
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
assert tx_transfer_signed.validate(b)
@ -409,14 +375,9 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_pk,
def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset
asset = Asset()
tx_create = Transaction.create([b.me],
[([user_pk], 50),
([user_pk, b.me], 50)],
asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 50), ([user_pk, b.me], 50)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -428,7 +389,7 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(b, user_pk,
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -455,14 +416,9 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(b, user_pk,
def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset
asset = Asset()
tx_create = Transaction.create([b.me],
[([user_pk], 50),
([user_pk, b.me], 50)],
asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 50), ([user_pk, b.me], 50)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -475,7 +431,7 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk,
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 50), ([b.me, user_pk], 50)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -506,16 +462,11 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk,
@pytest.mark.usefixtures('inputs')
def test_multiple_in_different_transactions(b, user_pk, user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset
# `b` creates a divisible asset and assigns 50 shares to `b` and
# 50 shares to `user_pk`
asset = Asset()
tx_create = Transaction.create([b.me],
[([user_pk], 50),
([b.me], 50)],
asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 50), ([b.me], 50)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -531,7 +482,7 @@ def test_multiple_in_different_transactions(b, user_pk, user_sk):
# split across two different transactions
tx_transfer1 = Transaction.transfer(tx_create.to_inputs([1]),
[([user_pk], 50)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer1_signed = tx_transfer1.sign([b.me_private])
# create block
block = b.create_block([tx_transfer1_signed])
@ -547,7 +498,7 @@ def test_multiple_in_different_transactions(b, user_pk, user_sk):
tx_transfer2 = Transaction.transfer(tx_create.to_inputs([0]) +
tx_transfer1.to_inputs([0]),
[([b.me], 100)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer2_signed = tx_transfer2.sign([user_sk])
assert tx_transfer2_signed.validate(b) == tx_transfer2_signed
@ -568,12 +519,10 @@ def test_multiple_in_different_transactions(b, user_pk, user_sk):
@pytest.mark.usefixtures('inputs')
def test_amount_error_transfer(b, user_pk, user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
from bigchaindb.common.exceptions import AmountError
# CREATE divisible asset
asset = Asset()
tx_create = Transaction.create([b.me], [([user_pk], 100)], asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 100)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -586,7 +535,7 @@ def test_amount_error_transfer(b, user_pk, user_sk):
# TRANSFER
# output amount less than input amount
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 50)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
with pytest.raises(AmountError):
tx_transfer_signed.validate(b)
@ -594,7 +543,7 @@ def test_amount_error_transfer(b, user_pk, user_sk):
# TRANSFER
# output amount greater than input amount
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 101)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
with pytest.raises(AmountError):
tx_transfer_signed.validate(b)
@ -612,12 +561,9 @@ def test_threshold_same_public_key(b, user_pk, user_sk):
# that does not mean that the code shouldn't work.
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset
asset = Asset()
tx_create = Transaction.create([b.me], [([user_pk, user_pk], 100)],
asset=asset)
tx_create = Transaction.create([b.me], [([user_pk, user_pk], 100)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -629,7 +575,7 @@ def test_threshold_same_public_key(b, user_pk, user_sk):
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk, user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -639,15 +585,9 @@ def test_threshold_same_public_key(b, user_pk, user_sk):
@pytest.mark.usefixtures('inputs')
def test_sum_amount(b, user_pk, user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset with 3 outputs with amount 1
asset = Asset()
tx_create = Transaction.create([b.me],
[([user_pk], 1),
([user_pk], 1),
([user_pk], 1)],
asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 1), ([user_pk], 1), ([user_pk], 1)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -660,7 +600,7 @@ def test_sum_amount(b, user_pk, user_sk):
# create a transfer transaction with one output and check if the amount
# is 3
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 3)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -672,12 +612,9 @@ def test_sum_amount(b, user_pk, user_sk):
@pytest.mark.usefixtures('inputs')
def test_divide(b, user_pk, user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
# CREATE divisible asset with 1 output with amount 3
asset = Asset()
tx_create = Transaction.create([b.me], [([user_pk], 3)],
asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 3)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -691,7 +628,7 @@ def test_divide(b, user_pk, user_sk):
# of each output is 1
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 1), ([b.me], 1), ([b.me], 1)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
assert tx_transfer_signed.validate(b) == tx_transfer_signed
@ -705,13 +642,10 @@ def test_divide(b, user_pk, user_sk):
@pytest.mark.usefixtures('inputs')
def test_non_positive_amounts_on_transfer(b, user_pk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
from bigchaindb.common.exceptions import AmountError
# CREATE divisible asset with 1 output with amount 3
asset = Asset()
tx_create = Transaction.create([b.me], [([user_pk], 3)],
asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 3)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -724,7 +658,7 @@ def test_non_positive_amounts_on_transfer(b, user_pk):
with pytest.raises(AmountError):
Transaction.transfer(tx_create.to_inputs(),
[([b.me], 4), ([b.me], -1)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
# Check that negative inputs are caught when validating a TRANSFER transaction
@ -732,13 +666,10 @@ def test_non_positive_amounts_on_transfer(b, user_pk):
@pytest.mark.usefixtures('inputs')
def test_non_positive_amounts_on_transfer_validate(b, user_pk, user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset, AssetLink
from bigchaindb.common.exceptions import AmountError
# CREATE divisible asset with 1 output with amount 3
asset = Asset()
tx_create = Transaction.create([b.me], [([user_pk], 3)],
asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 3)])
tx_create_signed = tx_create.sign([b.me_private])
# create block
block = b.create_block([tx_create_signed])
@ -752,7 +683,7 @@ def test_non_positive_amounts_on_transfer_validate(b, user_pk, user_sk):
# of each output is 1
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 4), ([b.me], 1)],
AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer.conditions[1].amount = -1
tx_transfer_signed = tx_transfer.sign([user_sk])
@ -765,14 +696,11 @@ def test_non_positive_amounts_on_transfer_validate(b, user_pk, user_sk):
@pytest.mark.usefixtures('inputs')
def test_non_positive_amounts_on_create(b, user_pk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset
from bigchaindb.common.exceptions import AmountError
# CREATE divisible asset with 1 output with amount 3
asset = Asset()
with pytest.raises(AmountError):
Transaction.create([b.me], [([user_pk], -3)],
asset=asset)
Transaction.create([b.me], [([user_pk], -3)])
# Check that negative inputs are caught when validating a CREATE transaction
@ -780,16 +708,12 @@ def test_non_positive_amounts_on_create(b, user_pk):
@pytest.mark.usefixtures('inputs')
def test_non_positive_amounts_on_create_validate(b, user_pk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import Asset
from bigchaindb.common.exceptions import AmountError
# CREATE divisible asset with 1 output with amount 3
asset = Asset()
tx_create = Transaction.create([b.me], [([user_pk], 3)],
asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 3)])
tx_create.conditions[0].amount = -3
with patch.object(Asset, 'validate_asset', return_value=None):
tx_create_signed = tx_create.sign([b.me_private])
tx_create_signed = tx_create.sign([b.me_private])
with pytest.raises(AmountError):
tx_create_signed.validate(b)

View File

@ -14,6 +14,16 @@ USER3_PUBLIC_KEY = 'Gbrg7JtxdjedQRmr81ZZbh1BozS7fBW88ZyxNDy7WLNC'
CC_FULFILLMENT_URI = 'cf:0:'
CC_CONDITION_URI = 'cc:0:3:47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU:0'
ASSET_DEFINITION = {
'data': {
'definition': 'Asset definition'
}
}
ASSET_LINK = {
'id': 'a' * 64
}
DATA = {
'msg': 'Hello BigchainDB!'
}
@ -118,6 +128,16 @@ def user2_cond(user2_Ed25519, user2_pub):
return Condition(user2_Ed25519, [user2_pub])
@pytest.fixture
def asset_definition():
return ASSET_DEFINITION
@pytest.fixture
def asset_link():
return ASSET_LINK
@pytest.fixture
def data():
return DATA
@ -125,8 +145,8 @@ def data():
@pytest.fixture
def utx(user_ffill, user_cond):
from bigchaindb.common.transaction import Transaction, Asset
return Transaction(Transaction.CREATE, Asset(), [user_ffill], [user_cond])
from bigchaindb.common.transaction import Transaction
return Transaction(Transaction.CREATE, {'data': None}, [user_ffill], [user_cond])
@pytest.fixture
@ -137,12 +157,12 @@ def tx(utx, user_priv):
@pytest.fixture
def transfer_utx(user_cond, user2_cond, utx):
from bigchaindb.common.transaction import (Fulfillment, TransactionLink,
Transaction, AssetLink)
Transaction)
user_cond = user_cond.to_dict()
ffill = Fulfillment(utx.conditions[0].fulfillment,
user_cond['owners_after'],
TransactionLink(utx.id, 0))
return Transaction('TRANSFER', AssetLink(utx.id), [ffill], [user2_cond])
return Transaction('TRANSFER', {'id': utx.id}, [ffill], [user2_cond])
@pytest.fixture

View File

@ -1,59 +0,0 @@
from pytest import raises
def test_asset_default_values():
from bigchaindb.common.transaction import Asset
asset = Asset()
assert asset.data is None
def test_asset_creation_with_data(data):
from bigchaindb.common.transaction import Asset
asset = Asset(data)
assert asset.data == data
def test_asset_invalid_asset_initialization():
from bigchaindb.common.transaction import Asset
# check types
with raises(TypeError):
Asset(data='some wrong type')
def test_invalid_asset_comparison(data):
from bigchaindb.common.transaction import Asset
assert Asset(data) != 'invalid comparison'
def test_asset_serialization(data):
from bigchaindb.common.transaction import Asset
expected = {
'data': data,
}
asset = Asset(data)
assert asset.to_dict() == expected
def test_asset_deserialization(data):
from bigchaindb.common.transaction import Asset
asset_dict = {
'data': data,
}
asset = Asset.from_dict(asset_dict)
expected = Asset(data)
assert asset == expected
def test_validate_asset():
from bigchaindb.common.transaction import Asset
# test amount errors
asset = Asset()
with raises(TypeError):
asset.validate_asset(amount='a')

View File

@ -1,5 +1,4 @@
from pytest import raises
from unittest.mock import patch
def test_fulfillment_serialization(ffill_uri, user_pub):
@ -146,9 +145,14 @@ def test_condition_hashlock_deserialization():
def test_invalid_condition_initialization(cond_uri, user_pub):
from bigchaindb.common.transaction import Condition
from bigchaindb.common.exceptions import AmountError
with raises(TypeError):
Condition(cond_uri, user_pub)
with raises(TypeError):
Condition(cond_uri, [user_pub], 'amount')
with raises(AmountError):
Condition(cond_uri, [user_pub], 0)
def test_generate_conditions_split_half_recursive(user_pub, user2_pub,
@ -242,49 +246,50 @@ def test_generate_conditions_invalid_parameters(user_pub, user2_pub,
Condition.generate([[user_pub]], 1)
def test_invalid_transaction_initialization():
from bigchaindb.common.transaction import Transaction, Asset
def test_invalid_transaction_initialization(asset_definition):
from bigchaindb.common.transaction import Transaction
with raises(ValueError):
Transaction(operation='invalid operation', asset=Asset())
Transaction(operation='invalid operation', asset=asset_definition)
with raises(TypeError):
Transaction(operation='CREATE', asset='invalid asset')
with raises(TypeError):
Transaction(operation='TRANSFER', asset={})
with raises(TypeError):
Transaction(
operation='CREATE',
asset=Asset(),
asset=asset_definition,
conditions='invalid conditions'
)
with raises(TypeError):
Transaction(
operation='CREATE',
asset=Asset(),
asset=asset_definition,
conditions=[],
fulfillments='invalid fulfillments'
)
with raises(TypeError):
Transaction(
operation='CREATE',
asset=Asset(),
asset=asset_definition,
conditions=[],
fulfillments=[],
metadata='invalid metadata'
)
def test_create_default_asset_on_tx_initialization():
from bigchaindb.common.transaction import Transaction, Asset
def test_create_default_asset_on_tx_initialization(asset_definition):
from bigchaindb.common.transaction import Transaction
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, None)
expected = Asset()
expected = {'data': None}
tx = Transaction(Transaction.CREATE, asset=expected)
asset = tx.asset
assert asset == expected
def test_transaction_serialization(user_ffill, user_cond, data):
from bigchaindb.common.transaction import Transaction, Asset
from bigchaindb.common.transaction import Transaction
tx_id = 'l0l'
@ -302,7 +307,7 @@ def test_transaction_serialization(user_ffill, user_cond, data):
}
}
tx = Transaction(Transaction.CREATE, Asset(data), [user_ffill],
tx = Transaction(Transaction.CREATE, {'data': data}, [user_ffill],
[user_cond])
tx_dict = tx.to_dict()
tx_dict['id'] = tx_id
@ -311,10 +316,10 @@ def test_transaction_serialization(user_ffill, user_cond, data):
def test_transaction_deserialization(user_ffill, user_cond, data):
from bigchaindb.common.transaction import Transaction, Asset
from bigchaindb.common.transaction import Transaction
from .util import validate_transaction_model
expected_asset = Asset(data)
expected_asset = {'data': data}
expected = Transaction(Transaction.CREATE, expected_asset, [user_ffill],
[user_cond], None, Transaction.VERSION)
@ -432,92 +437,28 @@ def test_cast_transaction_link_to_boolean():
assert bool(TransactionLink(False, False)) is True
def test_asset_link_serialization():
from bigchaindb.common.transaction import AssetLink
def test_add_fulfillment_to_tx(user_ffill, asset_definition):
from bigchaindb.common.transaction import Transaction
asset_id = 'a asset id'
expected = {
'id': asset_id,
}
asset_link = AssetLink(asset_id)
assert asset_link.to_dict() == expected
def test_asset_link_serialization_with_empty_payload():
from bigchaindb.common.transaction import AssetLink
expected = None
asset_link = AssetLink()
assert asset_link.to_dict() == expected
def test_asset_link_deserialization():
from bigchaindb.common.transaction import AssetLink
asset_id = 'a asset id'
expected = AssetLink(asset_id)
asset_link = {
'id': asset_id
}
asset_link = AssetLink.from_dict(asset_link)
assert asset_link == expected
def test_asset_link_deserialization_with_empty_payload():
from bigchaindb.common.transaction import AssetLink
expected = AssetLink()
asset_link = AssetLink.from_dict(None)
assert asset_link == expected
def test_cast_asset_link_to_boolean():
from bigchaindb.common.transaction import AssetLink
assert bool(AssetLink()) is False
assert bool(AssetLink('a')) is True
assert bool(AssetLink(False)) is True
def test_eq_asset_link():
from bigchaindb.common.transaction import AssetLink
asset_id_1 = 'asset_1'
asset_id_2 = 'asset_2'
assert AssetLink(asset_id_1) == AssetLink(asset_id_1)
assert AssetLink(asset_id_1) != AssetLink(asset_id_2)
def test_add_fulfillment_to_tx(user_ffill):
from bigchaindb.common.transaction import Transaction, Asset
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, Asset(), [], [])
tx = Transaction(Transaction.CREATE, asset_definition, [], [])
tx.add_fulfillment(user_ffill)
assert len(tx.fulfillments) == 1
def test_add_fulfillment_to_tx_with_invalid_parameters():
from bigchaindb.common.transaction import Transaction, Asset
def test_add_fulfillment_to_tx_with_invalid_parameters(asset_definition):
from bigchaindb.common.transaction import Transaction
tx = Transaction(Transaction.CREATE, asset_definition)
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, Asset())
with raises(TypeError):
tx.add_fulfillment('somewronginput')
def test_add_condition_to_tx(user_cond):
from bigchaindb.common.transaction import Transaction, Asset
def test_add_condition_to_tx(user_cond, asset_definition):
from bigchaindb.common.transaction import Transaction
from .util import validate_transaction_model
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, Asset())
tx = Transaction(Transaction.CREATE, asset_definition)
tx.add_condition(user_cond)
assert len(tx.conditions) == 1
@ -525,11 +466,10 @@ def test_add_condition_to_tx(user_cond):
validate_transaction_model(tx)
def test_add_condition_to_tx_with_invalid_parameters():
from bigchaindb.common.transaction import Transaction, Asset
def test_add_condition_to_tx_with_invalid_parameters(asset_definition):
from bigchaindb.common.transaction import Transaction
tx = Transaction(Transaction.CREATE, asset_definition, [], [])
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, Asset(), [], [])
with raises(TypeError):
tx.add_condition('somewronginput')
@ -541,13 +481,14 @@ def test_sign_with_invalid_parameters(utx, user_priv):
utx.sign(user_priv)
def test_validate_tx_simple_create_signature(user_ffill, user_cond, user_priv):
def test_validate_tx_simple_create_signature(user_ffill, user_cond, user_priv,
asset_definition):
from copy import deepcopy
from bigchaindb.common.crypto import PrivateKey
from bigchaindb.common.transaction import Transaction, Asset
from bigchaindb.common.transaction import Transaction
from .util import validate_transaction_model
tx = Transaction(Transaction.CREATE, Asset(), [user_ffill], [user_cond])
tx = Transaction(Transaction.CREATE, asset_definition, [user_ffill], [user_cond])
expected = deepcopy(user_cond)
expected.fulfillment.sign(str(tx).encode(), PrivateKey(user_priv))
tx.sign([user_priv])
@ -601,14 +542,15 @@ def test_validate_fulfillment_with_invalid_parameters(utx):
input_conditions) is False
def test_validate_multiple_fulfillments(user_ffill, user_cond, user_priv):
def test_validate_multiple_fulfillments(user_ffill, user_cond, user_priv,
asset_definition):
from copy import deepcopy
from bigchaindb.common.crypto import PrivateKey
from bigchaindb.common.transaction import Transaction, Asset
from bigchaindb.common.transaction import Transaction
from .util import validate_transaction_model
tx = Transaction(Transaction.CREATE, Asset(),
tx = Transaction(Transaction.CREATE, asset_definition,
[user_ffill, deepcopy(user_ffill)],
[user_cond, deepcopy(user_cond)])
@ -639,14 +581,16 @@ def test_validate_tx_threshold_create_signature(user_user2_threshold_ffill,
user_pub,
user2_pub,
user_priv,
user2_priv):
user2_priv,
asset_definition):
from copy import deepcopy
from bigchaindb.common.crypto import PrivateKey
from bigchaindb.common.transaction import Transaction, Asset
from bigchaindb.common.transaction import Transaction
from .util import validate_transaction_model
tx = Transaction(Transaction.CREATE, Asset(), [user_user2_threshold_ffill],
tx = Transaction(Transaction.CREATE, asset_definition,
[user_user2_threshold_ffill],
[user_user2_threshold_cond])
expected = deepcopy(user_user2_threshold_cond)
expected.fulfillment.subconditions[0]['body'].sign(str(tx).encode(),
@ -665,15 +609,15 @@ def test_validate_tx_threshold_create_signature(user_user2_threshold_ffill,
def test_multiple_fulfillment_validation_of_transfer_tx(user_ffill, user_cond,
user_priv, user2_pub,
user2_priv, user3_pub,
user3_priv):
user3_priv,
asset_definition):
from copy import deepcopy
from bigchaindb.common.transaction import (Transaction, TransactionLink,
Fulfillment, Condition, Asset,
AssetLink)
Fulfillment, Condition)
from cryptoconditions import Ed25519Fulfillment
from .util import validate_transaction_model
tx = Transaction(Transaction.CREATE, Asset(),
tx = Transaction(Transaction.CREATE, asset_definition,
[user_ffill, deepcopy(user_ffill)],
[user_cond, deepcopy(user_cond)])
tx.sign([user_priv])
@ -685,7 +629,7 @@ def test_multiple_fulfillment_validation_of_transfer_tx(user_ffill, user_cond,
[user3_pub]),
Condition(Ed25519Fulfillment(public_key=user3_pub),
[user3_pub])]
transfer_tx = Transaction('TRANSFER', AssetLink(tx.id),
transfer_tx = Transaction('TRANSFER', {'id': tx.id},
fulfillments, conditions)
transfer_tx = transfer_tx.sign([user_priv])
@ -720,7 +664,7 @@ def test_validate_fulfillments_of_transfer_tx_with_invalid_params(transfer_tx,
def test_create_create_transaction_single_io(user_cond, user_pub, data):
from bigchaindb.common.transaction import Transaction, Asset
from bigchaindb.common.transaction import Transaction
from .util import validate_transaction_model
expected = {
@ -742,8 +686,8 @@ def test_create_create_transaction_single_io(user_cond, user_pub, data):
'version': 1,
}
asset = Asset(data)
tx = Transaction.create([user_pub], [([user_pub], 1)], data, asset)
tx = Transaction.create([user_pub], [([user_pub], 1)], metadata=data,
asset=data)
tx_dict = tx.to_dict()
tx_dict['fulfillments'][0]['fulfillment'] = None
tx_dict.pop('id')
@ -753,17 +697,18 @@ def test_create_create_transaction_single_io(user_cond, user_pub, data):
validate_transaction_model(tx)
def test_validate_single_io_create_transaction(user_pub, user_priv, data):
from bigchaindb.common.transaction import Transaction, Asset
def test_validate_single_io_create_transaction(user_pub, user_priv, data,
asset_definition):
from bigchaindb.common.transaction import Transaction
tx = Transaction.create([user_pub], [([user_pub], 1)], data, Asset())
tx = Transaction.create([user_pub], [([user_pub], 1)], metadata=data)
tx = tx.sign([user_priv])
assert tx.fulfillments_valid() is True
def test_create_create_transaction_multiple_io(user_cond, user2_cond, user_pub,
user2_pub):
from bigchaindb.common.transaction import Transaction, Asset, Fulfillment
user2_pub, asset_definition):
from bigchaindb.common.transaction import Transaction, Fulfillment
# a fulfillment for a create transaction with multiple `owners_before`
# is a fulfillment for an implicit threshold condition with
@ -778,10 +723,8 @@ def test_create_create_transaction_multiple_io(user_cond, user2_cond, user_pub,
'operation': 'CREATE',
'version': 1
}
asset = Asset()
tx = Transaction.create([user_pub, user2_pub],
[([user_pub], 1), ([user2_pub], 1)],
asset=asset,
metadata={'message': 'hello'}).to_dict()
tx.pop('id')
tx.pop('asset')
@ -790,14 +733,14 @@ def test_create_create_transaction_multiple_io(user_cond, user2_cond, user_pub,
def test_validate_multiple_io_create_transaction(user_pub, user_priv,
user2_pub, user2_priv):
from bigchaindb.common.transaction import Transaction, Asset
user2_pub, user2_priv,
asset_definition):
from bigchaindb.common.transaction import Transaction
from .util import validate_transaction_model
tx = Transaction.create([user_pub, user2_pub],
[([user_pub], 1), ([user2_pub], 1)],
metadata={'message': 'hello'},
asset=Asset())
metadata={'message': 'hello'})
tx = tx.sign([user_priv, user2_priv])
assert tx.fulfillments_valid() is True
@ -807,7 +750,7 @@ def test_validate_multiple_io_create_transaction(user_pub, user_priv,
def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub,
user_user2_threshold_cond,
user_user2_threshold_ffill, data):
from bigchaindb.common.transaction import Transaction, Asset
from bigchaindb.common.transaction import Transaction
expected = {
'conditions': [user_user2_threshold_cond.to_dict()],
@ -827,9 +770,8 @@ def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub,
'operation': 'CREATE',
'version': 1
}
asset = Asset(data)
tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)],
data, asset)
metadata=data, asset=data)
tx_dict = tx.to_dict()
tx_dict.pop('id')
tx_dict['fulfillments'][0]['fulfillment'] = None
@ -838,12 +780,12 @@ def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub,
def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub,
data):
from bigchaindb.common.transaction import Transaction, Asset
data, asset_definition):
from bigchaindb.common.transaction import Transaction
from .util import validate_transaction_model
tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)],
data, Asset())
metadata=data)
tx = tx.sign([user_priv])
assert tx.fulfillments_valid() is True
@ -851,7 +793,7 @@ def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub,
def test_create_create_transaction_with_invalid_parameters(user_pub):
from bigchaindb.common.transaction import Transaction, AssetLink
from bigchaindb.common.transaction import Transaction
with raises(TypeError):
Transaction.create('not a list')
@ -866,12 +808,12 @@ def test_create_create_transaction_with_invalid_parameters(user_pub):
with raises(ValueError):
Transaction.create([user_pub], [([user_pub],)])
with raises(TypeError):
Transaction.create([user_pub], [([user_pub], 1)], metadata=[])
Transaction.create([user_pub], [([user_pub], 1)],
metadata='not a dict or none')
with raises(TypeError):
Transaction.create([user_pub],
[([user_pub], 1)],
metadata=None,
asset=AssetLink('mock_asset_link'))
asset='not a dict or none')
def test_conditions_to_inputs(tx):
@ -888,7 +830,7 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
user2_cond, user_priv):
from copy import deepcopy
from bigchaindb.common.crypto import PrivateKey
from bigchaindb.common.transaction import Transaction, AssetLink
from bigchaindb.common.transaction import Transaction
from bigchaindb.common.util import serialize
from .util import validate_transaction_model
@ -915,7 +857,7 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
}
inputs = tx.to_inputs([0])
transfer_tx = Transaction.transfer(inputs, [([user2_pub], 1)],
asset_link=AssetLink(tx.id))
asset_id=tx.id)
transfer_tx = transfer_tx.sign([user_priv])
transfer_tx = transfer_tx.to_dict()
@ -936,12 +878,12 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
def test_create_transfer_transaction_multiple_io(user_pub, user_priv,
user2_pub, user2_priv,
user3_pub, user2_cond):
from bigchaindb.common.transaction import Transaction, Asset, AssetLink
user3_pub, user2_cond,
asset_definition):
from bigchaindb.common.transaction import Transaction
asset = Asset()
tx = Transaction.create([user_pub], [([user_pub], 1), ([user2_pub], 1)],
asset=asset, metadata={'message': 'hello'})
metadata={'message': 'hello'})
tx = tx.sign([user_priv])
expected = {
@ -974,7 +916,7 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv,
transfer_tx = Transaction.transfer(tx.to_inputs(),
[([user2_pub], 1), ([user2_pub], 1)],
asset_link=AssetLink(tx.id))
asset_id=tx.id)
transfer_tx = transfer_tx.sign([user_priv, user2_priv])
assert len(transfer_tx.fulfillments) == 2
@ -992,41 +934,39 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv,
def test_create_transfer_with_invalid_parameters(tx, user_pub):
from bigchaindb.common.transaction import Transaction, Asset, AssetLink
mock_asset_link = AssetLink(tx.id)
from bigchaindb.common.transaction import Transaction
with raises(TypeError):
Transaction.transfer({}, [], mock_asset_link)
Transaction.transfer({}, [], tx.id)
with raises(ValueError):
Transaction.transfer([], [], mock_asset_link)
Transaction.transfer([], [], tx.id)
with raises(TypeError):
Transaction.transfer(['fulfillment'], {}, mock_asset_link)
Transaction.transfer(['fulfillment'], {}, tx.id)
with raises(ValueError):
Transaction.transfer(['fulfillment'], [], mock_asset_link)
Transaction.transfer(['fulfillment'], [], tx.id)
with raises(ValueError):
Transaction.transfer(['fulfillment'], [user_pub], mock_asset_link)
Transaction.transfer(['fulfillment'], [user_pub], tx.id)
with raises(ValueError):
Transaction.transfer(['fulfillment'], [([user_pub],)], mock_asset_link)
Transaction.transfer(['fulfillment'], [([user_pub],)], tx.id)
with raises(TypeError):
Transaction.transfer(['fulfillment'], [([user_pub], 1)],
mock_asset_link, metadata=[])
tx.id, metadata='not a dict or none')
with raises(TypeError):
Transaction.transfer(['fulfillment'], [([user_pub], 1)], Asset())
Transaction.transfer(['fulfillment'], [([user_pub], 1)],
['not a string'])
def test_cant_add_empty_condition():
from bigchaindb.common.transaction import Transaction, Asset
from bigchaindb.common.transaction import Transaction
tx = Transaction(Transaction.CREATE, None)
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, None)
with raises(TypeError):
tx.add_condition(None)
def test_cant_add_empty_fulfillment():
from bigchaindb.common.transaction import Transaction, Asset
from bigchaindb.common.transaction import Transaction
tx = Transaction(Transaction.CREATE, None)
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, None)
with raises(TypeError):
tx.add_fulfillment(None)

View File

@ -234,12 +234,9 @@ def signed_create_tx(b, create_tx):
@pytest.fixture
def signed_transfer_tx(signed_create_tx, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
inputs = signed_create_tx.to_inputs()
tx = Transaction.transfer(inputs,
[([user_pk], 1)],
AssetLink(signed_create_tx.id))
tx = Transaction.transfer(inputs, [([user_pk], 1)], asset_id=signed_create_tx.id)
return tx.sign([user_sk])

View File

@ -92,7 +92,6 @@ class TestBigchainApi(object):
@pytest.mark.genesis
def test_get_spent_with_double_spend(self, b, monkeypatch):
from bigchaindb.common.exceptions import DoubleSpend
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
tx = Transaction.create([b.me], [([b.me], 1)])
@ -104,14 +103,14 @@ class TestBigchainApi(object):
monkeypatch.setattr('time.time', lambda: 2)
transfer_tx = Transaction.transfer(tx.to_inputs(), [([b.me], 1)],
AssetLink(tx.id))
asset_id=tx.id)
transfer_tx = transfer_tx.sign([b.me_private])
block2 = b.create_block([transfer_tx])
b.write_block(block2)
monkeypatch.setattr('time.time', lambda: 3333333333)
transfer_tx2 = Transaction.transfer(tx.to_inputs(), [([b.me], 1)],
AssetLink(tx.id))
asset_id=tx.id)
transfer_tx2 = transfer_tx2.sign([b.me_private])
block3 = b.create_block([transfer_tx2])
b.write_block(block3)
@ -181,14 +180,13 @@ class TestBigchainApi(object):
@pytest.mark.usefixtures('inputs')
def test_write_transaction(self, b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)],
AssetLink(input_tx.id))
asset_id=input_tx.id)
tx = tx.sign([user_sk])
response = b.write_transaction(tx)
@ -201,14 +199,13 @@ class TestBigchainApi(object):
@pytest.mark.usefixtures('inputs')
def test_read_transaction(self, b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)],
AssetLink(input_tx.id))
asset_id=input_tx.id)
tx = tx.sign([user_sk])
b.write_transaction(tx)
@ -223,14 +220,13 @@ class TestBigchainApi(object):
@pytest.mark.usefixtures('inputs')
def test_read_transaction_invalid_block(self, b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)],
AssetLink(input_tx.id))
asset_id=input_tx.id)
tx = tx.sign([user_sk])
# There's no need to b.write_transaction(tx) to the backlog
@ -249,14 +245,13 @@ class TestBigchainApi(object):
@pytest.mark.usefixtures('inputs')
def test_read_transaction_invalid_block_and_backlog(self, b, user_pk, user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)],
AssetLink(input_tx.id))
asset_id=input_tx.id)
tx = tx.sign([user_sk])
# Make sure there's a copy of tx in the backlog
@ -489,14 +484,13 @@ class TestBigchainApi(object):
@pytest.mark.usefixtures('inputs')
def test_assign_transaction_one_node(self, b, user_pk, user_sk):
from bigchaindb.backend import query
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)],
AssetLink(input_tx.id))
asset_id=input_tx.id)
tx = tx.sign([user_sk])
b.write_transaction(tx)
@ -510,7 +504,6 @@ class TestBigchainApi(object):
def test_assign_transaction_multiple_nodes(self, b, user_pk, user_sk):
from bigchaindb.backend import query
from bigchaindb.common.crypto import generate_key_pair
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
# create 5 federation nodes
@ -523,7 +516,7 @@ class TestBigchainApi(object):
input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)],
asset_link=AssetLink(input_tx.id),
asset_id=input_tx.id,
metadata={'msg': random.random()})
tx = tx.sign([user_sk])
b.write_transaction(tx)
@ -539,8 +532,7 @@ class TestBigchainApi(object):
def test_non_create_input_not_found(self, b, user_pk):
from cryptoconditions import Ed25519Fulfillment
from bigchaindb.common.exceptions import TransactionDoesNotExist
from bigchaindb.common.transaction import (AssetLink, Fulfillment,
TransactionLink)
from bigchaindb.common.transaction import Fulfillment, TransactionLink
from bigchaindb.models import Transaction
from bigchaindb import Bigchain
@ -549,7 +541,7 @@ class TestBigchainApi(object):
[user_pk],
TransactionLink('somethingsomething', 0))
tx = Transaction.transfer([fulfillment], [([user_pk], 1)],
AssetLink('mock_asset_link'))
asset_id='mock_asset_link')
with pytest.raises(TransactionDoesNotExist):
tx.validate(Bigchain())
@ -599,7 +591,6 @@ class TestTransactionValidation(object):
def test_non_create_valid_input_wrong_owner(self, b, user_pk):
from bigchaindb.common.crypto import generate_key_pair
from bigchaindb.common.exceptions import InvalidSignature
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop()
@ -607,7 +598,7 @@ class TestTransactionValidation(object):
sk, pk = generate_key_pair()
tx = Transaction.create([pk], [([user_pk], 1)])
tx.operation = 'TRANSFER'
tx.asset = AssetLink(input_transaction.id)
tx.asset = {'id': input_transaction.id}
tx.fulfillments[0].tx_input = input_tx
with pytest.raises(InvalidSignature):
@ -644,14 +635,13 @@ class TestTransactionValidation(object):
def test_valid_non_create_transaction_after_block_creation(self, b,
user_pk,
user_sk):
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs()
transfer_tx = Transaction.transfer(inputs, [([user_pk], 1)],
AssetLink(input_tx.id))
asset_id=input_tx.id)
transfer_tx = transfer_tx.sign([user_sk])
assert transfer_tx == b.validate_transaction(transfer_tx)
@ -669,7 +659,6 @@ class TestTransactionValidation(object):
def test_transaction_not_in_valid_block(self, b, user_pk, user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.exceptions import TransactionNotInValidBlock
from bigchaindb.common.transaction import AssetLink
input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid)
@ -677,7 +666,7 @@ class TestTransactionValidation(object):
# create a transaction that's valid but not in a voted valid block
transfer_tx = Transaction.transfer(inputs, [([user_pk], 1)],
AssetLink(input_tx.id))
asset_id=input_tx.id)
transfer_tx = transfer_tx.sign([user_sk])
assert transfer_tx == b.validate_transaction(transfer_tx)
@ -689,7 +678,7 @@ class TestTransactionValidation(object):
# create transaction with the undecided input
tx_invalid = Transaction.transfer(transfer_tx.to_inputs(),
[([user_pk], 1)],
AssetLink(transfer_tx.asset.id))
asset_id=transfer_tx.asset['id'])
tx_invalid = tx_invalid.sign([user_sk])
with pytest.raises(TransactionNotInValidBlock):
@ -783,7 +772,6 @@ class TestMultipleInputs(object):
def test_transfer_single_owner_single_input(self, b, inputs, user_pk,
user_sk):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
@ -791,7 +779,7 @@ class TestMultipleInputs(object):
input_tx = b.get_transaction(tx_link.txid)
inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user2_pk], 1)],
AssetLink(input_tx.id))
asset_id=input_tx.id)
tx = tx.sign([user_sk])
# validate transaction
@ -804,7 +792,6 @@ class TestMultipleInputs(object):
user_pk,
inputs):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
@ -815,7 +802,7 @@ class TestMultipleInputs(object):
input_tx = b.get_transaction(tx_link.txid)
tx = Transaction.transfer(input_tx.to_inputs(),
[([user2_pk, user3_pk], 1)],
AssetLink(input_tx.id))
asset_id=input_tx.id)
tx = tx.sign([user_sk])
assert b.is_valid_transaction(tx) == tx
@ -827,7 +814,6 @@ class TestMultipleInputs(object):
user_sk,
user_pk):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
@ -847,7 +833,7 @@ class TestMultipleInputs(object):
inputs = input_tx.to_inputs()
transfer_tx = Transaction.transfer(inputs, [([user3_pk], 1)],
AssetLink(input_tx.id))
asset_id=input_tx.id)
transfer_tx = transfer_tx.sign([user_sk, user2_sk])
# validate transaction
@ -860,7 +846,6 @@ class TestMultipleInputs(object):
user_sk,
user_pk):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
@ -882,7 +867,7 @@ class TestMultipleInputs(object):
tx = Transaction.transfer(tx_input.to_inputs(),
[([user3_pk, user4_pk], 1)],
AssetLink(tx_input.id))
asset_id=tx_input.id)
tx = tx.sign([user_sk, user2_sk])
assert b.is_valid_transaction(tx) == tx
@ -891,7 +876,7 @@ class TestMultipleInputs(object):
def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_pk):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink, TransactionLink
from bigchaindb.common.transaction import TransactionLink
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
@ -907,7 +892,7 @@ class TestMultipleInputs(object):
assert owned_inputs_user2 == []
tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
AssetLink(tx.id))
asset_id=tx.id)
tx = tx.sign([user_sk])
block = b.create_block([tx])
b.write_block(block)
@ -922,7 +907,7 @@ class TestMultipleInputs(object):
user_pk,
genesis_block):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink, TransactionLink
from bigchaindb.common.transaction import TransactionLink
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
@ -944,7 +929,7 @@ class TestMultipleInputs(object):
# NOTE: The transaction itself is valid, still will mark the block
# as invalid to mock the behavior.
tx_invalid = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
AssetLink(tx.id))
asset_id=tx.id)
tx_invalid = tx_invalid.sign([user_sk])
block = b.create_block([tx_invalid])
b.write_block(block)
@ -963,17 +948,13 @@ class TestMultipleInputs(object):
def test_get_owned_ids_single_tx_multiple_outputs(self, b, user_sk,
user_pk):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import (TransactionLink, Asset,
AssetLink)
from bigchaindb.common.transaction import TransactionLink
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
# create divisible asset
asset = Asset()
tx_create = Transaction.create([b.me],
[([user_pk], 1), ([user_pk], 1)],
asset=asset)
tx_create = Transaction.create([b.me], [([user_pk], 1), ([user_pk], 1)])
tx_create_signed = tx_create.sign([b.me_private])
block = b.create_block([tx_create_signed])
b.write_block(block)
@ -990,7 +971,7 @@ class TestMultipleInputs(object):
# transfer divisible asset divided in two outputs
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([user2_pk], 1), ([user2_pk], 1)],
asset_link=AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
block = b.create_block([tx_transfer_signed])
b.write_block(block)
@ -1003,7 +984,7 @@ class TestMultipleInputs(object):
def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink, TransactionLink
from bigchaindb.common.transaction import TransactionLink
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
@ -1022,7 +1003,7 @@ class TestMultipleInputs(object):
assert owned_inputs_user1 == expected_owned_inputs_user1
tx = Transaction.transfer(tx.to_inputs(), [([user3_pk], 1)],
AssetLink(tx.id))
asset_id=tx.id)
tx = tx.sign([user_sk, user2_sk])
block = b.create_block([tx])
b.write_block(block)
@ -1034,7 +1015,6 @@ class TestMultipleInputs(object):
def test_get_spent_single_tx_single_output(self, b, user_sk, user_pk):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
@ -1054,7 +1034,7 @@ class TestMultipleInputs(object):
# create a transaction and block
tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
AssetLink(tx.id))
asset_id=tx.id)
tx = tx.sign([user_sk])
block = b.create_block([tx])
b.write_block(block)
@ -1067,7 +1047,6 @@ class TestMultipleInputs(object):
user_pk,
genesis_block):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
# create a new users
@ -1092,7 +1071,7 @@ class TestMultipleInputs(object):
# create a transaction and block
tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
AssetLink(tx.id))
asset_id=tx.id)
tx = tx.sign([user_sk])
block = b.create_block([tx])
b.write_block(block)
@ -1109,19 +1088,16 @@ class TestMultipleInputs(object):
def test_get_spent_single_tx_multiple_outputs(self, b, user_sk, user_pk):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import Asset, AssetLink
from bigchaindb.models import Transaction
# create a new users
user2_sk, user2_pk = crypto.generate_key_pair()
# create a divisible asset with 3 outputs
asset = Asset()
tx_create = Transaction.create([b.me],
[([user_pk], 1),
([user_pk], 1),
([user_pk], 1)],
asset=asset)
([user_pk], 1)])
tx_create_signed = tx_create.sign([b.me_private])
block = b.create_block([tx_create_signed])
b.write_block(block)
@ -1135,7 +1111,7 @@ class TestMultipleInputs(object):
# transfer the first 2 inputs
tx_transfer = Transaction.transfer(tx_create.to_inputs()[:2],
[([user2_pk], 1), ([user2_pk], 1)],
asset_link=AssetLink(tx_create.id))
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
block = b.create_block([tx_transfer_signed])
b.write_block(block)
@ -1151,7 +1127,6 @@ class TestMultipleInputs(object):
def test_get_spent_multiple_owners(self, b, user_sk, user_pk):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
@ -1176,7 +1151,7 @@ class TestMultipleInputs(object):
# create a transaction
tx = Transaction.transfer(transactions[0].to_inputs(),
[([user3_pk], 1)],
AssetLink(transactions[0].id))
asset_id=transactions[0].id)
tx = tx.sign([user_sk, user2_sk])
block = b.create_block([tx])
b.write_block(block)

View File

@ -271,7 +271,6 @@ def test_valid_block_voting_with_transfer_transactions(monkeypatch,
b, genesis_block):
from bigchaindb.backend import query
from bigchaindb.common import crypto, util
from bigchaindb.common.transaction import AssetLink
from bigchaindb.models import Transaction
from bigchaindb.pipelines import vote
@ -287,7 +286,7 @@ def test_valid_block_voting_with_transfer_transactions(monkeypatch,
# create a `TRANSFER` transaction
test_user2_priv, test_user2_pub = crypto.generate_key_pair()
tx2 = Transaction.transfer(tx.to_inputs(), [([test_user2_pub], 1)],
AssetLink(tx.id))
asset_id=tx.id)
tx2 = tx2.sign([test_user_priv])
monkeypatch.setattr('time.time', lambda: 2222222222)

View File

@ -127,7 +127,6 @@ def test_post_invalid_transaction(client, exc, msg, monkeypatch):
def test_post_transfer_transaction_endpoint(b, client, user_pk, user_sk):
sk, pk = crypto.generate_key_pair()
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import AssetLink
user_priv, user_pub = crypto.generate_key_pair()
@ -135,7 +134,7 @@ def test_post_transfer_transaction_endpoint(b, client, user_pk, user_sk):
create_tx = b.get_transaction(input_valid.txid)
transfer_tx = Transaction.transfer(create_tx.to_inputs(),
[([user_pub], 1)],
AssetLink(create_tx.id))
asset_id=create_tx.id)
transfer_tx = transfer_tx.sign([user_sk])
res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict()))
@ -148,7 +147,6 @@ def test_post_transfer_transaction_endpoint(b, client, user_pk, user_sk):
@pytest.mark.usefixtures('inputs')
def test_post_invalid_transfer_transaction_returns_400(b, client, user_pk, user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import AssetLink
user_priv, user_pub = crypto.generate_key_pair()
@ -156,7 +154,7 @@ def test_post_invalid_transfer_transaction_returns_400(b, client, user_pk, user_
create_tx = b.get_transaction(input_valid.txid)
transfer_tx = Transaction.transfer(create_tx.to_inputs(),
[([user_pub], 1)],
AssetLink(create_tx.id))
asset_id=create_tx.id)
res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict()))
assert res.status_code == 400