- blackified & fixed recovery / delete transactions issues becaues of data model transitions

- reintegrated get_transaction() call in query -> delegating this to get_complete_transactions_by_ids

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>
This commit is contained in:
Jürgen Eckel 2023-01-09 13:39:15 +01:00
parent 869406d30d
commit 51ae9874d6
No known key found for this signature in database
20 changed files with 94 additions and 95 deletions

View File

@ -17,9 +17,7 @@ class Asset:
return Asset(asset_dict["data"]) if "data" in asset_dict.keys() else Asset(asset_dict["id"]) return Asset(asset_dict["data"]) if "data" in asset_dict.keys() else Asset(asset_dict["id"])
def to_dict(self) -> dict: def to_dict(self) -> dict:
return { return {"data": self.data}
"data": self.data
}
@staticmethod @staticmethod
def from_list_dict(asset_dict_list: list[dict]) -> list[Asset]: def from_list_dict(asset_dict_list: list[dict]) -> list[Asset]:

View File

@ -20,8 +20,4 @@ class Block:
return Block(block_tuple[0], block_tuple[1], block_tuple[2], block_tuple[3]) return Block(block_tuple[0], block_tuple[1], block_tuple[2], block_tuple[3])
def to_dict(self) -> dict: def to_dict(self) -> dict:
return { return {"app_hash": self.app_hash, "height": self.height, "transactions": self.transactions}
"app_hash": self.app_hash,
"height": self.height,
"transactions": self.transactions
}

View File

@ -12,7 +12,4 @@ class Fulfills:
output_index: int = 0 output_index: int = 0
def to_dict(self) -> dict: def to_dict(self) -> dict:
return { return {"transaction_id": self.transaction_id, "output_index": self.output_index}
"transaction_id": self.transaction_id,
"output_index": self.output_index
}

View File

@ -56,5 +56,3 @@ class Input:
@staticmethod @staticmethod
def list_to_dict(input_list: list[Input]) -> list[dict]: def list_to_dict(input_list: list[Input]) -> list[dict]:
return [input.to_dict() for input in input_list or []] return [input.to_dict() for input in input_list or []]

View File

@ -20,6 +20,4 @@ class MetaData:
return MetaData(meta_data) return MetaData(meta_data)
def to_dict(self) -> dict: def to_dict(self) -> dict:
return { return {"metadata": self.metadata}
"metadata": self.metadata
}

View File

@ -17,10 +17,7 @@ class SubCondition:
return self.type, self.public_key return self.type, self.public_key
def to_dict(self) -> dict: def to_dict(self) -> dict:
return { return {"type": self.type, "public_key": self.public_key}
"type": self.type,
"public_key": self.public_key
}
@staticmethod @staticmethod
def from_dict(subcondition_dict: dict) -> SubCondition: def from_dict(subcondition_dict: dict) -> SubCondition:
@ -32,6 +29,7 @@ class SubCondition:
return None return None
return [subcondition.to_dict() for subcondition in subconditions] return [subcondition.to_dict() for subcondition in subconditions]
@dataclass @dataclass
class ConditionDetails: class ConditionDetails:
type: str = "" type: str = ""
@ -64,12 +62,12 @@ class ConditionDetails:
sub_conditions=sub_conditions, sub_conditions=sub_conditions,
) )
@dataclass @dataclass
class Condition: class Condition:
uri: str = "" uri: str = ""
details: ConditionDetails = field(default_factory=ConditionDetails) details: ConditionDetails = field(default_factory=ConditionDetails)
@staticmethod @staticmethod
def from_dict(data: dict) -> Condition: def from_dict(data: dict) -> Condition:
return Condition( return Condition(
@ -131,7 +129,6 @@ class Output:
"amount": str(self.amount), "amount": str(self.amount),
} }
@staticmethod @staticmethod
def list_to_dict(output_list: list[Output]) -> list[dict]: def list_to_dict(output_list: list[Output]) -> list[dict]:
return [output.to_dict() for output in output_list or []] return [output.to_dict() for output in output_list or []]

View File

@ -19,6 +19,4 @@ class Script:
return Script(script_dict["script"]) return Script(script_dict["script"])
def to_dict(self) -> dict: def to_dict(self) -> dict:
return { return {"script": self.script}
"script": self.script
}

View File

