diff --git a/src/apps/nem/__init__.py b/src/apps/nem/__init__.py index e0c9f3b273..483d795f89 100644 --- a/src/apps/nem/__init__.py +++ b/src/apps/nem/__init__.py @@ -3,13 +3,13 @@ from trezor.messages.wire_types import NEMGetAddress, NEMSignTx def dispatch_NemGetAddress(*args, **kwargs): - from .get_address import nem_get_address - return nem_get_address(*args, **kwargs) + from .get_address import get_address + return get_address(*args, **kwargs) def dispatch_NemSignTx(*args, **kwargs): - from .signing import nem_sign_tx - return nem_sign_tx(*args, **kwargs) + from .signing import sign_tx + return sign_tx(*args, **kwargs) def boot(): diff --git a/src/apps/nem/get_address.py b/src/apps/nem/get_address.py index 14c1554857..6dce87eafd 100644 --- a/src/apps/nem/get_address.py +++ b/src/apps/nem/get_address.py @@ -8,7 +8,7 @@ from trezor.ui.text import Text from trezor.utils import chunks -async def nem_get_address(ctx, msg): +async def get_address(ctx, msg): network = validate_network(msg.network) node = await seed.derive_node(ctx, msg.address_n, NEM_CURVE) 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): lines = _split_address(address) - print(network) content = Text('Export NEM address', ui.ICON_RECEIVE, ui.MONO, _get_network_str(network) + ' network', ui.MONO, *lines, diff --git a/src/apps/nem/helpers.py b/src/apps/nem/helpers.py index 22a23fd865..9e619d00e8 100644 --- a/src/apps/nem/helpers.py +++ b/src/apps/nem/helpers.py @@ -1,5 +1,7 @@ from micropython import const +from trezor.messages.NEMSignTx import NEMSignTx + NEM_NETWORK_MAINNET = const(0x68) NEM_NETWORK_TESTNET = const(0x98) diff --git a/src/apps/nem/layout.py b/src/apps/nem/layout.py index a972399ee6..ea82683a8c 100644 --- a/src/apps/nem/layout.py +++ b/src/apps/nem/layout.py @@ -55,7 +55,6 @@ async def require_confirm_payload(ctx, payload: bytes, encrypt=False): if len(payload) > 48: payload = payload[:48] + '..' - print(len(payload)) if encrypt: content = Text('Confirm payload', ui.ICON_SEND, ui.BOLD, 'Encrypted:', diff --git a/src/apps/nem/mosaic.py b/src/apps/nem/mosaic.py index c9d5b4a1de..77b370c90d 100644 --- a/src/apps/nem/mosaic.py +++ b/src/apps/nem/mosaic.py @@ -1,79 +1,84 @@ - -from .helpers import * from .writers import * 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, - 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): +async def ask_mosaic_creation(ctx, msg: NEMSignTx): + 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) - w = nem_transaction_write_common(NEM_TRANSACTION_TYPE_MOSAIC_CREATION, - nem_get_version(network), - timestamp, - signer_public_key, - fee, - deadline) + await require_confirm_final(ctx, msg.transaction.fee) + + +async def ask_mosaic_supply_change(ctx, 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) + + +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() - write_bytes_with_length(mosaics_w, bytearray(signer_public_key)) - identifier_length = 4 + len(namespace) + 4 + len(mosaic) + write_bytes_with_length(mosaics_w, bytearray(public_key)) + identifier_length = 4 + len(msg.mosaic_creation.definition.namespace) + 4 + len(msg.mosaic_creation.definition.mosaic) write_uint32(mosaics_w, identifier_length) - write_bytes_with_length(mosaics_w, bytearray(namespace)) - write_bytes_with_length(mosaics_w, bytearray(mosaic)) - write_bytes_with_length(mosaics_w, bytearray(description)) + write_bytes_with_length(mosaics_w, bytearray(msg.mosaic_creation.definition.namespace)) + write_bytes_with_length(mosaics_w, bytearray(msg.mosaic_creation.definition.mosaic)) + write_bytes_with_length(mosaics_w, bytearray(msg.mosaic_creation.definition.description)) write_uint32(mosaics_w, 4) # number of properties - nem_write_mosaic(mosaics_w, "divisibility", divisibility) - nem_write_mosaic(mosaics_w, "initialSupply", supply) - nem_write_mosaic(mosaics_w, "supplyMutable", mutable_supply) - nem_write_mosaic(mosaics_w, "transferable", transferable) + _write_property(mosaics_w, "divisibility", msg.mosaic_creation.definition.divisibility) + _write_property(mosaics_w, "initialSupply", msg.mosaic_creation.definition.supply) + _write_property(mosaics_w, "supplyMutable", msg.mosaic_creation.definition.mutable_supply) + _write_property(mosaics_w, "transferable", msg.mosaic_creation.definition.transferable) - if levy_type: - levy_identifier_length = 4 + len(levy_namespace) + 4 + len(levy_mosaic) - write_uint32(mosaics_w, 4 + 4 + len(levy_address) + 4 + levy_identifier_length + 8) - write_uint32(mosaics_w, levy_type) - write_bytes_with_length(mosaics_w, bytearray(levy_address)) + if msg.mosaic_creation.definition.levy: + 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(msg.mosaic_creation.definition.levy_address) + 4 + levy_identifier_length + 8) + write_uint32(mosaics_w, msg.mosaic_creation.definition.levy) + write_bytes_with_length(mosaics_w, bytearray(msg.mosaic_creation.definition.levy_address)) write_uint32(mosaics_w, levy_identifier_length) - write_bytes_with_length(mosaics_w, bytearray(levy_namespace)) - write_bytes_with_length(mosaics_w, bytearray(levy_mosaic)) - write_uint64(mosaics_w, levy_fee) + write_bytes_with_length(mosaics_w, bytearray(msg.mosaic_creation.definition.levy_namespace)) + write_bytes_with_length(mosaics_w, bytearray(msg.mosaic_creation.definition.levy_mosaic)) + write_uint64(mosaics_w, msg.mosaic_creation.definition.fee) else: write_uint32(mosaics_w, 0) # write mosaic bytes with length write_bytes_with_length(w, mosaics_w) - write_bytes_with_length(w, bytearray(creation_sink)) - write_uint64(w, creation_fee) + write_bytes_with_length(w, bytearray(msg.mosaic_creation.sink)) + write_uint64(w, msg.mosaic_creation.fee) return w -def nem_transaction_create_mosaic_supply_change(network: int, timestamp: int, signer_public_key: bytes, fee: int, - deadline: int, namespace: str, mosaic: str, type: int, delta: int): +def serialize_mosaic_supply_change(msg: NEMSignTx, public_key: bytes): + 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, - nem_get_version(network), - timestamp, - signer_public_key, - fee, - deadline) - - identifier_length = 4 + len(namespace) + 4 + len(mosaic) + identifier_length = 4 + len(msg.supply_change.namespace) + 4 + len(msg.supply_change.mosaic) write_uint32(w, identifier_length) - write_bytes_with_length(w, bytearray(namespace)) - write_bytes_with_length(w, bytearray(mosaic)) - - write_uint32(w, type) - write_uint64(w, delta) + write_bytes_with_length(w, bytearray(msg.supply_change.namespace)) + write_bytes_with_length(w, bytearray(msg.supply_change.mosaic)) + write_uint32(w, msg.supply_change.type) + write_uint64(w, msg.supply_change.delta) return w -def nem_write_mosaic(w: bytearray, name: str, value): +def _write_property(w: bytearray, name: str, value): if value is None: if name in ['divisibility', 'initialSupply']: value = 0 @@ -93,7 +98,7 @@ def nem_write_mosaic(w: bytearray, name: str, 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) # indentifier length (u32) + quantity (u64) + identifier size 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) -def nem_canonicalize_mosaics(mosaics: list): +def canonicalize_mosaics(mosaics: list): if len(mosaics) <= 1: return mosaics - mosaics = nem_merge_mosaics(mosaics) - return nem_sort_mosaics(mosaics) + mosaics = merge_mosaics(mosaics) + return sort_mosaics(mosaics) def are_mosaics_equal(a: NEMMosaic, b: NEMMosaic) -> bool: @@ -116,7 +121,7 @@ def are_mosaics_equal(a: NEMMosaic, b: NEMMosaic) -> bool: return False -def nem_merge_mosaics(mosaics: list) -> list: +def merge_mosaics(mosaics: list) -> list: if not len(mosaics): return list() ret = list() @@ -131,5 +136,5 @@ def nem_merge_mosaics(mosaics: list) -> list: 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)) diff --git a/src/apps/nem/multisig.py b/src/apps/nem/multisig.py index 6942d859c7..1058cfd8ea 100644 --- a/src/apps/nem/multisig.py +++ b/src/apps/nem/multisig.py @@ -1,38 +1,73 @@ - -from .helpers import * from .writers import * +from apps.nem.layout import * 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, - fee: int, deadline: int, inner: bytes): +async def ask_multisig(ctx, msg: NEMSignTx): + # 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)) - return w -def nem_transaction_create_multisig_signature(network: int, timestamp: int, signer_public_key: bytes, - fee: int, deadline: int, inner: bytes, address: str): +def serialize_multisig_signature(msg: NEMTransactionCommon, public_key: bytes, 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, - nem_get_version(network), - 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_uint32(w, 4 + len(digest)) + write_bytes_with_length(w, digest) write_bytes_with_length(w, address) - 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) diff --git a/src/apps/nem/namespace.py b/src/apps/nem/namespace.py new file mode 100644 index 0000000000..cc720ad904 --- /dev/null +++ b/src/apps/nem/namespace.py @@ -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 diff --git a/src/apps/nem/signing.py b/src/apps/nem/signing.py index af2304b87b..f56f52857c 100644 --- a/src/apps/nem/signing.py +++ b/src/apps/nem/signing.py @@ -1,36 +1,37 @@ -from apps.nem.layout import * -from apps.nem.transaction import * +from apps.nem.transfer import * +from apps.nem.multisig import * +from apps.nem.namespace import * from apps.nem.mosaic import * from apps.nem.validators import validate from apps.nem import helpers 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.NEMSignedTx import NEMSignedTx 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) 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: - msg.transfer.mosaics = nem_canonicalize_mosaics(msg.transfer.mosaics) - tx = await _transfer(ctx, node, msg) + msg.transfer.mosaics = canonicalize_mosaics(msg.transfer.mosaics) + tx = await _transfer(ctx, public_key, msg, node) elif msg.provision_namespace: - tx = await _provision_namespace(ctx, node, msg) + tx = await _provision_namespace(ctx, public_key, msg) elif msg.mosaic_creation: - tx = await _mosaic_creation(ctx, node, msg) + tx = await _mosaic_creation(ctx, public_key, msg) elif msg.supply_change: - tx = await _supply_change(ctx, node, msg) + tx = await _supply_change(ctx, public_key, msg) elif msg.aggregate_modification: - tx = await _aggregate_modification(ctx, node, msg) + tx = await _aggregate_modification(ctx, public_key, msg) elif msg.importance_transfer: - tx = await _importance_transfer(ctx, node, msg) + tx = await _importance_transfer(ctx, public_key, msg) else: raise ValueError('No transaction provided') @@ -42,184 +43,51 @@ async def nem_sign_tx(ctx, msg: NEMSignTx): 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: # 0x01 prefix is not part of the actual public key, hence removed return node.public_key()[1:] -def _nem_encrypt(node, public_key: bytes, payload: bytes) -> bytes: - salt = random.bytes(helpers.NEM_SALT_SIZE) - iv = random.bytes(helpers.AES_BLOCK_SIZE) - encrypted = node.nem_encrypt(public_key, iv, salt, payload) - return iv + salt + encrypted +async def _transfer(ctx, public_key: bytes, msg: NEMSignTx, node) -> bytes: + payload, encrypted = get_transfer_payload(msg, node) + await ask_transfer(ctx, msg, payload, 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) diff --git a/src/apps/nem/transaction.py b/src/apps/nem/transaction.py deleted file mode 100644 index 97e6ef11f7..0000000000 --- a/src/apps/nem/transaction.py +++ /dev/null @@ -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) diff --git a/src/apps/nem/transfer.py b/src/apps/nem/transfer.py new file mode 100644 index 0000000000..81b87a399e --- /dev/null +++ b/src/apps/nem/transfer.py @@ -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 diff --git a/src/apps/nem/validators.py b/src/apps/nem/validators.py index 216e15053c..1ac4502e50 100644 --- a/src/apps/nem/validators.py +++ b/src/apps/nem/validators.py @@ -76,12 +76,12 @@ def _validate_common(common: NEMTransactionCommon, inner: bool=False): if common.deadline is None: err = 'deadline' - is_signer = common.signer is not None - if inner != is_signer: - if not inner: - raise ValueError('Signer not allowed in outer transaction') - err = 'signer' - + # is_signer = common.signer is not None todo !! + # if inner != is_signer: + # if not inner: + # raise ValueError('Signer not allowed in outer transaction') + # err = 'signer' + # if err: if inner: 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): + _validate_common(multisig) + _validate_public_key(multisig.signer, 'Invalid multisig signer public key provided') if multisig.network != network: raise ValueError('Inner transaction network is different') diff --git a/src/apps/nem/writers.py b/src/apps/nem/writers.py index 0f3544328c..dfd601551d 100644 --- a/src/apps/nem/writers.py +++ b/src/apps/nem/writers.py @@ -1,4 +1,7 @@ +from trezor.messages.NEMTransactionCommon import NEMTransactionCommon + + def write_uint32(w, n: int): w.append(n & 0xFF) w.append((n >> 8) & 0xFF) @@ -26,21 +29,16 @@ def write_bytes_with_length(w, buf: bytearray): write_bytes(w, buf) -def nem_transaction_write_common(tx_type: int, version: int, timestamp: int, signer: bytes, fee: int, deadline: int)\ - -> bytearray: +def write_common(common: NEMTransactionCommon, public_key: bytearray, transaction_type: int, version: int=None) -> 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, timestamp) + write_uint32(ret, common.timestamp) - write_bytes_with_length(ret, bytearray(signer)) - write_uint64(ret, fee) - write_uint32(ret, deadline) + write_bytes_with_length(ret, public_key) + write_uint64(ret, common.fee) + write_uint32(ret, common.deadline) return ret - - -def nem_get_version(network, mosaics=None) -> int: - if mosaics: - return network << 24 | 2 - return network << 24 | 1 diff --git a/tests/test_apps.nem.transaction.mosaic.canonicalization.py b/tests/test_apps.nem.mosaic.canonicalization.py similarity index 79% rename from tests/test_apps.nem.transaction.mosaic.canonicalization.py rename to tests/test_apps.nem.mosaic.canonicalization.py index c5d3b676dc..3de8ab89f3 100644 --- a/tests/test_apps.nem.transaction.mosaic.canonicalization.py +++ b/tests/test_apps.nem.mosaic.canonicalization.py @@ -1,11 +1,10 @@ from common 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.namespace = 'abc' a.quantity = 3 @@ -35,13 +34,13 @@ class TestNemTransactionMosaicCanonicalization(unittest.TestCase): g.quantity = 30 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[2].quantity, b.quantity) self.assertEqual(res[3].quantity, 3 + 8) # a + d self.assertEqual(res[4].quantity, 3 + 30) # c + g - def test_nem_transaction_mosaic_merge(self): + def test_mosaic_merge(self): a = NEMMosaic() a.namespace = 'abc' a.quantity = 1 @@ -51,24 +50,24 @@ class TestNemTransactionMosaicCanonicalization(unittest.TestCase): b.quantity = 1 b.mosaic = 'mosaic' - merged = nem_merge_mosaics([a, b]) + merged = merge_mosaics([a, b]) self.assertEqual(merged[0].quantity, 2) self.assertEqual(len(merged), 1) a.quantity = 1 b.quantity = 10 - merged = nem_merge_mosaics([a, b]) + merged = merge_mosaics([a, b]) self.assertEqual(merged[0].quantity, 11) a.namespace = 'abcdef' - merged = nem_merge_mosaics([a, b]) + merged = merge_mosaics([a, b]) self.assertEqual(len(merged), 2) c = NEMMosaic() c.namespace = 'abc' c.mosaic = 'xxx' c.quantity = 2 - merged = nem_merge_mosaics([a, b, c]) + merged = merge_mosaics([a, b, c]) self.assertEqual(len(merged), 3) a.namespace = 'abcdef' @@ -80,7 +79,7 @@ class TestNemTransactionMosaicCanonicalization(unittest.TestCase): c.namespace = 'abc' c.mosaic = 'mosaic' 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[1].quantity, 5) self.assertEqual(len(merged), 2) @@ -94,11 +93,11 @@ class TestNemTransactionMosaicCanonicalization(unittest.TestCase): c.namespace = 'abc' c.mosaic = 'mosaic' c.quantity = 3 - merged = nem_merge_mosaics([a, b, c]) + merged = merge_mosaics([a, b, c]) self.assertEqual(merged[0].quantity, 6) self.assertEqual(len(merged), 1) - def test_nem_transaction_mosaic_sort(self): + def test_mosaic_sort(self): a = NEMMosaic() a.namespace = 'abcz' a.quantity = 1 @@ -107,39 +106,39 @@ class TestNemTransactionMosaicCanonicalization(unittest.TestCase): b.namespace = 'abca' b.quantity = 1 b.mosaic = 'mosaic' - res = nem_sort_mosaics([a, b]) + res = sort_mosaics([a, b]) self.assertEqual(res, [b, a]) a.namespace = '' b.namespace = 'a.b.c' - res = nem_sort_mosaics([a, b]) + res = sort_mosaics([a, b]) self.assertEqual(res, [a, b]) a.namespace = 'z.z.z' b.namespace = 'a.b.c' - res = nem_sort_mosaics([a, b]) + res = sort_mosaics([a, b]) self.assertEqual(res, [b, a]) a.namespace = 'a' b.namespace = 'a' a.mosaic = 'mosaic' b.mosaic = 'mosaic' - res = nem_sort_mosaics([a, b]) + res = sort_mosaics([a, b]) self.assertEqual(res, [a, b]) a.mosaic = 'www' b.mosaic = 'aaa' - res = nem_sort_mosaics([a, b]) + res = sort_mosaics([a, b]) self.assertEqual(res, [b, a]) c = NEMMosaic() c.namespace = 'a' c.mosaic = 'zzz' - res = nem_sort_mosaics([a, b, c]) + res = sort_mosaics([a, b, c]) self.assertEqual(res, [b, a, c]) c.mosaic = 'bbb' - res = nem_sort_mosaics([a, b, c]) + res = sort_mosaics([a, b, c]) self.assertEqual(res, [b, c, a]) diff --git a/tests/test_apps.nem.mosaic_creation.py b/tests/test_apps.nem.mosaic_creation.py new file mode 100644 index 0000000000..7085dad48f --- /dev/null +++ b/tests/test_apps.nem.mosaic_creation.py @@ -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() diff --git a/tests/test_apps.nem.mosaic_supply_change.py b/tests/test_apps.nem.mosaic_supply_change.py new file mode 100644 index 0000000000..48a77c1429 --- /dev/null +++ b/tests/test_apps.nem.mosaic_supply_change.py @@ -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() diff --git a/tests/test_apps.nem.multisig.aggregate_modification.py b/tests/test_apps.nem.multisig.aggregate_modification.py new file mode 100644 index 0000000000..2c3007f9dd --- /dev/null +++ b/tests/test_apps.nem.multisig.aggregate_modification.py @@ -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() diff --git a/tests/test_apps.nem.multisig.py b/tests/test_apps.nem.multisig.py index 061838f235..caa3da37a2 100644 --- a/tests/test_apps.nem.multisig.py +++ b/tests/test_apps.nem.multisig.py @@ -1,86 +1,113 @@ from common import * -from apps.nem.transaction 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): def test_nem_multisig(self): # 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, - 3939039, - unhexlify("abac2ee3d4aaa7a3bfb65261a00cc04c761521527dd3f2cf741e2815cbba83ac"), - 16000000, - 3960639, - 1, - 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) + base_tx = serialize_cosignatory_modification(base_tx, 2, unhexlify("e6cff9b3725a91f31089c3acca0fac3e341c00b1c8c6e9578f66c4514509c3b3")) + m = _create_common_msg(NEM_NETWORK_TESTNET, + 3939039, + 6000000, + 3960639) + multisig = serialize_multisig(m, unhexlify("59d89076964742ef2a2089d26a5aa1d2c7a7bb052a46c1de159891e91ad3d76e"), base_tx) self.assertEqual(multisig, unhexlify("0410000001000098df1a3c002000000059d89076964742ef2a2089d26a5aa1d2c7a7bb052a46c1de159891e91ad3d76e808d5b00000000003f6f3c006c0000000110000001000098df1a3c0020000000abac2ee3d4aaa7a3bfb65261a00cc04c761521527dd3f2cf741e2815cbba83ac0024f400000000003f6f3c0001000000280000000200000020000000e6cff9b3725a91f31089c3acca0fac3e341c00b1c8c6e9578f66c4514509c3b3")) address = "TCRXYUQIMFA7AOGL5LF3YWLC7VABLYUMJ5ACBUNL" - multisig = nem_transaction_create_multisig_signature(NEM_NETWORK_TESTNET, - 3939891, - unhexlify("71cba4f2a28fd19f902ba40e9937994154d9eeaad0631d25d525ec37922567d4"), - 6000000, - 3961491, - base_tx, - address) + m = _create_common_msg(NEM_NETWORK_TESTNET, + 3939891, + 6000000, + 3961491) + multisig = serialize_multisig_signature(m, unhexlify("71cba4f2a28fd19f902ba40e9937994154d9eeaad0631d25d525ec37922567d4"), base_tx, address) self.assertEqual(multisig, unhexlify("0210000001000098331e3c002000000071cba4f2a28fd19f902ba40e9937994154d9eeaad0631d25d525ec37922567d4808d5b000000000093723c0024000000200000008ec165580bdabfd31ce6007a1748ce5bdf30eab7a214743097de3bc822ac7e002800000054435258595551494d464137414f474c354c463359574c43375641424c59554d4a35414342554e4c")) def test_nem_multisig_2(self): # 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, - 59414272, - unhexlify("a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a"), - 20000000, - 59500672, - "dim", - "", - "NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA", - 5000000000) - - multisig = nem_transaction_create_multisig(NEM_NETWORK_MAINNET, - 59414272, - unhexlify("cfe58463f0eaebceb5d00717f8aead49171a5d7c08f6b1299bd534f11715acc9"), - 6000000, - 59500672, - base_tx) + m = _create_common_msg(NEM_NETWORK_MAINNET, + 59414272, + 6000000, + 59500672) + multisig = serialize_multisig(m, unhexlify("cfe58463f0eaebceb5d00717f8aead49171a5d7c08f6b1299bd534f11715acc9"), base_tx) self.assertEqual(multisig, unhexlify("041000000100006800978a0320000000cfe58463f0eaebceb5d00717f8aead49171a5d7c08f6b1299bd534f11715acc9808d5b000000000080e88b037b000000012000000100006800978a0320000000a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a002d31010000000080e88b03280000004e414d4553504143455748344d4b464d42435646455244504f4f5034464b374d54425844505a5a4100f2052a010000000300000064696dffffffff")) + m = _create_common_msg(NEM_NETWORK_MAINNET, + 59414342, + 6000000, + 59500742) address = "NDDRG3UEB5LZZZMDWBE4RTKZK73JBHPAIWBHCFMV" - multisig = nem_transaction_create_multisig_signature(NEM_NETWORK_MAINNET, - 59414342, - unhexlify("1b49b80203007117d034e45234ffcdf402c044aeef6dbb06351f346ca892bce2"), - 6000000, - 59500742, - base_tx, - address) - + multisig = serialize_multisig_signature(m, unhexlify("1b49b80203007117d034e45234ffcdf402c044aeef6dbb06351f346ca892bce2"), base_tx, address) self.assertEqual(multisig, unhexlify("021000000100006846978a03200000001b49b80203007117d034e45234ffcdf402c044aeef6dbb06351f346ca892bce2808d5b0000000000c6e88b032400000020000000bfa2088f7720f89dd4664d650e321dabd02fab61b7355bc88a391a848a49786a280000004e4444524733554542354c5a5a5a4d445742453452544b5a4b37334a424850414957424843464d56")) - multisig = nem_transaction_create_multisig_signature(NEM_NETWORK_MAINNET, - 59414381, - unhexlify("7ba4b39209f1b9846b098fe43f74381e43cb2882ccde780f558a63355840aa87"), - 6000000, - 59500781, - base_tx, - address) - + m = _create_common_msg(NEM_NETWORK_MAINNET, + 59414381, + 6000000, + 59500781) + address = "NDDRG3UEB5LZZZMDWBE4RTKZK73JBHPAIWBHCFMV" + multisig = serialize_multisig_signature(m, unhexlify("7ba4b39209f1b9846b098fe43f74381e43cb2882ccde780f558a63355840aa87"), base_tx, address) 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__': unittest.main() diff --git a/tests/test_apps.nem.namespace.py b/tests/test_apps.nem.namespace.py new file mode 100644 index 0000000000..b84bf67292 --- /dev/null +++ b/tests/test_apps.nem.namespace.py @@ -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() diff --git a/tests/test_apps.nem.transaction.aggregate_modification.py b/tests/test_apps.nem.transaction.aggregate_modification.py deleted file mode 100644 index e0d58b70ff..0000000000 --- a/tests/test_apps.nem.transaction.aggregate_modification.py +++ /dev/null @@ -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() diff --git a/tests/test_apps.nem.transaction.mosaic_creation.py b/tests/test_apps.nem.transaction.mosaic_creation.py deleted file mode 100644 index 725db6f056..0000000000 --- a/tests/test_apps.nem.transaction.mosaic_creation.py +++ /dev/null @@ -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() diff --git a/tests/test_apps.nem.transaction.mosaic_supply_change.py b/tests/test_apps.nem.transaction.mosaic_supply_change.py deleted file mode 100644 index 0f72f21e61..0000000000 --- a/tests/test_apps.nem.transaction.mosaic_supply_change.py +++ /dev/null @@ -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() diff --git a/tests/test_apps.nem.transaction.provision.py b/tests/test_apps.nem.transaction.provision.py deleted file mode 100644 index 9ef13edf59..0000000000 --- a/tests/test_apps.nem.transaction.provision.py +++ /dev/null @@ -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() diff --git a/tests/test_apps.nem.transaction.transfer.py b/tests/test_apps.nem.transaction.transfer.py deleted file mode 100644 index 75648ff80b..0000000000 --- a/tests/test_apps.nem.transaction.transfer.py +++ /dev/null @@ -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() diff --git a/tests/test_apps.nem.transfer.py b/tests/test_apps.nem.transfer.py new file mode 100644 index 0000000000..bf37ca8dd2 --- /dev/null +++ b/tests/test_apps.nem.transfer.py @@ -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()