feat(core): make first steps to unify Rust API for both models

wip: unify confirm_action

wip: unify confirm_fido

wip: unify request_pin, clean up prompts

wip: unify select_word

wip: unify request_number

refactor(core/reset): refactor confirm_share_words

[no changelog]
pull/2749/head
matejcik 1 year ago committed by Jiří Musil
parent c068c668fa
commit 497285f9a1

@ -108,4 +108,5 @@ static void _librust_qstrs(void) {
MP_QSTR_notification_level;
MP_QSTR_bootscreen;
MP_QSTR_skip_first_paint;
MP_QSTR_wrong_pin;
}

@ -128,7 +128,8 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// description: str | None = None,
/// verb: str | None = None,
/// verb_cancel: str | None = None,
/// hold: bool | None = None,
/// hold: bool = False,
/// hold_danger: bool = False, # unused on TR
/// reverse: bool = False,
/// ) -> object:
/// """Confirm action."""

@ -914,7 +914,12 @@ extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map)
let prompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
let subprompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_subprompt)?.try_into()?;
let allow_cancel: bool = kwargs.get_or(Qstr::MP_QSTR_allow_cancel, true)?;
let warning: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_warning)?.try_into_option()?;
let warning: bool = kwargs.get_or(Qstr::MP_QSTR_wrong_pin, false)?;
let warning = if warning {
Some("Wrong PIN".into())
} else {
None
};
let obj = LayoutObj::new(PinKeyboard::new(prompt, subprompt, warning, allow_cancel))?;
Ok(obj.into())
};
@ -999,6 +1004,7 @@ extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut M
let max_count: u32 = kwargs.get(Qstr::MP_QSTR_max_count)?.try_into()?;
let count: u32 = kwargs.get(Qstr::MP_QSTR_count)?.try_into()?;
let description_callback: Obj = kwargs.get(Qstr::MP_QSTR_description)?;
assert!(description_callback != Obj::const_none());
let callback = move |i: u32| {
StrBuffer::try_from(
@ -1485,7 +1491,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// prompt: str,
/// subprompt: str,
/// allow_cancel: bool = True,
/// warning: str | None = None,
/// wrong_pin: bool = False,
/// ) -> str | object:
/// """Request pin on device."""
Qstr::MP_QSTR_request_pin => obj_fn_kw!(0, new_request_pin).as_obj(),
@ -1536,7 +1542,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// count: int,
/// min_count: int,
/// max_count: int,
/// description: Callable[[int], str],
/// description: Callable[[int], str] | None = None,
/// ) -> object:
/// """Number input with + and - buttons, description, and info button."""
Qstr::MP_QSTR_request_number => obj_fn_kw!(0, new_request_number).as_obj(),

@ -47,7 +47,8 @@ def confirm_action(
description: str | None = None,
verb: str | None = None,
verb_cancel: str | None = None,
hold: bool | None = None,
hold: bool = False,
hold_danger: bool = False, # unused on TR
reverse: bool = False,
) -> object:
"""Confirm action."""
@ -281,7 +282,7 @@ def request_pin(
prompt: str,
subprompt: str,
allow_cancel: bool = True,
warning: str | None = None,
wrong_pin: bool = False,
) -> str | object:
"""Request pin on device."""
@ -338,7 +339,7 @@ def request_number(
count: int,
min_count: int,
max_count: int,
description: Callable[[int], str],
description: Callable[[int], str] | None = None,
) -> object:
"""Number input with + and - buttons, description, and info button."""

@ -20,7 +20,7 @@ def can_lock_device() -> bool:
async def request_pin(
ctx: GenericContext,
prompt: str = "Enter your PIN",
prompt: str,
attempts_remaining: int | None = None,
allow_cancel: bool = True,
) -> str:
@ -48,7 +48,7 @@ async def _pin_mismatch() -> None:
async def request_pin_and_sd_salt(
ctx: Context, prompt: str = "Enter your PIN", allow_cancel: bool = True
ctx: Context, prompt: str, allow_cancel: bool = True
) -> tuple[str, bytearray | None]:
if config.has_pin():
pin = await request_pin(ctx, prompt, config.get_pin_rem(), allow_cancel)
@ -68,7 +68,7 @@ def _set_last_unlock_time() -> None:
async def verify_user_pin(
ctx: GenericContext = wire.DUMMY_CONTEXT,
prompt: str = "Enter your PIN",
prompt: str = "Enter PIN",
allow_cancel: bool = True,
retry: bool = True,
cache_time_ms: int = 0,
@ -110,7 +110,7 @@ async def verify_user_pin(
while retry:
pin = await request_pin_on_device( # type: ignore ["request_pin_on_device" is possibly unbound]
ctx, "Wrong PIN, enter again", config.get_pin_rem(), allow_cancel
ctx, "Enter PIN", config.get_pin_rem(), allow_cancel, wrong_pin=True
)
if config.unlock(pin, salt):
_set_last_unlock_time()

@ -26,7 +26,7 @@ async def change_wipe_code(ctx: Context, msg: ChangeWipeCode) -> Success:
await _require_confirm_action(ctx, msg, has_wipe_code)
# Get the unlocking PIN.
pin, salt = await request_pin_and_sd_salt(ctx)
pin, salt = await request_pin_and_sd_salt(ctx, "Enter PIN")
if not msg.remove:
# Pre-check the entered PIN.

@ -69,7 +69,36 @@ async def _confirm_word(
return selected_word == checked_word
async def _confirm_share_words(
async def _share_words_confirmed(
ctx: GenericContext,
share_index: int | None,
share_words: Sequence[str],
num_of_shares: int | None = None,
group_index: int | None = None,
) -> bool:
"""Shows initial dialog asking the user to select words, then presents
word selectors. Shows success popup if the user is done, failure if the confirmation
went wrong.
Return true if the words are confirmed successfully.
"""
# TODO: confirm_action("Select the words bla bla")
if await _do_confirm_share_words(ctx, share_index, share_words, group_index):
await _show_confirmation_success(
ctx,
share_index,
num_of_shares,
group_index,
)
return True
else:
await _show_confirmation_failure(ctx)
return False
async def _do_confirm_share_words(
ctx: GenericContext,
share_index: int | None,
share_words: Sequence[str],
@ -119,9 +148,7 @@ async def _show_confirmation_success(
return await show_success(ctx, "success_recovery", text, subheader)
async def _show_confirmation_failure(
ctx: GenericContext, share_index: int | None
) -> None:
async def _show_confirmation_failure(ctx: GenericContext) -> None:
from trezor.ui.layouts import show_warning
await show_warning(
@ -160,11 +187,8 @@ async def bip39_show_and_confirm_mnemonic(ctx: GenericContext, mnemonic: str) ->
await show_share_words(ctx, words)
# make the user confirm some words from the mnemonic
if await _confirm_share_words(ctx, None, words):
await _show_confirmation_success(ctx)
if await _share_words_confirmed(ctx, None, words):
break # this share is confirmed, go to next one
else:
await _show_confirmation_failure(ctx, None)
# SLIP39
@ -184,11 +208,8 @@ async def slip39_basic_show_and_confirm_shares(
await show_share_words(ctx, share_words, index)
# make the user confirm words from the share
if await _confirm_share_words(ctx, index, share_words):
await _show_confirmation_success(ctx, index, len(shares))
if await _share_words_confirmed(ctx, index, share_words, len(shares)):
break # this share is confirmed, go to next one
else:
await _show_confirmation_failure(ctx, index)
async def slip39_advanced_show_and_confirm_shares(
@ -205,15 +226,7 @@ async def slip39_advanced_show_and_confirm_shares(
await show_share_words(ctx, share_words, share_index, group_index)
# make the user confirm words from the share
if await _confirm_share_words(
ctx, share_index, share_words, group_index
if await _share_words_confirmed(
ctx, share_index, share_words, len(group), group_index
):
await _show_confirmation_success(
ctx,
share_index,
len(group),
group_index,
)
break # this share is confirmed, go to next one
else:
await _show_confirmation_failure(ctx, share_index)

@ -65,15 +65,15 @@ async def confirm_action(
description: str | None = None,
description_param: str | None = None,
description_param_font: int = ui.BOLD,
verb: str | bytes | None = "OK",
verb_cancel: str | bytes | None = "cancel",
verb: str = "CONFIRM",
verb_cancel: str | None = None,
hold: bool = False,
reverse: bool = False,
exc: ExceptionType = wire.ActionCancelled,
br_code: ButtonRequestType = ButtonRequestType.Other,
) -> None:
if isinstance(verb, bytes) or isinstance(verb_cancel, bytes):
raise NotImplementedError
if verb_cancel is not None:
verb_cancel = verb_cancel.upper()
if description is not None and description_param is not None:
if description_param_font != ui.BOLD:

@ -211,19 +211,15 @@ async def confirm_action(
description: str | None = None,
description_param: str | None = None,
description_param_font: int = ui.BOLD,
verb: str | bytes | None = "CONFIRM",
verb_cancel: str | bytes | None = None,
verb: str = "CONFIRM",
verb_cancel: str | None = None,
hold: bool = False,
hold_danger: bool = False,
reverse: bool = False,
exc: ExceptionType = ActionCancelled,
br_code: ButtonRequestType = BR_TYPE_OTHER,
) -> None:
if isinstance(verb, bytes) or isinstance(verb_cancel, bytes):
raise NotImplementedError
if isinstance(verb, str):
verb = verb.upper()
if isinstance(verb_cancel, str):
if verb_cancel is not None:
verb_cancel = verb_cancel.upper()
if description is not None and description_param is not None:
@ -239,7 +235,7 @@ async def confirm_action(
title=title.upper(),
action=action,
description=description,
verb=verb,
verb=verb.upper(),
verb_cancel=verb_cancel,
hold=hold,
hold_danger=hold_danger,
@ -1087,20 +1083,17 @@ async def request_pin_on_device(
prompt: str,
attempts_remaining: int | None,
allow_cancel: bool,
wrong_pin: bool = False,
) -> str:
from trezor.wire import PinCancelled
await button_request(ctx, "pin_device", code=ButtonRequestType.PinEntry)
warning = "Wrong PIN" if "Wrong" in prompt else None
if attempts_remaining is None:
subprompt = ""
elif attempts_remaining == 1:
prompt = "Enter PIN"
subprompt = "Last attempt"
else:
prompt = "Enter PIN"
subprompt = f"{attempts_remaining} tries left"
dialog = RustLayout(
@ -1108,7 +1101,7 @@ async def request_pin_on_device(
prompt=prompt,
subprompt=subprompt,
allow_cancel=allow_cancel,
warning=warning,
wrong_pin=wrong_pin,
)
)
while True:

@ -1605,13 +1605,13 @@
"TT_test_msg_backup_device.py::test_no_backup_fails": "8d9a56256a6f45c58a3599580ae5c794b3ae4df7f9a9a716b84e584b54f5f83e",
"TT_test_msg_backup_device.py::test_no_backup_show_entropy_fails": "ab6fabda008f503c52c6ecde6b1c1b67505b9153c86320409b2d1275b3c3edad",
"TT_test_msg_change_wipe_code_t2.py::test_set_pin_to_wipe_code": "112c9320dc8c9176a361ba6f75898db94009eeab9d6886399a6f8a36c059dbc2",
"TT_test_msg_change_wipe_code_t2.py::test_set_remove_wipe_code": "32dc8d666f70ac010e236390a884d19468fcf62a58a008b4575a50221afd8aeb",
"TT_test_msg_change_wipe_code_t2.py::test_set_remove_wipe_code": "63664da599b20011a1d8350bffbc0f7c6b00e31021b050b4f7471746b9ec7475",
"TT_test_msg_change_wipe_code_t2.py::test_set_wipe_code_mismatch": "fd9742681596078c36d9c900cc146b1bc8e9dea20339f3b62f54374c78a3ba3e",
"TT_test_msg_change_wipe_code_t2.py::test_set_wipe_code_to_pin": "4c0617640571bb57a314aed5889fd1bbd0d3192b2b060eef7d3cdb9a3a904676",
"TT_test_msg_changepin_t2.py::test_change_failed": "6fbb9b62964f5321039c3634e575e26aed9486789de71eca64fc2941085e4a89",
"TT_test_msg_changepin_t2.py::test_change_invalid_current": "f4fdb1ac1778c55a970edc8a3a3708edd5e3c648b65f21eee17553d1fd6c763e",
"TT_test_msg_changepin_t2.py::test_change_pin": "4deb4d51580c004fe3be827a5cc5ae645a2abc1c9292e84353f91ec150bce687",
"TT_test_msg_changepin_t2.py::test_remove_pin": "bf61f8f1dfc29333e1a647a8340ea1b0538605b32311d0474a1ed3d361e57625",
"TT_test_msg_change_wipe_code_t2.py::test_set_wipe_code_to_pin": "fae7f7a7264dfe78e481d2c4fb5d8f3424213a8a467ee868d73a626c2f001304",
"TT_test_msg_changepin_t2.py::test_change_failed": "26a276353c6a131b7a5c841542b8a438b8cf4576e5576012fb8a2f03fcf16298",
"TT_test_msg_changepin_t2.py::test_change_invalid_current": "5bee6bd2434e8aa8ff00f91f0465e287b2a744f04985254c02b26d222ca69d15",
"TT_test_msg_changepin_t2.py::test_change_pin": "52b8a72b684558aedbeb9ea7d5e5e75fc14597499e789eb4bd7d541bd042beba",
"TT_test_msg_changepin_t2.py::test_remove_pin": "ed7c497fec840a33a92845661f594855ede3808d46b576f912968d1883905877",
"TT_test_msg_changepin_t2.py::test_set_failed": "8804b4cdf72f2e8333cedf2b3e863fdbee24c7b0b7116c9adc27378e4b1c3464",
"TT_test_msg_changepin_t2.py::test_set_pin": "7196f9822c322ea5a7836eeb6b36f52d6d8517ede89d1e4792ea112344715e01",
"TT_test_msg_loaddevice.py::test_load_device_1": "aa580b991d4859ab2e84b7519338de465dc191ee339dffd7b2183717ede9847e",
@ -1634,7 +1634,7 @@
"TT_test_pin.py::test_incorrect_pin_t2": "f7518258f2c344043c7e34ec3d942d6376b5786216bd29e77ace063cc16cfd66",
"TT_test_pin.py::test_no_protection": "e0db5107ba371eb8d7039e6ad3138f6bbb731c779f405b75c2e14128dfad756f",
"TT_test_protection_levels.py::test_apply_settings": "a76f90db9f514d6615b4c46409d3c43bc0c39b632d465ec37e11a5da35e9910b",
"TT_test_protection_levels.py::test_change_pin_t2": "e6f6e197893d22381d78fb929922fda66e110508db02e3e55197900f8608e166",
"TT_test_protection_levels.py::test_change_pin_t2": "97e51fae7e0bc42de8faafd00ecccc75d081e091012072a0d9cdd0182d8dff43",
"TT_test_protection_levels.py::test_get_address": "07b42309dd05c92fb44e74b2a916316b3d21d253503e19780ed21a4b608c657d",
"TT_test_protection_levels.py::test_get_entropy": "e404845c835f332df06e03b1d848771d2852356ce41ee6eab0827a0d8b8ab912",
"TT_test_protection_levels.py::test_get_public_key": "07b42309dd05c92fb44e74b2a916316b3d21d253503e19780ed21a4b608c657d",
@ -1650,7 +1650,7 @@
"TT_test_protection_levels.py::test_wipe_device": "fb5c6f84c198b2ac405c03005e5dc2de13092c85c36433af5cde2dc8c5a50f2d",
"TT_test_sdcard.py::test_sd_format": "a9ff5054ca7b1db85bf082e194794d9999527de809d77aacb49da99b8edd9c19",
"TT_test_sdcard.py::test_sd_no_format": "fd63178ef232fba05690e41ea9f99a1bc5ead8911c1217e78c5908a662d9636b",
"TT_test_sdcard.py::test_sd_protect_unlock": "74c0112bb0e1b0a86be5809a27814a164df5d00a1bf71ee2a9323dc61a361346",
"TT_test_sdcard.py::test_sd_protect_unlock": "44c56d087139dcc15617c15f71cce18ca66e5671c7729f9090c12f807fb6549c",
"TT_test_session.py::test_cannot_resume_ended_session": "e0db5107ba371eb8d7039e6ad3138f6bbb731c779f405b75c2e14128dfad756f",
"TT_test_session.py::test_clear_session": "2c16b2eb8ba4ab314456b3548aa104b3498ce1443cb4a1b217ee6c5efa7f450e",
"TT_test_session.py::test_derive_cardano_empty_session": "e0db5107ba371eb8d7039e6ad3138f6bbb731c779f405b75c2e14128dfad756f",

Loading…
Cancel
Save