mirror of
https://github.com/planetmint/planetmint.git
synced 2025-11-27 15:53:37 +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 import query
|
||||||
from planetmint.backend.utils import module_dispatch_registrar
|
from planetmint.backend.utils import module_dispatch_registrar
|
||||||
from planetmint.backend.tarantool.connection import TarantoolDB
|
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)
|
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)
|
_txinputs = sorted(_txinputs, key=itemgetter(6), reverse=False)
|
||||||
_txoutputs = sorted(_txoutputs, key=itemgetter(8), 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 = {
|
_obj = {
|
||||||
"inputs": [
|
"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(
|
"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"
|
# TODO Now it is working because of data type cast to INTEGER for field "output_index"
|
||||||
_in[4]) > 0 else None,
|
_in[4]) > 0 else None,
|
||||||
"fulfillment": _in[1]
|
"owners_before": _in[2]
|
||||||
} for _in in _txinputs
|
} for _in in _txinputs
|
||||||
],
|
],
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
@ -59,18 +69,18 @@ def _group_transaction_by_ids(connection, txids: list):
|
|||||||
if _txoutputs[0][7] is None:
|
if _txoutputs[0][7] is None:
|
||||||
_obj["outputs"] = [
|
_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]},
|
"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
|
} for _out in _txoutputs
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
_obj["outputs"] = [
|
_obj["outputs"] = [
|
||||||
{
|
{
|
||||||
"public_keys": [_key[3] for _key in _txkeys if _key[2] == _out[5]],
|
|
||||||
"amount": _out[1],
|
"amount": _out[1],
|
||||||
"condition": {"uri": _out[2], "details": {"subconditions": _out[7]}, "type": _out[3],
|
"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
|
} for _out in _txoutputs
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -78,10 +88,8 @@ def _group_transaction_by_ids(connection, txids: list):
|
|||||||
_obj["asset"] = {
|
_obj["asset"] = {
|
||||||
"id": _txobject[3]
|
"id": _txobject[3]
|
||||||
}
|
}
|
||||||
elif len(_txassets) == 1:
|
elif len(_txassets) > 0:
|
||||||
_obj["asset"] = {
|
_obj["asset"] = _txassets[0][1]
|
||||||
"data": _txassets[0][1]
|
|
||||||
}
|
|
||||||
_obj["metadata"] = _txmeta[0][1] if len(_txmeta) == 1 else None
|
_obj["metadata"] = _txmeta[0][1] if len(_txmeta) == 1 else None
|
||||||
_transactions.append(_obj)
|
_transactions.append(_obj)
|
||||||
return _transactions
|
return _transactions
|
||||||
@ -97,7 +105,7 @@ def store_transactions(connection, signed_transactions: list):
|
|||||||
assetsxspace = connection.space("assets")
|
assetsxspace = connection.space("assets")
|
||||||
|
|
||||||
for transaction in signed_transactions:
|
for transaction in signed_transactions:
|
||||||
txprepare = TransactionPrepare(transaction)
|
txprepare = TransactionDecompose(transaction)
|
||||||
txtuples = txprepare.convert_to_tuple()
|
txtuples = txprepare.convert_to_tuple()
|
||||||
|
|
||||||
txspace.insert(txtuples["transactions"])
|
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")
|
space = connection.space("assets")
|
||||||
try:
|
try:
|
||||||
if is_data and tx_id is not None:
|
if is_data and tx_id is not None:
|
||||||
space.insert((tx_id, asset["data"]))
|
space.insert((tx_id, asset))
|
||||||
else:
|
else:
|
||||||
space.insert((str(asset["id"]), asset["data"]))
|
space.insert((str(asset["id"]), asset))
|
||||||
except: # TODO Add Raise For Duplicate
|
except: # TODO Add Raise For Duplicate
|
||||||
print("DUPLICATE ERROR")
|
print("DUPLICATE ERROR")
|
||||||
|
|
||||||
@ -176,7 +184,7 @@ def get_asset(connection, asset_id: str):
|
|||||||
space = connection.space("assets")
|
space = connection.space("assets")
|
||||||
_data = space.select(asset_id, index="assetid_search")
|
_data = space.select(asset_id, index="assetid_search")
|
||||||
_data = _data.data
|
_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)
|
@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:
|
except ImportError:
|
||||||
from sha3 import sha3_256
|
from sha3 import sha3_256
|
||||||
|
|
||||||
from secrets import token_hex
|
|
||||||
from planetmint.common.crypto import PrivateKey, hash_data
|
from planetmint.common.crypto import PrivateKey, hash_data
|
||||||
from planetmint.common.exceptions import (KeypairMismatchException,
|
from planetmint.common.exceptions import (KeypairMismatchException,
|
||||||
InputDoesNotExist, DoubleSpend,
|
InputDoesNotExist, DoubleSpend,
|
||||||
@ -1182,6 +1181,7 @@ class Transaction(object):
|
|||||||
|
|
||||||
tx_body_serialized = Transaction._to_str(tx_body)
|
tx_body_serialized = Transaction._to_str(tx_body)
|
||||||
valid_tx_id = Transaction._to_hash(tx_body_serialized)
|
valid_tx_id = Transaction._to_hash(tx_body_serialized)
|
||||||
|
print("VALIDTX " + tx_body_serialized)
|
||||||
if proposed_tx_id != valid_tx_id:
|
if proposed_tx_id != valid_tx_id:
|
||||||
err_msg = ("The transaction's id '{}' isn't equal to "
|
err_msg = ("The transaction's id '{}' isn't equal to "
|
||||||
"the hash of its body, i.e. it's not valid.")
|
"the hash of its body, i.e. it's not valid.")
|
||||||
@ -1328,106 +1328,3 @@ class Transaction(object):
|
|||||||
raise InvalidSignature('Transaction signature is invalid.')
|
raise InvalidSignature('Transaction signature is invalid.')
|
||||||
|
|
||||||
return True
|
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)],
|
[([bob.public_key], 1)],
|
||||||
asset_id=tx.id)\
|
asset_id=tx.id)\
|
||||||
.sign([alice.private_key])
|
.sign([alice.private_key])
|
||||||
|
print("PROPOSEDTX " + str(same_input_double_spend.to_dict()))
|
||||||
|
|
||||||
b.store_bulk_transactions([tx])
|
b.store_bulk_transactions([tx])
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user