test(core): add T3T1 support

[no changelog]
pull/3601/head
Martin Milata 2 months ago
parent ebb480ef29
commit 73a7223e7b

@ -13,8 +13,9 @@ env:
PULL_COMMENT: | PULL_COMMENT: |
|core UI changes|device test|click test|persistence test| |core UI changes|device test|click test|persistence test|
|---------------|-----------|----------|----------------| |---------------|-----------|----------|----------------|
|Model T |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_device_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_device_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_device_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_device_test/master_diff.html)) |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_click_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_click_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_click_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_click_test/master_diff.html)) |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_persistence_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_persistence_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_persistence_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_persistence_test/master_diff.html))|| |T2T1 Model T |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_device_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_device_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_device_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_device_test/master_diff.html)) |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_click_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_click_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_click_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_click_test/master_diff.html)) |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_persistence_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_persistence_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_persistence_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2T1-core_persistence_test/master_diff.html))||
|Model Safe 3 |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_device_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_device_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_device_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_device_test/master_diff.html)) |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_click_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_click_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_click_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_click_test/master_diff.html)) |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_persistence_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_persistence_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_persistence_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_persistence_test/master_diff.html))|| |T2B1 Safe 3 |[#3280](https://github.com/trezor/trezor-firmware/issues/3280) |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_click_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_click_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_click_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T2B1-core_click_test/master_diff.html)) |[#2724](https://github.com/trezor/trezor-firmware/issues/2724) ||
|T3T1 |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T3T1-core_device_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T3T1-core_device_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T3T1-core_device_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T3T1-core_device_test/master_diff.html)) |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T3T1-core_click_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T3T1-core_click_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T3T1-core_click_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T3T1-core_click_test/master_diff.html)) |[test](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T3T1-core_persistence_test/index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T3T1-core_persistence_test/differing_screens.html)) [main](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T3T1-core_persistence_test/master_index.html)([screens](https://data.trezor.io/dev/firmware/ui_report/${{ github.run_id }}/T3T1-core_persistence_test/master_diff.html))||
|All |[main](https://data.trezor.io/dev/firmware/master_diff/${{ github.run_id }}/index.html)([screens](https://data.trezor.io/dev/firmware/master_diff/${{ github.run_id }}/master_diff.html)) || |All |[main](https://data.trezor.io/dev/firmware/master_diff/${{ github.run_id }}/index.html)([screens](https://data.trezor.io/dev/firmware/master_diff/${{ github.run_id }}/master_diff.html)) ||
jobs: jobs:

@ -170,14 +170,14 @@ if __debug__:
# Incrementing the counter for last events so we know what to await # Incrementing the counter for last events so we know what to await
debug_events.last_event += 1 debug_events.last_event += 1
# TT click on specific coordinates, with possible hold # Touchscreen devices click on specific coordinates, with possible hold
if ( if (
x is not None x is not None
and y is not None and y is not None
and utils.INTERNAL_MODEL in ("T2T1", "T3T1", "D001") and utils.INTERNAL_MODEL in ("T2T1", "T3T1", "D001")
): ):
click_chan.publish((debug_events.last_event, x, y, msg.hold_ms)) click_chan.publish((debug_events.last_event, x, y, msg.hold_ms))
# TR press specific button # Button devices press specific button
elif msg.physical_button is not None and utils.INTERNAL_MODEL in ("T2B1",): elif msg.physical_button is not None and utils.INTERNAL_MODEL in ("T2B1",):
button_chan.publish( button_chan.publish(
(debug_events.last_event, msg.physical_button, msg.hold_ms) (debug_events.last_event, msg.physical_button, msg.hold_ms)

@ -319,5 +319,5 @@ class TestNemHDNode(unittest.TestCase):
if __name__ == "__main__": if __name__ == "__main__":
if not utils.MODEL_IS_T2B1: if utils.INTERNAL_MODEL == "T2T1":
unittest.main() unittest.main()

@ -109,6 +109,7 @@ Tests can be run only for specific models - it is done by disallowing the tests
`@pytest.mark.skip_t1` `@pytest.mark.skip_t1`
`@pytest.mark.skip_t2` `@pytest.mark.skip_t2`
`@pytest.mark.skip_tr` `@pytest.mark.skip_tr`
`@pytest.mark.skip_t3t1`
are valid markers to skip current test for T1, TT and TR respectively. are valid markers to skip current test for T1, TT and TR respectively.
[pytest-random-order]: https://pypi.org/project/pytest-random-order/ [pytest-random-order]: https://pypi.org/project/pytest-random-order/

@ -44,7 +44,7 @@ from typing import (
from mnemonic import Mnemonic from mnemonic import Mnemonic
from typing_extensions import Literal from typing_extensions import Literal
from . import mapping, messages, protobuf from . import mapping, messages, models, protobuf
from .client import TrezorClient from .client import TrezorClient
from .exceptions import TrezorFailure from .exceptions import TrezorFailure
from .log import DUMP_BYTES from .log import DUMP_BYTES
@ -368,7 +368,7 @@ class DebugLink:
self.mapping = mapping.DEFAULT_MAPPING self.mapping = mapping.DEFAULT_MAPPING
# To be set by TrezorClientDebugLink (is not known during creation time) # To be set by TrezorClientDebugLink (is not known during creation time)
self.model: Optional[str] = None self.model: Optional[models.TrezorModel] = None
self.version: Tuple[int, int, int] = (0, 0, 0) self.version: Tuple[int, int, int] = (0, 0, 0)
# Where screenshots are being saved # Where screenshots are being saved
@ -452,7 +452,7 @@ class DebugLink:
def reset_debug_events(self) -> None: def reset_debug_events(self) -> None:
# Only supported on TT and above certain version # Only supported on TT and above certain version
if self.model in ("T", "Safe 3") and not self.legacy_debug: if (self.model is not models.T1B1) and not self.legacy_debug:
return self._call(messages.DebugLinkResetDebugEvents()) return self._call(messages.DebugLinkResetDebugEvents())
return None return None
@ -691,7 +691,7 @@ class DebugLink:
) -> None: ) -> None:
self.screenshot_recording_dir = directory self.screenshot_recording_dir = directory
# Different recording logic between core and legacy # Different recording logic between core and legacy
if self.model in ("T", "Safe 3"): if self.model is not models.T1B1:
self._call( self._call(
messages.DebugLinkRecordScreen( messages.DebugLinkRecordScreen(
target_directory=directory, refresh_index=refresh_index target_directory=directory, refresh_index=refresh_index
@ -705,7 +705,7 @@ class DebugLink:
def stop_recording(self) -> None: def stop_recording(self) -> None:
self.screenshot_recording_dir = None self.screenshot_recording_dir = None
# Different recording logic between TT and T1 # Different recording logic between TT and T1
if self.model in ("T", "Safe 3"): if self.model is not models.T1B1:
self._call(messages.DebugLinkRecordScreen(target_directory=None)) self._call(messages.DebugLinkRecordScreen(target_directory=None))
else: else:
self.t1_take_screenshots = False self.t1_take_screenshots = False
@ -732,7 +732,7 @@ class DebugLink:
TT handles them differently, see debuglink.start_recording. TT handles them differently, see debuglink.start_recording.
""" """
if self.model == "1" and self.t1_take_screenshots: if self.model is models.T1B1 and self.t1_take_screenshots:
self.save_screenshot_for_t1() self.save_screenshot_for_t1()
def save_screenshot_for_t1(self) -> None: def save_screenshot_for_t1(self) -> None:
@ -962,7 +962,7 @@ class TrezorClientDebugLink(TrezorClient):
# So that we can choose right screenshotting logic (T1 vs TT) # So that we can choose right screenshotting logic (T1 vs TT)
# and know the supported debug capabilities # and know the supported debug capabilities
self.debug.model = self.features.model self.debug.model = self.model
self.debug.version = self.version self.debug.version = self.version
def reset_debug_features(self) -> None: def reset_debug_features(self) -> None:

@ -3,6 +3,8 @@ from __future__ import annotations
from enum import Enum from enum import Enum
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from trezorlib import models
from .. import buttons from .. import buttons
from .. import translations as TR from .. import translations as TR
@ -44,9 +46,9 @@ def get_char_category(char: str) -> PassphraseCategory:
def go_next(debug: "DebugLink", wait: bool = False) -> "LayoutContent" | None: def go_next(debug: "DebugLink", wait: bool = False) -> "LayoutContent" | None:
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
return debug.click(buttons.OK, wait=wait) # type: ignore return debug.click(buttons.OK, wait=wait) # type: ignore
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
return debug.press_right(wait=wait) # type: ignore return debug.press_right(wait=wait) # type: ignore
else: else:
raise RuntimeError("Unknown model") raise RuntimeError("Unknown model")
@ -55,9 +57,10 @@ def go_next(debug: "DebugLink", wait: bool = False) -> "LayoutContent" | None:
def go_back( def go_back(
debug: "DebugLink", wait: bool = False, r_middle: bool = False debug: "DebugLink", wait: bool = False, r_middle: bool = False
) -> "LayoutContent" | None: ) -> "LayoutContent" | None:
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
return debug.click(buttons.CANCEL, wait=wait) # type: ignore return debug.click(buttons.CANCEL, wait=wait) # type: ignore
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
if r_middle: if r_middle:
return debug.press_middle(wait=wait) # type: ignore return debug.press_middle(wait=wait) # type: ignore
else: else:

@ -1,5 +1,7 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from trezorlib import models
from .. import buttons from .. import buttons
from .. import translations as TR from .. import translations as TR
from .common import get_possible_btn_texts, go_next from .common import get_possible_btn_texts, go_next
@ -16,13 +18,13 @@ DELETE_BTN_TEXTS = get_possible_btn_texts("inputs__delete") + get_possible_btn_t
def enter_word( def enter_word(
debug: "DebugLink", word: str, is_slip39: bool = False debug: "DebugLink", word: str, is_slip39: bool = False
) -> "LayoutContent": ) -> "LayoutContent":
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
typed_word = word[:4] typed_word = word[:4]
for coords in buttons.type_word(typed_word, is_slip39=is_slip39): for coords in buttons.type_word(typed_word, is_slip39=is_slip39):
debug.click(coords) debug.click(coords)
return debug.click(buttons.CONFIRM_WORD, wait=True) return debug.click(buttons.CONFIRM_WORD, wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
letter_index = 0 letter_index = 0
layout = debug.read_layout() layout = debug.read_layout()
@ -47,9 +49,9 @@ def enter_word(
def confirm_recovery(debug: "DebugLink") -> None: def confirm_recovery(debug: "DebugLink") -> None:
layout = debug.wait_layout() layout = debug.wait_layout()
TR.assert_equals(layout.title(), "recovery__title") TR.assert_equals(layout.title(), "recovery__title")
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click(buttons.OK, wait=True) debug.click(buttons.OK, wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
debug.press_right(wait=True) debug.press_right(wait=True)
debug.press_right() debug.press_right()
@ -60,7 +62,7 @@ def select_number_of_words(
if wait: if wait:
debug.wait_layout() debug.wait_layout()
TR.assert_equals(debug.read_layout().text_content(), "recovery__num_of_words") TR.assert_equals(debug.read_layout().text_content(), "recovery__num_of_words")
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
# click the number # click the number
word_option_offset = 6 word_option_offset = 6
word_options = (12, 18, 20, 24, 33) word_options = (12, 18, 20, 24, 33)
@ -69,7 +71,7 @@ def select_number_of_words(
) # raises if num of words is invalid ) # raises if num of words is invalid
coords = buttons.grid34(index % 3, index // 3) coords = buttons.grid34(index % 3, index // 3)
layout = debug.click(coords, wait=True) layout = debug.click(coords, wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
layout = debug.press_right(wait=True) layout = debug.press_right(wait=True)
TR.assert_equals(layout.title(), "word_count__title") TR.assert_equals(layout.title(), "word_count__title")
@ -92,7 +94,7 @@ def enter_share(
debug: "DebugLink", share: str, is_first: bool = True debug: "DebugLink", share: str, is_first: bool = True
) -> "LayoutContent": ) -> "LayoutContent":
TR.assert_in(debug.read_layout().title(), "recovery__title_recover") TR.assert_in(debug.read_layout().title(), "recovery__title_recover")
if debug.model == "Safe 3": if debug.model in (models.T2B1,):
layout = debug.wait_layout() layout = debug.wait_layout()
for _ in range(layout.page_count()): for _ in range(layout.page_count()):
layout = debug.press_right(wait=True) layout = debug.press_right(wait=True)
@ -146,11 +148,11 @@ def enter_seed_previous_correct(
if go_back: if go_back:
go_back = False go_back = False
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.swipe_right(wait=True) debug.swipe_right(wait=True)
for _ in range(len(bad_word)): for _ in range(len(bad_word)):
debug.click(buttons.RECOVERY_DELETE, wait=True) debug.click(buttons.RECOVERY_DELETE, wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
layout = debug.read_layout() layout = debug.read_layout()
while layout.get_middle_choice() not in DELETE_BTN_TEXTS: while layout.get_middle_choice() not in DELETE_BTN_TEXTS:
@ -177,9 +179,9 @@ def enter_seed_previous_correct(
def prepare_enter_seed(debug: "DebugLink") -> None: def prepare_enter_seed(debug: "DebugLink") -> None:
TR.assert_in(debug.read_layout().text_content(), "recovery__enter_backup") TR.assert_in(debug.read_layout().text_content(), "recovery__enter_backup")
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click(buttons.OK, wait=True) debug.click(buttons.OK, wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
debug.press_right(wait=True) debug.press_right(wait=True)
TR.assert_equals(debug.read_layout().title(), "recovery__title_recover") TR.assert_equals(debug.read_layout().title(), "recovery__title_recover")
debug.press_right() debug.press_right()

@ -3,7 +3,7 @@ from typing import TYPE_CHECKING
from shamir_mnemonic import shamir # type: ignore from shamir_mnemonic import shamir # type: ignore
from trezorlib import messages from trezorlib import messages, models
from .. import buttons from .. import buttons
from .. import translations as TR from .. import translations as TR
@ -17,17 +17,17 @@ def confirm_new_wallet(debug: "DebugLink") -> None:
debug.read_layout().title(), debug.read_layout().title(),
["reset__title_create_wallet", "reset__title_create_wallet_shamir"], ["reset__title_create_wallet", "reset__title_create_wallet_shamir"],
) )
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click(buttons.OK, wait=True) debug.click(buttons.OK, wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
debug.press_right(wait=True) debug.press_right(wait=True)
debug.press_right(wait=True) debug.press_right(wait=True)
def confirm_read(debug: "DebugLink", middle_r: bool = False) -> None: def confirm_read(debug: "DebugLink", middle_r: bool = False) -> None:
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click(buttons.OK, wait=True) debug.click(buttons.OK, wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
page_count = debug.read_layout().page_count() page_count = debug.read_layout().page_count()
if page_count > 1: if page_count > 1:
for _ in range(page_count - 1): for _ in range(page_count - 1):
@ -39,12 +39,12 @@ def confirm_read(debug: "DebugLink", middle_r: bool = False) -> None:
def set_selection(debug: "DebugLink", button: tuple[int, int], diff: int) -> None: def set_selection(debug: "DebugLink", button: tuple[int, int], diff: int) -> None:
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
assert "NumberInputDialog" in debug.read_layout().all_components() assert "NumberInputDialog" in debug.read_layout().all_components()
for _ in range(diff): for _ in range(diff):
debug.click(button) debug.click(button)
debug.click(buttons.OK, wait=True) debug.click(buttons.OK, wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
layout = debug.read_layout() layout = debug.read_layout()
if layout.title() in TR.translate( if layout.title() in TR.translate(
"reset__title_number_of_shares" "reset__title_number_of_shares"
@ -66,7 +66,7 @@ def read_words(
) -> list[str]: ) -> list[str]:
words: list[str] = [] words: list[str] = []
if debug.model == "Safe 3": if debug.model in (models.T2B1,):
debug.press_right(wait=True) debug.press_right(wait=True)
# Swiping through all the pages and loading the words # Swiping through all the pages and loading the words
@ -75,14 +75,14 @@ def read_words(
words.extend(layout.seed_words()) words.extend(layout.seed_words())
layout = debug.swipe_up(wait=True) layout = debug.swipe_up(wait=True)
assert layout is not None assert layout is not None
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
words.extend(layout.seed_words()) words.extend(layout.seed_words())
# There is hold-to-confirm button # There is hold-to-confirm button
if do_htc: if do_htc:
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click_hold(buttons.OK, hold_ms=1500) debug.click_hold(buttons.OK, hold_ms=1500)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
debug.press_right_htc(1200) debug.press_right_htc(1200)
else: else:
# It would take a very long time to test 16-of-16 with doing 1500 ms HTC after # It would take a very long time to test 16-of-16 with doing 1500 ms HTC after
@ -94,7 +94,7 @@ def read_words(
def confirm_words(debug: "DebugLink", words: list[str]) -> None: def confirm_words(debug: "DebugLink", words: list[str]) -> None:
layout = debug.wait_layout() layout = debug.wait_layout()
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
TR.assert_template(layout.text_content(), "reset__select_word_x_of_y_template") TR.assert_template(layout.text_content(), "reset__select_word_x_of_y_template")
for _ in range(3): for _ in range(3):
# "Select word 3 of 20" # "Select word 3 of 20"
@ -109,7 +109,7 @@ def confirm_words(debug: "DebugLink", words: list[str]) -> None:
wanted_word = words[word_pos - 1].lower() wanted_word = words[word_pos - 1].lower()
button_pos = btn_texts.index(wanted_word) button_pos = btn_texts.index(wanted_word)
layout = debug.click(buttons.RESET_WORD_CHECK[button_pos], wait=True) layout = debug.click(buttons.RESET_WORD_CHECK[button_pos], wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
TR.assert_in(layout.text_content(), "reset__select_correct_word") TR.assert_in(layout.text_content(), "reset__select_correct_word")
layout = debug.press_right(wait=True) layout = debug.press_right(wait=True)
for _ in range(3): for _ in range(3):

@ -20,7 +20,7 @@ from typing import TYPE_CHECKING
import pytest import pytest
from trezorlib import btc, device, exceptions, messages from trezorlib import btc, device, exceptions, messages, models
from trezorlib.protobuf import MessageType from trezorlib.protobuf import MessageType
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
@ -102,12 +102,12 @@ def test_autolock_interrupts_signing(device_handler: "BackgroundDeviceHandler"):
in debug.wait_layout().text_content().replace(" ", "") in debug.wait_layout().text_content().replace(" ", "")
) )
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click(buttons.OK, wait=True) debug.click(buttons.OK, wait=True)
layout = debug.click(buttons.OK, wait=True) layout = debug.click(buttons.OK, wait=True)
TR.assert_in(layout.text_content(), "send__total_amount") TR.assert_in(layout.text_content(), "send__total_amount")
assert "0.0039 BTC" in layout.text_content() assert "0.0039 BTC" in layout.text_content()
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
debug.press_right(wait=True) debug.press_right(wait=True)
layout = debug.press_right(wait=True) layout = debug.press_right(wait=True)
TR.assert_in(layout.text_content(), "send__total_amount") TR.assert_in(layout.text_content(), "send__total_amount")
@ -149,12 +149,12 @@ def test_autolock_does_not_interrupt_signing(device_handler: "BackgroundDeviceHa
in debug.wait_layout().text_content().replace(" ", "") in debug.wait_layout().text_content().replace(" ", "")
) )
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click(buttons.OK, wait=True) debug.click(buttons.OK, wait=True)
layout = debug.click(buttons.OK, wait=True) layout = debug.click(buttons.OK, wait=True)
TR.assert_in(layout.text_content(), "send__total_amount") TR.assert_in(layout.text_content(), "send__total_amount")
assert "0.0039 BTC" in layout.text_content() assert "0.0039 BTC" in layout.text_content()
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
debug.press_right(wait=True) debug.press_right(wait=True)
layout = debug.press_right(wait=True) layout = debug.press_right(wait=True)
TR.assert_in(layout.text_content(), "send__total_amount") TR.assert_in(layout.text_content(), "send__total_amount")
@ -168,9 +168,9 @@ def test_autolock_does_not_interrupt_signing(device_handler: "BackgroundDeviceHa
with device_handler.client: with device_handler.client:
device_handler.client.set_filter(messages.TxAck, sleepy_filter) device_handler.client.set_filter(messages.TxAck, sleepy_filter)
# confirm transaction # confirm transaction
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click(buttons.OK) debug.click(buttons.OK)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
debug.press_middle() debug.press_middle()
signatures, tx = device_handler.result() signatures, tx = device_handler.result()
@ -190,17 +190,17 @@ def test_autolock_passphrase_keyboard(device_handler: "BackgroundDeviceHandler")
assert "PassphraseKeyboard" in debug.wait_layout().all_components() assert "PassphraseKeyboard" in debug.wait_layout().all_components()
if debug.model == "Safe 3": if debug.model in (models.T2B1,):
# Going into the selected character category # Going into the selected character category
debug.press_middle() debug.press_middle()
# enter passphrase - slowly # enter passphrase - slowly
# keep clicking for long enough to trigger the autolock if it incorrectly ignored key presses # keep clicking for long enough to trigger the autolock if it incorrectly ignored key presses
for _ in range(math.ceil(11 / 1.5)): for _ in range(math.ceil(11 / 1.5)):
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
# click at "j" # click at "j"
debug.click(CENTER_BUTTON) debug.click(CENTER_BUTTON)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
# just go right # just go right
# NOTE: because of passphrase randomization it would be a pain to input # NOTE: because of passphrase randomization it would be a pain to input
# a specific passphrase, which is not in scope for this test. # a specific passphrase, which is not in scope for this test.
@ -208,9 +208,9 @@ def test_autolock_passphrase_keyboard(device_handler: "BackgroundDeviceHandler")
time.sleep(1.5) time.sleep(1.5)
# Send the passphrase to the client (TT has it clicked already, TR needs to input it) # Send the passphrase to the client (TT has it clicked already, TR needs to input it)
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click(buttons.OK, wait=True) debug.click(buttons.OK, wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
debug.input("j" * 8, wait=True) debug.input("j" * 8, wait=True)
# address corresponding to "jjjjjjjj" passphrase # address corresponding to "jjjjjjjj" passphrase
@ -227,16 +227,16 @@ def test_autolock_interrupts_passphrase(device_handler: "BackgroundDeviceHandler
assert "PassphraseKeyboard" in debug.wait_layout().all_components() assert "PassphraseKeyboard" in debug.wait_layout().all_components()
if debug.model == "Safe 3": if debug.model in (models.T2B1,):
# Going into the selected character category # Going into the selected character category
debug.press_middle() debug.press_middle()
# enter passphrase - slowly # enter passphrase - slowly
# autolock must activate even if we pressed some buttons # autolock must activate even if we pressed some buttons
for _ in range(math.ceil(6 / 1.5)): for _ in range(math.ceil(6 / 1.5)):
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click(CENTER_BUTTON) debug.click(CENTER_BUTTON)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
debug.press_middle() debug.press_middle()
time.sleep(1.5) time.sleep(1.5)
@ -267,7 +267,7 @@ def test_dryrun_locks_at_number_of_words(device_handler: "BackgroundDeviceHandle
layout = unlock_dry_run(debug) layout = unlock_dry_run(debug)
TR.assert_in(debug.wait_layout().text_content(), "recovery__num_of_words") TR.assert_in(debug.wait_layout().text_content(), "recovery__num_of_words")
if debug.model == "Safe 3": if debug.model in (models.T2B1,):
debug.press_right(wait=True) debug.press_right(wait=True)
# wait for autolock to trigger # wait for autolock to trigger
@ -300,10 +300,10 @@ def test_dryrun_locks_at_word_entry(device_handler: "BackgroundDeviceHandler"):
# select 20 words # select 20 words
recovery.select_number_of_words(debug, 20) recovery.select_number_of_words(debug, 20)
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
layout = debug.click(buttons.OK, wait=True) layout = debug.click(buttons.OK, wait=True)
assert layout.main_component() == "MnemonicKeyboard" assert layout.main_component() == "MnemonicKeyboard"
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
layout = debug.press_right(wait=True) layout = debug.press_right(wait=True)
assert "MnemonicKeyboard" in layout.all_components() assert "MnemonicKeyboard" in layout.all_components()
@ -326,7 +326,7 @@ def test_dryrun_enter_word_slowly(device_handler: "BackgroundDeviceHandler"):
# select 20 words # select 20 words
recovery.select_number_of_words(debug, 20) recovery.select_number_of_words(debug, 20)
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
layout = debug.click(buttons.OK, wait=True) layout = debug.click(buttons.OK, wait=True)
assert layout.main_component() == "MnemonicKeyboard" assert layout.main_component() == "MnemonicKeyboard"
@ -337,7 +337,7 @@ def test_dryrun_enter_word_slowly(device_handler: "BackgroundDeviceHandler"):
layout = debug.click(buttons.CONFIRM_WORD, wait=True) layout = debug.click(buttons.CONFIRM_WORD, wait=True)
# should not have locked, even though we took 9 seconds to type each letter # should not have locked, even though we took 9 seconds to type each letter
assert layout.main_component() == "MnemonicKeyboard" assert layout.main_component() == "MnemonicKeyboard"
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
layout = debug.press_right(wait=True) layout = debug.press_right(wait=True)
assert "MnemonicKeyboard" in layout.all_components() assert "MnemonicKeyboard" in layout.all_components()

@ -19,6 +19,8 @@ from typing import TYPE_CHECKING
import pytest import pytest
from trezorlib import models
from .. import buttons, common from .. import buttons, common
if TYPE_CHECKING: if TYPE_CHECKING:
@ -32,11 +34,21 @@ PIN4 = "1234"
def test_hold_to_lock(device_handler: "BackgroundDeviceHandler"): def test_hold_to_lock(device_handler: "BackgroundDeviceHandler"):
debug = device_handler.debuglink() debug = device_handler.debuglink()
short_duration = 1000 if debug.model == "T" else 500 short_duration = {
lock_duration = 3500 if debug.model == "T" else 1200 models.T1B1: 500,
models.T2B1: 500,
models.T2T1: 1000,
models.T3T1: 1000,
}[debug.model]
lock_duration = {
models.T1B1: 1200,
models.T2B1: 1200,
models.T2T1: 3500,
models.T3T1: 3500,
}[debug.model]
def hold(duration: int, wait: bool = True) -> None: def hold(duration: int, wait: bool = True) -> None:
if debug.model == "Safe 3": if debug.model in (models.T2B1,):
debug.press_right_htc(hold_ms=duration) debug.press_right_htc(hold_ms=duration)
else: else:
debug.input(x=13, y=37, hold_ms=duration, wait=wait) debug.input(x=13, y=37, hold_ms=duration, wait=wait)
@ -63,7 +75,7 @@ def test_hold_to_lock(device_handler: "BackgroundDeviceHandler"):
assert device_handler.features().unlocked is False assert device_handler.features().unlocked is False
# unlock by touching # unlock by touching
if debug.model == "Safe 3": if debug.model in (models.T2B1,):
# Doing a short HTC to simulate a click # Doing a short HTC to simulate a click
debug.press_right_htc(hold_ms=100) debug.press_right_htc(hold_ms=100)
layout = debug.wait_layout() layout = debug.wait_layout()

@ -36,7 +36,7 @@ if TYPE_CHECKING:
from ..device_handler import BackgroundDeviceHandler from ..device_handler import BackgroundDeviceHandler
pytestmark = [pytest.mark.skip_t1, pytest.mark.skip_t2] pytestmark = [pytest.mark.skip_t1, pytest.mark.skip_t2, pytest.mark.skip_t3t1]
# Testing the maximum length is really 50 # Testing the maximum length is really 50
# TODO: show some UI message when length reaches 50? # TODO: show some UI message when length reaches 50?

@ -20,7 +20,7 @@ from typing import TYPE_CHECKING, Generator
import pytest import pytest
from trezorlib import device, exceptions from trezorlib import device, exceptions, models
from .. import buttons from .. import buttons
from .. import translations as TR from .. import translations as TR
@ -96,9 +96,9 @@ def prepare(
# Set new PIN # Set new PIN
device_handler.run(device.change_pin) # type: ignore device_handler.run(device.change_pin) # type: ignore
TR.assert_in(debug.wait_layout().text_content(), "pin__turn_on") TR.assert_in(debug.wait_layout().text_content(), "pin__turn_on")
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
go_next(debug) go_next(debug)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
go_next(debug, wait=True) go_next(debug, wait=True)
go_next(debug, wait=True) go_next(debug, wait=True)
go_next(debug, wait=True) go_next(debug, wait=True)
@ -117,7 +117,7 @@ def prepare(
_input_see_confirm(debug, old_pin) _input_see_confirm(debug, old_pin)
TR.assert_in(debug.wait_layout().text_content(), "wipe_code__turn_on") TR.assert_in(debug.wait_layout().text_content(), "wipe_code__turn_on")
go_next(debug, wait=True) go_next(debug, wait=True)
if debug.model == "Safe 3": if debug.model in (models.T2B1,):
go_next(debug, wait=True) go_next(debug, wait=True)
go_next(debug, wait=True) go_next(debug, wait=True)
go_next(debug, wait=True) go_next(debug, wait=True)
@ -141,13 +141,13 @@ def _input_pin(debug: "DebugLink", pin: str, check: bool = False) -> None:
if check: if check:
before = debug.read_layout().pin() before = debug.read_layout().pin()
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
digits_order = debug.read_layout().tt_pin_digits_order() digits_order = debug.read_layout().tt_pin_digits_order()
for digit in pin: for digit in pin:
digit_index = digits_order.index(digit) digit_index = digits_order.index(digit)
coords = buttons.pin_passphrase_index(digit_index) coords = buttons.pin_passphrase_index(digit_index)
debug.click(coords, wait=True) debug.click(coords, wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
for digit in pin: for digit in pin:
navigate_to_action_and_press(debug, digit, TR_PIN_ACTIONS) navigate_to_action_and_press(debug, digit, TR_PIN_ACTIONS)
@ -158,9 +158,9 @@ def _input_pin(debug: "DebugLink", pin: str, check: bool = False) -> None:
def _see_pin(debug: "DebugLink") -> None: def _see_pin(debug: "DebugLink") -> None:
"""Navigate to "SHOW" and press it""" """Navigate to "SHOW" and press it"""
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click(buttons.TOP_ROW, wait=True) debug.click(buttons.TOP_ROW, wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
navigate_to_action_and_press(debug, SHOW, TR_PIN_ACTIONS) navigate_to_action_and_press(debug, SHOW, TR_PIN_ACTIONS)
@ -170,9 +170,9 @@ def _delete_pin(debug: "DebugLink", digits_to_delete: int, check: bool = True) -
before = debug.read_layout().pin() before = debug.read_layout().pin()
for _ in range(digits_to_delete): for _ in range(digits_to_delete):
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click(buttons.pin_passphrase_grid(9), wait=True) debug.click(buttons.pin_passphrase_grid(9), wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
navigate_to_action_and_press(debug, DELETE, TR_PIN_ACTIONS) navigate_to_action_and_press(debug, DELETE, TR_PIN_ACTIONS)
if check: if check:
@ -182,9 +182,9 @@ def _delete_pin(debug: "DebugLink", digits_to_delete: int, check: bool = True) -
def _delete_all(debug: "DebugLink", check: bool = True) -> None: def _delete_all(debug: "DebugLink", check: bool = True) -> None:
"""Navigate to "DELETE" and hold it until all digits are deleted""" """Navigate to "DELETE" and hold it until all digits are deleted"""
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click_hold(buttons.pin_passphrase_grid(9), hold_ms=1500) debug.click_hold(buttons.pin_passphrase_grid(9), hold_ms=1500)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
navigate_to_action_and_press(debug, DELETE, TR_PIN_ACTIONS, hold_ms=1000) navigate_to_action_and_press(debug, DELETE, TR_PIN_ACTIONS, hold_ms=1000)
if check: if check:
@ -201,9 +201,9 @@ def _cancel_pin(debug: "DebugLink") -> None:
def _confirm_pin(debug: "DebugLink") -> None: def _confirm_pin(debug: "DebugLink") -> None:
"""Navigate to "ENTER" and press it""" """Navigate to "ENTER" and press it"""
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
debug.click(buttons.pin_passphrase_grid(11), wait=True) debug.click(buttons.pin_passphrase_grid(11), wait=True)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
navigate_to_action_and_press(debug, ENTER, TR_PIN_ACTIONS) navigate_to_action_and_press(debug, ENTER, TR_PIN_ACTIONS)
@ -216,7 +216,7 @@ def _input_see_confirm(debug: "DebugLink", pin: str) -> None:
def _enter_two_times(debug: "DebugLink", pin1: str, pin2: str) -> None: def _enter_two_times(debug: "DebugLink", pin1: str, pin2: str) -> None:
_input_see_confirm(debug, pin1) _input_see_confirm(debug, pin1)
if debug.model == "Safe 3": if debug.model in (models.T2B1,):
# Please re-enter # Please re-enter
go_next(debug, wait=True) go_next(debug, wait=True)
@ -306,10 +306,10 @@ def test_pin_setup(device_handler: "BackgroundDeviceHandler"):
def test_pin_setup_mismatch(device_handler: "BackgroundDeviceHandler"): def test_pin_setup_mismatch(device_handler: "BackgroundDeviceHandler"):
with PIN_CANCELLED, prepare(device_handler, Situation.PIN_SETUP) as debug: with PIN_CANCELLED, prepare(device_handler, Situation.PIN_SETUP) as debug:
_enter_two_times(debug, "1", "2") _enter_two_times(debug, "1", "2")
if debug.model == "T": if debug.model in (models.T2T1, models.T3T1):
go_next(debug) go_next(debug)
_cancel_pin(debug) _cancel_pin(debug)
elif debug.model == "Safe 3": elif debug.model in (models.T2B1,):
debug.press_middle() debug.press_middle()
debug.press_no() debug.press_no()

@ -30,8 +30,8 @@ if TYPE_CHECKING:
from ..device_handler import BackgroundDeviceHandler from ..device_handler import BackgroundDeviceHandler
# TR-only # T2B1-only
pytestmark = [pytest.mark.skip_t1, pytest.mark.skip_t2] pytestmark = [pytest.mark.skip_t1, pytest.mark.skip_t2, pytest.mark.skip_t3t1]
@contextmanager @contextmanager

@ -23,7 +23,7 @@ from unittest import mock
import pytest import pytest
from trezorlib import btc, messages, tools from trezorlib import btc, messages, models, tools
if TYPE_CHECKING: if TYPE_CHECKING:
from _pytest.mark.structures import MarkDecorator from _pytest.mark.structures import MarkDecorator
@ -89,12 +89,14 @@ def parametrize_using_common_fixtures(*paths: str) -> "MarkDecorator":
skip_models = test.get("skip_models", []) skip_models = test.get("skip_models", [])
skip_marks = [] skip_marks = []
for skip_model in skip_models: for skip_model in skip_models:
if skip_model == "t1": if skip_model in ("t1", "t1b1"):
skip_marks.append(pytest.mark.skip_t1) skip_marks.append(pytest.mark.skip_t1)
if skip_model == "t2": if skip_model in ("t2", "t2t1"):
skip_marks.append(pytest.mark.skip_t2) skip_marks.append(pytest.mark.skip_t2)
if skip_model == "tr": if skip_model in ("tr", "t2b1"):
skip_marks.append(pytest.mark.skip_tr) skip_marks.append(pytest.mark.skip_tr)
if skip_model == "t3t1":
skip_marks.append(pytest.mark.skip_t3t1)
tests.append( tests.append(
pytest.param( pytest.param(
@ -173,10 +175,12 @@ def read_and_confirm_mnemonic(
debug: "DebugLink", choose_wrong: bool = False debug: "DebugLink", choose_wrong: bool = False
) -> Generator[None, "ButtonRequest", Optional[str]]: ) -> Generator[None, "ButtonRequest", Optional[str]]:
# TODO: these are very similar, reuse some code # TODO: these are very similar, reuse some code
if debug.model == "T": if debug.model is models.T2T1:
mnemonic = yield from read_and_confirm_mnemonic_tt(debug, choose_wrong) mnemonic = yield from read_and_confirm_mnemonic_tt(debug, choose_wrong)
elif debug.model == "Safe 3": elif debug.model is models.T2B1:
mnemonic = yield from read_and_confirm_mnemonic_tr(debug, choose_wrong) mnemonic = yield from read_and_confirm_mnemonic_tr(debug, choose_wrong)
elif debug.model is models.T3T1:
mnemonic = yield from read_and_confirm_mnemonic_tt(debug, choose_wrong)
else: else:
raise ValueError(f"Unknown model: {debug.model}") raise ValueError(f"Unknown model: {debug.model}")
@ -316,3 +320,7 @@ def swipe_till_the_end(debug: "DebugLink", br: messages.ButtonRequest) -> None:
if br.pages is not None: if br.pages is not None:
for _ in range(br.pages - 1): for _ in range(br.pages - 1):
debug.swipe_up() debug.swipe_up()
def is_core(client: "Client") -> bool:
return client.model in (models.T2T1, models.T2B1, models.T3T1)

@ -23,7 +23,7 @@ from typing import TYPE_CHECKING, Generator, Iterator
import pytest import pytest
import xdist import xdist
from trezorlib import debuglink, log from trezorlib import debuglink, log, models
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.device import apply_settings from trezorlib.device import apply_settings
from trezorlib.device import wipe as wipe_device from trezorlib.device import wipe as wipe_device
@ -207,6 +207,11 @@ def client(
and _raw_client.features.model == "Safe 3" and _raw_client.features.model == "Safe 3"
): ):
pytest.skip("Test excluded on Trezor R") pytest.skip("Test excluded on Trezor R")
if (
request.node.get_closest_marker("skip_t3t1")
and _raw_client.model is models.T3T1
):
pytest.skip("Test excluded on Trezor T3T1")
sd_marker = request.node.get_closest_marker("sd_card") sd_marker = request.node.get_closest_marker("sd_card")
if sd_marker and not _raw_client.features.sd_card_present: if sd_marker and not _raw_client.features.sd_card_present:
@ -390,6 +395,7 @@ def pytest_configure(config: "Config") -> None:
config.addinivalue_line("markers", "skip_t1: skip the test on Trezor One") config.addinivalue_line("markers", "skip_t1: skip the test on Trezor One")
config.addinivalue_line("markers", "skip_t2: skip the test on Trezor T") config.addinivalue_line("markers", "skip_t2: skip the test on Trezor T")
config.addinivalue_line("markers", "skip_tr: skip the test on Trezor R") config.addinivalue_line("markers", "skip_tr: skip the test on Trezor R")
config.addinivalue_line("markers", "skip_t3t1: skip the test on Trezor T3T1")
config.addinivalue_line( config.addinivalue_line(
"markers", "experimental: enable experimental features on Trezor" "markers", "experimental: enable experimental features on Trezor"
) )

@ -23,6 +23,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .payment_req import make_coinjoin_request from .payment_req import make_coinjoin_request
from .signtx import ( from .signtx import (
@ -453,7 +454,6 @@ def test_sign_tx_spend(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
messages.ButtonRequest(code=B.Other), messages.ButtonRequest(code=B.Other),
@ -462,7 +462,7 @@ def test_sign_tx_spend(client: Client):
request_output(0), request_output(0),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_output(0), request_output(0),
@ -528,7 +528,6 @@ def test_sign_tx_migration(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
messages.ButtonRequest(code=B.Other), messages.ButtonRequest(code=B.Other),
@ -537,7 +536,7 @@ def test_sign_tx_migration(client: Client):
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_2cc3c1), request_meta(TXHASH_2cc3c1),

@ -21,6 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import H_, parse_path from trezorlib.tools import H_, parse_path
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import ( from .signtx import (
assert_tx_matches, assert_tx_matches,
@ -72,14 +73,13 @@ def test_send_bch_change(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_bc37c2), request_meta(TXHASH_bc37c2),
@ -125,14 +125,13 @@ def test_send_bch_nochange(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_502e85), request_meta(TXHASH_502e85),
@ -184,14 +183,13 @@ def test_send_bch_oldaddr(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_502e85), request_meta(TXHASH_502e85),
@ -255,7 +253,6 @@ def test_attack_change_input(client: Client):
return msg return msg
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_filter(messages.TxAck, attack_processor) client.set_filter(messages.TxAck, attack_processor)
client.set_expected_responses( client.set_expected_responses(
[ [
@ -263,7 +260,7 @@ def test_attack_change_input(client: Client):
request_output(0), request_output(0),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(FAKE_TXHASH_bd32ff), request_meta(FAKE_TXHASH_bd32ff),
@ -331,13 +328,12 @@ def test_send_bch_multisig_wrongchange(client: Client):
amount=23_000, amount=23_000,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(FAKE_TXHASH_062fbd), request_meta(FAKE_TXHASH_062fbd),
@ -400,13 +396,12 @@ def test_send_bch_multisig_change(client: Client):
amount=24_000, amount=24_000,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -445,7 +440,7 @@ def test_send_bch_multisig_change(client: Client):
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -502,14 +497,13 @@ def test_send_bch_external_presigned(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_502e85), request_meta(TXHASH_502e85),

@ -21,6 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import H_, parse_path, tx_hash from trezorlib.tools import H_, parse_path, tx_hash
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import request_finished, request_input, request_meta, request_output from .signtx import request_finished, request_input, request_meta, request_output
@ -71,14 +72,13 @@ def test_send_bitcoin_gold_change(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(FAKE_TXHASH_6f0398), request_meta(FAKE_TXHASH_6f0398),
@ -125,14 +125,13 @@ def test_send_bitcoin_gold_nochange(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(FAKE_TXHASH_6f0398), request_meta(FAKE_TXHASH_6f0398),
@ -195,7 +194,6 @@ def test_attack_change_input(client: Client):
return msg return msg
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_filter(messages.TxAck, attack_processor) client.set_filter(messages.TxAck, attack_processor)
client.set_expected_responses( client.set_expected_responses(
[ [
@ -203,7 +201,7 @@ def test_attack_change_input(client: Client):
request_output(0), request_output(0),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(FAKE_TXHASH_6f0398), request_meta(FAKE_TXHASH_6f0398),
@ -257,13 +255,12 @@ def test_send_btg_multisig_change(client: Client):
amount=1_252_382_934 - 24_000 - 1_000, amount=1_252_382_934 - 24_000 - 1_000,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -302,7 +299,7 @@ def test_send_btg_multisig_change(client: Client):
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -351,16 +348,15 @@ def test_send_p2sh(client: Client):
amount=1_252_382_934 - 11_000 - 12_300_000, amount=1_252_382_934 - 11_000 - 12_300_000,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(FAKE_TXHASH_db7239), request_meta(FAKE_TXHASH_db7239),
@ -405,13 +401,12 @@ def test_send_p2sh_witness_change(client: Client):
amount=1_252_382_934 - 11_000 - 12_300_000, amount=1_252_382_934 - 11_000 - 12_300_000,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -466,13 +461,12 @@ def test_send_multisig_1(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(FAKE_TXHASH_7f1f6b), request_meta(FAKE_TXHASH_7f1f6b),
@ -495,7 +489,7 @@ def test_send_multisig_1(client: Client):
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(FAKE_TXHASH_7f1f6b), request_meta(FAKE_TXHASH_7f1f6b),
@ -584,14 +578,13 @@ def test_send_btg_external_presigned(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(FAKE_TXHASH_6f0398), request_meta(FAKE_TXHASH_6f0398),

@ -20,6 +20,7 @@ from trezorlib import btc, messages
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import ( from .signtx import (
request_extra_data, request_extra_data,
@ -57,13 +58,12 @@ def test_send_dash(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(inp1.prev_hash), request_meta(inp1.prev_hash),
@ -105,14 +105,13 @@ def test_send_dash_dip2_input(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(inp1.prev_hash), request_meta(inp1.prev_hash),

@ -20,6 +20,7 @@ from trezorlib import btc, messages
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import request_finished, request_input, request_meta, request_output from .signtx import request_finished, request_input, request_meta, request_output
@ -49,7 +50,12 @@ FAKE_TXHASH_51bc9c = bytes.fromhex(
"51bc9c71f10a81eef3caedb5333062eb4b1f70998adf02916fe98fdc04c572e8" "51bc9c71f10a81eef3caedb5333062eb4b1f70998adf02916fe98fdc04c572e8"
) )
pytestmark = [pytest.mark.altcoin, pytest.mark.decred, pytest.mark.skip_tr] pytestmark = [
pytest.mark.altcoin,
pytest.mark.decred,
pytest.mark.skip_tr,
pytest.mark.skip_t3t1,
]
def test_send_decred(client: Client): def test_send_decred(client: Client):
@ -72,13 +78,12 @@ def test_send_decred(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.FeeOverThreshold), messages.ButtonRequest(code=B.FeeOverThreshold),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -194,14 +199,13 @@ def test_spend_from_stake_generation_and_revocation_decred(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(FAKE_TXHASH_f8e2f2), request_meta(FAKE_TXHASH_f8e2f2),
@ -276,7 +280,6 @@ def test_send_decred_change(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
@ -284,7 +287,7 @@ def test_send_decred_change(client: Client):
request_input(2), request_input(2),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -383,7 +386,6 @@ def test_decred_multisig_change(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
@ -391,7 +393,7 @@ def test_decred_multisig_change(client: Client):
request_output(0), request_output(0),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(FAKE_TXHASH_9ac7d2), request_meta(FAKE_TXHASH_9ac7d2),

@ -52,6 +52,7 @@ VECTORS = ( # path, script_type, address
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
@pytest.mark.parametrize("path, script_type, address", VECTORS) @pytest.mark.parametrize("path, script_type, address", VECTORS)
def test_show_t1( def test_show_t1(
client: Client, path: str, script_type: messages.InputScriptType, address: str client: Client, path: str, script_type: messages.InputScriptType, address: str

@ -20,6 +20,7 @@ from trezorlib import btc, messages
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import ( from .signtx import (
request_extra_data, request_extra_data,
@ -61,13 +62,12 @@ def test_one_one_fee_sapling(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -126,16 +126,15 @@ def test_one_one_rewards_claim(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),

@ -21,7 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from ...common import MNEMONIC12 from ...common import MNEMONIC12, is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import ( from .signtx import (
assert_tx_matches, assert_tx_matches,
@ -83,12 +83,11 @@ def test_2_of_3(client: Client, chunkify: bool):
) )
# Expected responses are the same for both two signings # Expected responses are the same for both two signings
is_core = client.features.model in ("T", "Safe 3")
expected_responses = [ expected_responses = [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_6b07c1), request_meta(TXHASH_6b07c1),

@ -21,7 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.tools import H_, parse_path from trezorlib.tools import H_, parse_path
from ... import bip32 from ... import bip32
from ...common import MNEMONIC12 from ...common import MNEMONIC12, is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import request_finished, request_input, request_meta, request_output from .signtx import request_finished, request_input, request_meta, request_output
@ -145,7 +145,6 @@ def _responses(
change: int = 0, change: int = 0,
foreign: bool = False, foreign: bool = False,
): ):
is_core = client.features.model in ("T", "Safe 3")
resp = [ resp = [
request_input(0), request_input(0),
request_input(1), request_input(1),
@ -154,7 +153,7 @@ def _responses(
if change != 1: if change != 1:
resp.append(messages.ButtonRequest(code=B.ConfirmOutput)) resp.append(messages.ButtonRequest(code=B.ConfirmOutput))
if is_core: if is_core(client):
resp.append(messages.ButtonRequest(code=B.ConfirmOutput)) resp.append(messages.ButtonRequest(code=B.ConfirmOutput))
elif foreign: elif foreign:
resp.append(messages.ButtonRequest(code=B.UnknownDerivationPath)) resp.append(messages.ButtonRequest(code=B.UnknownDerivationPath))
@ -163,7 +162,7 @@ def _responses(
if change != 2: if change != 2:
resp.append(messages.ButtonRequest(code=B.ConfirmOutput)) resp.append(messages.ButtonRequest(code=B.ConfirmOutput))
if is_core: if is_core(client):
resp.append(messages.ButtonRequest(code=B.ConfirmOutput)) resp.append(messages.ButtonRequest(code=B.ConfirmOutput))
elif foreign: elif foreign:
resp.append(messages.ButtonRequest(code=B.UnknownDerivationPath)) resp.append(messages.ButtonRequest(code=B.UnknownDerivationPath))

@ -21,6 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import ( from .signtx import (
assert_tx_matches, assert_tx_matches,
@ -63,13 +64,12 @@ def test_opreturn(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),

@ -363,7 +363,7 @@ def test_signmessage_pagination(client: Client, message: str):
# We cannot differentiate between a newline and space in the message read from Trezor. # We cannot differentiate between a newline and space in the message read from Trezor.
# TODO: do the check also for model R # TODO: do the check also for model R
if client.features.model == "T": if client.model in (models.T2T1, models.T3T1):
message_read = IF.message_read.replace(" ", "").replace("...", "") message_read = IF.message_read.replace(" ", "").replace("...", "")
signed_message = message.replace("\n", "").replace(" ", "") signed_message = message.replace("\n", "").replace(" ", "")
assert signed_message in message_read assert signed_message in message_read

@ -23,6 +23,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import Cancelled, TrezorFailure from trezorlib.exceptions import Cancelled, TrezorFailure
from trezorlib.tools import H_, parse_path from trezorlib.tools import H_, parse_path
from ...common import is_core
from ...input_flows import ( from ...input_flows import (
InputFlowLockTimeBlockHeight, InputFlowLockTimeBlockHeight,
InputFlowLockTimeDatetime, InputFlowLockTimeDatetime,
@ -127,13 +128,12 @@ def test_one_one_fee(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_0dac36), request_meta(TXHASH_0dac36),
@ -181,13 +181,12 @@ def test_testnet_one_two_fee(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -232,13 +231,12 @@ def test_testnet_fee_high_warning(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.FeeOverThreshold), messages.ButtonRequest(code=B.FeeOverThreshold),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -285,14 +283,13 @@ def test_one_two_fee(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_50f6f1), request_meta(TXHASH_50f6f1),
@ -348,16 +345,15 @@ def test_one_three_fee(client: Client, chunkify: bool):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(2), request_output(2),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -420,7 +416,6 @@ def test_two_two(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
@ -428,7 +423,7 @@ def test_two_two(client: Client):
request_output(0), request_output(0),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_ac4ca0), request_meta(TXHASH_ac4ca0),
@ -565,13 +560,12 @@ def test_lots_of_change(client: Client):
request_change_outputs = [request_output(i + 1) for i in range(cnt)] request_change_outputs = [request_output(i + 1) for i in range(cnt)]
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
] ]
+ request_change_outputs + request_change_outputs
+ [ + [
@ -617,13 +611,12 @@ def test_fee_high_warning(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.FeeOverThreshold), messages.ButtonRequest(code=B.FeeOverThreshold),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -706,13 +699,12 @@ def test_not_enough_funds(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.Failure(code=messages.FailureType.NotEnoughFunds), messages.Failure(code=messages.FailureType.NotEnoughFunds),
] ]
) )
@ -737,13 +729,12 @@ def test_p2sh(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_58d56a), request_meta(TXHASH_58d56a),
@ -825,7 +816,6 @@ def test_attack_change_outputs(client: Client):
# Test if the transaction can be signed normally # Test if the transaction can be signed normally
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
@ -833,7 +823,7 @@ def test_attack_change_outputs(client: Client):
request_output(0), request_output(0),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_ac4ca0), request_meta(TXHASH_ac4ca0),
@ -993,14 +983,13 @@ def test_attack_change_input_address(client: Client):
# Now run the attack, must trigger the exception # Now run the attack, must trigger the exception
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_filter(messages.TxAck, attack_processor) client.set_filter(messages.TxAck, attack_processor)
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -1045,13 +1034,12 @@ def test_spend_coinbase(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(FAKE_TXHASH_005f6f), request_meta(FAKE_TXHASH_005f6f),
@ -1104,13 +1092,12 @@ def test_two_changes(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
request_output(2), request_output(2),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
@ -1164,13 +1151,12 @@ def test_change_on_main_chain_allowed(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -1429,13 +1415,12 @@ def test_lock_time(client: Client, lock_time: int, sequence: int):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),

@ -22,6 +22,7 @@ from trezorlib.exceptions import TrezorFailure
from trezorlib.messages import SafetyCheckLevel from trezorlib.messages import SafetyCheckLevel
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import ( from .signtx import (
assert_tx_matches, assert_tx_matches,
@ -216,20 +217,19 @@ def test_p2wpkh_in_p2sh_presigned(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(2), request_output(2),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_20912f), request_meta(TXHASH_20912f),
@ -268,20 +268,19 @@ def test_p2wpkh_in_p2sh_presigned(client: Client):
# Test corrupted script hash in scriptsig. # Test corrupted script hash in scriptsig.
inp1.script_sig[10] ^= 1 inp1.script_sig[10] ^= 1
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(2), request_output(2),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_20912f), request_meta(TXHASH_20912f),
@ -401,14 +400,13 @@ def test_p2wsh_external_presigned(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_ec16dc), request_meta(TXHASH_ec16dc),
@ -447,14 +445,13 @@ def test_p2wsh_external_presigned(client: Client):
# Test corrupted signature in witness. # Test corrupted signature in witness.
inp2.witness[10] ^= 1 inp2.witness[10] ^= 1
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_ec16dc), request_meta(TXHASH_ec16dc),
@ -513,14 +510,13 @@ def test_p2tr_external_presigned(client: Client):
script_type=messages.OutputScriptType.PAYTOTAPROOT, script_type=messages.OutputScriptType.PAYTOTAPROOT,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(1), request_input(1),
@ -546,14 +542,13 @@ def test_p2tr_external_presigned(client: Client):
# Test corrupted signature in witness. # Test corrupted signature in witness.
inp2.witness[10] ^= 1 inp2.witness[10] ^= 1
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(1), request_input(1),
@ -617,17 +612,16 @@ def test_p2wpkh_with_proof(client: Client):
with client: with client:
is_t1 = client.features.model == "1" is_t1 = client.features.model == "1"
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_e5b7e2), request_meta(TXHASH_e5b7e2),
@ -711,14 +705,13 @@ def test_p2tr_with_proof(client: Client):
with client: with client:
is_t1 = client.features.model == "1" is_t1 = client.features.model == "1"
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_input(1), request_input(1),

@ -21,6 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import ( from .signtx import (
request_finished, request_finished,
@ -115,8 +116,6 @@ def test_p2pkh_fee_bump(client: Client):
orig_index=1, orig_index=1,
) )
is_core = client.features.model in ("T", "Safe 3")
with client: with client:
client.set_expected_responses( client.set_expected_responses(
[ [
@ -133,7 +132,7 @@ def test_p2pkh_fee_bump(client: Client):
request_meta(TXHASH_beafc7), request_meta(TXHASH_beafc7),
request_input(0, TXHASH_beafc7), request_input(0, TXHASH_beafc7),
request_output(0, TXHASH_beafc7), request_output(0, TXHASH_beafc7),
(is_core, request_orig_input(0, TXHASH_50f6f1)), (is_core(client), request_orig_input(0, TXHASH_50f6f1)),
request_orig_input(0, TXHASH_50f6f1), request_orig_input(0, TXHASH_50f6f1),
request_orig_output(0, TXHASH_50f6f1), request_orig_output(0, TXHASH_50f6f1),
request_orig_output(1, TXHASH_50f6f1), request_orig_output(1, TXHASH_50f6f1),

@ -21,6 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import H_, parse_path from trezorlib.tools import H_, parse_path
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import ( from .signtx import (
assert_tx_matches, assert_tx_matches,
@ -66,16 +67,15 @@ def test_send_p2sh(client: Client, chunkify: bool):
amount=123_456_789 - 11_000 - 12_300_000, amount=123_456_789 - 11_000 - 12_300_000,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_20912f), request_meta(TXHASH_20912f),
@ -125,13 +125,12 @@ def test_send_p2sh_change(client: Client):
amount=123_456_789 - 11_000 - 12_300_000, amount=123_456_789 - 11_000 - 12_300_000,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -181,13 +180,12 @@ def test_testnet_segwit_big_amount(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(prev_hash), request_meta(prev_hash),
@ -239,12 +237,11 @@ def test_send_multisig_1(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
is_core = client.features.model in ("T", "Safe 3")
expected_responses = [ expected_responses = [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_338e2d), request_meta(TXHASH_338e2d),
@ -307,17 +304,16 @@ def test_attack_change_input_address(client: Client):
# Test if the transaction can be signed normally. # Test if the transaction can be signed normally.
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
# The user is required to confirm transfer to another account. # The user is required to confirm transfer to another account.
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_20912f), request_meta(TXHASH_20912f),
@ -387,17 +383,19 @@ def test_attack_mixed_inputs(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
is_core = client.features.model in ("T", "Safe 3")
expected_responses = [ expected_responses = [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=messages.ButtonRequestType.ConfirmOutput), messages.ButtonRequest(code=messages.ButtonRequestType.ConfirmOutput),
( (
is_core, is_core(client),
messages.ButtonRequest(code=messages.ButtonRequestType.ConfirmOutput), messages.ButtonRequest(code=messages.ButtonRequestType.ConfirmOutput),
), ),
(is_core, messages.ButtonRequest(code=messages.ButtonRequestType.SignTx)), (
is_core(client),
messages.ButtonRequest(code=messages.ButtonRequestType.SignTx),
),
messages.ButtonRequest(code=messages.ButtonRequestType.FeeOverThreshold), messages.ButtonRequest(code=messages.ButtonRequestType.FeeOverThreshold),
messages.ButtonRequest(code=messages.ButtonRequestType.SignTx), messages.ButtonRequest(code=messages.ButtonRequestType.SignTx),
request_input(0), request_input(0),

@ -21,6 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.tools import H_, parse_path from trezorlib.tools import H_, parse_path
from ...bip32 import deserialize from ...bip32 import deserialize
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import ( from .signtx import (
assert_tx_matches, assert_tx_matches,
@ -81,16 +82,15 @@ def test_send_p2sh(client: Client):
amount=123_456_789 - 11_000 - 12_300_000, amount=123_456_789 - 11_000 - 12_300_000,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_20912f), request_meta(TXHASH_20912f),
@ -137,13 +137,12 @@ def test_send_p2sh_change(client: Client):
amount=123_456_789 - 11_000 - 12_300_000, amount=123_456_789 - 11_000 - 12_300_000,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -191,16 +190,15 @@ def test_send_native(client: Client):
amount=100_000 - 40_000 - 10_000, amount=100_000 - 40_000 - 10_000,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_b36780), request_meta(TXHASH_b36780),
@ -279,13 +277,12 @@ def test_send_native_change(client: Client):
amount=100_000 - 40_000 - 10_000, amount=100_000 - 40_000 - 10_000,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -347,22 +344,20 @@ def test_send_both(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(2), request_output(2),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
(is_core, messages.ButtonRequest(code=B.SignTx)), (is_core(client), messages.ButtonRequest(code=B.SignTx)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_65047a), request_meta(TXHASH_65047a),
@ -433,12 +428,11 @@ def test_send_multisig_1(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
is_core = client.features.model in ("T", "Safe 3")
expected_responses = [ expected_responses = [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_b9abfa), request_meta(TXHASH_b9abfa),
@ -511,12 +505,11 @@ def test_send_multisig_2(client: Client):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
is_core = client.features.model in ("T", "Safe 3")
expected_responses = [ expected_responses = [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_b9abfa), request_meta(TXHASH_b9abfa),
@ -596,13 +589,12 @@ def test_send_multisig_3_change(client: Client):
script_type=messages.OutputScriptType.PAYTOP2SHWITNESS, script_type=messages.OutputScriptType.PAYTOP2SHWITNESS,
) )
is_core = client.features.model in ("T", "Safe 3")
expected_responses = [ expected_responses = [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.UnknownDerivationPath), messages.ButtonRequest(code=B.UnknownDerivationPath),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_b9abfa), request_meta(TXHASH_b9abfa),
@ -683,13 +675,12 @@ def test_send_multisig_4_change(client: Client):
script_type=messages.OutputScriptType.PAYTOWITNESS, script_type=messages.OutputScriptType.PAYTOWITNESS,
) )
is_core = client.features.model in ("T", "Safe 3")
expected_responses = [ expected_responses = [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.UnknownDerivationPath), messages.ButtonRequest(code=B.UnknownDerivationPath),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_b9abfa), request_meta(TXHASH_b9abfa),
@ -785,18 +776,17 @@ def test_multisig_mismatch_inputs_single(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
# Ensure that the multisig output is not identified as a change output. # Ensure that the multisig output is not identified as a change output.
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_1c022d), request_meta(TXHASH_1c022d),

@ -21,6 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import H_, parse_path from trezorlib.tools import H_, parse_path
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import ( from .signtx import (
assert_tx_matches, assert_tx_matches,
@ -79,13 +80,12 @@ def test_send_p2tr(client: Client, chunkify: bool):
script_type=messages.OutputScriptType.PAYTOADDRESS, script_type=messages.OutputScriptType.PAYTOADDRESS,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_output(0), request_output(0),
@ -134,14 +134,13 @@ def test_send_two_with_change(client: Client):
amount=6_800 + 13_000 - 200 - 15_000, amount=6_800 + 13_000 - 200 - 15_000,
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -224,8 +223,6 @@ def test_send_mixed(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
# process inputs # process inputs
@ -236,19 +233,19 @@ def test_send_mixed(client: Client):
# approve outputs # approve outputs
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(2), request_output(2),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(3), request_output(3),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
request_output(4), request_output(4),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
(is_core, messages.ButtonRequest(code=B.SignTx)), (is_core(client), messages.ButtonRequest(code=B.SignTx)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
# verify inputs # verify inputs
request_input(0), request_input(0),
@ -358,8 +355,6 @@ def test_attack_script_type(client: Client):
return msg return msg
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
is_core = client.features.model in ("T", "Safe 3")
client.set_filter(messages.TxAck, attack_processor) client.set_filter(messages.TxAck, attack_processor)
client.set_expected_responses( client.set_expected_responses(
[ [
@ -367,8 +362,8 @@ def test_attack_script_type(client: Client):
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
(is_core, messages.ButtonRequest(code=B.SignTx)), (is_core(client), messages.ButtonRequest(code=B.SignTx)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_input(1), request_input(1),

@ -21,6 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from ...common import is_core
from ...tx_cache import TxCache from ...tx_cache import TxCache
from .signtx import ( from .signtx import (
request_extra_data, request_extra_data,
@ -106,13 +107,12 @@ def test_one_one_fee_sapling(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_e38206), request_meta(TXHASH_e38206),
@ -260,14 +260,13 @@ def test_external_presigned(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_e38206), request_meta(TXHASH_e38206),

@ -16,7 +16,7 @@
import pytest import pytest
from trezorlib import cardano, device, messages from trezorlib import cardano, device, messages, models
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
@ -33,11 +33,13 @@ def show_details_input_flow(client: Client):
yield yield
client.debug.wait_layout() client.debug.wait_layout()
# Clicking for model T, pressing right for model R # Clicking for model T, pressing right for model R
if client.features.model == "T": if client.model in (models.T2T1, models.T3T1):
SHOW_ALL_BUTTON_POSITION = (143, 167) SHOW_ALL_BUTTON_POSITION = (143, 167)
client.debug.click(SHOW_ALL_BUTTON_POSITION) client.debug.click(SHOW_ALL_BUTTON_POSITION)
elif client.features.model == "Safe 3": elif client.model is models.T2B1:
client.debug.press_yes() client.debug.press_yes()
else:
raise NotImplementedError
# reset ui flow to continue "automatically" # reset ui flow to continue "automatically"
client.ui.input_flow = None client.ui.input_flow = None
yield yield

@ -28,6 +28,7 @@ from ...input_flows import InputFlowShowXpubQRCode
@pytest.mark.eos @pytest.mark.eos
@pytest.mark.skip_t1 @pytest.mark.skip_t1
@pytest.mark.skip_tr # coin not supported @pytest.mark.skip_tr # coin not supported
@pytest.mark.skip_t3t1
@pytest.mark.setup_client(mnemonic=MNEMONIC12) @pytest.mark.setup_client(mnemonic=MNEMONIC12)
def test_eos_get_public_key(client: Client): def test_eos_get_public_key(client: Client):
with client: with client:

@ -31,6 +31,7 @@ pytestmark = [
pytest.mark.eos, pytest.mark.eos,
pytest.mark.skip_t1, pytest.mark.skip_t1,
pytest.mark.skip_tr, # coin not supported pytest.mark.skip_tr, # coin not supported
pytest.mark.skip_t3t1,
pytest.mark.setup_client(mnemonic=MNEMONIC12), pytest.mark.setup_client(mnemonic=MNEMONIC12),
] ]

@ -199,7 +199,8 @@ METHODS = (
_call_signmessage, _call_signmessage,
pytest.param(_call_sign_typed_data, marks=pytest.mark.skip_t1), pytest.param(_call_sign_typed_data, marks=pytest.mark.skip_t1),
pytest.param( pytest.param(
_call_sign_typed_data_hash, marks=[pytest.mark.skip_t2, pytest.mark.skip_tr] _call_sign_typed_data_hash,
marks=[pytest.mark.skip_t2, pytest.mark.skip_tr, pytest.mark.skip_t3t1],
), ),
) )

@ -46,6 +46,7 @@ def test_slip25_disallowed(client: Client):
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
def test_legacy_restrictions(client: Client): def test_legacy_restrictions(client: Client):
path = parse_path("m/46'") path = parse_path("m/46'")
with pytest.raises(TrezorFailure, match="Invalid path for EthereumGetPublicKey"): with pytest.raises(TrezorFailure, match="Invalid path for EthereumGetPublicKey"):

@ -43,6 +43,7 @@ def test_ethereum_sign_typed_data(client: Client, parameters, result):
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
@parametrize_using_common_fixtures("ethereum/sign_typed_data.json") @parametrize_using_common_fixtures("ethereum/sign_typed_data.json")
def test_ethereum_sign_typed_data_blind(client: Client, parameters, result): def test_ethereum_sign_typed_data_blind(client: Client, parameters, result):
with client: with client:

@ -16,7 +16,7 @@
import pytest import pytest
from trezorlib import ethereum, exceptions, messages from trezorlib import ethereum, exceptions, messages, models
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.debuglink import message_filters from trezorlib.debuglink import message_filters
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
@ -208,7 +208,7 @@ def test_data_streaming(client: Client):
checked in vectorized function above. checked in vectorized function above.
""" """
with client: with client:
is_t1 = client.features.model == "1" is_t1 = client.model is models.T1B1
client.set_expected_responses( client.set_expected_responses(
[ [
messages.ButtonRequest(code=messages.ButtonRequestType.SignTx), messages.ButtonRequest(code=messages.ButtonRequestType.SignTx),

@ -26,6 +26,7 @@ from ...common import MNEMONIC12
@pytest.mark.altcoin @pytest.mark.altcoin
@pytest.mark.nem @pytest.mark.nem
@pytest.mark.skip_tr # coin not supported, @pytest.mark.skip_tr # coin not supported,
@pytest.mark.skip_t3t1
@pytest.mark.setup_client(mnemonic=MNEMONIC12) @pytest.mark.setup_client(mnemonic=MNEMONIC12)
@pytest.mark.parametrize("chunkify", (True, False)) @pytest.mark.parametrize("chunkify", (True, False))
def test_nem_getaddress(client: Client, chunkify: bool): def test_nem_getaddress(client: Client, chunkify: bool):

@ -28,6 +28,7 @@ pytestmark = [
pytest.mark.altcoin, pytest.mark.altcoin,
pytest.mark.nem, pytest.mark.nem,
pytest.mark.skip_tr, # coin not supported, pytest.mark.skip_tr, # coin not supported,
pytest.mark.skip_t3t1,
pytest.mark.setup_client(mnemonic=MNEMONIC12), pytest.mark.setup_client(mnemonic=MNEMONIC12),
] ]

@ -26,6 +26,7 @@ pytestmark = [
pytest.mark.altcoin, pytest.mark.altcoin,
pytest.mark.nem, pytest.mark.nem,
pytest.mark.skip_tr, # coin not supported, pytest.mark.skip_tr, # coin not supported,
pytest.mark.skip_t3t1,
pytest.mark.setup_client(mnemonic=MNEMONIC12), pytest.mark.setup_client(mnemonic=MNEMONIC12),
] ]

@ -26,6 +26,7 @@ pytestmark = [
pytest.mark.altcoin, pytest.mark.altcoin,
pytest.mark.nem, pytest.mark.nem,
pytest.mark.skip_tr, # coin not supported, pytest.mark.skip_tr, # coin not supported,
pytest.mark.skip_t3t1,
pytest.mark.setup_client(mnemonic=MNEMONIC12), pytest.mark.setup_client(mnemonic=MNEMONIC12),
] ]

@ -20,12 +20,13 @@ from trezorlib import messages, nem
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from ...common import MNEMONIC12 from ...common import MNEMONIC12, is_core
pytestmark = [ pytestmark = [
pytest.mark.altcoin, pytest.mark.altcoin,
pytest.mark.nem, pytest.mark.nem,
pytest.mark.skip_tr, # coin not supported, pytest.mark.skip_tr, # coin not supported,
pytest.mark.skip_t3t1,
pytest.mark.setup_client(mnemonic=MNEMONIC12), pytest.mark.setup_client(mnemonic=MNEMONIC12),
] ]
@ -33,7 +34,6 @@ pytestmark = [
# assertion data from T1 # assertion data from T1
@pytest.mark.parametrize("chunkify", (True, False)) @pytest.mark.parametrize("chunkify", (True, False))
def test_nem_signtx_simple(client: Client, chunkify: bool): def test_nem_signtx_simple(client: Client, chunkify: bool):
is_core = client.features.model in ("T", "Safe 3")
with client: with client:
client.set_expected_responses( client.set_expected_responses(
[ [
@ -42,7 +42,7 @@ def test_nem_signtx_simple(client: Client, chunkify: bool):
# Unencrypted message # Unencrypted message
messages.ButtonRequest(code=messages.ButtonRequestType.ConfirmOutput), messages.ButtonRequest(code=messages.ButtonRequestType.ConfirmOutput),
( (
is_core, is_core(client),
messages.ButtonRequest( messages.ButtonRequest(
code=messages.ButtonRequestType.ConfirmOutput code=messages.ButtonRequestType.ConfirmOutput
), ),
@ -85,7 +85,6 @@ def test_nem_signtx_simple(client: Client, chunkify: bool):
@pytest.mark.setup_client(mnemonic=MNEMONIC12) @pytest.mark.setup_client(mnemonic=MNEMONIC12)
def test_nem_signtx_encrypted_payload(client: Client): def test_nem_signtx_encrypted_payload(client: Client):
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
# Confirm transfer and network fee # Confirm transfer and network fee
@ -93,7 +92,7 @@ def test_nem_signtx_encrypted_payload(client: Client):
# Ask for encryption # Ask for encryption
messages.ButtonRequest(code=messages.ButtonRequestType.ConfirmOutput), messages.ButtonRequest(code=messages.ButtonRequestType.ConfirmOutput),
( (
is_core, is_core(client),
messages.ButtonRequest( messages.ButtonRequest(
code=messages.ButtonRequestType.ConfirmOutput code=messages.ButtonRequestType.ConfirmOutput
), ),

@ -82,6 +82,7 @@ def test_seed_mismatch(client: Client):
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
def test_invalid_seed_t1(client: Client): def test_invalid_seed_t1(client: Client):
with pytest.raises(exceptions.TrezorFailure, match="Invalid seed"): with pytest.raises(exceptions.TrezorFailure, match="Invalid seed"):
do_recover(client, ["stick"] * 12) do_recover(client, ["stick"] * 12)

@ -25,7 +25,7 @@ from ...common import MNEMONIC12
PIN4 = "1234" PIN4 = "1234"
PIN6 = "789456" PIN6 = "789456"
pytestmark = [pytest.mark.skip_t2, pytest.mark.skip_tr] pytestmark = [pytest.mark.skip_t2, pytest.mark.skip_tr, pytest.mark.skip_t3t1]
@pytest.mark.setup_client(uninitialized=True) @pytest.mark.setup_client(uninitialized=True)

@ -22,7 +22,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from ...common import EXTERNAL_ENTROPY, generate_entropy from ...common import EXTERNAL_ENTROPY, generate_entropy
pytestmark = [pytest.mark.skip_t2, pytest.mark.skip_tr] pytestmark = [pytest.mark.skip_t2, pytest.mark.skip_tr, pytest.mark.skip_t3t1]
STRENGTH = 128 STRENGTH = 128

@ -23,7 +23,7 @@ from trezorlib.tools import parse_path
from ...common import EXTERNAL_ENTROPY, generate_entropy from ...common import EXTERNAL_ENTROPY, generate_entropy
pytestmark = [pytest.mark.skip_t2, pytest.mark.skip_tr] pytestmark = [pytest.mark.skip_t2, pytest.mark.skip_tr, pytest.mark.skip_t3t1]
def reset_device(client: Client, strength: int): def reset_device(client: Client, strength: int):

@ -16,6 +16,7 @@ ROOT_PUBLIC_KEY = bytes.fromhex(
) )
@pytest.mark.skip_t3t1 # FIXME https://github.com/trezor/trezor-firmware/issues/3596
@pytest.mark.parametrize( @pytest.mark.parametrize(
"challenge", "challenge",
( (

@ -26,6 +26,7 @@ from trezorlib.tools import H_
pytestmark = [ pytestmark = [
pytest.mark.skip_t2, pytest.mark.skip_t2,
pytest.mark.skip_tr, pytest.mark.skip_tr,
pytest.mark.skip_t3t1,
pytest.mark.flaky(max_runs=5), pytest.mark.flaky(max_runs=5),
] ]

@ -27,7 +27,7 @@ PIN = "1234"
def _assert_busy(client: Client, should_be_busy: bool, screen: str = "Homescreen"): def _assert_busy(client: Client, should_be_busy: bool, screen: str = "Homescreen"):
assert client.features.busy is should_be_busy assert client.features.busy is should_be_busy
if client.debug.model in ("T", "Safe 3"): if client.model in (models.T2T1, models.T2B1, models.T3T1):
if should_be_busy: if should_be_busy:
assert "CoinJoinProgress" in client.debug.read_layout().all_components() assert "CoinJoinProgress" in client.debug.read_layout().all_components()
else: else:

@ -26,6 +26,7 @@ from ..common import MNEMONIC12
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
def test_layout(client: Client): def test_layout(client: Client):
layout = client.debug.state().layout layout = client.debug.state().layout
assert len(layout) == 1024 assert len(layout) == 1024
@ -33,6 +34,7 @@ def test_layout(client: Client):
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
@pytest.mark.setup_client(mnemonic=MNEMONIC12) @pytest.mark.setup_client(mnemonic=MNEMONIC12)
def test_mnemonic(client: Client): def test_mnemonic(client: Client):
client.ensure_unlocked() client.ensure_unlocked()
@ -42,6 +44,7 @@ def test_mnemonic(client: Client):
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
@pytest.mark.setup_client(mnemonic=MNEMONIC12, pin="1234", passphrase="") @pytest.mark.setup_client(mnemonic=MNEMONIC12, pin="1234", passphrase="")
def test_pin(client: Client): def test_pin(client: Client):
resp = client.call_raw(messages.GetAddress(address_n=parse_path("m/44'/0'/0'/0/0"))) resp = client.call_raw(messages.GetAddress(address_n=parse_path("m/44'/0'/0'/0/0")))

@ -2,13 +2,15 @@ from hashlib import blake2s
import pytest import pytest
from trezorlib import firmware from trezorlib import firmware, models
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
# size of FIRMWARE_AREA, see core/embed/models/model_*_layout.c
FIRMWARE_LENGTHS = { FIRMWARE_LENGTHS = {
"1": 7 * 128 * 1024 + 64 * 1024, models.T1B1: 7 * 128 * 1024 + 64 * 1024,
"T": 13 * 128 * 1024, models.T2T1: 13 * 128 * 1024,
"Safe 3": 13 * 128 * 1024, models.T2B1: 13 * 128 * 1024,
models.T3T1: 208 * 8 * 1024,
} }
@ -16,7 +18,7 @@ def test_firmware_hash_emu(client: Client) -> None:
if client.features.fw_vendor != "EMULATOR": if client.features.fw_vendor != "EMULATOR":
pytest.skip("Only for emulator") pytest.skip("Only for emulator")
data = b"\xff" * FIRMWARE_LENGTHS[client.features.model] data = b"\xff" * FIRMWARE_LENGTHS[client.model]
expected_hash = blake2s(data).digest() expected_hash = blake2s(data).digest()
hash = firmware.get_hash(client, None) hash = firmware.get_hash(client, None)
@ -34,7 +36,7 @@ def test_firmware_hash_hw(client: Client) -> None:
# TODO get firmware image from outside the environment, check for actual result # TODO get firmware image from outside the environment, check for actual result
challenge = b"Hello Trezor" challenge = b"Hello Trezor"
empty_data = b"\xff" * FIRMWARE_LENGTHS[client.features.model] empty_data = b"\xff" * FIRMWARE_LENGTHS[client.model]
empty_hash = blake2s(empty_data).digest() empty_hash = blake2s(empty_data).digest()
empty_hash_challenge = blake2s(empty_data, key=challenge).digest() empty_hash_challenge = blake2s(empty_data, key=challenge).digest()

@ -27,7 +27,11 @@ from ..translations import LANGUAGES, build_and_sign_blob, get_lang_json, set_la
pytestmark = pytest.mark.skip_t1 pytestmark = pytest.mark.skip_t1
MAX_DATA_LENGTH = {models.T2T1: 48 * 1024, models.T2B1: 32 * 1024} MAX_DATA_LENGTH = {
models.T2T1: 48 * 1024,
models.T2B1: 32 * 1024,
models.T3T1: 256 * 1024,
}
def get_ping_button(lang: str) -> str: def get_ping_button(lang: str) -> str:
@ -59,7 +63,7 @@ def _check_ping_screen_texts(client: Client, title: str, right_button: str) -> N
client.debug.press_yes() client.debug.press_yes()
# TT does not have a right button text (but a green OK tick) # TT does not have a right button text (but a green OK tick)
if client.features.model == "T": if client.model in (models.T2T1, models.T3T1):
right_button = "-" right_button = "-"
with client: with client:

@ -135,6 +135,7 @@ def test_apply_settings_passphrase_on_device(client: Client):
@pytest.mark.skip_t1 @pytest.mark.skip_t1
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_t3t1
def test_apply_homescreen_tr_toif_good(client: Client): def test_apply_homescreen_tr_toif_good(client: Client):
with client: with client:
_set_expected_responses(client) _set_expected_responses(client)
@ -147,6 +148,7 @@ def test_apply_homescreen_tr_toif_good(client: Client):
@pytest.mark.skip_t1 @pytest.mark.skip_t1
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_t3t1
@pytest.mark.setup_client(pin=None) # so that "PIN NOT SET" is shown in the header @pytest.mark.setup_client(pin=None) # so that "PIN NOT SET" is shown in the header
def test_apply_homescreen_tr_toif_with_notification(client: Client): def test_apply_homescreen_tr_toif_with_notification(client: Client):
with client: with client:
@ -156,6 +158,7 @@ def test_apply_homescreen_tr_toif_with_notification(client: Client):
@pytest.mark.skip_t1 @pytest.mark.skip_t1
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_t3t1
def test_apply_homescreen_tr_toif_with_long_label(client: Client): def test_apply_homescreen_tr_toif_with_long_label(client: Client):
with client: with client:
_set_expected_responses(client) _set_expected_responses(client)
@ -172,6 +175,7 @@ def test_apply_homescreen_tr_toif_with_long_label(client: Client):
@pytest.mark.skip_t1 @pytest.mark.skip_t1
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_t3t1
def test_apply_homescreen_tr_toif_wrong_size(client: Client): def test_apply_homescreen_tr_toif_wrong_size(client: Client):
# 64x64 img # 64x64 img
img = b"TOIG@\x00@\x009\x02\x00\x00}R\xdb\x81$A\x08\"\x03\xf3\xcf\xd2\x0c<\x01-{\xefc\xe6\xd5\xbbU\xa2\x08T\xd6\xcfw\xf4\xe7\xc7\xb7X\xf1\xe3\x1bl\xf0\xf7\x1b\xf8\x1f\xcf\xe7}\xe1\x83\xcf|>\x8d%\x14\xa5\xb3\xe9p5\xa1;~4:\xcd\xe0&\x11\x1d\xe9\xf6\xa1\x1fw\xf54\x95eWx\xda\xd0u\x91\x86\xb8\xbc\xdf\xdc\x008f\x15\xc6\xf6\x7f\xf0T\xb8\xc1\xa3\xc5_A\xc0G\x930\xe7\xdc=\xd5\xa7\xc1\xbcI\x16\xb8s\x9c&\xaa\x06\xc1}\x8b\x19\x9d'c\xc3\xe3^\xc3m\xb6n\xb0(\x16\xf6\xdeg\xb3\x96:i\xe5\x9c\x02\x93\x9fF\x9f-\xa7\"w\xf3X\x9f\x87\x08\x84\"v,\xab!9:<j+\xcb\xf3_\xc7\xd6^<\xce\xc1\xb8!\xec\x8f/\xb1\xc1\x8f\xbd\xcc\x06\x90\x0e\x98)[\xdb\x15\x99\xaf\xf2~\x8e\xd0\xdb\xcd\xfd\x90\x12\xb6\xdd\xc3\xdd|\x96$\x01P\x86H\xbc\xc0}\xa2\x08\xe5\x82\x06\xd2\xeb\x07[\r\xe4\xdeP\xf4\x86;\xa5\x14c\x12\xe3\xb16x\xad\xc7\x1d\x02\xef\x86<\xc6\x95\xd3/\xc4 \xa1\xf5V\xe2\t\xb2\x8a\xd6`\xf2\xcf\xb7\xd6\x07\xdf8X\xa7\x18\x03\x96\x82\xa4 \xeb.*kP\xceu\x9d~}H\xe9\xb8\x04<4\xff\xf8\xcf\xf6\xa0\xf2\xfcM\xe3/?k\xff\x18\x1d\xb1\xee\xc5\xf5\x1f\x01\x14\x03;\x1bU\x1f~\xcf\xb3\xf7w\xe5\nMfd/\xb93\x9fq\x9bQ\xb7'\xbfvq\x1d\xce\r\xbaDo\x90\xbc\xc5:?;\x84y\x8a\x1e\xad\xe9\xb7\x14\x10~\x9b@\xf8\x82\xdc\x89\xe7\xf0\xe0k4o\x9a\xa0\xc4\xb9\xba\xc56\x01i\x85EO'e6\xb7\x15\xb4G\x05\xe1\xe7%\xd3&\x93\x91\xc9CTQ\xeb\xcc\xd0\xd7E9\xa9JK\xcc\x00\x95(\xdc.\xd2#7:Yo}y_*\x1a\xae6)\x97\x9d\xc0\x80vl\x02\\M\xfe\xc9sW\xa8\xfbD\x99\xb8\xb0:\xbc\x80\xfd\xef\xd3\x94\xbe\x18j9z\x12S\xa1\xec$\x1c\xe3\xd1\xd0\xf4\xdd\xbfI\xf1rBj\x0f\x1cz\x1d\xf7\xa5tR\xb3\xfc\xa4\xd0\xfah\xc3Mj\xbe\x14r\x9d\x84z\xd2\x7f\x13\xb4w\xce\xa0\xaeW\xa4\x18\x0b\xe4\x8f\xe6\xc3\xbeQ\x93\xb0L<J\xe3g9\xb5W#f\xd1\x0b\x96|\xd6z1;\x85\x7f\xe3\xe6[\x02A\xdc\xa4\x02\x1b\x91\x88\x7f" img = b"TOIG@\x00@\x009\x02\x00\x00}R\xdb\x81$A\x08\"\x03\xf3\xcf\xd2\x0c<\x01-{\xefc\xe6\xd5\xbbU\xa2\x08T\xd6\xcfw\xf4\xe7\xc7\xb7X\xf1\xe3\x1bl\xf0\xf7\x1b\xf8\x1f\xcf\xe7}\xe1\x83\xcf|>\x8d%\x14\xa5\xb3\xe9p5\xa1;~4:\xcd\xe0&\x11\x1d\xe9\xf6\xa1\x1fw\xf54\x95eWx\xda\xd0u\x91\x86\xb8\xbc\xdf\xdc\x008f\x15\xc6\xf6\x7f\xf0T\xb8\xc1\xa3\xc5_A\xc0G\x930\xe7\xdc=\xd5\xa7\xc1\xbcI\x16\xb8s\x9c&\xaa\x06\xc1}\x8b\x19\x9d'c\xc3\xe3^\xc3m\xb6n\xb0(\x16\xf6\xdeg\xb3\x96:i\xe5\x9c\x02\x93\x9fF\x9f-\xa7\"w\xf3X\x9f\x87\x08\x84\"v,\xab!9:<j+\xcb\xf3_\xc7\xd6^<\xce\xc1\xb8!\xec\x8f/\xb1\xc1\x8f\xbd\xcc\x06\x90\x0e\x98)[\xdb\x15\x99\xaf\xf2~\x8e\xd0\xdb\xcd\xfd\x90\x12\xb6\xdd\xc3\xdd|\x96$\x01P\x86H\xbc\xc0}\xa2\x08\xe5\x82\x06\xd2\xeb\x07[\r\xe4\xdeP\xf4\x86;\xa5\x14c\x12\xe3\xb16x\xad\xc7\x1d\x02\xef\x86<\xc6\x95\xd3/\xc4 \xa1\xf5V\xe2\t\xb2\x8a\xd6`\xf2\xcf\xb7\xd6\x07\xdf8X\xa7\x18\x03\x96\x82\xa4 \xeb.*kP\xceu\x9d~}H\xe9\xb8\x04<4\xff\xf8\xcf\xf6\xa0\xf2\xfcM\xe3/?k\xff\x18\x1d\xb1\xee\xc5\xf5\x1f\x01\x14\x03;\x1bU\x1f~\xcf\xb3\xf7w\xe5\nMfd/\xb93\x9fq\x9bQ\xb7'\xbfvq\x1d\xce\r\xbaDo\x90\xbc\xc5:?;\x84y\x8a\x1e\xad\xe9\xb7\x14\x10~\x9b@\xf8\x82\xdc\x89\xe7\xf0\xe0k4o\x9a\xa0\xc4\xb9\xba\xc56\x01i\x85EO'e6\xb7\x15\xb4G\x05\xe1\xe7%\xd3&\x93\x91\xc9CTQ\xeb\xcc\xd0\xd7E9\xa9JK\xcc\x00\x95(\xdc.\xd2#7:Yo}y_*\x1a\xae6)\x97\x9d\xc0\x80vl\x02\\M\xfe\xc9sW\xa8\xfbD\x99\xb8\xb0:\xbc\x80\xfd\xef\xd3\x94\xbe\x18j9z\x12S\xa1\xec$\x1c\xe3\xd1\xd0\xf4\xdd\xbfI\xf1rBj\x0f\x1cz\x1d\xf7\xa5tR\xb3\xfc\xa4\xd0\xfah\xc3Mj\xbe\x14r\x9d\x84z\xd2\x7f\x13\xb4w\xce\xa0\xaeW\xa4\x18\x0b\xe4\x8f\xe6\xc3\xbeQ\x93\xb0L<J\xe3g9\xb5W#f\xd1\x0b\x96|\xd6z1;\x85\x7f\xe3\xe6[\x02A\xdc\xa4\x02\x1b\x91\x88\x7f"
@ -182,6 +186,7 @@ def test_apply_homescreen_tr_toif_wrong_size(client: Client):
@pytest.mark.skip_t1 @pytest.mark.skip_t1
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_t3t1
def test_apply_homescreen_tr_upload_jpeg_fail(client: Client): def test_apply_homescreen_tr_upload_jpeg_fail(client: Client):
with open(HERE / "test_bg.jpg", "rb") as f: with open(HERE / "test_bg.jpg", "rb") as f:
img = f.read() img = f.read()
@ -192,6 +197,7 @@ def test_apply_homescreen_tr_upload_jpeg_fail(client: Client):
@pytest.mark.skip_t1 @pytest.mark.skip_t1
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_t3t1
def test_apply_homescreen_tr_upload_t1_fail(client: Client): def test_apply_homescreen_tr_upload_t1_fail(client: Client):
with pytest.raises(exceptions.TrezorFailure), client: with pytest.raises(exceptions.TrezorFailure), client:
_set_expected_responses(client) _set_expected_responses(client)
@ -327,6 +333,7 @@ def test_apply_homescreen_jpeg_wrong_size(client: Client):
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
def test_apply_homescreen(client: Client): def test_apply_homescreen(client: Client):
with client: with client:
_set_expected_responses(client) _set_expected_responses(client)

@ -29,7 +29,7 @@ WIPE_CODE6 = "456789"
WIPE_CODE_MAX = "".join(chr((i % 9) + ord("1")) for i in range(MAX_PIN_LENGTH)) WIPE_CODE_MAX = "".join(chr((i % 9) + ord("1")) for i in range(MAX_PIN_LENGTH))
WIPE_CODE_TOO_LONG = WIPE_CODE_MAX + "1" WIPE_CODE_TOO_LONG = WIPE_CODE_MAX + "1"
pytestmark = [pytest.mark.skip_t2, pytest.mark.skip_tr] pytestmark = [pytest.mark.skip_t2, pytest.mark.skip_tr, pytest.mark.skip_t3t1]
def _set_wipe_code(client: Client, pin, wipe_code): def _set_wipe_code(client: Client, pin, wipe_code):

@ -16,7 +16,7 @@
import pytest import pytest
from trezorlib import btc, device, messages from trezorlib import btc, device, messages, models
from trezorlib.client import MAX_PIN_LENGTH, PASSPHRASE_TEST_PATH from trezorlib.client import MAX_PIN_LENGTH, PASSPHRASE_TEST_PATH
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
@ -38,9 +38,13 @@ def _check_wipe_code(client: Client, pin: str, wipe_code: str):
# Try to change the PIN to the current wipe code value. The operation should fail. # Try to change the PIN to the current wipe code value. The operation should fail.
with client, pytest.raises(TrezorFailure): with client, pytest.raises(TrezorFailure):
client.use_pin_sequence([pin, wipe_code, wipe_code]) client.use_pin_sequence([pin, wipe_code, wipe_code])
br_amount = 5 if client.debug.model == "T" else 6 br_count = {
models.T2T1: 5,
models.T2B1: 6,
models.T3T1: 5,
}[client.model]
client.set_expected_responses( client.set_expected_responses(
[messages.ButtonRequest()] * br_amount [messages.ButtonRequest()] * br_count
+ [messages.Failure(code=messages.FailureType.PinInvalid)] + [messages.Failure(code=messages.FailureType.PinInvalid)]
) )
device.change_pin(client) device.change_pin(client)
@ -62,10 +66,15 @@ def test_set_remove_wipe_code(client: Client):
_ensure_unlocked(client, PIN4) _ensure_unlocked(client, PIN4)
assert client.features.wipe_code_protection is False assert client.features.wipe_code_protection is False
br_count = {
models.T2T1: 5,
models.T2B1: 6,
models.T3T1: 5,
}[client.model]
with client: with client:
br_amount = 5 if client.debug.model == "T" else 6
client.set_expected_responses( client.set_expected_responses(
[messages.ButtonRequest()] * br_amount [messages.ButtonRequest()] * br_count
+ [messages.Success, messages.Features] + [messages.Success, messages.Features]
) )
client.use_pin_sequence([PIN4, WIPE_CODE_MAX, WIPE_CODE_MAX]) client.use_pin_sequence([PIN4, WIPE_CODE_MAX, WIPE_CODE_MAX])
@ -77,9 +86,8 @@ def test_set_remove_wipe_code(client: Client):
# Test change wipe code. # Test change wipe code.
with client: with client:
br_amount = 5 if client.debug.model == "T" else 6
client.set_expected_responses( client.set_expected_responses(
[messages.ButtonRequest()] * br_amount [messages.ButtonRequest()] * br_count
+ [messages.Success, messages.Features] + [messages.Success, messages.Features]
) )
client.use_pin_sequence([PIN4, WIPE_CODE6, WIPE_CODE6]) client.use_pin_sequence([PIN4, WIPE_CODE6, WIPE_CODE6])
@ -118,10 +126,14 @@ def test_set_wipe_code_to_pin(client: Client):
_ensure_unlocked(client, PIN4) _ensure_unlocked(client, PIN4)
with client: with client:
br_amount = 7 if client.debug.model == "T" else 8 br_count = {
models.T2T1: 7,
models.T2B1: 8,
models.T3T1: 7,
}[client.model]
client.set_expected_responses( client.set_expected_responses(
[messages.ButtonRequest()] * br_amount [messages.ButtonRequest()] * br_count
+ [messages.Success, messages.Features] + [messages.Success, messages.Features],
) )
client.use_pin_sequence([PIN4, PIN4, WIPE_CODE4, WIPE_CODE4]) client.use_pin_sequence([PIN4, PIN4, WIPE_CODE4, WIPE_CODE4])
device.change_wipe_code(client) device.change_wipe_code(client)
@ -134,9 +146,13 @@ def test_set_wipe_code_to_pin(client: Client):
def test_set_pin_to_wipe_code(client: Client): def test_set_pin_to_wipe_code(client: Client):
# Set wipe code. # Set wipe code.
with client: with client:
br_amount = 4 if client.debug.model == "T" else 5 br_count = {
models.T2T1: 4,
models.T2B1: 5,
models.T3T1: 4,
}[client.model]
client.set_expected_responses( client.set_expected_responses(
[messages.ButtonRequest()] * br_amount [messages.ButtonRequest()] * br_count
+ [messages.Success, messages.Features] + [messages.Success, messages.Features]
) )
client.use_pin_sequence([WIPE_CODE4, WIPE_CODE4]) client.use_pin_sequence([WIPE_CODE4, WIPE_CODE4])
@ -144,9 +160,13 @@ def test_set_pin_to_wipe_code(client: Client):
# Try to set the PIN to the current wipe code value. # Try to set the PIN to the current wipe code value.
with client, pytest.raises(TrezorFailure): with client, pytest.raises(TrezorFailure):
br_amount = 4 if client.debug.model == "T" else 6 br_count = {
models.T2T1: 4,
models.T2B1: 6,
models.T3T1: 4,
}[client.model]
client.set_expected_responses( client.set_expected_responses(
[messages.ButtonRequest()] * br_amount [messages.ButtonRequest()] * br_count
+ [messages.Failure(code=messages.FailureType.PinInvalid)] + [messages.Failure(code=messages.FailureType.PinInvalid)]
) )
client.use_pin_sequence([WIPE_CODE4, WIPE_CODE4]) client.use_pin_sequence([WIPE_CODE4, WIPE_CODE4])

@ -28,7 +28,7 @@ PIN6 = "789456"
PIN_MAX = "".join(chr((i % 9) + ord("1")) for i in range(MAX_PIN_LENGTH)) PIN_MAX = "".join(chr((i % 9) + ord("1")) for i in range(MAX_PIN_LENGTH))
PIN_TOO_LONG = PIN_MAX + "1" PIN_TOO_LONG = PIN_MAX + "1"
pytestmark = [pytest.mark.skip_t2, pytest.mark.skip_tr] pytestmark = [pytest.mark.skip_t2, pytest.mark.skip_tr, pytest.mark.skip_t3t1]
def _check_pin(client: Client, pin): def _check_pin(client: Client, pin):

@ -16,7 +16,7 @@
import pytest import pytest
from trezorlib import btc, device, messages from trezorlib import btc, device, messages, models
from trezorlib.client import MAX_PIN_LENGTH, PASSPHRASE_TEST_PATH from trezorlib.client import MAX_PIN_LENGTH, PASSPHRASE_TEST_PATH
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import Cancelled, TrezorFailure from trezorlib.exceptions import Cancelled, TrezorFailure
@ -62,10 +62,14 @@ def test_set_pin(client: Client):
# Let's set new PIN # Let's set new PIN
with client: with client:
br_amount = 4 if client.debug.model == "T" else 6 br_count = {
models.T2T1: 4,
models.T2B1: 6,
models.T3T1: 4,
}[client.model]
client.use_pin_sequence([PIN_MAX, PIN_MAX]) client.use_pin_sequence([PIN_MAX, PIN_MAX])
client.set_expected_responses( client.set_expected_responses(
[messages.ButtonRequest] * br_amount + [messages.Success, messages.Features] [messages.ButtonRequest] * br_count + [messages.Success, messages.Features]
) )
device.change_pin(client) device.change_pin(client)
@ -84,9 +88,13 @@ def test_change_pin(client: Client):
# Let's change PIN # Let's change PIN
with client: with client:
client.use_pin_sequence([PIN4, PIN_MAX, PIN_MAX]) client.use_pin_sequence([PIN4, PIN_MAX, PIN_MAX])
br_amount = 5 if client.debug.model == "T" else 6 br_count = {
models.T2T1: 5,
models.T2B1: 6,
models.T3T1: 5,
}[client.model]
client.set_expected_responses( client.set_expected_responses(
[messages.ButtonRequest] * br_amount + [messages.Success, messages.Features] [messages.ButtonRequest] * br_count + [messages.Success, messages.Features]
) )
device.change_pin(client) device.change_pin(client)

@ -59,6 +59,7 @@ def test_correct_pin(client: Client):
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
def test_incorrect_pin_t1(client: Client): def test_incorrect_pin_t1(client: Client):
with pytest.raises(PinException): with pytest.raises(PinException):
client.use_pin_sequence([BAD_PIN]) client.use_pin_sequence([BAD_PIN])
@ -82,6 +83,7 @@ def test_incorrect_pin_t2(client: Client):
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
def test_exponential_backoff_t1(client: Client): def test_exponential_backoff_t1(client: Client):
for attempt in range(3): for attempt in range(3):
start = time.time() start = time.time()

@ -21,7 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from ..common import MNEMONIC12, WITH_MOCK_URANDOM, get_test_address from ..common import MNEMONIC12, WITH_MOCK_URANDOM, get_test_address, is_core
from ..tx_cache import TxCache from ..tx_cache import TxCache
from .bitcoin.signtx import ( from .bitcoin.signtx import (
request_finished, request_finished,
@ -112,6 +112,7 @@ def test_apply_settings(client: Client):
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
def test_change_pin_t1(client: Client): def test_change_pin_t1(client: Client):
_assert_protection(client) _assert_protection(client)
with client: with client:
@ -212,6 +213,7 @@ def test_wipe_device(client: Client):
@pytest.mark.setup_client(uninitialized=True) @pytest.mark.setup_client(uninitialized=True)
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
def test_reset_device(client: Client): def test_reset_device(client: Client):
assert client.features.pin_protection is False assert client.features.pin_protection is False
assert client.features.passphrase_protection is False assert client.features.passphrase_protection is False
@ -241,6 +243,7 @@ def test_reset_device(client: Client):
@pytest.mark.setup_client(uninitialized=True) @pytest.mark.setup_client(uninitialized=True)
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
def test_recovery_device(client: Client): def test_recovery_device(client: Client):
assert client.features.pin_protection is False assert client.features.pin_protection is False
assert client.features.passphrase_protection is False assert client.features.passphrase_protection is False
@ -294,6 +297,7 @@ def test_sign_message(client: Client):
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
def test_verify_message_t1(client: Client): def test_verify_message_t1(client: Client):
_assert_protection(client) _assert_protection(client)
with client: with client:
@ -359,7 +363,6 @@ def test_signtx(client: Client):
_assert_protection(client) _assert_protection(client)
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.use_pin_sequence([PIN4]) client.use_pin_sequence([PIN4])
client.set_expected_responses( client.set_expected_responses(
[ [
@ -368,7 +371,7 @@ def test_signtx(client: Client):
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_meta(TXHASH_50f6f1), request_meta(TXHASH_50f6f1),

@ -113,7 +113,10 @@ def test_sd_protect_unlock(client: Client):
client.debug.input("1234") client.debug.input("1234")
yield # SD card problem yield # SD card problem
TR.assert_in(layout().text_content(), "sd_card__unplug_and_insert_correct") TR.assert_in_multiple(
layout().text_content(),
["sd_card__unplug_and_insert_correct", "sd_card__insert_correct_card"],
)
client.debug.press_no() # close client.debug.press_no() # close
with client, pytest.raises(TrezorFailure) as e: with client, pytest.raises(TrezorFailure) as e:

@ -18,7 +18,7 @@ import random
import pytest import pytest
from trezorlib import device, exceptions, messages from trezorlib import device, exceptions, messages, models
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
from trezorlib.messages import FailureType, SafetyCheckLevel from trezorlib.messages import FailureType, SafetyCheckLevel
@ -316,6 +316,7 @@ def test_passphrase_always_on_device(client: Client):
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.skip_tr @pytest.mark.skip_tr
@pytest.mark.skip_t3t1
@pytest.mark.setup_client(passphrase="") @pytest.mark.setup_client(passphrase="")
def test_passphrase_on_device_not_possible_on_t1(client: Client): def test_passphrase_on_device_not_possible_on_t1(client: Client):
# This setting makes no sense on T1. # This setting makes no sense on T1.
@ -401,12 +402,14 @@ def test_hide_passphrase_from_host(client: Client):
client.debug.wait_layout().text_content(), client.debug.wait_layout().text_content(),
"passphrase__access_hidden_wallet", "passphrase__access_hidden_wallet",
) )
if client.debug.model == "T": if client.model in (models.T2T1, models.T3T1):
client.debug.press_yes() client.debug.press_yes()
elif client.debug.model == "Safe 3": elif client.model is models.T2B1:
client.debug.press_right() client.debug.press_right()
client.debug.press_right() client.debug.press_right()
client.debug.press_yes() client.debug.press_yes()
else:
raise KeyError
client.watch_layout() client.watch_layout()
client.set_input_flow(input_flow) client.set_input_flow(input_flow)

@ -21,6 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from ...common import is_core
from ..bitcoin.signtx import request_finished, request_input, request_output from ..bitcoin.signtx import request_finished, request_input, request_output
B = messages.ButtonRequestType B = messages.ButtonRequestType
@ -95,13 +96,12 @@ def test_spend_v4_input(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_output(0), request_output(0),
@ -144,13 +144,12 @@ def test_send_to_multisig(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_output(0), request_output(0),
@ -192,13 +191,12 @@ def test_spend_v5_input(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_output(0), request_output(0),
@ -246,13 +244,12 @@ def test_one_two(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -305,13 +302,12 @@ def test_unified_address(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
request_output(1), request_output(1),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
@ -370,14 +366,13 @@ def test_external_presigned(client: Client):
) )
with client: with client:
is_core = client.features.model in ("T", "Safe 3")
client.set_expected_responses( client.set_expected_responses(
[ [
request_input(0), request_input(0),
request_input(1), request_input(1),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(1), request_input(1),
request_input(0), request_input(0),
@ -483,12 +478,11 @@ def test_spend_multisig(client: Client):
) )
# Expected responses are the same for both two signings # Expected responses are the same for both two signings
is_core = client.features.model in ("T", "Safe 3")
expected_responses = [ expected_responses = [
request_input(0), request_input(0),
request_output(0), request_output(0),
messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.ConfirmOutput),
(is_core, messages.ButtonRequest(code=B.ConfirmOutput)), (is_core(client), messages.ButtonRequest(code=B.ConfirmOutput)),
messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx),
request_input(0), request_input(0),
request_output(0), request_output(0),

@ -14,7 +14,7 @@ from __future__ import annotations
import time import time
from typing import Callable, Generator from typing import Callable, Generator
from trezorlib import messages from trezorlib import messages, models
from trezorlib.debuglink import DebugLink, LayoutContent from trezorlib.debuglink import DebugLink, LayoutContent
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.debuglink import multipage_content from trezorlib.debuglink import multipage_content
@ -44,8 +44,8 @@ class InputFlowBase:
self.BAK = BackupFlow(self.client) self.BAK = BackupFlow(self.client)
self.ETH = EthereumFlow(self.client) self.ETH = EthereumFlow(self.client)
def model(self) -> str | None: def model(self) -> str | models.TrezorModel:
return self.client.features.model return self.client.model
def get(self) -> Callable[[], BRGeneratorType]: def get(self) -> Callable[[], BRGeneratorType]:
self.client.watch_layout(True) self.client.watch_layout(True)
@ -53,10 +53,12 @@ class InputFlowBase:
# There could be one common input flow for all models # There could be one common input flow for all models
if hasattr(self, "input_flow_common"): if hasattr(self, "input_flow_common"):
return getattr(self, "input_flow_common") return getattr(self, "input_flow_common")
elif self.model() == "T": elif self.model() is models.T2T1:
return self.input_flow_tt return self.input_flow_tt
elif self.model() == "Safe 3": elif self.model() is models.T2B1:
return self.input_flow_tr return self.input_flow_tr
elif self.model() is models.T3T1:
return self.input_flow_t3t1
else: else:
raise ValueError("Unknown model") raise ValueError("Unknown model")
@ -68,6 +70,10 @@ class InputFlowBase:
"""Special for TR""" """Special for TR"""
raise NotImplementedError raise NotImplementedError
def input_flow_t3t1(self) -> BRGeneratorType:
"""Special for T3T1"""
raise NotImplementedError
def text_content(self) -> str: def text_content(self) -> str:
return self.debug.wait_layout().text_content() return self.debug.wait_layout().text_content()
@ -91,7 +97,7 @@ class InputFlowSetupDevicePINWIpeCode(InputFlowBase):
yield # do you want to set/change the wipe code? yield # do you want to set/change the wipe code?
self.debug.press_yes() self.debug.press_yes()
if self.debug.model == "Safe 3": if self.model() is models.T2B1:
yield from swipe_if_necessary(self.debug) # wipe code info yield from swipe_if_necessary(self.debug) # wipe code info
self.debug.press_yes() self.debug.press_yes()
@ -120,7 +126,7 @@ class InputFlowNewCodeMismatch(InputFlowBase):
yield # do you want to set/change the pin/wipe code? yield # do you want to set/change the pin/wipe code?
self.debug.press_yes() self.debug.press_yes()
if self.debug.model == "Safe 3": if self.model() is models.T2B1:
yield from swipe_if_necessary(self.debug) # code info yield from swipe_if_necessary(self.debug) # code info
self.debug.press_yes() self.debug.press_yes()
@ -247,6 +253,28 @@ class InputFlowSignMessagePagination(InputFlowBase):
yield yield
self.debug.press_yes() self.debug.press_yes()
def input_flow_t3t1(self) -> BRGeneratorType:
# collect screen contents into `message_read`.
# Using a helper debuglink function to assemble the final text.
layouts: list[LayoutContent] = []
br = yield # confirm address
self.debug.wait_layout()
self.debug.press_yes()
br = yield
assert br.pages is not None
for i in range(br.pages):
layout = self.debug.wait_layout()
layouts.append(layout)
if i < br.pages - 1:
self.debug.swipe_up()
self.message_read = multipage_content(layouts)
self.debug.press_yes()
class InputFlowSignMessageInfo(InputFlowBase): class InputFlowSignMessageInfo(InputFlowBase):
def __init__(self, client: Client): def __init__(self, client: Client):
@ -269,6 +297,23 @@ class InputFlowSignMessageInfo(InputFlowBase):
self.debug.press_no(wait=True) self.debug.press_no(wait=True)
self.debug.press_yes(wait=True) self.debug.press_yes(wait=True)
def input_flow_t3t1(self) -> BRGeneratorType:
yield
# show address/message info
self.debug.click(buttons.CORNER_BUTTON, wait=True)
self.debug.click(buttons.CORNER_BUTTON, wait=True)
self.debug.press_no(wait=True)
self.debug.synchronize_at("IconDialog")
# address mismatch?
self.debug.press_no()
yield
self.debug.press_yes()
yield
self.debug.press_no()
yield
self.debug.press_no(wait=True)
self.debug.press_yes(wait=True)
class InputFlowShowAddressQRCode(InputFlowBase): class InputFlowShowAddressQRCode(InputFlowBase):
def __init__(self, client: Client): def __init__(self, client: Client):
@ -309,6 +354,20 @@ class InputFlowShowAddressQRCode(InputFlowBase):
self.debug.press_right() self.debug.press_right()
self.debug.press_middle() self.debug.press_middle()
def input_flow_t3t1(self) -> BRGeneratorType:
yield
self.debug.click(buttons.CORNER_BUTTON, wait=True)
# synchronize; TODO get rid of this once we have single-global-layout
self.debug.synchronize_at("SimplePage")
self.debug.swipe_left(wait=True)
self.debug.swipe_right(wait=True)
self.debug.swipe_left(wait=True)
self.debug.click(buttons.CORNER_BUTTON, wait=True)
self.debug.press_no(wait=True)
self.debug.press_no(wait=True)
self.debug.press_yes()
class InputFlowShowAddressQRCodeCancel(InputFlowBase): class InputFlowShowAddressQRCodeCancel(InputFlowBase):
def __init__(self, client: Client): def __init__(self, client: Client):
@ -340,6 +399,17 @@ class InputFlowShowAddressQRCodeCancel(InputFlowBase):
self.debug.press_right() self.debug.press_right()
self.debug.press_right() self.debug.press_right()
def input_flow_t3t1(self) -> BRGeneratorType:
yield
self.debug.click(buttons.CORNER_BUTTON, wait=True)
# synchronize; TODO get rid of this once we have single-global-layout
self.debug.synchronize_at("SimplePage")
self.debug.swipe_left(wait=True)
self.debug.click(buttons.CORNER_BUTTON, wait=True)
self.debug.press_no(wait=True)
self.debug.press_yes()
class InputFlowShowMultisigXPUBs(InputFlowBase): class InputFlowShowMultisigXPUBs(InputFlowBase):
def __init__(self, client: Client, address: str, xpubs: list[str], index: int): def __init__(self, client: Client, address: str, xpubs: list[str], index: int):
@ -422,6 +492,40 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
# show address # show address
self.debug.press_middle() self.debug.press_middle()
def input_flow_t3t1(self) -> BRGeneratorType:
yield # multisig address warning
self.debug.press_yes()
yield # show address
layout = self.debug.wait_layout()
TR.assert_in(layout.title(), "address__title_receive_address")
assert "(MULTISIG)" in layout.title()
assert layout.text_content().replace(" ", "") == self.address
self.debug.click(buttons.CORNER_BUTTON)
assert "Qr" in self.all_components()
layout = self.debug.swipe_left(wait=True)
# address details
assert "Multisig 2 of 3" in layout.screen_content()
TR.assert_in(layout.screen_content(), "address_details__derivation_path")
# Three xpub pages with the same testing logic
for xpub_num in range(3):
expected_title = f"MULTISIG XPUB #{xpub_num + 1}"
layout = self.debug.swipe_left(wait=True)
assert expected_title in layout.title()
content = layout.text_content().replace(" ", "")
assert self.xpubs[xpub_num] in content
self.debug.click(buttons.CORNER_BUTTON, wait=True)
# show address
self.debug.press_no(wait=True)
# address mismatch
self.debug.press_no(wait=True)
# show address
self.debug.press_yes()
class InputFlowShowXpubQRCode(InputFlowBase): class InputFlowShowXpubQRCode(InputFlowBase):
def __init__(self, client: Client, passphrase: bool = False): def __init__(self, client: Client, passphrase: bool = False):
@ -482,6 +586,33 @@ class InputFlowShowXpubQRCode(InputFlowBase):
# Confirm # Confirm
self.debug.press_middle() self.debug.press_middle()
def input_flow_t3t1(self) -> BRGeneratorType:
if self.passphrase:
yield
self.debug.press_yes()
yield
self.debug.press_yes()
br = yield
layout = self.debug.wait_layout()
if "coinjoin" in layout.title().lower() or br.code == B.UnknownDerivationPath:
self.debug.press_yes()
br = yield
self.debug.click(buttons.CORNER_BUTTON, wait=True)
# synchronize; TODO get rid of this once we have single-global-layout
self.debug.synchronize_at("SimplePage")
self.debug.swipe_left(wait=True)
self.debug.swipe_right(wait=True)
self.debug.swipe_left(wait=True)
self.debug.click(buttons.CORNER_BUTTON, wait=True)
self.debug.press_no(wait=True)
self.debug.press_no(wait=True)
for _ in range(br.pages - 1):
self.debug.swipe_up(wait=True)
self.debug.press_yes()
class InputFlowPaymentRequestDetails(InputFlowBase): class InputFlowPaymentRequestDetails(InputFlowBase):
def __init__(self, client: Client, outputs: list[messages.TxOutputType]): def __init__(self, client: Client, outputs: list[messages.TxOutputType]):
@ -512,6 +643,30 @@ class InputFlowPaymentRequestDetails(InputFlowBase):
yield # confirm transaction yield # confirm transaction
self.debug.press_yes() self.debug.press_yes()
def input_flow_t3t1(self) -> BRGeneratorType:
yield # request to see details
self.debug.wait_layout()
self.debug.press_info()
yield # confirm first output
assert self.outputs[0].address[:16] in self.text_content() # type: ignore
self.debug.press_yes()
yield # confirm first output
self.debug.wait_layout()
self.debug.press_yes()
yield # confirm second output
assert self.outputs[1].address[:16] in self.text_content() # type: ignore
self.debug.press_yes()
yield # confirm second output
self.debug.wait_layout()
self.debug.press_yes()
yield # confirm transaction
self.debug.press_yes()
yield # confirm transaction
self.debug.press_yes()
class InputFlowSignTxHighFee(InputFlowBase): class InputFlowSignTxHighFee(InputFlowBase):
def __init__(self, client: Client): def __init__(self, client: Client):
@ -607,6 +762,11 @@ class InputFlowSignTxInformation(InputFlowBase):
self.assert_content(content, "confirm_total__title_sending_from") self.assert_content(content, "confirm_total__title_sending_from")
self.debug.press_yes() self.debug.press_yes()
def input_flow_t3t1(self) -> BRGeneratorType:
content = yield from sign_tx_go_to_info(self.client)
self.assert_content(content, "confirm_total__sending_from_account")
self.debug.press_yes()
class InputFlowSignTxInformationMixed(InputFlowBase): class InputFlowSignTxInformationMixed(InputFlowBase):
def __init__(self, client: Client): def __init__(self, client: Client):
@ -636,6 +796,15 @@ class InputFlowSignTxInformationMixed(InputFlowBase):
self.assert_content(content, "confirm_total__title_sending_from") self.assert_content(content, "confirm_total__title_sending_from")
self.debug.press_yes() self.debug.press_yes()
def input_flow_t3t1(self) -> BRGeneratorType:
# multiple accounts warning
yield
self.debug.press_yes()
content = yield from sign_tx_go_to_info(self.client)
self.assert_content(content, "confirm_total__sending_from_account")
self.debug.press_yes()
class InputFlowSignTxInformationCancel(InputFlowBase): class InputFlowSignTxInformationCancel(InputFlowBase):
def __init__(self, client: Client): def __init__(self, client: Client):
@ -649,6 +818,10 @@ class InputFlowSignTxInformationCancel(InputFlowBase):
yield from sign_tx_go_to_info_tr(self.client) yield from sign_tx_go_to_info_tr(self.client)
self.debug.press_left() self.debug.press_left()
def input_flow_t3t1(self) -> BRGeneratorType:
yield from sign_tx_go_to_info(self.client)
self.debug.press_no()
class InputFlowSignTxInformationReplacement(InputFlowBase): class InputFlowSignTxInformationReplacement(InputFlowBase):
def __init__(self, client: Client): def __init__(self, client: Client):
@ -685,6 +858,23 @@ class InputFlowSignTxInformationReplacement(InputFlowBase):
self.debug.press_right() self.debug.press_right()
yield yield
def input_flow_t3t1(self) -> BRGeneratorType:
yield # confirm txid
self.debug.press_yes()
yield # confirm address
self.debug.press_yes()
# go back to address
self.debug.press_no()
# confirm address
self.debug.press_yes()
yield # confirm amount
self.debug.press_yes()
yield # transaction summary, press info
self.debug.click(buttons.CORNER_BUTTON, wait=True)
self.debug.click(buttons.CORNER_BUTTON, wait=True)
self.debug.press_yes()
def lock_time_input_flow_tt( def lock_time_input_flow_tt(
debug: DebugLink, debug: DebugLink,
@ -746,6 +936,11 @@ class InputFlowLockTimeBlockHeight(InputFlowBase):
def input_flow_tr(self) -> BRGeneratorType: def input_flow_tr(self) -> BRGeneratorType:
yield from lock_time_input_flow_tr(self.debug, self.assert_func) yield from lock_time_input_flow_tr(self.debug, self.assert_func)
def input_flow_t3t1(self) -> BRGeneratorType:
yield from lock_time_input_flow_tt(
self.debug, self.assert_func, double_confirm=True
)
class InputFlowLockTimeDatetime(InputFlowBase): class InputFlowLockTimeDatetime(InputFlowBase):
def __init__(self, client: Client, lock_time_str: str): def __init__(self, client: Client, lock_time_str: str):
@ -763,6 +958,9 @@ class InputFlowLockTimeDatetime(InputFlowBase):
def input_flow_tr(self) -> BRGeneratorType: def input_flow_tr(self) -> BRGeneratorType:
yield from lock_time_input_flow_tr(self.debug, self.assert_func) yield from lock_time_input_flow_tr(self.debug, self.assert_func)
def input_flow_t3t1(self) -> BRGeneratorType:
yield from lock_time_input_flow_tt(self.debug, self.assert_func)
class InputFlowEIP712ShowMore(InputFlowBase): class InputFlowEIP712ShowMore(InputFlowBase):
SHOW_MORE = (143, 167) SHOW_MORE = (143, 167)
@ -773,9 +971,9 @@ class InputFlowEIP712ShowMore(InputFlowBase):
def _confirm_show_more(self) -> None: def _confirm_show_more(self) -> None:
"""Model-specific, either clicks a screen or presses a button.""" """Model-specific, either clicks a screen or presses a button."""
if self.model() == "T": if self.model() in (models.T2T1, models.T3T1):
self.debug.click(self.SHOW_MORE) self.debug.click(self.SHOW_MORE)
elif self.model() == "Safe 3": elif self.model() is models.T2B1:
self.debug.press_right() self.debug.press_right()
def input_flow_common(self) -> BRGeneratorType: def input_flow_common(self) -> BRGeneratorType:
@ -1087,6 +1285,31 @@ class InputFlowSlip39BasicBackup(InputFlowBase):
assert br.code == B.Success assert br.code == B.Success
self.debug.press_yes() self.debug.press_yes()
def input_flow_t3t1(self) -> BRGeneratorType:
yield # 1. Checklist
self.debug.press_yes()
if self.click_info:
yield from click_info_button_tt(self.debug)
yield # 2. Number of shares (5)
self.debug.press_yes()
yield # 3. Checklist
self.debug.press_yes()
if self.click_info:
yield from click_info_button_tt(self.debug)
yield # 4. Threshold (3)
self.debug.press_yes()
yield # 5. Checklist
self.debug.press_yes()
yield # 6. Confirm show seeds
self.debug.press_yes()
# Mnemonic phrases
self.mnemonics = yield from load_5_shares(self.debug)
br = yield # Confirm backup
assert br.code == B.Success
self.debug.press_yes()
class InputFlowSlip39BasicResetRecovery(InputFlowBase): class InputFlowSlip39BasicResetRecovery(InputFlowBase):
def __init__(self, client: Client): def __init__(self, client: Client):
@ -1140,6 +1363,24 @@ class InputFlowSlip39BasicResetRecovery(InputFlowBase):
assert br.code == B.Success assert br.code == B.Success
self.debug.press_yes() self.debug.press_yes()
def input_flow_t3t1(self) -> BRGeneratorType:
# 1. Confirm Reset
# 2. Backup your seed
# 3. Confirm warning
# 4. shares info
# 5. Set & Confirm number of shares
# 6. threshold info
# 7. Set & confirm threshold value
# 8. Confirm show seeds
yield from click_through(self.debug, screens=8, code=B.ResetDevice)
# Mnemonic phrases
self.mnemonics = yield from load_5_shares(self.debug)
br = yield # safety warning
assert br.code == B.Success
self.debug.press_yes()
def load_5_groups_5_shares( def load_5_groups_5_shares(
debug: DebugLink, debug: DebugLink,
@ -1229,6 +1470,40 @@ class InputFlowSlip39AdvancedBackup(InputFlowBase):
assert br.code == B.Success assert br.code == B.Success
self.debug.press_yes() self.debug.press_yes()
def input_flow_t3t1(self) -> BRGeneratorType:
yield # 1. Checklist
self.debug.press_yes()
if self.click_info:
yield from click_info_button_tt(self.debug)
yield # 2. Set and confirm group count
self.debug.press_yes()
yield # 3. Checklist
self.debug.press_yes()
if self.click_info:
yield from click_info_button_tt(self.debug)
yield # 4. Set and confirm group threshold
self.debug.press_yes()
yield # 5. Checklist
self.debug.press_yes()
for _ in range(5): # for each of 5 groups
if self.click_info:
yield from click_info_button_tt(self.debug)
yield # Set & Confirm number of shares
self.debug.press_yes()
if self.click_info:
yield from click_info_button_tt(self.debug)
yield # Set & confirm share threshold value
self.debug.press_yes()
yield # Confirm show seeds
self.debug.press_yes()
# Mnemonic phrases - show & confirm shares for all groups
self.mnemonics = yield from load_5_groups_5_shares(self.debug)
br = yield # Confirm backup
assert br.code == B.Success
self.debug.press_yes()
class InputFlowSlip39AdvancedResetRecovery(InputFlowBase): class InputFlowSlip39AdvancedResetRecovery(InputFlowBase):
def __init__(self, client: Client, click_info: bool): def __init__(self, client: Client, click_info: bool):
@ -1291,6 +1566,27 @@ class InputFlowSlip39AdvancedResetRecovery(InputFlowBase):
assert br.code == B.Success assert br.code == B.Success
self.debug.press_yes() self.debug.press_yes()
def input_flow_t3t1(self) -> BRGeneratorType:
# 1. Confirm Reset
# 2. Backup your seed
# 3. Confirm warning
# 4. shares info
# 5. Set & Confirm number of groups
# 6. threshold info
# 7. Set & confirm group threshold value
# 8-17: for each of 5 groups:
# 1. Set & Confirm number of shares
# 2. Set & confirm share threshold value
# 18. Confirm show seeds
yield from click_through(self.debug, screens=18, code=B.ResetDevice)
# Mnemonic phrases - show & confirm shares for all groups
self.mnemonics = yield from load_5_groups_5_shares(self.debug)
br = yield # safety warning
assert br.code == B.Success
self.debug.press_yes()
class InputFlowBip39RecoveryDryRun(InputFlowBase): class InputFlowBip39RecoveryDryRun(InputFlowBase):
def __init__(self, client: Client, mnemonic: list[str], mismatch: bool = False): def __init__(self, client: Client, mnemonic: list[str], mismatch: bool = False):
@ -1377,7 +1673,7 @@ class InputFlowSlip39AdvancedRecoveryAbort(InputFlowBase):
def input_flow_common(self) -> BRGeneratorType: def input_flow_common(self) -> BRGeneratorType:
yield from self.REC.confirm_recovery() yield from self.REC.confirm_recovery()
if self.debug.model == "T": if self.model() in (models.T2T1, models.T3T1):
yield from self.REC.input_number_of_words(20) yield from self.REC.input_number_of_words(20)
yield from self.REC.abort_recovery(True) yield from self.REC.abort_recovery(True)
@ -1390,7 +1686,7 @@ class InputFlowSlip39AdvancedRecoveryNoAbort(InputFlowBase):
def input_flow_common(self) -> BRGeneratorType: def input_flow_common(self) -> BRGeneratorType:
yield from self.REC.confirm_recovery() yield from self.REC.confirm_recovery()
if self.debug.model == "T": if self.model() in (models.T2T1, models.T3T1):
yield from self.REC.input_number_of_words(self.word_count) yield from self.REC.input_number_of_words(self.word_count)
yield from self.REC.abort_recovery(False) yield from self.REC.abort_recovery(False)
else: else:
@ -1489,7 +1785,7 @@ class InputFlowSlip39BasicRecoveryAbort(InputFlowBase):
def input_flow_common(self) -> BRGeneratorType: def input_flow_common(self) -> BRGeneratorType:
yield from self.REC.confirm_recovery() yield from self.REC.confirm_recovery()
if self.debug.model == "T": if self.model() in (models.T2T1, models.T3T1):
yield from self.REC.input_number_of_words(20) yield from self.REC.input_number_of_words(20)
yield from self.REC.abort_recovery(True) yield from self.REC.abort_recovery(True)
@ -1503,7 +1799,7 @@ class InputFlowSlip39BasicRecoveryNoAbort(InputFlowBase):
def input_flow_common(self) -> BRGeneratorType: def input_flow_common(self) -> BRGeneratorType:
yield from self.REC.confirm_recovery() yield from self.REC.confirm_recovery()
if self.debug.model == "T": if self.model() in (models.T2T1, models.T3T1):
yield from self.REC.input_number_of_words(self.word_count) yield from self.REC.input_number_of_words(self.word_count)
yield from self.REC.abort_recovery(False) yield from self.REC.abort_recovery(False)
else: else:
@ -1605,11 +1901,11 @@ class InputFlowResetSkipBackup(InputFlowBase):
yield # Skip Backup yield # Skip Backup
info_path = ( info_path = (
"backup__new_wallet_created" "backup__new_wallet_created"
if self.debug.model == "Safe 3" if self.model() is models.T2B1
else "backup__new_wallet_successfully_created" else "backup__new_wallet_successfully_created"
) )
TR.assert_in(self.text_content(), info_path) TR.assert_in(self.text_content(), info_path)
if self.debug.model == "Safe 3": if self.model() is models.T2B1:
self.debug.press_right() self.debug.press_right()
self.debug.press_no() self.debug.press_no()
yield # Confirm skip backup yield # Confirm skip backup

@ -1,4 +1,4 @@
from trezorlib import messages from trezorlib import messages, models
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from . import translations as TR from . import translations as TR
@ -18,7 +18,7 @@ class PinFlow:
yield # Enter PIN yield # Enter PIN
assert "PinKeyboard" in self.debug.wait_layout().all_components() assert "PinKeyboard" in self.debug.wait_layout().all_components()
self.debug.input(pin) self.debug.input(pin)
if self.debug.model == "Safe 3": if self.client.model is models.T2B1:
yield # Reenter PIN yield # Reenter PIN
TR.assert_in( TR.assert_in(
self.debug.wait_layout().text_content(), "pin__reenter_to_confirm" self.debug.wait_layout().text_content(), "pin__reenter_to_confirm"
@ -40,7 +40,7 @@ class BackupFlow:
def confirm_new_wallet(self) -> BRGeneratorType: def confirm_new_wallet(self) -> BRGeneratorType:
yield yield
TR.assert_in(self.debug.wait_layout().text_content(), "reset__by_continuing") TR.assert_in(self.debug.wait_layout().text_content(), "reset__by_continuing")
if self.debug.model == "Safe 3": if self.client.model is models.T2B1:
self.debug.press_right() self.debug.press_right()
self.debug.press_yes() self.debug.press_yes()
@ -56,7 +56,7 @@ class RecoveryFlow:
def confirm_recovery(self) -> BRGeneratorType: def confirm_recovery(self) -> BRGeneratorType:
yield yield
TR.assert_in(self._text_content(), "reset__by_continuing") TR.assert_in(self._text_content(), "reset__by_continuing")
if self.debug.model == "Safe 3": if self.client.model is models.T2B1:
self.debug.press_right() self.debug.press_right()
self.debug.press_yes() self.debug.press_yes()
@ -66,13 +66,13 @@ class RecoveryFlow:
self.debug.press_yes() self.debug.press_yes()
def setup_slip39_recovery(self, num_words: int) -> BRGeneratorType: def setup_slip39_recovery(self, num_words: int) -> BRGeneratorType:
if self.debug.model == "Safe 3": if self.client.model is models.T2B1:
yield from self.tr_recovery_homescreen() yield from self.tr_recovery_homescreen()
yield from self.input_number_of_words(num_words) yield from self.input_number_of_words(num_words)
yield from self.enter_any_share() yield from self.enter_any_share()
def setup_bip39_recovery(self, num_words: int) -> BRGeneratorType: def setup_bip39_recovery(self, num_words: int) -> BRGeneratorType:
if self.debug.model == "Safe 3": if self.client.model is models.T2B1:
yield from self.tr_recovery_homescreen() yield from self.tr_recovery_homescreen()
yield from self.input_number_of_words(num_words) yield from self.input_number_of_words(num_words)
yield from self.enter_your_backup() yield from self.enter_your_backup()
@ -89,7 +89,7 @@ class RecoveryFlow:
title in self.debug.wait_layout().title().lower() title in self.debug.wait_layout().title().lower()
for title in TR.translate("recovery__title_dry_run", lower=True) for title in TR.translate("recovery__title_dry_run", lower=True)
) )
if self.debug.model == "Safe 3" and not is_dry_run: if self.client.model is models.T2B1 and not is_dry_run:
# Normal recovery has extra info (not dry run) # Normal recovery has extra info (not dry run)
self.debug.press_right(wait=True) self.debug.press_right(wait=True)
self.debug.press_right(wait=True) self.debug.press_right(wait=True)
@ -102,7 +102,7 @@ class RecoveryFlow:
title in self.debug.wait_layout().title().lower() title in self.debug.wait_layout().title().lower()
for title in TR.translate("recovery__title_dry_run", lower=True) for title in TR.translate("recovery__title_dry_run", lower=True)
) )
if self.debug.model == "Safe 3" and not is_dry_run: if self.client.model is models.T2B1 and not is_dry_run:
# Normal recovery has extra info (not dry run) # Normal recovery has extra info (not dry run)
self.debug.press_right(wait=True) self.debug.press_right(wait=True)
self.debug.press_right(wait=True) self.debug.press_right(wait=True)
@ -110,7 +110,7 @@ class RecoveryFlow:
def abort_recovery(self, confirm: bool) -> BRGeneratorType: def abort_recovery(self, confirm: bool) -> BRGeneratorType:
yield yield
if self.debug.model == "Safe 3": if self.client.model is models.T2B1:
TR.assert_in(self._text_content(), "recovery__num_of_words") TR.assert_in(self._text_content(), "recovery__num_of_words")
else: else:
TR.assert_in(self._text_content(), "recovery__enter_any_share") TR.assert_in(self._text_content(), "recovery__enter_any_share")
@ -118,7 +118,7 @@ class RecoveryFlow:
yield yield
TR.assert_in(self._text_content(), "recovery__wanna_cancel_recovery") TR.assert_in(self._text_content(), "recovery__wanna_cancel_recovery")
if self.debug.model == "Safe 3": if self.client.model is models.T2B1:
self.debug.press_right() self.debug.press_right()
if confirm: if confirm:
self.debug.press_yes() self.debug.press_yes()
@ -128,7 +128,7 @@ class RecoveryFlow:
def input_number_of_words(self, num_words: int) -> BRGeneratorType: def input_number_of_words(self, num_words: int) -> BRGeneratorType:
br = yield br = yield
assert br.code == B.MnemonicWordCount assert br.code == B.MnemonicWordCount
if self.debug.model == "Safe 3": if self.client.model is models.T2B1:
TR.assert_in(self.debug.wait_layout().title(), "word_count__title") TR.assert_in(self.debug.wait_layout().title(), "word_count__title")
else: else:
TR.assert_in(self._text_content(), "recovery__num_of_words") TR.assert_in(self._text_content(), "recovery__num_of_words")
@ -180,7 +180,7 @@ class RecoveryFlow:
assert br.code == B.Success assert br.code == B.Success
text = get_text_possible_pagination(self.debug, br) text = get_text_possible_pagination(self.debug, br)
# TODO: make sure the translations fit on one page # TODO: make sure the translations fit on one page
if self.client.debug.model != "T": if self.client.model not in (models.T2T1, models.T3T1):
TR.assert_in(text, "recovery__dry_run_bip39_valid_match") TR.assert_in(text, "recovery__dry_run_bip39_valid_match")
self.debug.press_yes() self.debug.press_yes()
@ -189,7 +189,7 @@ class RecoveryFlow:
assert br.code == B.Success assert br.code == B.Success
text = get_text_possible_pagination(self.debug, br) text = get_text_possible_pagination(self.debug, br)
# TODO: make sure the translations fit on one page # TODO: make sure the translations fit on one page
if self.client.debug.model != "T": if self.client.model not in (models.T2T1, models.T3T1):
TR.assert_in(text, "recovery__dry_run_slip39_valid_match") TR.assert_in(text, "recovery__dry_run_slip39_valid_match")
self.debug.press_yes() self.debug.press_yes()
@ -198,7 +198,7 @@ class RecoveryFlow:
assert br.code == B.Warning assert br.code == B.Warning
text = get_text_possible_pagination(self.debug, br) text = get_text_possible_pagination(self.debug, br)
# TODO: make sure the translations fit on one page on TT # TODO: make sure the translations fit on one page on TT
if self.client.debug.model != "T": if self.client.model not in (models.T2T1, models.T3T1):
TR.assert_in(text, "recovery__dry_run_slip39_valid_mismatch") TR.assert_in(text, "recovery__dry_run_slip39_valid_mismatch")
self.debug.press_yes() self.debug.press_yes()
@ -207,7 +207,7 @@ class RecoveryFlow:
assert br.code == B.Warning assert br.code == B.Warning
text = get_text_possible_pagination(self.debug, br) text = get_text_possible_pagination(self.debug, br)
# TODO: make sure the translations fit on one page # TODO: make sure the translations fit on one page
if self.client.debug.model != "T": if self.client.model not in (models.T2T1, models.T3T1):
TR.assert_in(text, "recovery__dry_run_bip39_valid_mismatch") TR.assert_in(text, "recovery__dry_run_bip39_valid_mismatch")
self.debug.press_yes() self.debug.press_yes()
@ -240,7 +240,7 @@ class RecoveryFlow:
if index < len(shares) - 1: if index < len(shares) - 1:
if has_groups: if has_groups:
yield from self.success_share_group_entered() yield from self.success_share_group_entered()
if self.debug.model == "T" and click_info: if self.client.model in (models.T2T1, models.T3T1) and click_info:
yield from self.tt_click_info() yield from self.tt_click_info()
yield from self.success_more_shares_needed() yield from self.success_more_shares_needed()
@ -292,7 +292,7 @@ class EthereumFlow:
) )
assert br.pages is not None assert br.pages is not None
assert br.pages > 2 assert br.pages > 2
if self.debug.model == "T": if self.client.model in (models.T2T1, models.T3T1):
self.debug.swipe_up(wait=True) self.debug.swipe_up(wait=True)
self.debug.swipe_up(wait=True) self.debug.swipe_up(wait=True)
self.debug.click(self.GO_BACK) self.debug.click(self.GO_BACK)
@ -312,7 +312,7 @@ class EthereumFlow:
yield yield
TR.assert_equals(self.debug.wait_layout().title(), "words__recipient") TR.assert_equals(self.debug.wait_layout().title(), "words__recipient")
if self.debug.model == "T": if self.client.model in (models.T2T1, models.T3T1):
if cancel: if cancel:
self.debug.press_no() self.debug.press_no()
else: else:
@ -387,7 +387,7 @@ class EthereumFlow:
"ethereum__staking_claim_intro", "ethereum__staking_claim_intro",
], ],
) )
if self.debug.model == "T": if self.client.model in (models.T2T1, models.T3T1):
# confirm intro # confirm intro
if info: if info:
self.debug.press_info(wait=True) self.debug.press_info(wait=True)

@ -113,6 +113,18 @@ def assert_in(text: str, path: str, template: t.Iterable[t.Any] = ()) -> None:
assert False, f"{text} not found in {texts}" assert False, f"{text} not found in {texts}"
def assert_in_multiple(
text: str, paths: list[str], template: t.Iterable[t.Any] = ()
) -> None:
texts: list[str] = []
for path in paths:
texts += _resolve_path_to_texts(path, template)
for tt in texts:
if tt in text.lower():
return
assert False, f"{text} not found in {texts}"
def assert_startswith(text: str, path: str, template: t.Iterable[t.Any] = ()) -> None: def assert_startswith(text: str, path: str, template: t.Iterable[t.Any] = ()) -> None:
texts = _resolve_path_to_texts(path, template) texts = _resolve_path_to_texts(path, template)
for tt in texts: for tt in texts:

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save