mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
tx with conditions
This commit is contained in:
parent
ce945e3409
commit
b76bd72ea0
@ -3,7 +3,6 @@ import random
|
||||
import json
|
||||
import rapidjson
|
||||
|
||||
|
||||
import bigchaindb
|
||||
from bigchaindb import util
|
||||
from bigchaindb import config_utils
|
||||
@ -11,7 +10,6 @@ from bigchaindb import exceptions
|
||||
from bigchaindb import crypto
|
||||
from bigchaindb.monitor import Monitor
|
||||
|
||||
|
||||
monitor = Monitor()
|
||||
|
||||
|
||||
@ -150,7 +148,7 @@ class Bigchain(object):
|
||||
If no transaction with that `txid` was found it returns `None`
|
||||
"""
|
||||
|
||||
response = r.table('bigchain').concat_map(lambda doc: doc['block']['transactions'])\
|
||||
response = r.table('bigchain').concat_map(lambda doc: doc['block']['transactions']) \
|
||||
.filter(lambda transaction: transaction['id'] == txid).run(self.conn)
|
||||
|
||||
# transaction ids should be unique
|
||||
@ -181,8 +179,8 @@ class Bigchain(object):
|
||||
returns `None`
|
||||
"""
|
||||
|
||||
cursor = r.table('bigchain')\
|
||||
.get_all(payload_hash, index='payload_hash')\
|
||||
cursor = r.table('bigchain') \
|
||||
.get_all(payload_hash, index='payload_hash') \
|
||||
.run(self.conn)
|
||||
|
||||
transactions = list(cursor)
|
||||
@ -202,7 +200,7 @@ class Bigchain(object):
|
||||
"""
|
||||
# checks if an input was already spent
|
||||
# checks if the bigchain has any transaction with input `transaction_id`
|
||||
response = r.table('bigchain').concat_map(lambda doc: doc['block']['transactions'])\
|
||||
response = r.table('bigchain').concat_map(lambda doc: doc['block']['transactions']) \
|
||||
.filter(lambda transaction: transaction['transaction']['inputs'].contains(txid)).run(self.conn)
|
||||
|
||||
# a transaction_id should have been spent at most one time
|
||||
@ -226,11 +224,14 @@ class Bigchain(object):
|
||||
list: list of `txids` currently owned by `owner`
|
||||
"""
|
||||
|
||||
response = r.table('bigchain')\
|
||||
.concat_map(lambda doc: doc['block']['transactions'])\
|
||||
.filter({'transaction': {'new_owner': owner}})\
|
||||
.pluck('id')['id']\
|
||||
.run(self.conn)
|
||||
response = r.table('bigchain') \
|
||||
.concat_map(lambda doc: doc['block']['transactions']) \
|
||||
.filter(lambda tx: tx['transaction']['conditions']
|
||||
.contains(lambda c: c['new_owners']
|
||||
.contains(owner))) \
|
||||
.pluck('id')['id'] \
|
||||
.run(self.conn)
|
||||
|
||||
owned = []
|
||||
|
||||
# remove all inputs already spent
|
||||
@ -439,37 +440,37 @@ class Bigchain(object):
|
||||
if 'block_number' not in block:
|
||||
update['block_number'] = block_number
|
||||
|
||||
r.table('bigchain')\
|
||||
.get(vote['vote']['voting_for_block'])\
|
||||
.update(update)\
|
||||
.run(self.conn)
|
||||
r.table('bigchain') \
|
||||
.get(vote['vote']['voting_for_block']) \
|
||||
.update(update) \
|
||||
.run(self.conn)
|
||||
|
||||
def get_last_voted_block(self):
|
||||
"""Returns the last block that this node voted on."""
|
||||
|
||||
# query bigchain for all blocks this node is a voter but didn't voted on
|
||||
last_voted = r.table('bigchain')\
|
||||
.filter(r.row['block']['voters'].contains(self.me))\
|
||||
.filter(lambda doc: doc['votes'].contains(lambda vote: vote['node_pubkey'] == self.me))\
|
||||
.order_by(r.desc('block_number'))\
|
||||
.limit(1)\
|
||||
last_voted = r.table('bigchain') \
|
||||
.filter(r.row['block']['voters'].contains(self.me)) \
|
||||
.filter(lambda doc: doc['votes'].contains(lambda vote: vote['node_pubkey'] == self.me)) \
|
||||
.order_by(r.desc('block_number')) \
|
||||
.limit(1) \
|
||||
.run(self.conn)
|
||||
|
||||
# return last vote if last vote exists else return Genesis block
|
||||
last_voted = list(last_voted)
|
||||
if not last_voted:
|
||||
return list(r.table('bigchain')
|
||||
.filter(r.row['block_number'] == 0)
|
||||
.run(self.conn))[0]
|
||||
.filter(r.row['block_number'] == 0)
|
||||
.run(self.conn))[0]
|
||||
|
||||
return last_voted[0]
|
||||
|
||||
def get_unvoted_blocks(self):
|
||||
"""Return all the blocks that has not been voted by this node."""
|
||||
|
||||
unvoted = r.table('bigchain')\
|
||||
.filter(lambda doc: doc['votes'].contains(lambda vote: vote['node_pubkey'] == self.me).not_())\
|
||||
.order_by(r.asc((r.row['block']['timestamp'])))\
|
||||
unvoted = r.table('bigchain') \
|
||||
.filter(lambda doc: doc['votes'].contains(lambda vote: vote['node_pubkey'] == self.me).not_()) \
|
||||
.order_by(r.asc((r.row['block']['timestamp']))) \
|
||||
.run(self.conn)
|
||||
|
||||
if unvoted and unvoted[0].get('block_number') == 0:
|
||||
|
@ -144,6 +144,9 @@ def create_tx(current_owners, new_owners, inputs, operation, payload=None):
|
||||
},
|
||||
}
|
||||
"""
|
||||
current_owners = current_owners if isinstance(current_owners, list) else [current_owners]
|
||||
new_owners = new_owners if isinstance(new_owners, list) else [new_owners]
|
||||
inputs = inputs if isinstance(inputs, list) else [inputs]
|
||||
|
||||
# handle payload
|
||||
data = None
|
||||
@ -159,17 +162,14 @@ def create_tx(current_owners, new_owners, inputs, operation, payload=None):
|
||||
|
||||
# handle inputs
|
||||
fulfillments = []
|
||||
current_owners = current_owners if isinstance(current_owners, list) else [current_owners]
|
||||
|
||||
# transfer
|
||||
if inputs:
|
||||
for fid, inp in enumerate(inputs):
|
||||
fulfillment = ThresholdSha256Fulfillment(threshold=len(current_owners))
|
||||
for current_owner in current_owners:
|
||||
fulfillment.add_subfulfillment(Ed25519Fulfillment(public_key=current_owner))
|
||||
fulfillments.append({
|
||||
'current_owners': current_owners,
|
||||
'input': inp,
|
||||
'fulfillment': fulfillment.serialize_json(),
|
||||
'fulfillment': None,
|
||||
'fid': fid
|
||||
})
|
||||
# create
|
||||
@ -184,9 +184,18 @@ def create_tx(current_owners, new_owners, inputs, operation, payload=None):
|
||||
# handle outputs
|
||||
conditions = []
|
||||
for fulfillment in fulfillments:
|
||||
if len(new_owners) > 1:
|
||||
for new_owner in new_owners:
|
||||
condition = ThresholdSha256Fulfillment(threshold=len(new_owners))
|
||||
condition.add_subfulfillment(Ed25519Fulfillment(public_key=new_owner))
|
||||
elif len(new_owners) == 1:
|
||||
condition = Ed25519Fulfillment(public_key=new_owners[0])
|
||||
conditions.append({
|
||||
'new_owners': new_owners,
|
||||
'condition': None,
|
||||
'condition': {
|
||||
'details': json.loads(condition.serialize_json()),
|
||||
'uri': condition.condition.serialize_uri()
|
||||
},
|
||||
'cid': fulfillment['fid']
|
||||
})
|
||||
|
||||
@ -220,7 +229,7 @@ def sign_tx(transaction, private_key):
|
||||
|
||||
Args:
|
||||
transaction (dict): transaction to sign.
|
||||
private_key (str): base58 encoded private key to create a signature of the transaction.
|
||||
private_key (base58 str): base58 encoded private key to create a signature of the transaction.
|
||||
|
||||
Returns:
|
||||
dict: transaction with the `fulfillment` fields populated.
|
||||
|
2
setup.py
2
setup.py
@ -71,7 +71,7 @@ setup(
|
||||
'rethinkdb==2.2.0.post4',
|
||||
'pysha3==0.3',
|
||||
'pytz==2015.7',
|
||||
'cryptoconditions==0.1.4',
|
||||
'cryptoconditions==0.1.5',
|
||||
'statsd==3.2.1',
|
||||
'python-rapidjson==0.0.6',
|
||||
'logstats==0.2.1',
|
||||
|
@ -23,17 +23,24 @@ def test_remove_unclosed_sockets():
|
||||
|
||||
class TestBigchainApi(object):
|
||||
|
||||
def test_create_transaction(self, b, user_sk):
|
||||
def test_create_transaction_create(self, b, user_sk):
|
||||
tx = b.create_transaction(b.me, user_sk, None, 'CREATE')
|
||||
|
||||
assert sorted(tx) == sorted(['id', 'transaction'])
|
||||
assert sorted(tx['transaction']) == sorted(['current_owner', 'new_owner', 'input', 'operation',
|
||||
'timestamp', 'data'])
|
||||
assert sorted(tx) == sorted(['id', 'transaction', 'version'])
|
||||
assert sorted(tx['transaction']) == sorted(['conditions', 'data', 'fulfillments', 'operation', 'timestamp'])
|
||||
|
||||
def test_create_transaction_with_unsupported_payload_raises(self, b):
|
||||
with pytest.raises(TypeError):
|
||||
b.create_transaction('a', 'b', 'c', 'd', payload=[])
|
||||
|
||||
@pytest.mark.usefixtures('inputs')
|
||||
def test_create_transaction_transfer(self, b, user_vk, user_sk):
|
||||
input_tx = b.get_owned_ids(user_vk).pop()
|
||||
tx = b.create_transaction(b.me, user_sk, input_tx, 'TRANSFER')
|
||||
|
||||
assert sorted(tx) == sorted(['id', 'transaction', 'version'])
|
||||
assert sorted(tx['transaction']) == sorted(['conditions', 'data', 'fulfillments', 'operation', 'timestamp'])
|
||||
|
||||
def test_transaction_hash(self, b):
|
||||
payload = {'cats': 'are awesome'}
|
||||
tx = b.create_transaction('a', 'b', 'c', 'd', payload)
|
||||
|
Loading…
x
Reference in New Issue
Block a user