From f4e089c8a7163b2a39b896d90bc48f897a0b617f Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Mon, 14 Feb 2022 08:39:08 +0000 Subject: [PATCH 01/22] Integrate zenroom acceptance test --- acceptance/python/Dockerfile | 3 +- acceptance/python/src/test_zenroom.py | 207 ++++++++++++++++++++++++++ 2 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 acceptance/python/src/test_zenroom.py diff --git a/acceptance/python/Dockerfile b/acceptance/python/Dockerfile index a106dcf..340841b 100644 --- a/acceptance/python/Dockerfile +++ b/acceptance/python/Dockerfile @@ -7,4 +7,5 @@ RUN pip install --upgrade \ websocket-client~=0.47.0 \ pytest~=3.0 \ planetmint-driver>=0.9.0 \ - blns + blns \ + planetmint-cryptoconditions>=0.9.0 diff --git a/acceptance/python/src/test_zenroom.py b/acceptance/python/src/test_zenroom.py new file mode 100644 index 0000000..323cdbb --- /dev/null +++ b/acceptance/python/src/test_zenroom.py @@ -0,0 +1,207 @@ +# GOAL: +# In this script I tried to implement the ECDSA signature using zenroom + +# However, the scripts are customizable and so with the same procedure +# we can implement more complex smart contracts + +# PUBLIC IDENTITY +# The public identity of the users in this script (Bob and Alice) +# is the pair (ECDH public key, Testnet address) + +import json + +import hashlib +from cryptoconditions import ZenroomSha256 +from json.decoder import JSONDecodeError + +# from zenroom import zencode_exec + +# from bigchaindb_driver import BigchainDB +# # bdb_root_url = 'https://ipdb3.riddleandcode.com' +# bdb_root_url = 'http://localhost:9984/' +# bdb = BigchainDB(bdb_root_url) + +# The procedure to generate the keyring cannot be +# fixed in the code base, it depends on the particular +# smart contract +GENERATE_KEYPAIR = \ + """Rule input encoding base58 + Rule output encoding base58 + Scenario 'ecdh': Create the keypair + Given that I am known as 'Pippo' + When I create the ecdh key + When I create the testnet key + Then print data""" + +def genkey(): + return json.loads(ZenroomSha256.run_zenroom(GENERATE_KEYPAIR).output)['keys'] + +# There is not a unique way of generating the public +# key, for example, for the testnet I don't want the +# public key but the address (but there could exist +# a script in which the user want the public key and +# not the address) +# Thus we cannot fix it inside the script + +# secret key to public key +SK_TO_PK = \ + """Rule input encoding base58 + Rule output encoding base58 + Scenario 'ecdh': Create the keypair + Given that I am known as '{}' + Given I have the 'keys' + When I create the ecdh public key + When I create the testnet address + Then print my 'ecdh public key' + Then print my 'testnet address'""" + +def sk2pk(name, keys): + return json.loads(ZenroomSha256.run_zenroom(SK_TO_PK.format(name), + keys={'keys': keys}).output) +# Alice assert the composition of the houses + +# zen_public_keys is an identity dictionary + +alice, bob = genkey(), genkey() +print("============== ALICE KEYPAIR =================") +print(alice) +print("============== BOB KEYPAIR =================") +print(bob) + +asset = { + "data": { + "houses": [ + { + "name": "Harry", + "team": "Gryffindor", + }, + { + "name": "Draco", + "team": "Slytherin", + } + ], + } +} +zen_public_keys = sk2pk('Alice', alice) +zen_public_keys.update(sk2pk('Bob', bob)) + +data = { + 'also': 'more data' +} +print("============== PUBLIC IDENTITIES =================") +print(zen_public_keys) + +metadata = { +} + +version = '2.0' + +fulfill_script = """Rule input encoding base58 +Rule output encoding base58 +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 'data.signature' inside 'result' +When I verify the 'houses' has a signature in 'data.signature' by 'Alice' +Then print the string 'ok' +""" +# CRYPTO-CONDITIONS: instantiate an Ed25519 crypto-condition for buyer +zenSha = ZenroomSha256(script=fulfill_script, keys=zen_public_keys, data=data) + +# CRYPTO-CONDITIONS: generate the condition uri +condition_uri = zenSha.condition.serialize_uri() +# CRYPTO-CONDITIONS: construct an unsigned fulfillment dictionary +unsigned_fulfillment_dict = { + 'type': zenSha.TYPE_NAME, + 'script': fulfill_script, + 'keys': zen_public_keys, +} + +output = { + 'amount': '1000', + 'condition': { + 'details': unsigned_fulfillment_dict, + 'uri': condition_uri, + }, + 'data': data, + 'script': fulfill_script, + 'conf': '', + 'public_keys': (zen_public_keys['Alice']['ecdh_public_key'], ), +} + + +input_ = { + 'fulfillment': None, + 'fulfills': None, + 'owners_before': (zen_public_keys['Alice']['ecdh_public_key'], ), +} + +token_creation_tx = { + 'operation': 'CREATE', + 'asset': asset, + 'metadata': None, + 'outputs': (output,), + 'inputs': (input_,), + 'version': version, + 'id': None, +} + +# JSON: serialize the transaction-without-id to a json formatted string +message = json.dumps( + token_creation_tx, + sort_keys=True, + separators=(',', ':'), + ensure_ascii=False, +) + +print("====== GENERATE RESULT (METADATA) =======") +condition_script = """Rule input encoding base58 + Rule output encoding base58 + Scenario 'ecdh': create the signature of an object + Given I have the 'keys' + Given that I have a 'string dictionary' named 'houses' inside 'asset' + When I create the signature of 'houses' + When I rename the 'signature' to 'data.signature' + Then print the 'data.signature' + """ + +# THIS FILLS THE METADATA WITH THE RESULT +try: + assert(not zenSha.validate(message=message)) +except JSONDecodeError: + pass +except ValueError: + pass + +message = zenSha.sign(message, condition_script, alice) +assert(zenSha.validate(message=message)) +# now metadata looks like +# 'metadata': {'result': {'data.signature': {'r': 'fdoan0GYo9RGP8y0fq+PKZ9Q1V8+VqJtBkSMB1tUnGQ=', 's': 'RnJCEepYJcVgFG/Y6cRc/2DWPaz5Pe5NpdRWegrZk5A='}}} + +# CRYPTO-CONDITIONS: generate the fulfillment uri +fulfillment_uri = zenSha.serialize_uri() + +# add the fulfillment uri (signature) +token_creation_tx['inputs'][0]['fulfillment'] = fulfillment_uri +print(token_creation_tx) + +# JSON: serialize the id-less transaction to a json formatted string +json_str_tx = json.dumps( + token_creation_tx, + sort_keys=True, + separators=(',', ':'), + ensure_ascii=False, +) + + +# SHA3: hash the serialized id-less transaction to generate the id +shared_creation_txid = hashlib.sha3_256(json_str_tx.encode()).hexdigest() + +# add the id +token_creation_tx['id'] = shared_creation_txid + +# exit() +# send CREATE tx into the bdb network +# returned_creation_tx = bdb.transactions.send_async(token_creation_tx) + +# print(returned_creation_tx) \ No newline at end of file From ad01c4c543073b9617303dcd4b1d011d25882ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Eckel?= Date: Mon, 14 Feb 2022 15:26:08 +0100 Subject: [PATCH 02/22] fixed zenroom reference --- acceptance/python/Dockerfile | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/acceptance/python/Dockerfile b/acceptance/python/Dockerfile index 340841b..af022ac 100644 --- a/acceptance/python/Dockerfile +++ b/acceptance/python/Dockerfile @@ -1,11 +1,40 @@ FROM python:3.9 RUN apt-get update && apt-get install -y vim zsh +RUN apt-get update \ + && apt-get install -y git zsh\ + && pip install -U pip \ + && apt-get autoremove \ + && apt-get clean +RUN apt install sudo +RUN apt-get install -y python3 openssl ca-certificates git python3-dev +RUN apt-get install zsh gcc +RUN apt-get install libffi-dev +RUN apt-get install build-essential cmake -y + + RUN mkdir -p /src RUN pip install --upgrade \ pycco \ + #zenroom>=2.0.0 + #git+https://github.com/dyne/Zenroom.git@gitzenroom#subdirectory=bindings/python3 \ websocket-client~=0.47.0 \ pytest~=3.0 \ planetmint-driver>=0.9.0 \ blns \ - planetmint-cryptoconditions>=0.9.0 + git+https://github.com/planetmint/cryptoconditions.git@gitzenroom >=0.9.0 \ + chardet==3.0.4\ + aiohttp==3.7.4\ + abci==0.8.3\ + #planetmint-cryptoconditions>=0.9.0\ + flask-cors==3.0.10\ + flask-restful==0.3.9\ + flask==2.0.1\ + gunicorn==20.1.0\ + jsonschema==3.2.0\ + logstats==0.3.0\ + packaging>=20.9\ + pymongo==3.11.4\ + pyyaml==5.4.1\ + requests==2.25.1\ + setproctitle==1.2.2 From dd8f39712ed26f19af93a150a71bbb92bdd884a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Eckel?= Date: Tue, 15 Feb 2022 00:02:03 +0100 Subject: [PATCH 03/22] added additional dependences to the docker fils so that zenroom can be executed. added zenroom from git repo, because pypi servs an older buggy version --- Dockerfile | 2 +- Dockerfile-all-in-one | 2 +- Dockerfile-alpine | 2 +- Dockerfile-dev | 2 +- acceptance/python/Dockerfile | 77 +++++++++++++++++++++++------------- setup.py | 3 +- 6 files changed, 55 insertions(+), 33 deletions(-) diff --git a/Dockerfile b/Dockerfile index 20e657d..e7daeea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ COPY . /usr/src/app/ WORKDIR /usr/src/app RUN apt-get -qq update \ && apt-get -y upgrade \ - && apt-get install -y jq \ + && apt-get install -y jq vim zsh build-essential cmake\ && pip install . \ && apt-get autoremove \ && apt-get clean diff --git a/Dockerfile-all-in-one b/Dockerfile-all-in-one index 736934c..b64c832 100644 --- a/Dockerfile-all-in-one +++ b/Dockerfile-all-in-one @@ -9,7 +9,7 @@ WORKDIR /usr/src/app RUN apk --update add sudo bash \ && apk --update add python3 openssl ca-certificates git \ - && apk --update add --virtual build-dependencies python3-dev \ + && apk --update add --virtual build-dependencies python3-dev vim zsh build-essential cmake\ libffi-dev openssl-dev build-base jq zsh \ && apk add --no-cache libstdc++ dpkg gnupg \ && pip3 install --upgrade pip cffi \ diff --git a/Dockerfile-alpine b/Dockerfile-alpine index 0efa4cd..5eadd49 100644 --- a/Dockerfile-alpine +++ b/Dockerfile-alpine @@ -5,7 +5,7 @@ COPY . /usr/src/app/ WORKDIR /usr/src/app RUN apk --update add sudo \ && apk --update add python3 py-pip openssl ca-certificates git\ - && apk --update add --virtual build-dependencies python3-dev zsh \ + && apk --update add --virtual build-dependencies python3-dev zsh vim zsh build-essential cmake\ libffi-dev openssl-dev build-base \ && apk add --no-cache libstdc++ \ && pip3 install --upgrade pip cffi \ diff --git a/Dockerfile-dev b/Dockerfile-dev index c44b4f3..08c7642 100644 --- a/Dockerfile-dev +++ b/Dockerfile-dev @@ -3,7 +3,7 @@ FROM python:${python_version} LABEL maintainer "contact@ipdb.global" RUN apt-get update \ - && apt-get install -y git zsh\ + && apt-get install -y git zsh vim build-essential cmake\ && pip install -U pip \ && apt-get autoremove \ && apt-get clean diff --git a/acceptance/python/Dockerfile b/acceptance/python/Dockerfile index af022ac..6323c3a 100644 --- a/acceptance/python/Dockerfile +++ b/acceptance/python/Dockerfile @@ -1,40 +1,61 @@ FROM python:3.9 -RUN apt-get update && apt-get install -y vim zsh RUN apt-get update \ - && apt-get install -y git zsh\ && pip install -U pip \ && apt-get autoremove \ - && apt-get clean -RUN apt install sudo -RUN apt-get install -y python3 openssl ca-certificates git python3-dev -RUN apt-get install zsh gcc -RUN apt-get install libffi-dev -RUN apt-get install build-essential cmake -y - + && apt-get clean +RUN apt-get install -y vim zsh build-essential cmake RUN mkdir -p /src RUN pip install --upgrade \ pycco \ - #zenroom>=2.0.0 - #git+https://github.com/dyne/Zenroom.git@gitzenroom#subdirectory=bindings/python3 \ websocket-client~=0.47.0 \ pytest~=3.0 \ + git+https://github.com/planetmint/cryptoconditions.git@gitzenroom \ + #git+https://github.com/planetmint/planetmint-driver.git@gitzenroom \ + #planetmint-cryptoconditions>=0.9.0\ planetmint-driver>=0.9.0 \ - blns \ - git+https://github.com/planetmint/cryptoconditions.git@gitzenroom >=0.9.0 \ - chardet==3.0.4\ - aiohttp==3.7.4\ - abci==0.8.3\ - #planetmint-cryptoconditions>=0.9.0\ - flask-cors==3.0.10\ - flask-restful==0.3.9\ - flask==2.0.1\ - gunicorn==20.1.0\ - jsonschema==3.2.0\ - logstats==0.3.0\ - packaging>=20.9\ - pymongo==3.11.4\ - pyyaml==5.4.1\ - requests==2.25.1\ - setproctitle==1.2.2 + blns + + + + +#FROM python:3.9 +# +#RUN apt-get update && apt-get install -y vim zsh +#RUN apt-get update \ +# && apt-get install -y git zsh\ +# && pip install -U pip \ +# && apt-get autoremove \ +# && apt-get clean +#RUN apt install sudo +#RUN apt-get install -y python3 openssl ca-certificates git python3-dev +#RUN apt-get install zsh gcc +#RUN apt-get install libffi-dev +#RUN apt-get install build-essential cmake -y +# +# +#RUN mkdir -p /src +#RUN pip install --upgrade \ +# pycco \ +# websocket-client~=0.47.0 \ +# pytest~=3.0 \ +# planetmint-driver>=0.9.0 \ +# blns \ +# git+https://github.com/planetmint/cryptoconditions.git@gitzenroom >=0.9.0 \ +# chardet==3.0.4 \ +# aiohttp==3.7.4 \ +# abci==0.8.3 \ +# #planetmint-cryptoconditions>=0.9.0\ +# flask-cors==3.0.10 \ +# flask-restful==0.3.9 \ +# flask==2.0.1 \ +# gunicorn==20.1.0 \ +# jsonschema==3.2.0 \ +# logstats==0.3.0 \ +# packaging>=20.9 \ +# pymongo==3.11.4 \ +# pyyaml==5.4.1 \ +# requests==2.25.1 \ +# setproctitle==1.2.2 +# \ No newline at end of file diff --git a/setup.py b/setup.py index f837710..7aa0901 100644 --- a/setup.py +++ b/setup.py @@ -76,7 +76,8 @@ install_requires = [ 'chardet==3.0.4', 'aiohttp==3.7.4', 'abci==0.8.3', - 'planetmint-cryptoconditions>=0.9.0', + #'planetmint-cryptoconditions>=0.9.0', + 'planetmint-cryptoconditions @ git+https://github.com/planetmint/cryptoconditions.git@gitzenroom', 'flask-cors==3.0.10', 'flask-restful==0.3.9', 'flask==2.0.1', From ecb4b6dc74cf0575c7bd73f1980e809b2f9e8516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Eckel?= Date: Tue, 15 Feb 2022 00:08:24 +0100 Subject: [PATCH 04/22] using the custom planetmintdriver branch to avoid pypi zendesk downloads --- acceptance/python/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acceptance/python/Dockerfile b/acceptance/python/Dockerfile index 6323c3a..14defda 100644 --- a/acceptance/python/Dockerfile +++ b/acceptance/python/Dockerfile @@ -12,9 +12,9 @@ RUN pip install --upgrade \ websocket-client~=0.47.0 \ pytest~=3.0 \ git+https://github.com/planetmint/cryptoconditions.git@gitzenroom \ - #git+https://github.com/planetmint/planetmint-driver.git@gitzenroom \ + git+https://github.com/planetmint/planetmint-driver.git@gitzenroom \ #planetmint-cryptoconditions>=0.9.0\ - planetmint-driver>=0.9.0 \ + #planetmint-driver>=0.9.0 \ blns From 8c9eda1b4bb81fe4d529ddd74684417a778aac73 Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Mon, 21 Feb 2022 08:30:24 +0000 Subject: [PATCH 05/22] Added zenroom test --- acceptance/python/src/conftest.py | 89 ++++++++++ acceptance/python/src/test_zenroom.py | 236 +++++++------------------- 2 files changed, 146 insertions(+), 179 deletions(-) create mode 100644 acceptance/python/src/conftest.py diff --git a/acceptance/python/src/conftest.py b/acceptance/python/src/conftest.py new file mode 100644 index 0000000..34e8a3f --- /dev/null +++ b/acceptance/python/src/conftest.py @@ -0,0 +1,89 @@ +# Copyright © 2020 Interplanetary Database Association e.V., +# Planetmint and IPDB software contributors. +# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) +# Code is Apache-2.0 and docs are CC-BY-4.0 + +import pytest + +GENERATE_KEYPAIR = \ + """Rule input encoding base58 + Rule output encoding base58 + Scenario 'ecdh': Create the keypair + Given that I am known as 'Pippo' + When I create the ecdh key + When I create the testnet key + Then print data""" + +# secret key to public key +SK_TO_PK = \ + """Rule input encoding base58 + Rule output encoding base58 + Scenario 'ecdh': Create the keypair + Given that I am known as '{}' + Given I have the 'keys' + When I create the ecdh public key + When I create the testnet address + Then print my 'ecdh public key' + Then print my 'testnet address'""" + +FULFILL_SCRIPT = \ + """Rule input encoding base58 + Rule output encoding base58 + 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 'data.signature' inside 'result' + When I verify the 'houses' has a signature in 'data.signature' by 'Alice' + Then print the string 'ok'""" + +HOUSE_ASSETS = { + "data": { + "houses": [ + { + "name": "Harry", + "team": "Gryffindor", + }, + { + "name": "Draco", + "team": "Slytherin", + } + ], + } +} + +ZENROOM_DATA = { + 'also': 'more data' +} + +CONDITION_SCRIPT = """Rule input encoding base58 + Rule output encoding base58 + Scenario 'ecdh': create the signature of an object + Given I have the 'keys' + Given that I have a 'string dictionary' named 'houses' inside 'asset' + When I create the signature of 'houses' + When I rename the 'signature' to 'data.signature' + Then print the 'data.signature'""" + +@pytest.fixture +def gen_key_zencode(): + return GENERATE_KEYPAIR + +@pytest.fixture +def secret_key_to_private_key_zencode(): + return SK_TO_PK + +@pytest.fixture +def fulfill_script_zencode(): + return FULFILL_SCRIPT + +@pytest.fixture +def condition_script_zencode(): + return CONDITION_SCRIPT + +@pytest.fixture +def zenroom_house_assets(): + return HOUSE_ASSETS + +@pytest.fixture +def zenroom_data(): + return ZENROOM_DATA \ No newline at end of file diff --git a/acceptance/python/src/test_zenroom.py b/acceptance/python/src/test_zenroom.py index 323cdbb..2829fab 100644 --- a/acceptance/python/src/test_zenroom.py +++ b/acceptance/python/src/test_zenroom.py @@ -14,194 +14,72 @@ import hashlib from cryptoconditions import ZenroomSha256 from json.decoder import JSONDecodeError -# from zenroom import zencode_exec +def test_zenroom(gen_key_zencode, secret_key_to_private_key_zencode, fulfill_script_zencode, +condition_script_zencode, zenroom_data, zenroom_house_assets): + alice = json.loads(ZenroomSha256.run_zenroom(gen_key_zencode).output)['keys'] + bob = json.loads(ZenroomSha256.run_zenroom(gen_key_zencode).output)['keys'] -# from bigchaindb_driver import BigchainDB -# # bdb_root_url = 'https://ipdb3.riddleandcode.com' -# bdb_root_url = 'http://localhost:9984/' -# bdb = BigchainDB(bdb_root_url) + zen_public_keys = json.loads(ZenroomSha256.run_zenroom(secret_key_to_private_key_zencode.format('Alice'), + keys={'keys': alice}).output) + zen_public_keys.update(json.loads(ZenroomSha256.run_zenroom(secret_key_to_private_key_zencode.format('Bob'), + keys={'keys': bob}).output)) -# The procedure to generate the keyring cannot be -# fixed in the code base, it depends on the particular -# smart contract -GENERATE_KEYPAIR = \ - """Rule input encoding base58 - Rule output encoding base58 - Scenario 'ecdh': Create the keypair - Given that I am known as 'Pippo' - When I create the ecdh key - When I create the testnet key - Then print data""" + # CRYPTO-CONDITIONS: instantiate an Ed25519 crypto-condition for buyer + zenSha = ZenroomSha256(script=fulfill_script_zencode, keys=zen_public_keys, data=zenroom_data) -def genkey(): - return json.loads(ZenroomSha256.run_zenroom(GENERATE_KEYPAIR).output)['keys'] + # CRYPTO-CONDITIONS: generate the condition uri + condition_uri = zenSha.condition.serialize_uri() -# There is not a unique way of generating the public -# key, for example, for the testnet I don't want the -# public key but the address (but there could exist -# a script in which the user want the public key and -# not the address) -# Thus we cannot fix it inside the script - -# secret key to public key -SK_TO_PK = \ - """Rule input encoding base58 - Rule output encoding base58 - Scenario 'ecdh': Create the keypair - Given that I am known as '{}' - Given I have the 'keys' - When I create the ecdh public key - When I create the testnet address - Then print my 'ecdh public key' - Then print my 'testnet address'""" - -def sk2pk(name, keys): - return json.loads(ZenroomSha256.run_zenroom(SK_TO_PK.format(name), - keys={'keys': keys}).output) -# Alice assert the composition of the houses - -# zen_public_keys is an identity dictionary - -alice, bob = genkey(), genkey() -print("============== ALICE KEYPAIR =================") -print(alice) -print("============== BOB KEYPAIR =================") -print(bob) - -asset = { - "data": { - "houses": [ - { - "name": "Harry", - "team": "Gryffindor", - }, - { - "name": "Draco", - "team": "Slytherin", - } - ], + # CRYPTO-CONDITIONS: construct an unsigned fulfillment dictionary + unsigned_fulfillment_dict = { + 'type': zenSha.TYPE_NAME, + 'script': fulfill_script_zencode, + 'keys': zen_public_keys, } -} -zen_public_keys = sk2pk('Alice', alice) -zen_public_keys.update(sk2pk('Bob', bob)) -data = { - 'also': 'more data' -} -print("============== PUBLIC IDENTITIES =================") -print(zen_public_keys) - -metadata = { -} - -version = '2.0' - -fulfill_script = """Rule input encoding base58 -Rule output encoding base58 -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 'data.signature' inside 'result' -When I verify the 'houses' has a signature in 'data.signature' by 'Alice' -Then print the string 'ok' -""" -# CRYPTO-CONDITIONS: instantiate an Ed25519 crypto-condition for buyer -zenSha = ZenroomSha256(script=fulfill_script, keys=zen_public_keys, data=data) - -# CRYPTO-CONDITIONS: generate the condition uri -condition_uri = zenSha.condition.serialize_uri() -# CRYPTO-CONDITIONS: construct an unsigned fulfillment dictionary -unsigned_fulfillment_dict = { - 'type': zenSha.TYPE_NAME, - 'script': fulfill_script, - 'keys': zen_public_keys, -} - -output = { - 'amount': '1000', - 'condition': { - 'details': unsigned_fulfillment_dict, - 'uri': condition_uri, - }, - 'data': data, - 'script': fulfill_script, - 'conf': '', - 'public_keys': (zen_public_keys['Alice']['ecdh_public_key'], ), -} + output = { + 'amount': '1000', + 'condition': { + 'details': unsigned_fulfillment_dict, + 'uri': condition_uri, + }, + 'data': zenroom_data, + 'script': fulfill_script_zencode, + 'conf': '', + 'public_keys': (zen_public_keys['Alice']['ecdh_public_key'], ), + } -input_ = { - 'fulfillment': None, - 'fulfills': None, - 'owners_before': (zen_public_keys['Alice']['ecdh_public_key'], ), -} + input_ = { + 'fulfillment': None, + 'fulfills': None, + 'owners_before': (zen_public_keys['Alice']['ecdh_public_key'], ), + } -token_creation_tx = { - 'operation': 'CREATE', - 'asset': asset, - 'metadata': None, - 'outputs': (output,), - 'inputs': (input_,), - 'version': version, - 'id': None, -} + token_creation_tx = { + 'operation': 'CREATE', + 'asset': zenroom_house_assets, + 'metadata': None, + 'outputs': (output,), + 'inputs': (input_,), + 'version': '2.0', + 'id': None, + } -# JSON: serialize the transaction-without-id to a json formatted string -message = json.dumps( - token_creation_tx, - sort_keys=True, - separators=(',', ':'), - ensure_ascii=False, -) + # JSON: serialize the transaction-without-id to a json formatted string + message = json.dumps( + token_creation_tx, + sort_keys=True, + separators=(',', ':'), + ensure_ascii=False, + ) -print("====== GENERATE RESULT (METADATA) =======") -condition_script = """Rule input encoding base58 - Rule output encoding base58 - Scenario 'ecdh': create the signature of an object - Given I have the 'keys' - Given that I have a 'string dictionary' named 'houses' inside 'asset' - When I create the signature of 'houses' - When I rename the 'signature' to 'data.signature' - Then print the 'data.signature' - """ + try: + assert(not zenSha.validate(message=message)) + except JSONDecodeError: + pass + except ValueError: + pass -# THIS FILLS THE METADATA WITH THE RESULT -try: - assert(not zenSha.validate(message=message)) -except JSONDecodeError: - pass -except ValueError: - pass - -message = zenSha.sign(message, condition_script, alice) -assert(zenSha.validate(message=message)) -# now metadata looks like -# 'metadata': {'result': {'data.signature': {'r': 'fdoan0GYo9RGP8y0fq+PKZ9Q1V8+VqJtBkSMB1tUnGQ=', 's': 'RnJCEepYJcVgFG/Y6cRc/2DWPaz5Pe5NpdRWegrZk5A='}}} - -# CRYPTO-CONDITIONS: generate the fulfillment uri -fulfillment_uri = zenSha.serialize_uri() - -# add the fulfillment uri (signature) -token_creation_tx['inputs'][0]['fulfillment'] = fulfillment_uri -print(token_creation_tx) - -# JSON: serialize the id-less transaction to a json formatted string -json_str_tx = json.dumps( - token_creation_tx, - sort_keys=True, - separators=(',', ':'), - ensure_ascii=False, -) - - -# SHA3: hash the serialized id-less transaction to generate the id -shared_creation_txid = hashlib.sha3_256(json_str_tx.encode()).hexdigest() - -# add the id -token_creation_tx['id'] = shared_creation_txid - -# exit() -# send CREATE tx into the bdb network -# returned_creation_tx = bdb.transactions.send_async(token_creation_tx) - -# print(returned_creation_tx) \ No newline at end of file + message = zenSha.sign(message, condition_script_zencode, alice) + assert(zenSha.validate(message=message)) From 5f53ed08769a3909191433a0cfd08ed4afda5306 Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Mon, 21 Feb 2022 08:30:24 +0000 Subject: [PATCH 06/22] Added zenroom test Signed-off-by: Sangat Das --- acceptance/python/src/conftest.py | 89 ++++++++++ acceptance/python/src/test_zenroom.py | 236 +++++++------------------- 2 files changed, 146 insertions(+), 179 deletions(-) create mode 100644 acceptance/python/src/conftest.py diff --git a/acceptance/python/src/conftest.py b/acceptance/python/src/conftest.py new file mode 100644 index 0000000..34e8a3f --- /dev/null +++ b/acceptance/python/src/conftest.py @@ -0,0 +1,89 @@ +# Copyright © 2020 Interplanetary Database Association e.V., +# Planetmint and IPDB software contributors. +# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) +# Code is Apache-2.0 and docs are CC-BY-4.0 + +import pytest + +GENERATE_KEYPAIR = \ + """Rule input encoding base58 + Rule output encoding base58 + Scenario 'ecdh': Create the keypair + Given that I am known as 'Pippo' + When I create the ecdh key + When I create the testnet key + Then print data""" + +# secret key to public key +SK_TO_PK = \ + """Rule input encoding base58 + Rule output encoding base58 + Scenario 'ecdh': Create the keypair + Given that I am known as '{}' + Given I have the 'keys' + When I create the ecdh public key + When I create the testnet address + Then print my 'ecdh public key' + Then print my 'testnet address'""" + +FULFILL_SCRIPT = \ + """Rule input encoding base58 + Rule output encoding base58 + 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 'data.signature' inside 'result' + When I verify the 'houses' has a signature in 'data.signature' by 'Alice' + Then print the string 'ok'""" + +HOUSE_ASSETS = { + "data": { + "houses": [ + { + "name": "Harry", + "team": "Gryffindor", + }, + { + "name": "Draco", + "team": "Slytherin", + } + ], + } +} + +ZENROOM_DATA = { + 'also': 'more data' +} + +CONDITION_SCRIPT = """Rule input encoding base58 + Rule output encoding base58 + Scenario 'ecdh': create the signature of an object + Given I have the 'keys' + Given that I have a 'string dictionary' named 'houses' inside 'asset' + When I create the signature of 'houses' + When I rename the 'signature' to 'data.signature' + Then print the 'data.signature'""" + +@pytest.fixture +def gen_key_zencode(): + return GENERATE_KEYPAIR + +@pytest.fixture +def secret_key_to_private_key_zencode(): + return SK_TO_PK + +@pytest.fixture +def fulfill_script_zencode(): + return FULFILL_SCRIPT + +@pytest.fixture +def condition_script_zencode(): + return CONDITION_SCRIPT + +@pytest.fixture +def zenroom_house_assets(): + return HOUSE_ASSETS + +@pytest.fixture +def zenroom_data(): + return ZENROOM_DATA \ No newline at end of file diff --git a/acceptance/python/src/test_zenroom.py b/acceptance/python/src/test_zenroom.py index 323cdbb..2829fab 100644 --- a/acceptance/python/src/test_zenroom.py +++ b/acceptance/python/src/test_zenroom.py @@ -14,194 +14,72 @@ import hashlib from cryptoconditions import ZenroomSha256 from json.decoder import JSONDecodeError -# from zenroom import zencode_exec +def test_zenroom(gen_key_zencode, secret_key_to_private_key_zencode, fulfill_script_zencode, +condition_script_zencode, zenroom_data, zenroom_house_assets): + alice = json.loads(ZenroomSha256.run_zenroom(gen_key_zencode).output)['keys'] + bob = json.loads(ZenroomSha256.run_zenroom(gen_key_zencode).output)['keys'] -# from bigchaindb_driver import BigchainDB -# # bdb_root_url = 'https://ipdb3.riddleandcode.com' -# bdb_root_url = 'http://localhost:9984/' -# bdb = BigchainDB(bdb_root_url) + zen_public_keys = json.loads(ZenroomSha256.run_zenroom(secret_key_to_private_key_zencode.format('Alice'), + keys={'keys': alice}).output) + zen_public_keys.update(json.loads(ZenroomSha256.run_zenroom(secret_key_to_private_key_zencode.format('Bob'), + keys={'keys': bob}).output)) -# The procedure to generate the keyring cannot be -# fixed in the code base, it depends on the particular -# smart contract -GENERATE_KEYPAIR = \ - """Rule input encoding base58 - Rule output encoding base58 - Scenario 'ecdh': Create the keypair - Given that I am known as 'Pippo' - When I create the ecdh key - When I create the testnet key - Then print data""" + # CRYPTO-CONDITIONS: instantiate an Ed25519 crypto-condition for buyer + zenSha = ZenroomSha256(script=fulfill_script_zencode, keys=zen_public_keys, data=zenroom_data) -def genkey(): - return json.loads(ZenroomSha256.run_zenroom(GENERATE_KEYPAIR).output)['keys'] + # CRYPTO-CONDITIONS: generate the condition uri + condition_uri = zenSha.condition.serialize_uri() -# There is not a unique way of generating the public -# key, for example, for the testnet I don't want the -# public key but the address (but there could exist -# a script in which the user want the public key and -# not the address) -# Thus we cannot fix it inside the script - -# secret key to public key -SK_TO_PK = \ - """Rule input encoding base58 - Rule output encoding base58 - Scenario 'ecdh': Create the keypair - Given that I am known as '{}' - Given I have the 'keys' - When I create the ecdh public key - When I create the testnet address - Then print my 'ecdh public key' - Then print my 'testnet address'""" - -def sk2pk(name, keys): - return json.loads(ZenroomSha256.run_zenroom(SK_TO_PK.format(name), - keys={'keys': keys}).output) -# Alice assert the composition of the houses - -# zen_public_keys is an identity dictionary - -alice, bob = genkey(), genkey() -print("============== ALICE KEYPAIR =================") -print(alice) -print("============== BOB KEYPAIR =================") -print(bob) - -asset = { - "data": { - "houses": [ - { - "name": "Harry", - "team": "Gryffindor", - }, - { - "name": "Draco", - "team": "Slytherin", - } - ], + # CRYPTO-CONDITIONS: construct an unsigned fulfillment dictionary + unsigned_fulfillment_dict = { + 'type': zenSha.TYPE_NAME, + 'script': fulfill_script_zencode, + 'keys': zen_public_keys, } -} -zen_public_keys = sk2pk('Alice', alice) -zen_public_keys.update(sk2pk('Bob', bob)) -data = { - 'also': 'more data' -} -print("============== PUBLIC IDENTITIES =================") -print(zen_public_keys) - -metadata = { -} - -version = '2.0' - -fulfill_script = """Rule input encoding base58 -Rule output encoding base58 -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 'data.signature' inside 'result' -When I verify the 'houses' has a signature in 'data.signature' by 'Alice' -Then print the string 'ok' -""" -# CRYPTO-CONDITIONS: instantiate an Ed25519 crypto-condition for buyer -zenSha = ZenroomSha256(script=fulfill_script, keys=zen_public_keys, data=data) - -# CRYPTO-CONDITIONS: generate the condition uri -condition_uri = zenSha.condition.serialize_uri() -# CRYPTO-CONDITIONS: construct an unsigned fulfillment dictionary -unsigned_fulfillment_dict = { - 'type': zenSha.TYPE_NAME, - 'script': fulfill_script, - 'keys': zen_public_keys, -} - -output = { - 'amount': '1000', - 'condition': { - 'details': unsigned_fulfillment_dict, - 'uri': condition_uri, - }, - 'data': data, - 'script': fulfill_script, - 'conf': '', - 'public_keys': (zen_public_keys['Alice']['ecdh_public_key'], ), -} + output = { + 'amount': '1000', + 'condition': { + 'details': unsigned_fulfillment_dict, + 'uri': condition_uri, + }, + 'data': zenroom_data, + 'script': fulfill_script_zencode, + 'conf': '', + 'public_keys': (zen_public_keys['Alice']['ecdh_public_key'], ), + } -input_ = { - 'fulfillment': None, - 'fulfills': None, - 'owners_before': (zen_public_keys['Alice']['ecdh_public_key'], ), -} + input_ = { + 'fulfillment': None, + 'fulfills': None, + 'owners_before': (zen_public_keys['Alice']['ecdh_public_key'], ), + } -token_creation_tx = { - 'operation': 'CREATE', - 'asset': asset, - 'metadata': None, - 'outputs': (output,), - 'inputs': (input_,), - 'version': version, - 'id': None, -} + token_creation_tx = { + 'operation': 'CREATE', + 'asset': zenroom_house_assets, + 'metadata': None, + 'outputs': (output,), + 'inputs': (input_,), + 'version': '2.0', + 'id': None, + } -# JSON: serialize the transaction-without-id to a json formatted string -message = json.dumps( - token_creation_tx, - sort_keys=True, - separators=(',', ':'), - ensure_ascii=False, -) + # JSON: serialize the transaction-without-id to a json formatted string + message = json.dumps( + token_creation_tx, + sort_keys=True, + separators=(',', ':'), + ensure_ascii=False, + ) -print("====== GENERATE RESULT (METADATA) =======") -condition_script = """Rule input encoding base58 - Rule output encoding base58 - Scenario 'ecdh': create the signature of an object - Given I have the 'keys' - Given that I have a 'string dictionary' named 'houses' inside 'asset' - When I create the signature of 'houses' - When I rename the 'signature' to 'data.signature' - Then print the 'data.signature' - """ + try: + assert(not zenSha.validate(message=message)) + except JSONDecodeError: + pass + except ValueError: + pass -# THIS FILLS THE METADATA WITH THE RESULT -try: - assert(not zenSha.validate(message=message)) -except JSONDecodeError: - pass -except ValueError: - pass - -message = zenSha.sign(message, condition_script, alice) -assert(zenSha.validate(message=message)) -# now metadata looks like -# 'metadata': {'result': {'data.signature': {'r': 'fdoan0GYo9RGP8y0fq+PKZ9Q1V8+VqJtBkSMB1tUnGQ=', 's': 'RnJCEepYJcVgFG/Y6cRc/2DWPaz5Pe5NpdRWegrZk5A='}}} - -# CRYPTO-CONDITIONS: generate the fulfillment uri -fulfillment_uri = zenSha.serialize_uri() - -# add the fulfillment uri (signature) -token_creation_tx['inputs'][0]['fulfillment'] = fulfillment_uri -print(token_creation_tx) - -# JSON: serialize the id-less transaction to a json formatted string -json_str_tx = json.dumps( - token_creation_tx, - sort_keys=True, - separators=(',', ':'), - ensure_ascii=False, -) - - -# SHA3: hash the serialized id-less transaction to generate the id -shared_creation_txid = hashlib.sha3_256(json_str_tx.encode()).hexdigest() - -# add the id -token_creation_tx['id'] = shared_creation_txid - -# exit() -# send CREATE tx into the bdb network -# returned_creation_tx = bdb.transactions.send_async(token_creation_tx) - -# print(returned_creation_tx) \ No newline at end of file + message = zenSha.sign(message, condition_script_zencode, alice) + assert(zenSha.validate(message=message)) From 7a3a5e17137ce44304381ec06bed791f23441b95 Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Mon, 21 Feb 2022 08:34:23 +0000 Subject: [PATCH 07/22] Change reference to planetmint-driver to planetmint-driver-python Signed-off-by: Sangat Das --- docs/root/source/contributing/index.rst | 2 +- docs/root/source/contributing/ways-to-contribute/write-docs.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/root/source/contributing/index.rst b/docs/root/source/contributing/index.rst index cf0b606..a109838 100644 --- a/docs/root/source/contributing/index.rst +++ b/docs/root/source/contributing/index.rst @@ -11,7 +11,7 @@ There are many ways you can contribute to Planetmint. It includes several sub-projects. - `Planetmint Server `_ -- `Planetmint Python Driver `_ +- `Planetmint Python Driver `_ - `Planetmint JavaScript Driver `_ - `Planetmint Java Driver `_ - `cryptoconditions `_ (a Python package by us) diff --git a/docs/root/source/contributing/ways-to-contribute/write-docs.md b/docs/root/source/contributing/ways-to-contribute/write-docs.md index d223243..23bf7ea 100644 --- a/docs/root/source/contributing/ways-to-contribute/write-docs.md +++ b/docs/root/source/contributing/ways-to-contribute/write-docs.md @@ -19,7 +19,7 @@ If you're writing code, you should also update any related docs. However, you mi You can certainly do that! - The docs for Planetmint Server live under ``planetmint/docs/`` in the ``planetmint/planetmint`` repo. -- There are docs for the Python driver under ``planetmint-driver/docs/`` in the ``planetmint/planetmint-driver`` repo. +- There are docs for the Python driver under ``planetmint-driver/docs/`` in the ``planetmint/planetmint-driver-python`` repo. - There are docs for the JavaScript driver under ``planetmint/js-bigchaindb-driver`` in the ``planetmint/js-bigchaindb-driver`` repo. - The source code for the Planetmint website is in a private repo, but we can give you access if you ask. From 64f5ec01f13f5e15218b136da30ba33df13f8f38 Mon Sep 17 00:00:00 2001 From: ArpitShukla007 Date: Wed, 9 Mar 2022 09:06:45 +0000 Subject: [PATCH 08/22] Basic structuring --- .../{ => transactions}/common/__init__.py | 0 .../{ => transactions}/common/crypto.py | 0 .../{ => transactions}/common/exceptions.py | 0 planetmint/transactions/common/input.py | 117 ++++++++++++++++++ .../{ => transactions}/common/memoize.py | 0 .../common/schema/README.md | 0 .../common/schema/__init__.py | 0 ...saction_chain_migration_election_v2.0.yaml | 0 .../schema/transaction_create_v1.0.yaml | 0 .../schema/transaction_create_v2.0.yaml | 0 .../schema/transaction_transfer_v1.0.yaml | 0 .../schema/transaction_transfer_v2.0.yaml | 0 .../common/schema/transaction_v1.0.yaml | 0 .../common/schema/transaction_v2.0.yaml | 0 .../transaction_validator_election_v2.0.yaml | 0 .../common/schema/transaction_vote_v2.0.yaml | 0 .../{ => transactions}/common/transaction.py | 0 .../common/transaction_mode_types.py | 0 planetmint/{ => transactions}/common/utils.py | 0 19 files changed, 117 insertions(+) rename planetmint/{ => transactions}/common/__init__.py (100%) rename planetmint/{ => transactions}/common/crypto.py (100%) rename planetmint/{ => transactions}/common/exceptions.py (100%) create mode 100644 planetmint/transactions/common/input.py rename planetmint/{ => transactions}/common/memoize.py (100%) rename planetmint/{ => transactions}/common/schema/README.md (100%) rename planetmint/{ => transactions}/common/schema/__init__.py (100%) rename planetmint/{ => transactions}/common/schema/transaction_chain_migration_election_v2.0.yaml (100%) rename planetmint/{ => transactions}/common/schema/transaction_create_v1.0.yaml (100%) rename planetmint/{ => transactions}/common/schema/transaction_create_v2.0.yaml (100%) rename planetmint/{ => transactions}/common/schema/transaction_transfer_v1.0.yaml (100%) rename planetmint/{ => transactions}/common/schema/transaction_transfer_v2.0.yaml (100%) rename planetmint/{ => transactions}/common/schema/transaction_v1.0.yaml (100%) rename planetmint/{ => transactions}/common/schema/transaction_v2.0.yaml (100%) rename planetmint/{ => transactions}/common/schema/transaction_validator_election_v2.0.yaml (100%) rename planetmint/{ => transactions}/common/schema/transaction_vote_v2.0.yaml (100%) rename planetmint/{ => transactions}/common/transaction.py (100%) rename planetmint/{ => transactions}/common/transaction_mode_types.py (100%) rename planetmint/{ => transactions}/common/utils.py (100%) diff --git a/planetmint/common/__init__.py b/planetmint/transactions/common/__init__.py similarity index 100% rename from planetmint/common/__init__.py rename to planetmint/transactions/common/__init__.py diff --git a/planetmint/common/crypto.py b/planetmint/transactions/common/crypto.py similarity index 100% rename from planetmint/common/crypto.py rename to planetmint/transactions/common/crypto.py diff --git a/planetmint/common/exceptions.py b/planetmint/transactions/common/exceptions.py similarity index 100% rename from planetmint/common/exceptions.py rename to planetmint/transactions/common/exceptions.py diff --git a/planetmint/transactions/common/input.py b/planetmint/transactions/common/input.py new file mode 100644 index 0000000..6ef058f --- /dev/null +++ b/planetmint/transactions/common/input.py @@ -0,0 +1,117 @@ +# Copyright © 2020 Interplanetary Database Association e.V., +# Planetmint and IPDB software contributors. +# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) +# Code is Apache-2.0 and docs are CC-BY-4.0 + +class Input(object): + """A Input is used to spend assets locked by an Output. + + Wraps around a Crypto-condition Fulfillment. + + Attributes: + fulfillment (:class:`cryptoconditions.Fulfillment`): A Fulfillment + to be signed with a private key. + owners_before (:obj:`list` of :obj:`str`): A list of owners after a + Transaction was confirmed. + fulfills (:class:`~planetmint.common.transaction. TransactionLink`, + optional): A link representing the input of a `TRANSFER` + Transaction. + """ + + def __init__(self, fulfillment, owners_before, fulfills=None): + """Create an instance of an :class:`~.Input`. + + Args: + fulfillment (:class:`cryptoconditions.Fulfillment`): A + Fulfillment to be signed with a private key. + owners_before (:obj:`list` of :obj:`str`): A list of owners + after a Transaction was confirmed. + fulfills (:class:`~planetmint.common.transaction. + TransactionLink`, optional): A link representing the input + of a `TRANSFER` Transaction. + """ + if fulfills is not None and not isinstance(fulfills, TransactionLink): + raise TypeError('`fulfills` must be a TransactionLink instance') + if not isinstance(owners_before, list): + raise TypeError('`owners_before` must be a list instance') + + self.fulfillment = fulfillment + self.fulfills = fulfills + self.owners_before = owners_before + + def __eq__(self, other): + # TODO: If `other !== Fulfillment` return `False` + return self.to_dict() == other.to_dict() + + # NOTE: This function is used to provide a unique key for a given + # Input to suppliment memoization + def __hash__(self): + return hash((self.fulfillment, self.fulfills)) + + def to_dict(self): + """Transforms the object to a Python dictionary. + + Note: + If an Input hasn't been signed yet, this method returns a + dictionary representation. + + Returns: + dict: The Input as an alternative serialization format. + """ + try: + fulfillment = self.fulfillment.serialize_uri() + except (TypeError, AttributeError, ASN1EncodeError, ASN1DecodeError): + fulfillment = _fulfillment_to_details(self.fulfillment) + + try: + # NOTE: `self.fulfills` can be `None` and that's fine + fulfills = self.fulfills.to_dict() + except AttributeError: + fulfills = None + + input_ = { + 'owners_before': self.owners_before, + 'fulfills': fulfills, + 'fulfillment': fulfillment, + } + return input_ + + @classmethod + def generate(cls, public_keys): + # TODO: write docstring + # The amount here does not really matter. It is only use on the + # output data model but here we only care about the fulfillment + output = Output.generate(public_keys, 1) + return cls(output.fulfillment, public_keys) + + @classmethod + def from_dict(cls, data): + """Transforms a Python dictionary to an Input object. + + Note: + Optionally, this method can also serialize a Cryptoconditions- + Fulfillment that is not yet signed. + + Args: + data (dict): The Input to be transformed. + + Returns: + :class:`~planetmint.common.transaction.Input` + + Raises: + InvalidSignature: If an Input's URI couldn't be parsed. + """ + fulfillment = data['fulfillment'] + if not isinstance(fulfillment, (Fulfillment, type(None))): + try: + fulfillment = Fulfillment.from_uri(data['fulfillment']) + except ASN1DecodeError: + # TODO Remove as it is legacy code, and simply fall back on + # ASN1DecodeError + raise InvalidSignature("Fulfillment URI couldn't been parsed") + except TypeError: + # NOTE: See comment about this special case in + # `Input.to_dict` + fulfillment = _fulfillment_from_details(data['fulfillment']) + fulfills = TransactionLink.from_dict(data['fulfills']) + return cls(fulfillment, data['owners_before'], fulfills) diff --git a/planetmint/common/memoize.py b/planetmint/transactions/common/memoize.py similarity index 100% rename from planetmint/common/memoize.py rename to planetmint/transactions/common/memoize.py diff --git a/planetmint/common/schema/README.md b/planetmint/transactions/common/schema/README.md similarity index 100% rename from planetmint/common/schema/README.md rename to planetmint/transactions/common/schema/README.md diff --git a/planetmint/common/schema/__init__.py b/planetmint/transactions/common/schema/__init__.py similarity index 100% rename from planetmint/common/schema/__init__.py rename to planetmint/transactions/common/schema/__init__.py diff --git a/planetmint/common/schema/transaction_chain_migration_election_v2.0.yaml b/planetmint/transactions/common/schema/transaction_chain_migration_election_v2.0.yaml similarity index 100% rename from planetmint/common/schema/transaction_chain_migration_election_v2.0.yaml rename to planetmint/transactions/common/schema/transaction_chain_migration_election_v2.0.yaml diff --git a/planetmint/common/schema/transaction_create_v1.0.yaml b/planetmint/transactions/common/schema/transaction_create_v1.0.yaml similarity index 100% rename from planetmint/common/schema/transaction_create_v1.0.yaml rename to planetmint/transactions/common/schema/transaction_create_v1.0.yaml diff --git a/planetmint/common/schema/transaction_create_v2.0.yaml b/planetmint/transactions/common/schema/transaction_create_v2.0.yaml similarity index 100% rename from planetmint/common/schema/transaction_create_v2.0.yaml rename to planetmint/transactions/common/schema/transaction_create_v2.0.yaml diff --git a/planetmint/common/schema/transaction_transfer_v1.0.yaml b/planetmint/transactions/common/schema/transaction_transfer_v1.0.yaml similarity index 100% rename from planetmint/common/schema/transaction_transfer_v1.0.yaml rename to planetmint/transactions/common/schema/transaction_transfer_v1.0.yaml diff --git a/planetmint/common/schema/transaction_transfer_v2.0.yaml b/planetmint/transactions/common/schema/transaction_transfer_v2.0.yaml similarity index 100% rename from planetmint/common/schema/transaction_transfer_v2.0.yaml rename to planetmint/transactions/common/schema/transaction_transfer_v2.0.yaml diff --git a/planetmint/common/schema/transaction_v1.0.yaml b/planetmint/transactions/common/schema/transaction_v1.0.yaml similarity index 100% rename from planetmint/common/schema/transaction_v1.0.yaml rename to planetmint/transactions/common/schema/transaction_v1.0.yaml diff --git a/planetmint/common/schema/transaction_v2.0.yaml b/planetmint/transactions/common/schema/transaction_v2.0.yaml similarity index 100% rename from planetmint/common/schema/transaction_v2.0.yaml rename to planetmint/transactions/common/schema/transaction_v2.0.yaml diff --git a/planetmint/common/schema/transaction_validator_election_v2.0.yaml b/planetmint/transactions/common/schema/transaction_validator_election_v2.0.yaml similarity index 100% rename from planetmint/common/schema/transaction_validator_election_v2.0.yaml rename to planetmint/transactions/common/schema/transaction_validator_election_v2.0.yaml diff --git a/planetmint/common/schema/transaction_vote_v2.0.yaml b/planetmint/transactions/common/schema/transaction_vote_v2.0.yaml similarity index 100% rename from planetmint/common/schema/transaction_vote_v2.0.yaml rename to planetmint/transactions/common/schema/transaction_vote_v2.0.yaml diff --git a/planetmint/common/transaction.py b/planetmint/transactions/common/transaction.py similarity index 100% rename from planetmint/common/transaction.py rename to planetmint/transactions/common/transaction.py diff --git a/planetmint/common/transaction_mode_types.py b/planetmint/transactions/common/transaction_mode_types.py similarity index 100% rename from planetmint/common/transaction_mode_types.py rename to planetmint/transactions/common/transaction_mode_types.py diff --git a/planetmint/common/utils.py b/planetmint/transactions/common/utils.py similarity index 100% rename from planetmint/common/utils.py rename to planetmint/transactions/common/utils.py From e9b7aa0fc552e9ee1971efc4f4c58e8e78636624 Mon Sep 17 00:00:00 2001 From: ArpitShukla007 Date: Wed, 9 Mar 2022 17:10:37 +0000 Subject: [PATCH 09/22] Added new classes in transactions/common --- .../generate_http_server_api_documentation.py | 2 +- planetmint/__init__.py | 2 +- planetmint/backend/connection.py | 2 +- planetmint/backend/localmongodb/connection.py | 2 +- planetmint/backend/localmongodb/query.py | 2 +- planetmint/backend/schema.py | 4 +- planetmint/commands/planetmint.py | 4 +- planetmint/config_utils.py | 2 +- planetmint/elections/election.py | 8 +- planetmint/elections/vote.py | 4 +- planetmint/fastquery.py | 2 +- planetmint/lib.py | 4 +- planetmint/log.py | 2 +- .../migrations/chain_migration_election.py | 2 +- planetmint/models.py | 8 +- planetmint/transactions/common/crypto.py | 6 +- planetmint/transactions/common/input.py | 32 +- planetmint/transactions/common/output.py | 224 ++++++++ .../transactions/common/schema/__init__.py | 2 +- planetmint/transactions/common/transaction.py | 481 +----------------- .../transactions/common/transaction_link.py | 99 ++++ planetmint/transactions/common/utils.py | 52 +- .../upsert_validator/validator_election.py | 4 +- .../upsert_validator/validator_utils.py | 2 +- planetmint/utils.py | 2 +- planetmint/web/views/parameters.py | 2 +- planetmint/web/views/transactions.py | 4 +- setup.py | 2 +- tests/assets/test_digital_assets.py | 4 +- tests/assets/test_divisible_assets.py | 14 +- tests/backend/localmongodb/test_queries.py | 2 +- tests/backend/test_connection.py | 2 +- tests/commands/conftest.py | 2 +- tests/commands/test_commands.py | 4 +- tests/common/conftest.py | 14 +- tests/common/test_memoize.py | 4 +- tests/common/test_schema.py | 4 +- tests/common/test_transaction.py | 124 ++--- tests/common/utils.py | 4 +- tests/conftest.py | 18 +- tests/db/test_bigchain_api.py | 52 +- tests/tendermint/test_core.py | 12 +- tests/tendermint/test_fastquery.py | 2 +- tests/tendermint/test_integration.py | 6 +- tests/tendermint/test_lib.py | 22 +- tests/test_config_utils.py | 2 +- tests/test_core.py | 12 +- tests/test_parallel_validation.py | 2 +- .../test_upsert_validator_vote.py | 8 +- .../test_validator_election.py | 8 +- tests/utils.py | 6 +- .../validation/test_transaction_structure.py | 18 +- tests/web/test_outputs.py | 2 +- tests/web/test_transactions.py | 18 +- tests/web/test_websocket_server.py | 6 +- 55 files changed, 650 insertions(+), 684 deletions(-) create mode 100644 planetmint/transactions/common/output.py create mode 100644 planetmint/transactions/common/transaction_link.py diff --git a/docs/root/generate_http_server_api_documentation.py b/docs/root/generate_http_server_api_documentation.py index b43e163..4b84d57 100644 --- a/docs/root/generate_http_server_api_documentation.py +++ b/docs/root/generate_http_server_api_documentation.py @@ -9,7 +9,7 @@ import json import os import os.path -from planetmint.common.transaction import Transaction, Input, TransactionLink +from planetmint.transactions.common.transaction import Transaction, Input, TransactionLink from planetmint import lib from planetmint.web import server diff --git a/planetmint/__init__.py b/planetmint/__init__.py index 7c3b977..84c140a 100644 --- a/planetmint/__init__.py +++ b/planetmint/__init__.py @@ -94,7 +94,7 @@ config = { # the user wants to reconfigure the node. Check ``planetmint.config_utils`` # for more info. _config = copy.deepcopy(config) -from planetmint.common.transaction import Transaction # noqa +from planetmint.transactions.common.transaction import Transaction # noqa from planetmint import models # noqa from planetmint.upsert_validator import ValidatorElection # noqa from planetmint.elections.vote import Vote # noqa diff --git a/planetmint/backend/connection.py b/planetmint/backend/connection.py index d92204b..34708ce 100644 --- a/planetmint/backend/connection.py +++ b/planetmint/backend/connection.py @@ -10,7 +10,7 @@ from itertools import repeat import planetmint from planetmint.backend.exceptions import ConnectionError from planetmint.backend.utils import get_planetmint_config_value, get_planetmint_config_value_or_key_error -from planetmint.common.exceptions import ConfigurationError +from planetmint.transactions.common.exceptions import ConfigurationError BACKENDS = { 'localmongodb': 'planetmint.backend.localmongodb.connection.LocalMongoDBConnection', diff --git a/planetmint/backend/localmongodb/connection.py b/planetmint/backend/localmongodb/connection.py index 945a2ff..8ad3226 100644 --- a/planetmint/backend/localmongodb/connection.py +++ b/planetmint/backend/localmongodb/connection.py @@ -13,7 +13,7 @@ from planetmint.backend.exceptions import (DuplicateKeyError, OperationError, ConnectionError) from planetmint.backend.utils import get_planetmint_config_value -from planetmint.common.exceptions import ConfigurationError +from planetmint.transactions.common.exceptions import ConfigurationError from planetmint.utils import Lazy logger = logging.getLogger(__name__) diff --git a/planetmint/backend/localmongodb/query.py b/planetmint/backend/localmongodb/query.py index db98230..69f7bb2 100644 --- a/planetmint/backend/localmongodb/query.py +++ b/planetmint/backend/localmongodb/query.py @@ -11,7 +11,7 @@ from planetmint import backend from planetmint.backend.exceptions import DuplicateKeyError from planetmint.backend.utils import module_dispatch_registrar from planetmint.backend.localmongodb.connection import LocalMongoDBConnection -from planetmint.common.transaction import Transaction +from planetmint.transactions.common.transaction import Transaction register_query = module_dispatch_registrar(backend.query) diff --git a/planetmint/backend/schema.py b/planetmint/backend/schema.py index cb7bbcf..3e88d27 100644 --- a/planetmint/backend/schema.py +++ b/planetmint/backend/schema.py @@ -10,8 +10,8 @@ import logging import planetmint from planetmint.backend.connection import connect -from planetmint.common.exceptions import ValidationError -from planetmint.common.utils import validate_all_values_for_key_in_obj, validate_all_values_for_key_in_list +from planetmint.transactions.common.exceptions import ValidationError +from planetmint.transactions.common.utils import validate_all_values_for_key_in_obj, validate_all_values_for_key_in_list logger = logging.getLogger(__name__) diff --git a/planetmint/commands/planetmint.py b/planetmint/commands/planetmint.py index 5e534a7..4714fc1 100644 --- a/planetmint/commands/planetmint.py +++ b/planetmint/commands/planetmint.py @@ -17,8 +17,8 @@ import sys from planetmint.core import rollback from planetmint.migrations.chain_migration_election import ChainMigrationElection from planetmint.utils import load_node_key -from planetmint.common.transaction_mode_types import BROADCAST_TX_COMMIT -from planetmint.common.exceptions import (DatabaseDoesNotExist, +from planetmint.transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT +from planetmint.transactions.common.exceptions import (DatabaseDoesNotExist, ValidationError) from planetmint.elections.vote import Vote import planetmint diff --git a/planetmint/config_utils.py b/planetmint/config_utils.py index 1401df7..fa5d94d 100644 --- a/planetmint/config_utils.py +++ b/planetmint/config_utils.py @@ -25,7 +25,7 @@ from functools import lru_cache from pkg_resources import iter_entry_points, ResolutionError -from planetmint.common import exceptions +from planetmint.transactions.common import exceptions import planetmint diff --git a/planetmint/elections/election.py b/planetmint/elections/election.py index d73b319..f1f99f8 100644 --- a/planetmint/elections/election.py +++ b/planetmint/elections/election.py @@ -9,15 +9,15 @@ from uuid import uuid4 from planetmint import backend from planetmint.elections.vote import Vote -from planetmint.common.exceptions import (InvalidSignature, +from planetmint.transactions.common.exceptions import (InvalidSignature, MultipleInputsError, InvalidProposer, UnequalValidatorSet, DuplicateTransaction) from planetmint.tendermint_utils import key_from_base64, public_key_to_base64 -from planetmint.common.crypto import (public_key_from_ed25519_key) -from planetmint.common.transaction import Transaction -from planetmint.common.schema import (_validate_schema, +from planetmint.transactions.common.crypto import (public_key_from_ed25519_key) +from planetmint.transactions.common.transaction import Transaction +from planetmint.transactions.common.schema import (_validate_schema, TX_SCHEMA_COMMON, TX_SCHEMA_CREATE) diff --git a/planetmint/elections/vote.py b/planetmint/elections/vote.py index a4bb0c9..7a3e90c 100644 --- a/planetmint/elections/vote.py +++ b/planetmint/elections/vote.py @@ -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 -from planetmint.common.transaction import Transaction -from planetmint.common.schema import (_validate_schema, +from planetmint.transactions.common.transaction import Transaction +from planetmint.transactions.common.schema import (_validate_schema, TX_SCHEMA_COMMON, TX_SCHEMA_TRANSFER, TX_SCHEMA_VOTE) diff --git a/planetmint/fastquery.py b/planetmint/fastquery.py index c1aa843..bfbb6a8 100644 --- a/planetmint/fastquery.py +++ b/planetmint/fastquery.py @@ -5,7 +5,7 @@ from planetmint.utils import condition_details_has_owner from planetmint.backend import query -from planetmint.common.transaction import TransactionLink +from planetmint.transactions.common.transaction import TransactionLink class FastQuery(): diff --git a/planetmint/lib.py b/planetmint/lib.py index 4c59b26..8b66386 100644 --- a/planetmint/lib.py +++ b/planetmint/lib.py @@ -24,10 +24,10 @@ import requests import planetmint from planetmint import backend, config_utils, fastquery from planetmint.models import Transaction -from planetmint.common.exceptions import (SchemaValidationError, +from planetmint.transactions.common.exceptions import (SchemaValidationError, ValidationError, DoubleSpend) -from planetmint.common.transaction_mode_types import (BROADCAST_TX_COMMIT, +from planetmint.transactions.common.transaction_mode_types import (BROADCAST_TX_COMMIT, BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC) from planetmint.tendermint_utils import encode_transaction, merkleroot diff --git a/planetmint/log.py b/planetmint/log.py index d987fc6..091fe8e 100644 --- a/planetmint/log.py +++ b/planetmint/log.py @@ -6,7 +6,7 @@ import planetmint import logging -from planetmint.common.exceptions import ConfigurationError +from planetmint.transactions.common.exceptions import ConfigurationError from logging.config import dictConfig as set_logging_config import os diff --git a/planetmint/migrations/chain_migration_election.py b/planetmint/migrations/chain_migration_election.py index d913e84..03616cc 100644 --- a/planetmint/migrations/chain_migration_election.py +++ b/planetmint/migrations/chain_migration_election.py @@ -1,6 +1,6 @@ import json -from planetmint.common.schema import TX_SCHEMA_CHAIN_MIGRATION_ELECTION +from planetmint.transactions.common.schema import TX_SCHEMA_CHAIN_MIGRATION_ELECTION from planetmint.elections.election import Election diff --git a/planetmint/models.py b/planetmint/models.py index 001df55..e0edac6 100644 --- a/planetmint/models.py +++ b/planetmint/models.py @@ -4,11 +4,11 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 from planetmint.backend.schema import validate_language_key -from planetmint.common.exceptions import (InvalidSignature, +from planetmint.transactions.common.exceptions import (InvalidSignature, DuplicateTransaction) -from planetmint.common.schema import validate_transaction_schema -from planetmint.common.transaction import Transaction -from planetmint.common.utils import (validate_txn_obj, validate_key) +from planetmint.transactions.common.schema import validate_transaction_schema +from planetmint.transactions.common.transaction import Transaction +from planetmint.transactions.common.utils import (validate_txn_obj, validate_key) class Transaction(Transaction): diff --git a/planetmint/transactions/common/crypto.py b/planetmint/transactions/common/crypto.py index 72ea536..9205c27 100644 --- a/planetmint/transactions/common/crypto.py +++ b/planetmint/transactions/common/crypto.py @@ -26,10 +26,10 @@ def generate_key_pair(): """Generates a cryptographic key pair. Returns: - :class:`~planetmint.common.crypto.CryptoKeypair`: A + :class:`~planetmint.transactions.common.crypto.CryptoKeypair`: A :obj:`collections.namedtuple` with named fields - :attr:`~planetmint.common.crypto.CryptoKeypair.private_key` and - :attr:`~planetmint.common.crypto.CryptoKeypair.public_key`. + :attr:`~planetmint.transactions.common.crypto.CryptoKeypair.private_key` and + :attr:`~planetmint.transactions.common.crypto.CryptoKeypair.public_key`. """ # TODO FOR CC: Adjust interface so that this function becomes unnecessary diff --git a/planetmint/transactions/common/input.py b/planetmint/transactions/common/input.py index 6ef058f..927de97 100644 --- a/planetmint/transactions/common/input.py +++ b/planetmint/transactions/common/input.py @@ -3,6 +3,32 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 +from collections import namedtuple +from copy import deepcopy +from functools import reduce, lru_cache +import rapidjson + +import base58 +from cryptoconditions import Fulfillment, ThresholdSha256, Ed25519Sha256 +from cryptoconditions.exceptions import ( + ParsingError, ASN1DecodeError, ASN1EncodeError, UnsupportedTypeError) +try: + from hashlib import sha3_256 +except ImportError: + from sha3 import sha3_256 + +from planetmint.transactions.common.crypto import PrivateKey, hash_data +from planetmint.transactions.common.exceptions import (KeypairMismatchException, + InputDoesNotExist, DoubleSpend, + InvalidHash, InvalidSignature, + AmountError, AssetIdMismatch, + ThresholdTooDeep) +from planetmint.transactions.common.utils import serialize +from .memoize import memoize_from_dict, memoize_to_dict +from .utils import _fulfillment_to_details, _fulfillment_from_details +from .output import Output +from .transaction_link import TransactionLink + class Input(object): """A Input is used to spend assets locked by an Output. @@ -13,7 +39,7 @@ class Input(object): to be signed with a private key. owners_before (:obj:`list` of :obj:`str`): A list of owners after a Transaction was confirmed. - fulfills (:class:`~planetmint.common.transaction. TransactionLink`, + fulfills (:class:`~planetmint.transactions.common.transaction. TransactionLink`, optional): A link representing the input of a `TRANSFER` Transaction. """ @@ -26,7 +52,7 @@ class Input(object): Fulfillment to be signed with a private key. owners_before (:obj:`list` of :obj:`str`): A list of owners after a Transaction was confirmed. - fulfills (:class:`~planetmint.common.transaction. + fulfills (:class:`~planetmint.transactions.common.transaction. TransactionLink`, optional): A link representing the input of a `TRANSFER` Transaction. """ @@ -96,7 +122,7 @@ class Input(object): data (dict): The Input to be transformed. Returns: - :class:`~planetmint.common.transaction.Input` + :class:`~planetmint.transactions.common.transaction.Input` Raises: InvalidSignature: If an Input's URI couldn't be parsed. diff --git a/planetmint/transactions/common/output.py b/planetmint/transactions/common/output.py new file mode 100644 index 0000000..137542f --- /dev/null +++ b/planetmint/transactions/common/output.py @@ -0,0 +1,224 @@ +# Copyright © 2020 Interplanetary Database Association e.V., +# Planetmint and IPDB software contributors. +# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) +# Code is Apache-2.0 and docs are CC-BY-4.0 + +from collections import namedtuple +from copy import deepcopy +from functools import reduce, lru_cache +import rapidjson + +import base58 +from cryptoconditions import Fulfillment, ThresholdSha256, Ed25519Sha256 +from cryptoconditions.exceptions import ( + ParsingError, ASN1DecodeError, ASN1EncodeError, UnsupportedTypeError) +try: + from hashlib import sha3_256 +except ImportError: + from sha3 import sha3_256 + +from planetmint.transactions.common.crypto import PrivateKey, hash_data +from planetmint.transactions.common.exceptions import (KeypairMismatchException, + InputDoesNotExist, DoubleSpend, + InvalidHash, InvalidSignature, + AmountError, AssetIdMismatch, + ThresholdTooDeep) +from planetmint.transactions.common.utils import serialize +from .memoize import memoize_from_dict, memoize_to_dict +from .utils import _fulfillment_to_details, _fulfillment_from_details + +class Output(object): + """An Output is used to lock an asset. + + Wraps around a Crypto-condition Condition. + + Attributes: + fulfillment (:class:`cryptoconditions.Fulfillment`): A Fulfillment + to extract a Condition from. + public_keys (:obj:`list` of :obj:`str`, optional): A list of + owners before a Transaction was confirmed. + """ + + MAX_AMOUNT = 9 * 10 ** 18 + + def __init__(self, fulfillment, public_keys=None, amount=1): + """Create an instance of a :class:`~.Output`. + + Args: + fulfillment (:class:`cryptoconditions.Fulfillment`): A + Fulfillment to extract a Condition from. + public_keys (:obj:`list` of :obj:`str`, optional): A list of + owners before a Transaction was confirmed. + amount (int): The amount of Assets to be locked with this + Output. + + Raises: + TypeError: if `public_keys` is not instance of `list`. + """ + if not isinstance(public_keys, list) and public_keys is not None: + raise TypeError('`public_keys` must be a list instance or None') + if not isinstance(amount, int): + raise TypeError('`amount` must be an int') + if amount < 1: + raise AmountError('`amount` must be greater than 0') + if amount > self.MAX_AMOUNT: + raise AmountError('`amount` must be <= %s' % self.MAX_AMOUNT) + + self.fulfillment = fulfillment + self.amount = amount + self.public_keys = public_keys + + def __eq__(self, other): + # TODO: If `other !== Condition` return `False` + return self.to_dict() == other.to_dict() + + def to_dict(self): + """Transforms the object to a Python dictionary. + + Note: + A dictionary serialization of the Input the Output was + derived from is always provided. + + Returns: + dict: The Output as an alternative serialization format. + """ + # TODO FOR CC: It must be able to recognize a hashlock condition + # and fulfillment! + condition = {} + try: + condition['details'] = _fulfillment_to_details(self.fulfillment) + except AttributeError: + pass + + try: + condition['uri'] = self.fulfillment.condition_uri + except AttributeError: + condition['uri'] = self.fulfillment + + output = { + 'public_keys': self.public_keys, + 'condition': condition, + 'amount': str(self.amount), + } + return output + + @classmethod + def generate(cls, public_keys, amount): + """Generates a Output from a specifically formed tuple or list. + + Note: + If a ThresholdCondition has to be generated where the threshold + is always the number of subconditions it is split between, a + list of the following structure is sufficient: + + [(address|condition)*, [(address|condition)*, ...], ...] + + Args: + public_keys (:obj:`list` of :obj:`str`): The public key of + the users that should be able to fulfill the Condition + that is being created. + amount (:obj:`int`): The amount locked by the Output. + + Returns: + An Output that can be used in a Transaction. + + Raises: + TypeError: If `public_keys` is not an instance of `list`. + ValueError: If `public_keys` is an empty list. + """ + threshold = len(public_keys) + if not isinstance(amount, int): + raise TypeError('`amount` must be a int') + if amount < 1: + raise AmountError('`amount` needs to be greater than zero') + if not isinstance(public_keys, list): + raise TypeError('`public_keys` must be an instance of list') + if len(public_keys) == 0: + raise ValueError('`public_keys` needs to contain at least one' + 'owner') + elif len(public_keys) == 1 and not isinstance(public_keys[0], list): + if isinstance(public_keys[0], Fulfillment): + ffill = public_keys[0] + else: + ffill = Ed25519Sha256( + public_key=base58.b58decode(public_keys[0])) + return cls(ffill, public_keys, amount=amount) + else: + initial_cond = ThresholdSha256(threshold=threshold) + threshold_cond = reduce(cls._gen_condition, public_keys, + initial_cond) + return cls(threshold_cond, public_keys, amount=amount) + + @classmethod + def _gen_condition(cls, initial, new_public_keys): + """Generates ThresholdSha256 conditions from a list of new owners. + + Note: + This method is intended only to be used with a reduce function. + For a description on how to use this method, see + :meth:`~.Output.generate`. + + Args: + initial (:class:`cryptoconditions.ThresholdSha256`): + A Condition representing the overall root. + new_public_keys (:obj:`list` of :obj:`str`|str): A list of new + owners or a single new owner. + + Returns: + :class:`cryptoconditions.ThresholdSha256`: + """ + try: + threshold = len(new_public_keys) + except TypeError: + threshold = None + + if isinstance(new_public_keys, list) and len(new_public_keys) > 1: + ffill = ThresholdSha256(threshold=threshold) + reduce(cls._gen_condition, new_public_keys, ffill) + elif isinstance(new_public_keys, list) and len(new_public_keys) <= 1: + raise ValueError('Sublist cannot contain single owner') + else: + try: + new_public_keys = new_public_keys.pop() + except AttributeError: + pass + # NOTE: Instead of submitting base58 encoded addresses, a user + # of this class can also submit fully instantiated + # Cryptoconditions. In the case of casting + # `new_public_keys` to a Ed25519Fulfillment with the + # result of a `TypeError`, we're assuming that + # `new_public_keys` is a Cryptocondition then. + if isinstance(new_public_keys, Fulfillment): + ffill = new_public_keys + else: + ffill = Ed25519Sha256( + public_key=base58.b58decode(new_public_keys)) + initial.add_subfulfillment(ffill) + return initial + + @classmethod + def from_dict(cls, data): + """Transforms a Python dictionary to an Output object. + + Note: + To pass a serialization cycle multiple times, a + Cryptoconditions Fulfillment needs to be present in the + passed-in dictionary, as Condition URIs are not serializable + anymore. + + Args: + data (dict): The dict to be transformed. + + Returns: + :class:`~planetmint.transactions.common.transaction.Output` + """ + try: + fulfillment = _fulfillment_from_details(data['condition']['details']) + except KeyError: + # NOTE: Hashlock condition case + fulfillment = data['condition']['uri'] + try: + amount = int(data['amount']) + except ValueError: + raise AmountError('Invalid amount: %s' % data['amount']) + return cls(fulfillment, data['public_keys'], amount) \ No newline at end of file diff --git a/planetmint/transactions/common/schema/__init__.py b/planetmint/transactions/common/schema/__init__.py index df28597..0b4b20b 100644 --- a/planetmint/transactions/common/schema/__init__.py +++ b/planetmint/transactions/common/schema/__init__.py @@ -11,7 +11,7 @@ import jsonschema import yaml import rapidjson -from planetmint.common.exceptions import SchemaValidationError +from planetmint.transactions.common.exceptions import SchemaValidationError logger = logging.getLogger(__name__) diff --git a/planetmint/transactions/common/transaction.py b/planetmint/transactions/common/transaction.py index c7301f6..04245c4 100644 --- a/planetmint/transactions/common/transaction.py +++ b/planetmint/transactions/common/transaction.py @@ -25,15 +25,17 @@ try: except ImportError: from sha3 import sha3_256 -from planetmint.common.crypto import PrivateKey, hash_data -from planetmint.common.exceptions import (KeypairMismatchException, +from planetmint.transactions.common.crypto import PrivateKey, hash_data +from planetmint.transactions.common.exceptions import (KeypairMismatchException, InputDoesNotExist, DoubleSpend, InvalidHash, InvalidSignature, AmountError, AssetIdMismatch, ThresholdTooDeep) -from planetmint.common.utils import serialize +from planetmint.transactions.common.utils import serialize from .memoize import memoize_from_dict, memoize_to_dict - +from .input import Input +from .output import Output +from .transaction_link import TransactionLink UnspentOutput = namedtuple( 'UnspentOutput', ( @@ -47,441 +49,6 @@ UnspentOutput = namedtuple( ) ) - -class Input(object): - """A Input is used to spend assets locked by an Output. - - Wraps around a Crypto-condition Fulfillment. - - Attributes: - fulfillment (:class:`cryptoconditions.Fulfillment`): A Fulfillment - to be signed with a private key. - owners_before (:obj:`list` of :obj:`str`): A list of owners after a - Transaction was confirmed. - fulfills (:class:`~planetmint.common.transaction. TransactionLink`, - optional): A link representing the input of a `TRANSFER` - Transaction. - """ - - def __init__(self, fulfillment, owners_before, fulfills=None): - """Create an instance of an :class:`~.Input`. - - Args: - fulfillment (:class:`cryptoconditions.Fulfillment`): A - Fulfillment to be signed with a private key. - owners_before (:obj:`list` of :obj:`str`): A list of owners - after a Transaction was confirmed. - fulfills (:class:`~planetmint.common.transaction. - TransactionLink`, optional): A link representing the input - of a `TRANSFER` Transaction. - """ - if fulfills is not None and not isinstance(fulfills, TransactionLink): - raise TypeError('`fulfills` must be a TransactionLink instance') - if not isinstance(owners_before, list): - raise TypeError('`owners_before` must be a list instance') - - self.fulfillment = fulfillment - self.fulfills = fulfills - self.owners_before = owners_before - - def __eq__(self, other): - # TODO: If `other !== Fulfillment` return `False` - return self.to_dict() == other.to_dict() - - # NOTE: This function is used to provide a unique key for a given - # Input to suppliment memoization - def __hash__(self): - return hash((self.fulfillment, self.fulfills)) - - def to_dict(self): - """Transforms the object to a Python dictionary. - - Note: - If an Input hasn't been signed yet, this method returns a - dictionary representation. - - Returns: - dict: The Input as an alternative serialization format. - """ - try: - fulfillment = self.fulfillment.serialize_uri() - except (TypeError, AttributeError, ASN1EncodeError, ASN1DecodeError): - fulfillment = _fulfillment_to_details(self.fulfillment) - - try: - # NOTE: `self.fulfills` can be `None` and that's fine - fulfills = self.fulfills.to_dict() - except AttributeError: - fulfills = None - - input_ = { - 'owners_before': self.owners_before, - 'fulfills': fulfills, - 'fulfillment': fulfillment, - } - return input_ - - @classmethod - def generate(cls, public_keys): - # TODO: write docstring - # The amount here does not really matter. It is only use on the - # output data model but here we only care about the fulfillment - output = Output.generate(public_keys, 1) - return cls(output.fulfillment, public_keys) - - @classmethod - def from_dict(cls, data): - """Transforms a Python dictionary to an Input object. - - Note: - Optionally, this method can also serialize a Cryptoconditions- - Fulfillment that is not yet signed. - - Args: - data (dict): The Input to be transformed. - - Returns: - :class:`~planetmint.common.transaction.Input` - - Raises: - InvalidSignature: If an Input's URI couldn't be parsed. - """ - fulfillment = data['fulfillment'] - if not isinstance(fulfillment, (Fulfillment, type(None))): - try: - fulfillment = Fulfillment.from_uri(data['fulfillment']) - except ASN1DecodeError: - # TODO Remove as it is legacy code, and simply fall back on - # ASN1DecodeError - raise InvalidSignature("Fulfillment URI couldn't been parsed") - except TypeError: - # NOTE: See comment about this special case in - # `Input.to_dict` - fulfillment = _fulfillment_from_details(data['fulfillment']) - fulfills = TransactionLink.from_dict(data['fulfills']) - return cls(fulfillment, data['owners_before'], fulfills) - - -def _fulfillment_to_details(fulfillment): - """Encode a fulfillment as a details dictionary - - Args: - fulfillment: Crypto-conditions Fulfillment object - """ - - if fulfillment.type_name == 'ed25519-sha-256': - return { - 'type': 'ed25519-sha-256', - 'public_key': base58.b58encode(fulfillment.public_key).decode(), - } - - if fulfillment.type_name == 'threshold-sha-256': - subconditions = [ - _fulfillment_to_details(cond['body']) - for cond in fulfillment.subconditions - ] - return { - 'type': 'threshold-sha-256', - 'threshold': fulfillment.threshold, - 'subconditions': subconditions, - } - - raise UnsupportedTypeError(fulfillment.type_name) - - -def _fulfillment_from_details(data, _depth=0): - """Load a fulfillment for a signing spec dictionary - - Args: - data: tx.output[].condition.details dictionary - """ - if _depth == 100: - raise ThresholdTooDeep() - - if data['type'] == 'ed25519-sha-256': - public_key = base58.b58decode(data['public_key']) - return Ed25519Sha256(public_key=public_key) - - if data['type'] == 'threshold-sha-256': - threshold = ThresholdSha256(data['threshold']) - for cond in data['subconditions']: - cond = _fulfillment_from_details(cond, _depth + 1) - threshold.add_subfulfillment(cond) - return threshold - - raise UnsupportedTypeError(data.get('type')) - - -class TransactionLink(object): - """An object for unidirectional linking to a Transaction's Output. - - Attributes: - txid (str, optional): A Transaction to link to. - output (int, optional): An output's index in a Transaction with id - `txid`. - """ - - def __init__(self, txid=None, output=None): - """Create an instance of a :class:`~.TransactionLink`. - - Note: - In an IPLD implementation, this class is not necessary anymore, - as an IPLD link can simply point to an object, as well as an - objects properties. So instead of having a (de)serializable - class, we can have a simple IPLD link of the form: - `//transaction/outputs//`. - - Args: - txid (str, optional): A Transaction to link to. - output (int, optional): An Outputs's index in a Transaction with - id `txid`. - """ - self.txid = txid - self.output = output - - def __bool__(self): - return self.txid is not None and self.output is not None - - def __eq__(self, other): - # TODO: If `other !== TransactionLink` return `False` - return self.to_dict() == other.to_dict() - - def __hash__(self): - return hash((self.txid, self.output)) - - @classmethod - def from_dict(cls, link): - """Transforms a Python dictionary to a TransactionLink object. - - Args: - link (dict): The link to be transformed. - - Returns: - :class:`~planetmint.common.transaction.TransactionLink` - """ - try: - return cls(link['transaction_id'], link['output_index']) - except TypeError: - return cls() - - def to_dict(self): - """Transforms the object to a Python dictionary. - - Returns: - (dict|None): The link as an alternative serialization format. - """ - if self.txid is None and self.output is None: - return None - else: - return { - 'transaction_id': self.txid, - 'output_index': self.output, - } - - def to_uri(self, path=''): - if self.txid is None and self.output is None: - return None - return '{}/transactions/{}/outputs/{}'.format(path, self.txid, - self.output) - - -class Output(object): - """An Output is used to lock an asset. - - Wraps around a Crypto-condition Condition. - - Attributes: - fulfillment (:class:`cryptoconditions.Fulfillment`): A Fulfillment - to extract a Condition from. - public_keys (:obj:`list` of :obj:`str`, optional): A list of - owners before a Transaction was confirmed. - """ - - MAX_AMOUNT = 9 * 10 ** 18 - - def __init__(self, fulfillment, public_keys=None, amount=1): - """Create an instance of a :class:`~.Output`. - - Args: - fulfillment (:class:`cryptoconditions.Fulfillment`): A - Fulfillment to extract a Condition from. - public_keys (:obj:`list` of :obj:`str`, optional): A list of - owners before a Transaction was confirmed. - amount (int): The amount of Assets to be locked with this - Output. - - Raises: - TypeError: if `public_keys` is not instance of `list`. - """ - if not isinstance(public_keys, list) and public_keys is not None: - raise TypeError('`public_keys` must be a list instance or None') - if not isinstance(amount, int): - raise TypeError('`amount` must be an int') - if amount < 1: - raise AmountError('`amount` must be greater than 0') - if amount > self.MAX_AMOUNT: - raise AmountError('`amount` must be <= %s' % self.MAX_AMOUNT) - - self.fulfillment = fulfillment - self.amount = amount - self.public_keys = public_keys - - def __eq__(self, other): - # TODO: If `other !== Condition` return `False` - return self.to_dict() == other.to_dict() - - def to_dict(self): - """Transforms the object to a Python dictionary. - - Note: - A dictionary serialization of the Input the Output was - derived from is always provided. - - Returns: - dict: The Output as an alternative serialization format. - """ - # TODO FOR CC: It must be able to recognize a hashlock condition - # and fulfillment! - condition = {} - try: - condition['details'] = _fulfillment_to_details(self.fulfillment) - except AttributeError: - pass - - try: - condition['uri'] = self.fulfillment.condition_uri - except AttributeError: - condition['uri'] = self.fulfillment - - output = { - 'public_keys': self.public_keys, - 'condition': condition, - 'amount': str(self.amount), - } - return output - - @classmethod - def generate(cls, public_keys, amount): - """Generates a Output from a specifically formed tuple or list. - - Note: - If a ThresholdCondition has to be generated where the threshold - is always the number of subconditions it is split between, a - list of the following structure is sufficient: - - [(address|condition)*, [(address|condition)*, ...], ...] - - Args: - public_keys (:obj:`list` of :obj:`str`): The public key of - the users that should be able to fulfill the Condition - that is being created. - amount (:obj:`int`): The amount locked by the Output. - - Returns: - An Output that can be used in a Transaction. - - Raises: - TypeError: If `public_keys` is not an instance of `list`. - ValueError: If `public_keys` is an empty list. - """ - threshold = len(public_keys) - if not isinstance(amount, int): - raise TypeError('`amount` must be a int') - if amount < 1: - raise AmountError('`amount` needs to be greater than zero') - if not isinstance(public_keys, list): - raise TypeError('`public_keys` must be an instance of list') - if len(public_keys) == 0: - raise ValueError('`public_keys` needs to contain at least one' - 'owner') - elif len(public_keys) == 1 and not isinstance(public_keys[0], list): - if isinstance(public_keys[0], Fulfillment): - ffill = public_keys[0] - else: - ffill = Ed25519Sha256( - public_key=base58.b58decode(public_keys[0])) - return cls(ffill, public_keys, amount=amount) - else: - initial_cond = ThresholdSha256(threshold=threshold) - threshold_cond = reduce(cls._gen_condition, public_keys, - initial_cond) - return cls(threshold_cond, public_keys, amount=amount) - - @classmethod - def _gen_condition(cls, initial, new_public_keys): - """Generates ThresholdSha256 conditions from a list of new owners. - - Note: - This method is intended only to be used with a reduce function. - For a description on how to use this method, see - :meth:`~.Output.generate`. - - Args: - initial (:class:`cryptoconditions.ThresholdSha256`): - A Condition representing the overall root. - new_public_keys (:obj:`list` of :obj:`str`|str): A list of new - owners or a single new owner. - - Returns: - :class:`cryptoconditions.ThresholdSha256`: - """ - try: - threshold = len(new_public_keys) - except TypeError: - threshold = None - - if isinstance(new_public_keys, list) and len(new_public_keys) > 1: - ffill = ThresholdSha256(threshold=threshold) - reduce(cls._gen_condition, new_public_keys, ffill) - elif isinstance(new_public_keys, list) and len(new_public_keys) <= 1: - raise ValueError('Sublist cannot contain single owner') - else: - try: - new_public_keys = new_public_keys.pop() - except AttributeError: - pass - # NOTE: Instead of submitting base58 encoded addresses, a user - # of this class can also submit fully instantiated - # Cryptoconditions. In the case of casting - # `new_public_keys` to a Ed25519Fulfillment with the - # result of a `TypeError`, we're assuming that - # `new_public_keys` is a Cryptocondition then. - if isinstance(new_public_keys, Fulfillment): - ffill = new_public_keys - else: - ffill = Ed25519Sha256( - public_key=base58.b58decode(new_public_keys)) - initial.add_subfulfillment(ffill) - return initial - - @classmethod - def from_dict(cls, data): - """Transforms a Python dictionary to an Output object. - - Note: - To pass a serialization cycle multiple times, a - Cryptoconditions Fulfillment needs to be present in the - passed-in dictionary, as Condition URIs are not serializable - anymore. - - Args: - data (dict): The dict to be transformed. - - Returns: - :class:`~planetmint.common.transaction.Output` - """ - try: - fulfillment = _fulfillment_from_details(data['condition']['details']) - except KeyError: - # NOTE: Hashlock condition case - fulfillment = data['condition']['uri'] - try: - amount = int(data['amount']) - except ValueError: - raise AmountError('Invalid amount: %s' % data['amount']) - return cls(fulfillment, data['public_keys'], amount) - - class Transaction(object): """A Transaction is used to create and transfer assets. @@ -491,10 +58,10 @@ class Transaction(object): Attributes: operation (str): Defines the operation of the Transaction. - inputs (:obj:`list` of :class:`~planetmint.common. + inputs (:obj:`list` of :class:`~planetmint.transactions.common. transaction.Input`, optional): Define the assets to spend. - outputs (:obj:`list` of :class:`~planetmint.common. + outputs (:obj:`list` of :class:`~planetmint.transactions.common. transaction.Output`, optional): Define the assets to lock. asset (dict): Asset payload for this Transaction. ``CREATE`` Transactions require a dict with a ``data`` @@ -521,9 +88,9 @@ class Transaction(object): Args: operation (str): Defines the operation of the Transaction. asset (dict): Asset payload for this Transaction. - inputs (:obj:`list` of :class:`~planetmint.common. + inputs (:obj:`list` of :class:`~planetmint.transactions.common. transaction.Input`, optional): Define the assets to - outputs (:obj:`list` of :class:`~planetmint.common. + outputs (:obj:`list` of :class:`~planetmint.transactions.common. transaction.Output`, optional): Define the assets to lock. metadata (dict): Metadata to be stored along with the @@ -660,7 +227,7 @@ class Transaction(object): be created in this Transaction. Returns: - :class:`~planetmint.common.transaction.Transaction` + :class:`~planetmint.transactions.common.transaction.Transaction` """ (inputs, outputs) = cls.validate_create(tx_signers, recipients, asset, metadata) @@ -716,7 +283,7 @@ class Transaction(object): weight respectively. `inp2` is owned completely by `d`. Args: - inputs (:obj:`list` of :class:`~planetmint.common.transaction. + inputs (:obj:`list` of :class:`~planetmint.transactions.common.transaction. Input`): Converted `Output`s, intended to be used as inputs in the transfer to generate. recipients (:obj:`list` of :obj:`tuple`): A list of @@ -728,7 +295,7 @@ class Transaction(object): Transaction. Returns: - :class:`~planetmint.common.transaction.Transaction` + :class:`~planetmint.transactions.common.transaction.Transaction` """ (inputs, outputs) = cls.validate_transfer(inputs, recipients, asset_id, metadata) return cls(cls.TRANSFER, {'id': asset_id}, inputs, outputs, metadata) @@ -757,7 +324,7 @@ class Transaction(object): outputs should be returned as inputs. Returns: - :obj:`list` of :class:`~planetmint.common.transaction. + :obj:`list` of :class:`~planetmint.transactions.common.transaction. Input` """ # NOTE: If no indices are passed, we just assume to take all outputs @@ -774,7 +341,7 @@ class Transaction(object): """Adds an input to a Transaction's list of inputs. Args: - input_ (:class:`~planetmint.common.transaction. + input_ (:class:`~planetmint.transactions.common.transaction. Input`): An Input to be added to the Transaction. """ if not isinstance(input_, Input): @@ -785,7 +352,7 @@ class Transaction(object): """Adds an output to a Transaction's list of outputs. Args: - output (:class:`~planetmint.common.transaction. + output (:class:`~planetmint.transactions.common.transaction. Output`): An Output to be added to the Transaction. """ @@ -811,7 +378,7 @@ class Transaction(object): Transaction. Returns: - :class:`~planetmint.common.transaction.Transaction` + :class:`~planetmint.transactions.common.transaction.Transaction` """ # TODO: Singing should be possible with at least one of all private # keys supplied to this method. @@ -857,7 +424,7 @@ class Transaction(object): - ThresholdSha256. Args: - input_ (:class:`~planetmint.common.transaction. + input_ (:class:`~planetmint.transactions.common.transaction. Input`) The Input to be signed. message (str): The message to be signed key_pairs (dict): The keys to sign the Transaction with. @@ -878,7 +445,7 @@ class Transaction(object): """Signs a Ed25519Fulfillment. Args: - input_ (:class:`~planetmint.common.transaction. + input_ (:class:`~planetmint.transactions.common.transaction. Input`) The input to be signed. message (str): The message to be signed key_pairs (dict): The keys to sign the Transaction with. @@ -910,7 +477,7 @@ class Transaction(object): """Signs a ThresholdSha256. Args: - input_ (:class:`~planetmint.common.transaction. + input_ (:class:`~planetmint.transactions.common.transaction. Input`) The Input to be signed. message (str): The message to be signed key_pairs (dict): The keys to sign the Transaction with. @@ -962,7 +529,7 @@ class Transaction(object): evaluate parts of the validation-checks to `True`. Args: - outputs (:obj:`list` of :class:`~planetmint.common. + outputs (:obj:`list` of :class:`~planetmint.transactions.common. transaction.Output`): A list of Outputs to check the Inputs against. @@ -1025,7 +592,7 @@ class Transaction(object): does not validate against `output_condition_uri`. Args: - input_ (:class:`~planetmint.common.transaction. + input_ (:class:`~planetmint.transactions.common.transaction. Input`) The Input to be signed. operation (str): The type of Transaction. message (str): The fulfillment message. @@ -1134,7 +701,7 @@ class Transaction(object): transaction are related to the same asset id. Args: - transactions (:obj:`list` of :class:`~planetmint.common. + transactions (:obj:`list` of :class:`~planetmint.transactions.common. transaction.Transaction`): A list of Transactions. Usually input Transactions that should have a matching asset ID. @@ -1196,7 +763,7 @@ class Transaction(object): tx_body (dict): The Transaction to be transformed. Returns: - :class:`~planetmint.common.transaction.Transaction` + :class:`~planetmint.transactions.common.transaction.Transaction` """ operation = tx.get('operation', Transaction.CREATE) if isinstance(tx, dict) else Transaction.CREATE cls = Transaction.resolve_class(operation) diff --git a/planetmint/transactions/common/transaction_link.py b/planetmint/transactions/common/transaction_link.py new file mode 100644 index 0000000..8f36144 --- /dev/null +++ b/planetmint/transactions/common/transaction_link.py @@ -0,0 +1,99 @@ +# Copyright © 2020 Interplanetary Database Association e.V., +# Planetmint and IPDB software contributors. +# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) +# Code is Apache-2.0 and docs are CC-BY-4.0 + +from collections import namedtuple +from copy import deepcopy +from functools import reduce, lru_cache +import rapidjson + +import base58 +from cryptoconditions import Fulfillment, ThresholdSha256, Ed25519Sha256 +from cryptoconditions.exceptions import ( + ParsingError, ASN1DecodeError, ASN1EncodeError, UnsupportedTypeError) +try: + from hashlib import sha3_256 +except ImportError: + from sha3 import sha3_256 + +from planetmint.transactions.common.crypto import PrivateKey, hash_data +from planetmint.transactions.common.exceptions import (KeypairMismatchException, + InputDoesNotExist, DoubleSpend, + InvalidHash, InvalidSignature, + AmountError, AssetIdMismatch, + ThresholdTooDeep) +from planetmint.transactions.common.utils import serialize +from .memoize import memoize_from_dict, memoize_to_dict + +class TransactionLink(object): + """An object for unidirectional linking to a Transaction's Output. + + Attributes: + txid (str, optional): A Transaction to link to. + output (int, optional): An output's index in a Transaction with id + `txid`. + """ + + def __init__(self, txid=None, output=None): + """Create an instance of a :class:`~.TransactionLink`. + + Note: + In an IPLD implementation, this class is not necessary anymore, + as an IPLD link can simply point to an object, as well as an + objects properties. So instead of having a (de)serializable + class, we can have a simple IPLD link of the form: + `//transaction/outputs//`. + + Args: + txid (str, optional): A Transaction to link to. + output (int, optional): An Outputs's index in a Transaction with + id `txid`. + """ + self.txid = txid + self.output = output + + def __bool__(self): + return self.txid is not None and self.output is not None + + def __eq__(self, other): + # TODO: If `other !== TransactionLink` return `False` + return self.to_dict() == other.to_dict() + + def __hash__(self): + return hash((self.txid, self.output)) + + @classmethod + def from_dict(cls, link): + """Transforms a Python dictionary to a TransactionLink object. + + Args: + link (dict): The link to be transformed. + + Returns: + :class:`~planetmint.transactions.common.transaction.TransactionLink` + """ + try: + return cls(link['transaction_id'], link['output_index']) + except TypeError: + return cls() + + def to_dict(self): + """Transforms the object to a Python dictionary. + + Returns: + (dict|None): The link as an alternative serialization format. + """ + if self.txid is None and self.output is None: + return None + else: + return { + 'transaction_id': self.txid, + 'output_index': self.output, + } + + def to_uri(self, path=''): + if self.txid is None and self.output is None: + return None + return '{}/transactions/{}/outputs/{}'.format(path, self.txid, + self.output) \ No newline at end of file diff --git a/planetmint/transactions/common/utils.py b/planetmint/transactions/common/utils.py index b1834ea..a4e9f4d 100644 --- a/planetmint/transactions/common/utils.py +++ b/planetmint/transactions/common/utils.py @@ -3,12 +3,13 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 +import base58 import time import re import rapidjson import planetmint -from planetmint.common.exceptions import ValidationError +from planetmint.transactions.common.exceptions import ValidationError def gen_timestamp(): @@ -163,3 +164,52 @@ def validate_key(obj_name, key): 'key name cannot contain characters ' '".", "$" or null characters').format(key, obj_name) raise ValidationError(error_str) + +def _fulfillment_to_details(fulfillment): + """Encode a fulfillment as a details dictionary + + Args: + fulfillment: Crypto-conditions Fulfillment object + """ + + if fulfillment.type_name == 'ed25519-sha-256': + return { + 'type': 'ed25519-sha-256', + 'public_key': base58.b58encode(fulfillment.public_key).decode(), + } + + if fulfillment.type_name == 'threshold-sha-256': + subconditions = [ + _fulfillment_to_details(cond['body']) + for cond in fulfillment.subconditions + ] + return { + 'type': 'threshold-sha-256', + 'threshold': fulfillment.threshold, + 'subconditions': subconditions, + } + + raise UnsupportedTypeError(fulfillment.type_name) + + +def _fulfillment_from_details(data, _depth=0): + """Load a fulfillment for a signing spec dictionary + + Args: + data: tx.output[].condition.details dictionary + """ + if _depth == 100: + raise ThresholdTooDeep() + + if data['type'] == 'ed25519-sha-256': + public_key = base58.b58decode(data['public_key']) + return Ed25519Sha256(public_key=public_key) + + if data['type'] == 'threshold-sha-256': + threshold = ThresholdSha256(data['threshold']) + for cond in data['subconditions']: + cond = _fulfillment_from_details(cond, _depth + 1) + threshold.add_subfulfillment(cond) + return threshold + + raise UnsupportedTypeError(data.get('type')) \ No newline at end of file diff --git a/planetmint/upsert_validator/validator_election.py b/planetmint/upsert_validator/validator_election.py index 5f26f92..b88916e 100644 --- a/planetmint/upsert_validator/validator_election.py +++ b/planetmint/upsert_validator/validator_election.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 -from planetmint.common.exceptions import InvalidPowerChange +from planetmint.transactions.common.exceptions import InvalidPowerChange from planetmint.elections.election import Election -from planetmint.common.schema import TX_SCHEMA_VALIDATOR_ELECTION +from planetmint.transactions.common.schema import TX_SCHEMA_VALIDATOR_ELECTION from .validator_utils import (new_validator_set, encode_validator, validate_asset_public_key) diff --git a/planetmint/upsert_validator/validator_utils.py b/planetmint/upsert_validator/validator_utils.py index 69293c2..d1cf51c 100644 --- a/planetmint/upsert_validator/validator_utils.py +++ b/planetmint/upsert_validator/validator_utils.py @@ -4,7 +4,7 @@ import codecs from tendermint.abci import types_pb2 from tendermint.crypto import keys_pb2 -from planetmint.common.exceptions import InvalidPublicKey +from planetmint.transactions.common.exceptions import InvalidPublicKey def encode_validator(v): ed25519_public_key = v['public_key']['value'] diff --git a/planetmint/utils.py b/planetmint/utils.py index 51b0fa4..25dbc82 100644 --- a/planetmint/utils.py +++ b/planetmint/utils.py @@ -13,7 +13,7 @@ import setproctitle from packaging import version from planetmint.version import __tm_supported_versions__ from planetmint.tendermint_utils import key_from_base64 -from planetmint.common.crypto import key_pair_from_ed25519_key +from planetmint.transactions.common.crypto import key_pair_from_ed25519_key class ProcessGroup(object): diff --git a/planetmint/web/views/parameters.py b/planetmint/web/views/parameters.py index 530fc38..8f295e4 100644 --- a/planetmint/web/views/parameters.py +++ b/planetmint/web/views/parameters.py @@ -5,7 +5,7 @@ import re -from planetmint.common.transaction_mode_types import (BROADCAST_TX_COMMIT, +from planetmint.transactions.common.transaction_mode_types import (BROADCAST_TX_COMMIT, BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC) diff --git a/planetmint/web/views/transactions.py b/planetmint/web/views/transactions.py index c093ef7..eafaeed 100644 --- a/planetmint/web/views/transactions.py +++ b/planetmint/web/views/transactions.py @@ -12,8 +12,8 @@ import logging from flask import current_app, request, jsonify from flask_restful import Resource, reqparse -from planetmint.common.transaction_mode_types import BROADCAST_TX_ASYNC -from planetmint.common.exceptions import SchemaValidationError, ValidationError +from planetmint.transactions.common.transaction_mode_types import BROADCAST_TX_ASYNC +from planetmint.transactions.common.exceptions import SchemaValidationError, ValidationError from planetmint.web.views.base import make_error from planetmint.web.views import parameters from planetmint.models import Transaction diff --git a/setup.py b/setup.py index 7aa0901..e396d3a 100644 --- a/setup.py +++ b/setup.py @@ -138,5 +138,5 @@ setup( 'dev': dev_require + tests_require + docs_require, 'docs': docs_require, }, - package_data={'planetmint.common.schema': ['*.yaml']}, + package_data={'planetmint.transactions.common.schema': ['*.yaml']}, ) diff --git a/tests/assets/test_digital_assets.py b/tests/assets/test_digital_assets.py index ba3f062..b23b05d 100644 --- a/tests/assets/test_digital_assets.py +++ b/tests/assets/test_digital_assets.py @@ -21,7 +21,7 @@ def test_asset_transfer(b, signed_create_tx, user_pk, user_sk): def test_validate_transfer_asset_id_mismatch(b, signed_create_tx, user_pk, user_sk): - from planetmint.common.exceptions import AssetIdMismatch + from planetmint.transactions.common.exceptions import AssetIdMismatch from planetmint.models import Transaction tx_transfer = Transaction.transfer(signed_create_tx.to_inputs(), [([user_pk], 1)], @@ -52,7 +52,7 @@ def test_get_asset_id_transfer_transaction(b, signed_create_tx, user_pk): def test_asset_id_mismatch(alice, user_pk): from planetmint.models import Transaction - from planetmint.common.exceptions import AssetIdMismatch + from planetmint.transactions.common.exceptions import AssetIdMismatch tx1 = Transaction.create([alice.public_key], [([user_pk], 1)], metadata={'msg': random.random()}) diff --git a/tests/assets/test_divisible_assets.py b/tests/assets/test_divisible_assets.py index 437da55..59a8556 100644 --- a/tests/assets/test_divisible_assets.py +++ b/tests/assets/test_divisible_assets.py @@ -6,7 +6,7 @@ import pytest import random -from planetmint.common.exceptions import DoubleSpend +from planetmint.transactions.common.exceptions import DoubleSpend # CREATE divisible asset @@ -99,7 +99,7 @@ def test_single_in_single_own_multiple_out_mix_own_create(alice, user_pk, b): def test_single_in_multiple_own_single_out_single_own_create(alice, b, user_pk, user_sk): from planetmint.models import Transaction - from planetmint.common.transaction import _fulfillment_to_details + from planetmint.transactions.common.transaction import _fulfillment_to_details tx = Transaction.create([alice.public_key, user_pk], [([user_pk], 100)], asset={'name': random.random()}) tx_signed = tx.sign([alice.private_key, user_sk]) @@ -249,7 +249,7 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(alice, b, user_pk, def test_single_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk, user_sk): from planetmint.models import Transaction - from planetmint.common.transaction import _fulfillment_to_details + from planetmint.transactions.common.transaction import _fulfillment_to_details # CREATE divisible asset tx_create = Transaction.create([alice.public_key], [([alice.public_key, user_pk], 100)], @@ -316,7 +316,7 @@ def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk, user_sk): from planetmint.models import Transaction - from planetmint.common.transaction import _fulfillment_to_details + from planetmint.transactions.common.transaction import _fulfillment_to_details # CREATE divisible asset tx_create = Transaction.create([alice.public_key], [([user_pk, alice.public_key], 50), @@ -357,7 +357,7 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk, user_sk): from planetmint.models import Transaction - from planetmint.common.transaction import _fulfillment_to_details + from planetmint.transactions.common.transaction import _fulfillment_to_details # CREATE divisible asset tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)], @@ -397,7 +397,7 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(alice, b, user_pk, user_sk): from planetmint.models import Transaction - from planetmint.common.transaction import _fulfillment_to_details + from planetmint.transactions.common.transaction import _fulfillment_to_details # CREATE divisible asset tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)], @@ -486,7 +486,7 @@ def test_multiple_in_different_transactions(alice, b, user_pk, user_sk): # In other words `amount_in_inputs - amount_in_outputs == 0` def test_amount_error_transfer(alice, b, user_pk, user_sk): from planetmint.models import Transaction - from planetmint.common.exceptions import AmountError + from planetmint.transactions.common.exceptions import AmountError # CREATE divisible asset tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) diff --git a/tests/backend/localmongodb/test_queries.py b/tests/backend/localmongodb/test_queries.py index ec86410..0557527 100644 --- a/tests/backend/localmongodb/test_queries.py +++ b/tests/backend/localmongodb/test_queries.py @@ -238,7 +238,7 @@ def test_get_spending_transactions(user_pk, user_sk): def test_get_spending_transactions_multiple_inputs(): from planetmint.backend import connect, query from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair conn = connect() (alice_sk, alice_pk) = generate_key_pair() (bob_sk, bob_pk) = generate_key_pair() diff --git a/tests/backend/test_connection.py b/tests/backend/test_connection.py index 9ff8cc2..424a3d1 100644 --- a/tests/backend/test_connection.py +++ b/tests/backend/test_connection.py @@ -7,7 +7,7 @@ import pytest def test_get_connection_raises_a_configuration_error(monkeypatch): - from planetmint.common.exceptions import ConfigurationError + from planetmint.transactions.common.exceptions import ConfigurationError from planetmint.backend import connect with pytest.raises(ConfigurationError): diff --git a/tests/commands/conftest.py b/tests/commands/conftest.py index 73d25ff..6a1c19c 100644 --- a/tests/commands/conftest.py +++ b/tests/commands/conftest.py @@ -34,7 +34,7 @@ def mock_processes_start(monkeypatch): @pytest.fixture def mock_generate_key_pair(monkeypatch): - monkeypatch.setattr('planetmint.common.crypto.generate_key_pair', lambda: ('privkey', 'pubkey')) + monkeypatch.setattr('planetmint.transactions.common.crypto.generate_key_pair', lambda: ('privkey', 'pubkey')) @pytest.fixture diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index b6c90ad..81d5052 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -123,7 +123,7 @@ def test_drop_db_when_interactive_yes(mock_db_drop, monkeypatch): def test_drop_db_when_db_does_not_exist(mock_db_drop, capsys): from planetmint import config from planetmint.commands.planetmint import run_drop - from planetmint.common.exceptions import DatabaseDoesNotExist + from planetmint.transactions.common.exceptions import DatabaseDoesNotExist args = Namespace(config=None, yes=True) mock_db_drop.side_effect = DatabaseDoesNotExist @@ -404,7 +404,7 @@ def test_election_new_upsert_validator_invalid_election(caplog, b, priv_validato @pytest.mark.bdb def test_election_new_upsert_validator_invalid_power(caplog, b, priv_validator_path, user_sk): from planetmint.commands.planetmint import run_election_new_upsert_validator - from planetmint.common.exceptions import InvalidPowerChange + from planetmint.transactions.common.exceptions import InvalidPowerChange def mock_write(tx, mode): b.store_bulk_transactions([tx]) diff --git a/tests/common/conftest.py b/tests/common/conftest.py index 1f8d029..6a75eff 100644 --- a/tests/common/conftest.py +++ b/tests/common/conftest.py @@ -100,31 +100,31 @@ def user2_Ed25519(user2_pub): @pytest.fixture def user_input(user_Ed25519, user_pub): - from planetmint.common.transaction import Input + from planetmint.transactions.common.transaction import Input return Input(user_Ed25519, [user_pub]) @pytest.fixture def user_user2_threshold_output(user_user2_threshold, user_pub, user2_pub): - from planetmint.common.transaction import Output + from planetmint.transactions.common.transaction import Output return Output(user_user2_threshold, [user_pub, user2_pub]) @pytest.fixture def user_user2_threshold_input(user_user2_threshold, user_pub, user2_pub): - from planetmint.common.transaction import Input + from planetmint.transactions.common.transaction import Input return Input(user_user2_threshold, [user_pub, user2_pub]) @pytest.fixture def user_output(user_Ed25519, user_pub): - from planetmint.common.transaction import Output + from planetmint.transactions.common.transaction import Output return Output(user_Ed25519, [user_pub]) @pytest.fixture def user2_output(user2_Ed25519, user2_pub): - from planetmint.common.transaction import Output + from planetmint.transactions.common.transaction import Output return Output(user2_Ed25519, [user2_pub]) @@ -140,7 +140,7 @@ def data(): @pytest.fixture def utx(user_input, user_output): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction return Transaction(Transaction.CREATE, {'data': None}, [user_input], [user_output]) @@ -152,7 +152,7 @@ def tx(utx, user_priv): @pytest.fixture def transfer_utx(user_output, user2_output, utx): - from planetmint.common.transaction import (Input, TransactionLink, + from planetmint.transactions.common.transaction import (Input, TransactionLink, Transaction) user_output = user_output.to_dict() input = Input(utx.outputs[0].fulfillment, diff --git a/tests/common/test_memoize.py b/tests/common/test_memoize.py index f8a35c5..8665080 100644 --- a/tests/common/test_memoize.py +++ b/tests/common/test_memoize.py @@ -7,8 +7,8 @@ import pytest from copy import deepcopy from planetmint.models import Transaction -from planetmint.common.crypto import generate_key_pair -from planetmint.common.memoize import to_dict, from_dict +from planetmint.transactions.common.crypto import generate_key_pair +from planetmint.transactions.common.memoize import to_dict, from_dict pytestmark = pytest.mark.bdb diff --git a/tests/common/test_schema.py b/tests/common/test_schema.py index 62269b4..07cda88 100644 --- a/tests/common/test_schema.py +++ b/tests/common/test_schema.py @@ -13,8 +13,8 @@ from hypothesis import given from hypothesis.strategies import from_regex as regex from pytest import raises -from planetmint.common.exceptions import SchemaValidationError -from planetmint.common.schema import ( +from planetmint.transactions.common.exceptions import SchemaValidationError +from planetmint.transactions.common.schema import ( TX_SCHEMA_COMMON, validate_transaction_schema, ) diff --git a/tests/common/test_transaction.py b/tests/common/test_transaction.py index 268b714..2a7c811 100644 --- a/tests/common/test_transaction.py +++ b/tests/common/test_transaction.py @@ -21,7 +21,7 @@ pytestmark = mark.bdb def test_input_serialization(ffill_uri, user_pub): - from planetmint.common.transaction import Input + from planetmint.transactions.common.transaction import Input from cryptoconditions import Fulfillment expected = { @@ -34,7 +34,7 @@ def test_input_serialization(ffill_uri, user_pub): def test_input_deserialization_with_uri(ffill_uri, user_pub): - from planetmint.common.transaction import Input + from planetmint.transactions.common.transaction import Input from cryptoconditions import Fulfillment expected = Input(Fulfillment.from_uri(ffill_uri), [user_pub]) @@ -50,7 +50,7 @@ def test_input_deserialization_with_uri(ffill_uri, user_pub): @mark.skip(reason='None is tolerated because it is None before fulfilling.') def test_input_deserialization_with_invalid_input(user_pub): - from planetmint.common.transaction import Input + from planetmint.transactions.common.transaction import Input ffill = { 'owners_before': [user_pub], @@ -62,8 +62,8 @@ def test_input_deserialization_with_invalid_input(user_pub): def test_input_deserialization_with_invalid_fulfillment_uri(user_pub): - from planetmint.common.exceptions import InvalidSignature - from planetmint.common.transaction import Input + from planetmint.transactions.common.exceptions import InvalidSignature + from planetmint.transactions.common.transaction import Input ffill = { 'owners_before': [user_pub], @@ -75,7 +75,7 @@ def test_input_deserialization_with_invalid_fulfillment_uri(user_pub): def test_input_deserialization_with_unsigned_fulfillment(ffill_uri, user_pub): - from planetmint.common.transaction import Input + from planetmint.transactions.common.transaction import Input from cryptoconditions import Fulfillment expected = Input(Fulfillment.from_uri(ffill_uri), [user_pub]) @@ -90,7 +90,7 @@ def test_input_deserialization_with_unsigned_fulfillment(ffill_uri, user_pub): def test_output_serialization(user_Ed25519, user_pub): - from planetmint.common.transaction import Output + from planetmint.transactions.common.transaction import Output expected = { 'condition': { @@ -110,7 +110,7 @@ def test_output_serialization(user_Ed25519, user_pub): def test_output_deserialization(user_Ed25519, user_pub): - from planetmint.common.transaction import Output + from planetmint.transactions.common.transaction import Output expected = Output(user_Ed25519, [user_pub], 1) cond = { @@ -130,7 +130,7 @@ def test_output_deserialization(user_Ed25519, user_pub): def test_output_hashlock_serialization(): - from planetmint.common.transaction import Output + from planetmint.transactions.common.transaction import Output from cryptoconditions import PreimageSha256 secret = b'wow much secret' @@ -149,7 +149,7 @@ def test_output_hashlock_serialization(): def test_output_hashlock_deserialization(): - from planetmint.common.transaction import Output + from planetmint.transactions.common.transaction import Output from cryptoconditions import PreimageSha256 secret = b'wow much secret' @@ -169,8 +169,8 @@ def test_output_hashlock_deserialization(): def test_invalid_output_initialization(cond_uri, user_pub): - from planetmint.common.transaction import Output - from planetmint.common.exceptions import AmountError + from planetmint.transactions.common.transaction import Output + from planetmint.transactions.common.exceptions import AmountError with raises(TypeError): Output(cond_uri, user_pub) @@ -181,7 +181,7 @@ def test_invalid_output_initialization(cond_uri, user_pub): def test_generate_output_split_half_recursive(user_pub, user2_pub, user3_pub): - from planetmint.common.transaction import Output + from planetmint.transactions.common.transaction import Output from cryptoconditions import Ed25519Sha256, ThresholdSha256 expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub)) @@ -201,7 +201,7 @@ 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.common.transaction import Output + from planetmint.transactions.common.transaction import Output from cryptoconditions import Ed25519Sha256, ThresholdSha256 expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub)) @@ -220,7 +220,7 @@ def test_generate_outputs_split_half_single_owner(user_pub, def test_generate_outputs_flat_ownage(user_pub, user2_pub, user3_pub): - from planetmint.common.transaction import Output + from planetmint.transactions.common.transaction import Output from cryptoconditions import Ed25519Sha256, ThresholdSha256 expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub)) @@ -237,7 +237,7 @@ def test_generate_outputs_flat_ownage(user_pub, user2_pub, user3_pub): def test_generate_output_single_owner(user_pub): - from planetmint.common.transaction import Output + from planetmint.transactions.common.transaction import Output from cryptoconditions import Ed25519Sha256 expected = Ed25519Sha256(public_key=b58decode(user_pub)) @@ -247,7 +247,7 @@ def test_generate_output_single_owner(user_pub): def test_generate_output_single_owner_with_output(user_pub): - from planetmint.common.transaction import Output + from planetmint.transactions.common.transaction import Output from cryptoconditions import Ed25519Sha256 expected = Ed25519Sha256(public_key=b58decode(user_pub)) @@ -257,8 +257,8 @@ def test_generate_output_single_owner_with_output(user_pub): def test_generate_output_invalid_parameters(user_pub, user2_pub, user3_pub): - from planetmint.common.transaction import Output - from planetmint.common.exceptions import AmountError + from planetmint.transactions.common.transaction import Output + from planetmint.transactions.common.exceptions import AmountError with raises(ValueError): Output.generate([], 1) @@ -273,7 +273,7 @@ def test_generate_output_invalid_parameters(user_pub, user2_pub, user3_pub): def test_invalid_transaction_initialization(asset_definition): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction with raises(ValueError): Transaction(operation='invalid operation', asset=asset_definition) @@ -305,7 +305,7 @@ def test_invalid_transaction_initialization(asset_definition): def test_create_default_asset_on_tx_initialization(asset_definition): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction expected = {'data': None} tx = Transaction(Transaction.CREATE, asset=expected) @@ -315,7 +315,7 @@ def test_create_default_asset_on_tx_initialization(asset_definition): def test_transaction_serialization(user_input, user_output, data): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction expected = { 'id': None, @@ -339,14 +339,14 @@ def test_transaction_serialization(user_input, user_output, data): def test_transaction_deserialization(tri_state_transaction): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model tx = Transaction.from_dict(tri_state_transaction) validate_transaction_model(tx) def test_invalid_input_initialization(user_input, user_pub): - from planetmint.common.transaction import Input + from planetmint.transactions.common.transaction import Input with raises(TypeError): Input(user_input, user_pub) @@ -355,7 +355,7 @@ def test_invalid_input_initialization(user_input, user_pub): def test_transaction_link_serialization(): - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common.transaction import TransactionLink tx_id = 'a transaction id' expected = { @@ -368,7 +368,7 @@ def test_transaction_link_serialization(): def test_transaction_link_serialization_with_empty_payload(): - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common.transaction import TransactionLink expected = None tx_link = TransactionLink() @@ -377,7 +377,7 @@ def test_transaction_link_serialization_with_empty_payload(): def test_transaction_link_deserialization(): - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common.transaction import TransactionLink tx_id = 'a transaction id' expected = TransactionLink(tx_id, 0) @@ -391,7 +391,7 @@ def test_transaction_link_deserialization(): def test_transaction_link_deserialization_with_empty_payload(): - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common.transaction import TransactionLink expected = TransactionLink() tx_link = TransactionLink.from_dict(None) @@ -400,7 +400,7 @@ def test_transaction_link_deserialization_with_empty_payload(): def test_transaction_link_empty_to_uri(): - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common.transaction import TransactionLink expected = None tx_link = TransactionLink().to_uri() @@ -409,7 +409,7 @@ def test_transaction_link_empty_to_uri(): def test_transaction_link_to_uri(): - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common.transaction import TransactionLink expected = 'path/transactions/abc/outputs/0' tx_link = TransactionLink('abc', 0).to_uri('path') @@ -418,7 +418,7 @@ def test_transaction_link_to_uri(): def test_cast_transaction_link_to_boolean(): - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common.transaction import TransactionLink assert bool(TransactionLink()) is False assert bool(TransactionLink('a', None)) is False @@ -428,7 +428,7 @@ def test_cast_transaction_link_to_boolean(): def test_transaction_link_eq(): - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common.transaction import TransactionLink assert TransactionLink(1, 2) == TransactionLink(1, 2) assert TransactionLink(2, 2) != TransactionLink(1, 2) @@ -437,7 +437,7 @@ def test_transaction_link_eq(): def test_add_input_to_tx(user_input, asset_definition): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model tx = Transaction(Transaction.CREATE, asset_definition, [], []) @@ -449,7 +449,7 @@ def test_add_input_to_tx(user_input, asset_definition): def test_add_input_to_tx_with_invalid_parameters(asset_definition): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction tx = Transaction(Transaction.CREATE, asset_definition) with raises(TypeError): @@ -457,7 +457,7 @@ 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.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model tx = Transaction(Transaction.CREATE, asset_definition, [user_input]) @@ -469,7 +469,7 @@ 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.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction tx = Transaction(Transaction.CREATE, asset_definition, [], []) with raises(TypeError): @@ -485,7 +485,7 @@ 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.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model tx = Transaction(Transaction.CREATE, asset_definition, [user_input], [user_output]) @@ -507,7 +507,7 @@ def test_validate_tx_simple_create_signature(user_input, user_output, user_priv, def test_invoke_simple_signature_fulfillment_with_invalid_params(utx, user_input): - from planetmint.common.exceptions import KeypairMismatchException + from planetmint.transactions.common.exceptions import KeypairMismatchException with raises(KeypairMismatchException): invalid_key_pair = {'wrong_pub_key': 'wrong_priv_key'} @@ -518,7 +518,7 @@ def test_invoke_simple_signature_fulfillment_with_invalid_params(utx, def test_sign_threshold_with_invalid_params(utx, user_user2_threshold_input, user3_pub, user3_priv): - from planetmint.common.exceptions import KeypairMismatchException + from planetmint.transactions.common.exceptions import KeypairMismatchException with raises(KeypairMismatchException): utx._sign_threshold_signature_fulfillment(user_user2_threshold_input, @@ -532,7 +532,7 @@ def test_sign_threshold_with_invalid_params(utx, user_user2_threshold_input, def test_validate_input_with_invalid_parameters(utx): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction input_conditions = [out.fulfillment.condition_uri for out in utx.outputs] tx_dict = utx.to_dict() @@ -548,7 +548,7 @@ def test_validate_tx_threshold_create_signature(user_user2_threshold_input, user_priv, user2_priv, asset_definition): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model tx = Transaction(Transaction.CREATE, asset_definition, @@ -576,7 +576,7 @@ def test_validate_tx_threshold_create_signature(user_user2_threshold_input, def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv, asset_definition): from cryptoconditions import Ed25519Sha256, ThresholdSha256 - from planetmint.common.transaction import Input, Output, Transaction + from planetmint.transactions.common.transaction import Input, Output, Transaction threshold = ThresholdSha256(threshold=2) threshold.add_subfulfillment( @@ -621,7 +621,7 @@ def test_multiple_input_validation_of_transfer_tx(user_input, user_output, user2_priv, user3_pub, user3_priv, asset_definition): - from planetmint.common.transaction import (Transaction, TransactionLink, + from planetmint.transactions.common.transaction import (Transaction, TransactionLink, Input, Output) from cryptoconditions import Ed25519Sha256 from .utils import validate_transaction_model @@ -647,7 +647,7 @@ def test_multiple_input_validation_of_transfer_tx(user_input, user_output, def test_validate_inputs_of_transfer_tx_with_invalid_params( transfer_tx, cond_uri, utx, user2_pub, user_priv, ffill_uri): - from planetmint.common.transaction import Output + from planetmint.transactions.common.transaction import Output from cryptoconditions import Ed25519Sha256 invalid_out = Output(Ed25519Sha256.from_uri(ffill_uri), ['invalid']) @@ -668,7 +668,7 @@ def test_validate_inputs_of_transfer_tx_with_invalid_params( def test_create_create_transaction_single_io(user_output, user_pub, data): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model expected = { @@ -703,7 +703,7 @@ def test_create_create_transaction_single_io(user_output, user_pub, data): def test_validate_single_io_create_transaction(user_pub, user_priv, data, asset_definition): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction tx = Transaction.create([user_pub], [([user_pub], 1)], metadata=data) tx = tx.sign([user_priv]) @@ -712,7 +712,7 @@ def test_validate_single_io_create_transaction(user_pub, user_priv, data, def test_create_create_transaction_multiple_io(user_output, user2_output, user_pub, user2_pub, asset_definition): - from planetmint.common.transaction import Transaction, Input + 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 @@ -739,7 +739,7 @@ def test_create_create_transaction_multiple_io(user_output, user2_output, user_p def test_validate_multiple_io_create_transaction(user_pub, user_priv, user2_pub, user2_priv, asset_definition): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model tx = Transaction.create([user_pub, user2_pub], @@ -754,7 +754,7 @@ def test_validate_multiple_io_create_transaction(user_pub, user_priv, def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub, user_user2_threshold_output, user_user2_threshold_input, data): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction expected = { 'outputs': [user_user2_threshold_output.to_dict()], @@ -785,7 +785,7 @@ def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub, def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub, data, asset_definition): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)], @@ -797,7 +797,7 @@ def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub, def test_create_create_transaction_with_invalid_parameters(user_pub): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction with raises(TypeError): Transaction.create('not a list') @@ -832,7 +832,7 @@ def test_outputs_to_inputs(tx): def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, user2_output, user_priv): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model expected = { @@ -887,7 +887,7 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv, user2_pub, user2_priv, user3_pub, user2_output, asset_definition): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction tx = Transaction.create([user_pub], [([user_pub], 1), ([user2_pub], 1)], metadata={'message': 'hello'}) @@ -941,7 +941,7 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv, def test_create_transfer_with_invalid_parameters(tx, user_pub): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction with raises(TypeError): Transaction.transfer({}, [], tx.id) @@ -964,7 +964,7 @@ def test_create_transfer_with_invalid_parameters(tx, user_pub): def test_cant_add_empty_output(): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction tx = Transaction(Transaction.CREATE, None) with raises(TypeError): @@ -972,7 +972,7 @@ def test_cant_add_empty_output(): def test_cant_add_empty_input(): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction tx = Transaction(Transaction.CREATE, None) with raises(TypeError): @@ -980,7 +980,7 @@ def test_cant_add_empty_input(): def test_unfulfilled_transaction_serialized(unfulfilled_transaction): - from planetmint.common.transaction import 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) @@ -988,7 +988,7 @@ def test_unfulfilled_transaction_serialized(unfulfilled_transaction): def test_fulfilled_transaction_serialized(fulfilled_transaction): - from planetmint.common.transaction import 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) @@ -996,7 +996,7 @@ def test_fulfilled_transaction_serialized(fulfilled_transaction): def test_transaction_hash(fulfilled_transaction): - from planetmint.common.transaction import 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 @@ -1009,8 +1009,8 @@ def test_transaction_hash(fulfilled_transaction): def test_output_from_dict_invalid_amount(user_output): - from planetmint.common.transaction import Output - from planetmint.common.exceptions import AmountError + from planetmint.transactions.common.transaction import Output + from planetmint.transactions.common.exceptions import AmountError out = user_output.to_dict() out['amount'] = 'a' @@ -1019,7 +1019,7 @@ def test_output_from_dict_invalid_amount(user_output): def test_unspent_outputs_property(merlin, alice, bob, carol): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction tx = Transaction.create( [merlin.public_key], [([alice.public_key], 1), diff --git a/tests/common/utils.py b/tests/common/utils.py index d95575e..bd10303 100644 --- a/tests/common/utils.py +++ b/tests/common/utils.py @@ -5,8 +5,8 @@ def validate_transaction_model(tx): - from planetmint.common.transaction import Transaction - from planetmint.common.schema import validate_transaction_schema + from planetmint.transactions.common.transaction import Transaction + from planetmint.transactions.common.schema import validate_transaction_schema tx_dict = tx.to_dict() # Check that a transaction is valid by re-serializing it diff --git a/tests/conftest.py b/tests/conftest.py index af49f42..780abbb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -23,13 +23,13 @@ import pytest from pymongo import MongoClient from planetmint import ValidatorElection -from planetmint.common import crypto -from planetmint.common.transaction_mode_types import BROADCAST_TX_COMMIT +from planetmint.transactions.common import crypto +from planetmint.transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT from planetmint.tendermint_utils import key_from_base64 from planetmint.backend import schema, query -from planetmint.common.crypto import (key_pair_from_ed25519_key, +from planetmint.transactions.common.crypto import (key_pair_from_ed25519_key, public_key_from_ed25519_key) -from planetmint.common.exceptions import DatabaseDoesNotExist +from planetmint.transactions.common.exceptions import DatabaseDoesNotExist from planetmint.lib import Block from tests.utils import gen_vote @@ -149,7 +149,7 @@ def _bdb(_setup_database, _configure_planetmint): from planetmint import config from planetmint.backend import connect from .utils import flush_db - from planetmint.common.memoize import to_dict, from_dict + from planetmint.transactions.common.memoize import to_dict, from_dict from planetmint.models import Transaction conn = connect() yield @@ -205,13 +205,13 @@ def user2_pk(): @pytest.fixture def alice(): - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair return generate_key_pair() @pytest.fixture def bob(): - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair return generate_key_pair() @@ -227,7 +227,7 @@ def bob_pubkey(carol): @pytest.fixture def carol(): - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair return generate_key_pair() @@ -243,7 +243,7 @@ def carol_pubkey(carol): @pytest.fixture def merlin(): - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair return generate_key_pair() diff --git a/tests/db/test_bigchain_api.py b/tests/db/test_bigchain_api.py index b6d4124..9724cb6 100644 --- a/tests/db/test_bigchain_api.py +++ b/tests/db/test_bigchain_api.py @@ -15,7 +15,7 @@ class TestBigchainApi(object): def test_get_spent_with_double_spend_detected(self, b, alice): from planetmint.models import Transaction - from planetmint.common.exceptions import DoubleSpend + from planetmint.transactions.common.exceptions import DoubleSpend from planetmint.exceptions import CriticalDoubleSpend tx = Transaction.create([alice.public_key], [([alice.public_key], 1)]) @@ -81,8 +81,8 @@ class TestBigchainApi(object): @pytest.mark.usefixtures('inputs') def test_non_create_input_not_found(self, b, user_pk): from cryptoconditions import Ed25519Sha256 - from planetmint.common.exceptions import InputDoesNotExist - from planetmint.common.transaction import Input, TransactionLink + from planetmint.transactions.common.exceptions import InputDoesNotExist + from planetmint.transactions.common.transaction import Input, TransactionLink from planetmint.models import Transaction # Create an input for a non existing transaction @@ -117,8 +117,8 @@ class TestBigchainApi(object): class TestTransactionValidation(object): def test_non_create_input_not_found(self, b, signed_transfer_tx): - from planetmint.common.exceptions import InputDoesNotExist - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common.exceptions import InputDoesNotExist + from planetmint.transactions.common.transaction import TransactionLink signed_transfer_tx.inputs[0].fulfills = TransactionLink('c', 0) with pytest.raises(InputDoesNotExist): @@ -126,8 +126,8 @@ class TestTransactionValidation(object): @pytest.mark.usefixtures('inputs') def test_non_create_valid_input_wrong_owner(self, b, user_pk): - from planetmint.common.crypto import generate_key_pair - from planetmint.common.exceptions import InvalidSignature + from planetmint.transactions.common.crypto import generate_key_pair + from planetmint.transactions.common.exceptions import InvalidSignature from planetmint.models import Transaction input_tx = b.fastquery.get_outputs_by_public_key(user_pk).pop() @@ -144,7 +144,7 @@ class TestTransactionValidation(object): @pytest.mark.usefixtures('inputs') def test_non_create_double_spend(self, b, signed_create_tx, signed_transfer_tx, double_spend_tx): - from planetmint.common.exceptions import DoubleSpend + from planetmint.transactions.common.exceptions import DoubleSpend b.store_bulk_transactions([signed_create_tx, signed_transfer_tx]) @@ -156,7 +156,7 @@ class TestMultipleInputs(object): def test_transfer_single_owner_single_input(self, b, inputs, user_pk, user_sk): - from planetmint.common import crypto + from planetmint.transactions.common import crypto from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -177,7 +177,7 @@ class TestMultipleInputs(object): user_sk, user_pk, inputs): - from planetmint.common import crypto + from planetmint.transactions.common import crypto from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -199,7 +199,7 @@ class TestMultipleInputs(object): user_sk, user_pk, alice): - from planetmint.common import crypto + from planetmint.transactions.common import crypto from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -227,7 +227,7 @@ class TestMultipleInputs(object): user_sk, user_pk, alice): - from planetmint.common import crypto + from planetmint.transactions.common import crypto from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -252,8 +252,8 @@ class TestMultipleInputs(object): assert len(tx.outputs) == 1 def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_pk, alice): - from planetmint.common import crypto - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common import crypto + from planetmint.transactions.common.transaction import TransactionLink from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -280,8 +280,8 @@ class TestMultipleInputs(object): def test_get_owned_ids_single_tx_multiple_outputs(self, b, user_sk, user_pk, alice): - from planetmint.common import crypto - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common import crypto + from planetmint.transactions.common.transaction import TransactionLink from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -314,8 +314,8 @@ class TestMultipleInputs(object): TransactionLink(tx_transfer.id, 1)] def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk, alice): - from planetmint.common import crypto - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common import crypto + from planetmint.transactions.common.transaction import TransactionLink from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -346,7 +346,7 @@ class TestMultipleInputs(object): assert not spent_user1 def test_get_spent_single_tx_single_output(self, b, user_sk, user_pk, alice): - from planetmint.common import crypto + from planetmint.transactions.common import crypto from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -372,7 +372,7 @@ class TestMultipleInputs(object): assert spent_inputs_user1 == tx def test_get_spent_single_tx_multiple_outputs(self, b, user_sk, user_pk, alice): - from planetmint.common import crypto + from planetmint.transactions.common import crypto from planetmint.models import Transaction # create a new users @@ -409,7 +409,7 @@ class TestMultipleInputs(object): assert b.get_spent(tx_create.to_inputs()[2].fulfills.txid, 2) is None def test_get_spent_multiple_owners(self, b, user_sk, user_pk, alice): - from planetmint.common import crypto + from planetmint.transactions.common import crypto from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -445,7 +445,7 @@ class TestMultipleInputs(object): def test_get_outputs_filtered_only_unspent(): - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common.transaction import TransactionLink from planetmint.lib import Planetmint go = 'planetmint.fastquery.FastQuery.get_outputs_by_public_key' @@ -461,7 +461,7 @@ def test_get_outputs_filtered_only_unspent(): def test_get_outputs_filtered_only_spent(): - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common.transaction import TransactionLink from planetmint.lib import Planetmint go = 'planetmint.fastquery.FastQuery.get_outputs_by_public_key' with patch(go) as get_outputs: @@ -478,7 +478,7 @@ def test_get_outputs_filtered_only_spent(): @patch('planetmint.fastquery.FastQuery.filter_unspent_outputs') @patch('planetmint.fastquery.FastQuery.filter_spent_outputs') def test_get_outputs_filtered(filter_spent, filter_unspent): - from planetmint.common.transaction import TransactionLink + from planetmint.transactions.common.transaction import TransactionLink from planetmint.lib import Planetmint go = 'planetmint.fastquery.FastQuery.get_outputs_by_public_key' @@ -497,7 +497,7 @@ def test_cant_spend_same_input_twice_in_tx(b, alice): https://github.com/planetmint/planetmint/issues/1099 """ from planetmint.models import Transaction - from planetmint.common.exceptions import DoubleSpend + from planetmint.transactions.common.exceptions import DoubleSpend # create a divisible asset tx_create = Transaction.create([alice.public_key], [([alice.public_key], 100)]) @@ -517,7 +517,7 @@ def test_cant_spend_same_input_twice_in_tx(b, alice): def test_transaction_unicode(b, alice): import copy - from planetmint.common.utils import serialize + from planetmint.transactions.common.utils import serialize from planetmint.models import Transaction # http://www.fileformat.info/info/unicode/char/1f37a/index.htm diff --git a/tests/tendermint/test_core.py b/tests/tendermint/test_core.py index 5f54a1b..fdf3ec1 100644 --- a/tests/tendermint/test_core.py +++ b/tests/tendermint/test_core.py @@ -12,7 +12,7 @@ from tendermint.crypto import keys_pb2 from planetmint import App from planetmint.backend.localmongodb import query -from planetmint.common.crypto import generate_key_pair +from planetmint.transactions.common.crypto import generate_key_pair from planetmint.core import (OkCode, CodeTypeError, rollback) @@ -203,7 +203,7 @@ def test_info(b): def test_check_tx__signed_create_is_ok(b): from planetmint import App from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() bob = generate_key_pair() @@ -220,7 +220,7 @@ def test_check_tx__signed_create_is_ok(b): def test_check_tx__unsigned_create_is_error(b): from planetmint import App from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() bob = generate_key_pair() @@ -237,7 +237,7 @@ def test_deliver_tx__valid_create_updates_db_and_emits_event(b, init_chain_reque import multiprocessing as mp from planetmint import App from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() bob = generate_key_pair() @@ -274,7 +274,7 @@ def test_deliver_tx__valid_create_updates_db_and_emits_event(b, init_chain_reque def test_deliver_tx__double_spend_fails(b, init_chain_request): from planetmint import App from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() bob = generate_key_pair() @@ -303,7 +303,7 @@ def test_deliver_tx__double_spend_fails(b, init_chain_request): def test_deliver_transfer_tx__double_spend_fails(b, init_chain_request): from planetmint import App from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair app = App(b) app.init_chain(init_chain_request) diff --git a/tests/tendermint/test_fastquery.py b/tests/tendermint/test_fastquery.py index 98ca97a..61f8ac9 100644 --- a/tests/tendermint/test_fastquery.py +++ b/tests/tendermint/test_fastquery.py @@ -5,7 +5,7 @@ import pytest -from planetmint.common.transaction import TransactionLink +from planetmint.transactions.common.transaction import TransactionLink from planetmint.models import Transaction diff --git a/tests/tendermint/test_integration.py b/tests/tendermint/test_integration.py index a57a3b2..45b4db1 100644 --- a/tests/tendermint/test_integration.py +++ b/tests/tendermint/test_integration.py @@ -13,7 +13,7 @@ import pytest from abci.server import ProtocolHandler from abci.utils import read_messages -from planetmint.common.transaction_mode_types import BROADCAST_TX_COMMIT, BROADCAST_TX_SYNC +from planetmint.transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT, BROADCAST_TX_SYNC from planetmint.version import __tm_supported_versions__ from io import BytesIO @@ -22,7 +22,7 @@ from io import BytesIO def test_app(b, eventqueue_fixture, init_chain_request): from planetmint import App from planetmint.tendermint_utils import calculate_hash - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair from planetmint.models import Transaction app = App(b, eventqueue_fixture) @@ -113,7 +113,7 @@ def test_app(b, eventqueue_fixture, init_chain_request): @pytest.mark.abci def test_post_transaction_responses(tendermint_ws_url, b): - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair from planetmint.models import Transaction alice = generate_key_pair() diff --git a/tests/tendermint/test_lib.py b/tests/tendermint/test_lib.py index 2d9bc96..3f92554 100644 --- a/tests/tendermint/test_lib.py +++ b/tests/tendermint/test_lib.py @@ -17,7 +17,7 @@ import pytest from pymongo import MongoClient from planetmint import backend -from planetmint.common.transaction_mode_types import (BROADCAST_TX_COMMIT, +from planetmint.transactions.common.transaction_mode_types import (BROADCAST_TX_COMMIT, BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC) from planetmint.lib import Block @@ -27,7 +27,7 @@ from planetmint.lib import Block def test_asset_is_separated_from_transaciton(b): import copy from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() bob = generate_key_pair() @@ -83,7 +83,7 @@ def test_get_empty_block(_0, _1, b): def test_validation_error(b): from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() tx = Transaction.create([alice.public_key], @@ -98,7 +98,7 @@ def test_validation_error(b): @patch('requests.post') def test_write_and_post_transaction(mock_post, b): from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair from planetmint.tendermint_utils import encode_transaction alice = generate_key_pair() @@ -125,7 +125,7 @@ def test_write_and_post_transaction(mock_post, b): ]) def test_post_transaction_valid_modes(mock_post, b, mode): from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], @@ -140,8 +140,8 @@ def test_post_transaction_valid_modes(mock_post, b, mode): def test_post_transaction_invalid_mode(b): from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair - from planetmint.common.exceptions import ValidationError + from planetmint.transactions.common.crypto import generate_key_pair + from planetmint.transactions.common.exceptions import ValidationError alice = generate_key_pair() tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], @@ -357,7 +357,7 @@ def test_get_utxoset_merkle_root(b, utxoset): def test_get_spent_transaction_critical_double_spend(b, alice, bob, carol): from planetmint.models import Transaction from planetmint.exceptions import CriticalDoubleSpend - from planetmint.common.exceptions import DoubleSpend + from planetmint.transactions.common.exceptions import DoubleSpend asset = {'test': 'asset'} @@ -404,7 +404,7 @@ def test_get_spent_transaction_critical_double_spend(b, alice, bob, carol): def test_validation_with_transaction_buffer(b): - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair from planetmint.models import Transaction priv_key, pub_key = generate_key_pair() @@ -461,8 +461,8 @@ def test_migrate_abci_chain_generates_new_chains(b, chain, block_height, def test_get_spent_key_order(b, user_pk, user_sk, user2_pk, user2_sk): from planetmint import backend from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair - from planetmint.common.exceptions import DoubleSpend + from planetmint.transactions.common.crypto import generate_key_pair + from planetmint.transactions.common.exceptions import DoubleSpend alice = generate_key_pair() bob = generate_key_pair() diff --git a/tests/test_config_utils.py b/tests/test_config_utils.py index 4bcff77..ebf9874 100644 --- a/tests/test_config_utils.py +++ b/tests/test_config_utils.py @@ -298,7 +298,7 @@ def test_file_config(): def test_invalid_file_config(): from planetmint.config_utils import file_config - from planetmint.common import exceptions + from planetmint.transactions.common import exceptions with patch('builtins.open', mock_open(read_data='{_INVALID_JSON_}')): with pytest.raises(exceptions.ConfigurationError): file_config() diff --git a/tests/test_core.py b/tests/test_core.py index 6d61344..f87015e 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -12,7 +12,7 @@ from tendermint.crypto import keys_pb2 from planetmint import App from planetmint.backend.localmongodb import query -from planetmint.common.crypto import generate_key_pair +from planetmint.transactions.common.crypto import generate_key_pair from planetmint.core import (OkCode, CodeTypeError, rollback) @@ -203,7 +203,7 @@ def test_info(b): def test_check_tx__signed_create_is_ok(b): from planetmint import App from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() bob = generate_key_pair() @@ -220,7 +220,7 @@ def test_check_tx__signed_create_is_ok(b): def test_check_tx__unsigned_create_is_error(b): from planetmint import App from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() bob = generate_key_pair() @@ -237,7 +237,7 @@ def test_deliver_tx__valid_create_updates_db_and_emits_event(b, init_chain_reque import multiprocessing as mp from planetmint import App from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() bob = generate_key_pair() @@ -274,7 +274,7 @@ def test_deliver_tx__valid_create_updates_db_and_emits_event(b, init_chain_reque def test_deliver_tx__double_spend_fails(b, eventqueue_fixture, init_chain_request): from planetmint import App from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() bob = generate_key_pair() @@ -303,7 +303,7 @@ def test_deliver_tx__double_spend_fails(b, eventqueue_fixture, init_chain_reques def test_deliver_transfer_tx__double_spend_fails(b, init_chain_request): from planetmint import App from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair app = App(b) app.init_chain(init_chain_request) diff --git a/tests/test_parallel_validation.py b/tests/test_parallel_validation.py index a0aec26..df2a39d 100644 --- a/tests/test_parallel_validation.py +++ b/tests/test_parallel_validation.py @@ -5,7 +5,7 @@ import pytest -from planetmint.common.crypto import generate_key_pair +from planetmint.transactions.common.crypto import generate_key_pair from planetmint.models import Transaction diff --git a/tests/upsert_validator/test_upsert_validator_vote.py b/tests/upsert_validator/test_upsert_validator_vote.py index 5fb4fe0..1506459 100644 --- a/tests/upsert_validator/test_upsert_validator_vote.py +++ b/tests/upsert_validator/test_upsert_validator_vote.py @@ -9,10 +9,10 @@ import codecs from planetmint.elections.election import Election from planetmint.tendermint_utils import public_key_to_base64 from planetmint.upsert_validator import ValidatorElection -from planetmint.common.exceptions import AmountError -from planetmint.common.crypto import generate_key_pair -from planetmint.common.exceptions import ValidationError -from planetmint.common.transaction_mode_types import BROADCAST_TX_COMMIT +from planetmint.transactions.common.exceptions import AmountError +from planetmint.transactions.common.crypto import generate_key_pair +from planetmint.transactions.common.exceptions import ValidationError +from planetmint.transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT from planetmint.elections.vote import Vote from tests.utils import generate_block, gen_vote diff --git a/tests/upsert_validator/test_validator_election.py b/tests/upsert_validator/test_validator_election.py index 3b8e3e5..a51b8a1 100644 --- a/tests/upsert_validator/test_validator_election.py +++ b/tests/upsert_validator/test_validator_election.py @@ -9,7 +9,7 @@ import pytest from planetmint.tendermint_utils import public_key_to_base64 from planetmint.upsert_validator import ValidatorElection -from planetmint.common.exceptions import (DuplicateTransaction, +from planetmint.transactions.common.exceptions import (DuplicateTransaction, UnequalValidatorSet, InvalidProposer, MultipleInputsError, @@ -27,7 +27,7 @@ def test_upsert_validator_valid_election(b_mock, new_validator, node_key): def test_upsert_validator_invalid_election_public_key(b_mock, new_validator, node_key): - from planetmint.common.exceptions import InvalidPublicKey + from planetmint.transactions.common.exceptions import InvalidPublicKey for iv in ['ed25519-base32', 'ed25519-base64']: new_validator['public_key']['type'] = iv @@ -51,7 +51,7 @@ def test_upsert_validator_invalid_power_election(b_mock, new_validator, node_key def test_upsert_validator_invalid_proposed_election(b_mock, new_validator, node_key): - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() voters = ValidatorElection.recipients(b_mock) @@ -63,7 +63,7 @@ def test_upsert_validator_invalid_proposed_election(b_mock, new_validator, node_ def test_upsert_validator_invalid_inputs_election(b_mock, new_validator, node_key): - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() voters = ValidatorElection.recipients(b_mock) diff --git a/tests/utils.py b/tests/utils.py index 05a54e2..428f14d 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -11,8 +11,8 @@ from functools import singledispatch from planetmint.backend.localmongodb.connection import LocalMongoDBConnection from planetmint.backend.schema import TABLES -from planetmint.common import crypto -from planetmint.common.transaction_mode_types import BROADCAST_TX_COMMIT +from planetmint.transactions.common import crypto +from planetmint.transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT from planetmint.elections.election import Election, Vote from planetmint.tendermint_utils import key_to_base64 @@ -29,7 +29,7 @@ def flush_localmongo_db(connection, dbname): def generate_block(planet): - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair from planetmint.models import Transaction alice = generate_key_pair() diff --git a/tests/validation/test_transaction_structure.py b/tests/validation/test_transaction_structure.py index b710253..973f089 100644 --- a/tests/validation/test_transaction_structure.py +++ b/tests/validation/test_transaction_structure.py @@ -16,7 +16,7 @@ except ImportError: import sha3 from unittest.mock import MagicMock -from planetmint.common.exceptions import (AmountError, +from planetmint.transactions.common.exceptions import (AmountError, SchemaValidationError, ThresholdTooDeep) from planetmint.models import Transaction @@ -54,8 +54,8 @@ def test_tx_serialization_hash_function(signed_create_tx): def test_tx_serialization_with_incorrect_hash(signed_create_tx): - from planetmint.common.transaction import Transaction - from planetmint.common.exceptions import InvalidHash + from planetmint.transactions.common.transaction import Transaction + from planetmint.transactions.common.exceptions import InvalidHash tx = signed_create_tx.to_dict() tx['id'] = 'a' * 64 with pytest.raises(InvalidHash): @@ -63,7 +63,7 @@ def test_tx_serialization_with_incorrect_hash(signed_create_tx): def test_tx_serialization_with_no_hash(signed_create_tx): - from planetmint.common.exceptions import InvalidHash + from planetmint.transactions.common.exceptions import InvalidHash tx = signed_create_tx.to_dict() del tx['id'] with pytest.raises(InvalidHash): @@ -104,7 +104,7 @@ def test_validate_fails_metadata_empty_dict(b, create_tx, alice): # Asset def test_transfer_asset_schema(user_sk, signed_transfer_tx): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction tx = signed_transfer_tx.to_dict() validate(tx) tx['id'] = None @@ -149,7 +149,7 @@ def test_no_inputs(b, create_tx, alice): def test_create_single_input(b, create_tx, alice): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction tx = create_tx.to_dict() tx['inputs'] += tx['inputs'] tx = Transaction.from_dict(tx).sign([alice.private_key]).to_dict() @@ -161,7 +161,7 @@ def test_create_single_input(b, create_tx, alice): def test_create_tx_no_fulfills(b, create_tx, alice): - from planetmint.common.transaction import Transaction + from planetmint.transactions.common.transaction import Transaction tx = create_tx.to_dict() tx['inputs'][0]['fulfills'] = {'transaction_id': 'a' * 64, 'output_index': 0} @@ -213,7 +213,7 @@ def test_high_amounts(b, create_tx, alice): # Conditions def test_handle_threshold_overflow(): - from planetmint.common import transaction + from planetmint.transactions.common import transaction cond = { 'type': 'ed25519-sha-256', @@ -230,7 +230,7 @@ def test_handle_threshold_overflow(): def test_unsupported_condition_type(): - from planetmint.common import transaction + from planetmint.transactions.common import transaction from cryptoconditions.exceptions import UnsupportedTypeError with pytest.raises(UnsupportedTypeError): diff --git a/tests/web/test_outputs.py b/tests/web/test_outputs.py index db4e77a..112526a 100644 --- a/tests/web/test_outputs.py +++ b/tests/web/test_outputs.py @@ -84,7 +84,7 @@ def test_get_outputs_endpoint_with_invalid_spent(client, user_pk): @pytest.mark.abci def test_get_divisble_transactions_returns_500(b, client): from planetmint.models import Transaction - from planetmint.common import crypto + from planetmint.transactions.common import crypto import json TX_ENDPOINT = '/api/v1/transactions' diff --git a/tests/web/test_transactions.py b/tests/web/test_transactions.py index 3d2a73d..03bb334 100644 --- a/tests/web/test_transactions.py +++ b/tests/web/test_transactions.py @@ -14,8 +14,8 @@ try: except ImportError: from sha3 import sha3_256 -from planetmint.common import crypto -from planetmint.common.transaction_mode_types import (BROADCAST_TX_COMMIT, +from planetmint.transactions.common import crypto +from planetmint.transactions.common.transaction_mode_types import (BROADCAST_TX_COMMIT, BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC) @@ -133,7 +133,7 @@ def test_post_create_transaction_with_invalid_key(b, client, field, value, @pytest.mark.abci @patch('planetmint.web.views.base.logger') def test_post_create_transaction_with_invalid_id(mock_logger, b, client): - from planetmint.common.exceptions import InvalidHash + from planetmint.transactions.common.exceptions import InvalidHash from planetmint.models import Transaction user_priv, user_pub = crypto.generate_key_pair() @@ -170,7 +170,7 @@ def test_post_create_transaction_with_invalid_id(mock_logger, b, client): def test_post_create_transaction_with_invalid_signature(mock_logger, b, client): - from planetmint.common.exceptions import InvalidSignature + from planetmint.transactions.common.exceptions import InvalidSignature from planetmint.models import Transaction user_priv, user_pub = crypto.generate_key_pair() @@ -274,7 +274,7 @@ def test_post_create_transaction_with_invalid_schema(mock_logger, client): )) @patch('planetmint.web.views.base.logger') def test_post_invalid_transaction(mock_logger, client, exc, msg, monkeypatch,): - from planetmint.common import exceptions + from planetmint.transactions.common import exceptions exc_cls = getattr(exceptions, exc) def mock_validation(self_, tx): @@ -326,7 +326,7 @@ def test_post_transfer_transaction_endpoint(client, user_pk, user_sk, posted_cre @pytest.mark.abci def test_post_invalid_transfer_transaction_returns_400(client, user_pk, posted_create_tx): from planetmint.models import Transaction - from planetmint.common.exceptions import InvalidSignature + from planetmint.transactions.common.exceptions import InvalidSignature transfer_tx = Transaction.transfer(posted_create_tx.to_inputs(), [([user_pk], 1)], @@ -344,7 +344,7 @@ def test_post_invalid_transfer_transaction_returns_400(client, user_pk, posted_c @pytest.mark.abci def test_post_wrong_asset_division_transfer_returns_400(b, client, user_pk): from planetmint.models import Transaction - from planetmint.common.exceptions import AmountError + from planetmint.transactions.common.exceptions import AmountError priv_key, pub_key = crypto.generate_key_pair() @@ -425,7 +425,7 @@ def test_transactions_get_list_bad(client): ]) def test_post_transaction_valid_modes(mock_post, client, mode): from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair def _mock_post(*args, **kwargs): return Mock(json=Mock(return_value={'result': {'code': 0}})) @@ -446,7 +446,7 @@ def test_post_transaction_valid_modes(mock_post, client, mode): @pytest.mark.abci def test_post_transaction_invalid_mode(client): from planetmint.models import Transaction - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], diff --git a/tests/web/test_websocket_server.py b/tests/web/test_websocket_server.py index da83a4e..05b45fc 100644 --- a/tests/web/test_websocket_server.py +++ b/tests/web/test_websocket_server.py @@ -22,7 +22,7 @@ class MockWebSocket: def test_eventify_block_works_with_any_transaction(): from planetmint.web.websocket_server import eventify_block - from planetmint.common.crypto import generate_key_pair + from planetmint.transactions.common.crypto import generate_key_pair from planetmint.lib import Transaction alice = generate_key_pair() @@ -139,7 +139,7 @@ async def test_websocket_block_event(b, test_client, loop): from planetmint import events from planetmint.web.websocket_server import init_app, POISON_PILL, EVENTS_ENDPOINT from planetmint.models import Transaction - from planetmint.common import crypto + from planetmint.transactions.common import crypto user_priv, user_pub = crypto.generate_key_pair() tx = Transaction.create([user_pub], [([user_pub], 1)]) @@ -180,7 +180,7 @@ def test_integration_from_webapi_to_websocket(monkeypatch, client, loop): import random import aiohttp - from planetmint.common import crypto + from planetmint.transactions.common import crypto # TODO processes does not exist anymore, when reactivating this test it # will fail because of this from planetmint import processes From a421533e16ae7c827de9290fb8e87cce8e1f4d6a Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Wed, 9 Mar 2022 17:12:36 +0000 Subject: [PATCH 10/22] Added Create and Transfer as separate transactions --- planetmint/transactions/common/transaction.py | 6 +- .../types/assets}/__init__.py | 0 .../transactions/types/assets/create.py | 78 +++++++++++++++++ .../transactions/types/assets/transfer.py | 85 +++++++++++++++++++ .../transactions/types/elections/__init__.py | 0 .../types}/elections/election.py | 16 ++-- .../types}/elections/vote.py | 10 ++- 7 files changed, 181 insertions(+), 14 deletions(-) rename planetmint/{elections => transactions/types/assets}/__init__.py (100%) create mode 100644 planetmint/transactions/types/assets/create.py create mode 100644 planetmint/transactions/types/assets/transfer.py create mode 100644 planetmint/transactions/types/elections/__init__.py rename planetmint/{ => transactions/types}/elections/election.py (95%) rename planetmint/{ => transactions/types}/elections/vote.py (84%) diff --git a/planetmint/transactions/common/transaction.py b/planetmint/transactions/common/transaction.py index c7301f6..aa8de36 100644 --- a/planetmint/transactions/common/transaction.py +++ b/planetmint/transactions/common/transaction.py @@ -25,13 +25,13 @@ try: except ImportError: from sha3 import sha3_256 -from planetmint.common.crypto import PrivateKey, hash_data -from planetmint.common.exceptions import (KeypairMismatchException, +from planetmint.transactions.common.crypto import PrivateKey, hash_data +from planetmint.transactions.common.exceptions import (KeypairMismatchException, InputDoesNotExist, DoubleSpend, InvalidHash, InvalidSignature, AmountError, AssetIdMismatch, ThresholdTooDeep) -from planetmint.common.utils import serialize +from planetmint.transactions.common.utils import serialize from .memoize import memoize_from_dict, memoize_to_dict diff --git a/planetmint/elections/__init__.py b/planetmint/transactions/types/assets/__init__.py similarity index 100% rename from planetmint/elections/__init__.py rename to planetmint/transactions/types/assets/__init__.py diff --git a/planetmint/transactions/types/assets/create.py b/planetmint/transactions/types/assets/create.py new file mode 100644 index 0000000..8af8216 --- /dev/null +++ b/planetmint/transactions/types/assets/create.py @@ -0,0 +1,78 @@ +# Copyright © 2020 Interplanetary Database Association e.V., +# Planetmint and IPDB software contributors. +# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) +# Code is Apache-2.0 and docs are CC-BY-4.0 + +from planetmint.transactions.common.transaction import (Transaction, Input, Output) + +class Create(Transaction): + + OPERATION = 'CREATE' + # NOTE: This class inherits TRANSFER txn type. The `TRANSFER` property is + # overriden to re-use methods from parent class + TRANSFER = OPERATION + ALLOWED_OPERATIONS = (OPERATION,) + + @classmethod + def validate(self, tx_signers, recipients, asset, metadata): + if not isinstance(tx_signers, list): + raise TypeError('`tx_signers` must be a list instance') + if not isinstance(recipients, list): + raise TypeError('`recipients` must be a list instance') + if len(tx_signers) == 0: + raise ValueError('`tx_signers` list cannot be empty') + if len(recipients) == 0: + raise ValueError('`recipients` list cannot be empty') + if not (asset is None or isinstance(asset, dict)): + raise TypeError('`asset` must be a dict or None') + if not (metadata is None or isinstance(metadata, dict)): + raise TypeError('`metadata` must be a dict or None') + + inputs = [] + outputs = [] + + # generate_outputs + for recipient in recipients: + if not isinstance(recipient, tuple) or len(recipient) != 2: + raise ValueError(('Each `recipient` in the list must be a' + ' tuple of `([],' + ' )`')) + pub_keys, amount = recipient + outputs.append(Output.generate(pub_keys, amount)) + + # generate inputs + inputs.append(Input.generate(tx_signers)) + + return (inputs, outputs) + + @classmethod + def generate(cls, tx_signers, recipients, metadata=None, asset=None): + """A simple way to generate a `CREATE` transaction. + + Note: + This method currently supports the following Cryptoconditions + use cases: + - Ed25519 + - ThresholdSha256 + + Additionally, it provides support for the following Planetmint + use cases: + - Multiple inputs and outputs. + + Args: + tx_signers (:obj:`list` of :obj:`str`): A list of keys that + represent the signers of the CREATE Transaction. + recipients (:obj:`list` of :obj:`tuple`): A list of + ([keys],amount) that represent the recipients of this + Transaction. + metadata (dict): The metadata to be stored along with the + Transaction. + asset (dict): The metadata associated with the asset that will + be created in this Transaction. + + Returns: + :class:`~planetmint.common.transaction.Transaction` + """ + + (inputs, outputs) = cls.validate(tx_signers, recipients, asset, metadata) + return cls(cls.OPERATION, {'data': asset}, inputs, outputs, metadata) diff --git a/planetmint/transactions/types/assets/transfer.py b/planetmint/transactions/types/assets/transfer.py new file mode 100644 index 0000000..98c8602 --- /dev/null +++ b/planetmint/transactions/types/assets/transfer.py @@ -0,0 +1,85 @@ +# Copyright © 2020 Interplanetary Database Association e.V., +# Planetmint and IPDB software contributors. +# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) +# Code is Apache-2.0 and docs are CC-BY-4.0 + +from planetmint.transactions.common.transaction import (Transaction, Input, Output) +from planetmint.transactions.common.schema import (_validate_schema, + TX_SCHEMA_COMMON, + TX_SCHEMA_TRANSFER) +from copy import deepcopy + +class Transfer(Transaction): + + OPERATION = 'TRANSFER' + # NOTE: This class inherits TRANSFER txn type. The `TRANSFER` property is + # overriden to re-use methods from parent class + TRANSFER = OPERATION + ALLOWED_OPERATIONS = (OPERATION,) + + @classmethod + def validate(cls, inputs, recipients, asset_id, metadata): + if not isinstance(inputs, list): + raise TypeError('`inputs` must be a list instance') + if len(inputs) == 0: + raise ValueError('`inputs` must contain at least one item') + if not isinstance(recipients, list): + raise TypeError('`recipients` must be a list instance') + if len(recipients) == 0: + raise ValueError('`recipients` list cannot be empty') + + outputs = [] + for recipient in recipients: + if not isinstance(recipient, tuple) or len(recipient) != 2: + raise ValueError(('Each `recipient` in the list must be a' + ' tuple of `([],' + ' )`')) + pub_keys, amount = recipient + outputs.append(Output.generate(pub_keys, amount)) + + if not isinstance(asset_id, str): + raise TypeError('`asset_id` must be a string') + + return (deepcopy(inputs), outputs) + + @classmethod + def generate(cls, inputs, recipients, asset_id, metadata=None): + """A simple way to generate a `TRANSFER` transaction. + + Note: + Different cases for threshold conditions: + + Combining multiple `inputs` with an arbitrary number of + `recipients` can yield interesting cases for the creation of + threshold conditions we'd like to support. The following + notation is proposed: + + 1. The index of a `recipient` corresponds to the index of + an input: + e.g. `transfer([input1], [a])`, means `input1` would now be + owned by user `a`. + + 2. `recipients` can (almost) get arbitrary deeply nested, + creating various complex threshold conditions: + e.g. `transfer([inp1, inp2], [[a, [b, c]], d])`, means + `a`'s signature would have a 50% weight on `inp1` + compared to `b` and `c` that share 25% of the leftover + weight respectively. `inp2` is owned completely by `d`. + + Args: + inputs (:obj:`list` of :class:`~planetmint.common.transaction. + Input`): Converted `Output`s, intended to + be used as inputs in the transfer to generate. + recipients (:obj:`list` of :obj:`tuple`): A list of + ([keys],amount) that represent the recipients of this + Transaction. + asset_id (str): The asset ID of the asset to be transferred in + this Transaction. + metadata (dict): Python dictionary to be stored along with the + Transaction. + + Returns: + :class:`~planetmint.common.transaction.Transaction` + """ + (inputs, outputs) = cls.validate_transfer(inputs, recipients, asset_id, metadata) + return cls(cls.OPERATION, {'id': asset_id}, inputs, outputs, metadata) diff --git a/planetmint/transactions/types/elections/__init__.py b/planetmint/transactions/types/elections/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/planetmint/elections/election.py b/planetmint/transactions/types/elections/election.py similarity index 95% rename from planetmint/elections/election.py rename to planetmint/transactions/types/elections/election.py index d73b319..736212a 100644 --- a/planetmint/elections/election.py +++ b/planetmint/transactions/types/elections/election.py @@ -8,16 +8,18 @@ import base58 from uuid import uuid4 from planetmint import backend -from planetmint.elections.vote import Vote -from planetmint.common.exceptions import (InvalidSignature, +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer +from planetmint.transactions.types.elections.vote import Vote +from planetmint.transactions.common.exceptions import (InvalidSignature, MultipleInputsError, InvalidProposer, UnequalValidatorSet, DuplicateTransaction) from planetmint.tendermint_utils import key_from_base64, public_key_to_base64 -from planetmint.common.crypto import (public_key_from_ed25519_key) -from planetmint.common.transaction import Transaction -from planetmint.common.schema import (_validate_schema, +from planetmint.transactions.common.crypto import (public_key_from_ed25519_key) +from planetmint.transactions.common.transaction import Transaction +from planetmint.transactions.common.schema import (_validate_schema, TX_SCHEMA_COMMON, TX_SCHEMA_CREATE) @@ -161,11 +163,11 @@ class Election(Transaction): @classmethod def create(cls, tx_signers, recipients, metadata=None, asset=None): - raise NotImplementedError + Create.generate(tx_signers, recipients, metadata=None, asset=None) @classmethod def transfer(cls, tx_signers, recipients, metadata=None, asset=None): - raise NotImplementedError + Transfer.generate(tx_signers, recipients, metadata=None, asset=None) @classmethod def to_public_key(cls, election_id): diff --git a/planetmint/elections/vote.py b/planetmint/transactions/types/elections/vote.py similarity index 84% rename from planetmint/elections/vote.py rename to planetmint/transactions/types/elections/vote.py index a4bb0c9..16d7dcd 100644 --- a/planetmint/elections/vote.py +++ b/planetmint/transactions/types/elections/vote.py @@ -3,8 +3,10 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 -from planetmint.common.transaction import Transaction -from planetmint.common.schema import (_validate_schema, +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer +from planetmint.transactions.common.transaction import Transaction +from planetmint.transactions.common.schema import (_validate_schema, TX_SCHEMA_COMMON, TX_SCHEMA_TRANSFER, TX_SCHEMA_VOTE) @@ -57,8 +59,8 @@ class Vote(Transaction): @classmethod def create(cls, tx_signers, recipients, metadata=None, asset=None): - raise NotImplementedError + return Create.generate(tx_signers, recipients, metadata=None, asset=None) @classmethod def transfer(cls, tx_signers, recipients, metadata=None, asset=None): - raise NotImplementedError + return Transfer.generate(tx_signers, recipients, metadata=None, asset=None) From 1c744b744b75a8fe27c424a2ed4582fa444137cd Mon Sep 17 00:00:00 2001 From: ArpitShukla007 Date: Wed, 9 Mar 2022 17:39:14 +0000 Subject: [PATCH 11/22] Resolved errors related to transactions.common --- planetmint/transactions/common/utils.py | 8 ++++++++ tests/assets/test_divisible_assets.py | 10 +++++----- tests/validation/test_transaction_structure.py | 7 ++++--- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/planetmint/transactions/common/utils.py b/planetmint/transactions/common/utils.py index a4e9f4d..f734551 100644 --- a/planetmint/transactions/common/utils.py +++ b/planetmint/transactions/common/utils.py @@ -10,6 +10,14 @@ import rapidjson import planetmint from planetmint.transactions.common.exceptions import ValidationError +from cryptoconditions import Fulfillment, ThresholdSha256, Ed25519Sha256 +from planetmint.transactions.common.exceptions import (KeypairMismatchException, + InputDoesNotExist, DoubleSpend, + InvalidHash, InvalidSignature, + AmountError, AssetIdMismatch, + ThresholdTooDeep) +from cryptoconditions.exceptions import ( + ParsingError, ASN1DecodeError, ASN1EncodeError, UnsupportedTypeError) def gen_timestamp(): diff --git a/tests/assets/test_divisible_assets.py b/tests/assets/test_divisible_assets.py index 59a8556..570be4b 100644 --- a/tests/assets/test_divisible_assets.py +++ b/tests/assets/test_divisible_assets.py @@ -99,7 +99,7 @@ def test_single_in_single_own_multiple_out_mix_own_create(alice, user_pk, b): def test_single_in_multiple_own_single_out_single_own_create(alice, b, user_pk, user_sk): from planetmint.models import Transaction - from planetmint.transactions.common.transaction import _fulfillment_to_details + from planetmint.transactions.common.utils import _fulfillment_to_details tx = Transaction.create([alice.public_key, user_pk], [([user_pk], 100)], asset={'name': random.random()}) tx_signed = tx.sign([alice.private_key, user_sk]) @@ -249,7 +249,7 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(alice, b, user_pk, def test_single_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk, user_sk): from planetmint.models import Transaction - from planetmint.transactions.common.transaction import _fulfillment_to_details + from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset tx_create = Transaction.create([alice.public_key], [([alice.public_key, user_pk], 100)], @@ -316,7 +316,7 @@ def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk, user_sk): from planetmint.models import Transaction - from planetmint.transactions.common.transaction import _fulfillment_to_details + from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset tx_create = Transaction.create([alice.public_key], [([user_pk, alice.public_key], 50), @@ -357,7 +357,7 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk, user_sk): from planetmint.models import Transaction - from planetmint.transactions.common.transaction import _fulfillment_to_details + from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)], @@ -397,7 +397,7 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(alice, b, user_pk, user_sk): from planetmint.models import Transaction - from planetmint.transactions.common.transaction import _fulfillment_to_details + from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)], diff --git a/tests/validation/test_transaction_structure.py b/tests/validation/test_transaction_structure.py index 973f089..8cf33da 100644 --- a/tests/validation/test_transaction_structure.py +++ b/tests/validation/test_transaction_structure.py @@ -20,6 +20,7 @@ from planetmint.transactions.common.exceptions import (AmountError, SchemaValidationError, ThresholdTooDeep) from planetmint.models import Transaction +from planetmint.transactions.common.utils import _fulfillment_to_details, _fulfillment_from_details ################################################################################ # Helper functions @@ -226,7 +227,7 @@ def test_handle_threshold_overflow(): 'subconditions': [cond], } with pytest.raises(ThresholdTooDeep): - transaction._fulfillment_from_details(cond) + _fulfillment_from_details(cond) def test_unsupported_condition_type(): @@ -234,10 +235,10 @@ def test_unsupported_condition_type(): from cryptoconditions.exceptions import UnsupportedTypeError with pytest.raises(UnsupportedTypeError): - transaction._fulfillment_from_details({'type': 'a'}) + _fulfillment_from_details({'type': 'a'}) with pytest.raises(UnsupportedTypeError): - transaction._fulfillment_to_details(MagicMock(type_name='a')) + _fulfillment_to_details(MagicMock(type_name='a')) ################################################################################ From 396372203910c4734cc76fa8c829080d97f64a5a Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Wed, 9 Mar 2022 17:42:24 +0000 Subject: [PATCH 12/22] Fixing imports --- planetmint/transactions/types/assets/create.py | 7 +++---- planetmint/transactions/types/assets/transfer.py | 10 +++------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/planetmint/transactions/types/assets/create.py b/planetmint/transactions/types/assets/create.py index 8af8216..d8a1222 100644 --- a/planetmint/transactions/types/assets/create.py +++ b/planetmint/transactions/types/assets/create.py @@ -3,14 +3,13 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 -from planetmint.transactions.common.transaction import (Transaction, Input, Output) +from planetmint.transactions.common.transaction import Transaction +from planetmint.transactions.common.input import Input +from planetmint.transactions.common.output import Output class Create(Transaction): OPERATION = 'CREATE' - # NOTE: This class inherits TRANSFER txn type. The `TRANSFER` property is - # overriden to re-use methods from parent class - TRANSFER = OPERATION ALLOWED_OPERATIONS = (OPERATION,) @classmethod diff --git a/planetmint/transactions/types/assets/transfer.py b/planetmint/transactions/types/assets/transfer.py index 98c8602..444634f 100644 --- a/planetmint/transactions/types/assets/transfer.py +++ b/planetmint/transactions/types/assets/transfer.py @@ -3,18 +3,14 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 -from planetmint.transactions.common.transaction import (Transaction, Input, Output) -from planetmint.transactions.common.schema import (_validate_schema, - TX_SCHEMA_COMMON, - TX_SCHEMA_TRANSFER) +from planetmint.transactions.common.transaction import Transaction +from planetmint.transactions.common.input import Input +from planetmint.transactions.common.output import Output from copy import deepcopy class Transfer(Transaction): OPERATION = 'TRANSFER' - # NOTE: This class inherits TRANSFER txn type. The `TRANSFER` property is - # overriden to re-use methods from parent class - TRANSFER = OPERATION ALLOWED_OPERATIONS = (OPERATION,) @classmethod From 327ec2dc0993774563a875915fee569e526d3944 Mon Sep 17 00:00:00 2001 From: ArpitShukla007 Date: Thu, 10 Mar 2022 08:07:14 +0000 Subject: [PATCH 13/22] Resolved issues of election transaction --- planetmint/__init__.py | 2 +- planetmint/commands/planetmint.py | 2 +- planetmint/core.py | 2 +- planetmint/migrations/chain_migration_election.py | 2 +- planetmint/upsert_validator/validator_election.py | 2 +- tests/commands/test_commands.py | 2 +- tests/elections/test_election.py | 2 +- tests/tendermint/test_core.py | 2 +- tests/test_core.py | 2 +- tests/upsert_validator/conftest.py | 2 +- tests/upsert_validator/test_upsert_validator_vote.py | 4 ++-- tests/upsert_validator/test_validator_election.py | 2 +- tests/utils.py | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/planetmint/__init__.py b/planetmint/__init__.py index 84c140a..785daef 100644 --- a/planetmint/__init__.py +++ b/planetmint/__init__.py @@ -97,7 +97,7 @@ _config = copy.deepcopy(config) from planetmint.transactions.common.transaction import Transaction # noqa from planetmint import models # noqa from planetmint.upsert_validator import ValidatorElection # noqa -from planetmint.elections.vote import Vote # noqa +from planetmint.transactions.types.elections.vote import Vote # noqa Transaction.register_type(Transaction.CREATE, models.Transaction) Transaction.register_type(Transaction.TRANSFER, models.Transaction) diff --git a/planetmint/commands/planetmint.py b/planetmint/commands/planetmint.py index 4714fc1..d1d9707 100644 --- a/planetmint/commands/planetmint.py +++ b/planetmint/commands/planetmint.py @@ -20,7 +20,7 @@ from planetmint.utils import load_node_key from planetmint.transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT from planetmint.transactions.common.exceptions import (DatabaseDoesNotExist, ValidationError) -from planetmint.elections.vote import Vote +from planetmint.transactions.types.elections.vote import Vote import planetmint from planetmint import (backend, ValidatorElection, Planetmint) diff --git a/planetmint/core.py b/planetmint/core.py index 143bd55..43c13f4 100644 --- a/planetmint/core.py +++ b/planetmint/core.py @@ -21,7 +21,7 @@ from tendermint.abci.types_pb2 import ( ResponseCommit ) from planetmint import Planetmint -from planetmint.elections.election import Election +from planetmint.transactions.types.elections.election import Election from planetmint.tendermint_utils import (decode_transaction, calculate_hash) from planetmint.lib import Block diff --git a/planetmint/migrations/chain_migration_election.py b/planetmint/migrations/chain_migration_election.py index 03616cc..5e23e40 100644 --- a/planetmint/migrations/chain_migration_election.py +++ b/planetmint/migrations/chain_migration_election.py @@ -1,7 +1,7 @@ import json from planetmint.transactions.common.schema import TX_SCHEMA_CHAIN_MIGRATION_ELECTION -from planetmint.elections.election import Election +from planetmint.transactions.types.elections.election import Election class ChainMigrationElection(Election): diff --git a/planetmint/upsert_validator/validator_election.py b/planetmint/upsert_validator/validator_election.py index b88916e..31e4161 100644 --- a/planetmint/upsert_validator/validator_election.py +++ b/planetmint/upsert_validator/validator_election.py @@ -4,7 +4,7 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 from planetmint.transactions.common.exceptions import InvalidPowerChange -from planetmint.elections.election import Election +from planetmint.transactions.types.elections.election import Election from planetmint.transactions.common.schema import TX_SCHEMA_VALIDATOR_ELECTION from .validator_utils import (new_validator_set, encode_validator, validate_asset_public_key) diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 81d5052..1e9384f 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -13,7 +13,7 @@ import pytest from planetmint import ValidatorElection from planetmint.commands.planetmint import run_election_show -from planetmint.elections.election import Election +from planetmint.transactions.types.elections.election import Election from planetmint.lib import Block from planetmint.migrations.chain_migration_election import ChainMigrationElection diff --git a/tests/elections/test_election.py b/tests/elections/test_election.py index af0e08a..e58ec4f 100644 --- a/tests/elections/test_election.py +++ b/tests/elections/test_election.py @@ -3,7 +3,7 @@ import pytest from tests.utils import generate_election, generate_validators from planetmint.lib import Block -from planetmint.elections.election import Election +from planetmint.transactions.types.elections.election import Election from planetmint.migrations.chain_migration_election import ChainMigrationElection from planetmint.upsert_validator.validator_election import ValidatorElection diff --git a/tests/tendermint/test_core.py b/tests/tendermint/test_core.py index fdf3ec1..581fbe9 100644 --- a/tests/tendermint/test_core.py +++ b/tests/tendermint/test_core.py @@ -16,7 +16,7 @@ from planetmint.transactions.common.crypto import generate_key_pair from planetmint.core import (OkCode, CodeTypeError, rollback) -from planetmint.elections.election import Election +from planetmint.transactions.types.elections.election import Election from planetmint.lib import Block from planetmint.migrations.chain_migration_election import ChainMigrationElection from planetmint.upsert_validator.validator_election import ValidatorElection diff --git a/tests/test_core.py b/tests/test_core.py index f87015e..140cd22 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -16,7 +16,7 @@ from planetmint.transactions.common.crypto import generate_key_pair from planetmint.core import (OkCode, CodeTypeError, rollback) -from planetmint.elections.election import Election +from planetmint.transactions.types.elections.election import Election from planetmint.lib import Block from planetmint.migrations.chain_migration_election import ChainMigrationElection from planetmint.upsert_validator.validator_election import ValidatorElection diff --git a/tests/upsert_validator/conftest.py b/tests/upsert_validator/conftest.py index f4f71c4..39b8d26 100644 --- a/tests/upsert_validator/conftest.py +++ b/tests/upsert_validator/conftest.py @@ -19,7 +19,7 @@ def valid_upsert_validator_election_b(b, node_key, new_validator): @pytest.fixture -@patch('planetmint.elections.election.uuid4', lambda: 'mock_uuid4') +@patch('planetmint.transactions.types.elections.election.uuid4', lambda: 'mock_uuid4') def fixed_seed_election(b_mock, node_key, new_validator): voters = ValidatorElection.recipients(b_mock) return ValidatorElection.generate([node_key.public_key], diff --git a/tests/upsert_validator/test_upsert_validator_vote.py b/tests/upsert_validator/test_upsert_validator_vote.py index 1506459..95ec43c 100644 --- a/tests/upsert_validator/test_upsert_validator_vote.py +++ b/tests/upsert_validator/test_upsert_validator_vote.py @@ -6,14 +6,14 @@ import pytest import codecs -from planetmint.elections.election import Election +from planetmint.transactions.types.elections.election import Election from planetmint.tendermint_utils import public_key_to_base64 from planetmint.upsert_validator import ValidatorElection from planetmint.transactions.common.exceptions import AmountError from planetmint.transactions.common.crypto import generate_key_pair from planetmint.transactions.common.exceptions import ValidationError from planetmint.transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT -from planetmint.elections.vote import Vote +from planetmint.transactions.types.elections.vote import Vote from tests.utils import generate_block, gen_vote pytestmark = [pytest.mark.execute] diff --git a/tests/upsert_validator/test_validator_election.py b/tests/upsert_validator/test_validator_election.py index a51b8a1..db6f50f 100644 --- a/tests/upsert_validator/test_validator_election.py +++ b/tests/upsert_validator/test_validator_election.py @@ -74,7 +74,7 @@ def test_upsert_validator_invalid_inputs_election(b_mock, new_validator, node_ke election.validate(b_mock) -@patch('planetmint.elections.election.uuid4', lambda: 'mock_uuid4') +@patch('planetmint.transactions.types.elections.election.uuid4', lambda: 'mock_uuid4') def test_upsert_validator_invalid_election(b_mock, new_validator, node_key, fixed_seed_election): voters = ValidatorElection.recipients(b_mock) duplicate_election = ValidatorElection.generate([node_key.public_key], diff --git a/tests/utils.py b/tests/utils.py index 428f14d..4829d4e 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -13,7 +13,7 @@ from planetmint.backend.localmongodb.connection import LocalMongoDBConnection from planetmint.backend.schema import TABLES from planetmint.transactions.common import crypto from planetmint.transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT -from planetmint.elections.election import Election, Vote +from planetmint.transactions.types.elections.election import Election, Vote from planetmint.tendermint_utils import key_to_base64 From 51a92e3c3c0c7ad04c66d36951da73b331fc9b6c Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Sun, 13 Mar 2022 15:05:22 +0000 Subject: [PATCH 14/22] Resolve flake8 issues Signed-off-by: Sangat Das --- planetmint/backend/schema.py | 3 ++- planetmint/commands/planetmint.py | 4 +-- planetmint/lib.py | 19 ++++++-------- planetmint/models.py | 3 +-- planetmint/transactions/common/input.py | 24 +++--------------- planetmint/transactions/common/output.py | 22 +++------------- planetmint/transactions/common/transaction.py | 9 +++---- .../transactions/common/transaction_link.py | 25 +------------------ planetmint/transactions/common/utils.py | 14 ++++------- .../transactions/types/assets/transfer.py | 1 - .../transactions/types/elections/election.py | 13 ++++------ .../transactions/types/elections/vote.py | 6 ++--- planetmint/web/views/parameters.py | 6 ++--- tests/common/conftest.py | 4 +-- tests/common/test_transaction.py | 4 +-- tests/conftest.py | 4 +-- tests/tendermint/test_lib.py | 5 ++-- .../test_validator_election.py | 8 +++--- .../validation/test_transaction_structure.py | 8 ++---- tests/web/test_transactions.py | 5 ++-- 20 files changed, 52 insertions(+), 135 deletions(-) diff --git a/planetmint/backend/schema.py b/planetmint/backend/schema.py index 3e88d27..b19315b 100644 --- a/planetmint/backend/schema.py +++ b/planetmint/backend/schema.py @@ -11,7 +11,8 @@ import logging import planetmint from planetmint.backend.connection import connect from planetmint.transactions.common.exceptions import ValidationError -from planetmint.transactions.common.utils import validate_all_values_for_key_in_obj, validate_all_values_for_key_in_list +from planetmint.transactions.common.utils import ( + validate_all_values_for_key_in_obj, validate_all_values_for_key_in_list) logger = logging.getLogger(__name__) diff --git a/planetmint/commands/planetmint.py b/planetmint/commands/planetmint.py index d1d9707..9d09571 100644 --- a/planetmint/commands/planetmint.py +++ b/planetmint/commands/planetmint.py @@ -18,8 +18,8 @@ from planetmint.core import rollback from planetmint.migrations.chain_migration_election import ChainMigrationElection from planetmint.utils import load_node_key from planetmint.transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT -from planetmint.transactions.common.exceptions import (DatabaseDoesNotExist, - ValidationError) +from planetmint.transactions.common.exceptions import ( + DatabaseDoesNotExist, ValidationError) from planetmint.transactions.types.elections.vote import Vote import planetmint from planetmint import (backend, ValidatorElection, diff --git a/planetmint/lib.py b/planetmint/lib.py index 8b66386..4451d65 100644 --- a/planetmint/lib.py +++ b/planetmint/lib.py @@ -24,31 +24,26 @@ import requests import planetmint from planetmint import backend, config_utils, fastquery from planetmint.models import Transaction -from planetmint.transactions.common.exceptions import (SchemaValidationError, - ValidationError, - DoubleSpend) -from planetmint.transactions.common.transaction_mode_types import (BROADCAST_TX_COMMIT, - BROADCAST_TX_ASYNC, - BROADCAST_TX_SYNC) +from planetmint.transactions.common.exceptions import ( + SchemaValidationError, ValidationError, DoubleSpend) +from planetmint.transactions.common.transaction_mode_types import (BROADCAST_TX_COMMIT, BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC) from planetmint.tendermint_utils import encode_transaction, merkleroot from planetmint import exceptions as core_exceptions from planetmint.validation import BaseValidationRules - logger = logging.getLogger(__name__) - class Planetmint(object): - """Bigchain API + """Planetmint API Create, read, sign, write transactions to the database """ def __init__(self, connection=None): - """Initialize the Bigchain instance + """Initialize the Planetmint instance - A Bigchain instance has several configuration parameters (e.g. host). - If a parameter value is passed as an argument to the Bigchain + A Planetmint instance has several configuration parameters (e.g. host). + If a parameter value is passed as an argument to the Planetmint __init__ method, then that is the value it will have. Otherwise, the parameter value will come from an environment variable. If that environment variable isn't set, then the value diff --git a/planetmint/models.py b/planetmint/models.py index e0edac6..419cb44 100644 --- a/planetmint/models.py +++ b/planetmint/models.py @@ -4,8 +4,7 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 from planetmint.backend.schema import validate_language_key -from planetmint.transactions.common.exceptions import (InvalidSignature, - DuplicateTransaction) +from planetmint.transactions.common.exceptions import (InvalidSignature, DuplicateTransaction) from planetmint.transactions.common.schema import validate_transaction_schema from planetmint.transactions.common.transaction import Transaction from planetmint.transactions.common.utils import (validate_txn_obj, validate_key) diff --git a/planetmint/transactions/common/input.py b/planetmint/transactions/common/input.py index 927de97..ab123cb 100644 --- a/planetmint/transactions/common/input.py +++ b/planetmint/transactions/common/input.py @@ -3,28 +3,10 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 -from collections import namedtuple -from copy import deepcopy -from functools import reduce, lru_cache -import rapidjson +from cryptoconditions import Fulfillment +from cryptoconditions.exceptions import ASN1DecodeError, ASN1EncodeError -import base58 -from cryptoconditions import Fulfillment, ThresholdSha256, Ed25519Sha256 -from cryptoconditions.exceptions import ( - ParsingError, ASN1DecodeError, ASN1EncodeError, UnsupportedTypeError) -try: - from hashlib import sha3_256 -except ImportError: - from sha3 import sha3_256 - -from planetmint.transactions.common.crypto import PrivateKey, hash_data -from planetmint.transactions.common.exceptions import (KeypairMismatchException, - InputDoesNotExist, DoubleSpend, - InvalidHash, InvalidSignature, - AmountError, AssetIdMismatch, - ThresholdTooDeep) -from planetmint.transactions.common.utils import serialize -from .memoize import memoize_from_dict, memoize_to_dict +from planetmint.transactions.common.exceptions import InvalidSignature from .utils import _fulfillment_to_details, _fulfillment_from_details from .output import Output from .transaction_link import TransactionLink diff --git a/planetmint/transactions/common/output.py b/planetmint/transactions/common/output.py index 137542f..6462941 100644 --- a/planetmint/transactions/common/output.py +++ b/planetmint/transactions/common/output.py @@ -3,28 +3,12 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 -from collections import namedtuple -from copy import deepcopy -from functools import reduce, lru_cache -import rapidjson +from functools import reduce import base58 from cryptoconditions import Fulfillment, ThresholdSha256, Ed25519Sha256 -from cryptoconditions.exceptions import ( - ParsingError, ASN1DecodeError, ASN1EncodeError, UnsupportedTypeError) -try: - from hashlib import sha3_256 -except ImportError: - from sha3 import sha3_256 -from planetmint.transactions.common.crypto import PrivateKey, hash_data -from planetmint.transactions.common.exceptions import (KeypairMismatchException, - InputDoesNotExist, DoubleSpend, - InvalidHash, InvalidSignature, - AmountError, AssetIdMismatch, - ThresholdTooDeep) -from planetmint.transactions.common.utils import serialize -from .memoize import memoize_from_dict, memoize_to_dict +from planetmint.transactions.common.exceptions import AmountError from .utils import _fulfillment_to_details, _fulfillment_from_details class Output(object): @@ -221,4 +205,4 @@ class Output(object): amount = int(data['amount']) except ValueError: raise AmountError('Invalid amount: %s' % data['amount']) - return cls(fulfillment, data['public_keys'], amount) \ No newline at end of file + return cls(fulfillment, data['public_keys'], amount) diff --git a/planetmint/transactions/common/transaction.py b/planetmint/transactions/common/transaction.py index 04245c4..7058b86 100644 --- a/planetmint/transactions/common/transaction.py +++ b/planetmint/transactions/common/transaction.py @@ -13,13 +13,13 @@ Attributes: """ from collections import namedtuple from copy import deepcopy -from functools import reduce, lru_cache +from functools import lru_cache import rapidjson import base58 from cryptoconditions import Fulfillment, ThresholdSha256, Ed25519Sha256 from cryptoconditions.exceptions import ( - ParsingError, ASN1DecodeError, ASN1EncodeError, UnsupportedTypeError) + ParsingError, ASN1DecodeError, ASN1EncodeError) try: from hashlib import sha3_256 except ImportError: @@ -29,11 +29,10 @@ from planetmint.transactions.common.crypto import PrivateKey, hash_data from planetmint.transactions.common.exceptions import (KeypairMismatchException, InputDoesNotExist, DoubleSpend, InvalidHash, InvalidSignature, - AmountError, AssetIdMismatch, - ThresholdTooDeep) + AmountError, AssetIdMismatch) from planetmint.transactions.common.utils import serialize from .memoize import memoize_from_dict, memoize_to_dict -from .input import Input +from .input import Input from .output import Output from .transaction_link import TransactionLink diff --git a/planetmint/transactions/common/transaction_link.py b/planetmint/transactions/common/transaction_link.py index 8f36144..fcdbeb1 100644 --- a/planetmint/transactions/common/transaction_link.py +++ b/planetmint/transactions/common/transaction_link.py @@ -3,29 +3,6 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 -from collections import namedtuple -from copy import deepcopy -from functools import reduce, lru_cache -import rapidjson - -import base58 -from cryptoconditions import Fulfillment, ThresholdSha256, Ed25519Sha256 -from cryptoconditions.exceptions import ( - ParsingError, ASN1DecodeError, ASN1EncodeError, UnsupportedTypeError) -try: - from hashlib import sha3_256 -except ImportError: - from sha3 import sha3_256 - -from planetmint.transactions.common.crypto import PrivateKey, hash_data -from planetmint.transactions.common.exceptions import (KeypairMismatchException, - InputDoesNotExist, DoubleSpend, - InvalidHash, InvalidSignature, - AmountError, AssetIdMismatch, - ThresholdTooDeep) -from planetmint.transactions.common.utils import serialize -from .memoize import memoize_from_dict, memoize_to_dict - class TransactionLink(object): """An object for unidirectional linking to a Transaction's Output. @@ -96,4 +73,4 @@ class TransactionLink(object): if self.txid is None and self.output is None: return None return '{}/transactions/{}/outputs/{}'.format(path, self.txid, - self.output) \ No newline at end of file + self.output) diff --git a/planetmint/transactions/common/utils.py b/planetmint/transactions/common/utils.py index f734551..1033c72 100644 --- a/planetmint/transactions/common/utils.py +++ b/planetmint/transactions/common/utils.py @@ -10,14 +10,9 @@ import rapidjson import planetmint from planetmint.transactions.common.exceptions import ValidationError -from cryptoconditions import Fulfillment, ThresholdSha256, Ed25519Sha256 -from planetmint.transactions.common.exceptions import (KeypairMismatchException, - InputDoesNotExist, DoubleSpend, - InvalidHash, InvalidSignature, - AmountError, AssetIdMismatch, - ThresholdTooDeep) -from cryptoconditions.exceptions import ( - ParsingError, ASN1DecodeError, ASN1EncodeError, UnsupportedTypeError) +from cryptoconditions import ThresholdSha256, Ed25519Sha256 +from planetmint.transactions.common.exceptions import ThresholdTooDeep +from cryptoconditions.exceptions import UnsupportedTypeError def gen_timestamp(): @@ -220,4 +215,5 @@ def _fulfillment_from_details(data, _depth=0): threshold.add_subfulfillment(cond) return threshold - raise UnsupportedTypeError(data.get('type')) \ No newline at end of file + raise UnsupportedTypeError(data.get('type')) + \ No newline at end of file diff --git a/planetmint/transactions/types/assets/transfer.py b/planetmint/transactions/types/assets/transfer.py index 444634f..9fb709b 100644 --- a/planetmint/transactions/types/assets/transfer.py +++ b/planetmint/transactions/types/assets/transfer.py @@ -4,7 +4,6 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 from planetmint.transactions.common.transaction import Transaction -from planetmint.transactions.common.input import Input from planetmint.transactions.common.output import Output from copy import deepcopy diff --git a/planetmint/transactions/types/elections/election.py b/planetmint/transactions/types/elections/election.py index 736212a..594de15 100644 --- a/planetmint/transactions/types/elections/election.py +++ b/planetmint/transactions/types/elections/election.py @@ -11,17 +11,14 @@ from planetmint import backend from planetmint.transactions.types.assets.create import Create from planetmint.transactions.types.assets.transfer import Transfer from planetmint.transactions.types.elections.vote import Vote -from planetmint.transactions.common.exceptions import (InvalidSignature, - MultipleInputsError, - InvalidProposer, - UnequalValidatorSet, - DuplicateTransaction) +from planetmint.transactions.common.exceptions import ( + InvalidSignature, MultipleInputsError, InvalidProposer, + UnequalValidatorSet, DuplicateTransaction) from planetmint.tendermint_utils import key_from_base64, public_key_to_base64 from planetmint.transactions.common.crypto import (public_key_from_ed25519_key) from planetmint.transactions.common.transaction import Transaction -from planetmint.transactions.common.schema import (_validate_schema, - TX_SCHEMA_COMMON, - TX_SCHEMA_CREATE) +from planetmint.transactions.common.schema import ( + _validate_schema, TX_SCHEMA_COMMON, TX_SCHEMA_CREATE) class Election(Transaction): diff --git a/planetmint/transactions/types/elections/vote.py b/planetmint/transactions/types/elections/vote.py index 16d7dcd..a4b25f3 100644 --- a/planetmint/transactions/types/elections/vote.py +++ b/planetmint/transactions/types/elections/vote.py @@ -6,10 +6,8 @@ from planetmint.transactions.types.assets.create import Create from planetmint.transactions.types.assets.transfer import Transfer from planetmint.transactions.common.transaction import Transaction -from planetmint.transactions.common.schema import (_validate_schema, - TX_SCHEMA_COMMON, - TX_SCHEMA_TRANSFER, - TX_SCHEMA_VOTE) +from planetmint.transactions.common.schema import ( + _validate_schema, TX_SCHEMA_COMMON, TX_SCHEMA_TRANSFER, TX_SCHEMA_VOTE) class Vote(Transaction): diff --git a/planetmint/web/views/parameters.py b/planetmint/web/views/parameters.py index 8f295e4..6df22ff 100644 --- a/planetmint/web/views/parameters.py +++ b/planetmint/web/views/parameters.py @@ -5,10 +5,8 @@ import re -from planetmint.transactions.common.transaction_mode_types import (BROADCAST_TX_COMMIT, - BROADCAST_TX_ASYNC, - BROADCAST_TX_SYNC) - +from planetmint.transactions.common.transaction_mode_types import ( + BROADCAST_TX_COMMIT, BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC) def valid_txid(txid): if re.match('^[a-fA-F0-9]{64}$', txid): diff --git a/tests/common/conftest.py b/tests/common/conftest.py index 6a75eff..eea23ee 100644 --- a/tests/common/conftest.py +++ b/tests/common/conftest.py @@ -152,8 +152,8 @@ def tx(utx, user_priv): @pytest.fixture def transfer_utx(user_output, user2_output, utx): - from planetmint.transactions.common.transaction import (Input, TransactionLink, - Transaction) + from planetmint.transactions.common.transaction import ( + Input, TransactionLink, Transaction) user_output = user_output.to_dict() input = Input(utx.outputs[0].fulfillment, user_output['public_keys'], diff --git a/tests/common/test_transaction.py b/tests/common/test_transaction.py index 2a7c811..84ddb2b 100644 --- a/tests/common/test_transaction.py +++ b/tests/common/test_transaction.py @@ -621,8 +621,8 @@ def test_multiple_input_validation_of_transfer_tx(user_input, user_output, user2_priv, user3_pub, user3_priv, asset_definition): - from planetmint.transactions.common.transaction import (Transaction, TransactionLink, - Input, Output) + from planetmint.transactions.common.transaction import ( + Transaction, TransactionLink, Input, Output) from cryptoconditions import Ed25519Sha256 from .utils import validate_transaction_model diff --git a/tests/conftest.py b/tests/conftest.py index 780abbb..f553538 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -27,8 +27,8 @@ from planetmint.transactions.common import crypto from planetmint.transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT from planetmint.tendermint_utils import key_from_base64 from planetmint.backend import schema, query -from planetmint.transactions.common.crypto import (key_pair_from_ed25519_key, - public_key_from_ed25519_key) +from planetmint.transactions.common.crypto import ( + key_pair_from_ed25519_key, public_key_from_ed25519_key) from planetmint.transactions.common.exceptions import DatabaseDoesNotExist from planetmint.lib import Block from tests.utils import gen_vote diff --git a/tests/tendermint/test_lib.py b/tests/tendermint/test_lib.py index 3f92554..55fd2be 100644 --- a/tests/tendermint/test_lib.py +++ b/tests/tendermint/test_lib.py @@ -17,9 +17,8 @@ import pytest from pymongo import MongoClient from planetmint import backend -from planetmint.transactions.common.transaction_mode_types import (BROADCAST_TX_COMMIT, - BROADCAST_TX_ASYNC, - BROADCAST_TX_SYNC) +from planetmint.transactions.common.transaction_mode_types import ( + BROADCAST_TX_COMMIT, BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC) from planetmint.lib import Block diff --git a/tests/upsert_validator/test_validator_election.py b/tests/upsert_validator/test_validator_election.py index db6f50f..77aaf1c 100644 --- a/tests/upsert_validator/test_validator_election.py +++ b/tests/upsert_validator/test_validator_election.py @@ -9,11 +9,9 @@ import pytest from planetmint.tendermint_utils import public_key_to_base64 from planetmint.upsert_validator import ValidatorElection -from planetmint.transactions.common.exceptions import (DuplicateTransaction, - UnequalValidatorSet, - InvalidProposer, - MultipleInputsError, - InvalidPowerChange) +from planetmint.transactions.common.exceptions import ( + DuplicateTransaction, UnequalValidatorSet, InvalidProposer, + MultipleInputsError, InvalidPowerChange) pytestmark = pytest.mark.bdb diff --git a/tests/validation/test_transaction_structure.py b/tests/validation/test_transaction_structure.py index 8cf33da..5fcb425 100644 --- a/tests/validation/test_transaction_structure.py +++ b/tests/validation/test_transaction_structure.py @@ -16,9 +16,8 @@ except ImportError: import sha3 from unittest.mock import MagicMock -from planetmint.transactions.common.exceptions import (AmountError, - SchemaValidationError, - ThresholdTooDeep) +from planetmint.transactions.common.exceptions import ( + AmountError, SchemaValidationError, ThresholdTooDeep) from planetmint.models import Transaction from planetmint.transactions.common.utils import _fulfillment_to_details, _fulfillment_from_details @@ -214,8 +213,6 @@ def test_high_amounts(b, create_tx, alice): # Conditions def test_handle_threshold_overflow(): - from planetmint.transactions.common import transaction - cond = { 'type': 'ed25519-sha-256', 'public_key': 'a' * 43, @@ -231,7 +228,6 @@ def test_handle_threshold_overflow(): def test_unsupported_condition_type(): - from planetmint.transactions.common import transaction from cryptoconditions.exceptions import UnsupportedTypeError with pytest.raises(UnsupportedTypeError): diff --git a/tests/web/test_transactions.py b/tests/web/test_transactions.py index 03bb334..11846e4 100644 --- a/tests/web/test_transactions.py +++ b/tests/web/test_transactions.py @@ -15,9 +15,8 @@ except ImportError: from sha3 import sha3_256 from planetmint.transactions.common import crypto -from planetmint.transactions.common.transaction_mode_types import (BROADCAST_TX_COMMIT, - BROADCAST_TX_ASYNC, - BROADCAST_TX_SYNC) +from planetmint.transactions.common.transaction_mode_types import ( + BROADCAST_TX_COMMIT, BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC) TX_ENDPOINT = '/api/v1/transactions/' From 9b3bfc991119b3b31410f1a94b0f4fd569dea72a Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Mon, 14 Mar 2022 08:08:54 +0000 Subject: [PATCH 15/22] Resolve remaining flake8 issues Signed-off-by: Sangat Das --- planetmint/transactions/common/transaction.py | 7 +++---- planetmint/transactions/types/elections/election.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/planetmint/transactions/common/transaction.py b/planetmint/transactions/common/transaction.py index 7058b86..e89aa6b 100644 --- a/planetmint/transactions/common/transaction.py +++ b/planetmint/transactions/common/transaction.py @@ -26,10 +26,9 @@ except ImportError: from sha3 import sha3_256 from planetmint.transactions.common.crypto import PrivateKey, hash_data -from planetmint.transactions.common.exceptions import (KeypairMismatchException, - InputDoesNotExist, DoubleSpend, - InvalidHash, InvalidSignature, - AmountError, AssetIdMismatch) +from planetmint.transactions.common.exceptions import ( + KeypairMismatchException, InputDoesNotExist, DoubleSpend, + InvalidHash, InvalidSignature, AmountError, AssetIdMismatch) from planetmint.transactions.common.utils import serialize from .memoize import memoize_from_dict, memoize_to_dict from .input import Input diff --git a/planetmint/transactions/types/elections/election.py b/planetmint/transactions/types/elections/election.py index 594de15..d74fcbd 100644 --- a/planetmint/transactions/types/elections/election.py +++ b/planetmint/transactions/types/elections/election.py @@ -12,7 +12,7 @@ from planetmint.transactions.types.assets.create import Create from planetmint.transactions.types.assets.transfer import Transfer from planetmint.transactions.types.elections.vote import Vote from planetmint.transactions.common.exceptions import ( - InvalidSignature, MultipleInputsError, InvalidProposer, + InvalidSignature, MultipleInputsError, InvalidProposer, UnequalValidatorSet, DuplicateTransaction) from planetmint.tendermint_utils import key_from_base64, public_key_to_base64 from planetmint.transactions.common.crypto import (public_key_from_ed25519_key) From c3284fe060f329fb4344a22183dc01a41b132a7a Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Mon, 14 Mar 2022 09:13:58 +0000 Subject: [PATCH 16/22] Resolve remaining flake8 issues Signed-off-by: Sangat Das --- planetmint/lib.py | 3 ++- planetmint/transactions/common/utils.py | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/planetmint/lib.py b/planetmint/lib.py index 4451d65..bac5cc9 100644 --- a/planetmint/lib.py +++ b/planetmint/lib.py @@ -26,7 +26,8 @@ from planetmint import backend, config_utils, fastquery from planetmint.models import Transaction from planetmint.transactions.common.exceptions import ( SchemaValidationError, ValidationError, DoubleSpend) -from planetmint.transactions.common.transaction_mode_types import (BROADCAST_TX_COMMIT, BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC) +from planetmint.transactions.common.transaction_mode_types import ( + BROADCAST_TX_COMMIT, BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC) from planetmint.tendermint_utils import encode_transaction, merkleroot from planetmint import exceptions as core_exceptions from planetmint.validation import BaseValidationRules diff --git a/planetmint/transactions/common/utils.py b/planetmint/transactions/common/utils.py index 1033c72..e18580d 100644 --- a/planetmint/transactions/common/utils.py +++ b/planetmint/transactions/common/utils.py @@ -216,4 +216,3 @@ def _fulfillment_from_details(data, _depth=0): return threshold raise UnsupportedTypeError(data.get('type')) - \ No newline at end of file From 0fee3607ee4f230ef808abc60359c043eb3d7a61 Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Mon, 21 Mar 2022 19:52:10 +0000 Subject: [PATCH 17/22] Remove create and transfer code snippets from transaction.py Signed-off-by: Sangat Das --- .../generate_http_server_api_documentation.py | 11 +- planetmint/transactions/common/transaction.py | 131 ------------------ .../transactions/types/assets/create.py | 6 +- .../transactions/types/assets/transfer.py | 4 +- .../transactions/types/elections/election.py | 2 +- .../transactions/types/elections/vote.py | 2 +- tests/assets/test_digital_assets.py | 21 ++- tests/assets/test_divisible_assets.py | 105 +++++++------- tests/backend/localmongodb/test_queries.py | 20 +-- tests/commands/test_commands.py | 6 +- tests/common/test_memoize.py | 7 +- tests/common/test_transaction.py | 54 ++++---- tests/conftest.py | 16 +-- ...bigchain_api.py => test_planetmint_api.py} | 64 ++++----- tests/tendermint/test_core.py | 18 +-- tests/tendermint/test_fastquery.py | 21 +-- tests/tendermint/test_integration.py | 6 +- tests/tendermint/test_lib.py | 40 +++--- tests/test_core.py | 18 +-- tests/test_parallel_validation.py | 10 +- tests/test_txlist.py | 9 +- tests/web/test_assets.py | 7 +- tests/web/test_block_tendermint.py | 6 +- tests/web/test_metadata.py | 9 +- tests/web/test_transactions.py | 38 ++--- tests/web/test_websocket_server.py | 10 +- 26 files changed, 251 insertions(+), 390 deletions(-) rename tests/db/{test_bigchain_api.py => test_planetmint_api.py} (89%) diff --git a/docs/root/generate_http_server_api_documentation.py b/docs/root/generate_http_server_api_documentation.py index 4b84d57..1bf66ae 100644 --- a/docs/root/generate_http_server_api_documentation.py +++ b/docs/root/generate_http_server_api_documentation.py @@ -9,8 +9,11 @@ import json import os import os.path -from planetmint.transactions.common.transaction import Transaction, Input, TransactionLink +from planetmint.transactions.common.input import Input +from planetmint.transactions.common.transaction_link import TransactionLink from planetmint import lib +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer from planetmint.web import server @@ -133,7 +136,7 @@ def main(): privkey = 'CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z' pubkey = '4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD' asset = {'msg': 'Hello Planetmint!'} - tx = Transaction.create([pubkey], [([pubkey], 1)], asset=asset, metadata={'sequence': 0}) + tx = Create.generate([pubkey], [([pubkey], 1)], asset=asset, metadata={'sequence': 0}) tx = tx.sign([privkey]) ctx['tx'] = pretty_json(tx.to_dict()) ctx['public_keys'] = tx.outputs[0].public_keys[0] @@ -147,7 +150,7 @@ def main(): input_ = Input(fulfillment=tx.outputs[cid].fulfillment, fulfills=TransactionLink(txid=tx.id, output=cid), owners_before=tx.outputs[cid].public_keys) - tx_transfer = Transaction.transfer([input_], [([pubkey_transfer], 1)], asset_id=tx.id, metadata={'sequence': 1}) + tx_transfer = Transfer.generate([input_], [([pubkey_transfer], 1)], asset_id=tx.id, metadata={'sequence': 1}) tx_transfer = tx_transfer.sign([privkey]) ctx['tx_transfer'] = pretty_json(tx_transfer.to_dict()) ctx['public_keys_transfer'] = tx_transfer.outputs[0].public_keys[0] @@ -160,7 +163,7 @@ def main(): input_ = Input(fulfillment=tx_transfer.outputs[cid].fulfillment, fulfills=TransactionLink(txid=tx_transfer.id, output=cid), owners_before=tx_transfer.outputs[cid].public_keys) - tx_transfer_last = Transaction.transfer([input_], [([pubkey_transfer_last], 1)], + tx_transfer_last = Transfer.generate([input_], [([pubkey_transfer_last], 1)], asset_id=tx.id, metadata={'sequence': 2}) tx_transfer_last = tx_transfer_last.sign([privkey_transfer]) ctx['tx_transfer_last'] = pretty_json(tx_transfer_last.to_dict()) diff --git a/planetmint/transactions/common/transaction.py b/planetmint/transactions/common/transaction.py index e89aa6b..c21e99f 100644 --- a/planetmint/transactions/common/transaction.py +++ b/planetmint/transactions/common/transaction.py @@ -167,137 +167,6 @@ class Transaction(object): def _hash(self): self._id = hash_data(self.serialized) - @classmethod - def validate_create(cls, tx_signers, recipients, asset, metadata): - if not isinstance(tx_signers, list): - raise TypeError('`tx_signers` must be a list instance') - if not isinstance(recipients, list): - raise TypeError('`recipients` must be a list instance') - if len(tx_signers) == 0: - raise ValueError('`tx_signers` list cannot be empty') - if len(recipients) == 0: - raise ValueError('`recipients` list cannot be empty') - if not (asset is None or isinstance(asset, dict)): - raise TypeError('`asset` must be a dict or None') - if not (metadata is None or isinstance(metadata, dict)): - raise TypeError('`metadata` must be a dict or None') - - inputs = [] - outputs = [] - - # generate_outputs - for recipient in recipients: - if not isinstance(recipient, tuple) or len(recipient) != 2: - raise ValueError(('Each `recipient` in the list must be a' - ' tuple of `([],' - ' )`')) - pub_keys, amount = recipient - outputs.append(Output.generate(pub_keys, amount)) - - # generate inputs - inputs.append(Input.generate(tx_signers)) - - return (inputs, outputs) - - @classmethod - def create(cls, tx_signers, recipients, metadata=None, asset=None): - """A simple way to generate a `CREATE` transaction. - - Note: - This method currently supports the following Cryptoconditions - use cases: - - Ed25519 - - ThresholdSha256 - - Additionally, it provides support for the following Planetmint - use cases: - - Multiple inputs and outputs. - - Args: - tx_signers (:obj:`list` of :obj:`str`): A list of keys that - represent the signers of the CREATE Transaction. - recipients (:obj:`list` of :obj:`tuple`): A list of - ([keys],amount) that represent the recipients of this - Transaction. - metadata (dict): The metadata to be stored along with the - Transaction. - asset (dict): The metadata associated with the asset that will - be created in this Transaction. - - Returns: - :class:`~planetmint.transactions.common.transaction.Transaction` - """ - - (inputs, outputs) = cls.validate_create(tx_signers, recipients, asset, metadata) - return cls(cls.CREATE, {'data': asset}, inputs, outputs, metadata) - - @classmethod - def validate_transfer(cls, inputs, recipients, asset_id, metadata): - if not isinstance(inputs, list): - raise TypeError('`inputs` must be a list instance') - if len(inputs) == 0: - raise ValueError('`inputs` must contain at least one item') - if not isinstance(recipients, list): - raise TypeError('`recipients` must be a list instance') - if len(recipients) == 0: - raise ValueError('`recipients` list cannot be empty') - - outputs = [] - for recipient in recipients: - if not isinstance(recipient, tuple) or len(recipient) != 2: - raise ValueError(('Each `recipient` in the list must be a' - ' tuple of `([],' - ' )`')) - pub_keys, amount = recipient - outputs.append(Output.generate(pub_keys, amount)) - - if not isinstance(asset_id, str): - raise TypeError('`asset_id` must be a string') - - return (deepcopy(inputs), outputs) - - @classmethod - def transfer(cls, inputs, recipients, asset_id, metadata=None): - """A simple way to generate a `TRANSFER` transaction. - - Note: - Different cases for threshold conditions: - - Combining multiple `inputs` with an arbitrary number of - `recipients` can yield interesting cases for the creation of - threshold conditions we'd like to support. The following - notation is proposed: - - 1. The index of a `recipient` corresponds to the index of - an input: - e.g. `transfer([input1], [a])`, means `input1` would now be - owned by user `a`. - - 2. `recipients` can (almost) get arbitrary deeply nested, - creating various complex threshold conditions: - e.g. `transfer([inp1, inp2], [[a, [b, c]], d])`, means - `a`'s signature would have a 50% weight on `inp1` - compared to `b` and `c` that share 25% of the leftover - weight respectively. `inp2` is owned completely by `d`. - - Args: - inputs (:obj:`list` of :class:`~planetmint.transactions.common.transaction. - Input`): Converted `Output`s, intended to - be used as inputs in the transfer to generate. - recipients (:obj:`list` of :obj:`tuple`): A list of - ([keys],amount) that represent the recipients of this - Transaction. - asset_id (str): The asset ID of the asset to be transferred in - this Transaction. - metadata (dict): Python dictionary to be stored along with the - Transaction. - - Returns: - :class:`~planetmint.transactions.common.transaction.Transaction` - """ - (inputs, outputs) = cls.validate_transfer(inputs, recipients, asset_id, metadata) - return cls(cls.TRANSFER, {'id': asset_id}, inputs, outputs, metadata) - def __eq__(self, other): try: other = other.to_dict() diff --git a/planetmint/transactions/types/assets/create.py b/planetmint/transactions/types/assets/create.py index d8a1222..3a38783 100644 --- a/planetmint/transactions/types/assets/create.py +++ b/planetmint/transactions/types/assets/create.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 -from planetmint.transactions.common.transaction import Transaction +from planetmint.models import Transaction from planetmint.transactions.common.input import Input from planetmint.transactions.common.output import Output @@ -13,7 +13,7 @@ class Create(Transaction): ALLOWED_OPERATIONS = (OPERATION,) @classmethod - def validate(self, tx_signers, recipients, asset, metadata): + def validate_create(self, tx_signers, recipients, asset, metadata): if not isinstance(tx_signers, list): raise TypeError('`tx_signers` must be a list instance') if not isinstance(recipients, list): @@ -73,5 +73,5 @@ class Create(Transaction): :class:`~planetmint.common.transaction.Transaction` """ - (inputs, outputs) = cls.validate(tx_signers, recipients, asset, metadata) + (inputs, outputs) = cls.validate_create(tx_signers, recipients, asset, metadata) return cls(cls.OPERATION, {'data': asset}, inputs, outputs, metadata) diff --git a/planetmint/transactions/types/assets/transfer.py b/planetmint/transactions/types/assets/transfer.py index 9fb709b..a658bc0 100644 --- a/planetmint/transactions/types/assets/transfer.py +++ b/planetmint/transactions/types/assets/transfer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 -from planetmint.transactions.common.transaction import Transaction +from planetmint.models import Transaction from planetmint.transactions.common.output import Output from copy import deepcopy @@ -13,7 +13,7 @@ class Transfer(Transaction): ALLOWED_OPERATIONS = (OPERATION,) @classmethod - def validate(cls, inputs, recipients, asset_id, metadata): + def validate_transfer(cls, inputs, recipients, asset_id, metadata): if not isinstance(inputs, list): raise TypeError('`inputs` must be a list instance') if len(inputs) == 0: diff --git a/planetmint/transactions/types/elections/election.py b/planetmint/transactions/types/elections/election.py index d74fcbd..984d179 100644 --- a/planetmint/transactions/types/elections/election.py +++ b/planetmint/transactions/types/elections/election.py @@ -143,7 +143,7 @@ class Election(Transaction): uuid = uuid4() election_data['seed'] = str(uuid) - (inputs, outputs) = cls.validate_create(initiator, voters, election_data, metadata) + (inputs, outputs) = Create.validate_create(initiator, voters, election_data, metadata) election = cls(cls.OPERATION, {'data': election_data}, inputs, outputs, metadata) cls.validate_schema(election.to_dict()) return election diff --git a/planetmint/transactions/types/elections/vote.py b/planetmint/transactions/types/elections/vote.py index a4b25f3..9b8c33b 100644 --- a/planetmint/transactions/types/elections/vote.py +++ b/planetmint/transactions/types/elections/vote.py @@ -10,7 +10,7 @@ from planetmint.transactions.common.schema import ( _validate_schema, TX_SCHEMA_COMMON, TX_SCHEMA_TRANSFER, TX_SCHEMA_VOTE) -class Vote(Transaction): +class Vote(Transfer): OPERATION = 'VOTE' # NOTE: This class inherits TRANSFER txn type. The `TRANSFER` property is diff --git a/tests/assets/test_digital_assets.py b/tests/assets/test_digital_assets.py index b23b05d..3a5b88b 100644 --- a/tests/assets/test_digital_assets.py +++ b/tests/assets/test_digital_assets.py @@ -5,12 +5,11 @@ import pytest import random - +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer def test_asset_transfer(b, signed_create_tx, user_pk, user_sk): - from planetmint.models import Transaction - - tx_transfer = Transaction.transfer(signed_create_tx.to_inputs(), [([user_pk], 1)], + tx_transfer = Transfer.generate(signed_create_tx.to_inputs(), [([user_pk], 1)], signed_create_tx.id) tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -22,9 +21,8 @@ def test_asset_transfer(b, signed_create_tx, user_pk, user_sk): def test_validate_transfer_asset_id_mismatch(b, signed_create_tx, user_pk, user_sk): from planetmint.transactions.common.exceptions import AssetIdMismatch - from planetmint.models import Transaction - tx_transfer = Transaction.transfer(signed_create_tx.to_inputs(), [([user_pk], 1)], + tx_transfer = Transfer.generate(signed_create_tx.to_inputs(), [([user_pk], 1)], signed_create_tx.id) tx_transfer.asset['id'] = 'a' * 64 tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -37,14 +35,14 @@ def test_validate_transfer_asset_id_mismatch(b, signed_create_tx, user_pk, user_ def test_get_asset_id_create_transaction(alice, user_pk): from planetmint.models import Transaction - tx_create = Transaction.create([alice.public_key], [([user_pk], 1)]) + tx_create = Create.generate([alice.public_key], [([user_pk], 1)]) assert Transaction.get_asset_id(tx_create) == tx_create.id def test_get_asset_id_transfer_transaction(b, signed_create_tx, user_pk): from planetmint.models import Transaction - tx_transfer = Transaction.transfer(signed_create_tx.to_inputs(), [([user_pk], 1)], + tx_transfer = Transfer.generate(signed_create_tx.to_inputs(), [([user_pk], 1)], signed_create_tx.id) asset_id = Transaction.get_asset_id(tx_transfer) assert asset_id == tx_transfer.asset['id'] @@ -54,10 +52,10 @@ def test_asset_id_mismatch(alice, user_pk): from planetmint.models import Transaction from planetmint.transactions.common.exceptions import AssetIdMismatch - tx1 = Transaction.create([alice.public_key], [([user_pk], 1)], + tx1 = Create.generate([alice.public_key], [([user_pk], 1)], metadata={'msg': random.random()}) tx1.sign([alice.private_key]) - tx2 = Transaction.create([alice.public_key], [([user_pk], 1)], + tx2 = Create.generate([alice.public_key], [([user_pk], 1)], metadata={'msg': random.random()}) tx2.sign([alice.private_key]) @@ -66,8 +64,7 @@ def test_asset_id_mismatch(alice, user_pk): def test_create_valid_divisible_asset(b, user_pk, user_sk): - from planetmint.models import Transaction - tx = Transaction.create([user_pk], [([user_pk], 2)]) + tx = Create.generate([user_pk], [([user_pk], 2)]) tx_signed = tx.sign([user_sk]) assert tx_signed.validate(b) == tx_signed diff --git a/tests/assets/test_divisible_assets.py b/tests/assets/test_divisible_assets.py index 570be4b..d9d680f 100644 --- a/tests/assets/test_divisible_assets.py +++ b/tests/assets/test_divisible_assets.py @@ -3,9 +3,12 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 + import pytest import random +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer from planetmint.transactions.common.exceptions import DoubleSpend @@ -15,9 +18,9 @@ from planetmint.transactions.common.exceptions import DoubleSpend # Single output # Single owners_after def test_single_in_single_own_single_out_single_own_create(alice, user_pk, b): - from planetmint.models import Transaction + - tx = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) + tx = Create.generate([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) tx_signed = tx.sign([alice.private_key]) assert tx_signed.validate(b) == tx_signed @@ -32,9 +35,9 @@ def test_single_in_single_own_single_out_single_own_create(alice, user_pk, b): # Multiple outputs # Single owners_after per output def test_single_in_single_own_multiple_out_single_own_create(alice, user_pk, b): - from planetmint.models import Transaction + - tx = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk], 50)], + tx = Create.generate([alice.public_key], [([user_pk], 50), ([user_pk], 50)], asset={'name': random.random()}) tx_signed = tx.sign([alice.private_key]) @@ -51,9 +54,8 @@ def test_single_in_single_own_multiple_out_single_own_create(alice, user_pk, b): # Single output # Multiple owners_after def test_single_in_single_own_single_out_multiple_own_create(alice, user_pk, b): - from planetmint.models import Transaction - tx = Transaction.create([alice.public_key], [([user_pk, user_pk], 100)], asset={'name': random.random()}) + tx = Create.generate([alice.public_key], [([user_pk, user_pk], 100)], asset={'name': random.random()}) tx_signed = tx.sign([alice.private_key]) assert tx_signed.validate(b) == tx_signed @@ -74,9 +76,8 @@ def test_single_in_single_own_single_out_multiple_own_create(alice, user_pk, b): # Mix: one output with a single owners_after, one output with multiple # owners_after def test_single_in_single_own_multiple_out_mix_own_create(alice, user_pk, b): - from planetmint.models import Transaction - tx = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk, user_pk], 50)], + tx = Create.generate([alice.public_key], [([user_pk], 50), ([user_pk, user_pk], 50)], asset={'name': random.random()}) tx_signed = tx.sign([alice.private_key]) @@ -98,10 +99,10 @@ def test_single_in_single_own_multiple_out_mix_own_create(alice, user_pk, b): # Output combinations already tested above def test_single_in_multiple_own_single_out_single_own_create(alice, b, user_pk, user_sk): - from planetmint.models import Transaction + from planetmint.transactions.common.utils import _fulfillment_to_details - tx = Transaction.create([alice.public_key, user_pk], [([user_pk], 100)], asset={'name': random.random()}) + tx = Create.generate([alice.public_key, user_pk], [([user_pk], 100)], asset={'name': random.random()}) tx_signed = tx.sign([alice.private_key, user_sk]) assert tx_signed.validate(b) == tx_signed assert len(tx_signed.outputs) == 1 @@ -120,14 +121,13 @@ def test_single_in_multiple_own_single_out_single_own_create(alice, b, user_pk, # Single owners_after def test_single_in_single_own_single_out_single_own_transfer(alice, b, user_pk, user_sk): - from planetmint.models import Transaction # CREATE divisible asset - tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) + tx_create = Create.generate([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # TRANSFER - tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)], + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 100)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -146,14 +146,13 @@ def test_single_in_single_own_single_out_single_own_transfer(alice, b, user_pk, # Single owners_after def test_single_in_single_own_multiple_out_single_own_transfer(alice, b, user_pk, user_sk): - from planetmint.models import Transaction # CREATE divisible asset - tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) + tx_create = Create.generate([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # TRANSFER - tx_transfer = Transaction.transfer(tx_create.to_inputs(), + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 50), ([alice.public_key], 50)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -174,14 +173,13 @@ def test_single_in_single_own_multiple_out_single_own_transfer(alice, b, user_pk # Multiple owners_after def test_single_in_single_own_single_out_multiple_own_transfer(alice, b, user_pk, user_sk): - from planetmint.models import Transaction # CREATE divisible asset - tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) + tx_create = Create.generate([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # TRANSFER - tx_transfer = Transaction.transfer(tx_create.to_inputs(), + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key, alice.public_key], 100)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -211,14 +209,13 @@ def test_single_in_single_own_single_out_multiple_own_transfer(alice, b, user_pk # owners_after def test_single_in_single_own_multiple_out_mix_own_transfer(alice, b, user_pk, user_sk): - from planetmint.models import Transaction # CREATE divisible asset - tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) + tx_create = Create.generate([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # TRANSFER - tx_transfer = Transaction.transfer(tx_create.to_inputs(), + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 50), ([alice.public_key, alice.public_key], 50)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -248,16 +245,16 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(alice, b, user_pk, # Single owners_after def test_single_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk, user_sk): - from planetmint.models import Transaction + from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset - tx_create = Transaction.create([alice.public_key], [([alice.public_key, user_pk], 100)], + tx_create = Create.generate([alice.public_key], [([alice.public_key, user_pk], 100)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # TRANSFER - tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)], + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 100)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk]) @@ -284,15 +281,14 @@ def test_single_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk # Single owners_after def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk, user_sk): - from planetmint.models import Transaction # CREATE divisible asset - tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk], 50)], + tx_create = Create.generate([alice.public_key], [([user_pk], 50), ([user_pk], 50)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # TRANSFER - tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)], + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 100)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -315,17 +311,17 @@ def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk # Single owners_after def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk, user_sk): - from planetmint.models import Transaction + from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset - tx_create = Transaction.create([alice.public_key], [([user_pk, alice.public_key], 50), + tx_create = Create.generate([alice.public_key], [([user_pk, alice.public_key], 50), ([user_pk, alice.public_key], 50)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # TRANSFER - tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)], + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 100)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk]) @@ -356,16 +352,16 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_ # Single owners_after def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk, user_sk): - from planetmint.models import Transaction + from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset - tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)], + tx_create = Create.generate([alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # TRANSFER - tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)], + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 100)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk]) @@ -396,16 +392,16 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk # owners_after def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(alice, b, user_pk, user_sk): - from planetmint.models import Transaction + from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset - tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)], + tx_create = Create.generate([alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # TRANSFER - tx_transfer = Transaction.transfer(tx_create.to_inputs(), + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 50), ([alice.public_key, user_pk], 50)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk]) @@ -441,12 +437,11 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(alice, b, user_pk, # Single output # Single owners_after def test_multiple_in_different_transactions(alice, b, user_pk, user_sk): - from planetmint.models import Transaction - + # CREATE divisible asset # `b` creates a divisible asset and assigns 50 shares to `b` and # 50 shares to `user_pk` - tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([alice.public_key], 50)], + tx_create = Create.generate([alice.public_key], [([user_pk], 50), ([alice.public_key], 50)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) @@ -454,7 +449,7 @@ def test_multiple_in_different_transactions(alice, b, user_pk, user_sk): # `b` transfers its 50 shares to `user_pk` # after this transaction `user_pk` will have a total of 100 shares # split across two different transactions - tx_transfer1 = Transaction.transfer(tx_create.to_inputs([1]), + tx_transfer1 = Transfer.generate(tx_create.to_inputs([1]), [([user_pk], 50)], asset_id=tx_create.id) tx_transfer1_signed = tx_transfer1.sign([alice.private_key]) @@ -462,7 +457,7 @@ def test_multiple_in_different_transactions(alice, b, user_pk, user_sk): # TRANSFER # `user_pk` combines two different transaction with 50 shares each and # transfers a total of 100 shares back to `b` - tx_transfer2 = Transaction.transfer(tx_create.to_inputs([0]) + + tx_transfer2 = Transfer.generate(tx_create.to_inputs([0]) + tx_transfer1.to_inputs([0]), [([alice.private_key], 100)], asset_id=tx_create.id) @@ -485,18 +480,18 @@ def test_multiple_in_different_transactions(alice, b, user_pk, user_sk): # inputs needs to match the amount being sent in the outputs. # In other words `amount_in_inputs - amount_in_outputs == 0` def test_amount_error_transfer(alice, b, user_pk, user_sk): - from planetmint.models import Transaction + from planetmint.transactions.common.exceptions import AmountError # CREATE divisible asset - tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) + tx_create = Create.generate([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) b.store_bulk_transactions([tx_create_signed]) # TRANSFER # output amount less than input amount - tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 50)], + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 50)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -505,7 +500,7 @@ def test_amount_error_transfer(alice, b, user_pk, user_sk): # TRANSFER # output amount greater than input amount - tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 101)], + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 101)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -521,15 +516,13 @@ def test_threshold_same_public_key(alice, b, user_pk, user_sk): # Creating threshold conditions with the same key does not make sense but # that does not mean that the code shouldn't work. - from planetmint.models import Transaction - # CREATE divisible asset - tx_create = Transaction.create([alice.public_key], [([user_pk, user_pk], 100)], + tx_create = Create.generate([alice.public_key], [([user_pk, user_pk], 100)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # TRANSFER - tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)], + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 100)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk, user_sk]) @@ -543,16 +536,16 @@ def test_threshold_same_public_key(alice, b, user_pk, user_sk): def test_sum_amount(alice, b, user_pk, user_sk): - from planetmint.models import Transaction + # CREATE divisible asset with 3 outputs with amount 1 - tx_create = Transaction.create([alice.public_key], [([user_pk], 1), ([user_pk], 1), ([user_pk], 1)], + tx_create = Create.generate([alice.public_key], [([user_pk], 1), ([user_pk], 1), ([user_pk], 1)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # create a transfer transaction with one output and check if the amount # is 3 - tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 3)], + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 3)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -568,15 +561,15 @@ def test_sum_amount(alice, b, user_pk, user_sk): def test_divide(alice, b, user_pk, user_sk): - from planetmint.models import Transaction + # CREATE divisible asset with 1 output with amount 3 - tx_create = Transaction.create([alice.public_key], [([user_pk], 3)], asset={'name': random.random()}) + tx_create = Create.generate([alice.public_key], [([user_pk], 3)], asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # create a transfer transaction with 3 outputs and check if the amount # of each output is 1 - tx_transfer = Transaction.transfer(tx_create.to_inputs(), + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([alice.public_key], 1), ([alice.public_key], 1), ([alice.public_key], 1)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) diff --git a/tests/backend/localmongodb/test_queries.py b/tests/backend/localmongodb/test_queries.py index 0557527..80abb5d 100644 --- a/tests/backend/localmongodb/test_queries.py +++ b/tests/backend/localmongodb/test_queries.py @@ -4,6 +4,8 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 from copy import deepcopy +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer import pytest import pymongo @@ -215,16 +217,15 @@ def test_get_owned_ids(signed_create_tx, user_pk): def test_get_spending_transactions(user_pk, user_sk): from planetmint.backend import connect, query - from planetmint.models import Transaction conn = connect() out = [([user_pk], 1)] - tx1 = Transaction.create([user_pk], out * 3) + tx1 = Create.generate([user_pk], out * 3) tx1.sign([user_sk]) inputs = tx1.to_inputs() - tx2 = Transaction.transfer([inputs[0]], out, tx1.id).sign([user_sk]) - tx3 = Transaction.transfer([inputs[1]], out, tx1.id).sign([user_sk]) - tx4 = Transaction.transfer([inputs[2]], out, tx1.id).sign([user_sk]) + tx2 = Transfer.generate([inputs[0]], out, tx1.id).sign([user_sk]) + tx3 = Transfer.generate([inputs[1]], out, tx1.id).sign([user_sk]) + tx4 = Transfer.generate([inputs[2]], out, tx1.id).sign([user_sk]) txns = [deepcopy(tx.to_dict()) for tx in [tx1, tx2, tx3, tx4]] conn.db.transactions.insert_many(txns) @@ -237,7 +238,6 @@ def test_get_spending_transactions(user_pk, user_sk): def test_get_spending_transactions_multiple_inputs(): from planetmint.backend import connect, query - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair conn = connect() (alice_sk, alice_pk) = generate_key_pair() @@ -245,20 +245,20 @@ def test_get_spending_transactions_multiple_inputs(): (carol_sk, carol_pk) = generate_key_pair() out = [([alice_pk], 9)] - tx1 = Transaction.create([alice_pk], out).sign([alice_sk]) + tx1 = Create.generate([alice_pk], out).sign([alice_sk]) inputs1 = tx1.to_inputs() - tx2 = Transaction.transfer([inputs1[0]], + tx2 = Transfer.generate([inputs1[0]], [([alice_pk], 6), ([bob_pk], 3)], tx1.id).sign([alice_sk]) inputs2 = tx2.to_inputs() - tx3 = Transaction.transfer([inputs2[0]], + tx3 = Transfer.generate([inputs2[0]], [([bob_pk], 3), ([carol_pk], 3)], tx1.id).sign([alice_sk]) inputs3 = tx3.to_inputs() - tx4 = Transaction.transfer([inputs2[1], inputs3[0]], + tx4 = Transfer.generate([inputs2[1], inputs3[0]], [([carol_pk], 6)], tx1.id).sign([bob_sk]) diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 1e9384f..df4c1b8 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -259,16 +259,16 @@ def test_recover_db_on_start(mock_run_recover, @pytest.mark.bdb def test_run_recover(b, alice, bob): from planetmint.commands.planetmint import run_recover - from planetmint.models import Transaction + from planetmint.transactions.types.assets.create import Create from planetmint.lib import Block from planetmint.backend import query - tx1 = Transaction.create([alice.public_key], + tx1 = Create.generate([alice.public_key], [([alice.public_key], 1)], asset={'cycle': 'hero'}, metadata={'name': 'hohenheim'}) \ .sign([alice.private_key]) - tx2 = Transaction.create([bob.public_key], + tx2 = Create.generate([bob.public_key], [([bob.public_key], 1)], asset={'cycle': 'hero'}, metadata={'name': 'hohenheim'}) \ diff --git a/tests/common/test_memoize.py b/tests/common/test_memoize.py index 8665080..dd047cb 100644 --- a/tests/common/test_memoize.py +++ b/tests/common/test_memoize.py @@ -7,6 +7,7 @@ import pytest from copy import deepcopy from planetmint.models import Transaction +from planetmint.transactions.types.assets.create import Create from planetmint.transactions.common.crypto import generate_key_pair from planetmint.transactions.common.memoize import to_dict, from_dict @@ -23,7 +24,7 @@ def test_memoize_to_dict(b): assert to_dict.cache_info().hits == 0 assert to_dict.cache_info().misses == 0 - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset,)\ .sign([alice.private_key]) @@ -49,7 +50,7 @@ def test_memoize_from_dict(b): assert from_dict.cache_info().hits == 0 assert from_dict.cache_info().misses == 0 - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset,)\ .sign([alice.private_key]) @@ -76,7 +77,7 @@ def test_memoize_input_valid(b): assert Transaction._input_valid.cache_info().hits == 0 assert Transaction._input_valid.cache_info().misses == 0 - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset,)\ .sign([alice.private_key]) diff --git a/tests/common/test_transaction.py b/tests/common/test_transaction.py index 84ddb2b..1d20e7d 100644 --- a/tests/common/test_transaction.py +++ b/tests/common/test_transaction.py @@ -11,6 +11,8 @@ 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 pytest import mark, raises try: from hashlib import sha3_256 @@ -690,7 +692,7 @@ def test_create_create_transaction_single_io(user_output, user_pub, data): 'version': Transaction.VERSION, } - tx = Transaction.create([user_pub], [([user_pub], 1)], metadata=data, + tx = Create.generate([user_pub], [([user_pub], 1)], metadata=data, asset=data) tx_dict = tx.to_dict() tx_dict['inputs'][0]['fulfillment'] = None @@ -705,7 +707,7 @@ def test_validate_single_io_create_transaction(user_pub, user_priv, data, asset_definition): from planetmint.transactions.common.transaction import Transaction - tx = Transaction.create([user_pub], [([user_pub], 1)], metadata=data) + tx = Create.generate([user_pub], [([user_pub], 1)], metadata=data) tx = tx.sign([user_priv]) assert tx.inputs_valid() is True @@ -727,7 +729,7 @@ def test_create_create_transaction_multiple_io(user_output, user2_output, user_p 'operation': 'CREATE', 'version': Transaction.VERSION } - tx = Transaction.create([user_pub, user2_pub], + tx = Create.generate([user_pub, user2_pub], [([user_pub], 1), ([user2_pub], 1)], metadata={'message': 'hello'}).to_dict() tx.pop('id') @@ -742,7 +744,7 @@ def test_validate_multiple_io_create_transaction(user_pub, user_priv, from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model - tx = Transaction.create([user_pub, user2_pub], + tx = Create.generate([user_pub, user2_pub], [([user_pub], 1), ([user2_pub], 1)], metadata={'message': 'hello'}) tx = tx.sign([user_priv, user2_priv]) @@ -774,7 +776,7 @@ def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub, 'operation': 'CREATE', 'version': Transaction.VERSION } - tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)], + tx = Create.generate([user_pub], [([user_pub, user2_pub], 1)], metadata=data, asset=data) tx_dict = tx.to_dict() tx_dict.pop('id') @@ -788,7 +790,7 @@ def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub, from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model - tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)], + tx = Create.generate([user_pub], [([user_pub, user2_pub], 1)], metadata=data) tx = tx.sign([user_priv]) assert tx.inputs_valid() is True @@ -800,22 +802,22 @@ def test_create_create_transaction_with_invalid_parameters(user_pub): from planetmint.transactions.common.transaction import Transaction with raises(TypeError): - Transaction.create('not a list') + Create.generate('not a list') with raises(TypeError): - Transaction.create([], 'not a list') + Create.generate([], 'not a list') with raises(ValueError): - Transaction.create([], [user_pub]) + Create.generate([], [user_pub]) with raises(ValueError): - Transaction.create([user_pub], []) + Create.generate([user_pub], []) with raises(ValueError): - Transaction.create([user_pub], [user_pub]) + Create.generate([user_pub], [user_pub]) with raises(ValueError): - Transaction.create([user_pub], [([user_pub],)]) + Create.generate([user_pub], [([user_pub],)]) with raises(TypeError): - Transaction.create([user_pub], [([user_pub], 1)], + Create.generate([user_pub], [([user_pub], 1)], metadata='not a dict or none') with raises(TypeError): - Transaction.create([user_pub], + Create.generate([user_pub], [([user_pub], 1)], asset='not a dict or none') @@ -858,7 +860,7 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, 'version': Transaction.VERSION } inputs = tx.to_inputs([0]) - transfer_tx = Transaction.transfer(inputs, [([user2_pub], 1)], + transfer_tx = Transfer.generate(inputs, [([user2_pub], 1)], asset_id=tx.id) transfer_tx = transfer_tx.sign([user_priv]) transfer_tx = transfer_tx.to_dict() @@ -889,7 +891,7 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv, asset_definition): from planetmint.transactions.common.transaction import Transaction - tx = Transaction.create([user_pub], [([user_pub], 1), ([user2_pub], 1)], + tx = Create.generate([user_pub], [([user_pub], 1), ([user2_pub], 1)], metadata={'message': 'hello'}) tx = tx.sign([user_priv]) @@ -921,7 +923,7 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv, 'version': Transaction.VERSION } - transfer_tx = Transaction.transfer(tx.to_inputs(), + transfer_tx = Transfer.generate(tx.to_inputs(), [([user2_pub], 1), ([user2_pub], 1)], asset_id=tx.id) transfer_tx = transfer_tx.sign([user_priv, user2_priv]) @@ -944,22 +946,22 @@ def test_create_transfer_with_invalid_parameters(tx, user_pub): from planetmint.transactions.common.transaction import Transaction with raises(TypeError): - Transaction.transfer({}, [], tx.id) + Transfer.generate({}, [], tx.id) with raises(ValueError): - Transaction.transfer([], [], tx.id) + Transfer.generate([], [], tx.id) with raises(TypeError): - Transaction.transfer(['fulfillment'], {}, tx.id) + Transfer.generate(['fulfillment'], {}, tx.id) with raises(ValueError): - Transaction.transfer(['fulfillment'], [], tx.id) + Transfer.generate(['fulfillment'], [], tx.id) with raises(ValueError): - Transaction.transfer(['fulfillment'], [user_pub], tx.id) + Transfer.generate(['fulfillment'], [user_pub], tx.id) with raises(ValueError): - Transaction.transfer(['fulfillment'], [([user_pub],)], tx.id) + Transfer.generate(['fulfillment'], [([user_pub],)], tx.id) with raises(TypeError): - Transaction.transfer(['fulfillment'], [([user_pub], 1)], + Transfer.generate(['fulfillment'], [([user_pub], 1)], tx.id, metadata='not a dict or none') with raises(TypeError): - Transaction.transfer(['fulfillment'], [([user_pub], 1)], + Transfer.generate(['fulfillment'], [([user_pub], 1)], ['not a string']) @@ -1020,7 +1022,7 @@ def test_output_from_dict_invalid_amount(user_output): def test_unspent_outputs_property(merlin, alice, bob, carol): from planetmint.transactions.common.transaction import Transaction - tx = Transaction.create( + tx = Create.generate( [merlin.public_key], [([alice.public_key], 1), ([bob.public_key], 2), diff --git a/tests/conftest.py b/tests/conftest.py index f553538..8216072 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -285,9 +285,9 @@ def mock_get_validators(network_validators): @pytest.fixture def create_tx(alice, user_pk): - from planetmint.models import Transaction + from planetmint.transactions.types.assets.create import Create name = f'I am created by the create_tx fixture. My random identifier is {random.random()}.' - return Transaction.create([alice.public_key], [([user_pk], 1)], asset={'name': name}) + return Create.generate([alice.public_key], [([user_pk], 1)], asset={'name': name}) @pytest.fixture @@ -304,17 +304,17 @@ def posted_create_tx(b, signed_create_tx): @pytest.fixture def signed_transfer_tx(signed_create_tx, user_pk, user_sk): - from planetmint.models import Transaction + from planetmint.transactions.types.assets.transfer import Transfer inputs = signed_create_tx.to_inputs() - tx = Transaction.transfer(inputs, [([user_pk], 1)], asset_id=signed_create_tx.id) + tx = Transfer.generate(inputs, [([user_pk], 1)], asset_id=signed_create_tx.id) return tx.sign([user_sk]) @pytest.fixture def double_spend_tx(signed_create_tx, carol_pubkey, user_sk): - from planetmint.models import Transaction + from planetmint.transactions.types.assets.transfer import Transfer inputs = signed_create_tx.to_inputs() - tx = Transaction.transfer( + tx = Transfer.generate( inputs, [([carol_pubkey], 1)], asset_id=signed_create_tx.id) return tx.sign([user_sk]) @@ -326,11 +326,11 @@ def _get_height(b): @pytest.fixture def inputs(user_pk, b, alice): - from planetmint.models import Transaction + from planetmint.transactions.types.assets.create import Create # create blocks with transactions for `USER` to spend for height in range(1, 4): transactions = [ - Transaction.create( + Create.generate( [alice.public_key], [([user_pk], 1)], metadata={'msg': random.random()}, diff --git a/tests/db/test_bigchain_api.py b/tests/db/test_planetmint_api.py similarity index 89% rename from tests/db/test_bigchain_api.py rename to tests/db/test_planetmint_api.py index 9724cb6..0f08358 100644 --- a/tests/db/test_bigchain_api.py +++ b/tests/db/test_planetmint_api.py @@ -4,6 +4,8 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 from unittest.mock import patch +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer import pytest from base58 import b58decode @@ -18,15 +20,15 @@ class TestBigchainApi(object): from planetmint.transactions.common.exceptions import DoubleSpend from planetmint.exceptions import CriticalDoubleSpend - tx = Transaction.create([alice.public_key], [([alice.public_key], 1)]) + tx = Create.generate([alice.public_key], [([alice.public_key], 1)]) tx = tx.sign([alice.private_key]) b.store_bulk_transactions([tx]) - transfer_tx = Transaction.transfer(tx.to_inputs(), [([alice.public_key], 1)], + transfer_tx = Transfer.generate(tx.to_inputs(), [([alice.public_key], 1)], asset_id=tx.id) transfer_tx = transfer_tx.sign([alice.private_key]) - transfer_tx2 = Transaction.transfer(tx.to_inputs(), [([alice.public_key], 2)], + transfer_tx2 = Transfer.generate(tx.to_inputs(), [([alice.public_key], 2)], asset_id=tx.id) transfer_tx2 = transfer_tx2.sign([alice.private_key]) @@ -47,7 +49,7 @@ class TestBigchainApi(object): from planetmint.models import Transaction from planetmint.backend.exceptions import OperationError - tx = Transaction.create([alice.public_key], [([alice.public_key], 1)]) + tx = Create.generate([alice.public_key], [([alice.public_key], 1)]) tx = tx.sign([alice.private_key]) b.store_bulk_transactions([tx]) @@ -64,11 +66,11 @@ class TestBigchainApi(object): asset3 = {'msg': 'Planetmint 3'} # create the transactions - tx1 = Transaction.create([alice.public_key], [([alice.public_key], 1)], + tx1 = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset1).sign([alice.private_key]) - tx2 = Transaction.create([alice.public_key], [([alice.public_key], 1)], + tx2 = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset2).sign([alice.private_key]) - tx3 = Transaction.create([alice.public_key], [([alice.public_key], 1)], + tx3 = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset3).sign([alice.private_key]) # write the transactions to the DB @@ -89,7 +91,7 @@ class TestBigchainApi(object): input = Input(Ed25519Sha256(public_key=b58decode(user_pk)), [user_pk], TransactionLink('somethingsomething', 0)) - tx = Transaction.transfer([input], [([user_pk], 1)], + tx = Transfer.generate([input], [([user_pk], 1)], asset_id='mock_asset_link') with pytest.raises(InputDoesNotExist): tx.validate(b) @@ -99,7 +101,7 @@ class TestBigchainApi(object): asset1 = {'msg': 'Planetmint 1'} - tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset1).sign([alice.private_key]) b.store_bulk_transactions([tx]) @@ -133,7 +135,7 @@ class TestTransactionValidation(object): input_tx = b.fastquery.get_outputs_by_public_key(user_pk).pop() input_transaction = b.get_transaction(input_tx.txid) sk, pk = generate_key_pair() - tx = Transaction.create([pk], [([user_pk], 1)]) + tx = Create.generate([pk], [([user_pk], 1)]) tx.operation = 'TRANSFER' tx.asset = {'id': input_transaction.id} tx.inputs[0].fulfills = input_tx @@ -164,7 +166,7 @@ class TestMultipleInputs(object): tx_link = b.fastquery.get_outputs_by_public_key(user_pk).pop() input_tx = b.get_transaction(tx_link.txid) inputs = input_tx.to_inputs() - tx = Transaction.transfer(inputs, [([user2_pk], 1)], + tx = Transfer.generate(inputs, [([user2_pk], 1)], asset_id=input_tx.id) tx = tx.sign([user_sk]) @@ -185,7 +187,7 @@ class TestMultipleInputs(object): tx_link = b.fastquery.get_outputs_by_public_key(user_pk).pop() input_tx = b.get_transaction(tx_link.txid) - tx = Transaction.transfer(input_tx.to_inputs(), + tx = Transfer.generate(input_tx.to_inputs(), [([user2_pk, user3_pk], 1)], asset_id=input_tx.id) tx = tx.sign([user_sk]) @@ -205,7 +207,7 @@ class TestMultipleInputs(object): user2_sk, user2_pk = crypto.generate_key_pair() user3_sk, user3_pk = crypto.generate_key_pair() - tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)]) + tx = Create.generate([alice.public_key], [([user_pk, user2_pk], 1)]) tx = tx.sign([alice.private_key]) b.store_bulk_transactions([tx]) @@ -213,7 +215,7 @@ class TestMultipleInputs(object): input_tx = b.get_transaction(owned_input.txid) inputs = input_tx.to_inputs() - transfer_tx = Transaction.transfer(inputs, [([user3_pk], 1)], + transfer_tx = Transfer.generate(inputs, [([user3_pk], 1)], asset_id=input_tx.id) transfer_tx = transfer_tx.sign([user_sk, user2_sk]) @@ -234,7 +236,7 @@ class TestMultipleInputs(object): user3_sk, user3_pk = crypto.generate_key_pair() user4_sk, user4_pk = crypto.generate_key_pair() - tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)]) + tx = Create.generate([alice.public_key], [([user_pk, user2_pk], 1)]) tx = tx.sign([alice.private_key]) b.store_bulk_transactions([tx]) @@ -242,7 +244,7 @@ class TestMultipleInputs(object): tx_link = b.fastquery.get_outputs_by_public_key(user_pk).pop() tx_input = b.get_transaction(tx_link.txid) - tx = Transaction.transfer(tx_input.to_inputs(), + tx = Transfer.generate(tx_input.to_inputs(), [([user3_pk, user4_pk], 1)], asset_id=tx_input.id) tx = tx.sign([user_sk, user2_sk]) @@ -258,7 +260,7 @@ class TestMultipleInputs(object): user2_sk, user2_pk = crypto.generate_key_pair() - tx = Transaction.create([alice.public_key], [([user_pk], 1)]) + tx = Create.generate([alice.public_key], [([user_pk], 1)]) tx = tx.sign([alice.private_key]) b.store_bulk_transactions([tx]) @@ -267,7 +269,7 @@ class TestMultipleInputs(object): assert owned_inputs_user1 == [TransactionLink(tx.id, 0)] assert owned_inputs_user2 == [] - tx_transfer = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)], + tx_transfer = Transfer.generate(tx.to_inputs(), [([user2_pk], 1)], asset_id=tx.id) tx_transfer = tx_transfer.sign([user_sk]) b.store_bulk_transactions([tx_transfer]) @@ -287,7 +289,7 @@ class TestMultipleInputs(object): user2_sk, user2_pk = crypto.generate_key_pair() # create divisible asset - tx_create = Transaction.create([alice.public_key], [([user_pk], 1), ([user_pk], 1)]) + tx_create = Create.generate([alice.public_key], [([user_pk], 1), ([user_pk], 1)]) tx_create_signed = tx_create.sign([alice.private_key]) b.store_bulk_transactions([tx_create_signed]) @@ -301,7 +303,7 @@ class TestMultipleInputs(object): assert owned_inputs_user2 == [] # transfer divisible asset divided in two outputs - tx_transfer = Transaction.transfer(tx_create.to_inputs(), + tx_transfer = Transfer.generate(tx_create.to_inputs(), [([user2_pk], 1), ([user2_pk], 1)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -321,7 +323,7 @@ class TestMultipleInputs(object): user2_sk, user2_pk = crypto.generate_key_pair() user3_sk, user3_pk = crypto.generate_key_pair() - tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)]) + tx = Create.generate([alice.public_key], [([user_pk, user2_pk], 1)]) tx = tx.sign([alice.private_key]) b.store_bulk_transactions([tx]) @@ -333,7 +335,7 @@ class TestMultipleInputs(object): assert owned_inputs_user1 == owned_inputs_user2 assert owned_inputs_user1 == expected_owned_inputs_user1 - tx = Transaction.transfer(tx.to_inputs(), [([user3_pk], 1)], + tx = Transfer.generate(tx.to_inputs(), [([user3_pk], 1)], asset_id=tx.id) tx = tx.sign([user_sk, user2_sk]) b.store_bulk_transactions([tx]) @@ -351,7 +353,7 @@ class TestMultipleInputs(object): user2_sk, user2_pk = crypto.generate_key_pair() - tx = Transaction.create([alice.public_key], [([user_pk], 1)]) + tx = Create.generate([alice.public_key], [([user_pk], 1)]) tx = tx.sign([alice.private_key]) b.store_bulk_transactions([tx]) @@ -363,7 +365,7 @@ class TestMultipleInputs(object): assert spent_inputs_user1 is None # create a transaction and send it - tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)], + tx = Transfer.generate(tx.to_inputs(), [([user2_pk], 1)], asset_id=tx.id) tx = tx.sign([user_sk]) b.store_bulk_transactions([tx]) @@ -379,7 +381,7 @@ class TestMultipleInputs(object): user2_sk, user2_pk = crypto.generate_key_pair() # create a divisible asset with 3 outputs - tx_create = Transaction.create([alice.public_key], + tx_create = Create.generate([alice.public_key], [([user_pk], 1), ([user_pk], 1), ([user_pk], 1)]) @@ -393,7 +395,7 @@ class TestMultipleInputs(object): assert b.get_spent(input_tx.txid, input_tx.output) is None # transfer the first 2 inputs - tx_transfer = Transaction.transfer(tx_create.to_inputs()[:2], + tx_transfer = Transfer.generate(tx_create.to_inputs()[:2], [([user2_pk], 1), ([user2_pk], 1)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([user_sk]) @@ -418,7 +420,7 @@ class TestMultipleInputs(object): transactions = [] for i in range(3): payload = {'somedata': i} - tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)], + tx = Create.generate([alice.public_key], [([user_pk, user2_pk], 1)], payload) tx = tx.sign([alice.private_key]) transactions.append(tx) @@ -431,7 +433,7 @@ class TestMultipleInputs(object): assert b.get_spent(input_tx.txid, input_tx.output) is None # create a transaction - tx = Transaction.transfer(transactions[0].to_inputs(), + tx = Transfer.generate(transactions[0].to_inputs(), [([user3_pk], 1)], asset_id=transactions[0].id) tx = tx.sign([user_sk, user2_sk]) @@ -500,7 +502,7 @@ def test_cant_spend_same_input_twice_in_tx(b, alice): from planetmint.transactions.common.exceptions import DoubleSpend # create a divisible asset - tx_create = Transaction.create([alice.public_key], [([alice.public_key], 100)]) + tx_create = Create.generate([alice.public_key], [([alice.public_key], 100)]) tx_create_signed = tx_create.sign([alice.private_key]) assert b.validate_transaction(tx_create_signed) == tx_create_signed @@ -508,7 +510,7 @@ def test_cant_spend_same_input_twice_in_tx(b, alice): # Create a transfer transaction with duplicated fulfillments dup_inputs = tx_create.to_inputs() + tx_create.to_inputs() - tx_transfer = Transaction.transfer(dup_inputs, [([alice.public_key], 200)], + tx_transfer = Transfer.generate(dup_inputs, [([alice.public_key], 200)], asset_id=tx_create.id) tx_transfer_signed = tx_transfer.sign([alice.private_key]) with pytest.raises(DoubleSpend): @@ -524,7 +526,7 @@ def test_transaction_unicode(b, alice): beer_python = {'beer': '\N{BEER MUG}'} beer_json = '{"beer":"\N{BEER MUG}"}' - tx = (Transaction.create([alice.public_key], [([alice.public_key], 100)], beer_python) + tx = (Create.generate([alice.public_key], [([alice.public_key], 100)], beer_python) ).sign([alice.private_key]) tx_1 = copy.deepcopy(tx) diff --git a/tests/tendermint/test_core.py b/tests/tendermint/test_core.py index 581fbe9..c8e7942 100644 --- a/tests/tendermint/test_core.py +++ b/tests/tendermint/test_core.py @@ -4,6 +4,8 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 import json +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer import pytest import random @@ -208,7 +210,7 @@ def test_check_tx__signed_create_is_ok(b): alice = generate_key_pair() bob = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([bob.public_key], 1)])\ .sign([alice.private_key]) @@ -225,7 +227,7 @@ def test_check_tx__unsigned_create_is_error(b): alice = generate_key_pair() bob = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([bob.public_key], 1)]) app = App(b) @@ -243,7 +245,7 @@ def test_deliver_tx__valid_create_updates_db_and_emits_event(b, init_chain_reque bob = generate_key_pair() events = mp.Queue() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([bob.public_key], 1)])\ .sign([alice.private_key]) @@ -279,7 +281,7 @@ def test_deliver_tx__double_spend_fails(b, init_chain_request): alice = generate_key_pair() bob = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([bob.public_key], 1)])\ .sign([alice.private_key]) @@ -319,7 +321,7 @@ def test_deliver_transfer_tx__double_spend_fails(b, init_chain_request): 'msg': 'live long and prosper' } - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset)\ .sign([alice.private_key]) @@ -327,7 +329,7 @@ def test_deliver_transfer_tx__double_spend_fails(b, init_chain_request): result = app.deliver_tx(encode_tx_to_bytes(tx)) assert result.code == OkCode - tx_transfer = Transaction.transfer(tx.to_inputs(), + tx_transfer = Transfer.generate(tx.to_inputs(), [([bob.public_key], 1)], asset_id=tx.id)\ .sign([alice.private_key]) @@ -335,7 +337,7 @@ def test_deliver_transfer_tx__double_spend_fails(b, init_chain_request): result = app.deliver_tx(encode_tx_to_bytes(tx_transfer)) assert result.code == OkCode - double_spend = Transaction.transfer(tx.to_inputs(), + double_spend = Transfer.generate(tx.to_inputs(), [([carly.public_key], 1)], asset_id=tx.id)\ .sign([alice.private_key]) @@ -384,7 +386,7 @@ def test_store_pre_commit_state_in_end_block(b, alice, init_chain_request): from planetmint.backend import query from planetmint.models import Transaction - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset={'msg': 'live long and prosper'})\ .sign([alice.private_key]) diff --git a/tests/tendermint/test_fastquery.py b/tests/tendermint/test_fastquery.py index 61f8ac9..d79d511 100644 --- a/tests/tendermint/test_fastquery.py +++ b/tests/tendermint/test_fastquery.py @@ -6,7 +6,8 @@ import pytest from planetmint.transactions.common.transaction import TransactionLink -from planetmint.models import Transaction +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer pytestmark = pytest.mark.bdb @@ -14,9 +15,9 @@ pytestmark = pytest.mark.bdb @pytest.fixture def txns(b, user_pk, user_sk, user2_pk, user2_sk): - txs = [Transaction.create([user_pk], [([user2_pk], 1)]).sign([user_sk]), - Transaction.create([user2_pk], [([user_pk], 1)]).sign([user2_sk]), - Transaction.create([user_pk], [([user_pk], 1), ([user2_pk], 1)]) + txs = [Create.generate([user_pk], [([user2_pk], 1)]).sign([user_sk]), + Create.generate([user2_pk], [([user_pk], 1)]).sign([user2_sk]), + Create.generate([user_pk], [([user_pk], 1), ([user2_pk], 1)]) .sign([user_sk])] b.store_bulk_transactions(txs) return txs @@ -35,12 +36,12 @@ def test_get_outputs_by_public_key(b, user_pk, user2_pk, txns): def test_filter_spent_outputs(b, user_pk, user_sk): out = [([user_pk], 1)] - tx1 = Transaction.create([user_pk], out * 2) + tx1 = Create.generate([user_pk], out * 2) tx1.sign([user_sk]) inputs = tx1.to_inputs() - tx2 = Transaction.transfer([inputs[0]], out, tx1.id) + tx2 = Transfer.generate([inputs[0]], out, tx1.id) tx2.sign([user_sk]) # tx2 produces a new unspent. inputs[1] remains unspent. @@ -57,12 +58,12 @@ def test_filter_spent_outputs(b, user_pk, user_sk): def test_filter_unspent_outputs(b, user_pk, user_sk): out = [([user_pk], 1)] - tx1 = Transaction.create([user_pk], out * 2) + tx1 = Create.generate([user_pk], out * 2) tx1.sign([user_sk]) inputs = tx1.to_inputs() - tx2 = Transaction.transfer([inputs[0]], out, tx1.id) + tx2 = Transfer.generate([inputs[0]], out, tx1.id) tx2.sign([user_sk]) # tx2 produces a new unspent. input[1] remains unspent. @@ -80,13 +81,13 @@ def test_outputs_query_key_order(b, user_pk, user_sk, user2_pk, user2_sk): from planetmint import backend from planetmint.backend import connect - tx1 = Transaction.create([user_pk], + tx1 = Create.generate([user_pk], [([user_pk], 3), ([user_pk], 2), ([user_pk], 1)])\ .sign([user_sk]) b.store_bulk_transactions([tx1]) inputs = tx1.to_inputs() - tx2 = Transaction.transfer([inputs[1]], [([user2_pk], 2)], tx1.id).sign([user_sk]) + tx2 = Transfer.generate([inputs[1]], [([user2_pk], 2)], tx1.id).sign([user_sk]) assert tx2.validate(b) tx2_dict = tx2.to_dict() diff --git a/tests/tendermint/test_integration.py b/tests/tendermint/test_integration.py index 45b4db1..15a6eac 100644 --- a/tests/tendermint/test_integration.py +++ b/tests/tendermint/test_integration.py @@ -4,6 +4,7 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 import codecs +from planetmint.transactions.types.assets.create import Create from tendermint.abci import types_pb2 as types import json @@ -23,7 +24,6 @@ def test_app(b, eventqueue_fixture, init_chain_request): from planetmint import App from planetmint.tendermint_utils import calculate_hash from planetmint.transactions.common.crypto import generate_key_pair - from planetmint.models import Transaction app = App(b, eventqueue_fixture) p = ProtocolHandler(app) @@ -49,7 +49,7 @@ def test_app(b, eventqueue_fixture, init_chain_request): alice = generate_key_pair() bob = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([bob.public_key], 1)])\ .sign([alice.private_key]) etxn = json.dumps(tx.to_dict()).encode('utf8') @@ -118,7 +118,7 @@ def test_post_transaction_responses(tendermint_ws_url, b): alice = generate_key_pair() bob = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=None)\ .sign([alice.private_key]) diff --git a/tests/tendermint/test_lib.py b/tests/tendermint/test_lib.py index 55fd2be..211ece9 100644 --- a/tests/tendermint/test_lib.py +++ b/tests/tendermint/test_lib.py @@ -5,6 +5,8 @@ import os from unittest.mock import patch +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer try: @@ -25,7 +27,6 @@ from planetmint.lib import Block @pytest.mark.bdb def test_asset_is_separated_from_transaciton(b): import copy - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() @@ -40,7 +41,7 @@ def test_asset_is_separated_from_transaciton(b): 'tell a lie', 'hurt you']} - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([bob.public_key], 1)], metadata=None, asset=asset)\ @@ -81,11 +82,10 @@ def test_get_empty_block(_0, _1, b): def test_validation_error(b): - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=None)\ .sign([alice.private_key]).to_dict() @@ -96,12 +96,11 @@ def test_validation_error(b): @patch('requests.post') def test_write_and_post_transaction(mock_post, b): - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair from planetmint.tendermint_utils import encode_transaction alice = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=None)\ .sign([alice.private_key]).to_dict() @@ -123,10 +122,9 @@ def test_write_and_post_transaction(mock_post, b): BROADCAST_TX_COMMIT ]) def test_post_transaction_valid_modes(mock_post, b, mode): - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=None) \ .sign([alice.private_key]).to_dict() @@ -138,11 +136,10 @@ def test_post_transaction_valid_modes(mock_post, b, mode): def test_post_transaction_invalid_mode(b): - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair from planetmint.transactions.common.exceptions import ValidationError alice = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=None) \ .sign([alice.private_key]).to_dict() @@ -354,28 +351,27 @@ def test_get_utxoset_merkle_root(b, utxoset): @pytest.mark.bdb def test_get_spent_transaction_critical_double_spend(b, alice, bob, carol): - from planetmint.models import Transaction from planetmint.exceptions import CriticalDoubleSpend from planetmint.transactions.common.exceptions import DoubleSpend asset = {'test': 'asset'} - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset)\ .sign([alice.private_key]) - tx_transfer = Transaction.transfer(tx.to_inputs(), + tx_transfer = Transfer.generate(tx.to_inputs(), [([bob.public_key], 1)], asset_id=tx.id)\ .sign([alice.private_key]) - double_spend = Transaction.transfer(tx.to_inputs(), + double_spend = Transfer.generate(tx.to_inputs(), [([carol.public_key], 1)], asset_id=tx.id)\ .sign([alice.private_key]) - same_input_double_spend = Transaction.transfer(tx.to_inputs() + tx.to_inputs(), + same_input_double_spend = Transfer.generate(tx.to_inputs() + tx.to_inputs(), [([bob.public_key], 1)], asset_id=tx.id)\ .sign([alice.private_key]) @@ -404,15 +400,14 @@ def test_get_spent_transaction_critical_double_spend(b, alice, bob, carol): def test_validation_with_transaction_buffer(b): from planetmint.transactions.common.crypto import generate_key_pair - from planetmint.models import Transaction priv_key, pub_key = generate_key_pair() - create_tx = Transaction.create([pub_key], [([pub_key], 10)]).sign([priv_key]) - transfer_tx = Transaction.transfer(create_tx.to_inputs(), + create_tx = Create.generate([pub_key], [([pub_key], 10)]).sign([priv_key]) + transfer_tx = Transfer.generate(create_tx.to_inputs(), [([pub_key], 10)], asset_id=create_tx.id).sign([priv_key]) - double_spend = Transaction.transfer(create_tx.to_inputs(), + double_spend = Transfer.generate(create_tx.to_inputs(), [([pub_key], 10)], asset_id=create_tx.id).sign([priv_key]) @@ -459,21 +454,20 @@ def test_migrate_abci_chain_generates_new_chains(b, chain, block_height, @pytest.mark.bdb def test_get_spent_key_order(b, user_pk, user_sk, user2_pk, user2_sk): from planetmint import backend - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair from planetmint.transactions.common.exceptions import DoubleSpend alice = generate_key_pair() bob = generate_key_pair() - tx1 = Transaction.create([user_pk], + tx1 = Create.generate([user_pk], [([alice.public_key], 3), ([user_pk], 2)], asset=None)\ .sign([user_sk]) b.store_bulk_transactions([tx1]) inputs = tx1.to_inputs() - tx2 = Transaction.transfer([inputs[1]], [([user2_pk], 2)], tx1.id).sign([user_sk]) + tx2 = Transfer.generate([inputs[1]], [([user2_pk], 2)], tx1.id).sign([user_sk]) assert tx2.validate(b) tx2_dict = tx2.to_dict() @@ -483,7 +477,7 @@ def test_get_spent_key_order(b, user_pk, user_sk, user2_pk, user2_sk): backend.query.store_transactions(b.connection, [tx2_dict]) - tx3 = Transaction.transfer([inputs[1]], [([bob.public_key], 2)], tx1.id).sign([user_sk]) + tx3 = Transfer.generate([inputs[1]], [([bob.public_key], 2)], tx1.id).sign([user_sk]) with pytest.raises(DoubleSpend): tx3.validate(b) diff --git a/tests/test_core.py b/tests/test_core.py index 140cd22..d9a6efa 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -4,6 +4,8 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 import json +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer import pytest import random @@ -208,7 +210,7 @@ def test_check_tx__signed_create_is_ok(b): alice = generate_key_pair() bob = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([bob.public_key], 1)])\ .sign([alice.private_key]) @@ -225,7 +227,7 @@ def test_check_tx__unsigned_create_is_error(b): alice = generate_key_pair() bob = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([bob.public_key], 1)]) app = App(b) @@ -243,7 +245,7 @@ def test_deliver_tx__valid_create_updates_db_and_emits_event(b, init_chain_reque bob = generate_key_pair() events = mp.Queue() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([bob.public_key], 1)])\ .sign([alice.private_key]) @@ -279,7 +281,7 @@ def test_deliver_tx__double_spend_fails(b, eventqueue_fixture, init_chain_reques alice = generate_key_pair() bob = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([bob.public_key], 1)])\ .sign([alice.private_key]) @@ -319,7 +321,7 @@ def test_deliver_transfer_tx__double_spend_fails(b, init_chain_request): 'msg': 'live long and prosper' } - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset)\ .sign([alice.private_key]) @@ -327,7 +329,7 @@ def test_deliver_transfer_tx__double_spend_fails(b, init_chain_request): result = app.deliver_tx(encode_tx_to_bytes(tx)) assert result.code == OkCode - tx_transfer = Transaction.transfer(tx.to_inputs(), + tx_transfer = Transfer.generate(tx.to_inputs(), [([bob.public_key], 1)], asset_id=tx.id)\ .sign([alice.private_key]) @@ -335,7 +337,7 @@ def test_deliver_transfer_tx__double_spend_fails(b, init_chain_request): result = app.deliver_tx(encode_tx_to_bytes(tx_transfer)) assert result.code == OkCode - double_spend = Transaction.transfer(tx.to_inputs(), + double_spend = Transfer.generate(tx.to_inputs(), [([carly.public_key], 1)], asset_id=tx.id)\ .sign([alice.private_key]) @@ -384,7 +386,7 @@ def test_store_pre_commit_state_in_end_block(b, alice, init_chain_request): from planetmint.backend import query from planetmint.models import Transaction - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset={'msg': 'live long and prosper'})\ .sign([alice.private_key]) diff --git a/tests/test_parallel_validation.py b/tests/test_parallel_validation.py index df2a39d..29e8864 100644 --- a/tests/test_parallel_validation.py +++ b/tests/test_parallel_validation.py @@ -6,8 +6,8 @@ import pytest from planetmint.transactions.common.crypto import generate_key_pair -from planetmint.models import Transaction - +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer pytestmark = pytest.mark.tendermint @@ -16,8 +16,8 @@ def generate_create_and_transfer(keypair=None): if not keypair: keypair = generate_key_pair() priv_key, pub_key = keypair - create_tx = Transaction.create([pub_key], [([pub_key], 10)]).sign([priv_key]) - transfer_tx = Transaction.transfer( + create_tx = Create.generate([pub_key], [([pub_key], 10)]).sign([priv_key]) + transfer_tx = Transfer.generate( create_tx.to_inputs(), [([pub_key], 10)], asset_id=create_tx.id).sign([priv_key]) @@ -30,7 +30,7 @@ def test_validation_worker_process_multiple_transactions(b): keypair = generate_key_pair() create_tx, transfer_tx = generate_create_and_transfer(keypair) - double_spend = Transaction.transfer( + double_spend = Transfer.generate( create_tx.to_inputs(), [([keypair.public_key], 10)], asset_id=create_tx.id).sign([keypair.private_key]) diff --git a/tests/test_txlist.py b/tests/test_txlist.py index 50cf55c..8475be2 100644 --- a/tests/test_txlist.py +++ b/tests/test_txlist.py @@ -12,18 +12,19 @@ import pytest @pytest.fixture def txlist(b, user_pk, user2_pk, user_sk, user2_sk): - from planetmint.models import Transaction + from planetmint.transactions.types.assets.create import Create + from planetmint.transactions.types.assets.transfer import Transfer # Create two CREATE transactions - create1 = Transaction.create([user_pk], [([user2_pk], 6)]) \ + create1 = Create.generate([user_pk], [([user2_pk], 6)]) \ .sign([user_sk]) - create2 = Transaction.create([user2_pk], + create2 = Create.generate([user2_pk], [([user2_pk], 5), ([user_pk], 5)]) \ .sign([user2_sk]) # Create a TRANSFER transactions - transfer1 = Transaction.transfer(create1.to_inputs(), + transfer1 = Transfer.generate(create1.to_inputs(), [([user_pk], 8)], create1.id).sign([user2_sk]) diff --git a/tests/web/test_assets.py b/tests/web/test_assets.py index 9c632ef..58136c3 100644 --- a/tests/web/test_assets.py +++ b/tests/web/test_assets.py @@ -4,6 +4,7 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 import pytest +from planetmint.transactions.types.assets.create import Create ASSETS_ENDPOINT = '/api/v1/assets/' @@ -31,7 +32,7 @@ def test_get_assets_tendermint(client, b, alice): # create asset asset = {'msg': 'abc'} - tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset).sign([alice.private_key]) b.store_bulk_transactions([tx]) @@ -53,9 +54,9 @@ def test_get_assets_limit_tendermint(client, b, alice): # create two assets asset1 = {'msg': 'abc 1'} asset2 = {'msg': 'abc 2'} - tx1 = Transaction.create([alice.public_key], [([alice.public_key], 1)], + tx1 = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset1).sign([alice.private_key]) - tx2 = Transaction.create([alice.public_key], [([alice.public_key], 1)], + tx2 = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset2).sign([alice.private_key]) b.store_bulk_transactions([tx1]) diff --git a/tests/web/test_block_tendermint.py b/tests/web/test_block_tendermint.py index 2accbce..7fb034d 100644 --- a/tests/web/test_block_tendermint.py +++ b/tests/web/test_block_tendermint.py @@ -5,7 +5,7 @@ import pytest -from planetmint.models import Transaction +from planetmint.transactions.types.assets.create import Create from planetmint.lib import Block BLOCKS_ENDPOINT = '/api/v1/blocks/' @@ -15,7 +15,7 @@ BLOCKS_ENDPOINT = '/api/v1/blocks/' @pytest.mark.usefixtures('inputs') def test_get_block_endpoint(b, client, alice): import copy - tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset={'cycle': 'hero'}) + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset={'cycle': 'hero'}) tx = tx.sign([alice.private_key]) # with store_bulk_transactions we use `insert_many` where PyMongo @@ -48,7 +48,7 @@ def test_get_block_returns_404_if_not_found(client): @pytest.mark.bdb def test_get_block_containing_transaction(b, client, alice): - tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset={'cycle': 'hero'}) + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset={'cycle': 'hero'}) tx = tx.sign([alice.private_key]) b.store_bulk_transactions([tx]) diff --git a/tests/web/test_metadata.py b/tests/web/test_metadata.py index d9301f3..9e2acf2 100644 --- a/tests/web/test_metadata.py +++ b/tests/web/test_metadata.py @@ -4,6 +4,7 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 import pytest +from planetmint.transactions.types.assets.create import Create METADATA_ENDPOINT = '/api/v1/metadata/' @@ -22,7 +23,6 @@ def test_get_metadata_with_missing_text_search(client): @pytest.mark.bdb def test_get_metadata_tendermint(client, b, alice): - from planetmint.models import Transaction # test returns empty list when no assets are found res = client.get(METADATA_ENDPOINT + '?search=abc') @@ -32,7 +32,7 @@ def test_get_metadata_tendermint(client, b, alice): # create asset asset = {'msg': 'abc'} metadata = {'key': 'my_meta'} - tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], metadata=metadata, + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], metadata=metadata, asset=asset).sign([alice.private_key]) b.store_bulk_transactions([tx]) @@ -49,18 +49,17 @@ def test_get_metadata_tendermint(client, b, alice): @pytest.mark.bdb def test_get_metadata_limit_tendermint(client, b, alice): - from planetmint.models import Transaction # create two assets asset1 = {'msg': 'abc 1'} meta1 = {'key': 'meta 1'} - tx1 = Transaction.create([alice.public_key], [([alice.public_key], 1)], metadata=meta1, + tx1 = Create.generate([alice.public_key], [([alice.public_key], 1)], metadata=meta1, asset=asset1).sign([alice.private_key]) b.store_bulk_transactions([tx1]) asset2 = {'msg': 'abc 2'} meta2 = {'key': 'meta 2'} - tx2 = Transaction.create([alice.public_key], [([alice.public_key], 1)], metadata=meta2, + tx2 = Create.generate([alice.public_key], [([alice.public_key], 1)], metadata=meta2, asset=asset2).sign([alice.private_key]) b.store_bulk_transactions([tx2]) diff --git a/tests/web/test_transactions.py b/tests/web/test_transactions.py index 11846e4..109146e 100644 --- a/tests/web/test_transactions.py +++ b/tests/web/test_transactions.py @@ -15,6 +15,8 @@ except ImportError: from sha3 import sha3_256 from planetmint.transactions.common import crypto +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer from planetmint.transactions.common.transaction_mode_types import ( BROADCAST_TX_COMMIT, BROADCAST_TX_ASYNC, BROADCAST_TX_SYNC) @@ -38,10 +40,9 @@ def test_get_transaction_returns_404_if_not_found(client): @pytest.mark.abci def test_post_create_transaction_endpoint(b, client): - from planetmint.models import Transaction user_priv, user_pub = crypto.generate_key_pair() - tx = Transaction.create([user_pub], [([user_pub], 1)]) + tx = Create.generate([user_pub], [([user_pub], 1)]) tx = tx.sign([user_priv]) res = client.post(TX_ENDPOINT, data=json.dumps(tx.to_dict())) @@ -67,7 +68,6 @@ def test_post_create_transaction_endpoint(b, client): @pytest.mark.language def test_post_create_transaction_with_language(b, client, nested, language, expected_status_code): - from planetmint.models import Transaction from planetmint.backend.localmongodb.connection import LocalMongoDBConnection if isinstance(b.connection, LocalMongoDBConnection): @@ -79,7 +79,7 @@ def test_post_create_transaction_with_language(b, client, nested, language, else: asset = lang_obj - tx = Transaction.create([user_pub], [([user_pub], 1)], + tx = Create.generate([user_pub], [([user_pub], 1)], asset=asset) tx = tx.sign([user_priv]) res = client.post(TX_ENDPOINT, data=json.dumps(tx.to_dict())) @@ -105,16 +105,15 @@ def test_post_create_transaction_with_language(b, client, nested, language, ]) def test_post_create_transaction_with_invalid_key(b, client, field, value, err_key, expected_status_code): - from planetmint.models import Transaction from planetmint.backend.localmongodb.connection import LocalMongoDBConnection user_priv, user_pub = crypto.generate_key_pair() if isinstance(b.connection, LocalMongoDBConnection): if field == 'asset': - tx = Transaction.create([user_pub], [([user_pub], 1)], + tx = Create.generate([user_pub], [([user_pub], 1)], asset=value) elif field == 'metadata': - tx = Transaction.create([user_pub], [([user_pub], 1)], + tx = Create.generate([user_pub], [([user_pub], 1)], metadata=value) tx = tx.sign([user_priv]) res = client.post(TX_ENDPOINT, data=json.dumps(tx.to_dict())) @@ -133,10 +132,9 @@ def test_post_create_transaction_with_invalid_key(b, client, field, value, @patch('planetmint.web.views.base.logger') def test_post_create_transaction_with_invalid_id(mock_logger, b, client): from planetmint.transactions.common.exceptions import InvalidHash - from planetmint.models import Transaction user_priv, user_pub = crypto.generate_key_pair() - tx = Transaction.create([user_pub], [([user_pub], 1)]) + tx = Create.generate([user_pub], [([user_pub], 1)]) tx = tx.sign([user_priv]).to_dict() tx['id'] = 'abcd' * 16 @@ -170,10 +168,9 @@ def test_post_create_transaction_with_invalid_signature(mock_logger, b, client): from planetmint.transactions.common.exceptions import InvalidSignature - from planetmint.models import Transaction user_priv, user_pub = crypto.generate_key_pair() - tx = Transaction.create([user_pub], [([user_pub], 1)]).to_dict() + tx = Create.generate([user_pub], [([user_pub], 1)]).to_dict() tx['inputs'][0]['fulfillment'] = 64 * '0' tx['id'] = sha3_256( json.dumps( @@ -219,7 +216,7 @@ def test_post_create_transaction_with_invalid_structure(client): def test_post_create_transaction_with_invalid_schema(mock_logger, client): from planetmint.models import Transaction user_priv, user_pub = crypto.generate_key_pair() - tx = Transaction.create([user_pub], [([user_pub], 1)]).to_dict() + tx = Create.generate([user_pub], [([user_pub], 1)]).to_dict() del tx['version'] ed25519 = Ed25519Sha256(public_key=base58.b58decode(user_pub)) message = json.dumps( @@ -307,9 +304,8 @@ def test_post_invalid_transaction(mock_logger, client, exc, msg, monkeypatch,): @pytest.mark.abci def test_post_transfer_transaction_endpoint(client, user_pk, user_sk, posted_create_tx): - from planetmint.models import Transaction - transfer_tx = Transaction.transfer(posted_create_tx.to_inputs(), + transfer_tx = Transfer.generate(posted_create_tx.to_inputs(), [([user_pk], 1)], asset_id=posted_create_tx.id) transfer_tx = transfer_tx.sign([user_sk]) @@ -324,10 +320,9 @@ def test_post_transfer_transaction_endpoint(client, user_pk, user_sk, posted_cre @pytest.mark.abci def test_post_invalid_transfer_transaction_returns_400(client, user_pk, posted_create_tx): - from planetmint.models import Transaction from planetmint.transactions.common.exceptions import InvalidSignature - transfer_tx = Transaction.transfer(posted_create_tx.to_inputs(), + transfer_tx = Transfer.generate(posted_create_tx.to_inputs(), [([user_pk], 1)], asset_id=posted_create_tx.id) transfer_tx._hash() @@ -342,18 +337,17 @@ def test_post_invalid_transfer_transaction_returns_400(client, user_pk, posted_c @pytest.mark.abci def test_post_wrong_asset_division_transfer_returns_400(b, client, user_pk): - from planetmint.models import Transaction from planetmint.transactions.common.exceptions import AmountError priv_key, pub_key = crypto.generate_key_pair() - create_tx = Transaction.create([pub_key], + create_tx = Create.generate([pub_key], [([pub_key], 10)], asset={'test': 'asset'}).sign([priv_key]) res = client.post(TX_ENDPOINT + '?mode=commit', data=json.dumps(create_tx.to_dict())) assert res.status_code == 202 - transfer_tx = Transaction.transfer(create_tx.to_inputs(), + transfer_tx = Transfer.generate(create_tx.to_inputs(), [([pub_key], 20)], # 20 > 10 asset_id=create_tx.id).sign([priv_key]) res = client.post(TX_ENDPOINT + '?mode=commit', data=json.dumps(transfer_tx.to_dict())) @@ -423,7 +417,6 @@ def test_transactions_get_list_bad(client): ('?mode=commit', BROADCAST_TX_COMMIT), ]) def test_post_transaction_valid_modes(mock_post, client, mode): - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair def _mock_post(*args, **kwargs): @@ -432,7 +425,7 @@ def test_post_transaction_valid_modes(mock_post, client, mode): mock_post.side_effect = _mock_post alice = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=None) \ .sign([alice.private_key]) @@ -444,10 +437,9 @@ def test_post_transaction_valid_modes(mock_post, client, mode): @pytest.mark.abci def test_post_transaction_invalid_mode(client): - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=None) \ .sign([alice.private_key]) diff --git a/tests/web/test_websocket_server.py b/tests/web/test_websocket_server.py index 05b45fc..6846554 100644 --- a/tests/web/test_websocket_server.py +++ b/tests/web/test_websocket_server.py @@ -8,6 +8,8 @@ import json import queue import threading from unittest.mock import patch +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer import pytest @@ -27,10 +29,10 @@ def test_eventify_block_works_with_any_transaction(): alice = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)])\ .sign([alice.private_key]) - tx_transfer = Transaction.transfer(tx.to_inputs(), + tx_transfer = Transfer.generate(tx.to_inputs(), [([alice.public_key], 1)], asset_id=tx.id)\ .sign([alice.private_key]) @@ -142,7 +144,7 @@ async def test_websocket_block_event(b, test_client, loop): from planetmint.transactions.common import crypto user_priv, user_pub = crypto.generate_key_pair() - tx = Transaction.create([user_pub], [([user_pub], 1)]) + tx = Create.generate([user_pub], [([user_pub], 1)]) tx = tx.sign([user_priv]) event_source = asyncio.Queue(loop=loop) @@ -203,7 +205,7 @@ def test_integration_from_webapi_to_websocket(monkeypatch, client, loop): # Create a keypair and generate a new asset user_priv, user_pub = crypto.generate_key_pair() asset = {'random': random.random()} - tx = Transaction.create([user_pub], [([user_pub], 1)], asset=asset) + tx = Create.generate([user_pub], [([user_pub], 1)], asset=asset) tx = tx.sign([user_priv]) # Post the transaction to the Planetmint Web API client.post('/api/v1/transactions/', data=json.dumps(tx.to_dict())) From 0463fb22f99f7cd36b0166d4d83f996c46bfb9fe Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Tue, 22 Mar 2022 09:41:28 +0000 Subject: [PATCH 18/22] Resolve flake8 issues#1 Signed-off-by: Sangat Das --- .../transactions/types/elections/vote.py | 1 - tests/assets/test_divisible_assets.py | 12 +----------- tests/common/test_transaction.py | 7 ------- tests/db/test_planetmint_api.py | 18 ------------------ tests/tendermint/test_core.py | 6 ------ tests/test_core.py | 6 ------ tests/web/test_assets.py | 2 -- tests/web/test_transactions.py | 1 - tests/web/test_websocket_server.py | 3 --- 9 files changed, 1 insertion(+), 55 deletions(-) diff --git a/planetmint/transactions/types/elections/vote.py b/planetmint/transactions/types/elections/vote.py index 9b8c33b..c102a8c 100644 --- a/planetmint/transactions/types/elections/vote.py +++ b/planetmint/transactions/types/elections/vote.py @@ -5,7 +5,6 @@ from planetmint.transactions.types.assets.create import Create from planetmint.transactions.types.assets.transfer import Transfer -from planetmint.transactions.common.transaction import Transaction from planetmint.transactions.common.schema import ( _validate_schema, TX_SCHEMA_COMMON, TX_SCHEMA_TRANSFER, TX_SCHEMA_VOTE) diff --git a/tests/assets/test_divisible_assets.py b/tests/assets/test_divisible_assets.py index d9d680f..caf3a97 100644 --- a/tests/assets/test_divisible_assets.py +++ b/tests/assets/test_divisible_assets.py @@ -18,7 +18,6 @@ from planetmint.transactions.common.exceptions import DoubleSpend # Single output # Single owners_after def test_single_in_single_own_single_out_single_own_create(alice, user_pk, b): - tx = Create.generate([alice.public_key], [([user_pk], 100)], asset={'name': random.random()}) tx_signed = tx.sign([alice.private_key]) @@ -35,7 +34,6 @@ def test_single_in_single_own_single_out_single_own_create(alice, user_pk, b): # Multiple outputs # Single owners_after per output def test_single_in_single_own_multiple_out_single_own_create(alice, user_pk, b): - tx = Create.generate([alice.public_key], [([user_pk], 50), ([user_pk], 50)], asset={'name': random.random()}) @@ -245,7 +243,6 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(alice, b, user_pk, # Single owners_after def test_single_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk, user_sk): - from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset @@ -281,7 +278,6 @@ def test_single_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk # Single owners_after def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk, user_sk): - # CREATE divisible asset tx_create = Create.generate([alice.public_key], [([user_pk], 50), ([user_pk], 50)], asset={'name': random.random()}) @@ -311,7 +307,6 @@ def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk # Single owners_after def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk, user_sk): - from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset @@ -352,7 +347,6 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_ # Single owners_after def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk, user_sk): - from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset @@ -392,7 +386,6 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk # owners_after def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(alice, b, user_pk, user_sk): - from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset @@ -437,7 +430,7 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(alice, b, user_pk, # Single output # Single owners_after def test_multiple_in_different_transactions(alice, b, user_pk, user_sk): - + # CREATE divisible asset # `b` creates a divisible asset and assigns 50 shares to `b` and # 50 shares to `user_pk` @@ -480,7 +473,6 @@ def test_multiple_in_different_transactions(alice, b, user_pk, user_sk): # inputs needs to match the amount being sent in the outputs. # In other words `amount_in_inputs - amount_in_outputs == 0` def test_amount_error_transfer(alice, b, user_pk, user_sk): - from planetmint.transactions.common.exceptions import AmountError # CREATE divisible asset @@ -536,7 +528,6 @@ def test_threshold_same_public_key(alice, b, user_pk, user_sk): def test_sum_amount(alice, b, user_pk, user_sk): - # CREATE divisible asset with 3 outputs with amount 1 tx_create = Create.generate([alice.public_key], [([user_pk], 1), ([user_pk], 1), ([user_pk], 1)], @@ -561,7 +552,6 @@ def test_sum_amount(alice, b, user_pk, user_sk): def test_divide(alice, b, user_pk, user_sk): - # CREATE divisible asset with 1 output with amount 3 tx_create = Create.generate([alice.public_key], [([user_pk], 3)], asset={'name': random.random()}) diff --git a/tests/common/test_transaction.py b/tests/common/test_transaction.py index ce45cd1..691e475 100644 --- a/tests/common/test_transaction.py +++ b/tests/common/test_transaction.py @@ -705,7 +705,6 @@ def test_create_create_transaction_single_io(user_output, user_pub, data): def test_validate_single_io_create_transaction(user_pub, user_priv, data, asset_definition): - from planetmint.transactions.common.transaction import Transaction tx = Create.generate([user_pub], [([user_pub], 1)], metadata=data) tx = tx.sign([user_priv]) @@ -741,7 +740,6 @@ def test_create_create_transaction_multiple_io(user_output, user2_output, user_p def test_validate_multiple_io_create_transaction(user_pub, user_priv, user2_pub, user2_priv, asset_definition): - from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model tx = Create.generate([user_pub, user2_pub], @@ -787,7 +785,6 @@ def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub, def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub, data, asset_definition): - from planetmint.transactions.common.transaction import Transaction from .utils import validate_transaction_model tx = Create.generate([user_pub], [([user_pub, user2_pub], 1)], @@ -799,8 +796,6 @@ def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub, def test_create_create_transaction_with_invalid_parameters(user_pub): - from planetmint.transactions.common.transaction import Transaction - with raises(TypeError): Create.generate('not a list') with raises(TypeError): @@ -943,8 +938,6 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv, def test_create_transfer_with_invalid_parameters(tx, user_pub): - from planetmint.transactions.common.transaction import Transaction - with raises(TypeError): Transfer.generate({}, [], tx.id) with raises(ValueError): diff --git a/tests/db/test_planetmint_api.py b/tests/db/test_planetmint_api.py index 0f08358..cb95598 100644 --- a/tests/db/test_planetmint_api.py +++ b/tests/db/test_planetmint_api.py @@ -16,7 +16,6 @@ pytestmark = pytest.mark.bdb class TestBigchainApi(object): def test_get_spent_with_double_spend_detected(self, b, alice): - from planetmint.models import Transaction from planetmint.transactions.common.exceptions import DoubleSpend from planetmint.exceptions import CriticalDoubleSpend @@ -46,7 +45,6 @@ class TestBigchainApi(object): b.get_spent(tx.id, 0) def test_double_inclusion(self, b, alice): - from planetmint.models import Transaction from planetmint.backend.exceptions import OperationError tx = Create.generate([alice.public_key], [([alice.public_key], 1)]) @@ -58,7 +56,6 @@ class TestBigchainApi(object): b.store_bulk_transactions([tx]) def test_text_search(self, b, alice): - from planetmint.models import Transaction # define the assets asset1 = {'msg': 'Planetmint 1'} @@ -85,7 +82,6 @@ class TestBigchainApi(object): from cryptoconditions import Ed25519Sha256 from planetmint.transactions.common.exceptions import InputDoesNotExist from planetmint.transactions.common.transaction import Input, TransactionLink - from planetmint.models import Transaction # Create an input for a non existing transaction input = Input(Ed25519Sha256(public_key=b58decode(user_pk)), @@ -97,7 +93,6 @@ class TestBigchainApi(object): tx.validate(b) def test_write_transaction(self, b, user_sk, user_pk, alice, create_tx): - from planetmint.models import Transaction asset1 = {'msg': 'Planetmint 1'} @@ -130,7 +125,6 @@ class TestTransactionValidation(object): def test_non_create_valid_input_wrong_owner(self, b, user_pk): from planetmint.transactions.common.crypto import generate_key_pair from planetmint.transactions.common.exceptions import InvalidSignature - from planetmint.models import Transaction input_tx = b.fastquery.get_outputs_by_public_key(user_pk).pop() input_transaction = b.get_transaction(input_tx.txid) @@ -159,7 +153,6 @@ class TestMultipleInputs(object): def test_transfer_single_owner_single_input(self, b, inputs, user_pk, user_sk): from planetmint.transactions.common import crypto - from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -180,7 +173,6 @@ class TestMultipleInputs(object): user_pk, inputs): from planetmint.transactions.common import crypto - from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() user3_sk, user3_pk = crypto.generate_key_pair() @@ -202,7 +194,6 @@ class TestMultipleInputs(object): user_pk, alice): from planetmint.transactions.common import crypto - from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() user3_sk, user3_pk = crypto.generate_key_pair() @@ -230,7 +221,6 @@ class TestMultipleInputs(object): user_pk, alice): from planetmint.transactions.common import crypto - from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() user3_sk, user3_pk = crypto.generate_key_pair() @@ -256,7 +246,6 @@ class TestMultipleInputs(object): def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_pk, alice): from planetmint.transactions.common import crypto from planetmint.transactions.common.transaction import TransactionLink - from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -284,7 +273,6 @@ class TestMultipleInputs(object): user_pk, alice): from planetmint.transactions.common import crypto from planetmint.transactions.common.transaction import TransactionLink - from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -318,7 +306,6 @@ class TestMultipleInputs(object): def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk, alice): from planetmint.transactions.common import crypto from planetmint.transactions.common.transaction import TransactionLink - from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() user3_sk, user3_pk = crypto.generate_key_pair() @@ -349,7 +336,6 @@ class TestMultipleInputs(object): def test_get_spent_single_tx_single_output(self, b, user_sk, user_pk, alice): from planetmint.transactions.common import crypto - from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() @@ -375,7 +361,6 @@ class TestMultipleInputs(object): def test_get_spent_single_tx_multiple_outputs(self, b, user_sk, user_pk, alice): from planetmint.transactions.common import crypto - from planetmint.models import Transaction # create a new users user2_sk, user2_pk = crypto.generate_key_pair() @@ -412,7 +397,6 @@ class TestMultipleInputs(object): def test_get_spent_multiple_owners(self, b, user_sk, user_pk, alice): from planetmint.transactions.common import crypto - from planetmint.models import Transaction user2_sk, user2_pk = crypto.generate_key_pair() user3_sk, user3_pk = crypto.generate_key_pair() @@ -498,7 +482,6 @@ def test_cant_spend_same_input_twice_in_tx(b, alice): """Recreate duplicated fulfillments bug https://github.com/planetmint/planetmint/issues/1099 """ - from planetmint.models import Transaction from planetmint.transactions.common.exceptions import DoubleSpend # create a divisible asset @@ -520,7 +503,6 @@ def test_cant_spend_same_input_twice_in_tx(b, alice): def test_transaction_unicode(b, alice): import copy from planetmint.transactions.common.utils import serialize - from planetmint.models import Transaction # http://www.fileformat.info/info/unicode/char/1f37a/index.htm beer_python = {'beer': '\N{BEER MUG}'} diff --git a/tests/tendermint/test_core.py b/tests/tendermint/test_core.py index c8e7942..6f4ae8f 100644 --- a/tests/tendermint/test_core.py +++ b/tests/tendermint/test_core.py @@ -204,7 +204,6 @@ def test_info(b): def test_check_tx__signed_create_is_ok(b): from planetmint import App - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() @@ -221,7 +220,6 @@ def test_check_tx__signed_create_is_ok(b): def test_check_tx__unsigned_create_is_error(b): from planetmint import App - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() @@ -238,7 +236,6 @@ def test_check_tx__unsigned_create_is_error(b): def test_deliver_tx__valid_create_updates_db_and_emits_event(b, init_chain_request): import multiprocessing as mp from planetmint import App - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() @@ -275,7 +272,6 @@ def test_deliver_tx__valid_create_updates_db_and_emits_event(b, init_chain_reque def test_deliver_tx__double_spend_fails(b, init_chain_request): from planetmint import App - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() @@ -304,7 +300,6 @@ def test_deliver_tx__double_spend_fails(b, init_chain_request): def test_deliver_transfer_tx__double_spend_fails(b, init_chain_request): from planetmint import App - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair app = App(b) @@ -384,7 +379,6 @@ def test_end_block_return_validator_updates(b, init_chain_request): def test_store_pre_commit_state_in_end_block(b, alice, init_chain_request): from planetmint import App from planetmint.backend import query - from planetmint.models import Transaction tx = Create.generate([alice.public_key], [([alice.public_key], 1)], diff --git a/tests/test_core.py b/tests/test_core.py index d9a6efa..ae02b44 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -204,7 +204,6 @@ def test_info(b): def test_check_tx__signed_create_is_ok(b): from planetmint import App - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() @@ -221,7 +220,6 @@ def test_check_tx__signed_create_is_ok(b): def test_check_tx__unsigned_create_is_error(b): from planetmint import App - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() @@ -238,7 +236,6 @@ def test_check_tx__unsigned_create_is_error(b): def test_deliver_tx__valid_create_updates_db_and_emits_event(b, init_chain_request): import multiprocessing as mp from planetmint import App - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() @@ -275,7 +272,6 @@ def test_deliver_tx__valid_create_updates_db_and_emits_event(b, init_chain_reque def test_deliver_tx__double_spend_fails(b, eventqueue_fixture, init_chain_request): from planetmint import App - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair alice = generate_key_pair() @@ -304,7 +300,6 @@ def test_deliver_tx__double_spend_fails(b, eventqueue_fixture, init_chain_reques def test_deliver_transfer_tx__double_spend_fails(b, init_chain_request): from planetmint import App - from planetmint.models import Transaction from planetmint.transactions.common.crypto import generate_key_pair app = App(b) @@ -384,7 +379,6 @@ def test_end_block_return_validator_updates(b, init_chain_request): def test_store_pre_commit_state_in_end_block(b, alice, init_chain_request): from planetmint import App from planetmint.backend import query - from planetmint.models import Transaction tx = Create.generate([alice.public_key], [([alice.public_key], 1)], diff --git a/tests/web/test_assets.py b/tests/web/test_assets.py index 58136c3..b88c2ef 100644 --- a/tests/web/test_assets.py +++ b/tests/web/test_assets.py @@ -23,7 +23,6 @@ def test_get_assets_with_missing_text_search(client): @pytest.mark.bdb def test_get_assets_tendermint(client, b, alice): - from planetmint.models import Transaction # test returns empty list when no assets are found res = client.get(ASSETS_ENDPOINT + '?search=abc') @@ -49,7 +48,6 @@ def test_get_assets_tendermint(client, b, alice): @pytest.mark.bdb def test_get_assets_limit_tendermint(client, b, alice): - from planetmint.models import Transaction # create two assets asset1 = {'msg': 'abc 1'} diff --git a/tests/web/test_transactions.py b/tests/web/test_transactions.py index 109146e..b613c50 100644 --- a/tests/web/test_transactions.py +++ b/tests/web/test_transactions.py @@ -214,7 +214,6 @@ def test_post_create_transaction_with_invalid_structure(client): @pytest.mark.abci @patch('planetmint.web.views.base.logger') def test_post_create_transaction_with_invalid_schema(mock_logger, client): - from planetmint.models import Transaction user_priv, user_pub = crypto.generate_key_pair() tx = Create.generate([user_pub], [([user_pub], 1)]).to_dict() del tx['version'] diff --git a/tests/web/test_websocket_server.py b/tests/web/test_websocket_server.py index 6846554..d7d9d85 100644 --- a/tests/web/test_websocket_server.py +++ b/tests/web/test_websocket_server.py @@ -25,7 +25,6 @@ class MockWebSocket: def test_eventify_block_works_with_any_transaction(): from planetmint.web.websocket_server import eventify_block from planetmint.transactions.common.crypto import generate_key_pair - from planetmint.lib import Transaction alice = generate_key_pair() @@ -140,7 +139,6 @@ async def test_websocket_string_event(test_client, loop): async def test_websocket_block_event(b, test_client, loop): from planetmint import events from planetmint.web.websocket_server import init_app, POISON_PILL, EVENTS_ENDPOINT - from planetmint.models import Transaction from planetmint.transactions.common import crypto user_priv, user_pub = crypto.generate_key_pair() @@ -186,7 +184,6 @@ def test_integration_from_webapi_to_websocket(monkeypatch, client, loop): # TODO processes does not exist anymore, when reactivating this test it # will fail because of this from planetmint import processes - from planetmint.models import Transaction # Start Planetmint processes.start() From 43ecbffe5ed21c162812fa78fdd4fdca8ba2bf2e Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Wed, 23 Mar 2022 08:08:20 +0000 Subject: [PATCH 19/22] Resolve flake8 issues#2 Signed-off-by: Sangat Das --- tests/assets/test_divisible_assets.py | 6 +++--- tests/tendermint/test_integration.py | 7 ++++--- tests/utils.py | 4 ++-- tests/web/test_outputs.py | 10 ++++++---- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/tests/assets/test_divisible_assets.py b/tests/assets/test_divisible_assets.py index caf3a97..272c9d3 100644 --- a/tests/assets/test_divisible_assets.py +++ b/tests/assets/test_divisible_assets.py @@ -97,7 +97,6 @@ def test_single_in_single_own_multiple_out_mix_own_create(alice, user_pk, b): # Output combinations already tested above def test_single_in_multiple_own_single_out_single_own_create(alice, b, user_pk, user_sk): - from planetmint.transactions.common.utils import _fulfillment_to_details tx = Create.generate([alice.public_key, user_pk], [([user_pk], 100)], asset={'name': random.random()}) @@ -305,8 +304,9 @@ def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk # Multiple owners_before per input # Single output # Single owners_after -def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk, - user_sk): +def test_multiple_in_multiple_own_single_out_single_own_transfer( + alice, b, user_pk, + user_sk): from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset diff --git a/tests/tendermint/test_integration.py b/tests/tendermint/test_integration.py index 15a6eac..8b7bb85 100644 --- a/tests/tendermint/test_integration.py +++ b/tests/tendermint/test_integration.py @@ -5,6 +5,7 @@ import codecs from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer from tendermint.abci import types_pb2 as types import json @@ -114,7 +115,7 @@ def test_app(b, eventqueue_fixture, init_chain_request): @pytest.mark.abci def test_post_transaction_responses(tendermint_ws_url, b): from planetmint.transactions.common.crypto import generate_key_pair - from planetmint.models import Transaction + alice = generate_key_pair() bob = generate_key_pair() @@ -126,7 +127,7 @@ def test_post_transaction_responses(tendermint_ws_url, b): code, message = b.write_transaction(tx, BROADCAST_TX_COMMIT) assert code == 202 - tx_transfer = Transaction.transfer(tx.to_inputs(), + tx_transfer = Transfer.generate(tx.to_inputs(), [([bob.public_key], 1)], asset_id=tx.id)\ .sign([alice.private_key]) @@ -135,7 +136,7 @@ def test_post_transaction_responses(tendermint_ws_url, b): assert code == 202 carly = generate_key_pair() - double_spend = Transaction.transfer( + double_spend = Transfer.transfer( tx.to_inputs(), [([carly.public_key], 1)], asset_id=tx.id, diff --git a/tests/utils.py b/tests/utils.py index 4829d4e..ceffff0 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -13,6 +13,7 @@ from planetmint.backend.localmongodb.connection import LocalMongoDBConnection from planetmint.backend.schema import TABLES from planetmint.transactions.common import crypto from planetmint.transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT +from planetmint.transactions.types.assets.create import Create from planetmint.transactions.types.elections.election import Election, Vote from planetmint.tendermint_utils import key_to_base64 @@ -30,10 +31,9 @@ def flush_localmongo_db(connection, dbname): def generate_block(planet): from planetmint.transactions.common.crypto import generate_key_pair - from planetmint.models import Transaction alice = generate_key_pair() - tx = Transaction.create([alice.public_key], + tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=None)\ .sign([alice.private_key]) diff --git a/tests/web/test_outputs.py b/tests/web/test_outputs.py index 112526a..16783b8 100644 --- a/tests/web/test_outputs.py +++ b/tests/web/test_outputs.py @@ -3,7 +3,10 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 + import pytest +from planetmint.transactions.types.assets.create import Create +from planetmint.transactions.types.assets.transfer import Transfer from unittest.mock import MagicMock, patch @@ -83,7 +86,6 @@ def test_get_outputs_endpoint_with_invalid_spent(client, user_pk): @pytest.mark.abci def test_get_divisble_transactions_returns_500(b, client): - from planetmint.models import Transaction from planetmint.transactions.common import crypto import json @@ -96,7 +98,7 @@ def test_get_divisble_transactions_returns_500(b, client): bob_priv, bob_pub = crypto.generate_key_pair() carly_priv, carly_pub = crypto.generate_key_pair() - create_tx = Transaction.create([alice_pub], [([alice_pub], 4)]) + create_tx = Create.generate([alice_pub], [([alice_pub], 4)]) create_tx.sign([alice_priv]) res = client.post(TX_ENDPOINT, data=json.dumps(create_tx.to_dict())) @@ -104,7 +106,7 @@ def test_get_divisble_transactions_returns_500(b, client): mine([create_tx]) - transfer_tx = Transaction.transfer(create_tx.to_inputs(), + transfer_tx = Transfer.generate(create_tx.to_inputs(), [([alice_pub], 3), ([bob_pub], 1)], asset_id=create_tx.id) transfer_tx.sign([alice_priv]) @@ -114,7 +116,7 @@ def test_get_divisble_transactions_returns_500(b, client): mine([transfer_tx]) - transfer_tx_carly = Transaction.transfer([transfer_tx.to_inputs()[1]], + transfer_tx_carly = Transfer.generate([transfer_tx.to_inputs()[1]], [([carly_pub], 1)], asset_id=create_tx.id) transfer_tx_carly.sign([bob_priv]) From 635d68c7adae6d5306c387c83d67529364243706 Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Wed, 23 Mar 2022 08:23:33 +0000 Subject: [PATCH 20/22] Resolve flake8 issues#3 Signed-off-by: Sangat Das --- tests/assets/test_divisible_assets.py | 3 +-- tests/tendermint/test_integration.py | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/assets/test_divisible_assets.py b/tests/assets/test_divisible_assets.py index 272c9d3..031a9be 100644 --- a/tests/assets/test_divisible_assets.py +++ b/tests/assets/test_divisible_assets.py @@ -305,8 +305,7 @@ def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk # Single output # Single owners_after def test_multiple_in_multiple_own_single_out_single_own_transfer( - alice, b, user_pk, - user_sk): + alice, b, user_pk, user_sk): from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset diff --git a/tests/tendermint/test_integration.py b/tests/tendermint/test_integration.py index 8b7bb85..2326caf 100644 --- a/tests/tendermint/test_integration.py +++ b/tests/tendermint/test_integration.py @@ -116,7 +116,6 @@ def test_app(b, eventqueue_fixture, init_chain_request): def test_post_transaction_responses(tendermint_ws_url, b): from planetmint.transactions.common.crypto import generate_key_pair - alice = generate_key_pair() bob = generate_key_pair() tx = Create.generate([alice.public_key], From a7fe94de1da97fb3263ddbc7590beaf976cb9c73 Mon Sep 17 00:00:00 2001 From: Sangat Das Date: Wed, 23 Mar 2022 09:07:32 +0000 Subject: [PATCH 21/22] Resolve flake8 issues#4 Signed-off-by: Sangat Das --- tests/assets/test_divisible_assets.py | 4 ++-- tests/tendermint/test_integration.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/assets/test_divisible_assets.py b/tests/assets/test_divisible_assets.py index 031a9be..210efbe 100644 --- a/tests/assets/test_divisible_assets.py +++ b/tests/assets/test_divisible_assets.py @@ -304,8 +304,8 @@ def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk # Multiple owners_before per input # Single output # Single owners_after -def test_multiple_in_multiple_own_single_out_single_own_transfer( - alice, b, user_pk, user_sk): +def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk, + user_sk): from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset diff --git a/tests/tendermint/test_integration.py b/tests/tendermint/test_integration.py index 2326caf..69c818d 100644 --- a/tests/tendermint/test_integration.py +++ b/tests/tendermint/test_integration.py @@ -135,7 +135,7 @@ def test_post_transaction_responses(tendermint_ws_url, b): assert code == 202 carly = generate_key_pair() - double_spend = Transfer.transfer( + double_spend = Transfer.generate( tx.to_inputs(), [([carly.public_key], 1)], asset_id=tx.id, From 69ad661a6086f9a0108a479ae5b083928dc3e6f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Eckel?= Date: Wed, 23 Mar 2022 14:13:51 +0100 Subject: [PATCH 22/22] fixed last flake issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jürgen Eckel --- tests/assets/test_divisible_assets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/assets/test_divisible_assets.py b/tests/assets/test_divisible_assets.py index 210efbe..4381c06 100644 --- a/tests/assets/test_divisible_assets.py +++ b/tests/assets/test_divisible_assets.py @@ -305,13 +305,13 @@ def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk # Single output # Single owners_after def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk, - user_sk): + user_sk): from planetmint.transactions.common.utils import _fulfillment_to_details # CREATE divisible asset tx_create = Create.generate([alice.public_key], [([user_pk, alice.public_key], 50), - ([user_pk, alice.public_key], 50)], - asset={'name': random.random()}) + ([user_pk, alice.public_key], 50)], + asset={'name': random.random()}) tx_create_signed = tx_create.sign([alice.private_key]) # TRANSFER