addressed comments

This commit is contained in:
Rodolphe Marques 2016-11-09 17:48:39 +01:00
parent efb5439044
commit a2e28ae806
8 changed files with 44 additions and 124 deletions

View File

@ -413,7 +413,7 @@ class Asset(object):
self.updatable = updatable
self.refillable = refillable
self._validate_asset()
self.validate_asset()
def __eq__(self, other):
try:
@ -470,8 +470,9 @@ class Asset(object):
transaction are related to the same asset id.
Args:
transactions (list): list of transaction usually inputs that should
have a matching asset_id
transactions (:obj:`list` of :class:`~bigchaindb.common.
transaction.Transaction`): list of transaction usually inputs
that should have a matching asset_id
Returns:
str: uuid of the asset.
@ -488,11 +489,11 @@ class Asset(object):
# check that all the transasctions have the same asset_id
if len(asset_ids) > 1:
raise AssetIdMismatch(('All inputs of a transaction need'
' to have the same asset id.'))
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):
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')
@ -670,11 +671,11 @@ class Transaction(object):
if self.operation == self.CREATE:
amount = sum([condition.amount for condition in self.conditions])
self.asset._validate_asset(amount=amount)
self.asset.validate_asset(amount=amount)
else:
# In transactions other then `CREATE` we don't know if its a
# divisible asset or not, so we cannot validate the amount here
self.asset._validate_asset()
self.asset.validate_asset()
@classmethod
def create(cls, owners_before, owners_after, metadata=None, asset=None):
@ -719,8 +720,9 @@ class Transaction(object):
# generate_conditions
for owner_after in owners_after:
if not isinstance(owner_after, tuple) or len(owner_after) != 2:
raise ValueError(('Each `owner_after` in the list is a tuple'
' of `([<list of public keys>], <amount>)`'))
raise ValueError(('Each `owner_after` in the list must be a'
' tuple of `([<list of public keys>],'
' <amount>)`'))
pub_keys, amount = owner_after
conds.append(Condition.generate(pub_keys, amount))
@ -780,8 +782,9 @@ class Transaction(object):
conds = []
for owner_after in owners_after:
if not isinstance(owner_after, tuple) or len(owner_after) != 2:
raise ValueError(('Each `owner_after` in the list is a tuple'
' of `([<list of public keys>], <amount>)`'))
raise ValueError(('Each `owner_after` in the list must be a'
' tuple of `([<list of public keys>],'
' <amount>)`'))
pub_keys, amount = owner_after
conds.append(Condition.generate(pub_keys, amount))

View File

