Skip to content

Commit 8b248f6

Browse files
committed
Add helpers to convert from PublicKey & XOnlyPublicKey to Descriptor Keys
1 parent 9bf3f10 commit 8b248f6

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

src/descriptor/key.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::error;
88

99
use bitcoin::bip32::{self, XKeyIdentifier};
1010
use bitcoin::hashes::{hash160, ripemd160, sha256, Hash, HashEngine};
11-
use bitcoin::key::XOnlyPublicKey;
11+
use bitcoin::key::{PublicKey, XOnlyPublicKey};
1212
use bitcoin::secp256k1::{Secp256k1, Signing, Verification};
1313

1414
use crate::prelude::*;
@@ -670,6 +670,18 @@ impl FromStr for DescriptorPublicKey {
670670
}
671671
}
672672

673+
impl From<XOnlyPublicKey> for DescriptorPublicKey {
674+
fn from(key: XOnlyPublicKey) -> Self {
675+
DescriptorPublicKey::Single(SinglePub { origin: None, key: SinglePubKey::XOnly(key) })
676+
}
677+
}
678+
679+
impl From<PublicKey> for DescriptorPublicKey {
680+
fn from(key: PublicKey) -> Self {
681+
DescriptorPublicKey::Single(SinglePub { origin: None, key: SinglePubKey::FullKey(key) })
682+
}
683+
}
684+
673685
/// Descriptor key conversion error
674686
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
675687
pub enum ConversionError {
@@ -1260,7 +1272,7 @@ impl DefiniteDescriptorKey {
12601272
/// Construct an instance from a descriptor key and a derivation index
12611273
///
12621274
/// Returns `None` if the key contains a wildcard
1263-
fn new(key: DescriptorPublicKey) -> Option<Self> {
1275+
pub fn new(key: DescriptorPublicKey) -> Option<Self> {
12641276
if key.has_wildcard() {
12651277
None
12661278
} else {

src/descriptor/mod.rs

+56-1
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,8 @@ pub(crate) use write_descriptor;
10421042

10431043
#[cfg(test)]
10441044
mod tests {
1045-
use core::convert::TryFrom;
1045+
use bitcoin::XOnlyPublicKey;
1046+
use core::convert::TryFrom;
10461047

10471048
use bitcoin::blockdata::opcodes::all::{OP_CLTV, OP_CSV};
10481049
use bitcoin::blockdata::script::Instruction;
@@ -2183,4 +2184,58 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
21832184
)
21842185
.unwrap_err();
21852186
}
2187+
2188+
#[test]
2189+
fn convert_public_key_descriptor_to_definite_key() {
2190+
let descriptor_str = "wsh(or_d(pk(021d4ea7132d4e1a362ee5efd8d0b59dd4d1fe8906eefa7dd812b05a46b73d829b),pk(0302c8bbbb393f32c843149ce36d56405595aaabab2d0e1f4ca5f9de67dd7419f6)))";
2191+
let full_pk_descriptor: Descriptor<PublicKey> =
2192+
Descriptor::from_str(descriptor_str).unwrap();
2193+
2194+
struct TranslateFullPk;
2195+
2196+
impl Translator<bitcoin::PublicKey> for TranslateFullPk {
2197+
type TargetPk = DefiniteDescriptorKey;
2198+
type Error = core::convert::Infallible;
2199+
2200+
fn pk(
2201+
&mut self,
2202+
pk: &bitcoin::PublicKey,
2203+
) -> Result<DefiniteDescriptorKey, Self::Error> {
2204+
Ok(DefiniteDescriptorKey::new(DescriptorPublicKey::from(*pk))
2205+
.expect("DescriptorPublicKey from PublicKey has no wildcards"))
2206+
}
2207+
2208+
translate_hash_clone!(bitcoin::PublicKey, DefiniteDescriptorKey, Self::Error);
2209+
}
2210+
2211+
let converted_descriptor = full_pk_descriptor
2212+
.translate_pk(&mut TranslateFullPk)
2213+
.expect("infallible");
2214+
2215+
assert_eq!(full_pk_descriptor.to_string(), converted_descriptor.to_string());
2216+
2217+
let xonly_descriptor_str = "tr(1d4ea7132d4e1a362ee5efd8d0b59dd4d1fe8906eefa7dd812b05a46b73d829b,pk(02c8bbbb393f32c843149ce36d56405595aaabab2d0e1f4ca5f9de67dd7419f6))";
2218+
let xonly_pk_descriptor: Descriptor<XOnlyPublicKey> =
2219+
Descriptor::from_str(xonly_descriptor_str).unwrap();
2220+
2221+
struct TranslateXOnlyPk;
2222+
2223+
impl Translator<XOnlyPublicKey> for TranslateXOnlyPk {
2224+
type TargetPk = DefiniteDescriptorKey;
2225+
type Error = core::convert::Infallible;
2226+
2227+
fn pk(&mut self, pk: &XOnlyPublicKey) -> Result<DefiniteDescriptorKey, Self::Error> {
2228+
Ok(DefiniteDescriptorKey::new(DescriptorPublicKey::from(*pk))
2229+
.expect("DescriptorPublicKey from XOnlyPublicKey has no wildcards"))
2230+
}
2231+
2232+
translate_hash_clone!(XOnlyPublicKey, DefiniteDescriptorKey, Self::Error);
2233+
}
2234+
2235+
let xonly_converted_descriptor = xonly_pk_descriptor
2236+
.translate_pk(&mut TranslateXOnlyPk)
2237+
.expect("infallible");
2238+
2239+
assert_eq!(xonly_pk_descriptor.to_string(), xonly_converted_descriptor.to_string());
2240+
}
21862241
}

0 commit comments

Comments
 (0)