1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 23:48:12 +00:00

nem: refactored to directories

This commit is contained in:
Tomas Susanka 2018-04-12 14:53:10 +02:00 committed by Jan Pochyla
parent 32681972f1
commit 8de3cd7cac
16 changed files with 256 additions and 228 deletions

View File

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

View File

@ -0,0 +1,12 @@
from .layout import *
from .serialize import *
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)

View File

@ -0,0 +1,26 @@
from apps.nem.layout import *
from trezor.messages import NEMSignTx
from trezor.messages import NEMSupplyChangeType
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)

View File

@ -1,30 +1,6 @@
from .writers import * from apps.nem.writers import *
from trezor.messages.NEMMosaic import NEMMosaic from apps.nem.helpers import *
from trezor.messages import NEMSupplyChangeType from trezor.messages.NEMSignTx import NEMSignTx
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 serialize_mosaic_creation(msg: NEMSignTx, public_key: bytes): def serialize_mosaic_creation(msg: NEMSignTx, public_key: bytes):
@ -96,45 +72,3 @@ def _write_property(w: bytearray, name: str, value):
write_uint32(w, 4 + len(name) + 4 + len(value)) write_uint32(w, 4 + len(name) + 4 + len(value))
write_bytes_with_length(w, bytearray(name)) write_bytes_with_length(w, bytearray(name))
write_bytes_with_length(w, bytearray(value)) write_bytes_with_length(w, bytearray(value))
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)
write_uint32(w, identifier_length)
write_bytes_with_length(w, bytearray(namespace))
write_bytes_with_length(w, bytearray(mosaic))
write_uint64(w, quantity)
def canonicalize_mosaics(mosaics: list):
if len(mosaics) <= 1:
return mosaics
mosaics = merge_mosaics(mosaics)
return sort_mosaics(mosaics)
def are_mosaics_equal(a: NEMMosaic, b: NEMMosaic) -> bool:
if a.namespace == b.namespace and a.mosaic == b.mosaic:
return True
return False
def merge_mosaics(mosaics: list) -> list:
if not len(mosaics):
return list()
ret = list()
for i in mosaics:
found = False
for k, y in enumerate(ret):
if are_mosaics_equal(i, y):
ret[k].quantity += i.quantity
found = True
if not found:
ret.append(i)
return ret
def sort_mosaics(mosaics: list) -> list:
return sorted(mosaics, key=lambda m: (m.namespace, m.mosaic))

View File

@ -0,0 +1,29 @@
from .serialize import *
from .layout import *
async def ask(ctx, msg: NEMSignTx):
await ask_multisig(ctx, msg)
def initiate(public_key, msg: NEMSignTx, inner_tx: bytes) -> bytes:
return serialize_multisig(msg.multisig, public_key, inner_tx)
def cosign(public_key, msg: NEMSignTx, inner_tx: bytes) -> bytes:
return serialize_multisig_signature(msg.multisig,
public_key,
inner_tx,
msg.multisig.signer)
async def aggregate_modification(ctx, public_key: bytes, msg: NEMSignTx):
await ask_aggregate_modification(ctx, msg)
w = serialize_aggregate_modification(msg, public_key)
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

View File

@ -0,0 +1,36 @@
from apps.nem.layout import *
from trezor.messages import NEMModificationType
from trezor.messages import NEMSignTx
from trezor.crypto import nem
async def ask_multisig(ctx, msg: NEMSignTx):
address = nem.compute_address(msg.multisig.signer, msg.transaction.network)
if msg.cosigning:
await require_confirm_address(ctx, 'Cosign transaction for', address)
else:
await require_confirm_address(ctx, 'Initiate transaction for', address)
await require_confirm_fee(ctx, 'Confirm multisig fee', msg.multisig.fee)
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)

View File

