rework post-signing save process
This commit is contained in:
parent
2723f93d7c
commit
e8ae63922d
341
shared/auth.py
341
shared/auth.py
@ -513,7 +513,6 @@ class ApproveTransaction(UserAuthorizedAction):
|
||||
return await self.failure("Signing failed late", exc)
|
||||
|
||||
if self.approved_cb:
|
||||
kws = dict(psbt=self.psbt)
|
||||
if self.is_sd and (ch == "b"):
|
||||
self.cb_kws["slot_b"] = True
|
||||
|
||||
@ -801,8 +800,10 @@ async def done_signing(psbt, input_method=None, filename=None, force_vdisk=False
|
||||
with SFFile(TXN_OUTPUT_OFFSET, max_size=MAX_TXN_LEN, message="Saving...") as psram:
|
||||
if is_complete:
|
||||
txid = psbt.finalize(psram)
|
||||
noun = "Finalized TX ready for broadcast"
|
||||
else:
|
||||
psbt.serialize(psram)
|
||||
noun = "Partly Signed PSBT"
|
||||
txid = None
|
||||
|
||||
data_len = psram.tell()
|
||||
@ -810,186 +811,216 @@ async def done_signing(psbt, input_method=None, filename=None, force_vdisk=False
|
||||
|
||||
UserAuthorizedAction.cleanup()
|
||||
|
||||
n = 0
|
||||
ch = None
|
||||
fname_input_method = input_method
|
||||
|
||||
first_time = True
|
||||
if txid and await try_push_tx(data_len, txid, data_sha2):
|
||||
n = 1 # go directly to reexport menu after pushTX
|
||||
# go directly to reexport menu after pushTX
|
||||
first_time = False
|
||||
|
||||
# for specific cases, key teleport is an option
|
||||
offer_kt = False
|
||||
if not is_complete and psbt.active_multisig and version.has_qwerty:
|
||||
offer_kt = 'use Key Teleport to send PSBT to other co-signers'
|
||||
|
||||
while True:
|
||||
base_msg = "Finalized TX ready for broadcast" if is_complete else "Partly Signed PSBT"
|
||||
if n:
|
||||
ch = await import_export_prompt(base_msg, no_qr=False if version.has_qr else True)
|
||||
ch = None
|
||||
if first_time:
|
||||
# first time, assume they want to send out same way it came in -- dont prompt
|
||||
if input_method == "qr":
|
||||
ch = KEY_QR
|
||||
elif input_method == "nfc":
|
||||
ch = KEY_NFC
|
||||
elif input_method == "kt":
|
||||
# not reached .. because we offer KT method before this is called
|
||||
ch = 't'
|
||||
else:
|
||||
# SD/VDisk
|
||||
ch = {"force_vdisk": force_vdisk, "slot_b": slot_b}
|
||||
|
||||
if not ch:
|
||||
# show all possible export options (based on hardware enabled, features)
|
||||
ch = await import_export_prompt(noun, no_qr=not version.has_qr, offer_kt=offer_kt)
|
||||
|
||||
if ch == KEY_CANCEL:
|
||||
break
|
||||
elif ch == KEY_QR or input_method == "qr":
|
||||
|
||||
elif ch == KEY_QR:
|
||||
here = PSRAM.read_at(TXN_OUTPUT_OFFSET, data_len)
|
||||
hex_here = b2a_hex(here).upper()
|
||||
msg = txid or 'Partly Signed PSBT'
|
||||
try:
|
||||
await show_qr_code(hex_here.decode(), is_alnum=True, msg=msg)
|
||||
hex_here = b2a_hex(here).upper().decode()
|
||||
await show_qr_code(hex_here, is_alnum=True, msg=msg)
|
||||
except (ValueError, RuntimeError):
|
||||
from ux_q1 import show_bbqr_codes
|
||||
await show_bbqr_codes('T' if txid else 'P', hex_here, msg, already_hex=True)
|
||||
await show_bbqr_codes('T' if txid else 'P', here, msg)
|
||||
|
||||
msg = base_msg + " shared via QR."
|
||||
msg = noun + " shared via QR."
|
||||
del here
|
||||
elif ch == KEY_NFC or input_method == "nfc":
|
||||
|
||||
elif ch == KEY_NFC:
|
||||
from glob import NFC
|
||||
if is_complete:
|
||||
await NFC.share_signed_txn(txid, TXN_OUTPUT_OFFSET, data_len, data_sha2)
|
||||
else:
|
||||
await NFC.share_psbt(TXN_OUTPUT_OFFSET, data_len, data_sha2)
|
||||
msg = base_msg + " shared via NFC."
|
||||
|
||||
msg = noun + " shared via NFC."
|
||||
|
||||
elif ch == 't':
|
||||
# after saving to card, they might want to teleport it
|
||||
from teleport import kt_send_psbt
|
||||
ok = await kt_send_psbt(psbt)
|
||||
msg = 'Failed to Teleport' if not ok else 'Sent by Teleport'
|
||||
|
||||
else:
|
||||
assert isinstance(ch, dict) or input_method is None # SD/VDisk
|
||||
dis.fullscreen("Wait...")
|
||||
if ch is None:
|
||||
ch = {"force_vdisk": force_vdisk, "slot_b": slot_b}
|
||||
|
||||
if filename:
|
||||
_, basename = filename.rsplit('/', 1)
|
||||
base = basename.rsplit('.', 1)[0]
|
||||
else:
|
||||
base = fname_input_method
|
||||
|
||||
out2_fn = None
|
||||
out_fn = None
|
||||
|
||||
from glob import settings
|
||||
import os
|
||||
del_after = settings.get('del', 0)
|
||||
|
||||
while 1:
|
||||
# try to put back into same spot, but also do top-of-card
|
||||
if not is_complete:
|
||||
# keep the filename under control during multiple passes
|
||||
target_fname = base.replace('-part', '') + '-part.psbt'
|
||||
else:
|
||||
# add -signed to end. We won't offer to sign again.
|
||||
target_fname = base + '-signed.psbt'
|
||||
|
||||
try:
|
||||
with CardSlot(readonly=True, **ch) as card:
|
||||
out_full, out_fn = card.pick_filename(target_fname)
|
||||
out_path = out_full.rsplit("/", 1)[0] + "/"
|
||||
|
||||
except CardMissingError:
|
||||
prob = 'Missing card.\n\n'
|
||||
out_fn = None
|
||||
|
||||
if not out_fn:
|
||||
# need them to insert a card
|
||||
prob = ''
|
||||
else:
|
||||
# attempt write-out
|
||||
def _chunk_write(file_d, ofs, chunk=4096):
|
||||
written = 0
|
||||
while written < data_len:
|
||||
if (written + chunk) > data_len:
|
||||
chunk = data_len - written
|
||||
|
||||
file_d.write(PSRAM.read_at(ofs, chunk))
|
||||
written += chunk
|
||||
ofs += chunk
|
||||
|
||||
try:
|
||||
with CardSlot(**ch) as card:
|
||||
if is_complete and del_after:
|
||||
# don't write signed PSBT if we'd just delete it anyway
|
||||
out_fn = None
|
||||
else:
|
||||
with output_encoder(card.open(out_full, 'wb')) as fd:
|
||||
# save as updated PSBT
|
||||
if not is_complete:
|
||||
_chunk_write(fd, TXN_OUTPUT_OFFSET)
|
||||
else:
|
||||
psbt.serialize(fd)
|
||||
|
||||
if is_complete:
|
||||
# write out as hex too, if it's final
|
||||
out2_full, out2_fn = card.pick_filename(
|
||||
base + '-final.txn' if not del_after else 'tmp.txn',
|
||||
out_path)
|
||||
|
||||
if out2_full:
|
||||
with HexWriter(card.open(out2_full, 'w+t')) as fd:
|
||||
# save transaction, in hex
|
||||
if is_complete:
|
||||
_chunk_write(fd, TXN_OUTPUT_OFFSET)
|
||||
else:
|
||||
txid = psbt.finalize(fd)
|
||||
|
||||
if del_after:
|
||||
# rename it now that we know the txid
|
||||
after_full, out2_fn = card.pick_filename(
|
||||
txid + '.txn', out_path, overwrite=True)
|
||||
os.rename(out2_full, after_full)
|
||||
|
||||
if del_after:
|
||||
# this can do nothing if they swapped SDCard between steps, which is ok,
|
||||
# but if the original file is still there, this blows it away.
|
||||
# - if not yet final, the foo-part.psbt file stays
|
||||
try:
|
||||
card.securely_blank_file(filename)
|
||||
except: pass
|
||||
|
||||
# success and done!
|
||||
break
|
||||
|
||||
except OSError as exc:
|
||||
prob = 'Failed to write!\n\n%s\n\n' % exc
|
||||
sys.print_exception(exc)
|
||||
# fall through to try again
|
||||
|
||||
if force_vdisk:
|
||||
await ux_show_story(prob, title='Error')
|
||||
return
|
||||
|
||||
# prompt them to input another card?
|
||||
ch = await ux_show_story(
|
||||
prob + "Please insert an SDCard to receive signed transaction, "
|
||||
"and press OK.", title="Need Card")
|
||||
if ch == 'x':
|
||||
await ux_aborted()
|
||||
return
|
||||
|
||||
# done.
|
||||
if out_fn:
|
||||
msg = "Updated PSBT is:\n\n%s" % out_fn
|
||||
if out2_fn:
|
||||
msg += '\n\n'
|
||||
else:
|
||||
# del_after is probably set
|
||||
msg = ''
|
||||
|
||||
if out2_fn:
|
||||
msg += 'Finalized transaction (ready for broadcast):\n\n%s' % out2_fn
|
||||
if txid and not del_after:
|
||||
msg += '\n\nFinal TXID:\n' + txid
|
||||
# typical case: save to SD card, show filenames we used
|
||||
assert isinstance(ch, dict)
|
||||
msg = await _save_to_disk(psbt, txid, ch, is_complete, data_len, output_encoder, filename)
|
||||
if not msg:
|
||||
# it failed so start again with all possible options enabled.
|
||||
ch = None
|
||||
input_method = None
|
||||
first_time = False
|
||||
continue
|
||||
|
||||
msg += '\n\n'
|
||||
esc = '0'
|
||||
msg += 'Press (0) to save again by another method.'
|
||||
|
||||
if not is_complete and psbt.active_multisig and version.has_qwerty:
|
||||
# on Q, we can offer to "teleport" partly-signed file to othe other signers.
|
||||
msg += 'Press (T) to use Key Teleport to send PSBT to other co-signers. '
|
||||
esc += 't'
|
||||
|
||||
msg += 'Press (0) to re-export.'
|
||||
|
||||
ch = await ux_show_story(msg, title='PSBT Signed', escape=esc)
|
||||
|
||||
if ch == 't':
|
||||
from teleport import kt_send_psbt
|
||||
await kt_send_psbt(psbt)
|
||||
elif ch != '0':
|
||||
ch2 = await ux_show_story(msg, title='PSBT Signed', escape=esc)
|
||||
if ch2 != '0':
|
||||
break
|
||||
else:
|
||||
input_method = None
|
||||
n += 1
|
||||
first_time = False
|
||||
|
||||
async def _save_to_disk(psbt, txid, save_options, is_complete, data_len, output_encoder, filename=None):
|
||||
# Saving a PSBT from PSRAM to something disk-like.
|
||||
# - handle save-to-SD/VirtDisk cases. With re-attempt when no card, etc.
|
||||
assert isinstance(save_options, dict) # from import_export_prompt
|
||||
|
||||
from glob import dis, settings, PSRAM
|
||||
import os
|
||||
|
||||
dis.fullscreen("Wait...")
|
||||
|
||||
if filename:
|
||||
_, basename = filename.rsplit('/', 1)
|
||||
base = basename.rsplit('.', 1)[0]
|
||||
else:
|
||||
base = 'recent-txn'
|
||||
|
||||
# default encoding is binary
|
||||
output_encoder = output_encoder or (lambda x:x)
|
||||
|
||||
out2_fn = None
|
||||
out_fn = None
|
||||
|
||||
del_after = settings.get('del', 0)
|
||||
|
||||
def _chunk_write(file_d, ofs, chunk=4096):
|
||||
written = 0
|
||||
while written < data_len:
|
||||
if (written + chunk) > data_len:
|
||||
chunk = data_len - written
|
||||
|
||||
file_d.write(PSRAM.read_at(ofs, chunk))
|
||||
written += chunk
|
||||
ofs += chunk
|
||||
|
||||
while 1:
|
||||
# try to put back into same spot, but also do top-of-card
|
||||
if not is_complete:
|
||||
# keep the filename under control during multiple passes
|
||||
target_fname = base.replace('-part', '') + '-part.psbt'
|
||||
else:
|
||||
# add -signed to end. We won't offer to sign again.
|
||||
target_fname = base + '-signed.psbt'
|
||||
|
||||
# attempt write-out
|
||||
try:
|
||||
with CardSlot(**save_options) as card:
|
||||
out_full, out_fn = card.pick_filename(target_fname)
|
||||
out_path = out_full.rsplit("/", 1)[0] + "/"
|
||||
|
||||
if is_complete and del_after:
|
||||
# don't write signed PSBT if we'd just delete it anyway
|
||||
out_fn = None
|
||||
else:
|
||||
with output_encoder(card.open(out_full, 'wb')) as fd:
|
||||
# save as updated PSBT
|
||||
if not is_complete:
|
||||
_chunk_write(fd, TXN_OUTPUT_OFFSET)
|
||||
else:
|
||||
psbt.serialize(fd)
|
||||
|
||||
if is_complete:
|
||||
# write out as hex too, if it's final
|
||||
out2_full, out2_fn = card.pick_filename(
|
||||
base + '-final.txn' if not del_after else 'tmp.txn',
|
||||
out_path)
|
||||
|
||||
if out2_full:
|
||||
with HexWriter(card.open(out2_full, 'w+t')) as fd:
|
||||
# save transaction, in hex
|
||||
if is_complete:
|
||||
_chunk_write(fd, TXN_OUTPUT_OFFSET)
|
||||
else:
|
||||
txid = psbt.finalize(fd)
|
||||
|
||||
if del_after:
|
||||
# rename it now that we know the txid
|
||||
after_full, out2_fn = card.pick_filename(
|
||||
txid + '.txn', out_path, overwrite=True)
|
||||
os.rename(out2_full, after_full)
|
||||
|
||||
if del_after and filename:
|
||||
# this can do nothing if they swapped SDCard between steps, which is ok,
|
||||
# but if the original file is still there, this blows it away.
|
||||
# - if not yet final, the foo-part.psbt file stays
|
||||
try:
|
||||
card.securely_blank_file(filename)
|
||||
except: pass
|
||||
|
||||
# success and done!
|
||||
break
|
||||
|
||||
except CardMissingError:
|
||||
prob = 'Need a card!\n\n'
|
||||
|
||||
except OSError as exc:
|
||||
prob = 'Failed to write!\n\n%s\n\n' % exc
|
||||
sys.print_exception(exc)
|
||||
# fall through to try again
|
||||
|
||||
# If this point reached, some problem, we could not write.
|
||||
|
||||
if save_options.get('force_vdisk'):
|
||||
await ux_show_story(prob, title='Error')
|
||||
# they can't fix here, so give up
|
||||
return
|
||||
|
||||
# prompt them to input another card?
|
||||
ch = await ux_show_story(
|
||||
prob + "Please insert a card to receive signed transaction, "
|
||||
"and press OK.", title="Need Card")
|
||||
if ch == 'x':
|
||||
return
|
||||
|
||||
# Done, show the filenames we used.
|
||||
if out_fn:
|
||||
msg = "Updated PSBT is:\n\n%s" % out_fn
|
||||
if out2_fn:
|
||||
msg += '\n\n'
|
||||
else:
|
||||
# del_after is probably set
|
||||
msg = ''
|
||||
|
||||
if out2_fn:
|
||||
msg += 'Finalized transaction (ready for broadcast):\n\n%s' % out2_fn
|
||||
if txid and not del_after:
|
||||
msg += '\n\nFinal TXID:\n' + txid
|
||||
|
||||
return msg
|
||||
|
||||
|
||||
async def sign_psbt_file(filename, force_vdisk=False, slot_b=None, just_read=False, ux_abort=False):
|
||||
|
||||
@ -601,8 +601,13 @@ async def kt_send_psbt(psbt, psbt_len=None, post_signing=False):
|
||||
# - if from USB, we'd be uploading back, SD would be saved, etc
|
||||
return
|
||||
|
||||
ch = await ux_show_story("%d more signatures are still required. Press (T) to pick another co-signer to get it next using QR codes." % num_to_complete, title="Teleport PSBT?", escape='t')
|
||||
if ch != 't': return
|
||||
ch = await ux_show_story("%d more signatures are still required. Press (T) to pick another co-signer to sign next, using QR codes, or ENTER for other options." % num_to_complete, title="Teleport PSBT?", escape='t')
|
||||
if ch != 't':
|
||||
# ENTER/CANCEL both come here because we don't want to lose the PSBT
|
||||
# - they also do a "T" and teleport again
|
||||
from auth import done_signing
|
||||
await done_signing(psbt)
|
||||
return
|
||||
|
||||
|
||||
if not psbt_len:
|
||||
@ -681,6 +686,8 @@ async def kt_send_psbt(psbt, psbt_len=None, post_signing=False):
|
||||
await kt_do_send(rx_pubkey, 'p', raw=bin_psbt, prefix=ri, kp=kp,
|
||||
rx_label='[%s] co-signer' % xfp2str(m.next_xfp))
|
||||
|
||||
return True
|
||||
|
||||
async def kt_send_file_psbt(*a):
|
||||
# Menu item: choose a PSBT file from SD card, and send to co-signers.
|
||||
# Heavy code re-use here. Need to find the multisig wallet associated w/ file,
|
||||
|
||||
16
shared/ux.py
16
shared/ux.py
@ -392,7 +392,7 @@ def _import_prompt_builder(title, no_qr, no_nfc, slot_b_only=False):
|
||||
return prompt, escape
|
||||
|
||||
|
||||
def export_prompt_builder(what_it_is, no_qr=False, no_nfc=False, key0=None,
|
||||
def export_prompt_builder(what_it_is, no_qr=False, no_nfc=False, key0=None, offer_kt=False,
|
||||
force_prompt=False):
|
||||
# Build the prompt for export
|
||||
# - key0 can be for special stuff
|
||||
@ -401,7 +401,7 @@ def export_prompt_builder(what_it_is, no_qr=False, no_nfc=False, key0=None,
|
||||
|
||||
prompt, escape = None, KEY_CANCEL+"x"
|
||||
|
||||
if (NFC or VD) or (num_sd_slots>1) or key0 or force_prompt:
|
||||
if (NFC or VD) or (num_sd_slots>1) or key0 or force_prompt or offer_kt:
|
||||
# no need to spam with another prompt, only option is SD card
|
||||
|
||||
prompt = "Press (1) to save %s to SD Card" % what_it_is
|
||||
@ -431,6 +431,10 @@ def export_prompt_builder(what_it_is, no_qr=False, no_nfc=False, key0=None,
|
||||
prompt += ", (4) to show QR code"
|
||||
escape += '4'
|
||||
|
||||
if offer_kt:
|
||||
prompt += ", (T) to " + offer_kt
|
||||
escape += 't'
|
||||
|
||||
if key0:
|
||||
prompt += ', (0) ' + key0
|
||||
escape += '0'
|
||||
@ -471,19 +475,21 @@ def import_export_prompt_decode(ch):
|
||||
return dict(force_vdisk=force_vdisk, slot_b=slot_b)
|
||||
|
||||
async def import_export_prompt(what_it_is, is_import=False, no_qr=False,
|
||||
no_nfc=False, title=None, intro='', footnotes='',
|
||||
slot_b_only=False, force_prompt=False):
|
||||
no_nfc=False, title=None, intro='', footnotes='',
|
||||
offer_kt=False, slot_b_only=False, force_prompt=False):
|
||||
|
||||
# Show story allowing user to select source for importing/exporting
|
||||
# - return either str(mode) OR dict(file_args)
|
||||
# - KEY_NFC or KEY_QR for those sources
|
||||
# - KEY_CANCEL for abort by user
|
||||
# - dict() => do file system thing, using file_args to control vdisk vs. SD vs slot_b
|
||||
# - 't' => key teleport, but only offered with offer_kt is set (contetxt, and Q only)
|
||||
|
||||
if is_import:
|
||||
prompt, escape = _import_prompt_builder(what_it_is, no_qr, no_nfc, slot_b_only)
|
||||
else:
|
||||
prompt, escape = export_prompt_builder(what_it_is, no_qr, no_nfc,
|
||||
force_prompt=force_prompt)
|
||||
force_prompt=force_prompt, offer_kt=offer_kt)
|
||||
|
||||
# TODO: detect if we're only asking A or B, when just one card is inserted
|
||||
# - assume that's what they want to do
|
||||
|
||||
@ -809,6 +809,7 @@ def open_microsd(simulator, microsd_path):
|
||||
# open a file from the simulated microsd
|
||||
|
||||
def doit(fn, mode='rb'):
|
||||
assert fn, 'empty fname'
|
||||
return open(microsd_path(fn), mode)
|
||||
|
||||
return doit
|
||||
@ -928,7 +929,18 @@ def use_regtest(request, settings_set):
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def set_seed_words(sim_exec, sim_execfile, simulator, reset_seed_words):
|
||||
def set_seed_words(change_seed_words, reset_seed_words):
|
||||
def doit(w):
|
||||
return change_seed_words(w)
|
||||
|
||||
yield doit
|
||||
|
||||
# Important cleanup: restore normal key, because other tests assume that
|
||||
|
||||
reset_seed_words()
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def change_seed_words(sim_exec, sim_execfile, simulator):
|
||||
# load simulator w/ a specific bip32 master key
|
||||
|
||||
def doit(words):
|
||||
@ -943,30 +955,19 @@ def set_seed_words(sim_exec, sim_execfile, simulator, reset_seed_words):
|
||||
#print("sim xfp: 0x%08x" % simulator.master_fingerprint)
|
||||
return simulator.master_fingerprint
|
||||
|
||||
yield doit
|
||||
|
||||
# Important cleanup: restore normal key, because other tests assume that
|
||||
|
||||
reset_seed_words()
|
||||
return doit
|
||||
|
||||
@pytest.fixture()
|
||||
def reset_seed_words(sim_exec, sim_execfile, simulator):
|
||||
def reset_seed_words(change_seed_words):
|
||||
# load simulator w/ a specific bip39 seed phrase
|
||||
|
||||
def doit():
|
||||
words = simulator_fixed_words
|
||||
cmd = 'import main; main.WORDS = %r;' % words.split()
|
||||
sim_exec(cmd)
|
||||
rv = sim_execfile('devtest/set_seed.py')
|
||||
if rv: pytest.fail(rv)
|
||||
|
||||
simulator.start_encryption()
|
||||
simulator.check_mitm()
|
||||
new_xfp = change_seed_words(simulator_fixed_words)
|
||||
|
||||
#print("sim xfp: 0x%08x (reset)" % simulator.master_fingerprint)
|
||||
assert simulator.master_fingerprint == simulator_fixed_xfp
|
||||
assert new_xfp == simulator_fixed_xfp
|
||||
|
||||
return words
|
||||
return simulator_fixed_words
|
||||
|
||||
return doit
|
||||
|
||||
@ -1290,16 +1291,18 @@ def try_sign_microsd(open_microsd, cap_story, pick_menu_item, goto_home,
|
||||
else:
|
||||
assert False, 'timed out'
|
||||
|
||||
txid = None
|
||||
lines = story.split('\n')
|
||||
txid = None
|
||||
if 'Final TXID:' in lines:
|
||||
txid = lines[-1]
|
||||
result_fname = lines[-4]
|
||||
elif 'Key Teleport' in lines[-1]:
|
||||
# ignore "Press (T) to use Key Teleport to send PSBT to other co-signers" footer
|
||||
result_fname = lines[2]
|
||||
else:
|
||||
result_fname = lines[-2]
|
||||
txid = lines[lines.index('Final TXID:')+1]
|
||||
|
||||
# This is fragile!
|
||||
# ignore "Press (T) to use Key Teleport to send PSBT to other co-signers" footer
|
||||
# ignore "Press (0) to save again by..."
|
||||
# - want the .txn if present, else the .psbt file
|
||||
t, = [l for l in lines if l.endswith('.txn')] or [None]
|
||||
p, = [l for l in lines if l.endswith('.psbt')] or [None]
|
||||
result_fname = t or p
|
||||
|
||||
result = open_microsd(result_fname, 'rb').read()
|
||||
|
||||
@ -2024,7 +2027,7 @@ def signing_artifacts_reexport(cap_story, need_keypress, load_export, press_canc
|
||||
if txid:
|
||||
assert txid in story
|
||||
|
||||
assert "Press (0) to re-export." in story
|
||||
assert "Press (0) to save again" in story
|
||||
need_keypress("0")
|
||||
|
||||
to_do = ["sd", "vdisk", "nfc", "qr"]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# (c) Copyright 2020 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
||||
#
|
||||
# load up the simulator w/ indicated list of seed words
|
||||
# Load up the simulator w/ indicated list of seed words
|
||||
#
|
||||
from sim_settings import sim_defaults
|
||||
import stash, chains
|
||||
from pincodes import pa
|
||||
@ -11,7 +12,6 @@ from utils import xfp2str
|
||||
from actions import goto_top_menu
|
||||
from nvstore import SettingsObject
|
||||
|
||||
|
||||
tn = chains.BitcoinTestnet
|
||||
|
||||
stash.bip39_passphrase = ''
|
||||
@ -30,8 +30,9 @@ settings.set('words', len(main.WORDS))
|
||||
settings.set('terms_ok', True)
|
||||
settings.set('idle_to', 0)
|
||||
|
||||
print("New key in effect: %s" % settings.get('xpub', 'MISSING'))
|
||||
print(".. w/ fingerprint: %s" % xfp2str(settings.get('xfp', 0)))
|
||||
print("TESTING: New key in effect [%s]: %s..%s = %s" % (
|
||||
xfp2str(settings.get('xfp', 0)), main.WORDS[0], main.WORDS[-1],
|
||||
settings.get('xpub', 'MISSING')))
|
||||
|
||||
# impt: if going from xprv => seed words, main menu needs updating
|
||||
goto_top_menu()
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# (c) Copyright 2020 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
||||
#
|
||||
# load up the simulator w/ indicated test master key
|
||||
# load up the simulator w/ indicated test master key in TPRV format.
|
||||
#
|
||||
import main, ngu
|
||||
from sim_settings import sim_defaults
|
||||
import stash, chains
|
||||
@ -34,8 +35,9 @@ pa.change(new_secret=raw)
|
||||
pa.new_main_secret(raw)
|
||||
settings.set('words', False)
|
||||
|
||||
print("New key in effect: %s" % settings.get('xpub', 'MISSING'))
|
||||
print("Fingerprint: %s" % xfp2str(settings.get('xfp', 0)))
|
||||
|
||||
assert settings.get('xfp', 0) == swab32(node.my_fp())
|
||||
|
||||
print("TESTING: New tprv in effect [%s]: %s" % (
|
||||
settings.get('xpub', 'MISSING'),
|
||||
xfp2str(settings.get('xfp', 0))))
|
||||
|
||||
|
||||
@ -274,7 +274,7 @@ def try_sign_nfc(cap_story, pick_menu_item, goto_home, need_keypress,
|
||||
sim_exec('from pyb import SDCard; SDCard.ejected = False')
|
||||
|
||||
@pytest.fixture
|
||||
def ndef_parse_txn_psbt():
|
||||
def ndef_parse_txn_psbt(press_cancel):
|
||||
def doit(contents, txid=None, encoding='binary', expect_finalized=True):
|
||||
# from NFC data read, what did we get?
|
||||
got_txid = None
|
||||
|
||||
@ -1617,6 +1617,7 @@ def test_incomplete_signing(dev, try_sign, fake_txn, cap_story):
|
||||
oo.serialize(fd)
|
||||
mod_psbt = fd.getvalue()
|
||||
|
||||
raise pytest.xfail('issue #915 ')
|
||||
with pytest.raises(CCProtoError) as ee:
|
||||
orig, result = try_sign(mod_psbt, accept=True, finalize=True)
|
||||
|
||||
|
||||
@ -55,6 +55,7 @@ def grab_payload(press_select, need_keypress, press_cancel, nfc_read_url, cap_s
|
||||
else:
|
||||
press_select()
|
||||
|
||||
time.sleep(.1)
|
||||
title, story = cap_story()
|
||||
|
||||
assert 'Teleport' in title
|
||||
@ -349,6 +350,9 @@ def test_tx_seedvault(data, rx_start, tx_start, cap_menu, enter_complex, pick_me
|
||||
pick_menu_item('Restore Master')
|
||||
press_select()
|
||||
|
||||
time.sleep(.1)
|
||||
assert settings_get('xfp', -1) == simulator_fixed_xfp
|
||||
|
||||
def test_rx_truncated(rx_start, tx_start, cap_menu, enter_complex, pick_menu_item, rx_complete, cap_story, press_cancel, press_select):
|
||||
# Truncate the RX Code
|
||||
code, rx_pubkey = rx_start()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user