diff --git a/planetmint/backend/tarantool/const.py b/planetmint/backend/tarantool/const.py index 80b09e2..9efc9c1 100644 --- a/planetmint/backend/tarantool/const.py +++ b/planetmint/backend/tarantool/const.py @@ -11,6 +11,13 @@ TARANT_TABLE_GOVERNANCE = "governance" TARANT_TABLE_INPUT = "inputs" TARANT_TABLE_OUTPUT = "outputs" TARANT_TABLE_SCRIPT = "scripts" +TARANT_TABLE_BLOCKS = "blocks" +TARANT_TABLE_VALIDATOR_SETS = "validator_sets" +TARANT_TABLE_ABCI_CHAINS = "abci_chains" +TARANT_TABLE_UTXOS = "utxos" +TARANT_TABLE_PRE_COMMITS = "pre_commits" +TARANT_TABLE_ELECTIONS = "elections" + TARANT_TX_ID_SEARCH = "transaction_id" TARANT_ID_SEARCH = "id" diff --git a/planetmint/backend/tarantool/query.py b/planetmint/backend/tarantool/query.py index 8a2e619..0f22d86 100644 --- a/planetmint/backend/tarantool/query.py +++ b/planetmint/backend/tarantool/query.py @@ -7,8 +7,8 @@ import json import logging from uuid import uuid4 -from hashlib import sha256 from operator import itemgetter +from typing import Union from planetmint.backend import query @@ -18,9 +18,7 @@ from planetmint.exceptions import CriticalDoubleSpend 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, @@ -28,9 +26,15 @@ from planetmint.backend.tarantool.const import ( TARANT_INDEX_TX_BY_ASSET_ID, TARANT_INDEX_SPENDING_BY_ID_AND_OUTPUT_INDEX, TARANT_TABLE_GOVERNANCE, + TARANT_TABLE_ABCI_CHAINS, + TARANT_TABLE_BLOCKS, + TARANT_TABLE_VALIDATOR_SETS, + TARANT_TABLE_UTXOS, + TARANT_TABLE_PRE_COMMITS, + TARANT_TABLE_ELECTIONS ) from planetmint.backend.utils import module_dispatch_registrar -from planetmint.backend.models import Asset, Block, MetaData, Input, Script, Output +from planetmint.backend.models import Asset, Block, Output from planetmint.backend.tarantool.connection import TarantoolDBConnection @@ -39,7 +43,7 @@ register_query = module_dispatch_registrar(query) @register_query(TarantoolDBConnection) -def get_complete_transactions_by_ids(connection, txids: list, table=TARANT_TABLE_TRANSACTION) -> list[DbTransaction]: +def get_complete_transactions_by_ids(connection, txids: list) -> list[DbTransaction]: _transactions = [] for txid in txids: tx = get_transaction_by_id(connection, txid, TARANT_TABLE_TRANSACTION) @@ -61,7 +65,7 @@ def get_outputs_by_tx_id(connection, tx_id: str) -> list[Output]: @register_query(TarantoolDBConnection) -def get_transaction(connection, tx_id: str) -> DbTransaction: +def get_transaction(connection, tx_id: str) -> Union[DbTransaction, None]: transactions = get_complete_transactions_by_ids(connection, (tx_id)) if len(transactions) > 1 or len(transactions) == 0: return None @@ -184,8 +188,8 @@ def get_transaction_by_id(connection, transaction_id, table=TARANT_TABLE_TRANSAC @register_query(TarantoolDBConnection) -def get_transaction_single(connection, transaction_id, table=TARANT_TABLE_TRANSACTION) -> DbTransaction: - txs = get_complete_transactions_by_ids(txids=[transaction_id], connection=connection, table=table) +def get_transaction_single(connection, transaction_id) -> Union[DbTransaction, None]: + txs = get_complete_transactions_by_ids(txids=[transaction_id], connection=connection) return txs[0] if len(txs) == 1 else None @@ -216,7 +220,7 @@ def get_assets(connection, assets_ids: list) -> list[Asset]: @register_query(TarantoolDBConnection) -def get_spent(connection, fullfil_transaction_id: str, fullfil_output_index: str): +def get_spent(connection, fullfil_transaction_id: str, fullfil_output_index: str) -> list[DbTransaction]: _inputs = connection.run( connection.space(TARANT_TABLE_TRANSACTION).select( [fullfil_transaction_id, fullfil_output_index], index=TARANT_INDEX_SPENDING_BY_ID_AND_OUTPUT_INDEX @@ -226,8 +230,8 @@ def get_spent(connection, fullfil_transaction_id: str, fullfil_output_index: str @register_query(TarantoolDBConnection) -def get_latest_block(connection): - blocks = connection.run(connection.space("blocks").select()) +def get_latest_block(connection) -> Union[dict, None]: + blocks = connection.run(connection.space(TARANT_TABLE_BLOCKS).select()) if not blocks: return None @@ -241,7 +245,7 @@ def store_block(connection, block: dict): block_unique_id = uuid4().hex try: connection.run( - connection.space("blocks").insert( + connection.space(TARANT_TABLE_BLOCKS).insert( (block_unique_id, block["app_hash"], block["height"], block[TARANT_TABLE_TRANSACTION]) ), only_data=False, @@ -252,7 +256,7 @@ def store_block(connection, block: dict): @register_query(TarantoolDBConnection) -def get_txids_filtered(connection, asset_ids: list[str], operation: str = "", last_tx: bool = False): +def get_txids_filtered(connection, asset_ids: list[str], operation: str = "", last_tx: bool = False) -> list[str]: transactions = [] if operation == "CREATE": transactions = connection.run( @@ -300,7 +304,7 @@ def text_search(conn, search, table=TARANT_TABLE_ASSETS, limit=0): @register_query(TarantoolDBConnection) -def get_owned_ids(connection, owner: str): +def get_owned_ids(connection, owner: str) -> list[DbTransaction]: outputs = connection.run(connection.space(TARANT_TABLE_OUTPUT).select(owner, index="public_keys")) if len(outputs) == 0: return [] @@ -325,8 +329,8 @@ def get_spending_transactions(connection, inputs): @register_query(TarantoolDBConnection) -def get_block(connection, block_id=None): - _block = connection.run(connection.space("blocks").select(block_id, index="height", limit=1)) +def get_block(connection, block_id=None) -> Union[dict, None]: + _block = connection.run(connection.space(TARANT_TABLE_BLOCKS).select(block_id, index="height", limit=1)) if len(_block) == 0: return _block = Block.from_tuple(_block[0]) @@ -334,8 +338,8 @@ def get_block(connection, block_id=None): @register_query(TarantoolDBConnection) -def get_block_with_transaction(connection, txid: str): - _block = connection.run(connection.space("blocks").select(txid, index="block_by_transaction_id")) +def get_block_with_transaction(connection, txid: str) -> list[Block]: + _block = connection.run(connection.space(TARANT_TABLE_BLOCKS).select(txid, index="block_by_transaction_id")) return _block if len(_block) > 0 else [] @@ -361,7 +365,7 @@ def store_unspent_outputs(connection, *unspent_outputs: list): for utxo in unspent_outputs: try: output = connection.run( - connection.space("utxos").insert((uuid4().hex, utxo["transaction_id"], utxo["output_index"], utxo)) + connection.space(TARANT_TABLE_UTXOS).insert((uuid4().hex, utxo["transaction_id"], utxo["output_index"], utxo)) ) result.append(output) except Exception as e: @@ -376,7 +380,7 @@ def delete_unspent_outputs(connection, *unspent_outputs: list): if unspent_outputs: for utxo in unspent_outputs: output = connection.run( - connection.space("utxos").delete( + connection.space(TARANT_TABLE_UTXOS).delete( (utxo["transaction_id"], utxo["output_index"]), index="utxo_by_transaction_id_and_output_index" ) ) @@ -386,13 +390,13 @@ def delete_unspent_outputs(connection, *unspent_outputs: list): @register_query(TarantoolDBConnection) def get_unspent_outputs(connection, query=None): # for now we don't have implementation for 'query'. - _utxos = connection.run(connection.space("utxos").select([])) + _utxos = connection.run(connection.space(TARANT_TABLE_UTXOS).select([])) return [utx[3] for utx in _utxos] @register_query(TarantoolDBConnection) def store_pre_commit_state(connection, state: dict): - _precommit = connection.run(connection.space("pre_commits").select([], limit=1)) + _precommit = connection.run(connection.space(TARANT_TABLE_PRE_COMMITS).select([], limit=1)) _precommitTuple = ( (uuid4().hex, state["height"], state[TARANT_TABLE_TRANSACTION]) if _precommit is None or len(_precommit) == 0 @@ -400,7 +404,7 @@ def store_pre_commit_state(connection, state: dict): ) try: connection.run( - connection.space("pre_commits").upsert( + connection.space(TARANT_TABLE_PRE_COMMITS).upsert( _precommitTuple, op_list=[("=", 1, state["height"]), ("=", 2, state[TARANT_TABLE_TRANSACTION])], limit=1, @@ -413,8 +417,8 @@ def store_pre_commit_state(connection, state: dict): @register_query(TarantoolDBConnection) -def get_pre_commit_state(connection): - _commit = connection.run(connection.space("pre_commits").select([], index=TARANT_ID_SEARCH)) +def get_pre_commit_state(connection) -> dict: + _commit = connection.run(connection.space(TARANT_TABLE_PRE_COMMITS).select([], index=TARANT_ID_SEARCH)) if _commit is None or len(_commit) == 0: return None _commit = sorted(_commit, key=itemgetter(1), reverse=False)[0] @@ -423,11 +427,11 @@ def get_pre_commit_state(connection): @register_query(TarantoolDBConnection) def store_validator_set(conn, validators_update: dict): - _validator = conn.run(conn.space("validator_sets").select(validators_update["height"], index="height", limit=1)) + _validator = conn.run(conn.space(TARANT_TABLE_VALIDATOR_SETS).select(validators_update["height"], index="height", limit=1)) unique_id = uuid4().hex if _validator is None or len(_validator) == 0 else _validator[0][0] try: conn.run( - conn.space("validator_sets").upsert( + conn.space(TARANT_TABLE_VALIDATOR_SETS).upsert( (unique_id, validators_update["height"], validators_update["validators"]), op_list=[("=", 1, validators_update["height"]), ("=", 2, validators_update["validators"])], limit=1, @@ -441,16 +445,16 @@ def store_validator_set(conn, validators_update: dict): @register_query(TarantoolDBConnection) def delete_validator_set(connection, height: int): - _validators = connection.run(connection.space("validator_sets").select(height, index="height")) + _validators = connection.run(connection.space(TARANT_TABLE_VALIDATOR_SETS).select(height, index="height")) for _valid in _validators: - connection.run(connection.space("validator_sets").delete(_valid[0]), only_data=False) + connection.run(connection.space(TARANT_TABLE_VALIDATOR_SETS).delete(_valid[0]), only_data=False) @register_query(TarantoolDBConnection) def store_election(connection, election_id: str, height: int, is_concluded: bool): try: connection.run( - connection.space("elections").upsert( + connection.space(TARANT_TABLE_ELECTIONS).upsert( (election_id, height, is_concluded), op_list=[("=", 1, height), ("=", 2, is_concluded)], limit=1 ), only_data=False, @@ -465,7 +469,7 @@ def store_elections(connection, elections: list): try: for election in elections: _election = connection.run( # noqa: F841 - connection.space("elections").insert( + connection.space(TARANT_TABLE_ELECTIONS).insert( (election["election_id"], election["height"], election["is_concluded"]) ), only_data=False, @@ -477,14 +481,14 @@ def store_elections(connection, elections: list): @register_query(TarantoolDBConnection) def delete_elections(connection, height: int): - _elections = connection.run(connection.space("elections").select(height, index="height")) + _elections = connection.run(connection.space(TARANT_TABLE_ELECTIONS).select(height, index="height")) for _elec in _elections: - connection.run(connection.space("elections").delete(_elec[0]), only_data=False) + connection.run(connection.space(TARANT_TABLE_ELECTIONS).delete(_elec[0]), only_data=False) @register_query(TarantoolDBConnection) def get_validator_set(connection, height: int = None): - _validators = connection.run(connection.space("validator_sets").select()) + _validators = connection.run(connection.space(TARANT_TABLE_VALIDATOR_SETS).select()) if height is not None and _validators is not None: _validators = [ {"height": validator[1], "validators": validator[2]} for validator in _validators if validator[1] <= height @@ -497,8 +501,8 @@ def get_validator_set(connection, height: int = None): @register_query(TarantoolDBConnection) -def get_election(connection, election_id: str): - _elections = connection.run(connection.space("elections").select(election_id, index=TARANT_ID_SEARCH)) +def get_election(connection, election_id: str) -> dict: + _elections = connection.run(connection.space(TARANT_TABLE_ELECTIONS).select(election_id, index=TARANT_ID_SEARCH)) if _elections is None or len(_elections) == 0: return None _election = sorted(_elections, key=itemgetter(0), reverse=True)[0] @@ -507,29 +511,19 @@ def get_election(connection, election_id: str): @register_query(TarantoolDBConnection) def get_asset_tokens_for_public_key(connection, asset_id: str, public_key: str) -> list[DbTransaction]: - # 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") - # _transactions = connection.run(connection.space(TARANT_TABLE_ASSETS).select([asset_id], index="assetid_search")) - # _transactions = _transactions - # _keys = _keys.data id_transactions = connection.run(connection.space(TARANT_TABLE_GOVERNANCE).select([asset_id])) asset_id_transactions = connection.run( connection.space(TARANT_TABLE_GOVERNANCE).select([asset_id], index="governance_by_asset_id") ) transactions = id_transactions + asset_id_transactions - - # TODO return transaction class - # return transactions - return get_complete_transactions_by_ids(connection, [_tx[0] for _tx in transactions], TARANT_TABLE_GOVERNANCE) - # return get_complete_transactions_by_ids(connection=connection, txids=[_tx[1] for _tx in transactions]) + return get_complete_transactions_by_ids(connection, [_tx[0] for _tx in transactions]) @register_query(TarantoolDBConnection) def store_abci_chain(connection, height: int, chain_id: str, is_synced: bool = True): try: connection.run( - connection.space("abci_chains").upsert( + connection.space(TARANT_TABLE_ABCI_CHAINS).upsert( (chain_id, height, is_synced), op_list=[("=", 0, chain_id), ("=", 1, height), ("=", 2, is_synced)], ), @@ -542,15 +536,13 @@ def store_abci_chain(connection, height: int, chain_id: str, is_synced: bool = T @register_query(TarantoolDBConnection) def delete_abci_chain(connection, height: int): - hash_id_primarykey = sha256(json.dumps(obj={"height": height}).encode()).hexdigest() - # connection.run(connection.space("abci_chains").delete(hash_id_primarykey), only_data=False) - chains = connection.run(connection.space("abci_chains").select(height, index="height"), only_data=False) - connection.run(connection.space("abci_chains").delete(chains[0][0], index="id"), only_data=False) + chains = connection.run(connection.space(TARANT_TABLE_ABCI_CHAINS).select(height, index="height"), only_data=False) + connection.run(connection.space(TARANT_TABLE_ABCI_CHAINS).delete(chains[0][0], index="id"), only_data=False) @register_query(TarantoolDBConnection) -def get_latest_abci_chain(connection): - _all_chains = connection.run(connection.space("abci_chains").select()) +def get_latest_abci_chain(connection) -> Union[dict, None]: + _all_chains = connection.run(connection.space(TARANT_TABLE_ABCI_CHAINS).select()) if _all_chains is None or len(_all_chains) == 0: return None _chain = sorted(_all_chains, key=itemgetter(1), reverse=True)[0] diff --git a/planetmint/commands/planetmint.py b/planetmint/commands/planetmint.py index c8b4a9c..bba0f7a 100644 --- a/planetmint/commands/planetmint.py +++ b/planetmint/commands/planetmint.py @@ -196,7 +196,7 @@ def run_election_approve(args, planet): """ key = load_node_key(args.sk) - tx = planet.get_transaction(args.election_id, TARANT_TABLE_GOVERNANCE) + 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] @@ -230,7 +230,7 @@ def run_election_show(args, planet): :param planet: an instance of Planetmint """ - election = planet.get_transaction(args.election_id, TARANT_TABLE_GOVERNANCE) + 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 ca8048b..956fd86 100644 --- a/planetmint/lib.py +++ b/planetmint/lib.py @@ -245,12 +245,12 @@ class Planetmint(object): if unspent_outputs: return backend.query.delete_unspent_outputs(self.connection, *unspent_outputs) - def is_committed(self, transaction_id, table=TARANT_TABLE_TRANSACTION): - transaction = backend.query.get_transaction_by_id(self.connection, transaction_id, table) + def is_committed(self, transaction_id): + transaction = backend.query.get_transaction_single(self.connection, transaction_id) return bool(transaction) - def get_transaction(self, transaction_id, table=TARANT_TABLE_TRANSACTION): - return backend.query.get_transaction_single(self.connection, transaction_id, table) + def get_transaction(self, 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) @@ -261,9 +261,6 @@ class Planetmint(object): for txid in txids: yield self.get_transaction(txid) - def get_governance_transaction(self, transaction_id): - return backend.query.get_governance_transaction_by_id(self.connection, transaction_id) - def get_outputs_by_tx_id(self, txid): return backend.query.get_outputs_by_tx_id(self.connection, txid) @@ -390,13 +387,9 @@ class Planetmint(object): input_txs = [] input_conditions = [] - table = TARANT_TABLE_TRANSACTION - if tx.operation in GOVERNANCE_TRANSACTION_TYPES: - table = TARANT_TABLE_GOVERNANCE - for input_ in tx.inputs: input_txid = input_.fulfills.txid - input_tx = self.get_transaction(input_txid, table) + input_tx = self.get_transaction(input_txid) _output = self.get_outputs_by_tx_id(input_txid) if input_tx is None: for ctxn in current_transactions: @@ -614,7 +607,7 @@ class Planetmint(object): """ duplicates = any(txn for txn in current_transactions if txn.id == transaction.id) - if self.is_committed(transaction.id, TARANT_TABLE_GOVERNANCE) or duplicates: + if self.is_committed(transaction.id) or duplicates: raise DuplicateTransaction("transaction `{}` already exists".format(transaction.id)) current_validators = self.get_validators_dict() @@ -823,7 +816,7 @@ class Planetmint(object): validator_update = None for election_id, votes in elections.items(): - election = self.get_transaction(election_id, TARANT_TABLE_GOVERNANCE) + election = self.get_transaction(election_id) if election is None: continue diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 2cfd9a8..fdab1d5 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -14,7 +14,6 @@ from planetmint import ValidatorElection from planetmint.commands.planetmint import run_election_show from planetmint.commands.planetmint import run_election_new_chain_migration from planetmint.backend.connection import Connection -from planetmint.backend.tarantool.const import TARANT_TABLE_GOVERNANCE from planetmint.lib import Block from transactions.types.elections.chain_migration_election import ChainMigrationElection @@ -323,7 +322,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, TARANT_TABLE_GOVERNANCE) + assert b.get_transaction(election_id) @pytest.mark.bdb @@ -350,7 +349,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, TARANT_TABLE_GOVERNANCE) + assert b.get_transaction(election_id) @pytest.mark.abci @@ -359,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, TARANT_TABLE_GOVERNANCE) + assert b.get_transaction(election_id) @pytest.mark.bdb @@ -376,7 +375,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, TARANT_TABLE_GOVERNANCE) + assert b.get_transaction(election_id) @pytest.mark.bdb @@ -445,7 +444,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, TARANT_TABLE_GOVERNANCE) + assert b.get_transaction(run_election_approve) @pytest.mark.bdb @@ -462,7 +461,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, TARANT_TABLE_GOVERNANCE) + assert b.get_transaction(approval_id) @pytest.mark.bdb diff --git a/tests/tendermint/test_core.py b/tests/tendermint/test_core.py index 93788d5..84d5fbd 100644 --- a/tests/tendermint/test_core.py +++ b/tests/tendermint/test_core.py @@ -411,7 +411,7 @@ def test_rollback_pre_commit_state_after_crash(b): rollback(b) for tx in txs: - assert b.get_transaction(tx.id, TARANT_TABLE_GOVERNANCE) + 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) @@ -422,7 +422,7 @@ def test_rollback_pre_commit_state_after_crash(b): rollback(b) for tx in txs: - assert not b.get_transaction(tx.id, TARANT_TABLE_GOVERNANCE) + 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