@ -1,41 +1,10 @@
from .writers import * from apps.nem.writers import *
from apps.nem.layout import * from apps.nem.helpers import *
from trezor.messages.NEMSignTx import NEMSignTx
from trezor.crypto import hashlib from trezor.crypto import hashlib
from trezor.messages import NEMModificationType
from trezor.crypto import nem from trezor.crypto import nem
async def ask_multisig(ctx, msg: NEMSignTx):
address = nem.compute_address(msg.multisig.signer, msg.transaction.network)
if msg.cosigning:
await require_confirm_address(ctx, 'Cosign transaction for', address)
else:
await require_confirm_address(ctx, 'Initiate transaction for', address)
await require_confirm_fee(ctx, 'Confirm multisig fee', msg.multisig.fee)
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): def serialize_multisig(msg: NEMTransactionCommon, public_key: bytes, inner: bytes):
w = write_common(msg, bytearray(public_key), NEM_TRANSACTION_TYPE_MULTISIG) w = write_common(msg, bytearray(public_key), NEM_TRANSACTION_TYPE_MULTISIG)
write_bytes_with_length(w, bytearray(inner)) write_bytes_with_length(w, bytearray(inner))

View File

@ -1,29 +0,0 @@
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

View File

@ -0,0 +1,7 @@
from .layout import *
from .serialize import *
async def namespace(ctx, public_key: bytes, msg: NEMSignTx) -> bytearray:
await ask_provision_namespace(ctx, msg)
return serialize_provision_namespace(msg, public_key)

View File

@ -0,0 +1,13 @@
from apps.nem.layout import *
from trezor.messages import NEMSignTx
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)

View File

@ -0,0 +1,19 @@
from apps.nem.helpers import *
from apps.nem.writers import *
from trezor.messages.NEMSignTx import NEMSignTx
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

View File

@ -1,9 +1,9 @@
from apps.nem.transfer import * from apps.nem import namespace
from apps.nem.multisig import * from apps.nem import transfer
from apps.nem.namespace import * from apps.nem import mosaic
from apps.nem.mosaic import * from apps.nem import multisig
from apps.nem.validators import validate from apps.nem.validators import validate
from apps.nem import helpers from apps.nem.helpers import *
from apps.common import seed from apps.common import seed
from trezor.messages.NEMSignTx import NEMSignTx from trezor.messages.NEMSignTx import NEMSignTx
from trezor.messages.NEMSignedTx import NEMSignedTx from trezor.messages.NEMSignedTx import NEMSignedTx
@ -16,31 +16,33 @@ async def sign_tx(ctx, msg: NEMSignTx):
if msg.multisig: if msg.multisig:
public_key = msg.multisig.signer public_key = msg.multisig.signer
await ask_multisig(ctx, msg) await multisig.ask(ctx, msg)
else: else:
public_key = _get_public_key(node) public_key = _get_public_key(node)
if msg.transfer: if msg.transfer:
msg.transfer.mosaics = canonicalize_mosaics(msg.transfer.mosaics) tx = await transfer.transfer(ctx, public_key, msg, node)
tx = await _transfer(ctx, public_key, msg, node)
elif msg.provision_namespace: elif msg.provision_namespace:
tx = await _provision_namespace(ctx, public_key, msg) tx = await namespace.namespace(ctx, public_key, msg)
elif msg.mosaic_creation: elif msg.mosaic_creation:
tx = await _mosaic_creation(ctx, public_key, msg) tx = await mosaic.mosaic_creation(ctx, public_key, msg)
elif msg.supply_change: elif msg.supply_change:
tx = await _supply_change(ctx, public_key, msg) tx = await mosaic.supply_change(ctx, public_key, msg)
elif msg.aggregate_modification: elif msg.aggregate_modification:
tx = await _aggregate_modification(ctx, public_key, msg) tx = await multisig.aggregate_modification(ctx, public_key, msg)
elif msg.importance_transfer: elif msg.importance_transfer:
tx = await _importance_transfer(ctx, public_key, msg) tx = await transfer.importance_transfer(ctx, public_key, msg)
else: else:
raise ValueError('No transaction provided') raise ValueError('No transaction provided')
if msg.multisig: if msg.multisig:
# wrap transaction in multisig wrapper # wrap transaction in multisig wrapper
tx = _multisig(node, msg, tx) if msg.cosigning:
tx = multisig.cosign(_get_public_key(node), msg, tx)
else:
tx = multisig.initiate(_get_public_key(node), msg, tx)
signature = ed25519.sign(node.private_key(), tx, helpers.NEM_HASH_ALG) signature = ed25519.sign(node.private_key(), tx, NEM_HASH_ALG)
resp = NEMSignedTx() resp = NEMSignedTx()
resp.data = tx resp.data = tx
@ -48,58 +50,6 @@ async def sign_tx(ctx, msg: NEMSignTx):
return resp return resp
def _multisig(node, msg: NEMSignTx, inner_tx: bytes) -> bytes:
if msg.cosigning:
return serialize_multisig_signature(msg.multisig,
_get_public_key(node),
inner_tx,
msg.multisig.signer)
else:
return serialize_multisig(msg.multisig, _get_public_key(node), inner_tx)
def _get_public_key(node) -> bytes: def _get_public_key(node) -> bytes:
# 0x01 prefix is not part of the actual public key, hence removed # 0x01 prefix is not part of the actual public key, hence removed
return node.public_key()[1:] return node.public_key()[1:]
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)
w = serialize_aggregate_modification(msg, public_key)
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)

