From ac76ce0260aa02eb391e74494df86c579baee719 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sat, 5 Jul 2025 17:52:34 +0000 Subject: [PATCH 1/2] key: fix DefiniteDescriptorKey construction from key with hardened step Our current API allows constructing a DefiniteDescriptorKey with hardened steps, which means that you can't actually derive a public key. However, the point of this type is to provide a DescriptorPublicKey which implements the ToPublicKey trait. This is a backport, so it introduces the `has_hardened_steps` helper function but does *not* make it pub, in the interest of avoiding gratuitious API changes. --- src/descriptor/key.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/descriptor/key.rs b/src/descriptor/key.rs index 208876370..50619738c 100644 --- a/src/descriptor/key.rs +++ b/src/descriptor/key.rs @@ -607,6 +607,23 @@ impl DescriptorPublicKey { } } + /// Whether or not the key has a wildcard + pub fn has_hardened_step(&self) -> bool { + let paths = match self { + DescriptorPublicKey::Single(..) => &[], + DescriptorPublicKey::XPub(xpub) => core::slice::from_ref(&xpub.derivation_path), + DescriptorPublicKey::MultiXPub(xpub) => &xpub.derivation_paths.paths()[..], + }; + for p in paths { + for step in p.into_iter() { + if step.is_hardened() { + return true; + } + } + } + false + } + #[deprecated(note = "use at_derivation_index instead")] /// Deprecated name for [`Self::at_derivation_index`]. pub fn derive(self, index: u32) -> Result { @@ -1055,7 +1072,7 @@ impl DefiniteDescriptorKey { /// /// Returns `None` if the key contains a wildcard fn new(key: DescriptorPublicKey) -> Option { - if key.has_wildcard() || key.is_multipath() { + if key.has_wildcard() || key.is_multipath() || key.has_hardened_step() { None } else { Some(Self(key)) @@ -1089,7 +1106,7 @@ impl FromStr for DefiniteDescriptorKey { fn from_str(s: &str) -> Result { let inner = DescriptorPublicKey::from_str(s)?; DefiniteDescriptorKey::new(inner).ok_or(DescriptorKeyParseError( - "cannot parse multi-path keys or keys with a wilcard as a DerivedDescriptorKey", + "cannot parse multi-path keys, keys with a wildcard or keys with hardened derivation steps as a DerivedDescriptorKey", )) } } @@ -1587,5 +1604,10 @@ mod test { .parse::() .unwrap(); assert!(DefiniteDescriptorKey::new(desc).is_none()); + // xpub with hardened path + let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/1'/2" + .parse::() + .unwrap(); + assert!(DefiniteDescriptorKey::new(desc).is_none()); } } From d61103f8f39ba6c991535cc0dd9a9b503ed359ce Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sat, 5 Jul 2025 21:10:53 +0000 Subject: [PATCH 2/2] bump version to 10.2.3 --- Cargo-recent.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo-recent.lock b/Cargo-recent.lock index c82cb8935..8c7d60de5 100644 --- a/Cargo-recent.lock +++ b/Cargo-recent.lock @@ -261,7 +261,7 @@ dependencies = [ [[package]] name = "miniscript" -version = "10.2.2" +version = "10.2.3" dependencies = [ "base64", "bitcoin", diff --git a/Cargo.toml b/Cargo.toml index f431ebb7d..d2e2aa6b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "miniscript" -version = "10.2.2" +version = "10.2.3" authors = ["Andrew Poelstra , Sanket Kanjalkar "] license = "CC0-1.0" homepage = "https://github.com/rust-bitcoin/rust-miniscript/"