def verify_signature(signed_transaction): """Verify the signature of a transaction. Refer to the documentation of ``bigchaindb.util.verify_signature`` """ return util.verify_signature(signed_transaction)
def test_transform_create(b, user_private_key, user_public_key): tx = util.create_tx(user_public_key, user_public_key, None, 'CREATE') tx = util.transform_create(tx) tx = util.sign_tx(tx, b.me_private) assert tx['transaction']['current_owner'] == b.me assert tx['transaction']['new_owner'] == user_public_key assert util.verify_signature(tx)
def test_transform_create(b, user_sk, user_vk): from bigchaindb import util tx = util.create_tx(user_vk, user_vk, None, 'CREATE') tx = util.transform_create(tx) tx = util.sign_tx(tx, b.me_private) assert tx['transaction']['fulfillments'][0]['current_owners'][0] == b.me assert tx['transaction']['conditions'][0]['new_owners'][0] == user_vk assert util.verify_signature(tx)
def test_client_can_transfer_assets(mock_requests_post, client): from bigchaindb import util tx = client.transfer('a', 123) assert tx['transaction']['current_owner'] == client.public_key assert tx['transaction']['new_owner'] == 'a' assert tx['transaction']['input'] == 123 assert util.verify_signature(tx)
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']['current_owner'] == client.public_key assert tx['transaction']['new_owner'] == client.public_key assert tx['transaction']['input'] == None assert util.verify_signature(tx)
def create_transaction(): """API endpoint to push transactions to the Federation. Return: A JSON string containing the data about the transaction. """ bigchain = current_app.config['bigchain'] val = {} # `force` will try to format the body of the POST request even if the `content-type` header is not # set to `application/json` tx = request.get_json(force=True) if tx['transaction']['operation'] == 'CREATE': tx = util.transform_create(tx) tx = util.sign_tx(tx, bigchain.me_private) if not util.verify_signature(tx): val['error'] = 'Invalid transaction signature' val = bigchain.write_transaction(tx) return flask.jsonify(**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': if transaction['transaction']['input']: raise ValueError('A CREATE operation has no inputs') if transaction['transaction']['current_owner'] 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']['input']: raise ValueError( 'Only `CREATE` transactions can have null inputs') tx_input = bigchain.get_transaction( transaction['transaction']['input']) 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'])) # check if the input was already spent by a transaction other than # this one. spent = bigchain.get_spent(tx_input['id']) if spent and spent['id'] != transaction['id']: raise exceptions.DoubleSpend( 'input `{}` was already spent'.format( transaction['transaction']['input'])) # Check hash of the transaction calculated_hash = crypto.hash_data( util.serialize(transaction['transaction'])) if calculated_hash != transaction['id']: raise exceptions.InvalidHash() # Check signature if not util.verify_signature(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': if transaction['transaction']['input']: raise ValueError('A CREATE operation has no inputs') if transaction['transaction']['current_owner'] 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']['input']: raise ValueError( 'Only `CREATE` transactions can have null inputs') tx_input = bigchain.get_transaction( transaction['transaction']['input']) 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'])) # check if the input was already spent by a transaction other than # this one. spent = bigchain.get_spent(tx_input['id']) if spent and spent['id'] != transaction['id']: raise exceptions.DoubleSpend( 'input `{}` was already spent'.format( transaction['transaction']['input'])) # Check hash of the transaction calculated_hash = crypto.hash_data(util.serialize( transaction['transaction'])) if calculated_hash != transaction['id']: raise exceptions.InvalidHash() # Check signature if not util.verify_signature(transaction): raise exceptions.InvalidSignature() return transaction