@ -69,24 +69,28 @@ def store_transaction(connection, transaction):
raise NotImplementedError raise NotImplementedError
@singledispatch @singledispatch
def store_governance_transactions(connection, transactions): def store_governance_transactions(connection, transactions):
"""Store the list of governance transactions.""" """Store the list of governance transactions."""
raise NotImplementedError raise NotImplementedError
@singledispatch @singledispatch
def store_governance_transaction(connection, transaction): def store_governance_transaction(connection, transaction):
"""Store a single governance transaction.""" """Store a single governance transaction."""
raise NotImplementedError raise NotImplementedError
@singledispatch @singledispatch
def get_governance_transaction_by_id(connection, transaction_id): def get_governance_transaction_by_id(connection, transaction_id):
"""Get the transaction by transaction id.""" """Get the transaction by transaction id."""
raise NotImplementedError raise NotImplementedError
@singledispatch @singledispatch
def get_transaction_by_id(connection, transaction_id): def get_transaction_by_id(connection, transaction_id):
"""Get the transaction by transaction id.""" """Get the transaction by transaction id."""
@ -107,18 +111,21 @@ def get_transaction(connection, transaction_id):
raise NotImplementedError raise NotImplementedError
@singledispatch @singledispatch
def get_transactions_by_asset(connection, asset): def get_transactions_by_asset(connection, asset):
"""Get a transaction by id.""" """Get a transaction by id."""
raise NotImplementedError raise NotImplementedError
@singledispatch @singledispatch
def get_transactions_by_metadata(connection, metadata: str, limit: int = 1000) -> list[DbTransaction]: def get_transactions_by_metadata(connection, metadata: str, limit: int = 1000) -> list[DbTransaction]:
"""Get a transaction by its metadata cid.""" """Get a transaction by its metadata cid."""
raise NotImplementedError raise NotImplementedError
@singledispatch @singledispatch
def get_transactions(connection, transactions_ids) -> list[DbTransaction]: def get_transactions(connection, transactions_ids) -> list[DbTransaction]:
"""Get a transaction from the transactions table. """Get a transaction from the transactions table.

View File

@ -118,6 +118,7 @@ def drop_database(connection, dbname):
raise NotImplementedError raise NotImplementedError
@singledispatch @singledispatch
def init_database(connection, dbname): def init_database(connection, dbname):
"""Initialize the configured backend for use with Planetmint. """Initialize the configured backend for use with Planetmint.

View File

@ -38,7 +38,7 @@ class TarantoolDBConnection(DBConnection):
"pre_commits", "pre_commits",
"validator_sets", "validator_sets",
"transactions", "transactions",
"outputs" "outputs",
] ]
except tarantool.error.NetworkError as network_err: except tarantool.error.NetworkError as network_err:
logger.info("Host cant be reached") logger.info("Host cant be reached")
@ -95,12 +95,12 @@ class TarantoolDBConnection(DBConnection):
raise net_error raise net_error
def drop_database(self): def drop_database(self):
self.connect().call('drop') self.connect().call("drop")
# db_config = Config().get()["database"] # db_config = Config().get()["database"]
# cmd_resp = self.run_command(command=self.drop_path, config=db_config) # noqa: F841 # cmd_resp = self.run_command(command=self.drop_path, config=db_config) # noqa: F841
def init_database(self): def init_database(self):
self.connect().call('init') self.connect().call("init")
# db_config = Config().get()["database"] # db_config = Config().get()["database"]
# cmd_resp = self.run_command(command=self.init_path, config=db_config) # noqa: F841 # cmd_resp = self.run_command(command=self.init_path, config=db_config) # noqa: F841

View File

