mirror of
https://github.com/planetmint/planetmint.git
synced 2025-06-07 14:46:38 +00:00
Connection singleton (#265)
Created a Singleton for the connection classes.
This commit is contained in:
parent
e401995637
commit
713bd5267c
59
.github/workflows/unit-test-abci.yml
vendored
Normal file
59
.github/workflows/unit-test-abci.yml
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# 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: Unit tests - with direct ABCI
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Build container
|
||||||
|
run: |
|
||||||
|
docker-compose -f docker-compose.yml build --no-cache --build-arg abci_status=enable planetmint
|
||||||
|
|
||||||
|
- name: Save image
|
||||||
|
run: docker save -o planetmint.tar planetmint_planetmint
|
||||||
|
|
||||||
|
- name: Upload image
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: planetmint-abci
|
||||||
|
path: planetmint.tar
|
||||||
|
retention-days: 5
|
||||||
|
|
||||||
|
|
||||||
|
test-with-abci:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- db: "Tarantool with ABCI"
|
||||||
|
host: "tarantool"
|
||||||
|
port: 3303
|
||||||
|
abci: "enabled"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Download planetmint
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: planetmint-abci
|
||||||
|
|
||||||
|
- name: Load planetmint
|
||||||
|
run: docker load -i planetmint.tar
|
||||||
|
|
||||||
|
- name: Start containers
|
||||||
|
run: docker-compose -f docker-compose.yml up -d planetmint
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: docker exec planetmint_planetmint_1 pytest -v -m abci
|
60
.github/workflows/unit-test-no-abci.yml
vendored
Normal file
60
.github/workflows/unit-test-no-abci.yml
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# 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: Unit tests - with Planemint
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Build container
|
||||||
|
run: |
|
||||||
|
docker-compose -f docker-compose.yml build --no-cache planetmint
|
||||||
|
|
||||||
|
- name: Save image
|
||||||
|
run: docker save -o planetmint.tar planetmint_planetmint
|
||||||
|
|
||||||
|
- name: Upload image
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: planetmint
|
||||||
|
path: planetmint.tar
|
||||||
|
retention-days: 5
|
||||||
|
|
||||||
|
|
||||||
|
test-without-abci:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- db: "Tarantool without ABCI"
|
||||||
|
host: "tarantool"
|
||||||
|
port: 3303
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Download planetmint
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: planetmint
|
||||||
|
|
||||||
|
- name: Load planetmint
|
||||||
|
run: docker load -i planetmint.tar
|
||||||
|
|
||||||
|
- name: Start containers
|
||||||
|
run: docker-compose -f docker-compose.yml up -d bdb
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: docker exec planetmint_planetmint_1 pytest -v --cov=planetmint --cov-report xml:htmlcov/coverage.xml
|
||||||
|
|
||||||
|
- name: Upload Coverage to Codecov
|
||||||
|
uses: codecov/codecov-action@v3
|
109
.github/workflows/unit-test.yml
vendored
109
.github/workflows/unit-test.yml
vendored
@ -1,109 +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: Unit tests
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- abci_enabled: "ABCI enabled"
|
|
||||||
abci: "enabled"
|
|
||||||
- abci_disabled: "ABCI disabled"
|
|
||||||
abci: "disabled"
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check out repository code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Build container
|
|
||||||
run: |
|
|
||||||
if [[ "${{ matrix.abci }}" == "enabled" ]]; then
|
|
||||||
docker-compose -f docker-compose.yml build --no-cache --build-arg abci_status=enable planetmint
|
|
||||||
fi
|
|
||||||
if [[ ""${{ matrix.abci }}" == "disabled"" ]]; then
|
|
||||||
docker-compose -f docker-compose.yml build --no-cache planetmint
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Save image
|
|
||||||
run: docker save -o planetmint.tar planetmint_planetmint
|
|
||||||
|
|
||||||
- name: Upload image
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: planetmint-abci-${{matrix.abci}}
|
|
||||||
path: planetmint.tar
|
|
||||||
retention-days: 5
|
|
||||||
|
|
||||||
|
|
||||||
test-with-abci:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- db: "MongoDB with ABCI"
|
|
||||||
host: "mongodb"
|
|
||||||
port: 27017
|
|
||||||
abci: "enabled"
|
|
||||||
- db: "Tarantool with ABCI"
|
|
||||||
host: "tarantool"
|
|
||||||
port: 3303
|
|
||||||
abci: "enabled"
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check out repository code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Download planetmint
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: planetmint-abci-enabled
|
|
||||||
|
|
||||||
- name: Load planetmint
|
|
||||||
run: docker load -i planetmint.tar
|
|
||||||
|
|
||||||
- name: Start containers
|
|
||||||
run: docker-compose -f docker-compose.yml up -d planetmint
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: docker exec planetmint_planetmint_1 pytest -v -m abci
|
|
||||||
|
|
||||||
test-without-abci:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- db: "MongoDB without ABCI"
|
|
||||||
host: "mongodb"
|
|
||||||
port: 27017
|
|
||||||
- db: "Tarantool without ABCI"
|
|
||||||
host: "tarantool"
|
|
||||||
port: 3303
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check out repository code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Download planetmint
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: planetmint-abci-disabled
|
|
||||||
|
|
||||||
- name: Load planetmint
|
|
||||||
run: docker load -i planetmint.tar
|
|
||||||
|
|
||||||
- name: Start containers
|
|
||||||
run: docker-compose -f docker-compose.yml up -d bdb
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: docker exec planetmint_planetmint_1 pytest -v --cov=planetmint --cov-report xml:htmlcov/coverage.xml
|
|
||||||
|
|
||||||
- name: Upload Coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v3
|
|
@ -33,6 +33,11 @@ For reference, the possible headings are:
|
|||||||
* **Changed** moved transaction network validation to Planetmint class
|
* **Changed** moved transaction network validation to Planetmint class
|
||||||
* **Changed** adjusted test cases
|
* **Changed** adjusted test cases
|
||||||
|
|
||||||
|
## [1.2.2] - 2022-23-09
|
||||||
|
* **Changed** A connection singleton got introduced to avoid connection issues and unstable states.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [1.2.1] - 2022-20-09
|
## [1.2.1] - 2022-20-09
|
||||||
* **Changed** Create model now validates for CID strings for asset["data"] and metadata
|
* **Changed** Create model now validates for CID strings for asset["data"] and metadata
|
||||||
* **Changed** adjusted test cases
|
* **Changed** adjusted test cases
|
||||||
|
@ -34,5 +34,4 @@ COPY . /usr/src/app/
|
|||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
RUN pip install -e .[dev]
|
RUN pip install -e .[dev]
|
||||||
RUN pip install flask-cors
|
RUN pip install flask-cors
|
||||||
RUN pip install pynacl==1.4.0 base58==2.1.1 pyasn1==0.4.8 zenroom==2.1.0.dev1655293214 cryptography==3.4.7
|
RUN pip install pynacl==1.4.0 base58==2.1.1 pyasn1==0.4.8 zenroom==2.1.0.dev1655293214 cryptography==3.4.7
|
||||||
RUN planetmint -y configure
|
|
@ -38,6 +38,34 @@ def test_zenroom_signing(
|
|||||||
zenroomscpt = ZenroomSha256(script=fulfill_script_zencode, data=zenroom_data, keys=zen_public_keys)
|
zenroomscpt = ZenroomSha256(script=fulfill_script_zencode, data=zenroom_data, keys=zen_public_keys)
|
||||||
print(f"zenroom is: {zenroomscpt.script}")
|
print(f"zenroom is: {zenroomscpt.script}")
|
||||||
|
|
||||||
|
|
||||||
|
def test_zenroom_signing(
|
||||||
|
gen_key_zencode,
|
||||||
|
secret_key_to_private_key_zencode,
|
||||||
|
fulfill_script_zencode,
|
||||||
|
zenroom_data,
|
||||||
|
zenroom_house_assets,
|
||||||
|
condition_script_zencode,
|
||||||
|
):
|
||||||
|
|
||||||
|
biolabs = generate_keypair()
|
||||||
|
version = "2.0"
|
||||||
|
|
||||||
|
alice = json.loads(zencode_exec(gen_key_zencode).output)["keyring"]
|
||||||
|
bob = json.loads(zencode_exec(gen_key_zencode).output)["keyring"]
|
||||||
|
|
||||||
|
zen_public_keys = json.loads(
|
||||||
|
zencode_exec(secret_key_to_private_key_zencode.format("Alice"), keys=json.dumps({"keyring": alice})).output
|
||||||
|
)
|
||||||
|
zen_public_keys.update(
|
||||||
|
json.loads(
|
||||||
|
zencode_exec(secret_key_to_private_key_zencode.format("Bob"), keys=json.dumps({"keyring": bob})).output
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
zenroomscpt = ZenroomSha256(script=fulfill_script_zencode, data=zenroom_data, keys=zen_public_keys)
|
||||||
|
print(f"zenroom is: {zenroomscpt.script}")
|
||||||
|
|
||||||
# CRYPTO-CONDITIONS: generate the condition uri
|
# CRYPTO-CONDITIONS: generate the condition uri
|
||||||
condition_uri_zen = zenroomscpt.condition.serialize_uri()
|
condition_uri_zen = zenroomscpt.condition.serialize_uri()
|
||||||
print(f"\nzenroom condition URI: {condition_uri_zen}")
|
print(f"\nzenroom condition URI: {condition_uri_zen}")
|
||||||
@ -73,6 +101,7 @@ def test_zenroom_signing(
|
|||||||
"output": ["ok"],
|
"output": ["ok"],
|
||||||
"policies": {},
|
"policies": {},
|
||||||
}
|
}
|
||||||
|
metadata = {"result": {"output": ["ok"]}}
|
||||||
|
|
||||||
token_creation_tx = {
|
token_creation_tx = {
|
||||||
"operation": "CREATE",
|
"operation": "CREATE",
|
||||||
|
@ -27,7 +27,7 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
planetmint:
|
planetmint:
|
||||||
depends_on:
|
depends_on:
|
||||||
#- mongodb
|
- mongodb
|
||||||
- tendermint
|
- tendermint
|
||||||
- tarantool
|
- tarantool
|
||||||
build:
|
build:
|
||||||
@ -124,4 +124,4 @@ services:
|
|||||||
image: alpine
|
image: alpine
|
||||||
command: /bin/sh -c "./planetmint/scripts/clean.sh"
|
command: /bin/sh -c "./planetmint/scripts/clean.sh"
|
||||||
volumes:
|
volumes:
|
||||||
- $PWD:/planetmint
|
- $PWD:/planetmint
|
||||||
|
@ -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.0.1/http-client-server-api.html",
|
"docs": "https://docs.planetmint.io/projects/server/en/v1.3.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",
|
||||||
|
@ -22,9 +22,7 @@ Content-Type: application/json
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": "QmZs4UHLHCUGLQr6rzbtJTjT8Sf5pw6FNuaRZ5pzguk5FV",
|
||||||
"sequence": 0
|
|
||||||
},
|
|
||||||
"operation": "CREATE",
|
"operation": "CREATE",
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -20,9 +20,7 @@ Content-Type: application/json
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": "QmQ9Sc3VWZ3nH5FWVVi2MNMDhyjTiKrEb6mN79qqt1Uq9s",
|
||||||
"sequence": 1
|
|
||||||
},
|
|
||||||
"operation": "TRANSFER",
|
"operation": "TRANSFER",
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
@ -60,9 +58,7 @@ Content-Type: application/json
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": "QmRRg9RGq3TmV6nj2SXJacPuTdwaFDGTPACJLdN368pN3t",
|
||||||
"sequence": 2
|
|
||||||
},
|
|
||||||
"operation": "TRANSFER",
|
"operation": "TRANSFER",
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -19,9 +19,7 @@ Content-Type: application/json
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": "QmZs4UHLHCUGLQr6rzbtJTjT8Sf5pw6FNuaRZ5pzguk5FV",
|
||||||
"sequence": 0
|
|
||||||
},
|
|
||||||
"operation": "CREATE",
|
"operation": "CREATE",
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -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.0.1/http-client-server-api.html",
|
"docs": "https://docs.planetmint.io/projects/server/en/v1.2.2/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.0.1/",
|
"docs": "https://docs.planetmint.io/projects/server/en/v1.2.2/",
|
||||||
"software": "Planetmint",
|
"software": "Planetmint",
|
||||||
"version": "1.0.1"
|
"version": "1.3.1"
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,7 @@ Content-Type: application/json
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": "QmZs4UHLHCUGLQr6rzbtJTjT8Sf5pw6FNuaRZ5pzguk5FV",
|
||||||
"sequence": 0
|
|
||||||
},
|
|
||||||
"operation": "CREATE",
|
"operation": "CREATE",
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -19,9 +19,7 @@ Content-Type: application/json
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": "QmZs4UHLHCUGLQr6rzbtJTjT8Sf5pw6FNuaRZ5pzguk5FV",
|
||||||
"sequence": 0
|
|
||||||
},
|
|
||||||
"operation": "CREATE",
|
"operation": "CREATE",
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -42,7 +42,7 @@ This Code of Conduct applies both within project spaces and in public spaces
|
|||||||
when an individual is representing the project or its community.
|
when an individual is representing the project or its community.
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior directed at yourself or another community member may be
|
Instances of abusive, harassing, or otherwise unacceptable behavior directed at yourself or another community member may be
|
||||||
reported by contacting a project maintainer at [mail@planetmint.io](mailto:mail@planetmint.io). All
|
reported by contacting a project maintainer at [mail@planetmint.io](mailto:contact@planetmint.io). All
|
||||||
complaints will be reviewed and investigated and will result in a response that
|
complaints will be reviewed and investigated and will result in a response that
|
||||||
is appropriate to the circumstances. Maintainers are
|
is appropriate to the circumstances. Maintainers are
|
||||||
obligated to maintain confidentiality with regard to the reporter of an
|
obligated to maintain confidentiality with regard to the reporter of an
|
||||||
|
@ -3,7 +3,6 @@ import base58
|
|||||||
from hashlib import sha3_256
|
from hashlib import sha3_256
|
||||||
from cryptoconditions.types.zenroom import ZenroomSha256
|
from cryptoconditions.types.zenroom import ZenroomSha256
|
||||||
from planetmint_driver.crypto import generate_keypair
|
from planetmint_driver.crypto import generate_keypair
|
||||||
|
|
||||||
from .helper.hosts import Hosts
|
from .helper.hosts import Hosts
|
||||||
from zenroom import zencode_exec
|
from zenroom import zencode_exec
|
||||||
import time
|
import time
|
||||||
@ -72,7 +71,7 @@ def test_zenroom_signing(
|
|||||||
"output": ["ok"],
|
"output": ["ok"],
|
||||||
"policies": {},
|
"policies": {},
|
||||||
}
|
}
|
||||||
|
metadata = {"result": {"output": ["ok"]}}
|
||||||
token_creation_tx = {
|
token_creation_tx = {
|
||||||
"operation": "CREATE",
|
"operation": "CREATE",
|
||||||
"asset": {"data": {"test": "my asset"}},
|
"asset": {"data": {"test": "my asset"}},
|
||||||
|
@ -13,4 +13,4 @@ configuration or the ``PLANETMINT_DATABASE_BACKEND`` environment variable.
|
|||||||
|
|
||||||
# Include the backend interfaces
|
# Include the backend interfaces
|
||||||
from planetmint.backend import schema, query, convert # noqa
|
from planetmint.backend import schema, query, convert # noqa
|
||||||
from planetmint.backend.connection import connect, Connection
|
from planetmint.backend.connection import Connection
|
||||||
|
@ -20,92 +20,54 @@ BACKENDS = {
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def connect(
|
|
||||||
host: str = None, port: int = None, login: str = None, password: str = None, backend: str = None, **kwargs
|
|
||||||
):
|
|
||||||
try:
|
|
||||||
backend = backend
|
|
||||||
if not backend and kwargs and kwargs.get("backend"):
|
|
||||||
backend = kwargs["backend"]
|
|
||||||
|
|
||||||
if backend and backend != Config().get()["database"]["backend"]:
|
|
||||||
Config().init_config(backend)
|
|
||||||
else:
|
|
||||||
backend = Config().get()["database"]["backend"]
|
|
||||||
except KeyError:
|
|
||||||
logger.info("Backend {} not supported".format(backend))
|
|
||||||
raise ConfigurationError
|
|
||||||
|
|
||||||
host = host or Config().get()["database"]["host"] if not kwargs.get("host") else kwargs["host"]
|
|
||||||
port = port or Config().get()["database"]["port"] if not kwargs.get("port") else kwargs["port"]
|
|
||||||
login = login or Config().get()["database"]["login"] if not kwargs.get("login") else kwargs["login"]
|
|
||||||
password = password or Config().get()["database"]["password"]
|
|
||||||
try:
|
|
||||||
if backend == "tarantool_db":
|
|
||||||
modulepath, _, class_name = BACKENDS[backend].rpartition(".")
|
|
||||||
Class = getattr(import_module(modulepath), class_name)
|
|
||||||
return Class(host=host, port=port, user=login, password=password, kwargs=kwargs)
|
|
||||||
elif backend == "localmongodb":
|
|
||||||
modulepath, _, class_name = BACKENDS[backend].rpartition(".")
|
|
||||||
Class = getattr(import_module(modulepath), class_name)
|
|
||||||
dbname = _kwargs_parser(key="name", kwargs=kwargs) or Config().get()["database"]["name"]
|
|
||||||
replicaset = _kwargs_parser(key="replicaset", kwargs=kwargs) or Config().get()["database"]["replicaset"]
|
|
||||||
ssl = _kwargs_parser(key="ssl", kwargs=kwargs) or Config().get()["database"]["ssl"]
|
|
||||||
login = (
|
|
||||||
login or Config().get()["database"]["login"]
|
|
||||||
if _kwargs_parser(key="login", kwargs=kwargs) is None
|
|
||||||
else _kwargs_parser(key="login", kwargs=kwargs) # noqa: E501
|
|
||||||
)
|
|
||||||
password = (
|
|
||||||
password or Config().get()["database"]["password"]
|
|
||||||
if _kwargs_parser(key="password", kwargs=kwargs) is None
|
|
||||||
else _kwargs_parser(key="password", kwargs=kwargs) # noqa: E501
|
|
||||||
)
|
|
||||||
ca_cert = _kwargs_parser(key="ca_cert", kwargs=kwargs) or Config().get()["database"]["ca_cert"]
|
|
||||||
certfile = _kwargs_parser(key="certfile", kwargs=kwargs) or Config().get()["database"]["certfile"]
|
|
||||||
keyfile = _kwargs_parser(key="keyfile", kwargs=kwargs) or Config().get()["database"]["keyfile"]
|
|
||||||
keyfile_passphrase = (
|
|
||||||
_kwargs_parser(key="keyfile_passphrase", kwargs=kwargs)
|
|
||||||
or Config().get()["database"]["keyfile_passphrase"]
|
|
||||||
)
|
|
||||||
crlfile = _kwargs_parser(key="crlfile", kwargs=kwargs) or Config().get()["database"]["crlfile"]
|
|
||||||
max_tries = _kwargs_parser(key="max_tries", kwargs=kwargs)
|
|
||||||
connection_timeout = _kwargs_parser(key="connection_timeout", kwargs=kwargs)
|
|
||||||
|
|
||||||
return Class(
|
|
||||||
host=host,
|
|
||||||
port=port,
|
|
||||||
dbname=dbname,
|
|
||||||
max_tries=max_tries,
|
|
||||||
connection_timeout=connection_timeout,
|
|
||||||
replicaset=replicaset,
|
|
||||||
ssl=ssl,
|
|
||||||
login=login,
|
|
||||||
password=password,
|
|
||||||
ca_cert=ca_cert,
|
|
||||||
certfile=certfile,
|
|
||||||
keyfile=keyfile,
|
|
||||||
keyfile_passphrase=keyfile_passphrase,
|
|
||||||
crlfile=crlfile,
|
|
||||||
)
|
|
||||||
except tarantool.error.NetworkError as network_err:
|
|
||||||
print(f"Host {host}:{port} can't be reached.\n{network_err}")
|
|
||||||
raise network_err
|
|
||||||
|
|
||||||
|
|
||||||
def _kwargs_parser(key, kwargs):
|
def _kwargs_parser(key, kwargs):
|
||||||
if kwargs.get(key):
|
if kwargs.get(key):
|
||||||
return kwargs[key]
|
return kwargs[key]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class Connection:
|
class DBSingleton(type):
|
||||||
|
_instances = {}
|
||||||
|
|
||||||
|
def __call__(cls, *args, **kwargs):
|
||||||
|
if cls not in cls._instances:
|
||||||
|
try:
|
||||||
|
backend = kwargs.get("backend") if kwargs and kwargs.get("backend") else None
|
||||||
|
if backend is not None and backend != Config().get()["database"]["backend"]:
|
||||||
|
Config().init_config(backend)
|
||||||
|
else:
|
||||||
|
backend = Config().get()["database"]["backend"]
|
||||||
|
except KeyError:
|
||||||
|
logger.info("Backend {} not supported".format(backend))
|
||||||
|
raise ConfigurationError
|
||||||
|
modulepath, _, class_name = BACKENDS[backend].rpartition(".")
|
||||||
|
Class = getattr(import_module(modulepath), class_name)
|
||||||
|
cls._instances[cls] = super(DBSingleton, Class).__call__(*args, **kwargs)
|
||||||
|
return cls._instances[cls]
|
||||||
|
|
||||||
|
|
||||||
|
class Connection(metaclass=DBSingleton):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DBConnection(metaclass=DBSingleton):
|
||||||
"""Connection class interface.
|
"""Connection class interface.
|
||||||
All backend implementations should provide a connection class that inherits
|
All backend implementations should provide a connection class that inherits
|
||||||
from and implements this class.
|
from and implements this class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, host=None, port=None, dbname=None, connection_timeout=None, max_tries=None, **kwargs):
|
def __init__(
|
||||||
|
self,
|
||||||
|
host: str = None,
|
||||||
|
port: int = None,
|
||||||
|
login: str = None,
|
||||||
|
password: str = None,
|
||||||
|
backend: str = None,
|
||||||
|
connection_timeout: int = None,
|
||||||
|
max_tries: int = None,
|
||||||
|
**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.
|
||||||
@ -119,24 +81,16 @@ class Connection:
|
|||||||
**kwargs: arbitrary keyword arguments provided by the
|
**kwargs: arbitrary keyword arguments provided by the
|
||||||
configuration's ``database`` settings
|
configuration's ``database`` settings
|
||||||
"""
|
"""
|
||||||
|
|
||||||
dbconf = Config().get()["database"]
|
dbconf = Config().get()["database"]
|
||||||
|
|
||||||
self.host = host or dbconf["host"]
|
self.host = host or dbconf["host"] if not kwargs.get("host") else kwargs["host"]
|
||||||
self.port = port or dbconf["port"]
|
self.port = port or dbconf["port"] if not kwargs.get("port") else kwargs["port"]
|
||||||
self.dbname = dbname or dbconf["name"]
|
self.login = login or dbconf["login"] if not kwargs.get("login") else kwargs["login"]
|
||||||
self.connection_timeout = (
|
self.password = password or dbconf["password"] if not kwargs.get("password") else kwargs["password"]
|
||||||
connection_timeout if connection_timeout is not None else dbconf["connection_timeout"]
|
|
||||||
)
|
self.connection_timeout = connection_timeout if connection_timeout is not None else Config().get()["database"]
|
||||||
self.max_tries = max_tries if max_tries is not None else dbconf["max_tries"]
|
self.max_tries = max_tries if max_tries is not None else dbconf["max_tries"]
|
||||||
self.max_tries_counter = range(self.max_tries) if self.max_tries != 0 else repeat(0)
|
self.max_tries_counter = range(self.max_tries) if self.max_tries != 0 else repeat(0)
|
||||||
self._conn = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def conn(self):
|
|
||||||
if self._conn is None:
|
|
||||||
self.connect()
|
|
||||||
return self._conn
|
|
||||||
|
|
||||||
def run(self, query):
|
def run(self, query):
|
||||||
"""Run a query.
|
"""Run a query.
|
||||||
@ -159,23 +113,12 @@ class Connection:
|
|||||||
:exc:`~ConnectionError`: If the connection to the database
|
:exc:`~ConnectionError`: If the connection to the database
|
||||||
fails.
|
fails.
|
||||||
"""
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
attempt = 0
|
def close(self):
|
||||||
for i in self.max_tries_counter:
|
"""Try to close connection to the database.
|
||||||
attempt += 1
|
Raises:
|
||||||
try:
|
:exc:`~ConnectionError`: If the connection to the database
|
||||||
self._conn = self._connect()
|
fails.
|
||||||
except ConnectionError as exc:
|
"""
|
||||||
logger.warning(
|
raise NotImplementedError()
|
||||||
"Attempt %s/%s. Connection to %s:%s failed after %sms.",
|
|
||||||
attempt,
|
|
||||||
self.max_tries if self.max_tries != 0 else "∞",
|
|
||||||
self.host,
|
|
||||||
self.port,
|
|
||||||
self.connection_timeout,
|
|
||||||
)
|
|
||||||
if attempt == self.max_tries:
|
|
||||||
logger.critical("Cannot connect to the Database. Giving up.")
|
|
||||||
raise ConnectionError() from exc
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
@ -11,25 +11,13 @@ from planetmint.config import Config
|
|||||||
from planetmint.backend.exceptions import DuplicateKeyError, OperationError, ConnectionError
|
from planetmint.backend.exceptions import DuplicateKeyError, OperationError, ConnectionError
|
||||||
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 Connection
|
from planetmint.backend.connection import DBConnection, _kwargs_parser
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class LocalMongoDBConnection(Connection):
|
class LocalMongoDBConnection(DBConnection):
|
||||||
def __init__(
|
def __init__(self, host: str = None, port: int = None, login: str = None, password: str = None, **kwargs):
|
||||||
self,
|
|
||||||
replicaset=None,
|
|
||||||
ssl=None,
|
|
||||||
login=None,
|
|
||||||
password=None,
|
|
||||||
ca_cert=None,
|
|
||||||
certfile=None,
|
|
||||||
keyfile=None,
|
|
||||||
keyfile_passphrase=None,
|
|
||||||
crlfile=None,
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
"""Create a new Connection instance.
|
"""Create a new Connection instance.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -39,16 +27,27 @@ class LocalMongoDBConnection(Connection):
|
|||||||
configuration's ``database`` settings
|
configuration's ``database`` settings
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
super().__init__(host=host, port=port, login=login, password=password, **kwargs)
|
||||||
self.replicaset = replicaset or Config().get()["database"]["replicaset"]
|
|
||||||
self.ssl = ssl if ssl is not None else Config().get()["database"]["ssl"]
|
dbconf = Config().get()["database"]
|
||||||
self.login = login or Config().get()["database"]["login"]
|
self.dbname = _kwargs_parser(key="name", kwargs=kwargs) or dbconf["name"]
|
||||||
self.password = password or Config().get()["database"]["password"]
|
self.replicaset = _kwargs_parser(key="replicaset", kwargs=kwargs) or dbconf["replicaset"]
|
||||||
self.ca_cert = ca_cert or Config().get()["database"]["ca_cert"]
|
self.ssl = _kwargs_parser(key="ssl", kwargs=kwargs) or dbconf["ssl"]
|
||||||
self.certfile = certfile or Config().get()["database"]["certfile"]
|
|
||||||
self.keyfile = keyfile or Config().get()["database"]["keyfile"]
|
self.ca_cert = _kwargs_parser(key="ca_cert", kwargs=kwargs) or dbconf["ca_cert"]
|
||||||
self.keyfile_passphrase = keyfile_passphrase or Config().get()["database"]["keyfile_passphrase"]
|
self.certfile = _kwargs_parser(key="certfile", kwargs=kwargs) or dbconf["certfile"]
|
||||||
self.crlfile = crlfile or Config().get()["database"]["crlfile"]
|
self.keyfile = _kwargs_parser(key="keyfile", kwargs=kwargs) or dbconf["keyfile"]
|
||||||
|
self.keyfile_passphrase = (
|
||||||
|
_kwargs_parser(key="keyfile_passphrase", kwargs=kwargs) or dbconf["keyfile_passphrase"]
|
||||||
|
)
|
||||||
|
self.crlfile = _kwargs_parser(key="crlfile", kwargs=kwargs) or dbconf["crlfile"]
|
||||||
|
self.max_tries = _kwargs_parser(key="max_tries", kwargs=kwargs)
|
||||||
|
self.connection_timeout = (
|
||||||
|
_kwargs_parser(key="connection_timeout", kwargs=kwargs) or dbconf["connection_timeout"]
|
||||||
|
)
|
||||||
|
self.__conn = None
|
||||||
|
self.connect()
|
||||||
|
|
||||||
if not self.ssl:
|
if not self.ssl:
|
||||||
self.ssl = False
|
self.ssl = False
|
||||||
if not self.keyfile_passphrase:
|
if not self.keyfile_passphrase:
|
||||||
@ -56,7 +55,7 @@ class LocalMongoDBConnection(Connection):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def db(self):
|
def db(self):
|
||||||
return self.conn[self.dbname]
|
return self.connect()[self.dbname]
|
||||||
|
|
||||||
def query(self):
|
def query(self):
|
||||||
return Lazy()
|
return Lazy()
|
||||||
@ -72,10 +71,10 @@ class LocalMongoDBConnection(Connection):
|
|||||||
def run(self, query):
|
def run(self, query):
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
return query.run(self.conn)
|
return query.run(self.connect())
|
||||||
except pymongo.errors.AutoReconnect:
|
except pymongo.errors.AutoReconnect:
|
||||||
logger.warning("Lost connection to the database, " "retrying query.")
|
logger.warning("Lost connection to the database, " "retrying query.")
|
||||||
return query.run(self.conn)
|
return query.run(self.connect())
|
||||||
except pymongo.errors.AutoReconnect as exc:
|
except pymongo.errors.AutoReconnect as exc:
|
||||||
raise ConnectionError from exc
|
raise ConnectionError from exc
|
||||||
except pymongo.errors.DuplicateKeyError as exc:
|
except pymongo.errors.DuplicateKeyError as exc:
|
||||||
@ -84,7 +83,7 @@ class LocalMongoDBConnection(Connection):
|
|||||||
print(f"DETAILS: {exc.details}")
|
print(f"DETAILS: {exc.details}")
|
||||||
raise OperationError from exc
|
raise OperationError from exc
|
||||||
|
|
||||||
def _connect(self):
|
def connect(self):
|
||||||
"""Try to connect to the database.
|
"""Try to connect to the database.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@ -95,7 +94,8 @@ class LocalMongoDBConnection(Connection):
|
|||||||
:exc:`~ConfigurationError`: If there is a ConfigurationError while
|
:exc:`~ConfigurationError`: If there is a ConfigurationError while
|
||||||
connecting to the database.
|
connecting to the database.
|
||||||
"""
|
"""
|
||||||
|
if self.__conn:
|
||||||
|
return self.__conn
|
||||||
try:
|
try:
|
||||||
# FYI: the connection process might raise a
|
# FYI: the connection process might raise a
|
||||||
# `ServerSelectionTimeoutError`, that is a subclass of
|
# `ServerSelectionTimeoutError`, that is a subclass of
|
||||||
@ -131,15 +131,23 @@ class LocalMongoDBConnection(Connection):
|
|||||||
)
|
)
|
||||||
if self.login is not None:
|
if self.login is not None:
|
||||||
client[self.dbname].authenticate(self.login, mechanism="MONGODB-X509")
|
client[self.dbname].authenticate(self.login, mechanism="MONGODB-X509")
|
||||||
|
self.__conn = client
|
||||||
return client
|
return client
|
||||||
|
|
||||||
except (pymongo.errors.ConnectionFailure, pymongo.errors.OperationFailure) as exc:
|
except (pymongo.errors.ConnectionFailure, pymongo.errors.OperationFailure) as exc:
|
||||||
logger.info("Exception in _connect(): {}".format(exc))
|
logger.info("Exception in connect(): {}".format(exc))
|
||||||
raise ConnectionError(str(exc)) from exc
|
raise ConnectionError(str(exc)) from exc
|
||||||
except pymongo.errors.ConfigurationError as exc:
|
except pymongo.errors.ConfigurationError as exc:
|
||||||
raise ConfigurationError from exc
|
raise ConfigurationError from exc
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
try:
|
||||||
|
self.__conn.close()
|
||||||
|
self.__conn = None
|
||||||
|
except Exception as exc:
|
||||||
|
logger.info("Exception in planetmint.backend.localmongodb.close(): {}".format(exc))
|
||||||
|
raise ConnectionError(str(exc)) from exc
|
||||||
|
|
||||||
|
|
||||||
MONGO_OPTS = {
|
MONGO_OPTS = {
|
||||||
"socketTimeoutMS": 20000,
|
"socketTimeoutMS": 20000,
|
||||||
|
@ -14,7 +14,7 @@ register_query = module_dispatch_registrar(convert)
|
|||||||
|
|
||||||
@register_query(LocalMongoDBConnection)
|
@register_query(LocalMongoDBConnection)
|
||||||
def prepare_asset(connection, transaction_type, transaction_id, filter_operation, asset):
|
def prepare_asset(connection, transaction_type, transaction_id, filter_operation, asset):
|
||||||
if transaction_type in filter_operation:
|
if transaction_type not in filter_operation:
|
||||||
asset["id"] = transaction_id
|
asset["id"] = transaction_id
|
||||||
return asset
|
return asset
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ INDEXES = {
|
|||||||
def create_database(conn, dbname):
|
def create_database(conn, dbname):
|
||||||
logger.info("Create database `%s`.", dbname)
|
logger.info("Create database `%s`.", dbname)
|
||||||
# TODO: read and write concerns can be declared here
|
# TODO: read and write concerns can be declared here
|
||||||
conn.conn.get_database(dbname)
|
conn.connect().get_database(dbname)
|
||||||
|
|
||||||
|
|
||||||
@register_schema(LocalMongoDBConnection)
|
@register_schema(LocalMongoDBConnection)
|
||||||
@ -73,7 +73,7 @@ def create_tables(conn, dbname):
|
|||||||
# TODO: read and write concerns can be declared here
|
# TODO: read and write concerns can be declared here
|
||||||
try:
|
try:
|
||||||
logger.info(f"Create `{table_name}` table.")
|
logger.info(f"Create `{table_name}` table.")
|
||||||
conn.conn[dbname].create_collection(table_name)
|
conn.connect()[dbname].create_collection(table_name)
|
||||||
except CollectionInvalid:
|
except CollectionInvalid:
|
||||||
logger.info(f"Collection {table_name} already exists.")
|
logger.info(f"Collection {table_name} already exists.")
|
||||||
create_indexes(conn, dbname, table_name, INDEXES[table_name])
|
create_indexes(conn, dbname, table_name, INDEXES[table_name])
|
||||||
@ -82,9 +82,9 @@ def create_tables(conn, dbname):
|
|||||||
def create_indexes(conn, dbname, collection, indexes):
|
def create_indexes(conn, dbname, collection, indexes):
|
||||||
logger.info(f"Ensure secondary indexes for `{collection}`.")
|
logger.info(f"Ensure secondary indexes for `{collection}`.")
|
||||||
for fields, kwargs in indexes:
|
for fields, kwargs in indexes:
|
||||||
conn.conn[dbname][collection].create_index(fields, **kwargs)
|
conn.connect()[dbname][collection].create_index(fields, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@register_schema(LocalMongoDBConnection)
|
@register_schema(LocalMongoDBConnection)
|
||||||
def drop_database(conn, dbname):
|
def drop_database(conn, dbname):
|
||||||
conn.conn.drop_database(dbname)
|
conn.connect().drop_database(dbname)
|
||||||
|
@ -9,7 +9,7 @@ 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 connect
|
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,
|
||||||
@ -134,7 +134,7 @@ def init_database(connection=None, dbname=None):
|
|||||||
configuration.
|
configuration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
connection = connection or connect()
|
connection = connection or Connection()
|
||||||
dbname = dbname or Config().get()["database"]["name"]
|
dbname = dbname or Config().get()["database"]["name"]
|
||||||
|
|
||||||
create_database(connection, dbname)
|
create_database(connection, dbname)
|
||||||
|
@ -9,27 +9,28 @@ 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 Connection
|
from planetmint.backend.connection import DBConnection, ConnectionError
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class TarantoolDBConnection(Connection):
|
class TarantoolDBConnection(DBConnection):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
host: str = "localhost",
|
host: str = None,
|
||||||
port: int = 3303,
|
port: int = None,
|
||||||
user: str = None,
|
login: str = None,
|
||||||
password: str = None,
|
password: str = None,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
super().__init__(**kwargs)
|
super().__init__(host=host, port=port, login=login, password=password, **kwargs)
|
||||||
self.host = host
|
|
||||||
self.port = port
|
dbconf = Config().get()["database"]
|
||||||
# TODO add user support later on
|
self.init_path = dbconf["init_config"]["absolute_path"]
|
||||||
self.init_path = Config().get()["database"]["init_config"]["absolute_path"]
|
self.drop_path = dbconf["drop_config"]["absolute_path"]
|
||||||
self.drop_path = Config().get()["database"]["drop_config"]["absolute_path"]
|
self.__conn = None
|
||||||
|
self.connect()
|
||||||
self.SPACE_NAMES = [
|
self.SPACE_NAMES = [
|
||||||
"abci_chains",
|
"abci_chains",
|
||||||
"assets",
|
"assets",
|
||||||
@ -43,10 +44,11 @@ class TarantoolDBConnection(Connection):
|
|||||||
"inputs",
|
"inputs",
|
||||||
"outputs",
|
"outputs",
|
||||||
"keys",
|
"keys",
|
||||||
|
"scripts",
|
||||||
]
|
]
|
||||||
except tarantool.error.NetworkError as network_err:
|
except tarantool.error.NetworkError as network_err:
|
||||||
logger.info("Host cant be reached")
|
logger.info("Host cant be reached")
|
||||||
raise network_err
|
raise ConnectionError
|
||||||
except ConfigurationError:
|
except ConfigurationError:
|
||||||
logger.info("Exception in _connect(): {}")
|
logger.info("Exception in _connect(): {}")
|
||||||
raise ConfigurationError
|
raise ConfigurationError
|
||||||
@ -60,25 +62,43 @@ class TarantoolDBConnection(Connection):
|
|||||||
f.close()
|
f.close()
|
||||||
return "".join(execute).encode()
|
return "".join(execute).encode()
|
||||||
|
|
||||||
def _connect(self):
|
def connect(self):
|
||||||
return tarantool.connect(host=self.host, port=self.port)
|
if not self.__conn:
|
||||||
|
self.__conn = tarantool.connect(host=self.host, port=self.port)
|
||||||
|
return self.__conn
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
try:
|
||||||
|
if self.__conn:
|
||||||
|
self.__conn.close()
|
||||||
|
self.__conn = None
|
||||||
|
except Exception as exc:
|
||||||
|
logger.info("Exception in planetmint.backend.tarantool.close(): {}".format(exc))
|
||||||
|
raise ConnectionError(str(exc)) from exc
|
||||||
|
|
||||||
def get_space(self, space_name: str):
|
def get_space(self, space_name: str):
|
||||||
return self.conn.space(space_name)
|
return self.connect().space(space_name)
|
||||||
|
|
||||||
def space(self, space_name: str):
|
def space(self, space_name: str):
|
||||||
return self.query().space(space_name)
|
return self.query().space(space_name)
|
||||||
|
|
||||||
def run(self, query, only_data=True):
|
def exec(self, query, only_data=True):
|
||||||
try:
|
try:
|
||||||
return query.run(self.conn).data if only_data else query.run(self.conn)
|
conn = self.connect()
|
||||||
|
conn.execute(query) if only_data else conn.execute(query)
|
||||||
except tarantool.error.OperationalError as op_error:
|
except tarantool.error.OperationalError as op_error:
|
||||||
raise op_error
|
raise op_error
|
||||||
except tarantool.error.NetworkError as net_error:
|
except tarantool.error.NetworkError as net_error:
|
||||||
raise net_error
|
raise net_error
|
||||||
|
|
||||||
def get_connection(self):
|
def run(self, query, only_data=True):
|
||||||
return self.conn
|
try:
|
||||||
|
conn = self.connect()
|
||||||
|
return query.run(conn).data if only_data else query.run(conn)
|
||||||
|
except tarantool.error.OperationalError as op_error:
|
||||||
|
raise op_error
|
||||||
|
except tarantool.error.NetworkError as net_error:
|
||||||
|
raise net_error
|
||||||
|
|
||||||
def drop_database(self):
|
def drop_database(self):
|
||||||
db_config = Config().get()["database"]
|
db_config = Config().get()["database"]
|
||||||
@ -91,6 +111,11 @@ class TarantoolDBConnection(Connection):
|
|||||||
def run_command(self, command: str, config: dict):
|
def run_command(self, command: str, config: dict):
|
||||||
from subprocess import run
|
from subprocess import run
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.close()
|
||||||
|
except ConnectionError:
|
||||||
|
pass
|
||||||
|
|
||||||
print(f" commands: {command}")
|
print(f" commands: {command}")
|
||||||
host_port = "%s:%s" % (self.host, self.port)
|
host_port = "%s:%s" % (self.host, self.port)
|
||||||
execute_cmd = self._file_content_to_bytes(path=command)
|
execute_cmd = self._file_content_to_bytes(path=command)
|
||||||
@ -101,3 +126,20 @@ class TarantoolDBConnection(Connection):
|
|||||||
).stderr
|
).stderr
|
||||||
output = output.decode()
|
output = output.decode()
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def run_command_with_output(self, command: str):
|
||||||
|
from subprocess import run
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.close()
|
||||||
|
except ConnectionError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
host_port = "%s:%s" % (
|
||||||
|
Config().get()["database"]["host"],
|
||||||
|
Config().get()["database"]["port"],
|
||||||
|
)
|
||||||
|
output = run(["tarantoolctl", "connect", host_port], input=command, capture_output=True)
|
||||||
|
if output.returncode != 0:
|
||||||
|
raise Exception(f"Error while trying to execute cmd {command} on host:port {host_port}: {output.stderr}")
|
||||||
|
return output.stdout
|
||||||
|
@ -258,9 +258,9 @@ def run_drop(args):
|
|||||||
if response != "y":
|
if response != "y":
|
||||||
return
|
return
|
||||||
|
|
||||||
from planetmint.backend.connection import connect
|
from planetmint.backend.connection import Connection
|
||||||
|
|
||||||
conn = connect()
|
conn = Connection()
|
||||||
try:
|
try:
|
||||||
schema.drop_database(conn)
|
schema.drop_database(conn)
|
||||||
except DatabaseDoesNotExist:
|
except DatabaseDoesNotExist:
|
||||||
|
@ -4,6 +4,7 @@ import os
|
|||||||
|
|
||||||
# from planetmint.log import DEFAULT_LOGGING_CONFIG as log_config
|
# from planetmint.log import DEFAULT_LOGGING_CONFIG as log_config
|
||||||
from planetmint.version import __version__ # noqa
|
from planetmint.version import __version__ # noqa
|
||||||
|
from decouple import config
|
||||||
|
|
||||||
|
|
||||||
class Singleton(type):
|
class Singleton(type):
|
||||||
@ -26,7 +27,7 @@ class Config(metaclass=Singleton):
|
|||||||
# _base_database_localmongodb.keys() because dicts are unordered.
|
# _base_database_localmongodb.keys() because dicts are unordered.
|
||||||
# I tried to configure
|
# I tried to configure
|
||||||
self.log_config = DEFAULT_LOGGING_CONFIG
|
self.log_config = DEFAULT_LOGGING_CONFIG
|
||||||
db = "tarantool_db"
|
db = config("PLANETMINT_DATABASE_BACKEND", default="tarantool_db")
|
||||||
self.__private_database_keys_map = { # TODO Check if it is working after removing 'name' field
|
self.__private_database_keys_map = { # TODO Check if it is working after removing 'name' field
|
||||||
"tarantool_db": ("host", "port"),
|
"tarantool_db": ("host", "port"),
|
||||||
"localmongodb": ("host", "port", "name"),
|
"localmongodb": ("host", "port", "name"),
|
||||||
@ -95,7 +96,7 @@ class Config(metaclass=Singleton):
|
|||||||
"tendermint": {
|
"tendermint": {
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"port": 26657,
|
"port": 26657,
|
||||||
"version": "v0.31.5", # look for __tm_supported_versions__
|
"version": "v0.34.15", # look for __tm_supported_versions__
|
||||||
},
|
},
|
||||||
"database": self.__private_database_map,
|
"database": self.__private_database_map,
|
||||||
"log": {
|
"log": {
|
||||||
|
@ -8,6 +8,12 @@ MongoDB.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
from collections import namedtuple
|
||||||
|
from uuid import uuid4
|
||||||
|
from planetmint.backend.connection import Connection
|
||||||
|
|
||||||
|
import rapidjson
|
||||||
|
from hashlib import sha3_256
|
||||||
import json
|
import json
|
||||||
import rapidjson
|
import rapidjson
|
||||||
import requests
|
import requests
|
||||||
@ -87,7 +93,7 @@ class Planetmint(object):
|
|||||||
self.validation = config_utils.load_validation_plugin(validationPlugin)
|
self.validation = config_utils.load_validation_plugin(validationPlugin)
|
||||||
else:
|
else:
|
||||||
self.validation = BaseValidationRules
|
self.validation = BaseValidationRules
|
||||||
self.connection = connection if connection is not None else planetmint.backend.connect()
|
self.connection = connection if connection is not None else Connection()
|
||||||
|
|
||||||
def post_transaction(self, transaction, mode):
|
def post_transaction(self, transaction, mode):
|
||||||
"""Submit a valid transaction to the mempool."""
|
"""Submit a valid transaction to the mempool."""
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
# 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.0"
|
__version__ = "1.3.1"
|
||||||
__short_version__ = "1.3"
|
__short_version__ = "1.3"
|
||||||
|
|
||||||
# Supported Tendermint versions
|
# Supported Tendermint versions
|
||||||
|
1
setup.py
1
setup.py
@ -136,6 +136,7 @@ install_requires = [
|
|||||||
"PyNaCl==1.4.0",
|
"PyNaCl==1.4.0",
|
||||||
"pyasn1>=0.4.8",
|
"pyasn1>=0.4.8",
|
||||||
"cryptography==3.4.7",
|
"cryptography==3.4.7",
|
||||||
|
"python-decouple",
|
||||||
"planetmint-transactions==0.2.0",
|
"planetmint-transactions==0.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from planetmint.backend.connection import connect
|
from planetmint.backend.connection import Connection
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -27,5 +27,5 @@ from planetmint.backend.connection import connect
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def db_conn():
|
def db_conn():
|
||||||
conn = connect()
|
conn = Connection()
|
||||||
return conn
|
return conn
|
||||||
|
@ -7,16 +7,17 @@ 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.tarantool.connection import TarantoolDBConnection
|
||||||
|
|
||||||
|
with pytest.raises(ConnectionError):
|
||||||
|
TarantoolDBConnection("localhost", "1337", "mydb", "password")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip(reason="we currently do not suppport mongodb.")
|
||||||
|
def test_get_connection_raises_a_configuration_error_mongodb(monkeypatch):
|
||||||
|
from planetmint.backend.localmongodb.connection import LocalMongoDBConnection
|
||||||
from transactions.common.exceptions import ConfigurationError
|
from transactions.common.exceptions import ConfigurationError
|
||||||
from planetmint.backend.connection import connect
|
|
||||||
|
|
||||||
with pytest.raises(ConfigurationError):
|
with pytest.raises(ConnectionError):
|
||||||
connect("localhost", "1337", "mydb", "password", "msaccess")
|
conn = LocalMongoDBConnection("localhost", "1337", "mydb", "password")
|
||||||
|
|
||||||
with pytest.raises(ConfigurationError):
|
|
||||||
# We need to force a misconfiguration here
|
|
||||||
monkeypatch.setattr(
|
|
||||||
"planetmint.backend.connection.BACKENDS", {"catsandra": "planetmint.backend.meowmeow.Catsandra"}
|
|
||||||
)
|
|
||||||
|
|
||||||
connect("localhost", "1337", "mydb", "password", "catsandra")
|
|
||||||
|
@ -12,6 +12,7 @@ from argparse import Namespace
|
|||||||
from planetmint.config import Config
|
from planetmint.config import Config
|
||||||
from planetmint import ValidatorElection
|
from planetmint import ValidatorElection
|
||||||
from planetmint.commands.planetmint import run_election_show
|
from planetmint.commands.planetmint import run_election_show
|
||||||
|
from planetmint.backend.connection import Connection
|
||||||
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
|
||||||
from tests.utils import generate_election, generate_validators
|
from tests.utils import generate_election, generate_validators
|
||||||
@ -102,9 +103,7 @@ def test_bigchain_show_config(capsys):
|
|||||||
def test__run_init(mocker):
|
def test__run_init(mocker):
|
||||||
init_db_mock = mocker.patch("planetmint.backend.tarantool.connection.TarantoolDBConnection.init_database")
|
init_db_mock = mocker.patch("planetmint.backend.tarantool.connection.TarantoolDBConnection.init_database")
|
||||||
|
|
||||||
from planetmint.backend.connection import connect
|
conn = Connection()
|
||||||
|
|
||||||
conn = connect()
|
|
||||||
conn.init_database()
|
conn.init_database()
|
||||||
|
|
||||||
init_db_mock.assert_called_once_with()
|
init_db_mock.assert_called_once_with()
|
||||||
|
@ -20,7 +20,7 @@ from ipld import marshal, multihash
|
|||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from logging.config import dictConfig
|
from logging.config import dictConfig
|
||||||
from planetmint.backend.connection import connect
|
from planetmint.backend.connection import Connection
|
||||||
from planetmint.backend.tarantool.connection import TarantoolDBConnection
|
from planetmint.backend.tarantool.connection import TarantoolDBConnection
|
||||||
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
|
||||||
@ -118,7 +118,7 @@ def _setup_database(_configure_planetmint): # TODO Here is located setup databa
|
|||||||
|
|
||||||
print("Initializing test db")
|
print("Initializing test db")
|
||||||
dbname = Config().get()["database"]["name"]
|
dbname = Config().get()["database"]["name"]
|
||||||
conn = connect()
|
conn = Connection()
|
||||||
|
|
||||||
_drop_db(conn, dbname)
|
_drop_db(conn, dbname)
|
||||||
schema.init_database(conn, dbname)
|
schema.init_database(conn, dbname)
|
||||||
@ -127,7 +127,7 @@ def _setup_database(_configure_planetmint): # TODO Here is located setup databa
|
|||||||
yield
|
yield
|
||||||
|
|
||||||
print("Deleting `{}` database".format(dbname))
|
print("Deleting `{}` database".format(dbname))
|
||||||
conn = connect()
|
conn = Connection()
|
||||||
_drop_db(conn, dbname)
|
_drop_db(conn, dbname)
|
||||||
|
|
||||||
print("Finished deleting `{}`".format(dbname))
|
print("Finished deleting `{}`".format(dbname))
|
||||||
@ -140,7 +140,7 @@ def _bdb(_setup_database, _configure_planetmint):
|
|||||||
from .utils import flush_db
|
from .utils import flush_db
|
||||||
from planetmint.config import Config
|
from planetmint.config import Config
|
||||||
|
|
||||||
conn = connect()
|
conn = Connection()
|
||||||
yield
|
yield
|
||||||
dbname = Config().get()["database"]["name"]
|
dbname = Config().get()["database"]["name"]
|
||||||
flush_db(conn, dbname)
|
flush_db(conn, dbname)
|
||||||
@ -387,7 +387,7 @@ def db_name(db_config):
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def db_conn():
|
def db_conn():
|
||||||
return connect()
|
return Connection()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -91,7 +91,7 @@ def test_filter_unspent_outputs(b, user_pk, user_sk):
|
|||||||
|
|
||||||
def test_outputs_query_key_order(b, user_pk, user_sk, user2_pk, user2_sk):
|
def test_outputs_query_key_order(b, user_pk, user_sk, user2_pk, user2_sk):
|
||||||
from planetmint import backend
|
from planetmint import backend
|
||||||
from planetmint.backend.connection import connect
|
from planetmint.backend.connection import Connection
|
||||||
from planetmint.backend import query
|
from planetmint.backend import query
|
||||||
|
|
||||||
tx1 = Create.generate([user_pk], [([user_pk], 3), ([user_pk], 2), ([user_pk], 1)]).sign([user_sk])
|
tx1 = Create.generate([user_pk], [([user_pk], 3), ([user_pk], 2), ([user_pk], 1)]).sign([user_sk])
|
||||||
@ -116,7 +116,7 @@ def test_outputs_query_key_order(b, user_pk, user_sk, user2_pk, user2_sk):
|
|||||||
assert len(outputs) == 1
|
assert len(outputs) == 1
|
||||||
|
|
||||||
# clean the transaction, metdata and asset collection
|
# clean the transaction, metdata and asset collection
|
||||||
connection = connect()
|
connection = Connection()
|
||||||
query.delete_transactions(connection, txn_ids=[tx1.id, tx2.id])
|
query.delete_transactions(connection, txn_ids=[tx1.id, tx2.id])
|
||||||
|
|
||||||
b.store_bulk_transactions([tx1])
|
b.store_bulk_transactions([tx1])
|
||||||
|
@ -8,6 +8,8 @@ import pytest
|
|||||||
from planetmint.version import __tm_supported_versions__
|
from planetmint.version import __tm_supported_versions__
|
||||||
from transactions.types.assets.create import Create
|
from transactions.types.assets.create import Create
|
||||||
from transactions.types.assets.transfer import Transfer
|
from transactions.types.assets.transfer import Transfer
|
||||||
|
from transactions.common.exceptions import ConfigurationError
|
||||||
|
from planetmint.backend.connection import Connection, ConnectionError
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -28,7 +30,7 @@ def config(request, monkeypatch):
|
|||||||
"name": "bigchain",
|
"name": "bigchain",
|
||||||
},
|
},
|
||||||
"tendermint": {
|
"tendermint": {
|
||||||
"host": "localhost",
|
"host": "tendermint",
|
||||||
"port": 26657,
|
"port": 26657,
|
||||||
},
|
},
|
||||||
"CONFIGURED": True,
|
"CONFIGURED": True,
|
||||||
@ -48,28 +50,9 @@ def test_bigchain_class_default_initialization(config):
|
|||||||
assert planet.validation == BaseValidationRules
|
assert planet.validation == BaseValidationRules
|
||||||
|
|
||||||
|
|
||||||
def test_bigchain_class_initialization_with_parameters():
|
|
||||||
from planetmint import Planetmint
|
|
||||||
from planetmint.backend import connect
|
|
||||||
from planetmint.validation import BaseValidationRules
|
|
||||||
|
|
||||||
init_db_kwargs = {
|
|
||||||
"backend": "localmongodb",
|
|
||||||
"host": "this_is_the_db_host",
|
|
||||||
"port": 12345,
|
|
||||||
"name": "this_is_the_db_name",
|
|
||||||
}
|
|
||||||
connection = connect(**init_db_kwargs)
|
|
||||||
planet = Planetmint(connection=connection)
|
|
||||||
assert planet.connection == connection
|
|
||||||
assert planet.connection.host == init_db_kwargs["host"]
|
|
||||||
assert planet.connection.port == init_db_kwargs["port"]
|
|
||||||
# assert planet.connection.name == init_db_kwargs['name']
|
|
||||||
assert planet.validation == BaseValidationRules
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.bdb
|
@pytest.mark.bdb
|
||||||
def test_get_spent_issue_1271(b, alice, bob, carol):
|
def test_get_spent_issue_1271(b, alice, bob, carol):
|
||||||
|
b.connection.close()
|
||||||
tx_1 = Create.generate(
|
tx_1 = Create.generate(
|
||||||
[carol.public_key],
|
[carol.public_key],
|
||||||
[([carol.public_key], 8)],
|
[([carol.public_key], 8)],
|
||||||
|
@ -81,10 +81,40 @@ def test_get_outputs_endpoint_with_invalid_spent(client, user_pk):
|
|||||||
assert res.status_code == 400
|
assert res.status_code == 400
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip(
|
||||||
|
reason="just failing sometimes - a test to narrow down the issues of the test 'test_get_divisble_transactions_returns_500'"
|
||||||
|
)
|
||||||
|
@pytest.mark.abci
|
||||||
|
def test_get_divisble_transactions_returns_500_phase_one(b, client):
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
|
TX_ENDPOINT = "/api/v1/transactions"
|
||||||
|
|
||||||
|
def mine(tx_list):
|
||||||
|
b.store_bulk_transactions(tx_list)
|
||||||
|
|
||||||
|
alice_priv, alice_pub = crypto.generate_key_pair()
|
||||||
|
# bob_priv, bob_pub = crypto.generate_key_pair()
|
||||||
|
# carly_priv, carly_pub = crypto.generate_key_pair()
|
||||||
|
# time.sleep(1)
|
||||||
|
create_tx = Create.generate([alice_pub], [([alice_pub], 4)])
|
||||||
|
create_tx.sign([alice_priv])
|
||||||
|
# ATTENTION: comment out the next line and the test will never fail
|
||||||
|
res = client.post(TX_ENDPOINT, data=json.dumps(create_tx.to_dict()))
|
||||||
|
assert res.status_code == 202
|
||||||
|
|
||||||
|
mine([create_tx])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip(
|
||||||
|
reason="this test fails with strange inconsistent tarantool error messages. sometimes, it's even passing."
|
||||||
|
)
|
||||||
@pytest.mark.abci
|
@pytest.mark.abci
|
||||||
def test_get_divisble_transactions_returns_500(b, client):
|
def test_get_divisble_transactions_returns_500(b, client):
|
||||||
from transactions.common import crypto
|
from transactions.common import crypto
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
TX_ENDPOINT = "/api/v1/transactions"
|
TX_ENDPOINT = "/api/v1/transactions"
|
||||||
|
|
||||||
@ -94,7 +124,6 @@ def test_get_divisble_transactions_returns_500(b, client):
|
|||||||
alice_priv, alice_pub = crypto.generate_key_pair()
|
alice_priv, alice_pub = crypto.generate_key_pair()
|
||||||
bob_priv, bob_pub = crypto.generate_key_pair()
|
bob_priv, bob_pub = crypto.generate_key_pair()
|
||||||
carly_priv, carly_pub = crypto.generate_key_pair()
|
carly_priv, carly_pub = crypto.generate_key_pair()
|
||||||
|
|
||||||
create_tx = Create.generate([alice_pub], [([alice_pub], 4)])
|
create_tx = Create.generate([alice_pub], [([alice_pub], 4)])
|
||||||
create_tx.sign([alice_priv])
|
create_tx.sign([alice_priv])
|
||||||
|
|
||||||
@ -110,7 +139,6 @@ def test_get_divisble_transactions_returns_500(b, client):
|
|||||||
|
|
||||||
res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict()))
|
res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict()))
|
||||||
assert res.status_code == 202
|
assert res.status_code == 202
|
||||||
|
|
||||||
mine([transfer_tx])
|
mine([transfer_tx])
|
||||||
|
|
||||||
transfer_tx_carly = Transfer.generate([transfer_tx.to_inputs()[1]], [([carly_pub], 1)], asset_ids=[create_tx.id])
|
transfer_tx_carly = Transfer.generate([transfer_tx.to_inputs()[1]], [([carly_pub], 1)], asset_ids=[create_tx.id])
|
||||||
@ -118,7 +146,6 @@ def test_get_divisble_transactions_returns_500(b, client):
|
|||||||
|
|
||||||
res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx_carly.to_dict()))
|
res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx_carly.to_dict()))
|
||||||
assert res.status_code == 202
|
assert res.status_code == 202
|
||||||
|
|
||||||
mine([transfer_tx_carly])
|
mine([transfer_tx_carly])
|
||||||
|
|
||||||
asset_id = create_tx.id
|
asset_id = create_tx.id
|
||||||
|
@ -11,6 +11,7 @@ from unittest.mock import Mock, patch
|
|||||||
from cryptoconditions import Ed25519Sha256
|
from cryptoconditions import Ed25519Sha256
|
||||||
from ipld import multihash, marshal
|
from ipld import multihash, marshal
|
||||||
from hashlib import sha3_256
|
from hashlib import sha3_256
|
||||||
|
|
||||||
from transactions.common import crypto
|
from transactions.common import crypto
|
||||||
from transactions.common.transaction import Transaction
|
from transactions.common.transaction import Transaction
|
||||||
from transactions.types.assets.create import Create
|
from transactions.types.assets.create import Create
|
||||||
|
Loading…
x
Reference in New Issue
Block a user