Add transaction data class

Signed-off-by: cybnon <stefan.weber93@googlemail.com>
This commit is contained in:
cybnon 2022-11-29 15:50:17 +01:00
parent b4eb882b1e
commit 2028eb449d
6 changed files with 93 additions and 115 deletions

View File

@ -24,12 +24,14 @@ class Keys:
@staticmethod @staticmethod
def from_tuple(output: tuple) -> Keys: def from_tuple(output: tuple) -> Keys:
return Keys( return Keys(
tx_id=output[0], tx_id=output[1],
public_keys=output[1], output_id=output[2],
public_keys=output[3],
) )
def to_output_dict(self) -> dict: def to_dict(self) -> dict:
return { return {
"tx_id": self.tx_id, "tx_id": self.tx_id,
"output_id": self.output_id,
"public_keys": self.public_keys, "public_keys": self.public_keys,
} }

View File

@ -55,13 +55,14 @@ class Output:
def from_tuple(output: tuple) -> Output: def from_tuple(output: tuple) -> Output:
return Output( return Output(
tx_id=output[0], tx_id=output[0],
amount=output[1],
condition=Condition( condition=Condition(
uri=output[1], uri=output[2],
details=ConditionDetails( details=ConditionDetails(
type=output[2], type=output[3],
public_key=output[3], public_key=output[4],
threshold=output[4], threshold=output[6],
sub_conditions=output[5], sub_conditions=output[7],
), ),
), ),
) )

View File

@ -0,0 +1,38 @@
# Copyright © 2020 Interplanetary Database Association e.V.,
# Planetmint and IPDB software contributors.
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# 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
@dataclass
class Transaction:
id: str = ""
operation: str = ""
version: str = ""
@staticmethod
def from_dict(transaction: dict) -> Transaction:
return Transaction(
id=transaction["id"],
operation=transaction["operation"],
version=transaction["version"],
)
@staticmethod
def from_tuple(transaction: tuple) -> Transaction:
return Transaction(
id=transaction[0],
operation=transaction[1],
version=transaction[2],
)
def to_dict(self) -> dict:
return {
"id": self.id,
"operation": self.operation,
"version": self.version,
}

View File

@ -7,7 +7,7 @@
from functools import singledispatch from functools import singledispatch
from planetmint.backend.exceptions import OperationError from planetmint.backend.exceptions import OperationError
from planetmint.backend.interfaces import Asset, Block, MetaData, Input, Script, Output from planetmint.backend.interfaces import Asset, Block, MetaData, Input, Script, Output, Transaction
from planetmint.backend.models.keys import Keys from planetmint.backend.models.keys import Keys
@ -59,27 +59,26 @@ def store_transactions(connection, signed_transactions):
raise NotImplementedError raise NotImplementedError
@singledispatch @singledispatch
def get_transaction(connection, transaction_id): def store_transaction(connection, transaction):
"""Get a transaction from the transactions table. """Store a single transaction."""
Args:
transaction_id (str): the id of the transaction.
Returns:
The result of the operation.
"""
raise NotImplementedError raise NotImplementedError
@singledispatch @singledispatch
def get_transactions(connection, transaction_ids): def get_transaction(conn, transaction_id):
"""Get transactions from the transactions table. """Get a transaction from the database."""
raise NotImplementedError
@singledispatch
def get_transactions(connection, transactions_ids) -> list[Transaction]:
"""Get a transaction from the transactions table.
Args: Args:
transaction_ids (list): list of transaction ids to fetch transaction_id (str): the id of the transaction.
Returns: Returns:
The result of the operation. The result of the operation.

View File

