diff --git a/bigchaindb/core.py b/bigchaindb/core.py index d7eb55fe..81ddb2f9 100644 --- a/bigchaindb/core.py +++ b/bigchaindb/core.py @@ -359,22 +359,29 @@ class Bigchain(object): transactions.append(tx) return transactions - def get_txs_by_asset_id(self, asset_id): - """Retrieves transactions related to a particular asset. + def get_transactions_by_asset_id(self, asset_id): + """Retrieves valid or undecided transactions related to a particular + asset. - A digital asset in bigchaindb is identified by an uuid. This allows us to query all the transactions - related to a particular digital asset, knowing the id. + A digital asset in bigchaindb is identified by an uuid. This allows us + to query all the transactions related to a particular digital asset, + knowing the id. Args: asset_id (str): the id for this particular metadata. Returns: - A list of transactions containing related to the asset. If no transaction exists for that asset it - returns an empty list `[]` + A list of valid or undecided transactions related to the asset. + If no transaction exists for that asset it returns an empty list + `[]` """ - - cursor = self.backend.get_transactions_by_asset_id(asset_id) - return [Transaction.from_dict(tx) for tx in cursor] + txids = self.backend.get_txids_by_asset_id(asset_id) + transactions = [] + for txid in txids: + tx = self.get_transaction(txid) + if tx: + transactions.append(tx) + return transactions def get_asset_by_id(self, asset_id): """Returns the asset associated with an asset_id. diff --git a/bigchaindb/db/backends/rethinkdb.py b/bigchaindb/db/backends/rethinkdb.py index 1981fbc1..f01bdb4a 100644 --- a/bigchaindb/db/backends/rethinkdb.py +++ b/bigchaindb/db/backends/rethinkdb.py @@ -164,26 +164,29 @@ class RethinkDBBackend: metadata_id) .get_field('id')) - def get_transactions_by_asset_id(self, asset_id): - """Retrieves transactions related to a particular asset. + def get_txids_by_asset_id(self, asset_id): + """Retrieves transactions ids related to a particular asset. - A digital asset in bigchaindb is identified by an uuid. This allows us to query all the transactions - related to a particular digital asset, knowing the id. + A digital asset in bigchaindb is identified by an uuid. This allows us + to query all the transactions related to a particular digital asset, + knowing the id. Args: asset_id (str): the id for this particular metadata. Returns: - A list of transactions containing related to the asset. If no transaction exists for that asset it - returns an empty list `[]` + A list of transactions ids related to the asset. If no transaction + exists for that asset it returns an empty list `[]` """ + # here we only want to return the transaction ids since later on when + # we are going to retrieve the transaction with status validation return self.connection.run( r.table('bigchain', read_mode=self.read_mode) .get_all(asset_id, index='asset_id') .concat_map(lambda block: block['block']['transactions']) - .filter(lambda transaction: - transaction['transaction']['asset']['id'] == asset_id)) + .filter(lambda transaction: transaction['transaction']['asset']['id'] == asset_id) + .get_field('id')) def get_asset_by_id(self, asset_id): """Returns the asset associated with an asset_id. diff --git a/tests/assets/test_digital_assets.py b/tests/assets/test_digital_assets.py index 697415e7..5d8654f2 100644 --- a/tests/assets/test_digital_assets.py +++ b/tests/assets/test_digital_assets.py @@ -112,13 +112,13 @@ def test_asset_id_mismatch(b, user_pk): @pytest.mark.usefixtures('inputs') -def test_get_txs_by_asset_id(b, user_pk, user_sk): +def test_get_transactions_by_asset_id(b, user_pk, user_sk): from bigchaindb.models import Transaction tx_create = b.get_owned_ids(user_pk).pop() tx_create = b.get_transaction(tx_create.txid) asset_id = tx_create.asset.data_id - txs = b.get_txs_by_asset_id(asset_id) + txs = b.get_transactions_by_asset_id(asset_id) assert len(txs) == 1 assert txs[0].id == tx_create.id @@ -135,7 +135,7 @@ def test_get_txs_by_asset_id(b, user_pk, user_sk): vote = b.vote(block.id, b.get_last_voted_block().id, True) b.write_vote(vote) - txs = b.get_txs_by_asset_id(asset_id) + txs = b.get_transactions_by_asset_id(asset_id) assert len(txs) == 2 assert tx_create.id in [t.id for t in txs] @@ -144,6 +144,35 @@ def test_get_txs_by_asset_id(b, user_pk, user_sk): assert asset_id == txs[1].asset.data_id +@pytest.mark.usefixtures('inputs') +def test_get_transactions_by_asset_id_with_invalid_block(b, user_pk, user_sk): + from bigchaindb.models import Transaction + + tx_create = b.get_owned_ids(user_pk).pop() + tx_create = b.get_transaction(tx_create.txid) + asset_id = tx_create.asset.data_id + txs = b.get_transactions_by_asset_id(asset_id) + + assert len(txs) == 1 + assert txs[0].id == tx_create.id + assert txs[0].asset.data_id == asset_id + + # create a transfer transaction + tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)], + tx_create.asset) + tx_transfer_signed = tx_transfer.sign([user_sk]) + # create the block + block = b.create_block([tx_transfer_signed]) + b.write_block(block, durability='hard') + # vote the block invalid + vote = b.vote(block.id, b.get_last_voted_block().id, False) + b.write_vote(vote) + + txs = b.get_transactions_by_asset_id(asset_id) + + assert len(txs) == 1 + + @pytest.mark.usefixtures('inputs') def test_get_asset_by_id(b, user_pk, user_sk): from bigchaindb.models import Transaction @@ -163,7 +192,7 @@ def test_get_asset_by_id(b, user_pk, user_sk): vote = b.vote(block.id, b.get_last_voted_block().id, True) b.write_vote(vote) - txs = b.get_txs_by_asset_id(asset_id) + txs = b.get_transactions_by_asset_id(asset_id) assert len(txs) == 2 asset = b.get_asset_by_id(asset_id)