mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Problem: 2 implementations of fastquery exist. (#2365)
* Problem: 2 implementations of fastquery exist. Solution: Remove the old deprecated implementation. Update the tests. * Problem: There are still 3 outdated fastquery tests. Solution: Fix the tests.
This commit is contained in:
parent
1bad851e07
commit
744ab3d5ef
@ -1,60 +0,0 @@
|
||||
from bigchaindb.utils import condition_details_has_owner
|
||||
from bigchaindb.backend import query
|
||||
from bigchaindb.common.transaction import TransactionLink
|
||||
|
||||
|
||||
class FastQuery:
|
||||
"""Database queries that join on block results from a single node.
|
||||
|
||||
* Votes are not validated for security (security is a replication concern)
|
||||
* Votes come from only one node, and as such, non-byzantine fault tolerance
|
||||
is reduced.
|
||||
|
||||
Previously, to consider the status of a block, all votes for that block
|
||||
were retrieved and the election results were counted. This meant that a
|
||||
faulty node may still have been able to obtain a correct election result.
|
||||
However, from the point of view of a client, it is still neccesary to
|
||||
query multiple nodes to insure against getting an incorrect response from
|
||||
a byzantine node.
|
||||
"""
|
||||
|
||||
def __init__(self, connection):
|
||||
self.connection = connection
|
||||
|
||||
def get_outputs_by_public_key(self, public_key):
|
||||
"""Get outputs for a public key"""
|
||||
res = list(query.get_owned_ids(self.connection, public_key))
|
||||
txs = [tx for _, tx in self.filter_valid_items(res)]
|
||||
return [TransactionLink(tx['id'], index)
|
||||
for tx in txs
|
||||
for index, output in enumerate(tx['outputs'])
|
||||
if condition_details_has_owner(output['condition']['details'],
|
||||
public_key)]
|
||||
|
||||
def filter_spent_outputs(self, outputs):
|
||||
"""Remove outputs that have been spent
|
||||
|
||||
Args:
|
||||
outputs: list of TransactionLink
|
||||
"""
|
||||
links = [o.to_dict() for o in outputs]
|
||||
res = query.get_spending_transactions(self.connection, links)
|
||||
txs = [tx for _, tx in self.filter_valid_items(res)]
|
||||
spends = {TransactionLink.from_dict(input_['fulfills'])
|
||||
for tx in txs
|
||||
for input_ in tx['inputs']}
|
||||
return [ff for ff in outputs if ff not in spends]
|
||||
|
||||
def filter_unspent_outputs(self, outputs):
|
||||
"""Remove outputs that have not been spent
|
||||
|
||||
Args:
|
||||
outputs: list of TransactionLink
|
||||
"""
|
||||
links = [o.to_dict() for o in outputs]
|
||||
res = query.get_spending_transactions(self.connection, links)
|
||||
txs = [tx for _, tx in self.filter_valid_items(res)]
|
||||
spends = {TransactionLink.from_dict(input_['fulfills'])
|
||||
for tx in txs
|
||||
for input_ in tx['inputs']}
|
||||
return [ff for ff in outputs if ff in spends]
|
@ -978,41 +978,51 @@ def test_get_owned_ids_calls_get_outputs_filtered():
|
||||
assert res == gof()
|
||||
|
||||
|
||||
@pytest.mark.tendermint
|
||||
def test_get_outputs_filtered_only_unspent():
|
||||
from bigchaindb.common.transaction import TransactionLink
|
||||
from bigchaindb.core import Bigchain
|
||||
with patch('bigchaindb.fastquery.FastQuery.get_outputs_by_public_key') as get_outputs:
|
||||
from bigchaindb.tendermint.lib import BigchainDB
|
||||
|
||||
go = 'bigchaindb.tendermint.fastquery.FastQuery.get_outputs_by_public_key'
|
||||
with patch(go) as get_outputs:
|
||||
get_outputs.return_value = [TransactionLink('a', 1),
|
||||
TransactionLink('b', 2)]
|
||||
with patch('bigchaindb.fastquery.FastQuery.filter_spent_outputs') as filter_spent:
|
||||
fs = 'bigchaindb.tendermint.fastquery.FastQuery.filter_spent_outputs'
|
||||
with patch(fs) as filter_spent:
|
||||
filter_spent.return_value = [TransactionLink('b', 2)]
|
||||
out = Bigchain().get_outputs_filtered('abc', spent=False)
|
||||
out = BigchainDB().get_outputs_filtered('abc', spent=False)
|
||||
get_outputs.assert_called_once_with('abc')
|
||||
assert out == [TransactionLink('b', 2)]
|
||||
|
||||
|
||||
@pytest.mark.tendermint
|
||||
def test_get_outputs_filtered_only_spent():
|
||||
from bigchaindb.common.transaction import TransactionLink
|
||||
from bigchaindb.core import Bigchain
|
||||
with patch('bigchaindb.fastquery.FastQuery.get_outputs_by_public_key') as get_outputs:
|
||||
from bigchaindb.tendermint.lib import BigchainDB
|
||||
go = 'bigchaindb.tendermint.fastquery.FastQuery.get_outputs_by_public_key'
|
||||
with patch(go) as get_outputs:
|
||||
get_outputs.return_value = [TransactionLink('a', 1),
|
||||
TransactionLink('b', 2)]
|
||||
with patch('bigchaindb.fastquery.FastQuery.filter_unspent_outputs') as filter_spent:
|
||||
fs = 'bigchaindb.tendermint.fastquery.FastQuery.filter_unspent_outputs'
|
||||
with patch(fs) as filter_spent:
|
||||
filter_spent.return_value = [TransactionLink('b', 2)]
|
||||
out = Bigchain().get_outputs_filtered('abc', spent=True)
|
||||
out = BigchainDB().get_outputs_filtered('abc', spent=True)
|
||||
get_outputs.assert_called_once_with('abc')
|
||||
assert out == [TransactionLink('b', 2)]
|
||||
|
||||
|
||||
@patch('bigchaindb.fastquery.FastQuery.filter_unspent_outputs')
|
||||
@patch('bigchaindb.fastquery.FastQuery.filter_spent_outputs')
|
||||
@pytest.mark.tendermint
|
||||
@patch('bigchaindb.tendermint.fastquery.FastQuery.filter_unspent_outputs')
|
||||
@patch('bigchaindb.tendermint.fastquery.FastQuery.filter_spent_outputs')
|
||||
def test_get_outputs_filtered(filter_spent, filter_unspent):
|
||||
from bigchaindb.common.transaction import TransactionLink
|
||||
from bigchaindb.core import Bigchain
|
||||
with patch('bigchaindb.fastquery.FastQuery.get_outputs_by_public_key') as get_outputs:
|
||||
from bigchaindb.tendermint.lib import BigchainDB
|
||||
|
||||
go = 'bigchaindb.tendermint.fastquery.FastQuery.get_outputs_by_public_key'
|
||||
with patch(go) as get_outputs:
|
||||
get_outputs.return_value = [TransactionLink('a', 1),
|
||||
TransactionLink('b', 2)]
|
||||
out = Bigchain().get_outputs_filtered('abc')
|
||||
out = BigchainDB().get_outputs_filtered('abc')
|
||||
get_outputs.assert_called_once_with('abc')
|
||||
filter_spent.assert_not_called()
|
||||
filter_unspent.assert_not_called()
|
||||
|
@ -3,6 +3,7 @@ import pytest
|
||||
from bigchaindb.common.transaction import TransactionLink
|
||||
from bigchaindb.models import Transaction
|
||||
|
||||
|
||||
pytestmark = [pytest.mark.bdb, pytest.mark.tendermint]
|
||||
|
||||
|
||||
@ -25,3 +26,46 @@ def test_get_outputs_by_public_key(b, user_pk, user2_pk, txns):
|
||||
TransactionLink(txns[0].id, 0),
|
||||
TransactionLink(txns[2].id, 1),
|
||||
]
|
||||
|
||||
|
||||
def test_filter_spent_outputs(b, user_pk, user_sk):
|
||||
out = [([user_pk], 1)]
|
||||
tx1 = Transaction.create([user_pk], out * 2)
|
||||
tx1.sign([user_sk])
|
||||
|
||||
inputs = tx1.to_inputs()
|
||||
|
||||
tx2 = Transaction.transfer([inputs[0]], out, tx1.id)
|
||||
tx2.sign([user_sk])
|
||||
|
||||
# tx2 produces a new unspent. inputs[1] remains unspent.
|
||||
b.store_bulk_transactions([tx1, tx2])
|
||||
|
||||
outputs = b.fastquery.get_outputs_by_public_key(user_pk)
|
||||
unspents = b.fastquery.filter_spent_outputs(outputs)
|
||||
|
||||
assert set(unsp for unsp in unspents) == {
|
||||
inputs[1].fulfills,
|
||||
tx2.to_inputs()[0].fulfills,
|
||||
}
|
||||
|
||||
|
||||
def test_filter_unspent_outputs(b, user_pk, user_sk):
|
||||
out = [([user_pk], 1)]
|
||||
tx1 = Transaction.create([user_pk], out * 2)
|
||||
tx1.sign([user_sk])
|
||||
|
||||
inputs = tx1.to_inputs()
|
||||
|
||||
tx2 = Transaction.transfer([inputs[0]], out, tx1.id)
|
||||
tx2.sign([user_sk])
|
||||
|
||||
# tx2 produces a new unspent. input[1] remains unspent.
|
||||
b.store_bulk_transactions([tx1, tx2])
|
||||
|
||||
outputs = b.fastquery.get_outputs_by_public_key(user_pk)
|
||||
spents = b.fastquery.filter_unspent_outputs(outputs)
|
||||
|
||||
assert set(sp for sp in spents) == {
|
||||
inputs[0].fulfills,
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from bigchaindb.common.transaction import TransactionLink
|
||||
|
||||
pytestmark = pytest.mark.bdb
|
||||
|
||||
|
||||
def test_filter_valid_items(b, blockdata):
|
||||
blocks, _ = blockdata
|
||||
assert (b.fastquery.filter_valid_items(blocks, block_id_key=lambda b: b['id'])
|
||||
== [blocks[0], blocks[1]])
|
||||
|
||||
|
||||
def test_get_outputs_by_public_key(b, user_pk, user2_pk, blockdata):
|
||||
blocks, _ = blockdata
|
||||
assert b.fastquery.get_outputs_by_public_key(user_pk) == [
|
||||
TransactionLink(blocks[1]['block']['transactions'][0]['id'], 0)
|
||||
]
|
||||
assert b.fastquery.get_outputs_by_public_key(user2_pk) == [
|
||||
TransactionLink(blocks[0]['block']['transactions'][0]['id'], 0)
|
||||
]
|
Loading…
x
Reference in New Issue
Block a user