1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-26 16:18:22 +00:00

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

This commit is contained in:
Tomas Susanka 2018-04-24 17:17:40 +01:00 committed by Jan Pochyla
parent a45ac4ad4b
commit 616d117648
4 changed files with 136 additions and 9 deletions

View File

@ -21,6 +21,7 @@ NEM_SALT_SIZE = const(32)
AES_BLOCK_SIZE = const(16)
NEM_HASH_ALG = 'keccak'
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_ENCRYPTED_PAYLOAD_SIZE = const(960)

View File

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

View File

@ -3,6 +3,9 @@ from trezor.messages import NEMImportanceTransferMode
from trezor.messages import NEMTransfer
from trezor.messages import NEMImportanceTransfer
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):
@ -10,13 +13,59 @@ async def ask_transfer(ctx, common: NEMTransactionCommon, transfer: NEMTransfer,
await _require_confirm_payload(ctx, transfer.payload, encrypted)
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_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):
if imp.mode == NEMImportanceTransferMode.ImportanceTransfer_Activate:
m = 'Activate'
@ -51,10 +100,3 @@ async def _require_confirm_payload(ctx, payload: bytes, encrypt=False):
ui.NORMAL, *split_words(payload, 22),
icon_color=ui.RED)
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]

View File

@ -1,8 +1,25 @@
from common 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):
a = NEMMosaic()