nem: big refactoring of serialization

protocol classes are now used; reflected in unit tests
pull/25/head
Tomas Susanka 6 years ago committed by Jan Pochyla
parent 561ca35a08
commit d54d33df3a

@ -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():

@ -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,

@ -1,5 +1,7 @@
from micropython import const
from trezor.messages.NEMSignTx import NEMSignTx
NEM_NETWORK_MAINNET = const(0x68)
NEM_NETWORK_TESTNET = const(0x98)

@ -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:',

@ -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 *
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)
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 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):
w = nem_transaction_write_common(NEM_TRANSACTION_TYPE_MOSAIC_CREATION,
nem_get_version(network),
timestamp,
signer_public_key,
fee,
deadline)
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):
w = nem_transaction_write_common(NEM_TRANSACTION_TYPE_MOSAIC_SUPPLY_CHANGE,
nem_get_version(network),
timestamp,
signer_public_key,
fee,
deadline)
def serialize_mosaic_supply_change(msg: NEMSignTx, public_key: bytes):
w = write_common(msg.transaction, bytearray(public_key), NEM_TRANSACTION_TYPE_MOSAIC_SUPPLY_CHANGE)
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))

@ -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)
write_bytes_with_length(w, bytearray(inner))
async def ask_aggregate_modification(ctx, msg: NEMSignTx):
if not msg.multisig:
await require_confirm_action(ctx, 'Convert account to multisig account?')
return w
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 nem_transaction_create_multisig_signature(network: int, timestamp: int, signer_public_key: bytes,
fee: int, deadline: int, inner: bytes, address: str):
w = nem_transaction_write_common(NEM_TRANSACTION_TYPE_MULTISIG_SIGNATURE,
nem_get_version(network),
timestamp,
signer_public_key,
fee,
deadline)
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
hash = hashlib.sha3_256(inner).digest(True)
write_uint32(w, 4 + len(hash))
write_bytes_with_length(w, hash)
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)
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)

@ -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.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)
def _get_public_key(node) -> bytes:
# 0x01 prefix is not part of the actual public key, hence removed
return node.public_key()[1:]
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)
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)
await require_confirm_final(ctx, msg.transaction.fee)
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 _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)
)
async def _provision_namespace(ctx, public_key: bytes, msg: NEMSignTx) -> bytearray:
await ask_provision_namespace(ctx, msg)
return serialize_provision_namespace(msg, public_key)
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)
async def _mosaic_creation(ctx, public_key: bytes, msg: NEMSignTx) -> bytearray:
await ask_mosaic_creation(ctx, msg)
return serialize_mosaic_creation(msg, public_key)
if payload:
await require_confirm_payload(ctx, msg.transfer.payload, encrypted)
await require_confirm_final(ctx, msg.transaction.fee)
return tx
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)
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
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)
def _get_public_key(node) -> bytes:
# 0x01 prefix is not part of the actual public key, hence removed
return node.public_key()[1:]
if msg.aggregate_modification.relative_change:
serialize_minimum_cosignatories(w, msg.aggregate_modification.relative_change)
return w
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 _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)

@ -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:
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')

@ -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

@ -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])

@ -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()

@ -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()

@ -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 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
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)
m = _create_msg(NEM_NETWORK_TESTNET,
3939039,
16000000,
3960639,
1,
False)
base_tx = serialize_aggregate_modification(m, unhexlify("abac2ee3d4aaa7a3bfb65261a00cc04c761521527dd3f2cf741e2815cbba83ac"))
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
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_provision_msg(NEM_NETWORK_MAINNET,
59414272,
20000000,
59500672,
"dim",
"",
"NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA",
5000000000)
base_tx = serialize_provision_namespace(m, unhexlify("a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a"))
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()

@ -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()

@ -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…
Cancel
Save