Skip to content

Commit d1e4c56

Browse files
author
MarcoFalke
committed
Merge bitcoin/bitcoin#22363: test: refactor: use script_util helpers for creating P2{PKH,SH,WPKH,WSH} scripts
905d672 test: use script_util helpers for creating P2W{PKH,SH} scripts (Sebastian Falbesoner) 285a65c test: use script_util helpers for creating P2SH scripts (Sebastian Falbesoner) b57b633 test: use script_util helpers for creating P2PKH scripts (Sebastian Falbesoner) 61b6a01 test: wallet util: fix multisig P2SH-P2WSH script creation (Sebastian Falbesoner) Pull request description: PR #18788 (commit 08067ae) introduced functions to generate output scripts for various types. This PR replaces all manual CScript creations in the P2PKH, P2SH, P2WPKH, P2WSH formats with those helpers in order to increase readability and maintainability over the functional test codebase. The first commit fixes a bug in the wallet_util helper module w.r.t. to P2SH-P2WSH script creation (the result is not used in any test so far, hence it can still be seen as refactoring). The following table shows a summary of the output script patterns tackled in this PR: | Type | master branch | PR branch | | ---------- | ------------- | ------------- | | P2PKH | `CScript([OP_DUP, OP_HASH160, hash160(key), OP_EQUALVERIFY, OP_CHECKSIG])` | `key_to_p2pkh_script(key)` | | | `CScript([OP_DUP, OP_HASH160, keyhash, OP_EQUALVERIFY, OP_CHECKSIG])` | `keyhash_to_p2pkh_script(keyhash)` | | P2SH | `CScript([OP_HASH160, hash160(script), OP_EQUAL])` | `script_to_p2sh_script(script)` | | P2WPKH | `CScript([OP_0, hash160(key)])` | `key_to_p2wpkh_script(key)` | | P2WSH | `CScript([OP_0, sha256(script)])` | `script_to_p2wsh_script(script)` | Note that the `key_to_...` helpers can't be used if an invalid key size (not 33 or 65 bytes) is passed, which is the case in some rare instances where the scripts still have to be created manually. Possible follow-up ideas: * further simplify by identifying P2SH-wrapped scripts and using `key_to_p2sh_p2wpkh_script()` and `script_to_p2sh_p2wsh_script()` helpers * introduce and use `key_to_p2pk_script()` helper for P2PK scripts ACKs for top commit: rajarshimaitra: tACK bitcoin/bitcoin@905d672 LarryRuane: tACK 905d672 0xB10C: ACK 905d672 MarcoFalke: review ACK 905d672 🕹 Tree-SHA512: 7ccfe69699bc81168ac122b03536720013355c1b2fbb088355b616015318644c4d1cd27e20c4f56c89ad083ae609add4bc838cf6316794d0edb0ce9cf7fa0fd8
2 parents efff9c3 + 905d672 commit d1e4c56

File tree

10 files changed

+134
-162
lines changed

10 files changed

+134
-162
lines changed

test/functional/data/invalid_txs.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,32 @@
2929
CTxOut,
3030
MAX_MONEY,
3131
)
32-
from test_framework import script as sc
3332
from test_framework.blocktools import create_tx_with_script, MAX_BLOCK_SIGOPS
3433
from test_framework.script import (
3534
CScript,
35+
OP_0,
36+
OP_2DIV,
37+
OP_2MUL,
38+
OP_AND,
3639
OP_CAT,
37-
OP_SUBSTR,
38-
OP_LEFT,
39-
OP_RIGHT,
40+
OP_CHECKSIG,
41+
OP_DIV,
4042
OP_INVERT,
41-
OP_AND,
43+
OP_LEFT,
44+
OP_LSHIFT,
45+
OP_MOD,
46+
OP_MUL,
4247
OP_OR,
48+
OP_RIGHT,
49+
OP_RSHIFT,
50+
OP_SUBSTR,
51+
OP_TRUE,
4352
OP_XOR,
44-
OP_2MUL,
45-
OP_2DIV,
46-
OP_MUL,
47-
OP_DIV,
48-
OP_MOD,
49-
OP_LSHIFT,
50-
OP_RSHIFT
5153
)
52-
basic_p2sh = sc.CScript([sc.OP_HASH160, sc.hash160(sc.CScript([sc.OP_0])), sc.OP_EQUAL])
54+
from test_framework.script_util import (
55+
script_to_p2sh_script,
56+
)
57+
basic_p2sh = script_to_p2sh_script(CScript([OP_0]))
5358

