1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-16 19:38:09 +00:00

stellar: style and text api changes

This commit is contained in:
Jan Pochyla 2018-07-10 16:39:17 +02:00 committed by Tomas Susanka
parent b722fddc58
commit b46ce034d6
11 changed files with 259 additions and 267 deletions

View File

@ -1,21 +1,26 @@
from trezor.wire import register, protobuf_workflow from trezor.messages.MessageType import (
from trezor.messages.wire_types import StellarGetAddress StellarGetAddress,
from trezor.messages.wire_types import StellarGetPublicKey StellarGetPublicKey,
from trezor.messages.wire_types import StellarSignTx StellarSignTx,
)
from trezor.wire import protobuf_workflow, register
def dispatch_StellarGetAddress(*args, **kwargs): def dispatch_StellarGetAddress(*args, **kwargs):
from .get_address import get_address from .get_address import get_address
return get_address(*args, **kwargs) return get_address(*args, **kwargs)
def dispatch_StellarGetPublicKey(*args, **kwargs): def dispatch_StellarGetPublicKey(*args, **kwargs):
from .get_public_key import get_public_key from .get_public_key import get_public_key
return get_public_key(*args, **kwargs) return get_public_key(*args, **kwargs)
def dispatch_StellarSignTx(*args, **kwargs): def dispatch_StellarSignTx(*args, **kwargs):
from .sign_tx import sign_tx from .sign_tx import sign_tx
return sign_tx(*args, **kwargs) return sign_tx(*args, **kwargs)

View File

@ -1,37 +1,38 @@
from trezor.messages import wire_types
from micropython import const from micropython import const
STELLAR_CURVE = 'ed25519' from trezor.messages import MessageType
TX_TYPE = bytearray('\x00\x00\x00\x02')
STELLAR_CURVE = "ed25519"
TX_TYPE = bytearray("\x00\x00\x00\x02")
# source: https://github.com/stellar/go/blob/3d2c1defe73dbfed00146ebe0e8d7e07ce4bb1b6/xdr/Stellar-transaction.x#L16 # 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 # Inflation not supported see https://github.com/trezor/trezor-core/issues/202#issuecomment-393342089
op_codes = { op_codes = {
'StellarAccountMergeOp': const(8), "StellarAccountMergeOp": const(8),
'StellarAllowTrustOp': const(7), "StellarAllowTrustOp": const(7),
'StellarBumpSequenceOp': const(11), "StellarBumpSequenceOp": const(11),
'StellarChangeTrustOp': const(6), "StellarChangeTrustOp": const(6),
'StellarCreateAccountOp': const(0), "StellarCreateAccountOp": const(0),
'StellarCreatePassiveOfferOp': const(4), "StellarCreatePassiveOfferOp": const(4),
'StellarManageDataOp': const(10), "StellarManageDataOp": const(10),
'StellarManageOfferOp': const(3), "StellarManageOfferOp": const(3),
'StellarPathPaymentOp': const(2), "StellarPathPaymentOp": const(2),
'StellarPaymentOp': const(1), "StellarPaymentOp": const(1),
'StellarSetOptionsOp': const(5), "StellarSetOptionsOp": const(5),
} }
op_wire_types = [ op_wire_types = [
wire_types.StellarAccountMergeOp, MessageType.StellarAccountMergeOp,
wire_types.StellarAllowTrustOp, MessageType.StellarAllowTrustOp,
wire_types.StellarBumpSequenceOp, MessageType.StellarBumpSequenceOp,
wire_types.StellarChangeTrustOp, MessageType.StellarChangeTrustOp,
wire_types.StellarCreateAccountOp, MessageType.StellarCreateAccountOp,
wire_types.StellarCreatePassiveOfferOp, MessageType.StellarCreatePassiveOfferOp,
wire_types.StellarManageDataOp, MessageType.StellarManageDataOp,
wire_types.StellarManageOfferOp, MessageType.StellarManageOfferOp,
wire_types.StellarPathPaymentOp, MessageType.StellarPathPaymentOp,
wire_types.StellarPaymentOp, MessageType.StellarPaymentOp,
wire_types.StellarSetOptionsOp, MessageType.StellarSetOptionsOp,
] ]
# https://github.com/stellar/go/blob/e0ffe19f58879d3c31e2976b97a5bf10e13a337b/xdr/xdr_generated.go#L584 # 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) AMOUNT_DIVISIBILITY = const(7)
# https://github.com/stellar/go/blob/master/network/main.go # https://github.com/stellar/go/blob/master/network/main.go
NETWORK_PASSPHRASE_PUBLIC = 'Public Global Stellar Network ; September 2015' NETWORK_PASSPHRASE_PUBLIC = "Public Global Stellar Network ; September 2015"
NETWORK_PASSPHRASE_TESTNET = 'Test SDF Network ; September 2015' NETWORK_PASSPHRASE_TESTNET = "Test SDF Network ; September 2015"
# https://www.stellar.org/developers/guides/concepts/accounts.html#flags # https://www.stellar.org/developers/guides/concepts/accounts.html#flags
FLAG_AUTH_REQUIRED = const(1) FLAG_AUTH_REQUIRED = const(1)
@ -68,5 +69,5 @@ SIGN_TYPE_HASH = const(2)
def get_op_code(msg) -> int: def get_op_code(msg) -> int:
if msg.__qualname__ not in op_codes: if msg.__qualname__ not in op_codes:
raise ValueError('Stellar: op code unknown') raise ValueError("Stellar: op code unknown")
return op_codes[msg.__qualname__] return op_codes[msg.__qualname__]

