mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-06-28 00:27:45 +02:00
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:
parent
1d7a8e3369
commit
7e33f2bd52
|
@ -111,12 +111,12 @@ def get_blocks_status_from_transaction(connection, transaction_id):
|
|||
def get_txids_by_asset_id(connection, asset_id):
|
||||
"""Retrieves transactions ids related to a particular asset.
|
||||
|
||||
A digital asset in bigchaindb is identified by an uuid. This allows us
|
||||
to query all the transactions related to a particular digital asset,
|
||||
knowing the id.
|
||||
A digital asset in bigchaindb is identified by its ``CREATE``
|
||||
transaction's ID. Knowing this ID allows us to query all the
|
||||
transactions related to a particular digital asset.
|
||||
|
||||
Args:
|
||||
asset_id (str): the id for this particular metadata.
|
||||
asset_id (str): the ID of the asset.
|
||||
|
||||
Returns:
|
||||
A list of transactions ids related to the asset. If no transaction
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from itertools import chain
|
||||
from time import time
|
||||
|
||||
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):
|
||||
# here we only want to return the transaction ids since later on when
|
||||
# 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')
|
||||
.get_all(asset_id, index='asset_id')
|
||||
.concat_map(lambda block: block['block']['transactions'])
|
||||
.filter(lambda transaction: transaction['asset']['id'] == asset_id)
|
||||
.get_field('id'))
|
||||
|
||||
return chain(create_tx_cursor, transfer_tx_cursor)
|
||||
|
||||
|
||||
@register_query(RethinkDBConnection)
|
||||
def get_asset_by_id(connection, asset_id):
|
||||
return connection.run(
|
||||
r.table('bigchain', read_mode=READ_MODE)
|
||||
.get_all(asset_id, index='asset_id')
|
||||
.concat_map(lambda block: block['block']['transactions'])
|
||||
.filter(lambda transaction: transaction['asset']['id'] == asset_id)
|
||||
.filter(lambda transaction: transaction['operation'] == 'CREATE')
|
||||
.pluck('asset'))
|
||||
return connection.run(_get_asset_create_tx_query(asset_id).pluck('asset'))
|
||||
|
||||
|
||||
def _get_asset_create_tx_query(asset_id):
|
||||
return r.table('bigchain', read_mode=READ_MODE) \
|
||||
.get_all(asset_id, index='transaction_id') \
|
||||
.concat_map(lambda block: block['block']['transactions']) \
|
||||
.filter(lambda transaction: transaction['id'] == asset_id)
|
||||
|
||||
|
||||
@register_query(RethinkDBConnection)
|
||||
|
|
|
@ -60,7 +60,7 @@ def create_bigchain_secondary_index(connection, dbname):
|
|||
.table('bigchain')
|
||||
.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(
|
||||
r.db(dbname)
|
||||
.table('bigchain')
|
||||
|
|
|
@ -105,13 +105,14 @@ definitions:
|
|||
description: |
|
||||
Description of the asset being transacted. In the case of a ``TRANSFER``
|
||||
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
|
||||
required:
|
||||
- id
|
||||
properties:
|
||||
id:
|
||||
"$ref": "#/definitions/uuid4"
|
||||
"$ref": "#/definitions/sha3_hexdigest"
|
||||
description: |
|
||||
ID of the transaction that created the asset.
|
||||
data:
|
||||
description: |
|
||||
User provided metadata associated with the asset. May also be ``null``.
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from copy import deepcopy
|
||||
from functools import reduce
|
||||
from uuid import uuid4
|
||||
|
||||
from cryptoconditions import (Fulfillment as CCFulfillment,
|
||||
ThresholdSha256Fulfillment, Ed25519Fulfillment)
|
||||
|
@ -384,14 +383,11 @@ class Asset(object):
|
|||
|
||||
Attributes:
|
||||
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."""
|
||||
self.data = data
|
||||
self.data_id = data_id if data_id is not None else self.to_hash()
|
||||
|
||||
self.validate_asset()
|
||||
|
||||
def __eq__(self, other):
|
||||
|
@ -409,7 +405,6 @@ class Asset(object):
|
|||
format.
|
||||
"""
|
||||
return {
|
||||
'id': self.data_id,
|
||||
'data': self.data,
|
||||
}
|
||||
|
||||
|
@ -423,38 +418,37 @@ class Asset(object):
|
|||
Returns:
|
||||
:class:`~bigchaindb.common.transaction.Asset`
|
||||
"""
|
||||
return cls(asset.get('data'), asset['id'])
|
||||
|
||||
def to_hash(self):
|
||||
"""Generates a unqiue uuid for an Asset"""
|
||||
return str(uuid4())
|
||||
return cls(asset.get('data'))
|
||||
|
||||
@staticmethod
|
||||
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
|
||||
transaction are related to the same asset id.
|
||||
|
||||
Args:
|
||||
transactions (:obj:`list` of :class:`~bigchaindb.common.
|
||||
transaction.Transaction`): list of transaction usually inputs
|
||||
that should have a matching asset_id
|
||||
transaction.Transaction`): A list of Transactions.
|
||||
Usually input Transactions that should have a matching
|
||||
asset ID.
|
||||
|
||||
Returns:
|
||||
str: uuid of the asset.
|
||||
str: ID of the asset.
|
||||
|
||||
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):
|
||||
transactions = [transactions]
|
||||
|
||||
# create a set of asset_ids
|
||||
asset_ids = {tx.asset.data_id for tx in 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
|
||||
# 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'))
|
||||
|
@ -475,20 +469,20 @@ class Asset(object):
|
|||
raise AmountError('`amount` must be greater than 0')
|
||||
|
||||
|
||||
class AssetLink(Asset):
|
||||
class AssetLink(object):
|
||||
"""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.
|
||||
|
||||
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):
|
||||
return self.data_id is not None
|
||||
return self.id is not None
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, AssetLink) and \
|
||||
|
@ -514,12 +508,14 @@ class AssetLink(Asset):
|
|||
|
||||
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.data_id is None:
|
||||
if self.id is None:
|
||||
return None
|
||||
else:
|
||||
return {
|
||||
'id': self.data_id
|
||||
'id': self.id
|
||||
}
|
||||
|
||||
|
||||
|
@ -537,6 +533,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.
|
||||
metadata (dict):
|
||||
Metadata to be stored along with the Transaction.
|
||||
version (int): Defines the version number of a Transaction.
|
||||
|
@ -557,8 +557,8 @@ class Transaction(object):
|
|||
|
||||
Args:
|
||||
operation (str): Defines the operation of the Transaction.
|
||||
asset (:class:`~bigchaindb.common.transaction.Asset`): An Asset
|
||||
to be transferred or created in a Transaction.
|
||||
asset (:class:`~.Asset`|:class:`~.AssetLink`): An Asset to be
|
||||
created or an AssetLink linking an asset to be transferred.
|
||||
fulfillments (:obj:`list` of :class:`~bigchaindb.common.
|
||||
transaction.Fulfillment`, optional): Define the assets to
|
||||
spend.
|
||||
|
@ -575,10 +575,17 @@ class Transaction(object):
|
|||
raise ValueError('`operation` must be one of {}'
|
||||
.format(allowed_ops))
|
||||
|
||||
# Only assets for 'CREATE' operations can be un-defined.
|
||||
if (asset and not isinstance(asset, Asset) or
|
||||
not asset and operation != Transaction.CREATE):
|
||||
raise TypeError('`asset` must be an Asset instance')
|
||||
# Assets for 'CREATE' and 'GENESIS' operations must be None or of Asset
|
||||
# type and Assets for 'TRANSFER' operations must be of AssetLink type.
|
||||
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)))
|
||||
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):
|
||||
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.operation = operation
|
||||
self.asset = asset if asset else Asset()
|
||||
self.conditions = conditions if conditions else []
|
||||
self.fulfillments = fulfillments if fulfillments else []
|
||||
self.asset = asset or Asset()
|
||||
self.conditions = conditions or []
|
||||
self.fulfillments = fulfillments or []
|
||||
self.metadata = metadata
|
||||
|
||||
# validate asset
|
||||
|
@ -659,7 +666,7 @@ class Transaction(object):
|
|||
return cls(cls.CREATE, asset, fulfillments, conditions, metadata)
|
||||
|
||||
@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.
|
||||
|
||||
Note:
|
||||
|
@ -689,8 +696,9 @@ class Transaction(object):
|
|||
generate.
|
||||
owners_after (:obj:`list` of :obj:`str`): A list of keys that
|
||||
represent the receivers of this Transaction.
|
||||
asset (:class:`~bigchaindb.common.transaction.Asset`): An Asset
|
||||
to be transferred in this Transaction.
|
||||
asset_link (:class:`~bigchaindb.common.transaction.AssetLink`):
|
||||
An AssetLink linking an asset to be transferred in this
|
||||
Transaction.
|
||||
metadata (dict): Python dictionary to be stored along with the
|
||||
Transaction.
|
||||
|
||||
|
@ -716,7 +724,7 @@ class Transaction(object):
|
|||
conditions.append(Condition.generate(pub_keys, amount))
|
||||
|
||||
inputs = deepcopy(inputs)
|
||||
return cls(cls.TRANSFER, asset, inputs, conditions, metadata)
|
||||
return cls(cls.TRANSFER, asset_link, inputs, conditions, metadata)
|
||||
|
||||
def __eq__(self, other):
|
||||
try:
|
||||
|
@ -1056,12 +1064,6 @@ class Transaction(object):
|
|||
Returns:
|
||||
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 = {
|
||||
'fulfillments': [fulfillment.to_dict() for fulfillment
|
||||
in self.fulfillments],
|
||||
|
@ -1069,7 +1071,7 @@ class Transaction(object):
|
|||
in self.conditions],
|
||||
'operation': str(self.operation),
|
||||
'metadata': self.metadata,
|
||||
'asset': asset,
|
||||
'asset': self.asset.to_dict(),
|
||||
'version': self.version,
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ class Transaction(Transaction):
|
|||
|
||||
# validate asset id
|
||||
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'
|
||||
' match the asset id of the'
|
||||
' transaction'))
|
||||
|
|
|
@ -62,7 +62,7 @@ def main():
|
|||
""" Main function """
|
||||
privkey = 'CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z'
|
||||
pubkey = '4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD'
|
||||
asset = Asset(None, 'e6969f87-4fc9-4467-b62a-f0dfa1c85002')
|
||||
asset = Asset(None)
|
||||
tx = Transaction.create([pubkey], [([pubkey], 1)], asset=asset)
|
||||
tx = tx.sign([privkey])
|
||||
tx_json = json.dumps(tx.to_dict(), indent=2, sort_keys=True)
|
||||
|
|
|
@ -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:
|
||||
```json
|
||||
{
|
||||
"id": "<uuid>",
|
||||
"data": "<json document>"
|
||||
}
|
||||
```
|
||||
|
||||
For `TRANSFER` transactions we only keep the asset id.
|
||||
For `TRANSFER` transactions we only keep the asset ID:
|
||||
```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.
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
import pytest
|
||||
import random
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
@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)],
|
||||
tx_create.asset)
|
||||
AssetLink(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.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):
|
||||
|
@ -32,13 +34,14 @@ 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)],
|
||||
tx_create.asset)
|
||||
tx_transfer.asset.data_id = 'aaa'
|
||||
AssetLink(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)
|
||||
|
@ -50,18 +53,19 @@ def test_get_asset_id_create_transaction(b, user_pk):
|
|||
tx_create = Transaction.create([b.me], [([user_pk], 1)])
|
||||
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')
|
||||
def test_get_asset_id_transfer_transaction(b, user_pk, user_sk):
|
||||
from bigchaindb.common.transaction import AssetLink
|
||||
from bigchaindb.models import Transaction, Asset
|
||||
|
||||
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)],
|
||||
tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
# create a block
|
||||
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)
|
||||
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):
|
||||
from bigchaindb.models import Transaction, Asset
|
||||
from bigchaindb.common.exceptions import AssetIdMismatch
|
||||
|
||||
tx1 = Transaction.create([b.me], [([user_pk], 1)])
|
||||
tx2 = Transaction.create([b.me], [([user_pk], 1)])
|
||||
tx1 = 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):
|
||||
Asset.get_asset_id([tx1, tx2])
|
||||
|
@ -87,20 +93,21 @@ def test_asset_id_mismatch(b, user_pk):
|
|||
|
||||
@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()
|
||||
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)
|
||||
|
||||
assert len(txs) == 1
|
||||
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
|
||||
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])
|
||||
# create the block
|
||||
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 tx_create.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
|
||||
assert asset_id == txs[1].asset.data_id
|
||||
# FIXME: can I rely on the ordering here?
|
||||
assert asset_id == txs[0].id
|
||||
assert asset_id == txs[1].asset.id
|
||||
|
||||
|
||||
@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()
|
||||
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)
|
||||
|
||||
assert len(txs) == 1
|
||||
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
|
||||
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])
|
||||
# create the block
|
||||
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')
|
||||
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_transaction(tx_create.txid)
|
||||
asset_id = tx_create.asset.data_id
|
||||
|
||||
# create a transfer transaction
|
||||
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])
|
||||
# create the block
|
||||
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)
|
||||
b.write_vote(vote)
|
||||
|
||||
asset_id = Asset.get_asset_id([tx_create, tx_transfer])
|
||||
txs = b.get_transactions_by_asset_id(asset_id)
|
||||
assert len(txs) == 2
|
||||
|
||||
|
|
|
@ -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,
|
||||
user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
|
||||
# CREATE divisible asset
|
||||
asset = Asset()
|
||||
|
@ -146,7 +146,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)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
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,
|
||||
user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
|
||||
# CREATE divisible asset
|
||||
asset = Asset()
|
||||
|
@ -181,7 +181,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)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
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,
|
||||
user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
|
||||
# CREATE divisible asset
|
||||
asset = Asset()
|
||||
|
@ -217,7 +217,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)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
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,
|
||||
user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
|
||||
# CREATE divisible asset
|
||||
asset = Asset()
|
||||
|
@ -258,7 +258,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)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
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,
|
||||
user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
|
||||
# CREATE divisible asset
|
||||
asset = Asset()
|
||||
|
@ -299,7 +299,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)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
|
||||
|
||||
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,
|
||||
user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
|
||||
# CREATE divisible asset
|
||||
asset = Asset()
|
||||
|
@ -338,7 +338,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)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
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,
|
||||
user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
|
||||
# CREATE divisible asset
|
||||
asset = Asset()
|
||||
|
@ -375,7 +375,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)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
|
||||
|
||||
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,
|
||||
user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
|
||||
# CREATE divisible asset
|
||||
asset = Asset()
|
||||
|
@ -420,7 +420,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)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
|
||||
|
||||
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,
|
||||
user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
|
||||
# CREATE divisible asset
|
||||
asset = Asset()
|
||||
|
@ -466,7 +466,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)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
|
||||
|
||||
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')
|
||||
def test_multiple_in_different_transactions(b, user_pk, user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
|
||||
# CREATE divisible asset
|
||||
# `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
|
||||
tx_transfer1 = Transaction.transfer(tx_create.to_inputs([1]),
|
||||
[([user_pk], 50)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer1_signed = tx_transfer1.sign([b.me_private])
|
||||
# create block
|
||||
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_transfer1.to_inputs([0]),
|
||||
[([b.me], 100)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer2_signed = tx_transfer2.sign([user_sk])
|
||||
|
||||
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')
|
||||
def test_amount_error_transfer(b, user_pk, user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
from bigchaindb.common.exceptions import AmountError
|
||||
|
||||
# CREATE divisible asset
|
||||
|
@ -575,7 +575,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)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
with pytest.raises(AmountError):
|
||||
tx_transfer_signed.validate(b)
|
||||
|
@ -583,7 +583,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)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
with pytest.raises(AmountError):
|
||||
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.
|
||||
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
|
||||
# CREATE divisible asset
|
||||
asset = Asset()
|
||||
|
@ -617,7 +617,7 @@ def test_threshold_same_public_key(b, user_pk, user_sk):
|
|||
|
||||
# TRANSFER
|
||||
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])
|
||||
|
||||
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')
|
||||
def test_sum_amount(b, user_pk, user_sk):
|
||||
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
|
||||
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
|
||||
# is 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])
|
||||
|
||||
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')
|
||||
def test_divide(b, user_pk, user_sk):
|
||||
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
|
||||
asset = Asset()
|
||||
|
@ -677,7 +677,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)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
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')
|
||||
def test_non_positive_amounts_on_transfer(b, user_pk):
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.transaction import Asset
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
from bigchaindb.common.exceptions import AmountError
|
||||
|
||||
# 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):
|
||||
Transaction.transfer(tx_create.to_inputs(),
|
||||
[([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
|
||||
@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
|
||||
from bigchaindb.common.transaction import Asset, AssetLink
|
||||
from bigchaindb.common.exceptions import AmountError
|
||||
|
||||
# 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
|
||||
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
|
||||
[([b.me], 4), ([b.me], 1)],
|
||||
asset=tx_create.asset)
|
||||
AssetLink(tx_create.id))
|
||||
tx_transfer.conditions[1].amount = -1
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
|
|
|
@ -17,9 +17,6 @@ CC_CONDITION_URI = 'cc:0:3:47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU:0'
|
|||
DATA = {
|
||||
'msg': 'Hello BigchainDB!'
|
||||
}
|
||||
DATA_ID = '872fa6e6f46246cd44afdb2ee9cfae0e72885fb0910e2bcf9a5a2a4eadb417b8'
|
||||
|
||||
UUID4 = 'dc568f27-a113-46b4-9bd4-43015859e3e3'
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -126,16 +123,6 @@ def data():
|
|||
return DATA
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def data_id():
|
||||
return DATA_ID
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def uuid4():
|
||||
return UUID4
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def utx(user_ffill, user_cond):
|
||||
from bigchaindb.common.transaction import Transaction, Asset
|
||||
|
@ -150,12 +137,12 @@ def tx(utx, user_priv):
|
|||
@pytest.fixture
|
||||
def transfer_utx(user_cond, user2_cond, utx):
|
||||
from bigchaindb.common.transaction import (Fulfillment, TransactionLink,
|
||||
Transaction, Asset)
|
||||
Transaction, AssetLink)
|
||||
user_cond = user_cond.to_dict()
|
||||
ffill = Fulfillment(utx.conditions[0].fulfillment,
|
||||
user_cond['owners_after'],
|
||||
TransactionLink(utx.id, 0))
|
||||
return Transaction('TRANSFER', Asset(), [ffill], [user2_cond])
|
||||
return Transaction('TRANSFER', AssetLink(utx.id), [ffill], [user2_cond])
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
|
@ -6,7 +6,6 @@ def test_asset_default_values():
|
|||
|
||||
asset = Asset()
|
||||
assert asset.data is None
|
||||
assert asset.data_id
|
||||
|
||||
|
||||
def test_asset_creation_with_data(data):
|
||||
|
@ -24,32 +23,30 @@ def test_asset_invalid_asset_initialization():
|
|||
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
|
||||
|
||||
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
|
||||
|
||||
expected = {
|
||||
'id': data_id,
|
||||
'data': data,
|
||||
}
|
||||
asset = Asset(data, data_id)
|
||||
asset = Asset(data)
|
||||
assert asset.to_dict() == expected
|
||||
|
||||
|
||||
def test_asset_deserialization(data, data_id):
|
||||
def test_asset_deserialization(data):
|
||||
from bigchaindb.common.transaction import Asset
|
||||
|
||||
asset_dict = {
|
||||
'id': data_id,
|
||||
'data': data,
|
||||
}
|
||||
asset = Asset.from_dict(asset_dict)
|
||||
expected = Asset(data, data_id)
|
||||
expected = Asset(data)
|
||||
assert asset == expected
|
||||
|
||||
|
||||
|
|
|
@ -274,27 +274,17 @@ def test_invalid_transaction_initialization():
|
|||
|
||||
def test_create_default_asset_on_tx_initialization():
|
||||
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):
|
||||
tx = Transaction(Transaction.CREATE, None)
|
||||
expected = Asset()
|
||||
asset = tx.asset
|
||||
|
||||
expected.data_id = None
|
||||
asset.data_id = None
|
||||
assert asset == expected
|
||||
|
||||
# Fails because no asset hash
|
||||
with raises(ValidationError):
|
||||
validate_transaction_model(tx)
|
||||
|
||||
|
||||
def test_transaction_serialization(user_ffill, user_cond, data, data_id):
|
||||
def test_transaction_serialization(user_ffill, user_cond, data):
|
||||
from bigchaindb.common.transaction import Transaction, Asset
|
||||
from bigchaindb.common.exceptions import ValidationError
|
||||
from .util import validate_transaction_model
|
||||
|
||||
tx_id = 'l0l'
|
||||
|
||||
|
@ -308,30 +298,23 @@ def test_transaction_serialization(user_ffill, user_cond, data, data_id):
|
|||
'operation': Transaction.CREATE,
|
||||
'metadata': None,
|
||||
'asset': {
|
||||
'id': data_id,
|
||||
'data': data,
|
||||
}
|
||||
}
|
||||
|
||||
tx = Transaction(Transaction.CREATE, Asset(data, data_id), [user_ffill],
|
||||
tx = Transaction(Transaction.CREATE, Asset(data), [user_ffill],
|
||||
[user_cond])
|
||||
tx_dict = tx.to_dict()
|
||||
tx_dict['id'] = tx_id
|
||||
tx_dict['asset']['id'] = data_id
|
||||
|
||||
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, uuid4):
|
||||
def test_transaction_deserialization(user_ffill, user_cond, data):
|
||||
from bigchaindb.common.transaction import Transaction, Asset
|
||||
from .util import validate_transaction_model
|
||||
|
||||
|
||||
expected_asset = Asset(data, uuid4)
|
||||
expected_asset = Asset(data)
|
||||
expected = Transaction(Transaction.CREATE, expected_asset, [user_ffill],
|
||||
[user_cond], None, Transaction.VERSION)
|
||||
|
||||
|
@ -344,7 +327,6 @@ def test_transaction_deserialization(user_ffill, user_cond, data, uuid4):
|
|||
'operation': Transaction.CREATE,
|
||||
'metadata': None,
|
||||
'asset': {
|
||||
'id': uuid4,
|
||||
'data': data,
|
||||
}
|
||||
}
|
||||
|
@ -453,11 +435,11 @@ def test_cast_transaction_link_to_boolean():
|
|||
def test_asset_link_serialization():
|
||||
from bigchaindb.common.transaction import AssetLink
|
||||
|
||||
data_id = 'a asset id'
|
||||
asset_id = 'a asset id'
|
||||
expected = {
|
||||
'id': data_id,
|
||||
'id': asset_id,
|
||||
}
|
||||
asset_link = AssetLink(data_id)
|
||||
asset_link = AssetLink(asset_id)
|
||||
|
||||
assert asset_link.to_dict() == expected
|
||||
|
||||
|
@ -474,10 +456,10 @@ def test_asset_link_serialization_with_empty_payload():
|
|||
def test_asset_link_deserialization():
|
||||
from bigchaindb.common.transaction import AssetLink
|
||||
|
||||
data_id = 'a asset id'
|
||||
expected = AssetLink(data_id)
|
||||
asset_id = 'a asset id'
|
||||
expected = AssetLink(asset_id)
|
||||
asset_link = {
|
||||
'id': data_id
|
||||
'id': asset_id
|
||||
}
|
||||
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):
|
||||
from copy import deepcopy
|
||||
from bigchaindb.common.transaction import (Transaction, TransactionLink,
|
||||
Fulfillment, Condition, Asset)
|
||||
Fulfillment, Condition, Asset,
|
||||
AssetLink)
|
||||
from cryptoconditions import Ed25519Fulfillment
|
||||
from .util import validate_transaction_model
|
||||
|
||||
|
@ -702,7 +685,8 @@ 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', tx.asset, fulfillments, conditions)
|
||||
transfer_tx = Transaction('TRANSFER', AssetLink(tx.id),
|
||||
fulfillments, conditions)
|
||||
transfer_tx = transfer_tx.sign([user_priv])
|
||||
|
||||
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]])
|
||||
|
||||
|
||||
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 .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()],
|
||||
'metadata': data,
|
||||
'asset': {
|
||||
'id': uuid4,
|
||||
'data': data,
|
||||
},
|
||||
'fulfillments': [
|
||||
|
@ -759,7 +742,7 @@ def test_create_create_transaction_single_io(user_cond, user_pub, data, uuid4):
|
|||
'version': 1,
|
||||
}
|
||||
|
||||
asset = Asset(data, uuid4)
|
||||
asset = Asset(data)
|
||||
tx = Transaction.create([user_pub], [([user_pub], 1)], data, asset)
|
||||
tx_dict = tx.to_dict()
|
||||
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,
|
||||
user_user2_threshold_cond,
|
||||
user_user2_threshold_ffill, data,
|
||||
uuid4):
|
||||
user_user2_threshold_ffill, data):
|
||||
from bigchaindb.common.transaction import Transaction, Asset
|
||||
|
||||
expected = {
|
||||
'conditions': [user_user2_threshold_cond.to_dict()],
|
||||
'metadata': data,
|
||||
'asset': {
|
||||
'id': uuid4,
|
||||
'data': data,
|
||||
},
|
||||
'fulfillments': [
|
||||
|
@ -846,7 +827,7 @@ def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub,
|
|||
'operation': 'CREATE',
|
||||
'version': 1
|
||||
}
|
||||
asset = Asset(data, uuid4)
|
||||
asset = Asset(data)
|
||||
tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)],
|
||||
data, asset)
|
||||
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):
|
||||
from bigchaindb.common.transaction import Transaction
|
||||
from bigchaindb.common.transaction import Transaction, AssetLink
|
||||
|
||||
with raises(TypeError):
|
||||
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])
|
||||
with raises(ValueError):
|
||||
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):
|
||||
|
@ -897,10 +885,10 @@ def test_conditions_to_inputs(tx):
|
|||
|
||||
|
||||
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 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 .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()],
|
||||
'metadata': None,
|
||||
'asset': {
|
||||
'id': uuid4,
|
||||
'id': tx.id,
|
||||
},
|
||||
'fulfillments': [
|
||||
{
|
||||
|
@ -926,8 +914,8 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
|
|||
'version': 1
|
||||
}
|
||||
inputs = tx.to_inputs([0])
|
||||
asset = Asset(None, uuid4)
|
||||
transfer_tx = Transaction.transfer(inputs, [([user2_pub], 1)], asset=asset)
|
||||
transfer_tx = Transaction.transfer(inputs, [([user2_pub], 1)],
|
||||
asset_link=AssetLink(tx.id))
|
||||
transfer_tx = transfer_tx.sign([user_priv])
|
||||
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,
|
||||
user2_pub, user2_priv,
|
||||
user3_pub, user2_cond):
|
||||
from bigchaindb.common.transaction import Transaction, Asset
|
||||
from bigchaindb.common.transaction import Transaction, Asset, AssetLink
|
||||
|
||||
asset = Asset()
|
||||
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(),
|
||||
[([user2_pub], 1), ([user2_pub], 1)],
|
||||
asset=tx.asset)
|
||||
asset_link=AssetLink(tx.id))
|
||||
transfer_tx = transfer_tx.sign([user_priv, user2_priv])
|
||||
|
||||
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
|
||||
|
||||
|
||||
def test_create_transfer_with_invalid_parameters(user_pub):
|
||||
from bigchaindb.common.transaction import Transaction, Asset
|
||||
def test_create_transfer_with_invalid_parameters(tx, user_pub):
|
||||
from bigchaindb.common.transaction import Transaction, Asset, AssetLink
|
||||
mock_asset_link = AssetLink(tx.id)
|
||||
|
||||
with raises(TypeError):
|
||||
Transaction.transfer({}, [], Asset())
|
||||
Transaction.transfer({}, [], mock_asset_link)
|
||||
with raises(ValueError):
|
||||
Transaction.transfer([], [], Asset())
|
||||
Transaction.transfer([], [], mock_asset_link)
|
||||
with raises(TypeError):
|
||||
Transaction.transfer(['fulfillment'], {}, Asset())
|
||||
Transaction.transfer(['fulfillment'], {}, mock_asset_link)
|
||||
with raises(ValueError):
|
||||
Transaction.transfer(['fulfillment'], [], Asset())
|
||||
Transaction.transfer(['fulfillment'], [], mock_asset_link)
|
||||
with raises(ValueError):
|
||||
Transaction.transfer(['fulfillment'], [user_pub], Asset())
|
||||
Transaction.transfer(['fulfillment'], [user_pub], mock_asset_link)
|
||||
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():
|
||||
|
|
|
@ -8,6 +8,7 @@ Tasks:
|
|||
|
||||
import os
|
||||
import copy
|
||||
import random
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -123,9 +124,12 @@ 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)], signed_create_tx.asset)
|
||||
tx = Transaction.transfer(inputs,
|
||||
[([user_pk], 1)],
|
||||
AssetLink(signed_create_tx.id))
|
||||
return tx.sign([user_sk])
|
||||
|
||||
|
||||
|
@ -188,8 +192,10 @@ def inputs(user_pk, setup_database):
|
|||
prev_block_id = g.id
|
||||
for block in range(4):
|
||||
transactions = [
|
||||
Transaction.create([b.me], [([user_pk], 1)]).sign([b.me_private])
|
||||
for i in range(10)
|
||||
Transaction.create([b.me], [([user_pk], 1)],
|
||||
metadata={'msg': random.random()})
|
||||
.sign([b.me_private])
|
||||
for _ in range(10)
|
||||
]
|
||||
block = b.create_block(transactions)
|
||||
b.write_block(block)
|
||||
|
@ -216,9 +222,10 @@ def inputs_shared(user_pk, user2_pk, setup_database):
|
|||
prev_block_id = g.id
|
||||
for block in range(4):
|
||||
transactions = [
|
||||
Transaction.create(
|
||||
[b.me], [user_pk, user2_pk], payload={'i': i}).sign([b.me_private])
|
||||
for i in range(10)
|
||||
Transaction.create([b.me], [user_pk, user2_pk],
|
||||
metadata={'msg': random.random()})
|
||||
.sign([b.me_private])
|
||||
for _ in range(10)
|
||||
]
|
||||
block = b.create_block(transactions)
|
||||
b.write_block(block)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from time import sleep
|
||||
|
||||
import pytest
|
||||
import random
|
||||
|
||||
|
||||
@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):
|
||||
from bigchaindb.common.exceptions import DoubleSpend
|
||||
from bigchaindb.common.transaction import AssetLink
|
||||
from bigchaindb.models import Transaction
|
||||
|
||||
b.create_genesis_block()
|
||||
|
@ -104,14 +106,14 @@ class TestBigchainApi(object):
|
|||
|
||||
monkeypatch.setattr('time.time', lambda: 2)
|
||||
transfer_tx = Transaction.transfer(tx.to_inputs(), [([b.me], 1)],
|
||||
tx.asset)
|
||||
AssetLink(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)],
|
||||
tx.asset)
|
||||
AssetLink(tx.id))
|
||||
transfer_tx2 = transfer_tx2.sign([b.me_private])
|
||||
block3 = b.create_block([transfer_tx2])
|
||||
b.write_block(block3)
|
||||
|
@ -157,13 +159,15 @@ class TestBigchainApi(object):
|
|||
b.create_genesis_block()
|
||||
|
||||
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])
|
||||
block1 = b.create_block([tx1])
|
||||
b.write_block(block1)
|
||||
|
||||
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])
|
||||
block2 = b.create_block([tx2])
|
||||
b.write_block(block2)
|
||||
|
@ -181,12 +185,14 @@ 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)], input_tx.asset)
|
||||
tx = Transaction.transfer(inputs, [([user_pk], 1)],
|
||||
AssetLink(input_tx.id))
|
||||
tx = tx.sign([user_sk])
|
||||
response = b.write_transaction(tx)
|
||||
|
||||
|
@ -199,12 +205,14 @@ 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)], input_tx.asset)
|
||||
tx = Transaction.transfer(inputs, [([user_pk], 1)],
|
||||
AssetLink(input_tx.id))
|
||||
tx = tx.sign([user_sk])
|
||||
b.write_transaction(tx)
|
||||
|
||||
|
@ -219,12 +227,14 @@ 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)], input_tx.asset)
|
||||
tx = Transaction.transfer(inputs, [([user_pk], 1)],
|
||||
AssetLink(input_tx.id))
|
||||
tx = tx.sign([user_sk])
|
||||
# There's no need to b.write_transaction(tx) to the backlog
|
||||
|
||||
|
@ -243,12 +253,14 @@ 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)], input_tx.asset)
|
||||
tx = Transaction.transfer(inputs, [([user_pk], 1)],
|
||||
AssetLink(input_tx.id))
|
||||
tx = tx.sign([user_sk])
|
||||
|
||||
# Make sure there's a copy of tx in the backlog
|
||||
|
@ -482,12 +494,14 @@ 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)], input_tx.asset)
|
||||
tx = Transaction.transfer(inputs, [([user_pk], 1)],
|
||||
AssetLink(input_tx.id))
|
||||
tx = tx.sign([user_sk])
|
||||
b.write_transaction(tx)
|
||||
|
||||
|
@ -501,6 +515,7 @@ 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
|
||||
|
@ -512,7 +527,9 @@ class TestBigchainApi(object):
|
|||
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)], 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])
|
||||
b.write_transaction(tx)
|
||||
|
||||
|
@ -527,7 +544,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 (Fulfillment, Asset,
|
||||
from bigchaindb.common.transaction import (AssetLink, Fulfillment,
|
||||
TransactionLink)
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb import Bigchain
|
||||
|
@ -536,7 +553,8 @@ class TestBigchainApi(object):
|
|||
fulfillment = Fulfillment(Ed25519Fulfillment(public_key=user_pk),
|
||||
[user_pk],
|
||||
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):
|
||||
tx.validate(Bigchain())
|
||||
|
@ -546,8 +564,9 @@ class TestBigchainApi(object):
|
|||
from bigchaindb.models import Transaction
|
||||
|
||||
for _ in range(4):
|
||||
tx = Transaction.create([b.me],
|
||||
[([user_pk], 1)]).sign([b.me_private])
|
||||
tx = Transaction.create([b.me], [([user_pk], 1)],
|
||||
metadata={'msg': random.random()}) \
|
||||
.sign([b.me_private])
|
||||
b.write_transaction(tx)
|
||||
|
||||
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):
|
||||
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()
|
||||
|
@ -592,7 +612,7 @@ class TestTransactionValidation(object):
|
|||
sk, pk = generate_key_pair()
|
||||
tx = Transaction.create([pk], [([user_pk], 1)])
|
||||
tx.operation = 'TRANSFER'
|
||||
tx.asset = input_transaction.asset
|
||||
tx.asset = AssetLink(input_transaction.id)
|
||||
tx.fulfillments[0].tx_input = input_tx
|
||||
|
||||
with pytest.raises(InvalidSignature):
|
||||
|
@ -629,13 +649,14 @@ 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)],
|
||||
input_tx.asset)
|
||||
AssetLink(input_tx.id))
|
||||
transfer_tx = transfer_tx.sign([user_sk])
|
||||
|
||||
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):
|
||||
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)
|
||||
|
@ -660,7 +682,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)],
|
||||
input_tx.asset)
|
||||
AssetLink(input_tx.id))
|
||||
transfer_tx = transfer_tx.sign([user_sk])
|
||||
|
||||
assert transfer_tx == b.validate_transaction(transfer_tx)
|
||||
|
@ -672,7 +694,7 @@ class TestTransactionValidation(object):
|
|||
# create transaction with the undecided input
|
||||
tx_invalid = Transaction.transfer(transfer_tx.to_inputs(),
|
||||
[([user_pk], 1)],
|
||||
transfer_tx.asset)
|
||||
AssetLink(transfer_tx.asset.id))
|
||||
tx_invalid = tx_invalid.sign([user_sk])
|
||||
|
||||
with pytest.raises(TransactionNotInValidBlock):
|
||||
|
@ -766,13 +788,15 @@ 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()
|
||||
|
||||
tx_link = b.get_owned_ids(user_pk).pop()
|
||||
input_tx = b.get_transaction(tx_link.txid)
|
||||
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])
|
||||
|
||||
# validate transaction
|
||||
|
@ -785,6 +809,7 @@ 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()
|
||||
|
@ -794,7 +819,8 @@ class TestMultipleInputs(object):
|
|||
tx_link = owned_inputs.pop()
|
||||
input_tx = b.get_transaction(tx_link.txid)
|
||||
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])
|
||||
|
||||
assert b.is_valid_transaction(tx) == tx
|
||||
|
@ -806,6 +832,7 @@ 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()
|
||||
|
@ -825,7 +852,7 @@ class TestMultipleInputs(object):
|
|||
inputs = input_tx.to_inputs()
|
||||
|
||||
transfer_tx = Transaction.transfer(inputs, [([user3_pk], 1)],
|
||||
input_tx.asset)
|
||||
AssetLink(input_tx.id))
|
||||
transfer_tx = transfer_tx.sign([user_sk, user2_sk])
|
||||
|
||||
# validate transaction
|
||||
|
@ -838,6 +865,7 @@ 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()
|
||||
|
@ -858,7 +886,8 @@ class TestMultipleInputs(object):
|
|||
tx_input = b.get_transaction(tx_link.txid)
|
||||
|
||||
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])
|
||||
|
||||
assert b.is_valid_transaction(tx) == tx
|
||||
|
@ -868,7 +897,7 @@ class TestMultipleInputs(object):
|
|||
@pytest.mark.usefixtures('setup_database')
|
||||
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 TransactionLink
|
||||
from bigchaindb.common.transaction import AssetLink, TransactionLink
|
||||
from bigchaindb.models import Transaction
|
||||
|
||||
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_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])
|
||||
block = b.create_block([tx])
|
||||
b.write_block(block)
|
||||
|
@ -898,7 +928,7 @@ class TestMultipleInputs(object):
|
|||
user_sk,
|
||||
user_pk):
|
||||
from bigchaindb.common import crypto
|
||||
from bigchaindb.common.transaction import TransactionLink
|
||||
from bigchaindb.common.transaction import AssetLink, TransactionLink
|
||||
from bigchaindb.models import Transaction
|
||||
|
||||
genesis = b.create_genesis_block()
|
||||
|
@ -921,7 +951,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)],
|
||||
tx.asset)
|
||||
AssetLink(tx.id))
|
||||
tx_invalid = tx_invalid.sign([user_sk])
|
||||
block = b.create_block([tx_invalid])
|
||||
b.write_block(block)
|
||||
|
@ -941,7 +971,8 @@ 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
|
||||
from bigchaindb.common.transaction import (TransactionLink, Asset,
|
||||
AssetLink)
|
||||
from bigchaindb.models import Transaction
|
||||
|
||||
user2_sk, user2_pk = crypto.generate_key_pair()
|
||||
|
@ -967,7 +998,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=tx_create.asset)
|
||||
asset_link=AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
block = b.create_block([tx_transfer_signed])
|
||||
b.write_block(block)
|
||||
|
@ -981,7 +1012,7 @@ class TestMultipleInputs(object):
|
|||
@pytest.mark.usefixtures('setup_database')
|
||||
def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk):
|
||||
from bigchaindb.common import crypto
|
||||
from bigchaindb.common.transaction import TransactionLink
|
||||
from bigchaindb.common.transaction import AssetLink, TransactionLink
|
||||
from bigchaindb.models import Transaction
|
||||
|
||||
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 == 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])
|
||||
block = b.create_block([tx])
|
||||
b.write_block(block)
|
||||
|
@ -1012,6 +1044,7 @@ class TestMultipleInputs(object):
|
|||
@pytest.mark.usefixtures('setup_database')
|
||||
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()
|
||||
|
@ -1030,7 +1063,8 @@ class TestMultipleInputs(object):
|
|||
assert spent_inputs_user1 is None
|
||||
|
||||
# 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])
|
||||
block = b.create_block([tx])
|
||||
b.write_block(block)
|
||||
|
@ -1041,6 +1075,7 @@ class TestMultipleInputs(object):
|
|||
@pytest.mark.usefixtures('setup_database')
|
||||
def test_get_spent_single_tx_single_output_invalid_block(self, b, user_sk, user_pk):
|
||||
from bigchaindb.common import crypto
|
||||
from bigchaindb.common.transaction import AssetLink
|
||||
from bigchaindb.models import Transaction
|
||||
|
||||
genesis = b.create_genesis_block()
|
||||
|
@ -1066,7 +1101,8 @@ class TestMultipleInputs(object):
|
|||
assert spent_inputs_user1 is None
|
||||
|
||||
# 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])
|
||||
block = b.create_block([tx])
|
||||
b.write_block(block)
|
||||
|
@ -1084,8 +1120,8 @@ class TestMultipleInputs(object):
|
|||
@pytest.mark.usefixtures('setup_database')
|
||||
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
|
||||
from bigchaindb.common.transaction import Asset
|
||||
|
||||
# create a new users
|
||||
user2_sk, user2_pk = crypto.generate_key_pair()
|
||||
|
@ -1110,7 +1146,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=tx_create.asset)
|
||||
asset_link=AssetLink(tx_create.id))
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
block = b.create_block([tx_transfer_signed])
|
||||
b.write_block(block)
|
||||
|
@ -1126,8 +1162,8 @@ class TestMultipleInputs(object):
|
|||
|
||||
@pytest.mark.usefixtures('setup_database')
|
||||
def test_get_spent_multiple_owners(self, b, user_sk, user_pk):
|
||||
import random
|
||||
from bigchaindb.common import crypto
|
||||
from bigchaindb.common.transaction import AssetLink
|
||||
from bigchaindb.models import Transaction
|
||||
|
||||
user2_sk, user2_pk = crypto.generate_key_pair()
|
||||
|
@ -1151,7 +1187,8 @@ class TestMultipleInputs(object):
|
|||
|
||||
# create a transaction
|
||||
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])
|
||||
block = b.create_block([tx])
|
||||
b.write_block(block)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import random
|
||||
import time
|
||||
from unittest.mock import patch
|
||||
|
||||
|
@ -44,8 +45,9 @@ def test_create_block(b, user_pk):
|
|||
|
||||
block_maker = BlockPipeline()
|
||||
|
||||
for i in range(100):
|
||||
tx = Transaction.create([b.me], [([user_pk], 1)])
|
||||
for _ in range(100):
|
||||
tx = Transaction.create([b.me], [([user_pk], 1)],
|
||||
metadata={'msg': random.random()})
|
||||
tx = tx.sign([b.me_private])
|
||||
block_maker.create(tx)
|
||||
|
||||
|
@ -63,8 +65,9 @@ def test_write_block(b, user_pk):
|
|||
block_maker = BlockPipeline()
|
||||
|
||||
txs = []
|
||||
for i in range(100):
|
||||
tx = Transaction.create([b.me], [([user_pk], 1)])
|
||||
for _ in range(100):
|
||||
tx = Transaction.create([b.me], [([user_pk], 1)],
|
||||
metadata={'msg': random.random()})
|
||||
tx = tx.sign([b.me_private])
|
||||
txs.append(tx)
|
||||
|
||||
|
@ -83,8 +86,9 @@ def test_duplicate_transaction(b, user_pk):
|
|||
block_maker = block.BlockPipeline()
|
||||
|
||||
txs = []
|
||||
for i in range(10):
|
||||
tx = Transaction.create([b.me], [([user_pk], 1)])
|
||||
for _ in range(10):
|
||||
tx = Transaction.create([b.me], [([user_pk], 1)],
|
||||
metadata={'msg': random.random()})
|
||||
tx = tx.sign([b.me_private])
|
||||
txs.append(tx)
|
||||
|
||||
|
@ -114,7 +118,8 @@ def test_delete_tx(b, user_pk):
|
|||
from bigchaindb.pipelines.block import BlockPipeline
|
||||
block_maker = BlockPipeline()
|
||||
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])
|
||||
block_maker.create(tx)
|
||||
# make sure the tx appears in the backlog
|
||||
|
@ -150,10 +155,8 @@ def test_start(create_pipeline):
|
|||
|
||||
@pytest.mark.usefixtures('setup_database')
|
||||
def test_full_pipeline(b, user_pk):
|
||||
import random
|
||||
from bigchaindb.backend import query
|
||||
from bigchaindb.models import Block, Transaction
|
||||
from bigchaindb.pipelines.block import create_pipeline, get_changefeed
|
||||
from bigchaindb.pipelines.block import create_pipeline
|
||||
|
||||
outpipe = Pipe()
|
||||
|
||||
|
@ -166,7 +169,7 @@ def test_full_pipeline(b, user_pk):
|
|||
number_assigned_to_others = 0
|
||||
for i in range(100):
|
||||
tx = Transaction.create([b.me], [([user_pk], 1)],
|
||||
{'msg': random.random()})
|
||||
metadata={'msg': random.random()})
|
||||
tx = tx.sign([b.me_private])
|
||||
|
||||
tx = tx.to_dict()
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import os
|
||||
import random
|
||||
from bigchaindb import Bigchain
|
||||
from bigchaindb.pipelines import stale
|
||||
from multipipes import Pipe, Pipeline
|
||||
from unittest.mock import patch
|
||||
from bigchaindb import config_utils
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -89,7 +90,8 @@ def test_full_pipeline(monkeypatch, user_pk):
|
|||
monkeypatch.setattr('time.time', lambda: 1)
|
||||
|
||||
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])
|
||||
original_txc.append(tx.to_dict())
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import random
|
||||
import time
|
||||
from unittest.mock import patch
|
||||
|
||||
|
@ -5,9 +6,11 @@ from multipipes import Pipe, Pipeline
|
|||
import pytest
|
||||
|
||||
|
||||
# TODO: dummy_tx and dummy_block could be fixtures
|
||||
def dummy_tx(b):
|
||||
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])
|
||||
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):
|
||||
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
|
||||
|
||||
|
@ -292,7 +296,7 @@ def test_valid_block_voting_with_transfer_transactions(monkeypatch, b):
|
|||
# create a `TRANSFER` transaction
|
||||
test_user2_priv, test_user2_pub = crypto.generate_key_pair()
|
||||
tx2 = Transaction.transfer(tx.to_inputs(), [([test_user2_pub], 1)],
|
||||
tx.asset)
|
||||
AssetLink(tx.id))
|
||||
tx2 = tx2.sign([test_user_priv])
|
||||
|
||||
monkeypatch.setattr('time.time', lambda: 2222222222)
|
||||
|
|
|
@ -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):
|
||||
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()
|
||||
|
||||
input_valid = b.get_owned_ids(user_pk).pop()
|
||||
create_tx = b.get_transaction(input_valid.txid)
|
||||
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])
|
||||
|
||||
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')
|
||||
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()
|
||||
|
||||
input_valid = b.get_owned_ids(user_pk).pop()
|
||||
create_tx = b.get_transaction(input_valid.txid)
|
||||
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()))
|
||||
assert res.status_code == 400
|
||||
|
|
Loading…
Reference in New Issue
Block a user