refactor(core): convert parts of apps.management to layouts

pull/1533/head
Martin Milata 3 years ago
parent c09a142e2a
commit ffe6d65f72

@ -3,11 +3,10 @@ from trezor import ui, wire
from trezor.messages import ButtonRequestType, SafetyCheckLevel
from trezor.messages.Success import Success
from trezor.strings import format_duration_ms
from trezor.ui.components.tt.text import Text
from trezor.ui.layouts import confirm_action, require
from apps.base import reload_settings_from_storage
from apps.common import safety_checks
from apps.common.confirm import require_confirm, require_hold_to_confirm
if False:
from trezor.messages.ApplySettings import ApplySettings, EnumTypeSafetyCheckLevel
@ -101,37 +100,62 @@ async def apply_settings(ctx: wire.Context, msg: ApplySettings):
async def require_confirm_change_homescreen(ctx):
text = Text("Set homescreen", ui.ICON_CONFIG)
text.normal("Do you really want to", "change the homescreen", "image?")
await require_confirm(ctx, text, ButtonRequestType.ProtectCall)
await require(
confirm_action(
ctx,
"set_homescreen",
"Set homescreen",
description="Do you really want to change the homescreen image?",
br_code=ButtonRequestType.ProtectCall,
)
)
async def require_confirm_change_label(ctx, label):
text = Text("Change label", ui.ICON_CONFIG)
text.normal("Do you really want to", "change the label to")
text.bold("%s?" % label)
await require_confirm(ctx, text, ButtonRequestType.ProtectCall)
await require(
confirm_action(
ctx,
"set_label",
"Change label",
description="Do you really want to change the label to {}?",
description_param=label,
br_code=ButtonRequestType.ProtectCall,
)
)
async def require_confirm_change_passphrase(ctx, use):
text = Text("Enable passphrase" if use else "Disable passphrase", ui.ICON_CONFIG)
text.normal("Do you really want to")
text.normal("enable passphrase" if use else "disable passphrase")
text.normal("encryption?")
await require_confirm(ctx, text, ButtonRequestType.ProtectCall)
if use:
description = "Do you really want to enable passphrase encryption?"
else:
description = "Do you really want to disable passphrase encryption?"
await require(
confirm_action(
ctx,
"set_passphrase",
"Enable passphrase" if use else "Disable passphrase",
description=description,
br_code=ButtonRequestType.ProtectCall,
)
)
async def require_confirm_change_passphrase_source(
ctx, passphrase_always_on_device: bool
):
text = Text("Passphrase source", ui.ICON_CONFIG)
if passphrase_always_on_device:
text.normal(
"Do you really want to", "enter passphrase always", "on the device?"
)
description = "Do you really want to enter passphrase always on the device?"
else:
text.normal("Do you want to revoke", "the passphrase on device", "setting?")
await require_confirm(ctx, text, ButtonRequestType.ProtectCall)
description = "Do you want to revoke the passphrase on device setting?"
await require(
confirm_action(
ctx,
"set_passphrase_source",
"Passphrase source",
description=description,
br_code=ButtonRequestType.ProtectCall,
)
)
async def require_confirm_change_display_rotation(ctx, rotation):
@ -145,55 +169,85 @@ async def require_confirm_change_display_rotation(ctx, rotation):
label = "west"
else:
raise wire.DataError("Unsupported display rotation")
text = Text("Change rotation", ui.ICON_CONFIG, new_lines=False)
text.normal("Do you really want to", "change display rotation")
text.normal("to")
text.bold("%s?" % label)
await require_confirm(ctx, text, ButtonRequestType.ProtectCall)
await require(
confirm_action(
ctx,
"set_rotation",
"Change rotation",
description="Do you really want to change display rotation to {}?",
description_param=label,
br_code=ButtonRequestType.ProtectCall,
)
)
async def require_confirm_change_autolock_delay(ctx, delay_ms):
text = Text("Auto-lock delay", ui.ICON_CONFIG, new_lines=False)
text.normal("Do you really want to", "auto-lock your device", "after")
text.bold("{}?".format(format_duration_ms(delay_ms)))
await require_confirm(ctx, text, ButtonRequestType.ProtectCall)
await require(
confirm_action(
ctx,
"set_autolock_delay",
"Auto-lock delay",
description="Do you really want to auto-lock your device after {}?",
description_param=format_duration_ms(delay_ms),
br_code=ButtonRequestType.ProtectCall,
)
)
async def require_confirm_safety_checks(ctx, level: EnumTypeSafetyCheckLevel) -> None:
if level == SafetyCheckLevel.PromptAlways:
text = Text("Safety override", ui.ICON_CONFIG)
text.normal(
"Trezor will allow you to",
"approve some actions",
"which might be unsafe.",
await require(
confirm_action(
ctx,
"set_safety_checks",
"Safety override",
hold=True,
verb="Hold to confirm",
description="Trezor will allow you to approve some actions which might be unsafe.",
action="Are you sure?",
reverse=True,
larger_vspace=True,
br_code=ButtonRequestType.ProtectCall,
)
)
text.br_half()
text.bold("Are you sure?")
await require_hold_to_confirm(ctx, text, ButtonRequestType.ProtectCall)
elif level == SafetyCheckLevel.PromptTemporarily:
text = Text("Safety override", ui.ICON_CONFIG)
text.normal(
"Trezor will temporarily",
"allow you to approve",
"some actions which",
"might be unsafe.",
await require(
confirm_action(
ctx,
"set_safety_checks",
"Safety override",
hold=True,
verb="Hold to confirm",
description="Trezor will temporarily allow you to approve some actions which might be unsafe.",
action="Are you sure?",
reverse=True,
br_code=ButtonRequestType.ProtectCall,
)
)
text.bold("Are you sure?")
await require_hold_to_confirm(ctx, text, ButtonRequestType.ProtectCall)
elif level == SafetyCheckLevel.Strict:
text = Text("Safety checks", ui.ICON_CONFIG)
text.normal(
"Do you really want to", "enforce strict safety", "checks (recommended)?"
await require(
confirm_action(
ctx,
"set_safety_checks",
"Safety checks",
description="Do you really want to enforce strict safety checks (recommended)?",
br_code=ButtonRequestType.ProtectCall,
)
)
await require_confirm(ctx, text, ButtonRequestType.ProtectCall)
else:
raise ValueError # enum value out of range
async def require_confirm_experimental_features(ctx, enable: bool) -> None:
if enable:
text = Text("Experimental mode", ui.ICON_CONFIG)
text.normal("Enable experimental", "features?")
text.br_half()
text.bold("Only for development", "and beta testing!")
await require_confirm(ctx, text, ButtonRequestType.ProtectCall)
await require(
confirm_action(
ctx,
"set_experimental_features",
"Experimental mode",
description="Enable experimental features?",
action="Only for development and beta testing!",
reverse=True,
br_code=ButtonRequestType.ProtectCall,
)
)

@ -1,10 +1,8 @@
from storage.device import is_initialized
from trezor import config, ui, wire
from trezor import config, wire
from trezor.messages.Success import Success
from trezor.ui.components.tt.text import Text
from trezor.ui.layouts import require, show_success
from trezor.ui.layouts import confirm_action, require, show_success
from apps.common.confirm import require_confirm
from apps.common.request_pin import (
error_pin_invalid,
error_pin_matches_wipe_code,
@ -63,22 +61,40 @@ def require_confirm_change_pin(ctx: wire.Context, msg: ChangePin) -> None:
has_pin = config.has_pin()
if msg.remove and has_pin: # removing pin
text = Text("Remove PIN", ui.ICON_CONFIG)
text.normal("Do you really want to")
text.bold("disable PIN protection?")
return require_confirm(ctx, text)
return require(
confirm_action(
ctx,
"set_pin",
"Remove PIN",
description="Do you really want to",
action="disable PIN protection?",
reverse=True,
)
)
if not msg.remove and has_pin: # changing pin
text = Text("Change PIN", ui.ICON_CONFIG)
text.normal("Do you really want to")
text.bold("change your PIN?")
return require_confirm(ctx, text)
return require(
confirm_action(
ctx,
"set_pin",
"Change PIN",
description="Do you really want to",
action="change your PIN?",
reverse=True,
)
)
if not msg.remove and not has_pin: # setting new pin
text = Text("Enable PIN", ui.ICON_CONFIG)
text.normal("Do you really want to")
text.bold("enable PIN protection?")
return require_confirm(ctx, text)
return require(
confirm_action(
ctx,
"set_pin",
"Enable PIN",
description="Do you really want to",
action="enable PIN protection?",
reverse=True,
)
)
# removing non-existing PIN
raise wire.ProcessError("PIN protection already disabled")

@ -5,7 +5,7 @@ from trezor.messages import ButtonRequestType
from trezor.ui.components.tt.scroll import Paginated
from trezor.ui.components.tt.text import Text
from trezor.ui.components.tt.word_select import WordSelector
from trezor.ui.layouts import require, show_success, show_warning
from trezor.ui.layouts import confirm_action, require, show_success, show_warning
from apps.common import button_request
from apps.common.confirm import confirm, info_confirm, require_confirm
@ -23,13 +23,25 @@ if False:
async def confirm_abort(ctx: wire.GenericContext, dry_run: bool = False) -> bool:
if dry_run:
text = Text("Abort seed check", ui.ICON_WIPE)
text.normal("Do you really want to", "abort the seed check?")
return await confirm_action(
ctx,
"abort_recovery",
"Abort seed check",
description="Do you really want to abort the seed check?",
icon=ui.ICON_WIPE,
br_code=ButtonRequestType.ProtectCall,
)
else:
text = Text("Abort recovery", ui.ICON_WIPE)
text.normal("Do you really want to", "abort the recovery", "process?")
text.bold("All progress will be lost.")
return await confirm(ctx, text, code=ButtonRequestType.ProtectCall)
return await confirm_action(
ctx,
"abort_recovery",
"Abort recovery",
description="Do you really want to abort the recovery process?",
action="All progress will be lost.",
reverse=True,
icon=ui.ICON_WIPE,
br_code=ButtonRequestType.ProtectCall,
)
async def request_word_count(ctx: wire.GenericContext, dry_run: bool) -> int:

@ -9,9 +9,15 @@ from trezor.ui.components.tt.info import InfoConfirm
from trezor.ui.components.tt.num_input import NumInput
from trezor.ui.components.tt.scroll import Paginated
from trezor.ui.components.tt.text import Text
from trezor.ui.layouts import require, show_success
from trezor.ui.layouts import (
confirm_action,
confirm_hex,
require,
show_success,
show_warning,
)
from apps.common.confirm import confirm, require_confirm, require_hold_to_confirm
from apps.common.confirm import confirm, require_hold_to_confirm
if False:
from trezor import loop
@ -22,11 +28,18 @@ if __debug__:
async def show_internal_entropy(ctx, entropy: bytes):
entropy_str = ubinascii.hexlify(entropy).decode()
lines = utils.chunks(entropy_str, 16)
text = Text("Internal entropy", ui.ICON_RESET)
text.mono(*lines)
await require_confirm(ctx, text, ButtonRequestType.ResetDevice)
await require(
confirm_hex(
ctx,
"entropy",
"Internal entropy",
data=ubinascii.hexlify(entropy).decode(),
icon=ui.ICON_RESET,
icon_color=ui.ORANGE_ICON,
width=16,
br_code=ButtonRequestType.ResetDevice,
)
)
async def _show_share_words(ctx, share_words, share_index=None, group_index=None):
@ -186,34 +199,38 @@ async def _show_confirmation_success(
async def _show_confirmation_failure(ctx, share_index):
if share_index is None:
text = Text("Recovery seed", ui.ICON_WRONG, ui.RED)
header = "Recovery seed"
else:
text = Text("Recovery share #%s" % (share_index + 1), ui.ICON_WRONG, ui.RED)
text.bold("That is the wrong word.")
text.normal("Please check again.")
await require_confirm(
ctx, text, ButtonRequestType.ResetDevice, confirm="Check again", cancel=None
header = "Recovery share #%s" % (share_index + 1)
await require(
show_warning(
ctx,
"warning_backup_check",
header=header,
subheader="That is the wrong word.",
content="Please check again.",
button="Check again",
br_code=ButtonRequestType.ResetDevice,
)
)
async def show_backup_warning(ctx, slip39=False):
text = Text("Caution", ui.ICON_NOCOPY)
if slip39:
text.normal(
"Never make a digital",
"copy of your recovery",
"shares and never upload",
"them online!",
)
description = "Never make a digital copy of your recovery shares and never upload them online!"
else:
text.normal(
"Never make a digital",
"copy of your recovery",
"seed and never upload",
"it online!",
description = "Never make a digital copy of your recovery seed and never upload\nit online!"
await require(
confirm_action(
ctx,
"backup_warning",
"Caution",
description=description,
verb="I understand",
verb_cancel=None,
icon=ui.ICON_NOCOPY,
br_code=ButtonRequestType.ResetDevice,
)
await require_confirm(
ctx, text, ButtonRequestType.ResetDevice, "I understand", cancel=None
)

@ -62,6 +62,7 @@ async def confirm_action(
title: str,
action: str = None,
description: str = None,
description_param: str = None,
verb: Union[str, bytes, None] = Confirm.DEFAULT_CONFIRM,
verb_cancel: Union[str, bytes, None] = Confirm.DEFAULT_CANCEL,
hold: bool = False,
@ -80,7 +81,9 @@ async def confirm_action(
)
if reverse and description is not None:
text.normal(description)
text.format_parametrized(
description, description_param if description_param is not None else ""
)
elif action is not None:
text.bold(action)
@ -92,7 +95,9 @@ async def confirm_action(
if reverse and action is not None:
text.bold(action)
elif description is not None:
text.normal(description)
text.format_parametrized(
description, description_param if description_param is not None else ""
)
cls = HoldToConfirm if hold else Confirm
return is_confirmed(
@ -203,10 +208,12 @@ def _split_address(address: str) -> Iterator[str]:
return chunks(address, MONO_CHARS_PER_LINE)
def _hex_lines(hex_data: str, lines: int = TEXT_MAX_LINES) -> Iterator[str]:
if len(hex_data) >= MONO_HEX_PER_LINE * lines:
hex_data = hex_data[: (MONO_HEX_PER_LINE * lines - 3)] + "..."
return chunks(hex_data, MONO_HEX_PER_LINE)
def _hex_lines(
hex_data: str, lines: int = TEXT_MAX_LINES, width: int = MONO_HEX_PER_LINE
) -> Iterator[str]:
if len(hex_data) >= width * lines:
hex_data = hex_data[: (width * lines - 3)] + "..."
return chunks(hex_data, width)
def _show_address(
@ -370,14 +377,16 @@ def show_warning(
ctx: wire.GenericContext,
br_type: str,
content: str,
header: str = "Warning",
subheader: Optional[str] = None,
button: str = "Try again",
br_code: EnumTypeButtonRequestType = ButtonRequestType.Warning,
) -> Awaitable[bool]:
return _show_modal(
ctx,
br_type=br_type,
br_code=ButtonRequestType.Warning,
header="Warning",
br_code=br_code,
header=header,
subheader=subheader,
content=content,
button_confirm=button,
@ -450,9 +459,10 @@ async def confirm_hex(
br_code: EnumTypeButtonRequestType = ButtonRequestType.Other,
icon: str = ui.ICON_SEND, # TODO cleanup @ redesign
icon_color: int = ui.GREEN, # TODO cleanup @ redesign
width: int = MONO_HEX_PER_LINE,
) -> bool:
text = Text(title, icon, icon_color)
text.mono(*_hex_lines(data))
text.mono(*_hex_lines(data, width=width))
return is_confirmed(await interact(ctx, Confirm(text), br_type, br_code))

@ -175,7 +175,7 @@ def click_through(debug, screens, code=None):
debug.press_yes()
def read_and_confirm_mnemonic(debug, words):
def read_and_confirm_mnemonic(debug, words, choose_wrong=False):
"""Read a given number of mnemonic words from Trezor T screen and correctly
answer confirmation questions. Return the full mnemonic.
@ -201,7 +201,11 @@ def read_and_confirm_mnemonic(debug, words):
# check share
for _ in range(3):
index = debug.read_reset_word_pos()
debug.input(mnemonic[index])
if choose_wrong:
debug.input(mnemonic[(index + 1) % len(mnemonic)])
return None
else:
debug.input(mnemonic[index])
return " ".join(mnemonic)

@ -216,6 +216,91 @@ class TestMsgResetDeviceT2:
assert resp.pin_protection is True
assert resp.passphrase_protection is True
@pytest.mark.setup_client(uninitialized=True)
def test_reset_failed_check(self, client):
mnemonic = None
strength = 256 # 24 words
def input_flow():
nonlocal mnemonic
# 1. Confirm Reset
# 2. Backup your seed
# 3. Confirm warning
yield from click_through(client.debug, screens=3, code=B.ResetDevice)
# mnemonic phrases, wrong answer
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(
client.debug, words=24, choose_wrong=True
)
# warning screen
btn_code = yield
assert btn_code == B.ResetDevice
client.debug.press_yes()
# mnemonic phrases
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(client.debug, words=24)
# confirm recovery seed check
btn_code = yield
assert btn_code == B.Success
client.debug.press_yes()
# confirm success
btn_code = yield
assert btn_code == B.Success
client.debug.press_yes()
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
with mock.patch("os.urandom", os_urandom), client:
client.set_expected_responses(
[
proto.ButtonRequest(code=B.ResetDevice),
proto.EntropyRequest(),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.Success),
proto.Success,
proto.Features,
]
)
client.set_input_flow(input_flow)
# PIN, passphrase, display random
device.reset(
client,
display_random=False,
strength=strength,
passphrase_protection=False,
pin_protection=False,
label="test",
language="en-US",
)
# generate mnemonic locally
internal_entropy = client.debug.state().reset_entropy
entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY)
expected_mnemonic = Mnemonic("english").to_mnemonic(entropy)
# Compare that device generated proper mnemonic for given entropies
assert mnemonic == expected_mnemonic
# Check if device is properly initialized
resp = client.call_raw(proto.Initialize())
assert resp.initialized is True
assert resp.needs_backup is False
assert resp.pin_protection is False
assert resp.passphrase_protection is False
assert resp.backup_type is proto.BackupType.Bip39
@pytest.mark.setup_client(uninitialized=True)
def test_failed_pin(self, client):
# external_entropy = b'zlutoucky kun upel divoke ody' * 2

@ -67,20 +67,20 @@
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[withdrawal_amount_is_too_large]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[withdrawal_has_non_staking_path]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_with_multiple_chunks[large_transaction_to_be_-377cb9ff": "4a46dd8ac42295d853646a55ca1b85023b2235af6155be663b1de10a6c98def2",
"test_autolock.py::test_apply_auto_lock_delay": "38c720e0d29b7487060f2a0f8d256a5e5b4f735511e049c43f6ea62e560603ae",
"test_autolock.py::test_apply_auto_lock_delay": "de8ddc62320c82938920fa6b7d95cb571bd7fa766b192549971a975e24cc0b34",
"test_autolock.py::test_apply_auto_lock_delay_out_of_range[0]": "6badfcdd682ecaf16311749ef7a6c07c6a4d0df402427c8dd5a48d476751ed77",
"test_autolock.py::test_apply_auto_lock_delay_out_of_range[1]": "6badfcdd682ecaf16311749ef7a6c07c6a4d0df402427c8dd5a48d476751ed77",
"test_autolock.py::test_apply_auto_lock_delay_out_of_range[4194304]": "6badfcdd682ecaf16311749ef7a6c07c6a4d0df402427c8dd5a48d476751ed77",
"test_autolock.py::test_apply_auto_lock_delay_out_of_range[536871]": "6badfcdd682ecaf16311749ef7a6c07c6a4d0df402427c8dd5a48d476751ed77",
"test_autolock.py::test_apply_auto_lock_delay_out_of_range[9]": "6badfcdd682ecaf16311749ef7a6c07c6a4d0df402427c8dd5a48d476751ed77",
"test_autolock.py::test_apply_auto_lock_delay_valid[10]": "a751228f82166c107a8e8872919e2b010ef3079763adc473066e7a3ada36f864",
"test_autolock.py::test_apply_auto_lock_delay_valid[123]": "caf130bf5fa66fa5ac17432689046c1b6cd8b6a495bac3abef3c414d89b81e3f",
"test_autolock.py::test_apply_auto_lock_delay_valid[3601]": "b2a9a7f3e50afb04fb174627a07b939284aa0acc8b3b53af56f75a35ff1b32c9",
"test_autolock.py::test_apply_auto_lock_delay_valid[536870]": "ca2b4707227cc15089f4d6ba710706d2d5c270f19a4668c09f04f175143b202e",
"test_autolock.py::test_apply_auto_lock_delay_valid[60]": "af8d06c92fc5f9aad5685bf56e59b26ec44418a6174ff73db69803f23785802a",
"test_autolock.py::test_apply_auto_lock_delay_valid[7227]": "437cc6b0780d482a835c23f0935683c40177ae4b0ff31da4fc99eba603545ffe",
"test_autolock.py::test_autolock_cancels_ui": "bb4776bfea145528544554b11bdf13ae99f63a371e8eb0885b0a9bd5b608e027",
"test_autolock.py::test_autolock_default_value": "b9f4cd94638f5f8f4c02026b0ccaee89b42406ab63ce7fcef5c9164467de939b",
"test_autolock.py::test_apply_auto_lock_delay_valid[10]": "1c4d26c24483449997b79f385e2a6eab000dfca98bfe8f3c08e7f007370fca1c",
"test_autolock.py::test_apply_auto_lock_delay_valid[123]": "8c9f07104463543083dfb461810a5fc8727e3a2c09644b4b3e423a43970a72c7",
"test_autolock.py::test_apply_auto_lock_delay_valid[3601]": "941179a4f674b1c3d7004cc7073a29b327c70246eb853aa29f31e2e261f329e6",
"test_autolock.py::test_apply_auto_lock_delay_valid[536870]": "dd430048994310dee37453ae03dfe9c1e15c2fc2ce952dd755bf5df27730907f",
"test_autolock.py::test_apply_auto_lock_delay_valid[60]": "a0e602c8c04eae2dc6dd0768f0a627bcc0327b69d6a9645ecbc3e02f0e4c7908",
"test_autolock.py::test_apply_auto_lock_delay_valid[7227]": "f9e78f3bf23f4808d105da5ae1abc4f25ee550b7590aec0c15fcfb041eeb4413",
"test_autolock.py::test_autolock_cancels_ui": "a63bbf50bb612a87c459b27fe87b38f7b3e984b46c9d68b7604e40667072adc6",
"test_autolock.py::test_autolock_default_value": "e3e6a55dae2c8b152477080002d8b734e1bafe00f26e138294969e2dfd9c596e",
"test_basic.py-test_device_id_different": "bc6acd0386b9d009e6550519917d6e08632b3badde0b0cf04c95abe5f773038a",
"test_basic.py-test_device_id_same": "5a80508a71a9ef64f94762b07636f90e464832f0f4a3102af8fa1a8c69e94586",
"test_basic.py-test_features": "5a80508a71a9ef64f94762b07636f90e464832f0f4a3102af8fa1a8c69e94586",
@ -106,11 +106,11 @@
"test_msg_applysettings.py-test_apply_homescreen_toif_fail[TOIf\\x80\\x00\\x80\\x00~\\x00\\x00\\x00-fefdb3aa": "6badfcdd682ecaf16311749ef7a6c07c6a4d0df402427c8dd5a48d476751ed77",
"test_msg_applysettings.py-test_apply_homescreen_toif_fail[TOIf\\x90\\x00\\x90\\x00~XXXf\\x90\\x00-4f4d817c": "6badfcdd682ecaf16311749ef7a6c07c6a4d0df402427c8dd5a48d476751ed77",
"test_msg_applysettings.py-test_apply_homescreen_toif_fail[TOIg\\x90\\x00\\x90\\x00~\\x00\\x00\\x00-63ffc926": "6badfcdd682ecaf16311749ef7a6c07c6a4d0df402427c8dd5a48d476751ed77",
"test_msg_applysettings.py-test_apply_settings": "8f9f6013bb8a44fda279e9c7d091328fd7ccb39222a02bee701918528355083a",
"test_msg_applysettings.py-test_apply_settings": "9394ea770233a5679c6292c7afe75f4d3528f1b1576f47e6bef8ede6276eec8b",
"test_msg_applysettings.py-test_apply_settings_passphrase": "40de0143b32b5d06ece43d47be27bb91499f0c2417754ddb8e9e03ff41a7f6d4",
"test_msg_applysettings.py-test_apply_settings_passphrase_on_device": "3e6527e227bdde54f51bc9c417b176d0d87fdb6c40c4761368f50eb201b4beed",
"test_msg_applysettings.py-test_apply_settings_rotation": "6f0fa323dd2c82d01994273c023d3ed5e43d43c9c562664a10266f4a7f7ba4cc",
"test_msg_applysettings.py-test_experimental_features": "3127d41bd8615097295b917110ece9dd364986809288c7f958ff71d52106e346",
"test_msg_applysettings.py-test_apply_settings_rotation": "5789f4a9274b8a37af5b279296cf13a95be6e528738474a1c64d36bb0692e216",
"test_msg_applysettings.py-test_experimental_features": "388d5f0ee2e8c521fd82bf8687bd5bdba26ed34695d2a1aecb28f6a72df8df4c",
"test_msg_applysettings.py-test_label_too_long": "5a80508a71a9ef64f94762b07636f90e464832f0f4a3102af8fa1a8c69e94586",
"test_msg_applysettings.py-test_safety_checks": "4d37de3654678b7f16643cf4ef912a0bced545e0e0526e41ea0c9b820560344e",
"test_msg_authorize_coinjoin.py::test_cancel_authorization": "d8a608beb6165f5667cc44dcff6bdc17ebb4638ddd3bd09e7f0e1e75d1e21135",
@ -365,6 +365,7 @@
"test_msg_resetdevice_bip39_t2.py-test_reset_device": "5f1b6cdc46e416430df1afd114bceda57fb644108d594ce1f466460ba4917b41",
"test_msg_resetdevice_bip39_t2.py-test_reset_device_192": "d304d9902accbe23af2dcf73758a2e81b00da17e89f754ca83f209bac8eb8ee1",
"test_msg_resetdevice_bip39_t2.py-test_reset_device_pin": "1e4cef983f25b66931db5a8286c83f8faa3e09eb865896c7e946d2c8992e6d28",
"test_msg_resetdevice_bip39_t2.py-test_reset_failed_check": "b07b90b0c33200f431f1464750cf0934e558ae80a25ecb013c9ce652997df70c",
"test_msg_resetdevice_slip39_advanced.py-test_reset_device_slip39_advanced": "92dde100ab37934b7c39a9bfff15a4e73419b4f029c377f25f0b428c6e4a005c",
"test_msg_resetdevice_slip39_basic.py-test_reset_device_slip39_basic": "650ebacd885fe8c34237aceb835827472a845d8951f2ee573d94c97030603db3",
"test_msg_resetdevice_slip39_basic.py-test_reset_device_slip39_basic_256": "aa7f19f34dafbd5bf205858cd8f694f3278b309a3c8837e6596759d6a1066634",
@ -586,7 +587,7 @@
"test_msg_verifymessage_segwit_native.py-test_message_verify": "3aeca0b02254b83988008b5129812a749f320add09146d189fa294f2b5c80c34",
"test_msg_verifymessage_segwit_native.py-test_verify_utf": "62d12291ee0f0d4639d861ea61d55c9944c37aad24bd70dd35877e9d12a2b731",
"test_msg_webauthn.py::test_add_remove": "a9cdefeb089f197427257e097d07179b23de4fcad4ee91af0191ed767f80577c",
"test_msg_wipedevice.py::test_autolock_not_retained": "b519a86b80151e5c1a4849fc5d6e8e6c8f2953c80befee8dd05f7caec254b464",
"test_msg_wipedevice.py::test_autolock_not_retained": "b07784bf0739fcc5d5877f2a1670b88e10019346c56f9864b48d5cb56944b07b",
"test_msg_wipedevice.py::test_wipe_device": "bc6acd0386b9d009e6550519917d6e08632b3badde0b0cf04c95abe5f773038a",
"test_multisig.py-test_15_of_15": "9d1799a199b45785ac69ae6af715c251b10aebb60f981c9b73d78e53e1a91374",
"test_multisig.py-test_2_of_3": "2be92556edf4ff8eed340d535f379ee6915eae34fef25d669ce865848e7b4705",

Loading…
Cancel
Save