|
9 | 9 | key_to_p2pkh,
|
10 | 10 | key_to_p2sh_p2wpkh,
|
11 | 11 | key_to_p2wpkh,
|
| 12 | + script_to_p2sh, |
| 13 | + script_to_p2sh_p2wsh, |
| 14 | + script_to_p2wsh, |
12 | 15 | )
|
13 |
| -from test_framework.messages import sha256 |
14 | 16 | from test_framework.script import (
|
15 | 17 | CScript,
|
16 | 18 | OP_0,
|
| 19 | + OP_2, |
| 20 | + OP_3, |
| 21 | + OP_CHECKMULTISIG, |
17 | 22 | OP_CHECKSIG,
|
18 | 23 | OP_DUP,
|
19 | 24 | OP_EQUAL,
|
20 | 25 | OP_EQUALVERIFY,
|
21 | 26 | OP_HASH160,
|
22 | 27 | OP_NOP,
|
23 | 28 | hash160,
|
| 29 | + sha256, |
24 | 30 | )
|
25 | 31 | from test_framework.test_framework import BitcoinTestFramework
|
26 | 32 | from test_framework.util import (
|
|
41 | 47 | 'p2sh_p2wpkh_redeem_script',
|
42 | 48 | 'p2sh_p2wpkh_addr'])
|
43 | 49 |
|
| 50 | +Multisig = namedtuple('Multisig', ['privkeys', |
| 51 | + 'pubkeys', |
| 52 | + 'p2sh_script', |
| 53 | + 'p2sh_addr', |
| 54 | + 'redeem_script', |
| 55 | + 'p2wsh_script', |
| 56 | + 'p2wsh_addr', |
| 57 | + 'p2sh_p2wsh_script', |
| 58 | + 'p2sh_p2wsh_addr']) |
| 59 | + |
44 | 60 | class ImportMultiTest(BitcoinTestFramework):
|
45 | 61 | def set_test_params(self):
|
46 | 62 | self.num_nodes = 2
|
@@ -70,6 +86,28 @@ def get_key(self):
|
70 | 86 | CScript([OP_0, pkh]).hex(), # p2sh-p2wpkh redeem script
|
71 | 87 | key_to_p2sh_p2wpkh(pubkey)) # p2sh-p2wpkh addr
|
72 | 88 |
|
| 89 | + def get_multisig(self): |
| 90 | + """Generate a fresh multisig on node0 |
| 91 | +
|
| 92 | + Returns a named tuple of privkeys, pubkeys and all address and scripts.""" |
| 93 | + addrs = [] |
| 94 | + pubkeys = [] |
| 95 | + for _ in range(3): |
| 96 | + addr = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
| 97 | + addrs.append(addr['address']) |
| 98 | + pubkeys.append(addr['pubkey']) |
| 99 | + script_code = CScript([OP_2] + [hex_str_to_bytes(pubkey) for pubkey in pubkeys] + [OP_3, OP_CHECKMULTISIG]) |
| 100 | + witness_script = CScript([OP_0, sha256(script_code)]) |
| 101 | + return Multisig([self.nodes[0].dumpprivkey(addr) for addr in addrs], |
| 102 | + pubkeys, |
| 103 | + CScript([OP_HASH160, hash160(script_code), OP_EQUAL]).hex(), # p2sh |
| 104 | + script_to_p2sh(script_code), # p2sh addr |
| 105 | + script_code.hex(), # redeem script |
| 106 | + witness_script.hex(), # p2wsh |
| 107 | + script_to_p2wsh(script_code), # p2wsh addr |
| 108 | + CScript([OP_HASH160, witness_script, OP_EQUAL]).hex(), # p2sh-p2wsh |
| 109 | + script_to_p2sh_p2wsh(script_code)) # p2sh-p2wsh addr |
| 110 | + |
73 | 111 | def run_test(self):
|
74 | 112 | self.log.info("Mining blocks...")
|
75 | 113 | self.nodes[0].generate(1)
|
@@ -302,102 +340,90 @@ def run_test(self):
|
302 | 340 | assert_equal('timestamp' in address_assert, False)
|
303 | 341 |
|
304 | 342 | # P2SH address
|
305 |
| - sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
306 |
| - sig_address_2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
307 |
| - sig_address_3 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
308 |
| - multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) |
| 343 | + multisig = self.get_multisig() |
309 | 344 | self.nodes[1].generate(100)
|
310 |
| - self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) |
| 345 | + self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00) |
311 | 346 | self.nodes[1].generate(1)
|
312 | 347 | timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
|
313 | 348 |
|
314 | 349 | self.log.info("Should import a p2sh")
|
315 | 350 | result = self.nodes[1].importmulti([{
|
316 | 351 | "scriptPubKey": {
|
317 |
| - "address": multi_sig_script['address'] |
| 352 | + "address": multisig.p2sh_addr |
318 | 353 | },
|
319 | 354 | "timestamp": "now",
|
320 | 355 | }])
|
321 | 356 | assert_equal(result[0]['success'], True)
|
322 |
| - address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address']) |
| 357 | + address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) |
323 | 358 | assert_equal(address_assert['isscript'], True)
|
324 | 359 | assert_equal(address_assert['iswatchonly'], True)
|
325 | 360 | assert_equal(address_assert['timestamp'], timestamp)
|
326 |
| - p2shunspent = self.nodes[1].listunspent(0, 999999, [multi_sig_script['address']])[0] |
| 361 | + p2shunspent = self.nodes[1].listunspent(0, 999999, [multisig.p2sh_addr])[0] |
327 | 362 | assert_equal(p2shunspent['spendable'], False)
|
328 | 363 | assert_equal(p2shunspent['solvable'], False)
|
329 | 364 |
|
330 | 365 | # P2SH + Redeem script
|
331 |
| - sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
332 |
| - sig_address_2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
333 |
| - sig_address_3 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
334 |
| - multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) |
| 366 | + multisig = self.get_multisig() |
335 | 367 | self.nodes[1].generate(100)
|
336 |
| - self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) |
| 368 | + self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00) |
337 | 369 | self.nodes[1].generate(1)
|
338 | 370 | timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
|
339 | 371 |
|
340 | 372 | self.log.info("Should import a p2sh with respective redeem script")
|
341 | 373 | result = self.nodes[1].importmulti([{
|
342 | 374 | "scriptPubKey": {
|
343 |
| - "address": multi_sig_script['address'] |
| 375 | + "address": multisig.p2sh_addr |
344 | 376 | },
|
345 | 377 | "timestamp": "now",
|
346 |
| - "redeemscript": multi_sig_script['redeemScript'] |
| 378 | + "redeemscript": multisig.redeem_script |
347 | 379 | }])
|
348 | 380 | assert_equal(result[0]['success'], True)
|
349 |
| - address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address']) |
| 381 | + address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) |
350 | 382 | assert_equal(address_assert['timestamp'], timestamp)
|
351 | 383 |
|
352 |
| - p2shunspent = self.nodes[1].listunspent(0, 999999, [multi_sig_script['address']])[0] |
| 384 | + p2shunspent = self.nodes[1].listunspent(0, 999999, [multisig.p2sh_addr])[0] |
353 | 385 | assert_equal(p2shunspent['spendable'], False)
|
354 | 386 | assert_equal(p2shunspent['solvable'], True)
|
355 | 387 |
|
356 | 388 | # P2SH + Redeem script + Private Keys + !Watchonly
|
357 |
| - sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
358 |
| - sig_address_2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
359 |
| - sig_address_3 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
360 |
| - multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) |
| 389 | + multisig = self.get_multisig() |
361 | 390 | self.nodes[1].generate(100)
|
362 |
| - self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) |
| 391 | + self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00) |
363 | 392 | self.nodes[1].generate(1)
|
364 | 393 | timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
|
365 | 394 |
|
366 | 395 | self.log.info("Should import a p2sh with respective redeem script and private keys")
|
367 | 396 | result = self.nodes[1].importmulti([{
|
368 | 397 | "scriptPubKey": {
|
369 |
| - "address": multi_sig_script['address'] |
| 398 | + "address": multisig.p2sh_addr |
370 | 399 | },
|
371 | 400 | "timestamp": "now",
|
372 |
| - "redeemscript": multi_sig_script['redeemScript'], |
373 |
| - "keys": [self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])] |
| 401 | + "redeemscript": multisig.redeem_script, |
| 402 | + "keys": multisig.privkeys[0:2] |
374 | 403 | }])
|
375 | 404 | assert_equal(result[0]['success'], True)
|
376 |
| - address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address']) |
| 405 | + address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) |
377 | 406 | assert_equal(address_assert['timestamp'], timestamp)
|
378 | 407 |
|
379 |
| - p2shunspent = self.nodes[1].listunspent(0, 999999, [multi_sig_script['address']])[0] |
| 408 | + p2shunspent = self.nodes[1].listunspent(0, 999999, [multisig.p2sh_addr])[0] |
380 | 409 | assert_equal(p2shunspent['spendable'], False)
|
381 | 410 | assert_equal(p2shunspent['solvable'], True)
|
382 | 411 |
|
383 | 412 | # P2SH + Redeem script + Private Keys + Watchonly
|
384 |
| - sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
385 |
| - sig_address_2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
386 |
| - sig_address_3 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
387 |
| - multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) |
| 413 | + multisig = self.get_multisig() |
388 | 414 | self.nodes[1].generate(100)
|
389 |
| - self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) |
| 415 | + self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00) |
390 | 416 | self.nodes[1].generate(1)
|
391 | 417 | timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
|
392 | 418 |
|
393 | 419 | self.log.info("Should import a p2sh with respective redeem script and private keys")
|
394 | 420 | result = self.nodes[1].importmulti([{
|
395 | 421 | "scriptPubKey": {
|
396 |
| - "address": multi_sig_script['address'] |
| 422 | + "address": multisig.p2sh_addr |
397 | 423 | },
|
398 | 424 | "timestamp": "now",
|
399 |
| - "redeemscript": multi_sig_script['redeemScript'], |
400 |
| - "keys": [self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])], |
| 425 | + "redeemscript": multisig.redeem_script, |
| 426 | + "keys": multisig.privkeys[0:2], |
401 | 427 | "watchonly": True
|
402 | 428 | }])
|
403 | 429 | assert_equal(result[0]['success'], False)
|
@@ -565,32 +591,30 @@ def run_test(self):
|
565 | 591 | assert_equal(address_assert['ismine'], True)
|
566 | 592 |
|
567 | 593 | # P2WSH multisig address without scripts or keys
|
568 |
| - sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
569 |
| - sig_address_2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
570 |
| - multi_sig_script = self.nodes[0].addmultisigaddress(2, [sig_address_1['pubkey'], sig_address_2['pubkey']], "", "bech32") |
| 594 | + multisig = self.get_multisig() |
571 | 595 | self.log.info("Should import a p2wsh multisig as watch only without respective redeem script and private keys")
|
572 | 596 | result = self.nodes[1].importmulti([{
|
573 | 597 | "scriptPubKey": {
|
574 |
| - "address": multi_sig_script['address'] |
| 598 | + "address": multisig.p2wsh_addr |
575 | 599 | },
|
576 | 600 | "timestamp": "now"
|
577 | 601 | }])
|
578 | 602 | assert_equal(result[0]['success'], True)
|
579 |
| - address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address']) |
| 603 | + address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) |
580 | 604 | assert_equal(address_assert['solvable'], False)
|
581 | 605 |
|
582 | 606 | # Same P2WSH multisig address as above, but now with witnessscript + private keys
|
583 |
| - self.log.info("Should import a p2wsh with respective redeem script and private keys") |
| 607 | + self.log.info("Should import a p2wsh with respective witness script and private keys") |
584 | 608 | result = self.nodes[1].importmulti([{
|
585 | 609 | "scriptPubKey": {
|
586 |
| - "address": multi_sig_script['address'] |
| 610 | + "address": multisig.p2wsh_addr |
587 | 611 | },
|
588 | 612 | "timestamp": "now",
|
589 |
| - "witnessscript": multi_sig_script['redeemScript'], |
590 |
| - "keys": [self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])] |
| 613 | + "witnessscript": multisig.redeem_script, |
| 614 | + "keys": multisig.privkeys |
591 | 615 | }])
|
592 | 616 | assert_equal(result[0]['success'], True)
|
593 |
| - address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address']) |
| 617 | + address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) |
594 | 618 | assert_equal(address_assert['solvable'], True)
|
595 | 619 | assert_equal(address_assert['ismine'], True)
|
596 | 620 | assert_equal(address_assert['sigsrequired'], 2)
|
@@ -642,22 +666,19 @@ def run_test(self):
|
642 | 666 | assert_equal(address_assert['solvable'], True)
|
643 | 667 | assert_equal(address_assert['ismine'], True)
|
644 | 668 |
|
645 |
| - # P2SH-P2WSH 1-of-1 multisig + redeemscript with no private key |
646 |
| - sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) |
647 |
| - multi_sig_script = self.nodes[0].addmultisigaddress(1, [sig_address_1['pubkey']], "", "p2sh-segwit") |
648 |
| - scripthash = sha256(hex_str_to_bytes(multi_sig_script['redeemScript'])) |
649 |
| - redeem_script = CScript([OP_0, scripthash]) |
| 669 | + # P2SH-P2WSH multisig + redeemscript with no private key |
| 670 | + multisig = self.get_multisig() |
650 | 671 | self.log.info("Should import a p2sh-p2wsh with respective redeem script but no private key")
|
651 | 672 | result = self.nodes[1].importmulti([{
|
652 | 673 | "scriptPubKey": {
|
653 |
| - "address": multi_sig_script['address'] |
| 674 | + "address": multisig.p2sh_p2wsh_addr |
654 | 675 | },
|
655 | 676 | "timestamp": "now",
|
656 |
| - "redeemscript": bytes_to_hex_str(redeem_script), |
657 |
| - "witnessscript": multi_sig_script['redeemScript'] |
| 677 | + "redeemscript": multisig.p2wsh_script, |
| 678 | + "witnessscript": multisig.redeem_script, |
658 | 679 | }])
|
659 | 680 | assert_equal(result[0]['success'], True)
|
660 |
| - address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address']) |
| 681 | + address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) |
661 | 682 | assert_equal(address_assert['solvable'], True)
|
662 | 683 |
|
663 | 684 | if __name__ == '__main__':
|
|
0 commit comments