@ -345,14 +345,14 @@ class Bigchain(object):
return [Transaction.from_dict(tx) for tx in cursor]
def get_asset_by_id(self, asset_id):
"""Returns the asset associated with an asset_id
"""Returns the asset associated with an asset_id.
Args:
asset_id (str): The asset id
asset_id (str): The asset id.
Returns:
:class:`~bigchaindb.common.transaction.Asset` if the asset
exists else None
exists else None.
"""
cursor = self.backend.get_asset_by_id(asset_id)
cursor = list(cursor)

View File

@ -182,13 +182,13 @@ class RethinkDBBackend:
transaction['transaction']['asset']['id'] == asset_id))
def get_asset_by_id(self, asset_id):
"""Returns the asset associated with an asset_id
"""Returns the asset associated with an asset_id.
Args:
asset_id (str): The asset id
asset_id (str): The asset id.
Returns:
Returns a rethinkdb cursor
Returns a rethinkdb cursor.
"""
return self.connection.run(
r.table('bigchain', read_mode=self.read_mode)

View File

@ -42,7 +42,7 @@ class Transaction(Transaction):
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)
self.asset.validate_asset(amount=amount)
elif self.operation == Transaction.TRANSFER:
if not inputs_defined:
raise ValueError('Only `CREATE` transactions can have null '
@ -85,7 +85,7 @@ class Transaction(Transaction):
# get the asset creation to see if its divisible or not
asset = bigchain.get_asset_by_id(asset_id)
# validate the asset
asset._validate_asset(amount=input_amount)
asset.validate_asset(amount=input_amount)
# validate the amounts
output_amount = sum([condition.amount for
condition in self.conditions])

View File

@ -25,7 +25,7 @@ def test_validate_bad_asset_creation(b, user_vk):
# `divisible` needs to be a boolean
tx = Transaction.create([b.me], [([user_vk], 1)])
tx.asset.divisible = 1
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx_signed = tx.sign([b.me_private])
with pytest.raises(TypeError):
tx_signed.validate(b)
@ -33,7 +33,7 @@ def test_validate_bad_asset_creation(b, user_vk):
# `refillable` needs to be a boolean
tx = Transaction.create([b.me], [([user_vk], 1)])
tx.asset.refillable = 1
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx_signed = tx.sign([b.me_private])
with pytest.raises(TypeError):
b.validate_transaction(tx_signed)
@ -41,7 +41,7 @@ def test_validate_bad_asset_creation(b, user_vk):
# `updatable` needs to be a boolean
tx = Transaction.create([b.me], [([user_vk], 1)])
tx.asset.updatable = 1
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx_signed = tx.sign([b.me_private])
with pytest.raises(TypeError):
b.validate_transaction(tx_signed)
@ -49,7 +49,7 @@ def test_validate_bad_asset_creation(b, user_vk):
# `data` needs to be a dictionary
tx = Transaction.create([b.me], [([user_vk], 1)])
tx.asset.data = 'a'
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx_signed = tx.sign([b.me_private])
with pytest.raises(TypeError):
b.validate_transaction(tx_signed)
@ -189,7 +189,7 @@ def test_create_invalid_divisible_asset(b, user_vk, user_sk):
# even if a transaction is badly constructed the server should raise the
# exception
asset = Asset(divisible=False)
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction.create([user_vk], [([user_vk], 2)], asset=asset)
tx_signed = tx.sign([user_sk])
with pytest.raises(AmountError):
@ -197,7 +197,7 @@ def test_create_invalid_divisible_asset(b, user_vk, user_sk):
assert b.is_valid_transaction(tx_signed) is False
asset = Asset(divisible=True)
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction.create([user_vk], [([user_vk], 1)], asset=asset)
tx_signed = tx.sign([user_sk])
with pytest.raises(AmountError):

View File

@ -24,7 +24,7 @@ def test_single_in_single_own_single_out_single_own_create(b, user_vk):
# CREATE divisible asset
# Single input
# Single onwers_before
# Single owners_before
# Multiple outputs
# Single owners_after per output
def test_single_in_single_own_multiple_out_single_own_create(b, user_vk):
@ -98,7 +98,7 @@ def test_single_in_single_own_multiple_out_mix_own_create(b, user_vk):
# CREATE divisible asset
# Single input
# Multiple owners_before
# Ouput combinations already tested above
# Output combinations already tested above
def test_single_in_multiple_own_single_out_single_own_create(b, user_vk,
user_sk):
from bigchaindb.models import Transaction
@ -519,7 +519,7 @@ def test_multiple_in_different_transactions(b, user_vk, user_sk):
# `b` transfers its 50 shares to `user_vk`
# after this transaction `user_vk` will have a total of 100 shares
# split across two different transactions
tx_transfer1 = Transaction.transfer([tx_create.to_inputs()[1]],
tx_transfer1 = Transaction.transfer(tx_create.to_inputs([1]),
[([user_vk], 50)],
asset=tx_create.asset)
tx_transfer1_signed = tx_transfer1.sign([b.me_private])
@ -534,8 +534,8 @@ def test_multiple_in_different_transactions(b, user_vk, user_sk):
# TRANSFER
# `user_vk` combines two different transaction with 50 shares each and
# transfers a total of 100 shares back to `b`
tx_transfer2 = Transaction.transfer([tx_create.to_inputs()[0],
tx_transfer1.to_inputs()[0]],
tx_transfer2 = Transaction.transfer(tx_create.to_inputs([0]) +
tx_transfer1.to_inputs([0]),
[([b.me], 100)],
asset=tx_create.asset)
tx_transfer2_signed = tx_transfer2.sign([user_sk])

View File

@ -81,12 +81,12 @@ def test_validate_asset():
# test amount errors
asset = Asset(divisible=False)
with raises(AmountError):
asset._validate_asset(amount=2)
asset.validate_asset(amount=2)
asset = Asset(divisible=True)
with raises(AmountError):
asset._validate_asset(amount=1)
asset.validate_asset(amount=1)
asset = Asset()
with raises(TypeError):
asset._validate_asset(amount='a')
asset.validate_asset(amount='a')

View File

@ -228,31 +228,6 @@ def test_generate_conditions_single_owner_with_condition(user_pub):
assert cond.fulfillment.to_dict() == expected.to_dict()
# TODO FOR CC: see skip reason
@mark.skip(reason='threshold(hashlock).to_dict() exposes secret')
def test_generate_threshold_condition_with_hashlock(user_pub, user2_pub,
user3_pub):
from bigchaindb.common.transaction import Condition
from cryptoconditions import (PreimageSha256Fulfillment,
Ed25519Fulfillment,
ThresholdSha256Fulfillment)
secret = b'much secret, wow'
hashlock = PreimageSha256Fulfillment(preimage=secret)
expected_simple1 = Ed25519Fulfillment(public_key=user_pub)
expected_simple3 = Ed25519Fulfillment(public_key=user3_pub)
expected = ThresholdSha256Fulfillment(threshold=2)
expected_sub = ThresholdSha256Fulfillment(threshold=2)
expected_sub.add_subfulfillment(expected_simple1)
expected_sub.add_subfulfillment(hashlock)
expected.add_subfulfillment(expected_simple3)
cond = Condition.generate([[user_pub, hashlock], expected_simple3], 1)
assert cond.fulfillment.to_dict() == expected.to_dict()
def test_generate_conditions_invalid_parameters(user_pub, user2_pub,
user3_pub):
from bigchaindb.common.transaction import Condition
@ -300,7 +275,7 @@ def test_invalid_transaction_initialization():
def test_create_default_asset_on_tx_initialization():
from bigchaindb.common.transaction import Transaction, Asset
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, None)
expected = Asset()
asset = tx.asset
@ -493,7 +468,7 @@ def test_cast_transaction_link_to_boolean():
def test_add_fulfillment_to_tx(user_ffill):
from bigchaindb.common.transaction import Transaction, Asset
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, Asset(), [], [])
tx.add_fulfillment(user_ffill)
@ -503,7 +478,7 @@ def test_add_fulfillment_to_tx(user_ffill):
def test_add_fulfillment_to_tx_with_invalid_parameters():
from bigchaindb.common.transaction import Transaction, Asset
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, Asset())
with raises(TypeError):
tx.add_fulfillment('somewronginput')
@ -512,7 +487,7 @@ def test_add_fulfillment_to_tx_with_invalid_parameters():
def test_add_condition_to_tx(user_cond):
from bigchaindb.common.transaction import Transaction, Asset
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, Asset())
tx.add_condition(user_cond)
@ -522,7 +497,7 @@ def test_add_condition_to_tx(user_cond):
def test_add_condition_to_tx_with_invalid_parameters():
from bigchaindb.common.transaction import Transaction, Asset
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, Asset(), [], [])
with raises(TypeError):
tx.add_condition('somewronginput')
@ -605,9 +580,7 @@ def test_validate_multiple_fulfillments(user_ffill, user_cond, user_priv):
expected_first = deepcopy(tx)
expected_second = deepcopy(tx)
expected_first.fulfillments = [expected_first.fulfillments[0]]
expected_first.conditions = expected_first.conditions
expected_second.fulfillments = [expected_second.fulfillments[1]]
expected_second.conditions = expected_second.conditions
expected_first_bytes = str(expected_first).encode()
expected_first.fulfillments[0].fulfillment.sign(expected_first_bytes,
@ -854,62 +827,6 @@ def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub,
assert tx.fulfillments_valid() is True
@mark.skip(reason='Hashlocks are not implemented')
def test_create_create_transaction_hashlock(user_pub, data, data_id):
from cryptoconditions import PreimageSha256Fulfillment
from bigchaindb.common.transaction import Transaction, Condition, Asset
secret = b'much secret, wow'
hashlock = PreimageSha256Fulfillment(preimage=secret).condition_uri
cond = Condition(hashlock)
expected = {
'transaction': {
'conditions': [cond.to_dict(0)],
'metadata': {
'data': data,
},
'asset': {
'id': data_id,
'divisible': False,
'updatable': False,
'refillable': False,
'data': data,
},
'fulfillments': [
{
'owners_before': [
user_pub,
],
'fid': 0,
'fulfillment': None,
'input': None
},
],
'operation': 'CREATE',
},
'version': 1
}
asset = Asset(data, data_id)
tx = Transaction.create([user_pub], [], data, asset, secret).to_dict()
tx.pop('id')
tx['transaction']['metadata'].pop('id')
tx['transaction'].pop('timestamp')
tx['transaction']['fulfillments'][0]['fulfillment'] = None
assert tx == expected
@mark.skip(reson='Hashlocks are not implemented')
def test_validate_hashlock_create_transaction(user_pub, user_priv, data):
from bigchaindb.common.transaction import Transaction, Asset
tx = Transaction.create([user_pub], [], data, Asset(), b'much secret, wow')
tx = tx.sign([user_priv])
assert tx.fulfillments_valid() is True
def test_create_create_transaction_with_invalid_parameters(user_pub):
from bigchaindb.common.transaction import Transaction
@ -1071,7 +988,7 @@ def test_create_transfer_with_invalid_parameters(user_pub):
def test_cant_add_empty_condition():
from bigchaindb.common.transaction import Transaction, Asset
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, None)
with raises(TypeError):
tx.add_condition(None)
@ -1080,7 +997,7 @@ def test_cant_add_empty_condition():
def test_cant_add_empty_fulfillment():
from bigchaindb.common.transaction import Transaction, Asset
with patch.object(Asset, '_validate_asset', return_value=None):
with patch.object(Asset, 'validate_asset', return_value=None):
tx = Transaction(Transaction.CREATE, None)
with raises(TypeError):
tx.add_fulfillment(None)