Zeus Export
This commit is contained in:
parent
ab894d174d
commit
524e40512c
@ -5,7 +5,8 @@
|
||||
- Enhancement: Allow to specify start index for address explorer export and browsing
|
||||
- Enhancement: Allow unlimited index for BIP-85 derivations. Needs to be enabled first in `Danger Zone`
|
||||
- Enhancement: Add `Nunchuk` option to `Export Wallet`
|
||||
- Enhancement: `View Identity` shows temporary seed active on the top
|
||||
- Enhancement: Add `Zeus` option to `Export Wallet`
|
||||
- Enhancement: `View Identity` shows temporary seed active on the top
|
||||
- Change: `Passphrase` menu item is no longer offered if BIP39 passphrase
|
||||
already in use. Use `Restore Master` with ability to keep or purge current
|
||||
passphrase wallet settings.
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
|
||||
- Enhancement: Allow to specify start index for address explorer export and browsing
|
||||
- Enhancement: Add `Nunchuk` option to `Export Wallet`
|
||||
- Enhancement: Add `Zeus` option to `Export Wallet`
|
||||
- Enhancement: `View Identity` shows temporary seed active on the top
|
||||
- Change: `Passphrase` menu item is no longer offered if BIP39 passphrase
|
||||
already in use. Use `Restore Master` with ability to keep or purge current
|
||||
|
||||
@ -8,7 +8,7 @@ import ckcc, pyb, version, uasyncio, sys, uos
|
||||
from uhashlib import sha256
|
||||
from uasyncio import sleep_ms
|
||||
from ubinascii import hexlify as b2a_hex
|
||||
from utils import imported, pretty_short_delay, problem_file_line, get_filesize
|
||||
from utils import imported, problem_file_line, get_filesize
|
||||
from utils import xfp2str, B2A, addr_fmt_label
|
||||
from ux import ux_show_story, the_ux, ux_confirm, ux_dramatic_pause, ux_aborted
|
||||
from ux import ux_enter_bip32_index, ux_input_text, import_export_prompt
|
||||
@ -1079,29 +1079,29 @@ async def electrum_skeleton(*a):
|
||||
elif ch != 'y':
|
||||
return
|
||||
|
||||
# pick segwit or classic derivation+such
|
||||
# - Ordering and terminology from similar screen in Electrum.
|
||||
rv = []
|
||||
|
||||
rv.append(MenuItem(addr_fmt_label(AF_CLASSIC), f=electrum_skeleton_step2,
|
||||
arg=(AF_CLASSIC, account_num)))
|
||||
rv.append(MenuItem(addr_fmt_label(AF_P2WPKH_P2SH), f=electrum_skeleton_step2,
|
||||
arg=(AF_P2WPKH_P2SH, account_num)))
|
||||
rv.append(MenuItem(addr_fmt_label(AF_P2WPKH), f=electrum_skeleton_step2,
|
||||
arg=(AF_P2WPKH, account_num)))
|
||||
|
||||
rv = [
|
||||
MenuItem(addr_fmt_label(af), f=electrum_skeleton_step2,
|
||||
arg=(af, account_num))
|
||||
for af in [AF_P2WPKH, AF_CLASSIC, AF_P2WPKH_P2SH]
|
||||
]
|
||||
the_ux.push(MenuSystem(rv))
|
||||
|
||||
def ss_descriptor_export_story(addition="", background=None):
|
||||
def ss_descriptor_export_story(addition="", background="", acct=True):
|
||||
# saves memory being in a function
|
||||
return ("This saves a ranged xpub descriptor" + addition
|
||||
+ (background or
|
||||
'. Choose descriptor and address type for the wallet on next screens.'+PICK_ACCOUNT)
|
||||
+ background
|
||||
+ (PICK_ACCOUNT if acct else "")
|
||||
+ SENSITIVE_NOT_SECRET)
|
||||
|
||||
async def ss_descriptor_skeleton(label, _, item):
|
||||
async def ss_descriptor_skeleton(_0, _1, item):
|
||||
# Export of descriptor data (wallet)
|
||||
ch = await ux_show_story(ss_descriptor_export_story(), escape='1')
|
||||
int_ext, addition = None, ""
|
||||
allowed_af = [AF_P2WPKH, AF_CLASSIC, AF_P2WPKH_P2SH]
|
||||
if item.arg:
|
||||
int_ext, allowed_af, ll = item.arg
|
||||
addition = " for " + ll
|
||||
|
||||
ch = await ux_show_story(ss_descriptor_export_story(addition), escape='1')
|
||||
|
||||
account_num = 0
|
||||
if ch == '1':
|
||||
@ -1109,27 +1109,24 @@ async def ss_descriptor_skeleton(label, _, item):
|
||||
elif ch != 'y':
|
||||
return
|
||||
|
||||
int_ext = True
|
||||
ch = await ux_show_story(
|
||||
"To export receiving and change descriptors in one descriptor (<0;1> notation) press OK, "
|
||||
"press (1) to export receiving and change descriptors separately.", escape='1')
|
||||
if ch == "1":
|
||||
int_ext = False
|
||||
elif ch != "y":
|
||||
return
|
||||
if int_ext is None:
|
||||
ch = await ux_show_story(
|
||||
"To export receiving and change descriptors in one descriptor "
|
||||
"(<0;1> notation) press OK, press (1) to export "
|
||||
"receiving and change descriptors separately.", escape='1')
|
||||
if ch == "x": return
|
||||
int_ext = False if ch == "1" else True
|
||||
|
||||
# pick segwit or classic derivation+such
|
||||
# - Ordering and terminology from similar screen in Electrum.
|
||||
rv = []
|
||||
|
||||
rv.append(MenuItem(addr_fmt_label(AF_CLASSIC), f=descriptor_skeleton_step2,
|
||||
arg=(AF_CLASSIC, account_num, int_ext)))
|
||||
rv.append(MenuItem(addr_fmt_label(AF_P2WPKH_P2SH), f=descriptor_skeleton_step2,
|
||||
arg=(AF_P2WPKH_P2SH, account_num, int_ext)))
|
||||
rv.append(MenuItem(addr_fmt_label(AF_P2WPKH), f=descriptor_skeleton_step2,
|
||||
arg=(AF_P2WPKH, account_num, int_ext)))
|
||||
|
||||
the_ux.push(MenuSystem(rv))
|
||||
if len(allowed_af) == 1:
|
||||
await make_descriptor_wallet_export(allowed_af[0], account_num,
|
||||
int_ext=int_ext)
|
||||
else:
|
||||
rv = [
|
||||
MenuItem(addr_fmt_label(af), f=descriptor_skeleton_step2,
|
||||
arg=(af, account_num, int_ext))
|
||||
for af in allowed_af
|
||||
]
|
||||
the_ux.push(MenuSystem(rv))
|
||||
|
||||
async def samourai_post_mix_descriptor_export(*a):
|
||||
name = "POST-MIX"
|
||||
@ -1150,7 +1147,7 @@ async def samourai_account_descriptor(name, account_num):
|
||||
ch = await ux_show_story(
|
||||
ss_descriptor_export_story(
|
||||
addition=" for Samourai %s account." % name,
|
||||
background=" ")
|
||||
acct=False)
|
||||
)
|
||||
|
||||
if ch != 'y':
|
||||
|
||||
@ -139,8 +139,7 @@ async def write_text_file(fname_pattern, body, title, derive, addr_fmt):
|
||||
from ux import import_export_prompt
|
||||
|
||||
choice = await import_export_prompt("%s file" % title, is_import=False,
|
||||
no_qr=(not version.has_qwerty))
|
||||
|
||||
no_qr=(not version.has_qwerty))
|
||||
if choice == KEY_CANCEL:
|
||||
return
|
||||
elif choice == KEY_QR:
|
||||
|
||||
@ -171,6 +171,8 @@ WalletExportMenu = [
|
||||
MenuItem("Bitcoin Core", f=bitcoin_core_skeleton),
|
||||
MenuItem("Sparrow Wallet", f=named_generic_skeleton, arg="Sparrow"),
|
||||
MenuItem("Nunchuk", f=named_generic_skeleton, arg="Nunchuk"),
|
||||
MenuItem("Zeus", f=ss_descriptor_skeleton,
|
||||
arg=(True, [AF_P2WPKH, AF_P2WPKH_P2SH], "Zeus Wallet")),
|
||||
MenuItem("Electrum Wallet", f=electrum_skeleton),
|
||||
MenuItem("Wasabi Wallet", f=wasabi_skeleton),
|
||||
MenuItem("Unchained", f=unchained_capital_export),
|
||||
|
||||
@ -16,7 +16,7 @@ from helpers import xfp2str, slip132undo
|
||||
from conftest import simulator_fixed_xfp, simulator_fixed_tprv, simulator_fixed_words
|
||||
from ckcc_protocol.constants import AF_CLASSIC, AF_P2WPKH
|
||||
from pprint import pprint
|
||||
from charcodes import KEY_NFC
|
||||
from charcodes import KEY_NFC, KEY_QR
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -571,9 +571,8 @@ def test_export_xpub(use_nfc, acct_num, dev, cap_menu, pick_menu_item, goto_home
|
||||
@pytest.mark.parametrize("acct_num", [None, 0, 1, (2 ** 31) - 1])
|
||||
@pytest.mark.parametrize("int_ext", [True, False])
|
||||
def test_generic_descriptor_export(chain, addr_fmt, acct_num, goto_home, settings_set, need_keypress,
|
||||
pick_menu_item, way, cap_story, cap_menu, nfc_read_text, int_ext,
|
||||
microsd_path, settings_get, virtdisk_path, load_export, press_select,
|
||||
mk4_qr_not_allowed):
|
||||
pick_menu_item, way, cap_story, cap_menu, int_ext, settings_get,
|
||||
virtdisk_path, load_export, press_select, mk4_qr_not_allowed):
|
||||
mk4_qr_not_allowed(way)
|
||||
|
||||
settings_set('chain', chain)
|
||||
@ -585,7 +584,6 @@ def test_generic_descriptor_export(chain, addr_fmt, acct_num, goto_home, setting
|
||||
time.sleep(.1)
|
||||
_, story = cap_story()
|
||||
assert "This saves a ranged xpub descriptor" in story
|
||||
assert "Choose descriptor and address type for the wallet on next screens" in story
|
||||
assert "Press (1) to enter a non-zero account number" in story
|
||||
assert "sensitive--in terms of privacy" in story
|
||||
assert "not compromise your funds directly" in story
|
||||
@ -646,6 +644,89 @@ def test_generic_descriptor_export(chain, addr_fmt, acct_num, goto_home, setting
|
||||
assert xpub_target in xpub
|
||||
|
||||
|
||||
@pytest.mark.parametrize("chain", ["BTC", "XTN"])
|
||||
@pytest.mark.parametrize("way", ["nfc", "qr"])
|
||||
@pytest.mark.parametrize("addr_fmt", [AF_P2WPKH, AF_P2WPKH_P2SH])
|
||||
@pytest.mark.parametrize("acct_num", [None, 55])
|
||||
def test_zeus_descriptor_export(addr_fmt, acct_num, goto_home, need_keypress, pick_menu_item,
|
||||
way, cap_story, cap_menu, nfc_read_text, settings_get, chain,
|
||||
virtdisk_path, load_export, press_select, mk4_qr_not_allowed,
|
||||
settings_set, is_q1, press_cancel, cap_screen_qr, press_nfc):
|
||||
|
||||
mk4_qr_not_allowed(way)
|
||||
settings_set('chain', chain)
|
||||
chain_num = 1 if chain == "XTN" else 0
|
||||
|
||||
goto_home()
|
||||
pick_menu_item("Advanced/Tools")
|
||||
pick_menu_item("Export Wallet")
|
||||
pick_menu_item("Zeus")
|
||||
time.sleep(.1)
|
||||
title, story = cap_story()
|
||||
|
||||
assert "This saves a ranged xpub descriptor" in story
|
||||
assert "Press (1) to enter a non-zero account number" in story
|
||||
assert "sensitive--in terms of privacy" in story
|
||||
assert "not compromise your funds directly" in story
|
||||
|
||||
if isinstance(acct_num, int):
|
||||
need_keypress("1") # chosse account number
|
||||
for ch in str(acct_num):
|
||||
need_keypress(ch) # input num
|
||||
press_select() # confirm selection
|
||||
else:
|
||||
press_select() # confirm story
|
||||
|
||||
time.sleep(.1)
|
||||
menu = cap_menu()
|
||||
assert len(menu) == 2
|
||||
if addr_fmt == AF_P2WPKH:
|
||||
menu_item = "Segwit P2WPKH"
|
||||
desc_prefix = "wpkh("
|
||||
bip44_purpose = 84
|
||||
else:
|
||||
assert addr_fmt == AF_P2WPKH_P2SH
|
||||
menu_item = "P2SH-Segwit"
|
||||
desc_prefix = "sh(wpkh("
|
||||
bip44_purpose = 49
|
||||
|
||||
assert menu_item in menu
|
||||
pick_menu_item(menu_item)
|
||||
|
||||
time.sleep(.1)
|
||||
title, story = cap_story()
|
||||
|
||||
if way == "qr":
|
||||
assert ("%s to show QR" % (KEY_QR if is_q1 else "(4)")) in story
|
||||
need_keypress(KEY_QR if is_q1 else "4")
|
||||
time.sleep(.2)
|
||||
contents = cap_screen_qr().decode('ascii')
|
||||
else:
|
||||
assert ("ress %s to share via NFC" % (KEY_NFC if is_q1 else "(3)")) in story
|
||||
press_nfc()
|
||||
time.sleep(.2)
|
||||
contents = nfc_read_text()
|
||||
time.sleep(.5)
|
||||
press_cancel() # exit NFC animation
|
||||
|
||||
descriptor = contents.strip()
|
||||
|
||||
assert descriptor.startswith(desc_prefix)
|
||||
desc_obj = Descriptor.parse(descriptor)
|
||||
assert desc_obj.serialize(int_ext=True) == descriptor
|
||||
assert desc_obj.addr_fmt == addr_fmt
|
||||
assert len(desc_obj.keys) == 1
|
||||
xfp, derive, xpub = desc_obj.keys[0]
|
||||
assert xfp == settings_get("xfp")
|
||||
assert derive == f"m/{bip44_purpose}h/{chain_num}h/{acct_num if acct_num is not None else 0}h"
|
||||
seed = Mnemonic.to_seed(simulator_fixed_words)
|
||||
node = BIP32Node.from_master_secret(
|
||||
seed, netcode="BTC" if chain == "BTC" else "XTN"
|
||||
).subkey_for_path(derive[2:].replace("h", "H"))
|
||||
xpub_target = node.hwif()
|
||||
assert xpub_target in xpub
|
||||
|
||||
|
||||
@pytest.mark.parametrize("chain", ["BTC", "XTN", "XRT"])
|
||||
@pytest.mark.parametrize("account", ["Postmix", "Premix"])
|
||||
def test_samourai_vs_generic(chain, account, settings_set, pick_menu_item, goto_home,
|
||||
@ -680,7 +761,6 @@ def test_samourai_vs_generic(chain, account, settings_set, pick_menu_item, goto_
|
||||
_, story = cap_story()
|
||||
assert "This saves a ranged xpub descriptor" in story
|
||||
assert in_story in story
|
||||
assert "Choose an address type for the wallet on the next screen" not in story # NOT
|
||||
assert "Press 1 to enter a non-zero account number" not in story # NOT
|
||||
assert "sensitive--in terms of privacy" in story
|
||||
assert "not compromise your funds directly" in story
|
||||
|
||||
Loading…
Reference in New Issue
Block a user