From b7b9338f21d2c90ed4dec13e27ae0fb40c260326 Mon Sep 17 00:00:00 2001 From: Rodolphe Marques Date: Fri, 11 Nov 2016 15:25:59 +0100 Subject: [PATCH 1/2] get_transactions_by_asset_id now ignores invalid transactions --- bigchaindb/core.py | 25 ++++++++++++------- bigchaindb/db/backends/rethinkdb.py | 18 ++++++++------ tests/assets/test_digital_assets.py | 37 +++++++++++++++++++++++++---- 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/bigchaindb/core.py b/bigchaindb/core.py index 5a007eab..19add873 100644 --- a/bigchaindb/core.py +++ b/bigchaindb/core.py @@ -326,22 +326,29 @@ class Bigchain(object): cursor = self.backend.get_transactions_by_metadata_id(metadata_id) return [Transaction.from_dict(tx) for tx in cursor] - 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_spent(self, txid, cid): """Check if a `txid` was already used as an input. diff --git a/bigchaindb/db/backends/rethinkdb.py b/bigchaindb/db/backends/rethinkdb.py index 22937dd2..85799287 100644 --- a/bigchaindb/db/backends/rethinkdb.py +++ b/bigchaindb/db/backends/rethinkdb.py @@ -160,25 +160,29 @@ class RethinkDBBackend: .concat_map(lambda block: block['block']['transactions']) .filter(lambda transaction: transaction['transaction']['metadata']['id'] == metadata_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_spent(self, transaction_id, condition_id): """Check if a `txid` was already used as an input. diff --git a/tests/assets/test_digital_assets.py b/tests/assets/test_digital_assets.py index e18684c5..83d34b6d 100644 --- a/tests/assets/test_digital_assets.py +++ b/tests/assets/test_digital_assets.py @@ -1,5 +1,5 @@ import pytest -from ..db.conftest import inputs +from ..db.conftest import inputs # noqa @pytest.mark.usefixtures('inputs') @@ -131,13 +131,13 @@ def test_asset_id_mismatch(b, user_vk): @pytest.mark.usefixtures('inputs') -def test_get_txs_by_asset_id(b, user_vk, user_sk): +def test_get_transactions_by_asset_id(b, user_vk, user_sk): from bigchaindb.models import Transaction tx_create = b.get_owned_ids(user_vk).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 @@ -154,10 +154,39 @@ def test_get_txs_by_asset_id(b, user_vk, 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] assert tx_transfer.id in [t.id for t in txs] assert asset_id == txs[0].asset.data_id assert asset_id == txs[1].asset.data_id + + +@pytest.mark.usefixtures('inputs') +def test_get_transactions_by_asset_id_with_invalid_block(b, user_vk, user_sk): + from bigchaindb.models import Transaction + + tx_create = b.get_owned_ids(user_vk).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_vk], + 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 valid + 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 From aef5dcdf1b17a07d97562bb7b89505a55e726ce9 Mon Sep 17 00:00:00 2001 From: Rodolphe Marques Date: Fri, 18 Nov 2016 14:40:26 +0100 Subject: [PATCH 2/2] fixed typo --- tests/assets/test_digital_assets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/assets/test_digital_assets.py b/tests/assets/test_digital_assets.py index 83d34b6d..8143bef8 100644 --- a/tests/assets/test_digital_assets.py +++ b/tests/assets/test_digital_assets.py @@ -183,7 +183,7 @@ def test_get_transactions_by_asset_id_with_invalid_block(b, user_vk, user_sk): # create the block block = b.create_block([tx_transfer_signed]) b.write_block(block, durability='hard') - # vote the block valid + # vote the block invalid vote = b.vote(block.id, b.get_last_voted_block().id, False) b.write_vote(vote)