1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-10 15:30:55 +00:00

refactor(core/ui): raise exception on dialog cancel by default

This commit is contained in:
Martin Milata 2021-03-10 12:56:44 +01:00
parent 2b6ea25712
commit c0174ff217
40 changed files with 489 additions and 592 deletions

View File

@ -129,12 +129,10 @@ async def handle_EndSession(ctx: wire.Context, msg: EndSession) -> Success:
async def handle_Ping(ctx: wire.Context, msg: Ping) -> Success: async def handle_Ping(ctx: wire.Context, msg: Ping) -> Success:
if msg.button_protection: if msg.button_protection:
from trezor.ui.layouts import require, confirm_action from trezor.ui.layouts import confirm_action
from trezor.messages.ButtonRequestType import ProtectCall from trezor.messages.ButtonRequestType import ProtectCall
await require( await confirm_action(ctx, "ping", "Confirm", "ping", br_code=ProtectCall)
confirm_action(ctx, "ping", "Confirm", "ping", br_code=ProtectCall)
)
return Success(message=msg.message) return Success(message=msg.message)

View File

@ -2,7 +2,7 @@ from ubinascii import hexlify
from trezor.messages.BinanceGetPublicKey import BinanceGetPublicKey from trezor.messages.BinanceGetPublicKey import BinanceGetPublicKey
from trezor.messages.BinancePublicKey import BinancePublicKey from trezor.messages.BinancePublicKey import BinancePublicKey
from trezor.ui.layouts import require, show_pubkey from trezor.ui.layouts import show_pubkey
from apps.common import paths from apps.common import paths
from apps.common.keychain import Keychain, auto_keychain from apps.common.keychain import Keychain, auto_keychain
@ -15,6 +15,6 @@ async def get_public_key(ctx, msg: BinanceGetPublicKey, keychain: Keychain):
pubkey = node.public_key() pubkey = node.public_key()
if msg.show_display: if msg.show_display:
await require(show_pubkey(ctx, hexlify(pubkey).decode())) await show_pubkey(ctx, hexlify(pubkey).decode())
return BinancePublicKey(public_key=pubkey) return BinancePublicKey(public_key=pubkey)

View File

@ -4,7 +4,7 @@ from trezor import ui
from trezor.messages.AuthorizeCoinJoin import AuthorizeCoinJoin from trezor.messages.AuthorizeCoinJoin import AuthorizeCoinJoin
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.strings import format_amount from trezor.strings import format_amount
from trezor.ui.layouts import confirm_action, confirm_coinjoin, require from trezor.ui.layouts import confirm_action, confirm_coinjoin
from apps.base import set_authorization from apps.base import set_authorization
from apps.common.paths import validate_path from apps.common.paths import validate_path
@ -45,8 +45,7 @@ async def authorize_coinjoin(ctx: wire.Context, msg: AuthorizeCoinJoin) -> Succe
), ),
) )
await require( await confirm_action(
confirm_action(
ctx, ctx,
"coinjoin_coordinator", "coinjoin_coordinator",
title="Authorize CoinJoin", title="Authorize CoinJoin",
@ -55,20 +54,17 @@ async def authorize_coinjoin(ctx: wire.Context, msg: AuthorizeCoinJoin) -> Succe
description_param_font=ui.MONO, description_param_font=ui.MONO,
icon=ui.ICON_RECOVERY, icon=ui.ICON_RECOVERY,
) )
)
fee_per_anonymity = None fee_per_anonymity = None
if msg.fee_per_anonymity is not None: if msg.fee_per_anonymity is not None:
fee_per_anonymity = format_amount( fee_per_anonymity = format_amount(
msg.fee_per_anonymity, FEE_PER_ANONYMITY_DECIMALS msg.fee_per_anonymity, FEE_PER_ANONYMITY_DECIMALS
) )
await require( await confirm_coinjoin(
confirm_coinjoin(
ctx, ctx,
fee_per_anonymity, fee_per_anonymity,
format_coin_amount(msg.max_total_fee, coin, msg.amount_unit), format_coin_amount(msg.max_total_fee, coin, msg.amount_unit),
) )
)
set_authorization(CoinJoinAuthorization(msg, keychain, coin)) set_authorization(CoinJoinAuthorization(msg, keychain, coin))

View File

