diff --git a/src/apps/stellar/__init__.py b/src/apps/stellar/__init__.py index 52ac906bb6..4ad07eda36 100644 --- a/src/apps/stellar/__init__.py +++ b/src/apps/stellar/__init__.py @@ -1,21 +1,26 @@ -from trezor.wire import register, protobuf_workflow -from trezor.messages.wire_types import StellarGetAddress -from trezor.messages.wire_types import StellarGetPublicKey -from trezor.messages.wire_types import StellarSignTx +from trezor.messages.MessageType import ( + StellarGetAddress, + StellarGetPublicKey, + StellarSignTx, +) +from trezor.wire import protobuf_workflow, register def dispatch_StellarGetAddress(*args, **kwargs): from .get_address import get_address + return get_address(*args, **kwargs) def dispatch_StellarGetPublicKey(*args, **kwargs): from .get_public_key import get_public_key + return get_public_key(*args, **kwargs) def dispatch_StellarSignTx(*args, **kwargs): from .sign_tx import sign_tx + return sign_tx(*args, **kwargs) diff --git a/src/apps/stellar/consts.py b/src/apps/stellar/consts.py index 5e945b43ff..822978d6f7 100644 --- a/src/apps/stellar/consts.py +++ b/src/apps/stellar/consts.py @@ -1,37 +1,38 @@ -from trezor.messages import wire_types from micropython import const -STELLAR_CURVE = 'ed25519' -TX_TYPE = bytearray('\x00\x00\x00\x02') +from trezor.messages import MessageType + +STELLAR_CURVE = "ed25519" +TX_TYPE = bytearray("\x00\x00\x00\x02") # source: https://github.com/stellar/go/blob/3d2c1defe73dbfed00146ebe0e8d7e07ce4bb1b6/xdr/Stellar-transaction.x#L16 # Inflation not supported see https://github.com/trezor/trezor-core/issues/202#issuecomment-393342089 op_codes = { - 'StellarAccountMergeOp': const(8), - 'StellarAllowTrustOp': const(7), - 'StellarBumpSequenceOp': const(11), - 'StellarChangeTrustOp': const(6), - 'StellarCreateAccountOp': const(0), - 'StellarCreatePassiveOfferOp': const(4), - 'StellarManageDataOp': const(10), - 'StellarManageOfferOp': const(3), - 'StellarPathPaymentOp': const(2), - 'StellarPaymentOp': const(1), - 'StellarSetOptionsOp': const(5), + "StellarAccountMergeOp": const(8), + "StellarAllowTrustOp": const(7), + "StellarBumpSequenceOp": const(11), + "StellarChangeTrustOp": const(6), + "StellarCreateAccountOp": const(0), + "StellarCreatePassiveOfferOp": const(4), + "StellarManageDataOp": const(10), + "StellarManageOfferOp": const(3), + "StellarPathPaymentOp": const(2), + "StellarPaymentOp": const(1), + "StellarSetOptionsOp": const(5), } op_wire_types = [ - wire_types.StellarAccountMergeOp, - wire_types.StellarAllowTrustOp, - wire_types.StellarBumpSequenceOp, - wire_types.StellarChangeTrustOp, - wire_types.StellarCreateAccountOp, - wire_types.StellarCreatePassiveOfferOp, - wire_types.StellarManageDataOp, - wire_types.StellarManageOfferOp, - wire_types.StellarPathPaymentOp, - wire_types.StellarPaymentOp, - wire_types.StellarSetOptionsOp, + MessageType.StellarAccountMergeOp, + MessageType.StellarAllowTrustOp, + MessageType.StellarBumpSequenceOp, + MessageType.StellarChangeTrustOp, + MessageType.StellarCreateAccountOp, + MessageType.StellarCreatePassiveOfferOp, + MessageType.StellarManageDataOp, + MessageType.StellarManageOfferOp, + MessageType.StellarPathPaymentOp, + MessageType.StellarPaymentOp, + MessageType.StellarSetOptionsOp, ] # https://github.com/stellar/go/blob/e0ffe19f58879d3c31e2976b97a5bf10e13a337b/xdr/xdr_generated.go#L584 @@ -44,8 +45,8 @@ ASSET_TYPE_ALPHANUM12 = const(2) AMOUNT_DIVISIBILITY = const(7) # https://github.com/stellar/go/blob/master/network/main.go -NETWORK_PASSPHRASE_PUBLIC = 'Public Global Stellar Network ; September 2015' -NETWORK_PASSPHRASE_TESTNET = 'Test SDF Network ; September 2015' +NETWORK_PASSPHRASE_PUBLIC = "Public Global Stellar Network ; September 2015" +NETWORK_PASSPHRASE_TESTNET = "Test SDF Network ; September 2015" # https://www.stellar.org/developers/guides/concepts/accounts.html#flags FLAG_AUTH_REQUIRED = const(1) @@ -68,5 +69,5 @@ SIGN_TYPE_HASH = const(2) def get_op_code(msg) -> int: if msg.__qualname__ not in op_codes: - raise ValueError('Stellar: op code unknown') + raise ValueError("Stellar: op code unknown") return op_codes[msg.__qualname__] diff --git a/src/apps/stellar/get_address.py b/src/apps/stellar/get_address.py index ea662fb1f8..cad782dcc8 100644 --- a/src/apps/stellar/get_address.py +++ b/src/apps/stellar/get_address.py @@ -1,8 +1,9 @@ +from trezor.messages.StellarAddress import StellarAddress +from trezor.messages.StellarGetAddress import StellarGetAddress + from apps.common import seed from apps.common.display_address import show_address, show_qr from apps.stellar import helpers -from trezor.messages.StellarAddress import StellarAddress -from trezor.messages.StellarGetAddress import StellarGetAddress async def get_address(ctx, msg: StellarGetAddress): diff --git a/src/apps/stellar/get_public_key.py b/src/apps/stellar/get_public_key.py index 28ead6b3de..a37e181d1e 100644 --- a/src/apps/stellar/get_public_key.py +++ b/src/apps/stellar/get_public_key.py @@ -1,13 +1,15 @@ +from ubinascii import hexlify + +from trezor import ui +from trezor.messages import ButtonRequestType +from trezor.messages.StellarGetPublicKey import StellarGetPublicKey +from trezor.messages.StellarPublicKey import StellarPublicKey +from trezor.ui.text import Text + from apps.common import seed from apps.common.confirm import confirm from apps.common.display_address import split_address from apps.stellar import helpers -from trezor import ui -from trezor.messages.StellarPublicKey import StellarPublicKey -from trezor.messages.StellarGetPublicKey import StellarGetPublicKey -from trezor.messages import ButtonRequestType -from trezor.ui.text import Text -from ubinascii import hexlify async def get_public_key(ctx, msg: StellarGetPublicKey): @@ -24,13 +26,16 @@ async def get_public_key(ctx, msg: StellarGetPublicKey): async def _show(ctx, pubkey: bytes): lines = split_address(hexlify(pubkey)) - content = Text('Export Stellar ID', ui.ICON_RECEIVE, - ui.NORMAL, 'Share public account ID?', # todo only two lines are displayed - ui.MONO, *lines, - icon_color=ui.GREEN) + content = Text( + "Export Stellar ID", + ui.ICON_RECEIVE, + ui.NORMAL, + "Share public account ID?", # todo only two lines are displayed + ui.MONO, + *lines, + icon_color=ui.GREEN + ) return await confirm( - ctx, - content, - code=ButtonRequestType.Address, - cancel_style=ui.BTN_KEY) + ctx, content, code=ButtonRequestType.Address, cancel_style=ui.BTN_KEY + ) diff --git a/src/apps/stellar/helpers.py b/src/apps/stellar/helpers.py index 52cb1f9460..a433c7a7d2 100644 --- a/src/apps/stellar/helpers.py +++ b/src/apps/stellar/helpers.py @@ -1,8 +1,9 @@ -from trezor.crypto import base32 -from trezor.wire import ProcessError import ustruct -STELLAR_CURVE = 'ed25519' +from trezor.crypto import base32 +from trezor.wire import ProcessError + +STELLAR_CURVE = "ed25519" def public_key_from_address(address: str) -> bytes: @@ -27,7 +28,7 @@ def address_from_public_key(pubkey: bytes): def _crc16_checksum_verify(data: bytes, checksum: bytes): if _crc16_checksum(data) != checksum: - raise ProcessError('Invalid address checksum') + raise ProcessError("Invalid address checksum") def _crc16_checksum(data: bytes) -> bytes: @@ -42,8 +43,8 @@ def _crc16_checksum(data: bytes) -> bytes: for byte in data: for i in range(8): - bit = ((byte >> (7 - i) & 1) == 1) - c15 = ((crc >> 15 & 1) == 1) + bit = (byte >> (7 - i) & 1) == 1 + c15 = (crc >> 15 & 1) == 1 crc <<= 1 if c15 ^ bit: crc ^= polynomial diff --git a/src/apps/stellar/layout.py b/src/apps/stellar/layout.py index 6b6deaa29d..677bf625ee 100644 --- a/src/apps/stellar/layout.py +++ b/src/apps/stellar/layout.py @@ -1,63 +1,59 @@ -from apps.common.confirm import require_confirm, require_hold_to_confirm -from apps.stellar import consts -from trezor import ui +from trezor import ui, utils from trezor.messages import ButtonRequestType from trezor.ui.text import Text -from trezor import utils + +from apps.common.confirm import require_confirm, require_hold_to_confirm +from apps.stellar import consts async def require_confirm_init(ctx, address: str, network_passphrase: str): - content = Text('Confirm Stellar', ui.ICON_SEND, - ui.NORMAL, 'Initialize singing with', - ui.MONO, *split(address), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm Stellar", ui.ICON_SEND, icon_color=ui.GREEN) + text.normal("Initialize singing with") + text.mono(*split(address)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) network = get_network_warning(network_passphrase) if network: - content = Text('Confirm network', ui.ICON_CONFIRM, - ui.NORMAL, 'Transaction is on', - ui.BOLD, network, - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm network", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.normal("Transaction is on") + text.bold(network) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) async def require_confirm_memo(ctx, memo_type: int, memo_text: str): if memo_type == consts.MEMO_TYPE_TEXT: - title = 'Memo (TEXT)' + title = "Memo (TEXT)" elif memo_type == consts.MEMO_TYPE_ID: - title = 'Memo (ID)' + title = "Memo (ID)" elif memo_type == consts.MEMO_TYPE_HASH: - title = 'Memo (HASH)' + title = "Memo (HASH)" elif memo_type == consts.MEMO_TYPE_RETURN: - title = 'Memo (RETURN)' + title = "Memo (RETURN)" else: # MEMO_TYPE_NONE - title = 'No memo set!' # todo format this as ui.NORMAL not MONO - memo_text = 'Important: Many exchanges require a memo when depositing' - content = Text('Confirm memo', ui.ICON_CONFIRM, - ui.BOLD, title, - ui.MONO, *split(memo_text), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + title = "No memo set!" # todo format this as ui.NORMAL not MONO + memo_text = "Important: Many exchanges require a memo when depositing" + text = Text("Confirm memo", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold(title) + text.mono(*split(memo_text)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) async def require_confirm_final(ctx, fee: int, num_operations: int): - op_str = str(num_operations) + ' operation' + op_str = str(num_operations) + " operation" if num_operations > 1: - op_str += 's' - content = Text('Final confirm', ui.ICON_SEND, - ui.NORMAL, 'Sign this transaction', - ui.NORMAL, 'made up of ' + op_str, - ui.BOLD, 'and pay ' + format_amount(fee), - ui.NORMAL, 'for fee?', - icon_color=ui.GREEN) + op_str += "s" + text = Text("Final confirm", ui.ICON_SEND, icon_color=ui.GREEN) + text.normal("Sign this transaction") + text.normal("made up of " + op_str) + text.bold("and pay " + format_amount(fee)) + text.normal("for fee?") # we use SignTx, not ConfirmOutput, for compatibility with T1 - await require_hold_to_confirm(ctx, content, ButtonRequestType.SignTx) + await require_hold_to_confirm(ctx, text, ButtonRequestType.SignTx) def format_amount(amount: int, ticker=True) -> str: - t = '' + t = "" if ticker: - t = ' XLM' + t = " XLM" return utils.format_amount(amount, consts.AMOUNT_DIVISIBILITY) + t @@ -70,13 +66,13 @@ def split(text): def trim(payload: str, length: int, dots=True) -> str: if len(payload) > length: if dots: - return payload[:length - 2] + '..' - return payload[:length - 2] + return payload[: length - 2] + ".." + return payload[: length - 2] return payload # todo merge with nem -def trim_to_rows(payload: str, rows: int=1) -> str: +def trim_to_rows(payload: str, rows: int = 1) -> str: return trim(payload, rows * 17) @@ -84,5 +80,5 @@ def get_network_warning(network_passphrase: str): if network_passphrase == consts.NETWORK_PASSPHRASE_PUBLIC: return None if network_passphrase == consts.NETWORK_PASSPHRASE_TESTNET: - return 'testnet network' - return 'private network' + return "testnet network" + return "private network" diff --git a/src/apps/stellar/operations/__init__.py b/src/apps/stellar/operations/__init__.py index 7459249ed7..aab488776a 100644 --- a/src/apps/stellar/operations/__init__.py +++ b/src/apps/stellar/operations/__init__.py @@ -1,7 +1,5 @@ -from apps.stellar.operations import serialize -from apps.stellar.operations import layout -from apps.stellar import consts -from apps.stellar import writers +from apps.stellar import consts, writers +from apps.stellar.operations import layout, serialize async def operation(ctx, w, op): @@ -43,4 +41,4 @@ async def operation(ctx, w, op): await layout.confirm_set_options_op(ctx, op) serialize.serialize_set_options_op(w, op) else: - raise ValueError('serialize.Stellar: unknown operation') + raise ValueError("serialize.Stellar: unknown operation") diff --git a/src/apps/stellar/operations/layout.py b/src/apps/stellar/operations/layout.py index b2c7515982..809c008cae 100644 --- a/src/apps/stellar/operations/layout.py +++ b/src/apps/stellar/operations/layout.py @@ -1,10 +1,9 @@ -from apps.stellar.layout import split, format_amount, ui, trim_to_rows, require_confirm -from apps.stellar import consts +from ubinascii import hexlify + from trezor.messages import ButtonRequestType -from trezor.ui.text import Text from trezor.messages.StellarAccountMergeOp import StellarAccountMergeOp -from trezor.messages.StellarAssetType import StellarAssetType from trezor.messages.StellarAllowTrustOp import StellarAllowTrustOp +from trezor.messages.StellarAssetType import StellarAssetType from trezor.messages.StellarBumpSequenceOp import StellarBumpSequenceOp from trezor.messages.StellarChangeTrustOp import StellarChangeTrustOp from trezor.messages.StellarCreateAccountOp import StellarCreateAccountOp @@ -14,252 +13,238 @@ from trezor.messages.StellarManageOfferOp import StellarManageOfferOp from trezor.messages.StellarPathPaymentOp import StellarPathPaymentOp from trezor.messages.StellarPaymentOp import StellarPaymentOp from trezor.messages.StellarSetOptionsOp import StellarSetOptionsOp +from trezor.ui.text import Text from trezor.wire import ProcessError -from ubinascii import hexlify + +from apps.stellar import consts +from apps.stellar.layout import format_amount, require_confirm, split, trim_to_rows, ui async def confirm_source_account(ctx, source_account: bytes): - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, 'Source account:', - ui.MONO, *split(source_account), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("Source account:") + text.mono(*split(source_account)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) async def confirm_allow_trust_op(ctx, op: StellarAllowTrustOp): if op.is_authorized: - text = 'Allow Trust' + text = "Allow Trust" else: - text = 'Revoke Trust' - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, text, - ui.NORMAL, 'of %s by:' % op.asset_code, - ui.MONO, *split(trim_to_rows(op.trusted_account, 3)), - icon_color=ui.GREEN) + text = "Revoke Trust" + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold(text) + text.normal("of %s by:" % op.asset_code) + text.mono(*split(trim_to_rows(op.trusted_account, 3))) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) async def confirm_account_merge_op(ctx, op: StellarAccountMergeOp): - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, 'Account Merge', - ui.NORMAL, 'All XLM will be sent to:', - ui.MONO, *split(trim_to_rows(op.destination_account, 3)), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("Account Merge") + text.normal("All XLM will be sent to:") + text.mono(*split(trim_to_rows(op.destination_account, 3))) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) async def confirm_bump_sequence_op(ctx, op: StellarBumpSequenceOp): - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, 'Bump Sequence', - ui.NORMAL, 'Set sequence to', - ui.MONO, str(op.bump_to), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("Bump Sequence") + text.normal("Set sequence to") + text.mono(str(op.bump_to)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) async def confirm_change_trust_op(ctx, op: StellarChangeTrustOp): if op.limit == 0: - text = 'Delete Trust' + text = "Delete Trust" else: - text = 'Add Trust' - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, text, - ui.NORMAL, 'Asset: %s' % op.asset.code, - ui.NORMAL, 'Amount: %s' % format_amount(op.limit, ticker=False), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = "Add Trust" + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold(text) + text.normal("Asset: %s" % op.asset.code) + text.normal("Amount: %s" % format_amount(op.limit, ticker=False)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) await confirm_asset_issuer(ctx, op.asset) async def confirm_create_account_op(ctx, op: StellarCreateAccountOp): - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, 'Create Account', - ui.NORMAL, 'with %s' % format_amount(op.starting_balance), - ui.MONO, *split(trim_to_rows(op.new_account, 3)), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("Create Account") + text.normal("with %s" % format_amount(op.starting_balance)) + text.mono(*split(trim_to_rows(op.new_account, 3))) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) async def confirm_create_passive_offer_op(ctx, op: StellarCreatePassiveOfferOp): if op.amount == 0: - text = 'Delete Passive Offer' + text = "Delete Passive Offer" else: - text = 'New Passive Offer' + text = "New Passive Offer" await _confirm_offer(ctx, text, op) async def confirm_manage_offer_op(ctx, op: StellarManageOfferOp): if op.offer_id == 0: - text = 'New Offer' + text = "New Offer" else: if op.amount == 0: - text = 'Delete' + text = "Delete" else: - text = 'Update' - text += ' #%d' % op.offer_id + text = "Update" + text += " #%d" % op.offer_id await _confirm_offer(ctx, text, op) async def _confirm_offer(ctx, text, op): - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, text, - ui.NORMAL, 'Sell %s %s' % (format_amount(op.amount, ticker=False), op.selling_asset.code), - ui.NORMAL, 'For %f' % (op.price_n / op.price_d), - ui.NORMAL, 'Per %s' % format_asset_code(op.buying_asset), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold(text) + text.normal( + "Sell %s %s" % (format_amount(op.amount, ticker=False), op.selling_asset.code) + ) + text.normal("For %f" % (op.price_n / op.price_d)) + text.normal("Per %s" % format_asset_code(op.buying_asset)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) await confirm_asset_issuer(ctx, op.selling_asset) await confirm_asset_issuer(ctx, op.buying_asset) async def confirm_manage_data_op(ctx, op: StellarManageDataOp): from trezor.crypto.hashlib import sha256 + if op.value: - title = 'Set' + title = "Set" else: - title = 'Clear' - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, '%s data value key' % title, - ui.MONO, *split(op.key), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + title = "Clear" + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("%s data value key" % title) + text.mono(*split(op.key)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) if op.value: digest = sha256(op.value).digest() digest_str = hexlify(digest).decode() - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, 'Value (SHA-256):', - ui.MONO, *split(digest_str), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("Value (SHA-256):") + text.mono(*split(digest_str)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) async def confirm_path_payment_op(ctx, op: StellarPathPaymentOp): - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, 'Path Pay %s' % format_amount(op.destination_amount, ticker=False), - ui.BOLD, '%s to:' % format_asset_code(op.destination_asset), - ui.MONO, *split(trim_to_rows(op.destination_account, 3)), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("Path Pay %s" % format_amount(op.destination_amount, ticker=False)) + text.bold("%s to:" % format_asset_code(op.destination_asset)) + text.mono(*split(trim_to_rows(op.destination_account, 3))) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) await confirm_asset_issuer(ctx, op.destination_asset) # confirm what the sender is using to pay - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.NORMAL, 'Pay using', - ui.BOLD, format_amount(op.send_max, ticker=False), - ui.BOLD, format_asset_code(op.send_asset), - ui.NORMAL, 'This amount is debited', - ui.NORMAL, 'from your account.', - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.normal("Pay using") + text.bold(format_amount(op.send_max, ticker=False)) + text.bold(format_asset_code(op.send_asset)) + text.normal("This amount is debited") + text.normal("from your account.") + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) await confirm_asset_issuer(ctx, op.send_asset) async def confirm_payment_op(ctx, op: StellarPaymentOp): - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, 'Pay %s' % format_amount(op.amount, ticker=False), - ui.BOLD, '%s to:' % format_asset_code(op.asset), - ui.MONO, *split(trim_to_rows(op.destination_account, 3)), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("Pay %s" % format_amount(op.amount, ticker=False)) + text.bold("%s to:" % format_asset_code(op.asset)) + text.mono(*split(trim_to_rows(op.destination_account, 3))) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) await confirm_asset_issuer(ctx, op.asset) async def confirm_set_options_op(ctx, op: StellarSetOptionsOp): if op.inflation_destination_account: - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, 'Set Inflation Destination', - ui.MONO, *split(op.inflation_destination_account), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("Set Inflation Destination") + text.mono(*split(op.inflation_destination_account)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) if op.clear_flags: text = _format_flags(op.clear_flags) - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, 'Clear Flags', - ui.MONO, *text, - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("Clear Flags") + text.mono(*text) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) if op.set_flags: text = _format_flags(op.set_flags) - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, 'Set Flags', - ui.MONO, *text, - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("Set Flags") + text.mono(*text) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) thresholds = _format_thresholds(op) if thresholds: - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, 'Account Thresholds', - ui.MONO, *thresholds, - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("Account Thresholds") + text.mono(*thresholds) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) if op.home_domain: - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, 'Home Domain', - ui.MONO, *split(op.home_domain), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("Home Domain") + text.mono(*split(op.home_domain)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) if op.signer_type is not None: if op.signer_weight > 0: - text = 'Add Signer (%s)' + text = "Add Signer (%s)" else: - text = 'Remove Signer (%s)' + text = "Remove Signer (%s)" if op.signer_type == consts.SIGN_TYPE_ACCOUNT: - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, text % 'acc', - ui.MONO, *split(op.signer_key), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold(text % "acc") + text.mono(*split(op.signer_key)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) elif op.signer_type in (consts.SIGN_TYPE_PRE_AUTH, consts.SIGN_TYPE_HASH): if op.signer_type == consts.SIGN_TYPE_PRE_AUTH: - signer_type = 'auth' + signer_type = "auth" else: - signer_type = 'hash' - content = Text('Confirm operation', ui.ICON_CONFIRM, - ui.BOLD, text % signer_type, - ui.MONO, *split(hexlify(op.signer_key).decode()), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + signer_type = "hash" + text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold(text % signer_type) + text.mono(*split(hexlify(op.signer_key).decode())) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) else: - raise ProcessError('Stellar: invalid signer type') + raise ProcessError("Stellar: invalid signer type") def _format_thresholds(op: StellarSetOptionsOp) -> tuple: text = () if op.master_weight is not None: - text += ('Master Weight: %d' % op.master_weight, ) + text += ("Master Weight: %d" % op.master_weight,) if op.low_threshold is not None: - text += ('Low: %d' % op.low_threshold, ) + text += ("Low: %d" % op.low_threshold,) if op.medium_threshold is not None: - text += ('Medium: %d' % op.medium_threshold, ) + text += ("Medium: %d" % op.medium_threshold,) if op.high_threshold is not None: - text += ('High: %d' % op.high_threshold, ) + text += ("High: %d" % op.high_threshold,) return text def _format_flags(flags: int) -> tuple: if flags > consts.FLAGS_MAX_SIZE: - raise ProcessError('Stellar: invalid flags') + raise ProcessError("Stellar: invalid flags") text = () if flags & consts.FLAG_AUTH_REQUIRED: - text += ('AUTH_REQUIRED', ) + text += ("AUTH_REQUIRED",) if flags & consts.FLAG_AUTH_REVOCABLE: - text += ('AUTH_REVOCABLE', ) + text += ("AUTH_REVOCABLE",) if flags & consts.FLAG_AUTH_IMMUTABLE: - text += ('AUTH_IMMUTABLE', ) + text += ("AUTH_IMMUTABLE",) return text def format_asset_code(asset: StellarAssetType) -> str: if asset is None or asset.type == consts.ASSET_TYPE_NATIVE: - return 'XLM (native)' + return "XLM (native)" return asset.code async def confirm_asset_issuer(ctx, asset: StellarAssetType): if asset is None or asset.type == consts.ASSET_TYPE_NATIVE: return - content = Text('Confirm issuer', ui.ICON_CONFIRM, - ui.BOLD, '%s issuer:' % asset.code, - ui.MONO, *split(asset.issuer), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text("Confirm issuer", ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.bold("%s issuer:" % asset.code) + text.mono(*split(asset.issuer)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) diff --git a/src/apps/stellar/operations/serialize.py b/src/apps/stellar/operations/serialize.py index cf99893e9d..4ebc247f70 100644 --- a/src/apps/stellar/operations/serialize.py +++ b/src/apps/stellar/operations/serialize.py @@ -1,8 +1,6 @@ -from apps.stellar import writers -from apps.stellar import consts from trezor.messages.StellarAccountMergeOp import StellarAccountMergeOp -from trezor.messages.StellarAssetType import StellarAssetType from trezor.messages.StellarAllowTrustOp import StellarAllowTrustOp +from trezor.messages.StellarAssetType import StellarAssetType from trezor.messages.StellarBumpSequenceOp import StellarBumpSequenceOp from trezor.messages.StellarChangeTrustOp import StellarChangeTrustOp from trezor.messages.StellarCreateAccountOp import StellarCreateAccountOp @@ -14,6 +12,8 @@ from trezor.messages.StellarPaymentOp import StellarPaymentOp from trezor.messages.StellarSetOptionsOp import StellarSetOptionsOp from trezor.wire import ProcessError +from apps.stellar import consts, writers + def serialize_account_merge_op(w, msg: StellarAccountMergeOp): writers.write_pubkey(w, msg.destination_account) @@ -52,7 +52,7 @@ def serialize_create_passive_offer_op(w, msg: StellarCreatePassiveOfferOp): def serialize_manage_data_op(w, msg: StellarManageDataOp): if len(msg.key) > 64: - raise ProcessError('Stellar: max length of a key is 64 bytes') + raise ProcessError("Stellar: max length of a key is 64 bytes") writers.write_string(w, msg.key) writers.write_bool(w, bool(msg.value)) if msg.value: @@ -124,7 +124,7 @@ def serialize_set_options_op(w, msg: StellarSetOptionsOp): writers.write_bool(w, bool(msg.home_domain)) if msg.home_domain: if len(msg.home_domain) > 32: - raise ProcessError('Stellar: max length of a home domain is 32 bytes') + raise ProcessError("Stellar: max length of a home domain is 32 bytes") writers.write_string(w, msg.home_domain) # signer @@ -154,7 +154,7 @@ def _serialize_asset_code(w, asset_type: int, asset_code: str): # pad with zeros to 12 chars writers.write_bytes(w, code + bytearray([0] * (12 - len(code)))) else: - raise ProcessError('Stellar: invalid asset type') + raise ProcessError("Stellar: invalid asset type") def _serialize_asset(w, asset: StellarAssetType): diff --git a/src/apps/stellar/sign_tx.py b/src/apps/stellar/sign_tx.py index 49700fadb8..f8ddb88023 100644 --- a/src/apps/stellar/sign_tx.py +++ b/src/apps/stellar/sign_tx.py @@ -1,21 +1,20 @@ -from apps.common import seed -from apps.stellar import writers -from apps.stellar.operations import operation -from apps.stellar import helpers -from apps.stellar import layout -from apps.stellar import consts -from trezor.wire import ProcessError -from trezor.messages.StellarSignTx import StellarSignTx -from trezor.messages.StellarTxOpRequest import StellarTxOpRequest -from trezor.messages.StellarSignedTx import StellarSignedTx +from ubinascii import hexlify + from trezor.crypto.curve import ed25519 from trezor.crypto.hashlib import sha256 -from ubinascii import hexlify +from trezor.messages.StellarSignedTx import StellarSignedTx +from trezor.messages.StellarSignTx import StellarSignTx +from trezor.messages.StellarTxOpRequest import StellarTxOpRequest +from trezor.wire import ProcessError + +from apps.common import seed +from apps.stellar import consts, helpers, layout, writers +from apps.stellar.operations import operation async def sign_tx(ctx, msg: StellarSignTx): if msg.num_operations == 0: - raise ProcessError('Stellar: At least one operation is required') + raise ProcessError("Stellar: At least one operation is required") node = await seed.derive_node(ctx, msg.address_n, consts.STELLAR_CURVE) pubkey = seed.remove_ed25519_prefix(node.public_key()) @@ -50,7 +49,7 @@ async def _init(ctx, w: bytearray, pubkey: bytes, msg: StellarSignTx): address = helpers.address_from_public_key(pubkey) writers.write_pubkey(w, address) if helpers.public_key_from_address(msg.source_account) != pubkey: - raise ProcessError('Stellar: source account does not match address_n') + raise ProcessError("Stellar: source account does not match address_n") writers.write_uint32(w, msg.fee) writers.write_uint64(w, msg.sequence_number) @@ -80,11 +79,11 @@ async def _memo(ctx, w: bytearray, msg: StellarSignTx): writers.write_uint32(w, msg.memo_type) if msg.memo_type == consts.MEMO_TYPE_NONE: # nothing is serialized - memo_confirm_text = '' + memo_confirm_text = "" elif msg.memo_type == consts.MEMO_TYPE_TEXT: # Text: 4 bytes (size) + up to 28 bytes if len(msg.memo_text) > 28: - raise ProcessError('Stellar: max length of a memo text is 28 bytes') + raise ProcessError("Stellar: max length of a memo text is 28 bytes") writers.write_string(w, msg.memo_text) memo_confirm_text = msg.memo_text elif msg.memo_type == consts.MEMO_TYPE_ID: @@ -96,7 +95,7 @@ async def _memo(ctx, w: bytearray, msg: StellarSignTx): writers.write_bytes(w, bytearray(msg.memo_hash)) memo_confirm_text = hexlify(msg.memo_hash).decode() else: - raise ProcessError('Stellar invalid memo type') + raise ProcessError("Stellar invalid memo type") await layout.require_confirm_memo(ctx, msg.memo_type, memo_confirm_text) diff --git a/src/apps/stellar/writers.py b/src/apps/stellar/writers.py index 056cd19d63..f90baeee4d 100644 --- a/src/apps/stellar/writers.py +++ b/src/apps/stellar/writers.py @@ -1,13 +1,14 @@ import ustruct + from .helpers import public_key_from_address def write_uint32(w, n: int): - write_bytes(w, ustruct.pack('>L', n)) + write_bytes(w, ustruct.pack(">L", n)) def write_uint64(w, n: int): - write_bytes(w, ustruct.pack('>Q', n)) + write_bytes(w, ustruct.pack(">Q", n)) def write_string(w, s: str):