1#!/usr/bin/env python3 2# Copyright (c) 2019 The Bitcoin Core developers 3# Distributed under the MIT software license, see the accompanying 4# file COPYING or http://www.opensource.org/licenses/mit-license.php. 5"""Test the importdescriptors RPC. 6 7Test importdescriptors by generating keys on node0, importing the corresponding 8descriptors on node1 and then testing the address info for the different address 9variants. 10 11- `get_generate_key()` is called to generate keys and return the privkeys, 12 pubkeys and all variants of scriptPubKey and address. 13- `test_importdesc()` is called to send an importdescriptors call to node1, test 14 success, and (if unsuccessful) test the error code and error message returned. 15- `test_address()` is called to call getaddressinfo for an address on node1 16 and test the values returned.""" 17 18from test_framework.address import key_to_p2pkh 19from test_framework.test_framework import BitcoinTestFramework 20from test_framework.descriptors import descsum_create 21from test_framework.util import ( 22 assert_equal, 23 assert_raises_rpc_error, 24 find_vout_for_address, 25) 26from test_framework.wallet_util import ( 27 get_generate_key, 28 test_address, 29) 30 31class ImportDescriptorsTest(BitcoinTestFramework): 32 def set_test_params(self): 33 self.num_nodes = 2 34 self.extra_args = [["-addresstype=legacy"], 35 ["-addresstype=bech32", "-keypool=5"] 36 ] 37 self.setup_clean_chain = True 38 self.wallet_names = [] 39 40 def skip_test_if_missing_module(self): 41 self.skip_if_no_wallet() 42 self.skip_if_no_sqlite() 43 44 def test_importdesc(self, req, success, error_code=None, error_message=None, warnings=None, wallet=None): 45 """Run importdescriptors and assert success""" 46 if warnings is None: 47 warnings = [] 48 wrpc = self.nodes[1].get_wallet_rpc('w1') 49 if wallet is not None: 50 wrpc = wallet 51 52 result = wrpc.importdescriptors([req]) 53 observed_warnings = [] 54 if 'warnings' in result[0]: 55 observed_warnings = result[0]['warnings'] 56 assert_equal("\n".join(sorted(warnings)), "\n".join(sorted(observed_warnings))) 57 assert_equal(result[0]['success'], success) 58 if error_code is not None: 59 assert_equal(result[0]['error']['code'], error_code) 60 assert_equal(result[0]['error']['message'], error_message) 61 62 def run_test(self): 63 self.log.info('Setting up wallets') 64 self.nodes[0].createwallet(wallet_name='w0', disable_private_keys=False, descriptors=True) 65 w0 = self.nodes[0].get_wallet_rpc('w0') 66 67 self.nodes[1].createwallet(wallet_name='w1', disable_private_keys=True, blank=True, descriptors=True) 68 w1 = self.nodes[1].get_wallet_rpc('w1') 69 assert_equal(w1.getwalletinfo()['keypoolsize'], 0) 70 71 self.nodes[1].createwallet(wallet_name="wpriv", disable_private_keys=False, blank=True, descriptors=True) 72 wpriv = self.nodes[1].get_wallet_rpc("wpriv") 73 assert_equal(wpriv.getwalletinfo()['keypoolsize'], 0) 74 75 self.log.info('Mining coins') 76 w0.generatetoaddress(101, w0.getnewaddress()) 77 78 # RPC importdescriptors ----------------------------------------------- 79 80 # # Test import fails if no descriptor present 81 key = get_generate_key() 82 self.log.info("Import should fail if a descriptor is not provided") 83 self.test_importdesc({"timestamp": "now"}, 84 success=False, 85 error_code=-8, 86 error_message='Descriptor not found.') 87 88 # # Test importing of a P2PKH descriptor 89 key = get_generate_key() 90 self.log.info("Should import a p2pkh descriptor") 91 self.test_importdesc({"desc": descsum_create("pkh(" + key.pubkey + ")"), 92 "timestamp": "now", 93 "label": "Descriptor import test"}, 94 success=True) 95 test_address(w1, 96 key.p2pkh_addr, 97 solvable=True, 98 ismine=True, 99 labels=["Descriptor import test"]) 100 assert_equal(w1.getwalletinfo()['keypoolsize'], 0) 101 102 self.log.info("Internal addresses cannot have labels") 103 self.test_importdesc({"desc": descsum_create("pkh(" + key.pubkey + ")"), 104 "timestamp": "now", 105 "internal": True, 106 "label": "Descriptor import test"}, 107 success=False, 108 error_code=-8, 109 error_message="Internal addresses should not have a label") 110 111 self.log.info("Internal addresses should be detected as such") 112 key = get_generate_key() 113 addr = key_to_p2pkh(key.pubkey) 114 self.test_importdesc({"desc": descsum_create("pkh(" + key.pubkey + ")"), 115 "timestamp": "now", 116 "internal": True}, 117 success=True) 118 info = w1.getaddressinfo(addr) 119 assert_equal(info["ismine"], True) 120 assert_equal(info["ischange"], True) 121 122 # # Test importing of a P2SH-P2WPKH descriptor 123 key = get_generate_key() 124 self.log.info("Should not import a p2sh-p2wpkh descriptor without checksum") 125 self.test_importdesc({"desc": "sh(wpkh(" + key.pubkey + "))", 126 "timestamp": "now" 127 }, 128 success=False, 129 error_code=-5, 130 error_message="Missing checksum") 131 132 self.log.info("Should not import a p2sh-p2wpkh descriptor that has range specified") 133 self.test_importdesc({"desc": descsum_create("sh(wpkh(" + key.pubkey + "))"), 134 "timestamp": "now", 135 "range": 1, 136 }, 137 success=False, 138 error_code=-8, 139 error_message="Range should not be specified for an un-ranged descriptor") 140 141 self.log.info("Should not import a p2sh-p2wpkh descriptor and have it set to active") 142 self.test_importdesc({"desc": descsum_create("sh(wpkh(" + key.pubkey + "))"), 143 "timestamp": "now", 144 "active": True, 145 }, 146 success=False, 147 error_code=-8, 148 error_message="Active descriptors must be ranged") 149 150 self.log.info("Should import a (non-active) p2sh-p2wpkh descriptor") 151 self.test_importdesc({"desc": descsum_create("sh(wpkh(" + key.pubkey + "))"), 152 "timestamp": "now", 153 "active": False, 154 }, 155 success=True) 156 assert_equal(w1.getwalletinfo()['keypoolsize'], 0) 157 158 test_address(w1, 159 key.p2sh_p2wpkh_addr, 160 ismine=True, 161 solvable=True) 162 163 # Check persistence of data and that loading works correctly 164 w1.unloadwallet() 165 self.nodes[1].loadwallet('w1') 166 test_address(w1, 167 key.p2sh_p2wpkh_addr, 168 ismine=True, 169 solvable=True) 170 171 # # Test importing of a multisig descriptor 172 key1 = get_generate_key() 173 key2 = get_generate_key() 174 self.log.info("Should import a 1-of-2 bare multisig from descriptor") 175 self.test_importdesc({"desc": descsum_create("multi(1," + key1.pubkey + "," + key2.pubkey + ")"), 176 "timestamp": "now"}, 177 success=True) 178 self.log.info("Should not treat individual keys from the imported bare multisig as watchonly") 179 test_address(w1, 180 key1.p2pkh_addr, 181 ismine=False) 182 183 # # Test ranged descriptors 184 xpriv = "tprv8ZgxMBicQKsPeuVhWwi6wuMQGfPKi9Li5GtX35jVNknACgqe3CY4g5xgkfDDJcmtF7o1QnxWDRYw4H5P26PXq7sbcUkEqeR4fg3Kxp2tigg" 185 xpub = "tpubD6NzVbkrYhZ4YNXVQbNhMK1WqguFsUXceaVJKbmno2aZ3B6QfbMeraaYvnBSGpV3vxLyTTK9DYT1yoEck4XUScMzXoQ2U2oSmE2JyMedq3H" 186 addresses = ["2N7yv4p8G8yEaPddJxY41kPihnWvs39qCMf", "2MsHxyb2JS3pAySeNUsJ7mNnurtpeenDzLA"] # hdkeypath=m/0'/0'/0' and 1' 187 addresses += ["ncrt1qrd3n235cj2czsfmsuvqqpr3lu6lg0ju76qa6px", "ncrt1qfqeppuvj0ww98r6qghmdkj70tv8qpcheap27pj"] # wpkh subscripts corresponding to the above addresses 188 desc = "sh(wpkh(" + xpub + "/0/0/*" + "))" 189 190 self.log.info("Ranged descriptors cannot have labels") 191 self.test_importdesc({"desc":descsum_create(desc), 192 "timestamp": "now", 193 "range": [0, 100], 194 "label": "test"}, 195 success=False, 196 error_code=-8, 197 error_message='Ranged descriptors should not have a label') 198 199 self.log.info("Private keys required for private keys enabled wallet") 200 self.test_importdesc({"desc":descsum_create(desc), 201 "timestamp": "now", 202 "range": [0, 100]}, 203 success=False, 204 error_code=-4, 205 error_message='Cannot import descriptor without private keys to a wallet with private keys enabled', 206 wallet=wpriv) 207 208 self.log.info("Ranged descriptor import should warn without a specified range") 209 self.test_importdesc({"desc": descsum_create(desc), 210 "timestamp": "now"}, 211 success=True, 212 warnings=['Range not given, using default keypool range']) 213 assert_equal(w1.getwalletinfo()['keypoolsize'], 0) 214 215 # # Test importing of a ranged descriptor with xpriv 216 self.log.info("Should not import a ranged descriptor that includes xpriv into a watch-only wallet") 217 desc = "sh(wpkh(" + xpriv + "/0'/0'/*'" + "))" 218 self.test_importdesc({"desc": descsum_create(desc), 219 "timestamp": "now", 220 "range": 1}, 221 success=False, 222 error_code=-4, 223 error_message='Cannot import private keys to a wallet with private keys disabled') 224 225 self.log.info("Should not import a descriptor with hardened derivations when private keys are disabled") 226 self.test_importdesc({"desc": descsum_create("wpkh(" + xpub + "/1h/*)"), 227 "timestamp": "now", 228 "range": 1}, 229 success=False, 230 error_code=-4, 231 error_message='Cannot expand descriptor. Probably because of hardened derivations without private keys provided') 232 233 for address in addresses: 234 test_address(w1, 235 address, 236 ismine=False, 237 solvable=False) 238 239 self.test_importdesc({"desc": descsum_create(desc), "timestamp": "now", "range": -1}, 240 success=False, error_code=-8, error_message='End of range is too high') 241 242 self.test_importdesc({"desc": descsum_create(desc), "timestamp": "now", "range": [-1, 10]}, 243 success=False, error_code=-8, error_message='Range should be greater or equal than 0') 244 245 self.test_importdesc({"desc": descsum_create(desc), "timestamp": "now", "range": [(2 << 31 + 1) - 1000000, (2 << 31 + 1)]}, 246 success=False, error_code=-8, error_message='End of range is too high') 247 248 self.test_importdesc({"desc": descsum_create(desc), "timestamp": "now", "range": [2, 1]}, 249 success=False, error_code=-8, error_message='Range specified as [begin,end] must not have begin after end') 250 251 self.test_importdesc({"desc": descsum_create(desc), "timestamp": "now", "range": [0, 1000001]}, 252 success=False, error_code=-8, error_message='Range is too large') 253 254 # Make sure ranged imports import keys in order 255 w1 = self.nodes[1].get_wallet_rpc('w1') 256 self.log.info('Key ranges should be imported in order') 257 xpub = "tpubDAXcJ7s7ZwicqjprRaEWdPoHKrCS215qxGYxpusRLLmJuT69ZSicuGdSfyvyKpvUNYBW1s2U3NSrT6vrCYB9e6nZUEvrqnwXPF8ArTCRXMY" 258 addresses = [ 259 'ncrt1qtmp74ayg7p24uslctssvjm06q5phz4yrvy646e', # m/0'/0'/0 260 'ncrt1q8vprchan07gzagd5e6v9wd7azyucksq2vqu8lj', # m/0'/0'/1 261 'ncrt1qtuqdtha7zmqgcrr26n2rqxztv5y8rafjtaapkf', # m/0'/0'/2 262 'ncrt1qau64272ymawq26t90md6an0ps99qkrse7le8u6', # m/0'/0'/3 263 'ncrt1qsg97266hrh6cpmutqen8s4s962aryy77ced5p6', # m/0'/0'/4 264 ] 265 266 self.test_importdesc({'desc': descsum_create('wpkh([80002067/0h/0h]' + xpub + '/*)'), 267 'active': True, 268 'range' : [0, 2], 269 'timestamp': 'now' 270 }, 271 success=True) 272 self.test_importdesc({'desc': descsum_create('sh(wpkh([abcdef12/0h/0h]' + xpub + '/*))'), 273 'active': True, 274 'range' : [0, 2], 275 'timestamp': 'now' 276 }, 277 success=True) 278 self.test_importdesc({'desc': descsum_create('pkh([12345678/0h/0h]' + xpub + '/*)'), 279 'active': True, 280 'range' : [0, 2], 281 'timestamp': 'now' 282 }, 283 success=True) 284 285 assert_equal(w1.getwalletinfo()['keypoolsize'], 5 * 3) 286 for i, expected_addr in enumerate(addresses): 287 received_addr = w1.getnewaddress('', 'bech32') 288 assert_raises_rpc_error(-4, 'This wallet has no available keys', w1.getrawchangeaddress, 'bech32') 289 assert_equal(received_addr, expected_addr) 290 bech32_addr_info = w1.getaddressinfo(received_addr) 291 assert_equal(bech32_addr_info['desc'][:23], 'wpkh([80002067/0\'/0\'/{}]'.format(i)) 292 293 shwpkh_addr = w1.getnewaddress('', 'p2sh-segwit') 294 shwpkh_addr_info = w1.getaddressinfo(shwpkh_addr) 295 assert_equal(shwpkh_addr_info['desc'][:26], 'sh(wpkh([abcdef12/0\'/0\'/{}]'.format(i)) 296 297 pkh_addr = w1.getnewaddress('', 'legacy') 298 pkh_addr_info = w1.getaddressinfo(pkh_addr) 299 assert_equal(pkh_addr_info['desc'][:22], 'pkh([12345678/0\'/0\'/{}]'.format(i)) 300 301 assert_equal(w1.getwalletinfo()['keypoolsize'], 4 * 3) # After retrieving a key, we don't refill the keypool again, so it's one less for each address type 302 w1.keypoolrefill() 303 assert_equal(w1.getwalletinfo()['keypoolsize'], 5 * 3) 304 305 # Check active=False default 306 self.log.info('Check imported descriptors are not active by default') 307 self.test_importdesc({'desc': descsum_create('pkh([12345678/0h/0h]' + xpub + '/*)'), 308 'range' : [0, 2], 309 'timestamp': 'now', 310 'internal': True 311 }, 312 success=True) 313 assert_raises_rpc_error(-4, 'This wallet has no available keys', w1.getrawchangeaddress, 'legacy') 314 315 # # Test importing a descriptor containing a WIF private key 316 wif_priv = "cTe1f5rdT8A8DFgVWTjyPwACsDPJM9ff4QngFxUixCSvvbg1x6sh" 317 address = "2MuhcG52uHPknxDgmGPsV18jSHFBnnRgjPg" 318 desc = "sh(wpkh(" + wif_priv + "))" 319 self.log.info("Should import a descriptor with a WIF private key as spendable") 320 self.test_importdesc({"desc": descsum_create(desc), 321 "timestamp": "now"}, 322 success=True, 323 wallet=wpriv) 324 test_address(wpriv, 325 address, 326 solvable=True, 327 ismine=True) 328 txid = w0.sendtoaddress(address, 49.99995540) 329 w0.generatetoaddress(6, w0.getnewaddress()) 330 self.sync_blocks() 331 tx = wpriv.createrawtransaction([{"txid": txid, "vout": 0}], {w0.getnewaddress(): 49.999}) 332 signed_tx = wpriv.signrawtransactionwithwallet(tx) 333 w1.sendrawtransaction(signed_tx['hex']) 334 335 # Make sure that we can use import and use multisig as addresses 336 self.log.info('Test that multisigs can be imported, signed for, and getnewaddress\'d') 337 self.nodes[1].createwallet(wallet_name="wmulti_priv", disable_private_keys=False, blank=True, descriptors=True) 338 wmulti_priv = self.nodes[1].get_wallet_rpc("wmulti_priv") 339 assert_equal(wmulti_priv.getwalletinfo()['keypoolsize'], 0) 340 341 self.test_importdesc({"desc":"wsh(multi(2,tprv8ZgxMBicQKsPevADjDCWsa6DfhkVXicu8NQUzfibwX2MexVwW4tCec5mXdCW8kJwkzBRRmAay1KZya4WsehVvjTGVW6JLqiqd8DdZ4xSg52/84h/0h/0h/*,tprv8ZgxMBicQKsPdSNWUhDiwTScDr6JfkZuLshTRwzvZGnMSnGikV6jxpmdDkC3YRc4T3GD6Nvg9uv6hQg73RVv1EiTXDZwxVbsLugVHU8B1aq/84h/0h/0h/*,tprv8ZgxMBicQKsPeonDt8Ka2mrQmHa61hQ5FQCsvWBTpSNzBFgM58cV2EuXNAHF14VawVpznnme3SuTbA62sGriwWyKifJmXntfNeK7zeqMCj1/84h/0h/0h/*))#m2sr93jn", 342 "active": True, 343 "range": 1000, 344 "next_index": 0, 345 "timestamp": "now"}, 346 success=True, 347 wallet=wmulti_priv) 348 self.test_importdesc({"desc":"wsh(multi(2,tprv8ZgxMBicQKsPevADjDCWsa6DfhkVXicu8NQUzfibwX2MexVwW4tCec5mXdCW8kJwkzBRRmAay1KZya4WsehVvjTGVW6JLqiqd8DdZ4xSg52/84h/1h/0h/*,tprv8ZgxMBicQKsPdSNWUhDiwTScDr6JfkZuLshTRwzvZGnMSnGikV6jxpmdDkC3YRc4T3GD6Nvg9uv6hQg73RVv1EiTXDZwxVbsLugVHU8B1aq/84h/1h/0h/*,tprv8ZgxMBicQKsPeonDt8Ka2mrQmHa61hQ5FQCsvWBTpSNzBFgM58cV2EuXNAHF14VawVpznnme3SuTbA62sGriwWyKifJmXntfNeK7zeqMCj1/84h/1h/0h/*))#q3sztvx5", 349 "active": True, 350 "internal" : True, 351 "range": 1000, 352 "next_index": 0, 353 "timestamp": "now"}, 354 success=True, 355 wallet=wmulti_priv) 356 357 assert_equal(wmulti_priv.getwalletinfo()['keypoolsize'], 1001) # Range end (1000) is inclusive, so 1001 addresses generated 358 addr = wmulti_priv.getnewaddress('', 'bech32') 359 assert_equal(addr, 'ncrt1qdt0qy5p7dzhxzmegnn4ulzhard33s2809arjqgjndx87rv5vd0fqhrnwwh') # Derived at m/84'/0'/0'/0 360 change_addr = wmulti_priv.getrawchangeaddress('bech32') 361 assert_equal(change_addr, 'ncrt1qt9uhe3a9hnq7vajl7a094z4s3crm9ttf8zw3f5v9gr2nyd7e3lnsewy2df') 362 assert_equal(wmulti_priv.getwalletinfo()['keypoolsize'], 1000) 363 txid = w0.sendtoaddress(addr, 10) 364 self.nodes[0].generate(6) 365 self.sync_all() 366 send_txid = wmulti_priv.sendtoaddress(w0.getnewaddress(), 8) 367 decoded = wmulti_priv.decoderawtransaction(wmulti_priv.gettransaction(send_txid)['hex']) 368 assert_equal(len(decoded['vin'][0]['txinwitness']), 4) 369 self.nodes[0].generate(6) 370 self.sync_all() 371 372 self.nodes[1].createwallet(wallet_name="wmulti_pub", disable_private_keys=True, blank=True, descriptors=True) 373 wmulti_pub = self.nodes[1].get_wallet_rpc("wmulti_pub") 374 assert_equal(wmulti_pub.getwalletinfo()['keypoolsize'], 0) 375 376 self.test_importdesc({"desc":"wsh(multi(2,[7b2d0242/84h/0h/0h]tpubDCJtdt5dgJpdhW4MtaVYDhG4T4tF6jcLR1PxL43q9pq1mxvXgMS9Mzw1HnXG15vxUGQJMMSqCQHMTy3F1eW5VkgVroWzchsPD5BUojrcWs8/*,[59b09cd6/84h/0h/0h]tpubDDBF2BTR6s8drwrfDei8WxtckGuSm1cyoKxYY1QaKSBFbHBYQArWhHPA6eJrzZej6nfHGLSURYSLHr7GuYch8aY5n61tGqgn8b4cXrMuoPH/*,[e81a0532/84h/0h/0h]tpubDCsWoW1kuQB9kG5MXewHqkbjPtqPueRnXju7uM2NK7y3JYb2ajAZ9EiuZXNNuE4661RAfriBWhL8UsnAPpk8zrKKnZw1Ug7X4oHgMdZiU4E/*))#tsry0s5e", 377 "active": True, 378 "range": 1000, 379 "next_index": 0, 380 "timestamp": "now"}, 381 success=True, 382 wallet=wmulti_pub) 383 self.test_importdesc({"desc":"wsh(multi(2,[7b2d0242/84h/1h/0h]tpubDCXqdwWZcszwqYJSnZp8eARkxGJfHAk23KDxbztV4BbschfaTfYLTcSkSJ3TN64dRqwa1rnFUScsYormKkGqNbbPwkorQimVevXjxzUV9Gf/*,[59b09cd6/84h/1h/0h]tpubDCYfZY2ceyHzYzMMVPt9MNeiqtQ2T7Uyp9QSFwYXh8Vi9iJFYXcuphJaGXfF3jUQJi5Y3GMNXvM11gaL4txzZgNGK22BFAwMXynnzv4z2Jh/*,[e81a0532/84h/1h/0h]tpubDC6UGqnsQStngYuGD4MKsMy7eD1Yg9NTJfPdvjdG2JE5oZ7EsSL3WHg4Gsw2pR5K39ZwJ46M1wZayhedVdQtMGaUhq5S23PH6fnENK3V1sb/*))#c08a2rzv", 384 "active": True, 385 "internal" : True, 386 "range": 1000, 387 "next_index": 0, 388 "timestamp": "now"}, 389 success=True, 390 wallet=wmulti_pub) 391 392 assert_equal(wmulti_pub.getwalletinfo()['keypoolsize'], 1000) # The first one was already consumed by previous import and is detected as used 393 addr = wmulti_pub.getnewaddress('', 'bech32') 394 assert_equal(addr, 'ncrt1qp8s25ckjl7gr6x2q3dx3tn2pytwp05upkjztk6ey857tt50r5aeqwp24f4') # Derived at m/84'/0'/0'/1 395 change_addr = wmulti_pub.getrawchangeaddress('bech32') 396 assert_equal(change_addr, 'ncrt1qt9uhe3a9hnq7vajl7a094z4s3crm9ttf8zw3f5v9gr2nyd7e3lnsewy2df') 397 assert_equal(wmulti_pub.getwalletinfo()['keypoolsize'], 999) 398 txid = w0.sendtoaddress(addr, 10) 399 vout = find_vout_for_address(self.nodes[0], txid, addr) 400 self.nodes[0].generate(6) 401 self.sync_all() 402 assert_equal(wmulti_pub.getbalance(), wmulti_priv.getbalance()) 403 404 # Make sure that descriptor wallets containing multiple xpubs in a single descriptor load correctly 405 wmulti_pub.unloadwallet() 406 self.nodes[1].loadwallet('wmulti_pub') 407 408 self.log.info("Multisig with distributed keys") 409 self.nodes[1].createwallet(wallet_name="wmulti_priv1", descriptors=True) 410 wmulti_priv1 = self.nodes[1].get_wallet_rpc("wmulti_priv1") 411 res = wmulti_priv1.importdescriptors([ 412 { 413 "desc": descsum_create("wsh(multi(2,tprv8ZgxMBicQKsPevADjDCWsa6DfhkVXicu8NQUzfibwX2MexVwW4tCec5mXdCW8kJwkzBRRmAay1KZya4WsehVvjTGVW6JLqiqd8DdZ4xSg52/84h/0h/0h/*,[59b09cd6/84h/0h/0h]tpubDDBF2BTR6s8drwrfDei8WxtckGuSm1cyoKxYY1QaKSBFbHBYQArWhHPA6eJrzZej6nfHGLSURYSLHr7GuYch8aY5n61tGqgn8b4cXrMuoPH/*,[e81a0532/84h/0h/0h]tpubDCsWoW1kuQB9kG5MXewHqkbjPtqPueRnXju7uM2NK7y3JYb2ajAZ9EiuZXNNuE4661RAfriBWhL8UsnAPpk8zrKKnZw1Ug7X4oHgMdZiU4E/*))"), 414 "active": True, 415 "range": 1000, 416 "next_index": 0, 417 "timestamp": "now" 418 }, 419 { 420 "desc": descsum_create("wsh(multi(2,tprv8ZgxMBicQKsPevADjDCWsa6DfhkVXicu8NQUzfibwX2MexVwW4tCec5mXdCW8kJwkzBRRmAay1KZya4WsehVvjTGVW6JLqiqd8DdZ4xSg52/84h/1h/0h/*,[59b09cd6/84h/1h/0h]tpubDCYfZY2ceyHzYzMMVPt9MNeiqtQ2T7Uyp9QSFwYXh8Vi9iJFYXcuphJaGXfF3jUQJi5Y3GMNXvM11gaL4txzZgNGK22BFAwMXynnzv4z2Jh/*,[e81a0532/84h/1h/0h]tpubDC6UGqnsQStngYuGD4MKsMy7eD1Yg9NTJfPdvjdG2JE5oZ7EsSL3WHg4Gsw2pR5K39ZwJ46M1wZayhedVdQtMGaUhq5S23PH6fnENK3V1sb/*))"), 421 "active": True, 422 "internal" : True, 423 "range": 1000, 424 "next_index": 0, 425 "timestamp": "now" 426 }]) 427 assert_equal(res[0]['success'], True) 428 assert_equal(res[0]['warnings'][0], 'Not all private keys provided. Some wallet functionality may return unexpected errors') 429 assert_equal(res[1]['success'], True) 430 assert_equal(res[1]['warnings'][0], 'Not all private keys provided. Some wallet functionality may return unexpected errors') 431 432 self.nodes[1].createwallet(wallet_name='wmulti_priv2', blank=True, descriptors=True) 433 wmulti_priv2 = self.nodes[1].get_wallet_rpc('wmulti_priv2') 434 res = wmulti_priv2.importdescriptors([ 435 { 436 "desc": descsum_create("wsh(multi(2,[7b2d0242/84h/0h/0h]tpubDCJtdt5dgJpdhW4MtaVYDhG4T4tF6jcLR1PxL43q9pq1mxvXgMS9Mzw1HnXG15vxUGQJMMSqCQHMTy3F1eW5VkgVroWzchsPD5BUojrcWs8/*,tprv8ZgxMBicQKsPdSNWUhDiwTScDr6JfkZuLshTRwzvZGnMSnGikV6jxpmdDkC3YRc4T3GD6Nvg9uv6hQg73RVv1EiTXDZwxVbsLugVHU8B1aq/84h/0h/0h/*,[e81a0532/84h/0h/0h]tpubDCsWoW1kuQB9kG5MXewHqkbjPtqPueRnXju7uM2NK7y3JYb2ajAZ9EiuZXNNuE4661RAfriBWhL8UsnAPpk8zrKKnZw1Ug7X4oHgMdZiU4E/*))"), 437 "active": True, 438 "range": 1000, 439 "next_index": 0, 440 "timestamp": "now" 441 }, 442 { 443 "desc": descsum_create("wsh(multi(2,[7b2d0242/84h/1h/0h]tpubDCXqdwWZcszwqYJSnZp8eARkxGJfHAk23KDxbztV4BbschfaTfYLTcSkSJ3TN64dRqwa1rnFUScsYormKkGqNbbPwkorQimVevXjxzUV9Gf/*,tprv8ZgxMBicQKsPdSNWUhDiwTScDr6JfkZuLshTRwzvZGnMSnGikV6jxpmdDkC3YRc4T3GD6Nvg9uv6hQg73RVv1EiTXDZwxVbsLugVHU8B1aq/84h/1h/0h/*,[e81a0532/84h/1h/0h]tpubDC6UGqnsQStngYuGD4MKsMy7eD1Yg9NTJfPdvjdG2JE5oZ7EsSL3WHg4Gsw2pR5K39ZwJ46M1wZayhedVdQtMGaUhq5S23PH6fnENK3V1sb/*))"), 444 "active": True, 445 "internal" : True, 446 "range": 1000, 447 "next_index": 0, 448 "timestamp": "now" 449 }]) 450 assert_equal(res[0]['success'], True) 451 assert_equal(res[0]['warnings'][0], 'Not all private keys provided. Some wallet functionality may return unexpected errors') 452 assert_equal(res[1]['success'], True) 453 assert_equal(res[1]['warnings'][0], 'Not all private keys provided. Some wallet functionality may return unexpected errors') 454 455 rawtx = self.nodes[1].createrawtransaction([{'txid': txid, 'vout': vout}], {w0.getnewaddress(): 9.999}) 456 tx_signed_1 = wmulti_priv1.signrawtransactionwithwallet(rawtx) 457 assert_equal(tx_signed_1['complete'], False) 458 tx_signed_2 = wmulti_priv2.signrawtransactionwithwallet(tx_signed_1['hex']) 459 assert_equal(tx_signed_2['complete'], True) 460 self.nodes[1].sendrawtransaction(tx_signed_2['hex']) 461 462 self.log.info("Combo descriptors cannot be active") 463 self.test_importdesc({"desc": descsum_create("combo(tpubDCJtdt5dgJpdhW4MtaVYDhG4T4tF6jcLR1PxL43q9pq1mxvXgMS9Mzw1HnXG15vxUGQJMMSqCQHMTy3F1eW5VkgVroWzchsPD5BUojrcWs8/*)"), 464 "active": True, 465 "range": 1, 466 "timestamp": "now"}, 467 success=False, 468 error_code=-4, 469 error_message="Combo descriptors cannot be set to active") 470 471 self.log.info("Descriptors with no type cannot be active") 472 self.test_importdesc({"desc": descsum_create("pk(tpubDCJtdt5dgJpdhW4MtaVYDhG4T4tF6jcLR1PxL43q9pq1mxvXgMS9Mzw1HnXG15vxUGQJMMSqCQHMTy3F1eW5VkgVroWzchsPD5BUojrcWs8/*)"), 473 "active": True, 474 "range": 1, 475 "timestamp": "now"}, 476 success=True, 477 warnings=["Unknown output type, cannot set descriptor to active."]) 478 479if __name__ == '__main__': 480 ImportDescriptorsTest().main() 481