Skip to content

Commit a5bde01

Browse files
committed
tests: give feature_taproot access to sighash preimages
1 parent 5140825 commit a5bde01

File tree

2 files changed

+54
-22
lines changed

2 files changed

+54
-22
lines changed

test/functional/feature_taproot.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@
2525
CScript,
2626
CScriptNum,
2727
CScriptOp,
28+
hash256,
2829
LEAF_VERSION_TAPSCRIPT,
29-
LegacySignatureHash,
30+
LegacySignatureMsg,
3031
LOCKTIME_THRESHOLD,
3132
MAX_SCRIPT_ELEMENT_SIZE,
3233
OP_0,
@@ -70,8 +71,9 @@
7071
SIGHASH_NONE,
7172
SIGHASH_SINGLE,
7273
SIGHASH_ANYONECANPAY,
73-
SegwitV0SignatureHash,
74-
TaprootSignatureHash,
74+
SegwitV0SignatureMsg,
75+
TaggedHash,
76+
TaprootSignatureMsg,
7577
is_op_success,
7678
taproot_construct,
7779
)
@@ -194,8 +196,8 @@ def default_controlblock(ctx):
194196
"""Default expression for "controlblock": combine leafversion, negflag, pubkey_internal, merklebranch."""
195197
return bytes([get(ctx, "leafversion") + get(ctx, "negflag")]) + get(ctx, "pubkey_internal") + get(ctx, "merklebranch")
196198

197-
def default_sighash(ctx):
198-
"""Default expression for "sighash": depending on mode, compute BIP341, BIP143, or legacy sighash."""
199+
def default_sigmsg(ctx):
200+
"""Default expression for "sigmsg": depending on mode, compute BIP341, BIP143, or legacy sigmsg."""
199201
tx = get(ctx, "tx")
200202
idx = get(ctx, "idx")
201203
hashtype = get(ctx, "hashtype_actual")
@@ -208,18 +210,30 @@ def default_sighash(ctx):
208210
codeseppos = get(ctx, "codeseppos")
209211
leaf_ver = get(ctx, "leafversion")
210212
script = get(ctx, "script_taproot")
211-
return TaprootSignatureHash(tx, utxos, hashtype, idx, scriptpath=True, script=script, leaf_ver=leaf_ver, codeseparator_pos=codeseppos, annex=annex)
213+
return TaprootSignatureMsg(tx, utxos, hashtype, idx, scriptpath=True, script=script, leaf_ver=leaf_ver, codeseparator_pos=codeseppos, annex=annex)
212214
else:
213-
return TaprootSignatureHash(tx, utxos, hashtype, idx, scriptpath=False, annex=annex)
215+
return TaprootSignatureMsg(tx, utxos, hashtype, idx, scriptpath=False, annex=annex)
214216
elif mode == "witv0":
215217
# BIP143 signature hash
216218
scriptcode = get(ctx, "scriptcode")
217219
utxos = get(ctx, "utxos")
218-
return SegwitV0SignatureHash(scriptcode, tx, idx, hashtype, utxos[idx].nValue)
220+
return SegwitV0SignatureMsg(scriptcode, tx, idx, hashtype, utxos[idx].nValue)
219221
else:
220222
# Pre-segwit signature hash
221223
scriptcode = get(ctx, "scriptcode")
222-
return LegacySignatureHash(scriptcode, tx, idx, hashtype)[0]
224+
return LegacySignatureMsg(scriptcode, tx, idx, hashtype)[0]
225+
226+
def default_sighash(ctx):
227+
"""Default expression for "sighash": depending on mode, compute tagged hash or dsha256 of sigmsg."""
228+
msg = get(ctx, "sigmsg")
229+
mode = get(ctx, "mode")
230+
if mode == "taproot":
231+
return TaggedHash("TapSighash", msg)
232+
else:
233+
if msg is None:
234+
return (1).to_bytes(32, 'little')
235+
else:
236+
return hash256(msg)
223237

224238
def default_tweak(ctx):
225239
"""Default expression for "tweak": None if a leaf is specified, tap[0] otherwise."""
@@ -340,6 +354,8 @@ def default_scriptsig(ctx):
340354
"key_tweaked": default_key_tweaked,
341355
# The tweak to use (None for script path spends, the actual tweak for key path spends).
342356
"tweak": default_tweak,
357+
# The sigmsg value (preimage of sighash)
358+
"sigmsg": default_sigmsg,
343359
# The sighash value (32 bytes)
344360
"sighash": default_sighash,
345361
# The information about the chosen script path spend (TaprootLeafInfo object).

test/functional/test_framework/script.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -619,16 +619,15 @@ def FindAndDelete(script, sig):
619619
r += script[last_sop_idx:]
620620
return CScript(r)
621621

