Skip to content

Commit 8e5b09b

Browse files
committed
Introduce Translator trait
Overhaul TranslatePk triat This is merely fixing compiler errors and creating structs wherever necessary. This in preperation to allow associated enums for Hashes and Timelocks. Users can then write "hash(H)" and translate API(TBD in future commits will deal with it) Also adds fields for Sha256 associated data
1 parent 851120e commit 8e5b09b

26 files changed

+790
-515
lines changed

examples/xpub_descriptors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::str::FromStr;
1818

1919
use miniscript::bitcoin::secp256k1::{Secp256k1, Verification};
2020
use miniscript::bitcoin::{Address, Network};
21-
use miniscript::{Descriptor, DescriptorPublicKey, TranslatePk2};
21+
use miniscript::{Descriptor, DescriptorPublicKey};
2222

2323
const XPUB_1: &str = "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB";
2424
const XPUB_2: &str = "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH";
@@ -42,7 +42,7 @@ fn p2wsh<C: Verification>(secp: &Secp256k1<C>) -> Address {
4242

4343
let address = Descriptor::<DescriptorPublicKey>::from_str(&s)
4444
.unwrap()
45-
.translate_pk2(|xpk| xpk.derive_public_key(secp))
45+
.derived_descriptor(&secp, 0) // dummy index value if it not a wildcard
4646
.unwrap()
4747
.address(Network::Bitcoin)
4848
.unwrap();

src/descriptor/bare.rs

+7-11
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::prelude::*;
3131
use crate::util::{varint_len, witness_to_scriptsig};
3232
use crate::{
3333
BareCtx, Error, ForEach, ForEachKey, Miniscript, MiniscriptKey, Satisfier, ToPublicKey,
34-
TranslatePk,
34+
TranslatePk, Translator,
3535
};
3636

3737
/// Create a Bare Descriptor. That is descriptor that is
@@ -180,14 +180,11 @@ where
180180
{
181181
type Output = Bare<Q>;
182182

183-
fn translate_pk<Fpk, Fpkh, E>(&self, mut fpk: Fpk, mut fpkh: Fpkh) -> Result<Self::Output, E>
183+
fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
184184
where
185-
Fpk: FnMut(&P) -> Result<Q, E>,
186-
Fpkh: FnMut(&P::Hash) -> Result<Q::Hash, E>,
187-
Q: MiniscriptKey,
185+
T: Translator<P, Q, E>,
188186
{
189-
Ok(Bare::new(self.ms.translate_pk(&mut fpk, &mut fpkh)?)
190-
.expect("Translation cannot fail inside Bare"))
187+
Ok(Bare::new(self.ms.translate_pk(t)?).expect("Translation cannot fail inside Bare"))
191188
}
192189
}
193190

@@ -345,11 +342,10 @@ where
345342
{
346343
type Output = Pkh<Q>;
347344

348-
fn translate_pk<Fpk, Fpkh, E>(&self, mut fpk: Fpk, _fpkh: Fpkh) -> Result<Self::Output, E>
345+
fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
349346
where
350-
Fpk: FnMut(&P) -> Result<Q, E>,
351-
Fpkh: FnMut(&P::Hash) -> Result<Q::Hash, E>,
347+
T: Translator<P, Q, E>,
352348
{
353-
Ok(Pkh::new(fpk(&self.pk)?))
349+
Ok(Pkh::new(t.pk(&self.pk)?))
354350
}
355351
}

src/descriptor/key.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use core::str::FromStr;
44
use std::error;
55

66
use bitcoin::hashes::hex::FromHex;
7-
use bitcoin::hashes::{hash160, Hash, HashEngine};
7+
use bitcoin::hashes::{hash160, sha256, Hash, HashEngine};
88
use bitcoin::secp256k1::{Secp256k1, Signing, Verification};
99
use bitcoin::util::bip32;
1010
use bitcoin::{self, XOnlyPublicKey, XpubIdentifier};
@@ -737,6 +737,7 @@ impl<K: InnerXKey> DescriptorXKey<K> {
737737
impl MiniscriptKey for DescriptorPublicKey {
738738
// This allows us to be able to derive public keys even for PkH s
739739
type Hash = Self;
740+
type Sha256 = bitcoin::hashes::sha256::Hash;
740741

741742
fn is_uncompressed(&self) -> bool {
742743
match self {
@@ -802,6 +803,7 @@ impl fmt::Display for DerivedDescriptorKey {
802803
impl MiniscriptKey for DerivedDescriptorKey {
803804
// This allows us to be able to derive public keys even for PkH s
804805
type Hash = Self;
806+
type Sha256 = bitcoin::hashes::sha256::Hash;
805807

806808
fn is_uncompressed(&self) -> bool {
807809
self.key.is_uncompressed()
@@ -825,6 +827,10 @@ impl ToPublicKey for DerivedDescriptorKey {
825827
fn hash_to_hash160(hash: &Self) -> hash160::Hash {
826828
hash.to_public_key().to_pubkeyhash()
827829
}
830+
831+
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
832+
*hash
833+
}
828834
}
829835

830836
#[cfg(test)]

src/descriptor/mod.rs

+106-48
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use core::ops::Range;
2828
use core::str::{self, FromStr};
2929

3030
use bitcoin::blockdata::witness::Witness;
31+
use bitcoin::hashes::sha256;
3132
use bitcoin::util::address::WitnessVersion;
3233
use bitcoin::{self, secp256k1, Address, Network, Script, TxIn};
3334
use sync::Arc;
@@ -36,8 +37,8 @@ use self::checksum::verify_checksum;
3637
use crate::miniscript::{Legacy, Miniscript, Segwitv0};
3738
use crate::prelude::*;
3839
use crate::{
39-
expression, miniscript, BareCtx, Error, ForEach, ForEachKey, MiniscriptKey, Satisfier,
40-
ToPublicKey, TranslatePk, TranslatePk2,
40+
expression, miniscript, BareCtx, Error, ForEach, ForEachKey, MiniscriptKey, PkTranslator,
41+
Satisfier, ToPublicKey, TranslatePk, Translator,
4142
};
4243

4344
mod bare;
@@ -475,25 +476,19 @@ where
475476
Q: MiniscriptKey,
476477
{
477478
type Output = Descriptor<Q>;
479+
478480
/// Converts a descriptor using abstract keys to one using specific keys.
479-
///
480-
/// # Panics
481-
///
482-
/// If `fpk` returns an uncompressed key when converting to a Segwit descriptor.
483-
/// To prevent this panic, ensure `fpk` returns an error in this case instead.
484-
fn translate_pk<Fpk, Fpkh, E>(&self, mut fpk: Fpk, mut fpkh: Fpkh) -> Result<Descriptor<Q>, E>
481+
fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
485482
where
486-
Fpk: FnMut(&P) -> Result<Q, E>,
487-
Fpkh: FnMut(&P::Hash) -> Result<Q::Hash, E>,
488-
Q: MiniscriptKey,
483+
T: Translator<P, Q, E>,
489484
{
490485
let desc = match *self {
491-
Descriptor::Bare(ref bare) => Descriptor::Bare(bare.translate_pk(&mut fpk, &mut fpkh)?),
492-
Descriptor::Pkh(ref pk) => Descriptor::Pkh(pk.translate_pk(&mut fpk, &mut fpkh)?),
493-
Descriptor::Wpkh(ref pk) => Descriptor::Wpkh(pk.translate_pk(&mut fpk, &mut fpkh)?),
494-
Descriptor::Sh(ref sh) => Descriptor::Sh(sh.translate_pk(&mut fpk, &mut fpkh)?),
495-
Descriptor::Wsh(ref wsh) => Descriptor::Wsh(wsh.translate_pk(&mut fpk, &mut fpkh)?),
496-
Descriptor::Tr(ref tr) => Descriptor::Tr(tr.translate_pk(&mut fpk, &mut fpkh)?),
486+
Descriptor::Bare(ref bare) => Descriptor::Bare(bare.translate_pk(t)?),
487+
Descriptor::Pkh(ref pk) => Descriptor::Pkh(pk.translate_pk(t)?),
488+
Descriptor::Wpkh(ref pk) => Descriptor::Wpkh(pk.translate_pk(t)?),
489+
Descriptor::Sh(ref sh) => Descriptor::Sh(sh.translate_pk(t)?),
490+
Descriptor::Wsh(ref wsh) => Descriptor::Wsh(wsh.translate_pk(t)?),
491+
Descriptor::Tr(ref tr) => Descriptor::Tr(tr.translate_pk(t)?),
497492
};
498493
Ok(desc)
499494
}
@@ -529,7 +524,19 @@ impl Descriptor<DescriptorPublicKey> {
529524
/// In most cases, you would want to use [`Self::derived_descriptor`] directly to obtain
530525
/// a [`Descriptor<bitcoin::PublicKey>`]
531526
pub fn derive(&self, index: u32) -> Descriptor<DerivedDescriptorKey> {
532-
self.translate_pk2_infallible(|pk| pk.clone().derive(index))
527+
struct Derivator(u32);
528+
529+
impl PkTranslator<DescriptorPublicKey, DerivedDescriptorKey, ()> for Derivator {
530+
fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<DerivedDescriptorKey, ()> {
531+
Ok(pk.clone().derive(self.0))
532+
}
533+
534+
fn pkh(&mut self, pkh: &DescriptorPublicKey) -> Result<DerivedDescriptorKey, ()> {
535+
Ok(pkh.clone().derive(self.0))
536+
}
537+
}
538+
self.translate_pk(&mut Derivator(index))
539+
.expect("BIP 32 key index substitution cannot fail")
533540
}
534541

535542
/// Derive a [`Descriptor`] with a concrete [`bitcoin::PublicKey`] at a given index
@@ -561,9 +568,28 @@ impl Descriptor<DescriptorPublicKey> {
561568
secp: &secp256k1::Secp256k1<C>,
562569
index: u32,
563570
) -> Result<Descriptor<bitcoin::PublicKey>, ConversionError> {
564-
let derived = self
565-
.derive(index)
566-
.translate_pk2(|xpk| xpk.derive_public_key(secp))?;
571+
struct Derivator<'a, C: secp256k1::Verification>(&'a secp256k1::Secp256k1<C>);
572+
573+
impl<'a, C: secp256k1::Verification>
574+
PkTranslator<DerivedDescriptorKey, bitcoin::PublicKey, ConversionError>
575+
for Derivator<'a, C>
576+
{
577+
fn pk(
578+
&mut self,
579+
pk: &DerivedDescriptorKey,
580+
) -> Result<bitcoin::PublicKey, ConversionError> {
581+
pk.derive_public_key(&self.0)
582+
}
583+
584+
fn pkh(
585+
&mut self,
586+
pkh: &DerivedDescriptorKey,
587+
) -> Result<bitcoin::hashes::hash160::Hash, ConversionError> {
588+
Ok(pkh.derive_public_key(&self.0)?.to_pubkeyhash())
589+
}
590+
}
591+
592+
let derived = self.derive(index).translate_pk(&mut Derivator(secp))?;
567593
Ok(derived)
568594
}
569595

@@ -575,39 +601,79 @@ impl Descriptor<DescriptorPublicKey> {
575601
secp: &secp256k1::Secp256k1<C>,
576602
s: &str,
577603
) -> Result<(Descriptor<DescriptorPublicKey>, KeyMap), Error> {
578-
let parse_key = |s: &String,
579-
key_map: &mut KeyMap|
580-
-> Result<DescriptorPublicKey, DescriptorKeyParseError> {
604+
fn parse_key<C: secp256k1::Signing>(
605+
s: &String,
606+
key_map: &mut KeyMap,
607+
secp: &secp256k1::Secp256k1<C>,
608+
) -> Result<DescriptorPublicKey, Error> {
581609
let (public_key, secret_key) = match DescriptorSecretKey::from_str(s) {
582-
Ok(sk) => (sk.to_public(secp)?, Some(sk)),
583-
Err(_) => (DescriptorPublicKey::from_str(s)?, None),
610+
Ok(sk) => (
611+
sk.to_public(secp)
612+
.map_err(|e| Error::Unexpected(e.to_string()))?,
613+
Some(sk),
614+
),
615+
Err(_) => (
616+
DescriptorPublicKey::from_str(s)
617+
.map_err(|e| Error::Unexpected(e.to_string()))?,
618+
None,
619+
),
584620
};
585621

586622
if let Some(secret_key) = secret_key {
587623
key_map.insert(public_key.clone(), secret_key);
588624
}
589625

590626
Ok(public_key)
591-
};
627+
}
628+
629+
let mut keymap_pk = KeyMapWrapper(HashMap::new(), secp);
592630

593-
let mut keymap_pk = KeyMap::new();
594-
let mut keymap_pkh = KeyMap::new();
631+
struct KeyMapWrapper<'a, C: secp256k1::Signing>(KeyMap, &'a secp256k1::Secp256k1<C>);
632+
633+
impl<'a, C: secp256k1::Signing> Translator<String, DescriptorPublicKey, Error>
634+
for KeyMapWrapper<'a, C>
635+
{
636+
fn pk(&mut self, pk: &String) -> Result<DescriptorPublicKey, Error> {
637+
parse_key(pk, &mut self.0, self.1)
638+
}
639+
640+
fn pkh(&mut self, pkh: &String) -> Result<DescriptorPublicKey, Error> {
641+
parse_key(pkh, &mut self.0, self.1)
642+
}
643+
644+
fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, Error> {
645+
let hash =
646+
sha256::Hash::from_str(sha256).map_err(|e| Error::Unexpected(e.to_string()))?;
647+
Ok(hash)
648+
}
649+
}
595650

596651
let descriptor = Descriptor::<String>::from_str(s)?;
597652
let descriptor = descriptor
598-
.translate_pk(
599-
|pk| parse_key(pk, &mut keymap_pk),
600-
|pkh| parse_key(pkh, &mut keymap_pkh),
601-
)
653+
.translate_pk(&mut keymap_pk)
602654
.map_err(|e| Error::Unexpected(e.to_string()))?;
603655

604-
keymap_pk.extend(keymap_pkh.into_iter());
605-
606-
Ok((descriptor, keymap_pk))
656+
Ok((descriptor, keymap_pk.0))
607657
}
608658

609659
/// Serialize a descriptor to string with its secret keys
610660
pub fn to_string_with_secret(&self, key_map: &KeyMap) -> String {
661+
struct KeyMapLookUp<'a>(&'a KeyMap);
662+
663+
impl<'a> Translator<DescriptorPublicKey, String, ()> for KeyMapLookUp<'a> {
664+
fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<String, ()> {
665+
key_to_string(pk, self.0)
666+
}
667+
668+
fn pkh(&mut self, pkh: &DescriptorPublicKey) -> Result<String, ()> {
669+
key_to_string(pkh, self.0)
670+
}
671+
672+
fn sha256(&mut self, sha256: &sha256::Hash) -> Result<String, ()> {
673+
Ok(sha256.to_string())
674+
}
675+
}
676+
611677
fn key_to_string(pk: &DescriptorPublicKey, key_map: &KeyMap) -> Result<String, ()> {
612678
Ok(match key_map.get(pk) {
613679
Some(secret) => secret.to_string(),
@@ -616,10 +682,7 @@ impl Descriptor<DescriptorPublicKey> {
616682
}
617683

618684
let descriptor = self
619-
.translate_pk::<_, _, ()>(
620-
|pk| key_to_string(pk, key_map),
621-
|pkh| key_to_string(pkh, key_map),
622-
)
685+
.translate_pk(&mut KeyMapLookUp(key_map))
623686
.expect("Translation to string cannot fail");
624687

625688
descriptor.to_string()
@@ -731,7 +794,7 @@ mod tests {
731794
use crate::descriptor::{DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, SinglePub};
732795
#[cfg(feature = "compiler")]
733796
use crate::policy;
734-
use crate::{hex_script, Descriptor, DummyKey, Error, Miniscript, Satisfier, TranslatePk2};
797+
use crate::{hex_script, Descriptor, DummyKey, Error, Miniscript, Satisfier};
735798

736799
type StdDescriptor = Descriptor<PublicKey>;
737800
const TEST_PK: &'static str =
@@ -1468,19 +1531,14 @@ mod tests {
14681531
assert_eq!(desc_one.to_string(), raw_desc_one);
14691532
assert_eq!(desc_two.to_string(), raw_desc_two);
14701533

1471-
// Derive a child in case the descriptor is ranged. If it's not this won't have any
1472-
// effect
1473-
let desc_one = desc_one.derive(index);
1474-
let desc_two = desc_two.derive(index);
1475-
14761534
// Same address
14771535
let addr_one = desc_one
1478-
.translate_pk2(|xpk| xpk.derive_public_key(&secp_ctx))
1536+
.derived_descriptor(&secp_ctx, index)
14791537
.unwrap()
14801538
.address(bitcoin::Network::Bitcoin)
14811539
.unwrap();
14821540
let addr_two = desc_two
1483-
.translate_pk2(|xpk| xpk.derive_public_key(&secp_ctx))
1541+
.derived_descriptor(&secp_ctx, index)
14841542
.unwrap()
14851543
.address(bitcoin::Network::Bitcoin)
14861544
.unwrap();

src/descriptor/segwitv0.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use crate::prelude::*;
2929
use crate::util::varint_len;
3030
use crate::{
3131
Error, ForEach, ForEachKey, Miniscript, MiniscriptKey, Satisfier, Segwitv0, ToPublicKey,
32-
TranslatePk,
32+
TranslatePk, Translator,
3333
};
3434
/// A Segwitv0 wsh descriptor
3535
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
@@ -265,14 +265,13 @@ where
265265
{
266266
type Output = Wsh<Q>;
267267

268-
fn translate_pk<Fpk, Fpkh, E>(&self, mut fpk: Fpk, mut fpkh: Fpkh) -> Result<Self::Output, E>
268+
fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
269269
where
270-
Fpk: FnMut(&P) -> Result<Q, E>,
271-
Fpkh: FnMut(&P::Hash) -> Result<Q::Hash, E>,
270+
T: Translator<P, Q, E>,
272271
{
273272
let inner = match self.inner {
274-
WshInner::SortedMulti(ref smv) => WshInner::SortedMulti(smv.translate_pk(&mut fpk)?),
275-
WshInner::Ms(ref ms) => WshInner::Ms(ms.translate_pk(&mut fpk, &mut fpkh)?),
273+
WshInner::SortedMulti(ref smv) => WshInner::SortedMulti(smv.translate_pk(t)?),
274+
WshInner::Ms(ref ms) => WshInner::Ms(ms.translate_pk(t)?),
276275
};
277276
Ok(Wsh { inner })
278277
}
@@ -456,11 +455,10 @@ where
456455
{
457456
type Output = Wpkh<Q>;
458457

459-
fn translate_pk<Fpk, Fpkh, E>(&self, mut fpk: Fpk, _fpkh: Fpkh) -> Result<Self::Output, E>
458+
fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
460459
where
461-
Fpk: FnMut(&P) -> Result<Q, E>,
462-
Fpkh: FnMut(&P::Hash) -> Result<Q::Hash, E>,
460+
T: Translator<P, Q, E>,
463461
{
464-
Ok(Wpkh::new(fpk(&self.pk)?).expect("Uncompressed keys in Wpkh"))
462+
Ok(Wpkh::new(t.pk(&self.pk)?).expect("Uncompressed keys in Wpkh"))
465463
}
466464
}

0 commit comments

Comments
 (0)