diff --git a/bigchaindb/common/schema/__init__.py b/bigchaindb/common/schema/__init__.py index 52c70c13..2c005ac5 100644 --- a/bigchaindb/common/schema/__init__.py +++ b/bigchaindb/common/schema/__init__.py @@ -29,6 +29,8 @@ def _load_schema(name): TX_SCHEMA_PATH, TX_SCHEMA = _load_schema('transaction') +_, TX_SCHEMA_CREATE = _load_schema('transaction_create') +_, TX_SCHEMA_TRANSFER = _load_schema('transaction_transfer') VOTE_SCHEMA_PATH, VOTE_SCHEMA = _load_schema('vote') @@ -43,6 +45,10 @@ def _validate_schema(schema, body): def validate_transaction_schema(tx): """ Validate a transaction dict """ _validate_schema(TX_SCHEMA, tx) + if tx['operation'] == 'TRANSFER': + _validate_schema(TX_SCHEMA_TRANSFER, tx) + else: + _validate_schema(TX_SCHEMA_CREATE, tx) def validate_vote_schema(vote): diff --git a/bigchaindb/common/schema/transaction_create.yaml b/bigchaindb/common/schema/transaction_create.yaml new file mode 100644 index 00000000..090d4680 --- /dev/null +++ b/bigchaindb/common/schema/transaction_create.yaml @@ -0,0 +1,17 @@ +--- +"$schema": "http://json-schema.org/draft-04/schema#" +type: object +title: Transaction Schema - CREATE/GENESIS specific properties +required: +- asset +properties: + asset: + additionalProperties: false + properties: + data: + description: | + User provided metadata associated with the asset. May also be ``null``. + anyOf: + - type: object + additionalProperties: true + - type: 'null' diff --git a/bigchaindb/common/schema/transaction_transfer.yaml b/bigchaindb/common/schema/transaction_transfer.yaml new file mode 100644 index 00000000..80abbf95 --- /dev/null +++ b/bigchaindb/common/schema/transaction_transfer.yaml @@ -0,0 +1,18 @@ +--- +"$schema": "http://json-schema.org/draft-04/schema#" +type: object +title: Transaction Schema - TRANSFER specific properties +required: +- asset +properties: + asset: + additionalProperties: false + properties: + id: + "$ref": "#/definitions/sha3_hexdigest" + description: | + ID of the transaction that created the asset. +definitions: + sha3_hexdigest: + pattern: "[0-9a-f]{64}" + type: string diff --git a/bigchaindb/common/transaction.py b/bigchaindb/common/transaction.py index 02332c38..23b8f169 100644 --- a/bigchaindb/common/transaction.py +++ b/bigchaindb/common/transaction.py @@ -999,7 +999,8 @@ class Transaction(object): transactions = [transactions] # create a set of the transactions' asset ids - asset_ids = {tx.id if tx.operation == Transaction.CREATE else tx.asset['id'] + asset_ids = {tx.id if tx.operation == Transaction.CREATE + else tx.asset['id'] for tx in transactions} # check that all the transasctions have the same asset id diff --git a/bigchaindb/models.py b/bigchaindb/models.py index 4f7d31f2..5d4b6c9d 100644 --- a/bigchaindb/models.py +++ b/bigchaindb/models.py @@ -25,9 +25,6 @@ class Transaction(Transaction): Raises: ValidationError: If the transaction is invalid """ - if len(self.inputs) == 0: - raise ValidationError('Transaction contains no inputs') - input_conditions = [] inputs_defined = all([input_.fulfills for input_ in self.inputs]) @@ -117,8 +114,12 @@ class Transaction(Transaction): return self @classmethod - def from_dict(cls, tx_body): + def validate_structure(cls, tx_body): validate_transaction_schema(tx_body) + + @classmethod + def from_dict(cls, tx_body): + cls.validate_structure(tx_body) return super().from_dict(tx_body) diff --git a/tests/test_behaviours.py b/tests/test_behaviours.py new file mode 100644 index 00000000..72bb4f17 --- /dev/null +++ b/tests/test_behaviours.py @@ -0,0 +1,17 @@ +import pytest +from bigchaindb.common import exceptions as exc +from bigchaindb.models import Transaction + + +################################################################################ +# 1.1 - The asset ID of a CREATE transaction is the same as it's ID + + +def test_create_tx_no_asset_id(b): + tx = Transaction.create([b.me], [([b.me], 1)]) + # works + Transaction.validate_structure(tx.to_dict()) + # broken + tx.asset['id'] = 'b' * 64 + with pytest.raises(exc.SchemaValidationError): + Transaction.validate_structure(tx.to_dict())