@ -21,7 +21,9 @@ from planetmint.backend.tarantool.const import (
TARANT_TABLE_OUTPUT, TARANT_TABLE_OUTPUT,
TARANT_TABLE_SCRIPT, TARANT_TABLE_SCRIPT,
TARANT_TX_ID_SEARCH, TARANT_TX_ID_SEARCH,
TARANT_ID_SEARCH, TARANT_INDEX_TX_BY_ASSET_ID, TARANT_INDEX_SPENDING_BY_ID_AND_OUTPUT_INDEX, TARANT_ID_SEARCH,
TARANT_INDEX_TX_BY_ASSET_ID,
TARANT_INDEX_SPENDING_BY_ID_AND_OUTPUT_INDEX,
TARANT_TABLE_GOVERNANCE, TARANT_TABLE_GOVERNANCE,
) )
from planetmint.backend.utils import module_dispatch_registrar from planetmint.backend.utils import module_dispatch_registrar
@ -53,7 +55,12 @@ def get_outputs_by_tx_id(connection, tx_id: str) -> list[Output]:
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_transaction(connection, tx_id: str) -> DbTransaction: def get_transaction(connection, tx_id: str) -> DbTransaction:
return NotImplemented transactions = get_complete_transactions_by_ids(connection, (tx_id))
if len(transactions) > 1 or len(transactions) == 0:
return None
else:
return transactions[0]
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_transactions_by_asset(connection, asset: str, limit: int = 1000) -> list[DbTransaction]: def get_transactions_by_asset(connection, asset: str, limit: int = 1000) -> list[DbTransaction]:
@ -72,16 +79,21 @@ def get_transactions_by_metadata(connection, metadata: str, limit: int = 1000) -
tx_ids = [tx[0] for tx in txs] tx_ids = [tx[0] for tx in txs]
return get_complete_transactions_by_ids(connection, tx_ids) return get_complete_transactions_by_ids(connection, tx_ids)
def store_transaction_outputs(connection, output: Output, index: int) -> str: def store_transaction_outputs(connection, output: Output, index: int) -> str:
output_id = uuid4().hex output_id = uuid4().hex
connection.run(connection.space(TARANT_TABLE_OUTPUT).insert(( connection.run(
connection.space(TARANT_TABLE_OUTPUT).insert(
(
output_id, output_id,
int(output.amount), int(output.amount),
output.public_keys, output.public_keys,
output.condition.to_dict(), output.condition.to_dict(),
index, index,
output.transaction_id, output.transaction_id,
))) )
)
)
return output_id return output_id
@ -107,9 +119,11 @@ def store_transaction(connection, transaction):
transaction["metadata"], transaction["metadata"],
transaction["assets"], transaction["assets"],
transaction["inputs"], transaction["inputs"],
scripts) scripts,
)
connection.run(connection.space(TARANT_TABLE_TRANSACTION).insert(tx), only_data=False) connection.run(connection.space(TARANT_TABLE_TRANSACTION).insert(tx), only_data=False)
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def store_governance_transactions(connection, signed_transactions: list): def store_governance_transactions(connection, signed_transactions: list):
for transaction in signed_transactions: for transaction in signed_transactions:
@ -119,6 +133,7 @@ def store_governance_transactions(connection, signed_transactions: list):
for index, output in enumerate(transaction[TARANT_TABLE_OUTPUT]) for index, output in enumerate(transaction[TARANT_TABLE_OUTPUT])
] ]
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def store_governance_transaction(connection, transaction): def store_governance_transaction(connection, transaction):
scripts = None scripts = None
@ -131,9 +146,11 @@ def store_governance_transaction(connection, transaction):
transaction["metadata"], transaction["metadata"],
transaction["assets"], transaction["assets"],
transaction["inputs"], transaction["inputs"],
scripts) scripts,
)
connection.run(connection.space(TARANT_TABLE_GOVERNANCE).insert(tx), only_data=False) connection.run(connection.space(TARANT_TABLE_GOVERNANCE).insert(tx), only_data=False)
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_governance_transaction_by_id(connection, transaction_id): def get_governance_transaction_by_id(connection, transaction_id):
txs = connection.run(connection.space(TARANT_TABLE_GOVERNANCE).select(transaction_id, index=TARANT_ID_SEARCH)) txs = connection.run(connection.space(TARANT_TABLE_GOVERNANCE).select(transaction_id, index=TARANT_ID_SEARCH))
@ -141,6 +158,7 @@ def get_governance_transaction_by_id(connection, transaction_id):
return None return None
return DbTransaction.from_tuple(txs[0]) return DbTransaction.from_tuple(txs[0])
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_transaction_by_id(connection, transaction_id, table=TARANT_TABLE_TRANSACTION): def get_transaction_by_id(connection, transaction_id, table=TARANT_TABLE_TRANSACTION):
txs = connection.run(connection.space(table).select(transaction_id, index=TARANT_ID_SEARCH)) txs = connection.run(connection.space(table).select(transaction_id, index=TARANT_ID_SEARCH))
@ -162,9 +180,12 @@ def get_transactions(connection, transactions_ids: list) -> list[DbTransaction]:
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_asset(connection, asset_id: str) -> Asset: def get_asset(connection, asset_id: str) -> Asset:
_data = connection.run(connection.space(TARANT_TABLE_TRANSACTION).select(asset_id, index=TARANT_INDEX_TX_BY_ASSET_ID)) _data = connection.run(
connection.space(TARANT_TABLE_TRANSACTION).select(asset_id, index=TARANT_INDEX_TX_BY_ASSET_ID)
)
return Asset.from_dict(_data[0]) return Asset.from_dict(_data[0])
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_assets(connection, assets_ids: list) -> list[Asset]: def get_assets(connection, assets_ids: list) -> list[Asset]:
_returned_data = [] _returned_data = []
@ -203,7 +224,10 @@ def get_latest_block(connection):
def store_block(connection, block: dict): def store_block(connection, block: dict):
block_unique_id = uuid4().hex block_unique_id = uuid4().hex
connection.run( connection.run(
connection.space("blocks").insert((block_unique_id, block["app_hash"], block["height"], block[TARANT_TABLE_TRANSACTION])), only_data=False connection.space("blocks").insert(
(block_unique_id, block["app_hash"], block["height"], block[TARANT_TABLE_TRANSACTION])
),
only_data=False,
) )
@ -212,7 +236,9 @@ def get_txids_filtered(connection, asset_ids: list[str], operation: str = "", la
transactions = [] transactions = []
if operation == "CREATE": if operation == "CREATE":
transactions = connection.run( transactions = connection.run(
connection.space(TARANT_TABLE_TRANSACTION).select([asset_ids[0], operation], index="transactions_by_id_and_operation") connection.space(TARANT_TABLE_TRANSACTION).select(
[asset_ids[0], operation], index="transactions_by_id_and_operation"
)
) )
elif operation == "TRANSFER": elif operation == "TRANSFER":
transactions = connection.run( transactions = connection.run(
@ -295,34 +321,14 @@ def delete_transactions(connection, txn_ids: list):
for _id in txn_ids: for _id in txn_ids:
connection.run(connection.space(TARANT_TABLE_TRANSACTION).delete(_id), only_data=False) connection.run(connection.space(TARANT_TABLE_TRANSACTION).delete(_id), only_data=False)
for _id in txn_ids: 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( _outputs = connection.run(
connection.space(TARANT_TABLE_OUTPUT).select(_id, index=TARANT_ID_SEARCH), only_data=False 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
)
for _inpID in _inputs:
connection.run(
connection.space(TARANT_TABLE_INPUT).delete(_inpID[5], index="delete_search"), only_data=False
)
for _outpID in _outputs: for _outpID in _outputs:
connection.run( connection.run(
connection.space(TARANT_TABLE_OUTPUT).delete(_outpID[5], index="unique_search"), only_data=False 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)
for _id in txn_ids:
connection.run(connection.space(TARANT_TABLE_ASSETS).delete(_id, index=TARANT_TX_ID_SEARCH), only_data=False)
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def store_unspent_outputs(connection, *unspent_outputs: list): def store_unspent_outputs(connection, *unspent_outputs: list):
@ -342,8 +348,9 @@ def delete_unspent_outputs(connection, *unspent_outputs: list):
if unspent_outputs: if unspent_outputs:
for utxo in unspent_outputs: for utxo in unspent_outputs:
output = connection.run( output = connection.run(
connection.space("utxos") connection.space("utxos").delete(
.delete((utxo["transaction_id"], utxo["output_index"]), index="utxo_by_transaction_id_and_output_index") (utxo["transaction_id"], utxo["output_index"]), index="utxo_by_transaction_id_and_output_index"
)
) )
result.append(output) result.append(output)
return result return result
@ -461,7 +468,9 @@ def get_asset_tokens_for_public_key(connection, asset_id: str, public_key: str)
# _transactions = _transactions # _transactions = _transactions
# _keys = _keys.data # _keys = _keys.data
id_transactions = connection.run(connection.space(TARANT_TABLE_GOVERNANCE).select([asset_id])) 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")) asset_id_transactions = connection.run(
connection.space(TARANT_TABLE_GOVERNANCE).select([asset_id], index="governance_by_asset_id")
)
transactions = id_transactions + asset_id_transactions transactions = id_transactions + asset_id_transactions
# TODO return transaction class # TODO return transaction class

View File

@ -144,15 +144,18 @@ SCHEMA_DROP_COMMANDS = {
"scripts": "box.space.scripts:drop()", "scripts": "box.space.scripts:drop()",
} }
@register_schema(TarantoolDBConnection) @register_schema(TarantoolDBConnection)
def init_database(connection, db_name=None): def init_database(connection, db_name=None):
print('init database tarantool schema') print("init database tarantool schema")
connection.connect().call('init') connection.connect().call("init")
@register_schema(TarantoolDBConnection) @register_schema(TarantoolDBConnection)
def drop_database(connection, db_name=None): def drop_database(connection, db_name=None):
print('drop database tarantool schema') print("drop database tarantool schema")
connection.connect().call('drop') connection.connect().call("drop")
@register_schema(TarantoolDBConnection) @register_schema(TarantoolDBConnection)
def create_database(connection, dbname): def create_database(connection, dbname):
@ -180,4 +183,4 @@ def run_command_with_output(command):
@register_schema(TarantoolDBConnection) @register_schema(TarantoolDBConnection)
def create_tables(connection, dbname): def create_tables(connection, dbname):
connection.connect().call('init') connection.connect().call("init")

View File

@ -7,8 +7,4 @@ CHAIN_MIGRATION_ELECTION = "CHAIN_MIGRATION_ELECTION"
VALIDATOR_ELECTION = "VALIDATOR_ELECTION" VALIDATOR_ELECTION = "VALIDATOR_ELECTION"
VOTE = "VOTE" VOTE = "VOTE"
GOVERNANCE_TRANSACTION_TYPES = [ GOVERNANCE_TRANSACTION_TYPES = [CHAIN_MIGRATION_ELECTION, VALIDATOR_ELECTION, VOTE]
CHAIN_MIGRATION_ELECTION,
VALIDATOR_ELECTION,
VOTE
]

View File

@ -203,7 +203,7 @@ class App(BaseApplication):
block_txn_hash = calculate_hash(self.block_txn_ids) block_txn_hash = calculate_hash(self.block_txn_ids)
block = self.planetmint_node.get_latest_block() block = self.planetmint_node.get_latest_block()
logger.debug('BLOCK: ', block) logger.debug("BLOCK: ", block)
if self.block_txn_ids: if self.block_txn_ids:
self.block_txn_hash = calculate_hash([block["app_hash"], block_txn_hash]) self.block_txn_hash = calculate_hash([block["app_hash"], block_txn_hash])

View File

@ -468,7 +468,6 @@ class Planetmint(object):
# flatten and return all found assets # flatten and return all found assets
return list(chain.from_iterable([Asset.list_to_dict(tx.assets) for tx in asset_txs])) return list(chain.from_iterable([Asset.list_to_dict(tx.assets) for tx in asset_txs]))
def get_metadata(self, txn_ids) -> list[MetaData]: def get_metadata(self, txn_ids) -> list[MetaData]:
"""Return a list of metadata that match the transaction ids (txn_ids) """Return a list of metadata that match the transaction ids (txn_ids)

View File

@ -5,6 +5,7 @@
from planetmint.backend.tarantool.connection import TarantoolDBConnection from planetmint.backend.tarantool.connection import TarantoolDBConnection
def _check_spaces_by_list(conn, space_names): def _check_spaces_by_list(conn, space_names):
_exists = [] _exists = []
for name in space_names: for name in space_names:

View File

@ -305,7 +305,8 @@ def test_store_one_unspent_output(b, unspent_output_1, utxo_collection):
else: else:
utx_space = b.connection.get_space("utxos") utx_space = b.connection.get_space("utxos")
res = utx_space.select( res = utx_space.select(
[unspent_output_1["transaction_id"], unspent_output_1["output_index"]], index="utxo_by_transaction_id_and_output_index" [unspent_output_1["transaction_id"], unspent_output_1["output_index"]],
index="utxo_by_transaction_id_and_output_index",
) )
assert len(res.data) == 1 assert len(res.data) == 1

View File

@ -32,8 +32,8 @@ def flush_localmongo_db(connection, dbname):
@flush_db.register(TarantoolDBConnection) @flush_db.register(TarantoolDBConnection)
def flush_tarantool_db(connection, dbname): def flush_tarantool_db(connection, dbname):
connection.connect().call('drop') connection.connect().call("drop")
connection.connect().call('init') connection.connect().call("init")
def generate_block(planet): def generate_block(planet):