diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2f2c5762d..e35bad9db 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -89,6 +89,7 @@ jobs: apk add gmp-dev curl jq libsodium-dev git xxd procps python3 -m venv tezos_test_env --system-site-package source ./tezos_test_env/bin/activate + python3 -m pip install --upgrade pip -q python3 -m pip install -r ./tests/requirements.txt -q TMP_DIR=$(mktemp -d /tmp/foo-XXXXXX) tar xfz app_${{ matrix.device }}_dbg.tgz -C $TMP_DIR @@ -192,6 +193,7 @@ jobs: apk add gmp-dev curl jq libsodium-dev git xxd procps python3 -m venv tezos_test_env --system-site-package source ./tezos_test_env/bin/activate + python3 -m pip install --upgrade pip -q python3 -m pip install -r ./tests/requirements.txt -q ./tests/integration/run_test_local.sh -T100 -F -m ${{ matrix.device }} tests diff --git a/.github/workflows/coding_style_checks.yml b/.github/workflows/coding_style_checks.yml index ac30e70cf..a8ec73f95 100644 --- a/.github/workflows/coding_style_checks.yml +++ b/.github/workflows/coding_style_checks.yml @@ -23,3 +23,20 @@ jobs: source: './app/src' extensions: 'h,c' version: 15 + + pylint_check: + name: Python Lint Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.9' + + - name: Install pylint + run: pip install pylint -r tests/requirements.txt + + - name: Run pylint with .pylintrc + run: pylint --errors-only --rcfile=tests/integration/.pylintrc tests/integration/nano/ diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 4c051d2fe..863ce0419 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -12,4 +12,4 @@ jobs: python-version: '3.10' - run: python -m pip install pre-commit - run: python -m pip freeze --local - - run: SKIP=clang-format pre-commit run --all-files + - run: SKIP=clang-format,pylint pre-commit run --all-files diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8675de0c6..3d97c6391 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,3 +19,12 @@ repos: language: system files: ^ types: [file, c] + + - id: pylint + name: pylint + description: Run pylint with custom .pylintrc configuration + entry: pylint + language: system + pass_filenames: false + args: ["--errors-only", "--rcfile=tests/integration/.pylintrc", "tests/integration/nano/"] + types: [python] diff --git a/Makefile b/Makefile index 695ccfd00..1e776f0b1 100644 --- a/Makefile +++ b/Makefile @@ -122,6 +122,7 @@ integration_tests_basic_%: app_%.tgz \ apk add gmp-dev curl jq libsodium-dev git xxd procps; \ python3 -m venv tezos_test_env --system-site-package; \ source ./tezos_test_env/bin/activate; \ + python3 -m pip install --upgrade pip -q; \ python3 -m pip install -r tests/requirements.txt -q ; \ python3 -m pytest -n 32 tests/integration/nano/ --tb=no \ --device $* --app \$$TMP_DIR/app.elf \ diff --git a/scripts/test_swap.sh b/scripts/test_swap.sh index c649edc81..cabcfb261 100755 --- a/scripts/test_swap.sh +++ b/scripts/test_swap.sh @@ -151,7 +151,8 @@ run_tests() { --rm -v "$(realpath .):/app" \ ledger-app-tezos-integration-tests -c \ "cd /app && \ - pip install -r test/python/requirements.txt -q && \ + pip install --upgrade pip -q && \ + pip install -r test/python/requirements.txt -q && \ pip install protobuf==3.20.3 && pytest test/python $*" ) } diff --git a/tests/integration/.pylintrc b/tests/integration/.pylintrc new file mode 100644 index 000000000..0c5eedc64 --- /dev/null +++ b/tests/integration/.pylintrc @@ -0,0 +1,12 @@ +[MESSAGES CONTROL] +disable= + broad-exception-caught, + global-statement, + line-too-long, + protected-access, + redefined-outer-name, + too-few-public-methods, + too-many-arguments, + too-many-instance-attributes, + too-many-positional-arguments, + too-many-statements, diff --git a/tests/integration/nano/conftest.py b/tests/integration/nano/conftest.py index 7f35558a1..52ba34bc4 100644 --- a/tests/integration/nano/conftest.py +++ b/tests/integration/nano/conftest.py @@ -1,11 +1,29 @@ -import pytest +# Copyright 2024 Trilitech +# Copyright 2024 Functori + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Conftest base on `ragger` conftest.""" + from pathlib import Path +from typing import Dict, Generator, List, Union + +import pytest from ragger.firmware import Firmware -from typing import Dict, Callable, Generator, List, Optional, Tuple, Union from utils.app import TezosAppScreen, SpeculosTezosBackend, DEFAULT_SEED -from utils.backend import TezosBackend, APP_KIND +from utils.backend import AppKind FIRMWARES: List[Firmware] = [ Firmware.NANOS, @@ -16,6 +34,7 @@ DEVICES: List[str] = list(map(lambda fw: fw.device, FIRMWARES)) def pytest_addoption(parser): + """Register argparse-style options for pytest.""" parser.addoption("-D", "--device", type=str, choices=DEVICES, @@ -49,6 +68,7 @@ def pytest_addoption(parser): global_log_dir: Union[Path, None] = None def pytest_configure(config): + """Configure pytest.""" global global_log_dir log_dir = config.getoption("log_dir") if log_dir is not None: @@ -57,21 +77,24 @@ def pytest_configure(config): logs : Dict[str, List[pytest.TestReport]] = {} @pytest.hookimpl(tryfirst=True) -def pytest_runtest_logstart(nodeid, location): +def pytest_runtest_logstart(location): + """Called at the start of running the runtest protocol for a single item.""" logs[location[2]] = [] @pytest.hookimpl(tryfirst=True) def pytest_runtest_logreport(report): + """Called at the end of running the runtest protocol for a single test.""" logs[report.head_line].append(report) @pytest.hookimpl(tryfirst=True) -def pytest_runtest_logfinish(nodeid, location): +def pytest_runtest_logfinish(location): + """Called at the end of running the runtest protocol for a single item.""" if global_log_dir is not None: log_dir = global_log_dir / Path(location[0]).stem log_dir.mkdir(parents=True, exist_ok=True) head_line = location[2] log_file = log_dir / f"{head_line.replace(' ', '_')}.log" - with open(log_file, 'w') as writer: + with open(log_file, 'w', encoding="utf-8") as writer: for report in logs[head_line]: writer.write(f"============================== {report.when.capitalize()} {report.outcome} ==============================\n") writer.write(f"{report.longreprtext}\n") @@ -84,11 +107,13 @@ def pytest_runtest_logfinish(nodeid, location): @pytest.fixture(scope="session") def firmware(pytestconfig) -> Firmware : + """Get `firware` for pytest.""" device = pytestconfig.getoption("device") return next(fw for fw in FIRMWARES if fw.device == device) @pytest.fixture(scope="session") -def port(pytestconfig, request, worker_id) -> int : +def port(pytestconfig, worker_id) -> int : + """Get `port` for pytest.""" if worker_id == "master": return pytestconfig.getoption("port") # worker_id = gw0, gw1, ... @@ -96,18 +121,22 @@ def port(pytestconfig, request, worker_id) -> int : @pytest.fixture(scope="session") def display(pytestconfig) -> bool : + """Get `display` for pytest.""" return pytestconfig.getoption("display") @pytest.fixture(scope="session") def golden_run(pytestconfig) -> bool: + """Get `golden_run` for pytest.""" return pytestconfig.getoption("golden_run") @pytest.fixture(scope="session") def app_path(pytestconfig) -> Path: + """Get `app_path` for pytest.""" return Path(pytestconfig.getoption("app")) @pytest.fixture(scope="session") def speculos_args(pytestconfig) -> List[str]: + """Get `app_path` for pytest.""" speculos_args = pytestconfig.getoption("speculos_args") if speculos_args is None: return [] @@ -115,6 +144,7 @@ def speculos_args(pytestconfig) -> List[str]: @pytest.fixture(scope="function") def seed(request) -> str: + """Get `seed` for pytest.""" param = getattr(request, "param", None) return param.get("seed", DEFAULT_SEED) if param else DEFAULT_SEED @@ -125,6 +155,7 @@ def backend(app_path: Path, display: bool, seed: str, speculos_args: List[str]) -> Generator[SpeculosTezosBackend, None, None]: + """Get `backend` for pytest.""" if display: speculos_args += ["--display", "qt"] @@ -143,10 +174,12 @@ def backend(app_path: Path, yield b @pytest.fixture(scope="function") -def app(backend: SpeculosTezosBackend, golden_run: bool): - return TezosAppScreen(backend, APP_KIND.WALLET, golden_run) +def app(backend: SpeculosTezosBackend, golden_run: bool) -> TezosAppScreen: + """Get `app` for pytest.""" + return TezosAppScreen(backend, AppKind.WALLET, golden_run) def requires_device(device): + """Wrapper to run the pytest test only with the provided device.""" return pytest.mark.skipif( f"config.getvalue('device') != '{ device }'", reason=f"Test requires device to be { device }." diff --git a/tests/integration/nano/nanos/__init__.py b/tests/integration/nano/nanos/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/integration/nano/nanos/test_nanos_regression_batched_ops.py b/tests/integration/nano/nanos/test_nanos_regression_batched_ops.py index 1fe7796c4..08d460704 100755 --- a/tests/integration/nano/nanos/test_nanos_regression_batched_ops.py +++ b/tests/integration/nano/nanos/test_nanos_regression_batched_ops.py @@ -13,19 +13,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import sys +"""Check signing batch operation""" -file_path=os.path.abspath(__file__) -dir_path=os.path.dirname(file_path) -root_path=os.path.dirname(dir_path) -sys.path.append(root_path) +from pathlib import Path from conftest import requires_device -from pathlib import Path - -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Transaction @@ -42,7 +36,8 @@ # Destination: KT1CYT8oACUcCSNTu2qfgB4fj5bD7szYrpti @requires_device("nanos") -def test_nanos_regression_batched_ops(app): +def test_nanos_regression_batched_ops(app: TezosAppScreen): + """Check signing batch operation""" test_name = Path(__file__).stem app.setup_expert_mode() diff --git a/tests/integration/nano/nanosp/__init__.py b/tests/integration/nano/nanosp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/integration/nano/nanosp/test_nanosp_regression_potential_empty_screen.py b/tests/integration/nano/nanosp/test_nanosp_regression_potential_empty_screen.py index 1e0c7e8cf..d5c61eb9f 100755 --- a/tests/integration/nano/nanosp/test_nanosp_regression_potential_empty_screen.py +++ b/tests/integration/nano/nanosp/test_nanosp_regression_potential_empty_screen.py @@ -13,19 +13,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import sys +"""Check signing operation that display potentially empty screens""" -file_path=os.path.abspath(__file__) -dir_path=os.path.dirname(file_path) -root_path=os.path.dirname(dir_path) -sys.path.append(root_path) +from pathlib import Path from conftest import requires_device -from pathlib import Path - -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Transfer ticket @@ -43,7 +37,8 @@ # S @requires_device("nanosp") -def test_nanosp_regression_potential_empty_screen(app): +def test_nanosp_regression_potential_empty_screen(app: TezosAppScreen): + """Check signing operation that display potentially empty screens""" test_name = Path(__file__).stem app.setup_expert_mode() diff --git a/tests/integration/nano/nanosp/test_nanosp_regression_press_right_works_across_apdu_recieves.py b/tests/integration/nano/nanosp/test_nanosp_regression_press_right_works_across_apdu_recieves.py index 0d2a1918a..d1ab32855 100755 --- a/tests/integration/nano/nanosp/test_nanosp_regression_press_right_works_across_apdu_recieves.py +++ b/tests/integration/nano/nanosp/test_nanosp_regression_press_right_works_across_apdu_recieves.py @@ -13,28 +13,23 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import sys +"""Check no need to click right two times between APDUs during signing flow""" -file_path=os.path.abspath(__file__) -dir_path=os.path.dirname(file_path) -root_path=os.path.dirname(dir_path) -sys.path.append(root_path) +from pathlib import Path from conftest import requires_device -from pathlib import Path - -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Expression: {IF_NONE {{SWAP;IF {DIP {{DROP 1;PUSH unit Unit;PUSH bool True;PUSH string ";L\\S?p$-Fq)VDg\n]te\no4v0_8)\""}}} {{DROP 2;PUSH unit Unit;PUSH bool False;PUSH string "Li-%*edF6~?E[5Kmu?dyviwJ^2\"\\d$FyQ>>!>D$g(Qg";PUSH string "*Tx bytes: path = Path(test_name) / "reject_from_blind" def navigate() -> None: - app.navigate_until_text(Screen_text.Accept_risk, path / "clear") - app.navigate_until_text(Screen_text.Sign_reject, path / "blind") + app.navigate_until_text(ScreenText.ACCEPT_RISK, path / "clear") + app.navigate_until_text(ScreenText.SIGN_REJECT, path / "blind") send_and_navigate( send=expected_failure_send, diff --git a/tests/integration/nano/test_blindsign_too_deep.py b/tests/integration/nano/test_blindsign_too_deep.py index 4af12e15e..78a86397a 100755 --- a/tests/integration/nano/test_blindsign_too_deep.py +++ b/tests/integration/nano/test_blindsign_too_deep.py @@ -13,18 +13,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check blindsigning on too deep expression""" + from multiprocessing import Process, Queue from pathlib import Path -from utils.app import Screen, Screen_text, DEFAULT_ACCOUNT +from utils.app import Screen, ScreenText, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Expression: {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{42}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} -def test_blindsign_too_deep(app): +def test_blindsign_too_deep(app: TezosAppScreen): + """Check blindsigning on too deep expression""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) expression = Message.from_bytes("0502000000f702000000f202000000ed02000000e802000000e302000000de02000000d902000000d402000000cf02000000ca02000000c502000000c002000000bb02000000b602000000b102000000ac02000000a702000000a2020000009d02000000980200000093020000008e02000000890200000084020000007f020000007a02000000750200000070020000006b02000000660200000061020000005c02000000570200000052020000004d02000000480200000043020000003e02000000390200000034020000002f020000002a02000000250200000020020000001b02000000160200000011020000000c02000000070200000002002a") @@ -33,13 +36,13 @@ def send(result_queue: Queue) -> None: res = app.backend.sign(DEFAULT_ACCOUNT, expression, with_hash=True) result_queue.put(res) def assert_screen_i(i): - app.assert_screen(f"{str(i).zfill(5)}", path=(Path(test_name) / "clear")) + app.assert_screen(f"{str(i).zfill(5)}", path=Path(test_name) / "clear") result_queue: Queue = Queue() send_process = Process(target=send, args=(result_queue,)) send_process.start() - app.backend.wait_for_text_not_on_screen(Screen_text.Home) + app.backend.wait_for_text_not_on_screen(ScreenText.HOME) for i in range(6): # 'Review operation' @@ -55,7 +58,7 @@ def assert_screen_i(i): assert_screen_i(i+1) def blind_navigate() -> None: - app.navigate_until_text(Screen_text.Sign_accept, Path(test_name) / "blind") + app.navigate_until_text(ScreenText.SIGN_ACCEPT, Path(test_name) / "blind") navigate_process = Process(target=blind_navigate) navigate_process.start() diff --git a/tests/integration/nano/test_blindsign_too_large.py b/tests/integration/nano/test_blindsign_too_large.py index 97c59565a..fc62d9b41 100755 --- a/tests/integration/nano/test_blindsign_too_large.py +++ b/tests/integration/nano/test_blindsign_too_large.py @@ -13,17 +13,20 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check blindsigning on too large expression""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Expression: 12345678901234567890123456789012345678901234567890123456789012345678901234567890 -def test_blindsign_too_large(app): +def test_blindsign_too_large(app: TezosAppScreen): + """Check blindsigning on too large expression""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("050092abf8e3d9e5f8cfd9ae8a9fe5f28ea1d5b5abf1af82dae8a4b68df3d1889eb6f988f5e8d31a") diff --git a/tests/integration/nano/test_change_sign_instruction.py b/tests/integration/nano/test_change_sign_instruction.py index ffd2102e7..1a12c1d38 100755 --- a/tests/integration/nano/test_change_sign_instruction.py +++ b/tests/integration/nano/test_change_sign_instruction.py @@ -13,30 +13,33 @@ # See the License for the specific language governing permissions and # limitations under the License. -from utils.app import Screen, DEFAULT_ACCOUNT -from utils.backend import INS, StatusCode +"""Check signing instruction changes behaviour""" + +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT +from utils.backend import Ins, StatusCode from utils.message import Message -def test_change_sign_instruction(app): +def test_change_sign_instruction(app: TezosAppScreen): + """Check signing instruction changes behaviour""" - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000006c016e8874874d31c3fbd636e924d5a036a43ec8faa7d0860308362d80d30e01000000000000000000000000000000000000000000ff02000000020316") - payload=message.bytes + payload=bytes(message) - app.backend._ask_sign(INS.SIGN_WITH_HASH, DEFAULT_ACCOUNT) + app.backend._ask_sign(Ins.SIGN_WITH_HASH, DEFAULT_ACCOUNT) with app.expect_apdu_failure(StatusCode.INVALID_INS): - app.backend._continue_sign(INS.SIGN, + app.backend._continue_sign(Ins.SIGN, payload, last=True) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) - app.backend._ask_sign(INS.SIGN, DEFAULT_ACCOUNT) + app.backend._ask_sign(Ins.SIGN, DEFAULT_ACCOUNT) with app.expect_apdu_failure(StatusCode.INVALID_INS): - app.backend._continue_sign(INS.SIGN_WITH_HASH, + app.backend._continue_sign(Ins.SIGN_WITH_HASH, payload, last=True) diff --git a/tests/integration/nano/test_ensure_always_clearsign.py b/tests/integration/nano/test_ensure_always_clearsign.py index 5bdca4697..7d32f7a4a 100755 --- a/tests/integration/nano/test_ensure_always_clearsign.py +++ b/tests/integration/nano/test_ensure_always_clearsign.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check clear signing never blindsign""" + from pathlib import Path -from utils.app import DEFAULT_ACCOUNT +from utils.app import TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Transaction @@ -26,7 +28,8 @@ # Entrypoint: root # Data: {pair "[" (pair "Z" (pair "Y" (pair "X" (pair "W" (pair "V" (pair "U" (pair "T" (pair "S" (pair "R" (pair "Q" (pair "P" (pair "O" (pair "N" (pair "M" (pair "L" (pair "K" (pair "J" (pair "I" (pair "H" (pair "G" (pair "F" (pair "E" (pair "D" (pair "C" (pair "B" {})))))))))))))))))))))))));pair 10 (pair 9 (pair 8 (pair 7 (pair 6 (pair 5 (pair 4 (pair 3 (pair 2 (pair 1 {})))))))))} -def test_ensure_always_clearsign(app): +def test_ensure_always_clearsign(app: TezosAppScreen): + """Check clear signing never blindsign""" test_name = Path(__file__).stem app.setup_expert_mode() diff --git a/tests/integration/nano/test_get_pk.py b/tests/integration/nano/test_get_pk.py index 0593b7c53..4c82a0e9e 100755 --- a/tests/integration/nano/test_get_pk.py +++ b/tests/integration/nano/test_get_pk.py @@ -13,29 +13,31 @@ # See the License for the specific language governing permissions and # limitations under the License. -from utils.account import Account, SIGNATURE_TYPE -from utils.app import Screen +"""Module to test get-public-key instruction.""" -def test_get_pk(app): +from utils.account import Account, SigType +from utils.app import Screen, TezosAppScreen +def test_get_pk(app: TezosAppScreen): + """Test that public keys get from the app are correct.""" accounts = [ Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.ED25519, + SigType.ED25519, "edpkuXX2VdkdXzkN11oLCb8Aurdo1BTAtQiK8ZY9UPj2YMt3AHEpcY"), Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.SECP256K1, + SigType.SECP256K1, "sppk7bVy617DmGvXsMqcwsiLtnedTN2trUi5ugXcNig7en4rHJyunK1"), Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.SECP256R1, + SigType.SECP256R1, "p2pk67fq5pzuMMABZ9RDrooYbLrgmnQbLt8z7PTGM9mskf7LXS5tdBG"), Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.BIP32_ED25519, + SigType.BIP32_ED25519, "edpkumJgSsSxkpiB5hmTq6eZcrmc6BsJtLAhYceFTiziFqje4mongz") ] for account in accounts: - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) data = app.backend.get_public_key(account, with_prompt=False) diff --git a/tests/integration/nano/test_git.py b/tests/integration/nano/test_git.py index 2781b17f0..97c6b9a46 100755 --- a/tests/integration/nano/test_git.py +++ b/tests/integration/nano/test_git.py @@ -13,11 +13,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -from utils.app import Screen +"""Module to test git instruction.""" -def test_git(app): +from utils.app import Screen, TezosAppScreen - app.assert_screen(Screen.Home) +def test_git(app: TezosAppScreen): + """Test that the app commit is the same as the current git commit.""" + app.assert_screen(Screen.HOME) data = app.backend.git() diff --git a/tests/integration/nano/test_mixing_command.py b/tests/integration/nano/test_mixing_command.py index b49af6e4b..c2fdf66d3 100755 --- a/tests/integration/nano/test_mixing_command.py +++ b/tests/integration/nano/test_mixing_command.py @@ -13,44 +13,47 @@ # See the License for the specific language governing permissions and # limitations under the License. -from utils.app import Screen, DEFAULT_ACCOUNT -from utils.backend import INS, StatusCode +"""Check that mixing instruction fails""" -def test_mixing_command(app): +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT +from utils.backend import Ins, StatusCode - app.assert_screen(Screen.Home) +def test_mixing_command(app: TezosAppScreen): + """Check that mixing instruction fails""" - app.backend._ask_sign(INS.SIGN, DEFAULT_ACCOUNT) + app.assert_screen(Screen.HOME) + + app.backend._ask_sign(Ins.SIGN, DEFAULT_ACCOUNT) with app.expect_apdu_failure(StatusCode.UNEXPECTED_STATE): app.backend.version() - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) - app.backend._ask_sign(INS.SIGN_WITH_HASH, DEFAULT_ACCOUNT) + app.backend._ask_sign(Ins.SIGN_WITH_HASH, DEFAULT_ACCOUNT) with app.expect_apdu_failure(StatusCode.UNEXPECTED_STATE): - app.backend._ask_sign(INS.SIGN, DEFAULT_ACCOUNT) + app.backend._ask_sign(Ins.SIGN, DEFAULT_ACCOUNT) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) - app.backend._ask_sign(INS.SIGN, DEFAULT_ACCOUNT) + app.backend._ask_sign(Ins.SIGN, DEFAULT_ACCOUNT) with app.expect_apdu_failure(StatusCode.UNEXPECTED_STATE): - app.backend._ask_sign(INS.SIGN_WITH_HASH, DEFAULT_ACCOUNT) + app.backend._ask_sign(Ins.SIGN_WITH_HASH, DEFAULT_ACCOUNT) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) - app.backend._ask_sign(INS.SIGN, DEFAULT_ACCOUNT) + app.backend._ask_sign(Ins.SIGN, DEFAULT_ACCOUNT) with app.expect_apdu_failure(StatusCode.UNEXPECTED_STATE): app.backend.get_public_key(DEFAULT_ACCOUNT, with_prompt=True) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) - app.backend._ask_sign(INS.SIGN, DEFAULT_ACCOUNT) + app.backend._ask_sign(Ins.SIGN, DEFAULT_ACCOUNT) with app.expect_apdu_failure(StatusCode.UNEXPECTED_STATE): app.backend.get_public_key(DEFAULT_ACCOUNT, with_prompt=False) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) - app.backend._ask_sign(INS.SIGN, DEFAULT_ACCOUNT) + app.backend._ask_sign(Ins.SIGN, DEFAULT_ACCOUNT) with app.expect_apdu_failure(StatusCode.UNEXPECTED_STATE): app.backend.git() diff --git a/tests/integration/nano/test_parsing_errors.py b/tests/integration/nano/test_parsing_errors.py index 4a01f9609..05fece840 100755 --- a/tests/integration/nano/test_parsing_errors.py +++ b/tests/integration/nano/test_parsing_errors.py @@ -13,15 +13,18 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check parsing error handling""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.backend import StatusCode from utils.message import Message # original bytes : 0300000000000000000000000000000000000000000000000000000000000000006c016e8874874d31c3fbd636e924d5a036a43ec8faa7d0860308362d80d30e01000000000000000000000000000000000000000000ff02000000020316 -def test_parsing_errors(app): +def test_parsing_errors(app: TezosAppScreen): + """Check parsing error handling""" test_name = Path(__file__).stem def make_path(name: str) -> Path: @@ -36,7 +39,7 @@ def make_path(name: str) -> Path: with_hash=True, path=make_path("unknown_magic_bytes")) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) unknown_operation_message = Message.from_bytes("03000000000000000000000000000000000000000000000000000000000000000001016e8874874d31c3fbd636e924d5a036a43ec8faa7d0860308362d80d30e01000000000000000000000000000000000000000000ff02000000020316") @@ -45,7 +48,7 @@ def make_path(name: str) -> Path: with_hash=True, path=make_path("unknown_operation")) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) one_byte_removed_inside_message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000006c016e8874874d31c3fbd636e924d5a036a43ec8faa7d0860308362d80d30e010000000000000000000000000000000000000000ff02000000020316") @@ -54,7 +57,7 @@ def make_path(name: str) -> Path: with_hash=True, path=make_path("one_byte_removed_inside")) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) one_byte_added_at_the_end_message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000006c016e8874874d31c3fbd636e924d5a036a43ec8faa7d0860308362d80d30e01000000000000000000000000000000000000000000ff0200000002031645") @@ -63,7 +66,7 @@ def make_path(name: str) -> Path: with_hash=True, path=make_path("one_byte_added_at_the_end")) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) one_byte_added_inside_message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000006c016e8874874d31c3fbd636e924d5a036a43ec8faa7d0860308362d80d30e0100000000000000000000000000000000000000000000ff02000000020316") @@ -72,7 +75,7 @@ def make_path(name: str) -> Path: with_hash=True, path=make_path("one_byte_added_inside")) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) wrong_last_packet_message = Message.from_bytes("030000000000000000000000000000000000000000000000000000000000000000ce00ffdd6102321bc251e4a5190ad5b12b251069d9b4904e02030400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c63966303966323935326433343532386337333366393436313563666333396263353535363139666335353064643461363762613232303863653865383637616133643133613665663939646662653332633639373461613961323135306432316563613239633333343965353963313362393038316631") diff --git a/tests/integration/nano/test_provide_pk.py b/tests/integration/nano/test_provide_pk.py index 3a79ef895..516d4a094 100755 --- a/tests/integration/nano/test_provide_pk.py +++ b/tests/integration/nano/test_provide_pk.py @@ -13,38 +13,41 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Module to test get-public-key instruction.""" + from pathlib import Path -from utils.account import Account, SIGNATURE_TYPE -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.account import Account, SigType +from utils.app import Screen, TezosAppScreen -def test_provide_pk(app): +def test_provide_pk(app: TezosAppScreen): + """Test that public keys get from the app are correct and correctly displayed.""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) accounts = [ ( Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.ED25519, + SigType.ED25519, "edpkuXX2VdkdXzkN11oLCb8Aurdo1BTAtQiK8ZY9UPj2YMt3AHEpcY"), "ed25519" ), ( Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.SECP256K1, + SigType.SECP256K1, "sppk7bVy617DmGvXsMqcwsiLtnedTN2trUi5ugXcNig7en4rHJyunK1"), "secp256k1" ), ( Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.SECP256R1, + SigType.SECP256R1, "p2pk67fq5pzuMMABZ9RDrooYbLrgmnQbLt8z7PTGM9mskf7LXS5tdBG"), "secp256r1" ), ( Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.BIP32_ED25519, + SigType.BIP32_ED25519, "edpkumJgSsSxkpiB5hmTq6eZcrmc6BsJtLAhYceFTiziFqje4mongz"), "bip32_ed25519" ) @@ -52,7 +55,7 @@ def test_provide_pk(app): for (account, kind) in accounts: - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) data = app.provide_public_key(account, test_name + "/" + kind) diff --git a/tests/integration/nano/test_regression_continue_after_reject.py b/tests/integration/nano/test_regression_continue_after_reject.py index 70b587716..1b1025691 100755 --- a/tests/integration/nano/test_regression_continue_after_reject.py +++ b/tests/integration/nano/test_regression_continue_after_reject.py @@ -13,12 +13,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check the app still runs after rejects signing""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message -def test_regression_continue_after_reject(app): +def test_regression_continue_after_reject(app: TezosAppScreen): + """Check the app still runs after rejects signing""" test_name = Path(__file__).stem def make_path(name: str) -> Path: @@ -28,7 +31,7 @@ def make_path(name: str) -> Path: app.reject_public_key(DEFAULT_ACCOUNT, make_path("reject_public_key")) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000006c00ffdd6102321bc251e4a5190ad5b12b251069d9b4904e0203040001000000000000000000000000000000000000000000ff01000001070200000102076501000000015b076501000000015a0765010000000159076501000000015807650100000001570765010000000156076501000000015507650100000001540765010000000153076501000000015207650100000001510765010000000150076501000000014f076501000000014e076501000000014d076501000000014c076501000000014b076501000000014a0765010000000149076501000000014807650100000001470765010000000146076501000000014507650100000001440765010000000143076501000000014202000000000765000a0765000907650008076500070765000607650005076500040765000307650002076500010200000000") diff --git a/tests/integration/nano/test_reject_pk.py b/tests/integration/nano/test_reject_pk.py index 20f1b1740..65251f67f 100755 --- a/tests/integration/nano/test_reject_pk.py +++ b/tests/integration/nano/test_reject_pk.py @@ -13,14 +13,17 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check reject pk behaviour""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT -def test_reject_pk(app): +def test_reject_pk(app: TezosAppScreen): + """Check reject pk behaviour""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) app.reject_public_key(DEFAULT_ACCOUNT, test_name) diff --git a/tests/integration/nano/test_sign_ballot.py b/tests/integration/nano/test_sign_ballot.py index 8ea933d43..bde516d19 100755 --- a/tests/integration/nano/test_sign_ballot.py +++ b/tests/integration/nano/test_sign_ballot.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing ballot""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Ballot @@ -24,10 +26,11 @@ # Proposal: ProtoALphaALphaALphaALphaALphaALphaALpha61322gcLUGH # Ballot: yay -def test_sign_ballot(app): +def test_sign_ballot(app: TezosAppScreen): + """Check signing ballot""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000000600ffdd6102321bc251e4a5190ad5b12b251069d9b4000000200bcd7b2cadcd87ecb0d5c50330fb59feed7432bffecede8a09a2b86cfb33847b00") diff --git a/tests/integration/nano/test_sign_complex_operation.py b/tests/integration/nano/test_sign_complex_operation.py index 029397d80..709627212 100644 --- a/tests/integration/nano/test_sign_complex_operation.py +++ b/tests/integration/nano/test_sign_complex_operation.py @@ -13,10 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing complex operation""" + from pathlib import Path -from utils.app import Screen, Screen_text, DEFAULT_ACCOUNT -from utils.backend import StatusCode +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Transaction @@ -46,10 +47,11 @@ # Destination: tz3eydffbLkjdVb8zx42BvxpGV87zaRnqL3r # Entrypoint: default -def test_sign_complex_operation(app): +def test_sign_complex_operation(app: TezosAppScreen): + """Check signing complex operation""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) app.setup_expert_mode() message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000006d00ffdd6102321bc251e4a5190ad5b12b251069d9b4a0c21e040304c0843d0000000004050d036a000000060764035c038d9e00ffdd6102321bc251e4a5190ad5b12b251069d9b4904e05040500000002030600000004056303620000591e842444265757d6a65e3670ca18b5e662f9c0070002cc8e146741cf31fc00123b8c26baf95c57421a3c0000000764656661756c74") diff --git a/tests/integration/nano/test_sign_delegation.py b/tests/integration/nano/test_sign_delegation.py index 1e6b26788..ed1e77d19 100755 --- a/tests/integration/nano/test_sign_delegation.py +++ b/tests/integration/nano/test_sign_delegation.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing delegation""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Delegation @@ -23,10 +25,11 @@ # Storage limit: 889 # Delegate: tz1TmFPVZsGQ8MnrBJtnECJgkFUwLa6EWYDm -def test_sign_delegation(app): +def test_sign_delegation(app: TezosAppScreen): + """Check signing delegation""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000006e01774d99da021b92d8c3dfc2e814c7658440319be2c09a0cf40509f906ff00591e842444265757d6a65e3670ca18b5e662f9c0") diff --git a/tests/integration/nano/test_sign_failing_noop.py b/tests/integration/nano/test_sign_failing_noop.py index 4f4ec271a..f8d1c9c85 100755 --- a/tests/integration/nano/test_sign_failing_noop.py +++ b/tests/integration/nano/test_sign_failing_noop.py @@ -13,18 +13,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing failing noop""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Failing noop # Message: 396630396632393532643334353238633733336639343631356366633339626335353536313966633535306464346136376261323230386365386538363761613364313361366566393964666265333263363937346161396132313530643231656361323963333334396535396331336239303831663163313162343430616334643334353564656462653465653064653135613861663632306434633836323437643964313332646531626236646132336435666639643864666664613232626139613834 -def test_sign_failing_noop(app): +def test_sign_failing_noop(app: TezosAppScreen): + """Check signing failing noop""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("03000000000000000000000000000000000000000000000000000000000000000011000000c6396630396632393532643334353238633733336639343631356366633339626335353536313966633535306464346136376261323230386365386538363761613364313361366566393964666265333263363937346161396132313530643231656361323963333334396535396331336239303831663163313162343430616334643334353564656462653465653064653135613861663632306434633836323437643964313332646531626236646132336435666639643864666664613232626139613834") diff --git a/tests/integration/nano/test_sign_increase_paid_storage.py b/tests/integration/nano/test_sign_increase_paid_storage.py index 2ffe79c74..748a7d882 100755 --- a/tests/integration/nano/test_sign_increase_paid_storage.py +++ b/tests/integration/nano/test_sign_increase_paid_storage.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing increase paid storage""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Increase paid storage @@ -24,10 +26,11 @@ # Amount: 5 # Destination: KT18amZmM5W7qDWVt2pH6uj7sCEd3kbzLrHT -def test_sign_increase_paid_storage(app): +def test_sign_increase_paid_storage(app: TezosAppScreen): + """Check signing increase paid storage""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000007100ffdd6102321bc251e4a5190ad5b12b251069d9b4904e0203040501000000000000000000000000000000000000000000") diff --git a/tests/integration/nano/test_sign_micheline_without_hash.py b/tests/integration/nano/test_sign_micheline_without_hash.py index de8fb0c5c..e9e373dfe 100755 --- a/tests/integration/nano/test_sign_micheline_without_hash.py +++ b/tests/integration/nano/test_sign_micheline_without_hash.py @@ -13,17 +13,20 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing micheline wihout getting hash""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Expression: {"CACA";"POPO";"BOUDIN"} -def test_sign_micheline_without_hash(app): +def test_sign_micheline_without_hash(app: TezosAppScreen): + """Check signing micheline wihout getting hash""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("05020000001d0100000004434143410100000004504f504f0100000006424f5544494e") diff --git a/tests/integration/nano/test_sign_origination.py b/tests/integration/nano/test_sign_origination.py index 3f559a398..82c3da918 100755 --- a/tests/integration/nano/test_sign_origination.py +++ b/tests/integration/nano/test_sign_origination.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing origination""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Origination @@ -26,7 +28,8 @@ # Code: UNPAIR # Storage: pair "1" 2 -def test_sign_origination(app): +def test_sign_origination(app: TezosAppScreen): + """Check signing origination""" test_name = Path(__file__).stem app.setup_expert_mode() diff --git a/tests/integration/nano/test_sign_proposals.py b/tests/integration/nano/test_sign_proposals.py index 816ebdcfb..0cc09c172 100755 --- a/tests/integration/nano/test_sign_proposals.py +++ b/tests/integration/nano/test_sign_proposals.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing proposals""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Proposals @@ -24,10 +26,11 @@ # Proposal (0): ProtoALphaALphaALphaALphaALphaALphaALpha61322gcLUGH # Proposal (1): ProtoALphaALphaALphaALphaALphaALphaALphabc2a7ebx6WB -def test_sign_proposals(app): +def test_sign_proposals(app: TezosAppScreen): + """Check signing proposals""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000000500ffdd6102321bc251e4a5190ad5b12b251069d9b400000020000000400bcd7b2cadcd87ecb0d5c50330fb59feed7432bffecede8a09a2b86cfb33847b0bcd7b2cadcd87ecb0d5c50330fb59feed7432bffecede8a09a2b86dac301a2d") diff --git a/tests/integration/nano/test_sign_register_global_constant.py b/tests/integration/nano/test_sign_register_global_constant.py index c9294f607..1c26424eb 100755 --- a/tests/integration/nano/test_sign_register_global_constant.py +++ b/tests/integration/nano/test_sign_register_global_constant.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing register global constant""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Register global constant @@ -23,7 +25,8 @@ # Storage limit: 4 # Value: Pair "1" 2 -def test_sign_register_global_constant(app): +def test_sign_register_global_constant(app: TezosAppScreen): + """Check signing register global constant""" test_name = Path(__file__).stem app.setup_expert_mode() diff --git a/tests/integration/nano/test_sign_reveal.py b/tests/integration/nano/test_sign_reveal.py index 19796786a..b8abed62e 100755 --- a/tests/integration/nano/test_sign_reveal.py +++ b/tests/integration/nano/test_sign_reveal.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing reveal""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Reveal @@ -23,10 +25,11 @@ # Storage limit: 4 # Public key: edpkuXX2VdkdXzkN11oLCb8Aurdo1BTAtQiK8ZY9UPj2YMt3AHEpcY -def test_sign_reveal(app): +def test_sign_reveal(app: TezosAppScreen): + """Check signing reveal""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000006b00ffdd6102321bc251e4a5190ad5b12b251069d9b4904e02030400747884d9abdf16b3ab745158925f567e222f71225501826fa83347f6cbe9c393") diff --git a/tests/integration/nano/test_sign_sc_rollup_add_messages.py b/tests/integration/nano/test_sign_sc_rollup_add_messages.py index e84c4ec36..5d020781e 100755 --- a/tests/integration/nano/test_sign_sc_rollup_add_messages.py +++ b/tests/integration/nano/test_sign_sc_rollup_add_messages.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing smart rollup add message""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): SR: send messages @@ -25,10 +27,11 @@ # Message (1): 67 # Message (2): 89abcdef -def test_sign_sc_rollup_add_messages(app): +def test_sign_sc_rollup_add_messages(app: TezosAppScreen): + """Check signing smart rollup add message""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("030000000000000000000000000000000000000000000000000000000000000000c900ffdd6102321bc251e4a5190ad5b12b251069d9b4904e020304000000140000000301234500000001670000000489abcdef") diff --git a/tests/integration/nano/test_sign_sc_rollup_execute_outbox_message.py b/tests/integration/nano/test_sign_sc_rollup_execute_outbox_message.py index 0e61d14e9..b5083c355 100755 --- a/tests/integration/nano/test_sign_sc_rollup_execute_outbox_message.py +++ b/tests/integration/nano/test_sign_sc_rollup_execute_outbox_message.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing smart rollup execute outbox message""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): SR: execute outbox message @@ -25,7 +27,8 @@ # Commitment: src12UJzB8mg7yU6nWPzicH7ofJbFjyJEbHvwtZdfRXi8DQHNp1LY8 # Output proof: 396630396632393532643334353238633733336639343631356366633339626335353536313966633535306464346136376261323230386365386538363761613364313361366566393964666265333263363937346161396132313530643231656361323963333334396535396331336239303831663163313162343430616334643334353564656462653465653064653135613861663632306434633836323437643964313332646531626236646132336435666639643864666664613232626139613834 -def test_sign_sc_rollup_execute_outbox_message(app): +def test_sign_sc_rollup_execute_outbox_message(app: TezosAppScreen): + """Check signing smart rollup execute outbox message""" test_name = Path(__file__).stem app.setup_expert_mode() diff --git a/tests/integration/nano/test_sign_sc_rollup_originate.py b/tests/integration/nano/test_sign_sc_rollup_originate.py index dfe6f40fa..7adbdfd3b 100755 --- a/tests/integration/nano/test_sign_sc_rollup_originate.py +++ b/tests/integration/nano/test_sign_sc_rollup_originate.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing smart rollup originate""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): SR: originate @@ -28,14 +30,15 @@ # Whitelist (1): tz2WmivuMG8MMRKMEmzKRMMxMApxZQWYNS4W # Whitelist (2): tz3XMQscBFM9vPmpbYMavMmwxRMUWvWGZMQQ -def test_sign_sc_rollup_originate(app): +def test_sign_sc_rollup_originate(app: TezosAppScreen): + """Check signing smart rollup originate""" test_name = Path(__file__).stem app.setup_expert_mode() sc_rollup_originate_with_missing_white_list = "030000000000000000000000000000000000000000000000000000000000000000c800ffdd6102321bc251e4a5190ad5b12b251069d9b4904e02030400000000c63966303966323935326433343532386337333366393436313563666333396263353535363139666335353064643461363762613232303863653865383637616133643133613665663939646662653332633639373461613961323135306432316563613239633333343965353963313362393038316631633131623434306163346433343535646564626534656530646531356138616636323064346338363234376439643133326465316262366461323364356666396438646666646132326261396138340000000a07070100000001310002" - def check_sign(name: str, whitelist: bytes): + def check_sign(name: str, whitelist: str): message = Message.from_bytes(sc_rollup_originate_with_missing_white_list + whitelist) @@ -61,6 +64,9 @@ def check_sign(name: str, whitelist: bytes): # tz2WmivuMG8MMRKMEmzKRMMxMApxZQWYNS4W; # tz3XMQscBFM9vPmpbYMavMmwxRMUWvWGZMQQ # ] - check_sign("with_whitelist", "ff0000003f00ffdd6102321bc251e4a5190ad5b12b251069d9b401f6552df4f5ff51c3d13347cab045cfdb8b9bd8030278eb8b6ab9a768579cd5146b480789650c83f28e") + check_sign( + "with_whitelist", + "ff0000003f00ffdd6102321bc251e4a5190ad5b12b251069d9b401f6552df4f5ff51c3d13347cab045cfdb8b9bd8030278eb8b6ab9a768579cd5146b480789650c83f28e" + ) app.quit() diff --git a/tests/integration/nano/test_sign_set_consensus_key.py b/tests/integration/nano/test_sign_set_consensus_key.py index 684e8f036..97afa14ba 100755 --- a/tests/integration/nano/test_sign_set_consensus_key.py +++ b/tests/integration/nano/test_sign_set_consensus_key.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing set consensus key""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Set consensus key @@ -23,10 +25,11 @@ # Storage limit: 4 # Public key: edpkuXX2VdkdXzkN11oLCb8Aurdo1BTAtQiK8ZY9UPj2YMt3AHEpcY -def test_sign_set_consensus_key(app): +def test_sign_set_consensus_key(app: TezosAppScreen): + """Check signing set consensus key""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000007200c921d4487c90b4472da6cc566a58d79f0d991dbf904e02030400747884d9abdf16b3ab745158925f567e222f71225501826fa83347f6cbe9c393") diff --git a/tests/integration/nano/test_sign_set_deposit_limit.py b/tests/integration/nano/test_sign_set_deposit_limit.py index 97ca4ddae..e90d55c30 100755 --- a/tests/integration/nano/test_sign_set_deposit_limit.py +++ b/tests/integration/nano/test_sign_set_deposit_limit.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing set deposit limit""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Set deposit limit @@ -23,10 +25,11 @@ # Storage limit: 4 # Staking limit: 0.02 XTZ -def test_sign_set_deposit_limit(app): +def test_sign_set_deposit_limit(app: TezosAppScreen): + """Check signing set deposit limit""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("03000000000000000000000000000000000000000000000000000000000000000070027c252d3806e6519ed064026bdb98edf866117331e0d40304f80204ffa09c01") diff --git a/tests/integration/nano/test_sign_too_long_operation.py b/tests/integration/nano/test_sign_too_long_operation.py index d19261707..e6b76f0cc 100644 --- a/tests/integration/nano/test_sign_too_long_operation.py +++ b/tests/integration/nano/test_sign_too_long_operation.py @@ -13,16 +13,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing too long operation behaviour""" + from pathlib import Path from typing import Callable -from utils.app import Screen, Screen_text, DEFAULT_ACCOUNT +from utils.app import ScreenText, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message from utils.backend import StatusCode test_path = Path(Path(__file__).stem) -def _sign_too_long(app, msg: str, navigate: Callable[[], None]): +def _sign_too_long(app: TezosAppScreen, + msg: str, + navigate: Callable[[], None]): + """Sign a too long message""" app.setup_expert_mode() app.setup_blindsign_on() @@ -44,10 +49,11 @@ def _sign_too_long(app, msg: str, navigate: Callable[[], None]): app.quit() def _sign_decodable_too_long(app, msg: str, path: Path): + """Sign a decodable too long message""" def navigate() -> None: - app.navigate_until_text(Screen_text.Accept_risk, path / "clear_n_too_long_warning") - app.navigate_until_text(Screen_text.Sign_accept, path / "summary") + app.navigate_until_text(ScreenText.ACCEPT_RISK, path / "clear_n_too_long_warning") + app.navigate_until_text(ScreenText.SIGN_ACCEPT, path / "summary") _sign_too_long(app, msg, navigate) @@ -56,6 +62,7 @@ def _reject_too_long( msg: str, status_code: StatusCode, navigate: Callable[[], None]): + """Reject a too long message""" app.setup_expert_mode() app.setup_blindsign_on() @@ -123,27 +130,30 @@ def _reject_too_long( # Fee: 1 XTZ # Storage limit: 3 # Staking limit: 10 XTZ -basic_operation = "0300000000000000000000000000000000000000000000000000000000000000006b00ffdd6102321bc251e4a5190ad5b12b251069d9b4c0843d0b0104020320182716513907b6bab33f905396d031931c07e01bddd780780c1a56b9c086da6c00ffdd6102321bc251e4a5190ad5b12b251069d9b480897a0c0107c08db701000278eb8b6ab9a768579cd5146b480789650c83f28effff0d7570646174655f636f6e6669670000000607070005030a6e00ffdd6102321bc251e4a5190ad5b12b251069d9b4c08db7010d0105ff01ee572f02e5be5d097ba17369789582882e8abb87c900ffdd6102321bc251e4a5190ad5b12b251069d9b48092f4010e0106000000fa000000086d65737361676530000000086d65737361676531000000086d65737361676532000000086d65737361676533000000086d65737361676534000000086d65737361676535000000086d65737361676536000000086d65737361676537000000086d65737361676538000000086d65737361676539000000096d6573736167653130000000096d6573736167653131000000096d6573736167653132000000096d6573736167653133000000096d6573736167653134000000096d6573736167653135000000096d6573736167653136000000096d6573736167653137000000096d6573736167653138000000096d65737361676531397000ffdd6102321bc251e4a5190ad5b12b251069d9b4c0843d0f0103ff80ade204" +BASIC_OPERATION = "0300000000000000000000000000000000000000000000000000000000000000006b00ffdd6102321bc251e4a5190ad5b12b251069d9b4c0843d0b0104020320182716513907b6bab33f905396d031931c07e01bddd780780c1a56b9c086da6c00ffdd6102321bc251e4a5190ad5b12b251069d9b480897a0c0107c08db701000278eb8b6ab9a768579cd5146b480789650c83f28effff0d7570646174655f636f6e6669670000000607070005030a6e00ffdd6102321bc251e4a5190ad5b12b251069d9b4c08db7010d0105ff01ee572f02e5be5d097ba17369789582882e8abb87c900ffdd6102321bc251e4a5190ad5b12b251069d9b48092f4010e0106000000fa000000086d65737361676530000000086d65737361676531000000086d65737361676532000000086d65737361676533000000086d65737361676534000000086d65737361676535000000086d65737361676536000000086d65737361676537000000086d65737361676538000000086d65737361676539000000096d6573736167653130000000096d6573736167653131000000096d6573736167653132000000096d6573736167653133000000096d6573736167653134000000096d6573736167653135000000096d6573736167653136000000096d6573736167653137000000096d6573736167653138000000096d65737361676531397000ffdd6102321bc251e4a5190ad5b12b251069d9b4c0843d0f0103ff80ade204" -def test_sign_basic_too_long_operation(app): - _sign_decodable_too_long(app, basic_operation, basic_test_path / "accept") +def test_sign_basic_too_long_operation(app: TezosAppScreen): + """Check sign too long operation""" + _sign_decodable_too_long(app, BASIC_OPERATION, basic_test_path / "accept") -def test_reject_basic_too_long_operation_at_warning(app): +def test_reject_basic_too_long_operation_at_warning(app: TezosAppScreen): + """Check reject too long operation at warning""" path = basic_test_path / "reject_at_too_large_warning" def navigate() -> None: - app.navigate_until_text(Screen_text.Sign_reject, path / "clear_n_too_long_warning") + app.navigate_until_text(ScreenText.SIGN_REJECT, path / "clear_n_too_long_warning") - _reject_too_long(app, basic_operation, StatusCode.REJECT, navigate) + _reject_too_long(app, BASIC_OPERATION, StatusCode.REJECT, navigate) -def test_reject_basic_too_long_operation_at_summary(app): +def test_reject_basic_too_long_operation_at_summary(app: TezosAppScreen): + """Check reject too long operation at summary""" path = basic_test_path / "reject_at_summary" def navigate() -> None: - app.navigate_until_text(Screen_text.Accept_risk, path / "clear_n_too_long_warning") - app.navigate_until_text(Screen_text.Sign_reject, path / "summary") + app.navigate_until_text(ScreenText.ACCEPT_RISK, path / "clear_n_too_long_warning") + app.navigate_until_text(ScreenText.SIGN_REJECT, path / "summary") - _reject_too_long(app, basic_operation, StatusCode.REJECT, navigate) + _reject_too_long(app, BASIC_OPERATION, StatusCode.REJECT, navigate) ### Different kind of too long operation ### @@ -184,7 +194,8 @@ def navigate() -> None: # Storage limit: 5 # Amount: 5 XTZ # Destination: tz2JPgTWZZpxZZLqHMfS69UAy1UHm4Aw5iHu -def test_sign_too_long_operation_with_only_transactions(app): +def test_sign_too_long_operation_with_only_transactions(app: TezosAppScreen): + """Check sign too long operation that contains only transaction""" msg="0300000000000000000000000000000000000000000000000000000000000000006c00ffdd6102321bc251e4a5190ad5b12b251069d9b4000b010080ade2040000d2b3082b0fe03f0f7f39915cdba50e9d9b8ab057006c00ffdd6102321bc251e4a5190ad5b12b251069d9b4c0843d0c0101c0843d0001a55ae1858c1201514c97aa9122e77d3c4197a714006c00ffdd6102321bc251e4a5190ad5b12b251069d9b480897a0d010280897a000001e8e5519a315280a374c8765107979a6049de27006c00ffdd6102321bc251e4a5190ad5b12b251069d9b4c08db7010e0103c08db7010002d09584de879c4bbd3f494ed01b82e06a81e8e176006c00ffdd6102321bc251e4a5190ad5b12b251069d9b48092f4010f01048092f4010002cc8e146741cf31fc00123b8c26baf95c57421a3c006c00ffdd6102321bc251e4a5190ad5b12b251069d9b4c096b102100105c096b10200016e8874874d31c3fbd636e924d5a036a43ec8faa700" _sign_decodable_too_long(app, msg, test_path / "only_transactions") @@ -211,7 +222,8 @@ def test_sign_too_long_operation_with_only_transactions(app): # Proposal (17): ProxfordYmVfjWnRcgjWH36fW6PArwqykTFzotUxRs6gmTcZDuH # Proposal (18): PtParisBxoLz5gzMmn3d9WBQNoPSZakgnkMC2VNuQ3KXfUtUQeZ # Proposal (19): ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK -def test_sign_too_long_operation_without_fee_or_amount(app): +def test_sign_too_long_operation_without_fee_or_amount(app: TezosAppScreen): + """Check sign too long operation that doesn't have fees or amount""" msg="0300000000000000000000000000000000000000000000000000000000000000000500ffdd6102321bc251e4a5190ad5b12b251069d9b400000020000002800bcd7db2d718ba94e85bd262681049852e1f58512aa552124330d657845c73b70bcd7ffca03f57e38453f0d3e84c302403c05357448b4c2daef8b3a8be3c69c1000000000000000000000000000000000000000000000000000000000000000038ecdef0cd08640f318a9b055f6b0d0c9ae030913a871d9b9d86fb846317da213d0b4bacb5c3e152a167da26fefc266bd3a0e14fc4e41e6c53623bf482833da23e5e3a606afab74a59ca09e333633e2770b6492c5e594455b71e9a2f0ea92afb40cab83d3f37a64da26b57ad3d0432ae881293a25169ada387bfc74a1cbf9e6ec7ad4f7a000e28e9eefc58de8ea1172de843242bd2e688779953d3416a44640b4596285c6871691e25196c6a8d26d90a3ac91375731e3926103c517a13a0ba56cbb944f74244ea2681981f25995f8ebba8ff6cee8c036892fe901cb760c4e39ece5f061e34b5a21feab8dbdfe755ef17e70c9f565464f067ac5e7c02be830a488424520cf9bbf0a42770204d95dcc1f11e404fdb3e90c84850c4cfdb50c5c4b9d0a3f07b8adfcf61f5ca60f244ca9a876e76cbad9140980f6c88d0bf900ac6d8d2ea9f23a1a1011091841b12e32ce2f8c3facff27feee58bb7c9e90567d11425d57ed88be5a69815e39386a33f7dcad391f5f507e03b376e499272c86c6cf2a7d8325f11da2ff36934a586439f085655a833f2ff6a12d15e83b951fb684326e0d9b8c2314cc05ffa3fc655a98bb87155be4cf7ce67fee6b594ea9302e8655df20bf44c7d64e3d7da27d925d10af535fb36cef0ad41930c7929773f4731eba137dbff6586a04802d3f513c65a444d9d4debe42b17e9e7273f8f6c118ea3f4e06e0bcd7b2cadcd87ecb0d5c50330fb59feed7432bffecede8a09a2b86d1527c6a5" _sign_decodable_too_long(app, msg, test_path / "without_fee_or_amount") @@ -259,30 +271,33 @@ def test_sign_too_long_operation_without_fee_or_amount(app): # Fee: 5 XTZ # Storage limit: 3 # Value: 115792089237316195423570985008687907853269984665640564039457584007913129639936 -operation_with_too_large = "030000000000000000000000000000000000000000000000000000000000000000c900ffdd6102321bc251e4a5190ad5b12b251069d9b48092f4010b01060000017c000000086d65737361676530000000086d65737361676531000000086d65737361676532000000086d65737361676533000000086d65737361676534000000086d65737361676535000000086d65737361676536000000086d65737361676537000000086d65737361676538000000086d65737361676539000000096d6573736167653130000000096d6573736167653131000000096d6573736167653132000000096d6573736167653133000000096d6573736167653134000000096d6573736167653135000000096d6573736167653136000000096d6573736167653137000000096d6573736167653138000000096d6573736167653139000000096d6573736167653230000000096d6573736167653231000000096d6573736167653232000000096d6573736167653233000000096d6573736167653234000000096d6573736167653235000000096d6573736167653236000000096d6573736167653237000000096d6573736167653238000000096d65737361676532396f00ffdd6102321bc251e4a5190ad5b12b251069d9b4c096b1020c0103000000260080808080808080808080808080808080808080808080808080808080808080808080808020" +OPERATION_WITH_TOO_LARGE = "030000000000000000000000000000000000000000000000000000000000000000c900ffdd6102321bc251e4a5190ad5b12b251069d9b48092f4010b01060000017c000000086d65737361676530000000086d65737361676531000000086d65737361676532000000086d65737361676533000000086d65737361676534000000086d65737361676535000000086d65737361676536000000086d65737361676537000000086d65737361676538000000086d65737361676539000000096d6573736167653130000000096d6573736167653131000000096d6573736167653132000000096d6573736167653133000000096d6573736167653134000000096d6573736167653135000000096d6573736167653136000000096d6573736167653137000000096d6573736167653138000000096d6573736167653139000000096d6573736167653230000000096d6573736167653231000000096d6573736167653232000000096d6573736167653233000000096d6573736167653234000000096d6573736167653235000000096d6573736167653236000000096d6573736167653237000000096d6573736167653238000000096d65737361676532396f00ffdd6102321bc251e4a5190ad5b12b251069d9b4c096b1020c0103000000260080808080808080808080808080808080808080808080808080808080808080808080808020" -def test_sign_too_long_operation_with_too_large(app): +def test_sign_too_long_operation_with_too_large(app: TezosAppScreen): + """Check sign too long operation that will also fail the parsing""" path = too_large_test_path / "accept" def navigate() -> None: - app.navigate_until_text(Screen_text.Accept_risk, path / "clear_n_too_large_warning") - app.navigate_until_text(Screen_text.Sign_accept, path / "blindsigning") + app.navigate_until_text(ScreenText.ACCEPT_RISK, path / "clear_n_too_large_warning") + app.navigate_until_text(ScreenText.SIGN_ACCEPT, path / "blindsigning") - _sign_too_long(app, operation_with_too_large, navigate) + _sign_too_long(app, OPERATION_WITH_TOO_LARGE, navigate) -def test_reject_too_long_operation_with_too_large_at_too_large_warning(app): +def test_reject_too_long_operation_with_too_large_at_too_large_warning(app: TezosAppScreen): + """Check reject too long operation that will also fail the parsing at too large warning""" path = too_large_test_path / "reject_at_too_large_warning" def navigate() -> None: - app.navigate_until_text(Screen_text.Sign_reject, path / "clear_n_too_large_warning") + app.navigate_until_text(ScreenText.SIGN_REJECT, path / "clear_n_too_large_warning") - _reject_too_long(app, operation_with_too_large, StatusCode.PARSE_ERROR, navigate) + _reject_too_long(app, OPERATION_WITH_TOO_LARGE, StatusCode.PARSE_ERROR, navigate) -def test_reject_too_long_operation_with_too_large_at_blindsigning(app): +def test_reject_too_long_operation_with_too_large_at_blindsigning(app: TezosAppScreen): + """Check reject too long operation that will also fail the parsing at blindsigning""" path = too_large_test_path / "reject_at_blindsigning" def navigate() -> None: - app.navigate_until_text(Screen_text.Accept_risk, path / "clear_n_too_large_warning") - app.navigate_until_text(Screen_text.Sign_reject, path / "blindsigning") + app.navigate_until_text(ScreenText.ACCEPT_RISK, path / "clear_n_too_large_warning") + app.navigate_until_text(ScreenText.SIGN_REJECT, path / "blindsigning") - _reject_too_long(app, operation_with_too_large, StatusCode.REJECT, navigate) + _reject_too_long(app, OPERATION_WITH_TOO_LARGE, StatusCode.REJECT, navigate) diff --git a/tests/integration/nano/test_sign_transaction.py b/tests/integration/nano/test_sign_transaction.py index a62c42b2e..1d38253d0 100755 --- a/tests/integration/nano/test_sign_transaction.py +++ b/tests/integration/nano/test_sign_transaction.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing transaction""" + from pathlib import Path -from utils.app import Screen, Screen_text, DEFAULT_ACCOUNT +from utils.app import Screen, ScreenText, TezosAppScreen, DEFAULT_ACCOUNT from utils.backend import StatusCode from utils.message import Message @@ -29,7 +31,8 @@ # Destination: KT18amZmM5W7qDWVt2pH6uj7sCEd3kbzLrHT # Entrypoint: do # Parameter: CAR -def test_sign_transaction(app): +def test_sign_transaction(app: TezosAppScreen): + """Check signing transaction""" path = test_path / "basic" app.setup_expert_mode() @@ -57,7 +60,8 @@ def test_sign_transaction(app): # Destination: KT18amZmM5W7qDWVt2pH6uj7sCEd3kbzLrHT # Entrypoint: root # Data: {pair "[" (pair "Z" (pair "Y" (pair "X" (pair "W" (pair "V" (pair "U" (pair "T" (pair "S" (pair "R" (pair "Q" (pair "P" (pair "O" (pair "N" (pair "M" (pair "L" (pair "K" (pair "J" (pair "I" (pair "H" (pair "G" (pair "F" (pair "E" (pair "D" (pair "C" (pair "B" {})))))))))))))))))))))))));pair 10 (pair 9 (pair 8 (pair 7 (pair 6 (pair 5 (pair 4 (pair 3 (pair 2 (pair 1 {})))))))))} -def test_reject_transaction(app): +def test_reject_transaction(app: TezosAppScreen): + """Check reject transaction""" path = test_path / "reject" app.setup_expert_mode() @@ -77,7 +81,8 @@ def test_reject_transaction(app): # Storage limit: 4 # Amount: 0.01 XTZ # Destination: KT18amZmM5W7qDWVt2pH6uj7sCEd3kbzLrHT -def test_sign_simple_transaction(app): +def test_sign_simple_transaction(app: TezosAppScreen): + """Check sign not complex transaction""" path = test_path / "simple" app.setup_expert_mode() @@ -105,9 +110,10 @@ def test_sign_simple_transaction(app): # Destination: KT18amZmM5W7qDWVt2pH6uj7sCEd3kbzLrHT # Entrypoint: do # Parameter: CAR -def test_too_complex_transaction(app): +def test_too_complex_transaction(app: TezosAppScreen): + """Check sign complex transaction""" path = test_path / "complex" - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000006c016e8874874d31c3fbd636e924d5a036a43ec8faa7d0860308362d80d30e01000000000000000000000000000000000000000000ff02000000020316") @@ -115,7 +121,7 @@ def test_too_complex_transaction(app): message, with_hash=True, navigate=(lambda: app.navigate_until_text( - Screen_text.Back_home, + ScreenText.BACK_HOME, path)), status_code=StatusCode.REJECT) @@ -129,7 +135,8 @@ def test_too_complex_transaction(app): # Destination: tz2CJBeWWLsUDjVUDqGZL6od3DeBCNzYXrXk # Entrypoint: stake # Parameter: Unit -def test_sign_stake_transaction(app): +def test_sign_stake_transaction(app: TezosAppScreen): + """Check sign stake""" path = test_path / "stake" app.setup_expert_mode() @@ -157,7 +164,8 @@ def test_sign_stake_transaction(app): # Destination: tz2CJBeWWLsUDjVUDqGZL6od3DeBCNzYXrXk # Entrypoint: unstake # Parameter: Unit -def test_sign_unstake_transaction(app): +def test_sign_unstake_transaction(app: TezosAppScreen): + """Check sign unstake""" path = test_path / "unstake" app.setup_expert_mode() @@ -185,7 +193,8 @@ def test_sign_unstake_transaction(app): # Destination: tz2CJBeWWLsUDjVUDqGZL6od3DeBCNzYXrXk # Entrypoint: finalize_unstake # Parameter: Unit -def test_sign_finalize_unstake_transaction(app): +def test_sign_finalize_unstake_transaction(app: TezosAppScreen): + """Check sign finalize_unstake""" path = test_path / "finalize_unstake" app.setup_expert_mode() @@ -213,7 +222,8 @@ def test_sign_finalize_unstake_transaction(app): # Destination: tz2CJBeWWLsUDjVUDqGZL6od3DeBCNzYXrXk # Entrypoint: set_delegate_parameters # Parameter: Pair 4000000 (Pair 20000000 Unit) -def test_sign_set_delegate_parameters_transaction(app): +def test_sign_set_delegate_parameters_transaction(app: TezosAppScreen): + """Check sign set delegate parameters""" path = test_path / "delegate_parameters" app.setup_expert_mode() diff --git a/tests/integration/nano/test_sign_transfer_ticket.py b/tests/integration/nano/test_sign_transfer_ticket.py index 547bc29c9..708f0f61f 100755 --- a/tests/integration/nano/test_sign_transfer_ticket.py +++ b/tests/integration/nano/test_sign_transfer_ticket.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing transfer ticket""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Transfer ticket @@ -28,7 +30,8 @@ # Destination: KT18amZmM5W7qDWVt2pH6uj7sCEd3kbzLrHT # Entrypoint: default -def test_sign_transfer_ticket(app): +def test_sign_transfer_ticket(app: TezosAppScreen): + """Check signing transfer ticket""" test_name = Path(__file__).stem app.setup_expert_mode() diff --git a/tests/integration/nano/test_sign_with_another_seed.py b/tests/integration/nano/test_sign_with_another_seed.py index 793b0a0cb..e09089b4d 100755 --- a/tests/integration/nano/test_sign_with_another_seed.py +++ b/tests/integration/nano/test_sign_with_another_seed.py @@ -13,12 +13,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -import pytest +"""Check signing using another seed than [zebra*24]""" from pathlib import Path -from utils.account import Account, SIGNATURE_TYPE -from utils.app import Screen +import pytest + +from utils.account import Account, SigType +from utils.app import TezosAppScreen from utils.message import Message # Operation (0): Transaction @@ -30,13 +32,14 @@ # Parameter: CAR @pytest.mark.parametrize("seed", ["around dignity equal spread between young lawsuit interest climb wide that panther rather mom snake scene ecology reunion ice illegal brush"]) -def test_sign_with_another_seed(app): +def test_sign_with_another_seed(app: TezosAppScreen): + """Check signing using another seed than [zebra*24]""" test_name = Path(__file__).stem app.setup_expert_mode() account = Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.ED25519, + SigType.ED25519, "edpkupntwMyERpYniuK1GDWquPaPU1wYsQgMirJPLGmC4Y5dMUsQNo") message = Message.from_bytes("0300000000000000000000000000000000000000000000000000000000000000006c016e8874874d31c3fbd636e924d5a036a43ec8faa7d0860308362d80d30e01000000000000000000000000000000000000000000ff02000000020316") diff --git a/tests/integration/nano/test_sign_with_long_hash.py b/tests/integration/nano/test_sign_with_long_hash.py index b5cfb84f7..ad07111f9 100755 --- a/tests/integration/nano/test_sign_with_long_hash.py +++ b/tests/integration/nano/test_sign_with_long_hash.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing transaction with a long destination hash""" + from pathlib import Path -from utils.app import Screen, DEFAULT_ACCOUNT +from utils.app import TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message # Operation (0): Transaction @@ -26,7 +28,8 @@ # Entrypoint: root # Parameter: 0 -def test_sign_with_long_hash(app): +def test_sign_with_long_hash(app: TezosAppScreen): + """Check signing transaction with a long destination hash""" test_name = Path(__file__).stem app.setup_expert_mode() diff --git a/tests/integration/nano/test_sign_with_small_packet.py b/tests/integration/nano/test_sign_with_small_packet.py index eacd9e713..8a482feaf 100755 --- a/tests/integration/nano/test_sign_with_small_packet.py +++ b/tests/integration/nano/test_sign_with_small_packet.py @@ -13,13 +13,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing using small packet instead of full size packets""" + from pathlib import Path from utils.account import Account -from utils.app import send_and_navigate, Screen, Screen_text, DEFAULT_ACCOUNT +from utils.app import send_and_navigate, Screen, ScreenText, TezosAppScreen, DEFAULT_ACCOUNT from utils.message import Message -def test_sign_with_small_packet(app): +def test_sign_with_small_packet(app: TezosAppScreen): + """Check signing using small packet instead of full size packets""" test_name = Path(__file__).stem app.setup_expert_mode() @@ -29,11 +32,11 @@ def check_sign_with_small_packet( message: Message, path: str) -> None: - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) data = send_and_navigate( - send=(lambda: app.backend.sign(account, message, apdu_size=10)), - navigate=(lambda: app.navigate_until_text(Screen_text.Sign_accept, path))) + send=lambda: app.backend.sign(account, message, apdu_size=10), + navigate=lambda: app.navigate_until_text(ScreenText.SIGN_ACCEPT, path)) app.checker.check_signature( account, diff --git a/tests/integration/nano/test_tz1_bip25519_sign_micheline_basic.py b/tests/integration/nano/test_tz1_bip25519_sign_micheline_basic.py index f3b59c7c6..6d5ec7414 100755 --- a/tests/integration/nano/test_tz1_bip25519_sign_micheline_basic.py +++ b/tests/integration/nano/test_tz1_bip25519_sign_micheline_basic.py @@ -13,21 +13,24 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing with bip25519""" + from pathlib import Path -from utils.account import Account, SIGNATURE_TYPE -from utils.app import Screen +from utils.account import Account, SigType +from utils.app import Screen, TezosAppScreen from utils.message import Message # Expression: {"CACA";"POPO";"BOUDIN"} -def test_tz1_bip25519_sign_micheline_basic(app): +def test_tz1_bip25519_sign_micheline_basic(app: TezosAppScreen): + """Check signing with bip25519""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) account = Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.BIP32_ED25519, + SigType.BIP32_ED25519, "edpkumJgSsSxkpiB5hmTq6eZcrmc6BsJtLAhYceFTiziFqje4mongz") message = Message.from_bytes("05020000001d0100000004434143410100000004504f504f0100000006424f5544494e") diff --git a/tests/integration/nano/test_tz1_ed25519_sign_micheline_basic.py b/tests/integration/nano/test_tz1_ed25519_sign_micheline_basic.py index c377f660d..05fa1d95f 100755 --- a/tests/integration/nano/test_tz1_ed25519_sign_micheline_basic.py +++ b/tests/integration/nano/test_tz1_ed25519_sign_micheline_basic.py @@ -13,21 +13,24 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing with ed25519""" + from pathlib import Path -from utils.account import Account, SIGNATURE_TYPE -from utils.app import Screen +from utils.account import Account, SigType +from utils.app import Screen, TezosAppScreen from utils.message import Message # Expression: {"CACA";"POPO";"BOUDIN"} -def test_tz1_ed25519_sign_micheline_basic(app): +def test_tz1_ed25519_sign_micheline_basic(app: TezosAppScreen): + """Check signing with ed25519""" test_name = Path(__file__).stem - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) account = Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.ED25519, + SigType.ED25519, "edpkuXX2VdkdXzkN11oLCb8Aurdo1BTAtQiK8ZY9UPj2YMt3AHEpcY") message = Message.from_bytes("05020000001d0100000004434143410100000004504f504f0100000006424f5544494e") diff --git a/tests/integration/nano/test_tz2_sign_micheline_basic.py b/tests/integration/nano/test_tz2_sign_micheline_basic.py index 4d05c0b31..fa29e13f0 100755 --- a/tests/integration/nano/test_tz2_sign_micheline_basic.py +++ b/tests/integration/nano/test_tz2_sign_micheline_basic.py @@ -13,18 +13,22 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing with secp256k1""" + from pathlib import Path -from utils.account import Account, SIGNATURE_TYPE +from utils.account import Account, SigType +from utils.app import TezosAppScreen from utils.message import Message # Expression: {"CACA";"POPO";"BOUDIN"} -def test_tz2_sign_micheline_basic(app): +def test_tz2_sign_micheline_basic(app: TezosAppScreen): + """Check signing with secp256k1""" test_name = Path(__file__).stem account = Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.SECP256K1, + SigType.SECP256K1, "sppk7bVy617DmGvXsMqcwsiLtnedTN2trUi5ugXcNig7en4rHJyunK1") message = Message.from_bytes("05020000001d0100000004434143410100000004504f504f0100000006424f5544494e") diff --git a/tests/integration/nano/test_tz3_sign_micheline_basic.py b/tests/integration/nano/test_tz3_sign_micheline_basic.py index c488d93ce..f0839b34d 100755 --- a/tests/integration/nano/test_tz3_sign_micheline_basic.py +++ b/tests/integration/nano/test_tz3_sign_micheline_basic.py @@ -13,18 +13,22 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check signing with p256""" + from pathlib import Path -from utils.account import Account, SIGNATURE_TYPE +from utils.account import Account, SigType +from utils.app import TezosAppScreen from utils.message import Message # Expression: {"CACA";"POPO";"BOUDIN"} -def test_tz3_sign_micheline_basic(app): +def test_tz3_sign_micheline_basic(app: TezosAppScreen): + """Check signing with p256""" test_name = Path(__file__).stem account = Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.SECP256R1, + SigType.SECP256R1, "p2pk67fq5pzuMMABZ9RDrooYbLrgmnQbLt8z7PTGM9mskf7LXS5tdBG") message = Message.from_bytes("05020000001d0100000004434143410100000004504f504f0100000006424f5544494e") diff --git a/tests/integration/nano/test_unimplemented_commands.py b/tests/integration/nano/test_unimplemented_commands.py index aae16d49a..90e50aa11 100755 --- a/tests/integration/nano/test_unimplemented_commands.py +++ b/tests/integration/nano/test_unimplemented_commands.py @@ -13,25 +13,27 @@ # See the License for the specific language governing permissions and # limitations under the License. -from utils.app import Screen -from utils.backend import INS, StatusCode +"""Check unimplemented commands""" -def test_unimplemented_commands(app): +from utils.app import Screen, TezosAppScreen +from utils.backend import Ins, StatusCode +def test_unimplemented_commands(app: TezosAppScreen): + """Check unimplemented commands""" for ins in \ - [INS.AUTHORIZE_BAKING, \ - INS.SIGN_UNSAFE, \ - INS.RESET, \ - INS.QUERY_AUTH_KEY, \ - INS.QUERY_MAIN_HWM, \ - INS.SETUP, \ - INS.QUERY_ALL_HWM, \ - INS.DEAUTHORIZE, \ - INS.QUERY_AUTH_KEY_WITH_CURVE, \ - INS.HMAC, \ + [Ins.AUTHORIZE_BAKING, \ + Ins.SIGN_UNSAFE, \ + Ins.RESET, \ + Ins.QUERY_AUTH_KEY, \ + Ins.QUERY_MAIN_HWM, \ + Ins.SETUP, \ + Ins.QUERY_ALL_HWM, \ + Ins.DEAUTHORIZE, \ + Ins.QUERY_AUTH_KEY_WITH_CURVE, \ + Ins.HMAC, \ 0xff]: - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) with app.expect_apdu_failure(StatusCode.INVALID_INS): app.backend._exchange(ins) diff --git a/tests/integration/nano/test_version.py b/tests/integration/nano/test_version.py index 588a170da..c81640e53 100755 --- a/tests/integration/nano/test_version.py +++ b/tests/integration/nano/test_version.py @@ -13,11 +13,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -from utils.app import Screen +"""Module to test version instruction.""" -def test_version(app): +from utils.app import Screen, TezosAppScreen - app.assert_screen(Screen.Home) +def test_version(app: TezosAppScreen): + """Test that the app version is the same as the current version.""" + app.assert_screen(Screen.HOME) data = app.backend.version() diff --git a/tests/integration/nano/test_wrong_apdu_length.py b/tests/integration/nano/test_wrong_apdu_length.py index 170965a45..a5c444cd6 100755 --- a/tests/integration/nano/test_wrong_apdu_length.py +++ b/tests/integration/nano/test_wrong_apdu_length.py @@ -13,32 +13,34 @@ # See the License for the specific language governing permissions and # limitations under the License. -from utils.account import SIGNATURE_TYPE -from utils.app import Screen -from utils.backend import CLA, INDEX, INS, StatusCode +"""Check wrong apdu length behaviour""" -def test_wrong_apdu_length(app): +from utils.account import SigType +from utils.app import Screen, TezosAppScreen +from utils.backend import Cla, Index, Ins, StatusCode - app.assert_screen(Screen.Home) +def test_wrong_apdu_length(app: TezosAppScreen): + """Check wrong apdu length behaviour""" + app.assert_screen(Screen.HOME) raw = \ - int(CLA.DEFAULT).to_bytes(1, 'big') + \ - int(INS.VERSION).to_bytes(1, 'big') + \ - int(INDEX.FIRST).to_bytes(1, 'big') + \ - int(SIGNATURE_TYPE.ED25519).to_bytes(1, 'big') + \ + int(Cla.DEFAULT).to_bytes(1, 'big') + \ + int(Ins.VERSION).to_bytes(1, 'big') + \ + int(Index.FIRST).to_bytes(1, 'big') + \ + int(SigType.ED25519).to_bytes(1, 'big') + \ int(0x00).to_bytes(1, 'big') + \ int(0x00).to_bytes(1, 'big') # right size = 0x01 with app.expect_apdu_failure(StatusCode.WRONG_LENGTH_FOR_INS): app.backend.exchange_raw(raw) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) raw = \ - int(CLA.DEFAULT).to_bytes(1, 'big') + \ - int(INS.VERSION).to_bytes(1, 'big') + \ - int(INDEX.FIRST).to_bytes(1, 'big') + \ - int(SIGNATURE_TYPE.ED25519).to_bytes(1, 'big') + \ + int(Cla.DEFAULT).to_bytes(1, 'big') + \ + int(Ins.VERSION).to_bytes(1, 'big') + \ + int(Index.FIRST).to_bytes(1, 'big') + \ + int(SigType.ED25519).to_bytes(1, 'big') + \ int(0x01).to_bytes(1, 'big') # right size = 0x00 with app.expect_apdu_failure(StatusCode.WRONG_LENGTH_FOR_INS): diff --git a/tests/integration/nano/test_wrong_class.py b/tests/integration/nano/test_wrong_class.py index f7d5978bb..7d79bd076 100755 --- a/tests/integration/nano/test_wrong_class.py +++ b/tests/integration/nano/test_wrong_class.py @@ -13,31 +13,33 @@ # See the License for the specific language governing permissions and # limitations under the License. -from utils.account import SIGNATURE_TYPE -from utils.app import Screen -from utils.backend import INDEX, INS, StatusCode +"""Check wrong apdu class behaviour""" -def test_wrong_class(app): +from utils.account import SigType +from utils.app import Screen, TezosAppScreen +from utils.backend import Index, Ins, StatusCode - app.assert_screen(Screen.Home) +def test_wrong_class(app: TezosAppScreen): + """Check wrong apdu class behaviour""" + app.assert_screen(Screen.HOME) raw = \ int(0x00).to_bytes(1, 'big') + \ - int(INS.VERSION).to_bytes(1, 'big') + \ - int(INDEX.FIRST).to_bytes(1, 'big') + \ - int(SIGNATURE_TYPE.ED25519).to_bytes(1, 'big') + \ + int(Ins.VERSION).to_bytes(1, 'big') + \ + int(Index.FIRST).to_bytes(1, 'big') + \ + int(SigType.ED25519).to_bytes(1, 'big') + \ int(0x00).to_bytes(1, 'big') with app.expect_apdu_failure(StatusCode.CLASS): app.backend.exchange_raw(raw) - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) raw = \ int(0x81).to_bytes(1, 'big') + \ - int(INS.VERSION).to_bytes(1, 'big') + \ - int(INDEX.FIRST).to_bytes(1, 'big') + \ - int(SIGNATURE_TYPE.ED25519).to_bytes(1, 'big') + \ + int(Ins.VERSION).to_bytes(1, 'big') + \ + int(Index.FIRST).to_bytes(1, 'big') + \ + int(SigType.ED25519).to_bytes(1, 'big') + \ int(0x00).to_bytes(1, 'big') with app.expect_apdu_failure(StatusCode.CLASS): diff --git a/tests/integration/nano/test_wrong_derivation_path.py b/tests/integration/nano/test_wrong_derivation_path.py index b601cf286..a14cd5e95 100755 --- a/tests/integration/nano/test_wrong_derivation_path.py +++ b/tests/integration/nano/test_wrong_derivation_path.py @@ -13,22 +13,25 @@ # See the License for the specific language governing permissions and # limitations under the License. -from utils.account import Account, SIGNATURE_TYPE -from utils.app import Screen -from utils.backend import INS, StatusCode +"""Check wrong derivation path behaviour""" -def test_wrong_derivation_path(app): +from utils.account import Account, SigType +from utils.app import Screen, TezosAppScreen +from utils.backend import Ins, StatusCode + +def test_wrong_derivation_path(app: TezosAppScreen): + """Check wrong derivation path behaviour""" wrong_number_index_account = Account( bytes.fromhex("058000002c800006c18000000080000000"), - SIGNATURE_TYPE.ED25519, + SigType.ED25519, "__unused__") wrong_length_account = Account( bytes.fromhex("048000002c800006c180000000800000"), - SIGNATURE_TYPE.ED25519, + SigType.ED25519, "__unused__") too_much_index_account = Account( bytes.fromhex("0b8000002c800006c1800000008000000080000000800000008000000080000000800000008000000080000000"), - SIGNATURE_TYPE.ED25519, + SigType.ED25519, "__unused__") for account in [wrong_number_index_account, @@ -36,10 +39,10 @@ def test_wrong_derivation_path(app): too_much_index_account]: for sender in [lambda account: app.backend.get_public_key(account, with_prompt=False), lambda account: app.backend.get_public_key(account, with_prompt=True), - lambda account: app.backend._ask_sign(INS.SIGN, account), - lambda account: app.backend._ask_sign(INS.SIGN_WITH_HASH, account)]: + lambda account: app.backend._ask_sign(Ins.SIGN, account), + lambda account: app.backend._ask_sign(Ins.SIGN_WITH_HASH, account)]: - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) with app.expect_apdu_failure(StatusCode.WRONG_LENGTH_FOR_INS): sender(account) diff --git a/tests/integration/nano/test_wrong_derivation_type.py b/tests/integration/nano/test_wrong_derivation_type.py index d105ca8b1..12b967ab4 100755 --- a/tests/integration/nano/test_wrong_derivation_type.py +++ b/tests/integration/nano/test_wrong_derivation_type.py @@ -13,19 +13,22 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Check wrong derivation type behaviour""" + from utils.account import Account -from utils.app import Screen -from utils.backend import INS, StatusCode +from utils.app import Screen, TezosAppScreen +from utils.backend import Ins, StatusCode -def test_wrong_derivation_type(app): +def test_wrong_derivation_type(app: TezosAppScreen): + """Check wrong derivation type behaviour""" account = Account("m/44'/1729'/0'/0'", 0x04, "__unused__") for sender in [lambda account: app.backend.get_public_key(account, with_prompt=False), lambda account: app.backend.get_public_key(account, with_prompt=True), - lambda account: app.backend._ask_sign(INS.SIGN, account), - lambda account: app.backend._ask_sign(INS.SIGN_WITH_HASH, account)]: + lambda account: app.backend._ask_sign(Ins.SIGN, account), + lambda account: app.backend._ask_sign(Ins.SIGN_WITH_HASH, account)]: - app.assert_screen(Screen.Home) + app.assert_screen(Screen.HOME) with app.expect_apdu_failure(StatusCode.WRONG_PARAM): sender(account) diff --git a/tests/integration/nano/test_wrong_index.py b/tests/integration/nano/test_wrong_index.py index a3b47ede8..d26e0fc72 100755 --- a/tests/integration/nano/test_wrong_index.py +++ b/tests/integration/nano/test_wrong_index.py @@ -13,16 +13,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -from utils.app import DEFAULT_ACCOUNT, Screen -from utils.backend import INDEX, INS, StatusCode +"""Check wrong apdu index behaviour""" -def test_wrong_index(app): - for ins in [INS.GET_PUBLIC_KEY, - INS.PROMPT_PUBLIC_KEY]: - for index in [INDEX.OTHER, - INDEX.LAST]: +from utils.app import Screen, TezosAppScreen, DEFAULT_ACCOUNT +from utils.backend import Index, Ins, StatusCode - app.assert_screen(Screen.Home) +def test_wrong_index(app: TezosAppScreen): + """Check wrong apdu index behaviour""" + for ins in [Ins.GET_PUBLIC_KEY, + Ins.PROMPT_PUBLIC_KEY]: + for index in [Index.OTHER, + Index.LAST]: + + app.assert_screen(Screen.HOME) with app.expect_apdu_failure(StatusCode.WRONG_PARAM): app.backend._exchange(ins, diff --git a/tests/integration/nano/utils/account.py b/tests/integration/nano/utils/account.py index 8d6e1549f..39e3d074e 100644 --- a/tests/integration/nano/utils/account.py +++ b/tests/integration/nano/utils/account.py @@ -12,33 +12,46 @@ # See the License for the specific language governing permissions and # limitations under the License. -import base58 +"""Module providing an account interface.""" + from enum import IntEnum +from typing import Union + +import base58 from pytezos import pytezos from ragger.bip import pack_derivation_path -from typing import Union -class SIGNATURE_TYPE(IntEnum): + +class SigType(IntEnum): + """Class representing signature type.""" + ED25519 = 0x00 SECP256K1 = 0x01 SECP256R1 = 0x02 BIP32_ED25519 = 0x03 class Signature: + """Class representing signature.""" GENERIC_SIGNATURE_PREFIX = bytes.fromhex("04822b") # sig(96) + value: bytes + def __init__(self, value: bytes): value = Signature.GENERIC_SIGNATURE_PREFIX + value - self.value: bytes = base58.b58encode_check(value) + self.value = base58.b58encode_check(value) def __repr__(self) -> str: return self.value.hex() @classmethod - def from_tlv(self, tlv: Union[bytes, bytearray]) -> 'Signature': - if isinstance(tlv, bytes): tlv = bytearray(tlv) - # See: https://developers.ledger.com/docs/embedded-app/crypto-api/lcx__ecdsa_8h/#cx_ecdsa_sign + def from_tlv(cls, tlv: Union[bytes, bytearray]) -> 'Signature': + """Get Signature from tlv.""" + + if isinstance(tlv, bytes): + tlv = bytearray(tlv) + # See: + # https://developers.ledger.com/docs/embedded-app/crypto-api/lcx__ecdsa_8h/#cx_ecdsa_sign # TLV: 30 || L || 02 || Lr || r || 02 || Ls || s header_tag_index = 0 # Remove the unwanted parity information set here. @@ -64,38 +77,45 @@ def from_tlv(self, tlv: Union[bytes, bytearray]) -> 'Signature': s = tlv[s_index : s_index + s_len] # Sometimes \x00 are added or removed # A size adjustment is required here. - def adjust_size(bytes, size): - return bytes[-size:].rjust(size, b'\x00') - return Signature(adjust_size(r, 32) + adjust_size(s, 32)) + def adjust_size(raw, size): + return raw[-size:].rjust(size, b'\x00') + return cls(adjust_size(r, 32) + adjust_size(s, 32)) class Account: + """Class representing account.""" + + path: bytes + sig_type: Union[SigType, int] + public_key: str + def __init__(self, path: Union[str, bytes], - sig_type: SIGNATURE_TYPE, + sig_type: Union[SigType, int], public_key: str): - self.path: bytes = \ + self.path = \ pack_derivation_path(path) if isinstance(path, str) \ else path - self.sig_type: SIGNATURE_TYPE = sig_type - self.public_key: str = public_key + self.sig_type = sig_type + self.public_key = public_key def __repr__(self) -> str: return self.public_key @property def base58_decoded(self) -> bytes: + """Decodes public_key from base58 encoding.""" # Get the public_key without prefix public_key = base58.b58decode_check(self.public_key) if self.sig_type in [ - SIGNATURE_TYPE.ED25519, - SIGNATURE_TYPE.BIP32_ED25519 + SigType.ED25519, + SigType.BIP32_ED25519 ]: prefix = bytes.fromhex("0d0f25d9") # edpk(54) - elif self.sig_type == SIGNATURE_TYPE.SECP256K1: + elif self.sig_type == SigType.SECP256K1: prefix = bytes.fromhex("03fee256") # sppk(55) - elif self.sig_type == SIGNATURE_TYPE.SECP256R1: + elif self.sig_type == SigType.SECP256R1: prefix = bytes.fromhex("03b28b7f") # p2pk(55) else: assert False, \ @@ -106,8 +126,8 @@ def base58_decoded(self) -> bytes: public_key = public_key[len(prefix):] if self.sig_type in [ - SIGNATURE_TYPE.SECP256K1, - SIGNATURE_TYPE.SECP256R1 + SigType.SECP256K1, + SigType.SECP256R1 ]: assert public_key[0] in [0x02, 0x03], \ "Expected a prefix kind of 0x02 or 0x03 but got {public_key[0]}" @@ -116,6 +136,7 @@ def base58_decoded(self) -> bytes: return public_key def check_public_key(self, data: bytes) -> None: + """Checks if the data correspond to the public_key.""" # `data` should be: # length + kind + pk @@ -138,12 +159,15 @@ def check_public_key(self, data: bytes) -> None: def check_signature(self, signature: Union[bytes, Signature], message: Union[str, bytes]): - if isinstance(message, str): message = bytes.fromhex(message) + """Checks if signature correspond to a signature of message sign by the account.""" + + if isinstance(message, str): + message = bytes.fromhex(message) if isinstance(signature, bytes): signature = Signature(signature) \ if self.sig_type in [ - SIGNATURE_TYPE.ED25519, - SIGNATURE_TYPE.BIP32_ED25519 + SigType.ED25519, + SigType.BIP32_ED25519 ] \ else Signature.from_tlv(signature) ctxt = pytezos.using(key=self.public_key) diff --git a/tests/integration/nano/utils/app.py b/tests/integration/nano/utils/app.py index 4f2eda098..d8d8c7e24 100644 --- a/tests/integration/nano/utils/app.py +++ b/tests/integration/nano/utils/app.py @@ -13,39 +13,48 @@ # See the License for the specific language governing permissions and # limitations under the License. -import argparse -import git -import time +"""Tezos app backend.""" + from contextlib import contextmanager from enum import Enum +from io import BytesIO from multiprocessing import Process, Queue from pathlib import Path -from requests.exceptions import ConnectionError +import time +from typing import Callable, Generator, List, Optional, Tuple, Union + +import requests +import git from ragger.backend import SpeculosBackend from ragger.error import ExceptionRAPDU from ragger.navigator import NavInsID, NanoNavigator -from typing import Callable, Generator, List, Optional, Tuple, Union from .message import Message -from .account import Account, SIGNATURE_TYPE -from .backend import StatusCode, TezosBackend, APP_KIND +from .account import Account, SigType +from .backend import StatusCode, TezosBackend, AppKind version: Tuple[int, int, int] = (3, 0, 5) class TezosAPDUChecker: + """Helper to check APDU received.""" - def __init__(self, app_kind: APP_KIND): + app_kind: AppKind + + def __init__(self, app_kind: AppKind): self.app_kind = app_kind @property def commit(self) -> bytes: + """Current commit.""" repo = git.Repo(".") commit = repo.head.commit.hexsha[:8] - if repo.is_dirty(): commit += "*" + if repo.is_dirty(): + commit += "*" return bytes.fromhex(commit.encode('utf-8').hex() + "00") @property def version_bytes(self) -> bytes: + """Current version in bytes.""" return \ self.app_kind.to_bytes(1, byteorder='big') + \ version[0].to_bytes(1, byteorder='big') + \ @@ -53,16 +62,19 @@ def version_bytes(self) -> bytes: version[2].to_bytes(1, byteorder='big') def check_commit(self, commit: bytes) -> None: + """Check if the commit is the current commit.""" assert commit == self.commit, \ f"Expected commit {self.commit.hex()} but got {commit.hex()}" - def check_version(self, version: bytes) -> None: - assert version == self.version_bytes, \ - f"Expected version {self.version_bytes.hex()} but got {version.hex()}" + def check_version(self, raw_version: bytes) -> None: + """Check if the version is the current version.""" + assert raw_version == self.version_bytes, \ + f"Expected version {self.version_bytes.hex()} but got {raw_version.hex()}" def check_public_key(self, account: Account, public_key: bytes) -> None: + """Check that public_key is the account public key.""" account.check_public_key(public_key) def check_signature(self, @@ -70,17 +82,19 @@ def check_signature(self, message: Message, with_hash: bool, data: bytes) -> None: + """Check that data is a signature of message from account.""" if with_hash: assert data.startswith(message.hash), \ f"Expected a starting hash {message.hash.hex()} but got {data.hex()}" data = data[len(message.hash):] - account.check_signature(data, message.bytes) + account.check_signature(data, bytes(message)) MAX_ATTEMPTS = 50 def with_retry(f, attempts=MAX_ATTEMPTS): + """Try f until it succeeds or has been executed attempts times.""" while True: try: return f() @@ -93,6 +107,7 @@ def with_retry(f, attempts=MAX_ATTEMPTS): time.sleep(0.5) def run_simultaneously(processes: List[Process]) -> None: + """Executes multiples process at the same time.""" for process in processes: process.start() @@ -102,6 +117,7 @@ def run_simultaneously(processes: List[Process]) -> None: assert process.exitcode == 0, "Should have terminate successfully" def send_and_navigate(send: Callable[[], bytes], navigate: Callable[[], None]) -> bytes: + """Sends APDU and navigates.""" def _send(result_queue: Queue) -> None: res = send() @@ -114,6 +130,7 @@ def _send(result_queue: Queue) -> None: return result_queue.get() class SpeculosTezosBackend(TezosBackend, SpeculosBackend): + """Class representing Tezos app running on Speculos.""" # speculos can be slow to start up in a slow environment. # Here, we expect a little more @@ -121,7 +138,7 @@ def __enter__(self) -> "SpeculosTezosBackend": try: super().__enter__() return self - except Exception as e: + except Exception: process = self._client.process try: with_retry(self._client._wait_until_ready, attempts=5) @@ -139,50 +156,69 @@ def __enter__(self) -> "SpeculosTezosBackend": return self class Screen(str, Enum): - Home = "home" - Version = "version" - Settings = "settings" - Settings_expert_mode_disabled = "settings_expert_mode_disabled" - Settings_expert_mode_enabled = "settings_expert_mode_enabled" - Settings_blindsign_on = "settings_blindsign_on" - Settings_blindsign_off = "settings_blindsign_off" - Settings_back = "back" - Quit = "quit" - -class Screen_text(str, Enum): - Home = "Application" - Public_key_approve = "Approve" - Public_key_reject = "Reject" - Sign_accept = "Accept" - Sign_reject = "Reject" - Accept_risk = "Accept risk" - Back_home = "Home" - Blindsign = "blindsign" - Blindsign_nanos = "Blindsign" - - def blindsign(backend: SpeculosTezosBackend) -> "Screen_text": + """Class representing common, known app screens.""" + + HOME = "home" + VERSION = "version" + SETTINGS = "settings" + SETTINGS_EXPERT_MODE_DISABLED = "settings_expert_mode_disabled" + SETTINGS_EXPERT_MODE_ENABLED = "settings_expert_mode_enabled" + SETTINGS_BLINDSIGN_ON = "settings_blindsign_on" + SETTINGS_BLINDSIGN_OFF = "settings_blindsign_off" + SETTINGS_BACK = "back" + QUIT = "quit" + + def __str__(self) -> str: + return self.value + +class ScreenText(str, Enum): + """Class representing common, known app screen's text.""" + + HOME = "Application" + PUBLIC_KEY_APPROVE = "Approve" + PUBLIC_KEY_REJECT = "Reject" + SIGN_ACCEPT = "Accept" + SIGN_REJECT = "Reject" + ACCEPT_RISK = "Accept risk" + BACK_HOME = "Home" + BLINDSIGN = "blindsign" + BLINDSIGN_NANOS = "Blindsign" + + @classmethod + def blindsign(cls, backend: SpeculosTezosBackend) -> "ScreenText": + """Get blindsign text depending on device.""" if backend.firmware.device == "nanos": - return Screen_text.Blindsign_nanos - else: - return Screen_text.Blindsign + return cls.BLINDSIGN_NANOS + + return cls.BLINDSIGN class TezosAppScreen(): + """Class representing Tezos app management.""" + + backend: SpeculosTezosBackend + checker: TezosAPDUChecker + path: Path + snapshots_dir: Path + tmp_snapshots_dir: Path + snapshotted: List[str] + golden_run: bool + navigator: NanoNavigator def __init__(self, backend: SpeculosTezosBackend, - app_kind: APP_KIND, + app_kind: AppKind, golden_run: bool): self.backend = backend self.checker = TezosAPDUChecker(app_kind) - self.path: Path = Path(__file__).resolve().parent.parent - self.snapshots_dir: Path = self.path / "snapshots" / backend.firmware.name - self.tmp_snapshots_dir: Path = self.path / "snapshots-tmp" / backend.firmware.name + self.path = Path(__file__).resolve().parent.parent + self.snapshots_dir = self.path / "snapshots" / backend.firmware.name + self.tmp_snapshots_dir = self.path / "snapshots-tmp" / backend.firmware.name if not self.snapshots_dir.is_dir() and golden_run: self.snapshots_dir.mkdir(parents=True) if not self.tmp_snapshots_dir.is_dir(): self.tmp_snapshots_dir.mkdir(parents=True) - self.snapshotted: List[str] = [] + self.snapshotted = [] self.golden_run = golden_run self.navigator = NanoNavigator(backend, backend.firmware, golden_run) @@ -194,14 +230,19 @@ def __enter__(self) -> "TezosAppScreen": def __exit__(self, *args): self.backend.__exit__(*args) - def assert_screen(self, screen: Union[str, Screen], path: Optional[Union[str, Path]] = None) -> None: + def assert_screen(self, + screen: Union[str, Screen], + path: Optional[Union[str, Path]] = None) -> None: + """Check if the screen is the one expected.""" golden_run = self.golden_run and screen not in self.snapshotted if golden_run: self.snapshotted = self.snapshotted + [screen] input(f"Press ENTER to snapshot {screen}") - snapshots_dir = self.snapshots_dir if path is None else self.snapshots_dir / path - tmp_snapshots_dir = self.tmp_snapshots_dir if path is None else self.tmp_snapshots_dir / path + snapshots_dir = self.snapshots_dir if path is None \ + else self.snapshots_dir / path + tmp_snapshots_dir = self.tmp_snapshots_dir if path is None \ + else self.tmp_snapshots_dir / path if not snapshots_dir.is_dir() and golden_run: snapshots_dir.mkdir(parents=True) @@ -218,59 +259,65 @@ def check(): golden_run=golden_run) with_retry(check) - self.backend._last_screenshot = path + self.backend._last_screenshot = BytesIO(self.backend._client.get_screenshot()) def setup_expert_mode(self) -> None: - self.assert_screen(Screen.Home) + """Enable expert-mode from home screen.""" + self.assert_screen(Screen.HOME) self.backend.right_click() - self.assert_screen(Screen.Version) + self.assert_screen(Screen.VERSION) self.backend.right_click() - self.assert_screen(Screen.Settings) + self.assert_screen(Screen.SETTINGS) self.backend.both_click() - self.assert_screen(Screen.Settings_expert_mode_disabled) + self.assert_screen(Screen.SETTINGS_EXPERT_MODE_DISABLED) self.backend.both_click() - self.assert_screen(Screen.Settings_expert_mode_enabled) + self.assert_screen(Screen.SETTINGS_EXPERT_MODE_ENABLED) self.backend.left_click() - self.assert_screen(Screen.Settings_back) + self.assert_screen(Screen.SETTINGS_BACK) self.backend.both_click() - self.assert_screen(Screen.Home) + self.assert_screen(Screen.HOME) def setup_blindsign_on(self) -> None: - self.assert_screen(Screen.Home) + """Enable blindsign from home screen.""" + self.assert_screen(Screen.HOME) self.backend.right_click() - self.assert_screen(Screen.Version) + self.assert_screen(Screen.VERSION) self.backend.right_click() - self.assert_screen(Screen.Settings) + self.assert_screen(Screen.SETTINGS) self.backend.both_click() # expert_mode screen self.backend.right_click() - self.assert_screen(Screen.Settings_blindsign_off) + self.assert_screen(Screen.SETTINGS_BLINDSIGN_OFF) self.backend.both_click() - self.assert_screen(Screen.Settings_blindsign_on) + self.assert_screen(Screen.SETTINGS_BLINDSIGN_ON) self.backend.right_click() - self.assert_screen(Screen.Settings_back) + self.assert_screen(Screen.SETTINGS_BACK) self.backend.both_click() - self.assert_screen(Screen.Home) + self.assert_screen(Screen.HOME) def _quit(self) -> None: - self.assert_screen(Screen.Quit) + """Ensure quiting exit the app.""" + self.assert_screen(Screen.QUIT) try: self.backend.both_click() assert False, "Must have lost connection with speculos" - except ConnectionError: + except requests.exceptions.ConnectionError: pass def quit(self) -> None: - self.assert_screen(Screen.Home) + """Quit the app from home screen.""" + self.assert_screen(Screen.HOME) self.backend.right_click() - self.assert_screen(Screen.Version) + self.assert_screen(Screen.VERSION) self.backend.right_click() - self.assert_screen(Screen.Settings) + self.assert_screen(Screen.SETTINGS) self.backend.right_click() self._quit() - def navigate_until_text(self, text: Screen_text, path: Union[str, Path]) -> None: - if isinstance(path, str): path = Path(path) + def navigate_until_text(self, text: ScreenText, path: Union[str, Path]) -> None: + """Click right until the expected text is displayed, then both click.""" + if isinstance(path, str): + path = Path(path) self.navigator.\ navigate_until_text_and_compare(NavInsID.RIGHT_CLICK, [NavInsID.BOTH_CLICK], @@ -281,6 +328,7 @@ def navigate_until_text(self, text: Screen_text, path: Union[str, Path]) -> None @contextmanager def expect_apdu_failure(self, code: StatusCode) -> Generator[None, None, None]: + """Expect the body to fail with code.""" try: yield assert False, f"Expect fail with { code } but succeed" @@ -293,6 +341,7 @@ def _failing_send(self, send: Callable[[], bytes], navigate: Callable[[], None], status_code: StatusCode) -> None: + """Expect that send and navigates fails with status_code.""" def expected_failure_send() -> bytes: with self.expect_apdu_failure(status_code): send() @@ -305,19 +354,19 @@ def expected_failure_send() -> bytes: def provide_public_key(self, account: Account, path: Union[str, Path]) -> bytes: - + """Get the account's public key from the app after approving it.""" return send_and_navigate( - send=(lambda: self.backend.get_public_key(account, with_prompt=True)), - navigate=(lambda: self.navigate_until_text(Screen_text.Public_key_approve, path))) + send=lambda: self.backend.get_public_key(account, with_prompt=True), + navigate=lambda: self.navigate_until_text(ScreenText.PUBLIC_KEY_APPROVE, path)) def reject_public_key(self, account: Account, path: Union[str, Path]) -> None: - + """Reject the account's public key.""" self._failing_send( send=(lambda: self.backend.get_public_key(account, with_prompt=True)), navigate=(lambda: self.navigate_until_text( - Screen_text.Public_key_reject, + ScreenText.PUBLIC_KEY_REJECT, path)), status_code=StatusCode.REJECT) @@ -326,7 +375,7 @@ def _sign(self, message: Message, with_hash: bool, navigate: Callable[[], None]) -> bytes: - + """Requests to sign the message with account and navigates.""" return send_and_navigate( send=(lambda: self.backend.sign(account, message, with_hash)), navigate=navigate) @@ -336,24 +385,25 @@ def sign(self, message: Message, with_hash: bool, path: Union[str, Path]) -> bytes: - + """Sign the message with account.""" return self._sign( account, message, with_hash, - navigate=(lambda: self.navigate_until_text(Screen_text.Sign_accept, path))) + navigate=lambda: self.navigate_until_text(ScreenText.SIGN_ACCEPT, path)) def blind_sign(self, account: Account, message: Message, with_hash: bool, path: Union[str, Path]) -> bytes: - - if isinstance(path, str): path = Path(path) + """Blindsign the message with account.""" + if isinstance(path, str): + path = Path(path) def navigate() -> None: - self.navigate_until_text(Screen_text.Accept_risk, path / "clear") - self.navigate_until_text(Screen_text.Sign_accept, path / "blind") + self.navigate_until_text(ScreenText.ACCEPT_RISK, path / "clear") + self.navigate_until_text(ScreenText.SIGN_ACCEPT, path / "blind") return send_and_navigate( send=(lambda: self.backend.sign(account, message, with_hash)), @@ -365,7 +415,7 @@ def _failing_signing(self, with_hash: bool, navigate: Callable[[], None], status_code: StatusCode) -> None: - + """Expect requests signing and navigate fails with status_code.""" self._failing_send( send=(lambda: self.backend.sign(account, message, with_hash)), navigate=navigate, @@ -376,12 +426,13 @@ def reject_signing(self, message: Message, with_hash: bool, path: Union[str, Path]) -> None: + """Request and reject signing the message.""" self._failing_signing( account, message, with_hash, navigate=(lambda: self.navigate_until_text( - Screen_text.Sign_reject, + ScreenText.SIGN_REJECT, path)), status_code=StatusCode.REJECT) @@ -391,11 +442,12 @@ def hard_failing_signing(self, with_hash: bool, status_code: StatusCode, path: Union[str, Path]) -> None: + """Expect the signing request to hard fail.""" self._failing_signing(account, message, with_hash, navigate=(lambda: self.navigate_until_text( - Screen_text.Home, + ScreenText.HOME, path)), status_code=status_code) @@ -404,16 +456,17 @@ def parsing_error_signing(self, message: Message, with_hash: bool, path: Union[str, Path]) -> None: + """Expect the signing request to fail with parsing error.""" self._failing_signing(account, message, with_hash, navigate=(lambda: self.navigate_until_text( - Screen_text.Sign_reject, + ScreenText.SIGN_REJECT, path)), status_code=StatusCode.PARSE_ERROR) -DEFAULT_SEED = ('zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra') +DEFAULT_SEED = 'zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra zebra' DEFAULT_ACCOUNT = Account("m/44'/1729'/0'/0'", - SIGNATURE_TYPE.ED25519, + SigType.ED25519, "edpkuXX2VdkdXzkN11oLCb8Aurdo1BTAtQiK8ZY9UPj2YMt3AHEpcY") diff --git a/tests/integration/nano/utils/backend.py b/tests/integration/nano/utils/backend.py index 7746b9dcc..c76cd0cea 100644 --- a/tests/integration/nano/utils/backend.py +++ b/tests/integration/nano/utils/backend.py @@ -12,18 +12,25 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Tezos app backend.""" + from enum import IntEnum +from typing import Union + from ragger.backend.interface import BackendInterface, RAPDU from ragger.error import ExceptionRAPDU -from typing import Union -from .account import Account, SIGNATURE_TYPE +from .account import Account, SigType from .message import Message -class CLA(IntEnum): +class Cla(IntEnum): + """Class representing APDU class.""" + DEFAULT = 0x80 -class INS(IntEnum): +class Ins(IntEnum): + """Class representing instruction.""" + VERSION = 0x00 AUTHORIZE_BAKING = 0x01 GET_PUBLIC_KEY = 0x02 @@ -41,13 +48,17 @@ class INS(IntEnum): HMAC = 0x0e SIGN_WITH_HASH = 0x0f -class INDEX(IntEnum): +class Index(IntEnum): + """Class representing packet index.""" + FIRST = 0x00 OTHER = 0x01 LAST = 0x80 OTHER_LAST = 0x81 class StatusCode(IntEnum): + """Class representing the status code.""" + SECURITY = 0x6982 HID_REQUIRED = 0x6983 REJECT = 0x6985 @@ -66,26 +77,30 @@ class StatusCode(IntEnum): MEMORY_ERROR = 0x9200 PARSE_ERROR = 0x9405 -class APP_KIND(IntEnum): +class AppKind(IntEnum): + """Class representing the kind of app.""" + WALLET = 0x00 BAKING = 0x01 MAX_APDU_SIZE: int = 235 class TezosBackend(BackendInterface): + """Class representing the backen of the tezos app.""" def _exchange(self, - ins: INS, - index: INDEX = INDEX.FIRST, - sig_type: Union[SIGNATURE_TYPE, None] = None, + ins: Union[Ins, int], + index: Union[Index, int] = Index.FIRST, + sig_type: Union[SigType, int, None] = None, payload: bytes = b'') -> bytes: + """Override of `exchange` for the tezos app.""" - assert len(payload) <= MAX_APDU_SIZE, f"Apdu too large" + assert len(payload) <= MAX_APDU_SIZE, f"Apdu too large {len(payload)}" # Set to a non-existent value to ensure that p2 is unused p2: int = sig_type if sig_type is not None else 0xff - rapdu: RAPDU = self.exchange(CLA.DEFAULT, + rapdu: RAPDU = self.exchange(Cla.DEFAULT, ins, p1=index, p2=p2, @@ -97,28 +112,36 @@ def _exchange(self, return rapdu.data def git(self) -> bytes: - return self._exchange(INS.GIT) + """Requests the app commit.""" + return self._exchange(Ins.GIT) def version(self) -> bytes: - return self._exchange(INS.VERSION) + """Requests the app version.""" + return self._exchange(Ins.VERSION) def get_public_key(self, account: Account, with_prompt: bool = False) -> bytes: - - ins = INS.PROMPT_PUBLIC_KEY if with_prompt else INS.GET_PUBLIC_KEY - + """Requests the public key according to the account. + Use `with_prompt` ask user confirmation + """ + ins = Ins.PROMPT_PUBLIC_KEY if with_prompt else Ins.GET_PUBLIC_KEY return self._exchange(ins, sig_type=account.sig_type, payload=account.path) - def _ask_sign(self, ins: INS, account: Account) -> None: + def _ask_sign(self, ins: Ins, account: Account) -> None: + """Prepare to sign with the account.""" data: bytes = self._exchange(ins, sig_type=account.sig_type, payload=account.path) - assert not data - - def _continue_sign(self, ins: INS, payload: bytes, last: bool) -> bytes: - index: INDEX = INDEX.OTHER - if last: index = INDEX(index | INDEX.LAST) + assert not data, f"No data expected but got {data.hex()}" + + def _continue_sign(self, ins: Ins, payload: bytes, last: bool) -> bytes: + """Sends payload to sign. + Use `last` when sending the last packet + """ + index: Index = Index.OTHER + if last: + index = Index(index | Index.LAST) return self._exchange(ins, index, payload=payload) def sign(self, @@ -126,21 +149,21 @@ def sign(self, message: Message, with_hash: bool = False, apdu_size: int = MAX_APDU_SIZE) -> bytes: - msg = message.bytes + """Requests the signature of a message.""" + msg = bytes(message) assert msg, "Do not sign empty message" - ins = INS.SIGN_WITH_HASH if with_hash else INS.SIGN + ins = Ins.SIGN_WITH_HASH if with_hash else Ins.SIGN self._ask_sign(ins, account) - while(msg): + while msg: payload = msg[:apdu_size] msg = msg[apdu_size:] last = not msg data = self._continue_sign(ins, payload, last) if last: return data - else: - assert not data + assert not data, f"No data expected but got {data.hex()}" assert False, "We should have already returned" diff --git a/tests/integration/nano/utils/message.py b/tests/integration/nano/utils/message.py index 0062cc168..488803024 100644 --- a/tests/integration/nano/utils/message.py +++ b/tests/integration/nano/utils/message.py @@ -12,28 +12,37 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Implemenation of sent messages.""" + from hashlib import blake2b from typing import Union class Message: + """Class representing messages.""" HASH_SIZE = 32 + value: bytes + def __init__(self, value: bytes): - self.value: bytes = value + self.value = value @classmethod - def from_bytes(self, value: Union[str, bytes]) -> 'Message': - if isinstance(value, str): value = bytes.fromhex(value) - return Message(value) + def from_bytes(cls, value: Union[str, bytes]) -> 'Message': + """Get message from bytes or hex.""" + + if isinstance(value, str): + value = bytes.fromhex(value) + return cls(value) @property def hash(self) -> bytes: + """Hash of the message.""" + return blake2b( self.value, digest_size=Message.HASH_SIZE ).digest() - @property - def bytes(self) -> bytes: + def __bytes__(self) -> bytes: return self.value diff --git a/tests/integration/run_test_docker.sh b/tests/integration/run_test_docker.sh index cdb41f286..3a8ed0e52 100755 --- a/tests/integration/run_test_docker.sh +++ b/tests/integration/run_test_docker.sh @@ -33,5 +33,6 @@ docker run --rm -it -v "$(realpath .):/app" \ -c " apk add gmp-dev curl jq libsodium-dev git xxd procps; \ python3 -m venv tezos_test_env --system-site-package; \ source ./tezos_test_env/bin/activate; \ + python3 -m pip install --upgrade pip -q; \ python3 -m pip install -r tests/requirements.txt -q; \ ./tests/integration/run_test_local.sh -F -m $*" diff --git a/tests/requirements.txt b/tests/requirements.txt index 419eeb132..751725d2e 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -3,6 +3,7 @@ setuptools pkginfo cryptography base58 -pytezos +pytezos==3.13.4 GitPython pytest-xdist +ragger[tests,speculos,ledgerwallet]