5459

5560
class BadTxTemplate:
@@ -116,7 +121,7 @@ class SizeTooSmall(BadTxTemplate):
116121
def get_tx(self):
117122
tx = CTransaction()
118123
tx.vin.append(self.valid_txin)
119-
tx.vout.append(CTxOut(0, sc.CScript([sc.OP_TRUE])))
124+
tx.vout.append(CTxOut(0, CScript([OP_TRUE])))
120125
tx.calc_sha256()
121126
return tx
122127

@@ -230,7 +235,7 @@ class TooManySigops(BadTxTemplate):
230235
expect_disconnect = False
231236

232237
def get_tx(self):
233-
lotsa_checksigs = sc.CScript([sc.OP_CHECKSIG] * (MAX_BLOCK_SIGOPS))
238+
lotsa_checksigs = CScript([OP_CHECKSIG] * (MAX_BLOCK_SIGOPS))
234239
return create_tx_with_script(
235240
self.spend_tx, 0,
236241
script_pub_key=lotsa_checksigs,

test/functional/feature_block.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,17 @@
3737
OP_CHECKSIGVERIFY,
3838
OP_ELSE,
3939
OP_ENDIF,
40-
OP_EQUAL,
4140
OP_DROP,
4241
OP_FALSE,
43-
OP_HASH160,
4442
OP_IF,
4543
OP_INVALIDOPCODE,
4644
OP_RETURN,
4745
OP_TRUE,
4846
SIGHASH_ALL,
4947
LegacySignatureHash,
50-
hash160,
48+
)
49+
from test_framework.script_util import (
50+
script_to_p2sh_script,
5151
)
5252
from test_framework.test_framework import BitcoinTestFramework
5353
from test_framework.util import assert_equal
@@ -469,8 +469,7 @@ def run_test(self):
469469

470470
# Build the redeem script, hash it, use hash to create the p2sh script
471471
redeem_script = CScript([self.coinbase_pubkey] + [OP_2DUP, OP_CHECKSIGVERIFY] * 5 + [OP_CHECKSIG])
472-
redeem_script_hash = hash160(redeem_script)
473-
p2sh_script = CScript([OP_HASH160, redeem_script_hash, OP_EQUAL])
472+
p2sh_script = script_to_p2sh_script(redeem_script)
474473

475474
# Create a transaction that spends one satoshi to the p2sh_script, the rest to OP_TRUE
476475
# This must be signed because it is spending a coinbase