@ -11,13 +11,13 @@ from operator import itemgetter
from tarantool.error import DatabaseError from tarantool.error import DatabaseError
from planetmint.backend import query from planetmint.backend import query
from planetmint.backend.models.keys import Keys 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, \ 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_TABLE_TRANSACTION, TARANT_TABLE_INPUT, TARANT_TABLE_OUTPUT, TARANT_TABLE_SCRIPT, TARANT_TX_ID_SEARCH, \
TARANT_ID_SEARCH TARANT_ID_SEARCH
from planetmint.backend.utils import module_dispatch_registrar from planetmint.backend.utils import module_dispatch_registrar
from planetmint.backend.models import Asset, MetaData, Input, Script, Output from planetmint.backend.models import Asset, MetaData, Input, Script, Output
from planetmint.backend.tarantool.connection import TarantoolDBConnection from planetmint.backend.tarantool.connection import TarantoolDBConnection
from planetmint.backend.tarantool.transaction.tools import TransactionCompose, TransactionDecompose
register_query = module_dispatch_registrar(query) register_query = module_dispatch_registrar(query)
@ -26,10 +26,11 @@ register_query = module_dispatch_registrar(query)
def _group_transaction_by_ids(connection, txids: list): def _group_transaction_by_ids(connection, txids: list):
_transactions = [] _transactions = []
for txid in txids: for txid in txids:
_txobject = connection.run(connection.space(TARANT_TABLE_TRANSACTION).select(txid, index=TARANT_ID_SEARCH)) _txobject = connection.run(connection.space(TARANT_TABLE_TRANSACTION).get(txid, index=TARANT_ID_SEARCH))
if len(_txobject) == 0:
if _txobject is None:
continue continue
_txobject = _txobject[0]
_txinputs = get_inputs_by_tx_id(connection, txid) _txinputs = get_inputs_by_tx_id(connection, txid)
_txoutputs = get_outputs_by_tx_id(connection, txid) _txoutputs = get_outputs_by_tx_id(connection, txid)
_txkeys = get_keys_by_tx_id(connection, txid) _txkeys = get_keys_by_tx_id(connection, txid)
@ -37,17 +38,14 @@ def _group_transaction_by_ids(connection, txids: list):
_txmeta = get_metadata_by_tx_id(connection, txid) _txmeta = get_metadata_by_tx_id(connection, txid)
_txscript = get_script_by_tx_id(connection, txid) _txscript = get_script_by_tx_id(connection, txid)
_txoutputs = sorted(_txoutputs, key=itemgetter(8), reverse=False) _transaction = get_transaction(connection, txid)
result_map = { _transaction[TARANT_TABLE_TRANSACTION] = [tx.to_dict for tx in _transactions]
TARANT_TABLE_TRANSACTION: _txobject, _transaction[TARANT_TABLE_INPUT] + [input.to_input_dict() for input in _txinputs]
TARANT_TABLE_OUTPUT: _txoutputs, _transaction[TARANT_TABLE_OUTPUT] = [output.to_output_dict() for output in _txoutputs]
TARANT_TABLE_KEYS: _txkeys, _transaction[TARANT_TABLE_KEYS] = [key.to_dict() for key in _txkeys]
}
tx_compose = TransactionCompose(db_results=result_map)
_transaction = tx_compose.convert_to_dict()
_transaction[TARANT_TABLE_INPUT] = [input.to_input_dict() for input in _txinputs]
_transaction["assets"] = [asset.data for asset in _txassets] _transaction["assets"] = [asset.data for asset in _txassets]
_transaction["metadata"] = _txmeta.metadata _transaction["metadata"] = _txmeta.metadata
if _txscript.script: if _txscript.script:
_transaction[TARANT_TABLE_SCRIPT] = _txscript.script _transaction[TARANT_TABLE_SCRIPT] = _txscript.script
_transactions.append(_transaction) _transactions.append(_transaction)
@ -64,14 +62,14 @@ def get_inputs_by_tx_id(connection, tx_id: str) -> list[Input]:
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_outputs_by_tx_id(connection, tx_id: str) -> list[Output]: def get_outputs_by_tx_id(connection, tx_id: str) -> list[Output]:
_outputs = connection.run(connection.space(TARANT_TABLE_OUTPUT).select(tx_id, index=TARANT_ID_SEARCH)) _outputs = connection.run(connection.space(TARANT_TABLE_OUTPUT).select(tx_id, index=TARANT_ID_SEARCH))
_sorted_inputs = sorted(_outputs, key=itemgetter(6)) _sorted_outputs = sorted(_outputs, key=itemgetter(8))
return [Output.from_tuple(output) for output in _sorted_inputs] return [Output.from_tuple(output) for output in _sorted_outputs]
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_keys_by_tx_id(connection, tx_id: str) -> list[Keys]: def get_keys_by_tx_id(connection, tx_id: str) -> list[Keys]:
_keys = connection.run(connection.space(TARANT_TABLE_KEYS).select(tx_id, index=TARANT_ID_SEARCH)) _keys = connection.run(connection.space(TARANT_TABLE_KEYS).select(tx_id, index=TARANT_TX_ID_SEARCH))
_sorted_keys = sorted(_keys, key=itemgetter(6)) _sorted_keys = sorted(_keys, key=itemgetter(4))
return [Keys.from_tuple(key) for key in _sorted_keys] return [Keys.from_tuple(key) for key in _sorted_keys]
@ -166,15 +164,26 @@ def store_transactions(connection, signed_transactions: list):
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_transaction(connection, transaction_id: str): def store_transaction(connection, transaction):
_transactions = _group_transaction_by_ids(txids=[transaction_id], connection=connection) tx = Transaction(id=transaction["id"], operation=transaction["operation"], version=transaction["version"])
return next(iter(_transactions), None) connection.run(connection.space(TARANT_TABLE_TRANSACTION).insert(
tx.id,
tx.operation,
tx.version,
),
only_data=False)
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_transactions(connection, transactions_ids: list): 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)))
@register_query(TarantoolDBConnection)
def get_transactions(connection, transactions_ids: list) -> list[Transaction]:
_transactions = _group_transaction_by_ids(txids=transactions_ids, connection=connection) _transactions = _group_transaction_by_ids(txids=transactions_ids, connection=connection)
return _transactions return [Transaction.from_tuple(_transaction) for _transaction in _transactions]
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)

