Esempio n. 1
0
    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 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)
Esempio n. 3
0
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)
Esempio n. 4
0
    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