1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-04-19 08:39:03 +00:00

feat(eckhart): implement missing eckhart tests and flows

This commit is contained in:
Lukas Bielesch 2025-04-11 12:45:15 +02:00
parent 55935186d7
commit d744e4f091
57 changed files with 296 additions and 203 deletions

View File

@ -319,7 +319,18 @@ class LayoutContent(UnstructuredJSONReader):
def button_contents(self) -> list[str]:
"""Getting list of button contents."""
buttons = self.find_unique_value_by_key("buttons", default={}, only_type=dict)
if self.action_bar() != "":
# ActionBar is used in Eckhart layout
buttons = self.find_unique_value_by_key(
"ActionBar", default={}, only_type=dict
)
button_keys = ("left_button", "", "right_button")
else:
buttons = self.find_unique_value_by_key(
"buttons", default={}, only_type=dict
)
button_keys = ("left_btn", "middle_btn", "right_btn")
def get_button_content(btn_key: str) -> str:
button_obj = buttons.get(btn_key, {})
@ -336,7 +347,6 @@ class LayoutContent(UnstructuredJSONReader):
# default value
return "-"
button_keys = ("left_btn", "middle_btn", "right_btn")
return [get_button_content(btn_key) for btn_key in button_keys]
def seed_words(self) -> list[str]:

View File

@ -22,7 +22,7 @@ from trezorlib import device, exceptions, messages
from ..common import MOCK_GET_ENTROPY
from . import recovery, reset
from .common import go_next, LayoutType
from .common import LayoutType, go_next
if TYPE_CHECKING:
from ..device_handler import BackgroundDeviceHandler

View File

@ -27,7 +27,7 @@ BINANCE_PATH = parse_path("m/44h/714h/0h/0/0")
@pytest.mark.altcoin
@pytest.mark.binance
@pytest.mark.models("core", skip=["eckhart"])
@pytest.mark.models("core")
@pytest.mark.setup_client(
mnemonic="offer caution gift cross surge pretty orange during eye soldier popular holiday mention east eight office fashion ill parrot vault rent devote earth cousin"
)

View File

