mk4=Q rest fixed (sim tests)
This commit is contained in:
parent
964c8b77ab
commit
a3f1f7f5de
@ -86,11 +86,11 @@ class LoginUX:
|
||||
callgate.fast_wipe(False)
|
||||
# NOT REACHED
|
||||
|
||||
if ch in KEY_DELETE+KEY_LEFT:
|
||||
if has_qwerty and ch in KEY_DELETE+KEY_LEFT:
|
||||
if self.pin:
|
||||
self.pin = self.pin[:-1]
|
||||
self.show_pin()
|
||||
elif has_qwerty and self.pin_prefix:
|
||||
elif self.pin_prefix:
|
||||
# trying to delete past start of second half, take them
|
||||
# to first part again. Q only
|
||||
ux_show_phish_words(dis, None)
|
||||
@ -277,7 +277,6 @@ suffix break point is correct.\n\n'''
|
||||
if story:
|
||||
# give them background
|
||||
ch = await ux_show_story(story, title=title)
|
||||
|
||||
if ch == 'x': return None
|
||||
|
||||
# first first one
|
||||
|
||||
@ -369,14 +369,14 @@ class PasswordContent(NoteContentBase):
|
||||
# Edit, also used for add new
|
||||
|
||||
title = await ux_input_text(self.title, max_len=ONE_LINE, confirm_exit=False,
|
||||
prompt='Title', placeholder='(required for menu)')
|
||||
prompt='Title', placeholder='(required for menu)')
|
||||
if not title:
|
||||
return None
|
||||
|
||||
# blank is OK for all other values
|
||||
|
||||
user = await ux_input_text(self.user, max_len=ONE_LINE, scan_ok=True, confirm_exit=False,
|
||||
prompt='Username', placeholder='(optional)')
|
||||
prompt='Username', placeholder='(optional)')
|
||||
if user is None:
|
||||
user = self.user
|
||||
|
||||
@ -385,12 +385,12 @@ class PasswordContent(NoteContentBase):
|
||||
self.password = await get_a_password(self.password)
|
||||
|
||||
site = await ux_input_text(self.site, max_len=ONE_LINE, scan_ok=True, confirm_exit=False,
|
||||
prompt='Website', placeholder='(optional)')
|
||||
prompt='Website', placeholder='(optional)')
|
||||
if site is None:
|
||||
site = self.site
|
||||
|
||||
misc = await ux_input_text(self.misc, max_len=None, scan_ok=True, confirm_exit=False,
|
||||
prompt='More Notes', placeholder='(optional)')
|
||||
prompt='More Notes', placeholder='(optional)')
|
||||
if misc is None:
|
||||
misc = self.misc
|
||||
|
||||
@ -459,13 +459,13 @@ class NoteContent(NoteContentBase):
|
||||
# Edit, also used for add new
|
||||
|
||||
title = await ux_input_text(self.title, confirm_exit=False, max_len=CHARS_W-2,
|
||||
prompt='Title', placeholder='(required for menu)')
|
||||
prompt='Title', placeholder='(required for menu)')
|
||||
if not title:
|
||||
return
|
||||
|
||||
misc = await ux_input_text(self.misc, confirm_exit=False,
|
||||
max_len=None, scan_ok=True,
|
||||
prompt='Your Notes', placeholder='(freeform text)')
|
||||
max_len=None, scan_ok=True,
|
||||
prompt='Your Notes', placeholder='(freeform text)')
|
||||
if misc is None:
|
||||
misc = self.misc
|
||||
|
||||
|
||||
@ -349,12 +349,12 @@ async def add_dice_rolls(count, seed, judge_them, nwords=None, enforce=False):
|
||||
# this is slow enough to see
|
||||
md.update(ch)
|
||||
|
||||
elif ch == KEY_CANCEL:
|
||||
elif ch in KEY_CANCEL+"x":
|
||||
# Because the change (roll) has already been applied,
|
||||
# only let them abort if it's early still
|
||||
if count < 10 and judge_them:
|
||||
return 0, seed
|
||||
elif ch == KEY_ENTER:
|
||||
elif ch in KEY_ENTER+"y":
|
||||
if count < threshold and judge_them:
|
||||
if not count:
|
||||
return 0, seed
|
||||
@ -1126,7 +1126,7 @@ OK to continue or press (2) to hide this message forever.
|
||||
if version.has_qwerty and not PassphraseSaver.has_file():
|
||||
# no need for any menus if Q and no card present
|
||||
pp = await ux_input_text('', prompt="Your BIP-39 Passphrase",
|
||||
b39_complete=True, scan_ok=True, max_len=100)
|
||||
b39_complete=True, scan_ok=True, max_len=100)
|
||||
if not pp: return
|
||||
|
||||
await apply_pass_value(pp)
|
||||
|
||||
@ -88,7 +88,8 @@ async def import_tapsigner_backup_file(_1, _2, item):
|
||||
|
||||
while True:
|
||||
backup_key = await ux_input_text("", confirm_exit=False, hex_only=True,
|
||||
min_len=32, max_len=32, prompt='Backup Password (32 hex digits)')
|
||||
min_len=32, max_len=32,
|
||||
prompt='Backup Password (32 hex digits)')
|
||||
if backup_key is None:
|
||||
return
|
||||
|
||||
|
||||
@ -347,10 +347,10 @@ def _import_prompt_builder(title, no_qr, no_nfc, slot_b_only=False):
|
||||
from version import has_qwerty, num_sd_slots, has_qr
|
||||
from glob import NFC, VD
|
||||
|
||||
prompt, escape = None, KEY_CANCEL
|
||||
prompt, escape = None, KEY_CANCEL+"x"
|
||||
|
||||
if (NFC or VD) or num_sd_slots>1:
|
||||
if slot_b_only:
|
||||
if slot_b_only and (num_sd_slots>1):
|
||||
prompt = "Press (B) to import %s from lower slot SD Card" % title
|
||||
escape += "b"
|
||||
else:
|
||||
|
||||
@ -287,7 +287,10 @@ async def ux_input_text(pw, confirm_exit=True, hex_only=False, max_len=100, min_
|
||||
ch = await press.wait()
|
||||
if ch == 'y':
|
||||
if len(pw) < min_len:
|
||||
# enforce a minimum length, better: say so.
|
||||
ch = await ux_show_story('Need %d characters at least. Press OK '
|
||||
'to continue X to exit.' % min_len, escape="xy",
|
||||
strict_escape=True)
|
||||
if ch == "x": return
|
||||
continue
|
||||
return str(pw, 'ascii')
|
||||
elif ch == 'x':
|
||||
|
||||
@ -135,7 +135,6 @@ async def xor_all_done(new_words):
|
||||
num_parts = len(import_xor_parts)
|
||||
enc_parts = [bip39.a2b_words(w) for w in import_xor_parts]
|
||||
seed = xor(*enc_parts)
|
||||
num_parts = len(import_xor_parts)
|
||||
|
||||
msg = "You've entered %d parts so far.\n\n" % num_parts
|
||||
if num_parts >= 2:
|
||||
@ -151,7 +150,6 @@ async def xor_all_done(new_words):
|
||||
msg += "Press (1) to enter next list of words, or (2) if done with all words."
|
||||
|
||||
ch = await ux_show_story(msg, strict_escape=True, escape='12x'+KEY_CANCEL, sensitive=True)
|
||||
|
||||
if ch == 'x':
|
||||
# give up
|
||||
import_xor_parts.clear() # concern: we are contaminated w/ secrets
|
||||
@ -164,7 +162,7 @@ async def xor_all_done(new_words):
|
||||
await seed_word_entry("Part %s Words" % chr(65+len(import_xor_parts)),
|
||||
target_words, done_cb=xor_all_done)
|
||||
else:
|
||||
nxt = XORWordNestMenu(num_words=target_words)
|
||||
nxt = XORWordNestMenu(num_words=target_words, done_cb=xor_all_done)
|
||||
the_ux.push(nxt)
|
||||
|
||||
elif ch == '2':
|
||||
|
||||
@ -127,7 +127,7 @@ def sim_card_ejected(sim_exec, is_simulator):
|
||||
return
|
||||
|
||||
# see unix/frozen-modules/pyb.py class SDCard
|
||||
cmd = f'import pyb; pyb.SDCard.ejected={ejected}; RV.write("ok")'
|
||||
cmd = f'import files; files.CardSlot.sd_detect = lambda: int({ejected}); RV.write("ok")'
|
||||
assert sim_exec(cmd) == 'ok'
|
||||
|
||||
yield doit
|
||||
@ -601,7 +601,7 @@ def cap_screen_qr(cap_image):
|
||||
def get_pp_sofar(sim_exec):
|
||||
# get entry value for bip39 passphrase
|
||||
def doit():
|
||||
resp = sim_exec('import seed; RV.write(seed.pp_sofar)')
|
||||
resp = sim_exec('import seed; RV.write(seed.PassphraseMenu.pp_sofar)')
|
||||
assert 'Error' not in resp
|
||||
return resp
|
||||
|
||||
@ -675,7 +675,7 @@ def press_right(need_keypress, has_qwerty):
|
||||
return doit
|
||||
|
||||
@pytest.fixture
|
||||
def goto_home(cap_menu, press_cancel, press_select, pick_menu_item, has_qwerty, cap_screen):
|
||||
def goto_home(cap_menu, press_cancel, press_select, pick_menu_item, cap_screen):
|
||||
|
||||
def doit():
|
||||
# get to top, force a redraw
|
||||
@ -685,18 +685,19 @@ def goto_home(cap_menu, press_cancel, press_select, pick_menu_item, has_qwerty,
|
||||
|
||||
m = cap_menu()
|
||||
|
||||
if 'CANCEL' in m:
|
||||
# special case to get out of passphrase menu
|
||||
pick_menu_item('CANCEL')
|
||||
time.sleep(.01)
|
||||
if "Are you SURE ?" in cap_screen():
|
||||
press_select()
|
||||
|
||||
chk = cap_screen()
|
||||
if m[0] not in chk:
|
||||
# menu vs. screen wrong ... happens if looking at a story, not a menu
|
||||
press_cancel()
|
||||
continue
|
||||
|
||||
if 'CANCEL' in m:
|
||||
# special case to get out of passphrase menu
|
||||
pick_menu_item('CANCEL')
|
||||
time.sleep(.01)
|
||||
press_select()
|
||||
|
||||
if m[0] in { 'New Seed Words', 'Ready To Sign'}:
|
||||
break
|
||||
if len(m) > 1 and (m[1] == "Ready To Sign") and (m[0][0] == "["):
|
||||
|
||||
@ -6,7 +6,7 @@ import stash, chains
|
||||
from pincodes import pa
|
||||
from glob import settings
|
||||
import stash
|
||||
from seed import set_seed_value
|
||||
from seed import set_seed_value, PassphraseMenu
|
||||
from utils import xfp2str
|
||||
from actions import goto_top_menu
|
||||
from nvstore import SettingsObject
|
||||
@ -19,6 +19,7 @@ settings.current = sim_defaults
|
||||
|
||||
import main
|
||||
pa.tmp_value = None
|
||||
PassphraseMenu.pp_sofar = ''
|
||||
SettingsObject.master_sv_data = {}
|
||||
SettingsObject.master_nvram_key = None
|
||||
set_seed_value(main.WORDS)
|
||||
|
||||
@ -104,7 +104,7 @@ def my_enter_pin(cap_screen, need_keypress, is_q1, press_right, press_select):
|
||||
scr = cap_screen().split('\n')
|
||||
assert scr[-1] == 'Enter rest of PIN'
|
||||
|
||||
press_select()
|
||||
press_select()
|
||||
|
||||
time.sleep(0.1)
|
||||
return title, words
|
||||
@ -115,7 +115,7 @@ def my_enter_pin(cap_screen, need_keypress, is_q1, press_right, press_select):
|
||||
@pytest.fixture
|
||||
def change_pin(cap_screen, cap_story, cap_menu, press_select, my_enter_pin, press_cancel):
|
||||
def doit(old_pin, new_pin, hdr_text, expect_fail=None):
|
||||
# use standard menus and UX to change a PIN
|
||||
# use standard menus and UX to change a PIN
|
||||
title, story = cap_story()
|
||||
assert title == hdr_text
|
||||
assert "changing the main PIN used to unlock your Coldcard" in story
|
||||
|
||||
@ -608,7 +608,7 @@ def test_ephemeral_seed_import_tapsigner(way, testnet, pick_menu_item, cap_story
|
||||
def test_ephemeral_seed_import_tapsigner_fail(pick_menu_item, cap_story, fail, cap_screen,
|
||||
need_keypress, reset_seed_words, enter_hex,
|
||||
tapsigner_encrypted_backup, goto_eph_seed_menu,
|
||||
microsd_path, ephemeral_seed_disabled, is_q1,
|
||||
microsd_path, ephemeral_seed_disabled,
|
||||
settings_set, press_select, press_cancel):
|
||||
|
||||
|
||||
@ -648,8 +648,8 @@ def test_ephemeral_seed_import_tapsigner_fail(pick_menu_item, cap_story, fail, c
|
||||
enter_hex(backup_key_hex)
|
||||
time.sleep(0.3)
|
||||
|
||||
if fail == "key_len" and is_q1:
|
||||
assert "Need 32 char" in cap_screen()
|
||||
if fail == "key_len":
|
||||
assert "Need 32" in cap_screen()
|
||||
press_cancel()
|
||||
return
|
||||
|
||||
@ -1043,8 +1043,9 @@ def test_seed_vault_modifications(settings_set, reset_seed_words, pick_menu_item
|
||||
# first entry again
|
||||
press_select()
|
||||
pick_menu_item("Rename")
|
||||
for _ in range(11):
|
||||
for _ in range(10 if is_q1 else 9):
|
||||
press_delete()
|
||||
|
||||
if is_q1:
|
||||
do_keypresses("AA")
|
||||
else:
|
||||
@ -1054,7 +1055,7 @@ def test_seed_vault_modifications(settings_set, reset_seed_words, pick_menu_item
|
||||
# name changed to AA
|
||||
|
||||
press_select()
|
||||
|
||||
time.sleep(.1)
|
||||
m = cap_menu()
|
||||
assert m[0] == "AA"
|
||||
assert "Rename" in m
|
||||
@ -1083,7 +1084,7 @@ def test_seed_vault_modifications(settings_set, reset_seed_words, pick_menu_item
|
||||
assert "Delete" in m
|
||||
|
||||
pick_menu_item("Rename")
|
||||
for _ in range(11):
|
||||
for _ in range(10 if is_q1 else 9):
|
||||
press_delete()
|
||||
|
||||
if is_q1:
|
||||
|
||||
@ -71,7 +71,7 @@ def compute_policy_hash(policy):
|
||||
if type_ == Deriv:
|
||||
rv = []
|
||||
for orig in value or []:
|
||||
rv.append(orig if orig in ["any", "p2sh"] else orig.replace('p', "'").replace('h', "'"))
|
||||
rv.append(orig if orig in ["any", "p2sh"] else orig.replace('p', "h").replace("'", 'h'))
|
||||
elif type_ == WhitelistOpts:
|
||||
rv = OrderedDict()
|
||||
rv["mode"] = value.get("mode", "BASIC")
|
||||
@ -165,17 +165,17 @@ def hsm_reset(dev, sim_exec):
|
||||
(DICT(boot_to_hsm='123123'), 'Boot to HSM enabled'),
|
||||
|
||||
# msg signing
|
||||
(DICT(msg_paths=["m/1'/2p/3H"]), "m/1'/2'/3'"),
|
||||
(DICT(msg_paths=["m/1'/2p/3H"]), "m/1h/2h/3h"),
|
||||
(DICT(msg_paths=["m/1", "m/2"]), "m/1 OR m/2"),
|
||||
(DICT(msg_paths=["any"]), "(any path)"),
|
||||
|
||||
# data sharing
|
||||
(DICT(share_addrs=["m/1'/2p/3H"]), ['Address values values will be shared', "m/1'/2'/3'"]),
|
||||
(DICT(share_addrs=["m/1'/2p/3H"]), ['Address values values will be shared', "m/1h/2h/3h"]),
|
||||
(DICT(share_addrs=["m/1", "m/2"]), ['Address values values will be shared', "m/1 OR m/2"]),
|
||||
(DICT(share_addrs=["any"]), ['Address values values will be shared', "(any path)"]),
|
||||
(DICT(share_addrs=["p2sh", "any"]), ['Address values values will be shared', "(any P2SH)", "(any path"]),
|
||||
|
||||
(DICT(share_xpubs=["m/1'/2p/3H"]), ['XPUB values will be shared', "m/1'/2'/3'"]),
|
||||
(DICT(share_xpubs=["m/1'/2p/3H"]), ['XPUB values will be shared', "m/1h/2h/3h"]),
|
||||
(DICT(share_xpubs=["m/1", "m/2"]), ['XPUB values will be shared', "m/1 OR m/2"]),
|
||||
(DICT(share_xpubs=["any"]), ['XPUB values will be shared', "(any path)"]),
|
||||
|
||||
@ -898,7 +898,7 @@ def test_multiple_signings_multisig(cc_first, M_N, dev, quick_start_hsm,
|
||||
attempt_psbt(psbt)
|
||||
|
||||
|
||||
def test_sign_msg_good(quick_start_hsm, change_hsm, attempt_msg_sign, addr_fmt=AF_CLASSIC):
|
||||
def test_sign_msg_good(quick_start_hsm, change_hsm, attempt_msg_sign):
|
||||
# message signing, but only at certain derivations
|
||||
permit = ['m/73', "m/*'", 'm/1p/3h/4/5/6/7' ]
|
||||
block = ['m', 'm/72', permit[-1][:-2]]
|
||||
@ -907,15 +907,14 @@ def test_sign_msg_good(quick_start_hsm, change_hsm, attempt_msg_sign, addr_fmt=A
|
||||
policy = DICT(msg_paths=permit)
|
||||
quick_start_hsm(policy)
|
||||
|
||||
if 1:
|
||||
for addr_fmt in [ AF_CLASSIC, AF_P2WPKH, AF_P2WPKH_P2SH]:
|
||||
for addr_fmt in [ AF_CLASSIC, AF_P2WPKH, AF_P2WPKH_P2SH]:
|
||||
|
||||
for p in permit:
|
||||
p = p.replace('*', '75333')
|
||||
attempt_msg_sign(None, msg, p, addr_fmt=addr_fmt)
|
||||
for p in permit:
|
||||
p = p.replace('*', '75333')
|
||||
attempt_msg_sign(None, msg, p, addr_fmt=addr_fmt)
|
||||
|
||||
for p in block:
|
||||
attempt_msg_sign('not enabled for that path', msg, p, addr_fmt=addr_fmt)
|
||||
for p in block:
|
||||
attempt_msg_sign('not enabled for that path', msg, p, addr_fmt=addr_fmt)
|
||||
|
||||
policy = DICT(msg_paths=['any'])
|
||||
change_hsm(policy)
|
||||
|
||||
@ -589,7 +589,7 @@ def test_ux_duress_choices(with_wipe, subchoice, expect, xflags, xargs, words12,
|
||||
words = seed_story_to_words(story)
|
||||
else:
|
||||
ln = story.split('\n')
|
||||
assert ln[0] == 'Seed words (24):'
|
||||
assert ln[0] == ('Seed words (12):' if words12 else 'Seed words (24):')
|
||||
words = [i[4:] for i in ln[1:25]]
|
||||
|
||||
seed = Mnemonic.to_seed(' '.join(words), passphrase='')
|
||||
@ -699,7 +699,7 @@ from test_change_pins import change_pin, goto_pin_options, my_enter_pin
|
||||
def force_main_pin(change_pin, goto_pin_options, pick_menu_item, repl):
|
||||
# make main-pin match needs
|
||||
def doit(want_pin, expect_fail=None):
|
||||
pin_b4 = repl.eval('pa.pin').decode('ascii')
|
||||
pin_b4 = repl.eval('pa.pin').decode('ascii')
|
||||
if pin_b4 == want_pin:
|
||||
assert not expect_fail
|
||||
return
|
||||
|
||||
@ -16,7 +16,7 @@ def test_get_secrets(get_secrets, master_xpub):
|
||||
assert v['xpub'] == master_xpub
|
||||
|
||||
def test_home_menu(cap_menu, cap_story, cap_screen, need_keypress, reset_seed_words,
|
||||
press_select, press_cancel, is_q1):
|
||||
press_select, press_cancel, press_down, is_q1):
|
||||
reset_seed_words()
|
||||
# get to top, force a redraw
|
||||
press_cancel()
|
||||
@ -41,7 +41,17 @@ def test_home_menu(cap_menu, cap_story, cap_screen, need_keypress, reset_seed_wo
|
||||
# check 4 lines of menu are shown right
|
||||
scr = cap_screen().rstrip()
|
||||
chk = '\n'.join(m)
|
||||
assert scr == chk
|
||||
if is_q1:
|
||||
assert scr == chk
|
||||
else:
|
||||
# does not fit to single screen on mk4
|
||||
assert scr in chk
|
||||
# go down to the bottom
|
||||
for i in range(6):
|
||||
press_down()
|
||||
|
||||
scr = cap_screen().rstrip()
|
||||
assert scr in chk
|
||||
|
||||
# pick first item, expect a story
|
||||
need_keypress('0')
|
||||
@ -120,7 +130,8 @@ def word_menu_entry(cap_menu, pick_menu_item, is_q1, do_keypresses, cap_screen):
|
||||
assert which, "cant find: " + word
|
||||
|
||||
pick_menu_item(which)
|
||||
if '-' not in which: break
|
||||
if '-' not in which:
|
||||
break
|
||||
|
||||
return doit
|
||||
|
||||
@ -615,7 +626,6 @@ def test_bip39_complex(target, goto_home, pick_menu_item, cap_story,
|
||||
|
||||
enter_complex(target, apply=True)
|
||||
press_select()
|
||||
# import pdb;pdb.set_trace()
|
||||
verify_ephemeral_secret_ui(xpub=expect.hwif(), is_b39pw=True)
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user