tests(upgrade): migrate upgrade suites to direct EmulatorWrapper flow
What changed, and why it matters
This commit only changes automated test code for firmware upgrade scenarios. It does not modify the Trezor firmware itself, wallet logic, or any code that runs on user devices. There is no security-relevant change to end users.
No action required; this is a test-only refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors two Python test files under tests/upgrade_tests to use a new EmulatorWrapper calling convention (passing model directly, adding shared_profile_dir, prefer_nested for tropic-capable models) and removes legacy protocol-v1 session handling. It is a test-infrastructure migration with no changes to firmware, crypto, storage parsing, or device behavior.
Changed components
tests/upgrade_tests/test_firmware_upgrades.pytests/upgrade_tests/test_passphrase_consistency.pyInspect captured patch +509 / −350
diff --git a/tests/upgrade_tests/test_firmware_upgrades.py b/tests/upgrade_tests/test_firmware_upgrades.py
index e7b18a30..2e03c640 100644
--- a/tests/upgrade_tests/test_firmware_upgrades.py
+++ b/tests/upgrade_tests/test_firmware_upgrades.py
@@ -22,7 +22,7 @@ from typing import TYPE_CHECKING, List
import pytest
from shamir_mnemonic import shamir
-from trezorlib import btc, debuglink, device, exceptions, fido, messages, models
+from trezorlib import btc, debuglink, device, exceptions, fido, models
from trezorlib.cardano import get_public_key
from trezorlib.messages import (
ApplySettings,
@@ -37,9 +37,16 @@ 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 ALL_TAGS, EmulatorWrapper
+from ..emulators import EmulatorWrapper, is_tropic_capable_model
from ..input_flows import InputFlowSlip39BasicBackup
-from . import for_all, for_tags, recovery_old, version_from_tag
+from . import (
+ ALL_TAGS,
+ for_all,
+ for_tags,
+ recovery_old,
+ shared_profile_dir,
+ version_from_tag,
+)
if TYPE_CHECKING:
from trezorlib.client import Session
@@ -82,36 +89,15 @@ def lower_models_minimum_version(func):
return wrapper
-def _get_session(client: "Client", passphrase: str | object = "") -> "Session":
- if not client.is_protocol_v1():
- return client.get_session(passphrase=passphrase)
- if client.version >= (2, 3, 0):
- return client.get_session(passphrase=passphrase)
-
- from trezorlib.client import SessionV1
-
- from ..common import TEST_ADDRESS_N
-
- session = SessionV1.new(client)
- resp = session.call_raw(
- messages.GetAddress(address_n=TEST_ADDRESS_N, coin_name="Testnet")
- )
- if isinstance(resp, messages.ButtonRequest):
- resp = session._callback_button(resp)
- if isinstance(resp, messages.PassphraseRequest):
- resp = session.call_raw(messages.PassphraseAck(passphrase=passphrase))
- if isinstance(resp, messages.Deprecated_PassphraseStateRequest):
- session.id = resp.state
- resp = session.call_raw(messages.Deprecated_PassphraseStateAck())
- while isinstance(resp, messages.ButtonRequest):
- resp = session._callback_button(resp)
- return session
+def _get_session(client: "Client", passphrase: str | None = "") -> "Session":
+ # For now, just use the standard get_session method
+ # The special handling for protocol v1 < 2.3.0 is no longer needed
+ return client.get_session(passphrase=passphrase)
@for_all()
@lower_models_minimum_version
def test_upgrade_load(
- gen: str,
tag: str | None,
model: str | None,
) -> None:
@@ -126,27 +112,37 @@ def test_upgrade_load(
== ADDRESS
)
- with EmulatorWrapper(gen, tag, 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 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(gen, storage=storage) as emu:
- assert device_id == emu.client.features.device_id
- asserts(emu.client)
+ 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)
-@for_all("legacy")
+@for_all("T1B1")
@lower_models_minimum_version
def test_upgrade_load_pin(
- gen: str,
tag: str | None,
model: str | None,
) -> None:
@@ -162,21 +158,32 @@ def test_upgrade_load_pin(
session = client.get_session()
assert btc.get_address(session, "Bitcoin", PATH) == ADDRESS
- with EmulatorWrapper(gen, tag, 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 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(gen, storage=storage) as emu:
- assert device_id == emu.client.features.device_id
- asserts(emu.client)
+ 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)
# Test progressive upgrade of storage versions without unlocking in between.
@@ -186,13 +193,13 @@ def test_upgrade_load_pin(
# Storage Version 2: since legacy-v1.9.0 and core-v2.3.0 (wipe code)
# Storage Version 3: since legacy-v1.10.0 and core-v2.4.0 (long PIN)
@for_tags(
- ("legacy", ["v1.7.0", "v1.8.0", "v1.9.0"]),
- ("legacy", ["v1.7.0", "v1.8.0"]),
- ("legacy", ["v1.7.0", "v1.9.0"]),
- ("legacy", ["v1.8.0", "v1.9.0"]),
+ ("T1B1", ["v1.7.0", "v1.8.0", "v1.9.0"]),
+ ("T1B1", ["v1.7.0", "v1.8.0"]),
+ ("T1B1", ["v1.7.0", "v1.9.0"]),
+ ("T1B1", ["v1.8.0", "v1.9.0"]),
)
@lower_models_minimum_version
-def test_storage_upgrade_progressive(gen: str, tags: List[str]):
+def test_storage_upgrade_progressive(tags: List[str], model: str):
PIN = "1234"
def asserts(client: "Client") -> None:
@@ -203,31 +210,47 @@ def test_storage_upgrade_progressive(gen: str, tags: List[str]):
client.use_pin_sequence([PIN])
assert btc.get_address(client.get_session(), "Bitcoin", PATH) == ADDRESS
- with EmulatorWrapper(gen, tags[0], model="T1B1") 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(gen, tag, model="T1B1", storage=storage) as emu:
+ 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()
- with EmulatorWrapper(gen, storage=storage) as emu:
- assert device_id == emu.client.features.device_id
- asserts(emu.client)
-
-
-@for_all("legacy", legacy_minimum_version=(1, 9, 0))
+ 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,
+ 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)
+
+
+@for_all("T1B1", legacy_minimum_version=(1, 9, 0))
@lower_models_minimum_version
def test_upgrade_wipe_code(
- gen: str,
tag: str | None,
model: str | None,
):
@@ -242,44 +265,54 @@ def test_upgrade_wipe_code(
client.use_pin_sequence([PIN])
assert btc.get_address(client.get_session(), "Bitcoin", PATH) == ADDRESS
- with EmulatorWrapper(gen, tag, model) as emu:
- debuglink.load_device_by_mnemonic(
- emu.client.get_seedless_session(),
- mnemonic=MNEMONIC,
- pin=PIN,
- passphrase_protection=False,
- label=LABEL,
- )
+ 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(gen, storage=storage) 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)
+ # 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()
-@for_all("legacy")
+ 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)
+
+ # 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")
@lower_models_minimum_version
def test_upgrade_reset(
- gen: str,
tag: str | None,
model: str | None,
):
@@ -292,31 +325,41 @@ def test_upgrade_reset(
assert not client.features.unfinished_backup
assert not client.features.no_backup
- with EmulatorWrapper(gen, tag, 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 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(gen, storage=storage) 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=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()
@lower_models_minimum_version
def test_upgrade_reset_skip_backup(
- gen: str,
tag: str | None,
model: str | None,
):
@@ -329,32 +372,42 @@ def test_upgrade_reset_skip_backup(
assert not client.features.unfinished_backup
assert not client.features.no_backup
- with EmulatorWrapper(gen, tag, 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 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(gen, storage=storage) 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=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))
@lower_models_minimum_version
def test_upgrade_reset_no_backup(
- gen: str,
tag: str | None,
model: str | None,
):
@@ -367,193 +420,271 @@ def test_upgrade_reset_no_backup(
assert not client.features.unfinished_backup
assert client.features.no_backup
- with EmulatorWrapper(gen, tag, 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 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,
+ )
- 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(gen, storage=storage) 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=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
# Although Shamir was introduced in 2.1.2 already, the debug instrumentation was not present until 2.1.9.
-@for_all("core", core_minimum_version=(2, 1, 9))
+@for_all("T2T1", "T3W1", core_minimum_version=(2, 1, 9))
@lower_models_minimum_version
def test_upgrade_shamir_recovery(
- gen: str,
tag: str | None,
model: str | None,
):
- with (
- EmulatorWrapper(gen, tag, 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()
-
- device_handler.run_with_session(
- device.recover, seedless=True, pin_protection=False
- )
+ 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()
- 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()
+ device_handler.run_with_session(
+ device.recover, seedless=True, pin_protection=False
)
- device_id = emu.client.features.device_id
- storage = emu.get_storage()
- device_handler.check_finalize()
-
- with EmulatorWrapper(gen, storage=storage) 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)
-
- # second share
- layout = recovery.enter_share(debug, MNEMONIC_SLIP39_BASIC_20_3of6[2])
- assert (
- "2 of 3 shares entered" in layout.text_content()
- or "1 more share" in layout.text_content()
- )
-
- # last one
- layout = recovery.enter_share(debug, MNEMONIC_SLIP39_BASIC_20_3of6[1])
- 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("core", core_minimum_version=(2, 1, 9))
+ 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=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
+ )
+ 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))
@lower_models_minimum_version
def test_upgrade_shamir_backup(
- gen: str,
tag: str | None,
model: str | None,
):
- with EmulatorWrapper(gen, tag, 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(gen, storage=storage) 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
- )
+ 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)
- # 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
+ emu.client.features.backup_availability == BackupAvailability.Required
)
+ storage = emu.get_storage()
- # 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
+ 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
- # 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
+ # 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
+ )
+
+ # 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
+ )
+
+ # 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
)
- == address_passphrase
- )
@for_all(legacy_minimum_version=(1, 8, 4), core_minimum_version=(2, 1, 9))
@lower_models_minimum_version
def test_upgrade_u2f(
- gen: str,
tag: str | None,
model: str | None,
):
"""Check U2F counter stayed the same after an upgrade."""
- with EmulatorWrapper(gen, tag, 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 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)
- 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(gen, storage=storage) as emu:
- session = emu.client.get_seedless_session()
- counter = fido.get_next_counter(session)
- assert counter == 12
+ 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
-@for_all("core")
+@for_all("T2T1", "T3W1")
@lower_models_minimum_version
@pytest.mark.parametrize("backup_type", [BackupType.Bip39, BackupType.Slip39_Basic])
@pytest.mark.parametrize(
@@ -561,9 +692,8 @@ def test_upgrade_u2f(
[CardanoDerivationType.ICARUS, CardanoDerivationType.ICARUS_TREZOR],
)
def test_cardano_address_does_not_change_by_upgrade(
- gen: str,
- tag: str,
- model: str,
+ tag: str | None,
+ model: str | None,
backup_type: BackupType,
derivation_type: CardanoDerivationType,
):
@@ -582,26 +712,41 @@ def test_cardano_address_does_not_change_by_upgrade(
# SLIP-39 was not implemented for Cardano in v2.1.2
return
- with EmulatorWrapper(gen, tag, 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 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(gen, storage=storage) as emu:
- session = emu.client.get_session(derive_cardano=True)
- new_key = get_public_key(session, ADDRESS_N, derivation_type, show_display=True)
+ 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
+ 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 6252549d..9d1d27f6 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
-from . import for_all
+from ..emulators import EmulatorWrapper, is_tropic_capable_model
+from . import for_all, shared_profile_dir
SOURCE_ASK = 0
SOURCE_DEVICE = 1
@@ -43,28 +43,37 @@ mapping.DEFAULT_MAPPING.register(ApplySettingsCompat)
@pytest.fixture
-def emulator(gen: str, tag: str, model: str) -> Iterator[Emulator]:
- with EmulatorWrapper(gen, tag, 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) -> 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
@for_all(
- core_minimum_version=models.TREZOR_T.minimum_version,
+ "T1B1",
+ "T2T1",
+ "T3W1",
legacy_minimum_version=models.TREZOR_ONE.minimum_version,
+ core_minimum_version=models.TREZOR_T.minimum_version,
)
def test_passphrase_works(emulator: Emulator):
"""Check that passphrase handling in trezorlib works correctly in all versions."""
@@ -97,14 +106,18 @@ def test_passphrase_works(emulator: Emulator):
messages.Address,
]
with emulator.client as client:
- client.set_expected_responses(expected_responses)
+ if not client.is_thp():
+ client.set_expected_responses(expected_responses)
session = client.get_session(passphrase="TREZOR")
btc.get_address(session, "Testnet", parse_path("44h/1h/0h/0/0"))
@for_all(
- core_minimum_version=models.TREZOR_T.minimum_version,
+ "T1B1",
+ "T2T1",
+ "T3W1",
legacy_minimum_version=(1, 9, 0),
+ core_minimum_version=models.TREZOR_T.minimum_version,
)
def test_init_device(emulator: Emulator):
"""Check that passphrase caching and session_id retaining works correctly across
@@ -142,7 +155,8 @@ def test_init_device(emulator: Emulator):
]
with emulator.client as client:
- client.set_expected_responses(expected_responses)
+ if not client.is_thp():
+ client.set_expected_responses(expected_responses)
session = client.get_session(passphrase="TREZOR")
btc.get_address(session, "Testnet", parse_path("44h/1h/0h/0/0"))
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.