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