@ -3,7 +3,7 @@ from ubinascii import hexlify
from trezor import ui, wire from trezor import ui, wire
from trezor.messages.GetOwnershipProof import GetOwnershipProof from trezor.messages.GetOwnershipProof import GetOwnershipProof
from trezor.messages.OwnershipProof import OwnershipProof from trezor.messages.OwnershipProof import OwnershipProof
from trezor.ui.layouts import confirm_action, confirm_hex, require from trezor.ui.layouts import confirm_action, confirm_hex
from apps.common.paths import validate_path from apps.common.paths import validate_path
@ -65,17 +65,14 @@ async def get_ownership_proof(
# In order to set the "user confirmation" bit in the proof, the user must actually confirm. # In order to set the "user confirmation" bit in the proof, the user must actually confirm.
if msg.user_confirmation and not authorization: if msg.user_confirmation and not authorization:
if not msg.commitment_data: if not msg.commitment_data:
await require( await confirm_action(
confirm_action(
ctx, ctx,
"confirm_ownership_proof", "confirm_ownership_proof",
title="Proof of ownership", title="Proof of ownership",
description="Do you want to create a proof of ownership?", description="Do you want to create a proof of ownership?",
) )
)
else: else:
await require( await confirm_hex(
confirm_hex(
ctx, ctx,
"confirm_ownership_proof", "confirm_ownership_proof",
title="Proof of ownership", title="Proof of ownership",
@ -85,7 +82,6 @@ async def get_ownership_proof(
icon_color=ui.ORANGE_ICON, icon_color=ui.ORANGE_ICON,
truncate_middle=True, truncate_middle=True,
) )
)
ownership_proof, signature = generate_proof( ownership_proof, signature = generate_proof(
node, node,

View File

@ -2,7 +2,7 @@ from trezor import wire
from trezor.messages import InputScriptType from trezor.messages import InputScriptType
from trezor.messages.HDNodeType import HDNodeType from trezor.messages.HDNodeType import HDNodeType
from trezor.messages.PublicKey import PublicKey from trezor.messages.PublicKey import PublicKey
from trezor.ui.layouts import require, show_xpub from trezor.ui.layouts import show_xpub
from apps.common import coins, paths from apps.common import coins, paths
from apps.common.keychain import get_keychain from apps.common.keychain import get_keychain
@ -59,7 +59,7 @@ async def get_public_key(ctx: wire.Context, msg: GetPublicKey) -> PublicKey:
) )
if msg.show_display: if msg.show_display:
await require(show_xpub(ctx, node_xpub, "XPUB", "Cancel")) await show_xpub(ctx, node_xpub, "XPUB", "Cancel")
return PublicKey( return PublicKey(
node=node_type, node=node_type,

View File

@ -2,7 +2,7 @@ from trezor import wire
from trezor.crypto.curve import secp256k1 from trezor.crypto.curve import secp256k1
from trezor.messages.InputScriptType import SPENDADDRESS, SPENDP2SHWITNESS, SPENDWITNESS from trezor.messages.InputScriptType import SPENDADDRESS, SPENDP2SHWITNESS, SPENDWITNESS
from trezor.messages.MessageSignature import MessageSignature from trezor.messages.MessageSignature import MessageSignature
from trezor.ui.layouts import confirm_signverify, require from trezor.ui.layouts import confirm_signverify
from apps.common.paths import validate_path from apps.common.paths import validate_path
from apps.common.signverify import decode_message, message_digest from apps.common.signverify import decode_message, message_digest
@ -26,7 +26,7 @@ async def sign_message(
script_type = msg.script_type or 0 script_type = msg.script_type or 0
await validate_path(ctx, keychain, address_n) await validate_path(ctx, keychain, address_n)
await require(confirm_signverify(ctx, coin.coin_shortcut, decode_message(message))) await confirm_signverify(ctx, coin.coin_shortcut, decode_message(message))
node = keychain.derive(address_n) node = keychain.derive(address_n)
seckey = node.private_key() seckey = node.private_key()

View File

@ -4,7 +4,6 @@ from ubinascii import hexlify
from trezor.messages import AmountUnit, ButtonRequestType, OutputScriptType from trezor.messages import AmountUnit, ButtonRequestType, OutputScriptType
from trezor.strings import format_amount from trezor.strings import format_amount
from trezor.ui import layouts from trezor.ui import layouts
from trezor.ui.layouts import require
from .. import addresses from .. import addresses
from . import omni from . import omni
@ -70,7 +69,7 @@ async def confirm_output(
ctx, address_short, format_coin_amount(output.amount, coin, amount_unit) ctx, address_short, format_coin_amount(output.amount, coin, amount_unit)
) )
await require(layout) await layout
async def confirm_decred_sstx_submission( async def confirm_decred_sstx_submission(
@ -79,21 +78,17 @@ async def confirm_decred_sstx_submission(
assert output.address is not None assert output.address is not None
address_short = addresses.address_short(coin, output.address) address_short = addresses.address_short(coin, output.address)
await require( await layouts.confirm_decred_sstx_submission(
layouts.confirm_decred_sstx_submission(
ctx, address_short, format_coin_amount(output.amount, coin, amount_unit) ctx, address_short, format_coin_amount(output.amount, coin, amount_unit)
) )
)
async def confirm_replacement(ctx: wire.Context, description: str, txid: bytes) -> None: async def confirm_replacement(ctx: wire.Context, description: str, txid: bytes) -> None:
await require( await layouts.confirm_replacement(
layouts.confirm_replacement(
ctx, ctx,
description, description,
hexlify(txid).decode(), hexlify(txid).decode(),
) )
)
async def confirm_modify_output( async def confirm_modify_output(
@ -106,15 +101,13 @@ async def confirm_modify_output(
assert txo.address is not None assert txo.address is not None
address_short = addresses.address_short(coin, txo.address) address_short = addresses.address_short(coin, txo.address)
amount_change = txo.amount - orig_txo.amount amount_change = txo.amount - orig_txo.amount
await require( await layouts.confirm_modify_output(
layouts.confirm_modify_output(
ctx, ctx,
address_short, address_short,
amount_change, amount_change,
format_coin_amount(abs(amount_change), coin, amount_unit), format_coin_amount(abs(amount_change), coin, amount_unit),
format_coin_amount(txo.amount, coin, amount_unit), format_coin_amount(txo.amount, coin, amount_unit),
) )
)
async def confirm_modify_fee( async def confirm_modify_fee(
@ -124,14 +117,12 @@ async def confirm_modify_fee(
coin: CoinInfo, coin: CoinInfo,
amount_unit: EnumTypeAmountUnit, amount_unit: EnumTypeAmountUnit,
) -> None: ) -> None:
await require( await layouts.confirm_modify_fee(
layouts.confirm_modify_fee(
ctx, ctx,
user_fee_change, user_fee_change,
format_coin_amount(abs(user_fee_change), coin, amount_unit), format_coin_amount(abs(user_fee_change), coin, amount_unit),
format_coin_amount(total_fee_new, coin, amount_unit), format_coin_amount(total_fee_new, coin, amount_unit),
) )
)
async def confirm_joint_total( async def confirm_joint_total(
@ -141,12 +132,10 @@ async def confirm_joint_total(
coin: CoinInfo, coin: CoinInfo,
amount_unit: EnumTypeAmountUnit, amount_unit: EnumTypeAmountUnit,
) -> None: ) -> None:
await require( await layouts.confirm_joint_total(
layouts.confirm_joint_total(
ctx, ctx,
spending_amount=format_coin_amount(spending, coin, amount_unit), spending_amount=format_coin_amount(spending, coin, amount_unit),
total_amount=format_coin_amount(total, coin, amount_unit), total_amount=format_coin_amount(total, coin, amount_unit),
),
) )
@ -157,12 +146,10 @@ async def confirm_total(
coin: CoinInfo, coin: CoinInfo,
amount_unit: EnumTypeAmountUnit, amount_unit: EnumTypeAmountUnit,
) -> None: ) -> None:
await require( await layouts.confirm_total(
layouts.confirm_total(
ctx, ctx,
total_amount=format_coin_amount(spending, coin, amount_unit), total_amount=format_coin_amount(spending, coin, amount_unit),
fee_amount=format_coin_amount(fee, coin, amount_unit), fee_amount=format_coin_amount(fee, coin, amount_unit),
),
) )
@ -170,8 +157,7 @@ async def confirm_feeoverthreshold(
ctx: wire.Context, fee: int, coin: CoinInfo, amount_unit: EnumTypeAmountUnit ctx: wire.Context, fee: int, coin: CoinInfo, amount_unit: EnumTypeAmountUnit
) -> None: ) -> None:
fee_amount = format_coin_amount(fee, coin, amount_unit) fee_amount = format_coin_amount(fee, coin, amount_unit)
await require( await layouts.confirm_metadata(
layouts.confirm_metadata(
ctx, ctx,
"fee_over_threshold", "fee_over_threshold",
"High fee", "High fee",
@ -179,14 +165,12 @@ async def confirm_feeoverthreshold(
fee_amount, fee_amount,
ButtonRequestType.FeeOverThreshold, ButtonRequestType.FeeOverThreshold,
) )
)
async def confirm_change_count_over_threshold( async def confirm_change_count_over_threshold(
ctx: wire.Context, change_count: int ctx: wire.Context, change_count: int
) -> None: ) -> None:
await require( await layouts.confirm_metadata(
layouts.confirm_metadata(
ctx, ctx,
"change_count_over_threshold", "change_count_over_threshold",
"Warning", "Warning",
@ -194,7 +178,6 @@ async def confirm_change_count_over_threshold(
str(change_count), str(change_count),
ButtonRequestType.SignTx, ButtonRequestType.SignTx,
) )
)
async def confirm_nondefault_locktime( async def confirm_nondefault_locktime(
@ -213,8 +196,7 @@ async def confirm_nondefault_locktime(
text = "Locktime for this\ntransaction is set to\ntimestamp:\n{}" text = "Locktime for this\ntransaction is set to\ntimestamp:\n{}"
param = str(lock_time) param = str(lock_time)
await require( await layouts.confirm_metadata(
layouts.confirm_metadata(
ctx, ctx,
"nondefault_locktime", "nondefault_locktime",
title, title,
@ -222,4 +204,3 @@ async def confirm_nondefault_locktime(
param, param,
br_code=ButtonRequestType.SignTx, br_code=ButtonRequestType.SignTx,
) )
)

View File

@ -2,7 +2,7 @@ from trezor import wire
from trezor.crypto.curve import secp256k1 from trezor.crypto.curve import secp256k1
from trezor.messages.InputScriptType import SPENDADDRESS, SPENDP2SHWITNESS, SPENDWITNESS from trezor.messages.InputScriptType import SPENDADDRESS, SPENDP2SHWITNESS, SPENDWITNESS
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.ui.layouts import confirm_signverify, require from trezor.ui.layouts import confirm_signverify
from apps.common import coins from apps.common import coins
from apps.common.signverify import decode_message, message_digest from apps.common.signverify import decode_message, message_digest
@ -63,13 +63,11 @@ async def verify_message(ctx: wire.Context, msg: VerifyMessage) -> Success:
if addr != address: if addr != address:
raise wire.ProcessError("Invalid signature") raise wire.ProcessError("Invalid signature")
await require( await confirm_signverify(
confirm_signverify(
ctx, ctx,
coin.coin_shortcut, coin.coin_shortcut,
decode_message(message), decode_message(message),
address=address_short(coin, address), address=address_short(coin, address),
) )
)
return Success(message="Message verified") return Success(message="Message verified")

View File

@ -3,7 +3,7 @@ from ubinascii import hexlify
from trezor import log, wire from trezor import log, wire
from trezor.messages.CardanoPublicKey import CardanoPublicKey from trezor.messages.CardanoPublicKey import CardanoPublicKey
from trezor.messages.HDNodeType import HDNodeType from trezor.messages.HDNodeType import HDNodeType
from trezor.ui.layouts import require, show_pubkey from trezor.ui.layouts import show_pubkey
from apps.common import paths from apps.common import paths
from apps.common.seed import remove_ed25519_prefix from apps.common.seed import remove_ed25519_prefix
@ -36,7 +36,7 @@ async def get_public_key(
raise wire.ProcessError("Deriving public key failed") raise wire.ProcessError("Deriving public key failed")
if msg.show_display: if msg.show_display:
await require(show_pubkey(ctx, hexlify(key.node.public_key).decode())) await show_pubkey(ctx, hexlify(key.node.public_key).decode())
return key return key

View File

@ -1,5 +1,5 @@
from trezor.ui.constants import MONO_CHARS_PER_LINE from trezor.ui.constants import MONO_CHARS_PER_LINE
from trezor.ui.layouts import confirm_path_warning, require from trezor.ui.layouts import confirm_path_warning
from . import HARDENED from . import HARDENED
from .layout import address_n_to_str from .layout import address_n_to_str
@ -259,7 +259,7 @@ async def validate_path(
async def show_path_warning(ctx: wire.Context, path: Bip32Path) -> None: async def show_path_warning(ctx: wire.Context, path: Bip32Path) -> None:
await require(confirm_path_warning(ctx, address_n_to_str(path))) await confirm_path_warning(ctx, address_n_to_str(path))
def is_hardened(i: int) -> bool: def is_hardened(i: int) -> bool:

View File

@ -123,26 +123,28 @@ async def verify_user_pin(
async def error_pin_invalid(ctx: wire.Context) -> NoReturn: async def error_pin_invalid(ctx: wire.Context) -> NoReturn:
from trezor.ui.layouts import show_error from trezor.ui.layouts import show_error_and_raise
await show_error( await show_error_and_raise(
ctx, ctx,
"warning_wrong_pin", "warning_wrong_pin",
header="Wrong PIN", header="Wrong PIN",
content="The PIN you entered is invalid.", content="The PIN you entered is invalid.",
red=True, red=True,
exc=wire.PinInvalid,
) )
raise wire.PinInvalid assert False
async def error_pin_matches_wipe_code(ctx: wire.Context) -> NoReturn: async def error_pin_matches_wipe_code(ctx: wire.Context) -> NoReturn:
from trezor.ui.layouts import show_error from trezor.ui.layouts import show_error_and_raise
await show_error( await show_error_and_raise(
ctx, ctx,
"warning_invalid_new_pin", "warning_invalid_new_pin",
header="Invalid PIN", header="Invalid PIN",
content="The new PIN must be different from your\nwipe code.", content="The new PIN must be different from your\nwipe code.",
red=True, red=True,
exc=wire.PinInvalid,
) )
raise wire.PinInvalid assert False

View File

@ -1,7 +1,7 @@
import storage.sd_salt import storage.sd_salt
from storage.sd_salt import SD_CARD_HOT_SWAPPABLE from storage.sd_salt import SD_CARD_HOT_SWAPPABLE
from trezor import fatfs, sdcard, ui, wire from trezor import fatfs, sdcard, ui, wire
from trezor.ui.layouts import confirm_action, show_error from trezor.ui.layouts import confirm_action, show_error_and_raise
if False: if False:
from typing import Optional from typing import Optional
@ -11,9 +11,9 @@ class SdCardUnavailable(wire.ProcessError):
pass pass
async def _wrong_card_dialog(ctx: wire.GenericContext) -> bool: async def _confirm_retry_wrong_card(ctx: wire.GenericContext) -> None:
if SD_CARD_HOT_SWAPPABLE: if SD_CARD_HOT_SWAPPABLE:
return await confirm_action( await confirm_action(
ctx, ctx,
"warning_wrong_sd", "warning_wrong_sd",
"SD card protection", "SD card protection",
@ -23,20 +23,22 @@ async def _wrong_card_dialog(ctx: wire.GenericContext) -> bool:
verb_cancel="Abort", verb_cancel="Abort",
icon=ui.ICON_WRONG, icon=ui.ICON_WRONG,
larger_vspace=True, larger_vspace=True,
exc=SdCardUnavailable("Wrong SD card."),
) )
else: else:
return await show_error( await show_error_and_raise(
ctx, ctx,
"warning_wrong_sd", "warning_wrong_sd",
header="SD card protection", header="SD card protection",
subheader="Wrong SD card.", subheader="Wrong SD card.",
content="Please unplug the\ndevice and insert the correct SD card.", content="Please unplug the\ndevice and insert the correct SD card.",
exc=SdCardUnavailable("Wrong SD card."),
) )
async def insert_card_dialog(ctx: wire.GenericContext) -> bool: async def _confirm_retry_insert_card(ctx: wire.GenericContext) -> None:
if SD_CARD_HOT_SWAPPABLE: if SD_CARD_HOT_SWAPPABLE:
return await confirm_action( await confirm_action(
ctx, ctx,
"warning_no_sd", "warning_no_sd",
"SD card protection", "SD card protection",
@ -46,20 +48,22 @@ async def insert_card_dialog(ctx: wire.GenericContext) -> bool:
verb_cancel="Abort", verb_cancel="Abort",
icon=ui.ICON_WRONG, icon=ui.ICON_WRONG,
larger_vspace=True, larger_vspace=True,
exc=SdCardUnavailable("SD card required."),
) )
else: else:
return await show_error( await show_error_and_raise(
ctx, ctx,
"warning_no_sd", "warning_no_sd",
header="SD card protection", header="SD card protection",
subheader="SD card required.", subheader="SD card required.",
content="Please unplug the\ndevice and insert your SD card.", content="Please unplug the\ndevice and insert your SD card.",
exc=SdCardUnavailable("SD card required."),
) )
async def format_card_dialog(ctx: wire.GenericContext) -> bool: async def _confirm_format_card(ctx: wire.GenericContext) -> None:
# Format card? yes/no # Format card? yes/no
if not await confirm_action( await confirm_action(
ctx, ctx,
"warning_format_sd", "warning_format_sd",
"SD card error", "SD card error",
@ -70,11 +74,11 @@ async def format_card_dialog(ctx: wire.GenericContext) -> bool:
verb="Format", verb="Format",
verb_cancel="Cancel", verb_cancel="Cancel",
larger_vspace=True, larger_vspace=True,
): exc=SdCardUnavailable("SD card not formatted."),
return False )
# Confirm formatting # Confirm formatting
return await confirm_action( await confirm_action(
ctx, ctx,
"confirm_format_sd", "confirm_format_sd",
"Format SD card", "Format SD card",
@ -86,11 +90,15 @@ async def format_card_dialog(ctx: wire.GenericContext) -> bool:
icon_color=ui.RED, icon_color=ui.RED,
hold=True, hold=True,
larger_vspace=True, larger_vspace=True,
exc=SdCardUnavailable("SD card not formatted."),
) )
async def sd_problem_dialog(ctx: wire.GenericContext) -> bool: async def confirm_retry_sd(
return await confirm_action( ctx: wire.GenericContext,
exc: wire.ProcessError = SdCardUnavailable("Error accessing SD card."),
) -> None:
await confirm_action(
ctx, ctx,
"warning_sd_retry", "warning_sd_retry",
"SD card problem", "SD card problem",
@ -100,6 +108,7 @@ async def sd_problem_dialog(ctx: wire.GenericContext) -> bool:
icon_color=ui.RED, icon_color=ui.RED,
verb="Retry", verb="Retry",
verb_cancel="Abort", verb_cancel="Abort",
exc=exc,
) )
@ -116,8 +125,7 @@ async def ensure_sdcard(
mounted. mounted.
""" """
while not sdcard.is_present(): while not sdcard.is_present():
if not await insert_card_dialog(ctx): await _confirm_retry_insert_card(ctx)
raise SdCardUnavailable("SD card required.")
if not ensure_filesystem: if not ensure_filesystem:
return return
@ -134,8 +142,7 @@ async def ensure_sdcard(
# no error when mounting # no error when mounting
return return
if not await format_card_dialog(ctx): await _confirm_format_card(ctx)
raise SdCardUnavailable("SD card not formatted.")
# Proceed to formatting. Failure is caught by the outside OSError handler # Proceed to formatting. Failure is caught by the outside OSError handler
with sdcard.filesystem(mounted=False): with sdcard.filesystem(mounted=False):
@ -148,8 +155,7 @@ async def ensure_sdcard(
except OSError: except OSError:
# formatting failed, or generic I/O error (SD card power-on failed) # formatting failed, or generic I/O error (SD card power-on failed)
if not await sd_problem_dialog(ctx): await confirm_retry_sd(ctx)
raise SdCardUnavailable("Error accessing SD card.")
async def request_sd_salt( async def request_sd_salt(
@ -163,12 +169,10 @@ async def request_sd_salt(
try: try:
return storage.sd_salt.load_sd_salt() return storage.sd_salt.load_sd_salt()
except (storage.sd_salt.WrongSdCard, fatfs.NoFilesystem): except (storage.sd_salt.WrongSdCard, fatfs.NoFilesystem):
if not await _wrong_card_dialog(ctx): await _confirm_retry_wrong_card(ctx)
raise SdCardUnavailable("Wrong SD card.")
except OSError: except OSError:
# Generic problem with loading the SD salt (hardware problem, or we could # Generic problem with loading the SD salt (hardware problem, or we could
# not read the file, or there is a staged salt which cannot be committed). # not read the file, or there is a staged salt which cannot be committed).
# In either case, there is no good way to recover. If the user clicks Retry, # In either case, there is no good way to recover. If the user clicks Retry,
# we will try again. # we will try again.
if not await sd_problem_dialog(ctx): await confirm_retry_sd(ctx)
raise SdCardUnavailable("Error accessing SD card.")

View File

@ -4,7 +4,7 @@ from trezor import config, wire
from trezor.crypto import bip39, slip39 from trezor.crypto import bip39, slip39
from trezor.messages import BackupType from trezor.messages import BackupType
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.ui.layouts import confirm_action, require from trezor.ui.layouts import confirm_action
from apps.management import backup_types from apps.management import backup_types
@ -68,12 +68,10 @@ def _validate(msg) -> int:
async def _warn(ctx: wire.Context): async def _warn(ctx: wire.Context):
await require( await confirm_action(
confirm_action(
ctx, ctx,
"warn_loading_seed", "warn_loading_seed",
"Loading seed", "Loading seed",
"Loading private seed\nis not recommended.", "Loading private seed\nis not recommended.",
"Continue only if you\nknow what you are doing!", "Continue only if you\nknow what you are doing!",
) )
)

View File

@ -2,7 +2,7 @@ from ubinascii import hexlify
from trezor.messages.EthereumPublicKey import EthereumPublicKey from trezor.messages.EthereumPublicKey import EthereumPublicKey
from trezor.messages.HDNodeType import HDNodeType from trezor.messages.HDNodeType import HDNodeType
from trezor.ui.layouts import require, show_pubkey from trezor.ui.layouts import show_pubkey
from apps.common import coins, paths from apps.common import coins, paths
@ -30,6 +30,6 @@ async def get_public_key(ctx, msg, keychain):
) )
if msg.show_display: if msg.show_display:
await require(show_pubkey(ctx, hexlify(pubkey).decode())) await show_pubkey(ctx, hexlify(pubkey).decode())
return EthereumPublicKey(node=node_type, xpub=node_xpub) return EthereumPublicKey(node=node_type, xpub=node_xpub)

View File

@ -1,7 +1,7 @@
from trezor.crypto.curve import secp256k1 from trezor.crypto.curve import secp256k1
from trezor.crypto.hashlib import sha3_256 from trezor.crypto.hashlib import sha3_256
from trezor.messages.EthereumMessageSignature import EthereumMessageSignature from trezor.messages.EthereumMessageSignature import EthereumMessageSignature
from trezor.ui.layouts import confirm_signverify, require from trezor.ui.layouts import confirm_signverify
from trezor.utils import HashWriter from trezor.utils import HashWriter
from apps.common import paths from apps.common import paths
@ -23,7 +23,7 @@ def message_digest(message):
@with_keychain_from_path(*PATTERNS_ADDRESS) @with_keychain_from_path(*PATTERNS_ADDRESS)
async def sign_message(ctx, msg, keychain): async def sign_message(ctx, msg, keychain):
await paths.validate_path(ctx, keychain, msg.address_n) await paths.validate_path(ctx, keychain, msg.address_n)
await require(confirm_signverify(ctx, "ETH", decode_message(msg.message))) await confirm_signverify(ctx, "ETH", decode_message(msg.message))
node = keychain.derive(msg.address_n) node = keychain.derive(msg.address_n)
signature = secp256k1.sign( signature = secp256k1.sign(

View File

@ -2,7 +2,7 @@ from trezor import wire
from trezor.crypto.curve import secp256k1 from trezor.crypto.curve import secp256k1
from trezor.crypto.hashlib import sha3_256 from trezor.crypto.hashlib import sha3_256
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.ui.layouts import confirm_signverify, require from trezor.ui.layouts import confirm_signverify
from apps.common.signverify import decode_message from apps.common.signverify import decode_message
@ -29,8 +29,6 @@ async def verify_message(ctx, msg):
address = address_from_bytes(address_bytes) address = address_from_bytes(address_bytes)
await require( await confirm_signverify(ctx, "ETH", decode_message(msg.message), address=address)
confirm_signverify(ctx, "ETH", decode_message(msg.message), address=address)
)
return Success(message="Message verified") return Success(message="Message verified")

View File

@ -1,7 +1,7 @@
from ubinascii import hexlify from ubinascii import hexlify
from trezor.messages.LiskPublicKey import LiskPublicKey from trezor.messages.LiskPublicKey import LiskPublicKey
from trezor.ui.layouts import require, show_pubkey from trezor.ui.layouts import show_pubkey
from apps.common import paths from apps.common import paths
from apps.common.keychain import auto_keychain from apps.common.keychain import auto_keychain
@ -16,6 +16,6 @@ async def get_public_key(ctx, msg, keychain):
pubkey = pubkey[1:] # skip ed25519 pubkey marker pubkey = pubkey[1:] # skip ed25519 pubkey marker
if msg.show_display: if msg.show_display:
await require(show_pubkey(ctx, hexlify(pubkey).decode())) await show_pubkey(ctx, hexlify(pubkey).decode())
return LiskPublicKey(public_key=pubkey) return LiskPublicKey(public_key=pubkey)

View File

@ -4,7 +4,7 @@ from trezor import ui
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.strings import format_amount from trezor.strings import format_amount
from trezor.ui.components.tt.text import Text from trezor.ui.components.tt.text import Text
from trezor.ui.layouts import require, show_pubkey from trezor.ui.layouts import show_pubkey
from trezor.utils import chunks from trezor.utils import chunks
from apps.common.confirm import require_confirm, require_hold_to_confirm from apps.common.confirm import require_confirm, require_hold_to_confirm
@ -36,7 +36,7 @@ async def require_confirm_vote_tx(ctx, votes):
async def require_confirm_public_key(ctx, public_key): async def require_confirm_public_key(ctx, public_key):
return await require(show_pubkey(ctx, hexlify(public_key).decode())) return await show_pubkey(ctx, hexlify(public_key).decode())
async def require_confirm_multisig(ctx, multisignature): async def require_confirm_multisig(ctx, multisignature):

View File

@ -1,7 +1,7 @@
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 trezor.messages.LiskMessageSignature import LiskMessageSignature from trezor.messages.LiskMessageSignature import LiskMessageSignature
from trezor.ui.layouts import confirm_signverify, require from trezor.ui.layouts import confirm_signverify
from trezor.utils import HashWriter from trezor.utils import HashWriter
from apps.common import paths from apps.common import paths
@ -23,7 +23,7 @@ def message_digest(message):
@auto_keychain(__name__) @auto_keychain(__name__)
async def sign_message(ctx, msg, keychain): async def sign_message(ctx, msg, keychain):
await paths.validate_path(ctx, keychain, msg.address_n) await paths.validate_path(ctx, keychain, msg.address_n)
await require(confirm_signverify(ctx, "Lisk", decode_message(msg.message))) await confirm_signverify(ctx, "Lisk", decode_message(msg.message))
node = keychain.derive(msg.address_n) node = keychain.derive(msg.address_n)
seckey = node.private_key() seckey = node.private_key()

View File

@ -1,7 +1,7 @@
from trezor import wire from trezor import wire
from trezor.crypto.curve import ed25519 from trezor.crypto.curve import ed25519
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.ui.layouts import confirm_signverify, require from trezor.ui.layouts import confirm_signverify
from apps.common.signverify import decode_message from apps.common.signverify import decode_message
@ -16,8 +16,6 @@ async def verify_message(ctx, msg):
raise wire.ProcessError("Invalid signature") raise wire.ProcessError("Invalid signature")
address = get_address_from_public_key(msg.public_key) address = get_address_from_public_key(msg.public_key)
await require( await confirm_signverify(ctx, "Lisk", decode_message(msg.message), address=address)
confirm_signverify(ctx, "Lisk", decode_message(msg.message), address=address)
)
return Success(message="Message verified") return Success(message="Message verified")

View File

@ -3,7 +3,7 @@ from trezor import ui, wire
from trezor.messages import ButtonRequestType, SafetyCheckLevel from trezor.messages import ButtonRequestType, SafetyCheckLevel
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.strings import format_duration_ms from trezor.strings import format_duration_ms
from trezor.ui.layouts import confirm_action, require from trezor.ui.layouts import confirm_action
from apps.base import reload_settings_from_storage from apps.base import reload_settings_from_storage
from apps.common import safety_checks from apps.common import safety_checks
@ -100,20 +100,17 @@ async def apply_settings(ctx: wire.Context, msg: ApplySettings):
async def require_confirm_change_homescreen(ctx): async def require_confirm_change_homescreen(ctx):
await require( await confirm_action(
confirm_action(
ctx, ctx,
"set_homescreen", "set_homescreen",
"Set homescreen", "Set homescreen",
description="Do you really want to change the homescreen image?", description="Do you really want to change the homescreen image?",
br_code=ButtonRequestType.ProtectCall, br_code=ButtonRequestType.ProtectCall,
) )
)
async def require_confirm_change_label(ctx, label): async def require_confirm_change_label(ctx, label):
await require( await confirm_action(
confirm_action(
ctx, ctx,
"set_label", "set_label",
"Change label", "Change label",
@ -121,7 +118,6 @@ async def require_confirm_change_label(ctx, label):
description_param=label, description_param=label,
br_code=ButtonRequestType.ProtectCall, br_code=ButtonRequestType.ProtectCall,
) )
)
async def require_confirm_change_passphrase(ctx, use): async def require_confirm_change_passphrase(ctx, use):
@ -129,15 +125,13 @@ async def require_confirm_change_passphrase(ctx, use):
description = "Do you really want to enable passphrase encryption?" description = "Do you really want to enable passphrase encryption?"
else: else:
description = "Do you really want to disable passphrase encryption?" description = "Do you really want to disable passphrase encryption?"
await require( await confirm_action(
confirm_action(
ctx, ctx,
"set_passphrase", "set_passphrase",
"Enable passphrase" if use else "Disable passphrase", "Enable passphrase" if use else "Disable passphrase",
description=description, description=description,
br_code=ButtonRequestType.ProtectCall, br_code=ButtonRequestType.ProtectCall,
) )
)
async def require_confirm_change_passphrase_source( async def require_confirm_change_passphrase_source(
@ -147,15 +141,13 @@ async def require_confirm_change_passphrase_source(
description = "Do you really want to enter passphrase always on the device?" description = "Do you really want to enter passphrase always on the device?"
else: else:
description = "Do you want to revoke the passphrase on device setting?" description = "Do you want to revoke the passphrase on device setting?"
await require( await confirm_action(
confirm_action(
ctx, ctx,
"set_passphrase_source", "set_passphrase_source",
"Passphrase source", "Passphrase source",
description=description, description=description,
br_code=ButtonRequestType.ProtectCall, br_code=ButtonRequestType.ProtectCall,
) )
)
async def require_confirm_change_display_rotation(ctx, rotation): async def require_confirm_change_display_rotation(ctx, rotation):
@ -169,8 +161,7 @@ async def require_confirm_change_display_rotation(ctx, rotation):
label = "west" label = "west"
else: else:
raise wire.DataError("Unsupported display rotation") raise wire.DataError("Unsupported display rotation")
await require( await confirm_action(
confirm_action(
ctx, ctx,
"set_rotation", "set_rotation",
"Change rotation", "Change rotation",
@ -178,12 +169,10 @@ async def require_confirm_change_display_rotation(ctx, rotation):
description_param=label, description_param=label,
br_code=ButtonRequestType.ProtectCall, br_code=ButtonRequestType.ProtectCall,
) )
)
async def require_confirm_change_autolock_delay(ctx, delay_ms): async def require_confirm_change_autolock_delay(ctx, delay_ms):
await require( await confirm_action(
confirm_action(
ctx, ctx,
"set_autolock_delay", "set_autolock_delay",
"Auto-lock delay", "Auto-lock delay",
@ -191,13 +180,11 @@ async def require_confirm_change_autolock_delay(ctx, delay_ms):
description_param=format_duration_ms(delay_ms), description_param=format_duration_ms(delay_ms),
br_code=ButtonRequestType.ProtectCall, br_code=ButtonRequestType.ProtectCall,
) )
)
async def require_confirm_safety_checks(ctx, level: EnumTypeSafetyCheckLevel) -> None: async def require_confirm_safety_checks(ctx, level: EnumTypeSafetyCheckLevel) -> None:
if level == SafetyCheckLevel.PromptAlways: if level == SafetyCheckLevel.PromptAlways:
await require( await confirm_action(
confirm_action(
ctx, ctx,
"set_safety_checks", "set_safety_checks",
"Safety override", "Safety override",
@ -209,10 +196,8 @@ async def require_confirm_safety_checks(ctx, level: EnumTypeSafetyCheckLevel) ->
larger_vspace=True, larger_vspace=True,
br_code=ButtonRequestType.ProtectCall, br_code=ButtonRequestType.ProtectCall,
) )
)
elif level == SafetyCheckLevel.PromptTemporarily: elif level == SafetyCheckLevel.PromptTemporarily:
await require( await confirm_action(
confirm_action(
ctx, ctx,
"set_safety_checks", "set_safety_checks",
"Safety override", "Safety override",
@ -223,25 +208,21 @@ async def require_confirm_safety_checks(ctx, level: EnumTypeSafetyCheckLevel) ->
reverse=True, reverse=True,
br_code=ButtonRequestType.ProtectCall, br_code=ButtonRequestType.ProtectCall,
) )
)
elif level == SafetyCheckLevel.Strict: elif level == SafetyCheckLevel.Strict:
await require( await confirm_action(
confirm_action(
ctx, ctx,
"set_safety_checks", "set_safety_checks",
"Safety checks", "Safety checks",
description="Do you really want to enforce strict safety checks (recommended)?", description="Do you really want to enforce strict safety checks (recommended)?",
br_code=ButtonRequestType.ProtectCall, br_code=ButtonRequestType.ProtectCall,
) )
)
else: else:
raise ValueError # enum value out of range raise ValueError # enum value out of range
async def require_confirm_experimental_features(ctx, enable: bool) -> None: async def require_confirm_experimental_features(ctx, enable: bool) -> None:
if enable: if enable:
await require( await confirm_action(
confirm_action(
ctx, ctx,
"set_experimental_features", "set_experimental_features",
"Experimental mode", "Experimental mode",
@ -250,4 +231,3 @@ async def require_confirm_experimental_features(ctx, enable: bool) -> None:
reverse=True, reverse=True,
br_code=ButtonRequestType.ProtectCall, br_code=ButtonRequestType.ProtectCall,
) )
)

View File

@ -1,7 +1,7 @@
from storage.device import is_initialized from storage.device import is_initialized
from trezor import config, wire from trezor import config, wire
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.ui.layouts import confirm_action, require, show_success from trezor.ui.layouts import confirm_action, show_success
from apps.common.request_pin import ( from apps.common.request_pin import (
error_pin_invalid, error_pin_invalid,
@ -53,7 +53,7 @@ async def change_pin(ctx: wire.Context, msg: ChangePin) -> Success:
msg_screen = "You have successfully disabled PIN protection." msg_screen = "You have successfully disabled PIN protection."
msg_wire = "PIN removed" msg_wire = "PIN removed"
await require(show_success(ctx, "success_pin", msg_screen)) await show_success(ctx, "success_pin", msg_screen)
return Success(message=msg_wire) return Success(message=msg_wire)
@ -61,8 +61,7 @@ def require_confirm_change_pin(ctx: wire.Context, msg: ChangePin) -> None:
has_pin = config.has_pin() has_pin = config.has_pin()
if msg.remove and has_pin: # removing pin if msg.remove and has_pin: # removing pin
return require( return confirm_action(
confirm_action(
ctx, ctx,
"set_pin", "set_pin",
"Remove PIN", "Remove PIN",
@ -70,11 +69,9 @@ def require_confirm_change_pin(ctx: wire.Context, msg: ChangePin) -> None:
action="disable PIN protection?", action="disable PIN protection?",
reverse=True, reverse=True,
) )
)
if not msg.remove and has_pin: # changing pin if not msg.remove and has_pin: # changing pin
return require( return confirm_action(
confirm_action(
ctx, ctx,
"set_pin", "set_pin",
"Change PIN", "Change PIN",
@ -82,11 +79,9 @@ def require_confirm_change_pin(ctx: wire.Context, msg: ChangePin) -> None:
action="change your PIN?", action="change your PIN?",
reverse=True, reverse=True,
) )
)
if not msg.remove and not has_pin: # setting new pin if not msg.remove and not has_pin: # setting new pin
return require( return confirm_action(
confirm_action(
ctx, ctx,
"set_pin", "set_pin",
"Enable PIN", "Enable PIN",
@ -94,7 +89,6 @@ def require_confirm_change_pin(ctx: wire.Context, msg: ChangePin) -> None:
action="enable PIN protection?", action="enable PIN protection?",
reverse=True, reverse=True,
) )
)
# removing non-existing PIN # removing non-existing PIN
raise wire.ProcessError("PIN protection already disabled") raise wire.ProcessError("PIN protection already disabled")

View File

@ -2,7 +2,7 @@ from storage.device import is_initialized
from trezor import config, ui, wire from trezor import config, ui, wire
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.ui.components.tt.text import Text from trezor.ui.components.tt.text import Text
from trezor.ui.layouts import require, show_success from trezor.ui.layouts import show_success
from trezor.ui.popup import Popup from trezor.ui.popup import Popup
from apps.common.confirm import require_confirm from apps.common.confirm import require_confirm
@ -52,7 +52,7 @@ async def change_wipe_code(ctx: wire.Context, msg: ChangeWipeCode) -> Success:
msg_screen = "You have successfully disabled the wipe code." msg_screen = "You have successfully disabled the wipe code."
msg_wire = "Wipe code removed" msg_wire = "Wipe code removed"
await require(show_success(ctx, "success_wipe_code", msg_screen)) await show_success(ctx, "success_wipe_code", msg_screen)
return Success(message=msg_wire) return Success(message=msg_wire)

View File

@ -8,7 +8,7 @@ from trezor.crypto.hashlib import sha256
from trezor.errors import MnemonicError from trezor.errors import MnemonicError
from trezor.messages import BackupType from trezor.messages import BackupType
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.ui.layouts import require, show_success from trezor.ui.layouts import show_success
from apps.common import mnemonic from apps.common import mnemonic
from apps.homescreen.homescreen import homescreen from apps.homescreen.homescreen import homescreen
@ -146,11 +146,9 @@ async def _finish_recovery(
storage.recovery.end_progress() storage.recovery.end_progress()
await require( await show_success(
show_success(
ctx, "success_recovery", "You have successfully recovered your wallet." ctx, "success_recovery", "You have successfully recovered your wallet."
) )
)
return Success(message="Device recovered") return Success(message="Device recovered")

View File

@ -5,7 +5,7 @@ from trezor.messages import ButtonRequestType
from trezor.ui.components.tt.scroll import Paginated from trezor.ui.components.tt.scroll import Paginated
from trezor.ui.components.tt.text import Text from trezor.ui.components.tt.text import Text
from trezor.ui.components.tt.word_select import WordSelector from trezor.ui.components.tt.word_select import WordSelector
from trezor.ui.layouts import confirm_action, require, show_success, show_warning from trezor.ui.layouts import confirm_action, show_success, show_warning
from apps.common import button_request from apps.common import button_request
from apps.common.confirm import confirm, info_confirm, require_confirm from apps.common.confirm import confirm, info_confirm, require_confirm
@ -21,9 +21,9 @@ if False:
from trezor.messages.ResetDevice import EnumTypeBackupType from trezor.messages.ResetDevice import EnumTypeBackupType
async def confirm_abort(ctx: wire.GenericContext, dry_run: bool = False) -> bool: async def confirm_abort(ctx: wire.GenericContext, dry_run: bool = False) -> None:
if dry_run: if dry_run:
return await confirm_action( await confirm_action(
ctx, ctx,
"abort_recovery", "abort_recovery",
"Abort seed check", "Abort seed check",
@ -32,7 +32,7 @@ async def confirm_abort(ctx: wire.GenericContext, dry_run: bool = False) -> bool
br_code=ButtonRequestType.ProtectCall, br_code=ButtonRequestType.ProtectCall,
) )
else: else:
return await confirm_action( await confirm_action(
ctx, ctx,
"abort_recovery", "abort_recovery",
"Abort recovery", "Abort recovery",
@ -146,17 +146,13 @@ async def show_dry_run_result(
text = "The entered recovery\nshares are valid and\nmatch what is currently\nin the device." text = "The entered recovery\nshares are valid and\nmatch what is currently\nin the device."
else: else:
text = "The entered recovery\nseed is valid and\nmatches the one\nin the device." text = "The entered recovery\nseed is valid and\nmatches the one\nin the device."
await require( await show_success(ctx, "success_dry_recovery", text, button="Continue")
show_success(ctx, "success_dry_recovery", text, button="Continue")
)
else: else:
if is_slip39: if is_slip39:
text = "The entered recovery\nshares are valid but\ndo not match what is\ncurrently in the device." text = "The entered recovery\nshares are valid but\ndo not match what is\ncurrently in the device."
else: else:
text = "The entered recovery\nseed is valid but does\nnot match the one\nin the device." text = "The entered recovery\nseed is valid but does\nnot match the one\nin the device."
await require( await show_warning(ctx, "warning_dry_recovery", text, button="Continue")
show_warning(ctx, "warning_dry_recovery", text, button="Continue")
)
async def show_dry_run_different_type(ctx: wire.GenericContext) -> None: async def show_dry_run_different_type(ctx: wire.GenericContext) -> None:
@ -171,51 +167,41 @@ async def show_dry_run_different_type(ctx: wire.GenericContext) -> None:
async def show_invalid_mnemonic(ctx: wire.GenericContext, word_count: int) -> None: async def show_invalid_mnemonic(ctx: wire.GenericContext, word_count: int) -> None:
if backup_types.is_slip39_word_count(word_count): if backup_types.is_slip39_word_count(word_count):
await require( await show_warning(
show_warning(
ctx, ctx,
"warning_invalid_share", "warning_invalid_share",
"You have entered\nan invalid recovery\nshare.", "You have entered\nan invalid recovery\nshare.",
) )
)
else: else:
await require( await show_warning(
show_warning(
ctx, ctx,
"warning_invalid_seed", "warning_invalid_seed",
"You have entered\nan invalid recovery\nseed.", "You have entered\nan invalid recovery\nseed.",
) )
)
async def show_share_already_added(ctx: wire.GenericContext) -> None: async def show_share_already_added(ctx: wire.GenericContext) -> None:
await require( await show_warning(
show_warning(
ctx, ctx,
"warning_known_share", "warning_known_share",
"Share already entered,\nplease enter\na different share.", "Share already entered,\nplease enter\na different share.",
) )
)
async def show_identifier_mismatch(ctx: wire.GenericContext) -> None: async def show_identifier_mismatch(ctx: wire.GenericContext) -> None:
await require( await show_warning(
show_warning(
ctx, ctx,
"warning_mismatched_share", "warning_mismatched_share",
"You have entered\na share from another\nShamir Backup.", "You have entered\na share from another\nShamir Backup.",
) )
)
async def show_group_threshold_reached(ctx: wire.GenericContext) -> None: async def show_group_threshold_reached(ctx: wire.GenericContext) -> None:
await require( await show_warning(
show_warning(
ctx, ctx,
"warning_group_threshold", "warning_group_threshold",
"Threshold of this\ngroup has been reached.\nInput share from\ndifferent group.", "Threshold of this\ngroup has been reached.\nInput share from\ndifferent group.",
) )
)
class RecoveryHomescreen(ui.Component): class RecoveryHomescreen(ui.Component):
@ -288,5 +274,9 @@ async def homescreen_dialog(
break break
# user has chosen to abort, confirm the choice # user has chosen to abort, confirm the choice
dry_run = storage.recovery.is_dry_run() dry_run = storage.recovery.is_dry_run()
if await confirm_abort(ctx, dry_run): try:
await confirm_abort(ctx, dry_run)
except wire.ActionCancelled:
pass
else:
raise RecoveryAborted raise RecoveryAborted

View File

@ -6,7 +6,7 @@ from trezor.messages import BackupType
from trezor.messages.EntropyAck import EntropyAck from trezor.messages.EntropyAck import EntropyAck
from trezor.messages.EntropyRequest import EntropyRequest from trezor.messages.EntropyRequest import EntropyRequest
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.ui.layouts import confirm_backup, confirm_reset_device, require from trezor.ui.layouts import confirm_backup, confirm_reset_device
from trezor.ui.loader import LoadingAnimation from trezor.ui.loader import LoadingAnimation
from .. import backup_types from .. import backup_types
@ -33,7 +33,7 @@ async def reset_device(ctx: wire.Context, msg: ResetDevice) -> Success:
prompt = "Create a new wallet\nwith Super Shamir?" prompt = "Create a new wallet\nwith Super Shamir?"
else: else:
prompt = "Do you want to create\na new wallet?" prompt = "Do you want to create\na new wallet?"
await require(confirm_reset_device(ctx, prompt)) await confirm_reset_device(ctx, prompt)
await LoadingAnimation() await LoadingAnimation()
# wipe storage to make sure the device is in a clear state # wipe storage to make sure the device is in a clear state

View File

@ -9,13 +9,7 @@ from trezor.ui.components.tt.info import InfoConfirm
from trezor.ui.components.tt.num_input import NumInput from trezor.ui.components.tt.num_input import NumInput
from trezor.ui.components.tt.scroll import Paginated from trezor.ui.components.tt.scroll import Paginated
from trezor.ui.components.tt.text import Text from trezor.ui.components.tt.text import Text
from trezor.ui.layouts import ( from trezor.ui.layouts import confirm_action, confirm_hex, show_success, show_warning
confirm_action,
confirm_hex,
require,
show_success,
show_warning,
)
from apps.common.confirm import confirm, require_hold_to_confirm from apps.common.confirm import confirm, require_hold_to_confirm
@ -28,8 +22,7 @@ if __debug__:
async def show_internal_entropy(ctx, entropy: bytes): async def show_internal_entropy(ctx, entropy: bytes):
await require( await confirm_hex(
confirm_hex(
ctx, ctx,
"entropy", "entropy",
"Internal entropy", "Internal entropy",
@ -39,7 +32,6 @@ async def show_internal_entropy(ctx, entropy: bytes):
width=16, width=16,
br_code=ButtonRequestType.ResetDevice, br_code=ButtonRequestType.ResetDevice,
) )
)
async def _show_share_words(ctx, share_words, share_index=None, group_index=None): async def _show_share_words(ctx, share_words, share_index=None, group_index=None):
@ -192,9 +184,7 @@ async def _show_confirmation_success(
) )
text = "Continue with the next\nshare." text = "Continue with the next\nshare."
return await require( return await show_success(ctx, "success_recovery", text, subheader=subheader)
show_success(ctx, "success_recovery", text, subheader=subheader)
)
async def _show_confirmation_failure(ctx, share_index): async def _show_confirmation_failure(ctx, share_index):
@ -202,8 +192,7 @@ async def _show_confirmation_failure(ctx, share_index):
header = "Recovery seed" header = "Recovery seed"
else: else:
header = "Recovery share #%s" % (share_index + 1) header = "Recovery share #%s" % (share_index + 1)
await require( await show_warning(
show_warning(
ctx, ctx,
"warning_backup_check", "warning_backup_check",
header=header, header=header,
@ -212,7 +201,6 @@ async def _show_confirmation_failure(ctx, share_index):
button="Check again", button="Check again",
br_code=ButtonRequestType.ResetDevice, br_code=ButtonRequestType.ResetDevice,
) )
)
async def show_backup_warning(ctx, slip39=False): async def show_backup_warning(ctx, slip39=False):
@ -220,8 +208,7 @@ async def show_backup_warning(ctx, slip39=False):
description = "Never make a digital copy of your recovery shares and never upload them online!" description = "Never make a digital copy of your recovery shares and never upload them online!"
else: else:
description = "Never make a digital copy of your recovery seed and never upload\nit online!" description = "Never make a digital copy of your recovery seed and never upload\nit online!"
await require( await confirm_action(
confirm_action(
ctx, ctx,
"backup_warning", "backup_warning",
"Caution", "Caution",
@ -231,14 +218,11 @@ async def show_backup_warning(ctx, slip39=False):
icon=ui.ICON_NOCOPY, icon=ui.ICON_NOCOPY,
br_code=ButtonRequestType.ResetDevice, br_code=ButtonRequestType.ResetDevice,
) )
)
async def show_backup_success(ctx): async def show_backup_success(ctx):
text = "Use your backup\nwhen you need to\nrecover your wallet." text = "Use your backup\nwhen you need to\nrecover your wallet."
await require( await show_success(ctx, "success_backup", text, subheader="Your backup is done.")
show_success(ctx, "success_backup", text, subheader="Your backup is done.")
)
# BIP39 # BIP39

View File

@ -4,14 +4,14 @@ from trezor import config, wire
from trezor.crypto import random from trezor.crypto import random
from trezor.messages import SdProtectOperationType from trezor.messages import SdProtectOperationType
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.ui.layouts import confirm_action, require, show_success from trezor.ui.layouts import confirm_action, show_success
from apps.common.request_pin import ( from apps.common.request_pin import (
error_pin_invalid, error_pin_invalid,
request_pin, request_pin,
request_pin_and_sd_salt, request_pin_and_sd_salt,
) )
from apps.common.sdcard import ensure_sdcard, sd_problem_dialog from apps.common.sdcard import confirm_retry_sd, ensure_sdcard
if False: if False:
from typing import Awaitable, Tuple from typing import Awaitable, Tuple
@ -33,8 +33,7 @@ async def _set_salt(
try: try:
return storage.sd_salt.set_sd_salt(salt, salt_tag, stage) return storage.sd_salt.set_sd_salt(salt, salt_tag, stage)
except OSError: except OSError:
if not await sd_problem_dialog(ctx): await confirm_retry_sd(ctx, exc=wire.ProcessError("SD card I/O error."))
raise wire.ProcessError("SD card I/O error.")
async def sd_protect(ctx: wire.Context, msg: SdProtect) -> Success: async def sd_protect(ctx: wire.Context, msg: SdProtect) -> Success:
@ -84,8 +83,8 @@ async def sd_protect_enable(ctx: wire.Context, msg: SdProtect) -> Success:
storage.device.set_sd_salt_auth_key(salt_auth_key) storage.device.set_sd_salt_auth_key(salt_auth_key)
await require( await show_success(
show_success(ctx, "success_sd", "You have successfully enabled SD protection.") ctx, "success_sd", "You have successfully enabled SD protection."
) )
return Success(message="SD card protection enabled") return Success(message="SD card protection enabled")
@ -118,8 +117,8 @@ async def sd_protect_disable(ctx: wire.Context, msg: SdProtect) -> Success:
# because overall SD-protection was successfully disabled. # because overall SD-protection was successfully disabled.
pass pass
await require( await show_success(
show_success(ctx, "success_sd", "You have successfully disabled SD protection.") ctx, "success_sd", "You have successfully disabled SD protection."
) )
return Success(message="SD card protection disabled") return Success(message="SD card protection disabled")
@ -155,11 +154,9 @@ async def sd_protect_refresh(ctx: wire.Context, msg: SdProtect) -> Success:
# SD-protection was successfully refreshed. # SD-protection was successfully refreshed.
pass pass
await require( await show_success(
show_success(
ctx, "success_sd", "You have successfully refreshed SD protection." ctx, "success_sd", "You have successfully refreshed SD protection."
) )
)
return Success(message="SD card protection refreshed") return Success(message="SD card protection refreshed")
@ -173,6 +170,4 @@ def require_confirm_sd_protect(ctx: wire.Context, msg: SdProtect) -> Awaitable[N
else: else:
raise wire.ProcessError("Unknown operation") raise wire.ProcessError("Unknown operation")
return require( return confirm_action(ctx, "set_sd", "SD card protection", description=text)
confirm_action(ctx, "set_sd", "SD card protection", description=text)
)

View File

@ -1,12 +1,12 @@
import storage import storage
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.ui.layouts import confirm_wipe, require from trezor.ui.layouts import confirm_wipe
from .apply_settings import reload_settings_from_storage from .apply_settings import reload_settings_from_storage
async def wipe_device(ctx, msg): async def wipe_device(ctx, msg):
await require(confirm_wipe(ctx)) await confirm_wipe(ctx)
storage.wipe() storage.wipe()
reload_settings_from_storage() reload_settings_from_storage()

View File

@ -1,7 +1,7 @@
from trezor import wire from trezor import wire
from trezor.crypto import aes, hmac from trezor.crypto import aes, hmac
from trezor.messages.CipheredKeyValue import CipheredKeyValue from trezor.messages.CipheredKeyValue import CipheredKeyValue
from trezor.ui.layouts import confirm_action, require from trezor.ui.layouts import confirm_action
from apps.common.keychain import get_keychain from apps.common.keychain import get_keychain
from apps.common.paths import AlwaysMatchingSchema from apps.common.paths import AlwaysMatchingSchema
@ -27,9 +27,7 @@ async def cipher_key_value(ctx: Context, msg: CipherKeyValue) -> CipheredKeyValu
title = "Encrypt value" title = "Encrypt value"
else: else:
title = "Decrypt value" title = "Decrypt value"
await require( await confirm_action(ctx, "cipher_key_value", title, description=msg.key)
confirm_action(ctx, "cipher_key_value", title, description=msg.key)
)
node = keychain.derive(msg.address_n) node = keychain.derive(msg.address_n)
value = compute_cipher_key_value(msg, node.private_key()) value = compute_cipher_key_value(msg, node.private_key())

View File

@ -3,7 +3,7 @@ from ustruct import pack, unpack
from trezor import ui, wire from trezor import ui, wire
from trezor.crypto.hashlib import sha256 from trezor.crypto.hashlib import sha256
from trezor.messages.ECDHSessionKey import ECDHSessionKey from trezor.messages.ECDHSessionKey import ECDHSessionKey
from trezor.ui.layouts import confirm_hex, require from trezor.ui.layouts import confirm_hex
from apps.common import HARDENED from apps.common import HARDENED
from apps.common.keychain import get_keychain from apps.common.keychain import get_keychain
@ -47,8 +47,7 @@ async def require_confirm_ecdh_session_key(
ctx: wire.Context, identity: IdentityType ctx: wire.Context, identity: IdentityType
) -> None: ) -> None:
proto = identity.proto.upper() if identity.proto else "identity" proto = identity.proto.upper() if identity.proto else "identity"
await require( await confirm_hex(
confirm_hex(
ctx, ctx,
"ecdh_session_key", "ecdh_session_key",
"Decrypt %s" % proto, "Decrypt %s" % proto,
@ -56,7 +55,6 @@ async def require_confirm_ecdh_session_key(
icon=ui.ICON_DEFAULT, icon=ui.ICON_DEFAULT,
icon_color=ui.ORANGE_ICON, icon_color=ui.ORANGE_ICON,
) )
)
def get_ecdh_path(identity: str, index: int) -> Bip32Path: def get_ecdh_path(identity: str, index: int) -> Bip32Path:

View File

@ -1,7 +1,7 @@
from trezor.crypto import random from trezor.crypto import random
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.messages.Entropy import Entropy from trezor.messages.Entropy import Entropy
from trezor.ui.layouts import confirm_action, require from trezor.ui.layouts import confirm_action
if False: if False:
from trezor.wire import Context from trezor.wire import Context
@ -9,8 +9,7 @@ if False:
async def get_entropy(ctx: Context, msg: GetEntropy) -> Entropy: async def get_entropy(ctx: Context, msg: GetEntropy) -> Entropy:
await require( await confirm_action(
confirm_action(
ctx, ctx,
"get_entropy", "get_entropy",
"Confirm entropy", "Confirm entropy",
@ -18,7 +17,6 @@ async def get_entropy(ctx: Context, msg: GetEntropy) -> Entropy:
description="Continue only if you\nknow what you are doing!", description="Continue only if you\nknow what you are doing!",
br_code=ButtonRequestType.ProtectCall, br_code=ButtonRequestType.ProtectCall,
) )
)
size = min(msg.size, 1024) size = min(msg.size, 1024)
entropy = random.bytes(size) entropy = random.bytes(size)

View File

@ -3,7 +3,7 @@ from ustruct import pack, unpack
from trezor import wire from trezor import wire
from trezor.crypto.hashlib import sha256 from trezor.crypto.hashlib import sha256
from trezor.messages.SignedIdentity import SignedIdentity from trezor.messages.SignedIdentity import SignedIdentity
from trezor.ui.layouts import confirm_sign_identity, require from trezor.ui.layouts import confirm_sign_identity
from apps.common import HARDENED, coininfo from apps.common import HARDENED, coininfo
from apps.common.keychain import get_keychain from apps.common.keychain import get_keychain
@ -84,11 +84,9 @@ async def require_confirm_sign_identity(
ctx: wire.Context, identity: IdentityType, challenge_visual: Optional[str] ctx: wire.Context, identity: IdentityType, challenge_visual: Optional[str]
) -> None: ) -> None:
proto = identity.proto.upper() if identity.proto else "identity" proto = identity.proto.upper() if identity.proto else "identity"
await require( await confirm_sign_identity(
confirm_sign_identity(
ctx, proto, serialize_identity_without_proto(identity), challenge_visual ctx, proto, serialize_identity_without_proto(identity), challenge_visual
) )
)
def serialize_identity(identity: IdentityType) -> str: def serialize_identity(identity: IdentityType) -> str:

View File

@ -3,7 +3,7 @@ from ubinascii import hexlify
from trezor import ui, wire from trezor import ui, wire
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.ui.components.tt.text import Text from trezor.ui.components.tt.text import Text
from trezor.ui.layouts import confirm_action, require from trezor.ui.layouts import confirm_action
from trezor.ui.popup import Popup from trezor.ui.popup import Popup
from trezor.utils import chunks from trezor.utils import chunks
@ -23,8 +23,7 @@ if False:
async def require_confirm_watchkey(ctx): async def require_confirm_watchkey(ctx):
await require( await confirm_action(
confirm_action(
ctx, ctx,
"get_watchkey", "get_watchkey",
"Confirm export", "Confirm export",
@ -33,12 +32,10 @@ async def require_confirm_watchkey(ctx):
icon_color=ui.GREEN, icon_color=ui.GREEN,
br_code=ButtonRequestType.SignTx, br_code=ButtonRequestType.SignTx,
) )
)
async def require_confirm_keyimage_sync(ctx): async def require_confirm_keyimage_sync(ctx):
await require( await confirm_action(
confirm_action(
ctx, ctx,
"key_image_sync", "key_image_sync",
"Confirm ki sync", "Confirm ki sync",
@ -47,12 +44,10 @@ async def require_confirm_keyimage_sync(ctx):
icon_color=ui.GREEN, icon_color=ui.GREEN,
br_code=ButtonRequestType.SignTx, br_code=ButtonRequestType.SignTx,
) )
)
async def require_confirm_live_refresh(ctx): async def require_confirm_live_refresh(ctx):
await require( await confirm_action(
confirm_action(
ctx, ctx,
"live_refresh", "live_refresh",
"Confirm refresh", "Confirm refresh",
@ -61,7 +56,6 @@ async def require_confirm_live_refresh(ctx):
icon_color=ui.GREEN, icon_color=ui.GREEN,
br_code=ButtonRequestType.SignTx, br_code=ButtonRequestType.SignTx,
) )
)
async def require_confirm_tx_key(ctx, export_key=False): async def require_confirm_tx_key(ctx, export_key=False):
@ -69,8 +63,7 @@ async def require_confirm_tx_key(ctx, export_key=False):
description = "Do you really want to export tx_key?" description = "Do you really want to export tx_key?"
else: else:
description = "Do you really want to export tx_der\nfor tx_proof?" description = "Do you really want to export tx_der\nfor tx_proof?"
await require( await confirm_action(
confirm_action(
ctx, ctx,
"export_tx_key", "export_tx_key",
"Confirm export", "Confirm export",
@ -79,7 +72,6 @@ async def require_confirm_tx_key(ctx, export_key=False):
icon_color=ui.GREEN, icon_color=ui.GREEN,
br_code=ButtonRequestType.SignTx, br_code=ButtonRequestType.SignTx,
) )
)
async def require_confirm_transaction( async def require_confirm_transaction(

View File

@ -1,5 +1,5 @@
from trezor.messages.TezosPublicKey import TezosPublicKey from trezor.messages.TezosPublicKey import TezosPublicKey
from trezor.ui.layouts import require, show_pubkey from trezor.ui.layouts import show_pubkey
from apps.common import paths, seed from apps.common import paths, seed
from apps.common.keychain import with_slip44_keychain from apps.common.keychain import with_slip44_keychain
@ -16,6 +16,6 @@ async def get_public_key(ctx, msg, keychain):
pk_prefixed = helpers.base58_encode_check(pk, prefix=helpers.TEZOS_PUBLICKEY_PREFIX) pk_prefixed = helpers.base58_encode_check(pk, prefix=helpers.TEZOS_PUBLICKEY_PREFIX)
if msg.show_display: if msg.show_display:
await require(show_pubkey(ctx, pk_prefixed)) await show_pubkey(ctx, pk_prefixed)
return TezosPublicKey(public_key=pk_prefixed) return TezosPublicKey(public_key=pk_prefixed)

View File

@ -2,7 +2,7 @@ import storage.device
from trezor import wire from trezor import wire
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.messages.WebAuthnAddResidentCredential import WebAuthnAddResidentCredential from trezor.messages.WebAuthnAddResidentCredential import WebAuthnAddResidentCredential
from trezor.ui.layouts import require, show_error from trezor.ui.layouts import show_error_and_raise
from apps.common.confirm import require_confirm from apps.common.confirm import require_confirm
@ -41,8 +41,7 @@ async def add_resident_credential(
try: try:
cred = Fido2Credential.from_cred_id(bytes(msg.credential_id), None) cred = Fido2Credential.from_cred_id(bytes(msg.credential_id), None)
except Exception: except Exception:
await require( await show_error_and_raise(
show_error(
ctx, ctx,
"warning_credential", "warning_credential",
header="Import credential", header="Import credential",
@ -50,8 +49,6 @@ async def add_resident_credential(
content="The credential you are trying to import does\nnot belong to this authenticator.", content="The credential you are trying to import does\nnot belong to this authenticator.",
red=True, red=True,
) )
)
raise wire.ActionCancelled
content = ConfirmContent(ConfirmAddCredential(cred)) content = ConfirmContent(ConfirmAddCredential(cred))
await require_confirm(ctx, content) await require_confirm(ctx, content)

View File

@ -4,7 +4,7 @@ from trezor.messages.WebAuthnCredentials import WebAuthnCredentials
from trezor.messages.WebAuthnListResidentCredentials import ( from trezor.messages.WebAuthnListResidentCredentials import (
WebAuthnListResidentCredentials, WebAuthnListResidentCredentials,
) )
from trezor.ui.layouts import confirm_action, require from trezor.ui.layouts import confirm_action
from . import resident_credentials from . import resident_credentials
@ -12,14 +12,12 @@ from . import resident_credentials
async def list_resident_credentials( async def list_resident_credentials(
ctx: wire.Context, msg: WebAuthnListResidentCredentials ctx: wire.Context, msg: WebAuthnListResidentCredentials
) -> WebAuthnCredentials: ) -> WebAuthnCredentials:
await require( await confirm_action(
confirm_action(
ctx, ctx,
"credentials_list", "credentials_list",
title="List credentials", title="List credentials",
description="Do you want to export information about the resident credentials stored on this device?", description="Do you want to export information about the resident credentials stored on this device?",
) )
)
creds = [ creds = [
WebAuthnCredential( WebAuthnCredential(
index=cred.index, index=cred.index,

View File

@ -1,10 +1,10 @@
from trezor import loop, ui from trezor import loop, ui, wire
if __debug__: if __debug__:
from apps.debug import confirm_signal from apps.debug import confirm_signal
if False: if False:
from typing import List, Tuple, Optional, Any from typing import List, Tuple, Optional, Any, Awaitable
CONFIRMED = object() CONFIRMED = object()
CANCELLED = object() CANCELLED = object()
@ -15,6 +15,12 @@ def is_confirmed(x: Any) -> bool:
return x is CONFIRMED return x is CONFIRMED
async def raise_if_cancelled(a: Awaitable, exc: Any = wire.ActionCancelled) -> None:
result = await a
if result is CANCELLED:
raise exc
class ConfirmBase(ui.Layout): class ConfirmBase(ui.Layout):
def __init__( def __init__(
self, self,

View File

@ -11,12 +11,6 @@ if False:
LayoutType = Awaitable[Any] LayoutType = Awaitable[Any]
async def require(a: Awaitable[bool]) -> None:
result = await a
if not result:
raise wire.ActionCancelled
async def interact( async def interact(
ctx: wire.GenericContext, ctx: wire.GenericContext,
layout: LayoutType, layout: LayoutType,

View File

@ -1,6 +1,6 @@
from micropython import const from micropython import const
from trezor import ui from trezor import ui, wire
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.ui.container import Container from trezor.ui.container import Container
from trezor.ui.loader import LoaderDanger from trezor.ui.loader import LoaderDanger
@ -8,7 +8,7 @@ from trezor.ui.qr import Qr
from trezor.utils import chunks from trezor.utils import chunks
from ..components.common import break_path_to_lines from ..components.common import break_path_to_lines
from ..components.common.confirm import is_confirmed from ..components.common.confirm import is_confirmed, raise_if_cancelled
from ..components.tt.button import ButtonCancel, ButtonDefault from ..components.tt.button import ButtonCancel, ButtonDefault
from ..components.tt.confirm import Confirm, HoldToConfirm from ..components.tt.confirm import Confirm, HoldToConfirm
from ..components.tt.scroll import Paginated, paginate_text from ..components.tt.scroll import Paginated, paginate_text
@ -24,13 +24,23 @@ from ..constants.tt import (
from .common import interact from .common import interact
if False: if False:
from typing import Any, Iterator, List, Sequence, Union, Optional, Awaitable from typing import (
Iterator,
List,
Sequence,
Type,
Union,
Optional,
Awaitable,
NoReturn,
)
from trezor import wire
from trezor.messages.ButtonRequest import EnumTypeButtonRequestType from trezor.messages.ButtonRequest import EnumTypeButtonRequestType
from ..components.common.text import TextContent from ..components.common.text import TextContent
ExceptionType = Union[BaseException, Type[BaseException]]
__all__ = ( __all__ = (
"confirm_action", "confirm_action",
"confirm_wipe", "confirm_wipe",
@ -40,7 +50,7 @@ __all__ = (
"confirm_sign_identity", "confirm_sign_identity",
"confirm_signverify", "confirm_signverify",
"show_address", "show_address",
"show_error", "show_error_and_raise",
"show_pubkey", "show_pubkey",
"show_success", "show_success",
"show_xpub", "show_xpub",
@ -73,9 +83,10 @@ async def confirm_action(
icon_color: int = None, # TODO cleanup @ redesign icon_color: int = None, # TODO cleanup @ redesign
reverse: bool = False, # TODO cleanup @ redesign reverse: bool = False, # TODO cleanup @ redesign
larger_vspace: bool = False, # TODO cleanup @ redesign larger_vspace: bool = False, # TODO cleanup @ redesign
exc: ExceptionType = wire.ActionCancelled,
br_code: EnumTypeButtonRequestType = ButtonRequestType.Other, br_code: EnumTypeButtonRequestType = ButtonRequestType.Other,
**kwargs: Any, **kwargs: Any,
) -> bool: ) -> None:
text = Text( text = Text(
title, title,
icon if icon is not None else ui.ICON_DEFAULT, icon if icon is not None else ui.ICON_DEFAULT,
@ -107,23 +118,24 @@ async def confirm_action(
) )
cls = HoldToConfirm if hold else Confirm cls = HoldToConfirm if hold else Confirm
return is_confirmed( await raise_if_cancelled(
await interact( interact(
ctx, ctx,
cls(text, confirm=verb, cancel=verb_cancel), cls(text, confirm=verb, cancel=verb_cancel),
br_type, br_type,
br_code, br_code,
) ),
exc,
) )
# TODO cleanup @ redesign # TODO cleanup @ redesign
async def confirm_wipe(ctx: wire.GenericContext) -> bool: async def confirm_wipe(ctx: wire.GenericContext) -> None:
text = Text("Wipe device", ui.ICON_WIPE, ui.RED) text = Text("Wipe device", ui.ICON_WIPE, ui.RED)
text.normal("Do you really want to", "wipe the device?", "") text.normal("Do you really want to", "wipe the device?", "")
text.bold("All data will be lost.") text.bold("All data will be lost.")
return is_confirmed( await raise_if_cancelled(
await interact( interact(
ctx, ctx,
HoldToConfirm(text, confirm_style=ButtonCancel, loader_style=LoaderDanger), HoldToConfirm(text, confirm_style=ButtonCancel, loader_style=LoaderDanger),
"wipe_device", "wipe_device",
@ -132,7 +144,7 @@ async def confirm_wipe(ctx: wire.GenericContext) -> bool:
) )
async def confirm_reset_device(ctx: wire.GenericContext, prompt: str) -> bool: async def confirm_reset_device(ctx: wire.GenericContext, prompt: str) -> None:
text = Text("Create new wallet", ui.ICON_RESET, new_lines=False) text = Text("Create new wallet", ui.ICON_RESET, new_lines=False)
text.bold(prompt) text.bold(prompt)
text.br() text.br()
@ -141,8 +153,8 @@ async def confirm_reset_device(ctx: wire.GenericContext, prompt: str) -> bool:
text.br() text.br()
text.normal("to ") text.normal("to ")
text.bold("https://trezor.io/tos") text.bold("https://trezor.io/tos")
return is_confirmed( await raise_if_cancelled(
await interact( interact(
ctx, ctx,
Confirm(text, major_confirm=True), Confirm(text, major_confirm=True),
"setup_device", "setup_device",
@ -184,13 +196,13 @@ async def confirm_backup(ctx: wire.GenericContext) -> bool:
return confirmed return confirmed
async def confirm_path_warning(ctx: wire.GenericContext, path: str) -> bool: async def confirm_path_warning(ctx: wire.GenericContext, path: str) -> None:
text = Text("Confirm path", ui.ICON_WRONG, ui.RED) text = Text("Confirm path", ui.ICON_WRONG, ui.RED)
text.normal("Path") text.normal("Path")
text.mono(*break_path_to_lines(path, MONO_CHARS_PER_LINE)) text.mono(*break_path_to_lines(path, MONO_CHARS_PER_LINE))
text.normal("is unknown.", "Are you sure?") text.normal("is unknown.", "Are you sure?")
return is_confirmed( await raise_if_cancelled(
await interact( interact(
ctx, ctx,
Confirm(text), Confirm(text),
"path_warning", "path_warning",
@ -266,9 +278,9 @@ def _show_xpub(xpub: str, desc: str, cancel: str) -> Paginated:
async def show_xpub( async def show_xpub(
ctx: wire.GenericContext, xpub: str, desc: str, cancel: str ctx: wire.GenericContext, xpub: str, desc: str, cancel: str
) -> bool: ) -> None:
return is_confirmed( await raise_if_cancelled(
await interact( interact(
ctx, ctx,
_show_xpub(xpub, desc, cancel), _show_xpub(xpub, desc, cancel),
"show_xpub", "show_xpub",
@ -329,7 +341,7 @@ async def show_address(
def show_pubkey( def show_pubkey(
ctx: wire.Context, pubkey: str, title: str = "Confirm public key" ctx: wire.Context, pubkey: str, title: str = "Confirm public key"
) -> Awaitable[bool]: ) -> Awaitable[None]:
return confirm_hex( return confirm_hex(
ctx, ctx,
br_type="show_pubkey", br_type="show_pubkey",
@ -351,24 +363,26 @@ async def _show_modal(
button_cancel: Optional[str], button_cancel: Optional[str],
icon: str, icon: str,
icon_color: int, icon_color: int,
) -> bool: exc: ExceptionType = wire.ActionCancelled,
) -> None:
text = Text(header, icon, icon_color, new_lines=False) text = Text(header, icon, icon_color, new_lines=False)
if subheader: if subheader:
text.bold(subheader) text.bold(subheader)
text.br() text.br()
text.br_half() text.br_half()
text.normal(content) text.normal(content)
return is_confirmed( await raise_if_cancelled(
await interact( interact(
ctx, ctx,
Confirm(text, confirm=button_confirm, cancel=button_cancel), Confirm(text, confirm=button_confirm, cancel=button_cancel),
br_type, br_type,
br_code, br_code,
) ),
exc,
) )
def show_error( async def show_error_and_raise(
ctx: wire.GenericContext, ctx: wire.GenericContext,
br_type: str, br_type: str,
content: str, content: str,
@ -376,8 +390,9 @@ def show_error(
subheader: Optional[str] = None, subheader: Optional[str] = None,
button: str = "Close", button: str = "Close",
red: bool = False, red: bool = False,
) -> Awaitable[bool]: exc: ExceptionType = wire.ActionCancelled,
return _show_modal( ) -> NoReturn:
await _show_modal(
ctx, ctx,
br_type=br_type, br_type=br_type,
br_code=ButtonRequestType.Other, br_code=ButtonRequestType.Other,
@ -388,7 +403,9 @@ def show_error(
button_cancel=button, button_cancel=button,
icon=ui.ICON_WRONG, icon=ui.ICON_WRONG,
icon_color=ui.RED if red else ui.ORANGE_ICON, icon_color=ui.RED if red else ui.ORANGE_ICON,
exc=exc,
) )
raise exc
def show_warning( def show_warning(
@ -399,7 +416,7 @@ def show_warning(
subheader: Optional[str] = None, subheader: Optional[str] = None,
button: str = "Try again", button: str = "Try again",
br_code: EnumTypeButtonRequestType = ButtonRequestType.Warning, br_code: EnumTypeButtonRequestType = ButtonRequestType.Warning,
) -> Awaitable[bool]: ) -> Awaitable[None]:
return _show_modal( return _show_modal(
ctx, ctx,
br_type=br_type, br_type=br_type,
@ -420,7 +437,7 @@ def show_success(
content: str, content: str,
subheader: Optional[str] = None, subheader: Optional[str] = None,
button: str = "Continue", button: str = "Continue",
) -> Awaitable[bool]: ) -> Awaitable[None]:
return _show_modal( return _show_modal(
ctx, ctx,
br_type=br_type, br_type=br_type,
@ -439,14 +456,12 @@ async def confirm_output(
ctx: wire.GenericContext, ctx: wire.GenericContext,
address: str, address: str,
amount: str, amount: str,
) -> bool: ) -> None:
text = Text("Confirm sending", ui.ICON_SEND, ui.GREEN) text = Text("Confirm sending", ui.ICON_SEND, ui.GREEN)
text.normal(amount + " to") text.normal(amount + " to")
text.mono(*_split_address(address)) text.mono(*_split_address(address))
return is_confirmed( await raise_if_cancelled(
await interact( interact(ctx, Confirm(text), "confirm_output", ButtonRequestType.ConfirmOutput)
ctx, Confirm(text), "confirm_output", ButtonRequestType.ConfirmOutput
)
) )
@ -454,13 +469,13 @@ async def confirm_decred_sstx_submission(
ctx: wire.GenericContext, ctx: wire.GenericContext,
address: str, address: str,
amount: str, amount: str,
) -> bool: ) -> None:
text = Text("Purchase ticket", ui.ICON_SEND, ui.GREEN) text = Text("Purchase ticket", ui.ICON_SEND, ui.GREEN)
text.normal(amount) text.normal(amount)
text.normal("with voting rights to") text.normal("with voting rights to")
text.mono(*_split_address(address)) text.mono(*_split_address(address))
return is_confirmed( await raise_if_cancelled(
await interact( interact(
ctx, ctx,
Confirm(text), Confirm(text),
"confirm_decred_sstx_submission", "confirm_decred_sstx_submission",
@ -480,7 +495,7 @@ async def confirm_hex(
icon_color: int = ui.GREEN, # TODO cleanup @ redesign icon_color: int = ui.GREEN, # TODO cleanup @ redesign
width: int = MONO_HEX_PER_LINE, width: int = MONO_HEX_PER_LINE,
truncate_middle: bool = False, truncate_middle: bool = False,
) -> bool: ) -> None:
text = Text(title, icon, icon_color, new_lines=False) text = Text(title, icon, icon_color, new_lines=False)
description_lines = 0 description_lines = 0
if description is not None: if description is not None:
@ -496,34 +511,32 @@ async def confirm_hex(
) )
) )
content: ui.Layout = Confirm(text) content: ui.Layout = Confirm(text)
return is_confirmed(await interact(ctx, content, br_type, br_code)) await raise_if_cancelled(interact(ctx, content, br_type, br_code))
async def confirm_total( async def confirm_total(
ctx: wire.GenericContext, total_amount: str, fee_amount: str ctx: wire.GenericContext, total_amount: str, fee_amount: str
) -> bool: ) -> None:
text = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN) text = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
text.normal("Total amount:") text.normal("Total amount:")
text.bold(total_amount) text.bold(total_amount)
text.normal("including fee:") text.normal("including fee:")
text.bold(fee_amount) text.bold(fee_amount)
return is_confirmed( await raise_if_cancelled(
await interact( interact(ctx, HoldToConfirm(text), "confirm_total", ButtonRequestType.SignTx)
ctx, HoldToConfirm(text), "confirm_total", ButtonRequestType.SignTx
)
) )
async def confirm_joint_total( async def confirm_joint_total(
ctx: wire.GenericContext, spending_amount: str, total_amount: str ctx: wire.GenericContext, spending_amount: str, total_amount: str
) -> bool: ) -> None:
text = Text("Joint transaction", ui.ICON_SEND, ui.GREEN) text = Text("Joint transaction", ui.ICON_SEND, ui.GREEN)
text.normal("You are contributing:") text.normal("You are contributing:")
text.bold(spending_amount) text.bold(spending_amount)
text.normal("to the total amount:") text.normal("to the total amount:")
text.bold(total_amount) text.bold(total_amount)
return is_confirmed( await raise_if_cancelled(
await interact( interact(
ctx, HoldToConfirm(text), "confirm_joint_total", ButtonRequestType.SignTx ctx, HoldToConfirm(text), "confirm_joint_total", ButtonRequestType.SignTx
) )
) )
@ -536,26 +549,24 @@ async def confirm_metadata(
content: str, content: str,
param: Optional[str] = None, param: Optional[str] = None,
br_code: EnumTypeButtonRequestType = ButtonRequestType.SignTx, br_code: EnumTypeButtonRequestType = ButtonRequestType.SignTx,
) -> bool: ) -> None:
text = Text(title, ui.ICON_SEND, ui.GREEN, new_lines=False) text = Text(title, ui.ICON_SEND, ui.GREEN, new_lines=False)
text.format_parametrized(content, param if param is not None else "") text.format_parametrized(content, param if param is not None else "")
text.br() text.br()
text.normal("Continue?") text.normal("Continue?")
return is_confirmed(await interact(ctx, Confirm(text), br_type, br_code)) await raise_if_cancelled(interact(ctx, Confirm(text), br_type, br_code))
async def confirm_replacement( async def confirm_replacement(
ctx: wire.GenericContext, description: str, txid: str ctx: wire.GenericContext, description: str, txid: str
) -> bool: ) -> None:
text = Text(description, ui.ICON_SEND, ui.GREEN) text = Text(description, ui.ICON_SEND, ui.GREEN)
text.normal("Confirm transaction ID:") text.normal("Confirm transaction ID:")
text.mono(*_truncate_hex(txid, TEXT_MAX_LINES - 1)) text.mono(*_truncate_hex(txid, TEXT_MAX_LINES - 1))
return is_confirmed( await raise_if_cancelled(
await interact( interact(ctx, Confirm(text), "confirm_replacement", ButtonRequestType.SignTx)
ctx, Confirm(text), "confirm_replacement", ButtonRequestType.SignTx
)
) )
@ -565,7 +576,7 @@ async def confirm_modify_output(
sign: int, sign: int,
amount_change: str, amount_change: str,
amount_new: str, amount_new: str,
) -> bool: ) -> None:
page1 = Text("Modify amount", ui.ICON_SEND, ui.GREEN) page1 = Text("Modify amount", ui.ICON_SEND, ui.GREEN)
page1.normal("Address:") page1.normal("Address:")
page1.br_half() page1.br_half()
@ -581,7 +592,7 @@ async def confirm_modify_output(
page2.normal("New amount:") page2.normal("New amount:")
page2.bold(amount_new) page2.bold(amount_new)
return is_confirmed( await raise_if_cancelled(
interact( interact(
ctx, ctx,
Paginated([page1, Confirm(page2)]), Paginated([page1, Confirm(page2)]),
@ -596,7 +607,7 @@ async def confirm_modify_fee(
sign: int, sign: int,
user_fee_change: str, user_fee_change: str,
total_fee_new: str, total_fee_new: str,
) -> bool: ) -> None:
text = Text("Modify fee", ui.ICON_SEND, ui.GREEN) text = Text("Modify fee", ui.ICON_SEND, ui.GREEN)
if sign == 0: if sign == 0:
text.normal("Your fee did not change.") text.normal("Your fee did not change.")
@ -609,31 +620,29 @@ async def confirm_modify_fee(
text.br_half() text.br_half()
text.normal("Transaction fee:") text.normal("Transaction fee:")
text.bold(total_fee_new) text.bold(total_fee_new)
return is_confirmed( await raise_if_cancelled(
await interact(ctx, HoldToConfirm(text), "modify_fee", ButtonRequestType.SignTx) interact(ctx, HoldToConfirm(text), "modify_fee", ButtonRequestType.SignTx)
) )
async def confirm_coinjoin( async def confirm_coinjoin(
ctx: wire.GenericContext, fee_per_anonymity: Optional[str], total_fee: str ctx: wire.GenericContext, fee_per_anonymity: Optional[str], total_fee: str
) -> bool: ) -> None:
text = Text("Authorize CoinJoin", ui.ICON_RECOVERY, new_lines=False) text = Text("Authorize CoinJoin", ui.ICON_RECOVERY, new_lines=False)
if fee_per_anonymity is not None: if fee_per_anonymity is not None:
text.normal("Fee per anonymity set:\n") text.normal("Fee per anonymity set:\n")
text.bold("{} %\n".format(fee_per_anonymity)) text.bold("{} %\n".format(fee_per_anonymity))
text.normal("Maximum total fees:\n") text.normal("Maximum total fees:\n")
text.bold(total_fee) text.bold(total_fee)
return is_confirmed( await raise_if_cancelled(
await interact( interact(ctx, HoldToConfirm(text), "coinjoin_final", ButtonRequestType.Other)
ctx, HoldToConfirm(text), "coinjoin_final", ButtonRequestType.Other
)
) )
# TODO cleanup @ redesign # TODO cleanup @ redesign
async def confirm_sign_identity( async def confirm_sign_identity(
ctx: wire.GenericContext, proto: str, identity: str, challenge_visual: Optional[str] ctx: wire.GenericContext, proto: str, identity: str, challenge_visual: Optional[str]
) -> bool: ) -> None:
lines: List[TextContent] = [] lines: List[TextContent] = []
if challenge_visual: if challenge_visual:
lines.append(challenge_visual) lines.append(challenge_visual)
@ -643,14 +652,14 @@ async def confirm_sign_identity(
text = Text("Sign %s" % proto) text = Text("Sign %s" % proto)
text.normal(*lines) text.normal(*lines)
return is_confirmed( await raise_if_cancelled(
await interact(ctx, Confirm(text), "sign_identity", ButtonRequestType.Other) interact(ctx, Confirm(text), "sign_identity", ButtonRequestType.Other)
) )
async def confirm_signverify( async def confirm_signverify(
ctx: wire.GenericContext, coin: str, message: str, address: str = None ctx: wire.GenericContext, coin: str, message: str, address: str = None
) -> bool: ) -> None:
if address: if address:
header = "Verify {} message".format(coin) header = "Verify {} message".format(coin)
font = ui.MONO font = ui.MONO
@ -659,17 +668,16 @@ async def confirm_signverify(
text = Text(header) text = Text(header)
text.bold("Confirm address:") text.bold("Confirm address:")
text.mono(*_split_address(address)) text.mono(*_split_address(address))
if not is_confirmed( await raise_if_cancelled(
await interact(ctx, Confirm(text), br_type, ButtonRequestType.Other) interact(ctx, Confirm(text), br_type, ButtonRequestType.Other)
): )
return False
else: else:
header = "Sign {} message".format(coin) header = "Sign {} message".format(coin)
font = ui.NORMAL font = ui.NORMAL
br_type = "sign_message" br_type = "sign_message"
return is_confirmed( await raise_if_cancelled(
await interact( interact(
ctx, ctx,
paginate_text(message, header, font=font), paginate_text(message, header, font=font),
br_type, br_type,