Merge branch 'refactor-backend' into simplified_unit_tests

This commit is contained in:
Jürgen Eckel 2023-01-16 10:27:35 +01:00
commit 08b2924679
No known key found for this signature in database
43 changed files with 297 additions and 565 deletions

View File

@ -1,35 +0,0 @@
# 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
name: Documentation
on: [push, pull_request]
jobs:
documentation:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: 3.9
- name: Install tox
run: python -m pip install --upgrade tox tox-gh-actions
- name: Install dependencies
run: pip install .'[dev]'
- name: Run tox
run: tox -e docsroot

1
.gitignore vendored
View File

@ -53,7 +53,6 @@ pip-delete-this-directory.txt
# Unit test / coverage reports # Unit test / coverage reports
htmlcov/ htmlcov/
.tox/
.coverage .coverage
.coverage.* .coverage.*
.cache .cache

View File

@ -25,6 +25,16 @@ For reference, the possible headings are:
* **Known Issues** * **Known Issues**
* **Notes** * **Notes**
## [2.0.0] - 2023-12-01
* **Changed** changed tarantool db schema
* **Removed** removed text_search routes
* **Added** metadata / asset cid route for fetching transactions
## [1.4.1] - 2022-21-12
* **fixed** inconsistent cryptocondition keyring tag handling. Using cryptoconditions > 1.1.0 from now on.
## [1.4.0] - 2022-12-12
* **Added** added upgrade compatibility to older nodes to support v2.0 TX validity for nodes supporting v3.0 transactions (planetmint-transactions >= 0.4.1)
## [1.3.2] - 2022-28-11 ## [1.3.2] - 2022-28-11
* **Changed** new zenroom 2.3.1 support * **Changed** new zenroom 2.3.1 support

View File

@ -41,7 +41,6 @@ services:
- ./setup.py:/usr/src/app/setup.py - ./setup.py:/usr/src/app/setup.py
- ./setup.cfg:/usr/src/app/setup.cfg - ./setup.cfg:/usr/src/app/setup.cfg
- ./pytest.ini:/usr/src/app/pytest.ini - ./pytest.ini:/usr/src/app/pytest.ini
- ./tox.ini:/usr/src/app/tox.ini
environment: environment:
PLANETMINT_DATABASE_BACKEND: tarantool_db PLANETMINT_DATABASE_BACKEND: tarantool_db
PLANETMINT_DATABASE_HOST: tarantool PLANETMINT_DATABASE_HOST: tarantool

View File

@ -1,7 +1,7 @@
aafigure==0.6 aafigure==0.6
alabaster==0.7.12 alabaster==0.7.12
Babel==2.10.1 Babel==2.10.1
certifi==2021.10.8 certifi==2022.12.7
charset-normalizer==2.0.12 charset-normalizer==2.0.12
commonmark==0.9.1 commonmark==0.9.1
docutils==0.17.1 docutils==0.17.1

View File

@ -54,13 +54,13 @@ import sphinx_rtd_theme
extensions = [ extensions = [
"myst_parser", "myst_parser",
"sphinx.ext.napoleon",
"sphinx.ext.autosectionlabel", "sphinx.ext.autosectionlabel",
"sphinx.ext.autodoc", "sphinx.ext.autodoc",
"sphinx.ext.intersphinx", "sphinx.ext.intersphinx",
"sphinx.ext.coverage", "sphinx.ext.coverage",
"sphinx.ext.viewcode", "sphinx.ext.viewcode",
"sphinx.ext.todo", "sphinx.ext.todo",
"sphinx.ext.napoleon",
"sphinxcontrib.httpdomain", "sphinxcontrib.httpdomain",
"aafigure.sphinxext", "aafigure.sphinxext",
#'sphinx_toolbox.collapse', #'sphinx_toolbox.collapse',

View File

@ -4,7 +4,7 @@ Content-Type: application/json
{ {
"assets": "/assets/", "assets": "/assets/",
"blocks": "/blocks/", "blocks": "/blocks/",
"docs": "https://docs.planetmint.io/projects/server/en/v1.3.1/http-client-server-api.html", "docs": "https://docs.planetmint.io/projects/server/en/v1.4.1/http-client-server-api.html",
"metadata": "/metadata/", "metadata": "/metadata/",
"outputs": "/outputs/", "outputs": "/outputs/",
"streamedblocks": "ws://localhost:9985/api/v1/streams/valid_blocks", "streamedblocks": "ws://localhost:9985/api/v1/streams/valid_blocks",

View File

@ -7,15 +7,13 @@ Content-Type: application/json
{ {
"assets": [ "assets": [
{ {
"data": { "data": "QmQP5C3PmhH9oB84n7YqSY4WVqmYatdoo1BdwhH4zmcwqM"
"msg": "Hello Planetmint!"
}
} }
], ],
"id": "61e1312b80705e0dabb948c9d78dae7f62d64832abda822b13d89c4a7305d4ac", "id": "0fdeb547670bbea980389df53cf5a91e60159339084c6b0b5cc0b5494a679530",
"inputs": [ "inputs": [
{ {
"fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUCWcUaLa2U-nkmZ6oYj14aeV6B4TJH2NvZ8k2ZTwcGiaiCGXDQT2dEPfMCFwM8lwSousafCu4c7EgVZ1GzUDjsN", "fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUDklzRb5aUQz9slbaqSWap1AfC-cacTCN3CGtFy2LPK7JKEqKG2b0KQXnUcFksk_KH_v6ImFXHsclKSp1OJkIEI",
"fulfills": null, "fulfills": null,
"owners_before": [ "owners_before": [
"4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD" "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
@ -39,7 +37,7 @@ Content-Type: application/json
] ]
} }
], ],
"version": "2.0" "version": "3.0"
} }
] ]
} }

View File

@ -1,3 +1,3 @@
GET /api/v1/blocks?transaction_id=61e1312b80705e0dabb948c9d78dae7f62d64832abda822b13d89c4a7305d4ac HTTP/1.1 GET /api/v1/blocks?transaction_id=0fdeb547670bbea980389df53cf5a91e60159339084c6b0b5cc0b5494a679530 HTTP/1.1
Host: example.com Host: example.com

View File

@ -1,3 +1,3 @@
GET /api/v1/transactions?operation=TRANSFER&asset_id=61e1312b80705e0dabb948c9d78dae7f62d64832abda822b13d89c4a7305d4ac HTTP/1.1 GET /api/v1/transactions?operation=TRANSFER&asset_id=0fdeb547670bbea980389df53cf5a91e60159339084c6b0b5cc0b5494a679530 HTTP/1.1
Host: example.com Host: example.com

View File

@ -4,16 +4,16 @@ Content-Type: application/json
[{ [{
"assets": [ "assets": [
{ {
"id": "61e1312b80705e0dabb948c9d78dae7f62d64832abda822b13d89c4a7305d4ac" "id": "0fdeb547670bbea980389df53cf5a91e60159339084c6b0b5cc0b5494a679530"
} }
], ],
"id": "b6e1ab3d48bbbbb0e40b952e70ec5d439b2745e0ba0c44b4ee877657e9ac33f0", "id": "8d11fe2bd91c4747a41e0c3dbe1400c511175be42f008d6cff92cbfa9e04f799",
"inputs": [ "inputs": [
{ {
"fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUA4BB4fxDXK3CQTbKpH5gTAN76NG-iopNuuDEfBbZ1Fl-ipNU46t8VCvK9ghm9Q53aFRW6DDiW5wcWXxY0sS4EJ", "fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUCh-rpO-xqDm2fngjzxnKc39G16FpFMo0y50sHT7_uo1Itzvh4jsxnSGco2HjG6ZF-lSiGsASZ4uIIHuPM57yUI",
"fulfills": { "fulfills": {
"output_index": 0, "output_index": 0,
"transaction_id": "61e1312b80705e0dabb948c9d78dae7f62d64832abda822b13d89c4a7305d4ac" "transaction_id": "0fdeb547670bbea980389df53cf5a91e60159339084c6b0b5cc0b5494a679530"
}, },
"owners_before": [ "owners_before": [
"4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD" "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
@ -37,21 +37,21 @@ Content-Type: application/json
] ]
} }
], ],
"version": "2.0" "version": "3.0"
}, },
{ {
"assets": [ "assets": [
{ {
"id": "61e1312b80705e0dabb948c9d78dae7f62d64832abda822b13d89c4a7305d4ac" "id": "0fdeb547670bbea980389df53cf5a91e60159339084c6b0b5cc0b5494a679530"
} }
], ],
"id": "e43d3f93d90d22ef11c21607e3415bfcda4e0c7dd60412fbb55daf32978a3126", "id": "45c929b66d1b10db6c3c3e6b1adddc0778b473fced4a1f403c2646b25f3fd983",
"inputs": [ "inputs": [
{ {
"fulfillment": "pGSAICw7Ul-c2lG6NFbHp3FbKRC7fivQcNGO7GS4wV3A-1QggUBjj_XTjB3yJdG8JMNKnkkHvcX_BTOkl-YacRD4yKqxUCeL-VTgbrLgi5a3gGxNJcTkZP1gF0nsby8cgV4xmOcB", "fulfillment": "pGSAICw7Ul-c2lG6NFbHp3FbKRC7fivQcNGO7GS4wV3A-1QggUAc6OAQcXppDxCazw0UK2nwghctKNiZYDDsSOkAn0eQE8QjZ7GLzJpVb92oGXw_4FF7cLE0gg3nNxu7taQ8xakE",
"fulfills": { "fulfills": {
"output_index": 0, "output_index": 0,
"transaction_id": "b6e1ab3d48bbbbb0e40b952e70ec5d439b2745e0ba0c44b4ee877657e9ac33f0" "transaction_id": "8d11fe2bd91c4747a41e0c3dbe1400c511175be42f008d6cff92cbfa9e04f799"
}, },
"owners_before": [ "owners_before": [
"3yfQPHeWAa1MxTX9Zf9176QqcpcnWcanVZZbaHb8B3h9" "3yfQPHeWAa1MxTX9Zf9176QqcpcnWcanVZZbaHb8B3h9"
@ -75,5 +75,5 @@ Content-Type: application/json
] ]
} }
], ],
"version": "2.0" "version": "3.0"
}] }]

