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 (
@@ -29,6 +31,54 @@ def skip_test_if_missing_module(self):
29
31
self .skip_if_no_wallet ()
30
32
self .skip_if_no_py_sqlite3 ()
31
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
+
32
82
def run_test (self ):
33
83
self .generate (self .nodes [0 ], COINBASE_MATURITY + 1 )
34
84
@@ -218,6 +268,7 @@ def run_test(self):
218
268
conn .close ()
219
269
assert_raises_rpc_error (- 4 , "Unexpected legacy entry in descriptor wallet found." , self .nodes [0 ].loadwallet , "crashme" )
220
270
271
+ self .test_parent_descriptors ()
221
272
222
273
if __name__ == '__main__' :
223
274
WalletDescriptorTest (__file__ ).main ()
0 commit comments