planetmint/integration/python/src/test_threshold.py
Jürgen Eckel bd1cdf44e4
Integration of new cryptoconditions package name and newest zenroom version (#288)
* adjusted to neweest transaction package
* adjusted to new planetmint-cryptoconditions imports
* added Changelog and increased version

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>
2022-11-29 10:56:07 +01:00

320 lines
10 KiB
Python

# 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
# ## Imports
import time
import json
# For this test case we need the planetmint_driver.crypto package
import base58
import sha3
from planetmint_cryptoconditions import Ed25519Sha256, ThresholdSha256
from planetmint_driver.crypto import generate_keypair
# Import helper to deal with multiple nodes
from .helper.hosts import Hosts
def prepare_condition_details(condition: ThresholdSha256):
condition_details = {"subconditions": [], "threshold": condition.threshold, "type": condition.TYPE_NAME}
for s in condition.subconditions:
if s["type"] == "fulfillment" and s["body"].TYPE_NAME == "ed25519-sha-256":
condition_details["subconditions"].append(
{"type": s["body"].TYPE_NAME, "public_key": base58.b58encode(s["body"].public_key).decode()}
)
else:
condition_details["subconditions"].append(prepare_condition_details(s["body"]))
return condition_details
def test_threshold():
# Setup connection to test nodes
hosts = Hosts("/shared/hostnames")
pm = hosts.get_connection()
# Generate Keypars for Alice, Bob an Carol!
alice, bob, carol = generate_keypair(), generate_keypair(), generate_keypair()
# ## Alice and Bob create a transaction
# Alice and Bob just moved into a shared flat, no one can afford these
# high rents anymore. Bob suggests to get a dish washer for the
# kitchen. Alice agrees and here they go, creating the asset for their
# dish washer.
dw_asset = [{"data": {"dish washer": {"serial_number": 1337}}}]
# Create subfulfillments
alice_ed25519 = Ed25519Sha256(public_key=base58.b58decode(alice.public_key))
bob_ed25519 = Ed25519Sha256(public_key=base58.b58decode(bob.public_key))
carol_ed25519 = Ed25519Sha256(public_key=base58.b58decode(carol.public_key))
# Create threshold condition (2/3) and add subfulfillments
threshold_sha256 = ThresholdSha256(2)
threshold_sha256.add_subfulfillment(alice_ed25519)
threshold_sha256.add_subfulfillment(bob_ed25519)
threshold_sha256.add_subfulfillment(carol_ed25519)
# Create a condition uri and details for the output object
condition_uri = threshold_sha256.condition.serialize_uri()
condition_details = prepare_condition_details(threshold_sha256)
# Assemble output and input for the handcrafted tx
output = {
"amount": "1",
"condition": {
"details": condition_details,
"uri": condition_uri,
},
"public_keys": (alice.public_key, bob.public_key, carol.public_key),
}
# The yet to be fulfilled input:
input_ = {
"fulfillment": None,
"fulfills": None,
"owners_before": (alice.public_key, bob.public_key),
}
# Assemble the handcrafted transaction
handcrafted_dw_tx = {
"operation": "CREATE",
"asset": dw_asset,
"metadata": None,
"outputs": (output,),
"inputs": (input_,),
"version": "2.0",
"id": None,
}
# Create sha3-256 of message to sign
message = json.dumps(
handcrafted_dw_tx,
sort_keys=True,
separators=(",", ":"),
ensure_ascii=False,
)
message = sha3.sha3_256(message.encode())
# Sign message with Alice's und Bob's private key
alice_ed25519.sign(message.digest(), base58.b58decode(alice.private_key))
bob_ed25519.sign(message.digest(), base58.b58decode(bob.private_key))
# Create fulfillment and add uri to inputs
fulfillment_threshold = ThresholdSha256(2)
fulfillment_threshold.add_subfulfillment(alice_ed25519)
fulfillment_threshold.add_subfulfillment(bob_ed25519)
fulfillment_threshold.add_subcondition(carol_ed25519.condition)
fulfillment_uri = fulfillment_threshold.serialize_uri()
handcrafted_dw_tx["inputs"][0]["fulfillment"] = fulfillment_uri
# Create tx_id for handcrafted_dw_tx and send tx commit
json_str_tx = json.dumps(
handcrafted_dw_tx,
sort_keys=True,
separators=(",", ":"),
ensure_ascii=False,
)
dw_creation_txid = sha3.sha3_256(json_str_tx.encode()).hexdigest()
handcrafted_dw_tx["id"] = dw_creation_txid
pm.transactions.send_commit(handcrafted_dw_tx)
time.sleep(1)
# Assert that the tx is propagated to all nodes
hosts.assert_transaction(dw_creation_txid)
def test_weighted_threshold():
hosts = Hosts("/shared/hostnames")
pm = hosts.get_connection()
alice, bob, carol = generate_keypair(), generate_keypair(), generate_keypair()
assets = [{"data": {"trashcan": {"animals": ["racoon_1", "racoon_2"]}}}]
alice_ed25519 = Ed25519Sha256(public_key=base58.b58decode(alice.public_key))
bob_ed25519 = Ed25519Sha256(public_key=base58.b58decode(bob.public_key))
carol_ed25519 = Ed25519Sha256(public_key=base58.b58decode(carol.public_key))
threshold = ThresholdSha256(1)
threshold.add_subfulfillment(alice_ed25519)
sub_threshold = ThresholdSha256(2)
sub_threshold.add_subfulfillment(bob_ed25519)
sub_threshold.add_subfulfillment(carol_ed25519)
threshold.add_subfulfillment(sub_threshold)
condition_uri = threshold.condition.serialize_uri()
condition_details = prepare_condition_details(threshold)
# Assemble output and input for the handcrafted tx
output = {
"amount": "1",
"condition": {
"details": condition_details,
"uri": condition_uri,
},
"public_keys": (alice.public_key, bob.public_key, carol.public_key),
}
# The yet to be fulfilled input:
input_ = {
"fulfillment": None,
"fulfills": None,
"owners_before": (alice.public_key, bob.public_key),
}
# Assemble the handcrafted transaction
handcrafted_tx = {
"operation": "CREATE",
"asset": assets,
"metadata": None,
"outputs": (output,),
"inputs": (input_,),
"version": "2.0",
"id": None,
}
# Create sha3-256 of message to sign
message = json.dumps(
handcrafted_tx,
sort_keys=True,
separators=(",", ":"),
ensure_ascii=False,
)
message = sha3.sha3_256(message.encode())
# Sign message with Alice's und Bob's private key
alice_ed25519.sign(message.digest(), base58.b58decode(alice.private_key))
# Create fulfillment and add uri to inputs
sub_fulfillment_threshold = ThresholdSha256(2)
sub_fulfillment_threshold.add_subcondition(bob_ed25519.condition)
sub_fulfillment_threshold.add_subcondition(carol_ed25519.condition)
fulfillment_threshold = ThresholdSha256(1)
fulfillment_threshold.add_subfulfillment(alice_ed25519)
fulfillment_threshold.add_subfulfillment(sub_fulfillment_threshold)
fulfillment_uri = fulfillment_threshold.serialize_uri()
handcrafted_tx["inputs"][0]["fulfillment"] = fulfillment_uri
# Create tx_id for handcrafted_dw_tx and send tx commit
json_str_tx = json.dumps(
handcrafted_tx,
sort_keys=True,
separators=(",", ":"),
ensure_ascii=False,
)
creation_tx_id = sha3.sha3_256(json_str_tx.encode()).hexdigest()
handcrafted_tx["id"] = creation_tx_id
pm.transactions.send_commit(handcrafted_tx)
time.sleep(1)
# Assert that the tx is propagated to all nodes
hosts.assert_transaction(creation_tx_id)
# Now transfer created asset
alice_transfer_ed25519 = Ed25519Sha256(public_key=base58.b58decode(alice.public_key))
bob_transfer_ed25519 = Ed25519Sha256(public_key=base58.b58decode(bob.public_key))
carol_transfer_ed25519 = Ed25519Sha256(public_key=base58.b58decode(carol.public_key))
transfer_condition_uri = alice_transfer_ed25519.condition.serialize_uri()
# Assemble output and input for the handcrafted tx
transfer_output = {
"amount": "1",
"condition": {
"details": {
"type": alice_transfer_ed25519.TYPE_NAME,
"public_key": base58.b58encode(alice_transfer_ed25519.public_key).decode(),
},
"uri": transfer_condition_uri,
},
"public_keys": (alice.public_key,),
}
# The yet to be fulfilled input:
transfer_input_ = {
"fulfillment": None,
"fulfills": {"transaction_id": creation_tx_id, "output_index": 0},
"owners_before": (alice.public_key, bob.public_key, carol.public_key),
}
# Assemble the handcrafted transaction
handcrafted_transfer_tx = {
"operation": "TRANSFER",
"assets": [{"id": creation_tx_id}],
"metadata": None,
"outputs": (transfer_output,),
"inputs": (transfer_input_,),
"version": "2.0",
"id": None,
}
# Create sha3-256 of message to sign
message = json.dumps(
handcrafted_transfer_tx,
sort_keys=True,
separators=(",", ":"),
ensure_ascii=False,
)
message = sha3.sha3_256(message.encode())
message.update(
"{}{}".format(
handcrafted_transfer_tx["inputs"][0]["fulfills"]["transaction_id"],
handcrafted_transfer_tx["inputs"][0]["fulfills"]["output_index"],
).encode()
)
# Sign message with Alice's und Bob's private key
bob_transfer_ed25519.sign(message.digest(), base58.b58decode(bob.private_key))
carol_transfer_ed25519.sign(message.digest(), base58.b58decode(carol.private_key))
sub_fulfillment_threshold = ThresholdSha256(2)
sub_fulfillment_threshold.add_subfulfillment(bob_transfer_ed25519)
sub_fulfillment_threshold.add_subfulfillment(carol_transfer_ed25519)
# Create fulfillment and add uri to inputs
fulfillment_threshold = ThresholdSha256(1)
fulfillment_threshold.add_subcondition(alice_transfer_ed25519.condition)
fulfillment_threshold.add_subfulfillment(sub_fulfillment_threshold)
fulfillment_uri = fulfillment_threshold.serialize_uri()
handcrafted_transfer_tx["inputs"][0]["fulfillment"] = fulfillment_uri
# Create tx_id for handcrafted_dw_tx and send tx commit
json_str_tx = json.dumps(
handcrafted_transfer_tx,
sort_keys=True,
separators=(",", ":"),
ensure_ascii=False,
)
transfer_tx_id = sha3.sha3_256(json_str_tx.encode()).hexdigest()
handcrafted_transfer_tx["id"] = transfer_tx_id
pm.transactions.send_commit(handcrafted_transfer_tx)
time.sleep(1)
# Assert that the tx is propagated to all nodes
hosts.assert_transaction(transfer_tx_id)