View File

@ -1,8 +1,9 @@
from trezor.messages.StellarAddress import StellarAddress
from trezor.messages.StellarGetAddress import StellarGetAddress
from apps.common import seed from apps.common import seed
from apps.common.display_address import show_address, show_qr from apps.common.display_address import show_address, show_qr
from apps.stellar import helpers from apps.stellar import helpers
from trezor.messages.StellarAddress import StellarAddress
from trezor.messages.StellarGetAddress import StellarGetAddress
async def get_address(ctx, msg: StellarGetAddress): async def get_address(ctx, msg: StellarGetAddress):

View File

@ -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 import seed
from apps.common.confirm import confirm from apps.common.confirm import confirm
from apps.common.display_address import split_address from apps.common.display_address import split_address
from apps.stellar import helpers 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): 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): async def _show(ctx, pubkey: bytes):
lines = split_address(hexlify(pubkey)) lines = split_address(hexlify(pubkey))
content = Text('Export Stellar ID', ui.ICON_RECEIVE, content = Text(
ui.NORMAL, 'Share public account ID?', # todo only two lines are displayed "Export Stellar ID",
ui.MONO, *lines, ui.ICON_RECEIVE,
icon_color=ui.GREEN) ui.NORMAL,
"Share public account ID?", # todo only two lines are displayed
ui.MONO,
*lines,
icon_color=ui.GREEN
)
return await confirm( return await confirm(
ctx, ctx, content, code=ButtonRequestType.Address, cancel_style=ui.BTN_KEY
content, )
code=ButtonRequestType.Address,
cancel_style=ui.BTN_KEY)

View File

@ -1,8 +1,9 @@
from trezor.crypto import base32
from trezor.wire import ProcessError
import ustruct 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: 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): def _crc16_checksum_verify(data: bytes, checksum: bytes):
if _crc16_checksum(data) != checksum: if _crc16_checksum(data) != checksum:
raise ProcessError('Invalid address checksum') raise ProcessError("Invalid address checksum")
def _crc16_checksum(data: bytes) -> bytes: def _crc16_checksum(data: bytes) -> bytes:
@ -42,8 +43,8 @@ def _crc16_checksum(data: bytes) -> bytes:
for byte in data: for byte in data:
for i in range(8): for i in range(8):
bit = ((byte >> (7 - i) & 1) == 1) bit = (byte >> (7 - i) & 1) == 1
c15 = ((crc >> 15 & 1) == 1) c15 = (crc >> 15 & 1) == 1
crc <<= 1 crc <<= 1
if c15 ^ bit: if c15 ^ bit:
crc ^= polynomial crc ^= polynomial

