Updated validate_transaction to work with crypto conditions.

Updated get_spent to work with multiple inputs
This commit is contained in:
Rodolphe Marques
2016-04-07 15:38:38 +02:00
parent eea3cc015a
commit ade6bfb1c0
3 changed files with 16 additions and 20 deletions

View File

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

View File

@@ -188,29 +188,31 @@ class Bigchain(object):
transactions = list(cursor)
return transactions
def get_spent(self, txid):
def get_spent(self, inp):
"""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
given `txid` is only used once.
Args:
txid (str): transaction id.
inp (dict): Input of a transaction in the form `{'txid': 'transaction id', 'cid': 'condition id'}`
Returns:
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 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'])\
.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
transactions = list(response)
if transactions:
if len(transactions) != 1:
raise Exception('`{}` was spent more then once. There is a problem with the chain'.format(
txid))
inp['txid']))
else:
return transactions[0]
else:

View File

@@ -206,7 +206,7 @@ def create_tx(current_owners, new_owners, inputs, operation, payload=None):
return transaction
#TODO: Change sign_tx to populate the fulfillments
# TODO: Change sign_tx to populate the fulfillments
def sign_tx(transaction, private_key):
"""Sign a transaction