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])