1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-26 09:28:13 +00:00

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

This commit is contained in:
Martin Milata 2021-02-10 00:14:11 +01:00
parent f128e4a1c2
commit 035f114125
3 changed files with 141 additions and 102 deletions

View File

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

View File

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

View File

@ -8,7 +8,7 @@ from trezor.ui.qr import Qr
from trezor.utils import chunks
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.confirm import Confirm, HoldToConfirm
from ..components.tt.scroll import Paginated
@ -29,8 +29,6 @@ if False:
from trezor import wire
from trezor.messages.ButtonRequest import EnumTypeButtonRequestType
from . import LayoutType
__all__ = (
"confirm_action",
@ -55,39 +53,49 @@ __all__ = (
)
def confirm_action(
async def confirm_action(
ctx: wire.GenericContext,
br_type: str,
title: str,
action: str,
description: str = None,
verb: Union[str, bytes] = Confirm.DEFAULT_CONFIRM,
verb_cancel: Union[str, bytes] = Confirm.DEFAULT_CANCEL,
icon: str = None,
br_code: EnumTypeButtonRequestType = ButtonRequestType.Other,
**kwargs: Any,
) -> LayoutType:
) -> bool:
text = Text(title, icon if icon is not None else ui.ICON_DEFAULT, new_lines=False)
text.bold(action)
text.br()
if 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.normal("Do you really want to", "wipe the device?", "")
text.bold("All data will be lost.")
return interact(
return is_confirmed(
await interact(
ctx,
HoldToConfirm(text, confirm_style=ButtonCancel, loader_style=LoaderDanger),
"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.bold(prompt)
text.br()
@ -96,12 +104,14 @@ def confirm_reset_device(ctx: wire.GenericContext, prompt: str) -> LayoutType:
text.br()
text.normal("to")
text.bold("https://trezor.io/tos")
return interact(
return is_confirmed(
await interact(
ctx,
Confirm(text, major_confirm=True),
"setup_device",
ButtonRequestType.ResetDevice,
)
)
async def confirm_backup(ctx: wire.GenericContext) -> bool:
@ -115,39 +125,40 @@ async def confirm_backup(ctx: wire.GenericContext) -> bool:
text2.br_half()
text2.normal("You can back up your", "Trezor once, at any time.")
if (
if is_confirmed(
await interact(
ctx,
Confirm(text1, cancel="Skip", confirm="Back up", major_confirm=True),
"backup_device",
ButtonRequestType.ResetDevice,
)
is CONFIRMED
):
return True
confirmed = (
confirmed = is_confirmed(
await interact(
ctx,
Confirm(text2, cancel="Skip", confirm="Back up", major_confirm=True),
"backup_device",
ButtonRequestType.ResetDevice,
)
) is 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.normal("Path")
text.mono(*break_path_to_lines(path, MONO_CHARS_PER_LINE))
text.normal("is unknown.", "Are you sure?")
return interact(
return is_confirmed(
await interact(
ctx,
Confirm(text),
"path_warning",
ButtonRequestType.UnknownDerivationPath,
)
)
def _show_qr(
@ -203,11 +214,16 @@ def _show_xpub(xpub: str, desc: str, cancel: str) -> Paginated:
return content
def show_xpub(
async def show_xpub(
ctx: wire.GenericContext, xpub: str, desc: str, cancel: str
) -> LayoutType:
return interact(
ctx, _show_xpub(xpub, desc, cancel), "show_xpub", ButtonRequestType.PublicKey
) -> bool:
return is_confirmed(
await interact(
ctx,
_show_xpub(xpub, desc, cancel),
"show_xpub",
ButtonRequestType.PublicKey,
)
)
@ -222,17 +238,16 @@ async def show_address(
) -> None:
is_multisig = len(xpubs) > 0
while True:
if (
if is_confirmed(
await interact(
ctx,
_show_address(address, desc, network),
"show_address",
ButtonRequestType.Address,
)
is CONFIRMED
):
break
if (
if is_confirmed(
await interact(
ctx,
_show_qr(
@ -243,7 +258,6 @@ async def show_address(
"show_qr",
ButtonRequestType.Address,
)
is CONFIRMED
):
break
@ -252,169 +266,188 @@ async def show_address(
cancel = "Next" if i < len(xpubs) - 1 else "Address"
desc_xpub = "XPUB #%d" % (i + 1)
desc_xpub += " (yours)" if i == multisig_index else " (cosigner)"
if (
if is_confirmed(
await interact(
ctx,
_show_xpub(xpub, desc=desc_xpub, cancel=cancel),
"show_xpub",
ButtonRequestType.PublicKey,
)
is CONFIRMED
):
return
# FIXME: this is basically same as confirm_hex
# TODO: pagination for long keys
def show_pubkey(
async def show_pubkey(
ctx: wire.Context, pubkey: str, title: str = "Confirm public key"
) -> LayoutType:
) -> bool:
text = Text(title, ui.ICON_RECEIVE, ui.GREEN)
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,
br_type: str,
content: str,
subheader: Optional[str] = None,
button: str = "Try again",
) -> LayoutType:
) -> bool:
text = Text("Warning", ui.ICON_WRONG, ui.RED, new_lines=False)
if subheader:
text.bold(subheader)
text.br()
text.br_half()
text.normal(content)
return interact(
return is_confirmed(
await interact(
ctx,
Confirm(text, confirm=button, cancel=None),
br_type,
ButtonRequestType.Warning,
)
)
def show_success(
async def show_success(
ctx: wire.GenericContext,
br_type: str,
content: str,
subheader: Optional[str] = None,
button: str = "Continue",
) -> LayoutType:
) -> bool:
text = Text("Success", ui.ICON_CONFIRM, ui.GREEN, new_lines=False)
if subheader:
text.bold(subheader)
text.br()
text.br_half()
text.normal(content)
return interact(
return is_confirmed(
await interact(
ctx,
Confirm(text, confirm=button, cancel=None),
br_type,
ButtonRequestType.Success,
)
def confirm_output(
ctx: wire.GenericContext,
address: str,
amount: str,
) -> LayoutType:
text = Text("Confirm sending", ui.ICON_SEND, ui.GREEN)
text.normal(amount + " to")
text.mono(*_split_address(address))
return interact(
ctx, Confirm(text), "confirm_output", ButtonRequestType.ConfirmOutput
)
def confirm_decred_sstx_submission(
async def confirm_output(
ctx: wire.GenericContext,
address: str,
amount: str,
) -> LayoutType:
) -> bool:
text = Text("Confirm sending", ui.ICON_SEND, ui.GREEN)
text.normal(amount + " to")
text.mono(*_split_address(address))
return is_confirmed(
await interact(
ctx, Confirm(text), "confirm_output", ButtonRequestType.ConfirmOutput
)
)
async def confirm_decred_sstx_submission(
ctx: wire.GenericContext,
address: str,
amount: str,
) -> bool:
text = Text("Purchase ticket", ui.ICON_SEND, ui.GREEN)
text.normal(amount)
text.normal("with voting rights to")
text.mono(*_split_address(address))
return interact(
return is_confirmed(
await interact(
ctx,
Confirm(text),
"confirm_decred_sstx_submission",
ButtonRequestType.ConfirmOutput,
)
)
def confirm_hex(
async def confirm_hex(
ctx: wire.GenericContext,
br_type: str,
title: str,
data: str,
br_code: EnumTypeButtonRequestType = ButtonRequestType.Other,
) -> LayoutType:
) -> bool:
text = Text(title, ui.ICON_SEND, ui.GREEN)
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
) -> LayoutType:
) -> bool:
text = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
text.normal("Total amount:")
text.bold(total_amount)
text.normal("including fee:")
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
) -> LayoutType:
) -> bool:
text = Text("Joint transaction", ui.ICON_SEND, ui.GREEN)
text.normal("You are contributing:")
text.bold(spending_amount)
text.normal("to the total amount:")
text.bold(total_amount)
return interact(
return is_confirmed(
await interact(
ctx, HoldToConfirm(text), "confirm_joint_total", ButtonRequestType.SignTx
)
)
def confirm_metadata(
async def confirm_metadata(
ctx: wire.GenericContext,
br_type: str,
title: str,
content: str,
param: Optional[str] = None,
br_code: EnumTypeButtonRequestType = ButtonRequestType.SignTx,
) -> LayoutType:
) -> bool:
text = Text(title, ui.ICON_SEND, ui.GREEN, new_lines=False)
text.format_parametrized(content, param if param is not None else "")
text.br()
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
) -> LayoutType:
) -> bool:
text = Text(description, ui.ICON_SEND, ui.GREEN)
text.normal("Confirm transaction ID:")
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,
address: str,
sign: int,
amount_change: str,
amount_new: str,
) -> LayoutType:
) -> bool:
page1 = Text("Modify amount", ui.ICON_SEND, ui.GREEN)
page1.normal("Address:")
page1.br_half()
@ -430,20 +463,22 @@ def confirm_modify_output(
page2.normal("New amount:")
page2.bold(amount_new)
return interact(
return is_confirmed(
interact(
ctx,
Paginated([page1, Confirm(page2)]),
"modify_output",
ButtonRequestType.ConfirmOutput,
)
)
def confirm_modify_fee(
async def confirm_modify_fee(
ctx: wire.GenericContext,
sign: int,
user_fee_change: str,
total_fee_new: str,
) -> LayoutType:
) -> bool:
text = Text("Modify fee", ui.ICON_SEND, ui.GREEN)
if sign == 0:
text.normal("Your fee did not change.")
@ -456,4 +491,6 @@ def confirm_modify_fee(
text.br_half()
text.normal("Transaction fee:")
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)
)