Fix recursion error

This commit is contained in:
cybnon 2022-12-01 14:20:34 +01:00
parent 50ca7982ed
commit 3ebfed41c7
12 changed files with 74 additions and 56 deletions

View File

@ -7,6 +7,9 @@ from __future__ import annotations
from dataclasses import dataclass, field
from typing import Optional
from planetmint.backend.models import Asset, MetaData, Input, Output, Script
from planetmint.backend.models.keys import Keys
@dataclass
class Transaction:
@ -14,6 +17,12 @@ class Transaction:
operation: str = ""
version: str = ""
raw_transaction: dict = dict
assets: list[Asset] = None
metadata: MetaData = None
inputs: list[Input] = None
outputs: list[Output] = None
keys: Keys = None
script: Script = None
@staticmethod
def from_dict(transaction: dict) -> Transaction:
@ -21,6 +30,7 @@ class Transaction:
id=transaction["id"],
operation=transaction["operation"],
version=transaction["version"],
inputs=transaction["inputs"],
raw_transaction=transaction["transaction"],
)

View File

@ -68,12 +68,25 @@ def store_transaction(connection, transaction):
@singledispatch
def get_transaction(connection, transaction_id):
"""Get a transaction from the database."""
def get_transaction_space_by_id(connection, transaction_id):
"""Get the transaction space by transaction id."""
raise NotImplementedError
@singledispatch
def get_transaction_single(connection, transaction_id):
"""Get a single transaction by id."""
raise NotImplementedError
@singledispatch
def get_transaction(connection, transaction_id):
"""Get a transaction by id."""
raise NotImplementedError
@singledispatch
def get_transactions(connection, transactions_ids) -> list[Transaction]:
"""Get a transaction from the transactions table.

View File

@ -34,26 +34,16 @@ register_query = module_dispatch_registrar(query)
def _group_transaction_by_ids(connection, txids: list):
_transactions = []
for txid in txids:
tx = get_transaction(connection, txid)
tx = get_transaction_space_by_id(connection, txid)
if tx is None:
continue
_txinputs = get_inputs_by_tx_id(connection, txid)
_txoutputs = get_outputs_by_tx_id(connection, txid)
_txkeys = get_keys_by_tx_id(connection, txid)
_txassets = get_assets_by_tx_id(connection, txid)
_txmeta = get_metadata_by_tx_id(connection, txid)
_txscript = get_script_by_tx_id(connection, txid)
tx = {
TARANT_TABLE_TRANSACTION: tx,
TARANT_TABLE_INPUT: [tx_input.to_dict() for tx_input in _txinputs],
TARANT_TABLE_OUTPUT: [output.to_dict() for output in _txoutputs],
TARANT_TABLE_KEYS: [key.to_dict() for key in _txkeys],
TARANT_TABLE_ASSETS: _txassets,
TARANT_TABLE_META_DATA: _txmeta,
TARANT_TABLE_SCRIPT: _txscript.script if _txscript else None,
}
tx.inputs = get_inputs_by_tx_id(connection, txid)
tx.outputs = get_outputs_by_tx_id(connection, txid)
tx.keys = get_keys_by_tx_id(connection, txid)
tx.assets = get_assets_by_tx_id(connection, txid)
tx.metadata = get_metadata_by_tx_id(connection, txid)
tx.script = get_script_by_tx_id(connection, txid)
_transactions.append(tx)
return _transactions
@ -80,6 +70,10 @@ def get_keys_by_tx_id(connection, tx_id: str) -> list[Keys]:
return [Keys.from_tuple(key) for key in _sorted_keys]
@register_query(TarantoolDBConnection)
def get_transaction(connection, tx_id: str) -> Transaction:
return NotImplemented
@register_query(TarantoolDBConnection)
def store_transaction_inputs(connection, input: Input, index: int):
connection.run(
@ -180,17 +174,21 @@ def store_transaction(connection, transaction):
@register_query(TarantoolDBConnection)
def get_transaction(connection, transaction_id):
def get_transaction_space_by_id(connection, transaction_id):
txs = connection.run(connection.space(TARANT_TABLE_TRANSACTION).select(transaction_id, index=TARANT_ID_SEARCH))
if len(txs) == 0:
return None
return Transaction.from_tuple(txs[0])
@register_query(TarantoolDBConnection)
def get_transaction_single(connection, transaction_id):
return _group_transaction_by_ids(txids=[transaction_id], connection=connection)
@register_query(TarantoolDBConnection)
def get_transactions(connection, transactions_ids: list) -> list[Transaction]:
_transactions = _group_transaction_by_ids(txids=transactions_ids, connection=connection)
return [Transaction.from_tuple(_transaction) for _transaction in _transactions]
return _group_transaction_by_ids(txids=transactions_ids, connection=connection)
@register_query(TarantoolDBConnection)
@ -276,8 +274,7 @@ def get_spent(connection, fullfil_transaction_id: str, fullfil_output_index: str
[fullfil_transaction_id, str(fullfil_output_index)], index="spent_search"
)
)
_transactions = _group_transaction_by_ids(txids=[inp[0] for inp in _inputs], connection=connection)
return _transactions
return _group_transaction_by_ids(txids=[inp[0] for inp in _inputs], connection=connection)
@register_query(TarantoolDBConnection)
@ -371,8 +368,7 @@ def get_owned_ids(connection, owner: str):
if _keys is None or len(_keys) == 0:
return []
_transactionids = list(set([key[1] for key in _keys]))
_transactions = _group_transaction_by_ids(txids=_transactionids, connection=connection)
return _transactions
return _group_transaction_by_ids(txids=_transactionids, connection=connection)
@register_query(TarantoolDBConnection)
@ -579,8 +575,7 @@ def get_asset_tokens_for_public_key(
_transactions = connection.run(connection.space(TARANT_TABLE_ASSETS).select([asset_id], index="assetid_search"))
# _transactions = _transactions
# _keys = _keys.data
_grouped_transactions = _group_transaction_by_ids(connection=connection, txids=[_tx[1] for _tx in _transactions])
return _grouped_transactions
return _group_transaction_by_ids(connection=connection, txids=[_tx[1] for _tx in _transactions])
@register_query(TarantoolDBConnection)

View File

@ -193,7 +193,7 @@ def run_election_approve(args, planet):
"""
key = load_node_key(args.sk)
tx = planet.get_transaction(args.election_id)
tx = planet.get_transaction_space_by_id(args.election_id)
voting_powers = [v.amount for v in tx.outputs if key.public_key in v.public_keys]
if len(voting_powers) > 0:
voting_power = voting_powers[0]
@ -226,7 +226,7 @@ def run_election_show(args, planet):
:param planet: an instance of Planetmint
"""
election = planet.get_transaction(args.election_id)
election = planet.get_transaction_space_by_id(args.election_id)
if not election:
logger.error(f"No election found with election_id {args.election_id}")
return

View File

@ -742,23 +742,23 @@ class Planetmint(object):
# validators and their voting power in the network
return current_topology == voters
def count_votes(self, election_pk, transactions, getter=getattr):
def count_votes(self, election_pk, transactions):
votes = 0
for txn in transactions:
if getter(txn, "operation") == Vote.OPERATION:
for output in getter(txn, "outputs"):
if txn.operation == Vote.OPERATION:
for output in txn.outputs:
# NOTE: We enforce that a valid vote to election id will have only
# election_pk in the output public keys, including any other public key
# along with election_pk will lead to vote being not considered valid.
if len(getter(output, "public_keys")) == 1 and [election_pk] == getter(output, "public_keys"):
votes = votes + int(getter(output, "amount"))
if len(output.public_keys) == 1 and [election_pk] == output.public_keys:
votes = votes + output.amount
return votes
def get_commited_votes(self, transaction, election_pk=None): # TODO: move somewhere else
if election_pk is None:
election_pk = election_id_to_public_key(transaction.id)
txns = list(backend.query.get_asset_tokens_for_public_key(self.connection, transaction.id, election_pk))
return self.count_votes(election_pk, txns, dict.get)
return self.count_votes(election_pk, txns)
def _get_initiated_elections(self, height, txns): # TODO: move somewhere else
elections = []

View File

@ -37,7 +37,7 @@ class TransactionApi(Resource):
pool = current_app.config["bigchain_pool"]
with pool() as planet:
tx = planet.get_transaction(tx_id)
tx = planet.get_transaction_space_by_id(tx_id)
if not tx:
return make_error(404)

View File

@ -320,7 +320,7 @@ def test_election_new_upsert_validator_with_tendermint(b, priv_validator_path, u
election_id = run_election_new_upsert_validator(new_args, b)
assert b.get_transaction(election_id)
assert b.get_transaction_space_by_id(election_id)
@pytest.mark.bdb
@ -347,7 +347,7 @@ def test_election_new_upsert_validator_without_tendermint(caplog, b, priv_valida
with caplog.at_level(logging.INFO):
election_id = run_election_new_upsert_validator(args, b)
assert caplog.records[0].msg == "[SUCCESS] Submitted proposal with id: " + election_id
assert b.get_transaction(election_id)
assert b.get_transaction_space_by_id(election_id)
@pytest.mark.abci
@ -358,7 +358,7 @@ def test_election_new_chain_migration_with_tendermint(b, priv_validator_path, us
election_id = run_election_new_chain_migration(new_args, b)
assert b.get_transaction(election_id)
assert b.get_transaction_space_by_id(election_id)
@pytest.mark.bdb
@ -377,7 +377,7 @@ def test_election_new_chain_migration_without_tendermint(caplog, b, priv_validat
with caplog.at_level(logging.INFO):
election_id = run_election_new_chain_migration(args, b)
assert caplog.records[0].msg == "[SUCCESS] Submitted proposal with id: " + election_id
assert b.get_transaction(election_id)
assert b.get_transaction_space_by_id(election_id)
@pytest.mark.bdb
@ -446,7 +446,7 @@ def test_election_approve_with_tendermint(b, priv_validator_path, user_sk, valid
args = Namespace(action="approve", election_id=election_id, sk=priv_validator_path, config={})
approve = run_election_approve(args, b)
assert b.get_transaction(approve)
assert b.get_transaction_space_by_id(approve)
@pytest.mark.bdb
@ -463,7 +463,7 @@ def test_election_approve_without_tendermint(caplog, b, priv_validator_path, new
with caplog.at_level(logging.INFO):
approval_id = run_election_approve(args, b)
assert caplog.records[0].msg == "[SUCCESS] Your vote has been submitted"
assert b.get_transaction(approval_id)
assert b.get_transaction_space_by_id(approval_id)
@pytest.mark.bdb

View File

@ -105,7 +105,7 @@ class TestBigchainApi(object):
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], assets=[asset1]).sign([alice.private_key])
b.store_bulk_transactions([tx])
tx_from_db = b.get_transaction(tx.id)
tx_from_db = b.get_transaction_space_by_id(tx.id)
before = tx.to_dict()
after = tx_from_db.to_dict()
@ -131,7 +131,7 @@ class TestTransactionValidation(object):
from transactions.common.exceptions import InvalidSignature
input_tx = b.fastquery.get_outputs_by_public_key(user_pk).pop()
input_transaction = b.get_transaction(input_tx.txid)
input_transaction = b.get_transaction_space_by_id(input_tx.txid)
sk, pk = generate_key_pair()
tx = Create.generate([pk], [([user_pk], 1)])
tx.operation = "TRANSFER"
@ -158,7 +158,7 @@ class TestMultipleInputs(object):
user2_sk, user2_pk = crypto.generate_key_pair()
tx_link = b.fastquery.get_outputs_by_public_key(user_pk).pop()
input_tx = b.get_transaction(tx_link.txid)
input_tx = b.get_transaction_space_by_id(tx_link.txid)
inputs = input_tx.to_inputs()
tx = Transfer.generate(inputs, [([user2_pk], 1)], asset_ids=[input_tx.id])
tx = tx.sign([user_sk])
@ -175,7 +175,7 @@ class TestMultipleInputs(object):
user3_sk, user3_pk = crypto.generate_key_pair()
tx_link = b.fastquery.get_outputs_by_public_key(user_pk).pop()
input_tx = b.get_transaction(tx_link.txid)
input_tx = b.get_transaction_space_by_id(tx_link.txid)
tx = Transfer.generate(input_tx.to_inputs(), [([user2_pk, user3_pk], 1)], asset_ids=[input_tx.id])
tx = tx.sign([user_sk])
@ -195,7 +195,7 @@ class TestMultipleInputs(object):
b.store_bulk_transactions([tx])
owned_input = b.fastquery.get_outputs_by_public_key(user_pk).pop()
input_tx = b.get_transaction(owned_input.txid)
input_tx = b.get_transaction_space_by_id(owned_input.txid)
inputs = input_tx.to_inputs()
transfer_tx = Transfer.generate(inputs, [([user3_pk], 1)], asset_ids=[input_tx.id])
@ -220,7 +220,7 @@ class TestMultipleInputs(object):
# get input
tx_link = b.fastquery.get_outputs_by_public_key(user_pk).pop()
tx_input = b.get_transaction(tx_link.txid)
tx_input = b.get_transaction_space_by_id(tx_link.txid)
tx = Transfer.generate(tx_input.to_inputs(), [([user3_pk, user4_pk], 1)], asset_ids=[tx_input.id])
tx = tx.sign([user_sk, user2_sk])

View File

@ -235,7 +235,7 @@ def test_deliver_tx__valid_create_updates_db_and_emits_event(b, init_chain_reque
app.end_block(types.RequestEndBlock(height=99))
app.commit()
assert b.get_transaction(tx.id).id == tx.id
assert b.get_transaction_space_by_id(tx.id).id == tx.id
block_event = events.get()
assert block_event.data["transactions"] == [tx]
@ -264,7 +264,7 @@ def test_deliver_tx__double_spend_fails(b, init_chain_request):
app.end_block(types.RequestEndBlock(height=99))
app.commit()
assert b.get_transaction(tx.id).id == tx.id
assert b.get_transaction_space_by_id(tx.id).id == tx.id
result = app.deliver_tx(encode_tx_to_bytes(tx))
assert result.code == CodeTypeError
@ -410,7 +410,7 @@ def test_rollback_pre_commit_state_after_crash(b):
rollback(b)
for tx in txs:
assert b.get_transaction(tx.id)
assert b.get_transaction_space_by_id(tx.id)
assert b.get_latest_abci_chain()
assert len(b.get_validator_set()["validators"]) == 1
assert b.get_election(migration_election.id)
@ -421,7 +421,7 @@ def test_rollback_pre_commit_state_after_crash(b):
rollback(b)
for tx in txs:
assert not b.get_transaction(tx.id)
assert not b.get_transaction_space_by_id(tx.id)
assert not b.get_latest_abci_chain()
assert len(b.get_validator_set()["validators"]) == 4
assert len(b.get_validator_set(2)["validators"]) == 4

View File

@ -78,7 +78,7 @@ def test_app(b, eventqueue_fixture, init_chain_request):
data = p.process("commit", None)
res = next(read_messages(BytesIO(data), types.Response))
assert res.commit.data == new_block_hash.encode("utf-8")
assert b.get_transaction(tx.id).id == tx.id
assert b.get_transaction_space_by_id(tx.id).id == tx.id
block0 = b.get_latest_block()
assert block0

View File

@ -69,7 +69,7 @@ def test_asset_is_separated_from_transaciton(b):
b.store_bulk_transactions([tx])
assert "asset" not in backend.query.get_transaction(b.connection, tx.id)
assert backend.query.get_asset(b.connection, tx.id)["data"] == assets[0]
assert b.get_transaction(tx.id).to_dict() == tx_dict
assert b.get_transaction_space_by_id(tx.id).to_dict() == tx_dict
@pytest.mark.bdb

View File

@ -246,7 +246,7 @@ def test_upsert_validator(b, node_key, node_keys, ed25519_node_keys):
)
code, message = b.write_transaction(election, BROADCAST_TX_COMMIT)
assert code == 202
assert b.get_transaction(election.id)
assert b.get_transaction_space_by_id(election.id)
tx_vote = gen_vote(election, 0, ed25519_node_keys)
assert b.validate_transaction(tx_vote)