Skip to content

Commit 8fd89a9

Browse files
sgeislerdarosior
authored andcommitted
Make Descriptors derivable
Signed-off-by: Antoine Poinsot <[email protected]>
1 parent 1f8187a commit 8fd89a9

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

src/descriptor/mod.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ pub struct DescriptorXPub {
9292
#[derive(Debug, PartialEq)]
9393
pub struct DescriptorKeyParseError(&'static str);
9494

95+
impl fmt::Display for DescriptorKeyParseError {
96+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97+
f.write_str(self.0)
98+
}
99+
}
100+
95101
impl fmt::Display for DescriptorPublicKey {
96102
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97103
match *self {
@@ -225,6 +231,34 @@ impl DescriptorPublicKey {
225231
))
226232
}
227233
}
234+
235+
/// Derives a new key using the path if self is a wildcard xpub. Otehrwise returns a copy of
236+
/// self.
237+
///
238+
/// Panics if derivation path contains a hardened child number
239+
pub fn derive(&self, path: &[bip32::ChildNumber]) -> DescriptorPublicKey {
240+
assert!(path.into_iter().all(|c| c.is_normal()));
241+
242+
match *self {
243+
DescriptorPublicKey::PukKey(ref pk) => DescriptorPublicKey::PukKey(*pk),
244+
DescriptorPublicKey::XPub(ref xpub) => {
245+
if xpub.is_wildcard {
246+
DescriptorPublicKey::XPub(DescriptorXPub {
247+
origin: xpub.origin.clone(),
248+
xpub: xpub.xpub.clone(),
249+
derivation_path: (&xpub.derivation_path)
250+
.into_iter()
251+
.chain(path.iter())
252+
.cloned()
253+
.collect(),
254+
is_wildcard: false,
255+
})
256+
} else {
257+
self.clone()
258+
}
259+
}
260+
}
261+
}
228262
}
229263

230264
impl MiniscriptKey for DescriptorPublicKey {
@@ -613,6 +647,17 @@ impl<Pk: MiniscriptKey + ToPublicKey> Descriptor<Pk> {
613647
}
614648
}
615649

650+
impl Descriptor<DescriptorPublicKey> {
651+
/// Derives all wildcard keys in the descriptor using the supplied `path`
652+
pub fn derive(&self, path: &[bip32::ChildNumber]) -> Descriptor<DescriptorPublicKey> {
653+
self.translate_pk(
654+
|pk| Result::Ok::<DescriptorPublicKey, ()>(pk.derive(path)),
655+
|pkh| Result::Ok::<hash160::Hash, ()>(*pkh),
656+
)
657+
.expect("Translation fn can't fail.")
658+
}
659+
}
660+
616661
impl<Pk> expression::FromTree for Descriptor<Pk>
617662
where
618663
Pk: MiniscriptKey,

0 commit comments

Comments
 (0)