Renamed `asset` to `asset_data`. Added digital asset validation to

validate_transaction

Created and fixed tests.
This commit is contained in:
Rodolphe Marques 2016-08-24 15:57:24 +02:00 committed by tim
parent 1377ce2389
commit 0189ede72e
3 changed files with 117 additions and 6 deletions

View File

@ -1,4 +1,4 @@
from bigchaindb.exceptions import AssetIdMismatch, TransactionDoesNotExist
from bigchaindb.exceptions import AssetIdMismatch, TransactionDoesNotExist, AmountError
def get_asset_id(txids, bigchain):
@ -34,3 +34,35 @@ def get_asset_id(txids, bigchain):
if len(asset_ids) > 1:
raise AssetIdMismatch("All inputs of a transaction need to have the same asset id.")
return asset_ids.pop()
def validate_asset_creation(asset_data, divisible, updatable, refillable, amount):
"""Validate digital asset
Args:
asset_data (Optional[dict]): dictionary describing the digital asset (only used on a create transaction)
divisible (Optional[boolean): Whether the asset is divisible or not. Defaults to `False`.
updatable (Optional[boolean]): Whether the data in the asset can be updated in the future or not.
Defaults to `False`.
refillable (Optional[boolean]): Whether the amount of the asset can change after its creation.
Defaults to `False`.
amount (Optional[int]): The amount of "shares". Only relevant if the asset is marked as divisible.
Defaults to `1`.
"""
if asset_data is not None and not isinstance(asset_data, dict):
raise TypeError('`data` must be a dict instance or None')
if not isinstance(divisible, bool):
raise TypeError('`divisible` must be a boolean')
if not isinstance(refillable, bool):
raise TypeError('`refillable` must be a boolean')
if not isinstance(updatable, bool):
raise TypeError('`updatable` must be a boolean')
if not isinstance(amount, int):
raise TypeError('`amount` must be an int')
if divisible is False and amount != 1:
raise AmountError('Non-divisible assets must have amount 1')
if amount < 1:
raise AmountError('The amount cannot be less then 1')
if divisible or updatable or refillable or amount != 1:
raise NotImplementedError("Divisible assets are not yet implemented!")

View File

