nem: mosaics are checked against definition and user is asked appropriately

pull/25/head
Tomas Susanka 6 years ago committed by Jan Pochyla
parent a45ac4ad4b
commit 616d117648

@ -21,6 +21,7 @@ NEM_SALT_SIZE = const(32)
AES_BLOCK_SIZE = const(16) AES_BLOCK_SIZE = const(16)
NEM_HASH_ALG = 'keccak' NEM_HASH_ALG = 'keccak'
NEM_PUBLIC_KEY_SIZE = const(32) # ed25519 public key NEM_PUBLIC_KEY_SIZE = const(32) # ed25519 public key
NEM_LEVY_PERCENTILE_DIVISOR_ABSOLUTE = const(10000)
NEM_MAX_PLAIN_PAYLOAD_SIZE = const(1024) NEM_MAX_PLAIN_PAYLOAD_SIZE = const(1024)
NEM_MAX_ENCRYPTED_PAYLOAD_SIZE = const(960) NEM_MAX_ENCRYPTED_PAYLOAD_SIZE = const(960)

@ -0,0 +1,67 @@
# todo move to common and generate via script
def get_mosaic_definition(namespace_name: str, mosaic_name: str, network: int):
for m in mosaics:
if namespace_name == m["namespace"] and mosaic_name == m["mosaic"]:
if ("networks" not in m) or (network in m["networks"]):
return m
return None
mosaics = [
{
"name": "XEM",
"ticker": " XEM",
"namespace": "nem",
"mosaic": "xem",
"divisibility": 6
},
{
"name": "DIMCOIN",
"ticker": " DIM",
"namespace": "dim",
"mosaic": "coin",
"divisibility": 6,
"levy": "MosaicLevy_Percentile",
"fee": 10,
"levy_namespace": "dim",
"levy_mosaic": "coin",
"networks": [ 104 ]
},
{
"name": "DIM TOKEN",
"ticker": " DIMTOK",
"namespace": "dim",
"mosaic": "token",
"divisibility": 6,
"networks": [ 104 ]
},
{
"name": "Breeze Token",
"ticker": " BREEZE",
"namespace": "breeze",
"mosaic": "breeze-token",
"divisibility": 0,
"networks": [ 104 ]
},
{
"name": "PacNEM Game Credits",
"ticker": " PAC:HRT",
"namespace": "pacnem",
"mosaic": "heart",
"divisibility": 0,
"networks": [ 104 ]
},
{
"name": "PacNEM Score Tokens",
"ticker": " PAC:CHS",
"namespace": "pacnem",
"mosaic": "cheese",
"divisibility": 6,
"levy": "MosaicLevy_Percentile",
"fee": 100,
"levy_namespace": "nem",
"levy_mosaic": "xem",
"networks": [ 104 ]
}
]

