mirror of
https://github.com/planetmint/planetmint.git
synced 2025-03-30 15:08:31 +00:00
removed fastquery class
Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
This commit is contained in:
parent
9cf743f42c
commit
921e604724
@ -447,6 +447,7 @@ def get_outputs_by_tx_id(connection, tx_id: str) -> list[Output]:
|
||||
"""Retrieve outputs for a transaction by its id"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@singledispatch
|
||||
def get_outputs_by_owner(connection, public_key: str, table: str) -> list[Output]:
|
||||
"""Retrieve an owners outputs by public key"""
|
||||
|
@ -513,4 +513,4 @@ def get_latest_abci_chain(connection) -> Union[dict, None]:
|
||||
@catch_db_exception
|
||||
def get_outputs_by_owner(connection, public_key: str, table=TARANT_TABLE_OUTPUT) -> list[Output]:
|
||||
outputs = connection.connect().select(table, public_key, index="public_keys")
|
||||
return [Output.from_tuple(output) for output in outputs]
|
||||
return [Output.from_tuple(output) for output in outputs]
|
||||
|
@ -9,7 +9,6 @@ from transactions.common.exceptions import InputDoesNotExist
|
||||
|
||||
from planetmint import config_utils, backend
|
||||
from planetmint.const import GOVERNANCE_TRANSACTION_TYPES
|
||||
from planetmint.model.fastquery import FastQuery
|
||||
from planetmint.abci.utils import key_from_base64, merkleroot
|
||||
from planetmint.backend.connection import Connection
|
||||
from planetmint.backend.tarantool.const import (
|
||||
@ -87,7 +86,10 @@ class DataAccessor:
|
||||
elif spent is True:
|
||||
spent_outputs = []
|
||||
for output in outputs:
|
||||
if not any(utxo.transaction_id == output.transaction_id and utxo.index == output.index for utxo in unspent_outputs):
|
||||
if not any(
|
||||
utxo.transaction_id == output.transaction_id and utxo.index == output.index
|
||||
for utxo in unspent_outputs
|
||||
):
|
||||
spent_outputs.append(output)
|
||||
return unspent_outputs
|
||||
elif spent is False:
|
||||
@ -340,7 +342,3 @@ class DataAccessor:
|
||||
|
||||
# TODO Notice the sorted call!
|
||||
return merkleroot(sorted(hashes))
|
||||
|
||||
@property
|
||||
def fastquery(self):
|
||||
return FastQuery(self.connection)
|
||||
|
@ -1,76 +0,0 @@
|
||||
# Copyright © 2020 Interplanetary Database Association e.V.,
|
||||
# Planetmint and IPDB software contributors.
|
||||
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
|
||||
# Code is Apache-2.0 and docs are CC-BY-4.0
|
||||
|
||||
from planetmint.backend import query
|
||||
from transactions.common.transaction import TransactionLink
|
||||
|
||||
from planetmint.backend.models.output import ConditionDetails
|
||||
|
||||
|
||||
class FastQuery:
|
||||
"""Database queries that join on block results from a single node."""
|
||||
|
||||
def __init__(self, connection):
|
||||
self.connection = connection
|
||||
|
||||
def get_outputs_by_public_key(self, public_key):
|
||||
"""Get outputs for a public key"""
|
||||
txs = query.get_owned_ids(self.connection, public_key)
|
||||
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]
|
||||
txs = query.get_spending_transactions(self.connection, links)
|
||||
spends = {TransactionLink.from_dict(input.fulfills.to_dict()) 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]
|
||||
txs = query.get_spending_transactions(self.connection, links)
|
||||
spends = {TransactionLink.from_dict(input.fulfills.to_dict()) for tx in txs for input in tx.inputs}
|
||||
return [ff for ff in outputs if ff in spends]
|
||||
|
||||
|
||||
# TODO: Rename this function, it's handling fulfillments not conditions
|
||||
def condition_details_has_owner(condition_details, owner):
|
||||
"""Check if the public_key of owner is in the condition details
|
||||
as an Ed25519Fulfillment.public_key
|
||||
|
||||
Args:
|
||||
condition_details (dict): dict with condition details
|
||||
owner (str): base58 public key of owner
|
||||
|
||||
Returns:
|
||||
bool: True if the public key is found in the condition details, False otherwise
|
||||
|
||||
"""
|
||||
if isinstance(condition_details, ConditionDetails) and condition_details.sub_conditions is not None:
|
||||
result = condition_details_has_owner(condition_details.sub_conditions, owner)
|
||||
if result:
|
||||
return True
|
||||
elif isinstance(condition_details, list):
|
||||
for subcondition in condition_details:
|
||||
result = condition_details_has_owner(subcondition, owner)
|
||||
if result:
|
||||
return True
|
||||
else:
|
||||
if condition_details.public_key is not None and owner == condition_details.public_key:
|
||||
return True
|
||||
return False
|
@ -1,117 +0,0 @@
|
||||
# Copyright © 2020 Interplanetary Database Association e.V.,
|
||||
# Planetmint and IPDB software contributors.
|
||||
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
|
||||
# Code is Apache-2.0 and docs are CC-BY-4.0
|
||||
|
||||
import pytest
|
||||
|
||||
from transactions.common.transaction import TransactionLink
|
||||
from transactions.types.assets.create import Create
|
||||
from transactions.types.assets.transfer import Transfer
|
||||
|
||||
pytestmark = pytest.mark.bdb
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def txns(b, user_pk, user_sk, user2_pk, user2_sk, test_models):
|
||||
txs = [
|
||||
Create.generate([user_pk], [([user2_pk], 1)]).sign([user_sk]),
|
||||
Create.generate([user2_pk], [([user_pk], 1)]).sign([user2_sk]),
|
||||
Create.generate([user_pk], [([user_pk], 1), ([user2_pk], 1)]).sign([user_sk]),
|
||||
]
|
||||
b.models.store_bulk_transactions(txs)
|
||||
return txs
|
||||
|
||||
|
||||
def test_get_outputs_by_public_key(b, user_pk, user2_pk, txns, test_models):
|
||||
expected = [TransactionLink(txns[1].id, 0), TransactionLink(txns[2].id, 0)]
|
||||
actual = test_models.fastquery.get_outputs_by_public_key(user_pk)
|
||||
|
||||
_all_txs = set([tx.txid for tx in expected + actual])
|
||||
assert len(_all_txs) == 2
|
||||
# assert b.models.fastquery.get_outputs_by_public_key(user_pk) == [ # OLD VERIFICATION
|
||||
# TransactionLink(txns[1].id, 0),
|
||||
# TransactionLink(txns[2].id, 0)
|
||||
# ]
|
||||
actual_1 = test_models.fastquery.get_outputs_by_public_key(user2_pk)
|
||||
expected_1 = [
|
||||
TransactionLink(txns[0].id, 0),
|
||||
TransactionLink(txns[2].id, 1),
|
||||
]
|
||||
_all_tx_1 = set([tx.txid for tx in actual_1 + expected_1])
|
||||
assert len(_all_tx_1) == 2
|
||||
# assert b.models.fastquery.get_outputs_by_public_key(user2_pk) == [ # OLD VERIFICATION
|
||||
# TransactionLink(txns[0].id, 0),
|
||||
# TransactionLink(txns[2].id, 1),
|
||||
# ]
|
||||
|
||||
|
||||
def test_filter_spent_outputs(b, user_pk, user_sk, test_models):
|
||||
out = [([user_pk], 1)]
|
||||
tx1 = Create.generate([user_pk], out * 2)
|
||||
tx1.sign([user_sk])
|
||||
|
||||
inputs = tx1.to_inputs()
|
||||
|
||||
tx2 = Transfer.generate([inputs[0]], out, [tx1.id])
|
||||
tx2.sign([user_sk])
|
||||
|
||||
# tx2 produces a new unspent. inputs[1] remains unspent.
|
||||
b.models.store_bulk_transactions([tx1, tx2])
|
||||
|
||||
outputs = test_models.fastquery.get_outputs_by_public_key(user_pk)
|
||||
unspents = test_models.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, test_models):
|
||||
out = [([user_pk], 1)]
|
||||
tx1 = Create.generate([user_pk], out * 2)
|
||||
tx1.sign([user_sk])
|
||||
|
||||
inputs = tx1.to_inputs()
|
||||
|
||||
tx2 = Transfer.generate([inputs[0]], out, [tx1.id])
|
||||
tx2.sign([user_sk])
|
||||
|
||||
# tx2 produces a new unspent. input[1] remains unspent.
|
||||
b.models.store_bulk_transactions([tx1, tx2])
|
||||
|
||||
outputs = test_models.fastquery.get_outputs_by_public_key(user_pk)
|
||||
spents = test_models.fastquery.filter_unspent_outputs(outputs)
|
||||
|
||||
assert set(sp for sp in spents) == {
|
||||
inputs[0].fulfills,
|
||||
}
|
||||
|
||||
|
||||
def test_outputs_query_key_order(b, user_pk, user_sk, user2_pk, test_validator):
|
||||
tx1 = Create.generate([user_pk], [([user_pk], 3), ([user_pk], 2), ([user_pk], 1)]).sign([user_sk])
|
||||
b.models.store_bulk_transactions([tx1])
|
||||
|
||||
inputs = tx1.to_inputs()
|
||||
tx2 = Transfer.generate([inputs[1]], [([user2_pk], 2)], [tx1.id]).sign([user_sk])
|
||||
assert test_validator.validate_transaction(tx2)
|
||||
|
||||
b.models.store_bulk_transactions([tx2])
|
||||
|
||||
outputs = b.models.get_outputs_filtered(user_pk, spent=False)
|
||||
assert len(outputs) == 2
|
||||
|
||||
outputs = b.models.get_outputs_filtered(user2_pk, spent=False)
|
||||
assert len(outputs) == 1
|
||||
|
||||
# clean the transaction, metdata and asset collection
|
||||
b.models.delete_transactions([tx1.id, tx2.id])
|
||||
|
||||
b.models.store_bulk_transactions([tx1, tx2])
|
||||
|
||||
outputs = b.models.get_outputs_filtered(user_pk, spent=False)
|
||||
assert len(outputs) == 2
|
||||
|
||||
outputs = b.models.get_outputs_filtered(user2_pk, spent=False)
|
||||
assert len(outputs) == 1
|
Loading…
x
Reference in New Issue
Block a user