diff --git a/bigchaindb/consensus.py b/bigchaindb/consensus.py index c44b98fd..2f803c60 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 2612c1ed..b4ac1644 100644 --- a/bigchaindb/core.py +++ b/bigchaindb/core.py @@ -186,29 +186,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` - response = r.table('bigchain').concat_map(lambda doc: doc['block']['transactions']) \ - .filter(lambda transaction: transaction['transaction']['inputs'].contains(txid)).run(self.conn) + # 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']['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 d6f87751..e63aa1d1 100644 --- a/bigchaindb/util.py +++ b/bigchaindb/util.py @@ -221,7 +221,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 @@ -261,7 +261,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 @@ -322,7 +322,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) vk = crypto.VerifyingKey(fulfillment['current_owners'][0])