1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-09 23:11:10 +00:00

refactor(core): improve recovery_enter_share

This commit is contained in:
matejcik 2023-11-20 11:58:33 +01:00 committed by matejcik
parent 82290c2e5c
commit cd25071a29
9 changed files with 64 additions and 33 deletions

View File

@ -657,6 +657,7 @@ static void _librust_qstrs(void) {
MP_QSTR_show_homescreen; MP_QSTR_show_homescreen;
MP_QSTR_show_info; MP_QSTR_show_info;
MP_QSTR_show_info_with_cancel; MP_QSTR_show_info_with_cancel;
MP_QSTR_show_instructions;
MP_QSTR_show_lockscreen; MP_QSTR_show_lockscreen;
MP_QSTR_show_mismatch; MP_QSTR_show_mismatch;
MP_QSTR_show_passphrase; MP_QSTR_show_passphrase;

View File

@ -1457,11 +1457,11 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let recovery_type: RecoveryType = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?; let recovery_type: RecoveryType = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?;
let show_info: bool = kwargs.get(Qstr::MP_QSTR_show_info)?.try_into()?; let show_instructions: bool = kwargs.get(Qstr::MP_QSTR_show_instructions)?.try_into()?;
let mut paragraphs = ParagraphVecShort::new(); let mut paragraphs = ParagraphVecShort::new();
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, description)); paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, description));
if show_info { if show_instructions {
paragraphs paragraphs
.add(Paragraph::new( .add(Paragraph::new(
&theme::TEXT_NORMAL, &theme::TEXT_NORMAL,
@ -2048,7 +2048,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// button: str, /// button: str,
/// recovery_type: RecoveryType, /// recovery_type: RecoveryType,
/// info_button: bool, # unused on TR /// info_button: bool, # unused on TR
/// show_info: bool, /// show_instructions: bool,
/// ) -> LayoutObj[UiResult]: /// ) -> LayoutObj[UiResult]:
/// """Device recovery homescreen.""" /// """Device recovery homescreen."""
Qstr::MP_QSTR_confirm_recovery => obj_fn_kw!(0, new_confirm_recovery).as_obj(), Qstr::MP_QSTR_confirm_recovery => obj_fn_kw!(0, new_confirm_recovery).as_obj(),

View File

@ -2100,6 +2100,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// button: str, /// button: str,
/// recovery_type: RecoveryType, /// recovery_type: RecoveryType,
/// info_button: bool = False, /// info_button: bool = False,
/// show_instructions: bool = False, # unused on TT
/// ) -> LayoutObj[UiResult]: /// ) -> LayoutObj[UiResult]:
/// """Device recovery homescreen.""" /// """Device recovery homescreen."""
Qstr::MP_QSTR_confirm_recovery => obj_fn_kw!(0, new_confirm_recovery).as_obj(), Qstr::MP_QSTR_confirm_recovery => obj_fn_kw!(0, new_confirm_recovery).as_obj(),

View File

@ -972,7 +972,7 @@ def confirm_recovery(
button: str, button: str,
recovery_type: RecoveryType, recovery_type: RecoveryType,
info_button: bool, # unused on TR info_button: bool, # unused on TR
show_info: bool, show_instructions: bool,
) -> LayoutObj[UiResult]: ) -> LayoutObj[UiResult]:
"""Device recovery homescreen.""" """Device recovery homescreen."""
@ -1542,6 +1542,7 @@ def confirm_recovery(
button: str, button: str,
recovery_type: RecoveryType, recovery_type: RecoveryType,
info_button: bool = False, info_button: bool = False,
show_instructions: bool = False, # unused on TT
) -> LayoutObj[UiResult]: ) -> LayoutObj[UiResult]:
"""Device recovery homescreen.""" """Device recovery homescreen."""

View File

@ -275,20 +275,18 @@ async def _request_share_first_screen(
button_label, button_label,
text, text,
TR.recovery__word_count_template.format(word_count), TR.recovery__word_count_template.format(word_count),
show_info=True, show_instructions=True,
) )
else: # BIP-39 else: # BIP-39
await layout.homescreen_dialog( await layout.homescreen_dialog(
TR.buttons__continue, TR.buttons__continue,
TR.recovery__enter_backup, TR.recovery__enter_backup,
TR.recovery__word_count_template.format(word_count), TR.recovery__word_count_template.format(word_count),
show_info=True, show_instructions=True,
) )
async def _request_share_next_screen() -> None: async def _request_share_next_screen() -> None:
from trezor import strings
remaining = storage_recovery.fetch_slip39_remaining_shares() remaining = storage_recovery.fetch_slip39_remaining_shares()
group_count = storage_recovery.get_slip39_group_count() group_count = storage_recovery.get_slip39_group_count()
if not remaining: if not remaining:
@ -296,25 +294,12 @@ async def _request_share_next_screen() -> None:
raise RuntimeError raise RuntimeError
if group_count > 1: if group_count > 1:
await layout.homescreen_dialog( await layout.enter_share(
TR.buttons__enter, remaining_shares_info=_get_remaining_groups_and_shares()
TR.recovery__more_shares_needed,
remaining_shares_info=_get_remaining_groups_and_shares(),
) )
else: else:
still_needed_shares = remaining[0] entered = len(storage_recovery_shares.fetch_group(0))
already_entered_shares = len(storage_recovery_shares.fetch_group(0)) await layout.enter_share(entered_remaining=(entered, remaining[0]))
overall_needed = still_needed_shares + already_entered_shares
# TODO: consider kwargs in format here
entered = TR.recovery__x_of_y_entered_template.format(
already_entered_shares, overall_needed
)
needed = strings.format_plural(
TR.recovery__x_more_shares_needed_template_plural,
still_needed_shares,
TR.plurals__x_shares_needed,
)
await layout.homescreen_dialog(TR.buttons__enter_share, entered, needed)
def _get_remaining_groups_and_shares() -> "RemainingSharesInfo": def _get_remaining_groups_and_shares() -> "RemainingSharesInfo":

View File

@ -11,6 +11,8 @@ from trezor.ui.layouts.recovery import ( # noqa: F401
from apps.common import backup_types from apps.common import backup_types
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Awaitable, Callable
from trezor.enums import BackupType from trezor.enums import BackupType
# RemainingSharesInfo represents the data structure for remaining shares in SLIP-39 recovery: # RemainingSharesInfo represents the data structure for remaining shares in SLIP-39 recovery:
@ -123,11 +125,52 @@ async def show_invalid_mnemonic(word_count: int) -> None:
) )
def enter_share(
word_count: int | None = None,
entered_remaining: tuple[int, int] | None = None,
remaining_shares_info: RemainingSharesInfo | None = None,
) -> Awaitable[None]:
from trezor import strings
show_instructions = False
if word_count is not None:
# First-time entry. Show instructions and word count.
text = TR.recovery__enter_any_share
subtext = TR.recovery__word_count_template.format(word_count)
show_instructions = True
elif entered_remaining is not None:
# Basic Shamir. There is only one group, we report entered/remaining count.
entered, remaining = entered_remaining
total = entered + remaining
text = TR.recovery__x_of_y_entered_template.format(entered, total)
subtext = strings.format_plural(
TR.recovery__x_more_shares_needed_template_plural,
remaining,
TR.plurals__x_shares_needed,
)
else:
# SuperShamir. We cannot easily show entered/remaining across groups,
# the caller provided an info_func that has the details.
text = TR.recovery__more_shares_needed
subtext = None
return homescreen_dialog(
TR.buttons__enter_share,
text,
subtext,
show_instructions,
remaining_shares_info,
)
async def homescreen_dialog( async def homescreen_dialog(
button_label: str, button_label: str,
text: str, text: str,
subtext: str | None = None, subtext: str | None = None,
show_info: bool = False, show_instructions: bool = False,
remaining_shares_info: "RemainingSharesInfo | None" = None, remaining_shares_info: "RemainingSharesInfo | None" = None,
) -> None: ) -> None:
import storage.recovery as storage_recovery import storage.recovery as storage_recovery
@ -141,7 +184,7 @@ async def homescreen_dialog(
text, text,
subtext, subtext,
recovery_type, recovery_type,
show_info, show_instructions,
remaining_shares_info, remaining_shares_info,
): ):
raise RecoveryAborted raise RecoveryAborted

View File

@ -102,12 +102,12 @@ async def continue_recovery(
text: str, text: str,
subtext: str | None, subtext: str | None,
recovery_type: RecoveryType, recovery_type: RecoveryType,
show_info: bool = False, show_instructions: bool = False,
remaining_shares_info: "RemainingSharesInfo | None" = None, remaining_shares_info: "RemainingSharesInfo | None" = None,
) -> bool: ) -> bool:
result = await interact( result = await interact(
trezorui2.flow_continue_recovery( trezorui2.flow_continue_recovery(
first_screen=show_info, first_screen=show_instructions,
recovery_type=recovery_type, recovery_type=recovery_type,
text=text, text=text,
subtext=subtext, subtext=subtext,

View File

@ -106,7 +106,7 @@ async def continue_recovery(
text: str, text: str,
subtext: str | None, subtext: str | None,
recovery_type: RecoveryType, recovery_type: RecoveryType,
show_info: bool = False, show_instructions: bool = False,
remaining_shares_info: "RemainingSharesInfo | None" = None, # unused on TR remaining_shares_info: "RemainingSharesInfo | None" = None, # unused on TR
) -> bool: ) -> bool:
# TODO: implement info_func? # TODO: implement info_func?
@ -117,7 +117,7 @@ async def continue_recovery(
# Never showing info for dry-run, user already saw it and it is disturbing # Never showing info for dry-run, user already saw it and it is disturbing
if recovery_type in (RecoveryType.DryRun, RecoveryType.UnlockRepeatedBackup): if recovery_type in (RecoveryType.DryRun, RecoveryType.UnlockRepeatedBackup):
show_info = False show_instructions = False
if subtext: if subtext:
text += f"\n\n{subtext}" text += f"\n\n{subtext}"
@ -128,7 +128,7 @@ async def continue_recovery(
button=button_label, button=button_label,
recovery_type=recovery_type, recovery_type=recovery_type,
info_button=False, info_button=False,
show_info=show_info, # type: ignore [No parameter named "show_info"] show_instructions=show_instructions,
) )
while True: while True:
result = await interact( result = await interact(

View File

@ -133,7 +133,7 @@ async def continue_recovery(
text: str, text: str,
subtext: str | None, subtext: str | None,
recovery_type: RecoveryType, recovery_type: RecoveryType,
show_info: bool = False, show_instructions: bool = False,
remaining_shares_info: "RemainingSharesInfo | None" = None, remaining_shares_info: "RemainingSharesInfo | None" = None,
) -> bool: ) -> bool:
from trezor.enums import RecoveryType from trezor.enums import RecoveryType