test/functional/feature_fee_estimation.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
OP_1,
1919
OP_2,
2020
OP_DROP,
21-
OP_EQUAL,
22-
OP_HASH160,
2321
OP_TRUE,
24-
hash160,
22+
)
23+
from test_framework.script_util import (
24+
script_to_p2sh_script,
2525
)
2626
from test_framework.test_framework import BitcoinTestFramework
2727
from test_framework.util import (
@@ -37,8 +37,8 @@
3737
# time signing.
3838
REDEEM_SCRIPT_1 = CScript([OP_1, OP_DROP])
3939
REDEEM_SCRIPT_2 = CScript([OP_2, OP_DROP])
40-
P2SH_1 = CScript([OP_HASH160, hash160(REDEEM_SCRIPT_1), OP_EQUAL])
41-
P2SH_2 = CScript([OP_HASH160, hash160(REDEEM_SCRIPT_2), OP_EQUAL])
40+
P2SH_1 = script_to_p2sh_script(REDEEM_SCRIPT_1)
41+
P2SH_2 = script_to_p2sh_script(REDEEM_SCRIPT_2)
4242

4343
# Associated ScriptSig's to spend satisfy P2SH_1 and P2SH_2
4444
SCRIPT_SIG = [CScript([OP_TRUE, REDEEM_SCRIPT_1]), CScript([OP_TRUE, REDEEM_SCRIPT_2])]

test/functional/feature_segwit.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
CTransaction,
2424
CTxIn,
2525
CTxOut,
26-
sha256,
2726
tx_from_hex,
2827
)
2928
from test_framework.script import (
@@ -34,12 +33,13 @@
3433
OP_CHECKMULTISIG,
3534
OP_CHECKSIG,
3635
OP_DROP,
37-
OP_DUP,
38-
OP_EQUAL,
39-
OP_EQUALVERIFY,
40-
OP_HASH160,
4136
OP_TRUE,
42-
hash160,
37+
)
38+
from test_framework.script_util import (
39+
key_to_p2pkh_script,
40+
key_to_p2wpkh_script,
41+
script_to_p2sh_script,
42+
script_to_p2wsh_script,
4343
)
4444
from test_framework.test_framework import BitcoinTestFramework
4545
from test_framework.util import (
@@ -353,7 +353,7 @@ def run_test(self):
353353

354354
multisig_without_privkey_address = self.nodes[0].addmultisigaddress(2, [pubkeys[3], pubkeys[4]])['address']
355355
script = CScript([OP_2, hex_str_to_bytes(pubkeys[3]), hex_str_to_bytes(pubkeys[4]), OP_2, OP_CHECKMULTISIG])
356-
solvable_after_importaddress.append(CScript([OP_HASH160, hash160(script), OP_EQUAL]))
356+
solvable_after_importaddress.append(script_to_p2sh_script(script))
357357

358358
for i in compressed_spendable_address:
359359
v = self.nodes[0].getaddressinfo(i)
@@ -427,10 +427,10 @@ def run_test(self):
427427
op0 = CScript([OP_0])
428428
# 2N7MGY19ti4KDMSzRfPAssP6Pxyuxoi6jLe is the P2SH(P2PKH) version of mjoE3sSrb8ByYEvgnC3Aox86u1CHnfJA4V
429429
unsolvable_address_key = hex_str_to_bytes("02341AEC7587A51CDE5279E0630A531AEA2615A9F80B17E8D9376327BAEAA59E3D")
430-
unsolvablep2pkh = CScript([OP_DUP, OP_HASH160, hash160(unsolvable_address_key), OP_EQUALVERIFY, OP_CHECKSIG])
431-
unsolvablep2wshp2pkh = CScript([OP_0, sha256(unsolvablep2pkh)])
432-
p2shop0 = CScript([OP_HASH160, hash160(op0), OP_EQUAL])
433-
p2wshop1 = CScript([OP_0, sha256(op1)])
430+
unsolvablep2pkh = key_to_p2pkh_script(unsolvable_address_key)
431+
unsolvablep2wshp2pkh = script_to_p2wsh_script(unsolvablep2pkh)
432+
p2shop0 = script_to_p2sh_script(op0)
433+
p2wshop1 = script_to_p2wsh_script(op1)
434434
unsolvable_after_importaddress.append(unsolvablep2pkh)
435435
unsolvable_after_importaddress.append(unsolvablep2wshp2pkh)
436436
unsolvable_after_importaddress.append(op1) # OP_1 will be imported as script
@@ -450,16 +450,16 @@ def run_test(self):
450450
if (v['isscript']):
451451
bare = hex_str_to_bytes(v['hex'])
452452
importlist.append(bare.hex())
453-
importlist.append(CScript([OP_0, sha256(bare)]).hex())
453+
importlist.append(script_to_p2wsh_script(bare).hex())
454454
else:
455455
pubkey = hex_str_to_bytes(v['pubkey'])
456456
p2pk = CScript([pubkey, OP_CHECKSIG])
457-
p2pkh = CScript([OP_DUP, OP_HASH160, hash160(pubkey), OP_EQUALVERIFY, OP_CHECKSIG])
457+
p2pkh = key_to_p2pkh_script(pubkey)
458458
importlist.append(p2pk.hex())
459459
importlist.append(p2pkh.hex())
460-
importlist.append(CScript([OP_0, hash160(pubkey)]).hex())
461-
importlist.append(CScript([OP_0, sha256(p2pk)]).hex())
462-
importlist.append(CScript([OP_0, sha256(p2pkh)]).hex())
460+
importlist.append(key_to_p2wpkh_script(pubkey).hex())
461+
importlist.append(script_to_p2wsh_script(p2pk).hex())
462+
importlist.append(script_to_p2wsh_script(p2pkh).hex())
463463

464464
importlist.append(unsolvablep2pkh.hex())
465465
importlist.append(unsolvablep2wshp2pkh.hex())
@@ -614,22 +614,22 @@ def mine_and_test_listunspent(self, script_list, ismine):
614614
def p2sh_address_to_script(self, v):
615615
bare = CScript(hex_str_to_bytes(v['hex']))
616616
p2sh = CScript(hex_str_to_bytes(v['scriptPubKey']))
617-
p2wsh = CScript([OP_0, sha256(bare)])
618-
p2sh_p2wsh = CScript([OP_HASH160, hash160(p2wsh), OP_EQUAL])
617+
p2wsh = script_to_p2wsh_script(bare)
618+
p2sh_p2wsh = script_to_p2sh_script(p2wsh)
619619
return([bare, p2sh, p2wsh, p2sh_p2wsh])
620620

621621
def p2pkh_address_to_script(self, v):
622622
pubkey = hex_str_to_bytes(v['pubkey'])
623-
p2wpkh = CScript([OP_0, hash160(pubkey)])
624-
p2sh_p2wpkh = CScript([OP_HASH160, hash160(p2wpkh), OP_EQUAL])
623+
p2wpkh = key_to_p2wpkh_script(pubkey)
624+
p2sh_p2wpkh = script_to_p2sh_script(p2wpkh)
625625
p2pk = CScript([pubkey, OP_CHECKSIG])
626626
p2pkh = CScript(hex_str_to_bytes(v['scriptPubKey']))
627-
p2sh_p2pk = CScript([OP_HASH160, hash160(p2pk), OP_EQUAL])
628-
p2sh_p2pkh = CScript([OP_HASH160, hash160(p2pkh), OP_EQUAL])
629-
p2wsh_p2pk = CScript([OP_0, sha256(p2pk)])
630-
p2wsh_p2pkh = CScript([OP_0, sha256(p2pkh)])
631-
p2sh_p2wsh_p2pk = CScript([OP_HASH160, hash160(p2wsh_p2pk), OP_EQUAL])
632-
p2sh_p2wsh_p2pkh = CScript([OP_HASH160, hash160(p2wsh_p2pkh), OP_EQUAL])
627+
p2sh_p2pk = script_to_p2sh_script(p2pk)
628+
p2sh_p2pkh = script_to_p2sh_script(p2pkh)
629+
p2wsh_p2pk = script_to_p2wsh_script(p2pk)
630+
p2wsh_p2pkh = script_to_p2wsh_script(p2pkh)
631+
p2sh_p2wsh_p2pk = script_to_p2sh_script(p2wsh_p2pk)
632+
p2sh_p2wsh_p2pkh = script_to_p2sh_script(p2wsh_p2pkh)
633633
return [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]
634634

635635
def create_and_mine_tx_from_txids(self, txids, success=True):

test/functional/feature_taproot.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
OP_ENDIF,
5858
OP_EQUAL,
5959
OP_EQUALVERIFY,
60-
OP_HASH160,
6160
OP_IF,
6261
OP_NOP,
6362
OP_NOT,
@@ -76,12 +75,17 @@
7675
is_op_success,
7776
taproot_construct,
7877
)
78+
from test_framework.script_util import (
79+
key_to_p2wpkh_script,
80+
keyhash_to_p2pkh_script,
81+
script_to_p2sh_script,
82+
script_to_p2wsh_script,
83+
)
7984
from test_framework.test_framework import BitcoinTestFramework
8085
from test_framework.util import assert_raises_rpc_error, assert_equal
8186
from test_framework.key import generate_privkey, compute_xonly_pubkey, sign_schnorr, tweak_add_privkey, ECKey
8287
from test_framework.address import (
8388
hash160,
84-
sha256,
8589
)
8690
from collections import OrderedDict, namedtuple
8791
from io import BytesIO
@@ -458,13 +462,13 @@ def make_spender(comment, *, tap=None, witv0=False, script=None, pkh=None, p2sh=
458462
# P2WPKH
459463
assert script is None
460464
pubkeyhash = hash160(pkh)
461-
spk = CScript([OP_0, pubkeyhash])
462-
conf["scriptcode"] = CScript([OP_DUP, OP_HASH160, pubkeyhash, OP_EQUALVERIFY, OP_CHECKSIG])
465+
spk = key_to_p2wpkh_script(pkh)
466+
conf["scriptcode"] = keyhash_to_p2pkh_script(pubkeyhash)
463467
conf["script_witv0"] = None
464468
conf["inputs"] = [getter("sign"), pkh]
465469
elif script is not None:
466470
# P2WSH
467-
spk = CScript([OP_0, sha256(script)])
471+
spk = script_to_p2wsh_script(script)
468472
conf["scriptcode"] = script
469473
conf["script_witv0"] = script
470474
else:
@@ -475,7 +479,7 @@ def make_spender(comment, *, tap=None, witv0=False, script=None, pkh=None, p2sh=
475479
# P2PKH
476480
assert script is None
477481
pubkeyhash = hash160(pkh)
478-
spk = CScript([OP_DUP, OP_HASH160, pubkeyhash, OP_EQUALVERIFY, OP_CHECKSIG])
482+
spk = keyhash_to_p2pkh_script(pubkeyhash)
479483
conf["scriptcode"] = spk
480484
conf["inputs"] = [getter("sign"), pkh]
481485
elif script is not None:
@@ -496,7 +500,7 @@ def make_spender(comment, *, tap=None, witv0=False, script=None, pkh=None, p2sh=
496500
if p2sh:
497501
# P2SH wrapper can be combined with anything else
498502
conf["script_p2sh"] = spk
499-
spk = CScript([OP_HASH160, hash160(spk), OP_EQUAL])
503+
spk = script_to_p2sh_script(spk)
500504

501505
conf = {**conf, **kwargs}
502506

test/functional/mempool_accept.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,17 @@
2020
tx_from_hex,
2121
)
2222
from test_framework.script import (
23-
hash160,
2423
CScript,
2524
OP_0,
2625
OP_2,
2726
OP_3,
2827
OP_CHECKMULTISIG,
29-
OP_EQUAL,
3028
OP_HASH160,
3129
OP_RETURN,
3230
)
31+
from test_framework.script_util import (
32+
script_to_p2sh_script,
33+
)
3334
from test_framework.util import (
3435
assert_equal,
3536
assert_raises_rpc_error,
@@ -300,7 +301,7 @@ def run_test(self):
300301
rawtxs=[tx.serialize().hex()],
301302
)
302303
tx = tx_from_hex(raw_tx_reference)
303-
output_p2sh_burn = CTxOut(nValue=540, scriptPubKey=CScript([OP_HASH160, hash160(b'burn'), OP_EQUAL]))
304+
output_p2sh_burn = CTxOut(nValue=540, scriptPubKey=script_to_p2sh_script(b'burn'))
304305
num_scripts = 100000 // len(output_p2sh_burn.serialize()) # Use enough outputs to make the tx too large for our policy
305306
tx.vout = [output_p2sh_burn] * num_scripts
306307
self.check_mempool_result(

0 commit comments

Comments
 (0)