From eea3cc015a2b3210cb66b333a801af5c6ec77c83 Mon Sep 17 00:00:00 2001 From: Rodolphe Marques Date: Wed, 6 Apr 2016 16:26:24 +0200 Subject: [PATCH 1/2] small fix in the retrieval of the condition in verifying and signing transactions --- bigchaindb/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bigchaindb/util.py b/bigchaindb/util.py index 4604cc52..e0c9cbcb 100644 --- a/bigchaindb/util.py +++ b/bigchaindb/util.py @@ -246,7 +246,7 @@ def sign_tx(transaction, private_key): # update the fulfillment message fulfillment_message.update({ 'input': fulfillment['input'], - 'condition': conditions[fulfillment['cid']] + 'condition': conditions[fulfillment['fid']] }) # sign the fulfillment message @@ -307,7 +307,7 @@ def verify_signature(signed_transaction): # get previous condition previous_tx = b.get_transaction(fulfillment['input']['txid']) 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) public_key = PublicKey(fulfillment['current_owners'][0]) From ade6bfb1c0d7e4f7cbb3ec26a911ed0ea70d124a Mon Sep 17 00:00:00 2001 From: Rodolphe Marques Date: Thu, 7 Apr 2016 15:38:38 +0200 Subject: [PATCH 2/2] Updated validate_transaction to work with crypto conditions. Updated get_spent to work with multiple inputs --- bigchaindb/consensus.py | 22 ++++++++-------------- bigchaindb/core.py | 12 +++++++----- bigchaindb/util.py | 2 +- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/bigchaindb/consensus.py b/bigchaindb/consensus.py index a3090fc8..c34258c5 100644 --- a/bigchaindb/consensus.py +++ b/bigchaindb/consensus.py @@ -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) diff --git a/bigchaindb/core.py b/bigchaindb/core.py index 374708e9..413489b5 100644 --- a/bigchaindb/core.py +++ b/bigchaindb/core.py @@ -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: diff --git a/bigchaindb/util.py b/bigchaindb/util.py index e0c9cbcb..c767a425 100644 --- a/bigchaindb/util.py +++ b/bigchaindb/util.py @@ -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