mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-28 00:58:09 +00:00
nem: big refactoring of serialization
protocol classes are now used; reflected in unit tests
This commit is contained in:
parent
561ca35a08
commit
d54d33df3a
@ -3,13 +3,13 @@ from trezor.messages.wire_types import NEMGetAddress, NEMSignTx
|
|||||||
|
|
||||||
|
|
||||||
def dispatch_NemGetAddress(*args, **kwargs):
|
def dispatch_NemGetAddress(*args, **kwargs):
|
||||||
from .get_address import nem_get_address
|
from .get_address import get_address
|
||||||
return nem_get_address(*args, **kwargs)
|
return get_address(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def dispatch_NemSignTx(*args, **kwargs):
|
def dispatch_NemSignTx(*args, **kwargs):
|
||||||
from .signing import nem_sign_tx
|
from .signing import sign_tx
|
||||||
return nem_sign_tx(*args, **kwargs)
|
return sign_tx(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def boot():
|
def boot():
|
||||||
|
@ -8,7 +8,7 @@ from trezor.ui.text import Text
|
|||||||
from trezor.utils import chunks
|
from trezor.utils import chunks
|
||||||
|
|
||||||
|
|
||||||
async def nem_get_address(ctx, msg):
|
async def get_address(ctx, msg):
|
||||||
network = validate_network(msg.network)
|
network = validate_network(msg.network)
|
||||||
node = await seed.derive_node(ctx, msg.address_n, NEM_CURVE)
|
node = await seed.derive_node(ctx, msg.address_n, NEM_CURVE)
|
||||||
address = node.nem_address(network)
|
address = node.nem_address(network)
|
||||||
@ -23,7 +23,6 @@ async def nem_get_address(ctx, msg):
|
|||||||
|
|
||||||
async def _show_address(ctx, address: str, network: int):
|
async def _show_address(ctx, address: str, network: int):
|
||||||
lines = _split_address(address)
|
lines = _split_address(address)
|
||||||
print(network)
|
|
||||||
content = Text('Export NEM address', ui.ICON_RECEIVE,
|
content = Text('Export NEM address', ui.ICON_RECEIVE,
|
||||||
ui.MONO, _get_network_str(network) + ' network',
|
ui.MONO, _get_network_str(network) + ' network',
|
||||||
ui.MONO, *lines,
|
ui.MONO, *lines,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
from micropython import const
|
from micropython import const
|
||||||
|
from trezor.messages.NEMSignTx import NEMSignTx
|
||||||
|
|
||||||
|
|
||||||
NEM_NETWORK_MAINNET = const(0x68)
|
NEM_NETWORK_MAINNET = const(0x68)
|
||||||
NEM_NETWORK_TESTNET = const(0x98)
|
NEM_NETWORK_TESTNET = const(0x98)
|
||||||
|
@ -55,7 +55,6 @@ async def require_confirm_payload(ctx, payload: bytes, encrypt=False):
|
|||||||
|
|
||||||
if len(payload) > 48:
|
if len(payload) > 48:
|
||||||
payload = payload[:48] + '..'
|
payload = payload[:48] + '..'
|
||||||
print(len(payload))
|
|
||||||
if encrypt:
|
if encrypt:
|
||||||
content = Text('Confirm payload', ui.ICON_SEND,
|
content = Text('Confirm payload', ui.ICON_SEND,
|
||||||
ui.BOLD, 'Encrypted:',
|
ui.BOLD, 'Encrypted:',
|
||||||
|
@ -1,79 +1,84 @@
|
|||||||
|
|
||||||
from .helpers import *
|
|
||||||
from .writers import *
|
from .writers import *
|
||||||
from trezor.messages.NEMMosaic import NEMMosaic
|
from trezor.messages.NEMMosaic import NEMMosaic
|
||||||
|
from trezor.messages import NEMSupplyChangeType
|
||||||
|
from apps.nem.layout import *
|
||||||
|
|
||||||
|
|
||||||
def nem_transaction_create_mosaic_creation(network: int, timestamp: int, signer_public_key: bytes, fee:int,
|
async def ask_mosaic_creation(ctx, msg: NEMSignTx):
|
||||||
deadline: int, namespace: str, mosaic: str, description: str,
|
await require_confirm_action(ctx, 'Create mosaic "' + msg.mosaic_creation.definition.mosaic + '" under namespace "'
|
||||||
divisibility: int, supply: int, mutable_supply: bool, transferable: bool,
|
+ msg.mosaic_creation.definition.namespace + '"?')
|
||||||
levy_type: int, levy_fee: int, levy_address: str, levy_namespace: str,
|
await require_confirm_properties(ctx, msg.mosaic_creation.definition)
|
||||||
levy_mosaic: str, creation_sink: str, creation_fee: int):
|
await require_confirm_fee(ctx, 'Confirm creation fee', msg.mosaic_creation.fee)
|
||||||
|
|
||||||
w = nem_transaction_write_common(NEM_TRANSACTION_TYPE_MOSAIC_CREATION,
|
await require_confirm_final(ctx, msg.transaction.fee)
|
||||||
nem_get_version(network),
|
|
||||||
timestamp,
|
|
||||||
signer_public_key,
|
async def ask_mosaic_supply_change(ctx, msg: NEMSignTx):
|
||||||
fee,
|
await require_confirm_action(ctx, 'Modify supply for "' + msg.supply_change.mosaic + '" under namespace "'
|
||||||
deadline)
|
+ msg.supply_change.namespace + '"?')
|
||||||
|
if msg.supply_change.type == NEMSupplyChangeType.SupplyChange_Decrease:
|
||||||
|
ask_msg = 'Decrease supply by ' + str(msg.supply_change.delta) + ' whole units?'
|
||||||
|
elif msg.supply_change.type == NEMSupplyChangeType.SupplyChange_Increase:
|
||||||
|
ask_msg = 'Increase supply by ' + str(msg.supply_change.delta) + ' whole units?'
|
||||||
|
else:
|
||||||
|
raise ValueError('Invalid supply change type')
|
||||||
|
await require_confirm_action(ctx, ask_msg)
|
||||||
|
|
||||||
|
await require_confirm_final(ctx, msg.transaction.fee)
|
||||||
|
|
||||||
|
|
||||||
|
def serialize_mosaic_creation(msg: NEMSignTx, public_key: bytes):
|
||||||
|
w = write_common(msg.transaction, bytearray(public_key), NEM_TRANSACTION_TYPE_MOSAIC_CREATION)
|
||||||
|
|
||||||
mosaics_w = bytearray()
|
mosaics_w = bytearray()
|
||||||
write_bytes_with_length(mosaics_w, bytearray(signer_public_key))
|
write_bytes_with_length(mosaics_w, bytearray(public_key))
|
||||||
identifier_length = 4 + len(namespace) + 4 + len(mosaic)
|
identifier_length = 4 + len(msg.mosaic_creation.definition.namespace) + 4 + len(msg.mosaic_creation.definition.mosaic)
|
||||||
write_uint32(mosaics_w, identifier_length)
|
write_uint32(mosaics_w, identifier_length)
|
||||||
write_bytes_with_length(mosaics_w, bytearray(namespace))
|
write_bytes_with_length(mosaics_w, bytearray(msg.mosaic_creation.definition.namespace))
|
||||||
write_bytes_with_length(mosaics_w, bytearray(mosaic))
|
write_bytes_with_length(mosaics_w, bytearray(msg.mosaic_creation.definition.mosaic))
|
||||||
write_bytes_with_length(mosaics_w, bytearray(description))
|
write_bytes_with_length(mosaics_w, bytearray(msg.mosaic_creation.definition.description))
|
||||||
write_uint32(mosaics_w, 4) # number of properties
|
write_uint32(mosaics_w, 4) # number of properties
|
||||||
|
|
||||||
nem_write_mosaic(mosaics_w, "divisibility", divisibility)
|
_write_property(mosaics_w, "divisibility", msg.mosaic_creation.definition.divisibility)
|
||||||
nem_write_mosaic(mosaics_w, "initialSupply", supply)
|
_write_property(mosaics_w, "initialSupply", msg.mosaic_creation.definition.supply)
|
||||||
nem_write_mosaic(mosaics_w, "supplyMutable", mutable_supply)
|
_write_property(mosaics_w, "supplyMutable", msg.mosaic_creation.definition.mutable_supply)
|
||||||
nem_write_mosaic(mosaics_w, "transferable", transferable)
|
_write_property(mosaics_w, "transferable", msg.mosaic_creation.definition.transferable)
|
||||||
|
|
||||||
if levy_type:
|
if msg.mosaic_creation.definition.levy:
|
||||||
levy_identifier_length = 4 + len(levy_namespace) + 4 + len(levy_mosaic)
|
levy_identifier_length = 4 + len(msg.mosaic_creation.definition.levy_namespace) + 4 + len(msg.mosaic_creation.definition.levy_mosaic)
|
||||||
write_uint32(mosaics_w, 4 + 4 + len(levy_address) + 4 + levy_identifier_length + 8)
|
write_uint32(mosaics_w, 4 + 4 + len(msg.mosaic_creation.definition.levy_address) + 4 + levy_identifier_length + 8)
|
||||||
write_uint32(mosaics_w, levy_type)
|
write_uint32(mosaics_w, msg.mosaic_creation.definition.levy)
|
||||||
write_bytes_with_length(mosaics_w, bytearray(levy_address))
|
write_bytes_with_length(mosaics_w, bytearray(msg.mosaic_creation.definition.levy_address))
|
||||||
write_uint32(mosaics_w, levy_identifier_length)
|
write_uint32(mosaics_w, levy_identifier_length)
|
||||||
write_bytes_with_length(mosaics_w, bytearray(levy_namespace))
|
write_bytes_with_length(mosaics_w, bytearray(msg.mosaic_creation.definition.levy_namespace))
|
||||||
write_bytes_with_length(mosaics_w, bytearray(levy_mosaic))
|
write_bytes_with_length(mosaics_w, bytearray(msg.mosaic_creation.definition.levy_mosaic))
|
||||||
write_uint64(mosaics_w, levy_fee)
|
write_uint64(mosaics_w, msg.mosaic_creation.definition.fee)
|
||||||
else:
|
else:
|
||||||
write_uint32(mosaics_w, 0)
|
write_uint32(mosaics_w, 0)
|
||||||
|
|
||||||
# write mosaic bytes with length
|
# write mosaic bytes with length
|
||||||
write_bytes_with_length(w, mosaics_w)
|
write_bytes_with_length(w, mosaics_w)
|
||||||
|
|
||||||
write_bytes_with_length(w, bytearray(creation_sink))
|
write_bytes_with_length(w, bytearray(msg.mosaic_creation.sink))
|
||||||
write_uint64(w, creation_fee)
|
write_uint64(w, msg.mosaic_creation.fee)
|
||||||
|
|
||||||
return w
|
return w
|
||||||
|
|
||||||
|
|
||||||
def nem_transaction_create_mosaic_supply_change(network: int, timestamp: int, signer_public_key: bytes, fee: int,
|
def serialize_mosaic_supply_change(msg: NEMSignTx, public_key: bytes):
|
||||||
deadline: int, namespace: str, mosaic: str, type: int, delta: int):
|
w = write_common(msg.transaction, bytearray(public_key), NEM_TRANSACTION_TYPE_MOSAIC_SUPPLY_CHANGE)
|
||||||
|
|
||||||
w = nem_transaction_write_common(NEM_TRANSACTION_TYPE_MOSAIC_SUPPLY_CHANGE,
|
identifier_length = 4 + len(msg.supply_change.namespace) + 4 + len(msg.supply_change.mosaic)
|
||||||
nem_get_version(network),
|
|
||||||
timestamp,
|
|
||||||
signer_public_key,
|
|
||||||
fee,
|
|
||||||
deadline)
|
|
||||||
|
|
||||||
identifier_length = 4 + len(namespace) + 4 + len(mosaic)
|
|
||||||
write_uint32(w, identifier_length)
|
write_uint32(w, identifier_length)
|
||||||
write_bytes_with_length(w, bytearray(namespace))
|
write_bytes_with_length(w, bytearray(msg.supply_change.namespace))
|
||||||
write_bytes_with_length(w, bytearray(mosaic))
|
write_bytes_with_length(w, bytearray(msg.supply_change.mosaic))
|
||||||
|
|
||||||
write_uint32(w, type)
|
|
||||||
write_uint64(w, delta)
|
|
||||||
|
|
||||||
|
write_uint32(w, msg.supply_change.type)
|
||||||
|
write_uint64(w, msg.supply_change.delta)
|
||||||
return w
|
return w
|
||||||
|
|
||||||
|
|
||||||
def nem_write_mosaic(w: bytearray, name: str, value):
|
def _write_property(w: bytearray, name: str, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
if name in ['divisibility', 'initialSupply']:
|
if name in ['divisibility', 'initialSupply']:
|
||||||
value = 0
|
value = 0
|
||||||
@ -93,7 +98,7 @@ def nem_write_mosaic(w: bytearray, name: str, value):
|
|||||||
write_bytes_with_length(w, bytearray(value))
|
write_bytes_with_length(w, bytearray(value))
|
||||||
|
|
||||||
|
|
||||||
def nem_transaction_write_mosaic(w: bytearray, namespace: str, mosaic: str, quantity: int):
|
def serialize_mosaic(w: bytearray, namespace: str, mosaic: str, quantity: int):
|
||||||
identifier_length = 4 + len(namespace) + 4 + len(mosaic)
|
identifier_length = 4 + len(namespace) + 4 + len(mosaic)
|
||||||
# indentifier length (u32) + quantity (u64) + identifier size
|
# indentifier length (u32) + quantity (u64) + identifier size
|
||||||
write_uint32(w, 4 + 8 + identifier_length)
|
write_uint32(w, 4 + 8 + identifier_length)
|
||||||
@ -103,11 +108,11 @@ def nem_transaction_write_mosaic(w: bytearray, namespace: str, mosaic: str, quan
|
|||||||
write_uint64(w, quantity)
|
write_uint64(w, quantity)
|
||||||
|
|
||||||
|
|
||||||
def nem_canonicalize_mosaics(mosaics: list):
|
def canonicalize_mosaics(mosaics: list):
|
||||||
if len(mosaics) <= 1:
|
if len(mosaics) <= 1:
|
||||||
return mosaics
|
return mosaics
|
||||||
mosaics = nem_merge_mosaics(mosaics)
|
mosaics = merge_mosaics(mosaics)
|
||||||
return nem_sort_mosaics(mosaics)
|
return sort_mosaics(mosaics)
|
||||||
|
|
||||||
|
|
||||||
def are_mosaics_equal(a: NEMMosaic, b: NEMMosaic) -> bool:
|
def are_mosaics_equal(a: NEMMosaic, b: NEMMosaic) -> bool:
|
||||||
@ -116,7 +121,7 @@ def are_mosaics_equal(a: NEMMosaic, b: NEMMosaic) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def nem_merge_mosaics(mosaics: list) -> list:
|
def merge_mosaics(mosaics: list) -> list:
|
||||||
if not len(mosaics):
|
if not len(mosaics):
|
||||||
return list()
|
return list()
|
||||||
ret = list()
|
ret = list()
|
||||||
@ -131,5 +136,5 @@ def nem_merge_mosaics(mosaics: list) -> list:
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def nem_sort_mosaics(mosaics: list) -> list:
|
def sort_mosaics(mosaics: list) -> list:
|
||||||
return sorted(mosaics, key=lambda m: (m.namespace, m.mosaic))
|
return sorted(mosaics, key=lambda m: (m.namespace, m.mosaic))
|
||||||
|
@ -1,38 +1,73 @@
|
|||||||
|
|
||||||
from .helpers import *
|
|
||||||
from .writers import *
|
from .writers import *
|
||||||
|
from apps.nem.layout import *
|
||||||
from trezor.crypto import hashlib
|
from trezor.crypto import hashlib
|
||||||
|
from trezor.messages import NEMModificationType
|
||||||
|
from trezor.crypto import nem
|
||||||
|
|
||||||
|
|
||||||
def nem_transaction_create_multisig(network: int, timestamp: int, signer_public_key: bytes,
|
async def ask_multisig(ctx, msg: NEMSignTx):
|
||||||
fee: int, deadline: int, inner: bytes):
|
# todo
|
||||||
|
await require_confirm_action(ctx, 'Multisig?')
|
||||||
|
|
||||||
w = nem_transaction_write_common(NEM_TRANSACTION_TYPE_MULTISIG,
|
|
||||||
nem_get_version(network),
|
|
||||||
timestamp,
|
|
||||||
signer_public_key,
|
|
||||||
fee,
|
|
||||||
deadline)
|
|
||||||
|
|
||||||
|
async def ask_aggregate_modification(ctx, msg: NEMSignTx):
|
||||||
|
if not msg.multisig:
|
||||||
|
await require_confirm_action(ctx, 'Convert account to multisig account?')
|
||||||
|
|
||||||
|
for m in msg.aggregate_modification.modifications:
|
||||||
|
if m.type == NEMModificationType.CosignatoryModification_Add:
|
||||||
|
action = 'Add'
|
||||||
|
else:
|
||||||
|
action = 'Remove'
|
||||||
|
address = nem.compute_address(m.public_key, msg.transaction.network)
|
||||||
|
await require_confirm_address(ctx, action + ' cosignatory?', address)
|
||||||
|
|
||||||
|
if msg.aggregate_modification.relative_change:
|
||||||
|
if not msg.multisig:
|
||||||
|
action = 'Set minimum cosignatories to '
|
||||||
|
else:
|
||||||
|
action = 'Modify the number of cosignatories by '
|
||||||
|
await require_confirm_action(ctx, action + str(msg.aggregate_modification.relative_change) + '?')
|
||||||
|
|
||||||
|
await require_confirm_final(ctx, msg.transaction.fee)
|
||||||
|
|
||||||
|
|
||||||
|
def serialize_multisig(msg: NEMTransactionCommon, public_key: bytes, inner: bytes):
|
||||||
|
w = write_common(msg, bytearray(public_key), NEM_TRANSACTION_TYPE_MULTISIG)
|
||||||
write_bytes_with_length(w, bytearray(inner))
|
write_bytes_with_length(w, bytearray(inner))
|
||||||
|
|
||||||
return w
|
return w
|
||||||
|
|
||||||
|
|
||||||
def nem_transaction_create_multisig_signature(network: int, timestamp: int, signer_public_key: bytes,
|
def serialize_multisig_signature(msg: NEMTransactionCommon, public_key: bytes, inner: bytes, address: str):
|
||||||
fee: int, deadline: int, inner: bytes, address: str):
|
w = write_common(msg, bytearray(public_key), NEM_TRANSACTION_TYPE_MULTISIG_SIGNATURE)
|
||||||
|
digest = hashlib.sha3_256(inner).digest(True)
|
||||||
|
|
||||||
w = nem_transaction_write_common(NEM_TRANSACTION_TYPE_MULTISIG_SIGNATURE,
|
write_uint32(w, 4 + len(digest))
|
||||||
nem_get_version(network),
|
write_bytes_with_length(w, digest)
|
||||||
timestamp,
|
|
||||||
signer_public_key,
|
|
||||||
fee,
|
|
||||||
deadline)
|
|
||||||
|
|
||||||
hash = hashlib.sha3_256(inner).digest(True)
|
|
||||||
|
|
||||||
write_uint32(w, 4 + len(hash))
|
|
||||||
write_bytes_with_length(w, hash)
|
|
||||||
write_bytes_with_length(w, address)
|
write_bytes_with_length(w, address)
|
||||||
|
|
||||||
return w
|
return w
|
||||||
|
|
||||||
|
|
||||||
|
def serialize_aggregate_modification(msg: NEMSignTx, public_key: bytes):
|
||||||
|
version = msg.transaction.network << 24 | 1
|
||||||
|
if msg.aggregate_modification.relative_change:
|
||||||
|
version = msg.transaction.network << 24 | 2
|
||||||
|
|
||||||
|
w = write_common(msg.transaction,
|
||||||
|
bytearray(public_key),
|
||||||
|
NEM_TRANSACTION_TYPE_AGGREGATE_MODIFICATION,
|
||||||
|
version)
|
||||||
|
write_uint32(w, len(msg.aggregate_modification.modifications))
|
||||||
|
return w
|
||||||
|
|
||||||
|
|
||||||
|
def serialize_cosignatory_modification(w: bytearray, type: int, cosignatory_pubkey: bytes):
|
||||||
|
write_uint32(w, 4 + 4 + len(cosignatory_pubkey))
|
||||||
|
write_uint32(w, type)
|
||||||
|
write_bytes_with_length(w, bytearray(cosignatory_pubkey))
|
||||||
|
return w
|
||||||
|
|
||||||
|
|
||||||
|
def serialize_minimum_cosignatories(w: bytearray, relative_change: int):
|
||||||
|
write_uint32(w, 4)
|
||||||
|
write_uint32(w, relative_change)
|
||||||
|
29
src/apps/nem/namespace.py
Normal file
29
src/apps/nem/namespace.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from .writers import *
|
||||||
|
from apps.nem.layout import *
|
||||||
|
|
||||||
|
|
||||||
|
async def ask_provision_namespace(ctx, msg: NEMSignTx):
|
||||||
|
if msg.provision_namespace.parent:
|
||||||
|
await require_confirm_action(ctx, 'Create namespace "' + msg.provision_namespace.namespace + '"' +
|
||||||
|
'under namespace "' + msg.provision_namespace.parent + '"?')
|
||||||
|
else:
|
||||||
|
await require_confirm_action(ctx, 'Create namespace "' + msg.provision_namespace.namespace + '"?')
|
||||||
|
await require_confirm_fee(ctx, 'Confirm rental fee', msg.provision_namespace.fee)
|
||||||
|
|
||||||
|
await require_confirm_final(ctx, msg.transaction.fee)
|
||||||
|
|
||||||
|
|
||||||
|
def serialize_provision_namespace(msg: NEMSignTx, public_key: bytes) -> bytearray:
|
||||||
|
tx = write_common(msg.transaction,
|
||||||
|
bytearray(public_key),
|
||||||
|
NEM_TRANSACTION_TYPE_PROVISION_NAMESPACE)
|
||||||
|
|
||||||
|
write_bytes_with_length(tx, bytearray(msg.provision_namespace.sink))
|
||||||
|
write_uint64(tx, msg.provision_namespace.fee)
|
||||||
|
write_bytes_with_length(tx, bytearray(msg.provision_namespace.namespace))
|
||||||
|
if msg.provision_namespace.parent:
|
||||||
|
write_bytes_with_length(tx, bytearray(msg.provision_namespace.parent))
|
||||||
|
else:
|
||||||
|
write_uint32(tx, 0xffffffff)
|
||||||
|
|
||||||
|
return tx
|
@ -1,36 +1,37 @@
|
|||||||
from apps.nem.layout import *
|
from apps.nem.transfer import *
|
||||||
from apps.nem.transaction import *
|
from apps.nem.multisig import *
|
||||||
|
from apps.nem.namespace import *
|
||||||
from apps.nem.mosaic import *
|
from apps.nem.mosaic import *
|
||||||
from apps.nem.validators import validate
|
from apps.nem.validators import validate
|
||||||
from apps.nem import helpers
|
from apps.nem import helpers
|
||||||
from apps.common import seed
|
from apps.common import seed
|
||||||
from trezor.messages import NEMSupplyChangeType
|
|
||||||
from trezor.messages import NEMModificationType
|
|
||||||
from trezor.messages import NEMImportanceTransferMode
|
|
||||||
from trezor.messages.NEMSignTx import NEMSignTx
|
from trezor.messages.NEMSignTx import NEMSignTx
|
||||||
from trezor.messages.NEMSignedTx import NEMSignedTx
|
from trezor.messages.NEMSignedTx import NEMSignedTx
|
||||||
from trezor.crypto.curve import ed25519
|
from trezor.crypto.curve import ed25519
|
||||||
from trezor.crypto import random
|
|
||||||
from trezor.crypto import nem
|
|
||||||
|
|
||||||
|
|
||||||
async def nem_sign_tx(ctx, msg: NEMSignTx):
|
async def sign_tx(ctx, msg: NEMSignTx):
|
||||||
validate(msg)
|
validate(msg)
|
||||||
node = await seed.derive_node(ctx, msg.transaction.address_n, NEM_CURVE)
|
node = await seed.derive_node(ctx, msg.transaction.address_n, NEM_CURVE)
|
||||||
|
|
||||||
|
if msg.multisig:
|
||||||
|
public_key = msg.multisig.signer
|
||||||
|
else:
|
||||||
|
public_key = _get_public_key(node)
|
||||||
|
|
||||||
if msg.transfer:
|
if msg.transfer:
|
||||||
msg.transfer.mosaics = nem_canonicalize_mosaics(msg.transfer.mosaics)
|
msg.transfer.mosaics = canonicalize_mosaics(msg.transfer.mosaics)
|
||||||
tx = await _transfer(ctx, node, msg)
|
tx = await _transfer(ctx, public_key, msg, node)
|
||||||
elif msg.provision_namespace:
|
elif msg.provision_namespace:
|
||||||
tx = await _provision_namespace(ctx, node, msg)
|
tx = await _provision_namespace(ctx, public_key, msg)
|
||||||
elif msg.mosaic_creation:
|
elif msg.mosaic_creation:
|
||||||
tx = await _mosaic_creation(ctx, node, msg)
|
tx = await _mosaic_creation(ctx, public_key, msg)
|
||||||
elif msg.supply_change:
|
elif msg.supply_change:
|
||||||
tx = await _supply_change(ctx, node, msg)
|
tx = await _supply_change(ctx, public_key, msg)
|
||||||
elif msg.aggregate_modification:
|
elif msg.aggregate_modification:
|
||||||
tx = await _aggregate_modification(ctx, node, msg)
|
tx = await _aggregate_modification(ctx, public_key, msg)
|
||||||
elif msg.importance_transfer:
|
elif msg.importance_transfer:
|
||||||
tx = await _importance_transfer(ctx, node, msg)
|
tx = await _importance_transfer(ctx, public_key, msg)
|
||||||
else:
|
else:
|
||||||
raise ValueError('No transaction provided')
|
raise ValueError('No transaction provided')
|
||||||
|
|
||||||
@ -42,184 +43,51 @@ async def nem_sign_tx(ctx, msg: NEMSignTx):
|
|||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
async def _importance_transfer(ctx, node, msg: NEMSignTx):
|
|
||||||
if msg.importance_transfer.mode == NEMImportanceTransferMode.ImportanceTransfer_Activate:
|
|
||||||
m = 'Activate'
|
|
||||||
else:
|
|
||||||
m = 'Deactivate'
|
|
||||||
await require_confirm_action(ctx, m + ' remote harvesting?')
|
|
||||||
await require_confirm_final(ctx, msg.transaction.fee)
|
|
||||||
|
|
||||||
w = nem_transaction_create_importance_transfer(
|
|
||||||
msg.transaction.network,
|
|
||||||
msg.transaction.timestamp,
|
|
||||||
_get_public_key(node),
|
|
||||||
msg.transaction.fee,
|
|
||||||
msg.transaction.deadline,
|
|
||||||
msg.importance_transfer.mode,
|
|
||||||
msg.importance_transfer.public_key
|
|
||||||
)
|
|
||||||
return w
|
|
||||||
|
|
||||||
|
|
||||||
async def _aggregate_modification(ctx, node, msg: NEMSignTx):
|
|
||||||
if not msg.multisig:
|
|
||||||
await require_confirm_action(ctx, 'Convert account to multisig account?')
|
|
||||||
w = nem_transaction_create_aggregate_modification(
|
|
||||||
msg.transaction.network,
|
|
||||||
msg.transaction.timestamp,
|
|
||||||
_get_public_key(node),
|
|
||||||
msg.transaction.fee,
|
|
||||||
msg.transaction.deadline,
|
|
||||||
len(msg.aggregate_modification.modifications),
|
|
||||||
msg.aggregate_modification.relative_change
|
|
||||||
)
|
|
||||||
|
|
||||||
for m in msg.aggregate_modification.modifications:
|
|
||||||
if m.type == NEMModificationType.CosignatoryModification_Add:
|
|
||||||
action = 'Add'
|
|
||||||
else:
|
|
||||||
action = 'Remove'
|
|
||||||
address = nem.compute_address(m.public_key, msg.transaction.network)
|
|
||||||
await require_confirm_address(ctx, action + ' cosignatory?', address)
|
|
||||||
nem_transaction_write_cosignatory_modification(w, m.type, m.public_key)
|
|
||||||
|
|
||||||
if msg.aggregate_modification.relative_change:
|
|
||||||
if not msg.multisig:
|
|
||||||
action = 'Set minimum cosignatories to '
|
|
||||||
else:
|
|
||||||
action = 'Modify the number of cosignatories by '
|
|
||||||
await require_confirm_action(ctx, action + str(msg.aggregate_modification.relative_change) + '?')
|
|
||||||
|
|
||||||
nem_transaction_write_minimum_cosignatories(w, msg.aggregate_modification.relative_change)
|
|
||||||
|
|
||||||
await require_confirm_final(ctx, msg.transaction.fee)
|
|
||||||
return w
|
|
||||||
|
|
||||||
|
|
||||||
async def _supply_change(ctx, node, msg: NEMSignTx):
|
|
||||||
await require_confirm_action(ctx, 'Modify supply for "' + msg.supply_change.mosaic + '" under namespace "'
|
|
||||||
+ msg.supply_change.namespace + '"?')
|
|
||||||
if msg.supply_change.type == NEMSupplyChangeType.SupplyChange_Decrease:
|
|
||||||
ask_msg = 'Decrease supply by ' + str(msg.supply_change.delta) + ' whole units?'
|
|
||||||
elif msg.supply_change.type == NEMSupplyChangeType.SupplyChange_Increase:
|
|
||||||
ask_msg = 'Increase supply by ' + str(msg.supply_change.delta) + ' whole units?'
|
|
||||||
else:
|
|
||||||
raise ValueError('Invalid supply change type')
|
|
||||||
await require_confirm_action(ctx, ask_msg)
|
|
||||||
|
|
||||||
await require_confirm_final(ctx, msg.transaction.fee)
|
|
||||||
return nem_transaction_create_mosaic_supply_change(
|
|
||||||
msg.transaction.network,
|
|
||||||
msg.transaction.timestamp,
|
|
||||||
_get_public_key(node),
|
|
||||||
msg.transaction.fee,
|
|
||||||
msg.transaction.deadline,
|
|
||||||
msg.supply_change.namespace,
|
|
||||||
msg.supply_change.mosaic,
|
|
||||||
msg.supply_change.type,
|
|
||||||
msg.supply_change.delta
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def _mosaic_creation(ctx, node, msg: NEMSignTx) -> bytearray:
|
|
||||||
await require_confirm_action(ctx, 'Create mosaic "' + msg.mosaic_creation.definition.mosaic + '" under namespace "'
|
|
||||||
+ msg.mosaic_creation.definition.namespace + '"?')
|
|
||||||
await require_confirm_properties(ctx, msg.mosaic_creation.definition)
|
|
||||||
await require_confirm_fee(ctx, 'Confirm creation fee', msg.mosaic_creation.fee)
|
|
||||||
|
|
||||||
await require_confirm_final(ctx, msg.transaction.fee)
|
|
||||||
return nem_transaction_create_mosaic_creation(
|
|
||||||
msg.transaction.network,
|
|
||||||
msg.transaction.timestamp,
|
|
||||||
_get_public_key(node),
|
|
||||||
msg.transaction.fee,
|
|
||||||
msg.transaction.deadline,
|
|
||||||
msg.mosaic_creation.definition.namespace,
|
|
||||||
msg.mosaic_creation.definition.mosaic,
|
|
||||||
msg.mosaic_creation.definition.description,
|
|
||||||
msg.mosaic_creation.definition.divisibility,
|
|
||||||
msg.mosaic_creation.definition.supply,
|
|
||||||
msg.mosaic_creation.definition.mutable_supply,
|
|
||||||
msg.mosaic_creation.definition.transferable,
|
|
||||||
msg.mosaic_creation.definition.levy,
|
|
||||||
msg.mosaic_creation.definition.fee,
|
|
||||||
msg.mosaic_creation.definition.levy_address,
|
|
||||||
msg.mosaic_creation.definition.levy_namespace,
|
|
||||||
msg.mosaic_creation.definition.levy_mosaic,
|
|
||||||
msg.mosaic_creation.sink,
|
|
||||||
msg.mosaic_creation.fee)
|
|
||||||
|
|
||||||
|
|
||||||
async def _provision_namespace(ctx, node, msg: NEMSignTx) -> bytearray:
|
|
||||||
if msg.provision_namespace.parent:
|
|
||||||
await require_confirm_action(ctx, 'Create namespace "' + msg.provision_namespace.namespace + '"' +
|
|
||||||
'under namespace "' + msg.provision_namespace.parent + '"?')
|
|
||||||
else:
|
|
||||||
await require_confirm_action(ctx, 'Create namespace "' + msg.provision_namespace.namespace + '"?')
|
|
||||||
await require_confirm_fee(ctx, 'Confirm rental fee', msg.provision_namespace.fee)
|
|
||||||
|
|
||||||
await require_confirm_final(ctx, msg.transaction.fee)
|
|
||||||
return nem_transaction_create_provision_namespace(
|
|
||||||
msg.transaction.network,
|
|
||||||
msg.transaction.timestamp,
|
|
||||||
_get_public_key(node),
|
|
||||||
msg.transaction.fee,
|
|
||||||
msg.transaction.deadline,
|
|
||||||
msg.provision_namespace.namespace,
|
|
||||||
msg.provision_namespace.parent,
|
|
||||||
msg.provision_namespace.sink,
|
|
||||||
msg.provision_namespace.fee)
|
|
||||||
|
|
||||||
|
|
||||||
async def _transfer(ctx, node, msg: NEMSignTx) -> bytes:
|
|
||||||
payload, encrypted = _get_payload(msg, node)
|
|
||||||
tx = nem_transaction_create_transfer(
|
|
||||||
msg.transaction.network,
|
|
||||||
msg.transaction.timestamp,
|
|
||||||
_get_public_key(node),
|
|
||||||
msg.transaction.fee,
|
|
||||||
msg.transaction.deadline,
|
|
||||||
msg.transfer.recipient,
|
|
||||||
msg.transfer.amount,
|
|
||||||
payload,
|
|
||||||
encrypted,
|
|
||||||
len(msg.transfer.mosaics)
|
|
||||||
)
|
|
||||||
|
|
||||||
for mosaic in msg.transfer.mosaics:
|
|
||||||
await require_confirm_action(ctx, 'Confirm transfer of ' + str(mosaic.quantity) +
|
|
||||||
' raw units of ' + mosaic.namespace + '.' + mosaic.mosaic)
|
|
||||||
nem_transaction_write_mosaic(tx, mosaic.namespace, mosaic.mosaic, mosaic.quantity)
|
|
||||||
|
|
||||||
await require_confirm_transfer(ctx, msg.transfer.recipient, msg.transfer.amount)
|
|
||||||
|
|
||||||
if payload:
|
|
||||||
await require_confirm_payload(ctx, msg.transfer.payload, encrypted)
|
|
||||||
|
|
||||||
await require_confirm_final(ctx, msg.transaction.fee)
|
|
||||||
return tx
|
|
||||||
|
|
||||||
|
|
||||||
def _get_payload(msg: NEMSignTx, node) -> [bytes, bool]:
|
|
||||||
payload = msg.transfer.payload
|
|
||||||
encrypted = False
|
|
||||||
if msg.transfer.public_key is not None:
|
|
||||||
if payload is None:
|
|
||||||
raise ValueError("Public key provided but no payload to encrypt")
|
|
||||||
payload = _nem_encrypt(node, msg.transfer.public_key, msg.transfer.payload)
|
|
||||||
encrypted = True
|
|
||||||
|
|
||||||
return payload, encrypted
|
|
||||||
|
|
||||||
|
|
||||||
def _get_public_key(node) -> bytes:
|
def _get_public_key(node) -> bytes:
|
||||||
# 0x01 prefix is not part of the actual public key, hence removed
|
# 0x01 prefix is not part of the actual public key, hence removed
|
||||||
return node.public_key()[1:]
|
return node.public_key()[1:]
|
||||||
|
|
||||||
|
|
||||||
def _nem_encrypt(node, public_key: bytes, payload: bytes) -> bytes:
|
async def _transfer(ctx, public_key: bytes, msg: NEMSignTx, node) -> bytes:
|
||||||
salt = random.bytes(helpers.NEM_SALT_SIZE)
|
payload, encrypted = get_transfer_payload(msg, node)
|
||||||
iv = random.bytes(helpers.AES_BLOCK_SIZE)
|
await ask_transfer(ctx, msg, payload, encrypted)
|
||||||
encrypted = node.nem_encrypt(public_key, iv, salt, payload)
|
|
||||||
return iv + salt + encrypted
|
w = serialize_transfer(msg, public_key, payload, encrypted)
|
||||||
|
for mosaic in msg.transfer.mosaics:
|
||||||
|
serialize_mosaic(w, mosaic.namespace, mosaic.mosaic, mosaic.quantity)
|
||||||
|
return w
|
||||||
|
|
||||||
|
|
||||||
|
async def _provision_namespace(ctx, public_key: bytes, msg: NEMSignTx) -> bytearray:
|
||||||
|
await ask_provision_namespace(ctx, msg)
|
||||||
|
return serialize_provision_namespace(msg, public_key)
|
||||||
|
|
||||||
|
|
||||||
|
async def _mosaic_creation(ctx, public_key: bytes, msg: NEMSignTx) -> bytearray:
|
||||||
|
await ask_mosaic_creation(ctx, msg)
|
||||||
|
return serialize_mosaic_creation(msg, public_key)
|
||||||
|
|
||||||
|
|
||||||
|
async def _supply_change(ctx, public_key: bytes, msg: NEMSignTx):
|
||||||
|
await ask_mosaic_supply_change(ctx, msg)
|
||||||
|
return serialize_mosaic_supply_change(msg, public_key)
|
||||||
|
|
||||||
|
|
||||||
|
async def _aggregate_modification(ctx, public_key: bytes, msg: NEMSignTx):
|
||||||
|
await ask_aggregate_modification(ctx, msg)
|
||||||
|
if not msg.multisig:
|
||||||
|
w = serialize_aggregate_modification(msg, public_key)
|
||||||
|
else:
|
||||||
|
w = bytearray() # todo
|
||||||
|
|
||||||
|
for m in msg.aggregate_modification.modifications:
|
||||||
|
serialize_cosignatory_modification(w, m.type, m.public_key)
|
||||||
|
|
||||||
|
if msg.aggregate_modification.relative_change:
|
||||||
|
serialize_minimum_cosignatories(w, msg.aggregate_modification.relative_change)
|
||||||
|
return w
|
||||||
|
|
||||||
|
|
||||||
|
async def _importance_transfer(ctx, public_key: bytes, msg: NEMSignTx):
|
||||||
|
await ask_importance_transfer(ctx, msg)
|
||||||
|
return serialize_importance_transfer(msg, public_key)
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
|
|
||||||
from .helpers import *
|
|
||||||
from .writers import *
|
|
||||||
|
|
||||||
|
|
||||||
def nem_transaction_create_transfer(network: int, timestamp: int, signer_public_key: bytes, fee: int, deadline: int,
|
|
||||||
recipient: str, amount: int, payload: bytearray = None, encrypted: bool = False,
|
|
||||||
mosaics: int = 0) -> bytearray:
|
|
||||||
|
|
||||||
tx = nem_transaction_write_common(NEM_TRANSACTION_TYPE_TRANSFER,
|
|
||||||
nem_get_version(network, mosaics),
|
|
||||||
timestamp,
|
|
||||||
signer_public_key,
|
|
||||||
fee,
|
|
||||||
deadline)
|
|
||||||
|
|
||||||
write_bytes_with_length(tx, bytearray(recipient))
|
|
||||||
write_uint64(tx, amount)
|
|
||||||
|
|
||||||
if payload:
|
|
||||||
# payload + payload size (u32) + encryption flag (u32)
|
|
||||||
write_uint32(tx, len(payload) + 2 * 4)
|
|
||||||
if encrypted:
|
|
||||||
write_uint32(tx, 0x02)
|
|
||||||
else:
|
|
||||||
write_uint32(tx, 0x01)
|
|
||||||
write_bytes_with_length(tx, payload)
|
|
||||||
else:
|
|
||||||
write_uint32(tx, 0)
|
|
||||||
|
|
||||||
if mosaics:
|
|
||||||
write_uint32(tx, mosaics)
|
|
||||||
|
|
||||||
return tx
|
|
||||||
|
|
||||||
|
|
||||||
def nem_transaction_create_provision_namespace(network: int, timestamp: int, signer_public_key: bytes, fee: int,
|
|
||||||
deadline: int, namespace: str, parent: str, rental_sink: str,
|
|
||||||
rental_fee: int) -> bytearray:
|
|
||||||
|
|
||||||
tx = nem_transaction_write_common(NEM_TRANSACTION_TYPE_PROVISION_NAMESPACE,
|
|
||||||
nem_get_version(network),
|
|
||||||
timestamp,
|
|
||||||
signer_public_key,
|
|
||||||
fee,
|
|
||||||
deadline)
|
|
||||||
|
|
||||||
write_bytes_with_length(tx, bytearray(rental_sink))
|
|
||||||
write_uint64(tx, rental_fee)
|
|
||||||
write_bytes_with_length(tx, bytearray(namespace))
|
|
||||||
if parent:
|
|
||||||
write_bytes_with_length(tx, bytearray(parent))
|
|
||||||
else:
|
|
||||||
write_uint32(tx, 0xffffffff)
|
|
||||||
|
|
||||||
return tx
|
|
||||||
|
|
||||||
|
|
||||||
def nem_transaction_create_importance_transfer(network: int, timestamp: int, signer_public_key: bytes, fee: int,
|
|
||||||
deadline: int, mode: int, remote: bytes):
|
|
||||||
|
|
||||||
w = nem_transaction_write_common(NEM_TRANSACTION_TYPE_IMPORTANCE_TRANSFER,
|
|
||||||
nem_get_version(network),
|
|
||||||
timestamp,
|
|
||||||
signer_public_key,
|
|
||||||
fee,
|
|
||||||
deadline)
|
|
||||||
|
|
||||||
write_uint32(w, mode)
|
|
||||||
write_bytes_with_length(w, bytearray(remote))
|
|
||||||
return w
|
|
||||||
|
|
||||||
|
|
||||||
def nem_transaction_create_aggregate_modification(network: int, timestamp: int, signer_public_key: bytes, fee: int,
|
|
||||||
deadline: int, modifications: int, relative_change: bool):
|
|
||||||
|
|
||||||
w = nem_transaction_write_common(NEM_TRANSACTION_TYPE_AGGREGATE_MODIFICATION,
|
|
||||||
nem_get_version(network, relative_change),
|
|
||||||
timestamp,
|
|
||||||
signer_public_key,
|
|
||||||
fee,
|
|
||||||
deadline)
|
|
||||||
write_uint32(w, modifications)
|
|
||||||
return w
|
|
||||||
|
|
||||||
|
|
||||||
def nem_transaction_write_cosignatory_modification(w: bytearray, type: int, cosignatory: bytes):
|
|
||||||
write_uint32(w, 4 + 4 + len(cosignatory))
|
|
||||||
write_uint32(w, type)
|
|
||||||
write_bytes_with_length(w, bytearray(cosignatory))
|
|
||||||
return w
|
|
||||||
|
|
||||||
|
|
||||||
def nem_transaction_write_minimum_cosignatories(w: bytearray, relative_change: int):
|
|
||||||
write_uint32(w, 4)
|
|
||||||
write_uint32(w, relative_change)
|
|
85
src/apps/nem/transfer.py
Normal file
85
src/apps/nem/transfer.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
from .writers import *
|
||||||
|
from apps.nem.layout import *
|
||||||
|
from trezor.messages import NEMImportanceTransferMode
|
||||||
|
from trezor.crypto import random
|
||||||
|
|
||||||
|
|
||||||
|
async def ask_transfer(ctx, msg: NEMSignTx, payload, encrypted):
|
||||||
|
if payload:
|
||||||
|
await require_confirm_payload(ctx, msg.transfer.payload, encrypted)
|
||||||
|
|
||||||
|
for mosaic in msg.transfer.mosaics:
|
||||||
|
await require_confirm_action(ctx, 'Confirm transfer of ' + str(mosaic.quantity) +
|
||||||
|
' raw units of ' + mosaic.namespace + '.' + mosaic.mosaic)
|
||||||
|
|
||||||
|
await require_confirm_transfer(ctx, msg.transfer.recipient, msg.transfer.amount)
|
||||||
|
|
||||||
|
await require_confirm_final(ctx, msg.transaction.fee)
|
||||||
|
|
||||||
|
|
||||||
|
async def ask_importance_transfer(ctx, msg: NEMSignTx):
|
||||||
|
if msg.importance_transfer.mode == NEMImportanceTransferMode.ImportanceTransfer_Activate:
|
||||||
|
m = 'Activate'
|
||||||
|
else:
|
||||||
|
m = 'Deactivate'
|
||||||
|
await require_confirm_action(ctx, m + ' remote harvesting?')
|
||||||
|
await require_confirm_final(ctx, msg.transaction.fee)
|
||||||
|
|
||||||
|
|
||||||
|
def serialize_transfer(msg: NEMSignTx, public_key: bytes, payload: bytes=None, encrypted: bool=False) -> bytearray:
|
||||||
|
tx = write_common(msg.transaction,
|
||||||
|
bytearray(public_key),
|
||||||
|
NEM_TRANSACTION_TYPE_TRANSFER,
|
||||||
|
_get_version(msg.transaction.network, msg.transfer.mosaics))
|
||||||
|
|
||||||
|
write_bytes_with_length(tx, bytearray(msg.transfer.recipient))
|
||||||
|
write_uint64(tx, msg.transfer.amount)
|
||||||
|
|
||||||
|
if payload:
|
||||||
|
# payload + payload size (u32) + encryption flag (u32)
|
||||||
|
write_uint32(tx, len(payload) + 2 * 4)
|
||||||
|
if encrypted:
|
||||||
|
write_uint32(tx, 0x02)
|
||||||
|
else:
|
||||||
|
write_uint32(tx, 0x01)
|
||||||
|
write_bytes_with_length(tx, bytearray(payload))
|
||||||
|
else:
|
||||||
|
write_uint32(tx, 0)
|
||||||
|
|
||||||
|
if msg.transfer.mosaics:
|
||||||
|
write_uint32(tx, len(msg.transfer.mosaics))
|
||||||
|
|
||||||
|
return tx
|
||||||
|
|
||||||
|
|
||||||
|
def serialize_importance_transfer(msg: NEMSignTx, public_key: bytes) -> bytearray:
|
||||||
|
w = write_common(msg.transaction, bytearray(public_key), NEM_TRANSACTION_TYPE_IMPORTANCE_TRANSFER)
|
||||||
|
|
||||||
|
write_uint32(w, msg.importance_transfer.mode)
|
||||||
|
write_bytes_with_length(w, bytearray(msg.importance_transfer.public_key))
|
||||||
|
return w
|
||||||
|
|
||||||
|
|
||||||
|
def get_transfer_payload(msg: NEMSignTx, node) -> [bytes, bool]:
|
||||||
|
payload = msg.transfer.payload
|
||||||
|
encrypted = False
|
||||||
|
if msg.transfer.public_key is not None:
|
||||||
|
if payload is None:
|
||||||
|
raise ValueError("Public key provided but no payload to encrypt")
|
||||||
|
payload = _encrypt(node, msg.transfer.public_key, msg.transfer.payload)
|
||||||
|
encrypted = True
|
||||||
|
|
||||||
|
return payload, encrypted
|
||||||
|
|
||||||
|
|
||||||
|
def _encrypt(node, public_key: bytes, payload: bytes) -> bytes:
|
||||||
|
salt = random.bytes(NEM_SALT_SIZE)
|
||||||
|
iv = random.bytes(AES_BLOCK_SIZE)
|
||||||
|
encrypted = node.nem_encrypt(public_key, iv, salt, payload)
|
||||||
|
return iv + salt + encrypted
|
||||||
|
|
||||||
|
|
||||||
|
def _get_version(network, mosaics=None) -> int:
|
||||||
|
if mosaics:
|
||||||
|
return network << 24 | 2
|
||||||
|
return network << 24 | 1
|
@ -76,12 +76,12 @@ def _validate_common(common: NEMTransactionCommon, inner: bool=False):
|
|||||||
if common.deadline is None:
|
if common.deadline is None:
|
||||||
err = 'deadline'
|
err = 'deadline'
|
||||||
|
|
||||||
is_signer = common.signer is not None
|
# is_signer = common.signer is not None todo !!
|
||||||
if inner != is_signer:
|
# if inner != is_signer:
|
||||||
if not inner:
|
# if not inner:
|
||||||
raise ValueError('Signer not allowed in outer transaction')
|
# raise ValueError('Signer not allowed in outer transaction')
|
||||||
err = 'signer'
|
# err = 'signer'
|
||||||
|
#
|
||||||
if err:
|
if err:
|
||||||
if inner:
|
if inner:
|
||||||
raise ValueError('No ' + err + ' provided in inner transaction')
|
raise ValueError('No ' + err + ' provided in inner transaction')
|
||||||
@ -106,6 +106,8 @@ def _validate_importance_transfer(importance_transfer: NEMImportanceTransfer):
|
|||||||
|
|
||||||
|
|
||||||
def _validate_multisig(multisig: NEMTransactionCommon, network: int):
|
def _validate_multisig(multisig: NEMTransactionCommon, network: int):
|
||||||
|
_validate_common(multisig)
|
||||||
|
_validate_public_key(multisig.signer, 'Invalid multisig signer public key provided')
|
||||||
if multisig.network != network:
|
if multisig.network != network:
|
||||||
raise ValueError('Inner transaction network is different')
|
raise ValueError('Inner transaction network is different')
|
||||||
|
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
|
||||||
|
from trezor.messages.NEMTransactionCommon import NEMTransactionCommon
|
||||||
|
|
||||||
|
|
||||||
def write_uint32(w, n: int):
|
def write_uint32(w, n: int):
|
||||||
w.append(n & 0xFF)
|
w.append(n & 0xFF)
|
||||||
w.append((n >> 8) & 0xFF)
|
w.append((n >> 8) & 0xFF)
|
||||||
@ -26,21 +29,16 @@ def write_bytes_with_length(w, buf: bytearray):
|
|||||||
write_bytes(w, buf)
|
write_bytes(w, buf)
|
||||||
|
|
||||||
|
|
||||||
def nem_transaction_write_common(tx_type: int, version: int, timestamp: int, signer: bytes, fee: int, deadline: int)\
|
def write_common(common: NEMTransactionCommon, public_key: bytearray, transaction_type: int, version: int=None) -> bytearray:
|
||||||
-> bytearray:
|
|
||||||
ret = bytearray()
|
ret = bytearray()
|
||||||
write_uint32(ret, tx_type)
|
write_uint32(ret, transaction_type)
|
||||||
|
if version is None:
|
||||||
|
version = common.network << 24 | 1
|
||||||
write_uint32(ret, version)
|
write_uint32(ret, version)
|
||||||
write_uint32(ret, timestamp)
|
write_uint32(ret, common.timestamp)
|
||||||
|
|
||||||
write_bytes_with_length(ret, bytearray(signer))
|
write_bytes_with_length(ret, public_key)
|
||||||
write_uint64(ret, fee)
|
write_uint64(ret, common.fee)
|
||||||
write_uint32(ret, deadline)
|
write_uint32(ret, common.deadline)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def nem_get_version(network, mosaics=None) -> int:
|
|
||||||
if mosaics:
|
|
||||||
return network << 24 | 2
|
|
||||||
return network << 24 | 1
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
from common import *
|
from common import *
|
||||||
|
|
||||||
from apps.nem.mosaic import *
|
from apps.nem.mosaic import *
|
||||||
|
|
||||||
|
|
||||||
class TestNemTransactionMosaicCanonicalization(unittest.TestCase):
|
class TestNemMosaicCanonicalization(unittest.TestCase):
|
||||||
|
|
||||||
def test_nem_transaction_mosaic_canonicalization(self):
|
def test_mosaic_canonicalization(self):
|
||||||
a = NEMMosaic()
|
a = NEMMosaic()
|
||||||
a.namespace = 'abc'
|
a.namespace = 'abc'
|
||||||
a.quantity = 3
|
a.quantity = 3
|
||||||
@ -35,13 +34,13 @@ class TestNemTransactionMosaicCanonicalization(unittest.TestCase):
|
|||||||
g.quantity = 30
|
g.quantity = 30
|
||||||
g.mosaic = 'mosaic'
|
g.mosaic = 'mosaic'
|
||||||
|
|
||||||
res = nem_canonicalize_mosaics([a, b, c, d, e, f, g])
|
res = canonicalize_mosaics([a, b, c, d, e, f, g])
|
||||||
self.assertEqual(res, [e, f, b, a, c])
|
self.assertEqual(res, [e, f, b, a, c])
|
||||||
self.assertEqual(res[2].quantity, b.quantity)
|
self.assertEqual(res[2].quantity, b.quantity)
|
||||||
self.assertEqual(res[3].quantity, 3 + 8) # a + d
|
self.assertEqual(res[3].quantity, 3 + 8) # a + d
|
||||||
self.assertEqual(res[4].quantity, 3 + 30) # c + g
|
self.assertEqual(res[4].quantity, 3 + 30) # c + g
|
||||||
|
|
||||||
def test_nem_transaction_mosaic_merge(self):
|
def test_mosaic_merge(self):
|
||||||
a = NEMMosaic()
|
a = NEMMosaic()
|
||||||
a.namespace = 'abc'
|
a.namespace = 'abc'
|
||||||
a.quantity = 1
|
a.quantity = 1
|
||||||
@ -51,24 +50,24 @@ class TestNemTransactionMosaicCanonicalization(unittest.TestCase):
|
|||||||
b.quantity = 1
|
b.quantity = 1
|
||||||
b.mosaic = 'mosaic'
|
b.mosaic = 'mosaic'
|
||||||
|
|
||||||
merged = nem_merge_mosaics([a, b])
|
merged = merge_mosaics([a, b])
|
||||||
self.assertEqual(merged[0].quantity, 2)
|
self.assertEqual(merged[0].quantity, 2)
|
||||||
self.assertEqual(len(merged), 1)
|
self.assertEqual(len(merged), 1)
|
||||||
|
|
||||||
a.quantity = 1
|
a.quantity = 1
|
||||||
b.quantity = 10
|
b.quantity = 10
|
||||||
merged = nem_merge_mosaics([a, b])
|
merged = merge_mosaics([a, b])
|
||||||
self.assertEqual(merged[0].quantity, 11)
|
self.assertEqual(merged[0].quantity, 11)
|
||||||
|
|
||||||
a.namespace = 'abcdef'
|
a.namespace = 'abcdef'
|
||||||
merged = nem_merge_mosaics([a, b])
|
merged = merge_mosaics([a, b])
|
||||||
self.assertEqual(len(merged), 2)
|
self.assertEqual(len(merged), 2)
|
||||||
|
|
||||||
c = NEMMosaic()
|
c = NEMMosaic()
|
||||||
c.namespace = 'abc'
|
c.namespace = 'abc'
|
||||||
c.mosaic = 'xxx'
|
c.mosaic = 'xxx'
|
||||||
c.quantity = 2
|
c.quantity = 2
|
||||||
merged = nem_merge_mosaics([a, b, c])
|
merged = merge_mosaics([a, b, c])
|
||||||
self.assertEqual(len(merged), 3)
|
self.assertEqual(len(merged), 3)
|
||||||
|
|
||||||
a.namespace = 'abcdef'
|
a.namespace = 'abcdef'
|
||||||
@ -80,7 +79,7 @@ class TestNemTransactionMosaicCanonicalization(unittest.TestCase):
|
|||||||
c.namespace = 'abc'
|
c.namespace = 'abc'
|
||||||
c.mosaic = 'mosaic'
|
c.mosaic = 'mosaic'
|
||||||
c.quantity = 3
|
c.quantity = 3
|
||||||
merged = nem_merge_mosaics([a, b, c])
|
merged = merge_mosaics([a, b, c])
|
||||||
self.assertEqual(merged[0].quantity, 1)
|
self.assertEqual(merged[0].quantity, 1)
|
||||||
self.assertEqual(merged[1].quantity, 5)
|
self.assertEqual(merged[1].quantity, 5)
|
||||||
self.assertEqual(len(merged), 2)
|
self.assertEqual(len(merged), 2)
|
||||||
@ -94,11 +93,11 @@ class TestNemTransactionMosaicCanonicalization(unittest.TestCase):
|
|||||||
c.namespace = 'abc'
|
c.namespace = 'abc'
|
||||||
c.mosaic = 'mosaic'
|
c.mosaic = 'mosaic'
|
||||||
c.quantity = 3
|
c.quantity = 3
|
||||||
merged = nem_merge_mosaics([a, b, c])
|
merged = merge_mosaics([a, b, c])
|
||||||
self.assertEqual(merged[0].quantity, 6)
|
self.assertEqual(merged[0].quantity, 6)
|
||||||
self.assertEqual(len(merged), 1)
|
self.assertEqual(len(merged), 1)
|
||||||
|
|
||||||
def test_nem_transaction_mosaic_sort(self):
|
def test_mosaic_sort(self):
|
||||||
a = NEMMosaic()
|
a = NEMMosaic()
|
||||||
a.namespace = 'abcz'
|
a.namespace = 'abcz'
|
||||||
a.quantity = 1
|
a.quantity = 1
|
||||||
@ -107,39 +106,39 @@ class TestNemTransactionMosaicCanonicalization(unittest.TestCase):
|
|||||||
b.namespace = 'abca'
|
b.namespace = 'abca'
|
||||||
b.quantity = 1
|
b.quantity = 1
|
||||||
b.mosaic = 'mosaic'
|
b.mosaic = 'mosaic'
|
||||||
res = nem_sort_mosaics([a, b])
|
res = sort_mosaics([a, b])
|
||||||
self.assertEqual(res, [b, a])
|
self.assertEqual(res, [b, a])
|
||||||
|
|
||||||
a.namespace = ''
|
a.namespace = ''
|
||||||
b.namespace = 'a.b.c'
|
b.namespace = 'a.b.c'
|
||||||
res = nem_sort_mosaics([a, b])
|
res = sort_mosaics([a, b])
|
||||||
self.assertEqual(res, [a, b])
|
self.assertEqual(res, [a, b])
|
||||||
|
|
||||||
a.namespace = 'z.z.z'
|
a.namespace = 'z.z.z'
|
||||||
b.namespace = 'a.b.c'
|
b.namespace = 'a.b.c'
|
||||||
res = nem_sort_mosaics([a, b])
|
res = sort_mosaics([a, b])
|
||||||
self.assertEqual(res, [b, a])
|
self.assertEqual(res, [b, a])
|
||||||
|
|
||||||
a.namespace = 'a'
|
a.namespace = 'a'
|
||||||
b.namespace = 'a'
|
b.namespace = 'a'
|
||||||
a.mosaic = 'mosaic'
|
a.mosaic = 'mosaic'
|
||||||
b.mosaic = 'mosaic'
|
b.mosaic = 'mosaic'
|
||||||
res = nem_sort_mosaics([a, b])
|
res = sort_mosaics([a, b])
|
||||||
self.assertEqual(res, [a, b])
|
self.assertEqual(res, [a, b])
|
||||||
|
|
||||||
a.mosaic = 'www'
|
a.mosaic = 'www'
|
||||||
b.mosaic = 'aaa'
|
b.mosaic = 'aaa'
|
||||||
res = nem_sort_mosaics([a, b])
|
res = sort_mosaics([a, b])
|
||||||
self.assertEqual(res, [b, a])
|
self.assertEqual(res, [b, a])
|
||||||
|
|
||||||
c = NEMMosaic()
|
c = NEMMosaic()
|
||||||
c.namespace = 'a'
|
c.namespace = 'a'
|
||||||
c.mosaic = 'zzz'
|
c.mosaic = 'zzz'
|
||||||
res = nem_sort_mosaics([a, b, c])
|
res = sort_mosaics([a, b, c])
|
||||||
self.assertEqual(res, [b, a, c])
|
self.assertEqual(res, [b, a, c])
|
||||||
|
|
||||||
c.mosaic = 'bbb'
|
c.mosaic = 'bbb'
|
||||||
res = nem_sort_mosaics([a, b, c])
|
res = sort_mosaics([a, b, c])
|
||||||
self.assertEqual(res, [b, c, a])
|
self.assertEqual(res, [b, c, a])
|
||||||
|
|
||||||
|
|
150
tests/test_apps.nem.mosaic_creation.py
Normal file
150
tests/test_apps.nem.mosaic_creation.py
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
from common import *
|
||||||
|
|
||||||
|
from apps.nem.mosaic import *
|
||||||
|
from trezor.crypto import hashlib
|
||||||
|
from trezor.messages.NEMMosaicCreation import NEMMosaicCreation
|
||||||
|
from trezor.messages.NEMMosaicDefinition import NEMMosaicDefinition
|
||||||
|
|
||||||
|
|
||||||
|
class TestNemMosaicCreation(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_nem_transaction_mosaic_creation(self):
|
||||||
|
|
||||||
|
# http://bob.nem.ninja:8765/#/mosaic/68364353c29105e6d361ad1a42abbccbf419cfc7adb8b74c8f35d8f8bdaca3fa/0
|
||||||
|
m = _create_msg(NEM_NETWORK_TESTNET,
|
||||||
|
14070896,
|
||||||
|
108000000,
|
||||||
|
14074496,
|
||||||
|
'gimre.games.pong',
|
||||||
|
'paddles',
|
||||||
|
'Paddles for the bong game.\n',
|
||||||
|
0,
|
||||||
|
10000,
|
||||||
|
True,
|
||||||
|
True,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'TBMOSAICOD4F54EE5CDMR23CCBGOAM2XSJBR5OLC',
|
||||||
|
50000000000)
|
||||||
|
|
||||||
|
t = serialize_mosaic_creation(m, unhexlify('994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324'))
|
||||||
|
|
||||||
|
self.assertEqual(t, unhexlify('014000000100009870b4d60020000000994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd32400f36f060000000080c2d600de00000020000000994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd3241f0000001000000067696d72652e67616d65732e706f6e6707000000706164646c65731b000000506164646c657320666f722074686520626f6e672067616d652e0a04000000150000000c00000064697669736962696c69747901000000301a0000000d000000696e697469616c537570706c79050000003130303030190000000d000000737570706c794d757461626c650400000074727565180000000c0000007472616e7366657261626c650400000074727565000000002800000054424d4f534149434f443446353445453543444d523233434342474f414d3258534a4252354f4c4300743ba40b000000'))
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('68364353c29105e6d361ad1a42abbccbf419cfc7adb8b74c8f35d8f8bdaca3fa'))
|
||||||
|
|
||||||
|
def test_nem_transaction_mosaic_creation_with_levy(self):
|
||||||
|
# http://bob.nem.ninja:8765/#/mosaic/b2f4a98113ff1f3a8f1e9d7197aa982545297fe0aa3fa6094af8031569953a55/0
|
||||||
|
m = _create_msg(NEM_NETWORK_TESTNET,
|
||||||
|
21497248,
|
||||||
|
108000000,
|
||||||
|
21500848,
|
||||||
|
"alice.misc",
|
||||||
|
"bar",
|
||||||
|
"Special offer: get one bar extra by bying one foo!",
|
||||||
|
0,
|
||||||
|
1000,
|
||||||
|
False,
|
||||||
|
True,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
"TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
|
||||||
|
"nem",
|
||||||
|
"xem",
|
||||||
|
"TBMOSAICOD4F54EE5CDMR23CCBGOAM2XSJBR5OLC",
|
||||||
|
50000000000)
|
||||||
|
|
||||||
|
t = serialize_mosaic_creation(m, unhexlify("244fa194e2509ac0d2fbc18779c2618d8c2ebb61c16a3bcbebcf448c661ba8dc"),)
|
||||||
|
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('b2f4a98113ff1f3a8f1e9d7197aa982545297fe0aa3fa6094af8031569953a55'))
|
||||||
|
|
||||||
|
# http://chain.nem.ninja/#/mosaic/e8dc14821dbea4831d9051f86158ef348001447968fc22c01644fdaf2bda75c6/0
|
||||||
|
m = _create_msg(NEM_NETWORK_MAINNET,
|
||||||
|
69251020,
|
||||||
|
20000000,
|
||||||
|
69337420,
|
||||||
|
"dim",
|
||||||
|
"coin",
|
||||||
|
"DIM COIN",
|
||||||
|
6,
|
||||||
|
9000000000,
|
||||||
|
False,
|
||||||
|
True,
|
||||||
|
2,
|
||||||
|
10,
|
||||||
|
"NCGGLVO2G3CUACVI5GNX2KRBJSQCN4RDL2ZWJ4DP",
|
||||||
|
"dim",
|
||||||
|
"coin",
|
||||||
|
"NBMOSAICOD4F54EE5CDMR23CCBGOAM2XSIUX6TRS",
|
||||||
|
500000000)
|
||||||
|
|
||||||
|
t = serialize_mosaic_creation(m, unhexlify("a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a"))
|
||||||
|
self.assertEqual(t, unhexlify('0140000001000068ccaf200420000000a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a002d3101000000004c0122040c01000020000000a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a0f0000000300000064696d04000000636f696e0800000044494d20434f494e04000000150000000c00000064697669736962696c69747901000000361f0000000d000000696e697469616c537570706c790a000000393030303030303030301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c6504000000747275654b00000002000000280000004e4347474c564f32473343554143564935474e58324b52424a5351434e3452444c325a574a3444500f0000000300000064696d04000000636f696e0a00000000000000280000004e424d4f534149434f443446353445453543444d523233434342474f414d325853495558365452530065cd1d00000000'))
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('e8dc14821dbea4831d9051f86158ef348001447968fc22c01644fdaf2bda75c6'))
|
||||||
|
|
||||||
|
def test_nem_transaction_mosaic_creation_with_description(self):
|
||||||
|
# http://chain.nem.ninja/#/mosaic/269c6fda657aba3053a0e5b138c075808cc20e244e1182d9b730798b60a1f77b/0
|
||||||
|
m = _create_msg(NEM_NETWORK_MAINNET,
|
||||||
|
26729938,
|
||||||
|
108000000,
|
||||||
|
26733538,
|
||||||
|
"jabo38",
|
||||||
|
"red_token",
|
||||||
|
"This token is to celebrate the release of Namespaces and Mosaics "
|
||||||
|
"on the NEM system. This token was the fist ever mosaic created "
|
||||||
|
"other than nem.xem. There are only 10,000 Red Tokens that will "
|
||||||
|
"ever be created. It has no levy and can be traded freely among "
|
||||||
|
"third parties.",
|
||||||
|
2,
|
||||||
|
10000,
|
||||||
|
False,
|
||||||
|
True,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"NBMOSAICOD4F54EE5CDMR23CCBGOAM2XSIUX6TRS",
|
||||||
|
50000000000)
|
||||||
|
t = serialize_mosaic_creation(m, unhexlify("58956ac77951622dc5f1c938affbf017c458e30e6b21ddb5783d38b302531f23"))
|
||||||
|
|
||||||
|
self.assertEqual(t, unhexlify('0140000001000068d2dd97012000000058956ac77951622dc5f1c938affbf017c458e30e6b21ddb5783d38b302531f2300f36f0600000000e2eb9701c80100002000000058956ac77951622dc5f1c938affbf017c458e30e6b21ddb5783d38b302531f2317000000060000006a61626f3338090000007265645f746f6b656e0c0100005468697320746f6b656e20697320746f2063656c656272617465207468652072656c65617365206f66204e616d6573706163657320616e64204d6f7361696373206f6e20746865204e454d2073797374656d2e205468697320746f6b656e207761732074686520666973742065766572206d6f736169632063726561746564206f74686572207468616e206e656d2e78656d2e20546865726520617265206f6e6c792031302c3030302052656420546f6b656e7320746861742077696c6c206576657220626520637265617465642e20497420686173206e6f206c65767920616e642063616e2062652074726164656420667265656c7920616d6f6e6720746869726420706172746965732e04000000150000000c00000064697669736962696c69747901000000321a0000000d000000696e697469616c537570706c790500000031303030301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756500000000280000004e424d4f534149434f443446353445453543444d523233434342474f414d3258534955583654525300743ba40b000000'))
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('269c6fda657aba3053a0e5b138c075808cc20e244e1182d9b730798b60a1f77b'))
|
||||||
|
|
||||||
|
|
||||||
|
def _create_msg(network: int, timestamp: int, fee: int, deadline: int,
|
||||||
|
namespace: str, mosaic: str, description: str,
|
||||||
|
divisibility: int, supply: int, mutable_supply: bool, transferable: bool,
|
||||||
|
levy_type: int, levy_fee: int, levy_address: str, levy_namespace: str,
|
||||||
|
levy_mosaic: str, creation_sink: str, creation_fee: int):
|
||||||
|
m = NEMSignTx()
|
||||||
|
m.transaction = NEMTransactionCommon()
|
||||||
|
m.transaction.network = network
|
||||||
|
m.transaction.timestamp = timestamp
|
||||||
|
m.transaction.fee = fee
|
||||||
|
m.transaction.deadline = deadline
|
||||||
|
|
||||||
|
m.mosaic_creation = NEMMosaicCreation()
|
||||||
|
m.mosaic_creation.sink = creation_sink
|
||||||
|
m.mosaic_creation.fee = creation_fee
|
||||||
|
|
||||||
|
m.mosaic_creation.definition = NEMMosaicDefinition()
|
||||||
|
m.mosaic_creation.definition.namespace = namespace
|
||||||
|
m.mosaic_creation.definition.mosaic = mosaic
|
||||||
|
m.mosaic_creation.definition.description = description
|
||||||
|
m.mosaic_creation.definition.divisibility = divisibility
|
||||||
|
m.mosaic_creation.definition.supply = supply
|
||||||
|
m.mosaic_creation.definition.mutable_supply = mutable_supply
|
||||||
|
m.mosaic_creation.definition.transferable = transferable
|
||||||
|
m.mosaic_creation.definition.levy = levy_type
|
||||||
|
m.mosaic_creation.definition.fee = levy_fee
|
||||||
|
m.mosaic_creation.definition.levy_address = levy_address
|
||||||
|
m.mosaic_creation.definition.levy_namespace = levy_namespace
|
||||||
|
m.mosaic_creation.definition.levy_mosaic = levy_mosaic
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
87
tests/test_apps.nem.mosaic_supply_change.py
Normal file
87
tests/test_apps.nem.mosaic_supply_change.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
from common import *
|
||||||
|
|
||||||
|
from apps.nem.mosaic import *
|
||||||
|
from trezor.crypto import hashlib
|
||||||
|
from trezor.messages.NEMMosaicSupplyChange import NEMMosaicSupplyChange
|
||||||
|
|
||||||
|
|
||||||
|
class TestNemMosaicSupplyChange(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_nem_transaction_create_mosaic_supply_change(self):
|
||||||
|
|
||||||
|
# http://bigalice2.nem.ninja:7890/transaction/get?hash=33a50fdd4a54913643a580b2af08b9a5b51b7cee922bde380e84c573a7969c50
|
||||||
|
m = _create_msg(NEM_NETWORK_TESTNET,
|
||||||
|
14071648,
|
||||||
|
108000000,
|
||||||
|
14075248,
|
||||||
|
"gimre.games.pong",
|
||||||
|
"paddles",
|
||||||
|
1,
|
||||||
|
1234)
|
||||||
|
t = serialize_mosaic_supply_change(m, unhexlify("994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"))
|
||||||
|
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
||||||
|
unhexlify('33a50fdd4a54913643a580b2af08b9a5b51b7cee922bde380e84c573a7969c50'))
|
||||||
|
|
||||||
|
# http://bigalice2.nem.ninja:7890/transaction/get?hash=1ce8e8894d077a66ff22294b000825d090a60742ec407efd80eb8b19657704f2
|
||||||
|
m = _create_msg(NEM_NETWORK_TESTNET,
|
||||||
|
14126909,
|
||||||
|
108000000,
|
||||||
|
14130509,
|
||||||
|
"jabo38_ltd.fuzzy_kittens_cafe",
|
||||||
|
"coupons",
|
||||||
|
2,
|
||||||
|
1)
|
||||||
|
t = serialize_mosaic_supply_change(m, unhexlify("84afa1bbc993b7f5536344914dde86141e61f8cbecaf8c9cefc07391f3287cf5"))
|
||||||
|
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
||||||
|
unhexlify('1ce8e8894d077a66ff22294b000825d090a60742ec407efd80eb8b19657704f2'))
|
||||||
|
|
||||||
|
# http://bigalice3.nem.ninja:7890/transaction/get?hash=694e493e9576d2bcf60d85747e302ac2e1cc27783187947180d4275a713ff1ff
|
||||||
|
m = _create_msg(NEM_NETWORK_MAINNET,
|
||||||
|
53377685,
|
||||||
|
20000000,
|
||||||
|
53464085,
|
||||||
|
"abvapp",
|
||||||
|
"abv",
|
||||||
|
1,
|
||||||
|
9000000)
|
||||||
|
t = serialize_mosaic_supply_change(m, unhexlify("b7ccc27b21ba6cf5c699a8dc86ba6ba98950442597ff9fa30e0abe0f5f4dd05d"))
|
||||||
|
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
||||||
|
unhexlify('694e493e9576d2bcf60d85747e302ac2e1cc27783187947180d4275a713ff1ff'))
|
||||||
|
|
||||||
|
# http://bigalice3.nem.ninja:7890/transaction/get?hash=09836334e123970e068d5b411e4d1df54a3ead10acf1ad5935a2cdd9f9680185
|
||||||
|
m = _create_msg(NEM_NETWORK_MAINNET,
|
||||||
|
55176304,
|
||||||
|
20000000,
|
||||||
|
55262704,
|
||||||
|
"sushi",
|
||||||
|
"wasabi",
|
||||||
|
2,
|
||||||
|
20)
|
||||||
|
t = serialize_mosaic_supply_change(m, unhexlify("75f001a8641e2ce5c4386883dda561399ed346177411b492a677b73899502f13"))
|
||||||
|
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
||||||
|
unhexlify('09836334e123970e068d5b411e4d1df54a3ead10acf1ad5935a2cdd9f9680185'))
|
||||||
|
|
||||||
|
|
||||||
|
def _create_msg(network: int, timestamp: int, fee: int, deadline: int,
|
||||||
|
namespace: str, mosaic: str, mod_type: int, delta: int):
|
||||||
|
m = NEMSignTx()
|
||||||
|
m.transaction = NEMTransactionCommon()
|
||||||
|
m.transaction.network = network
|
||||||
|
m.transaction.timestamp = timestamp
|
||||||
|
m.transaction.fee = fee
|
||||||
|
m.transaction.deadline = deadline
|
||||||
|
|
||||||
|
m.supply_change = NEMMosaicSupplyChange()
|
||||||
|
m.supply_change.namespace = namespace
|
||||||
|
m.supply_change.mosaic = mosaic
|
||||||
|
m.supply_change.type = mod_type
|
||||||
|
m.supply_change.delta = delta
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
94
tests/test_apps.nem.multisig.aggregate_modification.py
Normal file
94
tests/test_apps.nem.multisig.aggregate_modification.py
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
from common import *
|
||||||
|
|
||||||
|
from apps.nem.multisig import *
|
||||||
|
from trezor.crypto import hashlib
|
||||||
|
from trezor.messages.NEMSignTx import NEMSignTx
|
||||||
|
from trezor.messages.NEMAggregateModification import NEMAggregateModification
|
||||||
|
from trezor.messages.NEMCosignatoryModification import NEMCosignatoryModification
|
||||||
|
|
||||||
|
|
||||||
|
class TestNemMultisigAggregateModification(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_nem_transaction_aggregate_modification(self):
|
||||||
|
# http://bob.nem.ninja:8765/#/aggregate/6a55471b17159e5b6cd579c421e95a4e39d92e3f78b0a55ee337e785a601d3a2
|
||||||
|
m = _create_msg(NEM_NETWORK_TESTNET,
|
||||||
|
0,
|
||||||
|
22000000,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
False)
|
||||||
|
t = serialize_aggregate_modification(m, unhexlify("462ee976890916e54fa825d26bdd0235f5eb5b6a143c199ab0ae5ee9328e08ce"))
|
||||||
|
|
||||||
|
serialize_cosignatory_modification(t, 1, unhexlify(
|
||||||
|
"994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"))
|
||||||
|
serialize_cosignatory_modification(t, 1, unhexlify(
|
||||||
|
"c54d6e33ed1446eedd7f7a80a588dd01857f723687a09200c1917d5524752f8b"))
|
||||||
|
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
||||||
|
unhexlify("6a55471b17159e5b6cd579c421e95a4e39d92e3f78b0a55ee337e785a601d3a2"))
|
||||||
|
|
||||||
|
# http://chain.nem.ninja/#/aggregate/cc64ca69bfa95db2ff7ac1e21fe6d27ece189c603200ebc9778d8bb80ca25c3c
|
||||||
|
m = _create_msg(NEM_NETWORK_MAINNET,
|
||||||
|
0,
|
||||||
|
40000000,
|
||||||
|
0,
|
||||||
|
5,
|
||||||
|
False)
|
||||||
|
t = serialize_aggregate_modification(m, unhexlify("f41b99320549741c5cce42d9e4bb836d98c50ed5415d0c3c2912d1bb50e6a0e5"))
|
||||||
|
|
||||||
|
serialize_cosignatory_modification(t, 1, unhexlify(
|
||||||
|
"1fbdbdde28daf828245e4533765726f0b7790e0b7146e2ce205df3e86366980b"))
|
||||||
|
serialize_cosignatory_modification(t, 1, unhexlify(
|
||||||
|
"f94e8702eb1943b23570b1b83be1b81536df35538978820e98bfce8f999e2d37"))
|
||||||
|
serialize_cosignatory_modification(t, 1, unhexlify(
|
||||||
|
"826cedee421ff66e708858c17815fcd831a4bb68e3d8956299334e9e24380ba8"))
|
||||||
|
serialize_cosignatory_modification(t, 1, unhexlify(
|
||||||
|
"719862cd7d0f4e875a6a0274c9a1738f38f40ad9944179006a54c34724c1274d"))
|
||||||
|
serialize_cosignatory_modification(t, 1, unhexlify(
|
||||||
|
"43aa69177018fc3e2bdbeb259c81cddf24be50eef9c5386db51d82386c41475a"))
|
||||||
|
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
||||||
|
unhexlify("cc64ca69bfa95db2ff7ac1e21fe6d27ece189c603200ebc9778d8bb80ca25c3c"))
|
||||||
|
|
||||||
|
def test_nem_transaction_aggregate_modification_relative_change(self):
|
||||||
|
# http://bob.nem.ninja:8765/#/aggregate/1fbdae5ba753e68af270930413ae90f671eb8ab58988116684bac0abd5726584
|
||||||
|
m = _create_msg(NEM_NETWORK_TESTNET,
|
||||||
|
6542254,
|
||||||
|
40000000,
|
||||||
|
6545854,
|
||||||
|
4,
|
||||||
|
True)
|
||||||
|
t = serialize_aggregate_modification(m, unhexlify("6bf7849c1eec6a2002995cc457dc00c4e29bad5c88de63f51e42dfdcd7b2131d"))
|
||||||
|
|
||||||
|
serialize_cosignatory_modification(t, 1, unhexlify(
|
||||||
|
"5f53d076c8c3ec3110b98364bc423092c3ec2be2b1b3c40fd8ab68d54fa39295"))
|
||||||
|
serialize_cosignatory_modification(t, 1, unhexlify(
|
||||||
|
"9eb199c2b4d406f64cb7aa5b2b0815264b56ba8fe44d558a6cb423a31a33c4c2"))
|
||||||
|
serialize_cosignatory_modification(t, 1, unhexlify(
|
||||||
|
"94b2323dab23a3faba24fa6ddda0ece4fbb06acfedd74e76ad9fae38d006882b"))
|
||||||
|
serialize_cosignatory_modification(t, 1, unhexlify(
|
||||||
|
"d88c6ee2a2cd3929d0d76b6b14ecb549d21296ab196a2b3a4cb2536bcce32e87"))
|
||||||
|
serialize_minimum_cosignatories(t, 2)
|
||||||
|
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
||||||
|
unhexlify("1fbdae5ba753e68af270930413ae90f671eb8ab58988116684bac0abd5726584"))
|
||||||
|
|
||||||
|
|
||||||
|
def _create_msg(network: int, timestamp: int, fee: int, deadline: int,
|
||||||
|
modifications: int, relative_change: bool):
|
||||||
|
m = NEMSignTx()
|
||||||
|
m.transaction = NEMTransactionCommon()
|
||||||
|
m.transaction.network = network
|
||||||
|
m.transaction.timestamp = timestamp
|
||||||
|
m.transaction.fee = fee
|
||||||
|
m.transaction.deadline = deadline
|
||||||
|
|
||||||
|
m.aggregate_modification = NEMAggregateModification()
|
||||||
|
for i in range(modifications):
|
||||||
|
m.aggregate_modification.modifications.append(NEMCosignatoryModification())
|
||||||
|
m.aggregate_modification.relative_change = relative_change
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
@ -1,86 +1,113 @@
|
|||||||
from common import *
|
from common import *
|
||||||
|
|
||||||
from apps.nem.transaction import *
|
|
||||||
from apps.nem.multisig import *
|
from apps.nem.multisig import *
|
||||||
|
from apps.nem.namespace import *
|
||||||
|
from trezor.messages.NEMSignTx import NEMSignTx
|
||||||
|
from trezor.messages.NEMAggregateModification import NEMAggregateModification
|
||||||
|
from trezor.messages.NEMProvisionNamespace import NEMProvisionNamespace
|
||||||
|
from trezor.messages.NEMCosignatoryModification import NEMCosignatoryModification
|
||||||
|
|
||||||
|
|
||||||
class TestNemMultisig(unittest.TestCase):
|
class TestNemMultisig(unittest.TestCase):
|
||||||
|
|
||||||
def test_nem_multisig(self):
|
def test_nem_multisig(self):
|
||||||
# http://bob.nem.ninja:8765/#/multisig/7d3a7087023ee29005262016706818579a2b5499eb9ca76bad98c1e6f4c46642
|
# http://bob.nem.ninja:8765/#/multisig/7d3a7087023ee29005262016706818579a2b5499eb9ca76bad98c1e6f4c46642
|
||||||
|
m = _create_msg(NEM_NETWORK_TESTNET,
|
||||||
|
3939039,
|
||||||
|
16000000,
|
||||||
|
3960639,
|
||||||
|
1,
|
||||||
|
False)
|
||||||
|
base_tx = serialize_aggregate_modification(m, unhexlify("abac2ee3d4aaa7a3bfb65261a00cc04c761521527dd3f2cf741e2815cbba83ac"))
|
||||||
|
|
||||||
base_tx = nem_transaction_create_aggregate_modification(NEM_NETWORK_TESTNET,
|
base_tx = serialize_cosignatory_modification(base_tx, 2, unhexlify("e6cff9b3725a91f31089c3acca0fac3e341c00b1c8c6e9578f66c4514509c3b3"))
|
||||||
3939039,
|
m = _create_common_msg(NEM_NETWORK_TESTNET,
|
||||||
unhexlify("abac2ee3d4aaa7a3bfb65261a00cc04c761521527dd3f2cf741e2815cbba83ac"),
|
3939039,
|
||||||
16000000,
|
6000000,
|
||||||
3960639,
|
3960639)
|
||||||
1,
|
multisig = serialize_multisig(m, unhexlify("59d89076964742ef2a2089d26a5aa1d2c7a7bb052a46c1de159891e91ad3d76e"), base_tx)
|
||||||
False)
|
|
||||||
|
|
||||||
base_tx = nem_transaction_write_cosignatory_modification(base_tx, 2, unhexlify("e6cff9b3725a91f31089c3acca0fac3e341c00b1c8c6e9578f66c4514509c3b3"))
|
|
||||||
multisig = nem_transaction_create_multisig(NEM_NETWORK_TESTNET,
|
|
||||||
3939039,
|
|
||||||
unhexlify("59d89076964742ef2a2089d26a5aa1d2c7a7bb052a46c1de159891e91ad3d76e"),
|
|
||||||
6000000,
|
|
||||||
3960639,
|
|
||||||
base_tx)
|
|
||||||
|
|
||||||
self.assertEqual(multisig, unhexlify("0410000001000098df1a3c002000000059d89076964742ef2a2089d26a5aa1d2c7a7bb052a46c1de159891e91ad3d76e808d5b00000000003f6f3c006c0000000110000001000098df1a3c0020000000abac2ee3d4aaa7a3bfb65261a00cc04c761521527dd3f2cf741e2815cbba83ac0024f400000000003f6f3c0001000000280000000200000020000000e6cff9b3725a91f31089c3acca0fac3e341c00b1c8c6e9578f66c4514509c3b3"))
|
self.assertEqual(multisig, unhexlify("0410000001000098df1a3c002000000059d89076964742ef2a2089d26a5aa1d2c7a7bb052a46c1de159891e91ad3d76e808d5b00000000003f6f3c006c0000000110000001000098df1a3c0020000000abac2ee3d4aaa7a3bfb65261a00cc04c761521527dd3f2cf741e2815cbba83ac0024f400000000003f6f3c0001000000280000000200000020000000e6cff9b3725a91f31089c3acca0fac3e341c00b1c8c6e9578f66c4514509c3b3"))
|
||||||
|
|
||||||
address = "TCRXYUQIMFA7AOGL5LF3YWLC7VABLYUMJ5ACBUNL"
|
address = "TCRXYUQIMFA7AOGL5LF3YWLC7VABLYUMJ5ACBUNL"
|
||||||
multisig = nem_transaction_create_multisig_signature(NEM_NETWORK_TESTNET,
|
m = _create_common_msg(NEM_NETWORK_TESTNET,
|
||||||
3939891,
|
3939891,
|
||||||
unhexlify("71cba4f2a28fd19f902ba40e9937994154d9eeaad0631d25d525ec37922567d4"),
|
6000000,
|
||||||
6000000,
|
3961491)
|
||||||
3961491,
|
multisig = serialize_multisig_signature(m, unhexlify("71cba4f2a28fd19f902ba40e9937994154d9eeaad0631d25d525ec37922567d4"), base_tx, address)
|
||||||
base_tx,
|
|
||||||
address)
|
|
||||||
|
|
||||||
self.assertEqual(multisig, unhexlify("0210000001000098331e3c002000000071cba4f2a28fd19f902ba40e9937994154d9eeaad0631d25d525ec37922567d4808d5b000000000093723c0024000000200000008ec165580bdabfd31ce6007a1748ce5bdf30eab7a214743097de3bc822ac7e002800000054435258595551494d464137414f474c354c463359574c43375641424c59554d4a35414342554e4c"))
|
self.assertEqual(multisig, unhexlify("0210000001000098331e3c002000000071cba4f2a28fd19f902ba40e9937994154d9eeaad0631d25d525ec37922567d4808d5b000000000093723c0024000000200000008ec165580bdabfd31ce6007a1748ce5bdf30eab7a214743097de3bc822ac7e002800000054435258595551494d464137414f474c354c463359574c43375641424c59554d4a35414342554e4c"))
|
||||||
|
|
||||||
def test_nem_multisig_2(self):
|
def test_nem_multisig_2(self):
|
||||||
# http://chain.nem.ninja/#/multisig/1016cf3bdd61bd57b9b2b07b6ff2dee390279d8d899265bdc23d42360abe2e6c
|
# http://chain.nem.ninja/#/multisig/1016cf3bdd61bd57b9b2b07b6ff2dee390279d8d899265bdc23d42360abe2e6c
|
||||||
|
m = _create_provision_msg(NEM_NETWORK_MAINNET,
|
||||||
|
59414272,
|
||||||
|
20000000,
|
||||||
|
59500672,
|
||||||
|
"dim",
|
||||||
|
"",
|
||||||
|
"NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA",
|
||||||
|
5000000000)
|
||||||
|
base_tx = serialize_provision_namespace(m, unhexlify("a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a"))
|
||||||
|
|
||||||
base_tx = nem_transaction_create_provision_namespace(NEM_NETWORK_MAINNET,
|
m = _create_common_msg(NEM_NETWORK_MAINNET,
|
||||||
59414272,
|
59414272,
|
||||||
unhexlify("a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a"),
|
6000000,
|
||||||
20000000,
|
59500672)
|
||||||
59500672,
|
|
||||||
"dim",
|
|
||||||
"",
|
|
||||||
"NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA",
|
|
||||||
5000000000)
|
|
||||||
|
|
||||||
multisig = nem_transaction_create_multisig(NEM_NETWORK_MAINNET,
|
|
||||||
59414272,
|
|
||||||
unhexlify("cfe58463f0eaebceb5d00717f8aead49171a5d7c08f6b1299bd534f11715acc9"),
|
|
||||||
6000000,
|
|
||||||
59500672,
|
|
||||||
base_tx)
|
|
||||||
|
|
||||||
|
multisig = serialize_multisig(m, unhexlify("cfe58463f0eaebceb5d00717f8aead49171a5d7c08f6b1299bd534f11715acc9"), base_tx)
|
||||||
self.assertEqual(multisig, unhexlify("041000000100006800978a0320000000cfe58463f0eaebceb5d00717f8aead49171a5d7c08f6b1299bd534f11715acc9808d5b000000000080e88b037b000000012000000100006800978a0320000000a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a002d31010000000080e88b03280000004e414d4553504143455748344d4b464d42435646455244504f4f5034464b374d54425844505a5a4100f2052a010000000300000064696dffffffff"))
|
self.assertEqual(multisig, unhexlify("041000000100006800978a0320000000cfe58463f0eaebceb5d00717f8aead49171a5d7c08f6b1299bd534f11715acc9808d5b000000000080e88b037b000000012000000100006800978a0320000000a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a002d31010000000080e88b03280000004e414d4553504143455748344d4b464d42435646455244504f4f5034464b374d54425844505a5a4100f2052a010000000300000064696dffffffff"))
|
||||||
|
|
||||||
|
m = _create_common_msg(NEM_NETWORK_MAINNET,
|
||||||
|
59414342,
|
||||||
|
6000000,
|
||||||
|
59500742)
|
||||||
address = "NDDRG3UEB5LZZZMDWBE4RTKZK73JBHPAIWBHCFMV"
|
address = "NDDRG3UEB5LZZZMDWBE4RTKZK73JBHPAIWBHCFMV"
|
||||||
multisig = nem_transaction_create_multisig_signature(NEM_NETWORK_MAINNET,
|
multisig = serialize_multisig_signature(m, unhexlify("1b49b80203007117d034e45234ffcdf402c044aeef6dbb06351f346ca892bce2"), base_tx, address)
|
||||||
59414342,
|
|
||||||
unhexlify("1b49b80203007117d034e45234ffcdf402c044aeef6dbb06351f346ca892bce2"),
|
|
||||||
6000000,
|
|
||||||
59500742,
|
|
||||||
base_tx,
|
|
||||||
address)
|
|
||||||
|
|
||||||
self.assertEqual(multisig, unhexlify("021000000100006846978a03200000001b49b80203007117d034e45234ffcdf402c044aeef6dbb06351f346ca892bce2808d5b0000000000c6e88b032400000020000000bfa2088f7720f89dd4664d650e321dabd02fab61b7355bc88a391a848a49786a280000004e4444524733554542354c5a5a5a4d445742453452544b5a4b37334a424850414957424843464d56"))
|
self.assertEqual(multisig, unhexlify("021000000100006846978a03200000001b49b80203007117d034e45234ffcdf402c044aeef6dbb06351f346ca892bce2808d5b0000000000c6e88b032400000020000000bfa2088f7720f89dd4664d650e321dabd02fab61b7355bc88a391a848a49786a280000004e4444524733554542354c5a5a5a4d445742453452544b5a4b37334a424850414957424843464d56"))
|
||||||
|
|
||||||
multisig = nem_transaction_create_multisig_signature(NEM_NETWORK_MAINNET,
|
m = _create_common_msg(NEM_NETWORK_MAINNET,
|
||||||
59414381,
|
59414381,
|
||||||
unhexlify("7ba4b39209f1b9846b098fe43f74381e43cb2882ccde780f558a63355840aa87"),
|
6000000,
|
||||||
6000000,
|
59500781)
|
||||||
59500781,
|
address = "NDDRG3UEB5LZZZMDWBE4RTKZK73JBHPAIWBHCFMV"
|
||||||
base_tx,
|
multisig = serialize_multisig_signature(m, unhexlify("7ba4b39209f1b9846b098fe43f74381e43cb2882ccde780f558a63355840aa87"), base_tx, address)
|
||||||
address)
|
|
||||||
|
|
||||||
self.assertEqual(multisig, unhexlify("02100000010000686d978a03200000007ba4b39209f1b9846b098fe43f74381e43cb2882ccde780f558a63355840aa87808d5b0000000000ede88b032400000020000000bfa2088f7720f89dd4664d650e321dabd02fab61b7355bc88a391a848a49786a280000004e4444524733554542354c5a5a5a4d445742453452544b5a4b37334a424850414957424843464d56"))
|
self.assertEqual(multisig, unhexlify("02100000010000686d978a03200000007ba4b39209f1b9846b098fe43f74381e43cb2882ccde780f558a63355840aa87808d5b0000000000ede88b032400000020000000bfa2088f7720f89dd4664d650e321dabd02fab61b7355bc88a391a848a49786a280000004e4444524733554542354c5a5a5a4d445742453452544b5a4b37334a424850414957424843464d56"))
|
||||||
|
|
||||||
|
|
||||||
|
def _create_common_msg(network: int, timestamp: int, fee: int, deadline: int):
|
||||||
|
m = NEMTransactionCommon()
|
||||||
|
m.network = network
|
||||||
|
m.timestamp = timestamp
|
||||||
|
m.fee = fee
|
||||||
|
m.deadline = deadline
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
|
def _create_msg(network: int, timestamp: int, fee: int, deadline: int,
|
||||||
|
modifications: int, relative_change: bool):
|
||||||
|
m = NEMSignTx()
|
||||||
|
m.transaction = _create_common_msg(network, timestamp, fee, deadline)
|
||||||
|
|
||||||
|
m.aggregate_modification = NEMAggregateModification()
|
||||||
|
for i in range(modifications):
|
||||||
|
m.aggregate_modification.modifications.append(NEMCosignatoryModification())
|
||||||
|
m.aggregate_modification.relative_change = relative_change
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
|
def _create_provision_msg(network: int, timestamp: int, fee: int, deadline: int,
|
||||||
|
name: str, parent: str, sink: str, rental_fee: int):
|
||||||
|
m = NEMSignTx()
|
||||||
|
m.transaction = _create_common_msg(network, timestamp, fee, deadline)
|
||||||
|
|
||||||
|
m.provision_namespace = NEMProvisionNamespace()
|
||||||
|
m.provision_namespace.namespace = name
|
||||||
|
m.provision_namespace.parent = parent
|
||||||
|
m.provision_namespace.sink = sink
|
||||||
|
m.provision_namespace.fee = rental_fee
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
69
tests/test_apps.nem.namespace.py
Normal file
69
tests/test_apps.nem.namespace.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
from common import *
|
||||||
|
|
||||||
|
from apps.nem.namespace import *
|
||||||
|
from trezor.crypto import hashlib
|
||||||
|
from trezor.messages.NEMProvisionNamespace import NEMProvisionNamespace
|
||||||
|
from trezor.messages.NEMSignTx import NEMSignTx
|
||||||
|
|
||||||
|
|
||||||
|
class TestNemNamespace(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_create_provision_namespace(self):
|
||||||
|
|
||||||
|
# http://bob.nem.ninja:8765/#/transfer/0acbf8df91e6a65dc56c56c43d65f31ff2a6a48d06fc66e78c7f3436faf3e74f
|
||||||
|
m = _create_msg(NEM_NETWORK_TESTNET,
|
||||||
|
56999445,
|
||||||
|
20000000,
|
||||||
|
57003045,
|
||||||
|
'gimre',
|
||||||
|
'',
|
||||||
|
'TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35',
|
||||||
|
5000000000)
|
||||||
|
t = serialize_provision_namespace(m, unhexlify('84afa1bbc993b7f5536344914dde86141e61f8cbecaf8c9cefc07391f3287cf5'))
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('f7cab28da57204d01a907c697836577a4ae755e6c9bac60dcc318494a22debb3'))
|
||||||
|
|
||||||
|
# http://bob.nem.ninja:8765/#/namespace/7ddd5fe607e1bfb5606e0ac576024c318c8300d237273117d4db32a60c49524d
|
||||||
|
m = _create_msg(NEM_NETWORK_TESTNET,
|
||||||
|
21496797,
|
||||||
|
108000000,
|
||||||
|
21500397,
|
||||||
|
'misc',
|
||||||
|
'alice',
|
||||||
|
'TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35',
|
||||||
|
5000000000)
|
||||||
|
t = serialize_provision_namespace(m, unhexlify('244fa194e2509ac0d2fbc18779c2618d8c2ebb61c16a3bcbebcf448c661ba8dc'))
|
||||||
|
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('7ddd5fe607e1bfb5606e0ac576024c318c8300d237273117d4db32a60c49524d'))
|
||||||
|
|
||||||
|
# http://chain.nem.ninja/#/namespace/57071aad93ca125dc231dc02c07ad8610cd243d35068f9b36a7d231383907569
|
||||||
|
m = _create_msg(NEM_NETWORK_MAINNET,
|
||||||
|
26699717,
|
||||||
|
108000000,
|
||||||
|
26703317,
|
||||||
|
'sex',
|
||||||
|
'',
|
||||||
|
'NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA',
|
||||||
|
50000000000)
|
||||||
|
t = serialize_provision_namespace(m, unhexlify('9f3c14f304309c8b72b2821339c4428793b1518bea72d58dd01f19d523518614'))
|
||||||
|
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('57071aad93ca125dc231dc02c07ad8610cd243d35068f9b36a7d231383907569'))
|
||||||
|
|
||||||
|
|
||||||
|
def _create_msg(network: int, timestamp: int, fee: int, deadline: int,
|
||||||
|
name: str, parent: str, sink: str, rental_fee: int):
|
||||||
|
m = NEMSignTx()
|
||||||
|
m.transaction = NEMTransactionCommon()
|
||||||
|
m.transaction.network = network
|
||||||
|
m.transaction.timestamp = timestamp
|
||||||
|
m.transaction.fee = fee
|
||||||
|
m.transaction.deadline = deadline
|
||||||
|
m.provision_namespace = NEMProvisionNamespace()
|
||||||
|
m.provision_namespace.namespace = name
|
||||||
|
m.provision_namespace.parent = parent
|
||||||
|
m.provision_namespace.sink = sink
|
||||||
|
m.provision_namespace.fee = rental_fee
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
@ -1,75 +0,0 @@
|
|||||||
from common import *
|
|
||||||
|
|
||||||
from apps.nem.transaction import *
|
|
||||||
from trezor.crypto import hashlib
|
|
||||||
|
|
||||||
|
|
||||||
class TestNemTransactionMosaicCreation(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_nem_transaction_aggregate_modification(self):
|
|
||||||
# http://bob.nem.ninja:8765/#/aggregate/6a55471b17159e5b6cd579c421e95a4e39d92e3f78b0a55ee337e785a601d3a2
|
|
||||||
t = nem_transaction_create_aggregate_modification(NEM_NETWORK_TESTNET,
|
|
||||||
0,
|
|
||||||
unhexlify("462ee976890916e54fa825d26bdd0235f5eb5b6a143c199ab0ae5ee9328e08ce"),
|
|
||||||
22000000,
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
False)
|
|
||||||
|
|
||||||
nem_transaction_write_cosignatory_modification(t, 1, unhexlify(
|
|
||||||
"994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"))
|
|
||||||
nem_transaction_write_cosignatory_modification(t, 1, unhexlify(
|
|
||||||
"c54d6e33ed1446eedd7f7a80a588dd01857f723687a09200c1917d5524752f8b"))
|
|
||||||
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
|
||||||
unhexlify("6a55471b17159e5b6cd579c421e95a4e39d92e3f78b0a55ee337e785a601d3a2"))
|
|
||||||
|
|
||||||
# http://chain.nem.ninja/#/aggregate/cc64ca69bfa95db2ff7ac1e21fe6d27ece189c603200ebc9778d8bb80ca25c3c
|
|
||||||
t = nem_transaction_create_aggregate_modification(NEM_NETWORK_MAINNET,
|
|
||||||
0,
|
|
||||||
unhexlify("f41b99320549741c5cce42d9e4bb836d98c50ed5415d0c3c2912d1bb50e6a0e5"),
|
|
||||||
40000000,
|
|
||||||
0,
|
|
||||||
5,
|
|
||||||
False)
|
|
||||||
|
|
||||||
nem_transaction_write_cosignatory_modification(t, 1, unhexlify(
|
|
||||||
"1fbdbdde28daf828245e4533765726f0b7790e0b7146e2ce205df3e86366980b"))
|
|
||||||
nem_transaction_write_cosignatory_modification(t, 1, unhexlify(
|
|
||||||
"f94e8702eb1943b23570b1b83be1b81536df35538978820e98bfce8f999e2d37"))
|
|
||||||
nem_transaction_write_cosignatory_modification(t, 1, unhexlify(
|
|
||||||
"826cedee421ff66e708858c17815fcd831a4bb68e3d8956299334e9e24380ba8"))
|
|
||||||
nem_transaction_write_cosignatory_modification(t, 1, unhexlify(
|
|
||||||
"719862cd7d0f4e875a6a0274c9a1738f38f40ad9944179006a54c34724c1274d"))
|
|
||||||
nem_transaction_write_cosignatory_modification(t, 1, unhexlify(
|
|
||||||
"43aa69177018fc3e2bdbeb259c81cddf24be50eef9c5386db51d82386c41475a"))
|
|
||||||
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
|
||||||
unhexlify("cc64ca69bfa95db2ff7ac1e21fe6d27ece189c603200ebc9778d8bb80ca25c3c"))
|
|
||||||
|
|
||||||
def test_nem_transaction_aggregate_modification_relative_change(self):
|
|
||||||
# http://bob.nem.ninja:8765/#/aggregate/1fbdae5ba753e68af270930413ae90f671eb8ab58988116684bac0abd5726584
|
|
||||||
t = nem_transaction_create_aggregate_modification(NEM_NETWORK_TESTNET,
|
|
||||||
6542254,
|
|
||||||
unhexlify("6bf7849c1eec6a2002995cc457dc00c4e29bad5c88de63f51e42dfdcd7b2131d"),
|
|
||||||
40000000,
|
|
||||||
6545854,
|
|
||||||
4,
|
|
||||||
True)
|
|
||||||
|
|
||||||
nem_transaction_write_cosignatory_modification(t, 1, unhexlify(
|
|
||||||
"5f53d076c8c3ec3110b98364bc423092c3ec2be2b1b3c40fd8ab68d54fa39295"))
|
|
||||||
nem_transaction_write_cosignatory_modification(t, 1, unhexlify(
|
|
||||||
"9eb199c2b4d406f64cb7aa5b2b0815264b56ba8fe44d558a6cb423a31a33c4c2"))
|
|
||||||
nem_transaction_write_cosignatory_modification(t, 1, unhexlify(
|
|
||||||
"94b2323dab23a3faba24fa6ddda0ece4fbb06acfedd74e76ad9fae38d006882b"))
|
|
||||||
nem_transaction_write_cosignatory_modification(t, 1, unhexlify(
|
|
||||||
"d88c6ee2a2cd3929d0d76b6b14ecb549d21296ab196a2b3a4cb2536bcce32e87"))
|
|
||||||
nem_transaction_write_minimum_cosignatories(t, 2)
|
|
||||||
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
|
||||||
unhexlify("1fbdae5ba753e68af270930413ae90f671eb8ab58988116684bac0abd5726584"))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
@ -1,111 +0,0 @@
|
|||||||
from common import *
|
|
||||||
|
|
||||||
from apps.nem.mosaic import *
|
|
||||||
from trezor.crypto import hashlib
|
|
||||||
|
|
||||||
|
|
||||||
class TestNemTransactionMosaicCreation(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_nem_transaction_mosaic_creation(self):
|
|
||||||
|
|
||||||
# http://bob.nem.ninja:8765/#/mosaic/68364353c29105e6d361ad1a42abbccbf419cfc7adb8b74c8f35d8f8bdaca3fa/0
|
|
||||||
t = nem_transaction_create_mosaic_creation(NEM_NETWORK_TESTNET,
|
|
||||||
14070896,
|
|
||||||
unhexlify('994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324'),
|
|
||||||
108000000,
|
|
||||||
14074496,
|
|
||||||
'gimre.games.pong',
|
|
||||||
'paddles',
|
|
||||||
'Paddles for the bong game.\n',
|
|
||||||
0,
|
|
||||||
10000,
|
|
||||||
True,
|
|
||||||
True,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
'',
|
|
||||||
'',
|
|
||||||
'',
|
|
||||||
'TBMOSAICOD4F54EE5CDMR23CCBGOAM2XSJBR5OLC',
|
|
||||||
50000000000)
|
|
||||||
|
|
||||||
self.assertEqual(t, unhexlify('014000000100009870b4d60020000000994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd32400f36f060000000080c2d600de00000020000000994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd3241f0000001000000067696d72652e67616d65732e706f6e6707000000706164646c65731b000000506164646c657320666f722074686520626f6e672067616d652e0a04000000150000000c00000064697669736962696c69747901000000301a0000000d000000696e697469616c537570706c79050000003130303030190000000d000000737570706c794d757461626c650400000074727565180000000c0000007472616e7366657261626c650400000074727565000000002800000054424d4f534149434f443446353445453543444d523233434342474f414d3258534a4252354f4c4300743ba40b000000'))
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('68364353c29105e6d361ad1a42abbccbf419cfc7adb8b74c8f35d8f8bdaca3fa'))
|
|
||||||
|
|
||||||
def test_nem_transaction_mosaic_creation_with_levy(self):
|
|
||||||
# http://bob.nem.ninja:8765/#/mosaic/b2f4a98113ff1f3a8f1e9d7197aa982545297fe0aa3fa6094af8031569953a55/0
|
|
||||||
t = nem_transaction_create_mosaic_creation(NEM_NETWORK_TESTNET,
|
|
||||||
21497248,
|
|
||||||
unhexlify("244fa194e2509ac0d2fbc18779c2618d8c2ebb61c16a3bcbebcf448c661ba8dc"),
|
|
||||||
108000000,
|
|
||||||
21500848,
|
|
||||||
"alice.misc",
|
|
||||||
"bar",
|
|
||||||
"Special offer: get one bar extra by bying one foo!",
|
|
||||||
0,
|
|
||||||
1000,
|
|
||||||
False,
|
|
||||||
True,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
"TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
|
|
||||||
"nem",
|
|
||||||
"xem",
|
|
||||||
"TBMOSAICOD4F54EE5CDMR23CCBGOAM2XSJBR5OLC",
|
|
||||||
50000000000)
|
|
||||||
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('b2f4a98113ff1f3a8f1e9d7197aa982545297fe0aa3fa6094af8031569953a55'))
|
|
||||||
|
|
||||||
# http://chain.nem.ninja/#/mosaic/e8dc14821dbea4831d9051f86158ef348001447968fc22c01644fdaf2bda75c6/0
|
|
||||||
t = nem_transaction_create_mosaic_creation(NEM_NETWORK_MAINNET,
|
|
||||||
69251020,
|
|
||||||
unhexlify("a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a"),
|
|
||||||
20000000,
|
|
||||||
69337420,
|
|
||||||
"dim",
|
|
||||||
"coin",
|
|
||||||
"DIM COIN",
|
|
||||||
6,
|
|
||||||
9000000000,
|
|
||||||
False,
|
|
||||||
True,
|
|
||||||
2,
|
|
||||||
10,
|
|
||||||
"NCGGLVO2G3CUACVI5GNX2KRBJSQCN4RDL2ZWJ4DP",
|
|
||||||
"dim",
|
|
||||||
"coin",
|
|
||||||
"NBMOSAICOD4F54EE5CDMR23CCBGOAM2XSIUX6TRS",
|
|
||||||
500000000)
|
|
||||||
self.assertEqual(t, unhexlify('0140000001000068ccaf200420000000a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a002d3101000000004c0122040c01000020000000a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a0f0000000300000064696d04000000636f696e0800000044494d20434f494e04000000150000000c00000064697669736962696c69747901000000361f0000000d000000696e697469616c537570706c790a000000393030303030303030301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c6504000000747275654b00000002000000280000004e4347474c564f32473343554143564935474e58324b52424a5351434e3452444c325a574a3444500f0000000300000064696d04000000636f696e0a00000000000000280000004e424d4f534149434f443446353445453543444d523233434342474f414d325853495558365452530065cd1d00000000'))
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('e8dc14821dbea4831d9051f86158ef348001447968fc22c01644fdaf2bda75c6'))
|
|
||||||
|
|
||||||
def test_nem_transaction_mosaic_creation_with_description(self):
|
|
||||||
# http://chain.nem.ninja/#/mosaic/269c6fda657aba3053a0e5b138c075808cc20e244e1182d9b730798b60a1f77b/0
|
|
||||||
t = nem_transaction_create_mosaic_creation(NEM_NETWORK_MAINNET,
|
|
||||||
26729938,
|
|
||||||
unhexlify("58956ac77951622dc5f1c938affbf017c458e30e6b21ddb5783d38b302531f23"),
|
|
||||||
108000000,
|
|
||||||
26733538,
|
|
||||||
"jabo38",
|
|
||||||
"red_token",
|
|
||||||
"This token is to celebrate the release of Namespaces and Mosaics "
|
|
||||||
"on the NEM system. This token was the fist ever mosaic created "
|
|
||||||
"other than nem.xem. There are only 10,000 Red Tokens that will "
|
|
||||||
"ever be created. It has no levy and can be traded freely among "
|
|
||||||
"third parties.",
|
|
||||||
2,
|
|
||||||
10000,
|
|
||||||
False,
|
|
||||||
True,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"NBMOSAICOD4F54EE5CDMR23CCBGOAM2XSIUX6TRS",
|
|
||||||
50000000000)
|
|
||||||
self.assertEqual(t, unhexlify('0140000001000068d2dd97012000000058956ac77951622dc5f1c938affbf017c458e30e6b21ddb5783d38b302531f2300f36f0600000000e2eb9701c80100002000000058956ac77951622dc5f1c938affbf017c458e30e6b21ddb5783d38b302531f2317000000060000006a61626f3338090000007265645f746f6b656e0c0100005468697320746f6b656e20697320746f2063656c656272617465207468652072656c65617365206f66204e616d6573706163657320616e64204d6f7361696373206f6e20746865204e454d2073797374656d2e205468697320746f6b656e207761732074686520666973742065766572206d6f736169632063726561746564206f74686572207468616e206e656d2e78656d2e20546865726520617265206f6e6c792031302c3030302052656420546f6b656e7320746861742077696c6c206576657220626520637265617465642e20497420686173206e6f206c65767920616e642063616e2062652074726164656420667265656c7920616d6f6e6720746869726420706172746965732e04000000150000000c00000064697669736962696c69747901000000321a0000000d000000696e697469616c537570706c790500000031303030301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756500000000280000004e424d4f534149434f443446353445453543444d523233434342474f414d3258534955583654525300743ba40b000000'))
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('269c6fda657aba3053a0e5b138c075808cc20e244e1182d9b730798b60a1f77b'))
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
@ -1,69 +0,0 @@
|
|||||||
from common import *
|
|
||||||
|
|
||||||
from apps.nem.mosaic import *
|
|
||||||
from trezor.crypto import hashlib
|
|
||||||
|
|
||||||
|
|
||||||
class TestNemTransactionMosaicCreation(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_nem_transaction_create_mosaic_supply_change(self):
|
|
||||||
|
|
||||||
# http://bigalice2.nem.ninja:7890/transaction/get?hash=33a50fdd4a54913643a580b2af08b9a5b51b7cee922bde380e84c573a7969c50
|
|
||||||
t = nem_transaction_create_mosaic_supply_change(NEM_NETWORK_TESTNET,
|
|
||||||
14071648,
|
|
||||||
unhexlify("994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"),
|
|
||||||
108000000,
|
|
||||||
14075248,
|
|
||||||
"gimre.games.pong",
|
|
||||||
"paddles",
|
|
||||||
1,
|
|
||||||
1234)
|
|
||||||
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
|
||||||
unhexlify('33a50fdd4a54913643a580b2af08b9a5b51b7cee922bde380e84c573a7969c50'))
|
|
||||||
|
|
||||||
# http://bigalice2.nem.ninja:7890/transaction/get?hash=1ce8e8894d077a66ff22294b000825d090a60742ec407efd80eb8b19657704f2
|
|
||||||
t = nem_transaction_create_mosaic_supply_change(NEM_NETWORK_TESTNET,
|
|
||||||
14126909,
|
|
||||||
unhexlify("84afa1bbc993b7f5536344914dde86141e61f8cbecaf8c9cefc07391f3287cf5"),
|
|
||||||
108000000,
|
|
||||||
14130509,
|
|
||||||
"jabo38_ltd.fuzzy_kittens_cafe",
|
|
||||||
"coupons",
|
|
||||||
2,
|
|
||||||
1)
|
|
||||||
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
|
||||||
unhexlify('1ce8e8894d077a66ff22294b000825d090a60742ec407efd80eb8b19657704f2'))
|
|
||||||
|
|
||||||
# http://bigalice3.nem.ninja:7890/transaction/get?hash=694e493e9576d2bcf60d85747e302ac2e1cc27783187947180d4275a713ff1ff
|
|
||||||
t = nem_transaction_create_mosaic_supply_change(NEM_NETWORK_MAINNET,
|
|
||||||
53377685,
|
|
||||||
unhexlify("b7ccc27b21ba6cf5c699a8dc86ba6ba98950442597ff9fa30e0abe0f5f4dd05d"),
|
|
||||||
20000000,
|
|
||||||
53464085,
|
|
||||||
"abvapp",
|
|
||||||
"abv",
|
|
||||||
1,
|
|
||||||
9000000)
|
|
||||||
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
|
||||||
unhexlify('694e493e9576d2bcf60d85747e302ac2e1cc27783187947180d4275a713ff1ff'))
|
|
||||||
|
|
||||||
# http://bigalice3.nem.ninja:7890/transaction/get?hash=09836334e123970e068d5b411e4d1df54a3ead10acf1ad5935a2cdd9f9680185
|
|
||||||
t = nem_transaction_create_mosaic_supply_change(NEM_NETWORK_MAINNET,
|
|
||||||
55176304,
|
|
||||||
unhexlify("75f001a8641e2ce5c4386883dda561399ed346177411b492a677b73899502f13"),
|
|
||||||
20000000,
|
|
||||||
55262704,
|
|
||||||
"sushi",
|
|
||||||
"wasabi",
|
|
||||||
2,
|
|
||||||
20)
|
|
||||||
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True),
|
|
||||||
unhexlify('09836334e123970e068d5b411e4d1df54a3ead10acf1ad5935a2cdd9f9680185'))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
@ -1,49 +0,0 @@
|
|||||||
from common import *
|
|
||||||
|
|
||||||
from apps.nem.transaction import *
|
|
||||||
from trezor.crypto import hashlib
|
|
||||||
|
|
||||||
|
|
||||||
class TestNemTransactionProvisition(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_create_provision_namespace(self):
|
|
||||||
|
|
||||||
# http://bob.nem.ninja:8765/#/transfer/0acbf8df91e6a65dc56c56c43d65f31ff2a6a48d06fc66e78c7f3436faf3e74f
|
|
||||||
t = nem_transaction_create_provision_namespace(NEM_NETWORK_TESTNET,
|
|
||||||
56999445,
|
|
||||||
unhexlify('84afa1bbc993b7f5536344914dde86141e61f8cbecaf8c9cefc07391f3287cf5'),
|
|
||||||
20000000,
|
|
||||||
57003045,
|
|
||||||
'gimre',
|
|
||||||
'',
|
|
||||||
'TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35',
|
|
||||||
5000000000)
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('f7cab28da57204d01a907c697836577a4ae755e6c9bac60dcc318494a22debb3'))
|
|
||||||
|
|
||||||
# http://bob.nem.ninja:8765/#/namespace/7ddd5fe607e1bfb5606e0ac576024c318c8300d237273117d4db32a60c49524d
|
|
||||||
t = nem_transaction_create_provision_namespace(NEM_NETWORK_TESTNET,
|
|
||||||
21496797,
|
|
||||||
unhexlify('244fa194e2509ac0d2fbc18779c2618d8c2ebb61c16a3bcbebcf448c661ba8dc'),
|
|
||||||
108000000,
|
|
||||||
21500397,
|
|
||||||
'misc',
|
|
||||||
'alice',
|
|
||||||
'TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35',
|
|
||||||
5000000000)
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('7ddd5fe607e1bfb5606e0ac576024c318c8300d237273117d4db32a60c49524d'))
|
|
||||||
|
|
||||||
# http://chain.nem.ninja/#/namespace/57071aad93ca125dc231dc02c07ad8610cd243d35068f9b36a7d231383907569
|
|
||||||
t = nem_transaction_create_provision_namespace(NEM_NETWORK_MAINNET,
|
|
||||||
26699717,
|
|
||||||
unhexlify('9f3c14f304309c8b72b2821339c4428793b1518bea72d58dd01f19d523518614'),
|
|
||||||
108000000,
|
|
||||||
26703317,
|
|
||||||
'sex',
|
|
||||||
'',
|
|
||||||
'NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA',
|
|
||||||
50000000000)
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('57071aad93ca125dc231dc02c07ad8610cd243d35068f9b36a7d231383907569'))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
@ -1,93 +0,0 @@
|
|||||||
from common import *
|
|
||||||
|
|
||||||
from apps.nem.transaction import *
|
|
||||||
from apps.nem.mosaic import *
|
|
||||||
from trezor.crypto import hashlib
|
|
||||||
|
|
||||||
|
|
||||||
class TestNemTransactionTransfer(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_create_transfer(self):
|
|
||||||
|
|
||||||
# http://bob.nem.ninja:8765/#/transfer/0acbf8df91e6a65dc56c56c43d65f31ff2a6a48d06fc66e78c7f3436faf3e74f
|
|
||||||
t = nem_transaction_create_transfer(NEM_NETWORK_TESTNET,
|
|
||||||
0,
|
|
||||||
unhexlify('e59ef184a612d4c3c4d89b5950eb57262c69862b2f96e59c5043bf41765c482f'),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
'TBGIMRE4SBFRUJXMH7DVF2IBY36L2EDWZ37GVSC4',
|
|
||||||
50000000000000)
|
|
||||||
|
|
||||||
self.assertEqual(t, unhexlify('01010000010000980000000020000000e59ef184a612d4c3c4d89b5950eb57262c69862b2f96e59c5043bf41765c482f00000000000000000000000028000000544247494d52453453424652554a584d48374456463249425933364c324544575a3337475653433400203d88792d000000000000'))
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('0acbf8df91e6a65dc56c56c43d65f31ff2a6a48d06fc66e78c7f3436faf3e74f'))
|
|
||||||
|
|
||||||
def test_create_transfer_with_payload(self):
|
|
||||||
|
|
||||||
# http://chain.nem.ninja/#/transfer/e90e98614c7598fbfa4db5411db1b331d157c2f86b558fb7c943d013ed9f71cb
|
|
||||||
t = nem_transaction_create_transfer(NEM_NETWORK_MAINNET,
|
|
||||||
0,
|
|
||||||
unhexlify(
|
|
||||||
'8d07f90fb4bbe7715fa327c926770166a11be2e494a970605f2e12557f66c9b9'),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
'NBT3WHA2YXG2IR4PWKFFMO772JWOITTD2V4PECSB',
|
|
||||||
5175000000000,
|
|
||||||
bytearray('Good luck!'))
|
|
||||||
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('e90e98614c7598fbfa4db5411db1b331d157c2f86b558fb7c943d013ed9f71cb'))
|
|
||||||
|
|
||||||
def test_create_transfer_with_mosaic(self):
|
|
||||||
|
|
||||||
# http://bob.nem.ninja:8765/#/transfer/3409d9ece28d6296d6d5e220a7e3cb8641a3fb235ffcbd20c95da64f003ace6c
|
|
||||||
t = nem_transaction_create_transfer(NEM_NETWORK_TESTNET,
|
|
||||||
14072100,
|
|
||||||
unhexlify('994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324'),
|
|
||||||
194000000,
|
|
||||||
14075700,
|
|
||||||
'TBLOODPLWOWMZ2TARX4RFPOSOWLULHXMROBN2WXI',
|
|
||||||
3000000,
|
|
||||||
bytearray('sending you 3 pairs of paddles\n'),
|
|
||||||
False,
|
|
||||||
2)
|
|
||||||
self.assertEqual(t, unhexlify('010100000200009824b9d60020000000994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd3248034900b0000000034c7d6002800000054424c4f4f44504c574f574d5a3254415258345246504f534f574c554c48584d524f424e32575849c0c62d000000000027000000010000001f00000073656e64696e6720796f752033207061697273206f6620706164646c65730a02000000'))
|
|
||||||
|
|
||||||
nem_transaction_write_mosaic(t, 'gimre.games.pong', 'paddles', 2)
|
|
||||||
nem_transaction_write_mosaic(t, 'nem', 'xem', 44000000)
|
|
||||||
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('3409d9ece28d6296d6d5e220a7e3cb8641a3fb235ffcbd20c95da64f003ace6c'))
|
|
||||||
|
|
||||||
# http://chain.nem.ninja/#/transfer/882dca18dcbe075e15e0ec5a1d7e6ccd69cc0f1309ffd3fde227bfbc107b3f6e
|
|
||||||
t = nem_transaction_create_transfer(NEM_NETWORK_MAINNET,
|
|
||||||
26730750,
|
|
||||||
unhexlify(
|
|
||||||
'f85ab43dad059b9d2331ddacc384ad925d3467f03207182e01296bacfb242d01'),
|
|
||||||
179500000,
|
|
||||||
26734350,
|
|
||||||
'NBE223WPKEBHQPCYUC4U4CDUQCRRFMPZLOQLB5OP',
|
|
||||||
1000000,
|
|
||||||
bytearray('enjoy! :)'),
|
|
||||||
False,
|
|
||||||
1)
|
|
||||||
nem_transaction_write_mosaic(t, 'imre.g', 'tokens', 1)
|
|
||||||
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('882dca18dcbe075e15e0ec5a1d7e6ccd69cc0f1309ffd3fde227bfbc107b3f6e'))
|
|
||||||
|
|
||||||
def test_create_transfer_with_encrypted_payload(self):
|
|
||||||
|
|
||||||
# http://chain.nem.ninja/#/transfer/40e89160e6f83d37f7c82defc0afe2c1605ae8c919134570a51dd27ea1bb516c
|
|
||||||
|
|
||||||
t = nem_transaction_create_transfer(NEM_NETWORK_MAINNET,
|
|
||||||
77229,
|
|
||||||
unhexlify('f85ab43dad059b9d2331ddacc384ad925d3467f03207182e01296bacfb242d01'),
|
|
||||||
30000000,
|
|
||||||
80829,
|
|
||||||
'NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3',
|
|
||||||
30000000,
|
|
||||||
unhexlify('4d9dcf9186967d30be93d6d5404ded22812dbbae7c3f0de501bcd7228cba45bded13000eec7b4c6215fc4d3588168c9218167cec98e6977359153a4132e050f594548e61e0dc61c153f0f53c5e65c595239c9eb7c4e7d48e0f4bb8b1dd2f5ddc'),
|
|
||||||
True)
|
|
||||||
|
|
||||||
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('40e89160e6f83d37f7c82defc0afe2c1605ae8c919134570a51dd27ea1bb516c'))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
116
tests/test_apps.nem.transfer.py
Normal file
116
tests/test_apps.nem.transfer.py
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
from common import *
|
||||||
|
|
||||||
|
from apps.nem.transfer import *
|
||||||
|
from apps.nem.mosaic import *
|
||||||
|
from trezor.crypto import hashlib
|
||||||
|
from trezor.messages.NEMTransfer import NEMTransfer
|
||||||
|
from trezor.messages.NEMSignTx import NEMSignTx
|
||||||
|
|
||||||
|
|
||||||
|
class TestNemTransfer(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_create_transfer(self):
|
||||||
|
|
||||||
|
# http://bob.nem.ninja:8765/#/transfer/0acbf8df91e6a65dc56c56c43d65f31ff2a6a48d06fc66e78c7f3436faf3e74f
|
||||||
|
m = _create_msg(NEM_NETWORK_TESTNET,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
'TBGIMRE4SBFRUJXMH7DVF2IBY36L2EDWZ37GVSC4',
|
||||||
|
50000000000000)
|
||||||
|
|
||||||
|
t = serialize_transfer(m, unhexlify('e59ef184a612d4c3c4d89b5950eb57262c69862b2f96e59c5043bf41765c482f'))
|
||||||
|
self.assertEqual(t, unhexlify('01010000010000980000000020000000e59ef184a612d4c3c4d89b5950eb57262c69862b2f96e59c5043bf41765c482f00000000000000000000000028000000544247494d52453453424652554a584d48374456463249425933364c324544575a3337475653433400203d88792d000000000000'))
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('0acbf8df91e6a65dc56c56c43d65f31ff2a6a48d06fc66e78c7f3436faf3e74f'))
|
||||||
|
|
||||||
|
def test_create_transfer_with_payload(self):
|
||||||
|
|
||||||
|
# http://chain.nem.ninja/#/transfer/e90e98614c7598fbfa4db5411db1b331d157c2f86b558fb7c943d013ed9f71cb
|
||||||
|
m = _create_msg(NEM_NETWORK_MAINNET,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
'NBT3WHA2YXG2IR4PWKFFMO772JWOITTD2V4PECSB',
|
||||||
|
5175000000000)
|
||||||
|
|
||||||
|
t = serialize_transfer(m,
|
||||||
|
unhexlify('8d07f90fb4bbe7715fa327c926770166a11be2e494a970605f2e12557f66c9b9'),
|
||||||
|
bytearray('Good luck!'))
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('e90e98614c7598fbfa4db5411db1b331d157c2f86b558fb7c943d013ed9f71cb'))
|
||||||
|
|
||||||
|
def test_create_transfer_with_encrypted_payload(self):
|
||||||
|
|
||||||
|
# http://chain.nem.ninja/#/transfer/40e89160e6f83d37f7c82defc0afe2c1605ae8c919134570a51dd27ea1bb516c
|
||||||
|
m = _create_msg(NEM_NETWORK_MAINNET,
|
||||||
|
77229,
|
||||||
|
30000000,
|
||||||
|
80829,
|
||||||
|
'NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3',
|
||||||
|
30000000)
|
||||||
|
|
||||||
|
t = serialize_transfer(m,
|
||||||
|
unhexlify('f85ab43dad059b9d2331ddacc384ad925d3467f03207182e01296bacfb242d01'),
|
||||||
|
unhexlify('4d9dcf9186967d30be93d6d5404ded22812dbbae7c3f0de501bcd7228cba45bded13000eec7b4c6215fc4d3588168c9218167cec98e6977359153a4132e050f594548e61e0dc61c153f0f53c5e65c595239c9eb7c4e7d48e0f4bb8b1dd2f5ddc'),
|
||||||
|
True)
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('40e89160e6f83d37f7c82defc0afe2c1605ae8c919134570a51dd27ea1bb516c'))
|
||||||
|
|
||||||
|
def test_create_transfer_with_mosaic(self):
|
||||||
|
|
||||||
|
# http://bob.nem.ninja:8765/#/transfer/3409d9ece28d6296d6d5e220a7e3cb8641a3fb235ffcbd20c95da64f003ace6c
|
||||||
|
m = _create_msg(NEM_NETWORK_TESTNET,
|
||||||
|
14072100,
|
||||||
|
194000000,
|
||||||
|
14075700,
|
||||||
|
'TBLOODPLWOWMZ2TARX4RFPOSOWLULHXMROBN2WXI',
|
||||||
|
3000000,
|
||||||
|
2)
|
||||||
|
|
||||||
|
t = serialize_transfer(m,
|
||||||
|
unhexlify('994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324'),
|
||||||
|
bytearray('sending you 3 pairs of paddles\n'),
|
||||||
|
False)
|
||||||
|
|
||||||
|
self.assertEqual(t, unhexlify('010100000200009824b9d60020000000994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd3248034900b0000000034c7d6002800000054424c4f4f44504c574f574d5a3254415258345246504f534f574c554c48584d524f424e32575849c0c62d000000000027000000010000001f00000073656e64696e6720796f752033207061697273206f6620706164646c65730a02000000'))
|
||||||
|
|
||||||
|
serialize_mosaic(t, 'gimre.games.pong', 'paddles', 2)
|
||||||
|
serialize_mosaic(t, 'nem', 'xem', 44000000)
|
||||||
|
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('3409d9ece28d6296d6d5e220a7e3cb8641a3fb235ffcbd20c95da64f003ace6c'))
|
||||||
|
|
||||||
|
# http://chain.nem.ninja/#/transfer/882dca18dcbe075e15e0ec5a1d7e6ccd69cc0f1309ffd3fde227bfbc107b3f6e
|
||||||
|
m = _create_msg(NEM_NETWORK_MAINNET,
|
||||||
|
26730750,
|
||||||
|
179500000,
|
||||||
|
26734350,
|
||||||
|
'NBE223WPKEBHQPCYUC4U4CDUQCRRFMPZLOQLB5OP',
|
||||||
|
1000000,
|
||||||
|
1)
|
||||||
|
|
||||||
|
t = serialize_transfer(m,
|
||||||
|
unhexlify('f85ab43dad059b9d2331ddacc384ad925d3467f03207182e01296bacfb242d01'),
|
||||||
|
bytearray('enjoy! :)'),
|
||||||
|
False)
|
||||||
|
serialize_mosaic(t, 'imre.g', 'tokens', 1)
|
||||||
|
|
||||||
|
self.assertEqual(hashlib.sha3_256(t).digest(True), unhexlify('882dca18dcbe075e15e0ec5a1d7e6ccd69cc0f1309ffd3fde227bfbc107b3f6e'))
|
||||||
|
|
||||||
|
|
||||||
|
def _create_msg(network: int, timestamp: int, fee: int, deadline: int,
|
||||||
|
recipient: str, amount: int, mosaics: int = 0):
|
||||||
|
m = NEMSignTx()
|
||||||
|
m.transaction = NEMTransactionCommon()
|
||||||
|
m.transaction.network = network
|
||||||
|
m.transaction.timestamp = timestamp
|
||||||
|
m.transaction.fee = fee
|
||||||
|
m.transaction.deadline = deadline
|
||||||
|
m.transfer = NEMTransfer()
|
||||||
|
m.transfer.recipient = recipient
|
||||||
|
m.transfer.amount = amount
|
||||||
|
m.transfer.mosaics = list()
|
||||||
|
for i in range(mosaics):
|
||||||
|
m.transfer.mosaics.append(NEMMosaic())
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Loading…
Reference in New Issue
Block a user