2016-06-16 16:57:48 +02:00
#!/usr/bin/env python3
2021-07-28 13:57:16 +02:00
# Copyright (c) 2014-2021 The Bitcoin Core developers
2016-06-16 16:57:48 +02:00
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
2018-12-06 19:29:32 +01:00
""" Test the importmulti RPC.
Test importmulti by generating keys on node0 , importing the scriptPubKeys and
addresses on node1 and then testing the address info for the different address
variants .
- ` get_key ( ) ` and ` get_multisig ( ) ` are called to generate keys on node0 and
return the privkeys , pubkeys and all variants of scriptPubKey and address .
- ` test_importmulti ( ) ` is called to send an importmulti call to node1 , test
success , and ( if unsuccessful ) test the error code and error message returned .
- ` test_address ( ) ` is called to call getaddressinfo for an address on node1
and test the values returned . """
2018-12-13 18:43:35 +01:00
2021-05-17 16:38:19 +02:00
from test_framework . blocktools import COINBASE_MATURITY
2018-11-30 23:49:03 +01:00
from test_framework . script import (
CScript ,
OP_NOP ,
)
2016-06-16 16:57:48 +02:00
from test_framework . test_framework import BitcoinTestFramework
2019-02-13 03:56:53 +01:00
from test_framework . descriptors import descsum_create
2018-09-10 19:08:13 +02:00
from test_framework . util import (
assert_equal ,
assert_greater_than ,
assert_raises_rpc_error ,
)
2018-12-13 18:43:35 +01:00
from test_framework . wallet_util import (
get_key ,
get_multisig ,
test_address ,
)
2018-12-06 00:28:32 +01:00
2020-04-24 01:00:12 +02:00
2018-09-10 19:08:13 +02:00
class ImportMultiTest ( BitcoinTestFramework ) :
2017-06-10 00:21:21 +02:00
def set_test_params ( self ) :
2016-06-16 16:57:48 +02:00
self . num_nodes = 2
2017-12-01 01:49:11 +01:00
self . extra_args = [ [ " -addresstype=legacy " ] , [ " -addresstype=legacy " ] ]
2016-06-16 16:57:48 +02:00
self . setup_clean_chain = True
2018-09-09 19:32:37 +02:00
def skip_test_if_missing_module ( self ) :
self . skip_if_no_wallet ( )
2017-04-03 15:34:04 +02:00
def setup_network ( self ) :
self . setup_nodes ( )
2016-06-16 16:57:48 +02:00
2019-08-25 23:49:49 +02:00
def test_importmulti ( self , req , success , error_code = None , error_message = None , warnings = None ) :
2018-12-06 15:52:38 +01:00
""" Run importmulti and assert success """
2019-08-25 23:49:49 +02:00
if warnings is None :
warnings = [ ]
2018-12-06 15:52:38 +01:00
result = self . nodes [ 1 ] . importmulti ( [ req ] )
2018-10-25 03:28:17 +02:00
observed_warnings = [ ]
if ' warnings ' in result [ 0 ] :
2020-04-24 01:00:12 +02:00
observed_warnings = result [ 0 ] [ ' warnings ' ]
2018-10-25 03:28:17 +02:00
assert_equal ( " \n " . join ( sorted ( warnings ) ) , " \n " . join ( sorted ( observed_warnings ) ) )
2018-12-06 15:52:38 +01:00
assert_equal ( result [ 0 ] [ ' success ' ] , success )
if error_code is not None :
assert_equal ( result [ 0 ] [ ' error ' ] [ ' code ' ] , error_code )
assert_equal ( result [ 0 ] [ ' error ' ] [ ' message ' ] , error_message )
2018-11-30 23:47:46 +01:00
def run_test ( self ) :
2017-03-08 00:46:17 +01:00
self . log . info ( " Mining blocks... " )
2020-11-10 18:02:31 +01:00
self . generate ( self . nodes [ 0 ] , 1 , sync_fun = self . no_op )
self . generate ( self . nodes [ 1 ] , 1 , sync_fun = self . no_op )
2016-11-08 22:55:02 +01:00
timestamp = self . nodes [ 1 ] . getblock ( self . nodes [ 1 ] . getbestblockhash ( ) ) [ ' mediantime ' ]
2016-06-16 16:57:48 +02:00
2018-02-09 17:12:27 +01:00
node0_address1 = self . nodes [ 0 ] . getaddressinfo ( self . nodes [ 0 ] . getnewaddress ( ) )
2016-06-16 16:57:48 +02:00
2018-11-30 23:47:46 +01:00
# Check only one address
2016-06-16 16:57:48 +02:00
assert_equal ( node0_address1 [ ' ismine ' ] , True )
2018-11-30 23:47:46 +01:00
# Node 1 sync test
assert_equal ( self . nodes [ 1 ] . getblockcount ( ) , 1 )
2016-06-16 16:57:48 +02:00
2018-11-30 23:47:46 +01:00
# Address Test - before import
2018-02-09 17:12:27 +01:00
address_info = self . nodes [ 1 ] . getaddressinfo ( node0_address1 [ ' address ' ] )
2016-06-16 16:57:48 +02:00
assert_equal ( address_info [ ' iswatchonly ' ] , False )
assert_equal ( address_info [ ' ismine ' ] , False )
# RPC importmulti -----------------------------------------------
2018-11-07 17:24:34 +01:00
# Bitcoin Address (implicit non-internal)
2017-03-08 00:46:17 +01:00
self . log . info ( " Should import an address " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2pkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = True ,
ismine = False ,
timestamp = timestamp ,
ischange = False )
2018-12-13 18:32:50 +01:00
watchonly_address = key . p2pkh_addr
2016-11-08 22:55:02 +01:00
watchonly_timestamp = timestamp
2016-06-16 16:57:48 +02:00
2017-03-08 00:46:17 +01:00
self . log . info ( " Should not import an invalid address " )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : " not valid address " } ,
" timestamp " : " now " } ,
2018-12-13 18:32:50 +01:00
success = False ,
2018-12-06 15:52:38 +01:00
error_code = - 5 ,
2018-10-25 03:28:17 +02:00
error_message = ' Invalid address \" not valid address \" ' )
2016-06-16 16:57:48 +02:00
# ScriptPubKey + internal
2017-03-08 00:46:17 +01:00
self . log . info ( " Should import a scriptPubKey with internal flag " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : key . p2pkh_script ,
" timestamp " : " now " ,
" internal " : True } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = True ,
ismine = False ,
timestamp = timestamp ,
ischange = True )
2016-06-16 16:57:48 +02:00
2018-10-09 07:43:20 +02:00
# ScriptPubKey + internal + label
self . log . info ( " Should not allow a label to be specified when internal is true " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : key . p2pkh_script ,
" timestamp " : " now " ,
" internal " : True ,
2019-10-28 11:11:20 +01:00
" label " : " Unsuccessful labelling for internal addresses " } ,
2018-12-13 18:32:50 +01:00
success = False ,
2018-12-06 15:52:38 +01:00
error_code = - 8 ,
error_message = ' Internal addresses should not have a label ' )
2018-10-09 07:43:20 +02:00
2016-11-28 23:19:27 +01:00
# Nonstandard scriptPubKey + !internal
self . log . info ( " Should not import a nonstandard scriptPubKey without internal flag " )
2019-02-18 16:35:48 +01:00
nonstandardScriptPubKey = key . p2pkh_script + CScript ( [ OP_NOP ] ) . hex ( )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : nonstandardScriptPubKey ,
" timestamp " : " now " } ,
2018-12-13 18:32:50 +01:00
success = False ,
2018-12-06 15:52:38 +01:00
error_code = - 8 ,
error_message = ' Internal must be set to true for nonstandard scriptPubKey imports. ' )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = False ,
ismine = False ,
timestamp = None )
2016-06-16 16:57:48 +02:00
2018-11-07 17:24:34 +01:00
# Address + Public key + !Internal(explicit)
2017-03-08 00:46:17 +01:00
self . log . info ( " Should import an address with public key " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2pkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " ,
" pubkeys " : [ key . pubkey ] ,
" internal " : False } ,
2018-12-13 18:32:50 +01:00
success = True ,
2018-10-25 03:28:17 +02:00
warnings = [ " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = True ,
ismine = False ,
timestamp = timestamp )
2016-06-16 16:57:48 +02:00
# ScriptPubKey + Public key + internal
2017-03-08 00:46:17 +01:00
self . log . info ( " Should import a scriptPubKey with internal and with public key " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : key . p2pkh_script ,
" timestamp " : " now " ,
" pubkeys " : [ key . pubkey ] ,
" internal " : True } ,
2018-12-13 18:32:50 +01:00
success = True ,
2018-10-25 03:28:17 +02:00
warnings = [ " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = True ,
ismine = False ,
timestamp = timestamp )
2016-06-16 16:57:48 +02:00
2016-11-28 23:19:27 +01:00
# Nonstandard scriptPubKey + Public key + !internal
self . log . info ( " Should not import a nonstandard scriptPubKey without internal and with public key " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : nonstandardScriptPubKey ,
" timestamp " : " now " ,
" pubkeys " : [ key . pubkey ] } ,
2018-12-13 18:32:50 +01:00
success = False ,
2018-12-06 15:52:38 +01:00
error_code = - 8 ,
error_message = ' Internal must be set to true for nonstandard scriptPubKey imports. ' )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = False ,
ismine = False ,
timestamp = None )
2016-06-16 16:57:48 +02:00
# Address + Private key + !watchonly
2017-03-08 00:46:17 +01:00
self . log . info ( " Should import an address with private key " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2pkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " ,
" keys " : [ key . privkey ] } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = False ,
ismine = True ,
timestamp = timestamp )
2016-06-16 16:57:48 +02:00
2017-10-11 12:12:59 +02:00
self . log . info ( " Should not import an address with private key if is already imported " )
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2pkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " ,
" keys " : [ key . privkey ] } ,
2018-12-13 18:32:50 +01:00
success = False ,
2018-12-06 15:52:38 +01:00
error_code = - 4 ,
2018-12-13 02:01:36 +01:00
error_message = ' The wallet already contains the private key for this address or script ( " ' + key . p2pkh_script + ' " ) ' )
2017-10-11 12:12:59 +02:00
2016-06-16 16:57:48 +02:00
# Address + Private key + watchonly
2018-10-25 03:28:17 +02:00
self . log . info ( " Should import an address with private key and with watchonly " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2pkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " ,
" keys " : [ key . privkey ] ,
" watchonly " : True } ,
2018-12-13 18:32:50 +01:00
success = True ,
2018-10-25 03:28:17 +02:00
warnings = [ " All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag. " ] )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = False ,
ismine = True ,
timestamp = timestamp )
2016-06-16 16:57:48 +02:00
# ScriptPubKey + Private key + internal
2017-03-08 00:46:17 +01:00
self . log . info ( " Should import a scriptPubKey with internal and with private key " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : key . p2pkh_script ,
" timestamp " : " now " ,
" keys " : [ key . privkey ] ,
" internal " : True } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = False ,
ismine = True ,
timestamp = timestamp )
2016-06-16 16:57:48 +02:00
2016-11-28 23:19:27 +01:00
# Nonstandard scriptPubKey + Private key + !internal
self . log . info ( " Should not import a nonstandard scriptPubKey without internal and with private key " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : nonstandardScriptPubKey ,
" timestamp " : " now " ,
" keys " : [ key . privkey ] } ,
2018-12-13 18:32:50 +01:00
success = False ,
2018-12-06 15:52:38 +01:00
error_code = - 8 ,
error_message = ' Internal must be set to true for nonstandard scriptPubKey imports. ' )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = False ,
ismine = False ,
timestamp = None )
2016-06-16 16:57:48 +02:00
# P2SH address
2018-12-13 18:43:35 +01:00
multisig = get_multisig ( self . nodes [ 0 ] )
2020-11-10 18:02:31 +01:00
self . generate ( self . nodes [ 1 ] , COINBASE_MATURITY , sync_fun = self . no_op )
2018-12-06 00:28:32 +01:00
self . nodes [ 1 ] . sendtoaddress ( multisig . p2sh_addr , 10.00 )
2020-11-10 18:02:31 +01:00
self . generate ( self . nodes [ 1 ] , 1 , sync_fun = self . no_op )
2016-11-08 22:55:02 +01:00
timestamp = self . nodes [ 1 ] . getblock ( self . nodes [ 1 ] . getbestblockhash ( ) ) [ ' mediantime ' ]
2016-06-16 16:57:48 +02:00
2017-03-08 00:46:17 +01:00
self . log . info ( " Should import a p2sh " )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : multisig . p2sh_addr } ,
" timestamp " : " now " } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
multisig . p2sh_addr ,
isscript = True ,
iswatchonly = True ,
timestamp = timestamp )
2018-12-06 00:28:32 +01:00
p2shunspent = self . nodes [ 1 ] . listunspent ( 0 , 999999 , [ multisig . p2sh_addr ] ) [ 0 ]
2016-06-16 16:57:48 +02:00
assert_equal ( p2shunspent [ ' spendable ' ] , False )
assert_equal ( p2shunspent [ ' solvable ' ] , False )
# P2SH + Redeem script
2018-12-13 18:43:35 +01:00
multisig = get_multisig ( self . nodes [ 0 ] )
2020-11-10 18:02:31 +01:00
self . generate ( self . nodes [ 1 ] , COINBASE_MATURITY , sync_fun = self . no_op )
2018-12-06 00:28:32 +01:00
self . nodes [ 1 ] . sendtoaddress ( multisig . p2sh_addr , 10.00 )
2020-11-10 18:02:31 +01:00
self . generate ( self . nodes [ 1 ] , 1 , sync_fun = self . no_op )
2016-11-08 22:55:02 +01:00
timestamp = self . nodes [ 1 ] . getblock ( self . nodes [ 1 ] . getbestblockhash ( ) ) [ ' mediantime ' ]
2016-06-16 16:57:48 +02:00
2017-03-08 00:46:17 +01:00
self . log . info ( " Should import a p2sh with respective redeem script " )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : multisig . p2sh_addr } ,
" timestamp " : " now " ,
" redeemscript " : multisig . redeem_script } ,
2018-12-13 18:32:50 +01:00
success = True ,
2018-10-25 03:28:17 +02:00
warnings = [ " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
multisig . p2sh_addr , timestamp = timestamp , iswatchonly = True , ismine = False , solvable = True )
2016-06-16 16:57:48 +02:00
2018-12-06 00:28:32 +01:00
p2shunspent = self . nodes [ 1 ] . listunspent ( 0 , 999999 , [ multisig . p2sh_addr ] ) [ 0 ]
2016-06-16 16:57:48 +02:00
assert_equal ( p2shunspent [ ' spendable ' ] , False )
assert_equal ( p2shunspent [ ' solvable ' ] , True )
# P2SH + Redeem script + Private Keys + !Watchonly
2018-12-13 18:43:35 +01:00
multisig = get_multisig ( self . nodes [ 0 ] )
2020-11-10 18:02:31 +01:00
self . generate ( self . nodes [ 1 ] , COINBASE_MATURITY , sync_fun = self . no_op )
2018-12-06 00:28:32 +01:00
self . nodes [ 1 ] . sendtoaddress ( multisig . p2sh_addr , 10.00 )
2020-11-10 18:02:31 +01:00
self . generate ( self . nodes [ 1 ] , 1 , sync_fun = self . no_op )
2016-11-08 22:55:02 +01:00
timestamp = self . nodes [ 1 ] . getblock ( self . nodes [ 1 ] . getbestblockhash ( ) ) [ ' mediantime ' ]
2016-06-16 16:57:48 +02:00
2017-03-08 00:46:17 +01:00
self . log . info ( " Should import a p2sh with respective redeem script and private keys " )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : multisig . p2sh_addr } ,
" timestamp " : " now " ,
" redeemscript " : multisig . redeem_script ,
" keys " : multisig . privkeys [ 0 : 2 ] } ,
2018-12-13 18:32:50 +01:00
success = True ,
2018-10-25 03:28:17 +02:00
warnings = [ " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
multisig . p2sh_addr ,
timestamp = timestamp ,
ismine = False ,
iswatchonly = True ,
solvable = True )
2016-06-16 16:57:48 +02:00
2018-12-06 00:28:32 +01:00
p2shunspent = self . nodes [ 1 ] . listunspent ( 0 , 999999 , [ multisig . p2sh_addr ] ) [ 0 ]
2016-06-16 16:57:48 +02:00
assert_equal ( p2shunspent [ ' spendable ' ] , False )
assert_equal ( p2shunspent [ ' solvable ' ] , True )
# P2SH + Redeem script + Private Keys + Watchonly
2018-12-13 18:43:35 +01:00
multisig = get_multisig ( self . nodes [ 0 ] )
2020-11-10 18:02:31 +01:00
self . generate ( self . nodes [ 1 ] , COINBASE_MATURITY , sync_fun = self . no_op )
2018-12-06 00:28:32 +01:00
self . nodes [ 1 ] . sendtoaddress ( multisig . p2sh_addr , 10.00 )
2020-11-10 18:02:31 +01:00
self . generate ( self . nodes [ 1 ] , 1 , sync_fun = self . no_op )
2017-02-21 16:53:07 +01:00
timestamp = self . nodes [ 1 ] . getblock ( self . nodes [ 1 ] . getbestblockhash ( ) ) [ ' mediantime ' ]
2016-06-16 16:57:48 +02:00
2017-03-08 00:46:17 +01:00
self . log . info ( " Should import a p2sh with respective redeem script and private keys " )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : multisig . p2sh_addr } ,
" timestamp " : " now " ,
" redeemscript " : multisig . redeem_script ,
" keys " : multisig . privkeys [ 0 : 2 ] ,
" watchonly " : True } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
multisig . p2sh_addr ,
iswatchonly = True ,
ismine = False ,
solvable = True ,
timestamp = timestamp )
2016-06-16 16:57:48 +02:00
2016-10-19 16:17:42 +02:00
# Address + Public key + !Internal + Wrong pubkey
2018-10-25 03:28:17 +02:00
self . log . info ( " Should not import an address with the wrong public key as non-solvable " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
wrong_key = get_key ( self . nodes [ 0 ] ) . pubkey
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2pkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " ,
" pubkeys " : [ wrong_key ] } ,
2018-12-13 18:32:50 +01:00
success = True ,
2018-10-25 03:28:17 +02:00
warnings = [ " Importing as non-solvable: some required keys are missing. If this is intentional, don ' t provide any keys, pubkeys, witnessscript, or redeemscript. " , " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = True ,
ismine = False ,
solvable = False ,
timestamp = timestamp )
2016-10-19 16:17:42 +02:00
# ScriptPubKey + Public key + internal + Wrong pubkey
2018-10-25 03:28:17 +02:00
self . log . info ( " Should import a scriptPubKey with internal and with a wrong public key as non-solvable " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
wrong_key = get_key ( self . nodes [ 0 ] ) . pubkey
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : key . p2pkh_script ,
" timestamp " : " now " ,
" pubkeys " : [ wrong_key ] ,
" internal " : True } ,
2018-12-13 18:32:50 +01:00
success = True ,
2018-10-25 03:28:17 +02:00
warnings = [ " Importing as non-solvable: some required keys are missing. If this is intentional, don ' t provide any keys, pubkeys, witnessscript, or redeemscript. " , " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = True ,
ismine = False ,
solvable = False ,
timestamp = timestamp )
2016-06-16 16:57:48 +02:00
2016-10-19 16:17:42 +02:00
# Address + Private key + !watchonly + Wrong private key
2018-10-25 03:28:17 +02:00
self . log . info ( " Should import an address with a wrong private key as non-solvable " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
wrong_privkey = get_key ( self . nodes [ 0 ] ) . privkey
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2pkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " ,
" keys " : [ wrong_privkey ] } ,
2018-12-13 18:32:50 +01:00
success = True ,
2018-10-25 03:28:17 +02:00
warnings = [ " Importing as non-solvable: some required keys are missing. If this is intentional, don ' t provide any keys, pubkeys, witnessscript, or redeemscript. " , " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = True ,
ismine = False ,
solvable = False ,
timestamp = timestamp )
2016-10-19 16:17:42 +02:00
# ScriptPubKey + Private key + internal + Wrong private key
2018-10-25 03:28:17 +02:00
self . log . info ( " Should import a scriptPubKey with internal and with a wrong private key as non-solvable " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
wrong_privkey = get_key ( self . nodes [ 0 ] ) . privkey
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : key . p2pkh_script ,
" timestamp " : " now " ,
" keys " : [ wrong_privkey ] ,
" internal " : True } ,
2018-12-13 18:32:50 +01:00
success = True ,
2018-10-25 03:28:17 +02:00
warnings = [ " Importing as non-solvable: some required keys are missing. If this is intentional, don ' t provide any keys, pubkeys, witnessscript, or redeemscript. " , " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
iswatchonly = True ,
ismine = False ,
solvable = False ,
timestamp = timestamp )
2016-11-08 22:55:02 +01:00
2017-02-21 16:53:07 +01:00
# Importing existing watch only address with new timestamp should replace saved timestamp.
assert_greater_than ( timestamp , watchonly_timestamp )
2017-03-17 23:04:13 +01:00
self . log . info ( " Should replace previously saved watch only timestamp. " )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : watchonly_address } ,
" timestamp " : " now " } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
watchonly_address ,
iswatchonly = True ,
ismine = False ,
timestamp = timestamp )
2017-02-21 16:53:07 +01:00
watchonly_timestamp = timestamp
2016-11-08 22:55:02 +01:00
# restart nodes to check for proper serialization/deserialization of watch only address
2017-03-24 04:56:31 +01:00
self . stop_nodes ( )
2017-06-09 22:35:17 +02:00
self . start_nodes ( )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
watchonly_address ,
iswatchonly = True ,
ismine = False ,
timestamp = watchonly_timestamp )
2016-10-19 16:17:42 +02:00
2017-02-03 22:23:13 +01:00
# Bad or missing timestamps
2017-03-08 00:46:17 +01:00
self . log . info ( " Should throw on invalid or missing timestamp values " )
2017-07-12 16:33:46 +02:00
assert_raises_rpc_error ( - 3 , ' Missing required timestamp field for key ' ,
2018-12-06 00:28:32 +01:00
self . nodes [ 1 ] . importmulti , [ { " scriptPubKey " : key . p2pkh_script } ] )
2017-07-12 16:33:46 +02:00
assert_raises_rpc_error ( - 3 , ' Expected number or " now " timestamp value for key. got type string ' ,
2018-11-30 23:47:46 +01:00
self . nodes [ 1 ] . importmulti , [ {
2018-12-06 00:28:32 +01:00
" scriptPubKey " : key . p2pkh_script ,
2018-11-30 23:47:46 +01:00
" timestamp " : " "
} ] )
2017-02-03 22:23:13 +01:00
2018-10-09 07:43:20 +02:00
# Import P2WPKH address as watch only
self . log . info ( " Should import a P2WPKH address as watch only " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2wpkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2wpkh_addr ,
iswatchonly = True ,
solvable = False )
2018-10-09 07:43:20 +02:00
# Import P2WPKH address with public key but no private key
self . log . info ( " Should import a P2WPKH address and public key as solvable but not spendable " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2wpkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " ,
" pubkeys " : [ key . pubkey ] } ,
2018-12-13 18:32:50 +01:00
success = True ,
2018-10-25 03:28:17 +02:00
warnings = [ " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2wpkh_addr ,
ismine = False ,
solvable = True )
2018-10-09 07:43:20 +02:00
# Import P2WPKH address with key and check it is spendable
self . log . info ( " Should import a P2WPKH address with key " )
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2wpkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " ,
" keys " : [ key . privkey ] } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2wpkh_addr ,
iswatchonly = False ,
ismine = True )
2018-10-09 07:43:20 +02:00
# P2WSH multisig address without scripts or keys
2018-12-13 18:43:35 +01:00
multisig = get_multisig ( self . nodes [ 0 ] )
2018-10-09 07:43:20 +02:00
self . log . info ( " Should import a p2wsh multisig as watch only without respective redeem script and private keys " )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : multisig . p2wsh_addr } ,
" timestamp " : " now " } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
multisig . p2sh_addr ,
solvable = False )
2018-10-09 07:43:20 +02:00
# Same P2WSH multisig address as above, but now with witnessscript + private keys
2018-12-06 00:28:32 +01:00
self . log . info ( " Should import a p2wsh with respective witness script and private keys " )
2018-12-06 15:52:38 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : multisig . p2wsh_addr } ,
" timestamp " : " now " ,
" witnessscript " : multisig . redeem_script ,
" keys " : multisig . privkeys } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
multisig . p2sh_addr ,
solvable = True ,
ismine = True ,
sigsrequired = 2 )
2018-10-09 07:43:20 +02:00
# P2SH-P2WPKH address with no redeemscript or public or private key
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-10-09 07:43:20 +02:00
self . log . info ( " Should import a p2sh-p2wpkh without redeem script or keys " )
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2sh_p2wpkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2sh_p2wpkh_addr ,
solvable = False ,
ismine = False )
2018-10-09 07:43:20 +02:00
# P2SH-P2WPKH address + redeemscript + public key with no private key
self . log . info ( " Should import a p2sh-p2wpkh with respective redeem script and pubkey as solvable " )
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2sh_p2wpkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " ,
" redeemscript " : key . p2sh_p2wpkh_redeem_script ,
" pubkeys " : [ key . pubkey ] } ,
2018-12-13 18:32:50 +01:00
success = True ,
2018-10-25 03:28:17 +02:00
warnings = [ " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2sh_p2wpkh_addr ,
solvable = True ,
ismine = False )
2018-10-09 07:43:20 +02:00
# P2SH-P2WPKH address + redeemscript + private key
2018-12-13 18:43:35 +01:00
key = get_key ( self . nodes [ 0 ] )
2018-10-09 07:43:20 +02:00
self . log . info ( " Should import a p2sh-p2wpkh with respective redeem script and private keys " )
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : key . p2sh_p2wpkh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " ,
" redeemscript " : key . p2sh_p2wpkh_redeem_script ,
" keys " : [ key . privkey ] } ,
2018-12-13 18:32:50 +01:00
success = True )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
key . p2sh_p2wpkh_addr ,
solvable = True ,
ismine = True )
2018-10-09 07:43:20 +02:00
2018-12-06 00:28:32 +01:00
# P2SH-P2WSH multisig + redeemscript with no private key
2018-12-13 18:43:35 +01:00
multisig = get_multisig ( self . nodes [ 0 ] )
2018-10-09 07:43:20 +02:00
self . log . info ( " Should import a p2sh-p2wsh with respective redeem script but no private key " )
2018-12-13 18:32:50 +01:00
self . test_importmulti ( { " scriptPubKey " : { " address " : multisig . p2sh_p2wsh_addr } ,
2018-12-06 15:52:38 +01:00
" timestamp " : " now " ,
" redeemscript " : multisig . p2wsh_script ,
" witnessscript " : multisig . redeem_script } ,
2018-12-13 18:32:50 +01:00
success = True ,
2018-10-25 03:28:17 +02:00
warnings = [ " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
2018-12-13 18:43:35 +01:00
test_address ( self . nodes [ 1 ] ,
multisig . p2sh_p2wsh_addr ,
solvable = True ,
ismine = False )
2017-02-03 22:23:13 +01:00
2018-12-13 02:01:36 +01:00
# Test importing of a P2SH-P2WPKH address via descriptor + private key
key = get_key ( self . nodes [ 0 ] )
2019-02-13 03:56:53 +01:00
self . log . info ( " Should not import a p2sh-p2wpkh address from descriptor without checksum and private key " )
2018-12-13 02:01:36 +01:00
self . test_importmulti ( { " desc " : " sh(wpkh( " + key . pubkey + " )) " ,
" timestamp " : " now " ,
2019-10-28 11:11:20 +01:00
" label " : " Unsuccessful P2SH-P2WPKH descriptor import " ,
2018-12-13 02:01:36 +01:00
" keys " : [ key . privkey ] } ,
2019-02-13 03:56:53 +01:00
success = False ,
error_code = - 5 ,
2019-08-03 01:19:53 +02:00
error_message = " Missing checksum " )
2019-02-13 03:56:53 +01:00
# Test importing of a P2SH-P2WPKH address via descriptor + private key
key = get_key ( self . nodes [ 0 ] )
2019-10-28 11:11:20 +01:00
p2sh_p2wpkh_label = " Successful P2SH-P2WPKH descriptor import "
2019-02-13 03:56:53 +01:00
self . log . info ( " Should import a p2sh-p2wpkh address from descriptor and private key " )
self . test_importmulti ( { " desc " : descsum_create ( " sh(wpkh( " + key . pubkey + " )) " ) ,
" timestamp " : " now " ,
2019-10-28 11:11:20 +01:00
" label " : p2sh_p2wpkh_label ,
2019-02-13 03:56:53 +01:00
" keys " : [ key . privkey ] } ,
2018-12-13 02:01:36 +01:00
success = True )
test_address ( self . nodes [ 1 ] ,
key . p2sh_p2wpkh_addr ,
solvable = True ,
ismine = True ,
2019-11-24 12:05:38 +01:00
labels = [ p2sh_p2wpkh_label ] )
2018-12-13 02:01:36 +01:00
# Test ranged descriptor fails if range is not specified
xpriv = " tprv8ZgxMBicQKsPeuVhWwi6wuMQGfPKi9Li5GtX35jVNknACgqe3CY4g5xgkfDDJcmtF7o1QnxWDRYw4H5P26PXq7sbcUkEqeR4fg3Kxp2tigg "
addresses = [ " 2N7yv4p8G8yEaPddJxY41kPihnWvs39qCMf " , " 2MsHxyb2JS3pAySeNUsJ7mNnurtpeenDzLA " ] # hdkeypath=m/0'/0'/0' and 1'
2019-06-07 10:05:00 +02:00
addresses + = [ " bcrt1qrd3n235cj2czsfmsuvqqpr3lu6lg0ju7scl8gn " , " bcrt1qfqeppuvj0ww98r6qghmdkj70tv8qpchehegrg8 " ] # wpkh subscripts corresponding to the above addresses
2018-12-13 02:01:36 +01:00
desc = " sh(wpkh( " + xpriv + " /0 ' /0 ' /* ' " + " )) "
self . log . info ( " Ranged descriptor import should fail without a specified range " )
2019-02-13 03:56:53 +01:00
self . test_importmulti ( { " desc " : descsum_create ( desc ) ,
2018-12-13 02:01:36 +01:00
" timestamp " : " now " } ,
success = False ,
error_code = - 8 ,
error_message = ' Descriptor is ranged, please specify the range ' )
2018-12-19 03:56:42 +01:00
# Test importing of a ranged descriptor with xpriv
2018-12-13 02:01:36 +01:00
self . log . info ( " Should import the ranged descriptor with specified range as solvable " )
2019-02-13 03:56:53 +01:00
self . test_importmulti ( { " desc " : descsum_create ( desc ) ,
2018-12-13 02:01:36 +01:00
" timestamp " : " now " ,
2019-02-27 22:59:35 +01:00
" range " : 1 } ,
2018-12-19 03:56:42 +01:00
success = True )
2018-12-13 02:01:36 +01:00
for address in addresses :
test_address ( self . nodes [ 1 ] ,
2018-12-19 03:56:42 +01:00
address ,
solvable = True ,
ismine = True )
2018-12-13 02:01:36 +01:00
2019-04-04 09:39:04 +02:00
self . test_importmulti ( { " desc " : descsum_create ( desc ) , " timestamp " : " now " , " range " : - 1 } ,
success = False , error_code = - 8 , error_message = ' End of range is too high ' )
self . test_importmulti ( { " desc " : descsum_create ( desc ) , " timestamp " : " now " , " range " : [ - 1 , 10 ] } ,
success = False , error_code = - 8 , error_message = ' Range should be greater or equal than 0 ' )
self . test_importmulti ( { " desc " : descsum_create ( desc ) , " timestamp " : " now " , " range " : [ ( 2 << 31 + 1 ) - 1000000 , ( 2 << 31 + 1 ) ] } ,
success = False , error_code = - 8 , error_message = ' End of range is too high ' )
self . test_importmulti ( { " desc " : descsum_create ( desc ) , " timestamp " : " now " , " range " : [ 2 , 1 ] } ,
success = False , error_code = - 8 , error_message = ' Range specified as [begin,end] must not have begin after end ' )
self . test_importmulti ( { " desc " : descsum_create ( desc ) , " timestamp " : " now " , " range " : [ 0 , 1000001 ] } ,
success = False , error_code = - 8 , error_message = ' Range is too large ' )
2019-06-07 10:05:00 +02:00
# Test importing a descriptor containing a WIF private key
wif_priv = " cTe1f5rdT8A8DFgVWTjyPwACsDPJM9ff4QngFxUixCSvvbg1x6sh "
address = " 2MuhcG52uHPknxDgmGPsV18jSHFBnnRgjPg "
desc = " sh(wpkh( " + wif_priv + " )) "
self . log . info ( " Should import a descriptor with a WIF private key as spendable " )
self . test_importmulti ( { " desc " : descsum_create ( desc ) ,
" timestamp " : " now " } ,
success = True )
test_address ( self . nodes [ 1 ] ,
address ,
solvable = True ,
ismine = True )
2019-06-07 15:34:58 +02:00
# dump the private key to ensure it matches what was imported
privkey = self . nodes [ 1 ] . dumpprivkey ( address )
assert_equal ( privkey , wif_priv )
2018-12-13 02:01:36 +01:00
# Test importing of a P2PKH address via descriptor
key = get_key ( self . nodes [ 0 ] )
2019-10-28 11:11:20 +01:00
p2pkh_label = " P2PKH descriptor import "
2018-12-13 02:01:36 +01:00
self . log . info ( " Should import a p2pkh address from descriptor " )
2019-02-13 03:56:53 +01:00
self . test_importmulti ( { " desc " : descsum_create ( " pkh( " + key . pubkey + " ) " ) ,
2018-12-13 02:01:36 +01:00
" timestamp " : " now " ,
2019-10-28 11:11:20 +01:00
" label " : p2pkh_label } ,
2018-12-13 02:01:36 +01:00
True ,
warnings = [ " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
test_address ( self . nodes [ 1 ] ,
key . p2pkh_addr ,
solvable = True ,
ismine = False ,
2019-11-24 12:05:38 +01:00
labels = [ p2pkh_label ] )
2018-12-13 02:01:36 +01:00
# Test import fails if both desc and scriptPubKey are provided
key = get_key ( self . nodes [ 0 ] )
self . log . info ( " Import should fail if both scriptPubKey and desc are provided " )
2019-02-13 03:56:53 +01:00
self . test_importmulti ( { " desc " : descsum_create ( " pkh( " + key . pubkey + " ) " ) ,
2018-12-13 02:01:36 +01:00
" scriptPubKey " : { " address " : key . p2pkh_addr } ,
" timestamp " : " now " } ,
success = False ,
error_code = - 8 ,
error_message = ' Both a descriptor and a scriptPubKey should not be provided. ' )
# Test import fails if neither desc nor scriptPubKey are present
key = get_key ( self . nodes [ 0 ] )
self . log . info ( " Import should fail if neither a descriptor nor a scriptPubKey are provided " )
self . test_importmulti ( { " timestamp " : " now " } ,
success = False ,
error_code = - 8 ,
error_message = ' Either a descriptor or scriptPubKey must be provided. ' )
# Test importing of a multisig via descriptor
key1 = get_key ( self . nodes [ 0 ] )
key2 = get_key ( self . nodes [ 0 ] )
self . log . info ( " Should import a 1-of-2 bare multisig from descriptor " )
2019-02-13 03:56:53 +01:00
self . test_importmulti ( { " desc " : descsum_create ( " multi(1, " + key1 . pubkey + " , " + key2 . pubkey + " ) " ) ,
2018-12-13 02:01:36 +01:00
" timestamp " : " now " } ,
2019-04-06 17:23:19 +02:00
success = True ,
warnings = [ " Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag. " ] )
2018-12-13 02:01:36 +01:00
self . log . info ( " Should not treat individual keys from the imported bare multisig as watchonly " )
test_address ( self . nodes [ 1 ] ,
key1 . p2pkh_addr ,
ismine = False ,
iswatchonly = False )
2018-11-06 15:23:51 +01:00
# Import pubkeys with key origin info
self . log . info ( " Addresses should have hd keypath and master key id after import with key origin " )
pub_addr = self . nodes [ 1 ] . getnewaddress ( )
2019-11-05 23:18:03 +01:00
pub_addr = self . nodes [ 1 ] . getnewaddress ( address_type = " bech32 " )
2018-11-06 15:23:51 +01:00
info = self . nodes [ 1 ] . getaddressinfo ( pub_addr )
pub = info [ ' pubkey ' ]
pub_keypath = info [ ' hdkeypath ' ]
pub_fpr = info [ ' hdmasterfingerprint ' ]
result = self . nodes [ 0 ] . importmulti (
[ {
2019-02-13 03:56:53 +01:00
' desc ' : descsum_create ( " wpkh([ " + pub_fpr + pub_keypath [ 1 : ] + " ] " + pub + " ) " ) ,
2018-11-06 15:23:51 +01:00
" timestamp " : " now " ,
} ]
)
assert result [ 0 ] [ ' success ' ]
pub_import_info = self . nodes [ 0 ] . getaddressinfo ( pub_addr )
assert_equal ( pub_import_info [ ' hdmasterfingerprint ' ] , pub_fpr )
assert_equal ( pub_import_info [ ' pubkey ' ] , pub )
assert_equal ( pub_import_info [ ' hdkeypath ' ] , pub_keypath )
# Import privkeys with key origin info
2019-11-05 23:18:03 +01:00
priv_addr = self . nodes [ 1 ] . getnewaddress ( address_type = " bech32 " )
2018-11-06 15:23:51 +01:00
info = self . nodes [ 1 ] . getaddressinfo ( priv_addr )
priv = self . nodes [ 1 ] . dumpprivkey ( priv_addr )
priv_keypath = info [ ' hdkeypath ' ]
priv_fpr = info [ ' hdmasterfingerprint ' ]
result = self . nodes [ 0 ] . importmulti (
[ {
2019-02-13 03:56:53 +01:00
' desc ' : descsum_create ( " wpkh([ " + priv_fpr + priv_keypath [ 1 : ] + " ] " + priv + " ) " ) ,
2018-11-06 15:23:51 +01:00
" timestamp " : " now " ,
} ]
)
assert result [ 0 ] [ ' success ' ]
priv_import_info = self . nodes [ 0 ] . getaddressinfo ( priv_addr )
assert_equal ( priv_import_info [ ' hdmasterfingerprint ' ] , priv_fpr )
assert_equal ( priv_import_info [ ' hdkeypath ' ] , priv_keypath )
# Make sure the key origin info are still there after a restart
self . stop_nodes ( )
self . start_nodes ( )
import_info = self . nodes [ 0 ] . getaddressinfo ( pub_addr )
assert_equal ( import_info [ ' hdmasterfingerprint ' ] , pub_fpr )
assert_equal ( import_info [ ' hdkeypath ' ] , pub_keypath )
import_info = self . nodes [ 0 ] . getaddressinfo ( priv_addr )
assert_equal ( import_info [ ' hdmasterfingerprint ' ] , priv_fpr )
assert_equal ( import_info [ ' hdkeypath ' ] , priv_keypath )
# Check legacy import does not import key origin info
self . log . info ( " Legacy imports don ' t have key origin info " )
pub_addr = self . nodes [ 1 ] . getnewaddress ( )
info = self . nodes [ 1 ] . getaddressinfo ( pub_addr )
pub = info [ ' pubkey ' ]
result = self . nodes [ 0 ] . importmulti (
[ {
' scriptPubKey ' : { ' address ' : pub_addr } ,
' pubkeys ' : [ pub ] ,
" timestamp " : " now " ,
} ]
)
assert result [ 0 ] [ ' success ' ]
pub_import_info = self . nodes [ 0 ] . getaddressinfo ( pub_addr )
assert_equal ( pub_import_info [ ' pubkey ' ] , pub )
assert ' hdmasterfingerprint ' not in pub_import_info
assert ' hdkeypath ' not in pub_import_info
2021-06-04 23:35:47 +02:00
# Bech32m addresses and descriptors cannot be imported
self . log . info ( " Bech32m addresses and descriptors cannot be imported " )
self . test_importmulti (
{
" scriptPubKey " : { " address " : " bcrt1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqc8gma6 " } ,
" timestamp " : " now " ,
} ,
success = False ,
error_code = - 5 ,
error_message = " Bech32m addresses cannot be imported into legacy wallets " ,
)
self . test_importmulti (
{
" desc " : descsum_create ( " tr( {} ) " . format ( pub ) ) ,
" timestamp " : " now " ,
} ,
success = False ,
error_code = - 5 ,
error_message = " Bech32m descriptors cannot be imported into legacy wallets " ,
)
2018-11-06 16:14:12 +01:00
# Import some public keys to the keypool of a no privkey wallet
self . log . info ( " Adding pubkey to keypool of disableprivkey wallet " )
self . nodes [ 1 ] . createwallet ( wallet_name = " noprivkeys " , disable_private_keys = True )
wrpc = self . nodes [ 1 ] . get_wallet_rpc ( " noprivkeys " )
2019-11-05 23:18:03 +01:00
addr1 = self . nodes [ 0 ] . getnewaddress ( address_type = " bech32 " )
addr2 = self . nodes [ 0 ] . getnewaddress ( address_type = " bech32 " )
2018-11-06 16:14:12 +01:00
pub1 = self . nodes [ 0 ] . getaddressinfo ( addr1 ) [ ' pubkey ' ]
pub2 = self . nodes [ 0 ] . getaddressinfo ( addr2 ) [ ' pubkey ' ]
result = wrpc . importmulti (
[ {
2019-02-13 03:56:53 +01:00
' desc ' : descsum_create ( ' wpkh( ' + pub1 + ' ) ' ) ,
2018-11-06 16:14:12 +01:00
' keypool ' : True ,
" timestamp " : " now " ,
} ,
{
2019-02-13 03:56:53 +01:00
' desc ' : descsum_create ( ' wpkh( ' + pub2 + ' ) ' ) ,
2018-11-06 16:14:12 +01:00
' keypool ' : True ,
" timestamp " : " now " ,
} ]
)
assert result [ 0 ] [ ' success ' ]
assert result [ 1 ] [ ' success ' ]
assert_equal ( wrpc . getwalletinfo ( ) [ " keypoolsize " ] , 2 )
2019-11-05 23:18:03 +01:00
newaddr1 = wrpc . getnewaddress ( address_type = " bech32 " )
2018-11-06 16:14:12 +01:00
assert_equal ( addr1 , newaddr1 )
2019-11-05 23:18:03 +01:00
newaddr2 = wrpc . getnewaddress ( address_type = " bech32 " )
2018-11-06 16:14:12 +01:00
assert_equal ( addr2 , newaddr2 )
# Import some public keys to the internal keypool of a no privkey wallet
self . log . info ( " Adding pubkey to internal keypool of disableprivkey wallet " )
2019-11-05 23:18:03 +01:00
addr1 = self . nodes [ 0 ] . getnewaddress ( address_type = " bech32 " )
addr2 = self . nodes [ 0 ] . getnewaddress ( address_type = " bech32 " )
2018-11-06 16:14:12 +01:00
pub1 = self . nodes [ 0 ] . getaddressinfo ( addr1 ) [ ' pubkey ' ]
pub2 = self . nodes [ 0 ] . getaddressinfo ( addr2 ) [ ' pubkey ' ]
result = wrpc . importmulti (
[ {
2019-02-13 03:56:53 +01:00
' desc ' : descsum_create ( ' wpkh( ' + pub1 + ' ) ' ) ,
2018-11-06 16:14:12 +01:00
' keypool ' : True ,
' internal ' : True ,
" timestamp " : " now " ,
} ,
{
2019-02-13 03:56:53 +01:00
' desc ' : descsum_create ( ' wpkh( ' + pub2 + ' ) ' ) ,
2018-11-06 16:14:12 +01:00
' keypool ' : True ,
' internal ' : True ,
" timestamp " : " now " ,
} ]
)
assert result [ 0 ] [ ' success ' ]
assert result [ 1 ] [ ' success ' ]
assert_equal ( wrpc . getwalletinfo ( ) [ " keypoolsize_hd_internal " ] , 2 )
2019-11-05 23:18:03 +01:00
newaddr1 = wrpc . getrawchangeaddress ( address_type = " bech32 " )
2018-11-06 16:14:12 +01:00
assert_equal ( addr1 , newaddr1 )
2019-11-05 23:18:03 +01:00
newaddr2 = wrpc . getrawchangeaddress ( address_type = " bech32 " )
2018-11-06 16:14:12 +01:00
assert_equal ( addr2 , newaddr2 )
# Import a multisig and make sure the keys don't go into the keypool
2019-03-22 18:21:58 +01:00
self . log . info ( ' Imported scripts with pubkeys should not have their pubkeys go into the keypool ' )
2019-11-05 23:18:03 +01:00
addr1 = self . nodes [ 0 ] . getnewaddress ( address_type = " bech32 " )
addr2 = self . nodes [ 0 ] . getnewaddress ( address_type = " bech32 " )
2018-11-06 16:14:12 +01:00
pub1 = self . nodes [ 0 ] . getaddressinfo ( addr1 ) [ ' pubkey ' ]
pub2 = self . nodes [ 0 ] . getaddressinfo ( addr2 ) [ ' pubkey ' ]
result = wrpc . importmulti (
[ {
2019-02-13 03:56:53 +01:00
' desc ' : descsum_create ( ' wsh(multi(2, ' + pub1 + ' , ' + pub2 + ' )) ' ) ,
2018-11-06 16:14:12 +01:00
' keypool ' : True ,
" timestamp " : " now " ,
} ]
)
assert result [ 0 ] [ ' success ' ]
assert_equal ( wrpc . getwalletinfo ( ) [ " keypoolsize " ] , 0 )
# Cannot import those pubkeys to keypool of wallet with privkeys
self . log . info ( " Pubkeys cannot be added to the keypool of a wallet with private keys " )
2020-09-29 02:24:06 +02:00
wrpc = self . nodes [ 1 ] . get_wallet_rpc ( self . default_wallet_name )
2018-11-06 16:14:12 +01:00
assert wrpc . getwalletinfo ( ) [ ' private_keys_enabled ' ]
result = wrpc . importmulti (
[ {
2019-02-13 03:56:53 +01:00
' desc ' : descsum_create ( ' wpkh( ' + pub1 + ' ) ' ) ,
2018-11-06 16:14:12 +01:00
' keypool ' : True ,
" timestamp " : " now " ,
} ]
)
assert_equal ( result [ 0 ] [ ' error ' ] [ ' code ' ] , - 8 )
assert_equal ( result [ 0 ] [ ' error ' ] [ ' message ' ] , " Keys can only be imported to the keypool when private keys are disabled " )
2018-12-16 20:08:55 +01:00
# Make sure ranged imports import keys in order
self . log . info ( ' Key ranges should be imported in order ' )
wrpc = self . nodes [ 1 ] . get_wallet_rpc ( " noprivkeys " )
assert_equal ( wrpc . getwalletinfo ( ) [ " keypoolsize " ] , 0 )
assert_equal ( wrpc . getwalletinfo ( ) [ " private_keys_enabled " ] , False )
xpub = " tpubDAXcJ7s7ZwicqjprRaEWdPoHKrCS215qxGYxpusRLLmJuT69ZSicuGdSfyvyKpvUNYBW1s2U3NSrT6vrCYB9e6nZUEvrqnwXPF8ArTCRXMY "
addresses = [
' bcrt1qtmp74ayg7p24uslctssvjm06q5phz4yrxucgnv ' , # m/0'/0'/0
' bcrt1q8vprchan07gzagd5e6v9wd7azyucksq2xc76k8 ' , # m/0'/0'/1
' bcrt1qtuqdtha7zmqgcrr26n2rqxztv5y8rafjp9lulu ' , # m/0'/0'/2
' bcrt1qau64272ymawq26t90md6an0ps99qkrse58m640 ' , # m/0'/0'/3
' bcrt1qsg97266hrh6cpmutqen8s4s962aryy77jp0fg0 ' , # m/0'/0'/4
]
result = wrpc . importmulti (
[ {
2019-02-13 03:56:53 +01:00
' desc ' : descsum_create ( ' wpkh([80002067/0h/0h] ' + xpub + ' /*) ' ) ,
2018-12-16 20:08:55 +01:00
' keypool ' : True ,
' timestamp ' : ' now ' ,
2019-02-27 22:59:35 +01:00
' range ' : [ 0 , 4 ] ,
2018-12-16 20:08:55 +01:00
} ]
)
for i in range ( 0 , 5 ) :
addr = wrpc . getnewaddress ( ' ' , ' bech32 ' )
assert_equal ( addr , addresses [ i ] )
2020-04-24 01:00:12 +02:00
2016-06-16 16:57:48 +02:00
if __name__ == ' __main__ ' :
2018-11-30 23:47:46 +01:00
ImportMultiTest ( ) . main ( )