Skip to content

Commit 71c550e

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

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 {
@@ -226,6 +232,34 @@ impl DescriptorPublicKey {
226232
))
227233
}
228234
}
235+
236+
/// Derives a new key using the path if self is a wildcard xpub. Otehrwise returns a copy of
237+
/// self.
238+
///
239+
/// Panics if derivation path contains a hardened child number
240+
pub fn derive(&self, path: &[bip32::ChildNumber]) -> DescriptorPublicKey {
241+
assert!(path.into_iter().all(|c| c.is_normal()));
242+
243+
match *self {
244+
DescriptorPublicKey::PukKey(ref pk) => DescriptorPublicKey::PukKey(*pk),
245+
DescriptorPublicKey::XPub(ref xpub) => {
246+
if xpub.is_wildcard {
247+
DescriptorPublicKey::XPub(DescriptorXPub {
248+
origin: xpub.origin.clone(),
249+
xpub: xpub.xpub.clone(),
250+
derivation_path: (&xpub.derivation_path)
251+
.into_iter()
252+
.chain(path.iter())
253+
.cloned()
254+
.collect(),
255+
is_wildcard: false,
256+
})
257+
} else {
258+
self.clone()
259+
}
260+
}
261+
}
262+
}
229263
}
230264

231265
impl MiniscriptKey for DescriptorPublicKey {
@@ -624,6 +658,17 @@ impl<Pk: MiniscriptKey + ToPublicKey> Descriptor<Pk> {
624658
}
625659
}
626660

661+
impl Descriptor<DescriptorPublicKey> {
662+
/// Derives all wildcard keys in the descriptor using the supplied `path`
663+
pub fn derive(&self, path: &[bip32::ChildNumber]) -> Descriptor<DescriptorPublicKey> {
664+
self.translate_pk(
665+
|pk| Result::Ok::<DescriptorPublicKey, ()>(pk.derive(path)),
666+
|pkh| Result::Ok::<hash160::Hash, ()>(*pkh),
667+
)
668+
.expect("Translation fn can't fail.")
669+
}
670+
}
671+
627672
impl<Pk> expression::FromTree for Descriptor<Pk>
628673
where
629674
Pk: MiniscriptKey,

0 commit comments

Comments
 (0)