250 migrate zenroom script usage within planetmint so that tx schema 21 is used (#253)

* * **Changed** adjusted to zenroom calling convention of PRP #13 (breaking change)
* **Changed** zenroom test cases to comply to the new calling convention
* **Fixed** zenroom signing bug (call of wrong function)
* **Changed** using cryptoconditions 0.10.0
* **Deprecated** usage of ripde160md as a address generation algorithm, isn't available from python 3.9.14 on, skipping these tests from now on.
* **Changed** script/ouptut tag to be of type array or object for schema v3.0 and v2.0
* **Changed** added 'script' handling to the common/transactions.py class
* **Fixed** data input handling to the transaction fullfillment methods

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>

* connected the version string in the banner of 'planetmint start' to the planetmint/version.py variables.

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>

* added input validation to the transaction script parsing and passing

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>

* added backend support for the scripts

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>

* adjusted tests to the new zenroom calling convention

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>

* blackified the code

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>

* increased version to 1.1.0

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>

* fixed docs building issues of dependency inheritance

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>
This commit is contained in:
Jürgen Eckel 2022-09-08 21:41:10 +02:00 committed by GitHub
parent e41ce5df76
commit d971709a79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 289 additions and 226 deletions

View File

@ -27,6 +27,18 @@ For reference, the possible headings are:
## [Unreleased] ## [Unreleased]
## [1.1.0] - 2022-09-05
* **Changed** adjusted to zenroom calling convention of PRP #13 (breaking change)
* **Changed** zenroom test cases to comply to the new calling convention
* **Fixed** zenroom signing bug (call of wrong function)
* **Changed** using cryptoconditions 0.10.0
* **Deprecated** usage of ripde160md as a address generation algorithm, isn't available from python 3.9.14 on, skipping these tests from now on.
* **Changed** script/ouptut tag to be of type array or object for schema v3.0 and v2.0
* **Changed** added 'script' handling to the common/transactions.py class
* **Fixed** data input handling to the transaction fullfillment methods
## [1.0.1] - 2022-07-07 ## [1.0.1] - 2022-07-07
updated documentation updated documentation
@ -1184,6 +1196,6 @@ The first public release of Planetmint, including:
- Initial documentation (in `planetmint/docs`). - Initial documentation (in `planetmint/docs`).
- Initial `README.md`, `ROADMAP.md`, `CODE_OF_CONDUCT.md`, and `CONTRIBUTING.md`. - Initial `README.md`, `ROADMAP.md`, `CODE_OF_CONDUCT.md`, and `CONTRIBUTING.md`.
- Packaging for PyPI, including `setup.py` and `setup.cfg`. - Packaging for PyPI, including `setup.py` and `setup.cfg`.
- Initial `Dockerfile` and `docker-compose.yml` (for deployment using Docker and Docker Compose). - Initial `Dockerfile` and `docker compose.yml` (for deployment using Docker and Docker Compose).
- Initial `.gitignore` (list of things for git to ignore). - Initial `.gitignore` (list of things for git to ignore).
- Initial `.travis.yml` (used by Travis CI). - Initial `.travis.yml` (used by Travis CI).

View File

@ -7,6 +7,7 @@ RUN apt-get -qq update \
&& apt-get -y upgrade \ && apt-get -y upgrade \
&& apt-get install -y jq vim zsh build-essential cmake\ && apt-get install -y jq vim zsh build-essential cmake\
&& pip install . \ && pip install . \
&& pip install pynacl==1.4.0 base58==2.1.1 pyasn1==0.4.8 zenroom==2.1.0.dev1655293214 cryptography==3.4.7\
&& apt-get autoremove \ && apt-get autoremove \
&& apt-get clean && apt-get clean

View File

@ -46,4 +46,7 @@ VOLUME /data/db /data/configdb /tendermint
EXPOSE 27017 28017 9984 9985 26656 26657 26658 EXPOSE 27017 28017 9984 9985 26656 26657 26658
RUN pip install pynacl==1.4.0 base58==2.1.1 pyasn1==0.4.8 zenroom==2.1.0.dev1655293214 cryptography==3.4.7
WORKDIR $HOME WORKDIR $HOME

View File

@ -9,7 +9,6 @@ RUN apt-get update \
&& pip install -U pip \ && pip install -U pip \
&& apt-get autoremove \ && apt-get autoremove \
&& apt-get clean && apt-get clean
ARG backend ARG backend
ARG abci_status ARG abci_status
@ -34,4 +33,6 @@ RUN mkdir -p /usr/src/app
COPY . /usr/src/app/ 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 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 RUN planetmint -y configure

View File

@ -4,7 +4,7 @@ RUN apt-get update \
&& pip install -U pip \ && pip install -U pip \
&& apt-get autoremove \ && apt-get autoremove \
&& apt-get clean && apt-get clean
RUN apt-get install -y vim zsh build-essential cmake RUN apt-get install -y vim zsh build-essential cmake git
RUN mkdir -p /src RUN mkdir -p /src
RUN /usr/local/bin/python -m pip install --upgrade pip RUN /usr/local/bin/python -m pip install --upgrade pip
@ -13,6 +13,7 @@ RUN pip install --upgrade \
pycco \ pycco \
websocket-client~=0.47.0 \ websocket-client~=0.47.0 \
pytest~=3.0 \ pytest~=3.0 \
planetmint-cryptoconditions>=0.9.9\ planetmint-cryptoconditions>=0.10.0\
planetmint-driver>=0.9.2 \ planetmint-driver>=0.9.2 \
blns blns
RUN pip install base58>=2.1.1 pynacl==1.4.0 zenroom==2.1.0.dev1655293214 pyasn1==0.4.8 cryptography==3.4.7

View File

@ -5,17 +5,16 @@
import pytest import pytest
CONDITION_SCRIPT = """ CONDITION_SCRIPT = """Scenario 'ecdh': create the signature of an object
Scenario 'ecdh': create the signature of an object
Given I have the 'keyring' Given I have the 'keyring'
Given that I have a 'string dictionary' named 'houses' inside 'asset' Given that I have a 'string dictionary' named 'houses'
When I create the signature of 'houses' When I create the signature of 'houses'
Then print the 'signature'""" Then print the 'signature'"""
FULFILL_SCRIPT = """Scenario 'ecdh': Bob verifies the signature from Alice FULFILL_SCRIPT = """Scenario 'ecdh': Bob verifies the signature from Alice
Given I have a 'ecdh public key' from 'Alice' Given I have a 'ecdh public key' from 'Alice'
Given that I have a 'string dictionary' named 'houses' inside 'asset' Given that I have a 'string dictionary' named 'houses'
Given I have a 'signature' named 'signature' inside 'metadata' Given I have a 'signature' named 'signature'
When I verify the 'houses' has a signature in 'signature' by 'Alice' When I verify the 'houses' has a signature in 'signature' by 'Alice'
Then print the string 'ok'""" Then print the string 'ok'"""
@ -33,25 +32,24 @@ GENERATE_KEYPAIR = """Scenario 'ecdh': Create the keypair
When I create the bitcoin key When I create the bitcoin key
Then print data""" Then print data"""
ZENROOM_DATA = {"also": "more data"} INITIAL_STATE = {"also": "more data"}
SCRIPT_INPUT = {
HOUSE_ASSETS = { "houses": [
"data": { {
"houses": [ "name": "Harry",
{ "team": "Gryffindor",
"name": "Harry", },
"team": "Gryffindor", {
}, "name": "Draco",
{ "team": "Slytherin",
"name": "Draco", },
"team": "Slytherin", ],
},
],
}
} }
metadata = {"units": 300, "type": "KG"} metadata = {"units": 300, "type": "KG"}
ZENROOM_DATA = {"that": "is my data"}
@pytest.fixture @pytest.fixture
def gen_key_zencode(): def gen_key_zencode():
@ -75,7 +73,12 @@ def condition_script_zencode():
@pytest.fixture @pytest.fixture
def zenroom_house_assets(): def zenroom_house_assets():
return HOUSE_ASSETS return SCRIPT_INPUT
@pytest.fixture
def zenroom_script_input():
return SCRIPT_INPUT
@pytest.fixture @pytest.fixture

View File

@ -15,6 +15,7 @@ def test_zenroom_signing(
fulfill_script_zencode, fulfill_script_zencode,
zenroom_data, zenroom_data,
zenroom_house_assets, zenroom_house_assets,
zenroom_script_input,
condition_script_zencode, condition_script_zencode,
): ):
@ -64,9 +65,18 @@ def test_zenroom_signing(
} }
metadata = {"result": {"output": ["ok"]}} metadata = {"result": {"output": ["ok"]}}
script_ = {
"code": {"type": "zenroom", "raw": "test_string", "parameters": [{"obj": "1"}, {"obj": "2"}]},
"state": "dd8bbd234f9869cab4cc0b84aa660e9b5ef0664559b8375804ee8dce75b10576",
"input": zenroom_script_input,
"output": ["ok"],
"policies": {},
}
token_creation_tx = { token_creation_tx = {
"operation": "CREATE", "operation": "CREATE",
"asset": zenroom_house_assets, "asset": {"data": {"test": "my asset"}},
"script": script_,
"metadata": metadata, "metadata": metadata,
"outputs": [ "outputs": [
output, output,
@ -79,35 +89,44 @@ def test_zenroom_signing(
} }
# JSON: serialize the transaction-without-id to a json formatted string # JSON: serialize the transaction-without-id to a json formatted string
message = json.dumps( tx = json.dumps(
token_creation_tx, token_creation_tx,
sort_keys=True, sort_keys=True,
separators=(",", ":"), separators=(",", ":"),
ensure_ascii=False, ensure_ascii=False,
) )
script_ = json.dumps(script_)
# major workflow: # major workflow:
# we store the fulfill script in the transaction/message (zenroom-sha) # we store the fulfill script in the transaction/message (zenroom-sha)
# the condition script is used to fulfill the transaction and create the signature # the condition script is used to fulfill the transaction and create the signature
# #
# the server should ick the fulfill script and recreate the zenroom-sha and verify the signature # the server should ick the fulfill script and recreate the zenroom-sha and verify the signature
message = zenroomscpt.sign(message, condition_script_zencode, alice) signed_input = zenroomscpt.sign(script_, condition_script_zencode, alice)
assert zenroomscpt.validate(message=message)
message = json.loads(message) input_signed = json.loads(signed_input)
input_signed["input"]["signature"] = input_signed["output"]["signature"]
del input_signed["output"]["signature"]
del input_signed["output"]["logs"]
input_signed["output"] = ["ok"] # define expected output that is to be compared
input_msg = json.dumps(input_signed)
assert zenroomscpt.validate(message=input_msg)
tx = json.loads(tx)
fulfillment_uri_zen = zenroomscpt.serialize_uri() fulfillment_uri_zen = zenroomscpt.serialize_uri()
message["inputs"][0]["fulfillment"] = fulfillment_uri_zen tx["inputs"][0]["fulfillment"] = fulfillment_uri_zen
tx = message tx["script"] = input_signed
tx["id"] = None tx["id"] = None
json_str_tx = json.dumps(tx, sort_keys=True, skipkeys=False, separators=(",", ":")) json_str_tx = json.dumps(tx, sort_keys=True, skipkeys=False, separators=(",", ":"))
# SHA3: hash the serialized id-less transaction to generate the id # SHA3: hash the serialized id-less transaction to generate the id
shared_creation_txid = sha3_256(json_str_tx.encode()).hexdigest() shared_creation_txid = sha3_256(json_str_tx.encode()).hexdigest()
message["id"] = shared_creation_txid tx["id"] = shared_creation_txid
# tx = json.dumps(tx)
# `https://example.com:9984` # `https://example.com:9984`
print(f"TX \n{tx}")
plntmnt = Planetmint(os.environ.get("PLANETMINT_ENDPOINT")) plntmnt = Planetmint(os.environ.get("PLANETMINT_ENDPOINT"))
sent_transfer_tx = plntmnt.transactions.send_commit(message) sent_transfer_tx = plntmnt.transactions.send_commit(tx)
print(f"\n\nstatus and result : + {sent_transfer_tx}") print(f"\n\nstatus and result : + {sent_transfer_tx}")

View File

@ -39,3 +39,8 @@ zipp==3.8.0
nest-asyncio==1.5.5 nest-asyncio==1.5.5
sphinx-press-theme==0.8.0 sphinx-press-theme==0.8.0
sphinx-documatt-theme sphinx-documatt-theme
base58>=2.1.1
pynacl==1.4.0
zenroom==2.1.0.dev1655293214
pyasn1==0.4.8
cryptography==3.4.7

View File

@ -6,7 +6,7 @@ RUN apt-get update \
&& apt-get clean && apt-get clean
RUN apt-get install -y vim RUN apt-get install -y vim
RUN apt-get update RUN apt-get update
RUN apt-get install -y build-essential cmake openssh-client openssh-server RUN apt-get install -y build-essential cmake openssh-client openssh-server git
RUN apt-get install -y zsh RUN apt-get install -y zsh
RUN mkdir -p /src RUN mkdir -p /src
@ -15,6 +15,7 @@ RUN pip install --upgrade \
pytest~=6.2.5 \ pytest~=6.2.5 \
pycco \ pycco \
websocket-client~=0.47.0 \ websocket-client~=0.47.0 \
planetmint-cryptoconditions>=0.9.9 \ planetmint-cryptoconditions>=0.10.0 \
planetmint-driver>=9.2.0 \ planetmint-driver>=9.2.0 \
blns blns
RUN pip install base58 pynacl==1.4.0 zenroom==2.1.0.dev1655293214 pyasn1==0.4.8 cryptography==3.4.7

View File

@ -5,17 +5,16 @@
import pytest import pytest
CONDITION_SCRIPT = """ CONDITION_SCRIPT = """Scenario 'ecdh': create the signature of an object
Scenario 'ecdh': create the signature of an object
Given I have the 'keyring' Given I have the 'keyring'
Given that I have a 'string dictionary' named 'houses' inside 'asset' Given that I have a 'string dictionary' named 'houses'
When I create the signature of 'houses' When I create the signature of 'houses'
Then print the 'signature'""" Then print the 'signature'"""
FULFILL_SCRIPT = """Scenario 'ecdh': Bob verifies the signature from Alice FULFILL_SCRIPT = """Scenario 'ecdh': Bob verifies the signature from Alice
Given I have a 'ecdh public key' from 'Alice' Given I have a 'ecdh public key' from 'Alice'
Given that I have a 'string dictionary' named 'houses' inside 'asset' Given that I have a 'string dictionary' named 'houses'
Given I have a 'signature' named 'signature' inside 'metadata' Given I have a 'signature' named 'signature'
When I verify the 'houses' has a signature in 'signature' by 'Alice' When I verify the 'houses' has a signature in 'signature' by 'Alice'
Then print the string 'ok'""" Then print the string 'ok'"""
@ -33,25 +32,24 @@ GENERATE_KEYPAIR = """Scenario 'ecdh': Create the keypair
When I create the bitcoin key When I create the bitcoin key
Then print data""" Then print data"""
ZENROOM_DATA = {"also": "more data"} INITIAL_STATE = {"also": "more data"}
SCRIPT_INPUT = {
HOUSE_ASSETS = { "houses": [
"data": { {
"houses": [ "name": "Harry",
{ "team": "Gryffindor",
"name": "Harry", },
"team": "Gryffindor", {
}, "name": "Draco",
{ "team": "Slytherin",
"name": "Draco", },
"team": "Slytherin", ],
},
],
}
} }
metadata = {"units": 300, "type": "KG"} metadata = {"units": 300, "type": "KG"}
ZENROOM_DATA = {"that": "is my data"}
@pytest.fixture @pytest.fixture
def gen_key_zencode(): def gen_key_zencode():
@ -75,7 +73,12 @@ def condition_script_zencode():
@pytest.fixture @pytest.fixture
def zenroom_house_assets(): def zenroom_house_assets():
return HOUSE_ASSETS return SCRIPT_INPUT
@pytest.fixture
def zenroom_script_input():
return SCRIPT_INPUT
@pytest.fixture @pytest.fixture

View File

@ -3,6 +3,7 @@ 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
@ -14,6 +15,7 @@ def test_zenroom_signing(
fulfill_script_zencode, fulfill_script_zencode,
zenroom_data, zenroom_data,
zenroom_house_assets, zenroom_house_assets,
zenroom_script_input,
condition_script_zencode, condition_script_zencode,
): ):
@ -24,17 +26,11 @@ def test_zenroom_signing(
bob = json.loads(zencode_exec(gen_key_zencode).output)["keyring"] bob = json.loads(zencode_exec(gen_key_zencode).output)["keyring"]
zen_public_keys = json.loads( zen_public_keys = json.loads(
zencode_exec( zencode_exec(secret_key_to_private_key_zencode.format("Alice"), keys=json.dumps({"keyring": alice})).output
secret_key_to_private_key_zencode.format("Alice"),
keys=json.dumps({"keyring": alice}),
).output
) )
zen_public_keys.update( zen_public_keys.update(
json.loads( json.loads(
zencode_exec( zencode_exec(secret_key_to_private_key_zencode.format("Bob"), keys=json.dumps({"keyring": bob})).output
secret_key_to_private_key_zencode.format("Bob"),
keys=json.dumps({"keyring": bob}),
).output
) )
) )
@ -68,9 +64,19 @@ def test_zenroom_signing(
], ],
} }
metadata = {"result": {"output": ["ok"]}} metadata = {"result": {"output": ["ok"]}}
script_ = {
"code": {"type": "zenroom", "raw": "test_string", "parameters": [{"obj": "1"}, {"obj": "2"}]},
"state": "dd8bbd234f9869cab4cc0b84aa660e9b5ef0664559b8375804ee8dce75b10576",
"input": zenroom_script_input,
"output": ["ok"],
"policies": {},
}
token_creation_tx = { token_creation_tx = {
"operation": "CREATE", "operation": "CREATE",
"asset": zenroom_house_assets, "asset": {"data": {"test": "my asset"}},
"script": script_,
"metadata": metadata, "metadata": metadata,
"outputs": [ "outputs": [
output, output,
@ -83,39 +89,44 @@ def test_zenroom_signing(
} }
# JSON: serialize the transaction-without-id to a json formatted string # JSON: serialize the transaction-without-id to a json formatted string
message = json.dumps( tx = json.dumps(
token_creation_tx, token_creation_tx,
sort_keys=True, sort_keys=True,
separators=(",", ":"), separators=(",", ":"),
ensure_ascii=False, ensure_ascii=False,
) )
script_ = json.dumps(script_)
# major workflow: # major workflow:
# we store the fulfill script in the transaction/message (zenroom-sha) # we store the fulfill script in the transaction/message (zenroom-sha)
# the condition script is used to fulfill the transaction and create the signature # the condition script is used to fulfill the transaction and create the signature
# #
# the server should ick the fulfill script and recreate the zenroom-sha and verify the signature # the server should ick the fulfill script and recreate the zenroom-sha and verify the signature
message = zenroomscpt.sign(message, condition_script_zencode, alice) signed_input = zenroomscpt.sign(script_, condition_script_zencode, alice)
assert zenroomscpt.validate(message=message)
message = json.loads(message) input_signed = json.loads(signed_input)
input_signed["input"]["signature"] = input_signed["output"]["signature"]
del input_signed["output"]["signature"]
del input_signed["output"]["logs"]
input_signed["output"] = ["ok"] # define expected output that is to be compared
input_msg = json.dumps(input_signed)
assert zenroomscpt.validate(message=input_msg)
tx = json.loads(tx)
fulfillment_uri_zen = zenroomscpt.serialize_uri() fulfillment_uri_zen = zenroomscpt.serialize_uri()
message["inputs"][0]["fulfillment"] = fulfillment_uri_zen tx["inputs"][0]["fulfillment"] = fulfillment_uri_zen
tx = message tx["script"] = input_signed
tx["id"] = None tx["id"] = None
json_str_tx = json.dumps(tx, sort_keys=True, skipkeys=False, separators=(",", ":")) json_str_tx = json.dumps(tx, sort_keys=True, skipkeys=False, separators=(",", ":"))
# SHA3: hash the serialized id-less transaction to generate the id # SHA3: hash the serialized id-less transaction to generate the id
shared_creation_txid = sha3_256(json_str_tx.encode()).hexdigest() shared_creation_txid = sha3_256(json_str_tx.encode()).hexdigest()
message["id"] = shared_creation_txid tx["id"] = shared_creation_txid
hosts = Hosts("/shared/hostnames") hosts = Hosts("/shared/hostnames")
pm_alpha = hosts.get_connection() pm_alpha = hosts.get_connection()
sent_transfer_tx = pm_alpha.transactions.send_commit(tx)
sent_transfer_tx = pm_alpha.transactions.send_commit(message)
time.sleep(1) time.sleep(1)
# Assert that transaction is stored on both planetmint nodes # Assert that transaction is stored on both planetmint nodes
hosts.assert_transaction(shared_creation_txid) hosts.assert_transaction(shared_creation_txid)
print(f"\n\nstatus and result : + {sent_transfer_tx}") print(f"\n\nstatus and result : + {sent_transfer_tx}")

View File

@ -11,3 +11,4 @@ box.space.transactions:drop()
box.space.inputs:drop() box.space.inputs:drop()
box.space.outputs:drop() box.space.outputs:drop()
box.space.keys:drop() box.space.keys:drop()
box.space.scripts:drop()

View File

@ -67,4 +67,8 @@ utxos = box.schema.space.create('utxos', {engine = 'memtx' , is_sync = false})
utxos:format({{name='transaction_id' , type='string'}, {name='output_index' , type='integer'}, {name='utxo_dict', type='string'}}) utxos:format({{name='transaction_id' , type='string'}, {name='output_index' , type='integer'}, {name='utxo_dict', type='string'}})
utxos:create_index('id_search', {type='hash' , parts={'transaction_id', 'output_index'}}) utxos:create_index('id_search', {type='hash' , parts={'transaction_id', 'output_index'}})
utxos:create_index('transaction_search', {type='tree', unique=false, parts={'transaction_id'}}) utxos:create_index('transaction_search', {type='tree', unique=false, parts={'transaction_id'}})
utxos:create_index('index_search', {type='tree', unique=false, parts={'output_index'}}) utxos:create_index('index_search', {type='tree', unique=false, parts={'output_index'}})
scripts = box.schema.space.create('scripts' , {engine='memtx' , is_sync=false})
scripts:format({{name='transaction_id', type='string'},{name='script' , type='any'}})
scripts:create_index('txid_search', {type='hash', parts={'transaction_id'}})

View File

@ -34,6 +34,7 @@ def _group_transaction_by_ids(connection, txids: list):
_txkeys = connection.run(connection.space("keys").select(txid, index="txid_search")) _txkeys = connection.run(connection.space("keys").select(txid, index="txid_search"))
_txassets = connection.run(connection.space("assets").select(txid, index="txid_search")) _txassets = connection.run(connection.space("assets").select(txid, index="txid_search"))
_txmeta = connection.run(connection.space("meta_data").select(txid, index="id_search")) _txmeta = connection.run(connection.space("meta_data").select(txid, index="id_search"))
_txscript = connection.run(connection.space("scripts").select(txid, index="txid_search"))
_txinputs = sorted(_txinputs, key=itemgetter(6), reverse=False) _txinputs = sorted(_txinputs, key=itemgetter(6), reverse=False)
_txoutputs = sorted(_txoutputs, key=itemgetter(8), reverse=False) _txoutputs = sorted(_txoutputs, key=itemgetter(8), reverse=False)
@ -44,6 +45,7 @@ def _group_transaction_by_ids(connection, txids: list):
"keys": _txkeys, "keys": _txkeys,
"asset": _txassets, "asset": _txassets,
"metadata": _txmeta, "metadata": _txmeta,
"script": _txscript,
} }
tx_compose = TransactionCompose(db_results=result_map) tx_compose = TransactionCompose(db_results=result_map)
_transaction = tx_compose.convert_to_dict() _transaction = tx_compose.convert_to_dict()
@ -74,6 +76,9 @@ def store_transactions(connection, signed_transactions: list):
if txtuples["asset"] is not None: if txtuples["asset"] is not None:
connection.run(connection.space("assets").insert(txtuples["asset"]), only_data=False) connection.run(connection.space("assets").insert(txtuples["asset"]), only_data=False)
if txtuples["script"] is not None:
connection.run(connection.space("scripts").insert(txtuples["script"]), only_data=False)
@register_query(TarantoolDBConnection) @register_query(TarantoolDBConnection)
def get_transaction(connection, transaction_id: str): def get_transaction(connection, transaction_id: str):

View File

@ -23,8 +23,10 @@ SPACE_NAMES = (
"outputs", "outputs",
"keys", "keys",
"utxos", "utxos",
"scripts",
) )
SPACE_COMMANDS = { SPACE_COMMANDS = {
"abci_chains": "abci_chains = box.schema.space.create('abci_chains', {engine='memtx', is_sync = false})", "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})", "assets": "assets = box.schema.space.create('assets' , {engine='memtx' , is_sync=false})",
@ -39,6 +41,7 @@ SPACE_COMMANDS = {
"outputs": "outputs = box.schema.space.create('outputs')", "outputs": "outputs = box.schema.space.create('outputs')",
"keys": "keys = box.schema.space.create('keys')", "keys": "keys = box.schema.space.create('keys')",
"utxos": "utxos = box.schema.space.create('utxos', {engine = 'memtx' , is_sync = false})", "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 = { INDEX_COMMANDS = {
@ -102,8 +105,12 @@ INDEX_COMMANDS = {
"transaction_search": "utxos:create_index('transaction_search', {type='tree', unique=false, parts={'transaction_id'}})", # noqa: E501 "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'}})", "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 = { 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 "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 "assets": "assets:format({{name='data' , type='string'}, {name='tx_id', type='string'}, {name='asset_id', type='string'}})", # noqa: E501
@ -118,6 +125,7 @@ SCHEMA_COMMANDS = {
"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 "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 "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 "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 = { SCHEMA_DROP_COMMANDS = {
@ -134,6 +142,7 @@ SCHEMA_DROP_COMMANDS = {
"outputs": "box.space.outputs:drop()", "outputs": "box.space.outputs:drop()",
"keys": "box.space.keys:drop()", "keys": "box.space.keys:drop()",
"utxos": "box.space.utxos:drop()", "utxos": "box.space.utxos:drop()",
"scripts": "box.space.scripts:drop()",
} }

View File

@ -40,6 +40,7 @@ class TransactionDecompose:
"inputs": [], "inputs": [],
"outputs": [], "outputs": [],
"keys": [], "keys": [],
"script": None,
"metadata": None, "metadata": None,
"asset": None, "asset": None,
} }
@ -132,6 +133,12 @@ class TransactionDecompose:
_map = self.get_map() _map = self.get_map()
return (self._transaction["id"], self._transaction["operation"], self._transaction["version"], _map) return (self._transaction["id"], self._transaction["operation"], self._transaction["version"], _map)
def __prepare_script(self):
try:
return (self._transaction["id"], self._transaction["script"])
except KeyError:
return None
def convert_to_tuple(self): def convert_to_tuple(self):
self._metadata_check() self._metadata_check()
self.__asset_check() self.__asset_check()
@ -140,6 +147,7 @@ class TransactionDecompose:
keys, outputs = self.__prepare_outputs() keys, outputs = self.__prepare_outputs()
self._tuple_transaction["outputs"] = outputs self._tuple_transaction["outputs"] = outputs
self._tuple_transaction["keys"] = keys self._tuple_transaction["keys"] = keys
self._tuple_transaction["script"] = self.__prepare_script()
return self._tuple_transaction return self._tuple_transaction
@ -197,6 +205,12 @@ class TransactionCompose:
_outputs.append(_out) _outputs.append(_out)
return _outputs return _outputs
def _get_script(self):
if self.db_results["script"]:
return self.db_results["script"][0][1]
else:
return None
def convert_to_dict(self): def convert_to_dict(self):
transaction = {k: None for k in list(self._map.keys())} transaction = {k: None for k in list(self._map.keys())}
transaction["id"] = self._get_transaction_id() transaction["id"] = self._get_transaction_id()
@ -206,4 +220,6 @@ class TransactionCompose:
transaction["operation"] = self._get_transaction_operation() transaction["operation"] = self._get_transaction_operation()
transaction["inputs"] = self._get_inputs() transaction["inputs"] = self._get_inputs()
transaction["outputs"] = self._get_outputs() transaction["outputs"] = self._get_outputs()
if self._get_script():
transaction["script"] = self._get_script()
return transaction return transaction

View File

@ -13,14 +13,14 @@ from planetmint.parallel_validation import ParallelValidationApp
from planetmint.web import server, websocket_server from planetmint.web import server, websocket_server
from planetmint.events import Exchange, EventTypes from planetmint.events import Exchange, EventTypes
from planetmint.utils import Process from planetmint.utils import Process
from planetmint.version import __version__
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
BANNER = """ BANNER = """
**************************************************************************** ****************************************************************************
* * * *
* Planetmint 2.2.2 * * Planetmint {} *
* codename "jumping sloth" * * codename "jumping sloth" *
* Initialization complete. Planetmint Server is ready and waiting. * * Initialization complete. Planetmint Server is ready and waiting. *
* * * *
@ -45,7 +45,7 @@ def start(args):
p_webapi = Process(name="planetmint_webapi", target=app_server.run, daemon=True) p_webapi = Process(name="planetmint_webapi", target=app_server.run, daemon=True)
p_webapi.start() p_webapi.start()
logger.info(BANNER.format(Config().get()["server"]["bind"])) logger.info(BANNER.format(__version__, Config().get()["server"]["bind"]))
# start websocket server # start websocket server
p_websocket_server = Process( p_websocket_server = Process(

View File

@ -69,6 +69,8 @@ def merkleroot(hashes):
return merkleroot(parent_hashes) return merkleroot(parent_hashes)
# ripemd160 is only available below python 3.9.13
@DeprecationWarning
def public_key64_to_address(base64_public_key): def public_key64_to_address(base64_public_key):
"""Note this only compatible with Tendermint 0.19.x""" """Note this only compatible with Tendermint 0.19.x"""
ed25519_public_key = public_key_from_base64(base64_public_key) ed25519_public_key = public_key_from_base64(base64_public_key)

View File

@ -212,7 +212,9 @@ definitions:
input: input:
type: object type: object
output: output:
type: object anyOf:
- type: object
- type: array
policies: policies:
type: object type: object
properties: properties:

View File

@ -216,7 +216,9 @@ definitions:
input: input:
type: object type: object
output: output:
type: object anyOf:
- type: object
- type: array
policies: policies:
type: object type: object
properties: properties:

View File

@ -93,6 +93,7 @@ class Transaction(object):
version=None, version=None,
hash_id=None, hash_id=None,
tx_dict=None, tx_dict=None,
script=None,
): ):
"""The constructor allows to create a customizable Transaction. """The constructor allows to create a customizable Transaction.
@ -139,12 +140,16 @@ class Transaction(object):
if metadata is not None and not isinstance(metadata, dict): if metadata is not None and not isinstance(metadata, dict):
raise TypeError("`metadata` must be a dict or None") raise TypeError("`metadata` must be a dict or None")
if script is not None and not isinstance(script, dict):
raise TypeError("`script` must be a dict or None")
self.version = version if version is not None else self.VERSION self.version = version if version is not None else self.VERSION
self.operation = operation self.operation = operation
self.asset = asset self.asset = asset
self.inputs = inputs or [] self.inputs = inputs or []
self.outputs = outputs or [] self.outputs = outputs or []
self.metadata = metadata self.metadata = metadata
self.script = script
self._id = hash_id self._id = hash_id
self.tx_dict = tx_dict self.tx_dict = tx_dict
@ -320,7 +325,7 @@ class Transaction(object):
elif isinstance(input_.fulfillment, ThresholdSha256): elif isinstance(input_.fulfillment, ThresholdSha256):
return cls._sign_threshold_signature_fulfillment(input_, message, key_pairs) return cls._sign_threshold_signature_fulfillment(input_, message, key_pairs)
elif isinstance(input_.fulfillment, ZenroomSha256): elif isinstance(input_.fulfillment, ZenroomSha256):
return cls._sign_threshold_signature_fulfillment(input_, message, key_pairs) return cls._sign_zenroom_fulfillment(input_, message, key_pairs)
else: else:
raise ValueError("Fulfillment couldn't be matched to " "Cryptocondition fulfillment type.") raise ValueError("Fulfillment couldn't be matched to " "Cryptocondition fulfillment type.")
@ -533,7 +538,10 @@ class Transaction(object):
ffill_valid = False ffill_valid = False
if isinstance(parsed_ffill, ZenroomSha256): if isinstance(parsed_ffill, ZenroomSha256):
ffill_valid = parsed_ffill.validate(message=message) import json
msg = json.loads(message)
ffill_valid = parsed_ffill.validate(message=json.dumps(msg["script"]))
else: else:
message = sha3_256(message.encode()) message = sha3_256(message.encode())
if input_.fulfills: if input_.fulfills:
@ -558,7 +566,7 @@ class Transaction(object):
Returns: Returns:
dict: The Transaction as an alternative serialization format. dict: The Transaction as an alternative serialization format.
""" """
return { tx_dict = {
"inputs": [input_.to_dict() for input_ in self.inputs], "inputs": [input_.to_dict() for input_ in self.inputs],
"outputs": [output.to_dict() for output in self.outputs], "outputs": [output.to_dict() for output in self.outputs],
"operation": str(self.operation), "operation": str(self.operation),
@ -567,6 +575,9 @@ class Transaction(object):
"version": self.version, "version": self.version,
"id": self._id, "id": self._id,
} }
if self.script:
tx_dict["script"] = self.script
return tx_dict
@staticmethod @staticmethod
# TODO: Remove `_dict` prefix of variable. # TODO: Remove `_dict` prefix of variable.
@ -699,6 +710,14 @@ class Transaction(object):
"version": tx["version"], "version": tx["version"],
"id": id, "id": id,
} }
try:
script_ = tx["script"]
script_dict = {"script": script_}
except KeyError:
script_ = None
pass
else:
local_dict = {**local_dict, **script_dict}
if not skip_schema_validation: if not skip_schema_validation:
cls.validate_id(local_dict) cls.validate_id(local_dict)
@ -715,6 +734,7 @@ class Transaction(object):
tx["version"], tx["version"],
hash_id=tx["id"], hash_id=tx["id"],
tx_dict=tx, tx_dict=tx,
script=script_,
) )
@classmethod @classmethod