View File

@ -1,63 +1,59 @@
from apps.common.confirm import require_confirm, require_hold_to_confirm from trezor import ui, utils
from apps.stellar import consts
from trezor import ui
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.ui.text import Text 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): async def require_confirm_init(ctx, address: str, network_passphrase: str):
content = Text('Confirm Stellar', ui.ICON_SEND, text = Text("Confirm Stellar", ui.ICON_SEND, icon_color=ui.GREEN)
ui.NORMAL, 'Initialize singing with', text.normal("Initialize singing with")
ui.MONO, *split(address), text.mono(*split(address))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
network = get_network_warning(network_passphrase) network = get_network_warning(network_passphrase)
if network: if network:
content = Text('Confirm network', ui.ICON_CONFIRM, text = Text("Confirm network", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.NORMAL, 'Transaction is on', text.normal("Transaction is on")
ui.BOLD, network, text.bold(network)
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
async def require_confirm_memo(ctx, memo_type: int, memo_text: str): async def require_confirm_memo(ctx, memo_type: int, memo_text: str):
if memo_type == consts.MEMO_TYPE_TEXT: if memo_type == consts.MEMO_TYPE_TEXT:
title = 'Memo (TEXT)' title = "Memo (TEXT)"
elif memo_type == consts.MEMO_TYPE_ID: elif memo_type == consts.MEMO_TYPE_ID:
title = 'Memo (ID)' title = "Memo (ID)"
elif memo_type == consts.MEMO_TYPE_HASH: elif memo_type == consts.MEMO_TYPE_HASH:
title = 'Memo (HASH)' title = "Memo (HASH)"
elif memo_type == consts.MEMO_TYPE_RETURN: elif memo_type == consts.MEMO_TYPE_RETURN:
title = 'Memo (RETURN)' title = "Memo (RETURN)"
else: # MEMO_TYPE_NONE else: # MEMO_TYPE_NONE
title = 'No memo set!' # todo format this as ui.NORMAL not MONO title = "No memo set!" # todo format this as ui.NORMAL not MONO
memo_text = 'Important: Many exchanges require a memo when depositing' memo_text = "Important: Many exchanges require a memo when depositing"
content = Text('Confirm memo', ui.ICON_CONFIRM, text = Text("Confirm memo", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, title, text.bold(title)
ui.MONO, *split(memo_text), text.mono(*split(memo_text))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
async def require_confirm_final(ctx, fee: int, num_operations: int): 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: if num_operations > 1:
op_str += 's' op_str += "s"
content = Text('Final confirm', ui.ICON_SEND, text = Text("Final confirm", ui.ICON_SEND, icon_color=ui.GREEN)
ui.NORMAL, 'Sign this transaction', text.normal("Sign this transaction")
ui.NORMAL, 'made up of ' + op_str, text.normal("made up of " + op_str)
ui.BOLD, 'and pay ' + format_amount(fee), text.bold("and pay " + format_amount(fee))
ui.NORMAL, 'for fee?', text.normal("for fee?")
icon_color=ui.GREEN)
# we use SignTx, not ConfirmOutput, for compatibility with T1 # 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: def format_amount(amount: int, ticker=True) -> str:
t = '' t = ""
if ticker: if ticker:
t = ' XLM' t = " XLM"
return utils.format_amount(amount, consts.AMOUNT_DIVISIBILITY) + t 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: def trim(payload: str, length: int, dots=True) -> str:
if len(payload) > length: if len(payload) > length:
if dots: if dots:
return payload[:length - 2] + '..' return payload[: length - 2] + ".."
return payload[:length - 2] return payload[: length - 2]
return payload return payload
# todo merge with nem # 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) return trim(payload, rows * 17)
@ -84,5 +80,5 @@ def get_network_warning(network_passphrase: str):
if network_passphrase == consts.NETWORK_PASSPHRASE_PUBLIC: if network_passphrase == consts.NETWORK_PASSPHRASE_PUBLIC:
return None return None
if network_passphrase == consts.NETWORK_PASSPHRASE_TESTNET: if network_passphrase == consts.NETWORK_PASSPHRASE_TESTNET:
return 'testnet network' return "testnet network"
return 'private network' return "private network"

View File

@ -1,7 +1,5 @@
from apps.stellar.operations import serialize from apps.stellar import consts, writers
from apps.stellar.operations import layout from apps.stellar.operations import layout, serialize
from apps.stellar import consts
from apps.stellar import writers
async def operation(ctx, w, op): async def operation(ctx, w, op):
@ -43,4 +41,4 @@ async def operation(ctx, w, op):
await layout.confirm_set_options_op(ctx, op) await layout.confirm_set_options_op(ctx, op)
serialize.serialize_set_options_op(w, op) serialize.serialize_set_options_op(w, op)
else: else:
raise ValueError('serialize.Stellar: unknown operation') raise ValueError("serialize.Stellar: unknown operation")

View File

@ -1,10 +1,9 @@
from apps.stellar.layout import split, format_amount, ui, trim_to_rows, require_confirm from ubinascii import hexlify
from apps.stellar import consts
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.ui.text import Text
from trezor.messages.StellarAccountMergeOp import StellarAccountMergeOp from trezor.messages.StellarAccountMergeOp import StellarAccountMergeOp
from trezor.messages.StellarAssetType import StellarAssetType
from trezor.messages.StellarAllowTrustOp import StellarAllowTrustOp from trezor.messages.StellarAllowTrustOp import StellarAllowTrustOp
from trezor.messages.StellarAssetType import StellarAssetType
from trezor.messages.StellarBumpSequenceOp import StellarBumpSequenceOp from trezor.messages.StellarBumpSequenceOp import StellarBumpSequenceOp
from trezor.messages.StellarChangeTrustOp import StellarChangeTrustOp from trezor.messages.StellarChangeTrustOp import StellarChangeTrustOp
from trezor.messages.StellarCreateAccountOp import StellarCreateAccountOp 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.StellarPathPaymentOp import StellarPathPaymentOp
from trezor.messages.StellarPaymentOp import StellarPaymentOp from trezor.messages.StellarPaymentOp import StellarPaymentOp
from trezor.messages.StellarSetOptionsOp import StellarSetOptionsOp from trezor.messages.StellarSetOptionsOp import StellarSetOptionsOp
from trezor.ui.text import Text
from trezor.wire import ProcessError 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): async def confirm_source_account(ctx, source_account: bytes):
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, 'Source account:', text.bold("Source account:")
ui.MONO, *split(source_account), text.mono(*split(source_account))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
async def confirm_allow_trust_op(ctx, op: StellarAllowTrustOp): async def confirm_allow_trust_op(ctx, op: StellarAllowTrustOp):
if op.is_authorized: if op.is_authorized:
text = 'Allow Trust' text = "Allow Trust"
else: else:
text = 'Revoke Trust' text = "Revoke Trust"
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, text, text.bold(text)
ui.NORMAL, 'of %s by:' % op.asset_code, text.normal("of %s by:" % op.asset_code)
ui.MONO, *split(trim_to_rows(op.trusted_account, 3)), text.mono(*split(trim_to_rows(op.trusted_account, 3)))
icon_color=ui.GREEN)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
async def confirm_account_merge_op(ctx, op: StellarAccountMergeOp): async def confirm_account_merge_op(ctx, op: StellarAccountMergeOp):
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, 'Account Merge', text.bold("Account Merge")
ui.NORMAL, 'All XLM will be sent to:', text.normal("All XLM will be sent to:")
ui.MONO, *split(trim_to_rows(op.destination_account, 3)), text.mono(*split(trim_to_rows(op.destination_account, 3)))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
async def confirm_bump_sequence_op(ctx, op: StellarBumpSequenceOp): async def confirm_bump_sequence_op(ctx, op: StellarBumpSequenceOp):
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, 'Bump Sequence', text.bold("Bump Sequence")
ui.NORMAL, 'Set sequence to', text.normal("Set sequence to")
ui.MONO, str(op.bump_to), text.mono(str(op.bump_to))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
async def confirm_change_trust_op(ctx, op: StellarChangeTrustOp): async def confirm_change_trust_op(ctx, op: StellarChangeTrustOp):
if op.limit == 0: if op.limit == 0:
text = 'Delete Trust' text = "Delete Trust"
else: else:
text = 'Add Trust' text = "Add Trust"
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, text, text.bold(text)
ui.NORMAL, 'Asset: %s' % op.asset.code, text.normal("Asset: %s" % op.asset.code)
ui.NORMAL, 'Amount: %s' % format_amount(op.limit, ticker=False), text.normal("Amount: %s" % format_amount(op.limit, ticker=False))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
await confirm_asset_issuer(ctx, op.asset) await confirm_asset_issuer(ctx, op.asset)
async def confirm_create_account_op(ctx, op: StellarCreateAccountOp): async def confirm_create_account_op(ctx, op: StellarCreateAccountOp):
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, 'Create Account', text.bold("Create Account")
ui.NORMAL, 'with %s' % format_amount(op.starting_balance), text.normal("with %s" % format_amount(op.starting_balance))
ui.MONO, *split(trim_to_rows(op.new_account, 3)), text.mono(*split(trim_to_rows(op.new_account, 3)))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
async def confirm_create_passive_offer_op(ctx, op: StellarCreatePassiveOfferOp): async def confirm_create_passive_offer_op(ctx, op: StellarCreatePassiveOfferOp):
if op.amount == 0: if op.amount == 0:
text = 'Delete Passive Offer' text = "Delete Passive Offer"
else: else:
text = 'New Passive Offer' text = "New Passive Offer"
await _confirm_offer(ctx, text, op) await _confirm_offer(ctx, text, op)
async def confirm_manage_offer_op(ctx, op: StellarManageOfferOp): async def confirm_manage_offer_op(ctx, op: StellarManageOfferOp):
if op.offer_id == 0: if op.offer_id == 0:
text = 'New Offer' text = "New Offer"
else: else:
if op.amount == 0: if op.amount == 0:
text = 'Delete' text = "Delete"
else: else:
text = 'Update' text = "Update"
text += ' #%d' % op.offer_id text += " #%d" % op.offer_id
await _confirm_offer(ctx, text, op) await _confirm_offer(ctx, text, op)
async def _confirm_offer(ctx, text, op): async def _confirm_offer(ctx, text, op):
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, text, text.bold(text)
ui.NORMAL, 'Sell %s %s' % (format_amount(op.amount, ticker=False), op.selling_asset.code), text.normal(
ui.NORMAL, 'For %f' % (op.price_n / op.price_d), "Sell %s %s" % (format_amount(op.amount, ticker=False), op.selling_asset.code)
ui.NORMAL, 'Per %s' % format_asset_code(op.buying_asset), )
icon_color=ui.GREEN) text.normal("For %f" % (op.price_n / op.price_d))
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) 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.selling_asset)
await confirm_asset_issuer(ctx, op.buying_asset) await confirm_asset_issuer(ctx, op.buying_asset)
async def confirm_manage_data_op(ctx, op: StellarManageDataOp): async def confirm_manage_data_op(ctx, op: StellarManageDataOp):
from trezor.crypto.hashlib import sha256 from trezor.crypto.hashlib import sha256
if op.value: if op.value:
title = 'Set' title = "Set"
else: else:
title = 'Clear' title = "Clear"
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, '%s data value key' % title, text.bold("%s data value key" % title)
ui.MONO, *split(op.key), text.mono(*split(op.key))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
if op.value: if op.value:
digest = sha256(op.value).digest() digest = sha256(op.value).digest()
digest_str = hexlify(digest).decode() digest_str = hexlify(digest).decode()
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, 'Value (SHA-256):', text.bold("Value (SHA-256):")
ui.MONO, *split(digest_str), text.mono(*split(digest_str))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
async def confirm_path_payment_op(ctx, op: StellarPathPaymentOp): async def confirm_path_payment_op(ctx, op: StellarPathPaymentOp):
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, 'Path Pay %s' % format_amount(op.destination_amount, ticker=False), text.bold("Path Pay %s" % format_amount(op.destination_amount, ticker=False))
ui.BOLD, '%s to:' % format_asset_code(op.destination_asset), text.bold("%s to:" % format_asset_code(op.destination_asset))
ui.MONO, *split(trim_to_rows(op.destination_account, 3)), text.mono(*split(trim_to_rows(op.destination_account, 3)))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
await confirm_asset_issuer(ctx, op.destination_asset) await confirm_asset_issuer(ctx, op.destination_asset)
# confirm what the sender is using to pay # confirm what the sender is using to pay
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.NORMAL, 'Pay using', text.normal("Pay using")
ui.BOLD, format_amount(op.send_max, ticker=False), text.bold(format_amount(op.send_max, ticker=False))
ui.BOLD, format_asset_code(op.send_asset), text.bold(format_asset_code(op.send_asset))
ui.NORMAL, 'This amount is debited', text.normal("This amount is debited")
ui.NORMAL, 'from your account.', text.normal("from your account.")
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
await confirm_asset_issuer(ctx, op.send_asset) await confirm_asset_issuer(ctx, op.send_asset)
async def confirm_payment_op(ctx, op: StellarPaymentOp): async def confirm_payment_op(ctx, op: StellarPaymentOp):
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, 'Pay %s' % format_amount(op.amount, ticker=False), text.bold("Pay %s" % format_amount(op.amount, ticker=False))
ui.BOLD, '%s to:' % format_asset_code(op.asset), text.bold("%s to:" % format_asset_code(op.asset))
ui.MONO, *split(trim_to_rows(op.destination_account, 3)), text.mono(*split(trim_to_rows(op.destination_account, 3)))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
await confirm_asset_issuer(ctx, op.asset) await confirm_asset_issuer(ctx, op.asset)
async def confirm_set_options_op(ctx, op: StellarSetOptionsOp): async def confirm_set_options_op(ctx, op: StellarSetOptionsOp):
if op.inflation_destination_account: if op.inflation_destination_account:
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, 'Set Inflation Destination', text.bold("Set Inflation Destination")
ui.MONO, *split(op.inflation_destination_account), text.mono(*split(op.inflation_destination_account))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
if op.clear_flags: if op.clear_flags:
text = _format_flags(op.clear_flags) text = _format_flags(op.clear_flags)
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, 'Clear Flags', text.bold("Clear Flags")
ui.MONO, *text, text.mono(*text)
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
if op.set_flags: if op.set_flags:
text = _format_flags(op.set_flags) text = _format_flags(op.set_flags)
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, 'Set Flags', text.bold("Set Flags")
ui.MONO, *text, text.mono(*text)
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
thresholds = _format_thresholds(op) thresholds = _format_thresholds(op)
if thresholds: if thresholds:
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, 'Account Thresholds', text.bold("Account Thresholds")
ui.MONO, *thresholds, text.mono(*thresholds)
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
if op.home_domain: if op.home_domain:
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, 'Home Domain', text.bold("Home Domain")
ui.MONO, *split(op.home_domain), text.mono(*split(op.home_domain))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
if op.signer_type is not None: if op.signer_type is not None:
if op.signer_weight > 0: if op.signer_weight > 0:
text = 'Add Signer (%s)' text = "Add Signer (%s)"
else: else:
text = 'Remove Signer (%s)' text = "Remove Signer (%s)"
if op.signer_type == consts.SIGN_TYPE_ACCOUNT: if op.signer_type == consts.SIGN_TYPE_ACCOUNT:
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, text % 'acc', text.bold(text % "acc")
ui.MONO, *split(op.signer_key), text.mono(*split(op.signer_key))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
elif op.signer_type in (consts.SIGN_TYPE_PRE_AUTH, consts.SIGN_TYPE_HASH): elif op.signer_type in (consts.SIGN_TYPE_PRE_AUTH, consts.SIGN_TYPE_HASH):
if op.signer_type == consts.SIGN_TYPE_PRE_AUTH: if op.signer_type == consts.SIGN_TYPE_PRE_AUTH:
signer_type = 'auth' signer_type = "auth"
else: else:
signer_type = 'hash' signer_type = "hash"
content = Text('Confirm operation', ui.ICON_CONFIRM, text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, text % signer_type, text.bold(text % signer_type)
ui.MONO, *split(hexlify(op.signer_key).decode()), text.mono(*split(hexlify(op.signer_key).decode()))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
else: else:
raise ProcessError('Stellar: invalid signer type') raise ProcessError("Stellar: invalid signer type")
def _format_thresholds(op: StellarSetOptionsOp) -> tuple: def _format_thresholds(op: StellarSetOptionsOp) -> tuple:
text = () text = ()
if op.master_weight is not None: 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: 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: 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: if op.high_threshold is not None:
text += ('High: %d' % op.high_threshold, ) text += ("High: %d" % op.high_threshold,)
return text return text
def _format_flags(flags: int) -> tuple: def _format_flags(flags: int) -> tuple:
if flags > consts.FLAGS_MAX_SIZE: if flags > consts.FLAGS_MAX_SIZE:
raise ProcessError('Stellar: invalid flags') raise ProcessError("Stellar: invalid flags")
text = () text = ()
if flags & consts.FLAG_AUTH_REQUIRED: if flags & consts.FLAG_AUTH_REQUIRED:
text += ('AUTH_REQUIRED', ) text += ("AUTH_REQUIRED",)
if flags & consts.FLAG_AUTH_REVOCABLE: if flags & consts.FLAG_AUTH_REVOCABLE:
text += ('AUTH_REVOCABLE', ) text += ("AUTH_REVOCABLE",)
if flags & consts.FLAG_AUTH_IMMUTABLE: if flags & consts.FLAG_AUTH_IMMUTABLE:
text += ('AUTH_IMMUTABLE', ) text += ("AUTH_IMMUTABLE",)
return text return text
def format_asset_code(asset: StellarAssetType) -> str: def format_asset_code(asset: StellarAssetType) -> str:
if asset is None or asset.type == consts.ASSET_TYPE_NATIVE: if asset is None or asset.type == consts.ASSET_TYPE_NATIVE:
return 'XLM (native)' return "XLM (native)"
return asset.code return asset.code
async def confirm_asset_issuer(ctx, asset: StellarAssetType): async def confirm_asset_issuer(ctx, asset: StellarAssetType):
if asset is None or asset.type == consts.ASSET_TYPE_NATIVE: if asset is None or asset.type == consts.ASSET_TYPE_NATIVE:
return return
content = Text('Confirm issuer', ui.ICON_CONFIRM, text = Text("Confirm issuer", ui.ICON_CONFIRM, icon_color=ui.GREEN)
ui.BOLD, '%s issuer:' % asset.code, text.bold("%s issuer:" % asset.code)
ui.MONO, *split(asset.issuer), text.mono(*split(asset.issuer))
icon_color=ui.GREEN) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)

