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