diff --git a/tests/common/__init__.py b/tests/common/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/common/conftest.py b/tests/common/conftest.py deleted file mode 100644 index fdc5ecf..0000000 --- a/tests/common/conftest.py +++ /dev/null @@ -1,311 +0,0 @@ -# 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 base58 import b58decode -import pytest -from cryptoconditions import ThresholdSha256, Ed25519Sha256 - - -USER_PRIVATE_KEY = "8eJ8q9ZQpReWyQT5aFCiwtZ5wDZC4eDnCen88p3tQ6ie" -USER_PUBLIC_KEY = "JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE" - -USER2_PRIVATE_KEY = "F86PQPiqMTwM2Qi2Sda3U4Vdh3AgadMdX3KNVsu5wNJr" -USER2_PUBLIC_KEY = "GDxwMFbwdATkQELZbMfW8bd9hbNYMZLyVXA3nur2aNbE" - -USER3_PRIVATE_KEY = "4rNQFzWQbVwuTiDVxwuFMvLG5zd8AhrQKCtVovBvcYsB" -USER3_PUBLIC_KEY = "Gbrg7JtxdjedQRmr81ZZbh1BozS7fBW88ZyxNDy7WLNC" - -CC_FULFILLMENT_URI = ( - "pGSAINdamAGCsQq31Uv-08lkBzoO4XLz2qYjJa8CGmj3B1EagUDlVkMAw2CscpCG4syAboKKh" - "Id_Hrjl2XTYc-BlIkkBVV-4ghWQozusxh45cBz5tGvSW_XwWVu-JGVRQUOOehAL" -) -CC_CONDITION_URI = "ni:///sha-256;" "eZI5q6j8T_fqv7xMROaei9_tmTMk4S7WR5Kr4onPHV8" "?fpt=ed25519-sha-256&cost=131072" - -ASSET_DEFINITION = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"} - -DATA = "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4" - - -@pytest.fixture -def user_priv(): - return USER_PRIVATE_KEY - - -@pytest.fixture -def user_pub(): - return USER_PUBLIC_KEY - - -@pytest.fixture -def user2_priv(): - return USER2_PRIVATE_KEY - - -@pytest.fixture -def user2_pub(): - return USER2_PUBLIC_KEY - - -@pytest.fixture -def user3_priv(): - return USER3_PRIVATE_KEY - - -@pytest.fixture -def user3_pub(): - return USER3_PUBLIC_KEY - - -@pytest.fixture -def ffill_uri(): - return CC_FULFILLMENT_URI - - -@pytest.fixture -def cond_uri(): - return CC_CONDITION_URI - - -@pytest.fixture -def user_Ed25519(user_pub): - return Ed25519Sha256(public_key=b58decode(user_pub)) - - -@pytest.fixture -def user_user2_threshold(user_pub, user2_pub): - user_pub_keys = [user_pub, user2_pub] - threshold = ThresholdSha256(threshold=len(user_pub_keys)) - for user_pub in user_pub_keys: - threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub))) - return threshold - - -@pytest.fixture -def user2_Ed25519(user2_pub): - return Ed25519Sha256(public_key=b58decode(user2_pub)) - - -@pytest.fixture -def user_input(user_Ed25519, user_pub): - from 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 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 transactions.common.transaction import Input - - return Input(user_user2_threshold, [user_pub, user2_pub]) - - -@pytest.fixture -def user_output(user_Ed25519, user_pub): - from transactions.common.transaction import Output - - return Output(user_Ed25519, [user_pub]) - - -@pytest.fixture -def user2_output(user2_Ed25519, user2_pub): - from transactions.common.transaction import Output - - return Output(user2_Ed25519, [user2_pub]) - - -@pytest.fixture -def asset_definition(): - return ASSET_DEFINITION - - -@pytest.fixture -def data(): - return DATA - - -@pytest.fixture -def utx(user_input, user_output): - from transactions.common.transaction import Transaction - - return Transaction(Transaction.CREATE, {"data": None}, [user_input], [user_output]) - - -@pytest.fixture -def tx(utx, user_priv): - return utx.sign([user_priv]) - - -@pytest.fixture -def transfer_utx(user_output, user2_output, utx): - from transactions.common.transaction import Input, TransactionLink, Transaction - - user_output = user_output.to_dict() - input = Input(utx.outputs[0].fulfillment, user_output["public_keys"], TransactionLink(utx.id, 0)) - return Transaction("TRANSFER", {"id": utx.id}, [input], [user2_output]) - - -@pytest.fixture -def transfer_tx(transfer_utx, user_priv): - return transfer_utx.sign([user_priv]) - - -@pytest.fixture(scope="session") -def dummy_transaction(): - return { - "asset": {"data": None}, - "id": 64 * "a", - "inputs": [ - { - "fulfillment": "dummy", - "fulfills": None, - "owners_before": [58 * "a"], - } - ], - "metadata": None, - "operation": "CREATE", - "outputs": [ - { - "amount": "1", - "condition": { - "details": {"public_key": 58 * "b", "type": "ed25519-sha-256"}, - "uri": "dummy", - }, - "public_keys": [58 * "b"], - } - ], - "version": "2.0", - } - - -@pytest.fixture -def unfulfilled_transaction(): - return { - "asset": {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}, - "id": None, - "inputs": [ - { - # XXX This could be None, see #1925 - # https://github.com/planetmint/planetmint/issues/1925 - "fulfillment": { - "public_key": "JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE", - "type": "ed25519-sha-256", - }, - "fulfills": None, - "owners_before": ["JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE"], - } - ], - "metadata": None, - "operation": "CREATE", - "outputs": [ - { - "amount": "1", - "condition": { - "details": { - "public_key": "JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE", - "type": "ed25519-sha-256", - }, - "uri": "ni:///sha-256;49C5UWNODwtcINxLgLc90bMCFqCymFYONGEmV4a0sG4?fpt=ed25519-sha-256&cost=131072", - }, - "public_keys": ["JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE"], - } - ], - "version": "1.0", - } - - -@pytest.fixture -def fulfilled_transaction(): - return { - "asset": {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}, - "id": None, - "inputs": [ - { - "fulfillment": ( - "pGSAIP_2P1Juh-94sD3uno1lxMPd9EkIalRo7QB014pT6dD9g" - "UANRNxasDy1Dfg9C2Fk4UgHdYFsJzItVYi5JJ_vWc6rKltn0k" - "jagynI0xfyR6X9NhzccTt5oiNH9mThEb4QmagN" - ), - "fulfills": None, - "owners_before": ["JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE"], - } - ], - "metadata": None, - "operation": "CREATE", - "outputs": [ - { - "amount": "1", - "condition": { - "details": { - "public_key": "JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE", - "type": "ed25519-sha-256", - }, - "uri": "ni:///sha-256;49C5UWNODwtcINxLgLc90bMCFqCymFYONGEmV4a0sG4?fpt=ed25519-sha-256&cost=131072", - }, - "public_keys": ["JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE"], - } - ], - "version": "1.0", - } - - -# TODO For reviewers: Pick which approach you like best: parametrized or not? -@pytest.fixture( - params=( - { - "id": None, - "fulfillment": {"public_key": "JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE", "type": "ed25519-sha-256"}, - }, - { - "id": None, - "fulfillment": ( - "pGSAIP_2P1Juh-94sD3uno1lxMPd9EkIalRo7QB014pT6dD9g" - "UANRNxasDy1Dfg9C2Fk4UgHdYFsJzItVYi5JJ_vWc6rKltn0k" - "jagynI0xfyR6X9NhzccTt5oiNH9mThEb4QmagN" - ), - }, - { - "id": "7a7c827cf4ef7985f08f4e9d16f5ffc58ca4e82271921dfbed32e70cb462485f", - "fulfillment": ( - "pGSAIP_2P1Juh-94sD3uno1lxMPd9EkIalRo7QB014pT6dD9g" - "UANRNxasDy1Dfg9C2Fk4UgHdYFsJzItVYi5JJ_vWc6rKltn0k" - "jagynI0xfyR6X9NhzccTt5oiNH9mThEb4QmagN" - ), - }, - ) -) -def tri_state_transaction(request): - tx = { - "asset": {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}, - "id": None, - "inputs": [ - {"fulfillment": None, "fulfills": None, "owners_before": ["JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE"]} - ], - "metadata": None, - "operation": "CREATE", - "outputs": [ - { - "amount": "1", - "condition": { - "details": { - "public_key": "JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE", - "type": "ed25519-sha-256", - }, - "uri": "ni:///sha-256;49C5UWNODwtcINxLgLc90bMCFqCymFYONGEmV4a0sG4?fpt=ed25519-sha-256&cost=131072", - }, - "public_keys": ["JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE"], - } - ], - "version": "2.0", - } - tx["id"] = request.param["id"] - tx["inputs"][0]["fulfillment"] = request.param["fulfillment"] - return tx diff --git a/tests/common/test_memoize.py b/tests/common/test_memoize.py deleted file mode 100644 index 89903c8..0000000 --- a/tests/common/test_memoize.py +++ /dev/null @@ -1,91 +0,0 @@ -# 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 -from copy import deepcopy - -from transactions.common.transaction import Transaction -from transactions.types.assets.create import Create -from transactions.common.crypto import generate_key_pair -from transactions.common.memoize import to_dict, from_dict - - -pytestmark = pytest.mark.bdb - - -def test_memoize_to_dict(b): - alice = generate_key_pair() - asset = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"} - - assert to_dict.cache_info().hits == 0 - assert to_dict.cache_info().misses == 0 - - tx = Create.generate( - [alice.public_key], - [([alice.public_key], 1)], - asset=asset, - ).sign([alice.private_key]) - - tx.to_dict() - - assert to_dict.cache_info().hits == 0 - assert to_dict.cache_info().misses == 1 - - tx.to_dict() - tx.to_dict() - - assert to_dict.cache_info().hits == 2 - assert to_dict.cache_info().misses == 1 - - -def test_memoize_from_dict(b): - alice = generate_key_pair() - asset = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"} - - assert from_dict.cache_info().hits == 0 - assert from_dict.cache_info().misses == 0 - - tx = Create.generate( - [alice.public_key], - [([alice.public_key], 1)], - asset=asset, - ).sign([alice.private_key]) - tx_dict = deepcopy(tx.to_dict()) - - Transaction.from_dict(tx_dict) - - assert from_dict.cache_info().hits == 0 - assert from_dict.cache_info().misses == 1 - - Transaction.from_dict(tx_dict) - Transaction.from_dict(tx_dict) - - assert from_dict.cache_info().hits == 2 - assert from_dict.cache_info().misses == 1 - - -def test_memoize_input_valid(b): - alice = generate_key_pair() - asset = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"} - - assert Transaction._input_valid.cache_info().hits == 0 - assert Transaction._input_valid.cache_info().misses == 0 - - tx = Create.generate( - [alice.public_key], - [([alice.public_key], 1)], - asset=asset, - ).sign([alice.private_key]) - - tx.inputs_valid() - - assert Transaction._input_valid.cache_info().hits == 0 - assert Transaction._input_valid.cache_info().misses == 1 - - tx.inputs_valid() - tx.inputs_valid() - - assert Transaction._input_valid.cache_info().hits == 2 - assert Transaction._input_valid.cache_info().misses == 1 diff --git a/tests/common/test_schema.py b/tests/common/test_schema.py deleted file mode 100644 index cdf400e..0000000 --- a/tests/common/test_schema.py +++ /dev/null @@ -1,142 +0,0 @@ -# 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 - -"""This module is tests related to schema checking, but _not_ of granular schematic -properties related to validation. -""" - -from unittest.mock import patch - -from hypothesis import given -from hypothesis.strategies import from_regex as regex -from pytest import raises - -from transactions.common.exceptions import SchemaValidationError -from transactions.common.schema import ( - TX_SCHEMA_COMMON, - validate_transaction_schema, -) - -SUPPORTED_CRYPTOCONDITION_TYPES = ("threshold-sha-256", "ed25519-sha-256") -UNSUPPORTED_CRYPTOCONDITION_TYPES = ("preimage-sha-256", "prefix-sha-256", "rsa-sha-256") - - -################################################################################ -# Test of schema utils - - -def _test_additionalproperties(node, path=""): - """Validate that each object node has additionalProperties set, so that - objects with junk keys do not pass as valid. - """ - if isinstance(node, list): - for i, nnode in enumerate(node): - _test_additionalproperties(nnode, path + str(i) + ".") - if isinstance(node, dict): - if node.get("type") == "object": - assert "additionalProperties" in node, "additionalProperties not set at path:" + path - for name, val in node.items(): - _test_additionalproperties(val, path + name + ".") - - -def test_transaction_schema_additionalproperties(): - _test_additionalproperties(TX_SCHEMA_COMMON) - - -################################################################################ -# Test call transaction schema - - -def test_validate_transaction_create(create_tx): - validate_transaction_schema(create_tx.to_dict()) - - -def test_validate_transaction_signed_create(signed_create_tx): - validate_transaction_schema(signed_create_tx.to_dict()) - - -def test_validate_transaction_signed_transfer(signed_transfer_tx): - validate_transaction_schema(signed_transfer_tx.to_dict()) - - -def test_validate_transaction_fails(): - with raises(SchemaValidationError): - validate_transaction_schema({}) - - -def test_validate_failure_inconsistent(): - with patch("jsonschema.validate"): - with raises(SchemaValidationError): - validate_transaction_schema({}) - - -@given( - condition_uri=regex( - r"^ni:\/\/\/sha-256;([a-zA-Z0-9_-]{{0,86}})\?fpt=({})" - r"&cost=[0-9]+(?![\n])$".format("|".join(t for t in SUPPORTED_CRYPTOCONDITION_TYPES)) - ) -) -def test_condition_uri_with_supported_fpt(dummy_transaction, condition_uri): - dummy_transaction["outputs"][0]["condition"]["uri"] = condition_uri - validate_transaction_schema(dummy_transaction) - - -@given( - condition_uri=regex( - r"^ni:\/\/\/sha-256;([a-zA-Z0-9_-]{{0,86}})\?fpt=" - r"({})&cost=[0-9]+(?![\n])$".format("|".join(UNSUPPORTED_CRYPTOCONDITION_TYPES)) - ) -) -def test_condition_uri_with_unsupported_fpt(dummy_transaction, condition_uri): - dummy_transaction["outputs"][0]["condition"]["uri"] = condition_uri - with raises(SchemaValidationError): - validate_transaction_schema(dummy_transaction) - - -@given( - condition_uri=regex( - r"^ni:\/\/\/sha-256;([a-zA-Z0-9_-]{{0,86}})\?fpt=(?!{})" - r"&cost=[0-9]+(?![\n])$".format("$|".join(t for t in SUPPORTED_CRYPTOCONDITION_TYPES)) - ) -) -def test_condition_uri_with_unknown_fpt(dummy_transaction, condition_uri): - dummy_transaction["outputs"][0]["condition"]["uri"] = condition_uri - with raises(SchemaValidationError): - validate_transaction_schema(dummy_transaction) - - -@given( - condition_uri=regex( - r"^ni:\/\/\/sha-256;([a-zA-Z0-9_-]{0,86})\?fpt=threshold-sha-256" - r"&cost=[0-9]+&subtypes=ed25519-sha-256(?![\n])$" - ) -) -def test_condition_uri_with_supported_subtype(dummy_transaction, condition_uri): - dummy_transaction["outputs"][0]["condition"]["uri"] = condition_uri - validate_transaction_schema(dummy_transaction) - - -@given( - condition_uri=regex( - r"^ni:\/\/\/sha-256;([a-zA-Z0-9_-]{0,86})\?fpt=threshold-sha-256&cost=" - r"[0-9]+&subtypes=(preimage-sha-256|prefix-sha-256|rsa-sha-256)(?![\n])$" - ) -) -def test_condition_uri_with_unsupported_subtype(dummy_transaction, condition_uri): - dummy_transaction["outputs"][0]["condition"]["uri"] = condition_uri - with raises(SchemaValidationError): - validate_transaction_schema(dummy_transaction) - - -@given( - condition_uri=regex( - r"^ni:\/\/\/sha-256;([a-zA-Z0-9_-]{{0,86}})\?fpt=threshold-sha-256" - r"&cost=[0-9]+&subtypes=(?!{})(?![\n])$".format("$|".join(t for t in SUPPORTED_CRYPTOCONDITION_TYPES)) - ) -) -def test_condition_uri_with_unknown_subtype(dummy_transaction, condition_uri): - dummy_transaction["outputs"][0]["condition"]["uri"] = condition_uri - with raises(SchemaValidationError): - validate_transaction_schema(dummy_transaction) diff --git a/tests/common/test_transaction.py b/tests/common/test_transaction.py deleted file mode 100644 index 752e78e..0000000 --- a/tests/common/test_transaction.py +++ /dev/null @@ -1,886 +0,0 @@ -# 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 - -"""These are tests of the API of the Transaction class and associated classes. -Tests for transaction validation are separate. -""" -import json -from copy import deepcopy - -from base58 import b58encode, b58decode -from transactions.types.assets.create import Create -from transactions.types.assets.transfer import Transfer -from transactions.common.transaction import Output -from transactions.common.transaction import Input -from transactions.common.exceptions import AmountError -from transactions.common.transaction import Transaction -from transactions.common.transaction import TransactionLink -from cryptoconditions import ThresholdSha256 -from cryptoconditions import Fulfillment -from cryptoconditions import PreimageSha256 -from cryptoconditions import Ed25519Sha256 -from pytest import mark, raises - -from hashlib import sha3_256 - -pytestmark = mark.bdb - - -def test_input_serialization(ffill_uri, user_pub): - expected = { - "owners_before": [user_pub], - "fulfillment": ffill_uri, - "fulfills": None, - } - input = Input(Fulfillment.from_uri(ffill_uri), [user_pub]) - assert input.to_dict() == expected - - -def test_input_deserialization_with_uri(ffill_uri, user_pub): - expected = Input(Fulfillment.from_uri(ffill_uri), [user_pub]) - ffill = { - "owners_before": [user_pub], - "fulfillment": ffill_uri, - "fulfills": None, - } - input = Input.from_dict(ffill) - - assert input == expected - - -@mark.skip(reason="None is tolerated because it is None before fulfilling.") -def test_input_deserialization_with_invalid_input(user_pub): - from transactions.common.transaction import Input - - ffill = { - "owners_before": [user_pub], - "fulfillment": None, - "fulfills": None, - } - with raises(TypeError): - Input.from_dict(ffill) - - -def test_input_deserialization_with_invalid_fulfillment_uri(user_pub): - from transactions.common.exceptions import InvalidSignature - from transactions.common.transaction import Input - - ffill = { - "owners_before": [user_pub], - "fulfillment": "an invalid fulfillment", - "fulfills": None, - } - with raises(InvalidSignature): - Input.from_dict(ffill) - - -def test_input_deserialization_with_unsigned_fulfillment(ffill_uri, user_pub): - expected = Input(Fulfillment.from_uri(ffill_uri), [user_pub]) - ffill = { - "owners_before": [user_pub], - "fulfillment": Fulfillment.from_uri(ffill_uri), - "fulfills": None, - } - input = Input.from_dict(ffill) - - assert input == expected - - -def test_output_serialization(user_Ed25519, user_pub): - from transactions.common.transaction import Output - - expected = { - "condition": { - "uri": user_Ed25519.condition_uri, - "details": { - "type": "ed25519-sha-256", - "public_key": b58encode(user_Ed25519.public_key).decode(), - }, - }, - "public_keys": [user_pub], - "amount": "1", - } - - cond = Output(user_Ed25519, [user_pub], 1) - - assert cond.to_dict() == expected - - -def test_output_deserialization(user_Ed25519, user_pub): - from transactions.common.transaction import Output - - expected = Output(user_Ed25519, [user_pub], 1) - cond = { - "condition": { - "uri": user_Ed25519.condition_uri, - "details": { - "type": "ed25519-sha-256", - "public_key": b58encode(user_Ed25519.public_key).decode(), - }, - }, - "public_keys": [user_pub], - "amount": "1", - } - cond = Output.from_dict(cond) - - assert cond == expected - - -def test_output_hashlock_serialization(): - secret = b"wow much secret" - hashlock = PreimageSha256(preimage=secret).condition_uri - - expected = { - "condition": { - "uri": hashlock, - }, - "public_keys": None, - "amount": "1", - } - cond = Output(hashlock, amount=1) - - assert cond.to_dict() == expected - - -def test_output_hashlock_deserialization(): - secret = b"wow much secret" - hashlock = PreimageSha256(preimage=secret).condition_uri - expected = Output(hashlock, amount=1) - - cond = { - "condition": {"uri": hashlock}, - "public_keys": None, - "amount": "1", - } - cond = Output.from_dict(cond) - - assert cond == expected - - -def test_invalid_output_initialization(cond_uri, user_pub): - with raises(TypeError): - Output(cond_uri, user_pub) - with raises(TypeError): - Output(cond_uri, [user_pub], "amount") - with raises(AmountError): - Output(cond_uri, [user_pub], 0) - - -def test_generate_output_split_half_recursive(user_pub, user2_pub, user3_pub): - expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub)) - expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub)) - expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub)) - - expected = ThresholdSha256(threshold=2) - expected.add_subfulfillment(expected_simple1) - expected_threshold = ThresholdSha256(threshold=2) - expected_threshold.add_subfulfillment(expected_simple2) - expected_threshold.add_subfulfillment(expected_simple3) - expected.add_subfulfillment(expected_threshold) - - cond = Output.generate([user_pub, [user2_pub, expected_simple3]], 1) - assert cond.fulfillment.to_dict() == expected.to_dict() - - -def test_generate_outputs_split_half_single_owner(user_pub, user2_pub, user3_pub): - expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub)) - expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub)) - expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub)) - - expected = ThresholdSha256(threshold=2) - expected_threshold = ThresholdSha256(threshold=2) - expected_threshold.add_subfulfillment(expected_simple2) - expected_threshold.add_subfulfillment(expected_simple3) - expected.add_subfulfillment(expected_threshold) - expected.add_subfulfillment(expected_simple1) - - cond = Output.generate([[expected_simple2, user3_pub], user_pub], 1) - assert cond.fulfillment.to_dict() == expected.to_dict() - - -def test_generate_outputs_flat_ownage(user_pub, user2_pub, user3_pub): - expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub)) - expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub)) - expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub)) - - expected = ThresholdSha256(threshold=3) - expected.add_subfulfillment(expected_simple1) - expected.add_subfulfillment(expected_simple2) - expected.add_subfulfillment(expected_simple3) - - cond = Output.generate([user_pub, user2_pub, expected_simple3], 1) - assert cond.fulfillment.to_dict() == expected.to_dict() - - -def test_generate_output_single_owner(user_pub): - expected = Ed25519Sha256(public_key=b58decode(user_pub)) - cond = Output.generate([user_pub], 1) - - assert cond.fulfillment.to_dict() == expected.to_dict() - - -def test_generate_output_single_owner_with_output(user_pub): - expected = Ed25519Sha256(public_key=b58decode(user_pub)) - cond = Output.generate([expected], 1) - - assert cond.fulfillment.to_dict() == expected.to_dict() - - -def test_generate_output_invalid_parameters(user_pub, user2_pub, user3_pub): - from transactions.common.transaction import Output - from transactions.common.exceptions import AmountError - - with raises(ValueError): - Output.generate([], 1) - with raises(TypeError): - Output.generate("not a list", 1) - with raises(ValueError): - Output.generate([[user_pub, [user2_pub, [user3_pub]]]], 1) - with raises(ValueError): - Output.generate([[user_pub]], 1) - with raises(AmountError): - Output.generate([[user_pub]], -1) - - -def test_invalid_transaction_initialization(asset_definition): - with raises(ValueError): - Transaction(operation="invalid operation", asset=asset_definition) - with raises(TypeError): - Transaction(operation="CREATE", asset="invalid asset") - with raises(TypeError): - Transaction(operation="TRANSFER", asset={}) - with raises(TypeError): - Transaction(operation="CREATE", asset=asset_definition, outputs="invalid outputs") - with raises(TypeError): - Transaction(operation="CREATE", asset=asset_definition, outputs=[], inputs="invalid inputs") - with raises(TypeError): - Transaction( - operation="CREATE", asset=asset_definition, outputs=[], inputs=[], metadata={"data": "invalid metadata"} - ) - - -def test_create_default_asset_on_tx_initialization(asset_definition): - expected = {"data": None} - tx = Transaction(Transaction.CREATE, asset=expected) - asset = tx.asset - - assert asset == expected - - -def test_transaction_serialization(user_input, user_output, data): - expected = { - "id": None, - "version": Transaction.VERSION, - # NOTE: This test assumes that Inputs and Outputs can - # successfully be serialized - "inputs": [user_input.to_dict()], - "outputs": [user_output.to_dict()], - "operation": Transaction.CREATE, - "metadata": None, - "asset": { - "data": data, - }, - } - - tx = Transaction(Transaction.CREATE, {"data": data}, [user_input], [user_output]) - tx_dict = tx.to_dict() - - assert tx_dict == expected - - -def test_transaction_deserialization(tri_state_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 transactions.common.transaction import Input - - with raises(TypeError): - Input(user_input, user_pub) - with raises(TypeError): - Input(user_input, tx_input="somethingthatiswrong") - - -def test_transaction_link_serialization(): - - tx_id = "a transaction id" - expected = { - "transaction_id": tx_id, - "output_index": 0, - } - tx_link = TransactionLink(tx_id, 0) - - assert tx_link.to_dict() == expected - - -def test_transaction_link_serialization_with_empty_payload(): - expected = None - tx_link = TransactionLink() - - assert tx_link.to_dict() == expected - - -def test_transaction_link_deserialization(): - tx_id = "a transaction id" - expected = TransactionLink(tx_id, 0) - tx_link = { - "transaction_id": tx_id, - "output_index": 0, - } - tx_link = TransactionLink.from_dict(tx_link) - - assert tx_link == expected - - -def test_transaction_link_deserialization_with_empty_payload(): - expected = TransactionLink() - tx_link = TransactionLink.from_dict(None) - - assert tx_link == expected - - -def test_transaction_link_empty_to_uri(): - expected = None - tx_link = TransactionLink().to_uri() - - assert expected == tx_link - - -def test_transaction_link_to_uri(): - expected = "path/transactions/abc/outputs/0" - tx_link = TransactionLink("abc", 0).to_uri("path") - - assert expected == tx_link - - -def test_cast_transaction_link_to_boolean(): - assert bool(TransactionLink()) is False - assert bool(TransactionLink("a", None)) is False - assert bool(TransactionLink(None, "b")) is False - assert bool(TransactionLink("a", "b")) is True - assert bool(TransactionLink(False, False)) is True - - -def test_transaction_link_eq(): - assert TransactionLink(1, 2) == TransactionLink(1, 2) - assert TransactionLink(2, 2) != TransactionLink(1, 2) - assert TransactionLink(1, 1) != TransactionLink(1, 2) - assert TransactionLink(2, 1) != TransactionLink(1, 2) - - -def test_add_input_to_tx(user_input, asset_definition): - from .utils import validate_transaction_model - - tx = Transaction(Transaction.CREATE, asset_definition, [], []) - tx.add_input(user_input) - - assert len(tx.inputs) == 1 - - validate_transaction_model(tx) - - -def test_add_input_to_tx_with_invalid_parameters(asset_definition): - tx = Transaction(Transaction.CREATE, asset_definition) - - with raises(TypeError): - tx.add_input("somewronginput") - - -def test_add_output_to_tx(user_output, user_input, asset_definition): - from .utils import validate_transaction_model - - tx = Transaction(Transaction.CREATE, asset_definition, [user_input]) - tx.add_output(user_output) - - assert len(tx.outputs) == 1 - - validate_transaction_model(tx) - - -def test_add_output_to_tx_with_invalid_parameters(asset_definition): - tx = Transaction(Transaction.CREATE, asset_definition, [], []) - - with raises(TypeError): - tx.add_output("somewronginput") - - -def test_sign_with_invalid_parameters(utx, user_priv): - with raises(TypeError): - utx.sign(None) - with raises(TypeError): - utx.sign(user_priv) - - -def test_validate_tx_simple_create_signature(user_input, user_output, user_priv, asset_definition): - from .utils import validate_transaction_model - - tx = Transaction(Transaction.CREATE, asset_definition, [user_input], [user_output]) - expected = deepcopy(user_output) - tx_dict = tx.to_dict() - tx_dict["inputs"][0]["fulfillment"] = None - serialized_tx = json.dumps(tx_dict, sort_keys=True, separators=(",", ":"), ensure_ascii=True) - message = sha3_256(serialized_tx.encode()).digest() - expected.fulfillment.sign(message, b58decode(user_priv)) - tx.sign([user_priv]) - - assert tx.inputs[0].to_dict()["fulfillment"] == expected.fulfillment.serialize_uri() - assert tx.inputs_valid() is True - - validate_transaction_model(tx) - - -def test_invoke_simple_signature_fulfillment_with_invalid_params(utx, user_input): - from transactions.common.exceptions import KeypairMismatchException - - with raises(KeypairMismatchException): - invalid_key_pair = {"wrong_pub_key": "wrong_priv_key"} - utx._sign_simple_signature_fulfillment(user_input, "somemessage", invalid_key_pair) - - -def test_sign_threshold_with_invalid_params(utx, user_user2_threshold_input, user3_pub, user3_priv): - from transactions.common.exceptions import KeypairMismatchException - - with raises(KeypairMismatchException): - utx._sign_threshold_signature_fulfillment(user_user2_threshold_input, "somemessage", {user3_pub: user3_priv}) - with raises(KeypairMismatchException): - user_user2_threshold_input.owners_before = [58 * "a"] - utx._sign_threshold_signature_fulfillment(user_user2_threshold_input, "somemessage", None) - - -def test_validate_input_with_invalid_parameters(utx): - input_conditions = [out.fulfillment.condition_uri for out in utx.outputs] - tx_dict = utx.to_dict() - tx_serialized = Transaction._to_str(tx_dict) - valid = utx._input_valid(utx.inputs[0], tx_serialized, input_conditions[0]) - assert not valid - - -def test_validate_tx_threshold_create_signature( - user_user2_threshold_input, - user_user2_threshold_output, - user_pub, - user2_pub, - user_priv, - user2_priv, - asset_definition, -): - from .utils import validate_transaction_model - - tx = Transaction(Transaction.CREATE, asset_definition, [user_user2_threshold_input], [user_user2_threshold_output]) - tx_dict = tx.to_dict() - tx_dict["inputs"][0]["fulfillment"] = None - serialized_tx = json.dumps(tx_dict, sort_keys=True, separators=(",", ":"), ensure_ascii=True) - message = sha3_256(serialized_tx.encode()).digest() - expected = deepcopy(user_user2_threshold_output) - expected.fulfillment.subconditions[0]["body"].sign(message, b58decode(user_priv)) - expected.fulfillment.subconditions[1]["body"].sign(message, b58decode(user2_priv)) - tx.sign([user_priv, user2_priv]) - - assert tx.inputs[0].to_dict()["fulfillment"] == expected.fulfillment.serialize_uri() - assert tx.inputs_valid() is True - - validate_transaction_model(tx) - - -def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv, asset_definition): - threshold = ThresholdSha256(threshold=2) - threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub))) - threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub))) - - threshold_input = Input(threshold, [user_pub, user_pub]) - threshold_output = Output(threshold, [user_pub, user_pub]) - - tx = Transaction(Transaction.CREATE, asset_definition, [threshold_input], [threshold_output]) - - tx_dict = tx.to_dict() - tx_dict["inputs"][0]["fulfillment"] = None - serialized_tx = json.dumps(tx_dict, sort_keys=True, separators=(",", ":"), ensure_ascii=True) - message = sha3_256(serialized_tx.encode()).digest() - - expected = deepcopy(threshold_input) - expected.fulfillment.subconditions[0]["body"].sign(message, b58decode(user_priv)) - expected.fulfillment.subconditions[1]["body"].sign(message, b58decode(user_priv)) - - tx.sign([user_priv, user_priv]) - - subconditions = tx.inputs[0].fulfillment.subconditions - expected_subconditions = expected.fulfillment.subconditions - assert subconditions[0]["body"].to_dict()["signature"] == expected_subconditions[0]["body"].to_dict()["signature"] - assert subconditions[1]["body"].to_dict()["signature"] == expected_subconditions[1]["body"].to_dict()["signature"] - - assert tx.inputs[0].to_dict()["fulfillment"] == expected.fulfillment.serialize_uri() - assert tx.inputs_valid() is True - - -def test_multiple_input_validation_of_transfer_tx( - user_input, user_output, user_priv, user2_pub, user2_priv, user3_pub, user3_priv, asset_definition -): - from .utils import validate_transaction_model - - tx = Transaction(Transaction.CREATE, asset_definition, [user_input], [user_output, deepcopy(user_output)]) - tx.sign([user_priv]) - - inputs = [ - Input(cond.fulfillment, cond.public_keys, TransactionLink(tx.id, index)) - for index, cond in enumerate(tx.outputs) - ] - outputs = [ - Output(Ed25519Sha256(public_key=b58decode(user3_pub)), [user3_pub]), - Output(Ed25519Sha256(public_key=b58decode(user3_pub)), [user3_pub]), - ] - transfer_tx = Transaction("TRANSFER", {"id": tx.id}, inputs, outputs) - transfer_tx = transfer_tx.sign([user_priv]) - - assert transfer_tx.inputs_valid(tx.outputs) is True - - validate_transaction_model(tx) - - -def test_validate_inputs_of_transfer_tx_with_invalid_params( - transfer_tx, cond_uri, utx, user2_pub, user_priv, ffill_uri -): - invalid_out = Output(Ed25519Sha256.from_uri(ffill_uri), ["invalid"]) - assert transfer_tx.inputs_valid([invalid_out]) is False - invalid_out = utx.outputs[0] - invalid_out.public_key = "invalid" - assert transfer_tx.inputs_valid([invalid_out]) is True - - with raises(TypeError): - assert transfer_tx.inputs_valid(None) is False - with raises(AttributeError): - transfer_tx.inputs_valid("not a list") - with raises(ValueError): - transfer_tx.inputs_valid([]) - with raises(TypeError): - transfer_tx.operation = "Operation that doesn't exist" - transfer_tx.inputs_valid([utx.outputs[0]]) - - -def test_create_create_transaction_single_io(user_output, user_pub, data): - from .utils import validate_transaction_model - - expected = { - "outputs": [user_output.to_dict()], - "metadata": data, - "asset": { - "data": data, - }, - "inputs": [{"owners_before": [user_pub], "fulfillment": None, "fulfills": None}], - "operation": "CREATE", - "version": Transaction.VERSION, - } - - tx = Create.generate([user_pub], [([user_pub], 1)], metadata=data, asset={"data": data}) - tx_dict = tx.to_dict() - tx_dict["inputs"][0]["fulfillment"] = None - tx_dict.pop("id") - - assert tx_dict == expected - - validate_transaction_model(tx) - - -def test_validate_single_io_create_transaction(user_pub, user_priv, data, asset_definition): - - tx = Create.generate([user_pub], [([user_pub], 1)], metadata=data) - tx = tx.sign([user_priv]) - assert tx.inputs_valid() is True - - -def test_create_create_transaction_multiple_io(user_output, user2_output, user_pub, user2_pub, asset_definition): - # a fulfillment for a create transaction with multiple `owners_before` - # is a fulfillment for an implicit threshold condition with - # weight = len(owners_before) - input = Input.generate([user_pub, user2_pub]).to_dict() - expected = { - "outputs": [user_output.to_dict(), user2_output.to_dict()], - "metadata": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4", - "inputs": [input], - "operation": "CREATE", - "version": Transaction.VERSION, - } - tx = Create.generate( - [user_pub, user2_pub], - [([user_pub], 1), ([user2_pub], 1)], - metadata="QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4", - ).to_dict() - tx.pop("id") - tx.pop("asset") - - assert tx == expected - - -def test_validate_multiple_io_create_transaction(user_pub, user_priv, user2_pub, user2_priv, asset_definition): - from .utils import validate_transaction_model - - tx = Create.generate( - [user_pub, user2_pub], - [([user_pub], 1), ([user2_pub], 1)], - metadata="QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4", - ) - tx = tx.sign([user_priv, user2_priv]) - assert tx.inputs_valid() is True - - validate_transaction_model(tx) - - -def test_create_create_transaction_threshold( - user_pub, user2_pub, user3_pub, user_user2_threshold_output, user_user2_threshold_input, data -): - expected = { - "outputs": [user_user2_threshold_output.to_dict()], - "metadata": data, - "asset": { - "data": data, - }, - "inputs": [ - { - "owners_before": [ - user_pub, - ], - "fulfillment": None, - "fulfills": None, - }, - ], - "operation": "CREATE", - "version": Transaction.VERSION, - } - tx = Create.generate([user_pub], [([user_pub, user2_pub], 1)], metadata=data, asset={"data": data}) - tx_dict = tx.to_dict() - tx_dict.pop("id") - tx_dict["inputs"][0]["fulfillment"] = None - - assert tx_dict == expected - - -def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub, data, asset_definition): - from .utils import validate_transaction_model - - tx = Create.generate([user_pub], [([user_pub, user2_pub], 1)], metadata=data) - tx = tx.sign([user_priv]) - assert tx.inputs_valid() is True - - validate_transaction_model(tx) - - -def test_create_create_transaction_with_invalid_parameters(user_pub): - with raises(TypeError): - Create.generate("not a list") - with raises(TypeError): - Create.generate([], "not a list") - with raises(ValueError): - Create.generate([], [user_pub]) - with raises(ValueError): - Create.generate([user_pub], []) - with raises(ValueError): - Create.generate([user_pub], [user_pub]) - with raises(ValueError): - Create.generate([user_pub], [([user_pub],)]) - with raises(TypeError): - Create.generate([user_pub], [([user_pub], 1)], metadata={"data": "not a cid string or none"}) - with raises(TypeError): - Create.generate([user_pub], [([user_pub], 1)], asset={"data": "not a dict or none"}) - - -def test_outputs_to_inputs(tx): - inputs = tx.to_inputs([0]) - assert len(inputs) == 1 - input = inputs.pop() - assert input.owners_before == tx.outputs[0].public_keys - assert input.fulfillment == tx.outputs[0].fulfillment - assert input.fulfills.txid == tx.id - assert input.fulfills.output == 0 - - -def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, user2_output, user_priv): - from .utils import validate_transaction_model - - expected = { - "id": None, - "outputs": [user2_output.to_dict()], - "metadata": None, - "asset": { - "id": tx.id, - }, - "inputs": [ - { - "owners_before": [user_pub], - "fulfillment": None, - "fulfills": {"transaction_id": tx.id, "output_index": 0}, - } - ], - "operation": "TRANSFER", - "version": Transaction.VERSION, - } - inputs = tx.to_inputs([0]) - 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() - - expected_input = deepcopy(inputs[0]) - json_serialized_tx = json.dumps(expected, sort_keys=True, separators=(",", ":"), ensure_ascii=True) - message = sha3_256(json_serialized_tx.encode()) - message.update( - "{}{}".format( - expected["inputs"][0]["fulfills"]["transaction_id"], - expected["inputs"][0]["fulfills"]["output_index"], - ).encode() - ) - expected_input.fulfillment.sign(message.digest(), b58decode(user_priv)) - expected_ffill = expected_input.fulfillment.serialize_uri() - transfer_ffill = transfer_tx["inputs"][0]["fulfillment"] - - assert transfer_ffill == expected_ffill - - transfer_tx = Transaction.from_dict(transfer_tx) - assert transfer_tx.inputs_valid([tx.outputs[0]]) is True - - validate_transaction_model(transfer_tx) - - -def test_create_transfer_transaction_multiple_io( - user_pub, user_priv, user2_pub, user2_priv, user3_pub, user2_output, asset_definition -): - tx = Create.generate( - [user_pub], [([user_pub], 1), ([user2_pub], 1)], metadata="QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4" - ) - tx = tx.sign([user_priv]) - - expected = { - "outputs": [user2_output.to_dict(), user2_output.to_dict()], - "metadata": None, - "inputs": [ - { - "owners_before": [user_pub], - "fulfillment": None, - "fulfills": {"transaction_id": tx.id, "output_index": 0}, - }, - { - "owners_before": [user2_pub], - "fulfillment": None, - "fulfills": {"transaction_id": tx.id, "output_index": 1}, - }, - ], - "operation": "TRANSFER", - "version": Transaction.VERSION, - } - - 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]) - - assert len(transfer_tx.inputs) == 2 - assert len(transfer_tx.outputs) == 2 - - assert transfer_tx.inputs_valid(tx.outputs) is True - - transfer_tx = transfer_tx.to_dict() - transfer_tx["inputs"][0]["fulfillment"] = None - transfer_tx["inputs"][1]["fulfillment"] = None - transfer_tx.pop("asset") - transfer_tx.pop("id") - - assert expected == transfer_tx - - -def test_create_transfer_with_invalid_parameters(tx, user_pub): - with raises(TypeError): - Transfer.generate({}, [], tx.id) - with raises(ValueError): - Transfer.generate([], [], tx.id) - with raises(TypeError): - Transfer.generate(["fulfillment"], {}, tx.id) - with raises(ValueError): - Transfer.generate(["fulfillment"], [], tx.id) - with raises(ValueError): - Transfer.generate(["fulfillment"], [user_pub], tx.id) - with raises(ValueError): - Transfer.generate(["fulfillment"], [([user_pub],)], tx.id) - with raises(TypeError): - Transfer.generate(["fulfillment"], [([user_pub], 1)], tx.id, metadata={"data": "not a cid string or none"}) - with raises(TypeError): - Transfer.generate(["fulfillment"], [([user_pub], 1)], ["not a string"]) - - -def test_cant_add_empty_output(): - - tx = Transaction(Transaction.CREATE, None) - - with raises(TypeError): - tx.add_output(None) - - -def test_cant_add_empty_input(): - tx = Transaction(Transaction.CREATE, None) - - with raises(TypeError): - tx.add_input(None) - - -def test_unfulfilled_transaction_serialized(unfulfilled_transaction): - tx_obj = Transaction.from_dict(unfulfilled_transaction) - expected = json.dumps(unfulfilled_transaction, sort_keys=True, separators=(",", ":"), ensure_ascii=True) - assert tx_obj.serialized == expected - - -def test_fulfilled_transaction_serialized(fulfilled_transaction): - tx_obj = Transaction.from_dict(fulfilled_transaction) - expected = json.dumps(fulfilled_transaction, sort_keys=True, separators=(",", ":"), ensure_ascii=True) - assert tx_obj.serialized == expected - - -def test_transaction_hash(fulfilled_transaction): - tx_obj = Transaction.from_dict(fulfilled_transaction) - assert tx_obj._id is None - assert tx_obj.id is None - thing_to_hash = json.dumps(fulfilled_transaction, sort_keys=True, separators=(",", ":"), ensure_ascii=True) - expected_hash_id = sha3_256(thing_to_hash.encode()).hexdigest() - tx_obj._hash() - assert tx_obj._id == expected_hash_id - assert tx_obj.id == expected_hash_id - - -def test_output_from_dict_invalid_amount(user_output): - from transactions.common.transaction import Output - from transactions.common.exceptions import AmountError - - out = user_output.to_dict() - out["amount"] = "a" - with raises(AmountError): - Output.from_dict(out) - - -def test_unspent_outputs_property(merlin, alice, bob, carol): - tx = Create.generate( - [merlin.public_key], - [([alice.public_key], 1), ([bob.public_key], 2), ([carol.public_key], 3)], - asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}, - ).sign([merlin.private_key]) - unspent_outputs = list(tx.unspent_outputs) - assert len(unspent_outputs) == 3 - assert all(utxo.transaction_id == tx.id for utxo in unspent_outputs) - assert all(utxo.asset_id == tx.id for utxo in unspent_outputs) - assert all(utxo.output_index == i for i, utxo in enumerate(unspent_outputs)) - unspent_output_0 = unspent_outputs[0] - assert unspent_output_0.amount == 1 - assert unspent_output_0.condition_uri == Ed25519Sha256(public_key=b58decode(alice.public_key)).condition_uri - unspent_output_1 = unspent_outputs[1] - assert unspent_output_1.amount == 2 - assert unspent_output_1.condition_uri == Ed25519Sha256(public_key=b58decode(bob.public_key)).condition_uri - unspent_output_2 = unspent_outputs[2] - assert unspent_output_2.amount == 3 - assert unspent_output_2.condition_uri == Ed25519Sha256(public_key=b58decode(carol.public_key)).condition_uri - - -def test_spent_outputs_property(signed_transfer_tx): - spent_outputs = list(signed_transfer_tx.spent_outputs) - tx = signed_transfer_tx.to_dict() - assert len(spent_outputs) == 1 - spent_output = spent_outputs[0] - assert spent_output["transaction_id"] == tx["inputs"][0]["fulfills"]["transaction_id"] - assert spent_output["output_index"] == tx["inputs"][0]["fulfills"]["output_index"] - # assert spent_output._asdict() == tx['inputs'][0]['fulfills'] diff --git a/tests/common/utils.py b/tests/common/utils.py deleted file mode 100644 index b110984..0000000 --- a/tests/common/utils.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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 - - -def validate_transaction_model(tx): - from transactions.common.transaction import Transaction - from transactions.common.schema import validate_transaction_schema - - tx_dict = tx.to_dict() - # Check that a transaction is valid by re-serializing it - # And calling validate_transaction_schema - validate_transaction_schema(tx_dict) - Transaction.from_dict(tx_dict)