@ -3,12 +3,12 @@ from ..db.conftest import inputs
def test_asset_creation(b, user_vk):
data = {'msg': 'hello'}
tx = b.create_transaction(b.me, user_vk, None, 'CREATE', data=data)
asset_data = {'msg': 'hello'}
tx = b.create_transaction(b.me, user_vk, None, 'CREATE', asset_data=asset_data)
tx_signed = b.sign_transaction(tx, b.me_private)
assert b.validate_transaction(tx_signed) == tx_signed
assert tx_signed['transaction']['asset']['data'] == data
assert tx_signed['transaction']['asset']['data'] == asset_data
assert tx_signed['transaction']['asset']['refillable'] is False
assert tx_signed['transaction']['asset']['divisible'] is False
assert tx_signed['transaction']['asset']['updatable'] is False
@ -26,6 +26,75 @@ def test_asset_transfer(b, user_vk, user_sk):
assert tx_transfer_signed['transaction']['asset'] == tx_create['transaction']['asset']['id']
def test_validate_bad_asset_creation(b, user_vk):
from bigchaindb.util import get_hash_data
from bigchaindb.exceptions import AmountError
tx = b.create_transaction(b.me, user_vk, None, 'CREATE')
tx['transaction']['asset'].update({'divisible': 1})
tx['id'] = get_hash_data(tx['transaction'])
tx_signed = b.sign_transaction(tx, b.me_private)
with pytest.raises(TypeError):
b.validate_transaction(tx_signed)
tx = b.create_transaction(b.me, user_vk, None, 'CREATE')
tx['transaction']['asset'].update({'refillable': 1})
tx['id'] = get_hash_data(tx['transaction'])
tx_signed = b.sign_transaction(tx, b.me_private)
with pytest.raises(TypeError):
b.validate_transaction(tx_signed)
tx = b.create_transaction(b.me, user_vk, None, 'CREATE')
tx['transaction']['asset'].update({'updatable': 1})
tx['id'] = get_hash_data(tx['transaction'])
tx_signed = b.sign_transaction(tx, b.me_private)
with pytest.raises(TypeError):
b.validate_transaction(tx_signed)
tx = b.create_transaction(b.me, user_vk, None, 'CREATE')
tx['transaction']['asset'].update({'data': 'a'})
tx['id'] = get_hash_data(tx['transaction'])
tx_signed = b.sign_transaction(tx, b.me_private)
with pytest.raises(TypeError):
b.validate_transaction(tx_signed)
tx = b.create_transaction(b.me, user_vk, None, 'CREATE')
tx['transaction']['conditions'][0]['amount'] = 'a'
tx['id'] = get_hash_data(tx['transaction'])
tx_signed = b.sign_transaction(tx, b.me_private)
with pytest.raises(TypeError):
b.validate_transaction(tx_signed)
tx = b.create_transaction(b.me, user_vk, None, 'CREATE')
tx['transaction']['conditions'][0]['amount'] = 2
tx['transaction']['asset'].update({'divisible': False})
tx['id'] = get_hash_data(tx['transaction'])
tx_signed = b.sign_transaction(tx, b.me_private)
with pytest.raises(AmountError):
b.validate_transaction(tx_signed)
tx = b.create_transaction(b.me, user_vk, None, 'CREATE')
tx['transaction']['conditions'][0]['amount'] = 0
tx['id'] = get_hash_data(tx['transaction'])
tx_signed = b.sign_transaction(tx, b.me_private)
with pytest.raises(AmountError):
b.validate_transaction(tx_signed)
@pytest.mark.usefixtures('inputs')
def test_validate_bad_asset_transfer(b, user_vk, user_sk):
from bigchaindb.util import get_hash_data
from bigchaindb.exceptions import AssetIdMismatch
tx_input = b.get_owned_ids(user_vk).pop()
tx = b.create_transaction(user_vk, user_vk, tx_input, 'TRANFER')
tx['transaction']['asset'] = 'aaa'
tx['id'] = get_hash_data(tx['transaction'])
tx_signed = b.sign_transaction(tx, user_sk)
with pytest.raises(AssetIdMismatch):
b.validate_transaction(tx_signed)
def test_validate_asset_arguments(b):
from bigchaindb.exceptions import AmountError
@ -35,6 +104,8 @@ def test_validate_asset_arguments(b):
b.create_transaction(b.me, b.me, None, 'CREATE', refillable=1)
with pytest.raises(TypeError):
b.create_transaction(b.me, b.me, None, 'CREATE', updatable=1)
with pytest.raises(TypeError):
b.create_transaction(b.me, b.me, None, 'CREATE', data='a')
with pytest.raises(TypeError):
b.create_transaction(b.me, b.me, None, 'CREATE', amount='a')
with pytest.raises(AmountError):
@ -82,3 +153,10 @@ def test_asset_id_mismatch(b, user_vk):
with pytest.raises(AssetIdMismatch):
get_asset_id([tx_input1['txid'], tx_input2['txid']], bigchain=b)
def test_get_asset_id_transaction_does_not_exist(b, user_vk):
from bigchaindb.exceptions import TransactionDoesNotExist
with pytest.raises(TransactionDoesNotExist):
b.create_transaction(user_vk, user_vk, {'txid': 'bored', 'cid': '0'}, 'TRANSFER')

View File

@ -720,8 +720,9 @@ class TestMultipleInputs(object):
assert len(tx.fulfillments) == 1
assert len(tx.conditions) == 1
@pytest.mark.skipif(reason=('Multiple inputs are only allowed for the same asset. Remove this after ',
'implementing multiple assets'))
@pytest.mark.skipif(reason=('Multiple inputs are only allowed for the '
'same asset. Remove this after implementing ',
'multiple assets'))
def test_transfer_single_owners_multiple_inputs(self, b, user_sk, user_vk):
from bigchaindb_common import crypto
from bigchaindb.models import Transaction