mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 15:38:11 +00:00
nem: mosaics are checked against definition and user is asked appropriately
This commit is contained in:
parent
a45ac4ad4b
commit
616d117648
@ -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)
|
||||
|
67
src/apps/nem/mosaic/definitions.py
Normal file
67
src/apps/nem/mosaic/definitions.py
Normal 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 ]
|
||||
}
|
||||
]
|
@ -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]
|
||||
|
@ -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()
|
Loading…
Reference in New Issue
Block a user