mirror of
https://github.com/planetmint/planetmint.git
synced 2025-06-08 07:06:38 +00:00
Added Create and Transfer as separate transactions
This commit is contained in:
parent
64f5ec01f1
commit
a421533e16
@ -25,13 +25,13 @@ 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
|
||||
|
||||
|
||||
|
78
planetmint/transactions/types/assets/create.py
Normal file
78
planetmint/transactions/types/assets/create.py
Normal file
@ -0,0 +1,78 @@
|
||||
# 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 planetmint.transactions.common.transaction import (Transaction, Input, Output)
|
||||
|
||||
class Create(Transaction):
|
||||
|
||||
OPERATION = 'CREATE'
|
||||
# NOTE: This class inherits TRANSFER txn type. The `TRANSFER` property is
|
||||
# overriden to re-use methods from parent class
|
||||
TRANSFER = OPERATION
|
||||
ALLOWED_OPERATIONS = (OPERATION,)
|
||||
|
||||
@classmethod
|
||||
def validate(self, tx_signers, recipients, asset, metadata):
|
||||
if not isinstance(tx_signers, list):
|
||||
raise TypeError('`tx_signers` must be a list instance')
|
||||
if not isinstance(recipients, list):
|
||||
raise TypeError('`recipients` must be a list instance')
|
||||
if len(tx_signers) == 0:
|
||||
raise ValueError('`tx_signers` list cannot be empty')
|
||||
if len(recipients) == 0:
|
||||
raise ValueError('`recipients` list cannot be empty')
|
||||
if not (asset is None or isinstance(asset, dict)):
|
||||
raise TypeError('`asset` must be a dict or None')
|
||||
if not (metadata is None or isinstance(metadata, dict)):
|
||||
raise TypeError('`metadata` must be a dict or None')
|
||||
|
||||
inputs = []
|
||||
outputs = []
|
||||
|
||||
# generate_outputs
|
||||
for recipient in recipients:
|
||||
if not isinstance(recipient, tuple) or len(recipient) != 2:
|
||||
raise ValueError(('Each `recipient` in the list must be a'
|
||||
' tuple of `([<list of public keys>],'
|
||||
' <amount>)`'))
|
||||
pub_keys, amount = recipient
|
||||
outputs.append(Output.generate(pub_keys, amount))
|
||||
|
||||
# generate inputs
|
||||
inputs.append(Input.generate(tx_signers))
|
||||
|
||||
return (inputs, outputs)
|
||||
|
||||
@classmethod
|
||||
def generate(cls, tx_signers, recipients, metadata=None, asset=None):
|
||||
"""A simple way to generate a `CREATE` transaction.
|
||||
|
||||
Note:
|
||||
This method currently supports the following Cryptoconditions
|
||||
use cases:
|
||||
- Ed25519
|
||||
- ThresholdSha256
|
||||
|
||||
Additionally, it provides support for the following Planetmint
|
||||
use cases:
|
||||
- Multiple inputs and outputs.
|
||||
|
||||
Args:
|
||||
tx_signers (:obj:`list` of :obj:`str`): A list of keys that
|
||||
represent the signers of the CREATE Transaction.
|
||||
recipients (:obj:`list` of :obj:`tuple`): A list of
|
||||
([keys],amount) that represent the recipients of this
|
||||
Transaction.
|
||||
metadata (dict): The metadata to be stored along with the
|
||||
Transaction.
|
||||
asset (dict): The metadata associated with the asset that will
|
||||
be created in this Transaction.
|
||||
|
||||
Returns:
|
||||
:class:`~planetmint.common.transaction.Transaction`
|
||||
"""
|
||||
|
||||
(inputs, outputs) = cls.validate(tx_signers, recipients, asset, metadata)
|
||||
return cls(cls.OPERATION, {'data': asset}, inputs, outputs, metadata)
|
85
planetmint/transactions/types/assets/transfer.py
Normal file
85
planetmint/transactions/types/assets/transfer.py
Normal file
@ -0,0 +1,85 @@
|
||||
# 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 planetmint.transactions.common.transaction import (Transaction, Input, Output)
|
||||
from planetmint.transactions.common.schema import (_validate_schema,
|
||||
TX_SCHEMA_COMMON,
|
||||
TX_SCHEMA_TRANSFER)
|
||||
from copy import deepcopy
|
||||
|
||||
class Transfer(Transaction):
|
||||
|
||||
OPERATION = 'TRANSFER'
|
||||
# NOTE: This class inherits TRANSFER txn type. The `TRANSFER` property is
|
||||
# overriden to re-use methods from parent class
|
||||
TRANSFER = OPERATION
|
||||
ALLOWED_OPERATIONS = (OPERATION,)
|
||||
|
||||
@classmethod
|
||||
def validate(cls, inputs, recipients, asset_id, metadata):
|
||||
if not isinstance(inputs, list):
|
||||
raise TypeError('`inputs` must be a list instance')
|
||||
if len(inputs) == 0:
|
||||
raise ValueError('`inputs` must contain at least one item')
|
||||
if not isinstance(recipients, list):
|
||||
raise TypeError('`recipients` must be a list instance')
|
||||
if len(recipients) == 0:
|
||||
raise ValueError('`recipients` list cannot be empty')
|
||||
|
||||
outputs = []
|
||||
for recipient in recipients:
|
||||
if not isinstance(recipient, tuple) or len(recipient) != 2:
|
||||
raise ValueError(('Each `recipient` in the list must be a'
|
||||
' tuple of `([<list of public keys>],'
|
||||
' <amount>)`'))
|
||||
pub_keys, amount = recipient
|
||||
outputs.append(Output.generate(pub_keys, amount))
|
||||
|
||||
if not isinstance(asset_id, str):
|
||||
raise TypeError('`asset_id` must be a string')
|
||||
|
||||
return (deepcopy(inputs), outputs)
|
||||
|
||||
@classmethod
|
||||
def generate(cls, inputs, recipients, asset_id, metadata=None):
|
||||
"""A simple way to generate a `TRANSFER` transaction.
|
||||
|
||||
Note:
|
||||
Different cases for threshold conditions:
|
||||
|
||||
Combining multiple `inputs` with an arbitrary number of
|
||||
`recipients` can yield interesting cases for the creation of
|
||||
threshold conditions we'd like to support. The following
|
||||
notation is proposed:
|
||||
|
||||
1. The index of a `recipient` corresponds to the index of
|
||||
an input:
|
||||
e.g. `transfer([input1], [a])`, means `input1` would now be
|
||||
owned by user `a`.
|
||||
|
||||
2. `recipients` can (almost) get arbitrary deeply nested,
|
||||
creating various complex threshold conditions:
|
||||
e.g. `transfer([inp1, inp2], [[a, [b, c]], d])`, means
|
||||
`a`'s signature would have a 50% weight on `inp1`
|
||||
compared to `b` and `c` that share 25% of the leftover
|
||||
weight respectively. `inp2` is owned completely by `d`.
|
||||
|
||||
Args:
|
||||
inputs (:obj:`list` of :class:`~planetmint.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
|
||||
([keys],amount) that represent the recipients of this
|
||||
Transaction.
|
||||
asset_id (str): The asset ID of the asset to be transferred in
|
||||
this Transaction.
|
||||
metadata (dict): Python dictionary to be stored along with the
|
||||
Transaction.
|
||||
|
||||
Returns:
|
||||
:class:`~planetmint.common.transaction.Transaction`
|
||||
"""
|
||||
(inputs, outputs) = cls.validate_transfer(inputs, recipients, asset_id, metadata)
|
||||
return cls(cls.OPERATION, {'id': asset_id}, inputs, outputs, metadata)
|
0
planetmint/transactions/types/elections/__init__.py
Normal file
0
planetmint/transactions/types/elections/__init__.py
Normal file
@ -8,16 +8,18 @@ import base58
|
||||
from uuid import uuid4
|
||||
|
||||
from planetmint import backend
|
||||
from planetmint.elections.vote import Vote
|
||||
from planetmint.common.exceptions import (InvalidSignature,
|
||||
from planetmint.transactions.types.assets.create import Create
|
||||
from planetmint.transactions.types.assets.transfer import Transfer
|
||||
from planetmint.transactions.types.elections.vote import Vote
|
||||
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)
|
||||
|
||||
@ -161,11 +163,11 @@ class Election(Transaction):
|
||||
|
||||
@classmethod
|
||||
def create(cls, tx_signers, recipients, metadata=None, asset=None):
|
||||
raise NotImplementedError
|
||||
Create.generate(tx_signers, recipients, metadata=None, asset=None)
|
||||
|
||||
@classmethod
|
||||
def transfer(cls, tx_signers, recipients, metadata=None, asset=None):
|
||||
raise NotImplementedError
|
||||
Transfer.generate(tx_signers, recipients, metadata=None, asset=None)
|
||||
|
||||
@classmethod
|
||||
def to_public_key(cls, election_id):
|
@ -3,8 +3,10 @@
|
||||
# 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.types.assets.create import Create
|
||||
from planetmint.transactions.types.assets.transfer import Transfer
|
||||
from planetmint.transactions.common.transaction import Transaction
|
||||
from planetmint.transactions.common.schema import (_validate_schema,
|
||||
TX_SCHEMA_COMMON,
|
||||
TX_SCHEMA_TRANSFER,
|
||||
TX_SCHEMA_VOTE)
|
||||
@ -57,8 +59,8 @@ class Vote(Transaction):
|
||||
|
||||
@classmethod
|
||||
def create(cls, tx_signers, recipients, metadata=None, asset=None):
|
||||
raise NotImplementedError
|
||||
return Create.generate(tx_signers, recipients, metadata=None, asset=None)
|
||||
|
||||
@classmethod
|
||||
def transfer(cls, tx_signers, recipients, metadata=None, asset=None):
|
||||
raise NotImplementedError
|
||||
return Transfer.generate(tx_signers, recipients, metadata=None, asset=None)
|
Loading…
x
Reference in New Issue
Block a user