Skip to content

Commit be6e11d

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

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, Clone, Copy)]
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. Otherwise returns self.
236+
///
237+
/// Panics if derivation path contains a hardened child number
238+
pub fn derive(self, path: &[bip32::ChildNumber]) -> DescriptorPublicKey {
239+
assert!(path.into_iter().all(|c| c.is_normal()));
240+
241+
match self {
242+
DescriptorPublicKey::PubKey(_) => self,
243+
DescriptorPublicKey::XPub(xpub) => {
244+
if xpub.is_wildcard {
245+
DescriptorPublicKey::XPub(DescriptorXPub {
246+
origin: xpub.origin,
247+
xpub: xpub.xpub,
248+
derivation_path: xpub
249+
.derivation_path
250+
.into_iter()
251+
.chain(path.iter())
252+
.cloned()
253+
.collect(),
254+
is_wildcard: false,
255+
})
256+
} else {
257+
DescriptorPublicKey::XPub(xpub)
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.clone().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)