diff --git a/acceptance/python/Dockerfile b/acceptance/python/Dockerfile index 14defda..b2add13 100644 --- a/acceptance/python/Dockerfile +++ b/acceptance/python/Dockerfile @@ -11,51 +11,7 @@ RUN pip install --upgrade \ pycco \ 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 \ + planetmint-cryptoconditions>=0.9.7\ + planetmint-driver>=0.9.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/acceptance/python/src/conftest.py b/acceptance/python/src/conftest.py index 34e8a3f..70614c6 100644 --- a/acceptance/python/src/conftest.py +++ b/acceptance/python/src/conftest.py @@ -5,36 +5,40 @@ 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'""" - +CONDITION_SCRIPT = """ + Scenario 'ecdh': create the signature of an object + Given I have the 'keyring' + Given that I have a 'string dictionary' named 'houses' inside 'asset' + When I create the signature of 'houses' + Then print the 'signature'""" + FULFILL_SCRIPT = \ - """Rule input encoding base58 - Rule output encoding base58 - Scenario 'ecdh': Bob verifies the signature from Alice + """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' + Given I have a 'signature' named 'signature' inside 'result' + When I verify the 'houses' has a signature in 'signature' by 'Alice' Then print the string 'ok'""" + +SK_TO_PK = \ + """Scenario 'ecdh': Create the keypair + Given that I am known as '{}' + Given I have the 'keyring' + When I create the ecdh public key + When I create the bitcoin address + Then print my 'ecdh public key' + Then print my 'bitcoin address'""" + +GENERATE_KEYPAIR = \ + """Scenario 'ecdh': Create the keypair + Given that I am known as 'Pippo' + When I create the ecdh key + When I create the bitcoin key + Then print data""" + +ZENROOM_DATA = { + 'also': 'more data' +} HOUSE_ASSETS = { "data": { @@ -51,19 +55,11 @@ HOUSE_ASSETS = { } } -ZENROOM_DATA = { - 'also': 'more data' +metadata = { + 'units': 300, + 'type': 'KG' } -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 @@ -86,4 +82,4 @@ def zenroom_house_assets(): @pytest.fixture def zenroom_data(): - return ZENROOM_DATA \ No newline at end of file + return ZENROOM_DATA diff --git a/acceptance/python/src/test_zenroom.py b/acceptance/python/src/test_zenroom.py index 2829fab..f7ebc56 100644 --- a/acceptance/python/src/test_zenroom.py +++ b/acceptance/python/src/test_zenroom.py @@ -1,68 +1,66 @@ -# 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 os import json +import base58 +from hashlib import sha3_256 +from cryptoconditions.types.ed25519 import Ed25519Sha256 +from cryptoconditions.types.zenroom import ZenroomSha256 +from planetmint_driver import Planetmint +from planetmint_driver.crypto import generate_keypair -import hashlib -from cryptoconditions import ZenroomSha256 -from json.decoder import JSONDecodeError -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'] + + + +def test_zenroom_signing(gen_key_zencode, secret_key_to_private_key_zencode, + fulfill_script_zencode, zenroom_data, zenroom_house_assets, + condition_script_zencode): + + biolabs = generate_keypair() + version = '2.0' + + alice = json.loads(ZenroomSha256.run_zenroom(gen_key_zencode).output)['keyring'] + bob = json.loads(ZenroomSha256.run_zenroom(gen_key_zencode).output)['keyring'] zen_public_keys = json.loads(ZenroomSha256.run_zenroom(secret_key_to_private_key_zencode.format('Alice'), - keys={'keys': alice}).output) + keys={'keyring': alice}).output) zen_public_keys.update(json.loads(ZenroomSha256.run_zenroom(secret_key_to_private_key_zencode.format('Bob'), - keys={'keys': bob}).output)) + keys={'keyring': bob}).output)) - # CRYPTO-CONDITIONS: instantiate an Ed25519 crypto-condition for buyer - zenSha = ZenroomSha256(script=fulfill_script_zencode, keys=zen_public_keys, data=zenroom_data) + + zenroomscpt = ZenroomSha256(script=fulfill_script_zencode, data=zenroom_data, keys=zen_public_keys) + print(F'zenroom is: {zenroomscpt.script}') + # CRYPTO-CONDITIONS: generate the condition uri - condition_uri = zenSha.condition.serialize_uri() + condition_uri_zen = zenroomscpt.condition.serialize_uri() + print(F'\nzenroom condition URI: {condition_uri_zen}') # CRYPTO-CONDITIONS: construct an unsigned fulfillment dictionary - unsigned_fulfillment_dict = { - 'type': zenSha.TYPE_NAME, - 'script': fulfill_script_zencode, - 'keys': zen_public_keys, + unsigned_fulfillment_dict_zen = { + 'type': zenroomscpt.TYPE_NAME, + 'public_key': base58.b58encode(biolabs.public_key).decode(), } - output = { - 'amount': '1000', + 'amount': '10', 'condition': { - 'details': unsigned_fulfillment_dict, - 'uri': condition_uri, + 'details': unsigned_fulfillment_dict_zen, + 'uri': condition_uri_zen, + }, - 'data': zenroom_data, - 'script': fulfill_script_zencode, - 'conf': '', - 'public_keys': (zen_public_keys['Alice']['ecdh_public_key'], ), + 'public_keys': [biolabs.public_key,], } - - input_ = { 'fulfillment': None, 'fulfills': None, - 'owners_before': (zen_public_keys['Alice']['ecdh_public_key'], ), + 'owners_before': [biolabs.public_key,] } - token_creation_tx = { 'operation': 'CREATE', 'asset': zenroom_house_assets, 'metadata': None, - 'outputs': (output,), - 'inputs': (input_,), - 'version': '2.0', + 'outputs': [output,], + 'inputs': [input_,], + 'version': version, 'id': None, } @@ -74,12 +72,36 @@ condition_script_zencode, zenroom_data, zenroom_house_assets): ensure_ascii=False, ) - try: - assert(not zenSha.validate(message=message)) - except JSONDecodeError: - pass - except ValueError: - pass + # major workflow: + # we store the fulfill script in the transaction/message (zenroom-sha) + # the condition script is used to fulfill the transaction and create the signature + # + # the server should ick the fulfill script and recreate the zenroom-sha and verify the signature - message = zenSha.sign(message, condition_script_zencode, alice) - assert(zenSha.validate(message=message)) + + + message = zenroomscpt.sign(message, condition_script_zencode, alice) + assert(zenroomscpt.validate(message=message)) + + message = json.loads(message) + fulfillment_uri_zen = zenroomscpt.serialize_uri() + + message['inputs'][0]['fulfillment'] = fulfillment_uri_zen + tx = message + tx['id'] = None + json_str_tx = json.dumps( + tx, + sort_keys=True, + skipkeys=False, + separators=(',', ':') + ) + # SHA3: hash the serialized id-less transaction to generate the id + shared_creation_txid = sha3_256(json_str_tx.encode()).hexdigest() + message['id'] = shared_creation_txid + + + # `https://example.com:9984` + plntmnt = Planetmint(os.environ.get('PLANETMINT_ENDPOINT')) + sent_transfer_tx = plntmnt.transactions.send_commit(message) + + print( f"\n\nstatus and result : + {sent_transfer_tx}") diff --git a/planetmint/start.py b/planetmint/start.py index 24dc356..e4ca953 100644 --- a/planetmint/start.py +++ b/planetmint/start.py @@ -43,7 +43,7 @@ def start(args): settings=planetmint.config['server'], log_config=planetmint.config['log'], planetmint_factory=Planetmint) - p_webapi = Process(name='planetmint_webapi', target=app_server.run, daemon=True) + p_webapi = Process(name='planetmint_webapi', target=app_server.run, daemon=False) p_webapi.start() logger.info(BANNER.format(planetmint.config['server']['bind'])) diff --git a/setup.py b/setup.py index 92c2f7c..6a8f886 100644 --- a/setup.py +++ b/setup.py @@ -77,7 +77,7 @@ install_requires = [ 'chardet==3.0.4', 'aiohttp==3.8.1', 'abci==0.8.3', - 'planetmint-cryptoconditions>=0.9.4', + 'planetmint-cryptoconditions>=0.9.7', 'flask-cors==3.0.10', 'flask-restful==0.3.9', 'flask==2.0.1', @@ -86,6 +86,7 @@ install_requires = [ 'logstats==0.3.0', 'packaging>=20.9', # TODO Consider not installing the db drivers, or putting them in extras. + 'protobuf==3.20.1', 'pymongo==3.11.4', 'python-rapidjson==1.0', 'pyyaml==5.4.1',