Skip to content

Commit bd82534

Browse files
sgeislerdarosior
authored andcommitted
Implement MiniscriptKey for DescriptorKey
Signed-off-by: Antoine Poinsot <[email protected]>
1 parent ade1761 commit bd82534

File tree

1 file changed

+59
-2
lines changed

1 file changed

+59
-2
lines changed

src/descriptor/mod.rs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ use std::fmt;
2727
use std::str::{self, FromStr};
2828

2929
use bitcoin::blockdata::{opcodes, script};
30+
use bitcoin::hashes::hash160;
3031
use bitcoin::hashes::hex::FromHex;
32+
use bitcoin::secp256k1;
3133
use bitcoin::util::bip32;
3234
use bitcoin::{self, Script};
3335

@@ -73,13 +75,13 @@ pub enum Descriptor<Pk: MiniscriptKey> {
7375
ShWsh(Miniscript<Pk, Segwitv0>),
7476
}
7577

76-
#[derive(Debug, Eq, PartialEq)]
78+
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
7779
pub enum DescriptorPublicKey {
7880
PukKey(bitcoin::PublicKey),
7981
XPub(DescriptorXPub),
8082
}
8183

82-
#[derive(Debug, Eq, PartialEq)]
84+
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
8385
pub struct DescriptorXPub {
8486
origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
8587
xpub: bip32::ExtendedPubKey,
@@ -90,6 +92,38 @@ pub struct DescriptorXPub {
9092
#[derive(Debug, PartialEq)]
9193
pub struct DescriptorKeyParseError(&'static str);
9294

95+
impl fmt::Display for DescriptorPublicKey {
96+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97+
match *self {
98+
DescriptorPublicKey::PukKey(ref pk) => pk.fmt(f),
99+
DescriptorPublicKey::XPub(ref xpub) => {
100+
if let Some((ref master_id, ref master_deriv)) = xpub.origin {
101+
fmt::Formatter::write_str(f, "[")?;
102+
for byte in master_id.into_bytes().iter() {
103+
write!(f, "{:02x}", byte)?;
104+
}
105+
fmt_derivation_path(f, master_deriv)?;
106+
fmt::Formatter::write_str(f, "]")?;
107+
}
108+
xpub.xpub.fmt(f)?;
109+
fmt_derivation_path(f, &xpub.derivation_path)?;
110+
if xpub.is_wildcard {
111+
write!(f, "/*")?;
112+
}
113+
Ok(())
114+
}
115+
}
116+
}
117+
}
118+
119+
/// Writes a derivation path to the formatter, no leading 'm'
120+
fn fmt_derivation_path(f: &mut fmt::Formatter, path: &bip32::DerivationPath) -> fmt::Result {
121+
for child in path {
122+
write!(f, "/{}", child)?;
123+
}
124+
Ok(())
125+
}
126+
93127
impl FromStr for DescriptorPublicKey {
94128
type Err = DescriptorKeyParseError;
95129

@@ -193,6 +227,24 @@ impl DescriptorPublicKey {
193227
}
194228
}
195229

230+
impl MiniscriptKey for DescriptorPublicKey {
231+
type Hash = hash160::Hash;
232+
233+
fn to_pubkeyhash(&self) -> Self::Hash {
234+
match *self {
235+
DescriptorPublicKey::PukKey(ref pk) => pk.to_pubkeyhash(),
236+
DescriptorPublicKey::XPub(ref xpub) => {
237+
let ctx = secp256k1::Secp256k1::verification_only();
238+
xpub.xpub
239+
.derive_pub(&ctx, &xpub.derivation_path)
240+
.expect("Won't fail, only normal derivations")
241+
.public_key
242+
.to_pubkeyhash()
243+
}
244+
}
245+
}
246+
}
247+
196248
impl<Pk: MiniscriptKey> Descriptor<Pk> {
197249
/// Convert a descriptor using abstract keys to one using specific keys
198250
/// This will panic if translatefpk returns an uncompressed key when
@@ -1225,6 +1277,7 @@ mod tests {
12251277
is_wildcard: true,
12261278
});
12271279
assert_eq!(expected, key.parse().unwrap());
1280+
assert_eq!(format!("{}", expected), key);
12281281

12291282
// Without origin
12301283
let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1";
@@ -1235,6 +1288,7 @@ mod tests {
12351288
is_wildcard: false,
12361289
});
12371290
assert_eq!(expected, key.parse().unwrap());
1291+
assert_eq!(format!("{}", expected), key);
12381292

12391293
// Without derivation path
12401294
let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
@@ -1245,6 +1299,7 @@ mod tests {
12451299
is_wildcard: false,
12461300
});
12471301
assert_eq!(expected, key.parse().unwrap());
1302+
assert_eq!(format!("{}", expected), key);
12481303

12491304
// Raw (compressed) pubkey
12501305
let key = "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8";
@@ -1255,6 +1310,7 @@ mod tests {
12551310
.unwrap(),
12561311
);
12571312
assert_eq!(expected, key.parse().unwrap());
1313+
assert_eq!(format!("{}", expected), key);
12581314

12591315
// Raw (uncompressed) pubkey
12601316
let key = "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a";
@@ -1265,6 +1321,7 @@ mod tests {
12651321
.unwrap(),
12661322
);
12671323
assert_eq!(expected, key.parse().unwrap());
1324+
assert_eq!(format!("{}", expected), key);
12681325
}
12691326

12701327
#[test]

0 commit comments

Comments
 (0)