mirror of
https://github.com/planetmint/planetmint.git
synced 2025-11-27 07:48:26 +00:00
Transaction Compose/Decompose for tarantool usages, move to backend.tarantool folder
This commit is contained in:
parent
7442ebe5be
commit
43fe80818b
@ -1,45 +0,0 @@
|
||||
import tarantool
|
||||
import os
|
||||
from planetmint.backend.tarantool.utils import run
|
||||
|
||||
|
||||
def init_tarantool():
|
||||
if os.path.exists(os.path.join(os.getcwd(), 'tarantool', 'init.lua')) is not True:
|
||||
path = os.getcwd()
|
||||
run(["mkdir", "tarantool_snap"])
|
||||
run(["ln", "-s", path + "/init.lua", "init.lua"], path + "/tarantool_snap")
|
||||
run(["tarantool", "init.lua"], path + "/tarantool")
|
||||
else:
|
||||
raise Exception("There is a instance of tarantool already created in %s" + os.getcwd() + "/tarantool_snap")
|
||||
|
||||
|
||||
def drop_tarantool():
|
||||
if os.path.exists(os.path.join(os.getcwd(), 'tarantool', 'init.lua')) is not True:
|
||||
path = os.getcwd()
|
||||
run(["ln", "-s", path + "/drop_db.lua", "drop_db.lua"], path + "/tarantool_snap")
|
||||
run(["tarantool", "drop_db.lua"])
|
||||
else:
|
||||
raise Exception("There is no tarantool spaces to drop")
|
||||
|
||||
|
||||
class TarantoolDB:
|
||||
def __init__(self, host: str, port: int, username: str, password: str):
|
||||
self.db_connect = tarantool.connect(host=host, port=port, user=username, password=password)
|
||||
self._spaces = {
|
||||
"abci_chains": self.db_connect.space("abci_chains"),
|
||||
"assets": self.db_connect.space("assets"),
|
||||
"blocks": {"blocks": self.db_connect.space("blocks"), "blocks_tx": self.db_connect.space("blocks_tx")},
|
||||
"elections": self.db_connect.space("elections"),
|
||||
"meta_data": self.db_connect.space("meta_data"),
|
||||
"pre_commits": self.db_connect.space("pre_commits"),
|
||||
"validators": self.db_connect.space("validators"),
|
||||
"transactions": {
|
||||
"transactions": self.db_connect.space("transactions"),
|
||||
"inputs": self.db_connect.space("inputs"),
|
||||
"outputs": self.db_connect.space("outputs"),
|
||||
"keys": self.db_connect.space("keys")
|
||||
}
|
||||
}
|
||||
|
||||
def get_space(self, spacename: str):
|
||||
return self._spaces[spacename]
|
||||
@ -11,7 +11,7 @@ from operator import itemgetter
|
||||
from planetmint.backend import query
|
||||
from planetmint.backend.utils import module_dispatch_registrar
|
||||
from planetmint.backend.tarantool.connection import TarantoolDB
|
||||
from planetmint.common.transaction import TransactionPrepare
|
||||
from planetmint.backend.tarantool.transaction.tools import TransactionCompose, TransactionDecompose
|
||||
|
||||
register_query = module_dispatch_registrar(query)
|
||||
|
||||
@ -38,15 +38,25 @@ def _group_transaction_by_ids(connection, txids: list):
|
||||
|
||||
_txinputs = sorted(_txinputs, key=itemgetter(6), reverse=False)
|
||||
_txoutputs = sorted(_txoutputs, key=itemgetter(8), reverse=False)
|
||||
result_map = {
|
||||
"transaction": _txobject,
|
||||
"inputs": _txinputs,
|
||||
"outputs": _txoutputs,
|
||||
"keys": _txkeys,
|
||||
"assets": _txassets,
|
||||
"metadata": _txmeta,
|
||||
}
|
||||
tx_compose = TransactionCompose()
|
||||
_transaction = tx_compose.convert_to_dict(db_results=result_map)
|
||||
|
||||
_obj = {
|
||||
"inputs": [
|
||||
{
|
||||
"owners_before": _in[2],
|
||||
"fulfillment": _in[1],
|
||||
"fulfills": {"transaction_id": _in[3], "output_index": int(_in[4])} if len(_in[3]) > 0 and len(
|
||||
# TODO Now it is working because of data type cast to INTEGER for field "output_index"
|
||||
_in[4]) > 0 else None,
|
||||
"fulfillment": _in[1]
|
||||
"owners_before": _in[2]
|
||||
} for _in in _txinputs
|
||||
],
|
||||
"outputs": [],
|
||||
@ -59,18 +69,18 @@ def _group_transaction_by_ids(connection, txids: list):
|
||||
if _txoutputs[0][7] is None:
|
||||
_obj["outputs"] = [
|
||||
{
|
||||
"public_keys": [_key[3] for _key in _txkeys if _key[2] == _out[5]],
|
||||
"amount": _out[1],
|
||||
"condition": {"details": {"type": _out[3], "public_key": _out[4]}, "uri": _out[2]},
|
||||
"amount": _out[1]
|
||||
"public_keys": [_key[3] for _key in _txkeys if _key[2] == _out[5]]
|
||||
} for _out in _txoutputs
|
||||
]
|
||||
else:
|
||||
_obj["outputs"] = [
|
||||
{
|
||||
"public_keys": [_key[3] for _key in _txkeys if _key[2] == _out[5]],
|
||||
"amount": _out[1],
|
||||
"condition": {"uri": _out[2], "details": {"subconditions": _out[7]}, "type": _out[3],
|
||||
"treshold": _out[6]}
|
||||
"treshold": _out[6]},
|
||||
"public_keys": [_key[3] for _key in _txkeys if _key[2] == _out[5]]
|
||||
} for _out in _txoutputs
|
||||
]
|
||||
|
||||
@ -78,10 +88,8 @@ def _group_transaction_by_ids(connection, txids: list):
|
||||
_obj["asset"] = {
|
||||
"id": _txobject[3]
|
||||
}
|
||||
elif len(_txassets) == 1:
|
||||
_obj["asset"] = {
|
||||
"data": _txassets[0][1]
|
||||
}
|
||||
elif len(_txassets) > 0:
|
||||
_obj["asset"] = _txassets[0][1]
|
||||
_obj["metadata"] = _txmeta[0][1] if len(_txmeta) == 1 else None
|
||||
_transactions.append(_obj)
|
||||
return _transactions
|
||||
@ -97,7 +105,7 @@ def store_transactions(connection, signed_transactions: list):
|
||||
assetsxspace = connection.space("assets")
|
||||
|
||||
for transaction in signed_transactions:
|
||||
txprepare = TransactionPrepare(transaction)
|
||||
txprepare = TransactionDecompose(transaction)
|
||||
txtuples = txprepare.convert_to_tuple()
|
||||
|
||||
txspace.insert(txtuples["transactions"])
|
||||
@ -154,9 +162,9 @@ def store_asset(connection, asset: dict, tx_id=None, is_data=False): # TODO con
|
||||
space = connection.space("assets")
|
||||
try:
|
||||
if is_data and tx_id is not None:
|
||||
space.insert((tx_id, asset["data"]))
|
||||
space.insert((tx_id, asset))
|
||||
else:
|
||||
space.insert((str(asset["id"]), asset["data"]))
|
||||
space.insert((str(asset["id"]), asset))
|
||||
except: # TODO Add Raise For Duplicate
|
||||
print("DUPLICATE ERROR")
|
||||
|
||||
@ -176,7 +184,7 @@ def get_asset(connection, asset_id: str):
|
||||
space = connection.space("assets")
|
||||
_data = space.select(asset_id, index="assetid_search")
|
||||
_data = _data.data
|
||||
return {"data": _data[0][1]} if len(_data) == 1 else []
|
||||
return _data[0][1] if len(_data) == 1 else []
|
||||
|
||||
|
||||
@register_query(TarantoolDB)
|
||||
|
||||
134
planetmint/backend/tarantool/transaction/tools.py
Normal file
134
planetmint/backend/tarantool/transaction/tools.py
Normal file
@ -0,0 +1,134 @@
|
||||
from secrets import token_hex
|
||||
|
||||
|
||||
def _save_keys_order(dictionary):
|
||||
if type(dictionary) is dict:
|
||||
keys = list(dictionary.keys())
|
||||
_map = {}
|
||||
for key in keys:
|
||||
_map[key] = _save_keys_order(dictionary=dictionary[key])
|
||||
|
||||
return _map
|
||||
elif type(dictionary) is list:
|
||||
dictionary = next(iter(dictionary), None)
|
||||
if dictionary is not None and type(dictionary) is dict:
|
||||
_map = {}
|
||||
keys = list(dictionary.keys())
|
||||
for key in keys:
|
||||
_map[key] = _save_keys_order(dictionary=dictionary[key])
|
||||
|
||||
return _map
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class TransactionDecompose:
|
||||
def __init__(self, _transaction):
|
||||
self._transaction = _transaction
|
||||
self._tuple_transaction = {
|
||||
"transactions": (),
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"keys": [],
|
||||
"metadata": (),
|
||||
"asset": "",
|
||||
"asset_data": (),
|
||||
"is_data": False
|
||||
}
|
||||
self.if_key = lambda dct, key: False if not key in dct.keys() else dct[key]
|
||||
|
||||
def get_map(self, dictionary: dict = None):
|
||||
return _save_keys_order(dictionary=dictionary) if dictionary is not None else _save_keys_order(
|
||||
dictionary=self._transaction)
|
||||
|
||||
def __create_hash(self, n: int):
|
||||
return token_hex(n)
|
||||
|
||||
def _metadata_check(self):
|
||||
metadata = self._transaction.get("metadata")
|
||||
self._tuple_transaction["metadata"] = (self._transaction["id"], metadata) if metadata is not None else ()
|
||||
|
||||
def __asset_check(self):
|
||||
_asset = self._transaction.get("asset")
|
||||
if _asset is None:
|
||||
self._tuple_transaction["asset"] = ""
|
||||
return
|
||||
|
||||
_id = self.if_key(dct=_asset, key="id")
|
||||
if _id is not False:
|
||||
self._tuple_transaction["asset"] = _id
|
||||
return
|
||||
|
||||
self._tuple_transaction["is_data"] = True
|
||||
self._tuple_transaction["asset_data"] = (self._transaction["id"], _asset)
|
||||
self._tuple_transaction["asset"] = ""
|
||||
|
||||
def __prepare_inputs(self):
|
||||
_inputs = []
|
||||
input_index = 0
|
||||
for _input in self._transaction["inputs"]:
|
||||
_inputs.append((self._transaction["id"],
|
||||
_input["fulfillment"],
|
||||
_input["owners_before"],
|
||||
_input["fulfills"]["transaction_id"] if _input["fulfills"] is not None else "",
|
||||
str(_input["fulfills"]["output_index"]) if _input["fulfills"] is not None else "",
|
||||
self.__create_hash(7),
|
||||
input_index))
|
||||
input_index = input_index + 1
|
||||
return _inputs
|
||||
|
||||
def __prepare_outputs(self):
|
||||
_outputs = []
|
||||
_keys = []
|
||||
output_index = 0
|
||||
for _output in self._transaction["outputs"]:
|
||||
output_id = self.__create_hash(7)
|
||||
if _output["condition"]["details"].get("subconditions") is None:
|
||||
_outputs.append((self._transaction["id"],
|
||||
_output["amount"],
|
||||
_output["condition"]["uri"],
|
||||
_output["condition"]["details"]["type"],
|
||||
_output["condition"]["details"]["public_key"],
|
||||
output_id,
|
||||
None,
|
||||
None,
|
||||
output_index
|
||||
))
|
||||
else:
|
||||
_outputs.append((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
|
||||
))
|
||||
output_index = output_index + 1
|
||||
for _key in _output["public_keys"]:
|
||||
key_id = self.__create_hash(7)
|
||||
_keys.append((key_id, self._transaction["id"], output_id, _key))
|
||||
return _keys, _outputs
|
||||
|
||||
def __prepare_transaction(self):
|
||||
return (self._transaction["id"],
|
||||
self._transaction["operation"],
|
||||
self._transaction["version"],
|
||||
self._tuple_transaction["asset"],
|
||||
self.get_map())
|
||||
|
||||
def convert_to_tuple(self):
|
||||
self._metadata_check()
|
||||
self.__asset_check()
|
||||
self._tuple_transaction["transactions"] = self.__prepare_transaction()
|
||||
self._tuple_transaction["inputs"] = self.__prepare_inputs()
|
||||
keys, outputs = self.__prepare_outputs()
|
||||
self._tuple_transaction["outputs"] = outputs
|
||||
self._tuple_transaction["keys"] = keys
|
||||
return self._tuple_transaction
|
||||
|
||||
|
||||
class TransactionCompose:
|
||||
def convert_to_dict(self, db_results):
|
||||
transaction_map = db_results["transaction"][4]
|
||||
@ -26,7 +26,6 @@ try:
|
||||
except ImportError:
|
||||
from sha3 import sha3_256
|
||||
|
||||
from secrets import token_hex
|
||||
from planetmint.common.crypto import PrivateKey, hash_data
|
||||
from planetmint.common.exceptions import (KeypairMismatchException,
|
||||
InputDoesNotExist, DoubleSpend,
|
||||
@ -1182,6 +1181,7 @@ class Transaction(object):
|
||||
|
||||
tx_body_serialized = Transaction._to_str(tx_body)
|
||||
valid_tx_id = Transaction._to_hash(tx_body_serialized)
|
||||
print("VALIDTX " + tx_body_serialized)
|
||||
if proposed_tx_id != valid_tx_id:
|
||||
err_msg = ("The transaction's id '{}' isn't equal to "
|
||||
"the hash of its body, i.e. it's not valid.")
|
||||
@ -1328,106 +1328,3 @@ class Transaction(object):
|
||||
raise InvalidSignature('Transaction signature is invalid.')
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class TransactionPrepare:
|
||||
def __init__(self, _transaction):
|
||||
self._transaction = _transaction
|
||||
self._tuple_transaction = {
|
||||
"transactions": (),
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"keys": [],
|
||||
"metadata": (),
|
||||
"asset": "",
|
||||
"asset_data": (),
|
||||
"is_data": False
|
||||
}
|
||||
self.if_key = lambda dct, key: False if not key in dct.keys() else dct[key]
|
||||
|
||||
def __create_hash(self, n: int):
|
||||
return token_hex(n)
|
||||
|
||||
def _metadata_check(self):
|
||||
metadata = self._transaction.get("metadata")
|
||||
self._tuple_transaction["metadata"] = (self._transaction["id"], metadata) if metadata is not None else ()
|
||||
|
||||
def __asset_check(self):
|
||||
_asset = self._transaction.get("asset")
|
||||
if _asset is None:
|
||||
self._tuple_transaction["asset"] = ""
|
||||
return
|
||||
|
||||
_id = self.if_key(dct=_asset, key="id")
|
||||
# data = self.if_key(dct=_asset, key="data")
|
||||
if _id is not False:
|
||||
self._tuple_transaction["asset"] = _id
|
||||
else:
|
||||
self._tuple_transaction["is_data"] = True
|
||||
_key = list(_asset.keys())[0]
|
||||
self._tuple_transaction["asset_data"] = (self._transaction["id"], _asset[_key])
|
||||
self._tuple_transaction["asset"] = ""
|
||||
|
||||
def __prepare_inputs(self):
|
||||
_inputs = []
|
||||
input_index = 0
|
||||
for _input in self._transaction["inputs"]:
|
||||
_inputs.append((self._transaction["id"],
|
||||
_input["fulfillment"],
|
||||
_input["owners_before"],
|
||||
_input["fulfills"]["transaction_id"] if _input["fulfills"] is not None else "",
|
||||
str(_input["fulfills"]["output_index"]) if _input["fulfills"] is not None else "",
|
||||
self.__create_hash(7),
|
||||
input_index))
|
||||
input_index = input_index + 1
|
||||
return _inputs
|
||||
|
||||
def __prepare_outputs(self):
|
||||
_outputs = []
|
||||
_keys = []
|
||||
output_index = 0
|
||||
for _output in self._transaction["outputs"]:
|
||||
output_id = self.__create_hash(7)
|
||||
if _output["condition"]["details"].get("subconditions") is None:
|
||||
_outputs.append((self._transaction["id"],
|
||||
_output["amount"],
|
||||
_output["condition"]["uri"],
|
||||
_output["condition"]["details"]["type"],
|
||||
_output["condition"]["details"]["public_key"],
|
||||
output_id,
|
||||
None,
|
||||
None,
|
||||
output_index
|
||||
))
|
||||
else:
|
||||
_outputs.append((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
|
||||
))
|
||||
output_index = output_index + 1
|
||||
for _key in _output["public_keys"]:
|
||||
key_id = self.__create_hash(7)
|
||||
_keys.append((key_id, self._transaction["id"], output_id, _key))
|
||||
return _keys, _outputs
|
||||
|
||||
def __prepare_transaction(self):
|
||||
return (self._transaction["id"],
|
||||
self._transaction["operation"],
|
||||
self._transaction["version"],
|
||||
self._tuple_transaction["asset"])
|
||||
|
||||
def convert_to_tuple(self):
|
||||
self._metadata_check()
|
||||
self.__asset_check()
|
||||
self._tuple_transaction["transactions"] = self.__prepare_transaction()
|
||||
self._tuple_transaction["inputs"] = self.__prepare_inputs()
|
||||
keys, outputs = self.__prepare_outputs()
|
||||
self._tuple_transaction["outputs"] = outputs
|
||||
self._tuple_transaction["keys"] = keys
|
||||
return self._tuple_transaction
|
||||
|
||||
@ -380,6 +380,7 @@ def test_get_spent_transaction_critical_double_spend(b, alice, bob, carol):
|
||||
[([bob.public_key], 1)],
|
||||
asset_id=tx.id)\
|
||||
.sign([alice.private_key])
|
||||
print("PROPOSEDTX " + str(same_input_double_spend.to_dict()))
|
||||
|
||||
b.store_bulk_transactions([tx])
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user