@ -3,6 +3,9 @@ from trezor.messages import NEMImportanceTransferMode
from trezor.messages import NEMTransfer from trezor.messages import NEMTransfer
from trezor.messages import NEMImportanceTransfer from trezor.messages import NEMImportanceTransfer
from trezor.messages import NEMTransactionCommon from trezor.messages import NEMTransactionCommon
from trezor.messages import NEMMosaic
from trezor.messages import NEMMosaicLevy
from apps.nem.mosaic.definitions import get_mosaic_definition
async def ask_transfer(ctx, common: NEMTransactionCommon, transfer: NEMTransfer, payload, encrypted): async def ask_transfer(ctx, common: NEMTransactionCommon, transfer: NEMTransfer, payload, encrypted):
@ -10,13 +13,59 @@ async def ask_transfer(ctx, common: NEMTransactionCommon, transfer: NEMTransfer,
await _require_confirm_payload(ctx, transfer.payload, encrypted) await _require_confirm_payload(ctx, transfer.payload, encrypted)
for mosaic in transfer.mosaics: for mosaic in transfer.mosaics:
await require_confirm_content(ctx, 'Confirm mosaic', _mosaics_message(mosaic)) await ask_transfer_mosaic(ctx, mosaic, common.network)
await _require_confirm_transfer(ctx, transfer.recipient, transfer.amount) await _require_confirm_transfer(ctx, transfer.recipient, transfer.amount)
await require_confirm_final(ctx, common.fee) await require_confirm_final(ctx, common.fee)
async def ask_transfer_mosaic(ctx, mosaic: NEMMosaic, network: int):
definition = get_mosaic_definition(mosaic.namespace, mosaic.mosaic, network)
if definition:
msg = Text('Confirm mosaic', ui.ICON_SEND,
ui.NORMAL, 'Confirm transfer of',
ui.BOLD, format_amount(mosaic.quantity, definition["divisibility"]) + definition["ticker"],
ui.NORMAL, 'of',
ui.BOLD, definition["name"],
icon_color=ui.GREEN)
await require_confirm(ctx, msg, ButtonRequestType.ConfirmOutput)
if "levy" in definition and "fee" in definition:
levy_msg = _get_levy_msg(definition, mosaic.quantity, network)
msg = Text('Confirm mosaic', ui.ICON_SEND,
ui.NORMAL, 'Confirm mosaic',
ui.NORMAL, 'levy fee of',
ui.BOLD, levy_msg,
icon_color=ui.GREEN)
await require_confirm(ctx, msg, ButtonRequestType.ConfirmOutput)
else:
msg = Text('Confirm mosaic', ui.ICON_SEND,
ui.BOLD, 'Unknown mosaic!',
ui.NORMAL, *split_words('Divisibility and levy cannot be shown for unknown mosaics', 22),
icon_color=ui.RED)
await require_confirm(ctx, msg, ButtonRequestType.ConfirmOutput)
msg = Text('Confirm mosaic', ui.ICON_SEND,
ui.NORMAL, 'Confirm transfer of',
ui.BOLD, str(mosaic.quantity) + ' raw units',
ui.NORMAL, 'of',
ui.BOLD, mosaic.namespace + '.' + mosaic.mosaic,
icon_color=ui.GREEN)
await require_confirm(ctx, msg, ButtonRequestType.ConfirmOutput)
def _get_levy_msg(mosaic_definition, quantity: int, network: int) -> str:
levy_definition = get_mosaic_definition(mosaic_definition["levy_namespace"], mosaic_definition["levy_mosaic"], network)
if mosaic_definition["levy"] == NEMMosaicLevy.MosaicLevy_Absolute:
levy_fee = mosaic_definition["fee"]
else:
levy_fee = quantity * mosaic_definition["fee"] / NEM_LEVY_PERCENTILE_DIVISOR_ABSOLUTE
return format_amount(levy_fee, levy_definition["divisibility"]) + levy_definition["ticker"]
async def ask_importance_transfer(ctx, common: NEMTransactionCommon, imp: NEMImportanceTransfer): async def ask_importance_transfer(ctx, common: NEMTransactionCommon, imp: NEMImportanceTransfer):
if imp.mode == NEMImportanceTransferMode.ImportanceTransfer_Activate: if imp.mode == NEMImportanceTransferMode.ImportanceTransfer_Activate:
m = 'Activate' m = 'Activate'
@ -51,10 +100,3 @@ async def _require_confirm_payload(ctx, payload: bytes, encrypt=False):
ui.NORMAL, *split_words(payload, 22), ui.NORMAL, *split_words(payload, 22),
icon_color=ui.RED) icon_color=ui.RED)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
def _mosaics_message(mosaic):
return [ui.NORMAL, 'Confirm transfer of',
ui.BOLD, str(mosaic.quantity) + ' raw units',
ui.NORMAL, 'of',
ui.BOLD, mosaic.namespace + '.' + mosaic.mosaic]

@ -1,8 +1,25 @@
from common import * from common import *
from apps.nem.transfer import * from apps.nem.transfer import *
from apps.nem.mosaic.definitions import get_mosaic_definition
class TestNemMosaicCanonicalization(unittest.TestCase): class TestNemMosaic(unittest.TestCase):
def test_get_mosaic_definition(self):
m = get_mosaic_definition("nem", "xem", 104)
self.assertEqual(m["name"], "XEM")
self.assertEqual(m["ticker"], " XEM")
m = get_mosaic_definition("nem", "xxx", 104)
self.assertEqual(m, None)
m = get_mosaic_definition("aaaa", "xxx", 104)
self.assertEqual(m, None)
m = get_mosaic_definition("pacnem", "cheese", 104)
self.assertEqual(m["name"], "PacNEM Score Tokens")
self.assertEqual(m["ticker"], " PAC:CHS")
self.assertEqual(m["fee"], 100)
def test_mosaic_canonicalization(self): def test_mosaic_canonicalization(self):
a = NEMMosaic() a = NEMMosaic()
Loading…
Cancel
Save