1616POLICY = 0x08 # WALLY_MINISCRIPT_POLICY_TEMPLATE
1717UNIQUE_KEYPATHS = 0x10 # WALLY_MINISCRIPT_UNIQUE_KEYPATHS
1818
19- MS_IS_RANGED = 0x1
20- MS_IS_MULTIPATH = 0x2
21- MS_IS_PRIVATE = 0x4
19+ MS_IS_RANGED = 0x1
20+ MS_IS_MULTIPATH = 0x2
21+ MS_IS_PRIVATE = 0x4
2222MS_IS_UNCOMPRESSED = 0x08
23- MS_IS_RAW = 0x010
24- MS_IS_DESCRIPTOR = 0x20
23+ MS_IS_RAW = 0x010
24+ MS_IS_DESCRIPTOR = 0x20
25+ MS_IS_X_ONLY = 0x40
26+ MS_IS_PARENTED = 0x80
2527
2628NO_CHECKSUM = 0x1 # WALLY_MS_CANONICAL_NO_CHECKSUM
2729
@@ -326,12 +328,16 @@ def make_keys(xpubs):
326328
327329 def test_key_iteration (self ):
328330 """Test iterating descriptor keys"""
331+ origin_fp = 'd34db33f'
332+ origin_path = "44'/0'/0'"
333+ origin = f'[{ origin_fp } /{ origin_path } ]'
329334 k1 = 'xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB'
330335 k2 = 'xprvA2YKGLieCs6cWCiczALiH1jzk3VCCS5M1pGQfWPkamCdR9UpBgE2Gb8AKAyVjKHkz8v37avcfRjdcnP19dVAmZrvZQfvTcXXSAiFNQ6tTtU'
331336 wif = 'L1AAHuEC7XuDM7pJ7yHLEqYK1QspMo8n1kgxyZVdgvEpVC1rkUrM'
332337 pk = '03b428da420cd337c7208ed42c5331ebb407bb59ffbe3dc27936a227c619804284'
333338 pk_u = '0414fc03b8df87cd7b872996810db8458d61da8448e531569c8517b469a119d267be5645686309c6e6736dbd93940707cc9143d3cf29f1b877ff340e2cb2d259cf'
334339 policy_keys = wally_map_from_dict ({f'@{ i } ' : xpub for i ,xpub in enumerate ([k1 ])})
340+ policy_keys_with_origins = wally_map_from_dict ({f'@{ i } ' : f'{ origin } { xpub } ' for i ,xpub in enumerate ([k1 ])})
335341 P = POLICY
336342
337343 # Valid args
@@ -355,20 +361,43 @@ def test_key_iteration(self):
355361 (0 , f'pk({ pk_u } )' , pk_u , '' , MS_IS_RAW | MS_IS_UNCOMPRESSED ),
356362 ]:
357363 d = c_void_p ()
358- keys = policy_keys if flags & P else None
359- ret = wally_descriptor_parse (descriptor , keys , NETWORK_BTC_MAIN , flags , d )
360- self .assertEqual (ret , WALLY_OK )
361- ret , num_keys = wally_descriptor_get_num_keys (d )
362- self .assertEqual ((ret , num_keys ), (WALLY_OK , 1 ))
363- ret , key_str = wally_descriptor_get_key (d , 0 )
364- self .assertEqual ((ret , key_str ), (WALLY_OK , expected ))
365- ret , path_len = wally_descriptor_get_key_child_path_str_len (d , 0 )
366- self .assertEqual ((ret , path_len ), (WALLY_OK , len (child_path )))
367- ret , path_str = wally_descriptor_get_key_child_path_str (d , 0 )
368- self .assertEqual ((ret , path_str ), (WALLY_OK , child_path ))
369- ret , features = wally_descriptor_get_key_features (d , 0 )
370- self .assertEqual ((ret , features ), (WALLY_OK , expected_features ))
371- wally_descriptor_free (d )
364+ buf , buf_len = make_cbuffer ('0' * 8 )
365+
366+ for with_origin in [False , True ] if expected == k1 else [False ]:
367+ keys = None
368+ if flags & P :
369+ keys = policy_keys_with_origins if with_origin else policy_keys
370+ elif with_origin :
371+ continue
372+ ret = wally_descriptor_parse (descriptor , keys , NETWORK_BTC_MAIN , flags , d )
373+ self .assertEqual (ret , WALLY_OK )
374+ ret , num_keys = wally_descriptor_get_num_keys (d )
375+ self .assertEqual ((ret , num_keys ), (WALLY_OK , 1 ))
376+ ret , key_str = wally_descriptor_get_key (d , 0 )
377+ self .assertEqual ((ret , key_str ), (WALLY_OK , expected ))
378+ ret , path_len = wally_descriptor_get_key_child_path_str_len (d , 0 )
379+ self .assertEqual ((ret , path_len ), (WALLY_OK , len (child_path )))
380+ ret , path_str = wally_descriptor_get_key_child_path_str (d , 0 )
381+ self .assertEqual ((ret , path_str ), (WALLY_OK , child_path ))
382+ ret , features = wally_descriptor_get_key_features (d , 0 )
383+ if with_origin :
384+ expected_features |= MS_IS_PARENTED
385+ self .assertEqual ((ret , features ), (WALLY_OK , expected_features ))
386+ ret = wally_descriptor_get_key_origin_fingerprint (d , 0 , buf , buf_len )
387+ # Ensure the key origin matches if present
388+ if with_origin :
389+ self .assertEqual (ret , WALLY_OK )
390+ ret , fp = wally_hex_from_bytes (buf , buf_len )
391+ self .assertEqual ((ret , fp ), (WALLY_OK , origin_fp ))
392+ else :
393+ self .assertEqual (ret , WALLY_EINVAL )
394+ ret , path_len = wally_descriptor_get_key_origin_path_str_len (d , 0 )
395+ expected_len = len (origin_path ) if with_origin else 0
396+ self .assertEqual ((ret , path_len ), (WALLY_OK , expected_len ))
397+ ret , path_str = wally_descriptor_get_key_origin_path_str (d , 0 )
398+ expected_path = origin_path if with_origin else ''
399+ self .assertEqual ((ret , path_str ), (WALLY_OK , expected_path ))
400+ wally_descriptor_free (d )
372401
373402
374403if __name__ == '__main__' :
0 commit comments