View File

@ -1,8 +1,6 @@
from apps.stellar import writers
from apps.stellar import consts
from trezor.messages.StellarAccountMergeOp import StellarAccountMergeOp from trezor.messages.StellarAccountMergeOp import StellarAccountMergeOp
from trezor.messages.StellarAssetType import StellarAssetType
from trezor.messages.StellarAllowTrustOp import StellarAllowTrustOp from trezor.messages.StellarAllowTrustOp import StellarAllowTrustOp
from trezor.messages.StellarAssetType import StellarAssetType
from trezor.messages.StellarBumpSequenceOp import StellarBumpSequenceOp from trezor.messages.StellarBumpSequenceOp import StellarBumpSequenceOp
from trezor.messages.StellarChangeTrustOp import StellarChangeTrustOp from trezor.messages.StellarChangeTrustOp import StellarChangeTrustOp
from trezor.messages.StellarCreateAccountOp import StellarCreateAccountOp from trezor.messages.StellarCreateAccountOp import StellarCreateAccountOp
@ -14,6 +12,8 @@ from trezor.messages.StellarPaymentOp import StellarPaymentOp
from trezor.messages.StellarSetOptionsOp import StellarSetOptionsOp from trezor.messages.StellarSetOptionsOp import StellarSetOptionsOp
from trezor.wire import ProcessError from trezor.wire import ProcessError
from apps.stellar import consts, writers
def serialize_account_merge_op(w, msg: StellarAccountMergeOp): def serialize_account_merge_op(w, msg: StellarAccountMergeOp):
writers.write_pubkey(w, msg.destination_account) 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): def serialize_manage_data_op(w, msg: StellarManageDataOp):
if len(msg.key) > 64: 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_string(w, msg.key)
writers.write_bool(w, bool(msg.value)) writers.write_bool(w, bool(msg.value))
if 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)) writers.write_bool(w, bool(msg.home_domain))
if msg.home_domain: if msg.home_domain:
if len(msg.home_domain) > 32: 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) writers.write_string(w, msg.home_domain)
# signer # signer
@ -154,7 +154,7 @@ def _serialize_asset_code(w, asset_type: int, asset_code: str):
# pad with zeros to 12 chars # pad with zeros to 12 chars
writers.write_bytes(w, code + bytearray([0] * (12 - len(code)))) writers.write_bytes(w, code + bytearray([0] * (12 - len(code))))
else: else:
raise ProcessError('Stellar: invalid asset type') raise ProcessError("Stellar: invalid asset type")
def _serialize_asset(w, asset: StellarAssetType): def _serialize_asset(w, asset: StellarAssetType):

