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]
## [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
updated documentation
@ -1184,6 +1196,6 @@ The first public release of Planetmint, including:
- Initial documentation (in `planetmint/docs`).
- Initial `README.md`, `ROADMAP.md`, `CODE_OF_CONDUCT.md`, and `CONTRIBUTING.md`.
- 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 `.travis.yml` (used by Travis CI).

View File

@ -7,6 +7,7 @@ RUN apt-get -qq update \
&& apt-get -y upgrade \
&& apt-get install -y jq vim zsh build-essential cmake\
&& 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 clean

View File

@ -46,4 +46,7 @@ VOLUME /data/db /data/configdb /tendermint
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

View File

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

View File

@ -4,7 +4,7 @@ RUN apt-get update \
&& pip install -U pip \
&& apt-get autoremove \
&& 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 /usr/local/bin/python -m pip install --upgrade pip
@ -13,6 +13,7 @@ RUN pip install --upgrade \
pycco \
websocket-client~=0.47.0 \
pytest~=3.0 \
planetmint-cryptoconditions>=0.9.9\
planetmint-cryptoconditions>=0.10.0\
planetmint-driver>=0.9.2 \
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
CONDITION_SCRIPT = """
Scenario 'ecdh': create the signature of an object
CONDITION_SCRIPT = """Scenario 'ecdh': create the signature of an object
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'
Then print the 'signature'"""
FULFILL_SCRIPT = """Scenario 'ecdh': Bob verifies the signature from Alice
Given I have a 'ecdh public key' from 'Alice'
Given that I have a 'string dictionary' named 'houses' inside 'asset'
Given I have a 'signature' named 'signature' inside 'metadata'
Given that I have a 'string dictionary' named 'houses'
Given I have a 'signature' named 'signature'
When I verify the 'houses' has a signature in 'signature' by 'Alice'
Then print the string 'ok'"""
@ -33,25 +32,24 @@ GENERATE_KEYPAIR = """Scenario 'ecdh': Create the keypair
When I create the bitcoin key
Then print data"""
ZENROOM_DATA = {"also": "more data"}
HOUSE_ASSETS = {
"data": {
"houses": [
{
"name": "Harry",
"team": "Gryffindor",
},
{
"name": "Draco",
"team": "Slytherin",
},
],
}
INITIAL_STATE = {"also": "more data"}
SCRIPT_INPUT = {
"houses": [
{
"name": "Harry",
"team": "Gryffindor",
},
{
"name": "Draco",
"team": "Slytherin",
},
],
}
metadata = {"units": 300, "type": "KG"}
ZENROOM_DATA = {"that": "is my data"}
@pytest.fixture
def gen_key_zencode():
@ -75,7 +73,12 @@ def condition_script_zencode():
@pytest.fixture
def zenroom_house_assets():
return HOUSE_ASSETS
return SCRIPT_INPUT
@pytest.fixture
def zenroom_script_input():
return SCRIPT_INPUT
@pytest.fixture

View File

@ -15,6 +15,7 @@ def test_zenroom_signing(
fulfill_script_zencode,
zenroom_data,
zenroom_house_assets,
zenroom_script_input,
condition_script_zencode,
):
@ -64,9 +65,18 @@ def test_zenroom_signing(
}
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 = {
"operation": "CREATE",
"asset": zenroom_house_assets,
"asset": {"data": {"test": "my asset"}},
"script": script_,
"metadata": metadata,
"outputs": [
output,
@ -79,35 +89,44 @@ def test_zenroom_signing(
}
# JSON: serialize the transaction-without-id to a json formatted string
message = json.dumps(
tx = json.dumps(
token_creation_tx,
sort_keys=True,
separators=(",", ":"),
ensure_ascii=False,
)
script_ = json.dumps(script_)
# major workflow:
# 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 server should ick the fulfill script and recreate the zenroom-sha and verify the signature
message = zenroomscpt.sign(message, condition_script_zencode, alice)
assert zenroomscpt.validate(message=message)
signed_input = zenroomscpt.sign(script_, condition_script_zencode, alice)
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()
message["inputs"][0]["fulfillment"] = fulfillment_uri_zen
tx = message
tx["inputs"][0]["fulfillment"] = fulfillment_uri_zen
tx["script"] = input_signed
tx["id"] = None
json_str_tx = json.dumps(tx, sort_keys=True, skipkeys=False, separators=(",", ":"))
# SHA3: hash the serialized id-less transaction to generate the id
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`
print(f"TX \n{tx}")
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}")

View File

@ -39,3 +39,8 @@ zipp==3.8.0
nest-asyncio==1.5.5
sphinx-press-theme==0.8.0
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
RUN apt-get install -y vim
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 mkdir -p /src
@ -15,6 +15,7 @@ RUN pip install --upgrade \
pytest~=6.2.5 \
pycco \
websocket-client~=0.47.0 \
planetmint-cryptoconditions>=0.9.9 \
planetmint-cryptoconditions>=0.10.0 \
planetmint-driver>=9.2.0 \
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
CONDITION_SCRIPT = """
Scenario 'ecdh': create the signature of an object
CONDITION_SCRIPT = """Scenario 'ecdh': create the signature of an object
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'
Then print the 'signature'"""
FULFILL_SCRIPT = """Scenario 'ecdh': Bob verifies the signature from Alice
Given I have a 'ecdh public key' from 'Alice'
Given that I have a 'string dictionary' named 'houses' inside 'asset'
Given I have a 'signature' named 'signature' inside 'metadata'
Given that I have a 'string dictionary' named 'houses'
Given I have a 'signature' named 'signature'
When I verify the 'houses' has a signature in 'signature' by 'Alice'
Then print the string 'ok'"""
@ -33,25 +32,24 @@ GENERATE_KEYPAIR = """Scenario 'ecdh': Create the keypair
When I create the bitcoin key
Then print data"""
ZENROOM_DATA = {"also": "more data"}
HOUSE_ASSETS = {
"data": {
"houses": [
{
"name": "Harry",
"team": "Gryffindor",
},
{
"name": "Draco",
"team": "Slytherin",
},
],
}
INITIAL_STATE = {"also": "more data"}
SCRIPT_INPUT = {
"houses": [
{
"name": "Harry",
"team": "Gryffindor",
},
{
"name": "Draco",
"team": "Slytherin",
},
],
}
metadata = {"units": 300, "type": "KG"}
ZENROOM_DATA = {"that": "is my data"}
@pytest.fixture
def gen_key_zencode():
@ -75,7 +73,12 @@ def condition_script_zencode():
@pytest.fixture
def zenroom_house_assets():
return HOUSE_ASSETS
return SCRIPT_INPUT
@pytest.fixture
def zenroom_script_input():
return SCRIPT_INPUT
@pytest.fixture

View File

@ -3,6 +3,7 @@ import base58
from hashlib import sha3_256
from cryptoconditions.types.zenroom import ZenroomSha256
from planetmint_driver.crypto import generate_keypair
from .helper.hosts import Hosts
from zenroom import zencode_exec
import time
@ -14,6 +15,7 @@ def test_zenroom_signing(
fulfill_script_zencode,
zenroom_data,
zenroom_house_assets,
zenroom_script_input,
condition_script_zencode,
):
@ -24,17 +26,11 @@ def test_zenroom_signing(
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
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
zencode_exec(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"]}}
script_ = {
"code": {"type": "zenroom", "raw": "test_string", "parameters": [{"obj": "1"}, {"obj": "2"}]},
"state": "dd8bbd234f9869cab4cc0b84aa660e9b5ef0664559b8375804ee8dce75b10576",
"input": zenroom_script_input,
"output": ["ok"],
"policies": {},
}
token_creation_tx = {
"operation": "CREATE",
"asset": zenroom_house_assets,
"asset": {"data": {"test": "my asset"}},
"script": script_,
"metadata": metadata,
"outputs": [
output,
@ -83,39 +89,44 @@ def test_zenroom_signing(
}
# JSON: serialize the transaction-without-id to a json formatted string
message = json.dumps(
tx = json.dumps(
token_creation_tx,
sort_keys=True,
separators=(",", ":"),
ensure_ascii=False,
)
script_ = json.dumps(script_)
# major workflow:
# 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 server should ick the fulfill script and recreate the zenroom-sha and verify the signature
message = zenroomscpt.sign(message, condition_script_zencode, alice)
assert zenroomscpt.validate(message=message)
signed_input = zenroomscpt.sign(script_, condition_script_zencode, alice)
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()
message["inputs"][0]["fulfillment"] = fulfillment_uri_zen
tx = message
tx["inputs"][0]["fulfillment"] = fulfillment_uri_zen
tx["script"] = input_signed
tx["id"] = None
json_str_tx = json.dumps(tx, sort_keys=True, skipkeys=False, separators=(",", ":"))
# SHA3: hash the serialized id-less transaction to generate the id
shared_creation_txid = sha3_256(json_str_tx.encode()).hexdigest()
message["id"] = shared_creation_txid
tx["id"] = shared_creation_txid
hosts = Hosts("/shared/hostnames")
pm_alpha = hosts.get_connection()
sent_transfer_tx = pm_alpha.transactions.send_commit(message)
sent_transfer_tx = pm_alpha.transactions.send_commit(tx)
time.sleep(1)
# Assert that transaction is stored on both planetmint nodes
hosts.assert_transaction(shared_creation_txid)
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.outputs:drop()
box.space.keys:drop()
box.space.scripts:drop()

View File

@ -68,3 +68,7 @@ utxos:format({{name='transaction_id' , type='string'}, {name='output_index' , ty
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('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"))
_txassets = connection.run(connection.space("assets").select(txid, index="txid_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)
_txoutputs = sorted(_txoutputs, key=itemgetter(8), reverse=False)
@ -44,6 +45,7 @@ def _group_transaction_by_ids(connection, txids: list):
"keys": _txkeys,
"asset": _txassets,
"metadata": _txmeta,
"script": _txscript,
}
tx_compose = TransactionCompose(db_results=result_map)
_transaction = tx_compose.convert_to_dict()
@ -74,6 +76,9 @@ def store_transactions(connection, signed_transactions: list):
if txtuples["asset"] is not None:
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)
def get_transaction(connection, transaction_id: str):

View File

@ -23,8 +23,10 @@ SPACE_NAMES = (
"outputs",
"keys",
"utxos",
"scripts",
)
SPACE_COMMANDS = {
"abci_chains": "abci_chains = box.schema.space.create('abci_chains', {engine='memtx', is_sync = false})",
"assets": "assets = box.schema.space.create('assets' , {engine='memtx' , is_sync=false})",
@ -39,6 +41,7 @@ SPACE_COMMANDS = {
"outputs": "outputs = box.schema.space.create('outputs')",
"keys": "keys = box.schema.space.create('keys')",
"utxos": "utxos = box.schema.space.create('utxos', {engine = 'memtx' , is_sync = false})",
"scripts": "scripts = box.schema.space.create('scripts', {engine = 'memtx' , is_sync = false})",
}
INDEX_COMMANDS = {
@ -102,8 +105,12 @@ INDEX_COMMANDS = {
"transaction_search": "utxos:create_index('transaction_search', {type='tree', unique=false, parts={'transaction_id'}})", # noqa: E501
"index_Search": "utxos:create_index('index_search', {type='tree', unique=false, parts={'output_index'}})",
},
"scripts": {
"txid_search": "scripts:create_index('txid_search', {type='tree', parts={'transaction_id'}})",
},
}
SCHEMA_COMMANDS = {
"abci_chains": "abci_chains:format({{name='height' , type='integer'},{name='is_synched' , type='boolean'},{name='chain_id',type='string'}, {name='id', type='string'}})", # noqa: E501
"assets": "assets:format({{name='data' , type='string'}, {name='tx_id', type='string'}, {name='asset_id', type='string'}})", # noqa: E501
@ -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
"keys": "keys:format({{name = 'id', type='string'}, {name = 'transaction_id', type = 'string'} ,{name = 'output_id', type = 'string'}, {name = 'public_key', type = 'string'}, {name = 'key_index', type = 'integer'}})", # noqa: E501
"utxos": "utxos:format({{name='transaction_id' , type='string'}, {name='output_index' , type='integer'}, {name='utxo_dict', type='string'}})", # noqa: E501
"scripts": "scripts:format({{name='transaction_id', type='string'},{name='script' , type='any'}})", # noqa: E501
}
SCHEMA_DROP_COMMANDS = {
@ -134,6 +142,7 @@ SCHEMA_DROP_COMMANDS = {
"outputs": "box.space.outputs:drop()",
"keys": "box.space.keys:drop()",
"utxos": "box.space.utxos:drop()",
"scripts": "box.space.scripts:drop()",
}

View File

@ -40,6 +40,7 @@ class TransactionDecompose:
"inputs": [],
"outputs": [],
"keys": [],
"script": None,
"metadata": None,
"asset": None,
}
@ -132,6 +133,12 @@ class TransactionDecompose:
_map = self.get_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):
self._metadata_check()
self.__asset_check()
@ -140,6 +147,7 @@ class TransactionDecompose:
keys, outputs = self.__prepare_outputs()
self._tuple_transaction["outputs"] = outputs
self._tuple_transaction["keys"] = keys
self._tuple_transaction["script"] = self.__prepare_script()
return self._tuple_transaction
@ -197,6 +205,12 @@ class TransactionCompose:
_outputs.append(_out)
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):
transaction = {k: None for k in list(self._map.keys())}
transaction["id"] = self._get_transaction_id()
@ -206,4 +220,6 @@ class TransactionCompose:
transaction["operation"] = self._get_transaction_operation()
transaction["inputs"] = self._get_inputs()
transaction["outputs"] = self._get_outputs()
if self._get_script():
transaction["script"] = self._get_script()
return transaction

View File

@ -13,14 +13,14 @@ from planetmint.parallel_validation import ParallelValidationApp
from planetmint.web import server, websocket_server
from planetmint.events import Exchange, EventTypes
from planetmint.utils import Process
from planetmint.version import __version__
logger = logging.getLogger(__name__)
BANNER = """
****************************************************************************
* *
* Planetmint 2.2.2 *
* Planetmint {} *
* codename "jumping sloth" *
* 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.start()
logger.info(BANNER.format(Config().get()["server"]["bind"]))
logger.info(BANNER.format(__version__, Config().get()["server"]["bind"]))
# start websocket server
p_websocket_server = Process(

View File

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

View File

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

View File

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

View File

@ -93,6 +93,7 @@ class Transaction(object):
version=None,
hash_id=None,
tx_dict=None,
script=None,
):
"""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):
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.operation = operation
self.asset = asset
self.inputs = inputs or []
self.outputs = outputs or []
self.metadata = metadata
self.script = script
self._id = hash_id
self.tx_dict = tx_dict
@ -320,7 +325,7 @@ class Transaction(object):
elif isinstance(input_.fulfillment, ThresholdSha256):
return cls._sign_threshold_signature_fulfillment(input_, message, key_pairs)
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:
raise ValueError("Fulfillment couldn't be matched to " "Cryptocondition fulfillment type.")
@ -533,7 +538,10 @@ class Transaction(object):
ffill_valid = False
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:
message = sha3_256(message.encode())
if input_.fulfills:
@ -558,7 +566,7 @@ class Transaction(object):
Returns:
dict: The Transaction as an alternative serialization format.
"""
return {
tx_dict = {
"inputs": [input_.to_dict() for input_ in self.inputs],
"outputs": [output.to_dict() for output in self.outputs],
"operation": str(self.operation),
@ -567,6 +575,9 @@ class Transaction(object):
"version": self.version,
"id": self._id,
}
if self.script:
tx_dict["script"] = self.script
return tx_dict
@staticmethod
# TODO: Remove `_dict` prefix of variable.
@ -699,6 +710,14 @@ class Transaction(object):
"version": tx["version"],
"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:
cls.validate_id(local_dict)
@ -715,6 +734,7 @@ class Transaction(object):
tx["version"],
hash_id=tx["id"],
tx_dict=tx,
script=script_,
)
@classmethod

View File

@ -195,6 +195,7 @@ def _fulfillment_to_details(fulfillment):
"type": "zenroom-sha-256",
"public_key": base58.b58encode(fulfillment.public_key).decode(),
"script": base58.b58encode(fulfillment.script).decode(),
"data": base58.b58encode(fulfillment.data).decode(),
}
raise UnsupportedTypeError(fulfillment.type_name)
@ -221,10 +222,10 @@ def _fulfillment_from_details(data, _depth=0):
return threshold
if data["type"] == "zenroom-sha-256":
public_key = base58.b58decode(data["public_key"])
script = base58.b58decode(data["script"])
# zenroom = ZenroomSha256(script=script, data=None, keys={public_key})
public_key_ = base58.b58decode(data["public_key"])
script_ = base58.b58decode(data["script"])
data_ = base58.b58decode(data["data"])
# 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"))

View File

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

View File

@ -108,9 +108,10 @@ tests_require = [
install_requires = [
"chardet==3.0.4",
"base58==2.1.1",
"aiohttp==3.8.1",
"abci==0.8.3",
"planetmint-cryptoconditions>=0.9.9",
"planetmint-cryptoconditions>=0.10.0",
"flask-cors==3.0.10",
"flask-restful==0.3.9",
"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:
- [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)

View File

@ -7,17 +7,16 @@ from cryptoconditions.types.ed25519 import Ed25519Sha256
from cryptoconditions.types.zenroom import ZenroomSha256
from planetmint.transactions.common.crypto import generate_key_pair
CONDITION_SCRIPT = """
Scenario 'ecdh': create the signature of an object
CONDITION_SCRIPT = """Scenario 'ecdh': create the signature of an object
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'
Then print the 'signature'"""
FULFILL_SCRIPT = """Scenario 'ecdh': Bob verifies the signature from Alice
Given I have a 'ecdh public key' from 'Alice'
Given that I have a 'string dictionary' named 'houses' inside 'asset'
Given I have a 'signature' named 'signature' inside 'metadata'
Given that I have a 'string dictionary' named 'houses'
Given I have a 'signature' named 'signature'
When I verify the 'houses' has a signature in 'signature' by 'Alice'
Then print the string 'ok'"""
@ -35,21 +34,18 @@ GENERATE_KEYPAIR = """Scenario 'ecdh': Create the keypair
When I create the bitcoin key
Then print data"""
ZENROOM_DATA = {"also": "more data"}
HOUSE_ASSETS = {
"data": {
"houses": [
{
"name": "Harry",
"team": "Gryffindor",
},
{
"name": "Draco",
"team": "Slytherin",
},
],
}
INITIAL_STATE = {"also": "more data"}
SCRIPT_INPUT = {
"houses": [
{
"name": "Harry",
"team": "Gryffindor",
},
{
"name": "Draco",
"team": "Slytherin",
},
],
}
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.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}")
# CRYPTO-CONDITIONS: generate the condition uri
@ -95,11 +91,19 @@ def test_zenroom_signing():
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"]}}
token_creation_tx = {
"operation": "CREATE",
"asset": HOUSE_ASSETS,
"asset": {"data": {"test": "my asset"}},
"metadata": metadata,
"script": script_,
"outputs": [
output,
],
@ -111,46 +115,65 @@ def test_zenroom_signing():
}
# JSON: serialize the transaction-without-id to a json formatted string
message = json.dumps(
tx = json.dumps(
token_creation_tx,
sort_keys=True,
separators=(",", ":"),
ensure_ascii=False,
)
script_ = json.dumps(script_)
# major workflow:
# 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 server should ick the fulfill script and recreate the zenroom-sha and verify the signature
message = zenroomscpt.sign(message, CONDITION_SCRIPT, alice)
assert zenroomscpt.validate(message=message)
signed_input = zenroomscpt.sign(script_, CONDITION_SCRIPT, alice)
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()
message["inputs"][0]["fulfillment"] = fulfillment_uri_zen
tx = message
tx["script"] = input_signed
tx["inputs"][0]["fulfillment"] = fulfillment_uri_zen
tx["id"] = None
json_str_tx = json.dumps(tx, sort_keys=True, skipkeys=False, separators=(",", ":"))
# SHA3: hash the serialized id-less transaction to generate the id
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.lib import Planetmint
from planetmint.transactions.common.exceptions import (
SchemaValidationError,
ValidationError,
)
try:
tx_obj = Transaction.from_dict(message)
except SchemaValidationError:
print(f"TX\n{tx}")
tx_obj = Transaction.from_dict(tx)
except SchemaValidationError as e:
print(e)
assert ()
except ValidationError as e:
print(e)
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}")
assert (tx_obj == False) is False

View File

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

View File

@ -10,9 +10,17 @@ import json
from copy import deepcopy
from base58 import b58encode, b58decode
from cryptoconditions import Ed25519Sha256
from planetmint.transactions.types.assets.create import Create
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
try:
@ -24,9 +32,6 @@ pytestmark = mark.bdb
def test_input_serialization(ffill_uri, user_pub):
from planetmint.transactions.common.transaction import Input
from cryptoconditions import Fulfillment
expected = {
"owners_before": [user_pub],
"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):
from planetmint.transactions.common.transaction import Input
from cryptoconditions import Fulfillment
expected = Input(Fulfillment.from_uri(ffill_uri), [user_pub])
ffill = {
"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):
from planetmint.transactions.common.transaction import Input
from cryptoconditions import Fulfillment
expected = Input(Fulfillment.from_uri(ffill_uri), [user_pub])
ffill = {
"owners_before": [user_pub],
@ -133,9 +132,6 @@ def test_output_deserialization(user_Ed25519, user_pub):
def test_output_hashlock_serialization():
from planetmint.transactions.common.transaction import Output
from cryptoconditions import PreimageSha256
secret = b"wow much secret"
hashlock = PreimageSha256(preimage=secret).condition_uri
@ -152,9 +148,6 @@ def test_output_hashlock_serialization():
def test_output_hashlock_deserialization():
from planetmint.transactions.common.transaction import Output
from cryptoconditions import PreimageSha256
secret = b"wow much secret"
hashlock = PreimageSha256(preimage=secret).condition_uri
expected = Output(hashlock, amount=1)
@ -170,9 +163,6 @@ def test_output_hashlock_deserialization():
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):
Output(cond_uri, user_pub)
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):
from planetmint.transactions.common.transaction import Output
from cryptoconditions import Ed25519Sha256, ThresholdSha256
expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub))
expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_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):
from planetmint.transactions.common.transaction import Output
from cryptoconditions import Ed25519Sha256, ThresholdSha256
expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub))
expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_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):
from planetmint.transactions.common.transaction import Output
from cryptoconditions import Ed25519Sha256, ThresholdSha256
expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub))
expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_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):
from planetmint.transactions.common.transaction import Output
from cryptoconditions import Ed25519Sha256
expected = Ed25519Sha256(public_key=b58decode(user_pub))
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):
from planetmint.transactions.common.transaction import Output
from cryptoconditions import Ed25519Sha256
expected = Ed25519Sha256(public_key=b58decode(user_pub))
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):
from planetmint.transactions.common.transaction import Transaction
with raises(ValueError):
Transaction(operation="invalid operation", asset=asset_definition)
with raises(TypeError):
@ -290,8 +263,6 @@ def test_invalid_transaction_initialization(asset_definition):
def test_create_default_asset_on_tx_initialization(asset_definition):
from planetmint.transactions.common.transaction import Transaction
expected = {"data": None}
tx = Transaction(Transaction.CREATE, asset=expected)
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):
from planetmint.transactions.common.transaction import Transaction
expected = {
"id": None,
"version": Transaction.VERSION,
@ -323,7 +292,6 @@ def test_transaction_serialization(user_input, user_output, data):
def test_transaction_deserialization(tri_state_transaction):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model
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():
from planetmint.transactions.common.transaction import TransactionLink
tx_id = "a transaction id"
expected = {
@ -353,8 +320,6 @@ def test_transaction_link_serialization():
def test_transaction_link_serialization_with_empty_payload():
from planetmint.transactions.common.transaction import TransactionLink
expected = None
tx_link = TransactionLink()
@ -362,8 +327,6 @@ def test_transaction_link_serialization_with_empty_payload():
def test_transaction_link_deserialization():
from planetmint.transactions.common.transaction import TransactionLink
tx_id = "a transaction id"
expected = TransactionLink(tx_id, 0)
tx_link = {
@ -376,8 +339,6 @@ def test_transaction_link_deserialization():
def test_transaction_link_deserialization_with_empty_payload():
from planetmint.transactions.common.transaction import TransactionLink
expected = TransactionLink()
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():
from planetmint.transactions.common.transaction import TransactionLink
expected = None
tx_link = TransactionLink().to_uri()
@ -394,8 +353,6 @@ def test_transaction_link_empty_to_uri():
def test_transaction_link_to_uri():
from planetmint.transactions.common.transaction import TransactionLink
expected = "path/transactions/abc/outputs/0"
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():
from planetmint.transactions.common.transaction import TransactionLink
assert bool(TransactionLink()) is False
assert bool(TransactionLink("a", None)) 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():
from planetmint.transactions.common.transaction import TransactionLink
assert TransactionLink(1, 2) == TransactionLink(1, 2)
assert TransactionLink(2, 2) != 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):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model
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):
from planetmint.transactions.common.transaction import Transaction
tx = Transaction(Transaction.CREATE, asset_definition)
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):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model
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):
from planetmint.transactions.common.transaction import Transaction
tx = Transaction(Transaction.CREATE, asset_definition, [], [])
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):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model
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):
from planetmint.transactions.common.transaction import Transaction
input_conditions = [out.fulfillment.condition_uri for out in utx.outputs]
tx_dict = utx.to_dict()
tx_serialized = Transaction._to_str(tx_dict)
@ -526,7 +470,6 @@ def test_validate_tx_threshold_create_signature(
user2_priv,
asset_definition,
):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model
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):
from cryptoconditions import Ed25519Sha256, ThresholdSha256
from planetmint.transactions.common.transaction import Input, Output, Transaction
threshold = ThresholdSha256(threshold=2)
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(
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
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(
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"])
assert transfer_tx.inputs_valid([invalid_out]) is False
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):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model
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):
from planetmint.transactions.common.transaction import Transaction, Input
# a fulfillment for a create transaction with multiple `owners_before`
# is a fulfillment for an implicit threshold condition with
# 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(
user_pub, user2_pub, user3_pub, user_user2_threshold_output, user_user2_threshold_input, data
):
from planetmint.transactions.common.transaction import Transaction
expected = {
"outputs": [user_user2_threshold_output.to_dict()],
"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):
from planetmint.transactions.common.transaction import Transaction
from .utils import validate_transaction_model
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(
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 = tx.sign([user_priv])
@ -873,7 +800,6 @@ def test_create_transfer_with_invalid_parameters(tx, user_pub):
def test_cant_add_empty_output():
from planetmint.transactions.common.transaction import Transaction
tx = Transaction(Transaction.CREATE, None)
@ -882,8 +808,6 @@ def test_cant_add_empty_output():
def test_cant_add_empty_input():
from planetmint.transactions.common.transaction import Transaction
tx = Transaction(Transaction.CREATE, None)
with raises(TypeError):
@ -891,24 +815,18 @@ def test_cant_add_empty_input():
def test_unfulfilled_transaction_serialized(unfulfilled_transaction):
from planetmint.transactions.common.transaction import Transaction
tx_obj = Transaction.from_dict(unfulfilled_transaction)
expected = json.dumps(unfulfilled_transaction, sort_keys=True, separators=(",", ":"), ensure_ascii=True)
assert tx_obj.serialized == expected
def test_fulfilled_transaction_serialized(fulfilled_transaction):
from planetmint.transactions.common.transaction import Transaction
tx_obj = Transaction.from_dict(fulfilled_transaction)
expected = json.dumps(fulfilled_transaction, sort_keys=True, separators=(",", ":"), ensure_ascii=True)
assert tx_obj.serialized == expected
def test_transaction_hash(fulfilled_transaction):
from planetmint.transactions.common.transaction import Transaction
tx_obj = Transaction.from_dict(fulfilled_transaction)
assert tx_obj._id is None
assert tx_obj.id is None

View File

@ -5,6 +5,7 @@
import base64
import json
from pytest import mark
try:
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():
from planetmint.tendermint_utils import public_key64_to_address