option to show/export full multisig addresses; do not return to home menu after setting unsort_ms

(cherry picked from commit 9b597592bc)
This commit is contained in:
scgbckbone 2025-01-28 11:42:22 +01:00
parent 7134f03eab
commit 6d4a4f4eaa
6 changed files with 35 additions and 26 deletions

View File

@ -17,6 +17,7 @@ This lists the new changes that have not yet been published in a normal release.
- Enhancement: Catch more DeltaMode cases in XOR path.
Thanks to [@dmonakhov](https://github.com/dmonakhov))
- Enhancement: BKPW override (for "developers")
- Enhancement: Add option to show/export full multisg addresses. Enable in `Settings->Multisig Wallets->Full Address View`.
- Change: If derivation path is omitted during message signing, default is used
based on address format (`m/44h/0h/0h/0/0` for p2pkh, and `m/84h/0h/0h/0/0` for p2wpkh).
Default is no longer root (m).

View File

@ -8,14 +8,13 @@ import chains, stash, version
from ux import ux_show_story, the_ux, ux_enter_bip32_index
from ux import export_prompt_builder, import_export_prompt_decode
from menu import MenuSystem, MenuItem
from public_constants import AFC_BECH32, AFC_BECH32M, AF_CLASSIC, AF_P2WPKH, AF_P2WPKH_P2SH, AF_P2TR
from public_constants import AFC_BECH32, AFC_BECH32M, AF_P2WPKH, AF_P2TR
from multisig import MultisigWallet
from miniscript import MiniScriptWallet
from uasyncio import sleep_ms
from uhashlib import sha256
from glob import settings
from auth import write_sig_file
from utils import censor_address
from charcodes import KEY_QR, KEY_NFC, KEY_PAGE_UP, KEY_PAGE_DOWN, KEY_HOME, KEY_LEFT, KEY_RIGHT
from charcodes import KEY_CANCEL
@ -188,7 +187,7 @@ class AddressListMenu(MenuSystem):
deriv = path.format(account=self.account_num, change=0, idx=self.start)
node = sv.derive_path(deriv, register=False)
address = chain.address(node, addr_fmt)
choices.append( (truncate_address(address), path, addr_fmt) )
choices.append((truncate_address(address), path, addr_fmt))
dis.progress_sofar(len(choices), len(chains.CommonDerivations))

View File

@ -13,7 +13,7 @@ from descriptor import Descriptor
from miniscript import Key, Sortedmulti, Number, Multi
from desc_utils import multisig_descriptor_template
from public_constants import AF_P2SH, AF_P2WSH_P2SH, AF_P2WSH, AFC_SCRIPT, MAX_SIGNERS, AF_P2TR
from menu import MenuSystem, MenuItem, NonDefaultMenuItem
from menu import MenuSystem, MenuItem, NonDefaultMenuItem, start_chooser, ToggleMenuItem
from opcodes import OP_CHECKMULTISIG
from exceptions import FatalPSBTIssue
from glob import settings
@ -1172,7 +1172,6 @@ def disable_checks_chooser():
return int(MultisigWallet.disable_checks), ch, xset
async def disable_checks_menu(*a):
from menu import start_chooser
if not MultisigWallet.disable_checks:
ch = await ux_show_story('''\
@ -1205,7 +1204,6 @@ def psbt_xpubs_policy_chooser():
async def trust_psbt_menu(*a):
# show a story then go into chooser
from menu import start_chooser
ch = await ux_show_story('''\
This setting controls what the Coldcard does \
@ -1230,18 +1228,16 @@ exists, otherwise 'Verify'.''')
if ch == 'x': return
start_chooser(psbt_xpubs_policy_chooser)
def unsorted_ms_chooser():
ch = ['Do Not Allow', 'Allow']
def unsort_ms_chooser():
def xset(idx, text):
settings.set('unsort_ms', idx)
from actions import goto_top_menu
goto_top_menu()
if idx:
settings.set('unsort_ms', idx)
else:
settings.remove_key('unsort_ms')
return settings.get('unsort_ms', 0), ch, xset
return settings.get('unsort_ms', 0), ['Do Not Allow', 'Allow'], xset
async def unsorted_ms_menu(*a):
from menu import start_chooser
if not settings.get("unsort_ms", None):
ch = await ux_show_story(
@ -1269,7 +1265,7 @@ async def unsorted_ms_menu(*a):
)
return
start_chooser(unsorted_ms_chooser)
start_chooser(unsort_ms_chooser)
class MultisigMenu(MenuSystem):

View File

@ -65,6 +65,7 @@ from utils import call_later_ms
# ptxurl = (str) URL for PushTx feature, clear to disable feature
# hmx = (bool) Force display of current XFP in home menu, even w/o tmp seed active
# unsort_ms = (bool) Allow unsorted multisig with BIP-67 disabled
# msas = multisig address show (do not censor multisig addresses)
# Stored w/ key=00 for access before login
# _skip_pin = hard code a PIN value (dangerous, only for debug)
@ -86,7 +87,7 @@ from utils import call_later_ms
# keep these settings only if unspecified on the other end
KEEP_IF_BLANK_SETTINGS = ["wa", "sighshchk", "emu", "rz", "b39skip",
"axskip", "del", "pms", "idle_to", "batt_to",
"bright"]
"bright", "msas"]
SEEDVAULT_FIELDS = ['seeds', 'seedvault', 'xfp', 'words', "bkpw"]

View File

@ -945,8 +945,9 @@ def reset_seed_words(sim_exec, sim_execfile, simulator):
@pytest.fixture()
def settings_set(sim_exec):
def doit(key, val):
x = sim_exec("settings.set('%s', %r)" % (key, val))
def doit(key, val, prelogin=False):
source = "from nvstore import SettingsObject;SettingsObject.prelogin()" if prelogin else "settings"
x = sim_exec("%s.set('%s', %r)" % (source, key, val))
assert x == ''
return doit
@ -954,8 +955,9 @@ def settings_set(sim_exec):
@pytest.fixture()
def settings_get(sim_exec):
def doit(key, def_val=None):
cmd = f"RV.write(repr(settings.get('{key}', {def_val!r})))"
def doit(key, def_val=None, prelogin=False):
source = "from nvstore import SettingsObject;SettingsObject.prelogin()" if prelogin else "settings"
cmd = f"RV.write(repr({source}.get('{key}', {def_val!r})))"
resp = sim_exec(cmd)
assert 'Traceback' not in resp, resp
return eval(resp)

View File

@ -12,7 +12,7 @@ from ckcc.protocol import CCProtocolPacker, MAX_TXN_LEN
from pprint import pprint
from base64 import b64encode, b64decode
from base58 import encode_base58_checksum
from helpers import B2A, fake_dest_addr, xfp2str, detruncate_address
from helpers import B2A, fake_dest_addr, xfp2str
from helpers import path_to_str, str_to_path, slip132undo, swab32, hash160
from struct import unpack, pack
from constants import *
@ -1266,7 +1266,7 @@ def make_myself_wallet(dev, set_bip39_pw, offer_ms_import, press_select, clear_m
title, story = offer_ms_import(config)
#print(story)
# dont care if update or create; accept it.
# don't care if update or create; accept it.
time.sleep(.1)
press_select()
@ -2288,11 +2288,12 @@ def test_bitcoind_ms_address(change, M_N, addr_fmt, clear_ms, goto_home, need_ke
pick_menu_item, cap_menu, cap_story, make_multisig, import_ms_wallet,
microsd_path, bitcoind_d_wallet_w_sk, use_regtest, load_export, way,
is_q1, press_select, start_idx, settings_set, set_addr_exp_start_idx,
desc):
desc, garbage_collector, virtdisk_path):
use_regtest()
clear_ms()
bitcoind = bitcoind_d_wallet_w_sk
M, N = M_N
path_f = microsd_path if way == "sd" else virtdisk_path
# whether to import as descriptor or old school to CC
descriptor = random.choice([True, False])
bip67 = True
@ -2343,7 +2344,12 @@ def test_bitcoind_ms_address(change, M_N, addr_fmt, clear_ms, goto_home, need_ke
assert "change addresses." not in story
assert "(0)" not in story
contents = load_export(way, label="Address summary", is_json=False, sig_check=False)
if way != "nfc":
contents, exp_fname = load_export(way, label="Address summary", is_json=False,
sig_check=False, ret_fname=True)
garbage_collector.append(path_f(exp_fname))
else:
contents = load_export(way, label="Address summary", is_json=False, sig_check=False)
addr_cont = contents.strip()
goto_home()
pick_menu_item('Settings')
@ -2351,7 +2357,12 @@ def test_bitcoind_ms_address(change, M_N, addr_fmt, clear_ms, goto_home, need_ke
press_select() # only one enrolled multisig - choose it
pick_menu_item('Descriptors')
pick_menu_item("Bitcoin Core")
contents = load_export(way, label="Bitcoin Core multisig setup", is_json=False, sig_check=False)
if way != "nfc":
contents, exp_fname = load_export(way, label="Bitcoin Core multisig setup", is_json=False,
sig_check=False, ret_fname=True)
garbage_collector.append(path_f(exp_fname))
else:
contents = load_export(way, label="Bitcoin Core multisig setup", is_json=False, sig_check=False)
text = contents.replace("importdescriptors ", "").strip()
# remove junk
r1 = text.find("[")
@ -2521,7 +2532,6 @@ def bitcoind_multisig(bitcoind, bitcoind_d_sim_watch, need_keypress, cap_story,
def test_legacy_multisig_witness_utxo_in_psbt(bitcoind, use_regtest, clear_ms, microsd_wipe, goto_home, need_keypress,
pick_menu_item, cap_story, load_export, microsd_path, cap_menu, try_sign,
is_q1, press_select):
use_regtest()
clear_ms()
microsd_wipe()