Merge remote-tracking branch 'remotes/origin/feat/128/multiple-input-output' into feat/127/crypto-conditions-ilp-bigchain-integration

Conflicts:
	bigchaindb/core.py
This commit is contained in:
diminator 2016-04-07 15:43:35 +02:00
commit a7ca11a593
No known key found for this signature in database
GPG Key ID: C3D8590E6D0D439A
3 changed files with 19 additions and 23 deletions

View File

@ -131,32 +131,26 @@ class BaseConsensusRules(AbstractConsensusRules):
else: else:
# check if the input exists, is owned by the current_owner # check if the input exists, is owned by the current_owner
if not transaction['transaction']['inputs']: if not transaction['transaction']['fulfillments']:
raise ValueError( raise ValueError(
'Only `CREATE` transactions can have null inputs') 'Transaction contains no fulfillments')
# check inputs # check inputs
for inp in transaction['transaction']['inputs']: for fulfillment in transaction['transaction']['fulfillments']:
tx_input = bigchain.get_transaction(inp) tx_input = bigchain.get_transaction(fulfillment['input']['txid'])
if not tx_input: if not tx_input:
raise exceptions.TransactionDoesNotExist( raise exceptions.TransactionDoesNotExist(
'input `{}` does not exist in the bigchain'.format( 'input `{}` does not exist in the bigchain'.format(
transaction['transaction']['input'])) fulfillment['input']['txid']))
if (tx_input['transaction']['new_owner'] !=
transaction['transaction']['current_owner']):
raise exceptions.TransactionOwnerError(
'current_owner `{}` does not own the input `{}`'.format(
transaction['transaction']['current_owner'],
transaction['transaction']['input']))
# check if the input was already spent by a transaction other than # check if the input was already spent by a transaction other than
# this one. # this one.
spent = bigchain.get_spent(tx_input['id']) spent = bigchain.get_spent(fulfillment['input'])
print(spent)
if spent and spent['id'] != transaction['id']: if spent and spent['id'] != transaction['id']:
raise exceptions.DoubleSpend( raise exceptions.DoubleSpend(
'input `{}` was already spent'.format(inp)) 'input `{}` was already spent'.format(fulfillment['input']))
# Check hash of the transaction # Check hash of the transaction
# remove the fulfillment messages (signatures) # remove the fulfillment messages (signatures)

View File

@ -186,29 +186,31 @@ class Bigchain(object):
transactions = list(cursor) transactions = list(cursor)
return transactions return transactions
def get_spent(self, txid): def get_spent(self, inp):
"""Check if a `txid` was already used as an input. """Check if a `txid` was already used as an input.
A transaction can be used as an input for another transaction. Bigchain needs to make sure that a A transaction can be used as an input for another transaction. Bigchain needs to make sure that a
given `txid` is only used once. given `txid` is only used once.
Args: Args:
txid (str): transaction id. inp (dict): Input of a transaction in the form `{'txid': 'transaction id', 'cid': 'condition id'}`
Returns: Returns:
The transaction that used the `txid` as an input if it exists else it returns `None` The transaction that used the `txid` as an input if it exists else it returns `None`
""" """
# checks if an input was already spent # checks if an input was already spent
# checks if the bigchain has any transaction with input `transaction_id` # checks if the bigchain has any transaction with input {'txid': ..., 'cid': ...}
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) .filter(lambda transaction: transaction['transaction']['fulfillments']
.contains(lambda fulfillment: fulfillment['input'] == inp))\
.run(self.conn)
# a transaction_id should have been spent at most one time # a transaction_id should have been spent at most one time
transactions = list(response) transactions = list(response)
if transactions: if transactions:
if len(transactions) != 1: if len(transactions) != 1:
raise Exception('`{}` was spent more then once. There is a problem with the chain'.format( raise Exception('`{}` was spent more then once. There is a problem with the chain'.format(
txid)) inp['txid']))
else: else:
return transactions[0] return transactions[0]
else: else:

View File

@ -221,7 +221,7 @@ def create_tx(current_owners, new_owners, inputs, operation, payload=None):
return transaction return transaction
#TODO: Change sign_tx to populate the fulfillments # TODO: Change sign_tx to populate the fulfillments
def sign_tx(transaction, private_key): def sign_tx(transaction, private_key):
"""Sign a transaction """Sign a transaction
@ -261,7 +261,7 @@ def sign_tx(transaction, private_key):
# update the fulfillment message # update the fulfillment message
fulfillment_message.update({ fulfillment_message.update({
'input': fulfillment['input'], 'input': fulfillment['input'],
'condition': conditions[fulfillment['cid']] 'condition': conditions[fulfillment['fid']]
}) })
# sign the fulfillment message # sign the fulfillment message
@ -322,7 +322,7 @@ def verify_signature(signed_transaction):
# get previous condition # get previous condition
previous_tx = b.get_transaction(fulfillment['input']['txid']) previous_tx = b.get_transaction(fulfillment['input']['txid'])
conditions = sorted(previous_tx['transaction']['conditions'], key=lambda d: d['cid']) conditions = sorted(previous_tx['transaction']['conditions'], key=lambda d: d['cid'])
fulfillment_message['condition'] = conditions[fulfillment['cid']] fulfillment_message['condition'] = conditions[fulfillment['fid']]
# verify the signature (for now lets assume there is only one owner) # verify the signature (for now lets assume there is only one owner)
vk = crypto.VerifyingKey(fulfillment['current_owners'][0]) vk = crypto.VerifyingKey(fulfillment['current_owners'][0])