Skip to content

Commit 5937090

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

File tree

2 files changed

+83
-2
lines changed

2 files changed

+83
-2
lines changed

src/descriptor/key.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::error;
99
use bitcoin::bip32::{self, XKeyIdentifier};
1010
use bitcoin::hashes::{hash160, ripemd160, sha256, Hash, HashEngine};
1111
use bitcoin::key::XOnlyPublicKey;
12+
use bitcoin::key::PublicKey;
1213
use bitcoin::secp256k1::{Secp256k1, Signing, Verification};
1314

1415
use crate::prelude::*;
@@ -670,6 +671,28 @@ impl FromStr for DescriptorPublicKey {
670671
}
671672
}
672673

674+
impl From<XOnlyPublicKey> for DescriptorPublicKey {
675+
fn from(key: XOnlyPublicKey) -> Self {
676+
DescriptorPublicKey::Single(
677+
SinglePub{
678+
origin: None,
679+
key: SinglePubKey::XOnly(key)
680+
}
681+
)
682+
}
683+
}
684+
685+
impl From<PublicKey> for DescriptorPublicKey {
686+
fn from(key: PublicKey) -> Self {
687+
DescriptorPublicKey::Single(
688+
SinglePub{
689+
origin: None,
690+
key: SinglePubKey::FullKey(key)
691+
}
692+
)
693+
}
694+
}
695+
673696
/// Descriptor key conversion error
674697
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
675698
pub enum ConversionError {
@@ -1260,7 +1283,7 @@ impl DefiniteDescriptorKey {
12601283
/// Construct an instance from a descriptor key and a derivation index
12611284
///
12621285
/// Returns `None` if the key contains a wildcard
1263-
fn new(key: DescriptorPublicKey) -> Option<Self> {
1286+
pub(crate) fn new(key: DescriptorPublicKey) -> Option<Self> {
12641287
if key.has_wildcard() {
12651288
None
12661289
} else {

src/descriptor/mod.rs

+59-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use core::str::{self, FromStr};
1717

1818
use bitcoin::hashes::{hash160, ripemd160, sha256};
1919
use bitcoin::{
20-
secp256k1, Address, Network, Script, ScriptBuf, TxIn, Weight, Witness, WitnessVersion,
20+
secp256k1, Address, Network, PublicKey, Script, ScriptBuf, TxIn, Weight, Witness, WitnessVersion, XOnlyPublicKey
2121
};
2222
use sync::Arc;
2323

@@ -1040,6 +1040,49 @@ macro_rules! write_descriptor {
10401040
}
10411041
pub(crate) use write_descriptor;
10421042

1043+
impl From<Descriptor<PublicKey>> for Descriptor<DefiniteDescriptorKey> {
1044+
fn from(descriptor: Descriptor<PublicKey>) -> Descriptor<DefiniteDescriptorKey> {
1045+
struct TranslateFullPk;
1046+
1047+
impl Translator<bitcoin::PublicKey> for TranslateFullPk {
1048+
type TargetPk = DefiniteDescriptorKey;
1049+
type Error = core::convert::Infallible;
1050+
1051+
fn pk(&mut self, pk: &bitcoin::PublicKey) -> Result<DefiniteDescriptorKey, Self::Error> {
1052+
Ok(DefiniteDescriptorKey::new(DescriptorPublicKey::from(pk.clone())).expect("DescriptorPublicKey from PublicKey has no wildcards"))
1053+
}
1054+
1055+
translate_hash_clone!(bitcoin::PublicKey, DefiniteDescriptorKey, Self::Error);
1056+
}
1057+
1058+
let converted_descriptor =
1059+
descriptor.translate_pk(&mut TranslateFullPk).expect("infallible");
1060+
converted_descriptor
1061+
}
1062+
}
1063+
1064+
impl From<Descriptor<XOnlyPublicKey>> for Descriptor<DefiniteDescriptorKey> {
1065+
fn from(descriptor: Descriptor<XOnlyPublicKey>) -> Descriptor<DefiniteDescriptorKey> {
1066+
struct TranslateXOnlyPk;
1067+
1068+
impl Translator<XOnlyPublicKey> for TranslateXOnlyPk {
1069+
type TargetPk = DefiniteDescriptorKey;
1070+
type Error = core::convert::Infallible;
1071+
1072+
fn pk(&mut self, pk: &XOnlyPublicKey) -> Result<DefiniteDescriptorKey, Self::Error> {
1073+
Ok(DefiniteDescriptorKey::new(DescriptorPublicKey::from(pk.clone())).expect("DescriptorPublicKey from XOnlyPublicKey has no wildcards"))
1074+
}
1075+
1076+
translate_hash_clone!(XOnlyPublicKey, DefiniteDescriptorKey, Self::Error);
1077+
}
1078+
1079+
let converted_descriptor =
1080+
descriptor.translate_pk(&mut TranslateXOnlyPk).expect("infallible");
1081+
converted_descriptor
1082+
}
1083+
}
1084+
1085+
10431086
#[cfg(test)]
10441087
mod tests {
10451088
use core::convert::TryFrom;
@@ -2183,4 +2226,19 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
21832226
)
21842227
.unwrap_err();
21852228
}
2229+
2230+
#[test]
2231+
fn convert_public_key_descriptor_to_definite_key() {
2232+
let descriptor_str = "wsh(or_d(pk(021d4ea7132d4e1a362ee5efd8d0b59dd4d1fe8906eefa7dd812b05a46b73d829b),pk(0302c8bbbb393f32c843149ce36d56405595aaabab2d0e1f4ca5f9de67dd7419f6)))";
2233+
let full_pk_descriptor: Descriptor<PublicKey> = Descriptor::from_str(descriptor_str).unwrap();
2234+
2235+
let definite_descriptor: Descriptor<DefiniteDescriptorKey> = full_pk_descriptor.clone().into();
2236+
assert_eq!(full_pk_descriptor.to_string(), definite_descriptor.to_string());
2237+
2238+
let xonly_descriptor_str = "tr(1d4ea7132d4e1a362ee5efd8d0b59dd4d1fe8906eefa7dd812b05a46b73d829b,pk(02c8bbbb393f32c843149ce36d56405595aaabab2d0e1f4ca5f9de67dd7419f6))";
2239+
let xonly_pk_descriptor: Descriptor<XOnlyPublicKey> = Descriptor::from_str(xonly_descriptor_str).unwrap();
2240+
2241+
let xonly_definite_descriptor: Descriptor<DefiniteDescriptorKey> = xonly_pk_descriptor.clone().into();
2242+
assert_eq!(xonly_pk_descriptor.to_string(), xonly_definite_descriptor.to_string());
2243+
}
21862244
}

0 commit comments

Comments
 (0)