From e9b7aa0fc552e9ee1971efc4f4c58e8e78636624 Mon Sep 17 00:00:00 2001 From: ArpitShukla007 Date: Wed, 9 Mar 2022 17:10:37 +0000 Subject: [PATCH] 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