optimize PSBT class
This commit is contained in:
parent
5a27fcc45a
commit
4439f3d7fe
@ -356,31 +356,20 @@ class ApproveTransaction(UserAuthorizedAction):
|
||||
# Do some analysis/ validation
|
||||
try:
|
||||
await self.psbt.validate() # might do UX: accept multisig import
|
||||
dis.progress_sofar(10, 100)
|
||||
|
||||
# consider_keys only needs num_our_keys to be set
|
||||
# it set during psbt.validate()
|
||||
self.psbt.consider_keys()
|
||||
dis.progress_sofar(20, 100)
|
||||
|
||||
ccc_c_xfp = CCCFeature.get_xfp() # can be None
|
||||
self.psbt.consider_inputs(cosign_xfp=ccc_c_xfp)
|
||||
dis.progress_sofar(50, 100)
|
||||
|
||||
self.psbt.consider_outputs()
|
||||
dis.progress_sofar(75, 100)
|
||||
|
||||
self.psbt.consider_dangerous_sighash()
|
||||
dis.progress_sofar(90, 100)
|
||||
self.psbt.consider_outputs(cosign_xfp=ccc_c_xfp)
|
||||
|
||||
except FraudulentChangeOutput as exc:
|
||||
# sys.print_exception(exc)
|
||||
#print('FraudulentChangeOutput: ' + exc.args[0])
|
||||
return await self.failure(exc.args[0], title='Change Fraud')
|
||||
except FatalPSBTIssue as exc:
|
||||
#print('FatalPSBTIssue: ' + exc.args[0])
|
||||
return await self.failure(exc.args[0])
|
||||
except BaseException as exc:
|
||||
sys.print_exception(exc)
|
||||
# sys.print_exception(exc)
|
||||
del self.psbt
|
||||
gc.collect()
|
||||
|
||||
@ -932,7 +921,7 @@ async def _save_to_disk(psbt, txid, save_options, is_complete, data_len, output_
|
||||
|
||||
del_after = settings.get('del', 0)
|
||||
|
||||
def _chunk_write(file_d, ofs, chunk=4096):
|
||||
def _chunk_write(file_d, ofs, chunk=1024):
|
||||
written = 0
|
||||
while written < data_len:
|
||||
if (written + chunk) > data_len:
|
||||
|
||||
@ -393,8 +393,8 @@ class Key:
|
||||
return cls.from_cc_data(vals["xfp"], vals["%s_deriv" % af_str], ek)
|
||||
|
||||
@classmethod
|
||||
def from_psbt_xpub(cls, pth, ek_bytes):
|
||||
xfp, *path = ustruct.unpack_from('<%dI' % (len(pth)//4), pth, 0)
|
||||
def from_psbt_xpub(cls, ek_bytes, xfp_path):
|
||||
xfp, *path = xfp_path
|
||||
koi = KeyOriginInfo(a2b_hex(xfp2str(xfp)), path)
|
||||
# TODO this should be done by C code, no need to base58 encode/decode
|
||||
# byte-serialized key should be decodable
|
||||
|
||||
@ -349,7 +349,7 @@ class ApprovalRule:
|
||||
# we are verifying the whole consensus-encoded txout
|
||||
txo_bytes = CTxOut(txo.nValue, txo.scriptPubKey).serialize()
|
||||
digest = chain.hash_message(txo_bytes)
|
||||
addr_fmt, pubkey = chains.verify_recover_pubkey(o.attestation, digest)
|
||||
addr_fmt, pubkey = chains.verify_recover_pubkey(psbt.get(o.attestation), digest)
|
||||
# we have extracted a valid pubkey from the sig, but is it
|
||||
# a whitelisted pubkey or something else?
|
||||
ver_addr = chain.pubkey_to_address(pubkey, addr_fmt)
|
||||
@ -372,11 +372,11 @@ class ApprovalRule:
|
||||
|
||||
# check the self-transfer percentage
|
||||
if self.min_pct_self_transfer:
|
||||
own_in_value = sum([i.amount for i in psbt.inputs if i.num_our_keys])
|
||||
own_in_value = sum([i.amount for i in psbt.inputs if i.sp_idxs])
|
||||
own_out_value = 0
|
||||
for idx, txo in psbt.output_iter():
|
||||
o = psbt.outputs[idx]
|
||||
if o.num_our_keys:
|
||||
if o.sp_idxs:
|
||||
own_out_value += txo.nValue
|
||||
percentage = (float(own_out_value) / own_in_value) * 100.0
|
||||
assert percentage >= self.min_pct_self_transfer, 'does not meet self transfer threshold, expected: %.2f, actual: %.2f' % (self.min_pct_self_transfer, percentage)
|
||||
@ -387,8 +387,8 @@ class ApprovalRule:
|
||||
assert len(psbt.inputs) == len(psbt.outputs), 'unequal number of inputs and outputs'
|
||||
|
||||
if "EQ_NUM_OWN_INS_OUTS" in self.patterns:
|
||||
own_ins = sum([1 for i in psbt.inputs if i.num_our_keys])
|
||||
own_outs = sum([1 for o in psbt.outputs if o.num_our_keys])
|
||||
own_ins = sum([1 for i in psbt.inputs if i.sp_idxs])
|
||||
own_outs = sum([1 for o in psbt.outputs if o.sp_idxs])
|
||||
assert own_ins == own_outs, 'unequal number of own inputs and outputs'
|
||||
|
||||
if "EQ_OUT_AMOUNTS" in self.patterns:
|
||||
@ -488,7 +488,7 @@ class HSMPolicy:
|
||||
# a list of paths we can accept for signing
|
||||
self.msg_paths = pop_deriv_list(j, 'msg_paths', ['any'])
|
||||
self.share_xpubs = pop_deriv_list(j, 'share_xpubs', ['any'])
|
||||
self.share_addrs = pop_deriv_list(j, 'share_addrs', ['p2sh', 'any', 'msas'])
|
||||
self.share_addrs = pop_deriv_list(j, 'share_addrs', ['any', 'msas'])
|
||||
|
||||
# free text shown at top
|
||||
self.notes = pop_string(j, 'notes', 1, 80)
|
||||
@ -573,7 +573,7 @@ class HSMPolicy:
|
||||
fd.write('\n')
|
||||
|
||||
def plist(pl):
|
||||
remap = {'any': '(any path)', 'p2sh': '(any P2SH)' }
|
||||
remap = {'any': '(any path)', 'msas': '(any miniscript)' }
|
||||
return ' OR '.join(remap.get(i, i) for i in pl)
|
||||
|
||||
fd.write('\nMessage signing:\n')
|
||||
@ -603,7 +603,7 @@ class HSMPolicy:
|
||||
fd.write('- XPUB values will be shared, if path matches: m OR %s.\n'
|
||||
% plist(self.share_xpubs))
|
||||
if self.share_addrs:
|
||||
fd.write('- Address values values will be shared, if path matches: %s.\n'
|
||||
fd.write('- Address values will be shared, if path matches: %s.\n'
|
||||
% plist(self.share_addrs))
|
||||
if self.priv_over_ux:
|
||||
fd.write('- Status responses optimized for privacy.\n')
|
||||
|
||||
1384
shared/psbt.py
1384
shared/psbt.py
File diff suppressed because it is too large
Load Diff
@ -754,8 +754,6 @@ async def kt_send_file_psbt(*a):
|
||||
psbt.consider_inputs()
|
||||
dis.progress_sofar(3, 4)
|
||||
|
||||
psbt.consider_keys()
|
||||
|
||||
except Exception as exc:
|
||||
# not going to do full reporting here, use our other code for that!
|
||||
await ux_show_story("Cannot validate PSBT?\n\n"+str(exc), "PSBT Load Failed")
|
||||
|
||||
@ -53,7 +53,7 @@ HSM_WHITELIST = frozenset({
|
||||
'blkc', 'hsts', # report status values
|
||||
'stok', 'smok', # completion check: sign txn or msg
|
||||
'xpub', 'msck', # quick status checks
|
||||
'p2sh', 'show', 'msas', # limited by HSM policy
|
||||
'show', 'msas', # limited by HSM policy
|
||||
'user', # auth HSM user, other user cmds not allowed
|
||||
'gslr', # read storage locker; hsm mode only, limited usage
|
||||
})
|
||||
|
||||
@ -510,8 +510,8 @@ class MiniScriptWallet(WalletABC):
|
||||
has_mine = 0
|
||||
|
||||
keys = []
|
||||
for k, v in xpubs_list:
|
||||
k = Key.from_psbt_xpub(k, v)
|
||||
for ek, xfp_pth in xpubs_list:
|
||||
k = Key.from_psbt_xpub(ek, xfp_pth)
|
||||
has_mine += k.validate(my_xfp, cls.disable_checks)
|
||||
keys.append(k)
|
||||
|
||||
@ -526,8 +526,8 @@ class MiniScriptWallet(WalletABC):
|
||||
|
||||
def validate_psbt_xpubs(self, psbt_xpubs):
|
||||
keys = set()
|
||||
for k, v in psbt_xpubs:
|
||||
key = Key.from_psbt_xpub(k, v)
|
||||
for ek, xfp_pth in psbt_xpubs:
|
||||
key = Key.from_psbt_xpub(ek, xfp_pth)
|
||||
key.validate(settings.get('xfp', 0), self.disable_checks)
|
||||
keys.add(key)
|
||||
|
||||
|
||||
@ -4,32 +4,40 @@
|
||||
from h import a2b_hex, b2a_hex
|
||||
from serializations import CTxOut
|
||||
from uio import BytesIO
|
||||
from public_constants import AF_CLASSIC, AF_P2WPKH, AF_P2SH
|
||||
|
||||
|
||||
cases = [
|
||||
# TxOut, type, is_segwit, hash160/pubkey,
|
||||
( 'c4f33d0000000000160014ad46a001d55bd55d157e716bf17c02f8964b5a19',
|
||||
'p2wpkh',
|
||||
'ad46a001d55bd55d157e716bf17c02f8964b5a19' ),
|
||||
( '202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac',
|
||||
'p2pkh',
|
||||
'8280b37df378db99f66f85c95a783a76ac7a6d59' ),
|
||||
|
||||
(
|
||||
'c4f33d0000000000160014ad46a001d55bd55d157e716bf17c02f8964b5a19',
|
||||
AF_P2WPKH,
|
||||
'ad46a001d55bd55d157e716bf17c02f8964b5a19'
|
||||
),
|
||||
(
|
||||
'202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac',
|
||||
AF_CLASSIC,
|
||||
'8280b37df378db99f66f85c95a783a76ac7a6d59'
|
||||
),
|
||||
# from legendary txid: 40eee3ae1760e3a8532263678cdf64569e6ad06abc133af64f735e52562bccc8
|
||||
( '301b0f000000000017a914e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a87',
|
||||
'p2sh',
|
||||
'e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a'),
|
||||
|
||||
(
|
||||
'301b0f000000000017a914e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a87',
|
||||
AF_P2SH,
|
||||
'e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a'
|
||||
),
|
||||
# from testnet: a4c89e0ffb84d06a1e62f0f9f0f5974db250878caa1f71f9992a1f865b8ff2fa
|
||||
# via <https://github.com/bitcoinjs/bitcoinjs-lib/issues/856>
|
||||
( 'b88201000000000017a914f0ca58dc8e539421a3cb4a9c22c059973075287c87',
|
||||
'p2sh',
|
||||
'f0ca58dc8e539421a3cb4a9c22c059973075287c'),
|
||||
|
||||
(
|
||||
'b88201000000000017a914f0ca58dc8e539421a3cb4a9c22c059973075287c87',
|
||||
AF_P2SH,
|
||||
'f0ca58dc8e539421a3cb4a9c22c059973075287c'
|
||||
),
|
||||
# XXX missing: P2SH segwit, 1of1 and N of M
|
||||
( 'd0f13d0000000000160014f2369bac6d24ed11313fa65adda1971d10e17bff',
|
||||
'p2wpkh',
|
||||
'f2369bac6d24ed11313fa65adda1971d10e17bff')
|
||||
(
|
||||
'd0f13d0000000000160014f2369bac6d24ed11313fa65adda1971d10e17bff',
|
||||
AF_P2WPKH,
|
||||
'f2369bac6d24ed11313fa65adda1971d10e17bff'
|
||||
)
|
||||
]
|
||||
|
||||
for raw_txo, expect_type, expect_hash in cases:
|
||||
|
||||
@ -14,7 +14,7 @@ from pysecp256k1 import ec_seckey_verify, ec_pubkey_parse, ec_pubkey_serialize,
|
||||
from mnemonic import Mnemonic
|
||||
from bip32 import BIP32Node
|
||||
from constants import AF_P2WSH
|
||||
from charcodes import KEY_QR
|
||||
from charcodes import KEY_QR, KEY_DELETE
|
||||
from bbqr import split_qrs
|
||||
from psbt import BasicPSBT
|
||||
|
||||
@ -1026,7 +1026,8 @@ def test_ccc_xpub_export(chain, c_num_words, acct, settings_set, load_export, se
|
||||
def test_multiple_multisig_wallets(settings_set, setup_ccc, enter_enabled_ccc, ccc_ms_setup,
|
||||
bitcoind_create_watch_only_wallet, cap_story, bitcoind,
|
||||
policy_sign, settings_get, cap_menu, pick_menu_item,
|
||||
press_select, load_export, offer_minsc_import, goto_home):
|
||||
press_select, load_export, offer_minsc_import, goto_home,
|
||||
need_keypress, is_q1, enter_text):
|
||||
# - 'build 2-of-N' path
|
||||
goto_home()
|
||||
settings_set("ccc", None)
|
||||
@ -1090,7 +1091,8 @@ def test_multiple_multisig_wallets(settings_set, setup_ccc, enter_enabled_ccc, c
|
||||
assert mi not in m
|
||||
|
||||
# export one of the wallets
|
||||
w_mn, w_name = ami.rsplit(" ", 1)
|
||||
w_mn, w_name = ami.split(":", 1)
|
||||
w_name = w_name.strip()
|
||||
new_name = "new"
|
||||
pick_menu_item(ami) # just another ms wallet
|
||||
pick_menu_item("Descriptors")
|
||||
@ -1100,17 +1102,21 @@ def test_multiple_multisig_wallets(settings_set, setup_ccc, enter_enabled_ccc, c
|
||||
# try importing duplicate does not work
|
||||
_, story = offer_minsc_import(ms_conf)
|
||||
assert "Duplicate wallet" in story
|
||||
press_select() # not importable - dupe
|
||||
|
||||
# try rename
|
||||
ms_conf = ms_conf.replace(w_name, new_name)
|
||||
_, story = offer_minsc_import(ms_conf)
|
||||
assert "Update NAME only of existing multisig wallet?" in story
|
||||
press_select()
|
||||
time.sleep(.1)
|
||||
pick_menu_item("Settings")
|
||||
pick_menu_item("Miniscript")
|
||||
pick_menu_item(w_name)
|
||||
pick_menu_item("Rename")
|
||||
for i in range(len(w_name)):
|
||||
need_keypress(KEY_DELETE if is_q1 else "x")
|
||||
|
||||
enter_text(new_name)
|
||||
time.sleep(.1)
|
||||
enter_enabled_ccc(words)
|
||||
m = cap_menu()
|
||||
assert f"{w_mn} {new_name}" in m
|
||||
assert f"{w_mn}: {new_name}" in m
|
||||
|
||||
|
||||
def test_remove_ccc(settings_set, setup_ccc, ccc_ms_setup, settings_get, policy_sign,
|
||||
|
||||
@ -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', "h").replace("'", 'h'))
|
||||
rv.append(orig if orig in ["any", "msas"] else orig.replace('p', "h").replace("'", 'h'))
|
||||
elif type_ == WhitelistOpts:
|
||||
rv = OrderedDict()
|
||||
rv["mode"] = value.get("mode", "BASIC")
|
||||
@ -170,10 +170,10 @@ def hsm_reset(dev, sim_exec):
|
||||
(DICT(msg_paths=["any"]), "(any path)"),
|
||||
|
||||
# data sharing
|
||||
(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_addrs=["m/1'/2p/3H"]), ['Address values will be shared', "m/1h/2h/3h"]),
|
||||
(DICT(share_addrs=["m/1", "m/2"]), ['Address values will be shared', "m/1 OR m/2"]),
|
||||
(DICT(share_addrs=["any"]), ['Address values will be shared', "(any path)"]),
|
||||
(DICT(share_addrs=["msas", "any"]), ['Address values will be shared', "(any miniscript)", "(any path"]),
|
||||
|
||||
(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"]),
|
||||
@ -564,7 +564,7 @@ def test_named_wallets(dev, start_hsm, tweak_rule, make_myself_wallet, hsm_statu
|
||||
policy = DICT(rules=[dict(wallet=wname)])
|
||||
|
||||
stat = start_hsm(policy)
|
||||
assert 'Any amount from multisig wallet' in stat.summary
|
||||
assert 'Any amount from miniscript wallet' in stat.summary
|
||||
assert wname in stat.summary
|
||||
assert 'wallets' not in stat
|
||||
|
||||
@ -581,7 +581,7 @@ def test_named_wallets(dev, start_hsm, tweak_rule, make_myself_wallet, hsm_statu
|
||||
|
||||
# check ms txn not accepted when rule spec's a single signer
|
||||
tweak_rule(0, dict(wallet='1'))
|
||||
attempt_psbt(psbt, 'wrong multisig wallet')
|
||||
attempt_psbt(psbt, 'wrong miniscript wallet')
|
||||
|
||||
@pytest.mark.bitcoind
|
||||
def test_named_wallets_miniscript(dev, start_hsm, tweak_rule, make_myself_wallet,
|
||||
@ -612,7 +612,7 @@ def test_named_wallets_miniscript(dev, start_hsm, tweak_rule, make_myself_wallet
|
||||
pick_menu_item(name)
|
||||
pick_menu_item("Descriptors")
|
||||
pick_menu_item("Bitcoin Core")
|
||||
text = load_export("sd", label="Bitcoin Core miniscript", is_json=False, sig_check=False)
|
||||
text = load_export("sd", label="Bitcoin Core miniscript", is_json=False)
|
||||
text = text.replace("importdescriptors ", "").strip()
|
||||
# remove junk
|
||||
r1 = text.find("[")
|
||||
@ -1239,37 +1239,6 @@ def test_show_addr(dev, quick_start_hsm, change_hsm):
|
||||
path = path.replace('*', '73')
|
||||
addr = doit(path, addr_fmt)
|
||||
|
||||
def test_show_p2sh_addr(dev, hsm_reset, start_hsm, change_hsm, make_myself_wallet, addr_vs_path):
|
||||
# MULTISIG addrs
|
||||
from test_multisig import HARD, make_redeem
|
||||
M = 4
|
||||
pm = lambda i: [HARD(45), i, 0,0]
|
||||
|
||||
# can't amke ms wallets inside HSM mode
|
||||
hsm_reset()
|
||||
keys, _ = make_myself_wallet(M) # slow AF
|
||||
|
||||
permit = ['p2sh', 'm/73']
|
||||
start_hsm(DICT(share_addrs=permit))
|
||||
|
||||
|
||||
scr, pubkeys, xfp_paths = make_redeem(M, keys, path_mapper=pm)
|
||||
assert len(scr) <= 520, "script too long for standard!"
|
||||
|
||||
got_addr = dev.send_recv(CCProtocolPacker.show_p2sh_address(
|
||||
M, xfp_paths, scr, addr_fmt=AF_P2WSH))
|
||||
addr_vs_path(got_addr, addr_fmt=AF_P2WSH, script=scr)
|
||||
|
||||
# turn it off; p2sh must be explicitly allowed
|
||||
for allow in ['m', 'any']:
|
||||
change_hsm(DICT(share_addrs=[allow]))
|
||||
dev.send_recv(CCProtocolPacker.show_address('m', AF_CLASSIC))
|
||||
|
||||
with pytest.raises(CCProtoError) as ee:
|
||||
got_addr = dev.send_recv(CCProtocolPacker.show_p2sh_address(
|
||||
M, xfp_paths, scr, addr_fmt=AF_P2WSH))
|
||||
assert 'Not allowed in HSM mode' in str(ee)
|
||||
|
||||
def test_show_miniscript_addr(dev, offer_minsc_import, start_hsm,
|
||||
change_hsm, need_keypress, clear_miniscript):
|
||||
clear_miniscript()
|
||||
@ -1282,7 +1251,7 @@ def test_show_miniscript_addr(dev, offer_minsc_import, start_hsm,
|
||||
need_keypress("y")
|
||||
time.sleep(.2)
|
||||
|
||||
policy = DICT(share_addrs=["any", "p2sh"], rules=[dict(wallet=name)])
|
||||
policy = DICT(share_addrs=["any"], rules=[dict(wallet=name)])
|
||||
start_hsm(policy)
|
||||
|
||||
with pytest.raises(CCProtoError) as ee:
|
||||
@ -1290,7 +1259,7 @@ def test_show_miniscript_addr(dev, offer_minsc_import, start_hsm,
|
||||
assert "Not allowed in HSM mode" in ee.value.args[0]
|
||||
|
||||
# change policy to allow miniscript address show
|
||||
policy = DICT(share_addrs=["any", "p2sh", "msas"], rules=[dict(wallet=name)])
|
||||
policy = DICT(share_addrs=["any", "msas"], rules=[dict(wallet=name)])
|
||||
change_hsm(policy)
|
||||
addr = dev.send_recv(CCProtocolPacker.miniscript_address(name, False, 0))
|
||||
assert addr[2:4] == "1q"
|
||||
@ -1574,7 +1543,7 @@ def worst_case_policy():
|
||||
|
||||
addrs = [render_address(b'\x00\x14' + prandom(20)) for i in range(5)]
|
||||
|
||||
p = DICT(period=30, share_xpubs=paths, share_addrs=paths+['p2sh'], msg_paths=paths,
|
||||
p = DICT(period=30, share_xpubs=paths, share_addrs=paths+['msas'], msg_paths=paths,
|
||||
warnings_ok=False, must_log=True)
|
||||
p.rules = [dict(
|
||||
local_conf=True,
|
||||
|
||||
@ -1693,6 +1693,7 @@ def test_minitapscript(leaf2_mine, recovery, minisc, clear_miniscript, goto_home
|
||||
time.sleep(0.1)
|
||||
title, story = cap_story()
|
||||
assert title == "OK TO SEND?"
|
||||
assert "warning" not in story
|
||||
assert "1 input" in story
|
||||
assert "20 outputs" in story
|
||||
assert "Consolidating" in story
|
||||
@ -1755,6 +1756,7 @@ def test_minitapscript(leaf2_mine, recovery, minisc, clear_miniscript, goto_home
|
||||
time.sleep(.1)
|
||||
title, story = cap_story()
|
||||
assert title == "OK TO SEND?"
|
||||
assert "warning" not in story
|
||||
assert "Consolidating" not in story
|
||||
assert "20 inputs" in story
|
||||
assert "2 outputs" in story
|
||||
|
||||
@ -1468,7 +1468,7 @@ def test_wrong_xfp(fake_txn, try_sign, addr_fmt):
|
||||
orig, result = try_sign(psbt, accept=True)
|
||||
|
||||
assert 'None of the keys' in str(ee)
|
||||
assert 'found 12345678' in str(ee)
|
||||
assert 'need 0F056943' in str(ee)
|
||||
|
||||
@pytest.mark.parametrize('addr_fmt', ["p2wpkh", "p2tr"])
|
||||
def test_wrong_xfp_multi(fake_txn, try_sign, addr_fmt, sim_root_dir):
|
||||
@ -1502,8 +1502,7 @@ def test_wrong_xfp_multi(fake_txn, try_sign, addr_fmt, sim_root_dir):
|
||||
pass
|
||||
else:
|
||||
assert 'None of the keys' in str(ee)
|
||||
# WEAK: device keeps them in order, but that's chance/impl defined...
|
||||
assert 'found '+', '.join(sorted(wrongs)) in str(ee)
|
||||
assert "need 0F056943" in str(ee)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('out_style', ADDR_STYLES_SINGLE)
|
||||
@ -1731,7 +1730,7 @@ def test_zero_xfp(dev, start_sign, end_sign, fake_txn, cap_story):
|
||||
assert 'Zero XFP' in story
|
||||
|
||||
# and then signing should work.
|
||||
signed = end_sign(True, finalize=True)
|
||||
end_sign(True, finalize=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("addr_fmt", ["p2pkh", "p2wpkh"])
|
||||
@ -3349,8 +3348,8 @@ def test_finalize_with_foreign_inputs(bitcoind, bitcoind_d_sim_watch, start_sign
|
||||
# EOF
|
||||
|
||||
@pytest.mark.bitcoind
|
||||
def test_taproot_keyspend(use_regtest, bitcoind_d_sim_watch, start_sign, end_sign, microsd_path, cap_story, goto_home,
|
||||
press_select, pick_menu_item, bitcoind):
|
||||
def test_taproot_keyspend(use_regtest, bitcoind_d_sim_watch, start_sign, end_sign, microsd_path,
|
||||
cap_story, goto_home, press_select, pick_menu_item, bitcoind, sim_root_dir):
|
||||
use_regtest()
|
||||
sim = bitcoind_d_sim_watch
|
||||
sim.keypoolrefill(10)
|
||||
@ -3361,7 +3360,8 @@ def test_taproot_keyspend(use_regtest, bitcoind_d_sim_watch, start_sign, end_sig
|
||||
psbt_resp = sim.walletcreatefundedpsbt([], [{dest_addr: 1.0}], 0, {"fee_rate": 20})
|
||||
psbt = psbt_resp.get("psbt")
|
||||
psbt_fname = "tr.psbt"
|
||||
open('debug/last.psbt', 'w').write(psbt)
|
||||
with open(f'{sim_root_dir}/debug/last.psbt', 'w')as f:
|
||||
f.write(psbt)
|
||||
with open(microsd_path(psbt_fname), "w") as f:
|
||||
f.write(psbt)
|
||||
goto_home()
|
||||
@ -3391,7 +3391,8 @@ def test_taproot_keyspend(use_regtest, bitcoind_d_sim_watch, start_sign, end_sig
|
||||
signed_psbt_fname = split_story[1]
|
||||
with open(microsd_path(signed_psbt_fname), "r") as f:
|
||||
signed_psbt = f.read().strip()
|
||||
open('debug/last.psbt', 'w').write(psbt)
|
||||
with open(f'{sim_root_dir}/debug/last.psbt', 'w') as f:
|
||||
f.write(psbt)
|
||||
signed_txn_fname = split_story[3]
|
||||
with open(microsd_path(signed_txn_fname), "r") as f:
|
||||
signed_txn = f.read().strip()
|
||||
@ -3422,7 +3423,8 @@ def test_taproot_keyspend(use_regtest, bitcoind_d_sim_watch, start_sign, end_sig
|
||||
0, {'subtractFeeFromOutputs': [0], "fee_rate": 20})
|
||||
psbt = psbt_resp.get("psbt")
|
||||
psbt_fname = "tr-all.psbt"
|
||||
open('debug/last.psbt', 'w').write(psbt)
|
||||
with open(f'{sim_root_dir}/debug/last.psbt', 'w') as f:
|
||||
f.write(psbt)
|
||||
with open(microsd_path(psbt_fname), "w") as f:
|
||||
f.write(psbt)
|
||||
goto_home()
|
||||
@ -3448,7 +3450,8 @@ def test_taproot_keyspend(use_regtest, bitcoind_d_sim_watch, start_sign, end_sig
|
||||
signed_psbt_fname = split_story[1]
|
||||
with open(microsd_path(signed_psbt_fname), "r") as f:
|
||||
signed_psbt = f.read().strip()
|
||||
open('debug/last.psbt', 'w').write(psbt)
|
||||
with open(f'{sim_root_dir}/debug/last.psbt', 'w') as f:
|
||||
f.write(psbt)
|
||||
signed_txn_fname = split_story[3]
|
||||
with open(microsd_path(signed_txn_fname), "r") as f:
|
||||
signed_txn = f.read().strip()
|
||||
@ -3497,7 +3500,8 @@ def test_taproot_keyspend(use_regtest, bitcoind_d_sim_watch, start_sign, end_sig
|
||||
signed_psbt_fname = split_story[1]
|
||||
with open(microsd_path(signed_psbt_fname), "r") as f:
|
||||
signed_psbt = f.read().strip()
|
||||
open('debug/last.psbt', 'w').write(psbt)
|
||||
with open(f'{sim_root_dir}/debug/last.psbt', 'w') as f:
|
||||
f.write(psbt)
|
||||
signed_txn_fname = split_story[3]
|
||||
with open(microsd_path(signed_txn_fname), "r") as f:
|
||||
signed_txn = f.read().strip()
|
||||
|
||||
@ -617,7 +617,7 @@ def test_teleport_big_ms(make_myself_wallet, clear_miniscript, fake_ms_txn, try_
|
||||
|
||||
|
||||
@pytest.mark.manual
|
||||
def test_teleport_real_ms(dev, fake_ms_txn):
|
||||
def test_teleport_real_ms(dev, fake_ms_txn, sim_root_dir):
|
||||
#
|
||||
# Do a 2-of-2 w/ USB-attached REAL Q and simulator
|
||||
# - build ms wallet beforehand, both devices (QR); default air-gap settings
|
||||
@ -648,11 +648,12 @@ def test_teleport_real_ms(dev, fake_ms_txn):
|
||||
# match the default paths created by CC in airgapped MS wallet creation.
|
||||
return str_to_path(deriv)
|
||||
|
||||
psbt = fake_ms_txn(3, 2, M, keys, fee=10000, outvals=None, inp_addr_fmt="p2sh",
|
||||
psbt = fake_ms_txn(3, 2, M, keys, fee=10000, outvals=None, inp_addr_fmt="p2wsh",
|
||||
outstyles=['p2pkh'], change_outputs=[],
|
||||
hack_change_out=False, input_amount=1E8, path_mapper=p2wsh_mapper)
|
||||
|
||||
open('debug/teleport_real_ms.psbt', 'wb').write(psbt)
|
||||
with open(f'{sim_root_dir}/debug/teleport_real_ms.psbt', 'wb') as f:
|
||||
f.write(psbt)
|
||||
|
||||
ll, sha = dev.upload_file(psbt)
|
||||
dev.send_recv(CCProtocolPacker.sign_transaction(ll, sha))
|
||||
|
||||
@ -137,10 +137,6 @@ def test_slip132(unit_test):
|
||||
# slip132 ?pub stuff
|
||||
unit_test('devtest/unit_slip132.py')
|
||||
|
||||
def test_multisig(unit_test):
|
||||
# scripts/multisig unit tests
|
||||
unit_test('devtest/unit_multisig.py')
|
||||
|
||||
def test_decoding(unit_test):
|
||||
# utils.py Hex/Base64 streaming decoders
|
||||
unit_test('devtest/unit_decoding.py')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user