drop sighash only after modifiable flags are properly set for v2 PSBT

This commit is contained in:
scgbckbone 2025-10-22 02:56:55 +02:00
parent 7c8aceb753
commit 6dd8237123
2 changed files with 14 additions and 9 deletions

View File

@ -2078,7 +2078,8 @@ class psbtObject(psbtProxy):
if sh_unusual and not settings.get("sighshchk"):
if self.consolidation_tx:
# policy: all inputs must be sighash ALL in purely consolidation txn
raise FatalPSBTIssue("Only sighash ALL is allowed for pure consolidation transactions.")
raise FatalPSBTIssue("Only sighash ALL/DEFAULT is allowed"
" for pure consolidation transactions.")
if none_sh:
# sighash NONE or NONE|ANYONECANPAY is proposed: block
@ -2473,24 +2474,21 @@ class psbtObject(psbtProxy):
sig = ngu.secp256k1.sign_schnorr(kpt, digest, ngu.random.bytes(32))
if inp.sighash != SIGHASH_DEFAULT:
sig += bytes([inp.sighash])
else:
# drop sighash from PSBT field if default (SIGHASH_DEFAULT)
inp.sighash = None
# in the common case of SIGHASH_DEFAULT, encoded as '0x00', a space optimization MUST be made by
# 'omitting' the sighash byte, resulting in a 64-byte signature with SIGHASH_DEFAULT assumed
inp.taproot_key_sig = sig
del kpt
drop_sighash = (inp.sighash == SIGHASH_DEFAULT)
del kp
else:
der_sig = self.ecdsa_grind_sign(sk, digest, inp.sighash)
inp.added_sigs = inp.added_sigs or []
inp.added_sigs.append((pk_coord, der_sig))
# drop sighash from PSBT field if default (SIGHASH_ALL)
if inp.sighash == SIGHASH_ALL:
inp.sighash = None
drop_sighash = (inp.sighash == SIGHASH_ALL)
# private key no longer required
stash.blank_object(sk)
@ -2500,6 +2498,12 @@ class psbtObject(psbtProxy):
if self.is_v2:
self.set_modifiable_flag(inp)
if drop_sighash:
# only drop after modifiable is set, in case of PSBTv2
# SIGHASH_DEFAULT if taproot
# SIGHASH_ALL if non-taproot
inp.sighash = None
del to_sign
gc.collect()

View File

@ -45,8 +45,9 @@ 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, press_down, is_q1):
press_select, press_cancel, press_down, is_q1, microsd_wipe):
reset_seed_words()
microsd_wipe()
# get to top, force a redraw
press_cancel()
press_cancel()
@ -86,7 +87,7 @@ def test_home_menu(cap_menu, cap_story, cap_screen, need_keypress, reset_seed_wo
need_keypress('0')
press_select()
time.sleep(.01) # required
time.sleep(.1) # required
title, body = cap_story()
assert title == 'NO-TITLE'