planetmint/tests/validation/test_transaction_structure.py
Lorenz Herzberger e401995637
updated asset migration (#276)
* started replacing asset with assets

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* switched asset_id for asset_ids

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* __init__ transfer now uses multiple assets

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed some test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* added VS Code debugging section to tests/README.md

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed typo

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* minor changes to get_transaction

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* Added ignore for .vscode

* convert cursor to list

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed get_assets

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* Resolved the error of validation for assets

* added additional check to get_transaction

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* adjusted backend queries for multiple assets

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* adjusted common tests for multiple assets

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed db test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed election test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed almost all tendermint tests

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed some command test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed validation test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* added comment to get_transaction_filtered

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed some core test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* Updated the unspent output function of Transaction according to new assets model

* fixed txlist tests

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* added comments to backend get_asset function, removed duplicate

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed further test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed some more tests

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* added TODOs and changed test_client for aiohttp_client

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* Solved assert comparision issue and handled key error with fallback.

* Converted asset to assets in websocket

* Resolved store transaction tests

* added check to fix vote test cases, requires future change

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed some test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed test case

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed test case, added TODO on transaction.py for COMPOSE DECOMPOSE

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed last test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* added planetmint-driver branch reference to dockerfiles for testing

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* Updated asset to assets on the acceptance/integration test suite

* changed get transaction list api point to use comma separated txids

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed acceptance test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* change cryptoconditions to asset-migration branch

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* adjusted doc strings

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed integration tests, removed unused code and adjusted some docstrings

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* adjusted some test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed some test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed some more test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed tendermint test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed web test cases

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* bumped up planetmint-transactions version number

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* resolved linting issues

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* fixed abci test

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

* updated changelog and version umber

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
Co-authored-by: ArpitShukla007 <arpitnshukla@gmail.com>
2022-10-28 11:45:27 +02:00

262 lines
7.7 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
"""All tests of transaction structure. The concern here is that transaction
structural / schematic issues are caught when reading a transaction
(ie going from dict -> transaction).
"""
import json
import pytest
import hashlib as sha3
from unittest.mock import MagicMock
from transactions.common.exceptions import AmountError, SchemaValidationError, ThresholdTooDeep
from transactions.common.transaction import Transaction
from transactions.common.utils import _fulfillment_to_details, _fulfillment_from_details
from ipld import marshal, multihash
################################################################################
# Helper functions
def validate(tx):
if isinstance(tx, Transaction):
tx = tx.to_dict()
Transaction.from_dict(tx, False)
def validate_raises(tx, exc=SchemaValidationError):
with pytest.raises(exc):
validate(tx)
# We should test that validation works when we expect it to
def test_validation_passes(signed_create_tx):
Transaction.from_dict(signed_create_tx.to_dict(), False)
################################################################################
# ID
def test_tx_serialization_hash_function(signed_create_tx):
tx = signed_create_tx.to_dict()
tx["id"] = None
payload = json.dumps(tx, skipkeys=False, sort_keys=True, separators=(",", ":"))
assert sha3.sha3_256(payload.encode()).hexdigest() == signed_create_tx.id
def test_tx_serialization_with_incorrect_hash(signed_create_tx):
from transactions.common.exceptions import InvalidHash
tx = signed_create_tx.to_dict()
tx["id"] = "a" * 64
with pytest.raises(InvalidHash):
Transaction.validate_id(tx)
def test_tx_serialization_with_no_hash(signed_create_tx):
from transactions.common.exceptions import InvalidHash
tx = signed_create_tx.to_dict()
del tx["id"]
with pytest.raises(InvalidHash):
Transaction.from_dict(tx, False)
################################################################################
# Operation
def test_validate_invalid_operation(b, create_tx, alice):
create_tx.operation = "something invalid"
signed_tx = create_tx.sign([alice.private_key])
validate_raises(signed_tx)
################################################################################
# Metadata
def test_validate_fails_metadata_empty_dict(b, create_tx, alice):
create_tx.metadata = multihash(marshal({"a": 1}))
signed_tx = create_tx.sign([alice.private_key])
validate(signed_tx)
create_tx._id = None
create_tx.fulfillment = None
create_tx.metadata = None
signed_tx = create_tx.sign([alice.private_key])
validate(signed_tx)
create_tx._id = None
create_tx.fulfillment = None
create_tx.metadata = {}
signed_tx = create_tx.sign([alice.private_key])
validate_raises(signed_tx)
################################################################################
# Asset
def test_transfer_asset_schema(user_sk, signed_transfer_tx):
from transactions.common.transaction import Transaction
tx = signed_transfer_tx.to_dict()
validate(tx)
tx["id"] = None
tx["assets"][0]["data"] = {}
tx = Transaction.from_dict(tx).sign([user_sk]).to_dict()
validate_raises(tx)
tx["id"] = None
del tx["assets"][0]["data"]
tx["assets"][0]["id"] = "b" * 63
tx = Transaction.from_dict(tx).sign([user_sk]).to_dict()
validate_raises(tx)
def test_create_tx_no_asset_id(b, create_tx, alice):
create_tx.assets[0]["id"] = "b" * 64
signed_tx = create_tx.sign([alice.private_key])
validate_raises(signed_tx)
def test_create_tx_asset_type(b, create_tx, alice):
create_tx.assets[0]["data"] = multihash(marshal({"a": ""}))
signed_tx = create_tx.sign([alice.private_key])
validate(signed_tx)
# validate_raises(signed_tx)
def test_create_tx_no_asset_data(b, create_tx, alice):
tx_body = create_tx.to_dict()
del tx_body["assets"][0]["data"]
tx_serialized = json.dumps(tx_body, skipkeys=False, sort_keys=True, separators=(",", ":"))
tx_body["id"] = sha3.sha3_256(tx_serialized.encode()).hexdigest()
validate_raises(tx_body)
################################################################################
# Inputs
def test_no_inputs(b, create_tx, alice):
create_tx.inputs = []
signed_tx = create_tx.sign([alice.private_key])
validate_raises(signed_tx)
def test_create_single_input(b, create_tx, alice):
from 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()
validate_raises(tx)
tx["id"] = None
tx["inputs"] = []
tx = Transaction.from_dict(tx).sign([alice.private_key]).to_dict()
validate_raises(tx)
def test_create_tx_no_fulfills(b, create_tx, alice):
from transactions.common.transaction import Transaction
tx = create_tx.to_dict()
tx["inputs"][0]["fulfills"] = {"transaction_id": "a" * 64, "output_index": 0}
tx = Transaction.from_dict(tx).sign([alice.private_key]).to_dict()
validate_raises(tx)
def test_transfer_has_inputs(user_sk, signed_transfer_tx, alice):
signed_transfer_tx.inputs = []
signed_transfer_tx._id = None
signed_transfer_tx.sign([user_sk])
validate_raises(signed_transfer_tx)
################################################################################
# Outputs
def test_low_amounts(b, user_sk, create_tx, signed_transfer_tx, alice):
for sk, tx in [(alice.private_key, create_tx), (user_sk, signed_transfer_tx)]:
tx.outputs[0].amount = 0
tx._id = None
tx.sign([sk])
validate_raises(tx, AmountError)
tx.outputs[0].amount = -1
tx._id = None
tx.sign([sk])
validate_raises(tx)
def test_high_amounts(b, create_tx, alice):
# Should raise a SchemaValidationError - don't want to allow ridiculously
# large numbers to get converted to int
create_tx.outputs[0].amount = 10**21
create_tx.sign([alice.private_key])
validate_raises(create_tx)
# Should raise AmountError
create_tx.outputs[0].amount = 9 * 10**18 + 1
create_tx._id = None
create_tx.sign([alice.private_key])
validate_raises(create_tx, AmountError)
# Should pass
create_tx.outputs[0].amount -= 1
create_tx._id = None
create_tx.sign([alice.private_key])
validate(create_tx)
################################################################################
# Conditions
def test_handle_threshold_overflow():
cond = {
"type": "ed25519-sha-256",
"public_key": "a" * 43,
}
for i in range(1000):
cond = {
"type": "threshold-sha-256",
"threshold": 1,
"subconditions": [cond],
}
with pytest.raises(ThresholdTooDeep):
_fulfillment_from_details(cond)
def test_unsupported_condition_type():
from cryptoconditions.exceptions import UnsupportedTypeError
with pytest.raises(UnsupportedTypeError):
_fulfillment_from_details({"type": "a"})
with pytest.raises(UnsupportedTypeError):
_fulfillment_to_details(MagicMock(type_name="a"))
################################################################################
# Version
def test_validate_version(b, create_tx, alice):
create_tx.version = "3.0"
create_tx.sign([alice.private_key])
validate(create_tx)
create_tx.version = "0.10"
create_tx._id = None
create_tx.sign([alice.private_key])
validate_raises(create_tx)
create_tx.version = "110"
create_tx._id = None
create_tx.sign([alice.private_key])
validate_raises(create_tx)