mirror of
https://github.com/planetmint/planetmint.git
synced 2025-06-07 14:46:38 +00:00
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:
parent
e41ce5df76
commit
d971709a79
14
CHANGELOG.md
14
CHANGELOG.md
@ -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).
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,10 +32,8 @@ GENERATE_KEYPAIR = """Scenario 'ecdh': Create the keypair
|
||||
When I create the bitcoin key
|
||||
Then print data"""
|
||||
|
||||
ZENROOM_DATA = {"also": "more data"}
|
||||
|
||||
HOUSE_ASSETS = {
|
||||
"data": {
|
||||
INITIAL_STATE = {"also": "more data"}
|
||||
SCRIPT_INPUT = {
|
||||
"houses": [
|
||||
{
|
||||
"name": "Harry",
|
||||
@ -47,11 +44,12 @@ HOUSE_ASSETS = {
|
||||
"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
|
||||
|
@ -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}")
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,10 +32,8 @@ GENERATE_KEYPAIR = """Scenario 'ecdh': Create the keypair
|
||||
When I create the bitcoin key
|
||||
Then print data"""
|
||||
|
||||
ZENROOM_DATA = {"also": "more data"}
|
||||
|
||||
HOUSE_ASSETS = {
|
||||
"data": {
|
||||
INITIAL_STATE = {"also": "more data"}
|
||||
SCRIPT_INPUT = {
|
||||
"houses": [
|
||||
{
|
||||
"name": "Harry",
|
||||
@ -47,11 +44,12 @@ HOUSE_ASSETS = {
|
||||
"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
|
||||
|
@ -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}")
|
||||
|
@ -11,3 +11,4 @@ box.space.transactions:drop()
|
||||
box.space.inputs:drop()
|
||||
box.space.outputs:drop()
|
||||
box.space.keys:drop()
|
||||
box.space.scripts:drop()
|
||||
|
@ -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'}})
|
||||
|
@ -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):
|
||||
|
@ -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()",
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -212,7 +212,9 @@ definitions:
|
||||
input:
|
||||
type: object
|
||||
output:
|
||||
type: object
|
||||
anyOf:
|
||||
- type: object
|
||||
- type: array
|
||||
policies:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -216,7 +216,9 @@ definitions:
|
||||
input:
|
||||
type: object
|
||||
output:
|
||||
type: object
|
||||
anyOf:
|
||||
- type: object
|
||||
- type: array
|
||||
policies:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -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
|
||||
|
@ -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"))
|
||||
|
@ -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"]
|
||||
|
3
setup.py
3
setup.py
@ -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",
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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,10 +34,8 @@ GENERATE_KEYPAIR = """Scenario 'ecdh': Create the keypair
|
||||
When I create the bitcoin key
|
||||
Then print data"""
|
||||
|
||||
ZENROOM_DATA = {"also": "more data"}
|
||||
|
||||
HOUSE_ASSETS = {
|
||||
"data": {
|
||||
INITIAL_STATE = {"also": "more data"}
|
||||
SCRIPT_INPUT = {
|
||||
"houses": [
|
||||
{
|
||||
"name": "Harry",
|
||||
@ -49,7 +46,6 @@ HOUSE_ASSETS = {
|
||||
"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
|
||||
|
@ -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))
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user