What changed, and why it matters
This commit is a test-only cleanup that renames parameters, refactors emulator selection logic, and fixes test helpers for navigating on-screen keyboards during recovery tests. It does not change any firmware, device, or production code, and there is no indication it fixes or introduces a security vulnerability.
No security action required. Treat as routine test maintenance.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors Trezor firmware upgrade and recovery test infrastructure. Key changes include: renaming legacy_minimum_version/core_minimum_version to model-specific names (t1b1_minimum_version, t2t1_minimum_version), replacing a context-manager-based shared_profile_dir with a pytest fixture, simplifying EmulatorWrapper to take a model name directly, adding a navigate_to_keyboard helper for UI tests, and adjusting Tropic model port handling in the emulator wrapper. All changes are confined to the tests/ directory and python/src/trezorlib/_internal/emulator.py test support code.
Changed components
tests/upgrade_tests/test_firmware_upgrades.pytests/upgrade_tests/test_passphrase_consistency.pytests/upgrade_tests/__init__.pytests/upgrade_tests/conftest.pytests/upgrade_tests/recovery_old.pytests/click_tests/recovery.pytests/recovery_helpers.pytests/emulators.pypython/src/trezorlib/_internal/emulator.pyInspect captured patch +613 / −560
diff --git a/python/src/trezorlib/_internal/emulator.py b/python/src/trezorlib/_internal/emulator.py
index 0ab7cf32..7dcd0611 100644
--- a/python/src/trezorlib/_internal/emulator.py
+++ b/python/src/trezorlib/_internal/emulator.py
@@ -381,6 +381,8 @@ class CoreEmulator(Emulator):
if sdcard is not None:
self.sdcard.write_bytes(sdcard)
+ self.tropic_model_port = tropic_model_port
+
if launch_tropic_model:
assert tropic_model_port
assert tropic_model_configfile
@@ -422,8 +424,8 @@ class CoreEmulator(Emulator):
if self.headless or self.disable_animation:
env["TREZOR_DISABLE_FADE"] = "1"
env["TREZOR_DISABLE_ANIMATION"] = "1"
- if self.tropic_model:
- env["TROPIC_MODEL_PORT"] = str(self.tropic_model.port)
+ if self.tropic_model_port is not None:
+ env["TROPIC_MODEL_PORT"] = str(self.tropic_model_port)
return env
diff --git a/tests/click_tests/recovery.py b/tests/click_tests/recovery.py
index ef737fd2..6a53f0ee 100644
--- a/tests/click_tests/recovery.py
+++ b/tests/click_tests/recovery.py
@@ -3,6 +3,7 @@ from typing import TYPE_CHECKING
from trezorlib.debuglink import LayoutType
from .. import translations as TR
+from ..recovery_helpers import navigate_to_keyboard
from .common import go_next
if TYPE_CHECKING:
@@ -194,8 +195,7 @@ def enter_share(
debug.swipe_up()
layout = debug.read_layout()
elif debug.layout_type is LayoutType.Eckhart:
- debug.click(debug.screen_buttons.ok())
- layout = debug.read_layout()
+ layout = navigate_to_keyboard(debug)
else:
raise ValueError("Unknown model")
diff --git a/tests/emulators.py b/tests/emulators.py
index ef98be71..c309bebe 100644
--- a/tests/emulators.py
+++ b/tests/emulators.py
@@ -52,6 +52,11 @@ def is_tropic_capable_model(model_internal_name: str | None) -> bool:
def gen_from_model(model_internal_name: str) -> str:
+ # Accept "core" and "legacy" directly for backward compatibility
+ # with callers that don't know the specific model (e.g., local builds).
+ if model_internal_name in ("core", "legacy"):
+ return model_internal_name
+
# Compare by internal_name string, not by object equality,
# because the models module may be patched during tests
legacy_names = {m.internal_name for m in LEGACY_MODELS}
@@ -104,8 +109,6 @@ def get_emulator_path(
gen: str,
model: str,
tag: str,
- *,
- prefer_nested: bool = False,
) -> Path:
expected_name = f"trezor-emu-{gen}-{model}-{tag}"
top_level_path = BINDIR / model / expected_name
@@ -113,25 +116,21 @@ def get_emulator_path(
p for p in (BINDIR / model).glob(f"*/{expected_name}") if p.is_file()
)
- if prefer_nested:
+ if is_tropic_capable_model(model):
if nested_paths:
return nested_paths[0]
raise ValueError(
f"tropic-capable emulator executable not found: {BINDIR / model / '*/' / expected_name}"
)
else:
- if top_level_path.exists():
- return top_level_path
- if nested_paths:
- return nested_paths[0]
+ return top_level_path
- return top_level_path
-
-def get_tags(*, prefer_nested: bool = False) -> dict[str, list[str]]:
+def get_tags() -> dict[str, list[str]]:
result = defaultdict(list)
for model_dir in sorted(p for p in BINDIR.iterdir() if p.is_dir()):
seen_tags = set()
+ model_name = model_dir.name
top_level_files = sorted(
p for p in model_dir.glob("trezor-emu-*") if p.is_file()
@@ -140,7 +139,7 @@ def get_tags(*, prefer_nested: bool = False) -> dict[str, list[str]]:
p for p in model_dir.glob("*/trezor-emu-*") if p.is_file()
)
- if prefer_nested:
+ if is_tropic_capable_model(model_name):
files = nested_files
else:
files = [*top_level_files, *nested_files]
@@ -186,9 +185,8 @@ class EmulatorWrapper:
def __init__(
self,
- gen_or_model: str | None,
+ model: str | None,
tag: str | None = None,
- model: str | None = None,
storage: bytes | None = None,
profile_dir: tempfile.TemporaryDirectory | None = None,
worker_id: int = 0,
@@ -196,25 +194,18 @@ class EmulatorWrapper:
auto_interact: bool = True,
main_args: Sequence[str] = ("-m", "main"),
launch_tropic_model: bool | None = None,
- prefer_nested: bool = False,
) -> None:
- if gen_or_model is None:
- raise ValueError("Either emulator gen or model must be provided")
+ if model is None:
+ raise ValueError("Model must be provided")
- if gen_or_model in ("core", "legacy"):
- gen = gen_or_model
- else:
- model = gen_or_model
- gen = gen_from_model(model)
+ gen = gen_from_model(model)
if launch_tropic_model is None:
launch_tropic_model = is_tropic_capable_model(model)
- if tag is not None and model is not None:
- executable = get_emulator_path(
- gen, model, tag, prefer_nested=prefer_nested
- )
+ if tag is not None:
+ executable = get_emulator_path(gen, model, tag)
else:
executable = LOCAL_BUILD_PATHS[gen]
diff --git a/tests/recovery_helpers.py b/tests/recovery_helpers.py
new file mode 100644
index 00000000..29f59baa
--- /dev/null
+++ b/tests/recovery_helpers.py
@@ -0,0 +1,29 @@
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from trezorlib.debuglink import DebugLink, LayoutContent
+
+KEYBOARD_COMPONENTS = ("MnemonicKeyboard", "Slip39Keyboard")
+MAX_ATTEMPTS = 10
+
+
+def layout_has_keyboard(layout: "LayoutContent") -> bool:
+ components = layout.all_components()
+ if any(name in components for name in KEYBOARD_COMPONENTS):
+ return True
+ return any(name in layout.json_str for name in KEYBOARD_COMPONENTS)
+
+
+def navigate_to_keyboard(debug: "DebugLink") -> "LayoutContent":
+ layout = debug.read_layout()
+
+ for _ in range(MAX_ATTEMPTS):
+ if layout_has_keyboard(layout):
+ return layout
+ debug.click(debug.screen_buttons.ok())
+ layout = debug.read_layout()
+
+ raise RuntimeError(
+ f"Keyboard not found after {MAX_ATTEMPTS} attempts. "
+ f"Expected one of: {', '.join(KEYBOARD_COMPONENTS)}"
+ )
diff --git a/tests/upgrade_tests/__init__.py b/tests/upgrade_tests/__init__.py
index 7641278a..cab3c208 100644
--- a/tests/upgrade_tests/__init__.py
+++ b/tests/upgrade_tests/__init__.py
@@ -15,8 +15,8 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import os
-import tempfile
-from contextlib import contextmanager
+import re
+from pathlib import Path
from typing import List, Tuple
import pytest
@@ -24,53 +24,74 @@ from _pytest.mark.structures import MarkDecorator
from trezorlib.models import T1B1, T2T1, T3W1, by_internal_name
-from ..emulators import (
- LOCAL_BUILD_PATHS,
- TROPIC_CAPABLE_MODELS,
- get_tags,
- stop_shared_tropic_model,
-)
-
-
-@contextmanager
-def shared_profile_dir() -> tempfile.TemporaryDirectory:
- profile_dir = tempfile.TemporaryDirectory()
- try:
- yield profile_dir
- finally:
- stop_shared_tropic_model(profile_dir.name)
- if os.environ.get("TREZOR_KEEP_PROFILE_DIR") != "1":
- profile_dir.cleanup()
-
+from ..emulators import LOCAL_BUILD_PATHS, get_tags
ALL_TAGS = get_tags()
-_NESTED_TAGS = get_tags(prefer_nested=True)
-for model in TROPIC_CAPABLE_MODELS:
- if model in _NESTED_TAGS:
- ALL_TAGS[model] = _NESTED_TAGS[model]
-SELECTED_GENS = [
- gen.strip() for gen in os.environ.get("TREZOR_UPGRADE_TEST", "").split(",") if gen
+SELECTED_MODELS = [
+ m.strip().upper()
+ for m in os.environ.get("TREZOR_UPGRADE_TEST", "").split(",")
+ if m.strip()
]
-if SELECTED_GENS:
- # if any gens were selected via the environment variable, force enable all selected
- LEGACY_ENABLED = "legacy" in SELECTED_GENS
- if "core" in SELECTED_GENS:
- raise ValueError(
- "TREZOR_UPGRADE_TEST=core is ambiguous. Use core-t2t1 or core-t3w1."
- )
- CORE_T2T1_ENABLED = "core-t2t1" in SELECTED_GENS
- CORE_T3W1_ENABLED = "core-t3w1" in SELECTED_GENS
- CORE_ENABLED = CORE_T2T1_ENABLED or CORE_T3W1_ENABLED
+
+def _detect_local_core_build_model() -> str | None:
+ build_dir = Path(LOCAL_BUILD_PATHS["core"]).parent
+ if not build_dir.exists():
+ return None
+
+ for trezorhal_path in sorted(build_dir.rglob("trezorhal.rs")):
+ try:
+ content = trezorhal_path.read_text()
+ except OSError:
+ continue
+
+ match = re.search(r'MODEL_INTERNAL_NAME: .* = b"([A-Z0-9]+)\\0";', content)
+ if match:
+ return match.group(1)
+
+ return None
+
+
+if SELECTED_MODELS:
+ # Validate all selected model names
+ for name in SELECTED_MODELS:
+ if by_internal_name(name) is None:
+ raise ValueError(
+ f"Unknown model in TREZOR_UPGRADE_TEST: {name}. "
+ "Use model names like T1B1, T2T1, T3W1."
+ )
+
+ _enabled_models = {by_internal_name(name) for name in SELECTED_MODELS}
+ LEGACY_ENABLED = T1B1 in _enabled_models
+ CORE_T2T1_ENABLED = T2T1 in _enabled_models
+ CORE_T3W1_ENABLED = T3W1 in _enabled_models
+ # Models without their own upgrade emulators (e.g. T3B1, T3T1) enable
+ # the core path so that persistence tests using core_only still run.
+ CORE_ENABLED = (
+ CORE_T2T1_ENABLED
+ or CORE_T3W1_ENABLED
+ or bool(_enabled_models - {T1B1, T2T1, T3W1})
+ )
else:
# if no selection was provided, select those for which we have emulators
LEGACY_ENABLED = LOCAL_BUILD_PATHS["legacy"].exists()
CORE_ENABLED = LOCAL_BUILD_PATHS["core"].exists()
- CORE_T2T1_ENABLED = CORE_ENABLED
- CORE_T3W1_ENABLED = CORE_ENABLED
+ detected_core_model = _detect_local_core_build_model() if CORE_ENABLED else None
+
+ # Fail explicitly if local core build exists but model cannot be detected.
+ # Silently defaulting to T2T1 for unknown builds masks configuration issues.
+ if CORE_ENABLED and detected_core_model is None:
+ raise ValueError(
+ "Local core emulator build detected but model could not be determined. "
+ "Please ensure trezorhal.rs exists with MODEL_INTERNAL_NAME, "
+ "or specify TREZOR_UPGRADE_TEST=T2T1|T3W1 explicitly."
+ )
+
+ CORE_T2T1_ENABLED = CORE_ENABLED and detected_core_model != "T3W1"
+ CORE_T3W1_ENABLED = CORE_ENABLED and detected_core_model == "T3W1"
def _is_model_enabled(model) -> bool:
@@ -105,8 +126,8 @@ def version_from_tag(tag: str | None) -> tuple | None:
def for_all(
*args: str,
- legacy_minimum_version: Tuple[int, int, int] = (1, 0, 0),
- core_minimum_version: Tuple[int, int, int] = (2, 0, 0),
+ t1b1_minimum_version: Tuple[int, int, int] = (1, 0, 0),
+ t2t1_minimum_version: Tuple[int, int, int] = (2, 0, 0),
# Intentionally starts at 2.9.3 for T3W1 upgrade coverage.
t3w1_minimum_version: Tuple[int, int, int] = (2, 9, 3),
) -> "MarkDecorator":
@@ -151,13 +172,13 @@ def for_all(
for model in models_to_test:
# Determine minimum version based on model
if model == T1B1:
- minimum_version = legacy_minimum_version
+ minimum_version = t1b1_minimum_version
elif model == T3W1:
minimum_version = t3w1_minimum_version
elif model == T2T1:
- minimum_version = core_minimum_version
+ minimum_version = t2t1_minimum_version
else:
- minimum_version = core_minimum_version
+ minimum_version = t2t1_minimum_version
try:
for tag in ALL_TAGS[model.internal_name]:
diff --git a/tests/upgrade_tests/conftest.py b/tests/upgrade_tests/conftest.py
new file mode 100644
index 00000000..7ed7cbc9
--- /dev/null
+++ b/tests/upgrade_tests/conftest.py
@@ -0,0 +1,37 @@
+import os
+import tempfile
+
+import pytest
+
+from ..emulators import stop_shared_tropic_model
+
+
+@pytest.fixture
+def shared_profile_dir():
+ keep_profile = os.environ.get("TREZOR_KEEP_PROFILE_DIR") == "1"
+ profile_dir = tempfile.TemporaryDirectory()
+ # TODO: in Python >=3.12, simplify to
+ # with tempfile.TemporaryDirectory(delete=not keep_profile) as path:
+ # yield path # str, not TemporaryDirectory
+
+ if keep_profile:
+ # Prevent automatic cleanup when the object is GC'd.
+ finalizer = getattr(profile_dir, "_finalizer", None)
+ if finalizer is not None:
+ try:
+ finalizer.detach()
+ except AttributeError:
+ pass
+
+ try:
+ yield profile_dir
+ finally:
+ if not keep_profile:
+ profile_dir.cleanup()
+
+
+@pytest.fixture(autouse=True)
+def _cleanup_shared_tropic_model(shared_profile_dir):
+ """Stop any shared Tropic model that was started during the test."""
+ yield
+ stop_shared_tropic_model(shared_profile_dir.name)
diff --git a/tests/upgrade_tests/recovery_old.py b/tests/upgrade_tests/recovery_old.py
index 900f60ae..44468a2e 100644
--- a/tests/upgrade_tests/recovery_old.py
+++ b/tests/upgrade_tests/recovery_old.py
@@ -1,5 +1,7 @@
from typing import TYPE_CHECKING
+from ..recovery_helpers import layout_has_keyboard, navigate_to_keyboard
+
if TYPE_CHECKING:
from trezorlib.debuglink import DebugLink, LayoutContent
@@ -9,7 +11,7 @@ def _enter_word(debug: "DebugLink", word: str, is_slip39: bool = False) -> None:
for coords in debug.button_actions.type_word(typed_word, is_slip39=is_slip39):
debug.click(coords, wait=False)
- debug.click(debug.screen_buttons.mnemonic_confirm())
+ debug.click(debug.screen_buttons.mnemonic_confirm(), wait=False)
def confirm_recovery(debug: "DebugLink") -> None:
@@ -35,8 +37,19 @@ def select_number_of_words(
def enter_share(debug: "DebugLink", share: str) -> "LayoutContent":
- debug.click(debug.screen_buttons.ok())
+ layout = navigate_to_keyboard(debug)
+
+ # Fast entry of all 20 words
for word in share.split(" "):
_enter_word(debug, word, is_slip39=True)
- return debug.read_layout()
+ # After all words entered, poll for recovery status to appear
+ import time
+
+ for _ in range(10): # max 1 second total
+ time.sleep(0.1)
+ layout = debug.read_layout()
+ if not layout_has_keyboard(layout):
+ break
+
+ return layout
diff --git a/tests/upgrade_tests/test_firmware_upgrades.py b/tests/upgrade_tests/test_firmware_upgrades.py
index 2e03c640..69b098df 100644
--- a/tests/upgrade_tests/test_firmware_upgrades.py
+++ b/tests/upgrade_tests/test_firmware_upgrades.py
@@ -37,16 +37,9 @@ from trezorlib.tools import H_, parse_path
from ..click_tests import recovery
from ..common import MNEMONIC_SLIP39_BASIC_20_3of6, MNEMONIC_SLIP39_BASIC_20_3of6_SECRET
from ..device_handler import BackgroundDeviceHandler
-from ..emulators import EmulatorWrapper, is_tropic_capable_model
+from ..emulators import EmulatorWrapper
from ..input_flows import InputFlowSlip39BasicBackup
-from . import (
- ALL_TAGS,
- for_all,
- for_tags,
- recovery_old,
- shared_profile_dir,
- version_from_tag,
-)
+from . import ALL_TAGS, for_all, for_tags, recovery_old, version_from_tag
if TYPE_CHECKING:
from trezorlib.client import Session
@@ -69,18 +62,21 @@ def lower_models_minimum_version(func):
original_trezors = models.ALL_MODELS.copy()
original_t1b1 = models.T1B1
original_t2t1 = models.T2T1
+ original_t3w1 = models.T3W1
models.T1B1 = dataclasses.replace(models.T1B1, minimum_version=(1, 0, 0))
models.T2T1 = dataclasses.replace(models.T2T1, minimum_version=(2, 0, 0))
+ models.T3W1 = dataclasses.replace(models.T3W1, minimum_version=(2, 0, 0))
models.TREZOR_ONE = models.T1B1
models.TREZOR_T = models.T2T1
- models.ALL_MODELS = {models.T1B1, models.T2T1}
+ models.ALL_MODELS = {models.T1B1, models.T2T1, models.T3W1}
try:
result = func(*args, **kwargs)
finally:
models.T1B1 = original_t1b1
models.T2T1 = original_t2t1
+ models.T3W1 = original_t3w1
models.TREZOR_ONE = models.T1B1
models.TREZOR_T = models.T2T1
models.ALL_MODELS = original_trezors
@@ -100,6 +96,7 @@ def _get_session(client: "Client", passphrase: str | None = "") -> "Session":
def test_upgrade_load(
tag: str | None,
model: str | None,
+ shared_profile_dir,
) -> None:
def asserts(client: "Client"):
client.refresh_features()
@@ -112,32 +109,29 @@ def test_upgrade_load(
== ADDRESS
)
- with shared_profile_dir() as profile_dir:
- with EmulatorWrapper(
- model,
- tag=tag,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- debuglink.load_device_by_mnemonic(
- emu.client.get_seedless_session(),
- mnemonic=MNEMONIC,
- pin="",
- passphrase_protection=False,
- label=LABEL,
- )
- device_id = emu.client.features.device_id
- asserts(emu.client)
- storage = emu.get_storage()
+ with EmulatorWrapper(
+ model,
+ tag=tag,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ debuglink.load_device_by_mnemonic(
+ emu.client.get_seedless_session(),
+ mnemonic=MNEMONIC,
+ pin="",
+ passphrase_protection=False,
+ label=LABEL,
+ )
+ device_id = emu.client.features.device_id
+ asserts(emu.client)
+ storage = emu.get_storage()
- with EmulatorWrapper(
- model,
- storage=storage,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- assert device_id == emu.client.features.device_id
- asserts(emu.client)
+ with EmulatorWrapper(
+ model,
+ storage=storage,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ assert device_id == emu.client.features.device_id
+ asserts(emu.client)
@for_all("T1B1")
@@ -145,6 +139,7 @@ def test_upgrade_load(
def test_upgrade_load_pin(
tag: str | None,
model: str | None,
+ shared_profile_dir,
) -> None:
PIN = "1234"
@@ -158,32 +153,29 @@ def test_upgrade_load_pin(
session = client.get_session()
assert btc.get_address(session, "Bitcoin", PATH) == ADDRESS
- with shared_profile_dir() as profile_dir:
- with EmulatorWrapper(
- model,
- tag=tag,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- debuglink.load_device_by_mnemonic(
- emu.client.get_seedless_session(),
- mnemonic=MNEMONIC,
- pin=PIN,
- passphrase_protection=False,
- label=LABEL,
- )
- device_id = emu.client.features.device_id
- asserts(emu.client)
- storage = emu.get_storage()
+ with EmulatorWrapper(
+ model,
+ tag=tag,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ debuglink.load_device_by_mnemonic(
+ emu.client.get_seedless_session(),
+ mnemonic=MNEMONIC,
+ pin=PIN,
+ passphrase_protection=False,
+ label=LABEL,
+ )
+ device_id = emu.client.features.device_id
+ asserts(emu.client)
+ storage = emu.get_storage()
- with EmulatorWrapper(
- model,
- storage=storage,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- assert device_id == emu.client.features.device_id
- asserts(emu.client)
+ with EmulatorWrapper(
+ model,
+ storage=storage,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ assert device_id == emu.client.features.device_id
+ asserts(emu.client)
# Test progressive upgrade of storage versions without unlocking in between.
@@ -199,7 +191,7 @@ def test_upgrade_load_pin(
("T1B1", ["v1.8.0", "v1.9.0"]),
)
@lower_models_minimum_version
-def test_storage_upgrade_progressive(tags: List[str], model: str):
+def test_storage_upgrade_progressive(tags: List[str], model: str, shared_profile_dir):
PIN = "1234"
def asserts(client: "Client") -> None:
@@ -210,49 +202,46 @@ def test_storage_upgrade_progressive(tags: List[str], model: str):
client.use_pin_sequence([PIN])
assert btc.get_address(client.get_session(), "Bitcoin", PATH) == ADDRESS
- with shared_profile_dir() as profile_dir:
- with EmulatorWrapper(
- model,
- tag=tags[0],
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- debuglink.load_device_by_mnemonic(
- emu.client.get_seedless_session(),
- mnemonic=MNEMONIC,
- pin=PIN,
- passphrase_protection=False,
- label=LABEL,
- )
- device_id = emu.client.features.device_id
- asserts(emu.client)
- storage = emu.get_storage()
-
- for tag in tags[1:]:
- with EmulatorWrapper(
- model,
- tag=tag,
- storage=storage,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- storage = emu.get_storage()
+ with EmulatorWrapper(
+ model,
+ tag=tags[0],
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ debuglink.load_device_by_mnemonic(
+ emu.client.get_seedless_session(),
+ mnemonic=MNEMONIC,
+ pin=PIN,
+ passphrase_protection=False,
+ label=LABEL,
+ )
+ device_id = emu.client.features.device_id
+ asserts(emu.client)
+ storage = emu.get_storage()
+ for tag in tags[1:]:
with EmulatorWrapper(
model,
+ tag=tag,
storage=storage,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
+ profile_dir=shared_profile_dir,
) as emu:
- assert device_id == emu.client.features.device_id
- asserts(emu.client)
+ storage = emu.get_storage()
+
+ with EmulatorWrapper(
+ model,
+ storage=storage,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ assert device_id == emu.client.features.device_id
+ asserts(emu.client)
-@for_all("T1B1", legacy_minimum_version=(1, 9, 0))
+@for_all("T1B1", t1b1_minimum_version=(1, 9, 0))
@lower_models_minimum_version
def test_upgrade_wipe_code(
tag: str | None,
model: str | None,
+ shared_profile_dir,
):
PIN = "1234"
WIPE_CODE = "4321"
@@ -265,49 +254,46 @@ def test_upgrade_wipe_code(
client.use_pin_sequence([PIN])
assert btc.get_address(client.get_session(), "Bitcoin", PATH) == ADDRESS
- with shared_profile_dir() as profile_dir:
- with EmulatorWrapper(
- model,
- tag=tag,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- debuglink.load_device_by_mnemonic(
- emu.client.get_seedless_session(),
- mnemonic=MNEMONIC,
- pin=PIN,
- passphrase_protection=False,
- label=LABEL,
- )
-
- # Set wipe code.
- emu.client.use_pin_sequence([PIN, WIPE_CODE, WIPE_CODE])
- session = emu.client.get_seedless_session()
- session.refresh_features()
- device.change_wipe_code(session)
-
- device_id = emu.client.features.device_id
- asserts(emu.client)
- storage = emu.get_storage()
-
- with EmulatorWrapper(
- model,
- storage=storage,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- assert device_id == emu.client.features.device_id
- asserts(emu.client)
+ with EmulatorWrapper(
+ model,
+ tag=tag,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ debuglink.load_device_by_mnemonic(
+ emu.client.get_seedless_session(),
+ mnemonic=MNEMONIC,
+ pin=PIN,
+ passphrase_protection=False,
+ label=LABEL,
+ )
- # Check that wipe code is set by changing the PIN to it.
- emu.client.use_pin_sequence([PIN, WIPE_CODE, WIPE_CODE])
- session = emu.client.get_seedless_session()
- session.refresh_features()
- with pytest.raises(
- exceptions.TrezorFailure,
- match="The new PIN must be different from your wipe code",
- ):
- return device.change_pin(session)
+ # Set wipe code.
+ emu.client.use_pin_sequence([PIN, WIPE_CODE, WIPE_CODE])
+ session = emu.client.get_seedless_session()
+ session.refresh_features()
+ device.change_wipe_code(session)
+
+ device_id = emu.client.features.device_id
+ asserts(emu.client)
+ storage = emu.get_storage()
+
+ with EmulatorWrapper(
+ model,
+ storage=storage,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ assert device_id == emu.client.features.device_id
+ asserts(emu.client)
+
+ # Check that wipe code is set by changing the PIN to it.
+ emu.client.use_pin_sequence([PIN, WIPE_CODE, WIPE_CODE])
+ session = emu.client.get_seedless_session()
+ session.refresh_features()
+ with pytest.raises(
+ exceptions.TrezorFailure,
+ match="The new PIN must be different from your wipe code",
+ ):
+ return device.change_pin(session)
@for_all("T1B1")
@@ -315,6 +301,7 @@ def test_upgrade_wipe_code(
def test_upgrade_reset(
tag: str | None,
model: str | None,
+ shared_profile_dir,
):
def asserts(client: "Client"):
assert not client.features.pin_protection
@@ -325,36 +312,33 @@ def test_upgrade_reset(
assert not client.features.unfinished_backup
assert not client.features.no_backup
- with shared_profile_dir() as profile_dir:
- with EmulatorWrapper(
- model,
- tag=tag,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- device.setup(
- emu.client.get_seedless_session(),
- strength=STRENGTH,
- passphrase_protection=False,
- pin_protection=False,
- label=LABEL,
- entropy_check_count=0,
- backup_type=BackupType.Bip39,
- )
- device_id = emu.client.features.device_id
- asserts(emu.client)
- address = btc.get_address(emu.client.get_session(), "Bitcoin", PATH)
- storage = emu.get_storage()
+ with EmulatorWrapper(
+ model,
+ tag=tag,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ device.setup(
+ emu.client.get_seedless_session(),
+ strength=STRENGTH,
+ passphrase_protection=False,
+ pin_protection=False,
+ label=LABEL,
+ entropy_check_count=0,
+ backup_type=BackupType.Bip39,
+ )
+ device_id = emu.client.features.device_id
+ asserts(emu.client)
+ address = btc.get_address(emu.client.get_session(), "Bitcoin", PATH)
+ storage = emu.get_storage()
- with EmulatorWrapper(
- model,
- storage=storage,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- assert device_id == emu.client.features.device_id
- asserts(emu.client)
- assert btc.get_address(emu.client.get_session(), "Bitcoin", PATH) == address
+ with EmulatorWrapper(
+ model,
+ storage=storage,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ assert device_id == emu.client.features.device_id
+ asserts(emu.client)
+ assert btc.get_address(emu.client.get_session(), "Bitcoin", PATH) == address
@for_all()
@@ -362,6 +346,7 @@ def test_upgrade_reset(
def test_upgrade_reset_skip_backup(
tag: str | None,
model: str | None,
+ shared_profile_dir,
):
def asserts(client: "Client"):
assert not client.features.pin_protection
@@ -372,44 +357,42 @@ def test_upgrade_reset_skip_backup(
assert not client.features.unfinished_backup
assert not client.features.no_backup
- with shared_profile_dir() as profile_dir:
- with EmulatorWrapper(
- model,
- tag=tag,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- device.setup(
- emu.client.get_seedless_session(),
- strength=STRENGTH,
- passphrase_protection=False,
- pin_protection=False,
- label=LABEL,
- skip_backup=True,
- entropy_check_count=0,
- backup_type=BackupType.Bip39,
- )
- device_id = emu.client.features.device_id
- asserts(emu.client)
- address = btc.get_address(emu.client.get_session(), "Bitcoin", PATH)
- storage = emu.get_storage()
-
- with EmulatorWrapper(
- model,
- storage=storage,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- assert device_id == emu.client.features.device_id
- asserts(emu.client)
- assert btc.get_address(emu.client.get_session(), "Bitcoin", PATH) == address
-
-
-@for_all(legacy_minimum_version=(1, 7, 2))
+ with EmulatorWrapper(
+ model,
+ tag=tag,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ device.setup(
+ emu.client.get_seedless_session(),
+ strength=STRENGTH,
+ passphrase_protection=False,
+ pin_protection=False,
+ label=LABEL,
+ skip_backup=True,
+ entropy_check_count=0,
+ backup_type=BackupType.Bip39,
+ )
+ device_id = emu.client.features.device_id
+ asserts(emu.client)
+ address = btc.get_address(emu.client.get_session(), "Bitcoin", PATH)
+ storage = emu.get_storage()
+
+ with EmulatorWrapper(
+ model,
+ storage=storage,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ assert device_id == emu.client.features.device_id
+ asserts(emu.client)
+ assert btc.get_address(emu.client.get_session(), "Bitcoin", PATH) == address
+
+
+@for_all(t1b1_minimum_version=(1, 7, 2))
@lower_models_minimum_version
def test_upgrade_reset_no_backup(
tag: str | None,
model: str | None,
+ shared_profile_dir,
):
def asserts(client: "Client"):
assert not client.features.pin_protection
@@ -420,268 +403,253 @@ def test_upgrade_reset_no_backup(
assert not client.features.unfinished_backup
assert client.features.no_backup
- with shared_profile_dir() as profile_dir:
- with EmulatorWrapper(
- model,
- tag=tag,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- device.setup(
- emu.client.get_seedless_session(),
- strength=STRENGTH,
- passphrase_protection=False,
- pin_protection=False,
- label=LABEL,
- no_backup=True,
- entropy_check_count=0,
- backup_type=BackupType.Bip39,
- )
+ with EmulatorWrapper(
+ model,
+ tag=tag,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ device.setup(
+ emu.client.get_seedless_session(),
+ strength=STRENGTH,
+ passphrase_protection=False,
+ pin_protection=False,
+ label=LABEL,
+ no_backup=True,
+ entropy_check_count=0,
+ backup_type=BackupType.Bip39,
+ )
- device_id = emu.client.features.device_id
- asserts(emu.client)
- address = btc.get_address(emu.client.get_session(), "Bitcoin", PATH)
- storage = emu.get_storage()
+ device_id = emu.client.features.device_id
+ asserts(emu.client)
+ address = btc.get_address(emu.client.get_session(), "Bitcoin", PATH)
+ storage = emu.get_storage()
- with EmulatorWrapper(
- model,
- storage=storage,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- assert device_id == emu.client.features.device_id
- asserts(emu.client)
- assert btc.get_address(emu.client.get_session(), "Bitcoin", PATH) == address
+ with EmulatorWrapper(
+ model,
+ storage=storage,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ assert device_id == emu.client.features.device_id
+ asserts(emu.client)
+ assert btc.get_address(emu.client.get_session(), "Bitcoin", PATH) == address
# Although Shamir was introduced in 2.1.2 already, the debug instrumentation was not present until 2.1.9.
-@for_all("T2T1", "T3W1", core_minimum_version=(2, 1, 9))
+@for_all("T2T1", "T3W1", t2t1_minimum_version=(2, 1, 9))
@lower_models_minimum_version
def test_upgrade_shamir_recovery(
tag: str | None,
model: str | None,
+ shared_profile_dir,
):
- with shared_profile_dir() as profile_dir:
- with (
- EmulatorWrapper(
- model,
- tag=tag,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu,
- BackgroundDeviceHandler(emu.client) as device_handler,
- ):
- assert emu.client.features.recovery_status == RecoveryStatus.Nothing
- emu.client.watch_layout(True)
- debug = device_handler.debuglink()
+ with (
+ EmulatorWrapper(
+ model,
+ tag=tag,
+ profile_dir=shared_profile_dir,
+ ) as emu,
+ BackgroundDeviceHandler(emu.client) as device_handler,
+ ):
+ assert emu.client.features.recovery_status == RecoveryStatus.Nothing
+ emu.client.watch_layout(True)
+ debug = device_handler.debuglink()
+
+ device_handler.run_with_session(
+ device.recover, seedless=True, pin_protection=False
+ )
- device_handler.run_with_session(
- device.recover, seedless=True, pin_protection=False
+ recovery_old.confirm_recovery(debug)
+ recovery_old.select_number_of_words(debug, version_from_tag(tag))
+ layout = recovery_old.enter_share(debug, MNEMONIC_SLIP39_BASIC_20_3of6[0])
+ if not debug.legacy_ui and not debug.legacy_debug:
+ assert (
+ "1 of 3 shares entered" in layout.text_content()
+ or "2 more shares" in layout.text_content()
+ or "Start entering" in layout.text_content()
+ )
+
+ device_id = emu.client.features.device_id
+ storage = emu.get_storage()
+ device_handler.check_finalize()
+
+ with EmulatorWrapper(
+ model,
+ storage=storage,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ assert device_id == emu.client.features.device_id
+ assert emu.client.features.recovery_status == RecoveryStatus.Recovery
+ debug = emu.client.debug
+ emu.client.watch_layout(True)
+
+ layout = debug.read_layout()
+ if (
+ "SelectWordCount" in layout.all_components()
+ or "SelectWordCountScreen" in layout.all_components()
+ ):
+ recovery.select_number_of_words(debug, num_of_words=20)
+
+ # second share
+ layout = recovery.enter_share(debug, MNEMONIC_SLIP39_BASIC_20_3of6[1])
+ second_share_text = layout.text_content()
+ if (
+ "1 of 3 shares entered" in second_share_text
+ or "2 more shares" in second_share_text
+ ):
+ remaining_shares = [
+ MNEMONIC_SLIP39_BASIC_20_3of6[0],
+ MNEMONIC_SLIP39_BASIC_20_3of6[2],
+ ]
+ else:
+ assert (
+ "2 of 3 shares entered" in second_share_text
+ or "1 more share" in second_share_text
+ or "Start entering" in second_share_text
)
+ remaining_shares = [MNEMONIC_SLIP39_BASIC_20_3of6[2]]
- recovery_old.confirm_recovery(debug)
- recovery_old.select_number_of_words(debug, version_from_tag(tag))
- layout = recovery_old.enter_share(debug, MNEMONIC_SLIP39_BASIC_20_3of6[0])
- if not debug.legacy_ui and not debug.legacy_debug:
+ # remaining shares
+ for index, share in enumerate(remaining_shares):
+ layout = recovery.enter_share(debug, share)
+ if index < len(remaining_shares) - 1:
assert (
- "1 of 3 shares entered" in layout.text_content()
- or "2 more shares" in layout.text_content()
+ "2 of 3 shares entered" in layout.text_content()
+ or "1 more share" in layout.text_content()
or "Start entering" in layout.text_content()
+ or "1 of 3 shares entered" in layout.text_content()
+ or "2 more shares" in layout.text_content()
)
-
- device_id = emu.client.features.device_id
- storage = emu.get_storage()
- device_handler.check_finalize()
-
- with EmulatorWrapper(
- model,
- storage=storage,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- assert device_id == emu.client.features.device_id
- assert emu.client.features.recovery_status == RecoveryStatus.Recovery
- debug = emu.client.debug
- emu.client.watch_layout(True)
-
- layout = debug.read_layout()
- if (
- "SelectWordCount" in layout.all_components()
- or "SelectWordCountScreen" in layout.all_components()
- ):
- recovery.select_number_of_words(debug, num_of_words=20)
-
- # second share
- layout = recovery.enter_share(debug, MNEMONIC_SLIP39_BASIC_20_3of6[1])
- second_share_text = layout.text_content()
- if (
- "1 of 3 shares entered" in second_share_text
- or "2 more shares" in second_share_text
- ):
- remaining_shares = [
- MNEMONIC_SLIP39_BASIC_20_3of6[0],
- MNEMONIC_SLIP39_BASIC_20_3of6[2],
- ]
else:
assert (
- "2 of 3 shares entered" in second_share_text
- or "1 more share" in second_share_text
- or "Start entering" in second_share_text
+ "Wallet recovery completed" in layout.text_content()
+ or "finished recovering" in layout.text_content()
)
- remaining_shares = [MNEMONIC_SLIP39_BASIC_20_3of6[2]]
-
- # remaining shares
- for index, share in enumerate(remaining_shares):
- layout = recovery.enter_share(debug, share)
- if index < len(remaining_shares) - 1:
- assert (
- "2 of 3 shares entered" in layout.text_content()
- or "1 more share" in layout.text_content()
- or "Start entering" in layout.text_content()
- or "1 of 3 shares entered" in layout.text_content()
- or "2 more shares" in layout.text_content()
- )
- else:
- assert (
- "Wallet recovery completed" in layout.text_content()
- or "finished recovering" in layout.text_content()
- )
-
- # Check the result
- state = debug.state()
- assert state.mnemonic_secret is not None
- assert state.mnemonic_secret.hex() == MNEMONIC_SLIP39_BASIC_20_3of6_SECRET
- assert state.mnemonic_type == BackupType.Slip39_Basic
-
-
-@for_all("T2T1", "T3W1", core_minimum_version=(2, 1, 9))
+
+ # Check the result
+ state = debug.state()
+ assert state.mnemonic_secret is not None
+ assert state.mnemonic_secret.hex() == MNEMONIC_SLIP39_BASIC_20_3of6_SECRET
+ assert state.mnemonic_type == BackupType.Slip39_Basic
+
+
+@for_all("T2T1", "T3W1", t2t1_minimum_version=(2, 1, 9))
@lower_models_minimum_version
def test_upgrade_shamir_backup(
tag: str | None,
model: str | None,
+ shared_profile_dir,
):
- with shared_profile_dir() as profile_dir:
- with EmulatorWrapper(
- model,
- tag=tag,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- session = emu.client.get_seedless_session()
- # Generate a new encrypted master secret and record it.
- device.setup(
- session,
- pin_protection=False,
- skip_backup=True,
- backup_type=BackupType.Slip39_Basic,
- entropy_check_count=0,
- )
- device_id = emu.client.features.device_id
- backup_type = emu.client.features.backup_type
- mnemonic_secret = emu.client.debug.state().mnemonic_secret
-
- # Set passphrase_source = HOST.
- session = emu.client.get_seedless_session()
- resp = session.call(
- ApplySettings(_passphrase_source=2, use_passphrase=True)
- )
- assert isinstance(resp, Success)
-
- # Get a passphrase-less and a passphrased address.
- session = _get_session(emu.client)
- address = btc.get_address(session, "Bitcoin", PATH)
- new_session = _get_session(emu.client, passphrase="TREZOR")
- address_passphrase = btc.get_address(new_session, "Bitcoin", PATH)
-
- assert (
- emu.client.features.backup_availability == BackupAvailability.Required
- )
- storage = emu.get_storage()
-
- with EmulatorWrapper(
- model,
- storage=storage,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- assert emu.client.features.device_id == device_id
+ with EmulatorWrapper(
+ model,
+ tag=tag,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ session = emu.client.get_seedless_session()
+ # Generate a new encrypted master secret and record it.
+ device.setup(
+ session,
+ pin_protection=False,
+ skip_backup=True,
+ backup_type=BackupType.Slip39_Basic,
+ entropy_check_count=0,
+ )
+ device_id = emu.client.features.device_id
+ backup_type = emu.client.features.backup_type
+ mnemonic_secret = emu.client.debug.state().mnemonic_secret
+
+ # Set passphrase_source = HOST.
+ session = emu.client.get_seedless_session()
+ resp = session.call(ApplySettings(_passphrase_source=2, use_passphrase=True))
+ assert isinstance(resp, Success)
+
+ # Get a passphrase-less and a passphrased address.
+ session = _get_session(emu.client)
+ address = btc.get_address(session, "Bitcoin", PATH)
+ new_session = _get_session(emu.client, passphrase="TREZOR")
+ address_passphrase = btc.get_address(new_session, "Bitcoin", PATH)
+
+ assert emu.client.features.backup_availability == BackupAvailability.Required
+ storage = emu.get_storage()
+
+ with EmulatorWrapper(
+ model,
+ storage=storage,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ assert emu.client.features.device_id == device_id
+
+ # Create a backup of the encrypted master secret.
+ assert emu.client.features.backup_availability == BackupAvailability.Required
+ session = emu.client.get_seedless_session()
+ with emu.client as client:
+ IF = InputFlowSlip39BasicBackup(client, False)
+ client.set_input_flow(IF.get())
+ device.backup(session)
+ assert (
+ emu.client.features.backup_availability == BackupAvailability.NotAvailable
+ )
- # Create a backup of the encrypted master secret.
- assert (
- emu.client.features.backup_availability == BackupAvailability.Required
+ # Check the backup type.
+ assert emu.client.features.backup_type == backup_type
+ tag_version = version_from_tag(tag)
+ if tag_version is not None:
+ expected_backup_type = (
+ BackupType.Slip39_Basic
+ if tag_version < (2, 7, 1)
+ else BackupType.Slip39_Basic_Extendable
)
- session = emu.client.get_seedless_session()
- with emu.client as client:
- IF = InputFlowSlip39BasicBackup(client, False)
- client.set_input_flow(IF.get())
- device.backup(session)
- assert (
- emu.client.features.backup_availability
- == BackupAvailability.NotAvailable
- )
-
- # Check the backup type.
- assert emu.client.features.backup_type == backup_type
- tag_version = version_from_tag(tag)
- if tag_version is not None:
- assert (
- backup_type == BackupType.Slip39_Basic
- if tag_version < (2, 7, 1)
- else BackupType.Slip39_Basic_Extendable
- )
+ assert backup_type == expected_backup_type
- # Check that the backup contains the originally generated encrypted master secret.
- groups = shamir.decode_mnemonics(IF.mnemonics[:3])
- ems = shamir.recover_ems(groups)
- assert ems.ciphertext == mnemonic_secret
+ # Check that the backup contains the originally generated encrypted master secret.
+ groups = shamir.decode_mnemonics(IF.mnemonics[:3])
+ ems = shamir.recover_ems(groups)
+ assert ems.ciphertext == mnemonic_secret
- # Check that addresses are the same after firmware upgrade and backup.
- assert btc.get_address(_get_session(emu.client), "Bitcoin", PATH) == address
- assert (
- btc.get_address(
- _get_session(emu.client, passphrase="TREZOR"), "Bitcoin", PATH
- )
- == address_passphrase
+ # Check that addresses are the same after firmware upgrade and backup.
+ assert btc.get_address(_get_session(emu.client), "Bitcoin", PATH) == address
+ assert (
+ btc.get_address(
+ _get_session(emu.client, passphrase="TREZOR"), "Bitcoin", PATH
)
+ == address_passphrase
+ )
-@for_all(legacy_minimum_version=(1, 8, 4), core_minimum_version=(2, 1, 9))
+@for_all(t1b1_minimum_version=(1, 8, 4), t2t1_minimum_version=(2, 1, 9))
@lower_models_minimum_version
def test_upgrade_u2f(
tag: str | None,
model: str | None,
+ shared_profile_dir,
):
"""Check U2F counter stayed the same after an upgrade."""
- with shared_profile_dir() as profile_dir:
- with EmulatorWrapper(
- model,
- tag=tag,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- debuglink.load_device_by_mnemonic(
- emu.client.get_seedless_session(),
- mnemonic=MNEMONIC,
- pin="",
- passphrase_protection=False,
- label=LABEL,
- )
- session = emu.client.get_seedless_session()
- fido.set_counter(session, 10)
+ with EmulatorWrapper(
+ model,
+ tag=tag,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ debuglink.load_device_by_mnemonic(
+ emu.client.get_seedless_session(),
+ mnemonic=MNEMONIC,
+ pin="",
+ passphrase_protection=False,
+ label=LABEL,
+ )
+ session = emu.client.get_seedless_session()
+ fido.set_counter(session, 10)
- counter = fido.get_next_counter(session)
- assert counter == 11
- storage = emu.get_storage()
+ counter = fido.get_next_counter(session)
+ assert counter == 11
+ storage = emu.get_storage()
- with EmulatorWrapper(
- model,
- storage=storage,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- session = emu.client.get_seedless_session()
- counter = fido.get_next_counter(session)
- assert counter == 12
+ with EmulatorWrapper(
+ model,
+ storage=storage,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ session = emu.client.get_seedless_session()
+ counter = fido.get_next_counter(session)
+ assert counter == 12
@for_all("T2T1", "T3W1")
@@ -696,6 +664,7 @@ def test_cardano_address_does_not_change_by_upgrade(
model: str | None,
backup_type: BackupType,
derivation_type: CardanoDerivationType,
+ shared_profile_dir,
):
"""
Check that the Cardano address does not change after upgrading app storage from v2
@@ -712,41 +681,34 @@ def test_cardano_address_does_not_change_by_upgrade(
# SLIP-39 was not implemented for Cardano in v2.1.2
return
- with shared_profile_dir() as profile_dir:
- with EmulatorWrapper(
- model,
- tag=tag,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- device.setup(
- emu.client.get_seedless_session(),
- pin_protection=False,
- passphrase_protection=False,
- skip_backup=True,
- backup_type=backup_type,
- entropy_check_count=0,
- )
- session = emu.client.get_session(derive_cardano=True)
- old_key = get_public_key(
- session, ADDRESS_N, derivation_type, show_display=True
- )
- storage = emu.get_storage()
-
- with EmulatorWrapper(
- model,
- storage=storage,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- session = emu.client.get_session(derive_cardano=True)
- new_key = get_public_key(
- session, ADDRESS_N, derivation_type, show_display=True
- )
-
- assert old_key.xpub == new_key.xpub
- assert old_key.node.public_key == new_key.node.public_key
- assert old_key.node.chain_code == new_key.node.chain_code
+ with EmulatorWrapper(
+ model,
+ tag=tag,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ device.setup(
+ emu.client.get_seedless_session(),
+ pin_protection=False,
+ passphrase_protection=False,
+ skip_backup=True,
+ backup_type=backup_type,
+ entropy_check_count=0,
+ )
+ session = emu.client.get_session(derive_cardano=True)
+ old_key = get_public_key(session, ADDRESS_N, derivation_type, show_display=True)
+ storage = emu.get_storage()
+
+ with EmulatorWrapper(
+ model,
+ storage=storage,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ session = emu.client.get_session(derive_cardano=True)
+ new_key = get_public_key(session, ADDRESS_N, derivation_type, show_display=True)
+
+ assert old_key.xpub == new_key.xpub
+ assert old_key.node.public_key == new_key.node.public_key
+ assert old_key.node.chain_code == new_key.node.chain_code
if __name__ == "__main__":
diff --git a/tests/upgrade_tests/test_passphrase_consistency.py b/tests/upgrade_tests/test_passphrase_consistency.py
index 9d1d27f6..49d76f82 100644
--- a/tests/upgrade_tests/test_passphrase_consistency.py
+++ b/tests/upgrade_tests/test_passphrase_consistency.py
@@ -22,8 +22,8 @@ from trezorlib import btc, device, mapping, messages, models, protobuf
from trezorlib._internal.emulator import Emulator
from trezorlib.tools import parse_path
-from ..emulators import EmulatorWrapper, is_tropic_capable_model
-from . import for_all, shared_profile_dir
+from ..emulators import EmulatorWrapper
+from . import for_all
SOURCE_ASK = 0
SOURCE_DEVICE = 1
@@ -43,37 +43,35 @@ mapping.DEFAULT_MAPPING.register(ApplySettingsCompat)
@pytest.fixture
-def emulator(tag: str, model: str) -> Iterator[Emulator]:
- with shared_profile_dir() as profile_dir:
- with EmulatorWrapper(
- model,
- tag=tag,
- profile_dir=profile_dir,
- prefer_nested=is_tropic_capable_model(model),
- ) as emu:
- # set up a passphrase-protected device
- device.setup(
- emu.client.get_seedless_session(),
- pin_protection=False,
- skip_backup=True,
- entropy_check_count=0,
- backup_type=messages.BackupType.Bip39,
- )
- emu.client.client._invalidate()
- resp = emu.client.get_seedless_session().call(
- ApplySettingsCompat(use_passphrase=True, passphrase_source=SOURCE_HOST)
- )
- assert isinstance(resp, messages.Success)
-
- yield emu
+def emulator(tag: str, model: str, shared_profile_dir) -> Iterator[Emulator]:
+ with EmulatorWrapper(
+ model,
+ tag=tag,
+ profile_dir=shared_profile_dir,
+ ) as emu:
+ # set up a passphrase-protected device
+ device.setup(
+ emu.client.get_seedless_session(),
+ pin_protection=False,
+ skip_backup=True,
+ entropy_check_count=0,
+ backup_type=messages.BackupType.Bip39,
+ )
+ emu.client.client._invalidate()
+ resp = emu.client.get_seedless_session().call(
+ ApplySettingsCompat(use_passphrase=True, passphrase_source=SOURCE_HOST)
+ )
+ assert isinstance(resp, messages.Success)
+
+ yield emu
@for_all(
"T1B1",
"T2T1",
"T3W1",
- legacy_minimum_version=models.TREZOR_ONE.minimum_version,
- core_minimum_version=models.TREZOR_T.minimum_version,
+ t1b1_minimum_version=models.T1B1.minimum_version,
+ t2t1_minimum_version=models.T2T1.minimum_version,
)
def test_passphrase_works(emulator: Emulator):
"""Check that passphrase handling in trezorlib works correctly in all versions."""
@@ -116,8 +114,8 @@ def test_passphrase_works(emulator: Emulator):
"T1B1",
"T2T1",
"T3W1",
- legacy_minimum_version=(1, 9, 0),
- core_minimum_version=models.TREZOR_T.minimum_version,
+ t1b1_minimum_version=(1, 9, 0),
+ t2t1_minimum_version=models.T2T1.minimum_version,
)
def test_init_device(emulator: Emulator):
"""Check that passphrase caching and session_id retaining works correctly across
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.