diff --git a/bigchaindb/core.py b/bigchaindb/core.py index 49ae59b2..555b7ebe 100644 --- a/bigchaindb/core.py +++ b/bigchaindb/core.py @@ -395,6 +395,13 @@ class Bigchain(object): ' with the chain'.format(txid)) # if its not and invalid transaction if status is not None: + if 'metadata' not in transaction: + metadata = list(self.get_metadata([transaction['id']])) + metadata = metadata[0] if metadata else None + if metadata: + metadata.pop('id', None) + transaction.update({'metadata': metadata}) + non_invalid_transactions.append(transaction) if non_invalid_transactions: diff --git a/bigchaindb/models.py b/bigchaindb/models.py index 981f7379..a1dde131 100644 --- a/bigchaindb/models.py +++ b/bigchaindb/models.py @@ -5,7 +5,7 @@ from bigchaindb.common.exceptions import (InvalidHash, InvalidSignature, DoubleSpend, InputDoesNotExist, TransactionNotInValidBlock, AssetIdMismatch, AmountError, - SybilError, + SybilError, ValidationError, DuplicateTransaction) from bigchaindb.common.transaction import Transaction from bigchaindb.common.utils import (gen_timestamp, serialize, @@ -47,9 +47,7 @@ class Transaction(Transaction): 'input `{}` does not exist in a valid block'.format( input_txid)) - print(input_txid, self.id) spent = bigchain.get_spent(input_txid, input_.fulfills.output) - print(spent) if spent and spent.id != self.id: raise DoubleSpend('input `{}` was already spent' .format(input_txid)) @@ -116,9 +114,11 @@ class Transaction(Transaction): # get metadata of the transaction metadata = list(bigchain.get_metadata([tx_dict['id']])) - if metadata: - metadata = metadata[0] - del metadata['id'] + if 'metadata' not in tx_dict: + metadata = metadata[0] if metadata else None + if metadata: + metadata.pop('id', None) + tx_dict.update({'metadata': metadata}) return cls.from_dict(tx_dict) @@ -407,8 +407,8 @@ class Block(object): if isinstance(metadata, dict): metadata.update({'id': transaction['id']}) metadatas.append(metadata) - else: - transaction.update({'metadata': metadata}) + elif metadata: + raise ValidationError('Invalid value for metadata') return (metadatas, block_dict) @@ -444,6 +444,10 @@ class Block(object): and a list of metadata, reconstruct the original block by putting the metadata of each transaction back into its original transaction. + NOTE: Till a transaction gets accepted the `metadata` of the transaction + is not moved outside of the transaction. So, if a transaction is found to + have metadata then it should not be overridden. + Args: block_dict (:obj:`dict`): The block dict as returned from a database call. @@ -457,9 +461,13 @@ class Block(object): metadatal = {m.pop('id'): m for m in metadatal} # add the metadata to their corresponding transactions for transaction in block_dict['block']['transactions']: - metadata = metadatal.get(transaction['id']) - if metadata: - transaction.update({'metadata': metadata}) + if 'metadata' not in transaction: + metadata = metadatal.get(transaction['id']) + if metadata: + metadata.pop('id', None) + transaction.update({'metadata': metadata}) + else: + transaction.update({'metadata': None}) return block_dict @staticmethod diff --git a/tests/backend/mongodb/test_queries.py b/tests/backend/mongodb/test_queries.py index 6e4222f4..fea2c7c4 100644 --- a/tests/backend/mongodb/test_queries.py +++ b/tests/backend/mongodb/test_queries.py @@ -421,7 +421,8 @@ def test_get_new_blocks_feed(b, create_tx): ts = str(random.random()) block = Block(transactions=[create_tx], timestamp=ts) b.write_block(block) - return block.decouple_assets()[1] + block_dict = block.decouple_assets()[1] + return block.decouple_metadata(block_dict)[1] create_block() b1 = create_block() diff --git a/tests/backend/rethinkdb/test_schema.py b/tests/backend/rethinkdb/test_schema.py index 6f77b672..e56dfd21 100644 --- a/tests/backend/rethinkdb/test_schema.py +++ b/tests/backend/rethinkdb/test_schema.py @@ -64,7 +64,8 @@ def test_create_tables(): assert conn.run(r.db(dbname).table_list().contains('backlog')) is True assert conn.run(r.db(dbname).table_list().contains('votes')) is True assert conn.run(r.db(dbname).table_list().contains('assets')) is True - assert len(conn.run(r.db(dbname).table_list())) == 4 + assert conn.run(r.db(dbname).table_list().contains('metadata')) is True + assert len(conn.run(r.db(dbname).table_list())) == 5 @pytest.mark.bdb diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py index 836c5970..c6eb355a 100644 --- a/tests/integration/test_integration.py +++ b/tests/integration/test_integration.py @@ -38,7 +38,6 @@ def test_get_owned_ids_works_after_double_spend(b, user_pk, user_sk): input_valid.id, {'1': 1}).sign([user_sk]) - print(tx_valid) # write the valid tx and wait for voting/block to catch up b.write_transaction(tx_valid) time.sleep(5)