View File

@ -1,3 +1,3 @@
GET /api/v1/transactions/61e1312b80705e0dabb948c9d78dae7f62d64832abda822b13d89c4a7305d4ac HTTP/1.1 GET /api/v1/transactions/0fdeb547670bbea980389df53cf5a91e60159339084c6b0b5cc0b5494a679530 HTTP/1.1
Host: example.com Host: example.com

View File

@ -4,15 +4,13 @@ Content-Type: application/json
{ {
"assets": [ "assets": [
{ {
"data": { "data": "QmQP5C3PmhH9oB84n7YqSY4WVqmYatdoo1BdwhH4zmcwqM"
"msg": "Hello Planetmint!"
}
} }
], ],
"id": "61e1312b80705e0dabb948c9d78dae7f62d64832abda822b13d89c4a7305d4ac", "id": "0fdeb547670bbea980389df53cf5a91e60159339084c6b0b5cc0b5494a679530",
"inputs": [ "inputs": [
{ {
"fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUCWcUaLa2U-nkmZ6oYj14aeV6B4TJH2NvZ8k2ZTwcGiaiCGXDQT2dEPfMCFwM8lwSousafCu4c7EgVZ1GzUDjsN", "fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUDklzRb5aUQz9slbaqSWap1AfC-cacTCN3CGtFy2LPK7JKEqKG2b0KQXnUcFksk_KH_v6ImFXHsclKSp1OJkIEI",
"fulfills": null, "fulfills": null,
"owners_before": [ "owners_before": [
"4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD" "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
@ -36,5 +34,5 @@ Content-Type: application/json
] ]
} }
], ],
"version": "2.0" "version": "3.0"
} }

View File

@ -6,7 +6,7 @@ Content-Type: application/json
"v1": { "v1": {
"assets": "/api/v1/assets/", "assets": "/api/v1/assets/",
"blocks": "/api/v1/blocks/", "blocks": "/api/v1/blocks/",
"docs": "https://docs.planetmint.io/projects/server/en/v1.2.2/http-client-server-api.html", "docs": "https://docs.planetmint.io/projects/server/en/v1.4.1/http-client-server-api.html",
"metadata": "/api/v1/metadata/", "metadata": "/api/v1/metadata/",
"outputs": "/api/v1/outputs/", "outputs": "/api/v1/outputs/",
"streamedblocks": "ws://localhost:9985/api/v1/streams/valid_blocks", "streamedblocks": "ws://localhost:9985/api/v1/streams/valid_blocks",
@ -15,7 +15,7 @@ Content-Type: application/json
"validators": "/api/v1/validators" "validators": "/api/v1/validators"
} }
}, },
"docs": "https://docs.planetmint.io/projects/server/en/v1.2.2/", "docs": "https://docs.planetmint.io/projects/server/en/v1.4.1/",
"software": "Planetmint", "software": "Planetmint",
"version": "1.3.1" "version": "1.4.1"
} }

View File

@ -5,15 +5,13 @@ Content-Type: application/json
{ {
"assets": [ "assets": [
{ {
"data": { "data": "QmQP5C3PmhH9oB84n7YqSY4WVqmYatdoo1BdwhH4zmcwqM"
"msg": "Hello Planetmint!"
}
} }
], ],
"id": "61e1312b80705e0dabb948c9d78dae7f62d64832abda822b13d89c4a7305d4ac", "id": "0fdeb547670bbea980389df53cf5a91e60159339084c6b0b5cc0b5494a679530",
"inputs": [ "inputs": [
{ {
"fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUCWcUaLa2U-nkmZ6oYj14aeV6B4TJH2NvZ8k2ZTwcGiaiCGXDQT2dEPfMCFwM8lwSousafCu4c7EgVZ1GzUDjsN", "fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUDklzRb5aUQz9slbaqSWap1AfC-cacTCN3CGtFy2LPK7JKEqKG2b0KQXnUcFksk_KH_v6ImFXHsclKSp1OJkIEI",
"fulfills": null, "fulfills": null,
"owners_before": [ "owners_before": [
"4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD" "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
@ -37,5 +35,5 @@ Content-Type: application/json
] ]
} }
], ],
"version": "2.0" "version": "3.0"
} }

View File

@ -4,15 +4,13 @@ Content-Type: application/json
{ {
"assets": [ "assets": [
{ {
"data": { "data": "QmQP5C3PmhH9oB84n7YqSY4WVqmYatdoo1BdwhH4zmcwqM"
"msg": "Hello Planetmint!"
}
} }
], ],
"id": "61e1312b80705e0dabb948c9d78dae7f62d64832abda822b13d89c4a7305d4ac", "id": "0fdeb547670bbea980389df53cf5a91e60159339084c6b0b5cc0b5494a679530",
"inputs": [ "inputs": [
{ {
"fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUCWcUaLa2U-nkmZ6oYj14aeV6B4TJH2NvZ8k2ZTwcGiaiCGXDQT2dEPfMCFwM8lwSousafCu4c7EgVZ1GzUDjsN", "fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUDklzRb5aUQz9slbaqSWap1AfC-cacTCN3CGtFy2LPK7JKEqKG2b0KQXnUcFksk_KH_v6ImFXHsclKSp1OJkIEI",
"fulfills": null, "fulfills": null,
"owners_before": [ "owners_before": [
"4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD" "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
@ -36,5 +34,5 @@ Content-Type: application/json
] ]
} }
], ],
"version": "2.0" "version": "3.0"
} }

View File

@ -3,14 +3,12 @@
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0 # Code is Apache-2.0 and docs are CC-BY-4.0
import tarantool
import logging import logging
from itertools import repeat from itertools import repeat
from importlib import import_module from importlib import import_module
from transactions.common.exceptions import ConfigurationError from transactions.common.exceptions import ConfigurationError
from planetmint.config import Config from planetmint.config import Config
from planetmint.backend.exceptions import ConnectionError
BACKENDS = { BACKENDS = {
"tarantool_db": "planetmint.backend.tarantool.connection.TarantoolDBConnection", "tarantool_db": "planetmint.backend.tarantool.connection.TarantoolDBConnection",
@ -69,6 +67,7 @@ class DBConnection(metaclass=DBSingleton):
**kwargs **kwargs
): ):
"""Create a new :class:`~.Connection` instance. """Create a new :class:`~.Connection` instance.
Args: Args:
host (str): the host to connect to. host (str): the host to connect to.
port (int): the port to connect to. port (int): the port to connect to.

View File

@ -39,7 +39,9 @@ class DbTransaction:
operation=transaction[1], operation=transaction[1],
version=transaction[2], version=transaction[2],
metadata=MetaData.from_dict(transaction[3]), metadata=MetaData.from_dict(transaction[3]),
assets=Asset.from_list_dict(transaction[4]), assets=Asset.from_list_dict(transaction[4])
if transaction[2] != "2.0"
else Asset.from_dict(transaction[4][0]),
inputs=Input.from_list_dict(transaction[5]), inputs=Input.from_list_dict(transaction[5]),
script=Script.from_dict(transaction[6]), script=Script.from_dict(transaction[6]),
) )
@ -66,7 +68,7 @@ class DbTransaction:
"outputs": Output.list_to_dict(self.outputs), "outputs": Output.list_to_dict(self.outputs),
"operation": self.operation, "operation": self.operation,
"metadata": self.metadata.to_dict() if self.metadata is not None else None, "metadata": self.metadata.to_dict() if self.metadata is not None else None,
"assets": Asset.list_to_dict(self.assets), "assets": Asset.list_to_dict(self.assets) if self.version != "2.0" else Asset.to_dict(self.assets),
"version": self.version, "version": self.version,
"id": self.id, "id": self.id,
"script": self.script.to_dict() if self.script is not None else None, "script": self.script.to_dict() if self.script is not None else None,

View File