View File

@ -195,6 +195,7 @@ def _fulfillment_to_details(fulfillment):
"type": "zenroom-sha-256", "type": "zenroom-sha-256",
"public_key": base58.b58encode(fulfillment.public_key).decode(), "public_key": base58.b58encode(fulfillment.public_key).decode(),
"script": base58.b58encode(fulfillment.script).decode(), "script": base58.b58encode(fulfillment.script).decode(),
"data": base58.b58encode(fulfillment.data).decode(),
} }
raise UnsupportedTypeError(fulfillment.type_name) raise UnsupportedTypeError(fulfillment.type_name)
@ -221,10 +222,10 @@ def _fulfillment_from_details(data, _depth=0):
return threshold return threshold
if data["type"] == "zenroom-sha-256": if data["type"] == "zenroom-sha-256":
public_key = base58.b58decode(data["public_key"]) public_key_ = base58.b58decode(data["public_key"])
script = base58.b58decode(data["script"]) script_ = base58.b58decode(data["script"])
# zenroom = ZenroomSha256(script=script, data=None, keys={public_key}) data_ = base58.b58decode(data["data"])
# TODO: assign to zenroom and evaluate the outcome # TODO: assign to zenroom and evaluate the outcome
ZenroomSha256(script=script, data=None, keys={public_key}) ZenroomSha256(script=script_, data=data_, keys={public_key_})
raise UnsupportedTypeError(data.get("type")) raise UnsupportedTypeError(data.get("type"))

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.0.1" __version__ = "1.1.1"
__short_version__ = "1.0" __short_version__ = "1.1"
# Supported Tendermint versions # Supported Tendermint versions
__tm_supported_versions__ = ["0.34.15"] __tm_supported_versions__ = ["0.34.15"]

