Skip to content

Commit 6151612

Browse files
Use KeySource instead of definite keys in Assets
1 parent 767e4f6 commit 6151612

File tree

2 files changed

+49
-48
lines changed

2 files changed

+49
-48
lines changed

src/descriptor/key.rs

-35
Original file line numberDiff line numberDiff line change
@@ -721,41 +721,6 @@ impl DescriptorPublicKey {
721721
}
722722
}
723723
}
724-
725-
/// Whether this key is the "parent" of a [`DefiniteDescriptorKey`]
726-
///
727-
/// The key is considered "parent" if it represents the non-derived version of a definite key,
728-
/// meaning it contains a wildcard where the definite key has a definite derivation number.
729-
///
730-
/// If `self` is a single key or doesn't contain any wildcards, the definite key will have to
731-
/// be exactly the same.
732-
///
733-
/// Returns the derivation path to apply to `self` to obtain the definite key.
734-
pub fn is_parent(&self, definite_key: &DefiniteDescriptorKey) -> Option<bip32::DerivationPath> {
735-
// If the key is `Single` or it's an `XPub` with no wildcard it will match the definite key
736-
// exactly, so we try this check first
737-
if self == &definite_key.0 {
738-
return Some(bip32::DerivationPath::default());
739-
}
740-
741-
match (self, &definite_key.0) {
742-
(DescriptorPublicKey::XPub(self_xkey), DescriptorPublicKey::XPub(definite_xkey))
743-
if definite_xkey.derivation_path.len() > 0 =>
744-
{
745-
let definite_path_len = definite_xkey.derivation_path.len();
746-
if self_xkey.origin == definite_xkey.origin
747-
&& self_xkey.xkey == definite_xkey.xkey
748-
&& self_xkey.derivation_path.as_ref()
749-
== &definite_xkey.derivation_path[..(definite_path_len - 1)]
750-
{
751-
Some(vec![definite_xkey.derivation_path[definite_path_len - 1]].into())
752-
} else {
753-
None
754-
}
755-
}
756-
_ => None,
757-
}
758-
}
759724
}
760725

761726
impl FromStr for DescriptorSecretKey {

src/plan.rs

+49-13
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,12 @@ impl TaprootAvailableLeaves {
534534
/// The Assets we can use to satisfy a particular spending path
535535
#[derive(Debug, Default)]
536536
pub 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+
553580
impl 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

640673
impl 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

Comments
 (0)