From ed584098882746a8357f916bce74be7a636ea85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ioan=20Biz=C4=83u?= Date: Tue, 4 Jun 2024 12:47:09 +0200 Subject: [PATCH] chore(core): update tests --- core/embed/rust/librust_qstr.h | 1 - .../embed/rust/src/ui/model_mercury/layout.rs | 21 ++--- core/mocks/generated/trezorui2.pyi | 4 +- core/src/apps/base.py | 4 +- .../management/recovery_device/homescreen.py | 3 +- .../src/trezor/ui/layouts/mercury/recovery.py | 10 +-- tests/click_tests/recovery.py | 24 +++-- tests/click_tests/reset.py | 9 +- .../click_tests/test_backup_slip39_custom.py | 2 +- tests/click_tests/test_recovery.py | 8 +- tests/click_tests/test_repeated_backup.py | 13 ++- tests/device_tests/test_repeated_backup.py | 90 ++++++++++++++++++- tests/ui_tests/fixtures.json | 54 +++++++++-- 13 files changed, 200 insertions(+), 43 deletions(-) diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h index 17dbfa03b4..ece0cbd029 100644 --- a/core/embed/rust/librust_qstr.h +++ b/core/embed/rust/librust_qstr.h @@ -212,7 +212,6 @@ static void _librust_qstrs(void) { MP_QSTR_device_name__change_template; MP_QSTR_device_name__title; MP_QSTR_disable_animation; - MP_QSTR_dry_run; MP_QSTR_encode; MP_QSTR_encoded_length; MP_QSTR_entropy__send; diff --git a/core/embed/rust/src/ui/model_mercury/layout.rs b/core/embed/rust/src/ui/model_mercury/layout.rs index 76e1f3e246..0f6c920cd3 100644 --- a/core/embed/rust/src/ui/model_mercury/layout.rs +++ b/core/embed/rust/src/ui/model_mercury/layout.rs @@ -488,6 +488,9 @@ impl ConfirmBlobParams { } } +const RECOVERY_TYPE_DRY_RUN: u32 = 1; +const RECOVERY_TYPE_UNLOCK_REPEATED_BACKUP: u32 = 2; + extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; @@ -1250,15 +1253,15 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut let _title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; 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 recovery_type: u32 = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?; let _info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?; let paragraphs = Paragraphs::new([Paragraph::new(&theme::TEXT_NORMAL, description)]); - let notification: TString = if dry_run { - TR::recovery__title_dry_run.into() - } else { - TR::recovery__title.into() + let notification = match recovery_type { + RECOVERY_TYPE_DRY_RUN => TR::recovery__title_dry_run.into(), + RECOVERY_TYPE_UNLOCK_REPEATED_BACKUP => TR::recovery__title_dry_run.into(), + _ => TR::recovery__title.into(), }; let content = SwipeUpScreen::new(paragraphs); @@ -1274,10 +1277,8 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { - let _dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?; - let obj = LayoutObj::new(Frame::left_aligned( - TR::recovery__select_num_of_words.into(), + TR::recovery__num_of_words.into(), SelectWordCount::new(), ))?; Ok(obj.into()) @@ -1903,7 +1904,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// title: str, /// description: str, /// button: str, - /// dry_run: bool, + /// recovery_type: RecoveryType, /// info_button: bool = False, /// ) -> LayoutObj[UiResult]: /// """Device recovery homescreen.""" @@ -1911,7 +1912,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// def select_word_count( /// *, - /// dry_run: bool, + /// recovery_type: RecoveryType, /// ) -> LayoutObj[int | str]: # TT returns int /// """Select mnemonic word count from (12, 18, 20, 24, 33).""" Qstr::MP_QSTR_select_word_count => obj_fn_kw!(0, new_select_word_count).as_obj(), diff --git a/core/mocks/generated/trezorui2.pyi b/core/mocks/generated/trezorui2.pyi index ddb7c3c70d..f58b64cce9 100644 --- a/core/mocks/generated/trezorui2.pyi +++ b/core/mocks/generated/trezorui2.pyi @@ -449,7 +449,7 @@ def confirm_recovery( title: str, description: str, button: str, - dry_run: bool, + recovery_type: RecoveryType, info_button: bool = False, ) -> LayoutObj[UiResult]: """Device recovery homescreen.""" @@ -458,7 +458,7 @@ def confirm_recovery( # rust/src/ui/model_mercury/layout.rs def select_word_count( *, - dry_run: bool, + recovery_type: RecoveryType, ) -> LayoutObj[int | str]: # TT returns int """Select mnemonic word count from (12, 18, 20, 24, 33).""" diff --git a/core/src/apps/base.py b/core/src/apps/base.py index f8779a0d90..36de3a71e5 100644 --- a/core/src/apps/base.py +++ b/core/src/apps/base.py @@ -352,6 +352,8 @@ async def handle_CancelAuthorization(msg: CancelAuthorization) -> protobuf.Messa def set_homescreen() -> None: import storage.recovery as storage_recovery + from apps.common import backup + set_default = workflow.set_default # local_cache_attribute if storage_cache.is_set(storage_cache.APP_COMMON_BUSY_DEADLINE_MS): @@ -369,7 +371,7 @@ def set_homescreen() -> None: set_default(screensaver, restart=True) - elif storage_recovery.is_in_progress(): + elif storage_recovery.is_in_progress() or backup.repeated_backup_enabled(): from apps.management.recovery_device.homescreen import recovery_homescreen set_default(recovery_homescreen) diff --git a/core/src/apps/management/recovery_device/homescreen.py b/core/src/apps/management/recovery_device/homescreen.py index 68eb7891d6..3455ccab77 100644 --- a/core/src/apps/management/recovery_device/homescreen.py +++ b/core/src/apps/management/recovery_device/homescreen.py @@ -21,7 +21,6 @@ async def recovery_homescreen() -> None: from apps.homescreen import homescreen if backup.repeated_backup_enabled(): - storage_recovery.end_progress() await _continue_repeated_backup() elif not storage_recovery.is_in_progress(): workflow.set_default(homescreen) @@ -208,6 +207,8 @@ async def _finish_recovery_unlock_repeated_backup( result = _check_secret_against_stored_secret(secret, is_slip39, backup_type) + storage_recovery.end_progress() + if result: backup.activate_repeated_backup() return Success(message="Backup unlocked") diff --git a/core/src/trezor/ui/layouts/mercury/recovery.py b/core/src/trezor/ui/layouts/mercury/recovery.py index f49ef08f45..89d411b7b8 100644 --- a/core/src/trezor/ui/layouts/mercury/recovery.py +++ b/core/src/trezor/ui/layouts/mercury/recovery.py @@ -2,7 +2,7 @@ from typing import Callable, Iterable import trezorui2 from trezor import TR -from trezor.enums import ButtonRequestType +from trezor.enums import ButtonRequestType, RecoveryType from ..common import interact from . import RustLayout, raise_if_not_confirmed @@ -25,8 +25,8 @@ async def _is_confirmed_info( return result is CONFIRMED -async def request_word_count(dry_run: bool) -> int: - selector = RustLayout(trezorui2.select_word_count(dry_run=dry_run)) +async def request_word_count(recovery_type: RecoveryType) -> int: + selector = RustLayout(trezorui2.select_word_count(recovery_type=recovery_type)) count = await interact(selector, "word_count", ButtonRequestType.MnemonicWordCount) return int(count) @@ -116,7 +116,7 @@ async def continue_recovery( text: str, subtext: str | None, info_func: Callable | None, - dry_run: bool, + recovery_type: RecoveryType, show_info: bool = False, # unused on TT ) -> bool: from ..common import button_request @@ -133,7 +133,7 @@ async def continue_recovery( description=description, button=button_label, info_button=info_func is not None, - dry_run=dry_run, + recovery_type=recovery_type, ) ) diff --git a/tests/click_tests/recovery.py b/tests/click_tests/recovery.py index 3f46fede21..c6e31027bc 100644 --- a/tests/click_tests/recovery.py +++ b/tests/click_tests/recovery.py @@ -105,11 +105,18 @@ def select_number_of_words( raise ValueError("Unknown model") if unlock_repeated_backup: - TR.assert_in(layout.text_content(), "recovery__enter_backup") + if debug.model in (models.T2B1,): + TR.assert_in(layout.text_content(), "recovery__enter_backup") + else: + TR.assert_in(layout.text_content(), "recovery__only_first_n_letters") elif num_of_words in (20, 33): TR.assert_in_multiple( layout.text_content(), - ["recovery__enter_any_share", "recovery__only_first_n_letters"], + [ + "recovery__enter_backup", + "recovery__enter_any_share", + "recovery__only_first_n_letters", + ], ) else: # BIP-39 TR.assert_in_multiple( @@ -125,14 +132,14 @@ def enter_share( before_title: str = "recovery__title_recover", ) -> "LayoutContent": if debug.model in (models.T2B1,): - TR.assert_in(debug.read_layout().title(), "recovery__title_recover") + TR.assert_in(debug.read_layout().title(), before_title) layout = debug.wait_layout() for _ in range(layout.page_count()): layout = debug.press_right(wait=True) elif debug.model in (models.T3T1,): layout = debug.swipe_up(wait=True) else: - TR.assert_in(debug.read_layout().title(), "recovery__title_recover") + TR.assert_in(debug.read_layout().title(), before_title) layout = debug.click(buttons.OK, wait=True) assert "MnemonicKeyboard" in layout.all_components() @@ -152,7 +159,12 @@ def enter_shares( ) -> None: TR.assert_in_multiple( debug.read_layout().text_content(), - ["recovery__enter_any_share", "recovery__only_first_n_letters", text], + [ + "recovery__enter_backup", + "recovery__enter_any_share", + "recovery__only_first_n_letters", + text, + ], ) for index, share in enumerate(shares): enter_share( @@ -160,7 +172,7 @@ def enter_shares( ) if index < len(shares) - 1: # FIXME: when ui-t3t1 done for shamir, we want to check the template below - TR.assert_in(debug.read_layout().title(), "recovery__title_recover") + TR.assert_in(debug.read_layout().title(), enter_share_before_title) # TR.assert_in( # debug.read_layout().text_content(), # "recovery__x_of_y_entered_template", diff --git a/tests/click_tests/reset.py b/tests/click_tests/reset.py index ea82c538d2..475af9a2f8 100644 --- a/tests/click_tests/reset.py +++ b/tests/click_tests/reset.py @@ -41,15 +41,18 @@ def confirm_read(debug: "DebugLink", middle_r: bool = False) -> None: debug.press_right(wait=True) -def cancel_backup(debug: "DebugLink", middle_r: bool = False) -> None: +def cancel_backup( + debug: "DebugLink", middle_r: bool = False, confirm: bool = False +) -> None: if debug.model in (models.T2T1,): debug.click(buttons.CANCEL, wait=True) debug.click(buttons.CANCEL, wait=True) elif debug.model in (models.T3T1,): debug.click(buttons.CORNER_BUTTON, wait=True) debug.click(buttons.VERTICAL_MENU[0], wait=True) - debug.swipe_up(wait=True) - debug.click(buttons.TAP_TO_CONFIRM) + if confirm: + debug.swipe_up(wait=True) + debug.click(buttons.TAP_TO_CONFIRM) elif debug.model in (models.T2B1,): debug.press_left(wait=True) debug.press_left(wait=True) diff --git a/tests/click_tests/test_backup_slip39_custom.py b/tests/click_tests/test_backup_slip39_custom.py index a99f8d54da..66c0d80338 100644 --- a/tests/click_tests/test_backup_slip39_custom.py +++ b/tests/click_tests/test_backup_slip39_custom.py @@ -62,7 +62,7 @@ def test_backup_slip39_custom( reset.confirm_new_wallet(debug) # cancel back up - reset.cancel_backup(debug) + reset.cancel_backup(debug, confirm=True) assert device_handler.result() == "Initialized" diff --git a/tests/click_tests/test_recovery.py b/tests/click_tests/test_recovery.py index 537cdaed7a..eab50c2d5f 100644 --- a/tests/click_tests/test_recovery.py +++ b/tests/click_tests/test_recovery.py @@ -19,7 +19,7 @@ from typing import TYPE_CHECKING, Generator import pytest -from trezorlib import device, messages +from trezorlib import device, messages, models from ..common import MNEMONIC12, MNEMONIC_SLIP39_BASIC_20_3of6 from . import recovery @@ -54,6 +54,8 @@ def prepare_recovery_and_evaluate( def test_recovery_slip39_basic(device_handler: "BackgroundDeviceHandler"): with prepare_recovery_and_evaluate(device_handler) as debug: recovery.confirm_recovery(debug) + if debug.model is models.T2B1: + recovery.confirm_recovery(debug) recovery.select_number_of_words(debug) recovery.enter_shares(debug, MNEMONIC_SLIP39_BASIC_20_3of6) @@ -64,6 +66,8 @@ def test_recovery_slip39_basic(device_handler: "BackgroundDeviceHandler"): def test_recovery_bip39(device_handler: "BackgroundDeviceHandler"): with prepare_recovery_and_evaluate(device_handler) as debug: recovery.confirm_recovery(debug) + if debug.model is models.T2B1: + recovery.confirm_recovery(debug) recovery.select_number_of_words(debug, num_of_words=12) recovery.enter_seed(debug, MNEMONIC12.split()) @@ -74,6 +78,8 @@ def test_recovery_bip39(device_handler: "BackgroundDeviceHandler"): def test_recovery_bip39_previous_word(device_handler: "BackgroundDeviceHandler"): with prepare_recovery_and_evaluate(device_handler) as debug: recovery.confirm_recovery(debug) + if debug.model is models.T2B1: + recovery.confirm_recovery(debug) recovery.select_number_of_words(debug, num_of_words=12) seed_words: list[str] = MNEMONIC12.split() diff --git a/tests/click_tests/test_repeated_backup.py b/tests/click_tests/test_repeated_backup.py index 8361f24cb3..8568e1aff8 100644 --- a/tests/click_tests/test_repeated_backup.py +++ b/tests/click_tests/test_repeated_backup.py @@ -60,14 +60,17 @@ def test_repeated_backup( # let's make a 1-of-1 backup to start with... + assert debug.model is not None + model_name: str = debug.model.internal_name + # shares=1 - reset.set_selection(debug, buttons.RESET_MINUS, 5 - 1) + reset.set_selection(debug, buttons.reset_minus(model_name), 5 - 1) # confirm checklist reset.confirm_read(debug) # threshold=1 - reset.set_selection(debug, buttons.RESET_PLUS, 0) + reset.set_selection(debug, buttons.reset_plus(model_name), 0) # confirm checklist reset.confirm_read(debug) @@ -133,17 +136,19 @@ def test_repeated_backup( # ... so let's try to do a 2-of-3 backup + debug.wait_layout() + # confirm checklist reset.confirm_read(debug) # shares=3 - reset.set_selection(debug, buttons.RESET_MINUS, 5 - 3) + reset.set_selection(debug, buttons.reset_minus(model_name), 5 - 3) # confirm checklist reset.confirm_read(debug) # threshold=2 - reset.set_selection(debug, buttons.RESET_MINUS, 1) + reset.set_selection(debug, buttons.reset_minus(model_name), 1) # confirm checklist reset.confirm_read(debug) diff --git a/tests/device_tests/test_repeated_backup.py b/tests/device_tests/test_repeated_backup.py index b27b9fd049..d236a78145 100644 --- a/tests/device_tests/test_repeated_backup.py +++ b/tests/device_tests/test_repeated_backup.py @@ -21,7 +21,7 @@ from trezorlib import device, messages from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.exceptions import Cancelled, TrezorFailure -from ..common import WITH_MOCK_URANDOM, MNEMONIC_SLIP39_BASIC_20_3of6 +from ..common import TEST_ADDRESS_N, WITH_MOCK_URANDOM, MNEMONIC_SLIP39_BASIC_20_3of6 from ..input_flows import InputFlowSlip39BasicBackup, InputFlowSlip39BasicRecoveryDryRun @@ -30,6 +30,7 @@ from ..input_flows import InputFlowSlip39BasicBackup, InputFlowSlip39BasicRecove @WITH_MOCK_URANDOM def test_repeated_backup(client: Client): assert client.features.backup_availability == messages.BackupAvailability.Required + assert client.features.recovery_status == messages.RecoveryStatus.Nothing # initial device backup mnemonics = [] @@ -42,6 +43,10 @@ def test_repeated_backup(client: Client): assert len(mnemonics) == 5 # cannot backup, since we already just did that! + assert ( + client.features.backup_availability == messages.BackupAvailability.NotAvailable + ) + assert client.features.recovery_status == messages.RecoveryStatus.Nothing with pytest.raises(TrezorFailure, match=r".*Seed already backed up"): device.backup(client) @@ -53,6 +58,10 @@ def test_repeated_backup(client: Client): client.set_input_flow(IF.get()) ret = device.recover(client, type=messages.RecoveryType.UnlockRepeatedBackup) assert ret == messages.Success(message="Backup unlocked") + assert ( + client.features.backup_availability == messages.BackupAvailability.Available + ) + assert client.features.recovery_status == messages.RecoveryStatus.Backup # we can now perform another backup with client: @@ -61,6 +70,10 @@ def test_repeated_backup(client: Client): device.backup(client) # the backup feature is locked again... + assert ( + client.features.backup_availability == messages.BackupAvailability.NotAvailable + ) + assert client.features.recovery_status == messages.RecoveryStatus.Nothing with pytest.raises(TrezorFailure, match=r".*Seed already backed up"): device.backup(client) @@ -70,6 +83,7 @@ def test_repeated_backup(client: Client): @WITH_MOCK_URANDOM def test_repeated_backup_cancel(client: Client): assert client.features.backup_availability == messages.BackupAvailability.Required + assert client.features.recovery_status == messages.RecoveryStatus.Nothing # initial device backup mnemonics = [] @@ -82,6 +96,10 @@ def test_repeated_backup_cancel(client: Client): assert len(mnemonics) == 5 # cannot backup, since we already just did that! + assert ( + client.features.backup_availability == messages.BackupAvailability.NotAvailable + ) + assert client.features.recovery_status == messages.RecoveryStatus.Nothing with pytest.raises(TrezorFailure, match=r".*Seed already backed up"): device.backup(client) @@ -93,6 +111,10 @@ def test_repeated_backup_cancel(client: Client): client.set_input_flow(IF.get()) ret = device.recover(client, type=messages.RecoveryType.UnlockRepeatedBackup) assert ret == messages.Success(message="Backup unlocked") + assert ( + client.features.backup_availability == messages.BackupAvailability.Available + ) + assert client.features.recovery_status == messages.RecoveryStatus.Backup client.debug.wait_layout() @@ -101,6 +123,72 @@ def test_repeated_backup_cancel(client: Client): with pytest.raises(Cancelled): client.call(messages.Cancel()) + client.refresh_features() + # the backup feature is locked again... + assert ( + client.features.backup_availability == messages.BackupAvailability.NotAvailable + ) + assert client.features.recovery_status == messages.RecoveryStatus.Nothing with pytest.raises(TrezorFailure, match=r".*Seed already backed up"): device.backup(client) + + +@pytest.mark.setup_client(needs_backup=True, mnemonic=MNEMONIC_SLIP39_BASIC_20_3of6) +@pytest.mark.skip_t1b1 +@WITH_MOCK_URANDOM +def test_repeated_backup_send_disallowed_message(client: Client): + assert client.features.backup_availability == messages.BackupAvailability.Required + assert client.features.recovery_status == messages.RecoveryStatus.Nothing + + # initial device backup + mnemonics = [] + with client: + IF = InputFlowSlip39BasicBackup(client, False) + client.set_input_flow(IF.get()) + device.backup(client) + mnemonics = IF.mnemonics + + assert len(mnemonics) == 5 + + # cannot backup, since we already just did that! + assert ( + client.features.backup_availability == messages.BackupAvailability.NotAvailable + ) + assert client.features.recovery_status == messages.RecoveryStatus.Nothing + with pytest.raises(TrezorFailure, match=r".*Seed already backed up"): + device.backup(client) + + # unlock repeated backup by entering 3 of the 5 shares we have got + with client: + IF = InputFlowSlip39BasicRecoveryDryRun( + client, mnemonics[:3], unlock_repeated_backup=True + ) + client.set_input_flow(IF.get()) + ret = device.recover(client, type=messages.RecoveryType.UnlockRepeatedBackup) + assert ret == messages.Success(message="Backup unlocked") + assert ( + client.features.backup_availability == messages.BackupAvailability.Available + ) + assert client.features.recovery_status == messages.RecoveryStatus.Backup + + client.debug.wait_layout() + + # send a GetAddress message + + resp = client.call_raw( + messages.GetAddress( + coin_name="Testnet", + address_n=TEST_ADDRESS_N, + show_display=True, + script_type=messages.InputScriptType.SPENDADDRESS, + ) + ) + assert isinstance(resp, messages.Failure) + assert "not allowed" in resp.message + + assert client.features.backup_availability == messages.BackupAvailability.Available + assert client.features.recovery_status == messages.RecoveryStatus.Backup + + # we are still on the confirmation screen! + assert client.debug.read_layout().text_content() == "Create additional backup?" diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index be1dd8a58d..a14f27ac14 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -774,6 +774,7 @@ "T2B1_cs_test_recovery.py::test_recovery_bip39": "b39bed5f9adcbcfb54a2c6da36aa1f694cd3fa17c94a262ce1f53000084852f3", "T2B1_cs_test_recovery.py::test_recovery_bip39_previous_word": "48dde6e5b926c445947b344bef1fff91f4016f4033a5b5693837d8e5757cd1a1", "T2B1_cs_test_recovery.py::test_recovery_slip39_basic": "78a2ce9924b7758a97853d1ab27bbbc2f8be1dfe9f2d14014de803aa0bb62d30", +"T2B1_cs_test_repeated_backup.py::test_repeated_backup": "36c95325fbb7fa1824a3a73f5c06db616bebea55519a045c87a676201c8f2944", "T2B1_cs_test_reset_bip39.py::test_reset_bip39": "e6ab28c1220196c73e1b73d59545788da3b71deea10189e31b3e2359d22017d5", "T2B1_cs_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "b385569c40eca2a1aa8538d03cdc9d639f98fbab78cf92aadb3ea6d2a6545eca", "T2B1_cs_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "b74fd6a67276594a8cd46fe94e9bd42913850dc90969977586d4f380587ebd0c", @@ -819,6 +820,7 @@ "T2B1_de_test_recovery.py::test_recovery_bip39": "4982804edb96e55b635b24f64ee07e5ab98d4a7c5aa999870c318d49f64e6bce", "T2B1_de_test_recovery.py::test_recovery_bip39_previous_word": "ae7d2ea0bf92eb7da2a2604f285687995849b267318ac5229f663784c448fcf1", "T2B1_de_test_recovery.py::test_recovery_slip39_basic": "26f47dfda39e927f17ded8054a2e892a24d56d0c04fead1e0ac30160c20d5f66", +"T2B1_de_test_repeated_backup.py::test_repeated_backup": "a6a47cb4922ad5b322212b81acfe2767e4a449e492ce60d1894088c26a86c4aa", "T2B1_de_test_reset_bip39.py::test_reset_bip39": "21b8c8ac69aaca28bbc7a8e64f2fa412be949dd61581567c9c9217400fe87392", "T2B1_de_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "8b7ae72358d1329f82ccaaa9a81b1c83ffa0585a2f345661b7b9299130a709e3", "T2B1_de_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "45a70b97b6285db99a3e826c2f243126c06ed04d1a544f48ee41275352291368", @@ -827,6 +829,8 @@ "T2B1_de_test_tutorial.py::test_tutorial_again_and_skip": "20748e3399998bb0b6566a5e7b66d7e7118dc9ea2894cb56f698bd4a46dca088", "T2B1_de_test_tutorial.py::test_tutorial_finish": "3585950c2b55023936d351114b0ae05ca2729fea7f5b1ae239d85e4aba586915", "T2B1_de_test_tutorial.py::test_tutorial_skip": "b3a83ecf8437bdde5bbfcf4daf8e8f53a7a2681db65879e138c6b25a3f1012a2", +"T2B1_en-test_repeated_backup.py::test_repeated_backup_cancel": "902b8f47380e0591bf3d5e410a9db86fe1a3b8221c968b89c97960fdd91e5100", +"T2B1_en-test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "660c0dd0c290f8320d0194c6df2c44c9741a7f05414c0afddad0b23b95c0906d", "T2B1_en_test_autolock.py::test_autolock_does_not_interrupt_preauthorized": "a67277433c9ad7c59332178eb5f280711273eb8555c1edf40cc523896c2d4425", "T2B1_en_test_autolock.py::test_autolock_does_not_interrupt_signing": "ad5313372d860f1bc3462da66e43b8c12226fc6b392ed48535c39f69f9bc4d38", "T2B1_en_test_autolock.py::test_autolock_interrupts_passphrase": "e73c51702985c2970a12ce1caa885cba2e7619e42dbcbfec52544af60b7fddfd", @@ -864,9 +868,7 @@ "T2B1_en_test_recovery.py::test_recovery_bip39": "fd055e526b66f7d0eb3b6968f3889eb4a3e589fd3700b6688e68ea5d6c0c18dd", "T2B1_en_test_recovery.py::test_recovery_bip39_previous_word": "10c4d76d4f636878540dcb6ba258a2d28489012298cf273af3808bcadbe38754", "T2B1_en_test_recovery.py::test_recovery_slip39_basic": "771d9bd01496b0fea72d5faca60fcc564e83d4a69e5fe02770238071dec7274d", -"T2B1_en_test_repeated_backup.py::test_repeated_backup": "cbdb2fc033538e4995a9ba5fc658a2e58936c209e5165244f3f13d65de7125bd", -"T2B1_en-test_repeated_backup.py::test_repeated_backup_cancel": "902b8f47380e0591bf3d5e410a9db86fe1a3b8221c968b89c97960fdd91e5100", -"T2B1_en-test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "660c0dd0c290f8320d0194c6df2c44c9741a7f05414c0afddad0b23b95c0906d", +"T2B1_en_test_repeated_backup.py::test_repeated_backup": "27c7fb9c9a9428f51060c4c4516b38f0c98e17360357576c55f7e3853adebdc6", "T2B1_en_test_reset_bip39.py::test_reset_bip39": "6d229eb212360ffad2bc72154588ec82f699ae6d0cbbf87fa950dd4c8e2ea9c9", "T2B1_en_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "5cd7eb5b96673f7f9dc066d2860ef4ab42926488a5117a2bc89caa667c3916e1", "T2B1_en_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "cb815314c0607f0d6f678f5a9b9b99d6e50cbb670a83b3463ad2bf8635f9319a", @@ -912,6 +914,7 @@ "T2B1_es_test_recovery.py::test_recovery_bip39": "d836420b4c87a47c4f6d764fa87917d64f40b9cd8154c1b0739e76c9b4226712", "T2B1_es_test_recovery.py::test_recovery_bip39_previous_word": "fb6366eb8f5862120aaecae5567e934546bf06bce43fce91305f4130b3e47640", "T2B1_es_test_recovery.py::test_recovery_slip39_basic": "40d49a424c770eae159c3ffa8d22709f014caf940e6600861c18e78538f5edb6", +"T2B1_es_test_repeated_backup.py::test_repeated_backup": "cad5adb87bf7e7904b43c6d2b94b06f3416eb7af549a1b6681b0a52c6d5826b2", "T2B1_es_test_reset_bip39.py::test_reset_bip39": "4c7a5cc6b7a02d600995bd5f4e0adf2fd2668eefcfb95bba353b693c9dbecf76", "T2B1_es_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "eaf165395e06b064f0a7c04443b94d1cf3c820ce2cdb84af79572765d06ff701", "T2B1_es_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "a6a4f83b123f5c17374408570b224661c6d9475973d6fe9e650f9a0f4bcc4417", @@ -957,6 +960,7 @@ "T2B1_fr_test_recovery.py::test_recovery_bip39": "7345536d86da59f83e498ac6fc6ee42f2b5c9ead902c41caae6d08c57f6129b6", "T2B1_fr_test_recovery.py::test_recovery_bip39_previous_word": "2293f0baf03ca5850988b736c0e6e684c116291a54108a77134a3e1dc16405f7", "T2B1_fr_test_recovery.py::test_recovery_slip39_basic": "af734abbec86878d07875a03fd264547e00ad61d11999d4f1ab5582ff46b2e15", +"T2B1_fr_test_repeated_backup.py::test_repeated_backup": "876b97800c34e78d911e3cc6b9babdeff31c7f8587fa51f044f332d8c81e80c0", "T2B1_fr_test_reset_bip39.py::test_reset_bip39": "ad5080eb9cd9d9b3ca2b3b6f966963836d0771eea4f747c443965b6dd3a55b8b", "T2B1_fr_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "7b5796f5dbaea0517898616bc3a273b658e8b22cbd381bc6d63192eda5445da3", "T2B1_fr_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "08a6bd98addc455004a97f148f85f22868640279ab222c9f65755f950be8108e", @@ -7902,6 +7906,7 @@ "T2T1_cs_test_recovery.py::test_recovery_bip39": "e8fc42659087a3b41e0e2db70cb3211895478d20fe7a775675ca6e2c06c1e77a", "T2T1_cs_test_recovery.py::test_recovery_bip39_previous_word": "9fce49fe5cd46312732a8643f9f0dd2694b376722b344d7106d3f4ee57f30a57", "T2T1_cs_test_recovery.py::test_recovery_slip39_basic": "c5e7eb0fb076bc6f1122a463c3b05c058dc3d59fed14d36e97b81b8bc34ccd15", +"T2T1_cs_test_repeated_backup.py::test_repeated_backup": "642f8cad1b9cd84827278c63ef2aa51fef50a4abb5c147d2f2ab995390a9d00a", "T2T1_cs_test_reset_bip39.py::test_reset_bip39": "537205ff560808738cb7f92a975db4f901822513dc6e04765644119009b53983", "T2T1_cs_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "10a2069bf16df7a0c32b5a5bd06a5c18ddb2c8e0fa537bc4323dd996fe863147", "T2T1_cs_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "7acbdf0286d917ead84b51545a6aaeee1cef56aa7d04599313860f2cb54b3c4b", @@ -7950,6 +7955,7 @@ "T2T1_de_test_recovery.py::test_recovery_bip39": "0e420d2c4ce7afee8e6f53557bc4117e4f93301d675c5706a46e9c46c8330a46", "T2T1_de_test_recovery.py::test_recovery_bip39_previous_word": "385fd9b6db99191f374ef6bf1885769270b04ed4c83b898410a820f5c1bfe795", "T2T1_de_test_recovery.py::test_recovery_slip39_basic": "44fa35cc2ffa836301818fa5c9fe5823e485da113a3329e878715bafb51ec154", +"T2T1_de_test_repeated_backup.py::test_repeated_backup": "5e752716e692f11f1f7f77278c082eb4e430f7a2338625d5f669fbc57c1f5c28", "T2T1_de_test_reset_bip39.py::test_reset_bip39": "f8f3be3e3f9a4aae2d38861d9a97ab186f65d8acb266074743a24c17e92898a2", "T2T1_de_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "6da2196b020cb7e6f05c32e11a0e9e2da6e501bb0ecfffe5974919158ba36444", "T2T1_de_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "f85bf415b444eacb4ae61ca3168dda8a11ba5b368171ca0df49888caff436680", @@ -7998,7 +8004,7 @@ "T2T1_en_test_recovery.py::test_recovery_bip39": "ee619ed8e0cf0fbd75a685830d1873e23896dcca6477b2bbf39eaa8d9b4c8531", "T2T1_en_test_recovery.py::test_recovery_bip39_previous_word": "b41a576c6e879512c80337f5d58fdaa93d2259ed42f164f808e52e0d3ccf1211", "T2T1_en_test_recovery.py::test_recovery_slip39_basic": "81bc28e27af3667606f0479720e4dbdfdb97805b9d94a6f3dfe9d9cb3b045c65", -"T2T1_en_test_repeated_backup.py::test_repeated_backup": "4ee56b338d37f74f892ad80e3ad35bb8f9113b4de602b57136899f52711ac0d9", +"T2T1_en_test_repeated_backup.py::test_repeated_backup": "7a36c6a237b8e7d0cce7a6fc7e6f20975e1c9abe0ed355acffde54dde903610c", "T2T1_en_test_reset_bip39.py::test_reset_bip39": "e7d4a85f9ebfaec35006a566e0a25167f276620d50d847a08721da861cac725a", "T2T1_en_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "259315387e0837ac718654d9180f5730370fa76d77318d620288885ebbddb0fb", "T2T1_en_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "878b828c11353fbfcd854fd54ed172dc7d395c753195d5444b5b57e3499e2bca", @@ -8047,6 +8053,7 @@ "T2T1_es_test_recovery.py::test_recovery_bip39": "5d80d9545989e7fdf8f8d25433956f1a0b527fa0931725816c84fa9de88597c3", "T2T1_es_test_recovery.py::test_recovery_bip39_previous_word": "0e74c799e720952caf98271764e8151da2f3f79a5456a1b8fdd4bea13ea780bc", "T2T1_es_test_recovery.py::test_recovery_slip39_basic": "db5ec08707ea408f9d08a8f0cfc42aba44358ee6ce94ff73af542ef8ca5993ec", +"T2T1_es_test_repeated_backup.py::test_repeated_backup": "2631bd836f3eed96c21f211a604d83ffd4f9fab24a50832d2e8fc612741067f2", "T2T1_es_test_reset_bip39.py::test_reset_bip39": "644226a8736f10de7878950e41d189b207474a40022365b87ea1ea24912c1eb3", "T2T1_es_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "4688e4198ef55ff8253965b16a612845cc9c29ae3dc9911723ac9c3d170738ef", "T2T1_es_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "0af93fcceb4cbc33d6a3bd9022bc3bc774cfca36a23bf05d6d181846fb3631d3", @@ -8095,6 +8102,7 @@ "T2T1_fr_test_recovery.py::test_recovery_bip39": "ee49084821d8836b2c6774c80b6f382af28bed1e110118b96fe55697cf76e215", "T2T1_fr_test_recovery.py::test_recovery_bip39_previous_word": "5bcecb9c0d7ff67fd388e13aa5daf4bf849a886efe7b9ae64a4579b15202be23", "T2T1_fr_test_recovery.py::test_recovery_slip39_basic": "676c1eaf8983dd9d07e476303f2c0370006740a4c2a34a11ae68735fdfdd3ee7", +"T2T1_fr_test_repeated_backup.py::test_repeated_backup": "13d382cde3a90905602a48886ae69dcb88f309bc73fc2d55da739ebfa11f5ff8", "T2T1_fr_test_reset_bip39.py::test_reset_bip39": "5d9a35bf67c9520002ee41abac5c556f1932b9fc2073a259c3a8acf4443fc64d", "T2T1_fr_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "d1e765a363f3e24219cef132d94ecc48d27a5564ca90b69a2231f7ec0a6ce89a", "T2T1_fr_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "c68e1a6538bf2b96293b23c4482f50f9a6de907ca3f0744bb88a74618ad9d306", @@ -9517,6 +9525,9 @@ "T2T1_cs_test_protection_levels.py::test_unlocked": "03c60806a17607d7e3b39d76d3d82144ceef92ebbf90bc25ecdd6233bc0081cf", "T2T1_cs_test_protection_levels.py::test_verify_message_t2": "7cbc1f75a41c00a6d53fe6372113fdba190489e8819fb6d4a7f6d9898b0115c1", "T2T1_cs_test_protection_levels.py::test_wipe_device": "e2f47c3779d782bb71d8dfd553560ef36b4d6fa67a629719e380e30af8727229", +"T2T1_cs_test_repeated_backup.py::test_repeated_backup": "6cdff3d90975350249abb78f90136fa0a5aa534e14483160c44a934a55850c0e", +"T2T1_cs_test_repeated_backup.py::test_repeated_backup_cancel": "2d34bfb184b3b67bb073d4a8c9f944318b353d7ebf7554d5ccbe67e100040125", +"T2T1_cs_test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "da2c71dd408d8ad4546b43a78353561fc6b2654b354239e9a13fef13cfaf6aa1", "T2T1_cs_test_sdcard.py::test_sd_format": "8f1ca58187e0eb32b6e23e369b1e9a3f68ee244023e2a0d25930d887f9bff5f2", "T2T1_cs_test_sdcard.py::test_sd_no_format": "3ba9a245bd44511b17d97932de2143ddd9ac0e2b63dd5f573a82779990c446fc", "T2T1_cs_test_sdcard.py::test_sd_protect_unlock": "f919e4e387fcb3806adb43f7b8f71ae3b14a30970b3d79bb4c9bd063804a084c", @@ -10984,6 +10995,9 @@ "T2T1_de_test_protection_levels.py::test_unlocked": "97cde4874c0952f2da6f2f41845b8ce279e4015ea95ef38bd8c0e0d55039b80d", "T2T1_de_test_protection_levels.py::test_verify_message_t2": "b0298371e1eb13ab94bd944dbfca4079e5e6751003fb9e0a2bb4dc35d02db844", "T2T1_de_test_protection_levels.py::test_wipe_device": "2b6b86e0caebab7123f67264d3082849c56ee4d94ce8da13fede6d1012b866cc", +"T2T1_de_test_repeated_backup.py::test_repeated_backup": "56831fe1a4a60cb5d0f2df41b9a7cd2170de42a411abab9c4dc2bd232fb6e020", +"T2T1_de_test_repeated_backup.py::test_repeated_backup_cancel": "ca70ffbb6b6979ea00e2f746ad940edf1f54a030be9bbdbaa77a97899261cd26", +"T2T1_de_test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "15a17645203e88c272f965d20dc725015f2a0c8e4dc0c3b9b6b52dfc4239a669", "T2T1_de_test_sdcard.py::test_sd_format": "3e307eee23db4db1a7f3810af0d90d6720da8e5bd81cbd4e924579ff4528b51c", "T2T1_de_test_sdcard.py::test_sd_no_format": "3d0bc9d38a1d1ad8eba878d6ed1038eb8ba78e74a6e3385b65ea29f07794ea22", "T2T1_de_test_sdcard.py::test_sd_protect_unlock": "89dfea5d01815a7927af69127a7fbece5b8ba3bd36713298ea2edc8f860d6d32", @@ -12451,9 +12465,9 @@ "T2T1_en_test_protection_levels.py::test_unlocked": "4488e2b6f06fdff05749ac271d080182f1c95645de37898457ff12f0fb190381", "T2T1_en_test_protection_levels.py::test_verify_message_t2": "cc09f0acf9e48b1355dae0be65a2a97abbe2811808feee08d46ae7146ce6bb6f", "T2T1_en_test_protection_levels.py::test_wipe_device": "7ff017de646b7cf70832605e1750c635d0eb661d51534b56007b49e82b927011", -"T2T1_en_test_repeated_backup.py::test_repeated_backup": "321a6c7a274e20fbddcc0dbdff31181950a613c97a77ad48ce1bb31845ffdc0e", -"T2T1_en_test_repeated_backup.py::test_repeated_backup_cancel": "9ab2f1f9e49582efa1e98c728b38ce1a21c4f09d398b20f616507f67a6a292b2", -"T2T1_en_test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "dc906965730138e588e4efb5e7eb71609c504f5910352ce04bd926358184af36", +"T2T1_en_test_repeated_backup.py::test_repeated_backup": "ac745f23dd716f1ddfc16321f076ce9c2a09104016d4fd5a3bb6f0c087b35f4b", +"T2T1_en_test_repeated_backup.py::test_repeated_backup_cancel": "87df4f0e06f4b330181c948e8026c2196cfe28442d4b52b6625bb524f8ca41dc", +"T2T1_en_test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "76245bc793c903336b45693c44d8baf3d5dfef5a2134edef03c164dbfb552592", "T2T1_en_test_sdcard.py::test_sd_format": "83d0d9b4eab3bf0eafc22d7d95e8b70bce477ba9c8b4ba13eeca9380ad5fdafa", "T2T1_en_test_sdcard.py::test_sd_no_format": "14511e3d3ee535d97287d8ade25101e8c16db17c1dc5d3151b91e5e8eba61ba5", "T2T1_en_test_sdcard.py::test_sd_protect_unlock": "1302f9a0835cac621142a17031d2150553e676261a3eeeefd32fcf1e69c7bd1a", @@ -13939,6 +13953,9 @@ "T2T1_es_test_protection_levels.py::test_unlocked": "6bf1c8d03bbf9a844f5fc4e31fe7faad8d6c49a9d5d8edcd9c0e04e975386632", "T2T1_es_test_protection_levels.py::test_verify_message_t2": "c970730c7f45321957056c9c1c47ed605d50ec6030a61c093cc82e4b910dd26a", "T2T1_es_test_protection_levels.py::test_wipe_device": "9aaa390ea2296772b8715597159be66d6660d5c418ee783eb44d8443afaee71b", +"T2T1_es_test_repeated_backup.py::test_repeated_backup": "7b6dad1637154eb006c908b1d42a4ac586095124ef181b52b95a2227b51948cb", +"T2T1_es_test_repeated_backup.py::test_repeated_backup_cancel": "3aa092960cfd10022c75571dd4bcda206c5859147a2a0bd6e563baa3d3cc1cf9", +"T2T1_es_test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "8d9ac03652d328978d3005af4cb00397f78fead4cb6ce73a5834675c6fe9cfdd", "T2T1_es_test_sdcard.py::test_sd_format": "96fa6f12c78fc4f0e0d0e65e07d29772b9a27291564a7c12b0ec18a441b4b2fc", "T2T1_es_test_sdcard.py::test_sd_no_format": "307242047f19b261c47bbb5a7c2813fac42420a064ae97c8b05de27f746a9b7f", "T2T1_es_test_sdcard.py::test_sd_protect_unlock": "7296463f55e2a2142ace309c3a6665e398103e24b015ec0aeff34d2c2537c697", @@ -15406,6 +15423,9 @@ "T2T1_fr_test_protection_levels.py::test_unlocked": "ac2d18bf535dd2478eb723fa3d3779561dec2e724c3c4f52303505e124a31383", "T2T1_fr_test_protection_levels.py::test_verify_message_t2": "43cbe7d1e773a37c12dfebceb242c36af16bbf4e2fdb4b8ecf6f9cece3ba1980", "T2T1_fr_test_protection_levels.py::test_wipe_device": "0ed047d904ef99bb35e8e37dcff3d930706c77be2f4c7312233f2e3c956d1f6e", +"T2T1_fr_test_repeated_backup.py::test_repeated_backup": "6389f52c62503b077c8fb39d2885698832c1742809e30024fdbbdbcea395bf14", +"T2T1_fr_test_repeated_backup.py::test_repeated_backup_cancel": "61811c1d10a51d08328aec611e2c2d0246ea87af1d39b6654f5fdca4f5b18534", +"T2T1_fr_test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "f8eddf3a2cb156bdae3f3f7bab97bd6e983dba427e3b7003d6144668600453a3", "T2T1_fr_test_sdcard.py::test_sd_format": "9654a743fdad9525d04b1ee8129874d437113d1d3d3cbb0793dca406cfb65d53", "T2T1_fr_test_sdcard.py::test_sd_no_format": "28930db57ccfe8bd016be50b62fe6ff6ec0f22e6a0258e772a18135c948827b6", "T2T1_fr_test_sdcard.py::test_sd_protect_unlock": "6b793848153a9bbc263cd1c97b536ceaad0e278344e353e8d2ba331b95369836", @@ -15515,6 +15535,7 @@ "T3T1_cs_test_recovery.py::test_recovery_bip39": "18c8812c18b401f400ffdaada20bb4c27a6a41b4dc2f0688ff5097b4110b068a", "T3T1_cs_test_recovery.py::test_recovery_bip39_previous_word": "b6662f23a3ff5d506f2f1d1bbf031631c3f679a5544909a5d93276a79accc373", "T3T1_cs_test_recovery.py::test_recovery_slip39_basic": "c7ad24179dbfd03696098715a52b656d3f0163a7c92bcc1fb7cd187b0500ca68", +"T3T1_cs_test_repeated_backup.py::test_repeated_backup": "15806a9c477e81aea6b787073c234c08e9ae73743a8c0a64e813c0b26c0a2dbf", "T3T1_cs_test_reset_bip39.py::test_reset_bip39": "e28fb99da24382dc1837eb73b4dd931f25303f10183ed9a24a1a83f1c7670c25", "T3T1_cs_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "cf2402357fcc8abf2cba193738c748eb772beb83c7c6514f450769a6840a0ac6", "T3T1_cs_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "1a44e7bcc26d1ca6cb9fadc6cf0191785aee096418134e55190d5768ca6b5f3b", @@ -15563,6 +15584,7 @@ "T3T1_de_test_recovery.py::test_recovery_bip39": "d83b2cee9cfa4797ab78e42a802a694229f678a3e57351f02a742aedfd1c2c91", "T3T1_de_test_recovery.py::test_recovery_bip39_previous_word": "8da9662ee48ee3329c17d30902bf5305091d4aa12eb64707e88084551aad00a6", "T3T1_de_test_recovery.py::test_recovery_slip39_basic": "fd7d77d98db12b3a8a0577c886b3c12e1ec5a5756bf0aa6bc3c51d6f94ede7b6", +"T3T1_de_test_repeated_backup.py::test_repeated_backup": "7765d462b04db75e7126820bc4965e248ca6223cf4f6a474a0b476a13dfc4b0a", "T3T1_de_test_reset_bip39.py::test_reset_bip39": "0ff514b16b04bb1f0074b7634c52b6b36ad329f414347a791fb15036bff453d2", "T3T1_de_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "e36dce460a5e3079ae9cff437499e7888cdb6db0aa06351d2dbdd7cc2cb3ab36", "T3T1_de_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "cf5b36770a72897133375b53da0e75af30020527805559fec6dbb0f23f36812c", @@ -15611,6 +15633,7 @@ "T3T1_en_test_recovery.py::test_recovery_bip39": "187dad507b8f40708ac427df04320873a2c3c33dcd945940e5fbcce6315fb669", "T3T1_en_test_recovery.py::test_recovery_bip39_previous_word": "0504b66f958dd19d44317f31feab77d35a9b11eb2003e37ea982da938aad649d", "T3T1_en_test_recovery.py::test_recovery_slip39_basic": "2935d5cad9408dde53b8cf5b85ff8c790dbcaa430aac699a4c9b357624eacffc", +"T3T1_en_test_repeated_backup.py::test_repeated_backup": "a15baa2dc5551b8c4cb6e9a80e5a790168dc1c8942b2c771a33872d6ee9bcdbc", "T3T1_en_test_reset_bip39.py::test_reset_bip39": "f80c0528314bcd56f0d30c55e7dbbacc3c515e9373a2c30d1cacc207ae62d8d4", "T3T1_en_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "2a2448f1351b0d8a9a6019ae50529ee7ea5941b00ee6a606104b8cf438477ef5", "T3T1_en_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "bc17b8a30057c03723fe8295ccabb585a200adfaacecf58eacdddaa7bf60119b", @@ -15659,6 +15682,7 @@ "T3T1_es_test_recovery.py::test_recovery_bip39": "871937fc5138f48093f14856a78e8e2698fe407aef57835c2a990c96a462b3e9", "T3T1_es_test_recovery.py::test_recovery_bip39_previous_word": "8984517a676690a5d26a4f7a578aa455285e444c933eac7a8b37905d51157808", "T3T1_es_test_recovery.py::test_recovery_slip39_basic": "d2c58b863e451bf92a2b0ad5cd2f33491ebf9b43b59029facb636008bd130998", +"T3T1_es_test_repeated_backup.py::test_repeated_backup": "024820fe86519b7d64b5611b5ad909a066e523602a093b886e5402754c68da78", "T3T1_es_test_reset_bip39.py::test_reset_bip39": "2499fdabac63aa4a08d66bdfc8cf5a0fd1e43723275fe421efca3af92a7d40fa", "T3T1_es_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "d0a4a63450a7fd91840fc9625342b602c7ee1b4f2afdd97e60804cd50dd8d6bd", "T3T1_es_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "d9c3c13c8671cb73f53e49e1b47c9d48f8342b4d99f84554cfbb988b8c01e23b", @@ -15707,6 +15731,7 @@ "T3T1_fr_test_recovery.py::test_recovery_bip39": "4f284e9efe88666971e0393a9cc85afb8047b83ca624f0cfe6fca40d9ff1b188", "T3T1_fr_test_recovery.py::test_recovery_bip39_previous_word": "cda4bfe6f5a79c2fbe98e7e41c55bdc485e51d579ed18c049b929e0bc58ecb2c", "T3T1_fr_test_recovery.py::test_recovery_slip39_basic": "05b4e2cf341661ab300379b05b733f8f01eeeeb0f3ee8be599534112af834874", +"T3T1_fr_test_repeated_backup.py::test_repeated_backup": "bfa127da6f3ed4b101c03629cf914757824c9c48376e900862f14094b649c374", "T3T1_fr_test_reset_bip39.py::test_reset_bip39": "9a740aeba8b98e23a610f9a818c5795f4840c9266b08b19d8bf80424cb54731d", "T3T1_fr_test_reset_slip39_advanced.py::test_reset_slip39_advanced[16of16]": "35a82795eb4679fdb6a1c487bde9921bdf32753ac84b896bb51a4a40e0c1491a", "T3T1_fr_test_reset_slip39_advanced.py::test_reset_slip39_advanced[2of2]": "7e8ace86befb58f6aa15069c167ece1173aceef84cd40658a710a6e50f2ba952", @@ -17044,6 +17069,9 @@ "T3T1_cs_test_protection_levels.py::test_unlocked": "854ce0adfc5484833dfc53d50576360845bccb7b90f79b483390de89d1110ad4", "T3T1_cs_test_protection_levels.py::test_verify_message_t2": "6ae0f587d7912085cabb946b309ef40bbdf395f6262874528b131c802cb91de1", "T3T1_cs_test_protection_levels.py::test_wipe_device": "2f8c6a82c0ef95ba95aaa61ca51f5ce5d6e41eaa393eb77888a787ace26e62f9", +"T3T1_cs_test_repeated_backup.py::test_repeated_backup": "1530169e1bb9417ac7508687b10969347b6ad96e8cba41d5d47b594f137d649c", +"T3T1_cs_test_repeated_backup.py::test_repeated_backup_cancel": "4c877d5f4af05261ea9472334b76809b4a7c0288ae48ac3603066cd305cc56ab", +"T3T1_cs_test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "fec56b8b9b10b19929e3d164b7e0619fe70a337df1a2e670488ec2cb7a45085d", "T3T1_cs_test_sdcard.py::test_sd_format": "b63a9b869f151749ed52f553205efe47cf27e739d619207a2da01edcc45fe25b", "T3T1_cs_test_sdcard.py::test_sd_no_format": "211314ec715ae96a1f1d7b617189a8bb9675c3d73cc10c057c6529ec9b8f4d05", "T3T1_cs_test_sdcard.py::test_sd_protect_unlock": "2d1a02d63396c5f1f40cd11ca6f4fc8dcead9d7a55f8d65fbff608d2f62a324a", @@ -18426,6 +18454,9 @@ "T3T1_de_test_protection_levels.py::test_unlocked": "6eb345e6e13315dadd852980389140e0f86e3e88c4d600b2f1a23b75bb67f21d", "T3T1_de_test_protection_levels.py::test_verify_message_t2": "789d2139229a19875ae544dd3c674507c3c5529c4db1b280f3ac58e061fc798d", "T3T1_de_test_protection_levels.py::test_wipe_device": "77f586b70d92b151c51ccfae935eed1440c07ebbadc9b65126afedc1ddcc0ce5", +"T3T1_de_test_repeated_backup.py::test_repeated_backup": "ca0355e458cc41ed2ecd6f8befdec56b379e94d050b46cec1a88fd04a813f04e", +"T3T1_de_test_repeated_backup.py::test_repeated_backup_cancel": "755dd6aa88cf49222fd0b3e0b14f80498b7d9d4b37aaa1efe8317c654e2d598b", +"T3T1_de_test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "2feeac0a912b21191dc24d64a677118ff7e6f2e5373b82b92c9f6bcd6c1b2481", "T3T1_de_test_sdcard.py::test_sd_format": "0e6df7ed3603f447d88657afe33057877c7651c8a0a2f745845be8382e3327d7", "T3T1_de_test_sdcard.py::test_sd_no_format": "0e559e831f007e7cbc37f6f59673781a1dedbb5410ec9eaade877157e8af4f82", "T3T1_de_test_sdcard.py::test_sd_protect_unlock": "e76e8ed1145f4c0d70e54331fe599916a9f977fb285936ca0350f970befba1fe", @@ -19808,6 +19839,9 @@ "T3T1_en_test_protection_levels.py::test_unlocked": "e08a96b24f115b72eb3f17fa5ee9628d1ae3321f0f5d0d4686da930e7f0e5081", "T3T1_en_test_protection_levels.py::test_verify_message_t2": "f9687ed380da703aff31ea1cfbf280ec78dee613f75082a5a295ffd0843f5634", "T3T1_en_test_protection_levels.py::test_wipe_device": "2975d9b2fd1e6118e259de6ef3b3fbe7c016a7579c282287ae22c4ff02896187", +"T3T1_en_test_repeated_backup.py::test_repeated_backup": "ab8ff27b0d2aa4793b58c172d8656058bba8b267caf08240975e752fb758fd95", +"T3T1_en_test_repeated_backup.py::test_repeated_backup_cancel": "16a8b9333a55c1632057775c26ab4d2be68a8e031ff07d92cff2a637462cea8b", +"T3T1_en_test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "96fce6572203403798314678a3d2ffd082dca7954b2f470251c66323bc804cb1", "T3T1_en_test_sdcard.py::test_sd_format": "85e8d653d42a1f84de35ebd00cee1ada97ee367f9f0bff5ad3bb1c07782d0c38", "T3T1_en_test_sdcard.py::test_sd_no_format": "266a9ae0966cb0720c2515bcf91bfe3315103d0e174387cf389e998d6994d5e1", "T3T1_en_test_sdcard.py::test_sd_protect_unlock": "dd0572acab338caa3ca3c4b493dc7f857cbd8e89ef7f74144e122cf22e1283d6", @@ -21190,6 +21224,9 @@ "T3T1_es_test_protection_levels.py::test_unlocked": "f405182f1a710776b7c10478c62f2b11c7cd010782a042d6b815948f7e395ab0", "T3T1_es_test_protection_levels.py::test_verify_message_t2": "ddcd6d07feeaf593ca84319b84f862046f249a75727cfc05ccdc3c77d9f63a2d", "T3T1_es_test_protection_levels.py::test_wipe_device": "d3986f59a058c52b372a414cd5cb5c0e0285dd303496c7d99c586354554fdde9", +"T3T1_es_test_repeated_backup.py::test_repeated_backup": "201745a4d2d588124650751e31f5842bb41c987a4f914e643aa722e910de5775", +"T3T1_es_test_repeated_backup.py::test_repeated_backup_cancel": "4faa4b2d679bdbe2e190ba93fb1140dc179cacc767fe1cef0c4d49e63eb21b3a", +"T3T1_es_test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "2b6b56e7fd69f22973ef2a4b80b3dfa18f5c1089b937e7b40cfb3145e8c705d1", "T3T1_es_test_sdcard.py::test_sd_format": "1e8ceaa3c419aab4e97088704eb487daa132d4262c490c626efd9d18eecf66e5", "T3T1_es_test_sdcard.py::test_sd_no_format": "1df941e39cb0f5ae7ad5fd0ed61dcd1458a62e256be7faf19f106f9ae9fea197", "T3T1_es_test_sdcard.py::test_sd_protect_unlock": "7b3f9196da8bae50bc4b5688101bf65e71437555b9329598f775e5b0bfd137a0", @@ -22572,6 +22609,9 @@ "T3T1_fr_test_protection_levels.py::test_unlocked": "a4424a33b98437db465a6f6210207566290124a2cefd4c19fec3a3dc9a868b6f", "T3T1_fr_test_protection_levels.py::test_verify_message_t2": "c0433481942e7e93e5488b819637a3412741694b106213a72dbb164521d4fb1b", "T3T1_fr_test_protection_levels.py::test_wipe_device": "004dc079ae5d42d366094c23ed0bacf2b97f637ef6ae22d7124d8db293e1b2cb", +"T3T1_fr_test_repeated_backup.py::test_repeated_backup": "dcc58095596457261a7ff1d0118fd3ef80d3b7b3786edcdfde5f3776e553fcd8", +"T3T1_fr_test_repeated_backup.py::test_repeated_backup_cancel": "c8a2086b7128ac2d39f900e3c6f70c27191e855547d299e027ffff421619cbb6", +"T3T1_fr_test_repeated_backup.py::test_repeated_backup_send_disallowed_message": "1745fc4e388d18bfc3c0124542c4f0d82fe8ad0081998fe913437ae4f90767d3", "T3T1_fr_test_sdcard.py::test_sd_format": "5731b0f2b788c135ba4f226ff6ef4ac95068a639eb02b79a2286f0ca33baa6a3", "T3T1_fr_test_sdcard.py::test_sd_no_format": "43e6b840991931da598895059d9e9bdb75b50bd56ba15b2de0abf6323f308053", "T3T1_fr_test_sdcard.py::test_sd_protect_unlock": "89bc355f195af4a376c40ddb556a51e2aee85a3a183c997857f4cb51cb99b3cd",