chore(tests): adapt device tests to paging information ButtonRequests

pull/1538/head
matejcik 3 years ago committed by matejcik
parent d047c98cb2
commit 7cdde940af

@ -14,7 +14,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/44'/1815'/0'/0/1",
@ -44,7 +43,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/44'/1815'/0'/0/1",
@ -79,7 +77,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -115,7 +112,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/44'/1815'/0'/0/1",
@ -160,7 +156,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -197,7 +192,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -234,7 +228,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -270,7 +263,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -306,7 +298,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -344,7 +335,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -384,7 +374,6 @@
],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -419,7 +408,6 @@
],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -455,7 +443,6 @@
],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -487,7 +474,6 @@
],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -527,7 +513,6 @@
}
],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -563,7 +548,6 @@
],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -595,7 +579,6 @@
"auxiliary_data": {
"blob": "a200a11864a118c843aa00ff01a119012c590100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -636,7 +619,6 @@
"nonce": 22634813
}
},
"input_flow": [["SWIPE", "SWIPE", "YES"], ["SWIPE", "SWIPE", "SWIPE", "SWIPE", "SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -666,7 +648,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/44'/1815'/0'/0/1",
@ -706,7 +687,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["YES"], ["SWIPE", "YES"], ["SWIPE", "SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -754,7 +734,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -813,7 +792,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -844,7 +822,6 @@
"certificates": [],
"withdrawals": [],
"auxiliary_data": null,
"input_flow": [["YES"], ["YES"]],
"inputs": [
{
"path": "m/44'/1815'/0'/0/0",

@ -20,7 +20,7 @@ from pathlib import Path
import pytest
from trezorlib import btc, tools
from trezorlib.messages import ButtonRequestType as B
from trezorlib.messages import ButtonRequest, ButtonRequestType as B
# fmt: off
# 1 2 3 4 5 6 7 8 9 10 11 12
@ -130,16 +130,16 @@ def recovery_enter_shares(debug, shares, groups=False):
yield
debug.press_yes()
# Input word number
code = yield
assert code == B.MnemonicWordCount
br = yield
assert br.code == B.MnemonicWordCount
debug.input(str(word_count))
# Homescreen - proceed to share entry
yield
debug.press_yes()
# Enter shares
for index, share in enumerate(shares):
code = yield
assert code == B.MnemonicInput
br = yield
assert br.code == B.MnemonicInput
# Enter mnemonic words
for word in share.split(" "):
debug.input(word)
@ -171,11 +171,11 @@ def click_through(debug, screens, code=None):
for _ in range(screens):
received = yield
if code is not None:
assert received == code
assert received.code == code
debug.press_yes()
def read_and_confirm_mnemonic(debug, words, choose_wrong=False):
def read_and_confirm_mnemonic(debug, choose_wrong=False):
"""Read a given number of mnemonic words from Trezor T screen and correctly
answer confirmation questions. Return the full mnemonic.
@ -185,13 +185,13 @@ def read_and_confirm_mnemonic(debug, words, choose_wrong=False):
def input_flow():
yield from click_through(client.debug, screens=3)
yield # confirm mnemonic entry
mnemonic = read_and_confirm_mnemonic(client.debug, words=20)
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
"""
mnemonic = []
while True:
br = yield
mnemonic.extend(debug.read_reset_word().split())
if len(mnemonic) < words:
if br.page_number < br.pages:
debug.swipe_up()
else:
# last page is confirmation
@ -210,6 +210,15 @@ def read_and_confirm_mnemonic(debug, words, choose_wrong=False):
return " ".join(mnemonic)
def paging_responses(pages, code=None):
"""Generate a sequence of ButtonRequests for paging through a specified number
of screens.
"""
return [
ButtonRequest(code=code, page_number=i + 1, pages=pages) for i in range(pages)
]
def get_test_address(client):
"""Fetch a testnet address on a fixed path. Useful to make a pin/passphrase
protected call, or to identify the root secret (seed+passphrase)"""

@ -40,8 +40,6 @@ def test_cardano_sign_tx(client, parameters, result):
withdrawals = [cardano.parse_withdrawal(w) for w in parameters["withdrawals"]]
auxiliary_data = cardano.parse_auxiliary_data(parameters["auxiliary_data"])
input_flow = parameters.get("input_flow", ())
if parameters.get("security_checks") == "prompt":
device.apply_settings(
client, safety_checks=messages.SafetyCheckLevel.PromptTemporarily
@ -50,8 +48,6 @@ def test_cardano_sign_tx(client, parameters, result):
device.apply_settings(client, safety_checks=messages.SafetyCheckLevel.Strict)
with client:
client.set_input_flow(_to_device_actions(client, input_flow))
response = cardano.sign_tx(
client=client,
inputs=inputs,
@ -79,11 +75,7 @@ def test_cardano_sign_tx_failed(client, parameters, result):
withdrawals = [cardano.parse_withdrawal(w) for w in parameters["withdrawals"]]
auxiliary_data = cardano.parse_auxiliary_data(parameters["auxiliary_data"])
input_flow = parameters.get("input_flow", ())
with client:
client.set_input_flow(_to_device_actions(client, input_flow))
with pytest.raises(TrezorFailure, match=result["error_message"]):
cardano.sign_tx(
client=client,
@ -108,12 +100,16 @@ def test_cardano_sign_tx_with_multiple_chunks(client, parameters, result):
withdrawals = [cardano.parse_withdrawal(w) for w in parameters["withdrawals"]]
auxiliary_data = cardano.parse_auxiliary_data(parameters["auxiliary_data"])
input_flow = parameters.get("input_flow", ())
expected_responses = [
messages.PassphraseRequest(),
messages.ButtonRequest(),
messages.ButtonRequest(),
# XXX as many ButtonRequests as paginations. We are relying on the fact that
# there is only one fixture whose pagination is known.
# If that changes, we'll need to figure out something else.
messages.ButtonRequest(page_number=1),
messages.ButtonRequest(page_number=2),
messages.ButtonRequest(page_number=3),
messages.ButtonRequest(page_number=1),
messages.ButtonRequest(page_number=2),
]
expected_responses += [
messages.CardanoSignedTxChunk(signed_tx_chunk=bytes.fromhex(signed_tx_chunk))
@ -124,9 +120,7 @@ def test_cardano_sign_tx_with_multiple_chunks(client, parameters, result):
]
with client:
client.set_input_flow(_to_device_actions(client, input_flow))
client.set_expected_responses(expected_responses)
response = cardano.sign_tx(
client=client,
inputs=inputs,
@ -142,18 +136,3 @@ def test_cardano_sign_tx_with_multiple_chunks(client, parameters, result):
)
assert response.tx_hash.hex() == result["tx_hash"]
assert response.serialized_tx.hex() == result["serialized_tx"]
def _to_device_actions(client, input_flow):
if not input_flow:
yield
for sequence in input_flow:
yield
for action in sequence:
if action == "SWIPE":
client.debug.swipe_up()
elif action == "YES":
client.debug.press_yes()
else:
raise ValueError("Invalid input action")

@ -27,6 +27,7 @@ from ..common import (
MNEMONIC_SLIP39_ADVANCED_20,
MNEMONIC_SLIP39_BASIC_20_3of6,
click_through,
paging_responses,
read_and_confirm_mnemonic,
)
@ -36,13 +37,15 @@ from ..common import (
def test_backup_bip39(client):
assert client.features.needs_backup is True
mnemonic = None
words = 12
mnemonic_pages = ((words + 3) // 4) + 1
def input_flow():
nonlocal mnemonic
yield # Confirm Backup
client.debug.press_yes()
yield # Mnemonic phrases
mnemonic = read_and_confirm_mnemonic(client.debug, words=12)
# Mnemonic phrases
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
yield # Confirm success
client.debug.press_yes()
yield # Backup is done
@ -53,7 +56,9 @@ def test_backup_bip39(client):
client.set_expected_responses(
[
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
]
+ paging_responses(mnemonic_pages, code=B.ResetDevice)
+ [
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.Success),
messages.Success,
@ -76,6 +81,8 @@ def test_backup_bip39(client):
def test_backup_slip39_basic(client):
assert client.features.needs_backup is True
mnemonics = []
words = 20
mnemonic_pages = ((words + 3) // 4) + 1
def input_flow():
# 1. Checklist
@ -88,8 +95,8 @@ def test_backup_slip39_basic(client):
# Mnemonic phrases
for _ in range(5):
yield # Phrase screen
mnemonic = read_and_confirm_mnemonic(client.debug, words=20)
# Phrase screen
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
mnemonics.append(mnemonic)
yield # Confirm continue to next
client.debug.press_yes()
@ -101,23 +108,13 @@ def test_backup_slip39_basic(client):
with client:
client.set_input_flow(input_flow)
client.set_expected_responses(
[
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
[messages.ButtonRequest(code=B.ResetDevice)] * 6 # intro screens
+ [
*paging_responses(mnemonic_pages, code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
]
* 5 # individual shares
+ [
messages.ButtonRequest(code=B.Success),
messages.Success,
messages.Features,
@ -142,6 +139,8 @@ def test_backup_slip39_basic(client):
def test_backup_slip39_advanced(client):
assert client.features.needs_backup is True
mnemonics = []
words = 20
mnemonic_pages = ((words + 3) // 4) + 1
def input_flow():
# 1. Checklist
@ -158,8 +157,8 @@ def test_backup_slip39_advanced(client):
# Mnemonic phrases
for _ in range(5):
for _ in range(5):
yield # Phrase screen
mnemonic = read_and_confirm_mnemonic(client.debug, words=20)
# Phrase screen
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
mnemonics.append(mnemonic)
yield # Confirm continue to next
client.debug.press_yes()
@ -171,73 +170,18 @@ def test_backup_slip39_advanced(client):
with client:
client.set_input_flow(input_flow)
client.set_expected_responses(
[
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice), # group #1 counts
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice), # group #2 counts
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice), # group #3 counts
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice), # group #4 counts
[messages.ButtonRequest(code=B.ResetDevice)] * 6 # intro screens
+ [
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice), # group #5 counts
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice), # show seeds
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
]
* 5 # group thresholds
+ [
*paging_responses(mnemonic_pages, code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success), # show seeds ends here
]
* 25 # individual shares
+ [
messages.ButtonRequest(code=B.Success),
messages.Success,
messages.Features,

@ -31,20 +31,6 @@ ADDRESS_N = parse_path("m/44'/194'/0'/0/0")
@pytest.mark.skip_t1
@pytest.mark.setup_client(mnemonic=MNEMONIC12)
class TestMsgEosSignTx:
@pytest.mark.setup_client(uninitialized=True)
def input_flow(self, debug, pages):
# confirm number of actions
yield
debug.press_yes()
# swipe through pages
yield
for _ in range(pages - 1):
debug.swipe_up()
# confirm last page
debug.press_yes()
def test_eos_signtx_transfer_token(self, client):
transaction = {
"expiration": "2018-07-14T10:43:28",
@ -73,7 +59,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=3))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -108,7 +93,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=2))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -143,7 +127,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=2))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -174,7 +157,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=2))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -211,7 +193,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=3))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -247,7 +228,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=2))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -278,7 +258,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=0))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -314,7 +293,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=2))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -349,7 +327,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=2))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -407,7 +384,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=8))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -438,7 +414,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=0))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -503,7 +478,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=6))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -534,7 +508,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=0))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -565,7 +538,6 @@ class TestMsgEosSignTx:
}
with client:
client.set_input_flow(self.input_flow(client.debug, pages=2))
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -646,36 +618,7 @@ class TestMsgEosSignTx:
"transaction_extensions": [],
}
def input_flow():
# confirm number of actions
yield
client.debug.press_yes()
# swipe through new account
yield
for _ in range(5):
client.debug.swipe_up()
# confirm new account
client.debug.press_yes()
# swipe through buyrambytes
yield
client.debug.swipe_up()
# confirm buyrambytes
client.debug.press_yes()
# swipe through delegatebw
yield
for _ in range(2):
client.debug.swipe_up()
# confirm delegatebw
client.debug.press_yes()
with client:
client.set_input_flow(input_flow)
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (
@ -714,27 +657,7 @@ class TestMsgEosSignTx:
"context_free_data": [],
}
def input_flow():
# confirm number of actions
yield
client.debug.press_yes()
# swipe through setcode
yield
client.debug.swipe_up()
# confirm setcode
client.debug.press_yes()
# swipe through setabi
yield
client.debug.swipe_up()
# confirm setabi
client.debug.press_yes()
with client:
client.set_input_flow(input_flow)
resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID)
assert isinstance(resp, EosSignedTx)
assert (

@ -177,7 +177,7 @@ def test_show_multisig_xpubs(
def input_flow():
yield # show address
lines = client.debug.wait_layout().lines
lines = client.debug.wait_layout().lines # TODO: do not need to *wait* now?
assert lines[0] == "Multisig 2 of 3"
assert "".join(lines[1:]) == address
@ -190,6 +190,7 @@ def test_show_multisig_xpubs(
lines1 = client.debug.wait_layout().lines
assert lines1[0] == "XPUB #1 " + ("(yours)" if i == 0 else "(cosigner)")
client.debug.swipe_up()
yield
lines2 = client.debug.wait_layout().lines
assert lines2[0] == "XPUB #1 " + ("(yours)" if i == 0 else "(cosigner)")
assert "".join(lines1[1:] + lines2[1:]) == xpubs[0]
@ -199,6 +200,7 @@ def test_show_multisig_xpubs(
lines1 = client.debug.wait_layout().lines
assert lines1[0] == "XPUB #2 " + ("(yours)" if i == 1 else "(cosigner)")
client.debug.swipe_up()
yield
lines2 = client.debug.wait_layout().lines
assert lines2[0] == "XPUB #2 " + ("(yours)" if i == 1 else "(cosigner)")
assert "".join(lines1[1:] + lines2[1:]) == xpubs[1]
@ -208,6 +210,7 @@ def test_show_multisig_xpubs(
lines1 = client.debug.wait_layout().lines
assert lines1[0] == "XPUB #3 " + ("(yours)" if i == 2 else "(cosigner)")
client.debug.swipe_up()
yield
lines2 = client.debug.wait_layout().lines
assert lines2[0] == "XPUB #3 " + ("(yours)" if i == 2 else "(cosigner)")
assert "".join(lines1[1:] + lines2[1:]) == xpubs[2]

@ -16,48 +16,27 @@
import pytest
from trezorlib import lisk, messages as proto
from trezorlib import lisk
VECTORS = ( # pubkey, signature, message
(
"eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294",
"7858ae7cd52ea6d4b17e800ca60144423db5560bfd618b663ffbf26ab66758563df45cbffae8463db22dc285dd94309083b8c807776085b97d05374d79867d05",
"This is an example of a signed message.",
),
(
"8bca6b65a1a877767b746ea0b3c4310d404aa113df99c1b554e1802d70185ab5",
"458ca5896d0934866992268f7509b5e954d568b1251e20c19bd3149ee3c86ffb5a44d1c2a0abbb99a3ab4767272dbb0e419b4579e890a24919ebbbe6cc0f970f",
"VeryLongMessage!" * 64,
),
)
@pytest.mark.altcoin
@pytest.mark.lisk
class TestMsgLiskVerifymessage:
def test_verify(self, client):
with client:
client.set_expected_responses(
[
proto.ButtonRequest(code=proto.ButtonRequestType.Other),
proto.ButtonRequest(code=proto.ButtonRequestType.Other),
proto.Success(message="Message verified"),
]
)
lisk.verify_message(
client,
bytes.fromhex(
"eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294"
),
bytes.fromhex(
"7858ae7cd52ea6d4b17e800ca60144423db5560bfd618b663ffbf26ab66758563df45cbffae8463db22dc285dd94309083b8c807776085b97d05374d79867d05"
),
"This is an example of a signed message.",
)
def test_verify_long(self, client):
with client:
client.set_expected_responses(
[
proto.ButtonRequest(code=proto.ButtonRequestType.Other),
proto.ButtonRequest(code=proto.ButtonRequestType.Other),
proto.Success(message="Message verified"),
]
)
lisk.verify_message(
client,
bytes.fromhex(
"8bca6b65a1a877767b746ea0b3c4310d404aa113df99c1b554e1802d70185ab5"
),
bytes.fromhex(
"458ca5896d0934866992268f7509b5e954d568b1251e20c19bd3149ee3c86ffb5a44d1c2a0abbb99a3ab4767272dbb0e419b4579e890a24919ebbbe6cc0f970f"
),
"VeryLongMessage!" * 64,
)
@pytest.mark.parametrize("pubkey, signature, message", VECTORS)
def test_verify(client, pubkey, signature, message):
with client:
lisk.verify_message(
client, bytes.fromhex(pubkey), bytes.fromhex(signature), message
)

@ -16,12 +16,13 @@
import pytest
from trezorlib import messages as proto, nem
from trezorlib.messages import ButtonRequestType as B
from trezorlib import nem
from trezorlib.tools import parse_path
from ..common import MNEMONIC12
ADDRESS_N = parse_path("m/44'/1'/0'/0'/0'")
# assertion data from T1
@pytest.mark.altcoin
@ -78,7 +79,7 @@ class TestMsgNEMSignTxMosaics:
}
# not using client.nem_sign_tx() because of swiping
tx = self._nem_sign(client, 2, test_suite)
tx = nem.sign_tx(client, ADDRESS_N, test_suite)
assert (
tx.data.hex()
== "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
@ -113,7 +114,7 @@ class TestMsgNEMSignTxMosaics:
}
# not using client.nem_sign_tx() because of swiping
tx = self._nem_sign(client, 2, test_suite)
tx = nem.sign_tx(client, ADDRESS_N, test_suite)
assert (
tx.data.hex()
== "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
@ -152,7 +153,7 @@ class TestMsgNEMSignTxMosaics:
"creationFee": 1500,
}
tx = self._nem_sign(client, 6, test_suite)
tx = nem.sign_tx(client, ADDRESS_N, test_suite)
assert (
tx.data.hex()
== "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
@ -161,41 +162,3 @@ class TestMsgNEMSignTxMosaics:
tx.signature.hex()
== "b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a"
)
def _nem_sign(self, client, num_of_swipes, test_suite):
n = parse_path("m/44'/1'/0'/0'/0'")
def input_flow():
# Confirm Action
btn_code = yield
assert btn_code == B.ConfirmOutput
client.debug.press_yes()
# Swipe and confirm
yield
for _ in range(num_of_swipes):
client.debug.swipe_up()
client.debug.press_yes()
# Confirm Action
btn_code = yield
assert btn_code == B.ConfirmOutput
client.debug.press_yes()
# Sign Tx
btn_code = yield
assert btn_code == B.SignTx
client.debug.press_yes()
with client:
client.set_expected_responses(
[
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
proto.NEMSignedTx,
]
)
client.set_input_flow(input_flow)
return nem.sign_tx(client, n, test_suite)

@ -143,9 +143,9 @@ def test_invalid_seed_core(client):
assert layout.text == "Bip39Keyboard"
client.debug.input("stick")
code = yield
br = yield
layout = client.debug.wait_layout()
assert code == messages.ButtonRequestType.Warning
assert br.code == messages.ButtonRequestType.Warning
assert "invalid recovery seed" in layout.text
client.debug.click(buttons.OK)

@ -164,8 +164,8 @@ def test_same_share(client):
for word in second_share:
debug.input(word)
code = yield
assert code == messages.ButtonRequestType.Warning
br = yield
assert br.code == messages.ButtonRequestType.Warning
client.cancel()
@ -204,8 +204,8 @@ def test_group_threshold_reached(client):
for word in second_share:
debug.input(word)
code = yield
assert code == messages.ButtonRequestType.Warning
br = yield
assert br.code == messages.ButtonRequestType.Warning
client.cancel()

@ -154,8 +154,8 @@ def test_ask_word_number(client):
for _ in range(20):
debug.input("slush")
code = yield # Invalid share
assert code == messages.ButtonRequestType.Warning
br = yield # Invalid share
assert br.code == messages.ButtonRequestType.Warning
debug.press_yes()
yield # Homescreen - start process
@ -168,8 +168,8 @@ def test_ask_word_number(client):
for _ in range(33):
debug.input("slush")
code = yield # Invalid share
assert code == messages.ButtonRequestType.Warning
br = yield # Invalid share
assert br.code == messages.ButtonRequestType.Warning
debug.press_yes()
yield # Homescreen
@ -206,8 +206,8 @@ def test_ask_word_number(client):
for word in share:
debug.input(word)
code = yield # Invalid share
assert code == messages.ButtonRequestType.Warning
br = yield # Invalid share
assert br.code == messages.ButtonRequestType.Warning
debug.press_yes()
yield # Proceed to next share
@ -257,8 +257,8 @@ def test_wrong_nth_word(client, nth_word):
debug.input(share[-1])
break
code = yield
assert code == messages.ButtonRequestType.Warning
br = yield
assert br.code == messages.ButtonRequestType.Warning
client.cancel()
@ -294,8 +294,8 @@ def test_same_share(client):
for word in second_share:
debug.input(word)
code = yield
assert code == messages.ButtonRequestType.Warning
br = yield
assert br.code == messages.ButtonRequestType.Warning
client.cancel()

@ -27,15 +27,16 @@ from ..common import (
MNEMONIC12,
click_through,
generate_entropy,
paging_responses,
read_and_confirm_mnemonic,
)
EXTERNAL_ENTROPY = b"zlutoucky kun upel divoke ody" * 2
STRENGTH_TO_WORDS = {128: 12, 192: 18, 256: 24}
def reset_device(client, strength):
words = STRENGTH_TO_WORDS[strength]
words = strength // 32 * 3
mnemonic_pages = ((words + 3) // 4) + 1
mnemonic = None
def input_flow():
@ -46,18 +47,16 @@ def reset_device(client, strength):
yield from click_through(client.debug, screens=3, code=B.ResetDevice)
# mnemonic phrases
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(client.debug, words=words)
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
# confirm recovery seed check
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
# confirm success
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
@ -68,7 +67,9 @@ def reset_device(client, strength):
proto.EntropyRequest(),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
]
+ paging_responses(mnemonic_pages, code=B.ResetDevice)
+ [
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.Success),
proto.Success,
@ -123,13 +124,15 @@ class TestMsgResetDeviceT2:
def test_reset_device_pin(self, client):
mnemonic = None
strength = 256 # 24 words
words = strength // 32 * 3
mnemonic_pages = (words // 4) + 1
def input_flow():
nonlocal mnemonic
# Confirm Reset
btn_code = yield
assert btn_code == B.ResetDevice
br = yield
assert br.code == B.ResetDevice
client.debug.press_yes()
# Enter new PIN
@ -141,33 +144,31 @@ class TestMsgResetDeviceT2:
client.debug.input("654")
# Confirm entropy
btn_code = yield
assert btn_code == B.ResetDevice
br = yield
assert br.code == B.ResetDevice
client.debug.press_yes()
# Backup your seed
btn_code = yield
assert btn_code == B.ResetDevice
br = yield
assert br.code == B.ResetDevice
client.debug.press_yes()
# Confirm warning
btn_code = yield
assert btn_code == B.ResetDevice
br = yield
assert br.code == B.ResetDevice
client.debug.press_yes()
# mnemonic phrases
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(client.debug, words=24)
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
# confirm recovery seed check
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
# confirm success
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
@ -181,7 +182,9 @@ class TestMsgResetDeviceT2:
proto.EntropyRequest(),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
]
+ paging_responses(mnemonic_pages, code=B.ResetDevice)
+ [
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.Success),
proto.Success,
@ -220,6 +223,8 @@ class TestMsgResetDeviceT2:
def test_reset_failed_check(self, client):
mnemonic = None
strength = 256 # 24 words
words = strength // 32 * 3
mnemonic_pages = (words // 4) + 1
def input_flow():
nonlocal mnemonic
@ -229,30 +234,26 @@ class TestMsgResetDeviceT2:
yield from click_through(client.debug, screens=3, code=B.ResetDevice)
# mnemonic phrases, wrong answer
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(
client.debug, words=24, choose_wrong=True
mnemonic = yield from read_and_confirm_mnemonic(
client.debug, choose_wrong=True
)
# warning screen
btn_code = yield
assert btn_code == B.ResetDevice
br = yield
assert br.code == B.ResetDevice
client.debug.press_yes()
# mnemonic phrases
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(client.debug, words=24)
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
# confirm recovery seed check
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
# confirm success
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
@ -263,9 +264,11 @@ class TestMsgResetDeviceT2:
proto.EntropyRequest(),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
]
+ paging_responses(mnemonic_pages, code=B.ResetDevice)
+ [proto.ButtonRequest(code=B.ResetDevice)]
+ paging_responses(mnemonic_pages, code=B.ResetDevice)
+ [
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.Success),
proto.Success,

@ -23,7 +23,12 @@ from trezorlib import device, messages as proto
from trezorlib.exceptions import TrezorFailure
from trezorlib.messages import BackupType, ButtonRequestType as B
from ..common import click_through, generate_entropy, read_and_confirm_mnemonic
from ..common import (
click_through,
generate_entropy,
paging_responses,
read_and_confirm_mnemonic,
)
EXTERNAL_ENTROPY = b"zlutoucky kun upel divoke ody" * 2
@ -35,6 +40,7 @@ class TestMsgResetDeviceT2:
def test_reset_device_slip39_advanced(self, client):
strength = 128
word_count = 20
mnemonic_page_count = (word_count // 4) + 1
member_threshold = 3
all_mnemonics = []
@ -56,19 +62,17 @@ class TestMsgResetDeviceT2:
for g in range(5):
for h in range(5):
# mnemonic phrases
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(client.debug, words=word_count)
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
all_mnemonics.append(mnemonic)
# Confirm continue to next share
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
# safety warning
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
@ -94,56 +98,14 @@ class TestMsgResetDeviceT2:
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice), # group #5 counts
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice), # show seeds
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
]
+ [
# individual mnemonic
*paging_responses(mnemonic_page_count, code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success), # show seeds ends here
]
* (5 * 5) # groups * shares
+ [
proto.ButtonRequest(code=B.Success),
proto.Success,
proto.Features,

@ -28,14 +28,16 @@ from ..common import (
EXTERNAL_ENTROPY,
click_through,
generate_entropy,
paging_responses,
read_and_confirm_mnemonic,
)
STRENGTH_TO_WORDS = {128: 20, 256: 33}
def reset_device(client, strength):
words = STRENGTH_TO_WORDS[strength]
# per SLIP-39: strength in bits, rounded up to nearest multiple of 10, plus 70 bits
# of metadata, split into 10-bit words
word_count = ((strength + 9) // 10) + 7
mnemonic_pages = ((word_count + 3) // 4) + 1
member_threshold = 3
all_mnemonics = []
@ -53,19 +55,17 @@ def reset_device(client, strength):
# show & confirm shares
for h in range(5):
# mnemonic phrases
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(client.debug, words=words)
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
all_mnemonics.append(mnemonic)
# Confirm continue to next share
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
# safety warning
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
@ -81,16 +81,14 @@ def reset_device(client, strength):
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
proto.ButtonRequest(code=B.ResetDevice),
]
+ [
# individual mnemonic
*paging_responses(mnemonic_pages, code=B.ResetDevice),
proto.ButtonRequest(code=B.Success),
]
* 5 # number of shares
+ [
proto.ButtonRequest(code=B.Success),
proto.Success,
proto.Features,

@ -18,6 +18,7 @@
import pytest
from trezorlib import btc, messages
from trezorlib.debuglink import message_filters
from trezorlib.tools import parse_path
S = messages.InputScriptType
@ -233,18 +234,20 @@ MESSAGE_LENGTHS = (
@pytest.mark.parametrize("message", MESSAGE_LENGTHS)
def test_signmessage_pagination(client, message):
message_read = ""
message += "End."
def input_flow():
# collect screen contents into `message_read`.
# Join lines that are separated by a single "-" string, space-separate lines otherwise.
nonlocal message_read
yield
# start assuming there was a word break; this avoids prepending space at start
word_break = True
max_attempts = 100
while max_attempts:
page = 0
while True:
br = yield
assert br.page_number == page + 1
page = br.page_number
layout = client.debug.wait_layout()
for line in layout.lines[1:]:
if line == "-":
@ -258,16 +261,12 @@ def test_signmessage_pagination(client, message):
# attach with space
message_read += " " + line
if not message_read.endswith("End."):
if page < br.pages:
client.debug.swipe_up()
else:
client.debug.press_yes()
break
max_attempts -= 1
assert max_attempts > 0, "failed to scroll through message"
with client:
client.set_input_flow(input_flow)
client.debug.watch_layout(True)
@ -282,13 +281,20 @@ def test_signmessage_pagination(client, message):
@pytest.mark.skip_t1
def test_signmessage_pagination_trailing_newline(client):
# This can currently only be tested by a human via the UI test diff:
message = "THIS\nMUST\nNOT\nBE\nPAGINATED\n"
# The trailing newline must not cause a new paginated screen to appear.
# The UI must be a single dialog without pagination.
btc.sign_message(
client,
coin_name="Bitcoin",
n=parse_path("m/44h/0h/0h/0/0"),
message=message,
)
with client:
client.set_expected_responses(
[
# expect a ButtonRequest that does not have pagination set
message_filters.ButtonRequest(pages=None),
messages.MessageSignature,
]
)
btc.sign_message(
client,
coin_name="Bitcoin",
n=parse_path("m/44h/0h/0h/0/0"),
message=message,
)

@ -662,7 +662,7 @@ class TestMsgSigntx:
nonlocal finished
for expected in (B.ConfirmOutput, B.FeeOverThreshold, B.SignTx):
br = yield
assert br == expected
assert br.code == expected
client.debug.press_yes()
finished = True

@ -517,10 +517,7 @@ def test_p2wpkh_in_p2sh_fee_bump_from_external(client):
request_output(0),
request_orig_output(0, TXHASH_334cd7),
messages.ButtonRequest(code=B.ConfirmOutput),
(
client.features.model == "1",
messages.ButtonRequest(code=B.ConfirmOutput),
),
messages.ButtonRequest(code=B.ConfirmOutput),
request_orig_output(1, TXHASH_334cd7),
messages.ButtonRequest(code=B.SignTx),
request_input(0),

@ -29,15 +29,8 @@ TEZOS_PATH_15 = parse_path("m/44'/1729'/15'")
@pytest.mark.tezos
@pytest.mark.skip_t1
class TestMsgTezosSignTx:
def input_flow(self, debug, num_pages):
yield
for _ in range(num_pages - 1):
debug.swipe_up()
debug.press_yes()
def test_tezos_sign_tx_proposal(self, client):
with client:
client.set_input_flow(self.input_flow(client.debug, num_pages=1))
resp = tezos.sign_tx(
client,
TEZOS_PATH_10,
@ -70,7 +63,6 @@ class TestMsgTezosSignTx:
def test_tezos_sign_tx_multiple_proposals(self, client):
with client:
client.set_input_flow(self.input_flow(client.debug, num_pages=2))
resp = tezos.sign_tx(
client,
TEZOS_PATH_10,

@ -23,11 +23,18 @@ from shamir_mnemonic import shamir
from trezorlib import device, messages
from trezorlib.messages import BackupType, ButtonRequestType as B
from ..common import EXTERNAL_ENTROPY, click_through, read_and_confirm_mnemonic
from ..common import (
EXTERNAL_ENTROPY,
click_through,
paging_responses,
read_and_confirm_mnemonic,
)
def backup_flow_bip39(client):
mnemonic = None
words = 12
mnemonic_pages = ((words + 3) // 4) + 1
def input_flow():
nonlocal mnemonic
@ -36,25 +43,25 @@ def backup_flow_bip39(client):
yield from click_through(client.debug, screens=1, code=B.ResetDevice)
# mnemonic phrases
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(client.debug, words=12)
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
# confirm recovery seed check
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
# confirm success
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
with client:
client.set_expected_responses(
[
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
]
+ paging_responses(mnemonic_pages, code=B.ResetDevice)
+ [
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.Success),
messages.Success,
@ -69,6 +76,8 @@ def backup_flow_bip39(client):
def backup_flow_slip39_basic(client):
mnemonics = []
words = 20
mnemonic_pages = ((words + 3) // 4) + 1
def input_flow():
# 1. Checklist
@ -81,8 +90,8 @@ def backup_flow_slip39_basic(client):
# Mnemonic phrases
for _ in range(5):
yield # Phrase screen
mnemonic = read_and_confirm_mnemonic(client.debug, words=20)
# Phrase screen
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
mnemonics.append(mnemonic)
yield # Confirm continue to next
client.debug.press_yes()
@ -96,7 +105,7 @@ def backup_flow_slip39_basic(client):
client.set_expected_responses(
[messages.ButtonRequest(code=B.ResetDevice)] * 6 # intro screens
+ [
messages.ButtonRequest(code=B.ResetDevice),
*paging_responses(mnemonic_pages, code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
]
* 5 # individual shares
@ -115,6 +124,8 @@ def backup_flow_slip39_basic(client):
def backup_flow_slip39_advanced(client):
mnemonics = []
words = 20
mnemonic_pages = ((words + 3) // 4) + 1
def input_flow():
# 1. Confirm Reset
@ -132,19 +143,17 @@ def backup_flow_slip39_advanced(client):
for _ in range(5):
for _ in range(5):
# mnemonic phrases
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(client.debug, words=20)
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
mnemonics.append(mnemonic)
# Confirm continue to next share
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
# safety warning
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
with client:
@ -157,7 +166,7 @@ def backup_flow_slip39_advanced(client):
]
* 5 # group thresholds
+ [
messages.ButtonRequest(code=B.ResetDevice),
*paging_responses(mnemonic_pages, code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
]
* 25 # individual shares

@ -23,7 +23,12 @@ from trezorlib import btc, device, messages
from trezorlib.messages import BackupType, ButtonRequestType as B
from trezorlib.tools import parse_path
from ..common import EXTERNAL_ENTROPY, click_through, read_and_confirm_mnemonic
from ..common import (
EXTERNAL_ENTROPY,
click_through,
paging_responses,
read_and_confirm_mnemonic,
)
@pytest.mark.skip_t1
@ -39,8 +44,9 @@ def test_reset_recovery(client):
def reset(client, strength=128, skip_backup=False):
words = strength // 32 * 3
mnemonic_pages = ((words + 3) // 4) + 1
mnemonic = None
word_count = strength // 32 * 3
def input_flow():
nonlocal mnemonic
@ -51,28 +57,29 @@ def reset(client, strength=128, skip_backup=False):
yield from click_through(client.debug, screens=3, code=B.ResetDevice)
# mnemonic phrases
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(client.debug, words=word_count)
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
# confirm recovery seed check
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
# confirm success
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
with client:
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
with mock.patch("os.urandom", os_urandom), client:
client.set_expected_responses(
[
messages.ButtonRequest(code=B.ResetDevice),
messages.EntropyRequest(),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
]
+ paging_responses(mnemonic_pages, code=B.ResetDevice)
+ [
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.Success),
messages.Success,
@ -81,19 +88,17 @@ def reset(client, strength=128, skip_backup=False):
)
client.set_input_flow(input_flow)
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
with mock.patch("os.urandom", os_urandom), client:
# No PIN, no passphrase, don't display random
device.reset(
client,
display_random=False,
strength=strength,
passphrase_protection=False,
pin_protection=False,
label="test",
language="en-US",
backup_type=BackupType.Bip39,
)
# No PIN, no passphrase, don't display random
device.reset(
client,
display_random=False,
strength=strength,
passphrase_protection=False,
pin_protection=False,
label="test",
language="en-US",
backup_type=BackupType.Bip39,
)
# Check if device is properly initialized
assert client.features.initialized is True

@ -25,6 +25,7 @@ from trezorlib.tools import parse_path
from ..common import (
EXTERNAL_ENTROPY,
click_through,
paging_responses,
read_and_confirm_mnemonic,
recovery_enter_shares,
)
@ -62,6 +63,7 @@ def reset(client, strength=128):
# per SLIP-39: strength in bits, rounded up to nearest multiple of 10, plus 70 bits
# of metadata, split into 10-bit words
word_count = ((strength + 9) // 10) + 7
mnemonic_pages = ((word_count + 3) // 4) + 1
def input_flow():
# 1. Confirm Reset
@ -81,19 +83,17 @@ def reset(client, strength=128):
for g in range(5):
for h in range(5):
# mnemonic phrases
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(client.debug, words=word_count)
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
all_mnemonics.append(mnemonic)
# Confirm continue to next share
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
# safety warning
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
@ -119,56 +119,14 @@ def reset(client, strength=128):
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice), # group #5 counts
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice), # show seeds
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
]
+ [
# individual mnemonic
*paging_responses(mnemonic_pages, code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success), # show seeds ends here
]
* (5 * 5) # groups * shares
+ [
messages.ButtonRequest(code=B.Success),
messages.Success,
messages.Features,

@ -23,7 +23,12 @@ from trezorlib import btc, device, messages
from trezorlib.messages import BackupType, ButtonRequestType as B
from trezorlib.tools import parse_path
from ..common import click_through, read_and_confirm_mnemonic, recovery_enter_shares
from ..common import (
click_through,
paging_responses,
read_and_confirm_mnemonic,
recovery_enter_shares,
)
EXTERNAL_ENTROPY = b"zlutoucky kun upel divoke ody" * 2
MOCK_OS_URANDOM = mock.Mock(return_value=EXTERNAL_ENTROPY)
@ -49,6 +54,7 @@ def reset(client, strength=128):
# per SLIP-39: strength in bits, rounded up to nearest multiple of 10, plus 70 bits
# of metadata, split into 10-bit words
word_count = ((strength + 9) // 10) + 7
mnemonic_pages = ((word_count + 3) // 4) + 1
def input_flow():
# 1. Confirm Reset
@ -64,19 +70,17 @@ def reset(client, strength=128):
# show & confirm shares
for h in range(5):
# mnemonic phrases
btn_code = yield
assert btn_code == B.ResetDevice
mnemonic = read_and_confirm_mnemonic(client.debug, words=word_count)
mnemonic = yield from read_and_confirm_mnemonic(client.debug)
all_mnemonics.append(mnemonic)
# Confirm continue to next share
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
# safety warning
btn_code = yield
assert btn_code == B.Success
br = yield
assert br.code == B.Success
client.debug.press_yes()
with client:
@ -91,16 +95,14 @@ def reset(client, strength=128):
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
messages.ButtonRequest(code=B.ResetDevice),
]
+ [
# individual mnemonic
*paging_responses(mnemonic_pages, code=B.ResetDevice),
messages.ButtonRequest(code=B.Success),
]
* 5 # number of shares
+ [
messages.ButtonRequest(code=B.Success),
messages.Success,
messages.Features,

Loading…
Cancel
Save