View File

@ -1,21 +1,20 @@
from apps.common import seed from ubinascii import hexlify
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 trezor.crypto.curve import ed25519 from trezor.crypto.curve import ed25519
from trezor.crypto.hashlib import sha256 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): async def sign_tx(ctx, msg: StellarSignTx):
if msg.num_operations == 0: 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) node = await seed.derive_node(ctx, msg.address_n, consts.STELLAR_CURVE)
pubkey = seed.remove_ed25519_prefix(node.public_key()) 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) address = helpers.address_from_public_key(pubkey)
writers.write_pubkey(w, address) writers.write_pubkey(w, address)
if helpers.public_key_from_address(msg.source_account) != pubkey: 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_uint32(w, msg.fee)
writers.write_uint64(w, msg.sequence_number) 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) writers.write_uint32(w, msg.memo_type)
if msg.memo_type == consts.MEMO_TYPE_NONE: if msg.memo_type == consts.MEMO_TYPE_NONE:
# nothing is serialized # nothing is serialized
memo_confirm_text = '' memo_confirm_text = ""
elif msg.memo_type == consts.MEMO_TYPE_TEXT: elif msg.memo_type == consts.MEMO_TYPE_TEXT:
# Text: 4 bytes (size) + up to 28 bytes # Text: 4 bytes (size) + up to 28 bytes
if len(msg.memo_text) > 28: 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) writers.write_string(w, msg.memo_text)
memo_confirm_text = msg.memo_text memo_confirm_text = msg.memo_text
elif msg.memo_type == consts.MEMO_TYPE_ID: 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)) writers.write_bytes(w, bytearray(msg.memo_hash))
memo_confirm_text = hexlify(msg.memo_hash).decode() memo_confirm_text = hexlify(msg.memo_hash).decode()
else: 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) await layout.require_confirm_memo(ctx, msg.memo_type, memo_confirm_text)

View File

@ -1,13 +1,14 @@
import ustruct import ustruct
from .helpers import public_key_from_address from .helpers import public_key_from_address
def write_uint32(w, n: int): 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): 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): def write_string(w, s: str):