View File

@ -0,0 +1,19 @@
from .layout import *
from .serialize import *
async def transfer(ctx, public_key: bytes, msg: NEMSignTx, node):
msg.transfer.mosaics = canonicalize_mosaics(msg.transfer.mosaics)
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 importance_transfer(ctx, public_key: bytes, msg: NEMSignTx):
await ask_importance_transfer(ctx, msg)
return serialize_importance_transfer(msg, public_key)

View File

@ -0,0 +1,25 @@
from apps.nem.layout import *
from trezor.messages import NEMImportanceTransferMode
from trezor.messages import NEMSignTx
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)

View File

@ -1,31 +1,10 @@
from .writers import * from apps.nem.writers import *
from apps.nem.layout import * from apps.nem.helpers import *
from trezor.messages import NEMImportanceTransferMode from trezor.messages.NEMMosaic import NEMMosaic
from trezor.messages.NEMSignTx import NEMSignTx
from trezor.crypto import random 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: def serialize_transfer(msg: NEMSignTx, public_key: bytes, payload: bytes=None, encrypted: bool=False) -> bytearray:
tx = write_common(msg.transaction, tx = write_common(msg.transaction,
bytearray(public_key), bytearray(public_key),
@ -52,6 +31,16 @@ def serialize_transfer(msg: NEMSignTx, public_key: bytes, payload: bytes=None, e
return tx return tx
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)
write_uint32(w, identifier_length)
write_bytes_with_length(w, bytearray(namespace))
write_bytes_with_length(w, bytearray(mosaic))
write_uint64(w, quantity)
def serialize_importance_transfer(msg: NEMSignTx, public_key: bytes) -> bytearray: def serialize_importance_transfer(msg: NEMSignTx, public_key: bytes) -> bytearray:
w = write_common(msg.transaction, bytearray(public_key), NEM_TRANSACTION_TYPE_IMPORTANCE_TRANSFER) w = write_common(msg.transaction, bytearray(public_key), NEM_TRANSACTION_TYPE_IMPORTANCE_TRANSFER)
@ -83,3 +72,35 @@ def _get_version(network, mosaics=None) -> int:
if mosaics: if mosaics:
return network << 24 | 2 return network << 24 | 2
return network << 24 | 1 return network << 24 | 1
def canonicalize_mosaics(mosaics: list):
if len(mosaics) <= 1:
return mosaics
mosaics = merge_mosaics(mosaics)
return sort_mosaics(mosaics)
def are_mosaics_equal(a: NEMMosaic, b: NEMMosaic) -> bool:
if a.namespace == b.namespace and a.mosaic == b.mosaic:
return True
return False
def merge_mosaics(mosaics: list) -> list:
if not len(mosaics):
return list()
ret = list()
for i in mosaics:
found = False
for k, y in enumerate(ret):
if are_mosaics_equal(i, y):
ret[k].quantity += i.quantity
found = True
if not found:
ret.append(i)
return ret
def sort_mosaics(mosaics: list) -> list:
return sorted(mosaics, key=lambda m: (m.namespace, m.mosaic))

View File

@ -1,5 +1,5 @@
from common import * from common import *
from apps.nem.mosaic import * from apps.nem.transfer import *
class TestNemMosaicCanonicalization(unittest.TestCase): class TestNemMosaicCanonicalization(unittest.TestCase):