Skip to content

Commit ab25ef8

Browse files
author
MarcoFalke
committed
Merge bitcoin/bitcoin#23305: test: refactor: add script_util helper for creating bare multisig scripts
4718897 test: add script_util helper for creating bare multisig scripts (Sebastian Falbesoner) Pull request description: This PR is a follow-up to #22363 and #23118 and introduces a helper `keys_to_multisig_script` for creating bare multisig outputs in the form of ``` OP_K PubKey1 PubKey2 ... PubKeyN OP_N OP_CHECKMULTISIG ``` The function takes a list of pubkeys (both hex- and byte-strings are accepted due to the `script_util.check_key` helper being used internally) and optionally a threshold _k_. If no threshold is passed, a n-of-n multisig output is created, with _n_ being the number of passed pubkeys. ACKs for top commit: shaavan: utACK 4718897 rajarshimaitra: tACK bitcoin/bitcoin@4718897 Tree-SHA512: b452d8a75b0d17316b66ac4ed4c6893fe59c7c417719931d4cd3955161f59afca43503cd09b83a35b5a252a122eb3f0fbb9da9f0e7c944cf8da572a02219ed9d
2 parents e77d967 + 4718897 commit ab25ef8

File tree

5 files changed

+23
-18
lines changed

5 files changed

+23
-18
lines changed

test/functional/feature_segwit.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,14 @@
3030
CScript,
3131
OP_0,
3232
OP_1,
33-
OP_2,
34-
OP_CHECKMULTISIG,
3533
OP_DROP,
3634
OP_TRUE,
3735
)
3836
from test_framework.script_util import (
3937
key_to_p2pk_script,
4038
key_to_p2pkh_script,
4139
key_to_p2wpkh_script,
40+
keys_to_multisig_script,
4241
script_to_p2sh_script,
4342
script_to_p2wsh_script,
4443
)
@@ -149,7 +148,7 @@ def run_test(self):
149148
key = get_generate_key()
150149
self.pubkey.append(key.pubkey)
151150

152-
multiscript = CScript([OP_1, bytes.fromhex(self.pubkey[-1]), OP_1, OP_CHECKMULTISIG])
151+
multiscript = keys_to_multisig_script([self.pubkey[-1]])
153152
p2sh_ms_addr = self.nodes[i].createmultisig(1, [self.pubkey[-1]], 'p2sh-segwit')['address']
154153
bip173_ms_addr = self.nodes[i].createmultisig(1, [self.pubkey[-1]], 'bech32')['address']
155154
assert_equal(p2sh_ms_addr, script_to_p2sh_p2wsh(multiscript))
@@ -389,7 +388,7 @@ def run_test(self):
389388
# Money sent to P2SH of multisig of this should only be seen after importaddress with the BASE58 P2SH address.
390389

391390
multisig_without_privkey_address = self.nodes[0].addmultisigaddress(2, [pubkeys[3], pubkeys[4]])['address']
392-
script = CScript([OP_2, bytes.fromhex(pubkeys[3]), bytes.fromhex(pubkeys[4]), OP_2, OP_CHECKMULTISIG])
391+
script = keys_to_multisig_script([pubkeys[3], pubkeys[4]])
393392
solvable_after_importaddress.append(script_to_p2sh_script(script))
394393

395394
for i in compressed_spendable_address:

