Skip to content

Commit 7b3b3a8

Browse files
committed
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. The next commits will change the API to reflect this, but this commit is on its own to make it easier for me to backport it.
1 parent 19eb66f commit 7b3b3a8

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

src/descriptor/key.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,13 +334,17 @@ impl DescriptorMultiXKey<bip32::Xpriv> {
334334
pub enum NonDefiniteKeyError {
335335
Wildcard,
336336
Multipath,
337+
HardenedStep,
337338
}
338339

339340
impl fmt::Display for NonDefiniteKeyError {
340341
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341342
match *self {
342343
Self::Wildcard => f.write_str("key with a wildcard cannot be a DerivedDescriptorKey"),
343344
Self::Multipath => f.write_str("multipath key cannot be a DerivedDescriptorKey"),
345+
Self::HardenedStep => {
346+
f.write_str("key with hardened derivation steps cannot be a DerivedDescriptorKey")
347+
}
344348
}
345349
}
346350
}
@@ -819,6 +823,23 @@ impl DescriptorPublicKey {
819823
}
820824
}
821825

826+
/// Whether or not the key has a wildcard
827+
pub fn has_hardened_step(&self) -> bool {
828+
let paths = match self {
829+
DescriptorPublicKey::Single(..) => &[],
830+
DescriptorPublicKey::XPub(xpub) => core::slice::from_ref(&xpub.derivation_path),
831+
DescriptorPublicKey::MultiXPub(xpub) => &xpub.derivation_paths.paths()[..],
832+
};
833+
for p in paths {
834+
for step in p.into_iter() {
835+
if step.is_hardened() {
836+
return true;
837+
}
838+
}
839+
}
840+
false
841+
}
842+
822843
#[deprecated(note = "use at_derivation_index instead")]
823844
/// Deprecated name for [`Self::at_derivation_index`].
824845
pub fn derive(self, index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
@@ -1276,6 +1297,8 @@ impl DefiniteDescriptorKey {
12761297
pub fn new(key: DescriptorPublicKey) -> Result<Self, NonDefiniteKeyError> {
12771298
if key.has_wildcard() {
12781299
Err(NonDefiniteKeyError::Wildcard)
1300+
} else if key.has_hardened_step() {
1301+
Err(NonDefiniteKeyError::HardenedStep)
12791302
} else if key.is_multipath() {
12801303
Err(NonDefiniteKeyError::Multipath)
12811304
} else {
@@ -1785,5 +1808,13 @@ mod test {
17851808
.parse::<DescriptorPublicKey>()
17861809
.unwrap();
17871810
assert!(matches!(DefiniteDescriptorKey::new(desc), Err(NonDefiniteKeyError::Multipath)));
1811+
// xpub with hardened path
1812+
let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/1'/2"
1813+
.parse::<DescriptorPublicKey>()
1814+
.unwrap();
1815+
assert!(matches!(
1816+
DefiniteDescriptorKey::new(desc),
1817+
Err(NonDefiniteKeyError::HardenedStep)
1818+
));
17881819
}
17891820
}

0 commit comments

Comments
 (0)