622-
def LegacySignatureHash(script, txTo, inIdx, hashtype):
623-
"""Consensus-correct SignatureHash
622+
def LegacySignatureMsg(script, txTo, inIdx, hashtype):
623+
"""Preimage of the signature hash, if it exists.
624624
625-
Returns (hash, err) to precisely match the consensus-critical behavior of
626-
the SIGHASH_SINGLE bug. (inIdx is *not* checked for validity)
625+
Returns either (None, err) to indicate error (which translates to sighash 1),
626+
or (msg, None).
627627
"""
628-
HASH_ONE = b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
629628

630629
if inIdx >= len(txTo.vin):
631-
return (HASH_ONE, "inIdx %d out of range (%d)" % (inIdx, len(txTo.vin)))
630+
return (None, "inIdx %d out of range (%d)" % (inIdx, len(txTo.vin)))
632631
txtmp = CTransaction(txTo)
633632

634633
for txin in txtmp.vin:
@@ -645,7 +644,7 @@ def LegacySignatureHash(script, txTo, inIdx, hashtype):
645644
elif (hashtype & 0x1f) == SIGHASH_SINGLE:
646645
outIdx = inIdx
647646
if outIdx >= len(txtmp.vout):
648-
return (HASH_ONE, "outIdx %d out of range (%d)" % (outIdx, len(txtmp.vout)))
647+
return (None, "outIdx %d out of range (%d)" % (outIdx, len(txtmp.vout)))
649648

650649
tmp = txtmp.vout[outIdx]
651650
txtmp.vout = []
@@ -665,15 +664,27 @@ def LegacySignatureHash(script, txTo, inIdx, hashtype):
665664
s = txtmp.serialize_without_witness()
666665
s += struct.pack(b"<I", hashtype)
667666

668-
hash = hash256(s)
667+
return (s, None)
669668

670-
return (hash, None)
669+
def LegacySignatureHash(*args, **kwargs):
670+
"""Consensus-correct SignatureHash
671+
672+
Returns (hash, err) to precisely match the consensus-critical behavior of
673+
the SIGHASH_SINGLE bug. (inIdx is *not* checked for validity)
674+
"""
675+
676+
HASH_ONE = b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
677+
msg, err = LegacySignatureMsg(*args, **kwargs)
678+
if msg is None:
679+
return (HASH_ONE, err)
680+
else:
681+
return (hash256(msg), err)
671682

672683
# TODO: Allow cached hashPrevouts/hashSequence/hashOutputs to be provided.
673684
# Performance optimization probably not necessary for python tests, however.
674685
# Note that this corresponds to sigversion == 1 in EvalScript, which is used
675686
# for version 0 witnesses.
676-
def SegwitV0SignatureHash(script, txTo, inIdx, hashtype, amount):
687+
def SegwitV0SignatureMsg(script, txTo, inIdx, hashtype, amount):
677688

678689
hashPrevouts = 0
679690
hashSequence = 0
@@ -711,8 +722,10 @@ def SegwitV0SignatureHash(script, txTo, inIdx, hashtype, amount):
711722
ss += ser_uint256(hashOutputs)
712723
ss += struct.pack("<i", txTo.nLockTime)
713724
ss += struct.pack("<I", hashtype)
725+
return ss
714726

715-
return hash256(ss)
727+
def SegwitV0SignatureHash(*args, **kwargs):
728+
return hash256(SegwitV0SignatureMsg(*args, **kwargs))
716729

717730
class TestFrameworkScript(unittest.TestCase):
718731
def test_bn2vch(self):
@@ -742,7 +755,7 @@ def test_cscriptnum_encoding(self):
742755
for value in values:
743756
self.assertEqual(CScriptNum.decode(CScriptNum.encode(CScriptNum(value))), value)
744757

745-
def TaprootSignatureHash(txTo, spent_utxos, hash_type, input_index = 0, scriptpath = False, script = CScript(), codeseparator_pos = -1, annex = None, leaf_ver = LEAF_VERSION_TAPSCRIPT):
758+
def TaprootSignatureMsg(txTo, spent_utxos, hash_type, input_index = 0, scriptpath = False, script = CScript(), codeseparator_pos = -1, annex = None, leaf_ver = LEAF_VERSION_TAPSCRIPT):
746759
assert (len(txTo.vin) == len(spent_utxos))
747760
assert (input_index < len(txTo.vin))
748761
out_type = SIGHASH_ALL if hash_type == 0 else hash_type & 3
@@ -783,7 +796,10 @@ def TaprootSignatureHash(txTo, spent_utxos, hash_type, input_index = 0, scriptpa
783796
ss += bytes([0])
784797
ss += struct.pack("<i", codeseparator_pos)
785798
assert len(ss) == 175 - (in_type == SIGHASH_ANYONECANPAY) * 49 - (out_type != SIGHASH_ALL and out_type != SIGHASH_SINGLE) * 32 + (annex is not None) * 32 + scriptpath * 37
786-
return TaggedHash("TapSighash", ss)
799+
return ss
800+
801+
def TaprootSignatureHash(*args, **kwargs):
802+
return TaggedHash("TapSighash", TaprootSignatureMsg(*args, **kwargs))
787803

788804
def taproot_tree_helper(scripts):
789805
if len(scripts) == 0:

0 commit comments

Comments
 (0)