fix(core/ui): don't return CONFIRMED/CANCELLED from layouts

pull/1533/head
Martin Milata 3 years ago
parent f128e4a1c2
commit 035f114125

@ -4,13 +4,17 @@ if __debug__:
from apps.debug import confirm_signal from apps.debug import confirm_signal
if False: if False:
from typing import List, Tuple, Optional from typing import List, Tuple, Optional, Any
CONFIRMED = object() CONFIRMED = object()
CANCELLED = object() CANCELLED = object()
INFO = object() INFO = object()
def is_confirmed(x: Any) -> bool:
return x is CONFIRMED
class ConfirmBase(ui.Layout): class ConfirmBase(ui.Layout):
def __init__( def __init__(
self, self,

@ -3,8 +3,6 @@ from trezor.messages import ButtonRequestType
from trezor.messages.ButtonAck import ButtonAck from trezor.messages.ButtonAck import ButtonAck
from trezor.messages.ButtonRequest import ButtonRequest from trezor.messages.ButtonRequest import ButtonRequest
from ..components.common.confirm import CONFIRMED
if False: if False:
from typing import Any, Awaitable from typing import Any, Awaitable
@ -13,9 +11,9 @@ if False:
LayoutType = Awaitable[Any] LayoutType = Awaitable[Any]
async def require(a: LayoutType) -> None: async def require(a: Awaitable[bool]) -> None:
result = await a result = await a
if result is not CONFIRMED: if not result:
raise wire.ActionCancelled raise wire.ActionCancelled

@ -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 CONFIRMED from ..components.common.confirm import is_confirmed
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 from ..components.tt.scroll import Paginated
@ -29,8 +29,6 @@ if False:
from trezor import wire from trezor import wire
from trezor.messages.ButtonRequest import EnumTypeButtonRequestType from trezor.messages.ButtonRequest import EnumTypeButtonRequestType
from . import LayoutType
__all__ = ( __all__ = (
"confirm_action", "confirm_action",
@ -55,39 +53,49 @@ __all__ = (
) )
def confirm_action( async def confirm_action(
ctx: wire.GenericContext, ctx: wire.GenericContext,
br_type: str, br_type: str,
title: str, title: str,
action: str, action: str,
description: str = None, description: str = None,
verb: Union[str, bytes] = Confirm.DEFAULT_CONFIRM, verb: Union[str, bytes] = Confirm.DEFAULT_CONFIRM,
verb_cancel: Union[str, bytes] = Confirm.DEFAULT_CANCEL,
icon: str = None, icon: str = None,
br_code: EnumTypeButtonRequestType = ButtonRequestType.Other, br_code: EnumTypeButtonRequestType = ButtonRequestType.Other,
**kwargs: Any, **kwargs: Any,
) -> LayoutType: ) -> bool:
text = Text(title, icon if icon is not None else ui.ICON_DEFAULT, new_lines=False) text = Text(title, icon if icon is not None else ui.ICON_DEFAULT, new_lines=False)
text.bold(action) text.bold(action)
text.br() text.br()
if description: if description:
text.normal(description) text.normal(description)
return interact(ctx, Confirm(text, confirm=verb), br_type, br_code) return is_confirmed(
await interact(
ctx,
Confirm(text, confirm=verb, cancel=verb_cancel),
br_type,
br_code,
)
)
def confirm_wipe(ctx: wire.GenericContext) -> LayoutType: async def confirm_wipe(ctx: wire.GenericContext) -> bool:
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 interact( return is_confirmed(
ctx, await interact(
HoldToConfirm(text, confirm_style=ButtonCancel, loader_style=LoaderDanger), ctx,
"wipe_device", HoldToConfirm(text, confirm_style=ButtonCancel, loader_style=LoaderDanger),
ButtonRequestType.WipeDevice, "wipe_device",
ButtonRequestType.WipeDevice,
)
) )
def confirm_reset_device(ctx: wire.GenericContext, prompt: str) -> LayoutType: async def confirm_reset_device(ctx: wire.GenericContext, prompt: str) -> bool:
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()
@ -96,11 +104,13 @@ def confirm_reset_device(ctx: wire.GenericContext, prompt: str) -> LayoutType:
text.br() text.br()
text.normal("to") text.normal("to")
text.bold("https://trezor.io/tos") text.bold("https://trezor.io/tos")
return interact( return is_confirmed(
ctx, await interact(
Confirm(text, major_confirm=True), ctx,
"setup_device", Confirm(text, major_confirm=True),
ButtonRequestType.ResetDevice, "setup_device",
ButtonRequestType.ResetDevice,
)
) )
@ -115,38 +125,39 @@ async def confirm_backup(ctx: wire.GenericContext) -> bool:
text2.br_half() text2.br_half()
text2.normal("You can back up your", "Trezor once, at any time.") text2.normal("You can back up your", "Trezor once, at any time.")
if ( if is_confirmed(
await interact( await interact(
ctx, ctx,
Confirm(text1, cancel="Skip", confirm="Back up", major_confirm=True), Confirm(text1, cancel="Skip", confirm="Back up", major_confirm=True),
"backup_device", "backup_device",
ButtonRequestType.ResetDevice, ButtonRequestType.ResetDevice,
) )
is CONFIRMED
): ):
return True return True
confirmed = ( confirmed = is_confirmed(
await interact( await interact(
ctx, ctx,
Confirm(text2, cancel="Skip", confirm="Back up", major_confirm=True), Confirm(text2, cancel="Skip", confirm="Back up", major_confirm=True),
"backup_device", "backup_device",
ButtonRequestType.ResetDevice, ButtonRequestType.ResetDevice,
) )
) is CONFIRMED )
return confirmed return confirmed
def confirm_path_warning(ctx: wire.GenericContext, path: str) -> LayoutType: async def confirm_path_warning(ctx: wire.GenericContext, path: str) -> bool:
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 interact( return is_confirmed(
ctx, await interact(
Confirm(text), ctx,
"path_warning", Confirm(text),
ButtonRequestType.UnknownDerivationPath, "path_warning",
ButtonRequestType.UnknownDerivationPath,
)
) )
@ -203,11 +214,16 @@ def _show_xpub(xpub: str, desc: str, cancel: str) -> Paginated:
return content return content
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
) -> LayoutType: ) -> bool:
return interact( return is_confirmed(
ctx, _show_xpub(xpub, desc, cancel), "show_xpub", ButtonRequestType.PublicKey await interact(
ctx,
_show_xpub(xpub, desc, cancel),
"show_xpub",
ButtonRequestType.PublicKey,
)
) )
@ -222,17 +238,16 @@ async def show_address(
) -> None: ) -> None:
is_multisig = len(xpubs) > 0 is_multisig = len(xpubs) > 0
while True: while True:
if ( if is_confirmed(
await interact( await interact(
ctx, ctx,
_show_address(address, desc, network), _show_address(address, desc, network),
"show_address", "show_address",
ButtonRequestType.Address, ButtonRequestType.Address,
) )
is CONFIRMED
): ):
break break
if ( if is_confirmed(
await interact( await interact(
ctx, ctx,
_show_qr( _show_qr(
@ -243,7 +258,6 @@ async def show_address(
"show_qr", "show_qr",
ButtonRequestType.Address, ButtonRequestType.Address,
) )
is CONFIRMED
): ):
break break
@ -252,169 +266,188 @@ async def show_address(
cancel = "Next" if i < len(xpubs) - 1 else "Address" cancel = "Next" if i < len(xpubs) - 1 else "Address"
desc_xpub = "XPUB #%d" % (i + 1) desc_xpub = "XPUB #%d" % (i + 1)
desc_xpub += " (yours)" if i == multisig_index else " (cosigner)" desc_xpub += " (yours)" if i == multisig_index else " (cosigner)"
if ( if is_confirmed(
await interact( await interact(
ctx, ctx,
_show_xpub(xpub, desc=desc_xpub, cancel=cancel), _show_xpub(xpub, desc=desc_xpub, cancel=cancel),
"show_xpub", "show_xpub",
ButtonRequestType.PublicKey, ButtonRequestType.PublicKey,
) )
is CONFIRMED
): ):
return return
# FIXME: this is basically same as confirm_hex # FIXME: this is basically same as confirm_hex
# TODO: pagination for long keys # TODO: pagination for long keys
def show_pubkey( async def show_pubkey(
ctx: wire.Context, pubkey: str, title: str = "Confirm public key" ctx: wire.Context, pubkey: str, title: str = "Confirm public key"
) -> LayoutType: ) -> bool:
text = Text(title, ui.ICON_RECEIVE, ui.GREEN) text = Text(title, ui.ICON_RECEIVE, ui.GREEN)
text.mono(*_hex_lines(pubkey)) text.mono(*_hex_lines(pubkey))
return interact(ctx, Confirm(text), "show_pubkey", ButtonRequestType.PublicKey) return is_confirmed(
await interact(ctx, Confirm(text), "show_pubkey", ButtonRequestType.PublicKey)
)
def show_warning( async def show_warning(
ctx: wire.GenericContext, ctx: wire.GenericContext,
br_type: str, br_type: str,
content: str, content: str,
subheader: Optional[str] = None, subheader: Optional[str] = None,
button: str = "Try again", button: str = "Try again",
) -> LayoutType: ) -> bool:
text = Text("Warning", ui.ICON_WRONG, ui.RED, new_lines=False) text = Text("Warning", ui.ICON_WRONG, ui.RED, 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 interact( return is_confirmed(
ctx, await interact(
Confirm(text, confirm=button, cancel=None), ctx,
br_type, Confirm(text, confirm=button, cancel=None),
ButtonRequestType.Warning, br_type,
ButtonRequestType.Warning,
)
) )
def show_success( async def show_success(
ctx: wire.GenericContext, ctx: wire.GenericContext,
br_type: str, br_type: str,
content: str, content: str,
subheader: Optional[str] = None, subheader: Optional[str] = None,
button: str = "Continue", button: str = "Continue",
) -> LayoutType: ) -> bool:
text = Text("Success", ui.ICON_CONFIRM, ui.GREEN, new_lines=False) text = Text("Success", ui.ICON_CONFIRM, ui.GREEN, 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 interact( return is_confirmed(
ctx, await interact(
Confirm(text, confirm=button, cancel=None), ctx,
br_type, Confirm(text, confirm=button, cancel=None),
ButtonRequestType.Success, br_type,
ButtonRequestType.Success,
)
) )
def confirm_output( async def confirm_output(
ctx: wire.GenericContext, ctx: wire.GenericContext,
address: str, address: str,
amount: str, amount: str,
) -> LayoutType: ) -> bool:
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 interact( return is_confirmed(
ctx, Confirm(text), "confirm_output", ButtonRequestType.ConfirmOutput await interact(
ctx, Confirm(text), "confirm_output", ButtonRequestType.ConfirmOutput
)
) )
def confirm_decred_sstx_submission( async def confirm_decred_sstx_submission(
ctx: wire.GenericContext, ctx: wire.GenericContext,
address: str, address: str,
amount: str, amount: str,
) -> LayoutType: ) -> bool:
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 interact( return is_confirmed(
ctx, await interact(
Confirm(text), ctx,
"confirm_decred_sstx_submission", Confirm(text),
ButtonRequestType.ConfirmOutput, "confirm_decred_sstx_submission",
ButtonRequestType.ConfirmOutput,
)
) )
def confirm_hex( async def confirm_hex(
ctx: wire.GenericContext, ctx: wire.GenericContext,
br_type: str, br_type: str,
title: str, title: str,
data: str, data: str,
br_code: EnumTypeButtonRequestType = ButtonRequestType.Other, br_code: EnumTypeButtonRequestType = ButtonRequestType.Other,
) -> LayoutType: ) -> bool:
text = Text(title, ui.ICON_SEND, ui.GREEN) text = Text(title, ui.ICON_SEND, ui.GREEN)
text.mono(*_hex_lines(data)) text.mono(*_hex_lines(data))
return interact(ctx, Confirm(text), br_type, br_code) return is_confirmed(await interact(ctx, Confirm(text), br_type, br_code))
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
) -> LayoutType: ) -> bool:
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 interact(ctx, HoldToConfirm(text), "confirm_total", ButtonRequestType.SignTx) return is_confirmed(
await interact(
ctx, HoldToConfirm(text), "confirm_total", ButtonRequestType.SignTx
)
)
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
) -> LayoutType: ) -> bool:
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 interact( return is_confirmed(
ctx, HoldToConfirm(text), "confirm_joint_total", ButtonRequestType.SignTx await interact(
ctx, HoldToConfirm(text), "confirm_joint_total", ButtonRequestType.SignTx
)
) )
def confirm_metadata( async def confirm_metadata(
ctx: wire.GenericContext, ctx: wire.GenericContext,
br_type: str, br_type: str,
title: str, title: str,
content: str, content: str,
param: Optional[str] = None, param: Optional[str] = None,
br_code: EnumTypeButtonRequestType = ButtonRequestType.SignTx, br_code: EnumTypeButtonRequestType = ButtonRequestType.SignTx,
) -> LayoutType: ) -> bool:
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 interact(ctx, Confirm(text), br_type, br_code) return is_confirmed(await interact(ctx, Confirm(text), br_type, br_code))
def confirm_replacement( async def confirm_replacement(
ctx: wire.GenericContext, description: str, txid: str ctx: wire.GenericContext, description: str, txid: str
) -> LayoutType: ) -> bool:
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(*_hex_lines(txid, TEXT_MAX_LINES - 1)) text.mono(*_hex_lines(txid, TEXT_MAX_LINES - 1))
return interact(ctx, Confirm(text), "confirm_replacement", ButtonRequestType.SignTx) return is_confirmed(
await interact(
ctx, Confirm(text), "confirm_replacement", ButtonRequestType.SignTx
)
)
def confirm_modify_output( async def confirm_modify_output(
ctx: wire.GenericContext, ctx: wire.GenericContext,
address: str, address: str,
sign: int, sign: int,
amount_change: str, amount_change: str,
amount_new: str, amount_new: str,
) -> LayoutType: ) -> bool:
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()
@ -430,20 +463,22 @@ def confirm_modify_output(
page2.normal("New amount:") page2.normal("New amount:")
page2.bold(amount_new) page2.bold(amount_new)
return interact( return is_confirmed(
ctx, interact(
Paginated([page1, Confirm(page2)]), ctx,
"modify_output", Paginated([page1, Confirm(page2)]),
ButtonRequestType.ConfirmOutput, "modify_output",
ButtonRequestType.ConfirmOutput,
)
) )
def confirm_modify_fee( async def confirm_modify_fee(
ctx: wire.GenericContext, ctx: wire.GenericContext,
sign: int, sign: int,
user_fee_change: str, user_fee_change: str,
total_fee_new: str, total_fee_new: str,
) -> LayoutType: ) -> bool:
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.")
@ -456,4 +491,6 @@ 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 interact(ctx, HoldToConfirm(text), "modify_fee", ButtonRequestType.SignTx) return is_confirmed(
await interact(ctx, HoldToConfirm(text), "modify_fee", ButtonRequestType.SignTx)
)

Loading…
Cancel
Save