View File

@ -1,7 +1,3 @@
import copy
import json
from secrets import token_hex
from transactions.common.memoize import HDict from transactions.common.memoize import HDict
from planetmint.backend.tarantool.const import TARANT_TABLE_META_DATA, TARANT_TABLE_ASSETS, TARANT_TABLE_KEYS, \ from planetmint.backend.tarantool.const import TARANT_TABLE_META_DATA, TARANT_TABLE_ASSETS, TARANT_TABLE_KEYS, \
@ -55,58 +51,12 @@ class TransactionDecompose:
else _save_keys_order(dictionary=self._transaction) else _save_keys_order(dictionary=self._transaction)
) )
def __create_hash(self, n: int):
return token_hex(n)
def __prepare_outputs(self):
_outputs = []
_keys = []
output_index = 0
for _output in self._transaction[TARANT_TABLE_OUTPUT]:
output_id = self.__create_hash(7)
if _output["condition"]["details"].get("subconditions") is None:
tmp_output = (
self._transaction["id"],
_output["amount"],
_output["condition"]["uri"],
_output["condition"]["details"]["type"],
_output["condition"]["details"]["public_key"],
output_id,
None,
None,
output_index,
)
else:
tmp_output = (
self._transaction["id"],
_output["amount"],
_output["condition"]["uri"],
_output["condition"]["details"]["type"],
None,
output_id,
_output["condition"]["details"]["threshold"],
_output["condition"]["details"]["subconditions"],
output_index,
)
_outputs.append(tmp_output)
output_index = output_index + 1
key_index = 0
for _key in _output["public_keys"]:
key_id = self.__create_hash(7)
_keys.append((key_id, self._transaction["id"], output_id, _key, key_index))
key_index = key_index + 1
return _keys, _outputs
def __prepare_transaction(self): def __prepare_transaction(self):
_map = self.get_map() _map = self.get_map()
return (self._transaction["id"], self._transaction["operation"], self._transaction["version"], _map) return (self._transaction["id"], self._transaction["operation"], self._transaction["version"], _map)
def convert_to_tuple(self): def convert_to_tuple(self):
self._tuple_transaction[TARANT_TABLE_TRANSACTION] = self.__prepare_transaction() self._tuple_transaction[TARANT_TABLE_TRANSACTION] = self.__prepare_transaction()
keys, outputs = self.__prepare_outputs()
self._tuple_transaction[TARANT_TABLE_OUTPUT] = outputs
self._tuple_transaction[TARANT_TABLE_KEYS] = keys
return self._tuple_transaction return self._tuple_transaction
@ -124,30 +74,9 @@ class TransactionCompose:
def _get_transaction_id(self): def _get_transaction_id(self):
return self.db_results[TARANT_TABLE_TRANSACTION][0] return self.db_results[TARANT_TABLE_TRANSACTION][0]
def _get_outputs(self):
_outputs = []
for _output in self.db_results[TARANT_TABLE_OUTPUT]:
_out = copy.deepcopy(self._map[TARANT_TABLE_OUTPUT][_output[-1]])
_out["amount"] = _output[1]
_tmp_keys = [(_key[3], _key[4]) for _key in self.db_results[TARANT_TABLE_KEYS] if _key[2] == _output[5]]
_sorted_keys = sorted(_tmp_keys, key=lambda tup: (tup[1]))
_out["public_keys"] = [_key[0] for _key in _sorted_keys]
_out["condition"]["uri"] = _output[2]
if _output[7] is None:
_out["condition"]["details"]["type"] = _output[3]
_out["condition"]["details"]["public_key"] = _output[4]
else:
_out["condition"]["details"]["subconditions"] = _output[7]
_out["condition"]["details"]["type"] = _output[3]
_out["condition"]["details"]["threshold"] = _output[6]
_outputs.append(_out)
return _outputs
def convert_to_dict(self): def convert_to_dict(self):
transaction = {k: None for k in list(self._map.keys())} transaction = {k: None for k in list(self._map.keys())}
transaction["id"] = self._get_transaction_id() transaction["id"] = self._get_transaction_id()
transaction["version"] = self._get_transaction_version() transaction["version"] = self._get_transaction_version()
transaction["operation"] = self._get_transaction_operation() transaction["operation"] = self._get_transaction_operation()
transaction[TARANT_TABLE_OUTPUT] = self._get_outputs()
return transaction return transaction