Skip to content

Commit b152fa1

Browse files
sgeislerdarosior
andcommitted
Make Descriptors derivable
Co-Authored-by: Antoine Poinsot <[email protected]>
1 parent 934a05f commit b152fa1

File tree

1 file changed

+46
-5
lines changed

1 file changed

+46
-5
lines changed

src/descriptor/mod.rs

Lines changed: 46 additions & 5 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 {
@@ -239,13 +245,37 @@ impl DescriptorPublicKey {
239245
))
240246
}
241247
}
248+
249+
/// Derives the specified child key if self is a wildcard xpub. Otherwise returns self.
250+
///
251+
/// Panics if given a hardened child number
252+
pub fn derive(self, child_number: bip32::ChildNumber) -> DescriptorPublicKey {
253+
debug_assert!(child_number.is_normal());
254+
255+
match self {
256+
DescriptorPublicKey::PubKey(_) => self,
257+
DescriptorPublicKey::XPub(xpub) => {
258+
if xpub.is_wildcard {
259+
DescriptorPublicKey::XPub(DescriptorXPub {
260+
origin: xpub.origin,
261+
xpub: xpub.xpub,
262+
derivation_path: xpub.derivation_path.into_child(child_number),
263+
is_wildcard: false,
264+
})
265+
} else {
266+
DescriptorPublicKey::XPub(xpub)
267+
}
268+
}
269+
}
270+
}
242271
}
243272

244273
impl MiniscriptKey for DescriptorPublicKey {
245-
type Hash = hash160::Hash;
274+
// This allows us to be able to derive public keys even for PkH s
275+
type Hash = Self;
246276

247-
fn to_pubkeyhash(&self) -> Self::Hash {
248-
self.to_public_key().to_pubkeyhash()
277+
fn to_pubkeyhash(&self) -> Self {
278+
self.clone()
249279
}
250280
}
251281

@@ -264,7 +294,7 @@ impl ToPublicKey for DescriptorPublicKey {
264294
}
265295

266296
fn hash_to_hash160(hash: &Self::Hash) -> hash160::Hash {
267-
*hash
297+
hash.to_public_key().to_pubkeyhash()
268298
}
269299
}
270300

@@ -627,6 +657,17 @@ impl<Pk: MiniscriptKey + ToPublicKey> Descriptor<Pk> {
627657
}
628658
}
629659

660+
impl Descriptor<DescriptorPublicKey> {
661+
/// Derives all wildcard keys in the descriptor using the supplied `child_number`
662+
pub fn derive(&self, child_number: bip32::ChildNumber) -> Descriptor<DescriptorPublicKey> {
663+
self.translate_pk(
664+
|pk| Result::Ok::<DescriptorPublicKey, ()>(pk.clone().derive(child_number)),
665+
|pk| Result::Ok::<DescriptorPublicKey, ()>(pk.clone().derive(child_number)),
666+
)
667+
.expect("Translation fn can't fail.")
668+
}
669+
}
670+
630671
impl<Pk> expression::FromTree for Descriptor<Pk>
631672
where
632673
Pk: MiniscriptKey,
@@ -1413,7 +1454,7 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
14131454
let policy: policy::concrete::Policy<DescriptorPublicKey> = descriptor_str.parse().unwrap();
14141455
let descriptor = Descriptor::Sh(policy.compile().unwrap());
14151456
let derived_descriptor =
1416-
descriptor.derive(&[bip32::ChildNumber::from_normal_idx(42).unwrap()]);
1457+
descriptor.derive(bip32::ChildNumber::from_normal_idx(42).unwrap());
14171458

14181459
let res_descriptor_str = "thresh(2,\
14191460
pk([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/42),\

0 commit comments

Comments
 (0)