mirror of
https://github.com/planetmint/planetmint.git
synced 2025-06-05 13:46:37 +00:00
Added new classes in transactions/common
This commit is contained in:
parent
64f5ec01f1
commit
e9b7aa0fc5
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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__)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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__)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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():
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
224
planetmint/transactions/common/output.py
Normal file
224
planetmint/transactions/common/output.py
Normal file
@ -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)
|
@ -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__)
|
||||
|
@ -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:
|
||||
`/<tx_id>/transaction/outputs/<output>/`.
|
||||
|
||||
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)
|
||||
|
99
planetmint/transactions/common/transaction_link.py
Normal file
99
planetmint/transactions/common/transaction_link.py
Normal file
@ -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:
|
||||
`/<tx_id>/transaction/outputs/<output>/`.
|
||||
|
||||
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)
|
@ -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'))
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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']
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
2
setup.py
2
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']},
|
||||
)
|
||||
|
@ -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()})
|
||||
|
@ -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()})
|
||||
|
@ -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()
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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])
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from planetmint.common.transaction import TransactionLink
|
||||
from planetmint.transactions.common.transaction import TransactionLink
|
||||
from planetmint.models import Transaction
|
||||
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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):
|
||||
|
@ -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'
|
||||
|
@ -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)],
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user