From 3edd3656460d3724b5cdc4cb3aeafff2024fe6ff Mon Sep 17 00:00:00 2001 From: cybnon Date: Wed, 30 Nov 2022 12:47:59 +0100 Subject: [PATCH 1/6] fix tests Signed-off-by: cybnon --- planetmint/backend/models/input.py | 2 +- planetmint/backend/models/output.py | 2 +- planetmint/backend/models/transaction.py | 5 +++ planetmint/backend/query.py | 2 +- planetmint/backend/tarantool/query.py | 41 ++++++++++++------------ planetmint/lib.py | 7 ++-- tests/backend/tarantool/test_queries.py | 9 +++--- tests/db/test_planetmint_api.py | 6 ++-- 8 files changed, 39 insertions(+), 35 deletions(-) diff --git a/planetmint/backend/models/input.py b/planetmint/backend/models/input.py index fcc0491..421615e 100644 --- a/planetmint/backend/models/input.py +++ b/planetmint/backend/models/input.py @@ -42,7 +42,7 @@ class Input: return Input(tx_id, fulfills, owners_before, fulfillment) - def to_input_dict(self) -> dict: + def to_dict(self) -> dict: fulfills = { "transaction_id": self.fulfills.transaction_id, "output_index": self.fulfills.output_index diff --git a/planetmint/backend/models/output.py b/planetmint/backend/models/output.py index 4ea8c82..0b04835 100644 --- a/planetmint/backend/models/output.py +++ b/planetmint/backend/models/output.py @@ -67,7 +67,7 @@ class Output: ), ) - def to_output_dict(self) -> dict: + def to_dict(self) -> dict: return { "id": self.tx_id, "amount": self.amount, diff --git a/planetmint/backend/models/transaction.py b/planetmint/backend/models/transaction.py index 0db0ca4..632e61c 100644 --- a/planetmint/backend/models/transaction.py +++ b/planetmint/backend/models/transaction.py @@ -12,6 +12,7 @@ class Transaction: id: str = "" operation: str = "" version: str = "" + raw_transaction: dict = dict @staticmethod def from_dict(transaction: dict) -> Transaction: @@ -19,6 +20,7 @@ class Transaction: id=transaction["id"], operation=transaction["operation"], version=transaction["version"], + raw_transaction=transaction["transaction"], ) @@ -28,11 +30,14 @@ class Transaction: id=transaction[0], operation=transaction[1], version=transaction[2], + raw_transaction=transaction[3], ) + def to_dict(self) -> dict: return { "id": self.id, "operation": self.operation, "version": self.version, + "transaction": self.raw_transaction, } diff --git a/planetmint/backend/query.py b/planetmint/backend/query.py index 7d3abbd..0af2057 100644 --- a/planetmint/backend/query.py +++ b/planetmint/backend/query.py @@ -67,7 +67,7 @@ def store_transaction(connection, transaction): @singledispatch -def get_transaction(conn, transaction_id): +def get_transaction(connection, transaction_id): """Get a transaction from the database.""" raise NotImplementedError diff --git a/planetmint/backend/tarantool/query.py b/planetmint/backend/tarantool/query.py index 9453295..6416b36 100644 --- a/planetmint/backend/tarantool/query.py +++ b/planetmint/backend/tarantool/query.py @@ -26,9 +26,8 @@ register_query = module_dispatch_registrar(query) def _group_transaction_by_ids(connection, txids: list): _transactions = [] for txid in txids: - _txobject = connection.run(connection.space(TARANT_TABLE_TRANSACTION).get(txid, index=TARANT_ID_SEARCH)) - - if _txobject is None: + tx = get_transaction(connection, txid) + if tx is None: continue _txinputs = get_inputs_by_tx_id(connection, txid) @@ -38,17 +37,17 @@ def _group_transaction_by_ids(connection, txids: list): _txmeta = get_metadata_by_tx_id(connection, txid) _txscript = get_script_by_tx_id(connection, txid) - _transaction = get_transaction(connection, txid) - _transaction[TARANT_TABLE_TRANSACTION] = [tx.to_dict for tx in _transactions] - _transaction[TARANT_TABLE_INPUT] + [input.to_input_dict() for input in _txinputs] - _transaction[TARANT_TABLE_OUTPUT] = [output.to_output_dict() for output in _txoutputs] - _transaction[TARANT_TABLE_KEYS] = [key.to_dict() for key in _txkeys] - _transaction["assets"] = [asset.data for asset in _txassets] - _transaction["metadata"] = _txmeta.metadata + 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, + } - if _txscript.script: - _transaction[TARANT_TABLE_SCRIPT] = _txscript.script - _transactions.append(_transaction) + _transactions.append(tx) return _transactions @@ -141,6 +140,7 @@ def store_transaction_keys(connection, keys: Keys, output_id: str, index: int): @register_query(TarantoolDBConnection) def store_transactions(connection, signed_transactions: list): for transaction in signed_transactions: + store_transaction(connection, transaction) [store_transaction_inputs(connection, Input.from_dict(input, transaction["id"]), index) for index, input in enumerate(transaction[TARANT_TABLE_INPUT])] @@ -165,19 +165,20 @@ def store_transactions(connection, signed_transactions: list): @register_query(TarantoolDBConnection) def store_transaction(connection, transaction): - tx = Transaction(id=transaction["id"], operation=transaction["operation"], version=transaction["version"]) + tx = (transaction["id"], transaction["operation"], transaction["version"], + transaction) connection.run(connection.space(TARANT_TABLE_TRANSACTION).insert( - tx.id, - tx.operation, - tx.version, + tx ), only_data=False) @register_query(TarantoolDBConnection) -def get_transaction(connection, transaction_id: str) -> Transaction: - return Transaction.from_tuple( - connection.run(connection.space(TARANT_TABLE_TRANSACTION).get(transaction_id, index=TARANT_ID_SEARCH))) +def get_transaction(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) diff --git a/planetmint/lib.py b/planetmint/lib.py index bcfd977..91d63ec 100644 --- a/planetmint/lib.py +++ b/planetmint/lib.py @@ -8,11 +8,8 @@ MongoDB. """ import logging -from collections import namedtuple -from uuid import uuid4 from planetmint.backend.connection import Connection -from hashlib import sha3_256 import json import rapidjson import requests @@ -40,6 +37,7 @@ from transactions.common.transaction import VALIDATOR_ELECTION, CHAIN_MIGRATION_ from transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT, BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC from transactions.types.elections.election import Election from transactions.types.elections.validator_utils import election_id_to_public_key + from planetmint.config import Config from planetmint import backend, config_utils, fastquery from planetmint.tendermint_utils import ( @@ -230,8 +228,7 @@ class Planetmint(object): return bool(transaction) def get_transaction(self, transaction_id): - transaction = backend.query.get_transaction(self.connection, transaction_id) - return Transaction.from_dict(transaction, False) + return backend.query.get_transaction(self.connection, transaction_id) def get_transactions(self, txn_ids): return backend.query.get_transactions(self.connection, txn_ids) diff --git a/tests/backend/tarantool/test_queries.py b/tests/backend/tarantool/test_queries.py index 9c704e1..4efe905 100644 --- a/tests/backend/tarantool/test_queries.py +++ b/tests/backend/tarantool/test_queries.py @@ -204,8 +204,8 @@ def test_get_owned_ids(signed_create_tx, user_pk, db_conn): query.store_transactions(connection=db_conn, signed_transactions=[signed_create_tx.to_dict()]) txns = list(query.get_owned_ids(connection=db_conn, owner=user_pk)) tx_dict = signed_create_tx.to_dict() - founded = [tx for tx in txns if tx["id"] == tx_dict["id"]] - assert founded[0] == tx_dict + founded = [tx for tx in txns if tx["transactions"].id == tx_dict["id"]] + assert founded[0]["transactions"].raw_transaction == tx_dict def test_get_spending_transactions(user_pk, user_sk, db_conn): @@ -225,7 +225,8 @@ def test_get_spending_transactions(user_pk, user_sk, db_conn): txns = list(query.get_spending_transactions(connection=db_conn, inputs=links)) # tx3 not a member because input 1 not asked for - assert txns == [tx2.to_dict(), tx4.to_dict()] + assert txns[0]["transactions"].raw_transaction == tx2.to_dict() + assert txns[1]["transactions"].raw_transaction == tx4.to_dict() def test_get_spending_transactions_multiple_inputs(db_conn): @@ -261,7 +262,7 @@ def test_get_spending_transactions_multiple_inputs(db_conn): txns = list(query.get_spending_transactions(connection=db_conn, inputs=[li])) assert len(txns) == num if len(txns): - assert [tx["id"] for tx in txns] == match + assert [tx["transactions"].id for tx in txns] == match def test_store_block(db_conn): diff --git a/tests/db/test_planetmint_api.py b/tests/db/test_planetmint_api.py index 98dcb55..2c08ed3 100644 --- a/tests/db/test_planetmint_api.py +++ b/tests/db/test_planetmint_api.py @@ -110,10 +110,10 @@ class TestBigchainApi(object): before = tx.to_dict() after = tx_from_db.to_dict() - assert before["assets"][0]["data"] == after["assets"][0]["data"] + assert before["assets"][0]["data"] == after["transaction"]["assets"][0]["data"] before.pop("asset", None) - after.pop("asset", None) - assert before == after + after["transaction"].pop("asset", None) + assert before == after["transaction"] class TestTransactionValidation(object): From ba37a68a3a5715a98d209e263f612dcd6412c621 Mon Sep 17 00:00:00 2001 From: cybnon Date: Thu, 1 Dec 2022 09:44:41 +0100 Subject: [PATCH 2/6] Fix more tests Signed-off-by: cybnon --- planetmint/backend/query.py | 13 +++++++++++++ planetmint/backend/tarantool/query.py | 18 +++++++++++++++++- planetmint/fastquery.py | 2 +- planetmint/lib.py | 9 ++++----- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/planetmint/backend/query.py b/planetmint/backend/query.py index 0af2057..b1ce577 100644 --- a/planetmint/backend/query.py +++ b/planetmint/backend/query.py @@ -100,6 +100,19 @@ def get_asset(connection, asset_id) -> Asset: raise NotImplementedError +@singledispatch +def get_assets_by_tx_id(connection, tx_id: str) -> list[Asset]: + """Get assets by transaction id. + + Args: + tx_id (str): the id of the transaction. + + Returns: + The result of the operation. + """ + + raise NotImplementedError + @singledispatch def get_spent(connection, transaction_id, condition_id): diff --git a/planetmint/backend/tarantool/query.py b/planetmint/backend/tarantool/query.py index 6416b36..08eac29 100644 --- a/planetmint/backend/tarantool/query.py +++ b/planetmint/backend/tarantool/query.py @@ -33,7 +33,7 @@ def _group_transaction_by_ids(connection, txids: list): _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(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) @@ -243,12 +243,28 @@ def get_assets(connection, assets_ids: list) -> list[Asset]: _returned_data = [] for _id in list(set(assets_ids)): res = connection.run(connection.space(TARANT_TABLE_ASSETS).select(_id, index=TARANT_TX_ID_SEARCH)) + if len(res) is 0: + continue _returned_data.append(res[0]) sorted_assets = sorted(_returned_data, key=lambda k: k[1], reverse=False) return [Asset.from_tuple(asset) for asset in sorted_assets] +@register_query(TarantoolDBConnection) +def get_assets_by_tx_id(connection, tx_id: str) -> list[Asset]: + res = connection.run(connection.space(TARANT_TABLE_ASSETS).select(tx_id, index=TARANT_TX_ID_SEARCH)) + if len(res) > 1: + return _from_tuple_list_to_asset_list(res) + + sorted_assets = sorted(res, key=lambda k: k[1], reverse=False) + return _from_tuple_list_to_asset_list(sorted_assets) + + +def _from_tuple_list_to_asset_list(_data: list) -> list[Asset]: + return [Asset.from_tuple(asset) for asset in _data] + + @register_query(TarantoolDBConnection) def get_spent(connection, fullfil_transaction_id: str, fullfil_output_index: str): _inputs = connection.run( diff --git a/planetmint/fastquery.py b/planetmint/fastquery.py index 7832a5c..dae6dd8 100644 --- a/planetmint/fastquery.py +++ b/planetmint/fastquery.py @@ -18,7 +18,7 @@ class FastQuery: """Get outputs for a public key""" txs = list(query.get_owned_ids(self.connection, public_key)) return [ - TransactionLink(tx["id"], index) + TransactionLink(tx["transactions"].id, index) for tx in txs for index, output in enumerate(tx["outputs"]) if condition_details_has_owner(output["condition"]["details"], public_key) diff --git a/planetmint/lib.py b/planetmint/lib.py index 91d63ec..7b19b69 100644 --- a/planetmint/lib.py +++ b/planetmint/lib.py @@ -262,7 +262,6 @@ class Planetmint(object): def get_spent(self, txid, output, current_transactions=[]): transactions = backend.query.get_spent(self.connection, txid, output) - transactions = list(transactions) if transactions else [] if len(transactions) > 1: raise core_exceptions.CriticalDoubleSpend( "`{}` was spent more than once. There is a problem" " with the chain".format(txid) @@ -278,10 +277,10 @@ class Planetmint(object): if len(transactions) + len(current_spent_transactions) > 1: raise DoubleSpend('tx "{}" spends inputs twice'.format(txid)) elif transactions: - transaction = backend.query.get_transaction(self.connection, transactions[0]["id"]) - assets = backend.query.get_assets(self.connection, [transaction["id"]]) - transaction["assets"] = [asset.data for asset in assets] - transaction = Transaction.from_dict(transaction, False) + tx_id = transactions[0]["transactions"].id + tx = backend.query.get_transaction(self.connection, tx_id) + assets = backend.query.get_assets_by_tx_id(self.connection, tx_id) + transaction = {"transactions": tx} | {"assets": [asset.data for asset in assets]} elif current_spent_transactions: transaction = current_spent_transactions[0] From 50ca7982ed9668782cd344cb17a261a144e3fa2e Mon Sep 17 00:00:00 2001 From: cybnon Date: Thu, 1 Dec 2022 10:25:34 +0100 Subject: [PATCH 3/6] Format file --- planetmint/backend/interfaces.py | 16 ++- planetmint/backend/models/asset.py | 5 +- planetmint/backend/models/fulfills.py | 3 +- planetmint/backend/models/input.py | 35 +++-- planetmint/backend/models/keys.py | 2 +- planetmint/backend/models/metadata.py | 5 +- planetmint/backend/models/output.py | 7 +- planetmint/backend/models/script.py | 5 +- planetmint/backend/models/transaction.py | 3 +- planetmint/backend/query.py | 12 +- planetmint/backend/tarantool/query.py | 122 ++++++++++-------- .../backend/tarantool/transaction/tools.py | 11 +- tests/backend/tarantool/test_queries.py | 6 +- tests/tendermint/test_lib.py | 2 +- 14 files changed, 130 insertions(+), 104 deletions(-) diff --git a/planetmint/backend/interfaces.py b/planetmint/backend/interfaces.py index 2277565..449f3fa 100644 --- a/planetmint/backend/interfaces.py +++ b/planetmint/backend/interfaces.py @@ -4,7 +4,7 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 from dataclasses import dataclass - + # NOTE: only here temporarily from planetmint.backend.models import Asset, MetaData, Input from planetmint.backend.models import Output @@ -16,37 +16,41 @@ class Block: app_hash: str = None height: int = None + @dataclass class Script: id: str = None script = None - + + @dataclass class UTXO: id: str = None output_index: int = None utxo: dict = None + @dataclass class Transaction: id: str = None assets: list[Asset] = None metadata: MetaData = None - version: str = None # TODO: make enum - operation: str = None # TODO: make enum + version: str = None # TODO: make enum + operation: str = None # TODO: make enum inputs: list[Input] = None outputs: list[Output] = None script: str = None + @dataclass class Validator: id: str = None height: int = None validators = None - + + @dataclass class ABCIChain: height: str = None is_synced: bool = None chain_id: str = None - diff --git a/planetmint/backend/models/asset.py b/planetmint/backend/models/asset.py index 6dc120c..f2f18c5 100644 --- a/planetmint/backend/models/asset.py +++ b/planetmint/backend/models/asset.py @@ -7,12 +7,13 @@ from __future__ import annotations import json from dataclasses import dataclass + @dataclass class Asset: id: str = "" tx_id: str = "" data: str = "" - + @staticmethod def from_tuple(asset_tuple: tuple) -> Asset: - return Asset(asset_tuple[2], asset_tuple[1], json.loads(asset_tuple[0])) \ No newline at end of file + return Asset(asset_tuple[2], asset_tuple[1], json.loads(asset_tuple[0])) diff --git a/planetmint/backend/models/fulfills.py b/planetmint/backend/models/fulfills.py index 096a178..ae072be 100644 --- a/planetmint/backend/models/fulfills.py +++ b/planetmint/backend/models/fulfills.py @@ -5,7 +5,8 @@ from dataclasses import dataclass + @dataclass class Fulfills: transaction_id: str = "" - output_index: int = 0 \ No newline at end of file + output_index: int = 0 diff --git a/planetmint/backend/models/input.py b/planetmint/backend/models/input.py index 421615e..261c7f9 100644 --- a/planetmint/backend/models/input.py +++ b/planetmint/backend/models/input.py @@ -9,25 +9,23 @@ from typing import Optional from .fulfills import Fulfills + @dataclass class Input: tx_id: str = "" fulfills: Optional[Fulfills] = None owners_before: list[str] = field(default_factory=list) fulfillment: str = "" - + @staticmethod def from_dict(input_dict: dict, tx_id: str = "") -> Input: fulfills = None - + if input_dict["fulfills"]: - fulfills = Fulfills( - input_dict["fulfills"]["transaction_id"], - input_dict["fulfills"]["output_index"] - ) - + fulfills = Fulfills(input_dict["fulfills"]["transaction_id"], input_dict["fulfills"]["output_index"]) + return Input(tx_id, fulfills, input_dict["owners_before"], input_dict["fulfillment"]) - + @staticmethod def from_tuple(input_tuple: tuple) -> Input: tx_id = input_tuple[0] @@ -39,17 +37,14 @@ class Input: if fulfills_tx_id: # TODO: the output_index should be an unsigned int fulfills = Fulfills(fulfills_tx_id, int(input_tuple[4])) - + return Input(tx_id, fulfills, owners_before, fulfillment) - + def to_dict(self) -> dict: - fulfills = { - "transaction_id": self.fulfills.transaction_id, - "output_index": self.fulfills.output_index - } if self.fulfills else None - - return { - "fulfills": fulfills, - "fulfillment": self.fulfillment, - "owners_before": self.owners_before - } \ No newline at end of file + fulfills = ( + {"transaction_id": self.fulfills.transaction_id, "output_index": self.fulfills.output_index} + if self.fulfills + else None + ) + + return {"fulfills": fulfills, "fulfillment": self.fulfillment, "owners_before": self.owners_before} diff --git a/planetmint/backend/models/keys.py b/planetmint/backend/models/keys.py index 063b032..1032061 100644 --- a/planetmint/backend/models/keys.py +++ b/planetmint/backend/models/keys.py @@ -7,6 +7,7 @@ from __future__ import annotations from dataclasses import dataclass, field from typing import Optional + @dataclass class Keys: tx_id: str = "" @@ -20,7 +21,6 @@ class Keys: public_keys=output["public_keys"], ) - @staticmethod def from_tuple(output: tuple) -> Keys: return Keys( diff --git a/planetmint/backend/models/metadata.py b/planetmint/backend/models/metadata.py index c645a63..1f4c1fa 100644 --- a/planetmint/backend/models/metadata.py +++ b/planetmint/backend/models/metadata.py @@ -8,11 +8,12 @@ import json from dataclasses import dataclass from typing import Optional + @dataclass class MetaData: id: str = "" metadata: Optional[str] = None - + @staticmethod def from_tuple(meta_data_tuple: tuple) -> MetaData: - return MetaData(meta_data_tuple[0], json.loads(meta_data_tuple[1])) \ No newline at end of file + return MetaData(meta_data_tuple[0], json.loads(meta_data_tuple[1])) diff --git a/planetmint/backend/models/output.py b/planetmint/backend/models/output.py index 0b04835..cbd75fb 100644 --- a/planetmint/backend/models/output.py +++ b/planetmint/backend/models/output.py @@ -114,13 +114,8 @@ def output_with_sub_conditions(output, tx_id) -> Output: type=sub_condition["type"], public_key=sub_condition["public_key"], ) - for sub_condition in output["condition"]["details"][ - "subconditions" - ] + for sub_condition in output["condition"]["details"]["subconditions"] ], ), ), ) - - - diff --git a/planetmint/backend/models/script.py b/planetmint/backend/models/script.py index ce26968..d2df58f 100644 --- a/planetmint/backend/models/script.py +++ b/planetmint/backend/models/script.py @@ -7,13 +7,12 @@ from __future__ import annotations from dataclasses import dataclass from typing import Optional + @dataclass class Script: id: str = "" script: Optional[str] = None - + @staticmethod def from_tuple(script_tuple: tuple) -> Script: return Script(script_tuple[0], script_tuple[1]) - - diff --git a/planetmint/backend/models/transaction.py b/planetmint/backend/models/transaction.py index 632e61c..0ba2e30 100644 --- a/planetmint/backend/models/transaction.py +++ b/planetmint/backend/models/transaction.py @@ -7,6 +7,7 @@ from __future__ import annotations from dataclasses import dataclass, field from typing import Optional + @dataclass class Transaction: id: str = "" @@ -23,7 +24,6 @@ class Transaction: raw_transaction=transaction["transaction"], ) - @staticmethod def from_tuple(transaction: tuple) -> Transaction: return Transaction( @@ -33,7 +33,6 @@ class Transaction: raw_transaction=transaction[3], ) - def to_dict(self) -> dict: return { "id": self.id, diff --git a/planetmint/backend/query.py b/planetmint/backend/query.py index b1ce577..afb9ef2 100644 --- a/planetmint/backend/query.py +++ b/planetmint/backend/query.py @@ -59,6 +59,7 @@ def store_transactions(connection, signed_transactions): raise NotImplementedError + @singledispatch def store_transaction(connection, transaction): """Store a single transaction.""" @@ -100,6 +101,7 @@ def get_asset(connection, asset_id) -> Asset: raise NotImplementedError + @singledispatch def get_assets_by_tx_id(connection, tx_id: str) -> list[Asset]: """Get assets by transaction id. @@ -188,6 +190,7 @@ def get_block_with_transaction(connection, txid): raise NotImplementedError + @singledispatch def get_metadata_by_tx_id(connection, transaction_id: str) -> MetaData: """Get metadata from the metadata table containing `transaction_id`. @@ -201,6 +204,7 @@ def get_metadata_by_tx_id(connection, transaction_id: str) -> MetaData: """ raise NotImplementedError + @singledispatch def store_transaction_outputs_and_keys(connection, output: Output, index: int): """Store the transaction outputs. @@ -222,6 +226,7 @@ def store_transaction_outputs(connection, output: Output, index: int): """ raise NotImplementedError + @singledispatch def store_transaction_keys(connection, keys: [Keys], output_id: str, index: int): """Store the transaction keys. @@ -493,21 +498,25 @@ def get_latest_abci_chain(conn): """ raise NotImplementedError + @singledispatch def get_inputs_by_tx_id(connection, tx_id) -> list[Input]: """Retrieve inputs for a transaction by its id""" raise NotImplementedError + @singledispatch def store_transaction_inputs(connection, inputs: list[Input]): """Store inputs for a transaction""" raise NotImplementedError + @singledispatch def _group_transaction_by_ids(txids: list, connection): """Returns the transactions object (JSON TYPE), from list of ids.""" raise NotImplementedError + @singledispatch def get_script_by_tx_id(connection, tx_id: str) -> Script: """Retrieve script for a transaction by its id""" @@ -519,7 +528,8 @@ 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_keys_by_tx_id(connection, tx_id: str) -> list[Keys]: """Retrieve keys for a transaction by its id""" - raise NotImplementedError \ No newline at end of file + raise NotImplementedError diff --git a/planetmint/backend/tarantool/query.py b/planetmint/backend/tarantool/query.py index 08eac29..9bf1aae 100644 --- a/planetmint/backend/tarantool/query.py +++ b/planetmint/backend/tarantool/query.py @@ -12,9 +12,17 @@ from tarantool.error import DatabaseError from planetmint.backend import query from planetmint.backend.models.keys import Keys from planetmint.backend.models.transaction import Transaction -from planetmint.backend.tarantool.const import TARANT_TABLE_META_DATA, TARANT_TABLE_ASSETS, TARANT_TABLE_KEYS, \ - TARANT_TABLE_TRANSACTION, TARANT_TABLE_INPUT, TARANT_TABLE_OUTPUT, TARANT_TABLE_SCRIPT, TARANT_TX_ID_SEARCH, \ - TARANT_ID_SEARCH +from planetmint.backend.tarantool.const import ( + TARANT_TABLE_META_DATA, + TARANT_TABLE_ASSETS, + TARANT_TABLE_KEYS, + TARANT_TABLE_TRANSACTION, + TARANT_TABLE_INPUT, + TARANT_TABLE_OUTPUT, + TARANT_TABLE_SCRIPT, + TARANT_TX_ID_SEARCH, + TARANT_ID_SEARCH, +) from planetmint.backend.utils import module_dispatch_registrar from planetmint.backend.models import Asset, MetaData, Input, Script, Output from planetmint.backend.tarantool.connection import TarantoolDBConnection @@ -74,16 +82,20 @@ def get_keys_by_tx_id(connection, tx_id: str) -> list[Keys]: @register_query(TarantoolDBConnection) def store_transaction_inputs(connection, input: Input, index: int): - connection.run(connection.space(TARANT_TABLE_INPUT).insert(( - input.tx_id, - input.fulfillment, - input.owners_before, - input.fulfills.transaction_id if input.fulfills else "", - # TODO: the output_index should be an unsigned int - str(input.fulfills.output_index) if input.fulfills else "", - uuid4().hex, - index - ))) + connection.run( + connection.space(TARANT_TABLE_INPUT).insert( + ( + input.tx_id, + input.fulfillment, + input.owners_before, + input.fulfills.transaction_id if input.fulfills else "", + # TODO: the output_index should be an unsigned int + str(input.fulfills.output_index) if input.fulfills else "", + uuid4().hex, + index, + ) + ) + ) @register_query(TarantoolDBConnection) @@ -119,22 +131,14 @@ def store_transaction_outputs(connection, output: Output, index: int) -> str: index, ) - connection.run(connection.space(TARANT_TABLE_OUTPUT).insert(( - tmp_output - ))) + connection.run(connection.space(TARANT_TABLE_OUTPUT).insert((tmp_output))) return output_id @register_query(TarantoolDBConnection) def store_transaction_keys(connection, keys: Keys, output_id: str, index: int): for key in keys.public_keys: - connection.run(connection.space(TARANT_TABLE_KEYS).insert(( - uuid4().hex, - keys.tx_id, - output_id, - key, - index - ))) + connection.run(connection.space(TARANT_TABLE_KEYS).insert((uuid4().hex, keys.tx_id, output_id, key, index))) @register_query(TarantoolDBConnection) @@ -142,12 +146,17 @@ def store_transactions(connection, signed_transactions: list): for transaction in signed_transactions: store_transaction(connection, transaction) - [store_transaction_inputs(connection, Input.from_dict(input, transaction["id"]), index) for - index, input in enumerate(transaction[TARANT_TABLE_INPUT])] + [ + store_transaction_inputs(connection, Input.from_dict(input, transaction["id"]), index) + for index, input in enumerate(transaction[TARANT_TABLE_INPUT]) + ] - [store_transaction_outputs_and_keys(connection, Output.outputs_and_keys_dict(output, transaction["id"]), index) - for index, output in - enumerate(transaction[TARANT_TABLE_OUTPUT])] + [ + store_transaction_outputs_and_keys( + connection, Output.outputs_and_keys_dict(output, transaction["id"]), index + ) + for index, output in enumerate(transaction[TARANT_TABLE_OUTPUT]) + ] store_metadatas(connection, [MetaData(transaction["id"], transaction["metadata"])]) @@ -160,17 +169,14 @@ def store_transactions(connection, signed_transactions: list): if TARANT_TABLE_SCRIPT in transaction: connection.run( connection.space(TARANT_TABLE_SCRIPT).insert((transaction["id"], transaction[TARANT_TABLE_SCRIPT])), - only_data=False) + only_data=False, + ) @register_query(TarantoolDBConnection) def store_transaction(connection, transaction): - tx = (transaction["id"], transaction["operation"], transaction["version"], - transaction) - connection.run(connection.space(TARANT_TABLE_TRANSACTION).insert( - tx - ), - only_data=False) + tx = (transaction["id"], transaction["operation"], transaction["version"], transaction) + connection.run(connection.space(TARANT_TABLE_TRANSACTION).insert(tx), only_data=False) @register_query(TarantoolDBConnection) @@ -191,9 +197,7 @@ def get_transactions(connection, transactions_ids: list) -> list[Transaction]: def store_metadatas(connection, metadata: list[MetaData]): for meta in metadata: connection.run( - connection.space(TARANT_TABLE_META_DATA).insert( - (meta.id, json.dumps(meta.metadata)) - ) # noqa: E713 + connection.space(TARANT_TABLE_META_DATA).insert((meta.id, json.dumps(meta.metadata))) # noqa: E713 ) @@ -268,8 +272,9 @@ def _from_tuple_list_to_asset_list(_data: list) -> list[Asset]: @register_query(TarantoolDBConnection) def get_spent(connection, fullfil_transaction_id: str, fullfil_output_index: str): _inputs = connection.run( - connection.space(TARANT_TABLE_INPUT).select([fullfil_transaction_id, str(fullfil_output_index)], - index="spent_search") + connection.space(TARANT_TABLE_INPUT).select( + [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 @@ -304,7 +309,7 @@ def store_block(connection, block: dict): @register_query(TarantoolDBConnection) def get_txids_filtered( - connection, asset_ids: list[str], operation: str = None, last_tx: any = None + connection, asset_ids: list[str], operation: str = None, last_tx: any = None ): # TODO here is used 'OR' operator actions = { "CREATE": {"sets": ["CREATE", asset_ids], "index": "transaction_search"}, @@ -330,7 +335,9 @@ def get_txids_filtered( _transactions.extend(_tmp_transactions) else: _tx_ids = connection.run(connection.space(TARANT_TABLE_TRANSACTION).select(asset_ids, index=TARANT_ID_SEARCH)) - _assets_ids = connection.run(connection.space(TARANT_TABLE_ASSETS).select(asset_ids, index="only_asset_search")) + _assets_ids = connection.run( + connection.space(TARANT_TABLE_ASSETS).select(asset_ids, index="only_asset_search") + ) return tuple(set([sublist[1] for sublist in _assets_ids] + [sublist[0] for sublist in _tx_ids])) if last_tx: @@ -409,20 +416,27 @@ def delete_transactions(connection, txn_ids: list): for _id in txn_ids: connection.run(connection.space(TARANT_TABLE_TRANSACTION).delete(_id), only_data=False) for _id in txn_ids: - _inputs = connection.run(connection.space(TARANT_TABLE_INPUT).select(_id, index=TARANT_ID_SEARCH), - only_data=False) - _outputs = connection.run(connection.space(TARANT_TABLE_OUTPUT).select(_id, index=TARANT_ID_SEARCH), - only_data=False) - _keys = connection.run(connection.space(TARANT_TABLE_KEYS).select(_id, index=TARANT_TX_ID_SEARCH), - only_data=False) + _inputs = connection.run( + connection.space(TARANT_TABLE_INPUT).select(_id, index=TARANT_ID_SEARCH), only_data=False + ) + _outputs = connection.run( + connection.space(TARANT_TABLE_OUTPUT).select(_id, index=TARANT_ID_SEARCH), only_data=False + ) + _keys = connection.run( + connection.space(TARANT_TABLE_KEYS).select(_id, index=TARANT_TX_ID_SEARCH), only_data=False + ) for _kID in _keys: - connection.run(connection.space(TARANT_TABLE_KEYS).delete(_kID[0], index=TARANT_ID_SEARCH), only_data=False) + connection.run( + connection.space(TARANT_TABLE_KEYS).delete(_kID[0], index=TARANT_ID_SEARCH), only_data=False + ) for _inpID in _inputs: - connection.run(connection.space(TARANT_TABLE_INPUT).delete(_inpID[5], index="delete_search"), - only_data=False) + connection.run( + connection.space(TARANT_TABLE_INPUT).delete(_inpID[5], index="delete_search"), only_data=False + ) for _outpID in _outputs: - connection.run(connection.space(TARANT_TABLE_OUTPUT).delete(_outpID[5], index="unique_search"), - only_data=False) + connection.run( + connection.space(TARANT_TABLE_OUTPUT).delete(_outpID[5], index="unique_search"), only_data=False + ) for _id in txn_ids: connection.run(connection.space(TARANT_TABLE_META_DATA).delete(_id, index=TARANT_ID_SEARCH), only_data=False) @@ -558,7 +572,7 @@ def get_election(connection, election_id: str): @register_query(TarantoolDBConnection) def get_asset_tokens_for_public_key( - connection, asset_id: str, public_key: str + connection, asset_id: str, public_key: str ): # FIXME Something can be wrong with this function ! (public_key) is not used # noqa: E501 # space = connection.space("keys") # _keys = space.select([public_key], index="keys_search") diff --git a/planetmint/backend/tarantool/transaction/tools.py b/planetmint/backend/tarantool/transaction/tools.py index 19e82b7..cd4d0ac 100644 --- a/planetmint/backend/tarantool/transaction/tools.py +++ b/planetmint/backend/tarantool/transaction/tools.py @@ -1,7 +1,14 @@ from transactions.common.memoize import HDict -from planetmint.backend.tarantool.const import TARANT_TABLE_META_DATA, TARANT_TABLE_ASSETS, TARANT_TABLE_KEYS, \ - TARANT_TABLE_TRANSACTION, TARANT_TABLE_INPUT, TARANT_TABLE_OUTPUT, TARANT_TABLE_SCRIPT +from planetmint.backend.tarantool.const import ( + TARANT_TABLE_META_DATA, + TARANT_TABLE_ASSETS, + TARANT_TABLE_KEYS, + TARANT_TABLE_TRANSACTION, + TARANT_TABLE_INPUT, + TARANT_TABLE_OUTPUT, + TARANT_TABLE_SCRIPT, +) def get_items(_list): diff --git a/tests/backend/tarantool/test_queries.py b/tests/backend/tarantool/test_queries.py index 4efe905..d6e7eac 100644 --- a/tests/backend/tarantool/test_queries.py +++ b/tests/backend/tarantool/test_queries.py @@ -49,7 +49,7 @@ def test_write_assets(db_conn): Asset("2", "2", "2"), Asset("3", "3", "3"), # Duplicated id. Should not be written to the database - Asset("1", "1", "1") + Asset("1", "1", "1"), ] # write the assets @@ -65,7 +65,7 @@ def test_write_assets(db_conn): def test_get_assets(db_conn): from planetmint.backend.tarantool import query - + assets = [ Asset("1", "1"), Asset("2", "2"), @@ -186,7 +186,7 @@ def test_get_metadata(db_conn): metadata = [ MetaData("dd86682db39e4b424df0eec1413cfad65488fd48712097c5d865ca8e8e059b64", None), - MetaData("55a2303e3bcd653e4b5bd7118d39c0e2d48ee2f18e22fbcf64e906439bdeb45d", {"key": "value"}) + MetaData("55a2303e3bcd653e4b5bd7118d39c0e2d48ee2f18e22fbcf64e906439bdeb45d", {"key": "value"}), ] # conn.db.metadata.insert_many(deepcopy(metadata), ordered=False) diff --git a/tests/tendermint/test_lib.py b/tests/tendermint/test_lib.py index 2f4d64e..e942e3c 100644 --- a/tests/tendermint/test_lib.py +++ b/tests/tendermint/test_lib.py @@ -479,7 +479,7 @@ def test_get_spent_key_order(b, user_pk, user_sk, user2_pk, user2_sk): inputs = tx1.to_inputs() tx2 = Transfer.generate([inputs[1]], [([user2_pk], 2)], [tx1.id]).sign([user_sk]) assert b.validate_transaction(tx2) - + b.store_bulk_transactions([tx2]) tx3 = Transfer.generate([inputs[1]], [([bob.public_key], 2)], [tx1.id]).sign([user_sk]) From 3ebfed41c7134f0637e80d4f0b1835e6f1e6d593 Mon Sep 17 00:00:00 2001 From: cybnon Date: Thu, 1 Dec 2022 14:20:34 +0100 Subject: [PATCH 4/6] Fix recursion error --- planetmint/backend/models/transaction.py | 10 ++++ planetmint/backend/query.py | 17 ++++++- planetmint/backend/tarantool/query.py | 47 +++++++++---------- planetmint/commands/planetmint.py | 4 +- planetmint/lib.py | 12 ++--- planetmint/web/views/transactions.py | 2 +- tests/commands/test_commands.py | 12 ++--- tests/db/test_planetmint_api.py | 12 ++--- tests/tendermint/test_core.py | 8 ++-- tests/tendermint/test_integration.py | 2 +- tests/tendermint/test_lib.py | 2 +- .../test_upsert_validator_vote.py | 2 +- 12 files changed, 74 insertions(+), 56 deletions(-) diff --git a/planetmint/backend/models/transaction.py b/planetmint/backend/models/transaction.py index 0ba2e30..8fd3e9e 100644 --- a/planetmint/backend/models/transaction.py +++ b/planetmint/backend/models/transaction.py @@ -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"], ) diff --git a/planetmint/backend/query.py b/planetmint/backend/query.py index afb9ef2..1d445ef 100644 --- a/planetmint/backend/query.py +++ b/planetmint/backend/query.py @@ -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. diff --git a/planetmint/backend/tarantool/query.py b/planetmint/backend/tarantool/query.py index 9bf1aae..7d34bf0 100644 --- a/planetmint/backend/tarantool/query.py +++ b/planetmint/backend/tarantool/query.py @@ -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) diff --git a/planetmint/commands/planetmint.py b/planetmint/commands/planetmint.py index 5026d90..64585ff 100644 --- a/planetmint/commands/planetmint.py +++ b/planetmint/commands/planetmint.py @@ -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 diff --git a/planetmint/lib.py b/planetmint/lib.py index 7b19b69..397ded1 100644 --- a/planetmint/lib.py +++ b/planetmint/lib.py @@ -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 = [] diff --git a/planetmint/web/views/transactions.py b/planetmint/web/views/transactions.py index 2660588..236a9d6 100644 --- a/planetmint/web/views/transactions.py +++ b/planetmint/web/views/transactions.py @@ -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) diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index ab2762a..0b9186a 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -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 diff --git a/tests/db/test_planetmint_api.py b/tests/db/test_planetmint_api.py index 2c08ed3..301507e 100644 --- a/tests/db/test_planetmint_api.py +++ b/tests/db/test_planetmint_api.py @@ -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]) diff --git a/tests/tendermint/test_core.py b/tests/tendermint/test_core.py index d036a1b..44d4dc1 100644 --- a/tests/tendermint/test_core.py +++ b/tests/tendermint/test_core.py @@ -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 diff --git a/tests/tendermint/test_integration.py b/tests/tendermint/test_integration.py index 341ef09..6a36d74 100644 --- a/tests/tendermint/test_integration.py +++ b/tests/tendermint/test_integration.py @@ -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 diff --git a/tests/tendermint/test_lib.py b/tests/tendermint/test_lib.py index e942e3c..cd5b0b7 100644 --- a/tests/tendermint/test_lib.py +++ b/tests/tendermint/test_lib.py @@ -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 diff --git a/tests/upsert_validator/test_upsert_validator_vote.py b/tests/upsert_validator/test_upsert_validator_vote.py index b0e649e..86d045d 100644 --- a/tests/upsert_validator/test_upsert_validator_vote.py +++ b/tests/upsert_validator/test_upsert_validator_vote.py @@ -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) From 135d04996980fd5e4c1f9db192835fdd7e68e860 Mon Sep 17 00:00:00 2001 From: cybnon Date: Thu, 1 Dec 2022 16:22:15 +0100 Subject: [PATCH 5/6] More fixes Signed-off-by: cybnon --- planetmint/backend/models/asset.py | 4 ++-- planetmint/backend/models/output.py | 4 +++- planetmint/backend/tarantool/query.py | 13 +++++++++---- planetmint/lib.py | 16 ++++++++-------- tests/commands/test_commands.py | 12 ++++++------ tests/db/test_planetmint_api.py | 14 +++++++------- tests/tendermint/test_core.py | 8 ++++---- tests/tendermint/test_integration.py | 2 +- tests/tendermint/test_lib.py | 6 +++--- .../test_upsert_validator_vote.py | 2 +- 10 files changed, 44 insertions(+), 37 deletions(-) diff --git a/planetmint/backend/models/asset.py b/planetmint/backend/models/asset.py index f2f18c5..2071954 100644 --- a/planetmint/backend/models/asset.py +++ b/planetmint/backend/models/asset.py @@ -12,8 +12,8 @@ from dataclasses import dataclass class Asset: id: str = "" tx_id: str = "" - data: str = "" + data: dict = "" @staticmethod def from_tuple(asset_tuple: tuple) -> Asset: - return Asset(asset_tuple[2], asset_tuple[1], json.loads(asset_tuple[0])) + return Asset(asset_tuple[2], asset_tuple[1], json.loads(asset_tuple[0])["data"]) diff --git a/planetmint/backend/models/output.py b/planetmint/backend/models/output.py index cbd75fb..c8a8067 100644 --- a/planetmint/backend/models/output.py +++ b/planetmint/backend/models/output.py @@ -37,8 +37,9 @@ class Condition: @dataclass class Output: + id: str = "" tx_id: str = "" - amount: int = 0 + amount: str = '0' public_keys: List[str] = field(default_factory=list) condition: Condition = field(default_factory=Condition) @@ -54,6 +55,7 @@ class Output: @staticmethod def from_tuple(output: tuple) -> Output: return Output( + id=output[5], tx_id=output[0], amount=output[1], condition=Condition( diff --git a/planetmint/backend/tarantool/query.py b/planetmint/backend/tarantool/query.py index 7d34bf0..1a3296d 100644 --- a/planetmint/backend/tarantool/query.py +++ b/planetmint/backend/tarantool/query.py @@ -31,7 +31,7 @@ register_query = module_dispatch_registrar(query) @register_query(TarantoolDBConnection) -def _group_transaction_by_ids(connection, txids: list): +def _group_transaction_by_ids(connection, txids: list) -> list[Transaction]: _transactions = [] for txid in txids: tx = get_transaction_space_by_id(connection, txid) @@ -39,8 +39,9 @@ def _group_transaction_by_ids(connection, txids: list): continue 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) + _output = get_outputs_by_tx_id(connection, txid) + _keys = get_keys_by_tx_id(connection, txid) + tx.outputs = [_enricht_output_with_public_keys(_keys, output) for output in _output] 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) @@ -49,6 +50,10 @@ def _group_transaction_by_ids(connection, txids: list): return _transactions +def _enricht_output_with_public_keys(keys: list[Keys], output: Output) -> Output: + output.public_keys = [key.public_keys for key in keys if key.output_id == output.id] + return output + @register_query(TarantoolDBConnection) def get_inputs_by_tx_id(connection, tx_id: str) -> list[Input]: _inputs = connection.run(connection.space(TARANT_TABLE_INPUT).select(tx_id, index=TARANT_ID_SEARCH)) @@ -183,7 +188,7 @@ def get_transaction_space_by_id(connection, transaction_id): @register_query(TarantoolDBConnection) def get_transaction_single(connection, transaction_id): - return _group_transaction_by_ids(txids=[transaction_id], connection=connection) + return _group_transaction_by_ids(txids=[transaction_id], connection=connection)[0] @register_query(TarantoolDBConnection) diff --git a/planetmint/lib.py b/planetmint/lib.py index 397ded1..da69bf4 100644 --- a/planetmint/lib.py +++ b/planetmint/lib.py @@ -224,11 +224,11 @@ class Planetmint(object): return backend.query.delete_unspent_outputs(self.connection, *unspent_outputs) def is_committed(self, transaction_id): - transaction = backend.query.get_transaction(self.connection, transaction_id) + transaction = backend.query.get_transaction_space_by_id(self.connection, transaction_id) return bool(transaction) def get_transaction(self, transaction_id): - return backend.query.get_transaction(self.connection, transaction_id) + return backend.query.get_transaction_single(self.connection, transaction_id) def get_transactions(self, txn_ids): return backend.query.get_transactions(self.connection, txn_ids) @@ -278,7 +278,7 @@ class Planetmint(object): raise DoubleSpend('tx "{}" spends inputs twice'.format(txid)) elif transactions: tx_id = transactions[0]["transactions"].id - tx = backend.query.get_transaction(self.connection, tx_id) + tx = backend.query.get_transaction_single(self.connection, tx_id) assets = backend.query.get_assets_by_tx_id(self.connection, tx_id) transaction = {"transactions": tx} | {"assets": [asset.data for asset in assets]} elif current_spent_transactions: @@ -693,7 +693,7 @@ class Planetmint(object): return recipients def show_election_status(self, transaction): - data = transaction.assets[0]["data"] + data = transaction.assets[0] if "public_key" in data.keys(): data["public_key"] = public_key_to_base64(data["public_key"]["value"]) response = "" @@ -757,7 +757,7 @@ class Planetmint(object): 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)) + txns = backend.query.get_asset_tokens_for_public_key(self.connection, transaction.id, election_pk) return self.count_votes(election_pk, txns) def _get_initiated_elections(self, height, txns): # TODO: move somewhere else @@ -851,7 +851,7 @@ class Planetmint(object): votes_committed = self.get_commited_votes(transaction, election_pk) votes_current = self.count_votes(election_pk, current_votes) - total_votes = sum(output.amount for output in transaction.outputs) + total_votes = sum(int(output.amount) for output in transaction.outputs) if (votes_committed < (2 / 3) * total_votes) and (votes_committed + votes_current >= (2 / 3) * total_votes): return True @@ -909,7 +909,7 @@ class Planetmint(object): if election.operation == CHAIN_MIGRATION_ELECTION: self.migrate_abci_chain() if election.operation == VALIDATOR_ELECTION: - validator_updates = [election.assets[0]["data"]] + validator_updates = [election.assets[0].data] curr_validator_set = self.get_validators(new_height) updated_validator_set = new_validator_set(curr_validator_set, validator_updates) @@ -917,7 +917,7 @@ class Planetmint(object): # TODO change to `new_height + 2` when upgrading to Tendermint 0.24.0. self.store_validator_set(new_height + 1, updated_validator_set) - return encode_validator(election.assets[0]["data"]) + return encode_validator(election.assets[0].data) Block = namedtuple("Block", ("app_hash", "height", "transactions")) diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 0b9186a..ab2762a 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -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_space_by_id(election_id) + assert b.get_transaction(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_space_by_id(election_id) + assert b.get_transaction(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_space_by_id(election_id) + assert b.get_transaction(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_space_by_id(election_id) + assert b.get_transaction(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_space_by_id(approve) + assert b.get_transaction(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_space_by_id(approval_id) + assert b.get_transaction(approval_id) @pytest.mark.bdb diff --git a/tests/db/test_planetmint_api.py b/tests/db/test_planetmint_api.py index 301507e..2c73339 100644 --- a/tests/db/test_planetmint_api.py +++ b/tests/db/test_planetmint_api.py @@ -105,12 +105,12 @@ 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_space_by_id(tx.id) + tx_from_db = b.get_transaction(tx.id) before = tx.to_dict() after = tx_from_db.to_dict() - assert before["assets"][0]["data"] == after["transaction"]["assets"][0]["data"] + assert before["assets"][0] == after["transaction"]["assets"][0] before.pop("asset", None) after["transaction"].pop("asset", None) assert before == after["transaction"] @@ -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_space_by_id(input_tx.txid) + input_transaction = b.get_transaction(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_space_by_id(tx_link.txid) + input_tx = b.get_transaction(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_space_by_id(tx_link.txid) + input_tx = b.get_transaction(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_space_by_id(owned_input.txid) + input_tx = b.get_transaction(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_space_by_id(tx_link.txid) + tx_input = b.get_transaction(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]) diff --git a/tests/tendermint/test_core.py b/tests/tendermint/test_core.py index 44d4dc1..d036a1b 100644 --- a/tests/tendermint/test_core.py +++ b/tests/tendermint/test_core.py @@ -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_space_by_id(tx.id).id == tx.id + assert b.get_transaction(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_space_by_id(tx.id).id == tx.id + assert b.get_transaction(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_space_by_id(tx.id) + assert b.get_transaction(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_space_by_id(tx.id) + assert not b.get_transaction(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 diff --git a/tests/tendermint/test_integration.py b/tests/tendermint/test_integration.py index 6a36d74..341ef09 100644 --- a/tests/tendermint/test_integration.py +++ b/tests/tendermint/test_integration.py @@ -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_space_by_id(tx.id).id == tx.id + assert b.get_transaction(tx.id).id == tx.id block0 = b.get_latest_block() assert block0 diff --git a/tests/tendermint/test_lib.py b/tests/tendermint/test_lib.py index cd5b0b7..7eef6af 100644 --- a/tests/tendermint/test_lib.py +++ b/tests/tendermint/test_lib.py @@ -67,9 +67,9 @@ def test_asset_is_separated_from_transaciton(b): tx_dict = copy.deepcopy(tx.to_dict()) 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_space_by_id(tx.id).to_dict() == tx_dict + assert "asset" not in backend.query.get_transaction_single(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 @pytest.mark.bdb diff --git a/tests/upsert_validator/test_upsert_validator_vote.py b/tests/upsert_validator/test_upsert_validator_vote.py index 86d045d..b0e649e 100644 --- a/tests/upsert_validator/test_upsert_validator_vote.py +++ b/tests/upsert_validator/test_upsert_validator_vote.py @@ -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_space_by_id(election.id) + assert b.get_transaction(election.id) tx_vote = gen_vote(election, 0, ed25519_node_keys) assert b.validate_transaction(tx_vote) From 0fd2bc41fca908642ba9a01003184b739c46e965 Mon Sep 17 00:00:00 2001 From: cybnon Date: Mon, 5 Dec 2022 09:10:15 +0100 Subject: [PATCH 6/6] Further fixes Signed-off-by: cybnon --- planetmint/backend/models/__init__.py | 2 ++ planetmint/backend/models/asset.py | 11 +++++++++++ .../{transaction.py => dbtransaction.py} | 19 ++++++++++++------- planetmint/backend/models/input.py | 6 ++++++ planetmint/backend/models/metadata.py | 6 ++++++ planetmint/backend/models/output.py | 4 ++++ planetmint/backend/models/script.py | 6 ++++++ planetmint/backend/query.py | 10 +++++++--- planetmint/backend/tarantool/query.py | 14 +++++++------- planetmint/commands/planetmint.py | 4 ++-- planetmint/lib.py | 4 ++-- planetmint/web/views/transactions.py | 2 +- 12 files changed, 66 insertions(+), 22 deletions(-) rename planetmint/backend/models/{transaction.py => dbtransaction.py} (70%) diff --git a/planetmint/backend/models/__init__.py b/planetmint/backend/models/__init__.py index d8d99e3..c102251 100644 --- a/planetmint/backend/models/__init__.py +++ b/planetmint/backend/models/__init__.py @@ -9,3 +9,5 @@ from .input import Input from .metadata import MetaData from .script import Script from .output import Output +from .keys import Keys +from .dbtransaction import DbTransaction diff --git a/planetmint/backend/models/asset.py b/planetmint/backend/models/asset.py index 2071954..d1b3674 100644 --- a/planetmint/backend/models/asset.py +++ b/planetmint/backend/models/asset.py @@ -17,3 +17,14 @@ class Asset: @staticmethod def from_tuple(asset_tuple: tuple) -> Asset: return Asset(asset_tuple[2], asset_tuple[1], json.loads(asset_tuple[0])["data"]) + + def to_dict(self) -> dict: + return { + "id": self.id, + "tx_id": self.tx_id, + "data": self.data + } + + @staticmethod + def list_to_dict(asset_list: list[Asset]) -> list[dict]: + return [asset.to_dict() for asset in asset_list] diff --git a/planetmint/backend/models/transaction.py b/planetmint/backend/models/dbtransaction.py similarity index 70% rename from planetmint/backend/models/transaction.py rename to planetmint/backend/models/dbtransaction.py index 8fd3e9e..9022aa3 100644 --- a/planetmint/backend/models/transaction.py +++ b/planetmint/backend/models/dbtransaction.py @@ -4,15 +4,14 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 from __future__ import annotations -from dataclasses import dataclass, field -from typing import Optional +from dataclasses import dataclass from planetmint.backend.models import Asset, MetaData, Input, Output, Script from planetmint.backend.models.keys import Keys @dataclass -class Transaction: +class DbTransaction: id: str = "" operation: str = "" version: str = "" @@ -25,8 +24,8 @@ class Transaction: script: Script = None @staticmethod - def from_dict(transaction: dict) -> Transaction: - return Transaction( + def from_dict(transaction: dict) -> DbTransaction: + return DbTransaction( id=transaction["id"], operation=transaction["operation"], version=transaction["version"], @@ -35,8 +34,8 @@ class Transaction: ) @staticmethod - def from_tuple(transaction: tuple) -> Transaction: - return Transaction( + def from_tuple(transaction: tuple) -> DbTransaction: + return DbTransaction( id=transaction[0], operation=transaction[1], version=transaction[2], @@ -48,5 +47,11 @@ class Transaction: "id": self.id, "operation": self.operation, "version": self.version, + "inputs": Input.list_to_dict(self.inputs), + "assets": Asset.list_to_dict(self.assets), + "metadata": self.metadata.to_dict(), + "outputs": Output.list_to_dict(self.outputs), + "keys": self.keys.to_dict(), + "script": self.script.to_dict(), "transaction": self.raw_transaction, } diff --git a/planetmint/backend/models/input.py b/planetmint/backend/models/input.py index 261c7f9..51047a7 100644 --- a/planetmint/backend/models/input.py +++ b/planetmint/backend/models/input.py @@ -48,3 +48,9 @@ class Input: ) return {"fulfills": fulfills, "fulfillment": self.fulfillment, "owners_before": self.owners_before} + + @staticmethod + def list_to_dict(input_list: list[Input]) -> list[dict]: + return [input.to_dict() for input in input_list] + + diff --git a/planetmint/backend/models/metadata.py b/planetmint/backend/models/metadata.py index 1f4c1fa..c362a3f 100644 --- a/planetmint/backend/models/metadata.py +++ b/planetmint/backend/models/metadata.py @@ -17,3 +17,9 @@ class MetaData: @staticmethod def from_tuple(meta_data_tuple: tuple) -> MetaData: return MetaData(meta_data_tuple[0], json.loads(meta_data_tuple[1])) + + def to_dict(self) -> dict: + return { + "id": self.id, + "metadata": self.metadata + } diff --git a/planetmint/backend/models/output.py b/planetmint/backend/models/output.py index c8a8067..b8e72b5 100644 --- a/planetmint/backend/models/output.py +++ b/planetmint/backend/models/output.py @@ -85,6 +85,10 @@ class Output: }, } + @staticmethod + def list_to_dict(output_list: list[Output]) -> list[dict]: + return [output.to_dict() for output in output_list] + def output_with_public_key(output, tx_id) -> Output: return Output( diff --git a/planetmint/backend/models/script.py b/planetmint/backend/models/script.py index d2df58f..682a728 100644 --- a/planetmint/backend/models/script.py +++ b/planetmint/backend/models/script.py @@ -16,3 +16,9 @@ class Script: @staticmethod def from_tuple(script_tuple: tuple) -> Script: return Script(script_tuple[0], script_tuple[1]) + + def to_dict(self) -> dict: + return { + "id": self.id, + "script": self.script + } diff --git a/planetmint/backend/query.py b/planetmint/backend/query.py index 1d445ef..5d7ddc9 100644 --- a/planetmint/backend/query.py +++ b/planetmint/backend/query.py @@ -6,9 +6,13 @@ """Query interfaces for backends.""" from functools import singledispatch + +from planetmint.backend.models import Asset, MetaData, Output, Input, Script + from planetmint.backend.exceptions import OperationError -from planetmint.backend.interfaces import Asset, Block, MetaData, Input, Script, Output, Transaction from planetmint.backend.models.keys import Keys +from planetmint.backend.interfaces import Block +from planetmint.backend.models.dbtransaction import DbTransaction @singledispatch @@ -75,7 +79,7 @@ def get_transaction_space_by_id(connection, transaction_id): @singledispatch -def get_transaction_single(connection, transaction_id): +def get_transaction_single(connection, transaction_id) -> DbTransaction: """Get a single transaction by id.""" raise NotImplementedError @@ -88,7 +92,7 @@ def get_transaction(connection, transaction_id): raise NotImplementedError @singledispatch -def get_transactions(connection, transactions_ids) -> list[Transaction]: +def get_transactions(connection, transactions_ids) -> list[DbTransaction]: """Get a transaction from the transactions table. Args: diff --git a/planetmint/backend/tarantool/query.py b/planetmint/backend/tarantool/query.py index 1a3296d..6a65830 100644 --- a/planetmint/backend/tarantool/query.py +++ b/planetmint/backend/tarantool/query.py @@ -11,7 +11,7 @@ from operator import itemgetter from tarantool.error import DatabaseError from planetmint.backend import query from planetmint.backend.models.keys import Keys -from planetmint.backend.models.transaction import Transaction +from planetmint.backend.models.dbtransaction import DbTransaction from planetmint.backend.tarantool.const import ( TARANT_TABLE_META_DATA, TARANT_TABLE_ASSETS, @@ -31,7 +31,7 @@ register_query = module_dispatch_registrar(query) @register_query(TarantoolDBConnection) -def _group_transaction_by_ids(connection, txids: list) -> list[Transaction]: +def _group_transaction_by_ids(connection, txids: list) -> list[DbTransaction]: _transactions = [] for txid in txids: tx = get_transaction_space_by_id(connection, txid) @@ -76,7 +76,7 @@ def get_keys_by_tx_id(connection, tx_id: str) -> list[Keys]: @register_query(TarantoolDBConnection) -def get_transaction(connection, tx_id: str) -> Transaction: +def get_transaction(connection, tx_id: str) -> DbTransaction: return NotImplemented @register_query(TarantoolDBConnection) @@ -174,7 +174,7 @@ def store_transactions(connection, signed_transactions: list): @register_query(TarantoolDBConnection) def store_transaction(connection, transaction): - tx = (transaction["id"], transaction["operation"], transaction["version"], transaction) + tx = (transaction["id"], transaction["operation"], transaction["version"], [transaction]) connection.run(connection.space(TARANT_TABLE_TRANSACTION).insert(tx), only_data=False) @@ -183,16 +183,16 @@ 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]) + return DbTransaction.from_tuple(txs[0]) @register_query(TarantoolDBConnection) -def get_transaction_single(connection, transaction_id): +def get_transaction_single(connection, transaction_id) -> DbTransaction: return _group_transaction_by_ids(txids=[transaction_id], connection=connection)[0] @register_query(TarantoolDBConnection) -def get_transactions(connection, transactions_ids: list) -> list[Transaction]: +def get_transactions(connection, transactions_ids: list) -> list[DbTransaction]: return _group_transaction_by_ids(txids=transactions_ids, connection=connection) diff --git a/planetmint/commands/planetmint.py b/planetmint/commands/planetmint.py index 64585ff..5026d90 100644 --- a/planetmint/commands/planetmint.py +++ b/planetmint/commands/planetmint.py @@ -193,7 +193,7 @@ def run_election_approve(args, planet): """ key = load_node_key(args.sk) - tx = planet.get_transaction_space_by_id(args.election_id) + tx = planet.get_transaction(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_space_by_id(args.election_id) + election = planet.get_transaction(args.election_id) if not election: logger.error(f"No election found with election_id {args.election_id}") return diff --git a/planetmint/lib.py b/planetmint/lib.py index da69bf4..26cbbbb 100644 --- a/planetmint/lib.py +++ b/planetmint/lib.py @@ -279,8 +279,8 @@ class Planetmint(object): elif transactions: tx_id = transactions[0]["transactions"].id tx = backend.query.get_transaction_single(self.connection, tx_id) - assets = backend.query.get_assets_by_tx_id(self.connection, tx_id) - transaction = {"transactions": tx} | {"assets": [asset.data for asset in assets]} + tx.assets = backend.query.get_assets_by_tx_id(self.connection, tx_id) + transaction = tx.to_dict() elif current_spent_transactions: transaction = current_spent_transactions[0] diff --git a/planetmint/web/views/transactions.py b/planetmint/web/views/transactions.py index 236a9d6..2660588 100644 --- a/planetmint/web/views/transactions.py +++ b/planetmint/web/views/transactions.py @@ -37,7 +37,7 @@ class TransactionApi(Resource): pool = current_app.config["bigchain_pool"] with pool() as planet: - tx = planet.get_transaction_space_by_id(tx_id) + tx = planet.get_transaction(tx_id) if not tx: return make_error(404)