test/functional/mempool_accept.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,11 @@
2222
from test_framework.script import (
2323
CScript,
2424
OP_0,
25-
OP_2,
26-
OP_3,
27-
OP_CHECKMULTISIG,
2825
OP_HASH160,
2926
OP_RETURN,
3027
)
3128
from test_framework.script_util import (
29+
keys_to_multisig_script,
3230
script_to_p2sh_script,
3331
)
3432
from test_framework.util import (
@@ -283,7 +281,7 @@ def run_test(self):
283281
key = ECKey()
284282
key.generate()
285283
pubkey = key.get_pubkey().get_bytes()
286-
tx.vout[0].scriptPubKey = CScript([OP_2, pubkey, pubkey, pubkey, OP_3, OP_CHECKMULTISIG]) # Some bare multisig script (2-of-3)
284+
tx.vout[0].scriptPubKey = keys_to_multisig_script([pubkey] * 3, k=2) # Some bare multisig script (2-of-3)
287285
self.check_mempool_result(
288286
result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bare-multisig'}],
289287
rawtxs=[tx.serialize().hex()],

test/functional/test_framework/blocktools.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@
3232
CScriptNum,
3333
CScriptOp,
3434
OP_1,
35-
OP_CHECKMULTISIG,
3635
OP_RETURN,
3736
OP_TRUE,
3837
)
3938
from .script_util import (
4039
key_to_p2pk_script,
4140
key_to_p2wpkh_script,
41+
keys_to_multisig_script,
4242
script_to_p2wsh_script,
4343
)
4444
from .util import assert_equal
@@ -209,7 +209,7 @@ def witness_script(use_p2wsh, pubkey):
209209
pkscript = key_to_p2wpkh_script(pubkey)
210210
else:
211211
# 1-of-1 multisig
212-
witness_script = CScript([OP_1, bytes.fromhex(pubkey), OP_1, OP_CHECKMULTISIG])
212+
witness_script = keys_to_multisig_script([pubkey])
213213
pkscript = script_to_p2wsh_script(witness_script)
214214
return pkscript.hex()
215215

@@ -218,7 +218,7 @@ def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount):
218218
219219
Optionally wrap the segwit output using P2SH."""
220220
if use_p2wsh:
221-
program = CScript([OP_1, bytes.fromhex(pubkey), OP_1, OP_CHECKMULTISIG])
221+
program = keys_to_multisig_script([pubkey])
222222
addr = script_to_p2sh_p2wsh(program) if encode_p2sh else script_to_p2wsh(program)
223223
else:
224224
addr = key_to_p2sh_p2wpkh(pubkey) if encode_p2sh else key_to_p2wpkh(pubkey)

test/functional/test_framework/script_util.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"""Useful Script constants and utils."""
66
from test_framework.script import (
77
CScript,
8+
CScriptOp,
89
OP_0,
10+
OP_CHECKMULTISIG,
911
OP_CHECKSIG,
1012
OP_DUP,
1113
OP_EQUAL,
@@ -41,6 +43,17 @@ def key_to_p2pk_script(key):
4143
return CScript([key, OP_CHECKSIG])
4244

4345

46+
def keys_to_multisig_script(keys, *, k=None):
47+
n = len(keys)
48+
if k is None: # n-of-n multisig by default
49+
k = n
50+
assert k <= n
51+
op_k = CScriptOp.encode_op_n(k)
52+
op_n = CScriptOp.encode_op_n(n)
53+
checked_keys = [check_key(key) for key in keys]
54+
return CScript([op_k] + checked_keys + [op_n, OP_CHECKMULTISIG])
55+
56+
4457
def keyhash_to_p2pkh_script(hash):
4558
assert len(hash) == 20
4659
return CScript([OP_DUP, OP_HASH160, hash, OP_EQUALVERIFY, OP_CHECKSIG])

test/functional/test_framework/wallet_util.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,10 @@
1515
script_to_p2wsh,
1616
)
1717
from test_framework.key import ECKey
18-
from test_framework.script import (
19-
CScript,
20-
OP_2,
21-
OP_3,
22-
OP_CHECKMULTISIG,
23-
)
2418
from test_framework.script_util import (
2519
key_to_p2pkh_script,
2620
key_to_p2wpkh_script,
21+
keys_to_multisig_script,
2722
script_to_p2sh_script,
2823
script_to_p2wsh_script,
2924
)
@@ -92,7 +87,7 @@ def get_multisig(node):
9287
addr = node.getaddressinfo(node.getnewaddress())
9388
addrs.append(addr['address'])
9489
pubkeys.append(addr['pubkey'])
95-
script_code = CScript([OP_2] + [bytes.fromhex(pubkey) for pubkey in pubkeys] + [OP_3, OP_CHECKMULTISIG])
90+
script_code = keys_to_multisig_script(pubkeys, k=2)
9691
witness_script = script_to_p2wsh_script(script_code)
9792
return Multisig(privkeys=[node.dumpprivkey(addr) for addr in addrs],
9893
pubkeys=pubkeys,

0 commit comments

Comments
 (0)