@ -103,7 +103,7 @@ BINANCE_TEST_VECTORS = [
@pytest.mark.altcoin
@pytest.mark.binance
@pytest.mark.models("core", skip=["eckhart"])
@pytest.mark.models("core")
@pytest.mark.setup_client(
mnemonic="offer caution gift cross surge pretty orange during eye soldier popular holiday mention east eight office fashion ill parrot vault rent devote earth cousin"
)

View File

@ -153,9 +153,6 @@ VECTORS_DESCRIPTORS = ( # coin, account, script_type, descriptors
)
pytestmark = pytest.mark.models(skip=["eckhart"])
def _address_n(purpose, coin, account, script_type):
res = [H_(purpose), H_(0) if coin == "Bitcoin" else H_(1), H_(account)]
if purpose == 10025 and script_type == messages.InputScriptType.SPENDTAPROOT:

View File

@ -244,7 +244,7 @@ VECTORS_MULTISIG = ( # script_type, bip48_type, address, xpubs, ignore_xpub_mag
)
@pytest.mark.models("core", skip=["eckhart"])
@pytest.mark.models("core")
@pytest.mark.multisig
@pytest.mark.parametrize(
"script_type, bip48_type, address, xpubs, ignore_xpub_magic", VECTORS_MULTISIG

View File

@ -24,8 +24,6 @@ from ...common import is_core
from ...input_flows import InputFlowConfirmAllWarnings
from .signtx import forge_prevtx
pytestmark = pytest.mark.models(skip=["eckhart"])
VECTORS = ( # path, script_types
# GreenAddress A m/[1,4]/address_index
(

View File

@ -35,8 +35,6 @@ from ...input_flows import (
S = messages.InputScriptType
pytestmark = pytest.mark.models(skip=["eckhart"])
def case(
id: str,

View File

@ -1613,7 +1613,7 @@ def test_information_cancel(client: Client):
@pytest.mark.models(
"core",
skip=["delizia", "eckhart"],
skip=["delizia"],
reason="Cannot test layouts on T1, not implemented in Delizia UI",
)
def test_information_replacement(client: Client):

View File

@ -33,7 +33,7 @@ PREV_HASH, PREV_TX = forge_prevtx([(INPUT_ADDRESS, 12_300_000)], network="testne
PREV_TXES = {PREV_HASH: PREV_TX}
pytestmark = [pytest.mark.models("core", skip=["eckhart"]), pytest.mark.experimental]
pytestmark = [pytest.mark.models("core"), pytest.mark.experimental]
def case(id, *args, altcoin: bool = False, models: str | None = None):

View File

@ -32,8 +32,6 @@ from .signtx import (
request_output,
)
pytestmark = pytest.mark.models(skip=["eckhart"])
B = messages.ButtonRequestType
TX_CACHE_TESTNET = TxCache("Testnet")

View File

@ -23,8 +23,6 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from ...input_flows import InputFlowSignVerifyMessageLong
pytestmark = pytest.mark.models(skip=["eckhart"])
@pytest.mark.models("legacy")
def test_message_long_legacy(client: Client):

View File

@ -14,13 +14,9 @@
# You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest
from trezorlib import btc
from trezorlib.debuglink import TrezorClientDebugLink as Client
pytestmark = pytest.mark.models(skip=["eckhart"])
def test_message_long(client: Client):
ret = btc.verify_message(

View File

@ -14,13 +14,9 @@
# You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest
from trezorlib import btc
from trezorlib.debuglink import TrezorClientDebugLink as Client
pytestmark = pytest.mark.models(skip=["eckhart"])
def test_message_long(client: Client):
ret = btc.verify_message(

View File

@ -29,11 +29,7 @@ from trezorlib.tools import parse_path
from ...common import parametrize_using_common_fixtures
from ...input_flows import InputFlowShowXpubQRCode
pytestmark = [
pytest.mark.altcoin,
pytest.mark.cardano,
pytest.mark.models("core", skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.cardano, pytest.mark.models("core")]
@parametrize_using_common_fixtures(

View File

@ -24,11 +24,7 @@ from trezorlib.tools import parse_path
from ...common import MNEMONIC_SLIP39_BASIC_20_3of6
pytestmark = [
pytest.mark.altcoin,
pytest.mark.cardano,
pytest.mark.models("core", skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.cardano, pytest.mark.models("core")]
ADDRESS_N = parse_path("m/1852h/1815h/0h")

View File

@ -22,11 +22,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from ...common import parametrize_using_common_fixtures
pytestmark = [
pytest.mark.altcoin,
pytest.mark.cardano,
pytest.mark.models("core", skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.cardano, pytest.mark.models("core")]
@parametrize_using_common_fixtures(

View File

@ -24,11 +24,7 @@ from trezorlib.exceptions import TrezorFailure
from ...common import parametrize_using_common_fixtures
from ...input_flows import InputFlowConfirmAllWarnings
pytestmark = [
pytest.mark.altcoin,
pytest.mark.cardano,
pytest.mark.models("core", skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.cardano, pytest.mark.models("core")]
def show_details_input_flow(client: Client):

View File

@ -26,7 +26,7 @@ from ...input_flows import InputFlowShowXpubQRCode
@pytest.mark.altcoin
@pytest.mark.eos
@pytest.mark.models("t2t1", skip=["eckhart"])
@pytest.mark.models("t2t1")
@pytest.mark.setup_client(mnemonic=MNEMONIC12)
def test_eos_get_public_key(client: Client):
with client:

View File

@ -29,7 +29,7 @@ ADDRESS_N = parse_path("m/44h/194h/0h/0/0")
pytestmark = [
pytest.mark.altcoin,
pytest.mark.eos,
pytest.mark.models("t2t1", skip=["eckhart"]),
pytest.mark.models("t2t1"),
pytest.mark.setup_client(mnemonic=MNEMONIC12),
]

View File

@ -13,11 +13,7 @@ from ...input_flows import InputFlowConfirmAllWarnings
from . import common
from .test_sign_typed_data import DATA as TYPED_DATA
pytestmark = [
pytest.mark.altcoin,
pytest.mark.ethereum,
pytest.mark.models(skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.ethereum]
ERC20_OPERATION = "a9059cbb000000000000000000000000574bbb36871ba6b78e27f4b4dcfb76ea0091880b0000000000000000000000000000000000000000000000000000000000000123"
ERC20_BUILTIN_TOKEN = "0xdac17f958d2ee523a2206206994597c13d831ec7" # USDT

View File

@ -13,11 +13,7 @@ from trezorlib.tools import parse_path
from .common import make_defs, make_network, make_payload, make_token, sign_payload
from .test_definitions import DEFAULT_ERC20_PARAMS, ERC20_FAKE_ADDRESS
pytestmark = [
pytest.mark.altcoin,
pytest.mark.ethereum,
pytest.mark.models(skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.ethereum]
def fails(client: Client, network: bytes, match: str) -> None:

View File

@ -23,11 +23,7 @@ from trezorlib.tools import parse_path
from ...common import parametrize_using_common_fixtures
from ...input_flows import InputFlowShowAddressQRCode
pytestmark = [
pytest.mark.altcoin,
pytest.mark.ethereum,
pytest.mark.models(skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.ethereum]
@parametrize_using_common_fixtures("ethereum/getaddress.json")

View File

@ -23,11 +23,7 @@ from trezorlib.tools import parse_path
from ...common import parametrize_using_common_fixtures
pytestmark = [
pytest.mark.altcoin,
pytest.mark.ethereum,
pytest.mark.models(skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.ethereum]
@parametrize_using_common_fixtures("ethereum/getpublickey.json")

View File

@ -23,11 +23,7 @@ from trezorlib.tools import parse_path
from ...common import parametrize_using_common_fixtures
from ...input_flows import InputFlowEIP712Cancel, InputFlowEIP712ShowMore
pytestmark = [
pytest.mark.altcoin,
pytest.mark.ethereum,
pytest.mark.models(skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.ethereum]
@pytest.mark.models("core")
@ -99,7 +95,7 @@ DATA = {
}
@pytest.mark.models("core", skip="delizia", reason="Not yet implemented in new UI")
@pytest.mark.models("core")
def test_ethereum_sign_typed_data_show_more_button(client: Client):
with client:
client.watch_layout()

View File

@ -24,11 +24,7 @@ from trezorlib.tools import parse_path
from ...common import parametrize_using_common_fixtures
from ...input_flows import InputFlowSignVerifyMessageLong
pytestmark = [
pytest.mark.altcoin,
pytest.mark.ethereum,
pytest.mark.models(skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.ethereum]
@parametrize_using_common_fixtures("ethereum/signmessage.json")

View File

@ -37,11 +37,7 @@ from .common import encode_network
TO_ADDR = "0x1d1c328764a41bda0492b66baa30c4a339ff85ef"
pytestmark = [
pytest.mark.altcoin,
pytest.mark.ethereum,
pytest.mark.models(skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.ethereum]
def make_defs(parameters: dict) -> messages.EthereumDefinitions:
@ -134,11 +130,7 @@ def test_signtx_fee_info(client: Client):
)
@pytest.mark.models(
"core",
skip="delizia",
reason="T1 does not support input flows; Delizia can't send Cancel on Summary",
)
@pytest.mark.models("core")
def test_signtx_go_back_from_summary(client: Client):
input_flow = InputFlowEthereumSignTxGoBackFromSummary(client).get()
_do_test_signtx(
@ -441,7 +433,7 @@ HEXDATA = "0123456789abcd000023456789abcd010003456789abcd020000456789abcd0300000
@pytest.mark.parametrize(
"flow", (input_flow_data_skip, input_flow_data_scroll_down, input_flow_data_go_back)
)
@pytest.mark.models("core", skip="delizia", reason="Not yet implemented in new UI")
@pytest.mark.models("core")
def test_signtx_data_pagination(client: Client, flow):
def _sign_tx_call():
ethereum.sign_tx(

View File

@ -41,7 +41,7 @@ TEST_VECTORS = [
pytestmark = [
pytest.mark.altcoin,
pytest.mark.monero,
pytest.mark.models("core", skip=["eckhart"]),
pytest.mark.models("core"),
pytest.mark.setup_client(mnemonic=MNEMONIC12),
]

View File

@ -25,7 +25,7 @@ from ...common import MNEMONIC12
@pytest.mark.altcoin
@pytest.mark.monero
@pytest.mark.models("core", skip=["eckhart"])
@pytest.mark.models("core")
@pytest.mark.setup_client(mnemonic=MNEMONIC12)
def test_monero_getwatchkey(client: Client):
res = monero.get_watch_key(client, parse_path("m/44h/128h/0h"))

View File

@ -25,7 +25,7 @@ from ...common import MNEMONIC12
@pytest.mark.altcoin
@pytest.mark.nem
@pytest.mark.models("t1b1", "t2t1", skip=["eckhart"])
@pytest.mark.models("t1b1", "t2t1")
@pytest.mark.setup_client(mnemonic=MNEMONIC12)
@pytest.mark.parametrize("chunkify", (True, False))
def test_nem_getaddress(client: Client, chunkify: bool):

View File

@ -27,7 +27,7 @@ ADDRESS_N = parse_path("m/44h/1h/0h/0h/0h")
pytestmark = [
pytest.mark.altcoin,
pytest.mark.nem,
pytest.mark.models("t1b1", "t2t1", skip=["eckhart"]),
pytest.mark.models("t1b1", "t2t1"),
pytest.mark.setup_client(mnemonic=MNEMONIC12),
]

View File

@ -25,7 +25,7 @@ from ...common import MNEMONIC12
pytestmark = [
pytest.mark.altcoin,
pytest.mark.nem,
pytest.mark.models("t1b1", "t2t1", skip=["eckhart"]),
pytest.mark.models("t1b1", "t2t1"),
pytest.mark.setup_client(mnemonic=MNEMONIC12),
]

View File

@ -25,7 +25,7 @@ from ...common import MNEMONIC12
pytestmark = [
pytest.mark.altcoin,
pytest.mark.nem,
pytest.mark.models("t1b1", "t2t1", skip=["eckhart"]),
pytest.mark.models("t1b1", "t2t1"),
pytest.mark.setup_client(mnemonic=MNEMONIC12),
]

View File

@ -25,7 +25,7 @@ from ...common import MNEMONIC12, is_core
pytestmark = [
pytest.mark.altcoin,
pytest.mark.nem,
pytest.mark.models("t1b1", "t2t1", skip=["eckhart"]),
pytest.mark.models("t1b1", "t2t1"),
pytest.mark.setup_client(mnemonic=MNEMONIC12),
]

View File

@ -22,7 +22,7 @@ import pytest
from trezorlib import messages, nostr
from trezorlib.tools import parse_path
pytestmark = [pytest.mark.altcoin, pytest.mark.models("core", skip=["eckhart"])]
pytestmark = [pytest.mark.altcoin, pytest.mark.models("core")]
# test data from NIP-06: https://github.com/nostr-protocol/nips/blob/master/06.md

View File

@ -28,11 +28,7 @@ CUSTOM_MNEMONIC = (
"whip snack decide blur unfold fiction pumpkin athlete"
)
pytestmark = [
pytest.mark.altcoin,
pytest.mark.ripple,
pytest.mark.models("core", skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.ripple, pytest.mark.models("core")]
# data from https://iancoleman.io/bip39/
TEST_VECTORS = [

View File

@ -21,11 +21,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import parse_path
pytestmark = [
pytest.mark.altcoin,
pytest.mark.ripple,
pytest.mark.models("core", skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.ripple, pytest.mark.models("core")]
@pytest.mark.parametrize("chunkify", (True, False))

View File

@ -22,11 +22,7 @@ from trezorlib.tools import parse_path
from ...common import parametrize_using_common_fixtures
pytestmark = [
pytest.mark.altcoin,
pytest.mark.solana,
pytest.mark.models("core", skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.solana, pytest.mark.models("core")]
@parametrize_using_common_fixtures(

View File

@ -22,11 +22,7 @@ from trezorlib.tools import parse_path
from ...common import parametrize_using_common_fixtures
pytestmark = [
pytest.mark.altcoin,
pytest.mark.solana,
pytest.mark.models("core", skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.solana, pytest.mark.models("core")]
@parametrize_using_common_fixtures(

View File

@ -26,11 +26,7 @@ from ...input_flows import InputFlowConfirmAllWarnings
from .construct.instructions import PROGRAMS, UnknownInstruction
from .construct.transaction import Message, RawInstruction
pytestmark = [
pytest.mark.altcoin,
pytest.mark.solana,
pytest.mark.models("core", skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.solana, pytest.mark.models("core")]
@parametrize_using_common_fixtures(

View File

@ -61,11 +61,7 @@ from trezorlib.tools import parse_path
from ...common import parametrize_using_common_fixtures
from ...input_flows import InputFlowShowAddressQRCode
pytestmark = [
pytest.mark.altcoin,
pytest.mark.stellar,
pytest.mark.models(skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.stellar]
def parameters_to_proto(parameters):

View File

@ -9,7 +9,7 @@ from trezorlib.debuglink import TrezorClientDebugLink as Client
from ..common import compact_size
pytestmark = pytest.mark.models("safe", skip=["eckhart"])
pytestmark = pytest.mark.models("safe")
ROOT_PUBLIC_KEY = {
models.T2B1: bytes.fromhex(
@ -21,6 +21,9 @@ ROOT_PUBLIC_KEY = {
models.T3B1: bytes.fromhex(
"047f77368dea2d4d61e989f474a56723c3212dacf8a808d8795595ef38441427c4389bc454f02089d7f08b873005e4c28d432468997871c0bf286fd3861e21e96a"
),
models.T3W1: bytes.fromhex(
"04521192e173a9da4e3023f747d836563725372681eba3079c56ff11b2fc137ab189eb4155f371127651b5594f8c332fc1e9c0f3b80d4212822668b63189706578"
),
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -39,7 +39,9 @@ def _assert_busy(client: Client, should_be_busy: bool, screen: str = "Homescreen
@pytest.mark.setup_client(pin=PIN)
def test_busy_state(client: Client):
_assert_busy(client, False, "Lockscreen")
screen = "Homescreen" if client.layout_type is LayoutType.Eckhart else "Lockscreen"
_assert_busy(client, False, screen)
assert client.features.unlocked is False
# Show busy dialog for 1 minute.

View File

@ -70,7 +70,7 @@ def test_cancel_message_via_initialize(client: Client, message):
assert isinstance(resp, m.Features)
@pytest.mark.models("core", skip=["eckhart"])
@pytest.mark.models("core")
def test_cancel_on_paginated(client: Client):
"""Check that device is responsive on paginated screen. See #1708."""
# In #1708, the device would ignore USB (or UDP) events while waiting for the user

View File

@ -5,16 +5,14 @@ import pytest
from trezorlib import firmware, models
from trezorlib.debuglink import TrezorClientDebugLink as Client
pytestmark = pytest.mark.models(skip=["eckhart"])
# size of FIRMWARE_AREA, see core/embed/models/model_*_layout.c
# size of FIRMWARE_MAXSIZE, see core/embed/models/<model>/model_<model>.h
FIRMWARE_LENGTHS = {
models.T1B1: 7 * 128 * 1024 + 64 * 1024,
models.T2T1: 13 * 128 * 1024,
models.T2B1: 13 * 128 * 1024,
models.T3T1: 208 * 8 * 1024,
models.T3B1: 208 * 8 * 1024,
models.T3W1: 208 * 8 * 1024, # FIXME: fill in the correct value
models.T3W1: 430 * 8 * 1024,
}

View File

@ -35,7 +35,7 @@ from ..translations import (
sign_blob,
)
pytestmark = pytest.mark.models("core", skip=["eckhart"])
pytestmark = pytest.mark.models("core")
MAX_DATA_LENGTH = {

View File

@ -19,6 +19,7 @@ from pathlib import Path
import pytest
from trezorlib import btc, device, exceptions, messages, misc, models
from trezorlib.debuglink import LayoutType
from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.tools import parse_path
@ -203,9 +204,14 @@ def test_apply_homescreen_toif(client: Client):
device.apply_settings(client, homescreen=img)
@pytest.mark.models(skip=["legacy", "safe3", "eckhart"])
@pytest.mark.models(skip=["legacy", "safe3"])
def test_apply_homescreen_jpeg(client: Client):
with open(HERE / "test_bg.jpg", "rb") as f:
file_name = (
"test_bg_eckhart.jpg"
if client.debug.layout_type is LayoutType.Eckhart
else "test_bg.jpg"
)
with open(HERE / file_name, "rb") as f:
img = f.read()
with client:
_set_expected_responses(client)
@ -325,7 +331,6 @@ def test_apply_homescreen(client: Client):
@pytest.mark.setup_client(pin=None)
@pytest.mark.models(skip="eckhart")
def test_safety_checks(client: Client):
def get_bad_address():
btc.get_address(client, "Bitcoin", parse_path("m/44h"), show_display=True)

View File

@ -68,8 +68,6 @@ def test_backup_bip39(client: Client):
def test_backup_slip39_basic(client: Client, click_info: bool):
if click_info and client.layout_type is LayoutType.Caesar:
pytest.skip("click_info not implemented on T2B1")
if click_info and client.layout_type is LayoutType.Eckhart:
pytest.skip("click_info not yet implemented on T3W1")
assert client.features.backup_availability == messages.BackupAvailability.Required
@ -129,8 +127,6 @@ def test_backup_slip39_single(client: Client):
def test_backup_slip39_advanced(client: Client, click_info: bool):
if click_info and client.layout_type is LayoutType.Caesar:
pytest.skip("click_info not implemented on T2B1")
if click_info and client.layout_type is LayoutType.Eckhart:
pytest.skip("click_info not yet implemented on T3W1")
assert client.features.backup_availability == messages.BackupAvailability.Required

View File

@ -181,22 +181,25 @@ def test_change_invalid_current(client: Client):
_check_pin(client, PIN4)
@pytest.mark.models("delizia")
@pytest.mark.models("delizia", "eckhart")
@pytest.mark.setup_client(pin=None)
def test_pin_menu_cancel_setup(client: Client):
def cancel_pin_setup_input_flow():
yield
# enter context menu
client.debug.click(client.debug.screen_buttons.menu())
client.debug.synchronize_at("VerticalMenu")
# click "Cancel PIN setup"
client.debug.click(client.debug.screen_buttons.vertical_menu_items()[0])
client.debug.synchronize_at("Paragraphs")
# swipe through info screen
client.debug.swipe_up()
client.debug.synchronize_at("PromptScreen")
# tap to confirm
client.debug.click(client.debug.screen_buttons.tap_to_confirm())
if client.layout_type is LayoutType.Delizia:
# enter context menu
client.debug.click(client.debug.screen_buttons.menu())
client.debug.synchronize_at("VerticalMenu")
# click "Cancel PIN setup"
client.debug.click(client.debug.screen_buttons.vertical_menu_items()[0])
client.debug.synchronize_at("Paragraphs")
# swipe through info screen
client.debug.swipe_up()
client.debug.synchronize_at("PromptScreen")
# tap to confirm
client.debug.click(client.debug.screen_buttons.tap_to_confirm())
elif client.layout_type is LayoutType.Eckhart:
client.debug.press_no()
with client, pytest.raises(Cancelled):
client.set_input_flow(cancel_pin_setup_input_flow)

View File

@ -279,7 +279,6 @@ def test_recovery_device(client: Client):
)
@pytest.mark.models(skip=["eckhart"])
def test_sign_message(client: Client):
_assert_protection(client)
with client:
@ -321,7 +320,7 @@ def test_verify_message_t1(client: Client):
)
@pytest.mark.models("core", skip=["eckhart"])
@pytest.mark.models("core")
def test_verify_message_t2(client: Client):
_assert_protection(client)
with client:

View File

@ -22,11 +22,7 @@ from trezorlib.tools import parse_path
from ...input_flows import InputFlowShowAddressQRCode
pytestmark = [
pytest.mark.altcoin,
pytest.mark.tezos,
pytest.mark.models("core", skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.tezos, pytest.mark.models("core")]
TEST_VECTORS = [
("m/44h/1729h/0h", "tz1Kef7BSg6fo75jk37WkKRYSnJDs69KVqt9"),

View File

@ -23,7 +23,7 @@ from trezorlib.tools import parse_path
@pytest.mark.altcoin
@pytest.mark.tezos
@pytest.mark.models("core", skip=["eckhart"])
@pytest.mark.models("core")
def test_tezos_get_public_key(client: Client):
path = parse_path("m/44h/1729h/0h")
pk = get_public_key(client, path)

View File

@ -25,11 +25,7 @@ TEZOS_PATH = parse_path("m/44h/1729h/0h")
TEZOS_PATH_10 = parse_path("m/44h/1729h/10h")
TEZOS_PATH_15 = parse_path("m/44h/1729h/15h")
pytestmark = [
pytest.mark.altcoin,
pytest.mark.tezos,
pytest.mark.models("core", skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.tezos, pytest.mark.models("core")]
def test_tezos_sign_tx_proposal(client: Client):

View File

@ -50,11 +50,7 @@ TXHASH_4b6cec = bytes.fromhex(
VERSION_GROUP_ID = 0x26A7270A
BRANCH_ID = 0xC2D6D0B4
pytestmark = [
pytest.mark.altcoin,
pytest.mark.zcash,
pytest.mark.models(skip=["eckhart"]),
]
pytestmark = [pytest.mark.altcoin, pytest.mark.zcash]
def test_version_group_id_missing(client: Client):

View File

@ -257,7 +257,26 @@ class InputFlowSignMessagePagination(InputFlowBase):
self.debug.press_yes()
def input_flow_eckhart(self) -> BRGeneratorType:
assert False, "Not implemented"
# 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.read_layout()
self.debug.press_yes()
br = yield
assert br.pages is not None
for i in range(br.pages or 1):
layout = self.debug.read_layout()
layouts.append(layout)
if br.pages and i < br.pages - 1:
self.debug.click(self.debug.screen_buttons.ok())
self.message_read = multipage_content(layouts)
self.debug.press_yes()
class InputFlowSignVerifyMessageLong(InputFlowBase):
@ -352,7 +371,38 @@ class InputFlowSignVerifyMessageLong(InputFlowBase):
br = yield
def input_flow_eckhart(self) -> BRGeneratorType:
assert False, "Not implemented"
# 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.read_layout()
self.debug.press_yes()
br = yield # confirm address intro
self.debug.click(self.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0])
br = yield # confirm address long
self.debug.read_layout()
assert br.pages is not None
for i in range(br.pages):
layout = self.debug.read_layout()
layouts.append(layout)
if i < br.pages - 1:
self.debug.click(self.debug.screen_buttons.ok())
self.message_read = multipage_content(layouts)
self.debug.press_yes()
if self.verify:
# "The signature is valid!" screen
self.debug.press_yes()
br = yield
class InputFlowSignMessageInfo(InputFlowBase):
@ -384,13 +434,12 @@ class InputFlowSignMessageInfo(InputFlowBase):
def input_flow_eckhart(self) -> BRGeneratorType:
yield
# go to menu
# go to info menu
self.debug.click(self.debug.screen_buttons.menu())
# show address/message info
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0])
# close menu
self.debug.click(self.debug.screen_buttons.menu())
# cancel flow
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[1])
self.debug.click(self.debug.screen_buttons.cancel())
# confirm cancel
self.debug.click(self.debug.screen_buttons.ok())
yield
@ -733,6 +782,10 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
assert "Multisig 2 of 3" in layout.screen_content()
assert TR.address_details__derivation_path in layout.screen_content()
# three xpub pages with the same testing logic
for _xpub_num in range(3):
self.debug.click(self.client.debug.screen_buttons.ok())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
# menu
@ -868,6 +921,12 @@ class InputFlowShowXpubQRCode(InputFlowBase):
br = yield
layout = self.debug.read_layout()
# In case of page overflow, paginete to the last page
# The last page is the confirm page
if br.pages > 2:
for _ in range(br.pages - 2):
self.debug.click(self.debug.screen_buttons.ok())
assert layout.subtitle() in (TR.address__public_key, "XPUB")
self.debug.click(self.debug.screen_buttons.menu())
@ -949,7 +1008,27 @@ class InputFlowPaymentRequestDetails(InputFlowBase):
self.debug.press_yes()
def input_flow_eckhart(self) -> BRGeneratorType:
assert False, "Not implemented"
yield # request to see details
self.debug.read_layout()
self.debug.press_info()
yield # confirm first output
assert self.outputs[0].address[:16] in self.text_content() # type: ignore
self.debug.click(self.debug.screen_buttons.ok())
yield # confirm first output
self.debug.read_layout()
self.debug.click(self.debug.screen_buttons.ok())
yield # confirm second output
assert self.outputs[1].address[:16] in self.text_content() # type: ignore
self.debug.click(self.debug.screen_buttons.ok())
yield # confirm second output
self.debug.read_layout()
self.debug.click(self.debug.screen_buttons.ok())
yield # confirm transaction
self.debug.click(self.debug.screen_buttons.ok())
self.debug.press_yes()
class InputFlowSignTxHighFee(InputFlowBase):
@ -1444,14 +1523,13 @@ class InputFlowEIP712ShowMore(InputFlowBase):
def _confirm_show_more(self) -> None:
"""Model-specific, either clicks a screen or presses a button."""
if self.client.layout_type in (
LayoutType.Bolt,
LayoutType.Delizia,
LayoutType.Eckhart,
):
if self.client.layout_type is LayoutType.Bolt:
self.debug.click(self.SHOW_MORE)
elif self.client.layout_type is LayoutType.Caesar:
self.debug.press_right()
elif self.client.layout_type in (LayoutType.Delizia, LayoutType.Eckhart):
self.debug.click(self.debug.screen_buttons.menu())
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0])
else:
raise NotImplementedError

View File

@ -345,6 +345,10 @@ class RecoveryFlow:
mnemonic = share.split(" ")
yield from self.input_mnemonic(mnemonic)
# Caesar does not have the info button
if self.client.layout_type is LayoutType.Caesar:
click_info = False
if index < len(shares) - 1:
if has_groups:
yield from self.success_share_group_entered()
@ -398,7 +402,7 @@ class EthereumFlow:
def confirm_data(self, info: bool = False, cancel: bool = False) -> BRGeneratorType:
assert (yield).name == "confirm_data"
assert self.debug.read_layout().title() == TR.ethereum__title_input_data
assert TR.ethereum__title_input_data in self.debug.read_layout().title()
if info:
self.debug.press_info()
elif cancel:
@ -410,28 +414,50 @@ class EthereumFlow:
br = yield
assert br.name == "confirm_data"
assert br.pages is not None
assert self.debug.read_layout().title() == TR.ethereum__title_input_data
for _ in range(br.pages):
assert TR.ethereum__title_input_data in self.debug.read_layout().title()
for _ in range(br.pages - 1):
self.debug.read_layout()
go_next(self.debug)
self.debug.read_layout()
if self.client.layout_type in (LayoutType.Bolt, LayoutType.Caesar):
self.debug.read_layout()
go_next(self.debug)
self.debug.read_layout()
elif self.client.layout_type is LayoutType.Delizia:
self.debug.read_layout()
self.debug.click(self.debug.screen_buttons.tap_to_confirm())
elif self.client.layout_type is LayoutType.Eckhart:
self.debug.read_layout()
self.debug.click(self.debug.screen_buttons.ok())
def paginate_data_go_back(self) -> BRGeneratorType:
br = yield
assert br.name == "confirm_data"
assert br.pages is not None
assert br.pages > 2
assert self.debug.read_layout().title() == TR.ethereum__title_input_data
if self.client.layout_type is LayoutType.Caesar:
self.debug.press_right()
self.debug.press_right()
self.debug.press_left()
self.debug.press_left()
self.debug.press_left()
elif self.client.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
assert TR.ethereum__title_input_data in self.debug.read_layout().title()
if self.client.layout_type is LayoutType.Bolt:
self.debug.swipe_up()
self.debug.swipe_up()
self.debug.click(self.GO_BACK)
elif self.client.layout_type is LayoutType.Caesar:
self.debug.press_right()
self.debug.press_right()
self.debug.press_left()
self.debug.press_left()
self.debug.press_left()
elif self.client.layout_type is LayoutType.Delizia:
# Scroll to the last page data page
for _ in range(br.pages - 2):
self.debug.swipe_up()
# Close the menu wuth the cross button
self.debug.click(self.debug.screen_buttons.menu())
elif self.client.layout_type is LayoutType.Eckhart:
# Scroll to the last page
for _ in range(br.pages - 1):
self.debug.click(self.debug.screen_buttons.ok())
# Go back to the first page and then cancel
for _ in range(br.pages):
self.debug.click(self.debug.screen_buttons.cancel())
else:
raise ValueError(f"Unknown layout: {self.client.layout_type}")
@ -504,7 +530,6 @@ class EthereumFlow:
assert (yield).name == "confirm_output"
title = self.debug.read_layout().title()
assert TR.words__address in title
assert TR.words__recipient in title
if cancel:
self.debug.press_no()
@ -516,10 +541,15 @@ class EthereumFlow:
assert layout.title() == TR.words__title_summary
assert TR.send__maximum_fee in layout.text_content()
if go_back_from_summary:
self.debug.press_no()
assert (yield).name == "confirm_ethereum_tx"
self.debug.press_yes()
assert (yield).name == "confirm_ethereum_tx"
# Get back to the address screen
self.debug.swipe_down()
title = self.debug.read_layout().title()
assert TR.words__address in title
# Get back to the summary screen
self.debug.swipe_up()
layout = self.debug.read_layout()
assert layout.title() == TR.words__title_summary
assert TR.send__maximum_fee in layout.text_content()
if info:
self.debug.click(self.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
@ -534,6 +564,46 @@ class EthereumFlow:
self.debug.click(self.debug.screen_buttons.tap_to_confirm())
assert (yield).name == "confirm_ethereum_tx"
def _confirm_tx_eckhart(
self, cancel: bool, info: bool, go_back_from_summary: bool
) -> BRGeneratorType:
assert (yield).name == "confirm_output"
title = self.debug.read_layout().title()
assert TR.words__address in title
if cancel:
self.debug.press_no()
return
self.debug.click(self.debug.screen_buttons.ok())
assert (yield).name == "confirm_total"
layout = self.debug.read_layout()
assert layout.title() == TR.words__title_summary
assert TR.send__maximum_fee in layout.text_content()
if go_back_from_summary:
# Get back to the address screen
self.debug.click(self.debug.screen_buttons.cancel())
title = self.debug.read_layout().title()
assert TR.words__address in title
# Get back to the summary screen
self.debug.click(self.debug.screen_buttons.ok())
layout = self.debug.read_layout()
assert layout.title() == TR.words__title_summary
assert TR.send__maximum_fee in layout.text_content()
if info:
self.debug.click(self.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0])
text = self.debug.read_layout().text_content()
assert TR.ethereum__gas_limit in text
assert TR.ethereum__gas_price in text
self.debug.click(self.debug.screen_buttons.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.click(self.debug.screen_buttons.ok())
self.debug.read_layout()
assert (yield).name == "confirm_ethereum_tx"
def confirm_tx(
self,
cancel: bool = False,
@ -546,6 +616,8 @@ class EthereumFlow:
yield from self._confirm_tx_caesar(cancel, info, go_back_from_summary)
elif self.client.layout_type is LayoutType.Delizia:
yield from self._confirm_tx_delizia(cancel, info, go_back_from_summary)
elif self.client.layout_type is LayoutType.Eckhart:
yield from self._confirm_tx_eckhart(cancel, info, go_back_from_summary)
else:
raise ValueError("Unknown model!")
@ -648,5 +720,35 @@ class EthereumFlow:
self.debug.press_yes()
elif self.client.layout_type is LayoutType.Eckhart:
# confirm intro
if info:
self.debug.click(self.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0])
assert self.debug.read_layout().title() in (
TR.ethereum__staking_stake_address,
TR.ethereum__staking_claim_address,
)
self.debug.click(self.debug.screen_buttons.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.click(self.debug.screen_buttons.ok())
br = yield
assert br.code == B.SignTx
assert br.name == "confirm_total"
# confirm summary
if info:
self.debug.click(self.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0])
assert TR.ethereum__gas_limit in self.debug.read_layout().text_content()
assert TR.ethereum__gas_price in self.debug.read_layout().text_content()
self.debug.click(self.debug.screen_buttons.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.press_yes()
else:
raise ValueError("Unknown model!")