fixup! fixup! chore(core): disallow repeated backup for BIP39

Ioan Bizău 4 weeks ago
parent f2a344aa4c
commit af5fd845cf

@ -1432,10 +1432,10 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
let title = if dry_run {
TR::recovery__title_dry_run
} else if unlock_repeated_backup {
TR::recovery__title_unlock_repeated_backup.try_into()?
TR::recovery__title_unlock_repeated_backup
} else {
TR::recovery__title
};
}.try_into()?;
content_in_button_page(
title.try_into()?,

@ -1390,7 +1390,9 @@ 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 button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?;
let unlock_repeated_backup: bool = kwargs.get(Qstr::MP_QSTR_unlock_repeated_backup)?.try_into()?;
let unlock_repeated_backup: bool = kwargs
.get(Qstr::MP_QSTR_unlock_repeated_backup)?
.try_into()?;
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?;
let paragraphs = Paragraphs::new([
@ -1400,12 +1402,12 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
.with_spacing(theme::RECOVERY_SPACING);
let notification: TString = if dry_run {
TR::recovery__title_dry_run.try_into()?
TR::recovery__title_dry_run
} else if unlock_repeated_backup {
TR::recovery__title_unlock_repeated_backup.try_into()?
TR::recovery__title_unlock_repeated_backup
} else {
TR::recovery__title.try_into()?
};
TR::recovery__title
}.try_into()?;
let obj = if info_button {
LayoutObj::new(Frame::left_aligned(

@ -57,7 +57,10 @@ def confirm_recovery(debug: "DebugLink", title: str = "recovery__title") -> None
def select_number_of_words(
debug: "DebugLink", num_of_words: int = 20, wait: bool = True
debug: "DebugLink",
num_of_words: int = 20,
wait: bool = True,
unlock_repeated_backup=False,
) -> None:
if wait:
debug.wait_layout()
@ -84,16 +87,21 @@ def select_number_of_words(
else:
raise ValueError("Unknown model")
if num_of_words in (20, 33):
if unlock_repeated_backup:
TR.assert_in(layout.text_content(), "recovery__enter_backup")
elif num_of_words in (20, 33):
TR.assert_in(layout.text_content(), "recovery__enter_any_share")
else:
else: # BIP-39
TR.assert_in(layout.text_content(), "recovery__enter_backup")
def enter_share(
debug: "DebugLink", share: str, is_first: bool = True
debug: "DebugLink",
share: str,
is_first: bool = True,
before_title: str = "recovery__title_recover",
) -> "LayoutContent":
TR.assert_in(debug.read_layout().title(), "recovery__title_recover")
TR.assert_in(debug.read_layout().title(), before_title)
if debug.model in (models.T2B1,):
layout = debug.wait_layout()
for _ in range(layout.page_count()):
@ -112,11 +120,15 @@ def enter_share(
def enter_shares(
debug: "DebugLink",
shares: list[str],
enter_share_before_title: str = "recovery__title_recover",
text: str = "recovery__enter_any_share",
after_layout_text: str = "recovery__wallet_recovered",
) -> None:
TR.assert_in(debug.read_layout().text_content(), "recovery__enter_any_share")
TR.assert_in(debug.read_layout().text_content(), text)
for index, share in enumerate(shares):
enter_share(debug, share, is_first=index == 0)
enter_share(
debug, share, is_first=index == 0, before_title=enter_share_before_title
)
if index < len(shares) - 1:
TR.assert_in(
debug.read_layout().text_content(),

@ -107,12 +107,12 @@ def test_repeated_backup(
recovery.confirm_recovery(debug, "recovery__title_unlock_repeated_backup")
recovery.select_number_of_words(debug, num_of_words=20)
recovery.select_number_of_words(debug, num_of_words=20, unlock_repeated_backup=True)
recovery.enter_seed(
debug,
initial_backup_1_of_1,
True,
"recovery__enter_any_share",
"recovery__enter_backup",
"recovery__unlock_repeated_backup",
)
@ -184,9 +184,13 @@ def test_repeated_backup(
recovery.confirm_recovery(debug, "recovery__title_unlock_repeated_backup")
# ... this time with the 2 shares from the *new* backup, which was a 2-of-3!
recovery.select_number_of_words(debug, num_of_words=20)
recovery.select_number_of_words(debug, num_of_words=20, unlock_repeated_backup=True)
recovery.enter_shares(
debug, second_backup_2_of_3[-2:], "recovery__unlock_repeated_backup"
debug,
second_backup_2_of_3[-2:],
"recovery__title_unlock_repeated_backup",
"recovery__enter_backup",
"recovery__unlock_repeated_backup",
)
assert device_handler.result().message == "Backup unlocked"

@ -47,7 +47,9 @@ def test_repeated_backup(client: Client):
# unlock repeated backup by entering 3 of the 5 shares we have got
with client:
IF = InputFlowSlip39BasicRecoveryDryRun(client, mnemonics[:3])
IF = InputFlowSlip39BasicRecoveryDryRun(
client, mnemonics[:3], unlock_repeated_backup=True
)
client.set_input_flow(IF.get())
ret = device.recover(
client, recovery_kind=messages.RecoveryKind.UnlockRepeatedBackup

@ -1800,15 +1800,25 @@ class InputFlowSlip39AdvancedRecoveryShareAlreadyEntered(InputFlowBase):
class InputFlowSlip39BasicRecoveryDryRun(InputFlowBase):
def __init__(self, client: Client, shares: list[str], mismatch: bool = False):
def __init__(
self,
client: Client,
shares: list[str],
mismatch: bool = False,
unlock_repeated_backup=False,
):
super().__init__(client)
self.shares = shares
self.mismatch = mismatch
self.unlock_repeated_backup = unlock_repeated_backup
self.word_count = len(shares[0].split(" "))
def input_flow_common(self) -> BRGeneratorType:
yield from self.REC.confirm_dry_run()
yield from self.REC.setup_slip39_recovery(self.word_count)
if self.unlock_repeated_backup:
yield from self.REC.setup_repeated_backup_recovery(self.word_count)
else:
yield from self.REC.setup_slip39_recovery(self.word_count)
yield from self.REC.input_all_slip39_shares(self.shares)
if self.mismatch:
yield from self.REC.warning_slip39_dryrun_mismatch()

@ -71,6 +71,12 @@ class RecoveryFlow:
yield from self.input_number_of_words(num_words)
yield from self.enter_any_share()
def setup_repeated_backup_recovery(self, num_words: int) -> BRGeneratorType:
if self.client.model is models.T2B1:
yield from self.tr_recovery_homescreen()
yield from self.input_number_of_words(num_words)
yield from self.enter_your_backup()
def setup_bip39_recovery(self, num_words: int) -> BRGeneratorType:
if self.client.model is models.T2B1:
yield from self.tr_recovery_homescreen()

Loading…
Cancel
Save