@@ -534,8 +534,12 @@ impl TaprootAvailableLeaves {
534534/// The Assets we can use to satisfy a particular spending path
535535#[ derive( Debug , Default ) ]
536536pub struct Assets {
537- /// Keys the user can sign for, and how
538- pub keys : HashSet < ( DescriptorPublicKey , CanSign ) > ,
537+ /// Keys the user can sign for, and how. A pair `(fingerprint, derivation_path)` is
538+ /// provided, meaning that the user can sign using the key with `fingerprint`,
539+ /// derived with either `derivation_path` or a derivation path that extends `derivation_path`
540+ /// by exactly one child number. For example, if the derivation path `m/0/1` is provided, the
541+ /// user can sign with either `m/0/1` or `m/0/1/*`.
542+ pub keys : HashSet < ( bip32:: KeySource , CanSign ) > ,
539543 /// Set of available sha256 preimages
540544 pub sha256_preimages : HashSet < sha256:: Hash > ,
541545 /// Set of available hash256 preimages
@@ -550,16 +554,44 @@ pub struct Assets {
550554 pub relative_timelock : Option < Sequence > ,
551555}
552556
557+ // Checks if the `pk` is a "direct child" of the `derivation_path` provided.
558+ // Direct child means that the key derivation path is either the same as the
559+ // `derivation_path`, or the same extened by exactly one child number.
560+ // For example, `pk/0/1/2` is a direct child of `m/0/1` and of `m/0/1/2`,
561+ // but not of `m/0`.
562+ fn is_key_direct_child_of (
563+ pk : & DefiniteDescriptorKey ,
564+ derivation_path : & bip32:: DerivationPath ,
565+ ) -> bool {
566+ for pk_derivation_path in pk. full_derivation_paths ( ) {
567+ if & pk_derivation_path == derivation_path {
568+ return true ;
569+ }
570+
571+ let definite_path_len = pk_derivation_path. len ( ) ;
572+ if derivation_path. as_ref ( ) == & pk_derivation_path[ ..( definite_path_len - 1 ) ] {
573+ return true ;
574+ }
575+ }
576+
577+ return false ;
578+ }
579+
553580impl Assets {
554581 pub ( crate ) fn has_ecdsa_key ( & self , pk : & DefiniteDescriptorKey ) -> bool {
555- self . keys
556- . iter ( )
557- . any ( |( key, can_sign) | can_sign. ecdsa && key. is_parent ( pk) . is_some ( ) )
582+ self . keys . iter ( ) . any ( |( keysource, can_sign) | {
583+ can_sign. ecdsa
584+ && pk. master_fingerprint ( ) == keysource. 0
585+ && is_key_direct_child_of ( pk, & keysource. 1 )
586+ } )
558587 }
559588
560589 pub ( crate ) fn has_taproot_internal_key ( & self , pk : & DefiniteDescriptorKey ) -> Option < usize > {
561- self . keys . iter ( ) . find_map ( |( key, can_sign) | {
562- if !can_sign. taproot . key_spend || !key. is_parent ( pk) . is_some ( ) {
590+ self . keys . iter ( ) . find_map ( |( keysource, can_sign) | {
591+ if !can_sign. taproot . key_spend
592+ || pk. master_fingerprint ( ) != keysource. 0
593+ || !is_key_direct_child_of ( pk, & keysource. 1 )
594+ {
563595 None
564596 } else {
565597 Some ( can_sign. taproot . sig_len ( ) )
@@ -572,9 +604,10 @@ impl Assets {
572604 pk : & DefiniteDescriptorKey ,
573605 tap_leaf_hash : & TapLeafHash ,
574606 ) -> Option < usize > {
575- self . keys . iter ( ) . find_map ( |( key , can_sign) | {
607+ self . keys . iter ( ) . find_map ( |( keysource , can_sign) | {
576608 if !can_sign. taproot . script_spend . is_available ( tap_leaf_hash)
577- || !key. is_parent ( pk) . is_some ( )
609+ || pk. master_fingerprint ( ) != keysource. 0
610+ || !is_key_direct_child_of ( pk, & keysource. 1 )
578611 {
579612 None
580613 } else {
@@ -639,11 +672,14 @@ impl AssetProvider<DefiniteDescriptorKey> for Assets {
639672
640673impl FromIterator < DescriptorPublicKey > for Assets {
641674 fn from_iter < I : IntoIterator < Item = DescriptorPublicKey > > ( iter : I ) -> Self {
675+ let mut keys = HashSet :: new ( ) ;
676+ for pk in iter {
677+ for deriv_path in pk. full_derivation_paths ( ) {
678+ keys. insert ( ( ( pk. master_fingerprint ( ) , deriv_path) , CanSign :: default ( ) ) ) ;
679+ }
680+ }
642681 Assets {
643- keys : iter
644- . into_iter ( )
645- . map ( |pk| ( pk, CanSign :: default ( ) ) )
646- . collect ( ) ,
682+ keys,
647683 ..Default :: default ( )
648684 }
649685 }
0 commit comments