@ -31,12 +31,12 @@ def store_asset(connection, asset: dict) -> Asset:
@singledispatch @singledispatch
def store_assets(connection, assets: list) -> list[Asset]: def store_assets(connection, assets: list) -> list[Asset]:
"""Write a list of assets to the assets table. """Write a list of assets to the assets table.
backend
Args:
assets (list): a list of assets to write.
Returns: Args:
The database response. assets (list): a list of assets to write.
Returns:
The database response.
""" """
raise NotImplementedError raise NotImplementedError
@ -70,27 +70,6 @@ def store_transaction(connection, transaction):
raise NotImplementedError raise NotImplementedError
@singledispatch
def store_governance_transactions(connection, transactions):
"""Store the list of governance transactions."""
raise NotImplementedError
@singledispatch
def store_governance_transaction(connection, transaction):
"""Store a single governance transaction."""
raise NotImplementedError
@singledispatch
def get_governance_transaction_by_id(connection, transaction_id):
"""Get the transaction by transaction id."""
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."""
@ -243,6 +222,7 @@ def store_transaction_outputs(connection, output: Output, index: int):
@singledispatch @singledispatch
def get_assets(connection, asset_ids) -> list[Asset]: def get_assets(connection, asset_ids) -> list[Asset]:
"""Get a list of assets from the assets table. """Get a list of assets from the assets table.
Args: Args:
asset_ids (list): a list of ids for the assets to be retrieved from asset_ids (list): a list of ids for the assets to be retrieved from
the database. the database.

View File

@ -9,7 +9,6 @@ import logging
from functools import singledispatch from functools import singledispatch
from planetmint.config import Config from planetmint.config import Config
from planetmint.backend.connection import Connection
from transactions.common.exceptions import ValidationError from transactions.common.exceptions import ValidationError
from transactions.common.utils import ( from transactions.common.utils import (
validate_all_values_for_key_in_obj, validate_all_values_for_key_in_obj,

View File

@ -1,78 +0,0 @@
box.cfg{listen = 3303}
function indexed_pattern_search(space_name, field_no, pattern)
if (box.space[space_name] == nil) then
print("Error: Failed to find the specified space")
return nil
end
local index_no = -1
for i=0,box.schema.INDEX_MAX,1 do
if (box.space[space_name].index[i] == nil) then break end
if (box.space[space_name].index[i].type == "TREE"
and box.space[space_name].index[i].parts[1].fieldno == field_no
and (box.space[space_name].index[i].parts[1].type == "scalar"
or box.space[space_name].index[i].parts[1].type == "string")) then
index_no = i
break
end
end
if (index_no == -1) then
print("Error: Failed to find an appropriate index")
return nil
end
local index_search_key = ""
local index_search_key_length = 0
local last_character = ""
local c = ""
local c2 = ""
for i=1,string.len(pattern),1 do
c = string.sub(pattern, i, i)
if (last_character ~= "%") then
if (c == '^' or c == "$" or c == "(" or c == ")" or c == "."
or c == "[" or c == "]" or c == "*" or c == "+"
or c == "-" or c == "?") then
break
end
if (c == "%") then
c2 = string.sub(pattern, i + 1, i + 1)
if (string.match(c2, "%p") == nil) then break end
index_search_key = index_search_key .. c2
else
index_search_key = index_search_key .. c
end
end
last_character = c
end
index_search_key_length = string.len(index_search_key)
local result_set = {}
local number_of_tuples_in_result_set = 0
local previous_tuple_field = ""
while true do
local number_of_tuples_since_last_yield = 0
local is_time_for_a_yield = false
for _,tuple in box.space[space_name].index[index_no]:
pairs(index_search_key,{iterator = box.index.GE}) do
if (string.sub(tuple[field_no], 1, index_search_key_length)
> index_search_key) then
break
end
number_of_tuples_since_last_yield = number_of_tuples_since_last_yield + 1
if (number_of_tuples_since_last_yield >= 10
and tuple[field_no] ~= previous_tuple_field) then
index_search_key = tuple[field_no]
is_time_for_a_yield = true
break
end
previous_tuple_field = tuple[field_no]
if (string.match(tuple[field_no], pattern) ~= nil) then
number_of_tuples_in_result_set = number_of_tuples_in_result_set + 1
result_set[number_of_tuples_in_result_set] = tuple
end
end
if (is_time_for_a_yield ~= true) then
break
end
require('fiber').yield()
end
return result_set
end

View File

@ -9,7 +9,8 @@ import tarantool
from planetmint.config import Config from planetmint.config import Config
from transactions.common.exceptions import ConfigurationError from transactions.common.exceptions import ConfigurationError
from planetmint.utils import Lazy from planetmint.utils import Lazy
from planetmint.backend.connection import DBConnection, ConnectionError from planetmint.backend.connection import DBConnection
from planetmint.backend.exceptions import ConnectionError
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -11,6 +11,13 @@ TARANT_TABLE_GOVERNANCE = "governance"
TARANT_TABLE_INPUT = "inputs" TARANT_TABLE_INPUT = "inputs"
TARANT_TABLE_OUTPUT = "outputs" TARANT_TABLE_OUTPUT = "outputs"
TARANT_TABLE_SCRIPT = "scripts" 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_TX_ID_SEARCH = "transaction_id"
TARANT_ID_SEARCH = "id" TARANT_ID_SEARCH = "id"

View File

@ -1,8 +0,0 @@
box.space.abci_chains:drop()
box.space.blocks:drop()
box.space.elections:drop()
box.space.pre_commits:drop()
box.space.utxos:drop()
box.space.validators:drop()
box.space.transactions:drop()
box.space.outputs:drop()

View File

@ -7,8 +7,8 @@
import json import json
import logging import logging
from uuid import uuid4 from uuid import uuid4
from hashlib import sha256
from operator import itemgetter from operator import itemgetter
from typing import Union
from planetmint.backend import query from planetmint.backend import query
@ -18,9 +18,7 @@ from planetmint.exceptions import CriticalDoubleSpend
from planetmint.backend.tarantool.const import ( from planetmint.backend.tarantool.const import (
TARANT_TABLE_META_DATA, TARANT_TABLE_META_DATA,
TARANT_TABLE_ASSETS, TARANT_TABLE_ASSETS,
TARANT_TABLE_KEYS,
TARANT_TABLE_TRANSACTION, TARANT_TABLE_TRANSACTION,
TARANT_TABLE_INPUT,
TARANT_TABLE_OUTPUT, TARANT_TABLE_OUTPUT,
TARANT_TABLE_SCRIPT, TARANT_TABLE_SCRIPT,
TARANT_TX_ID_SEARCH, TARANT_TX_ID_SEARCH,
@ -28,10 +26,17 @@ from planetmint.backend.tarantool.const import (
TARANT_INDEX_TX_BY_ASSET_ID, TARANT_INDEX_TX_BY_ASSET_ID,
TARANT_INDEX_SPENDING_BY_ID_AND_OUTPUT_INDEX, TARANT_INDEX_SPENDING_BY_ID_AND_OUTPUT_INDEX,
TARANT_TABLE_GOVERNANCE, 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.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 from planetmint.backend.tarantool.connection import TarantoolDBConnection
from transactions.common.transaction import Transaction
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -39,7 +44,7 @@ register_query = module_dispatch_registrar(query)
@register_query(TarantoolDBConnection) @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 = [] _transactions = []
for txid in txids: for txid in txids:
tx = get_transaction_by_id(connection, txid, TARANT_TABLE_TRANSACTION) tx = get_transaction_by_id(connection, txid, TARANT_TABLE_TRANSACTION)
@ -61,7 +66,7 @@ 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) -> Union[DbTransaction, None]:
transactions = get_complete_transactions_by_ids(connection, (tx_id)) transactions = get_complete_transactions_by_ids(connection, (tx_id))
if len(transactions) > 1 or len(transactions) == 0: if len(transactions) > 1 or len(transactions) == 0:
return None return None
@ -109,9 +114,9 @@ def store_transaction_outputs(connection, output: Output, index: int) -> str:
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def store_transactions(connection, signed_transactions: list): def store_transactions(connection, signed_transactions: list, table=TARANT_TABLE_TRANSACTION):
for transaction in signed_transactions: for transaction in signed_transactions:
store_transaction(connection, transaction) store_transaction(connection, transaction, table)
[ [
store_transaction_outputs(connection, Output.outputs_dict(output, transaction["id"]), index) store_transaction_outputs(connection, Output.outputs_dict(output, transaction["id"]), index)
for index, output in enumerate(transaction[TARANT_TABLE_OUTPUT]) for index, output in enumerate(transaction[TARANT_TABLE_OUTPUT])
@ -119,81 +124,45 @@ def store_transactions(connection, signed_transactions: list):
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def store_transaction(connection, transaction): def store_transaction(connection, transaction, table=TARANT_TABLE_TRANSACTION):
scripts = None scripts = None
if TARANT_TABLE_SCRIPT in transaction: if TARANT_TABLE_SCRIPT in transaction:
scripts = transaction[TARANT_TABLE_SCRIPT] scripts = transaction[TARANT_TABLE_SCRIPT]
asset_obj = Transaction.get_assets_tag(transaction["version"])
if transaction["version"] == "2.0":
asset_array = [transaction[asset_obj]]
else:
asset_array = transaction[asset_obj]
tx = ( tx = (
transaction["id"], transaction["id"],
transaction["operation"], transaction["operation"],
transaction["version"], transaction["version"],
transaction["metadata"], transaction["metadata"],
transaction["assets"], asset_array,
transaction["inputs"], transaction["inputs"],
scripts, scripts,
) )
try: try:
connection.run(connection.space(TARANT_TABLE_TRANSACTION).insert(tx), only_data=False) connection.run(connection.space(table).insert(tx), only_data=False)
except Exception as e: except Exception as e:
logger.info(f"Could not insert transactions: {e}") logger.info(f"Could not insert transactions: {e}")
if e.args[0] == 3 and e.args[1].startswith('Duplicate key exists in'): if e.args[0] == 3 and e.args[1].startswith("Duplicate key exists in"):
raise CriticalDoubleSpend() raise CriticalDoubleSpend()
else: else:
raise OperationDataInsertionError() raise OperationDataInsertionError()
@register_query(TarantoolDBConnection)
def store_governance_transactions(connection, signed_transactions: list):
for transaction in signed_transactions:
store_governance_transaction(connection, transaction)
[
store_transaction_outputs(connection, Output.outputs_dict(output, transaction["id"]), index)
for index, output in enumerate(transaction[TARANT_TABLE_OUTPUT])
]
@register_query(TarantoolDBConnection)
def store_governance_transaction(connection, transaction):
scripts = None
if TARANT_TABLE_SCRIPT in transaction:
scripts = transaction[TARANT_TABLE_SCRIPT]
tx = (
transaction["id"],
transaction["operation"],
transaction["version"],
transaction["metadata"],
transaction["assets"],
transaction["inputs"],
scripts,
)
try:
connection.run(connection.space(TARANT_TABLE_GOVERNANCE).insert(tx), only_data=False)
except Exception as e:
if e.args[0] == 3 and e.args[1].startswith('Duplicate key exists in'):
raise CriticalDoubleSpend()
else:
raise OperationDataInsertionError()
@register_query(TarantoolDBConnection)
def get_governance_transaction_by_id(connection, transaction_id):
txs = connection.run(connection.space(TARANT_TABLE_GOVERNANCE).select(transaction_id, index=TARANT_ID_SEARCH))
if len(txs) == 0:
return None
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), only_data=False)
if len(txs) == 0: if len(txs) == 0:
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_single(connection, transaction_id, table=TARANT_TABLE_TRANSACTION) -> DbTransaction: def get_transaction_single(connection, transaction_id) -> Union[DbTransaction, None]:
txs = get_complete_transactions_by_ids(txids=[transaction_id], connection=connection, table=table) txs = get_complete_transactions_by_ids(txids=[transaction_id], connection=connection)
return txs[0] if len(txs) == 1 else None return txs[0] if len(txs) == 1 else None
@ -224,7 +193,7 @@ def get_assets(connection, assets_ids: list) -> list[Asset]:
@register_query(TarantoolDBConnection) @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( _inputs = connection.run(
connection.space(TARANT_TABLE_TRANSACTION).select( connection.space(TARANT_TABLE_TRANSACTION).select(
[fullfil_transaction_id, fullfil_output_index], index=TARANT_INDEX_SPENDING_BY_ID_AND_OUTPUT_INDEX [fullfil_transaction_id, fullfil_output_index], index=TARANT_INDEX_SPENDING_BY_ID_AND_OUTPUT_INDEX
@ -234,8 +203,8 @@ def get_spent(connection, fullfil_transaction_id: str, fullfil_output_index: str
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_latest_block(connection): def get_latest_block(connection) -> Union[dict, None]:
blocks = connection.run(connection.space("blocks").select()) blocks = connection.run(connection.space(TARANT_TABLE_BLOCKS).select())
if not blocks: if not blocks:
return None return None
@ -249,7 +218,7 @@ def store_block(connection, block: dict):
block_unique_id = uuid4().hex block_unique_id = uuid4().hex
try: try:
connection.run( connection.run(
connection.space("blocks").insert( connection.space(TARANT_TABLE_BLOCKS).insert(
(block_unique_id, block["app_hash"], block["height"], block[TARANT_TABLE_TRANSACTION]) (block_unique_id, block["app_hash"], block["height"], block[TARANT_TABLE_TRANSACTION])
), ),
only_data=False, only_data=False,
@ -260,7 +229,7 @@ def store_block(connection, block: dict):
@register_query(TarantoolDBConnection) @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 = [] transactions = []
if operation == "CREATE": if operation == "CREATE":
transactions = connection.run( transactions = connection.run(
@ -308,7 +277,7 @@ def text_search(conn, search, table=TARANT_TABLE_ASSETS, limit=0):
@register_query(TarantoolDBConnection) @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")) outputs = connection.run(connection.space(TARANT_TABLE_OUTPUT).select(owner, index="public_keys"))
if len(outputs) == 0: if len(outputs) == 0:
return [] return []
@ -333,8 +302,8 @@ def get_spending_transactions(connection, inputs):
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_block(connection, block_id=None): def get_block(connection, block_id=None) -> Union[dict, None]:
_block = connection.run(connection.space("blocks").select(block_id, index="height", limit=1)) _block = connection.run(connection.space(TARANT_TABLE_BLOCKS).select(block_id, index="height", limit=1))
if len(_block) == 0: if len(_block) == 0:
return return
_block = Block.from_tuple(_block[0]) _block = Block.from_tuple(_block[0])
@ -342,8 +311,8 @@ def get_block(connection, block_id=None):
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_block_with_transaction(connection, txid: str): def get_block_with_transaction(connection, txid: str) -> list[Block]:
_block = connection.run(connection.space("blocks").select(txid, index="block_by_transaction_id")) _block = connection.run(connection.space(TARANT_TABLE_BLOCKS).select(txid, index="block_by_transaction_id"))
return _block if len(_block) > 0 else [] return _block if len(_block) > 0 else []
@ -351,7 +320,7 @@ def get_block_with_transaction(connection, txid: str):
def delete_transactions(connection, txn_ids: list): def delete_transactions(connection, txn_ids: list):
try: try:
for _id in txn_ids: for _id in txn_ids:
_outputs = get_outputs_by_tx_id( connection, _id) _outputs = get_outputs_by_tx_id(connection, _id)
for x in range(len(_outputs)): for x in range(len(_outputs)):
connection.connect().call("delete_output", (_outputs[x].id)) connection.connect().call("delete_output", (_outputs[x].id))
for _id in txn_ids: for _id in txn_ids:
@ -369,7 +338,9 @@ def store_unspent_outputs(connection, *unspent_outputs: list):
for utxo in unspent_outputs: for utxo in unspent_outputs:
try: try:
output = connection.run( 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) result.append(output)
except Exception as e: except Exception as e:
@ -384,7 +355,7 @@ 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").delete( connection.space(TARANT_TABLE_UTXOS).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"
) )
) )
@ -394,13 +365,13 @@ def delete_unspent_outputs(connection, *unspent_outputs: list):
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_unspent_outputs(connection, query=None): # for now we don't have implementation for 'query'. 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] return [utx[3] for utx in _utxos]
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def store_pre_commit_state(connection, state: dict): 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 = ( _precommitTuple = (
(uuid4().hex, state["height"], state[TARANT_TABLE_TRANSACTION]) (uuid4().hex, state["height"], state[TARANT_TABLE_TRANSACTION])
if _precommit is None or len(_precommit) == 0 if _precommit is None or len(_precommit) == 0
@ -408,7 +379,7 @@ def store_pre_commit_state(connection, state: dict):
) )
try: try:
connection.run( connection.run(
connection.space("pre_commits").upsert( connection.space(TARANT_TABLE_PRE_COMMITS).upsert(
_precommitTuple, _precommitTuple,
op_list=[("=", 1, state["height"]), ("=", 2, state[TARANT_TABLE_TRANSACTION])], op_list=[("=", 1, state["height"]), ("=", 2, state[TARANT_TABLE_TRANSACTION])],
limit=1, limit=1,
@ -421,8 +392,8 @@ def store_pre_commit_state(connection, state: dict):
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_pre_commit_state(connection): def get_pre_commit_state(connection) -> dict:
_commit = connection.run(connection.space("pre_commits").select([], index=TARANT_ID_SEARCH)) _commit = connection.run(connection.space(TARANT_TABLE_PRE_COMMITS).select([], index=TARANT_ID_SEARCH))
if _commit is None or len(_commit) == 0: if _commit is None or len(_commit) == 0:
return None return None
_commit = sorted(_commit, key=itemgetter(1), reverse=False)[0] _commit = sorted(_commit, key=itemgetter(1), reverse=False)[0]
@ -431,11 +402,13 @@ def get_pre_commit_state(connection):
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def store_validator_set(conn, validators_update: dict): 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] unique_id = uuid4().hex if _validator is None or len(_validator) == 0 else _validator[0][0]
try: try:
conn.run( conn.run(
conn.space("validator_sets").upsert( conn.space(TARANT_TABLE_VALIDATOR_SETS).upsert(
(unique_id, validators_update["height"], validators_update["validators"]), (unique_id, validators_update["height"], validators_update["validators"]),
op_list=[("=", 1, validators_update["height"]), ("=", 2, validators_update["validators"])], op_list=[("=", 1, validators_update["height"]), ("=", 2, validators_update["validators"])],
limit=1, limit=1,
@ -449,16 +422,16 @@ def store_validator_set(conn, validators_update: dict):
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def delete_validator_set(connection, height: int): 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: 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) @register_query(TarantoolDBConnection)
def store_election(connection, election_id: str, height: int, is_concluded: bool): def store_election(connection, election_id: str, height: int, is_concluded: bool):
try: try:
connection.run( 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 (election_id, height, is_concluded), op_list=[("=", 1, height), ("=", 2, is_concluded)], limit=1
), ),
only_data=False, only_data=False,
@ -473,7 +446,7 @@ def store_elections(connection, elections: list):
try: try:
for election in elections: for election in elections:
_election = connection.run( # noqa: F841 _election = connection.run( # noqa: F841
connection.space("elections").insert( connection.space(TARANT_TABLE_ELECTIONS).insert(
(election["election_id"], election["height"], election["is_concluded"]) (election["election_id"], election["height"], election["is_concluded"])
), ),
only_data=False, only_data=False,
@ -485,14 +458,14 @@ def store_elections(connection, elections: list):
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def delete_elections(connection, height: int): 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: 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) @register_query(TarantoolDBConnection)
def get_validator_set(connection, height: int = None): 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: if height is not None and _validators is not None:
_validators = [ _validators = [
{"height": validator[1], "validators": validator[2]} for validator in _validators if validator[1] <= height {"height": validator[1], "validators": validator[2]} for validator in _validators if validator[1] <= height
@ -505,8 +478,8 @@ def get_validator_set(connection, height: int = None):
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_election(connection, election_id: str): def get_election(connection, election_id: str) -> dict:
_elections = connection.run(connection.space("elections").select(election_id, index=TARANT_ID_SEARCH)) _elections = connection.run(connection.space(TARANT_TABLE_ELECTIONS).select(election_id, index=TARANT_ID_SEARCH))
if _elections is None or len(_elections) == 0: if _elections is None or len(_elections) == 0:
return None return None
_election = sorted(_elections, key=itemgetter(0), reverse=True)[0] _election = sorted(_elections, key=itemgetter(0), reverse=True)[0]
@ -515,29 +488,19 @@ def get_election(connection, election_id: str):
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_asset_tokens_for_public_key(connection, asset_id: str, public_key: str) -> list[DbTransaction]: 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])) id_transactions = connection.run(connection.space(TARANT_TABLE_GOVERNANCE).select([asset_id]))
asset_id_transactions = connection.run( asset_id_transactions = connection.run(
connection.space(TARANT_TABLE_GOVERNANCE).select([asset_id], index="governance_by_asset_id") 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
return get_complete_transactions_by_ids(connection, [_tx[0] for _tx in 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])
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def store_abci_chain(connection, height: int, chain_id: str, is_synced: bool = True): def store_abci_chain(connection, height: int, chain_id: str, is_synced: bool = True):
try: try:
connection.run( connection.run(
connection.space("abci_chains").upsert( connection.space(TARANT_TABLE_ABCI_CHAINS).upsert(
(chain_id, height, is_synced), (chain_id, height, is_synced),
op_list=[("=", 0, chain_id), ("=", 1, height), ("=", 2, is_synced)], op_list=[("=", 0, chain_id), ("=", 1, height), ("=", 2, is_synced)],
), ),
@ -550,15 +513,13 @@ def store_abci_chain(connection, height: int, chain_id: str, is_synced: bool = T
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def delete_abci_chain(connection, height: int): def delete_abci_chain(connection, height: int):
hash_id_primarykey = sha256(json.dumps(obj={"height": height}).encode()).hexdigest() chains = connection.run(connection.space(TARANT_TABLE_ABCI_CHAINS).select(height, index="height"), only_data=False)
# connection.run(connection.space("abci_chains").delete(hash_id_primarykey), only_data=False) connection.run(connection.space(TARANT_TABLE_ABCI_CHAINS).delete(chains[0][0], index="id"), 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)
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_latest_abci_chain(connection): def get_latest_abci_chain(connection) -> Union[dict, None]:
_all_chains = connection.run(connection.space("abci_chains").select()) _all_chains = connection.run(connection.space(TARANT_TABLE_ABCI_CHAINS).select())
if _all_chains is None or len(_all_chains) == 0: if _all_chains is None or len(_all_chains) == 0:
return None return None
_chain = sorted(_all_chains, key=itemgetter(1), reverse=True)[0] _chain = sorted(_all_chains, key=itemgetter(1), reverse=True)[0]

View File

@ -8,142 +8,6 @@ from planetmint.backend.tarantool.connection import TarantoolDBConnection
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
register_schema = module_dispatch_registrar(backend.schema) register_schema = module_dispatch_registrar(backend.schema)
SPACE_NAMES = (
"abci_chains",
"assets",
"blocks",
"blocks_tx",
"elections",
"meta_data",
"pre_commits",
"validators",
"transactions",
"inputs",
"outputs",
"keys",
"utxos",
"scripts",
)
SPACE_COMMANDS = {
"abci_chains": "abci_chains = box.schema.space.create('abci_chains', {engine='memtx', is_sync = false})",
"assets": "assets = box.schema.space.create('assets' , {engine='memtx' , is_sync=false})",
"blocks": "blocks = box.schema.space.create('blocks' , {engine='memtx' , is_sync=false})",
"blocks_tx": "blocks_tx = box.schema.space.create('blocks_tx')",
"elections": "elections = box.schema.space.create('elections',{engine = 'memtx' , is_sync = false})",
"meta_data": "meta_datas = box.schema.space.create('meta_data',{engine = 'memtx' , is_sync = false})",
"pre_commits": "pre_commits = box.schema.space.create('pre_commits' , {engine='memtx' , is_sync=false})",
"validators": "validators = box.schema.space.create('validators' , {engine = 'memtx' , is_sync = false})",
"transactions": "transactions = box.schema.space.create('transactions',{engine='memtx' , is_sync=false})",
"inputs": "inputs = box.schema.space.create('inputs')",
"outputs": "outputs = box.schema.space.create('outputs')",
"keys": "keys = box.schema.space.create('keys')",
"utxos": "utxos = box.schema.space.create('utxos', {engine = 'memtx' , is_sync = false})",
"scripts": "scripts = box.schema.space.create('scripts', {engine = 'memtx' , is_sync = false})",
}
INDEX_COMMANDS = {
"abci_chains": {
"id_search": "abci_chains:create_index('id_search' ,{type='tree', parts={'id'}})",
"height_search": "abci_chains:create_index('height_search' ,{type='tree', unique=false, parts={'height'}})",
},
"assets": {
"txid_search": "assets:create_index('txid_search', {type='tree', parts={'tx_id'}})",
"assetid_search": "assets:create_index('assetid_search', {type='tree',unique=false, parts={'asset_id', 'tx_id'}})", # noqa: E501
"only_asset_search": "assets:create_index('only_asset_search', {type='tree', unique=false, parts={'asset_id'}})", # noqa: E501
"text_search": "assets:create_index('secondary', {unique=false,parts={1,'string'}})",
},
"blocks": {
"id_search": "blocks:create_index('id_search' , {type='tree' , parts={'block_id'}})",
"block_search": "blocks:create_index('block_search' , {type='tree', unique = false, parts={'height'}})",
"block_id_search": "blocks:create_index('block_id_search', {type = 'hash', parts ={'block_id'}})",
},
"blocks_tx": {
"id_search": "blocks_tx:create_index('id_search',{ type = 'tree', parts={'transaction_id'}})",
"block_search": "blocks_tx:create_index('block_search', {type = 'tree',unique=false, parts={'block_id'}})",
},
"elections": {
"id_search": "elections:create_index('id_search' , {type='tree', parts={'election_id'}})",
"height_search": "elections:create_index('height_search' , {type='tree',unique=false, parts={'height'}})",
"update_search": "elections:create_index('update_search', {type='tree', unique=false, parts={'election_id', 'height'}})", # noqa: E501
},
"meta_data": {
"id_search": "meta_datas:create_index('id_search', { type='tree' , parts={'transaction_id'}})",
"text_search": "meta_datas:create_index('secondary', {unique=false,parts={2,'string'}})",
},
"pre_commits": {
"id_search": "pre_commits:create_index('id_search', {type ='tree' , parts={'commit_id'}})",
"height_search": "pre_commits:create_index('height_search', {type ='tree',unique=true, parts={'height'}})",
},
"validators": {
"id_search": "validators:create_index('id_search' , {type='tree' , parts={'validator_id'}})",
"height_search": "validators:create_index('height_search' , {type='tree', unique=true, parts={'height'}})",
},
"transactions": {
"id_search": "transactions:create_index('id_search' , {type = 'tree' , parts={'transaction_id'}})",
"transaction_search": "transactions:create_index('transaction_search' , {type = 'tree',unique=false, parts={'operation', 'transaction_id'}})", # noqa: E501
},
"inputs": {
"delete_search": "inputs:create_index('delete_search' , {type = 'tree', parts={'input_id'}})",
"spent_search": "inputs:create_index('spent_search' , {type = 'tree', unique=false, parts={'fulfills_transaction_id', 'fulfills_output_index'}})", # noqa: E501
"id_search": "inputs:create_index('id_search', {type = 'tree', unique=false, parts = {'transaction_id'}})",
},
"outputs": {
"unique_search": "outputs:create_index('unique_search' ,{type='tree', parts={'output_id'}})",
"id_search": "outputs:create_index('id_search' ,{type='tree', unique=false, parts={'transaction_id'}})",
},
"keys": {
"id_search": "keys:create_index('id_search', {type = 'tree', parts={'id'}})",
"keys_search": "keys:create_index('keys_search', {type = 'tree', unique=false, parts={'public_key'}})",
"txid_search": "keys:create_index('txid_search', {type = 'tree', unique=false, parts={'transaction_id'}})",
"output_search": "keys:create_index('output_search', {type = 'tree', unique=false, parts={'output_id'}})",
},
"utxos": {
"id_search": "utxos:create_index('id_search', {type='tree' , parts={'transaction_id', 'output_index'}})",
"transaction_search": "utxos:create_index('transaction_search', {type='tree', unique=false, parts={'transaction_id'}})", # noqa: E501
"index_Search": "utxos:create_index('index_search', {type='tree', unique=false, parts={'output_index'}})",
},
"scripts": {
"txid_search": "scripts:create_index('txid_search', {type='tree', parts={'transaction_id'}})",
},
}
SCHEMA_COMMANDS = {
"abci_chains": "abci_chains:format({{name='height' , type='integer'},{name='is_synched' , type='boolean'},{name='chain_id',type='string'}, {name='id', type='string'}})", # noqa: E501
"assets": "assets:format({{name='data' , type='string'}, {name='tx_id', type='string'}, {name='asset_id', type='string'}})", # noqa: E501
"blocks": "blocks:format{{name='app_hash',type='string'},{name='height' , type='integer'},{name='block_id' , type='string'}}", # noqa: E501
"blocks_tx": "blocks_tx:format{{name='transaction_id', type = 'string'}, {name = 'block_id', type = 'string'}}",
"elections": "elections:format({{name='election_id' , type='string'},{name='height' , type='integer'}, {name='is_concluded' , type='boolean'}})", # noqa: E501
"meta_data": "meta_datas:format({{name='transaction_id' , type='string'}, {name='meta_data' , type='string'}})", # noqa: E501
"pre_commits": "pre_commits:format({{name='commit_id', type='string'}, {name='height',type='integer'}, {name='transactions',type=any}})", # noqa: E501
"validators": "validators:format({{name='validator_id' , type='string'},{name='height',type='integer'},{name='validators' , type='any'}})", # noqa: E501
"transactions": "transactions:format({{name='transaction_id' , type='string'}, {name='operation' , type='string'}, {name='version' ,type='string'}, {name='dict_map', type='any'}})", # noqa: E501
"inputs": "inputs:format({{name='transaction_id' , type='string'}, {name='fulfillment' , type='any'}, {name='owners_before' , type='array'}, {name='fulfills_transaction_id', type = 'string'}, {name='fulfills_output_index', type = 'string'}, {name='input_id', type='string'}, {name='input_index', type='number'}})", # noqa: E501
"outputs": "outputs:format({{name='transaction_id' , type='string'}, {name='amount' , type='string'}, {name='uri', type='string'}, {name='details_type', type='string'}, {name='details_public_key', type='any'}, {name = 'output_id', type = 'string'}, {name='treshold', type='any'}, {name='subconditions', type='any'}, {name='output_index', type='number'}})", # noqa: E501
"keys": "keys:format({{name = 'id', type='string'}, {name = 'transaction_id', type = 'string'} ,{name = 'output_id', type = 'string'}, {name = 'public_key', type = 'string'}, {name = 'key_index', type = 'integer'}})", # noqa: E501
"utxos": "utxos:format({{name='transaction_id' , type='string'}, {name='output_index' , type='integer'}, {name='utxo_dict', type='string'}})", # noqa: E501
"scripts": "scripts:format({{name='transaction_id', type='string'},{name='script' , type='any'}})", # noqa: E501
}
SCHEMA_DROP_COMMANDS = {
"abci_chains": "box.space.abci_chains:drop()",
"assets": "box.space.assets:drop()",
"blocks": "box.space.blocks:drop()",
"blocks_tx": "box.space.blocks_tx:drop()",
"elections": "box.space.elections:drop()",
"meta_data": "box.space.meta_data:drop()",
"pre_commits": "box.space.pre_commits:drop()",
"validators": "box.space.validators:drop()",
"transactions": "box.space.transactions:drop()",
"inputs": "box.space.inputs:drop()",
"outputs": "box.space.outputs:drop()",
"keys": "box.space.keys:drop()",
"utxos": "box.space.utxos: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):

View File

@ -196,7 +196,7 @@ def run_election_approve(args, planet):
""" """
key = load_node_key(args.sk) 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] voting_powers = [v.amount for v in tx.outputs if key.public_key in v.public_keys]
if len(voting_powers) > 0: if len(voting_powers) > 0:
voting_power = voting_powers[0] voting_power = voting_powers[0]
@ -230,7 +230,7 @@ def run_election_show(args, planet):
:param planet: an instance of Planetmint :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: if not election:
logger.error(f"No election found with election_id {args.election_id}") logger.error(f"No election found with election_id {args.election_id}")
return return

View File

@ -163,8 +163,8 @@ class Planetmint(object):
else: else:
txns.append(transaction) txns.append(transaction)
backend.query.store_transactions(self.connection, txns) backend.query.store_transactions(self.connection, txns, TARANT_TABLE_TRANSACTION)
backend.query.store_governance_transactions(self.connection, gov_txns) backend.query.store_transactions(self.connection, gov_txns, TARANT_TABLE_GOVERNANCE)
def delete_transactions(self, txs): def delete_transactions(self, txs):
return backend.query.delete_transactions(self.connection, txs) return backend.query.delete_transactions(self.connection, txs)
@ -245,12 +245,12 @@ class Planetmint(object):
if unspent_outputs: if unspent_outputs:
return backend.query.delete_unspent_outputs(self.connection, *unspent_outputs) return backend.query.delete_unspent_outputs(self.connection, *unspent_outputs)
def is_committed(self, transaction_id, table=TARANT_TABLE_TRANSACTION): def is_committed(self, transaction_id):
transaction = backend.query.get_transaction_by_id(self.connection, transaction_id, table) transaction = backend.query.get_transaction_single(self.connection, transaction_id)
return bool(transaction) return bool(transaction)
def get_transaction(self, transaction_id, table=TARANT_TABLE_TRANSACTION): def get_transaction(self, transaction_id):
return backend.query.get_transaction_single(self.connection, transaction_id, table) return backend.query.get_transaction_single(self.connection, transaction_id)
def get_transactions(self, txn_ids): def get_transactions(self, txn_ids):
return backend.query.get_transactions(self.connection, txn_ids) return backend.query.get_transactions(self.connection, txn_ids)
@ -261,9 +261,6 @@ class Planetmint(object):
for txid in txids: for txid in txids:
yield self.get_transaction(txid) 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): def get_outputs_by_tx_id(self, txid):
return backend.query.get_outputs_by_tx_id(self.connection, txid) return backend.query.get_outputs_by_tx_id(self.connection, txid)
@ -390,13 +387,9 @@ class Planetmint(object):
input_txs = [] input_txs = []
input_conditions = [] input_conditions = []
table = TARANT_TABLE_TRANSACTION
if tx.operation in GOVERNANCE_TRANSACTION_TYPES:
table = TARANT_TABLE_GOVERNANCE
for input_ in tx.inputs: for input_ in tx.inputs:
input_txid = input_.fulfills.txid 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) _output = self.get_outputs_by_tx_id(input_txid)
if input_tx is None: if input_tx is None:
for ctxn in current_transactions: for ctxn in current_transactions:
@ -430,7 +423,7 @@ class Planetmint(object):
# validate asset id # validate asset id
asset_id = tx.get_asset_id(input_txs) asset_id = tx.get_asset_id(input_txs)
if asset_id != tx.assets[0]["id"]: if asset_id != Transaction.read_out_asset_id(tx):
raise AssetIdMismatch(("The asset id of the input does not" " match the asset id of the" " transaction")) raise AssetIdMismatch(("The asset id of the input does not" " match the asset id of the" " transaction"))
# convert planetmint.Output objects to transactions.common.Output objects # convert planetmint.Output objects to transactions.common.Output objects
@ -614,7 +607,7 @@ class Planetmint(object):
""" """
duplicates = any(txn for txn in current_transactions if txn.id == transaction.id) 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)) raise DuplicateTransaction("transaction `{}` already exists".format(transaction.id))
current_validators = self.get_validators_dict() current_validators = self.get_validators_dict()
@ -823,7 +816,7 @@ class Planetmint(object):
validator_update = None validator_update = None
for election_id, votes in elections.items(): 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: if election is None:
continue continue

View File

@ -3,8 +3,8 @@
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0 # Code is Apache-2.0 and docs are CC-BY-4.0
__version__ = "1.3.2" __version__ = "1.4.1"
__short_version__ = "1.3" __short_version__ = "1.4"
# Supported Tendermint versions # Supported Tendermint versions
__tm_supported_versions__ = ["0.34.15"] __tm_supported_versions__ = ["0.34.15"]

View File

@ -92,6 +92,13 @@ class TransactionListApi(Resource):
except ValidationError as e: except ValidationError as e:
return make_error(400, "Invalid transaction ({}): {}".format(type(e).__name__, e)) return make_error(400, "Invalid transaction ({}): {}".format(type(e).__name__, e))
else: else:
if tx_obj.version != Transaction.VERSION:
return make_error(
401,
"Invalid transaction version: The transaction is valid, \
but this node only accepts transaction with higher \
schema version number.",
)
status_code, message = planet.write_transaction(tx_obj, mode) status_code, message = planet.write_transaction(tx_obj, mode)
if status_code == 202: if status_code == 202:

View File

@ -103,7 +103,6 @@ tests_require = [
"pytest-flask", "pytest-flask",
"pytest-aiohttp", "pytest-aiohttp",
"pytest-asyncio", "pytest-asyncio",
"tox",
] + docs_require ] + docs_require
install_requires = [ install_requires = [
@ -130,7 +129,7 @@ install_requires = [
"planetmint-ipld>=0.0.3", "planetmint-ipld>=0.0.3",
"pyasn1>=0.4.8", "pyasn1>=0.4.8",
"python-decouple", "python-decouple",
# "planetmint-transactions>=0.2.2", "planetmint-transactions>=0.5.0",
] ]
setup( setup(

View File

@ -9,7 +9,7 @@ from transactions.types.assets.create import Create
from transactions.types.assets.transfer import Transfer from transactions.types.assets.transfer import Transfer
def test_asset_transfer(b, signed_create_tx, user_pk, user_sk): def test_asset_transfer(b, signed_create_tx, user_pk, user_sk, _bdb):
tx_transfer = Transfer.generate(signed_create_tx.to_inputs(), [([user_pk], 1)], [signed_create_tx.id]) tx_transfer = Transfer.generate(signed_create_tx.to_inputs(), [([user_pk], 1)], [signed_create_tx.id])
tx_transfer_signed = tx_transfer.sign([user_sk]) tx_transfer_signed = tx_transfer.sign([user_sk])
@ -24,7 +24,7 @@ def test_asset_transfer(b, signed_create_tx, user_pk, user_sk):
# from planetmint.transactions.common.exceptions import AssetIdMismatch # from planetmint.transactions.common.exceptions import AssetIdMismatch
def test_validate_transfer_asset_id_mismatch(b, signed_create_tx, user_pk, user_sk): def test_validate_transfer_asset_id_mismatch(b, signed_create_tx, user_pk, user_sk, _bdb):
from transactions.common.exceptions import AssetIdMismatch from transactions.common.exceptions import AssetIdMismatch
tx_transfer = Transfer.generate(signed_create_tx.to_inputs(), [([user_pk], 1)], [signed_create_tx.id]) tx_transfer = Transfer.generate(signed_create_tx.to_inputs(), [([user_pk], 1)], [signed_create_tx.id])
@ -69,7 +69,23 @@ def test_asset_id_mismatch(alice, user_pk):
Transaction.get_asset_id([tx1, tx2]) Transaction.get_asset_id([tx1, tx2])
def test_create_valid_divisible_asset(b, user_pk, user_sk): def test_create_valid_divisible_asset(b, user_pk, user_sk, _bdb):
tx = Create.generate([user_pk], [([user_pk], 2)]) tx = Create.generate([user_pk], [([user_pk], 2)])
tx_signed = tx.sign([user_sk]) tx_signed = tx.sign([user_sk])
assert b.validate_transaction(tx_signed) == tx_signed assert b.validate_transaction(tx_signed) == tx_signed
def test_v_2_0_validation_create(b, signed_2_0_create_tx, _bdb):
validated = b.validate_transaction(signed_2_0_create_tx)
assert validated.to_dict() == signed_2_0_create_tx
def test_v_2_0_validation_create_invalid(b, signed_2_0_create_tx_assets, _bdb):
assert b.validate_transaction(signed_2_0_create_tx_assets)
def test_v_2_0_validation_transfer(b, signed_2_0_create_tx, signed_2_0_transfer_tx, _bdb):
validated = b.validate_transaction(signed_2_0_create_tx)
b.store_bulk_transactions([validated])
assert validated.to_dict() == signed_2_0_create_tx
assert b.validate_transaction(signed_2_0_transfer_tx).to_dict() == signed_2_0_transfer_tx

View File

@ -3,8 +3,6 @@
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0 # Code is Apache-2.0 and docs are CC-BY-4.0
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 = []

View File

@ -7,7 +7,7 @@ import pytest
def test_get_connection_raises_a_configuration_error(monkeypatch): def test_get_connection_raises_a_configuration_error(monkeypatch):
from planetmint.backend.connection import ConnectionError from planetmint.backend.exceptions import ConnectionError
from planetmint.backend.tarantool.connection import TarantoolDBConnection from planetmint.backend.tarantool.connection import TarantoolDBConnection
with pytest.raises(ConnectionError): with pytest.raises(ConnectionError):

View File

@ -14,7 +14,6 @@ from planetmint import ValidatorElection
from planetmint.commands.planetmint import run_election_show from planetmint.commands.planetmint import run_election_show
from planetmint.commands.planetmint import run_election_new_chain_migration from planetmint.commands.planetmint import run_election_new_chain_migration
from planetmint.backend.connection import Connection from planetmint.backend.connection import Connection
from planetmint.backend.tarantool.const import TARANT_TABLE_GOVERNANCE
from planetmint.lib import Block from planetmint.lib import Block
from transactions.types.elections.chain_migration_election import ChainMigrationElection 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) 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 @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): with caplog.at_level(logging.INFO):
election_id = run_election_new_upsert_validator(args, b) election_id = run_election_new_upsert_validator(args, b)
assert caplog.records[0].msg == "[SUCCESS] Submitted proposal with id: " + election_id 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 @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) 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 @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): with caplog.at_level(logging.INFO):
election_id = run_election_new_chain_migration(args, b) election_id = run_election_new_chain_migration(args, b)
assert caplog.records[0].msg == "[SUCCESS] Submitted proposal with id: " + election_id 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 @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={}) args = Namespace(action="approve", election_id=election_id, sk=priv_validator_path, config={})
approve = run_election_approve(args, b) approve = run_election_approve(args, b)
assert b.get_transaction(approve, TARANT_TABLE_GOVERNANCE) assert b.get_transaction(approve)
@pytest.mark.bdb @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): with caplog.at_level(logging.INFO):
approval_id = run_election_approve(args, b) approval_id = run_election_approve(args, b)
assert caplog.records[0].msg == "[SUCCESS] Your vote has been submitted" 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 @pytest.mark.bdb

View File

@ -27,7 +27,6 @@ from transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT
from planetmint.tendermint_utils import key_from_base64 from planetmint.tendermint_utils import key_from_base64
from planetmint.backend import schema, query from planetmint.backend import schema, query
from transactions.common.crypto import key_pair_from_ed25519_key, public_key_from_ed25519_key from transactions.common.crypto import key_pair_from_ed25519_key, public_key_from_ed25519_key
from transactions.common.exceptions import DatabaseDoesNotExist
from planetmint.lib import Block from planetmint.lib import Block
from tests.utils import gen_vote from tests.utils import gen_vote
from planetmint.config import Config from planetmint.config import Config
@ -736,3 +735,110 @@ def generate_votes(election, voters, keys):
v = gen_vote(election, voter, keys) v = gen_vote(election, voter, keys)
votes.append(v) votes.append(v)
return votes return votes
@pytest.fixture
def signed_2_0_create_tx():
return {
"inputs": [
{
"owners_before": ["7WaJCRqUJMZjVyQxqq8GNjkw11gacFmDAZGPLdNxfBgx"],
"fulfills": None,
"fulfillment": "pGSAIGC5nQ37hCCMAWIUBAJn4wVBOkHlURaWzWLjE5rTzG91gUC0Akx2m_AoPy1H6yTz7Ou2I-OGjNjWgvR5EATn8XZ1u-g91XL3CkSXXiL2sUJqDibJQJjGZjag_7fRu5_VkDUD",
}
],
"outputs": [
{
"public_keys": ["7WaJCRqUJMZjVyQxqq8GNjkw11gacFmDAZGPLdNxfBgx"],
"condition": {
"details": {
"type": "ed25519-sha-256",
"public_key": "7WaJCRqUJMZjVyQxqq8GNjkw11gacFmDAZGPLdNxfBgx",
},
"uri": "ni:///sha-256;xtKK2YRiX7_EPF2harsf-PELcJwfHQM7jZ_YvilEOOI?fpt=ed25519-sha-256&cost=131072",
},
"amount": "3000",
}
],
"operation": "CREATE",
"metadata": "QmRBri4SARi56PgB2ALFVjHsLhQDUh4jYbeiHaU94vLoxd",
"asset": {"data": "QmW5GVMW98D3mktSDfWHS8nX2UiCd8gP1uCiujnFX4yK8n"},
"version": "2.0",
"id": "334014a29d99a488789c711b7dc5fceb534d1a9290b14d0270dbe6b60e2f036e",
}
@pytest.fixture
def signed_2_0_create_tx_assets():
return {
"inputs": [
{
"owners_before": ["5V4AANHTSLdQH1mEA1pohW3jMduY9xMJ1voos7gRfMQF"],
"fulfills": None,
"fulfillment": "pGSAIEKelMEu8AzcA9kcDLrsEXhSpZG-lf2c9CuZpzZU_ONkgUBMztcnweWqwHVfVk9Y-IRgfdh864yXYTrTKzSMy6uvNjQeLtGzKxz4gjb01NUu6WLvZBAvr0Ws4glfxKiDLjkP",
}
],
"outputs": [
{
"public_keys": ["5V4AANHTSLdQH1mEA1pohW3jMduY9xMJ1voos7gRfMQF"],
"condition": {
"details": {
"type": "ed25519-sha-256",
"public_key": "5V4AANHTSLdQH1mEA1pohW3jMduY9xMJ1voos7gRfMQF",
},
"uri": "ni:///sha-256;M3l9yVs7ItjP-lxT7B2ta6rpRa-GHt6TBSYpy8l-IS8?fpt=ed25519-sha-256&cost=131072",
},
"amount": "3000",
}
],
"operation": "CREATE",
"metadata": "QmRBri4SARi56PgB2ALFVjHsLhQDUh4jYbeiHaU94vLoxd",
"assets": {"data": "QmW5GVMW98D3mktSDfWHS8nX2UiCd8gP1uCiujnFX4yK8n"},
"version": "2.0",
"id": "3e2a2c5eef5e6a0c4e1e5f8d0dc1d3d9b4f035592a9788f8bfa7d59f86d123d3",
}
@pytest.fixture
def signed_2_0_transfer_tx():
return {
"inputs": [
{
"owners_before": ["7WaJCRqUJMZjVyQxqq8GNjkw11gacFmDAZGPLdNxfBgx"],
"fulfills": {
"transaction_id": "334014a29d99a488789c711b7dc5fceb534d1a9290b14d0270dbe6b60e2f036e",
"output_index": 0,
},
"fulfillment": "pGSAIGC5nQ37hCCMAWIUBAJn4wVBOkHlURaWzWLjE5rTzG91gUBHNp8jobEyMqcIcIFl-TaAEDHRMyigDutgCIIomyVgb1a0LIk5eEpMTVP4ACxZnrVH-SIKEDHNdH4FGyBMka4B",
}
],
"outputs": [
{
"public_keys": ["3m1tUV5hmWPBaNQEoyFtZxFgDFiHYAYvPMzczNHwWp5v"],
"condition": {
"details": {
"type": "ed25519-sha-256",
"public_key": "3m1tUV5hmWPBaNQEoyFtZxFgDFiHYAYvPMzczNHwWp5v",
},
"uri": "ni:///sha-256;4pXSmxViATpOG8Mcc0gYsa-4bjRnLk5MY06VXv_UeJA?fpt=ed25519-sha-256&cost=131072",
},
"amount": "50",
},
{
"public_keys": ["7WaJCRqUJMZjVyQxqq8GNjkw11gacFmDAZGPLdNxfBgx"],
"condition": {
"details": {
"type": "ed25519-sha-256",
"public_key": "7WaJCRqUJMZjVyQxqq8GNjkw11gacFmDAZGPLdNxfBgx",
},
"uri": "ni:///sha-256;xtKK2YRiX7_EPF2harsf-PELcJwfHQM7jZ_YvilEOOI?fpt=ed25519-sha-256&cost=131072",
},
"amount": "2950",
},
],
"operation": "TRANSFER",
"metadata": "QmTjWHzypFxE8uuXJXMJQJxgAEKjoWmQimGiutmPyJ6CAB",
"asset": {"id": "334014a29d99a488789c711b7dc5fceb534d1a9290b14d0270dbe6b60e2f036e"},
"version": "2.0",
"id": "e577641b0e2eb619e282f802516ce043e9d4af51dd4b6c959e18246e85cae2a6",
}

View File

@ -50,7 +50,6 @@ class TestBigchainApi(object):
with pytest.raises(CriticalDoubleSpend): with pytest.raises(CriticalDoubleSpend):
b.store_bulk_transactions([transfer_tx2]) b.store_bulk_transactions([transfer_tx2])
def test_double_inclusion(self, b, alice): def test_double_inclusion(self, b, alice):
from tarantool.error import DatabaseError from tarantool.error import DatabaseError

View File

@ -411,7 +411,7 @@ def test_rollback_pre_commit_state_after_crash(b):
rollback(b) rollback(b)
for tx in txs: 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 b.get_latest_abci_chain()
assert len(b.get_validator_set()["validators"]) == 1 assert len(b.get_validator_set()["validators"]) == 1
assert b.get_election(migration_election.id) assert b.get_election(migration_election.id)
@ -422,7 +422,7 @@ def test_rollback_pre_commit_state_after_crash(b):
rollback(b) rollback(b)
for tx in txs: 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 not b.get_latest_abci_chain()
assert len(b.get_validator_set()["validators"]) == 4 assert len(b.get_validator_set()["validators"]) == 4
assert len(b.get_validator_set(2)["validators"]) == 4 assert len(b.get_validator_set(2)["validators"]) == 4

View File

@ -170,69 +170,21 @@ def test_update_utxoset(b, signed_create_tx, signed_transfer_tx, db_conn):
@pytest.mark.bdb @pytest.mark.bdb
def test_store_transaction(mocker, b, signed_create_tx, signed_transfer_tx, db_context): def test_store_transaction(mocker, b, signed_create_tx, signed_transfer_tx):
from planetmint.backend.tarantool.connection import TarantoolDBConnection
mocked_store_transaction = mocker.patch("planetmint.backend.query.store_transactions") mocked_store_transaction = mocker.patch("planetmint.backend.query.store_transactions")
b.store_bulk_transactions([signed_create_tx]) b.store_bulk_transactions([signed_create_tx])
if not isinstance(b.connection, TarantoolDBConnection): mocked_store_transaction.assert_any_call(b.connection, [signed_create_tx.to_dict()], "transactions")
mongo_client = MongoClient(host=db_context.host, port=db_context.port)
utxoset = mongo_client[db_context.name]["utxos"]
assert utxoset.count_documents({}) == 1
utxo = utxoset.find_one()
assert utxo["transaction_id"] == signed_create_tx.id
assert utxo["output_index"] == 0
mocked_store_transaction.assert_called_once_with(
b.connection,
[signed_create_tx.to_dict()],
)
mocked_store_transaction.reset_mock() mocked_store_transaction.reset_mock()
b.store_bulk_transactions([signed_transfer_tx]) b.store_bulk_transactions([signed_transfer_tx])
if not isinstance(b.connection, TarantoolDBConnection):
assert utxoset.count_documents({}) == 1
utxo = utxoset.find_one()
assert utxo["transaction_id"] == signed_transfer_tx.id
assert utxo["output_index"] == 0
if not isinstance(b.connection, TarantoolDBConnection):
mocked_store_transaction.assert_called_once_with(
b.connection,
[signed_transfer_tx.to_dict()],
)
@pytest.mark.bdb @pytest.mark.bdb
def test_store_bulk_transaction(mocker, b, signed_create_tx, signed_transfer_tx, db_context): def test_store_bulk_transaction(mocker, b, signed_create_tx, signed_transfer_tx):
from planetmint.backend.tarantool.connection import TarantoolDBConnection
mocked_store_transactions = mocker.patch("planetmint.backend.query.store_transactions") mocked_store_transactions = mocker.patch("planetmint.backend.query.store_transactions")
b.store_bulk_transactions((signed_create_tx,)) b.store_bulk_transactions((signed_create_tx,))
if not isinstance(b.connection, TarantoolDBConnection): mocked_store_transactions.assert_any_call(b.connection, [signed_create_tx.to_dict()], "transactions")
mongo_client = MongoClient(host=db_context.host, port=db_context.port)
utxoset = mongo_client[db_context.name]["utxos"]
assert utxoset.count_documents({}) == 1
utxo = utxoset.find_one()
assert utxo["transaction_id"] == signed_create_tx.id
assert utxo["output_index"] == 0
mocked_store_transactions.assert_called_once_with(
b.connection,
[signed_create_tx.to_dict()],
)
mocked_store_transactions.reset_mock() mocked_store_transactions.reset_mock()
b.store_bulk_transactions((signed_transfer_tx,)) b.store_bulk_transactions((signed_transfer_tx,))
if not isinstance(b.connection, TarantoolDBConnection):
assert utxoset.count_documents({}) == 1
utxo = utxoset.find_one()
assert utxo["transaction_id"] == signed_transfer_tx.id
assert utxo["output_index"] == 0
if not isinstance(b.connection, TarantoolDBConnection):
mocked_store_transactions.assert_called_once_with(
b.connection,
[signed_transfer_tx.to_dict()],
)
@pytest.mark.bdb @pytest.mark.bdb

View File

@ -89,7 +89,7 @@ def test_get_spent_issue_1271(b, alice, bob, carol):
assert b.validate_transaction(tx_5) assert b.validate_transaction(tx_5)
b.store_bulk_transactions([tx_5]) b.store_bulk_transactions([tx_5])
assert b.get_spent(tx_2.id, 0) == tx_5.to_dict() assert b.get_spent(tx_2.id, 0) == tx_5.to_dict()
assert not b.get_spent(tx_5.id, 0) assert not b.get_spent(tx_5.id, 0)
assert b.get_outputs_filtered(alice.public_key) assert b.get_outputs_filtered(alice.public_key)
assert b.get_outputs_filtered(alice.public_key, spent=False) assert b.get_outputs_filtered(alice.public_key, spent=False)

View File

@ -248,7 +248,7 @@ def test_upsert_validator(b, node_key, node_keys, ed25519_node_keys):
) )
code, message = b.write_transaction(election, BROADCAST_TX_COMMIT) code, message = b.write_transaction(election, BROADCAST_TX_COMMIT)
assert code == 202 assert code == 202
assert b.get_transaction(election.id, TARANT_TABLE_GOVERNANCE) assert b.get_transaction(election.id)
tx_vote = gen_vote(election, 0, ed25519_node_keys) tx_vote = gen_vote(election, 0, ed25519_node_keys)
assert b.validate_transaction(tx_vote) assert b.validate_transaction(tx_vote)

View File

@ -10,7 +10,7 @@ import random
from functools import singledispatch from functools import singledispatch
from planetmint.backend.localmongodb.connection import LocalMongoDBConnection from planetmint.backend.localmongodb.connection import LocalMongoDBConnection
from planetmint.backend.tarantool.connection import TarantoolDBConnection from planetmint.backend.tarantool.connection import TarantoolDBConnection
from planetmint.backend.schema import TABLES, SPACE_NAMES from planetmint.backend.schema import TABLES
from transactions.common import crypto from transactions.common import crypto
from transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT from transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT
from transactions.types.assets.create import Create from transactions.types.assets.create import Create
@ -40,7 +40,9 @@ def generate_block(planet):
from transactions.common.crypto import generate_key_pair from transactions.common.crypto import generate_key_pair
alice = generate_key_pair() alice = generate_key_pair()
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], assets=[{"data":None}]).sign([alice.private_key]) tx = Create.generate([alice.public_key], [([alice.public_key], 1)], assets=[{"data": None}]).sign(
[alice.private_key]
)
code, message = planet.write_transaction(tx, BROADCAST_TX_COMMIT) code, message = planet.write_transaction(tx, BROADCAST_TX_COMMIT)
assert code == 202 assert code == 202

31
tox.ini
View File

@ -1,31 +0,0 @@
[tox]
skipsdist = true
envlist = py{39}, docsroot
[gh-actions]
python =
3.9 = docsroot
[base]
basepython = python3.9
deps = pip>=9.0.1
[testenv]
usedevelop = True
setenv =
PYTHONPATH={toxinidir}:{toxinidir}/planetmint
deps = {[base]deps}
install_command = pip install {opts} {packages}
extras = test
commands = pytest -v -n auto --cov=planetmint --basetemp={envtmpdir}
[testenv:docsroot]
basepython = {[base]basepython}
changedir = docs/root/source
deps =
{[base]deps}
typing-extensions
-r{toxinidir}/docs/root/requirements.txt
extras = None
commands = sphinx-build -b html -d {envtmpdir}/doctrees . {envtmpdir}/html