def validate_fulfillments(signed_transaction): """Validate the fulfillments of a transaction. Refer to the documentation of ``bigchaindb.util.validate_fulfillments`` """ return util.validate_fulfillments(signed_transaction)
def test_client_can_create_assets(mock_requests_post, client): from bigchaindb import util tx = client.create() # XXX: `CREATE` operations require the node that receives the transaction to modify the data in # the transaction itself. # `current_owner` will be overwritten with the public key of the node in the federation # that will create the real transaction. `signature` will be overwritten with the new signature. # Note that this scenario is ignored by this test. assert tx['transaction']['fulfillments'][0]['current_owners'][0] == client.public_key assert tx['transaction']['conditions'][0]['new_owners'][0] == client.public_key assert tx['transaction']['fulfillments'][0]['input'] is None assert util.validate_fulfillments(tx)
def validate_transaction(bigchain, transaction): """Validate a transaction. Args: bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. transaction (dict): transaction to validate. Returns: The transaction if the transaction is valid else it raises an exception describing the reason why the transaction is invalid. Raises: OperationError: if the transaction operation is not supported TransactionDoesNotExist: if the input of the transaction is not found TransactionOwnerError: if the new transaction is using an input it doesn't own DoubleSpend: if the transaction is a double spend InvalidHash: if the hash of the transaction is wrong InvalidSignature: if the signature of the transaction is wrong """ # If the operation is CREATE the transaction should have no inputs and # should be signed by a federation node if transaction['transaction']['operation'] == 'CREATE': # TODO: for now lets assume a CREATE transaction only has one fulfillment if transaction['transaction']['fulfillments'][0]['input']: raise ValueError('A CREATE operation has no inputs') # TODO: for now lets assume a CREATE transaction only has one current_owner if transaction['transaction']['fulfillments'][0]['current_owners'][ 0] not in (bigchain.nodes_except_me + [bigchain.me]): raise exceptions.OperationError( 'Only federation nodes can use the operation `CREATE`') else: # check if the input exists, is owned by the current_owner if not transaction['transaction']['fulfillments']: raise ValueError('Transaction contains no fulfillments') # check inputs for fulfillment in transaction['transaction']['fulfillments']: if not fulfillment['input']: raise ValueError( 'Only `CREATE` transactions can have null inputs') tx_input = bigchain.get_transaction( fulfillment['input']['txid']) if not tx_input: raise exceptions.TransactionDoesNotExist( 'input `{}` does not exist in the bigchain'.format( fulfillment['input']['txid'])) # TODO: check if current owners own tx_input (maybe checked by InvalidSignature) # check if the input was already spent by a transaction other than # this one. spent = bigchain.get_spent(fulfillment['input']) if spent and spent['id'] != transaction['id']: raise exceptions.DoubleSpend( 'input `{}` was already spent'.format( fulfillment['input'])) # Check hash of the transaction calculated_hash = util.get_hash_data(transaction) if calculated_hash != transaction['id']: raise exceptions.InvalidHash() # Check fulfillments if not util.validate_fulfillments(transaction): raise exceptions.InvalidSignature() return transaction
def validate_transaction(bigchain, transaction): """Validate a transaction. Args: bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. transaction (dict): transaction to validate. Returns: The transaction if the transaction is valid else it raises an exception describing the reason why the transaction is invalid. Raises: OperationError: if the transaction operation is not supported TransactionDoesNotExist: if the input of the transaction is not found TransactionOwnerError: if the new transaction is using an input it doesn't own DoubleSpend: if the transaction is a double spend InvalidHash: if the hash of the transaction is wrong InvalidSignature: if the signature of the transaction is wrong """ # If the operation is CREATE the transaction should have no inputs and # should be signed by a federation node if transaction['transaction']['operation'] == 'CREATE': # TODO: for now lets assume a CREATE transaction only has one fulfillment if transaction['transaction']['fulfillments'][0]['input']: raise ValueError('A CREATE operation has no inputs') # TODO: for now lets assume a CREATE transaction only has one current_owner if transaction['transaction']['fulfillments'][0]['current_owners'][0] not in ( bigchain.federation_nodes + [bigchain.me]): raise exceptions.OperationError( 'Only federation nodes can use the operation `CREATE`') else: # check if the input exists, is owned by the current_owner if not transaction['transaction']['fulfillments']: raise ValueError('Transaction contains no fulfillments') # check inputs for fulfillment in transaction['transaction']['fulfillments']: if not fulfillment['input']: raise ValueError('Only `CREATE` transactions can have null inputs') tx_input = bigchain.get_transaction(fulfillment['input']['txid']) if not tx_input: raise exceptions.TransactionDoesNotExist( 'input `{}` does not exist in the bigchain'.format( fulfillment['input']['txid'])) # TODO: check if current owners own tx_input (maybe checked by InvalidSignature) # check if the input was already spent by a transaction other than # this one. spent = bigchain.get_spent(fulfillment['input']) if spent and spent['id'] != transaction['id']: raise exceptions.DoubleSpend( 'input `{}` was already spent'.format(fulfillment['input'])) # Check hash of the transaction calculated_hash = util.get_hash_data(transaction) if calculated_hash != transaction['id']: raise exceptions.InvalidHash() # Check fulfillments if not util.validate_fulfillments(transaction): raise exceptions.InvalidSignature() return transaction