mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Added support for multiple owners_before in CREATE transactions
Added some type checking Remove code for hashlocks and timelocks. They were partially implemented features that we need to revisit.
This commit is contained in:
parent
9a5bc816d8
commit
19cfe172ea
@ -102,10 +102,10 @@ class Fulfillment(object):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def generate(cls, owners_before):
|
def generate(cls, owners_before):
|
||||||
# TODO: write docstring
|
# TODO: write docstring
|
||||||
|
# The amount here does not really matter. It is only use on the
|
||||||
if len(owners_before) == 1:
|
# condition data model but here we only care about the fulfillment
|
||||||
ffill = Ed25519Fulfillment(public_key=owners_before[0])
|
condition = Condition.generate(owners_before, 1)
|
||||||
return cls(ffill, owners_before)
|
return cls(condition.fulfillment, condition.owners_after)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, ffill):
|
def from_dict(cls, ffill):
|
||||||
@ -308,14 +308,7 @@ class Condition(object):
|
|||||||
TypeError: If `owners_after` is not an instance of `list`.
|
TypeError: If `owners_after` is not an instance of `list`.
|
||||||
TypeError: If `owners_after` is an empty list.
|
TypeError: If `owners_after` is an empty list.
|
||||||
"""
|
"""
|
||||||
# TODO: We probably want to remove the tuple logic for weights here
|
|
||||||
# again:
|
|
||||||
# github.com/bigchaindb/bigchaindb/issues/730#issuecomment-255144756
|
|
||||||
if isinstance(owners_after, tuple):
|
|
||||||
owners_after, threshold = owners_after
|
|
||||||
else:
|
|
||||||
threshold = len(owners_after)
|
threshold = len(owners_after)
|
||||||
|
|
||||||
if not isinstance(amount, int):
|
if not isinstance(amount, int):
|
||||||
raise TypeError('`amount` must be a int')
|
raise TypeError('`amount` must be a int')
|
||||||
if not isinstance(owners_after, list):
|
if not isinstance(owners_after, list):
|
||||||
@ -724,8 +717,7 @@ class Transaction(object):
|
|||||||
self.asset._validate_asset()
|
self.asset._validate_asset()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, owners_before, owners_after, metadata=None, asset=None,
|
def create(cls, owners_before, owners_after, metadata=None, asset=None):
|
||||||
secret=None, time_expire=None):
|
|
||||||
# TODO: Update docstring
|
# TODO: Update docstring
|
||||||
"""A simple way to generate a `CREATE` transaction.
|
"""A simple way to generate a `CREATE` transaction.
|
||||||
|
|
||||||
@ -761,45 +753,28 @@ class Transaction(object):
|
|||||||
raise TypeError('`owners_before` must be a list instance')
|
raise TypeError('`owners_before` must be a list instance')
|
||||||
if not isinstance(owners_after, list):
|
if not isinstance(owners_after, list):
|
||||||
raise TypeError('`owners_after` must be a list instance')
|
raise TypeError('`owners_after` must be a list instance')
|
||||||
|
if len(owners_before) == 0:
|
||||||
if (len(owners_before) > 0 and len(owners_after) == 0 and
|
raise ValueError('`owners_before` list cannot be empty')
|
||||||
time_expire is not None):
|
if len(owners_after) == 0:
|
||||||
raise NotImplementedError('Timeout conditions will be implemented '
|
raise ValueError('`owners_after` list cannot be empty')
|
||||||
'later')
|
|
||||||
elif (len(owners_before) > 0 and len(owners_after) == 0 and
|
|
||||||
secret is None):
|
|
||||||
raise ValueError('Define a secret to create a hashlock condition')
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise ValueError("These are not the cases you're looking for ;)")
|
|
||||||
|
|
||||||
metadata = Metadata(metadata)
|
metadata = Metadata(metadata)
|
||||||
|
ffills = []
|
||||||
# TODO: Not sure there is a need to ensure that `owners_before == 1`
|
|
||||||
# TODO: For divisible assets we will need to create one hashlock
|
|
||||||
# condition per output
|
|
||||||
# if (len(owners_before) == 1 and len(owners_after) == 0 and
|
|
||||||
# secret is not None):
|
|
||||||
# # NOTE: Hashlock condition case
|
|
||||||
# hashlock = PreimageSha256Fulfillment(preimage=secret)
|
|
||||||
# cond_tx = Condition(hashlock.condition_uri, amount=amount)
|
|
||||||
# ffill = Ed25519Fulfillment(public_key=owners_before[0])
|
|
||||||
# ffill_tx = Fulfillment(ffill, owners_before)
|
|
||||||
# return cls(cls.CREATE, asset, [ffill_tx], [cond_tx], metadata)
|
|
||||||
|
|
||||||
ffils = []
|
|
||||||
conds = []
|
conds = []
|
||||||
|
|
||||||
# generate_conditions
|
# generate_conditions
|
||||||
for owner_after in owners_after:
|
for owner_after in owners_after:
|
||||||
# TODO: Check types so this doesn't fail unpacking
|
# TODO: Check types so this doesn't fail unpacking
|
||||||
|
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>)`'))
|
||||||
pub_keys, amount = owner_after
|
pub_keys, amount = owner_after
|
||||||
conds.append(Condition.generate(pub_keys, amount))
|
conds.append(Condition.generate(pub_keys, amount))
|
||||||
|
|
||||||
# generate fulfillments
|
# generate fulfillments
|
||||||
ffils.append(Fulfillment.generate(owners_before))
|
ffills.append(Fulfillment.generate(owners_before))
|
||||||
|
|
||||||
return cls(cls.CREATE, asset, ffils, conds, metadata)
|
return cls(cls.CREATE, asset, ffills, conds, metadata)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def transfer(cls, inputs, owners_after, asset, metadata=None):
|
def transfer(cls, inputs, owners_after, asset, metadata=None):
|
||||||
|
@ -98,17 +98,22 @@ def test_single_in_single_own_multiple_out_mix_own_create(b, user_vk):
|
|||||||
# Single input
|
# Single input
|
||||||
# Multiple owners_before
|
# Multiple owners_before
|
||||||
# Ouput combinations already tested above
|
# Ouput combinations already tested above
|
||||||
# TODO: Support multiple owners_before in CREATE transactions
|
def test_single_in_multiple_own_single_out_single_own_create(b, user_vk,
|
||||||
@pytest.mark.skip(reason=('CREATE transaction do not support multiple'
|
user_sk):
|
||||||
' owners_before'))
|
|
||||||
def test_single_in_multiple_own_single_out_single_own_create(b, user_vk):
|
|
||||||
from bigchaindb.models import Transaction
|
from bigchaindb.models import Transaction
|
||||||
from bigchaindb.common.transaction import Asset
|
from bigchaindb.common.transaction import Asset
|
||||||
|
|
||||||
asset = Asset(divisible=True)
|
asset = Asset(divisible=True)
|
||||||
tx = Transaction.create([b.me, b.me], [([user_vk], 100)], asset=asset)
|
tx = Transaction.create([b.me, user_vk], [([user_vk], 100)], asset=asset)
|
||||||
tx_signed = tx.sign([b.me, b.me])
|
tx_signed = tx.sign([b.me_private, user_sk])
|
||||||
assert tx_signed.validate(b) == tx_signed
|
assert tx_signed.validate(b) == tx_signed
|
||||||
|
assert len(tx_signed.conditions) == 1
|
||||||
|
assert tx_signed.conditions[0].amount == 100
|
||||||
|
assert len(tx_signed.fulfillments) == 1
|
||||||
|
|
||||||
|
ffill = tx_signed.fulfillments[0].fulfillment.to_dict()
|
||||||
|
assert 'subfulfillments' in ffill
|
||||||
|
assert len(ffill['subfulfillments']) == 2
|
||||||
|
|
||||||
|
|
||||||
# TRANSFER divisible asset
|
# TRANSFER divisible asset
|
||||||
|
@ -874,7 +874,8 @@ def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub,
|
|||||||
'version': 1
|
'version': 1
|
||||||
}
|
}
|
||||||
asset = Asset(data, data_id)
|
asset = Asset(data, data_id)
|
||||||
tx = Transaction.create([user_pub], [user_pub, user2_pub], data, asset)
|
tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)],
|
||||||
|
data, asset)
|
||||||
tx_dict = tx.to_dict()
|
tx_dict = tx.to_dict()
|
||||||
tx_dict.pop('id')
|
tx_dict.pop('id')
|
||||||
tx_dict['transaction']['metadata'].pop('id')
|
tx_dict['transaction']['metadata'].pop('id')
|
||||||
@ -888,11 +889,13 @@ def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub,
|
|||||||
data):
|
data):
|
||||||
from bigchaindb.common.transaction import Transaction, Asset
|
from bigchaindb.common.transaction import Transaction, Asset
|
||||||
|
|
||||||
tx = Transaction.create([user_pub], [user_pub, user2_pub], data, Asset())
|
tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)],
|
||||||
|
data, Asset())
|
||||||
tx = tx.sign([user_priv])
|
tx = tx.sign([user_priv])
|
||||||
assert tx.fulfillments_valid() is True
|
assert tx.fulfillments_valid() is True
|
||||||
|
|
||||||
|
|
||||||
|
@mark.skip(reason='Hashlocks are not implemented')
|
||||||
def test_create_create_transaction_hashlock(user_pub, data, data_id):
|
def test_create_create_transaction_hashlock(user_pub, data, data_id):
|
||||||
from cryptoconditions import PreimageSha256Fulfillment
|
from cryptoconditions import PreimageSha256Fulfillment
|
||||||
from bigchaindb.common.transaction import Transaction, Condition, Asset
|
from bigchaindb.common.transaction import Transaction, Condition, Asset
|
||||||
@ -939,6 +942,7 @@ def test_create_create_transaction_hashlock(user_pub, data, data_id):
|
|||||||
assert tx == expected
|
assert tx == expected
|
||||||
|
|
||||||
|
|
||||||
|
@mark.skip(reson='Hashlocks are not implemented')
|
||||||
def test_validate_hashlock_create_transaction(user_pub, user_priv, data):
|
def test_validate_hashlock_create_transaction(user_pub, user_priv, data):
|
||||||
from bigchaindb.common.transaction import Transaction, Asset
|
from bigchaindb.common.transaction import Transaction, Asset
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user