|
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