@@ -238,63 +238,81 @@ def test_features_and_depth(self):
238238 k1 = 'xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB'
239239 k2 = 'xprvA2YKGLieCs6cWCiczALiH1jzk3VCCS5M1pGQfWPkamCdR9UpBgE2Gb8AKAyVjKHkz8v37avcfRjdcnP19dVAmZrvZQfvTcXXSAiFNQ6tTtU'
240240 # Valid args
241+ # descriptor, flags, expected_features, expected_depth, expected keys
241242 cases = [
242243 # Bip32 xpub
243244 (f'pkh({ k1 } )' ,
244- 0 , MS_IS_DESCRIPTOR , 2 ),
245+ 0 , MS_IS_DESCRIPTOR , 2 , 1 ),
245246 # Bip32 xpub with range
246247 (f'pkh({ k1 } /*)' ,
247- 0 , MS_IS_RANGED | MS_IS_DESCRIPTOR , 2 ),
248+ 0 , MS_IS_RANGED | MS_IS_DESCRIPTOR , 2 , 1 ),
248249 # BIP32 xprv
249250 (f'pkh({ k2 } /*)' ,
250- 0 , MS_IS_PRIVATE | MS_IS_RANGED | MS_IS_DESCRIPTOR , 2 ),
251+ 0 , MS_IS_PRIVATE | MS_IS_RANGED | MS_IS_DESCRIPTOR , 2 , 1 ),
251252 # WIF
252253 ('pkh(L1AAHuEC7XuDM7pJ7yHLEqYK1QspMo8n1kgxyZVdgvEpVC1rkUrM)' ,
253- 0 , MS_IS_PRIVATE | MS_IS_RAW | MS_IS_DESCRIPTOR , 2 ),
254+ 0 , MS_IS_PRIVATE | MS_IS_RAW | MS_IS_DESCRIPTOR , 2 , 1 ),
254255 # Hex pubkey, compressed
255256 ('pk(03b428da420cd337c7208ed42c5331ebb407bb59ffbe3dc27936a227c619804284)' ,
256- 0 , MS_IS_RAW | MS_IS_DESCRIPTOR , 2 ),
257+ 0 , MS_IS_RAW | MS_IS_DESCRIPTOR , 2 , 1 ),
257258 # Hex pubkey, uncompressed
258259 ('pk(0414fc03b8df87cd7b872996810db8458d61da8448e531569c8517b469a119d267be5645686309c6e6736dbd93940707cc9143d3cf29f1b877ff340e2cb2d259cf)' ,
259- 0 , MS_IS_UNCOMPRESSED | MS_IS_RAW | MS_IS_DESCRIPTOR , 2 ),
260+ 0 , MS_IS_UNCOMPRESSED | MS_IS_RAW | MS_IS_DESCRIPTOR , 2 , 1 ),
260261 # Miniscript
261262 ('j:and_v(vdv:after(1567547623),older(2016))' ,
262- MS_ONLY , 0 , 3 ),
263+ MS_ONLY , 0 , 3 , 0 ),
263264 # pk() is both descriptor and miniscript valid and should parse as each
264265 (f'or_d(thresh(1,pk({ k1 } )),and_v(v:thresh(1,pk({ k2 } /)),older(30)))' ,
265- 0 , MS_IS_PRIVATE , 5 ),
266+ 0 , MS_IS_PRIVATE , 5 , 2 ),
266267 (f'or_d(thresh(1,pk({ k1 } )),and_v(v:thresh(1,pk({ k2 } /)),older(30)))' ,
267- MS_ONLY , MS_IS_PRIVATE , 5 ),
268+ MS_ONLY , MS_IS_PRIVATE , 5 , 2 ),
268269 ]
269270 if is_elements_build :
270271 slip77 = 'ct(slip77(b2396b3ee20509cdb64fe24180a14a72dbd671728eaa49bac69d2bdecb5f5a04),elpkh(xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH))'
271272 cases .extend ([
272273 # Parsing a descriptor as elements returns elements in its features
273274 (f'tr({ k1 } )' ,
274- AS_ELEMENTS , MS_IS_DESCRIPTOR | MS_IS_ELEMENTS , 2 ),
275+ AS_ELEMENTS , MS_IS_DESCRIPTOR | MS_IS_ELEMENTS , 2 , 1 ),
275276 # el-prefixed builtins return elements in their features
276277 (f'eltr({ k1 } )' ,
277- 0 , MS_IS_DESCRIPTOR | MS_IS_ELEMENTS , 2 ),
278+ 0 , MS_IS_DESCRIPTOR | MS_IS_ELEMENTS , 2 , 1 ),
279+ # Note that ct() blinding keys aren't returned in the key count.
278280 # slip77 builtins return elements and slip77 in their features,
279- # and the ct() parent wrapper is included in their depth
281+ # and the ct() parent wrapper is included in their depth.
280282 (slip77 ,
281- 0 , MS_IS_DESCRIPTOR | MS_IS_ELEMENTS | MS_IS_SLIP77 , 3 ),
283+ 0 , MS_IS_DESCRIPTOR | MS_IS_ELEMENTS | MS_IS_SLIP77 , 3 , 1 ),
284+ # An xpub ELIP-150 key
285+ (f'ct({ k1 } ,elpkh({ k1 } ))' ,
286+ 0 , MS_IS_DESCRIPTOR | MS_IS_ELEMENTS | MS_IS_ELIP150 , 3 , 1 ),
287+ # A hex public ELIP-150 key.
288+ (f'ct(0286fc9a38e765d955e9b0bcc18fa9ae81b0c893e2dd1ef5542a9c73780a086b90,elpkh({ k1 } ))' ,
289+ 0 , MS_IS_DESCRIPTOR | MS_IS_ELEMENTS | MS_IS_ELIP150 , 3 , 1 ),
290+ # An xpriv ELIP-150 key. Note that MS_IS_PRIVATE is not
291+ # returned because the blinding key is not included in the
292+ # key count.
293+ (f'ct({ k2 } ,elpkh({ k1 } ))' ,
294+ 0 , MS_IS_DESCRIPTOR | MS_IS_ELEMENTS | MS_IS_ELIP150 , 3 , 1 ),
295+ # A hex private ELIP-150 key. As above MS_IS_PRIVATE is not
296+ # returned.
297+ (f'ct(c25deb86fa11e49d651d7eae27c220ef930fbd86ea023eebfa73e54875647963,elpkh({ k1 } ))' ,
298+ 0 , MS_IS_DESCRIPTOR | MS_IS_ELEMENTS | MS_IS_ELIP150 , 3 , 1 ),
282299 ])
283300
284- for descriptor , flags , expected , expected_depth in cases :
301+ for descriptor , flags , expected_features , expected_depth , expected_keys in cases :
285302 d = c_void_p ()
286303 ret = wally_descriptor_parse (descriptor , None , NETWORK_NONE , flags , d )
287304 ret , features = wally_descriptor_get_features (d )
288- self .assertEqual ((ret , features ), (WALLY_OK , expected ))
305+ self .assertEqual ((ret , features ), (WALLY_OK , expected_features ))
289306 ret , depth = wally_descriptor_get_depth (d )
290307 self .assertEqual ((ret , depth ), (WALLY_OK , expected_depth ))
308+ ret , num_keys = wally_descriptor_get_num_keys (d )
309+ self .assertEqual ((ret , num_keys ), (WALLY_OK , expected_keys ))
291310 wally_descriptor_free (d )
292311 # Check the maximum depth parsing limit
293312 for limit , expected in [(depth - 1 , WALLY_EINVAL ), (depth , WALLY_OK )]:
294313 ret = wally_descriptor_parse (descriptor , None , NETWORK_NONE ,
295314 flags | (limit << 16 ), d )
296315 self .assertEqual (ret , expected )
297- wally_descriptor_free (d )
298316
299317 # Invalid args
300318 ret , features = wally_descriptor_get_features (None ) # NULL descriptor
0 commit comments