2023-08-11 15:57:32 +00:00
|
|
|
import re
|
2022-10-25 10:46:37 +00:00
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
|
2023-05-04 12:16:40 +00:00
|
|
|
from shamir_mnemonic import shamir # type: ignore
|
2019-11-04 14:45:54 +00:00
|
|
|
|
2024-03-09 21:05:05 +00:00
|
|
|
from trezorlib import messages, models
|
2019-11-04 14:45:54 +00:00
|
|
|
|
|
|
|
from .. import buttons
|
2023-08-11 15:57:32 +00:00
|
|
|
from .. import translations as TR
|
2019-11-04 14:45:54 +00:00
|
|
|
|
2022-10-25 10:46:37 +00:00
|
|
|
if TYPE_CHECKING:
|
|
|
|
from trezorlib.debuglink import DebugLink
|
|
|
|
|
2019-11-04 14:45:54 +00:00
|
|
|
|
2023-05-04 12:16:40 +00:00
|
|
|
def confirm_new_wallet(debug: "DebugLink") -> None:
|
2023-08-11 15:57:32 +00:00
|
|
|
TR.assert_equals_multiple(
|
|
|
|
debug.read_layout().title(),
|
|
|
|
["reset__title_create_wallet", "reset__title_create_wallet_shamir"],
|
|
|
|
)
|
2024-03-09 21:05:05 +00:00
|
|
|
if debug.model in (models.T2T1, models.T3T1):
|
2023-05-12 09:19:35 +00:00
|
|
|
debug.click(buttons.OK, wait=True)
|
2024-03-09 21:05:05 +00:00
|
|
|
elif debug.model in (models.T2B1,):
|
2023-05-12 09:19:35 +00:00
|
|
|
debug.press_right(wait=True)
|
|
|
|
debug.press_right(wait=True)
|
2019-11-04 14:45:54 +00:00
|
|
|
|
|
|
|
|
2023-08-11 15:57:32 +00:00
|
|
|
def confirm_read(debug: "DebugLink", middle_r: bool = False) -> None:
|
2024-03-09 21:05:05 +00:00
|
|
|
if debug.model in (models.T2T1, models.T3T1):
|
2023-05-12 09:19:35 +00:00
|
|
|
debug.click(buttons.OK, wait=True)
|
2024-03-09 21:05:05 +00:00
|
|
|
elif debug.model in (models.T2B1,):
|
2023-08-11 15:57:32 +00:00
|
|
|
page_count = debug.read_layout().page_count()
|
|
|
|
if page_count > 1:
|
|
|
|
for _ in range(page_count - 1):
|
|
|
|
debug.press_right(wait=True)
|
2023-06-26 08:50:28 +00:00
|
|
|
if middle_r:
|
|
|
|
debug.press_middle(wait=True)
|
2023-05-12 09:19:35 +00:00
|
|
|
else:
|
2023-06-26 08:50:28 +00:00
|
|
|
debug.press_right(wait=True)
|
2019-11-04 14:45:54 +00:00
|
|
|
|
|
|
|
|
2022-10-25 10:46:37 +00:00
|
|
|
def set_selection(debug: "DebugLink", button: tuple[int, int], diff: int) -> None:
|
2024-03-09 21:05:05 +00:00
|
|
|
if debug.model in (models.T2T1, models.T3T1):
|
2023-05-12 09:19:35 +00:00
|
|
|
assert "NumberInputDialog" in debug.read_layout().all_components()
|
|
|
|
for _ in range(diff):
|
|
|
|
debug.click(button)
|
|
|
|
debug.click(buttons.OK, wait=True)
|
2024-03-09 21:05:05 +00:00
|
|
|
elif debug.model in (models.T2B1,):
|
2023-05-12 09:19:35 +00:00
|
|
|
layout = debug.read_layout()
|
2023-08-11 15:57:32 +00:00
|
|
|
if layout.title() in TR.translate(
|
|
|
|
"reset__title_number_of_shares"
|
|
|
|
) + TR.translate("words__title_threshold"):
|
2023-05-12 09:19:35 +00:00
|
|
|
# Special info screens
|
|
|
|
layout = debug.press_right(wait=True)
|
|
|
|
assert "NumberInput" in layout.all_components()
|
|
|
|
if button == buttons.RESET_MINUS:
|
|
|
|
for _ in range(diff):
|
|
|
|
debug.press_left(wait=True)
|
|
|
|
else:
|
|
|
|
for _ in range(diff):
|
|
|
|
debug.press_right(wait=True)
|
|
|
|
debug.press_middle(wait=True)
|
2019-11-04 14:45:54 +00:00
|
|
|
|
|
|
|
|
2023-05-04 12:16:40 +00:00
|
|
|
def read_words(
|
|
|
|
debug: "DebugLink", backup_type: messages.BackupType, do_htc: bool = True
|
|
|
|
) -> list[str]:
|
2022-10-25 10:46:37 +00:00
|
|
|
words: list[str] = []
|
2023-06-26 08:50:28 +00:00
|
|
|
|
2024-03-09 21:05:05 +00:00
|
|
|
if debug.model in (models.T2B1,):
|
2023-08-11 15:57:32 +00:00
|
|
|
debug.press_right(wait=True)
|
2023-05-12 09:19:35 +00:00
|
|
|
|
|
|
|
# Swiping through all the pages and loading the words
|
2023-08-11 15:57:32 +00:00
|
|
|
layout = debug.read_layout()
|
2023-06-26 08:50:28 +00:00
|
|
|
for _ in range(layout.page_count() - 1):
|
|
|
|
words.extend(layout.seed_words())
|
|
|
|
layout = debug.swipe_up(wait=True)
|
2023-05-04 12:16:40 +00:00
|
|
|
assert layout is not None
|
2024-03-09 21:05:05 +00:00
|
|
|
if debug.model in (models.T2T1, models.T3T1):
|
2023-05-12 09:19:35 +00:00
|
|
|
words.extend(layout.seed_words())
|
2022-10-25 10:46:37 +00:00
|
|
|
|
2023-05-04 12:16:40 +00:00
|
|
|
# There is hold-to-confirm button
|
|
|
|
if do_htc:
|
2024-03-09 21:05:05 +00:00
|
|
|
if debug.model in (models.T2T1, models.T3T1):
|
2023-05-12 09:19:35 +00:00
|
|
|
debug.click_hold(buttons.OK, hold_ms=1500)
|
2024-03-09 21:05:05 +00:00
|
|
|
elif debug.model in (models.T2B1,):
|
2023-05-12 09:19:35 +00:00
|
|
|
debug.press_right_htc(1200)
|
2023-05-04 12:16:40 +00:00
|
|
|
else:
|
|
|
|
# It would take a very long time to test 16-of-16 with doing 1500 ms HTC after
|
|
|
|
# each word set
|
|
|
|
debug.press_yes()
|
2019-11-04 14:45:54 +00:00
|
|
|
|
|
|
|
return words
|
|
|
|
|
|
|
|
|
2022-10-25 10:46:37 +00:00
|
|
|
def confirm_words(debug: "DebugLink", words: list[str]) -> None:
|
2019-11-04 14:45:54 +00:00
|
|
|
layout = debug.wait_layout()
|
2024-03-09 21:05:05 +00:00
|
|
|
if debug.model in (models.T2T1, models.T3T1):
|
2023-08-11 15:57:32 +00:00
|
|
|
TR.assert_template(layout.text_content(), "reset__select_word_x_of_y_template")
|
2023-05-12 09:19:35 +00:00
|
|
|
for _ in range(3):
|
|
|
|
# "Select word 3 of 20"
|
|
|
|
# ^
|
2023-08-11 15:57:32 +00:00
|
|
|
word_pos_match = re.search(r"\d+", debug.wait_layout().text_content())
|
|
|
|
assert word_pos_match is not None
|
|
|
|
word_pos = int(word_pos_match.group(0))
|
2023-05-12 09:19:35 +00:00
|
|
|
# Unifying both the buttons and words to lowercase
|
|
|
|
btn_texts = [
|
|
|
|
text.lower() for text in layout.tt_check_seed_button_contents()
|
|
|
|
]
|
|
|
|
wanted_word = words[word_pos - 1].lower()
|
|
|
|
button_pos = btn_texts.index(wanted_word)
|
|
|
|
layout = debug.click(buttons.RESET_WORD_CHECK[button_pos], wait=True)
|
2024-03-09 21:05:05 +00:00
|
|
|
elif debug.model in (models.T2B1,):
|
2023-08-11 15:57:32 +00:00
|
|
|
TR.assert_in(layout.text_content(), "reset__select_correct_word")
|
2023-05-12 09:19:35 +00:00
|
|
|
layout = debug.press_right(wait=True)
|
|
|
|
for _ in range(3):
|
|
|
|
# "SELECT 2ND WORD"
|
|
|
|
# ^
|
2023-08-11 15:57:32 +00:00
|
|
|
word_pos_match = re.search(r"\d+", layout.title())
|
|
|
|
assert word_pos_match is not None
|
|
|
|
word_pos = int(word_pos_match.group(0))
|
|
|
|
|
2023-05-12 09:19:35 +00:00
|
|
|
wanted_word = words[word_pos - 1].lower()
|
|
|
|
|
|
|
|
while not layout.get_middle_choice() == wanted_word:
|
|
|
|
layout = debug.press_right(wait=True)
|
|
|
|
|
|
|
|
layout = debug.press_middle(wait=True)
|
2019-11-04 14:45:54 +00:00
|
|
|
|
|
|
|
|
2022-10-25 10:46:37 +00:00
|
|
|
def validate_mnemonics(mnemonics: list[str], expected_ems: bytes) -> None:
|
2019-11-04 14:45:54 +00:00
|
|
|
# We expect these combinations to recreate the secret properly
|
|
|
|
# In case of click tests the mnemonics are always XofX so no need for combinations
|
2021-02-03 12:39:26 +00:00
|
|
|
groups = shamir.decode_mnemonics(mnemonics)
|
|
|
|
ems = shamir.recover_ems(groups)
|
|
|
|
assert expected_ems == ems.ciphertext
|