Skip to content

Commit 9e96e12

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

File tree

2 files changed

+60
-3
lines changed

2 files changed

+60
-3
lines changed

src/descriptor/key.rs

Lines changed: 14 additions & 2 deletions
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::*;
@@ -473,6 +473,18 @@ impl FromStr for DescriptorPublicKey {
473473
}
474474
}
475475

476+
impl From<XOnlyPublicKey> for DescriptorPublicKey {
477+
fn from(key: XOnlyPublicKey) -> Self {
478+
DescriptorPublicKey::Single(SinglePub { origin: None, key: SinglePubKey::XOnly(key) })
479+
}
480+
}
481+
482+
impl From<PublicKey> for DescriptorPublicKey {
483+
fn from(key: PublicKey) -> Self {
484+
DescriptorPublicKey::Single(SinglePub { origin: None, key: SinglePubKey::FullKey(key) })
485+
}
486+
}
487+
476488
/// Descriptor key conversion error
477489
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
478490
pub enum ConversionError {
@@ -1036,7 +1048,7 @@ impl DefiniteDescriptorKey {
10361048
/// Construct an instance from a descriptor key and a derivation index
10371049
///
10381050
/// Returns `None` if the key contains a wildcard
1039-
fn new(key: DescriptorPublicKey) -> Option<Self> {
1051+
pub fn new(key: DescriptorPublicKey) -> Option<Self> {
10401052
if key.has_wildcard() {
10411053
None
10421054
} else {

src/descriptor/mod.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1004,7 +1004,7 @@ mod tests {
10041004
use bitcoin::hashes::Hash;
10051005
use bitcoin::script::PushBytes;
10061006
use bitcoin::sighash::EcdsaSighashType;
1007-
use bitcoin::{bip32, PublicKey, Sequence};
1007+
use bitcoin::{bip32, PublicKey, Sequence, XOnlyPublicKey};
10081008

10091009
use super::checksum::desc_checksum;
10101010
use super::*;
@@ -2064,4 +2064,49 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
20642064
)
20652065
.unwrap_err();
20662066
}
2067+
2068+
#[test]
2069+
fn convert_public_key_descriptor_to_definite_key() {
2070+
let descriptor_str = "wsh(or_d(pk(021d4ea7132d4e1a362ee5efd8d0b59dd4d1fe8906eefa7dd812b05a46b73d829b),pk(0302c8bbbb393f32c843149ce36d56405595aaabab2d0e1f4ca5f9de67dd7419f6)))";
2071+
let full_pk_descriptor: Descriptor<PublicKey> =
2072+
Descriptor::from_str(descriptor_str).unwrap();
2073+
2074+
struct TranslateFullPk;
2075+
2076+
impl Translator<bitcoin::PublicKey, DefiniteDescriptorKey, ()> for TranslateFullPk {
2077+
fn pk(&mut self, pk: &bitcoin::PublicKey) -> Result<DefiniteDescriptorKey, ()> {
2078+
Ok(DefiniteDescriptorKey::new(DescriptorPublicKey::from(*pk))
2079+
.expect("DescriptorPublicKey from PublicKey has no wildcards"))
2080+
}
2081+
2082+
translate_hash_clone!(bitcoin::PublicKey, DefiniteDescriptorKey, ());
2083+
}
2084+
2085+
let converted_descriptor = full_pk_descriptor
2086+
.translate_pk(&mut TranslateFullPk)
2087+
.expect("infallible");
2088+
2089+
assert_eq!(full_pk_descriptor.to_string(), converted_descriptor.to_string());
2090+
2091+
let xonly_descriptor_str = "tr(1d4ea7132d4e1a362ee5efd8d0b59dd4d1fe8906eefa7dd812b05a46b73d829b,pk(02c8bbbb393f32c843149ce36d56405595aaabab2d0e1f4ca5f9de67dd7419f6))";
2092+
let xonly_pk_descriptor: Descriptor<XOnlyPublicKey> =
2093+
Descriptor::from_str(xonly_descriptor_str).unwrap();
2094+
2095+
struct TranslateXOnlyPk;
2096+
2097+
impl Translator<XOnlyPublicKey, DefiniteDescriptorKey, ()> for TranslateXOnlyPk {
2098+
fn pk(&mut self, pk: &XOnlyPublicKey) -> Result<DefiniteDescriptorKey, ()> {
2099+
Ok(DefiniteDescriptorKey::new(DescriptorPublicKey::from(*pk))
2100+
.expect("DescriptorPublicKey from XOnlyPublicKey has no wildcards"))
2101+
}
2102+
2103+
translate_hash_clone!(XOnlyPublicKey, DefiniteDescriptorKey, ());
2104+
}
2105+
2106+
let xonly_converted_descriptor = xonly_pk_descriptor
2107+
.translate_pk(&mut TranslateXOnlyPk)
2108+
.expect("infallible");
2109+
2110+
assert_eq!(xonly_pk_descriptor.to_string(), xonly_converted_descriptor.to_string());
2111+
}
20672112
}

0 commit comments

Comments
 (0)