9
9
except ImportError :
10
10
pass
11
11
12
+ import re
13
+
12
14
from test_framework .blocktools import COINBASE_MATURITY
13
15
from test_framework .test_framework import BitcoinTestFramework
14
16
from test_framework .util import (
@@ -24,65 +26,115 @@ def set_test_params(self):
24
26
self .setup_clean_chain = True
25
27
self .num_nodes = 1
26
28
self .extra_args = [['-keypool=100' ]]
27
- self .wallet_names = []
28
29
29
30
def skip_test_if_missing_module (self ):
30
31
self .skip_if_no_wallet ()
31
32
self .skip_if_no_py_sqlite3 ()
32
33
34
+ def test_parent_descriptors (self ):
35
+ self .log .info ("Check that parent_descs is the same for all RPCs and is normalized" )
36
+ self .nodes [0 ].createwallet (wallet_name = "parent_descs" )
37
+ wallet = self .nodes [0 ].get_wallet_rpc ("parent_descs" )
38
+ default_wallet = self .nodes [0 ].get_wallet_rpc (self .default_wallet_name )
39
+
40
+ addr = wallet .getnewaddress ()
41
+ parent_desc = wallet .getaddressinfo (addr )["parent_desc" ]
42
+
43
+ # Verify that the parent descriptor is normalized
44
+ # First remove the checksum
45
+ desc_verify = parent_desc .split ("#" )[0 ]
46
+ # Next extract the xpub
47
+ desc_verify = re .sub (r"tpub\w+?(?=/)" , "" , desc_verify )
48
+ # Extract origin info
49
+ origin_match = re .search (r'\[([\da-fh/]+)\]' , desc_verify )
50
+ origin_part = origin_match .group (1 ) if origin_match else ""
51
+ # Split on "]" for everything after the origin info
52
+ after_origin = desc_verify .split ("]" , maxsplit = 1 )[- 1 ]
53
+ # Look for the hardened markers “h” inside each piece
54
+ # We don't need to check for aspostrophe as normalization will not output aspostrophe
55
+ found_hardened_in_origin = "h" in origin_part
56
+ found_hardened_after_origin = "h" in after_origin
57
+ assert_equal (found_hardened_in_origin , True )
58
+ assert_equal (found_hardened_after_origin , False )
59
+
60
+ # Send some coins so we can check listunspent, listtransactions, listunspent, and gettransaction
61
+ since_block = self .nodes [0 ].getbestblockhash ()
62
+ txid = default_wallet .sendtoaddress (addr , 1 )
63
+ self .generate (self .nodes [0 ], 1 )
64
+
65
+ unspent = wallet .listunspent ()
66
+ assert_equal (len (unspent ), 1 )
67
+ assert_equal (unspent [0 ]["parent_descs" ], [parent_desc ])
68
+
69
+ txs = wallet .listtransactions ()
70
+ assert_equal (len (txs ), 1 )
71
+ assert_equal (txs [0 ]["parent_descs" ], [parent_desc ])
72
+
73
+ txs = wallet .listsinceblock (since_block )["transactions" ]
74
+ assert_equal (len (txs ), 1 )
75
+ assert_equal (txs [0 ]["parent_descs" ], [parent_desc ])
76
+
77
+ tx = wallet .gettransaction (txid = txid , verbose = True )
78
+ assert_equal (tx ["details" ][0 ]["parent_descs" ], [parent_desc ])
79
+
80
+ wallet .unloadwallet ()
81
+
33
82
def run_test (self ):
83
+ self .generate (self .nodes [0 ], COINBASE_MATURITY + 1 )
84
+
34
85
# Make a descriptor wallet
35
86
self .log .info ("Making a descriptor wallet" )
36
87
self .nodes [0 ].createwallet (wallet_name = "desc1" )
88
+ wallet = self .nodes [0 ].get_wallet_rpc ("desc1" )
37
89
38
90
# A descriptor wallet should have 100 addresses * 4 types = 400 keys
39
91
self .log .info ("Checking wallet info" )
40
- wallet_info = self . nodes [ 0 ] .getwalletinfo ()
92
+ wallet_info = wallet .getwalletinfo ()
41
93
assert_equal (wallet_info ['format' ], 'sqlite' )
42
94
assert_equal (wallet_info ['keypoolsize' ], 400 )
43
95
assert_equal (wallet_info ['keypoolsize_hd_internal' ], 400 )
44
96
assert 'keypoololdest' not in wallet_info
45
97
46
98
# Check that getnewaddress works
47
99
self .log .info ("Test that getnewaddress and getrawchangeaddress work" )
48
- addr = self . nodes [ 0 ] .getnewaddress ("" , "legacy" )
49
- addr_info = self . nodes [ 0 ] .getaddressinfo (addr )
100
+ addr = wallet .getnewaddress ("" , "legacy" )
101
+ addr_info = wallet .getaddressinfo (addr )
50
102
assert addr_info ['desc' ].startswith ('pkh(' )
51
103
assert_equal (addr_info ['hdkeypath' ], 'm/44h/1h/0h/0/0' )
52
104
53
- addr = self . nodes [ 0 ] .getnewaddress ("" , "p2sh-segwit" )
54
- addr_info = self . nodes [ 0 ] .getaddressinfo (addr )
105
+ addr = wallet .getnewaddress ("" , "p2sh-segwit" )
106
+ addr_info = wallet .getaddressinfo (addr )
55
107
assert addr_info ['desc' ].startswith ('sh(wpkh(' )
56
108
assert_equal (addr_info ['hdkeypath' ], 'm/49h/1h/0h/0/0' )
57
109
58
- addr = self . nodes [ 0 ] .getnewaddress ("" , "bech32" )
59
- addr_info = self . nodes [ 0 ] .getaddressinfo (addr )
110
+ addr = wallet .getnewaddress ("" , "bech32" )
111
+ addr_info = wallet .getaddressinfo (addr )
60
112
assert addr_info ['desc' ].startswith ('wpkh(' )
61
113
assert_equal (addr_info ['hdkeypath' ], 'm/84h/1h/0h/0/0' )
62
114
63
- addr = self . nodes [ 0 ] .getnewaddress ("" , "bech32m" )
64
- addr_info = self . nodes [ 0 ] .getaddressinfo (addr )
115
+ addr = wallet .getnewaddress ("" , "bech32m" )
116
+ addr_info = wallet .getaddressinfo (addr )
65
117
assert addr_info ['desc' ].startswith ('tr(' )
66
118
assert_equal (addr_info ['hdkeypath' ], 'm/86h/1h/0h/0/0' )
67
119
68
120
# Check that getrawchangeaddress works
69
- addr = self . nodes [ 0 ] .getrawchangeaddress ("legacy" )
70
- addr_info = self . nodes [ 0 ] .getaddressinfo (addr )
121
+ addr = wallet .getrawchangeaddress ("legacy" )
122
+ addr_info = wallet .getaddressinfo (addr )
71
123
assert addr_info ['desc' ].startswith ('pkh(' )
72
124
assert_equal (addr_info ['hdkeypath' ], 'm/44h/1h/0h/1/0' )
73
125
74
- addr = self . nodes [ 0 ] .getrawchangeaddress ("p2sh-segwit" )
75
- addr_info = self . nodes [ 0 ] .getaddressinfo (addr )
126
+ addr = wallet .getrawchangeaddress ("p2sh-segwit" )
127
+ addr_info = wallet .getaddressinfo (addr )
76
128
assert addr_info ['desc' ].startswith ('sh(wpkh(' )
77
129
assert_equal (addr_info ['hdkeypath' ], 'm/49h/1h/0h/1/0' )
78
130
79
- addr = self . nodes [ 0 ] .getrawchangeaddress ("bech32" )
80
- addr_info = self . nodes [ 0 ] .getaddressinfo (addr )
131
+ addr = wallet .getrawchangeaddress ("bech32" )
132
+ addr_info = wallet .getaddressinfo (addr )
81
133
assert addr_info ['desc' ].startswith ('wpkh(' )
82
134
assert_equal (addr_info ['hdkeypath' ], 'm/84h/1h/0h/1/0' )
83
135
84
- addr = self . nodes [ 0 ] .getrawchangeaddress ("bech32m" )
85
- addr_info = self . nodes [ 0 ] .getaddressinfo (addr )
136
+ addr = wallet .getrawchangeaddress ("bech32m" )
137
+ addr_info = wallet .getaddressinfo (addr )
86
138
assert addr_info ['desc' ].startswith ('tr(' )
87
139
assert_equal (addr_info ['hdkeypath' ], 'm/86h/1h/0h/1/0' )
88
140
@@ -216,6 +268,7 @@ def run_test(self):
216
268
conn .close ()
217
269
assert_raises_rpc_error (- 4 , "Unexpected legacy entry in descriptor wallet found." , self .nodes [0 ].loadwallet , "crashme" )
218
270
271
+ self .test_parent_descriptors ()
219
272
220
273
if __name__ == '__main__' :
221
274
WalletDescriptorTest (__file__ ).main ()
0 commit comments