View File

@ -108,9 +108,10 @@ tests_require = [
install_requires = [ install_requires = [
"chardet==3.0.4", "chardet==3.0.4",
"base58==2.1.1",
"aiohttp==3.8.1", "aiohttp==3.8.1",
"abci==0.8.3", "abci==0.8.3",
"planetmint-cryptoconditions>=0.9.9", "planetmint-cryptoconditions>=0.10.0",
"flask-cors==3.0.10", "flask-cors==3.0.10",
"flask-restful==0.3.9", "flask-restful==0.3.9",
"flask==2.1.2", "flask==2.1.2",

View File

@ -10,7 +10,7 @@ Code is Apache-2.0 and docs are CC-BY-4.0
Most of the tests in the `tests/` folder are unit tests. For info about how to write and run tests, see [the docs about contributing to Planetmint](http://docs.planetmint.io/en/latest/index.html), especially: Most of the tests in the `tests/` folder are unit tests. For info about how to write and run tests, see [the docs about contributing to Planetmint](http://docs.planetmint.io/en/latest/index.html), especially:
- [Write Code - Remember to Write Tests](https://docs.planetmint.io/en/latest/contributing/dev-setup-coding-and-contribution-process/write-code.html?highlight=write%20code#remember-to-write-tests) - [Write Code - Remember to Write Tests](https://docs.planetmint.io/en/latest/contributing/dev-setup-coding-and-contribution-process/write-code.html?highlight=write%20code#remember-to-write-tests)
- [Notes on Running a Local Dev Node with Docker Compose](https://docs.planetmint.io/en/latest/contributing/dev-setup-coding-and-contribution-process/run-node-with-docker-compose.html), especially `make test` - [Notes on Running a Local Dev Node with Docker Compose](https://docs.planetmint.io/en/latest/contributing/dev-setup-coding-and-contribution-process/run-node-with-docker compose.html), especially `make test`
- [ - [
Notes on Running a Local Dev Node as Processes (and Running All Tests)](https://docs.planetmint.io/en/latest/contributing/dev-setup-coding-and-contribution-process/run-node-as-processes.html) Notes on Running a Local Dev Node as Processes (and Running All Tests)](https://docs.planetmint.io/en/latest/contributing/dev-setup-coding-and-contribution-process/run-node-as-processes.html)

View File

@ -7,17 +7,16 @@ from cryptoconditions.types.ed25519 import Ed25519Sha256
from cryptoconditions.types.zenroom import ZenroomSha256 from cryptoconditions.types.zenroom import ZenroomSha256
from planetmint.transactions.common.crypto import generate_key_pair from planetmint.transactions.common.crypto import generate_key_pair
CONDITION_SCRIPT = """ CONDITION_SCRIPT = """Scenario 'ecdh': create the signature of an object
Scenario 'ecdh': create the signature of an object
Given I have the 'keyring' Given I have the 'keyring'
Given that I have a 'string dictionary' named 'houses' inside 'asset' Given that I have a 'string dictionary' named 'houses'
When I create the signature of 'houses' When I create the signature of 'houses'
Then print the 'signature'""" Then print the 'signature'"""
FULFILL_SCRIPT = """Scenario 'ecdh': Bob verifies the signature from Alice FULFILL_SCRIPT = """Scenario 'ecdh': Bob verifies the signature from Alice
Given I have a 'ecdh public key' from 'Alice' Given I have a 'ecdh public key' from 'Alice'
Given that I have a 'string dictionary' named 'houses' inside 'asset' Given that I have a 'string dictionary' named 'houses'
Given I have a 'signature' named 'signature' inside 'metadata' Given I have a 'signature' named 'signature'
When I verify the 'houses' has a signature in 'signature' by 'Alice' When I verify the 'houses' has a signature in 'signature' by 'Alice'
Then print the string 'ok'""" Then print the string 'ok'"""
@ -35,21 +34,18 @@ GENERATE_KEYPAIR = """Scenario 'ecdh': Create the keypair
When I create the bitcoin key When I create the bitcoin key
Then print data""" Then print data"""
ZENROOM_DATA = {"also": "more data"} INITIAL_STATE = {"also": "more data"}
SCRIPT_INPUT = {
HOUSE_ASSETS = { "houses": [
"data": { {
"houses": [ "name": "Harry",
{ "team": "Gryffindor",
"name": "Harry", },
"team": "Gryffindor", {
}, "name": "Draco",
{ "team": "Slytherin",
"name": "Draco", },
"team": "Slytherin", ],
},
],
}
} }
metadata = {"units": 300, "type": "KG"} metadata = {"units": 300, "type": "KG"}
@ -66,7 +62,7 @@ def test_zenroom_signing():
zen_public_keys = json.loads(zencode_exec(SK_TO_PK.format("Alice"), keys=json.dumps({"keyring": alice})).output) zen_public_keys = json.loads(zencode_exec(SK_TO_PK.format("Alice"), keys=json.dumps({"keyring": alice})).output)
zen_public_keys.update(json.loads(zencode_exec(SK_TO_PK.format("Bob"), keys=json.dumps({"keyring": bob})).output)) zen_public_keys.update(json.loads(zencode_exec(SK_TO_PK.format("Bob"), keys=json.dumps({"keyring": bob})).output))
zenroomscpt = ZenroomSha256(script=FULFILL_SCRIPT, data=ZENROOM_DATA, keys=zen_public_keys) zenroomscpt = ZenroomSha256(script=FULFILL_SCRIPT, data=INITIAL_STATE, keys=zen_public_keys)
print(f"zenroom is: {zenroomscpt.script}") print(f"zenroom is: {zenroomscpt.script}")
# CRYPTO-CONDITIONS: generate the condition uri # CRYPTO-CONDITIONS: generate the condition uri
@ -95,11 +91,19 @@ def test_zenroom_signing():
biolabs.public_key, biolabs.public_key,
], ],
} }
script_ = {
"code": {"type": "zenroom", "raw": "test_string", "parameters": [{"obj": "1"}, {"obj": "2"}]},
"state": "dd8bbd234f9869cab4cc0b84aa660e9b5ef0664559b8375804ee8dce75b10576",
"input": SCRIPT_INPUT,
"output": ["ok"],
"policies": {},
}
metadata = {"result": {"output": ["ok"]}} metadata = {"result": {"output": ["ok"]}}
token_creation_tx = { token_creation_tx = {
"operation": "CREATE", "operation": "CREATE",
"asset": HOUSE_ASSETS, "asset": {"data": {"test": "my asset"}},
"metadata": metadata, "metadata": metadata,
"script": script_,
"outputs": [ "outputs": [
output, output,
], ],
@ -111,46 +115,65 @@ def test_zenroom_signing():
} }
# JSON: serialize the transaction-without-id to a json formatted string # JSON: serialize the transaction-without-id to a json formatted string
message = json.dumps( tx = json.dumps(
token_creation_tx, token_creation_tx,
sort_keys=True, sort_keys=True,
separators=(",", ":"), separators=(",", ":"),
ensure_ascii=False, ensure_ascii=False,
) )
script_ = json.dumps(script_)
# major workflow: # major workflow:
# we store the fulfill script in the transaction/message (zenroom-sha) # we store the fulfill script in the transaction/message (zenroom-sha)
# the condition script is used to fulfill the transaction and create the signature # the condition script is used to fulfill the transaction and create the signature
# #
# the server should ick the fulfill script and recreate the zenroom-sha and verify the signature # the server should ick the fulfill script and recreate the zenroom-sha and verify the signature
message = zenroomscpt.sign(message, CONDITION_SCRIPT, alice) signed_input = zenroomscpt.sign(script_, CONDITION_SCRIPT, alice)
assert zenroomscpt.validate(message=message)
message = json.loads(message) input_signed = json.loads(signed_input)
input_signed["input"]["signature"] = input_signed["output"]["signature"]
del input_signed["output"]["signature"]
del input_signed["output"]["logs"]
input_signed["output"] = ["ok"] # define expected output that is to be compared
input_msg = json.dumps(input_signed)
assert zenroomscpt.validate(message=input_msg)
tx = json.loads(tx)
fulfillment_uri_zen = zenroomscpt.serialize_uri() fulfillment_uri_zen = zenroomscpt.serialize_uri()
message["inputs"][0]["fulfillment"] = fulfillment_uri_zen tx["script"] = input_signed
tx = message tx["inputs"][0]["fulfillment"] = fulfillment_uri_zen
tx["id"] = None tx["id"] = None
json_str_tx = json.dumps(tx, sort_keys=True, skipkeys=False, separators=(",", ":")) json_str_tx = json.dumps(tx, sort_keys=True, skipkeys=False, separators=(",", ":"))
# SHA3: hash the serialized id-less transaction to generate the id # SHA3: hash the serialized id-less transaction to generate the id
shared_creation_txid = sha3_256(json_str_tx.encode()).hexdigest() shared_creation_txid = sha3_256(json_str_tx.encode()).hexdigest()
message["id"] = shared_creation_txid tx["id"] = shared_creation_txid
from planetmint.models import Transaction from planetmint.models import Transaction
from planetmint.lib import Planetmint
from planetmint.transactions.common.exceptions import ( from planetmint.transactions.common.exceptions import (
SchemaValidationError, SchemaValidationError,
ValidationError, ValidationError,
) )
try: try:
tx_obj = Transaction.from_dict(message) print(f"TX\n{tx}")
except SchemaValidationError: tx_obj = Transaction.from_dict(tx)
except SchemaValidationError as e:
print(e)
assert () assert ()
except ValidationError as e: except ValidationError as e:
print(e) print(e)
assert () assert ()
planet = Planetmint()
try:
planet.validate_transaction(tx_obj)
except ValidationError as e:
print("Invalid transaction ({}): {}".format(type(e).__name__, e))
assert ()
except e:
print(f"Exception : {e}")
assert ()
print(f"VALIDATED : {tx_obj}") print(f"VALIDATED : {tx_obj}")
assert (tx_obj == False) is False assert (tx_obj == False) is False

View File

@ -5,6 +5,7 @@
from base58 import b58decode from base58 import b58decode
import pytest import pytest
from cryptoconditions import ThresholdSha256, Ed25519Sha256
USER_PRIVATE_KEY = "8eJ8q9ZQpReWyQT5aFCiwtZ5wDZC4eDnCen88p3tQ6ie" USER_PRIVATE_KEY = "8eJ8q9ZQpReWyQT5aFCiwtZ5wDZC4eDnCen88p3tQ6ie"
@ -69,15 +70,11 @@ def cond_uri():
@pytest.fixture @pytest.fixture
def user_Ed25519(user_pub): def user_Ed25519(user_pub):
from cryptoconditions import Ed25519Sha256
return Ed25519Sha256(public_key=b58decode(user_pub)) return Ed25519Sha256(public_key=b58decode(user_pub))
@pytest.fixture @pytest.fixture
def user_user2_threshold(user_pub, user2_pub): def user_user2_threshold(user_pub, user2_pub):
from cryptoconditions import ThresholdSha256, Ed25519Sha256
user_pub_keys = [user_pub, user2_pub] user_pub_keys = [user_pub, user2_pub]
threshold = ThresholdSha256(threshold=len(user_pub_keys)) threshold = ThresholdSha256(threshold=len(user_pub_keys))
for user_pub in user_pub_keys: for user_pub in user_pub_keys:
@ -87,8 +84,6 @@ def user_user2_threshold(user_pub, user2_pub):
@pytest.fixture @pytest.fixture
def user2_Ed25519(user2_pub): def user2_Ed25519(user2_pub):
from cryptoconditions import Ed25519Sha256
return Ed25519Sha256(public_key=b58decode(user2_pub)) return Ed25519Sha256(public_key=b58decode(user2_pub))

View File

@ -10,9 +10,17 @@ import json
from copy import deepcopy from copy import deepcopy
from base58 import b58encode, b58decode from base58 import b58encode, b58decode
from cryptoconditions import Ed25519Sha256
from planetmint.transactions.types.assets.create import Create from planetmint.transactions.types.assets.create import Create
from planetmint.transactions.types.assets.transfer import Transfer from planetmint.transactions.types.assets.transfer import Transfer
from planetmint.transactions.common.transaction import Output
from planetmint.transactions.common.transaction import Input
from planetmint.transactions.common.exceptions import AmountError
from planetmint.transactions.common.transaction import Transaction
from planetmint.transactions.common.transaction import TransactionLink
from cryptoconditions import ThresholdSha256
from cryptoconditions import Fulfillment
from cryptoconditions import PreimageSha256
from cryptoconditions import Ed25519Sha256
from pytest import mark, raises from pytest import mark, raises
try: try:
@ -24,9 +32,6 @@ pytestmark = mark.bdb
def test_input_serialization(ffill_uri, user_pub): def test_input_serialization(ffill_uri, user_pub):
from planetmint.transactions.common.transaction import Input
from cryptoconditions import Fulfillment
expected = { expected = {
"owners_before": [user_pub], "owners_before": [user_pub],
"fulfillment": ffill_uri, "fulfillment": ffill_uri,
@ -37,9 +42,6 @@ def test_input_serialization(ffill_uri, user_pub):
def test_input_deserialization_with_uri(ffill_uri, user_pub): def test_input_deserialization_with_uri(ffill_uri, user_pub):
from planetmint.transactions.common.transaction import Input
from cryptoconditions import Fulfillment
expected = Input(Fulfillment.from_uri(ffill_uri), [user_pub]) expected = Input(Fulfillment.from_uri(ffill_uri), [user_pub])
ffill = { ffill = {
"owners_before": [user_pub], "owners_before": [user_pub],
@ -78,9 +80,6 @@ def test_input_deserialization_with_invalid_fulfillment_uri(user_pub):
def test_input_deserialization_with_unsigned_fulfillment(ffill_uri, user_pub): def test_input_deserialization_with_unsigned_fulfillment(ffill_uri, user_pub):
from planetmint.transactions.common.transaction import Input
from cryptoconditions import Fulfillment
expected = Input(Fulfillment.from_uri(ffill_uri), [user_pub]) expected = Input(Fulfillment.from_uri(ffill_uri), [user_pub])
ffill = { ffill = {
"owners_before": [user_pub], "owners_before": [user_pub],
@ -133,9 +132,6 @@ def test_output_deserialization(user_Ed25519, user_pub):
def test_output_hashlock_serialization(): def test_output_hashlock_serialization():
from planetmint.transactions.common.transaction import Output
from cryptoconditions import PreimageSha256
secret = b"wow much secret" secret = b"wow much secret"
hashlock = PreimageSha256(preimage=secret).condition_uri hashlock = PreimageSha256(preimage=secret).condition_uri
@ -152,9 +148,6 @@ def test_output_hashlock_serialization():
def test_output_hashlock_deserialization(): def test_output_hashlock_deserialization():
from planetmint.transactions.common.transaction import Output
from cryptoconditions import PreimageSha256
secret = b"wow much secret" secret = b"wow much secret"
hashlock = PreimageSha256(preimage=secret).condition_uri hashlock = PreimageSha256(preimage=secret).condition_uri
expected = Output(hashlock, amount=1) expected = Output(hashlock, amount=1)
@ -170,9 +163,6 @@ def test_output_hashlock_deserialization():
def test_invalid_output_initialization(cond_uri, user_pub): def test_invalid_output_initialization(cond_uri, user_pub):
from planetmint.transactions.common.transaction import Output
from planetmint.transactions.common.exceptions import AmountError
with raises(TypeError): with raises(TypeError):
Output(cond_uri, user_pub) Output(cond_uri, user_pub)
with raises(TypeError): with raises(TypeError):
@ -182,9 +172,6 @@ def test_invalid_output_initialization(cond_uri, user_pub):
def test_generate_output_split_half_recursive(user_pub, user2_pub, user3_pub): def test_generate_output_split_half_recursive(user_pub, user2_pub, user3_pub):
from planetmint.transactions.common.transaction import Output
from cryptoconditions import Ed25519Sha256, ThresholdSha256
expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub)) expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub))
expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub)) expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub))
expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub)) expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub))
@ -201,9 +188,6 @@ def test_generate_output_split_half_recursive(user_pub, user2_pub, user3_pub):
def test_generate_outputs_split_half_single_owner(user_pub, user2_pub, user3_pub): def test_generate_outputs_split_half_single_owner(user_pub, user2_pub, user3_pub):
from planetmint.transactions.common.transaction import Output
from cryptoconditions import Ed25519Sha256, ThresholdSha256
expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub)) expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub))
expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub)) expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub))
expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub)) expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub))
@ -220,9 +204,6 @@ def test_generate_outputs_split_half_single_owner(user_pub, user2_pub, user3_pub
def test_generate_outputs_flat_ownage(user_pub, user2_pub, user3_pub): def test_generate_outputs_flat_ownage(user_pub, user2_pub, user3_pub):
from planetmint.transactions.common.transaction import Output
from cryptoconditions import Ed25519Sha256, ThresholdSha256
expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub)) expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub))
expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub)) expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub))
expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub)) expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub))
@ -237,9 +218,6 @@ def test_generate_outputs_flat_ownage(user_pub, user2_pub, user3_pub):
def test_generate_output_single_owner(user_pub): def test_generate_output_single_owner(user_pub):
from planetmint.transactions.common.transaction import Output
from cryptoconditions import Ed25519Sha256
expected = Ed25519Sha256(public_key=b58decode(user_pub)) expected = Ed25519Sha256(public_key=b58decode(user_pub))
cond = Output.generate([user_pub], 1) cond = Output.generate([user_pub], 1)
@ -247,9 +225,6 @@ def test_generate_output_single_owner(user_pub):
def test_generate_output_single_owner_with_output(user_pub): def test_generate_output_single_owner_with_output(user_pub):
from planetmint.transactions.common.transaction import Output
from cryptoconditions import Ed25519Sha256
expected = Ed25519Sha256(public_key=b58decode(user_pub)) expected = Ed25519Sha256(public_key=b58decode(user_pub))
cond = Output.generate([expected], 1) cond = Output.generate([expected], 1)
@ -273,8 +248,6 @@ def test_generate_output_invalid_parameters(user_pub, user2_pub, user3_pub):
def test_invalid_transaction_initialization(asset_definition): def test_invalid_transaction_initialization(asset_definition):
from planetmint.transactions.common.transaction import Transaction
with raises(ValueError): with raises(ValueError):
Transaction(operation="invalid operation", asset=asset_definition) Transaction(operation="invalid operation", asset=asset_definition)
with raises(TypeError): with raises(TypeError):
@ -290,8 +263,6 @@ def test_invalid_transaction_initialization(asset_definition):
def test_create_default_asset_on_tx_initialization(asset_definition): def test_create_default_asset_on_tx_initialization(asset_definition):
from planetmint.transactions.common.transaction import Transaction
expected = {"data": None} expected = {"data": None}
tx = Transaction(Transaction.CREATE, asset=expected) tx = Transaction(Transaction.CREATE, asset=expected)
asset = tx.asset asset = tx.asset
@ -300,8 +271,6 @@ def test_create_default_asset_on_tx_initialization(asset_definition):
def test_transaction_serialization(user_input, user_output, data): def test_transaction_serialization(user_input, user_output, data):
from planetmint.transactions.common.transaction import Transaction
expected = { expected = {
"id": None, "id": None,
"version": Transaction.VERSION, "version": Transaction.VERSION,
@ -323,7 +292,6 @@ def test_transaction_serialization(user_input, user_output, data):
def test_transaction_deserialization(tri_state_transaction): def test_transaction_deserialization(tri_state_transaction):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model from .utils import validate_transaction_model
tx = Transaction.from_dict(tri_state_transaction) tx = Transaction.from_dict(tri_state_transaction)
@ -340,7 +308,6 @@ def test_invalid_input_initialization(user_input, user_pub):
def test_transaction_link_serialization(): def test_transaction_link_serialization():
from planetmint.transactions.common.transaction import TransactionLink
tx_id = "a transaction id" tx_id = "a transaction id"
expected = { expected = {
@ -353,8 +320,6 @@ def test_transaction_link_serialization():
def test_transaction_link_serialization_with_empty_payload(): def test_transaction_link_serialization_with_empty_payload():
from planetmint.transactions.common.transaction import TransactionLink
expected = None expected = None
tx_link = TransactionLink() tx_link = TransactionLink()
@ -362,8 +327,6 @@ def test_transaction_link_serialization_with_empty_payload():
def test_transaction_link_deserialization(): def test_transaction_link_deserialization():
from planetmint.transactions.common.transaction import TransactionLink
tx_id = "a transaction id" tx_id = "a transaction id"
expected = TransactionLink(tx_id, 0) expected = TransactionLink(tx_id, 0)
tx_link = { tx_link = {
@ -376,8 +339,6 @@ def test_transaction_link_deserialization():
def test_transaction_link_deserialization_with_empty_payload(): def test_transaction_link_deserialization_with_empty_payload():
from planetmint.transactions.common.transaction import TransactionLink
expected = TransactionLink() expected = TransactionLink()
tx_link = TransactionLink.from_dict(None) tx_link = TransactionLink.from_dict(None)
@ -385,8 +346,6 @@ def test_transaction_link_deserialization_with_empty_payload():
def test_transaction_link_empty_to_uri(): def test_transaction_link_empty_to_uri():
from planetmint.transactions.common.transaction import TransactionLink
expected = None expected = None
tx_link = TransactionLink().to_uri() tx_link = TransactionLink().to_uri()
@ -394,8 +353,6 @@ def test_transaction_link_empty_to_uri():
def test_transaction_link_to_uri(): def test_transaction_link_to_uri():
from planetmint.transactions.common.transaction import TransactionLink
expected = "path/transactions/abc/outputs/0" expected = "path/transactions/abc/outputs/0"
tx_link = TransactionLink("abc", 0).to_uri("path") tx_link = TransactionLink("abc", 0).to_uri("path")
@ -403,8 +360,6 @@ def test_transaction_link_to_uri():
def test_cast_transaction_link_to_boolean(): def test_cast_transaction_link_to_boolean():
from planetmint.transactions.common.transaction import TransactionLink
assert bool(TransactionLink()) is False assert bool(TransactionLink()) is False
assert bool(TransactionLink("a", None)) is False assert bool(TransactionLink("a", None)) is False
assert bool(TransactionLink(None, "b")) is False assert bool(TransactionLink(None, "b")) is False
@ -413,8 +368,6 @@ def test_cast_transaction_link_to_boolean():
def test_transaction_link_eq(): def test_transaction_link_eq():
from planetmint.transactions.common.transaction import TransactionLink
assert TransactionLink(1, 2) == TransactionLink(1, 2) assert TransactionLink(1, 2) == TransactionLink(1, 2)
assert TransactionLink(2, 2) != TransactionLink(1, 2) assert TransactionLink(2, 2) != TransactionLink(1, 2)
assert TransactionLink(1, 1) != TransactionLink(1, 2) assert TransactionLink(1, 1) != TransactionLink(1, 2)
@ -422,7 +375,6 @@ def test_transaction_link_eq():
def test_add_input_to_tx(user_input, asset_definition): def test_add_input_to_tx(user_input, asset_definition):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model from .utils import validate_transaction_model
tx = Transaction(Transaction.CREATE, asset_definition, [], []) tx = Transaction(Transaction.CREATE, asset_definition, [], [])
@ -434,8 +386,6 @@ def test_add_input_to_tx(user_input, asset_definition):
def test_add_input_to_tx_with_invalid_parameters(asset_definition): def test_add_input_to_tx_with_invalid_parameters(asset_definition):
from planetmint.transactions.common.transaction import Transaction
tx = Transaction(Transaction.CREATE, asset_definition) tx = Transaction(Transaction.CREATE, asset_definition)
with raises(TypeError): with raises(TypeError):
@ -443,7 +393,6 @@ def test_add_input_to_tx_with_invalid_parameters(asset_definition):
def test_add_output_to_tx(user_output, user_input, asset_definition): def test_add_output_to_tx(user_output, user_input, asset_definition):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model from .utils import validate_transaction_model
tx = Transaction(Transaction.CREATE, asset_definition, [user_input]) tx = Transaction(Transaction.CREATE, asset_definition, [user_input])
@ -455,8 +404,6 @@ def test_add_output_to_tx(user_output, user_input, asset_definition):
def test_add_output_to_tx_with_invalid_parameters(asset_definition): def test_add_output_to_tx_with_invalid_parameters(asset_definition):
from planetmint.transactions.common.transaction import Transaction
tx = Transaction(Transaction.CREATE, asset_definition, [], []) tx = Transaction(Transaction.CREATE, asset_definition, [], [])
with raises(TypeError): with raises(TypeError):
@ -471,7 +418,6 @@ def test_sign_with_invalid_parameters(utx, user_priv):
def test_validate_tx_simple_create_signature(user_input, user_output, user_priv, asset_definition): def test_validate_tx_simple_create_signature(user_input, user_output, user_priv, asset_definition):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model from .utils import validate_transaction_model
tx = Transaction(Transaction.CREATE, asset_definition, [user_input], [user_output]) tx = Transaction(Transaction.CREATE, asset_definition, [user_input], [user_output])
@ -508,8 +454,6 @@ def test_sign_threshold_with_invalid_params(utx, user_user2_threshold_input, use
def test_validate_input_with_invalid_parameters(utx): def test_validate_input_with_invalid_parameters(utx):
from planetmint.transactions.common.transaction import Transaction
input_conditions = [out.fulfillment.condition_uri for out in utx.outputs] input_conditions = [out.fulfillment.condition_uri for out in utx.outputs]
tx_dict = utx.to_dict() tx_dict = utx.to_dict()
tx_serialized = Transaction._to_str(tx_dict) tx_serialized = Transaction._to_str(tx_dict)
@ -526,7 +470,6 @@ def test_validate_tx_threshold_create_signature(
user2_priv, user2_priv,
asset_definition, asset_definition,
): ):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model from .utils import validate_transaction_model
tx = Transaction(Transaction.CREATE, asset_definition, [user_user2_threshold_input], [user_user2_threshold_output]) tx = Transaction(Transaction.CREATE, asset_definition, [user_user2_threshold_input], [user_user2_threshold_output])
@ -546,9 +489,6 @@ def test_validate_tx_threshold_create_signature(
def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv, asset_definition): def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv, asset_definition):
from cryptoconditions import Ed25519Sha256, ThresholdSha256
from planetmint.transactions.common.transaction import Input, Output, Transaction
threshold = ThresholdSha256(threshold=2) threshold = ThresholdSha256(threshold=2)
threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub))) threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub)))
threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub))) threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub)))
@ -581,8 +521,6 @@ def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv, asset_definiti
def test_multiple_input_validation_of_transfer_tx( def test_multiple_input_validation_of_transfer_tx(
user_input, user_output, user_priv, user2_pub, user2_priv, user3_pub, user3_priv, asset_definition user_input, user_output, user_priv, user2_pub, user2_priv, user3_pub, user3_priv, asset_definition
): ):
from planetmint.transactions.common.transaction import Transaction, TransactionLink, Input, Output
from cryptoconditions import Ed25519Sha256
from .utils import validate_transaction_model from .utils import validate_transaction_model
tx = Transaction(Transaction.CREATE, asset_definition, [user_input], [user_output, deepcopy(user_output)]) tx = Transaction(Transaction.CREATE, asset_definition, [user_input], [user_output, deepcopy(user_output)])
@ -607,9 +545,6 @@ def test_multiple_input_validation_of_transfer_tx(
def test_validate_inputs_of_transfer_tx_with_invalid_params( def test_validate_inputs_of_transfer_tx_with_invalid_params(
transfer_tx, cond_uri, utx, user2_pub, user_priv, ffill_uri transfer_tx, cond_uri, utx, user2_pub, user_priv, ffill_uri
): ):
from planetmint.transactions.common.transaction import Output
from cryptoconditions import Ed25519Sha256
invalid_out = Output(Ed25519Sha256.from_uri(ffill_uri), ["invalid"]) invalid_out = Output(Ed25519Sha256.from_uri(ffill_uri), ["invalid"])
assert transfer_tx.inputs_valid([invalid_out]) is False assert transfer_tx.inputs_valid([invalid_out]) is False
invalid_out = utx.outputs[0] invalid_out = utx.outputs[0]
@ -628,7 +563,6 @@ def test_validate_inputs_of_transfer_tx_with_invalid_params(
def test_create_create_transaction_single_io(user_output, user_pub, data): def test_create_create_transaction_single_io(user_output, user_pub, data):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model from .utils import validate_transaction_model
expected = { expected = {
@ -660,8 +594,6 @@ def test_validate_single_io_create_transaction(user_pub, user_priv, data, asset_
def test_create_create_transaction_multiple_io(user_output, user2_output, user_pub, user2_pub, asset_definition): def test_create_create_transaction_multiple_io(user_output, user2_output, user_pub, user2_pub, asset_definition):
from planetmint.transactions.common.transaction import Transaction, Input
# a fulfillment for a create transaction with multiple `owners_before` # a fulfillment for a create transaction with multiple `owners_before`
# is a fulfillment for an implicit threshold condition with # is a fulfillment for an implicit threshold condition with
# weight = len(owners_before) # weight = len(owners_before)
@ -695,8 +627,6 @@ def test_validate_multiple_io_create_transaction(user_pub, user_priv, user2_pub,
def test_create_create_transaction_threshold( def test_create_create_transaction_threshold(
user_pub, user2_pub, user3_pub, user_user2_threshold_output, user_user2_threshold_input, data user_pub, user2_pub, user3_pub, user_user2_threshold_output, user_user2_threshold_input, data
): ):
from planetmint.transactions.common.transaction import Transaction
expected = { expected = {
"outputs": [user_user2_threshold_output.to_dict()], "outputs": [user_user2_threshold_output.to_dict()],
"metadata": data, "metadata": data,
@ -763,7 +693,6 @@ def test_outputs_to_inputs(tx):
def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, user2_output, user_priv): def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, user2_output, user_priv):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model from .utils import validate_transaction_model
expected = { expected = {
@ -812,8 +741,6 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, user2_ou
def test_create_transfer_transaction_multiple_io( def test_create_transfer_transaction_multiple_io(
user_pub, user_priv, user2_pub, user2_priv, user3_pub, user2_output, asset_definition user_pub, user_priv, user2_pub, user2_priv, user3_pub, user2_output, asset_definition
): ):
from planetmint.transactions.common.transaction import Transaction
tx = Create.generate([user_pub], [([user_pub], 1), ([user2_pub], 1)], metadata={"message": "hello"}) tx = Create.generate([user_pub], [([user_pub], 1), ([user2_pub], 1)], metadata={"message": "hello"})
tx = tx.sign([user_priv]) tx = tx.sign([user_priv])
@ -873,7 +800,6 @@ def test_create_transfer_with_invalid_parameters(tx, user_pub):
def test_cant_add_empty_output(): def test_cant_add_empty_output():
from planetmint.transactions.common.transaction import Transaction
tx = Transaction(Transaction.CREATE, None) tx = Transaction(Transaction.CREATE, None)
@ -882,8 +808,6 @@ def test_cant_add_empty_output():
def test_cant_add_empty_input(): def test_cant_add_empty_input():
from planetmint.transactions.common.transaction import Transaction
tx = Transaction(Transaction.CREATE, None) tx = Transaction(Transaction.CREATE, None)
with raises(TypeError): with raises(TypeError):
@ -891,24 +815,18 @@ def test_cant_add_empty_input():
def test_unfulfilled_transaction_serialized(unfulfilled_transaction): def test_unfulfilled_transaction_serialized(unfulfilled_transaction):
from planetmint.transactions.common.transaction import Transaction
tx_obj = Transaction.from_dict(unfulfilled_transaction) tx_obj = Transaction.from_dict(unfulfilled_transaction)
expected = json.dumps(unfulfilled_transaction, sort_keys=True, separators=(",", ":"), ensure_ascii=True) expected = json.dumps(unfulfilled_transaction, sort_keys=True, separators=(",", ":"), ensure_ascii=True)
assert tx_obj.serialized == expected assert tx_obj.serialized == expected
def test_fulfilled_transaction_serialized(fulfilled_transaction): def test_fulfilled_transaction_serialized(fulfilled_transaction):
from planetmint.transactions.common.transaction import Transaction
tx_obj = Transaction.from_dict(fulfilled_transaction) tx_obj = Transaction.from_dict(fulfilled_transaction)
expected = json.dumps(fulfilled_transaction, sort_keys=True, separators=(",", ":"), ensure_ascii=True) expected = json.dumps(fulfilled_transaction, sort_keys=True, separators=(",", ":"), ensure_ascii=True)
assert tx_obj.serialized == expected assert tx_obj.serialized == expected
def test_transaction_hash(fulfilled_transaction): def test_transaction_hash(fulfilled_transaction):
from planetmint.transactions.common.transaction import Transaction
tx_obj = Transaction.from_dict(fulfilled_transaction) tx_obj = Transaction.from_dict(fulfilled_transaction)
assert tx_obj._id is None assert tx_obj._id is None
assert tx_obj.id is None assert tx_obj.id is None

View File

@ -5,6 +5,7 @@
import base64 import base64
import json import json
from pytest import mark
try: try:
from hashlib import sha3_256 from hashlib import sha3_256
@ -47,6 +48,9 @@ SAMPLE_PUBLIC_KEY = {
} }
@mark.skip(
reason="ripemd160, the core of pulbic_key64_to_address is no longer supported by hashlib (from python 3.9.13 on)"
)
def test_convert_base64_public_key_to_address(): def test_convert_base64_public_key_to_address():
from planetmint.tendermint_utils import public_key64_to_address from planetmint.tendermint_utils import public_key64_to_address