Skip to content

Commit 7150566

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

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

src/descriptor/mod.rs

Lines changed: 46 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,35 @@ impl DescriptorPublicKey {
225231
))
226232
}
227233
}
234+
235+
/// Derives a new key using the path if self is a wildcard xpub. Otherwise 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::PubKey(_) => self,
244+
DescriptorPublicKey::XPub(xpub) => {
245+
if xpub.is_wildcard {
246+
DescriptorPublicKey::XPub(DescriptorXPub {
247+
origin: xpub.origin,
248+
xpub: xpub.xpub,
249+
derivation_path: xpub
250+
.derivation_path
251+
.into_iter()
252+
.chain(path.iter())
253+
.cloned()
254+
.collect(),
255+
is_wildcard: false,
256+
})
257+
} else {
258+
DescriptorPublicKey::XPub(xpub)
259+
}
260+
}
261+
}
262+
}
228263
}
229264

230265
impl MiniscriptKey for DescriptorPublicKey {
@@ -613,6 +648,17 @@ impl<Pk: MiniscriptKey + ToPublicKey> Descriptor<Pk> {
613648
}
614649
}
615650

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

0 commit comments

Comments
 (0)