Skip to content

Commit fce14d0

Browse files
committed
Merge #426: Rework translate API to allow associated types to be translated
8e5b09b Introduce Translator trait (sanket1729) 851120e Add impl_from_tree! (sanket1729) c43129c Misc rustfmt change (sanket1729) Pull request description: The Translate API currently does not support translating the hashes and timelocks. Ideally, we want to write an HTLC as `or( and( alice_key, older(timeout), and(bob_key, sha256(hash)))`. But it is impossible to use placeholders for `hash`, and `timelock`. It is only possible for keys. This is a significant API change, but I think it is for good. The diff is large, but reviewing `lib.rs` is the main diff, other diffs are just chasing compiler errors ACKs for top commit: tcharding: ACK 8e5b09b apoelstra: ACK 8e5b09b Tree-SHA512: 291ccbbb76a4768c83878728288db117ed2fc45608f911ac02d8e3ec0a2ef384c10e0e086a9debf76d324978f8a6f6812f737b276a86194b3d93a032c3bd6c7d
2 parents ea76eb1 + 8e5b09b commit fce14d0

27 files changed

+1027
-822
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

+21-48
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
//!
2020
2121
use core::fmt;
22-
use core::str::FromStr;
2322

2423
use bitcoin::blockdata::script;
2524
use bitcoin::{Address, Network, Script};
@@ -32,7 +31,7 @@ use crate::prelude::*;
3231
use crate::util::{varint_len, witness_to_scriptsig};
3332
use crate::{
3433
BareCtx, Error, ForEach, ForEachKey, Miniscript, MiniscriptKey, Satisfier, ToPublicKey,
35-
TranslatePk,
34+
TranslatePk, Translator,
3635
};
3736

3837
/// Create a Bare Descriptor. That is descriptor that is
@@ -145,35 +144,24 @@ impl<Pk: MiniscriptKey> Liftable<Pk> for Bare<Pk> {
145144
}
146145
}
147146

148-
impl<Pk> FromTree for Bare<Pk>
149-
where
150-
Pk: MiniscriptKey + FromStr,
151-
Pk::Hash: FromStr,
152-
<Pk as FromStr>::Err: ToString,
153-
<<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString,
154-
{
147+
impl_from_tree!(
148+
Bare<Pk>,
155149
fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
156150
let sub = Miniscript::<Pk, BareCtx>::from_tree(top)?;
157151
BareCtx::top_level_checks(&sub)?;
158152
Bare::new(sub)
159153
}
160-
}
161-
162-
impl<Pk> FromStr for Bare<Pk>
163-
where
164-
Pk: MiniscriptKey + FromStr,
165-
Pk::Hash: FromStr,
166-
<Pk as FromStr>::Err: ToString,
167-
<<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString,
168-
{
169-
type Err = Error;
154+
);
170155

156+
impl_from_str!(
157+
Bare<Pk>,
158+
type Err = Error;,
171159
fn from_str(s: &str) -> Result<Self, Self::Err> {
172160
let desc_str = verify_checksum(s)?;
173161
let top = expression::Tree::from_str(desc_str)?;
174162
Self::from_tree(&top)
175163
}
176-
}
164+
);
177165

178166
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Bare<Pk> {
179167
fn for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, pred: F) -> bool
@@ -192,14 +180,11 @@ where
192180
{
193181
type Output = Bare<Q>;
194182

195-
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>
196184
where
197-
Fpk: FnMut(&P) -> Result<Q, E>,
198-
Fpkh: FnMut(&P::Hash) -> Result<Q::Hash, E>,
199-
Q: MiniscriptKey,
185+
T: Translator<P, Q, E>,
200186
{
201-
Ok(Bare::new(self.ms.translate_pk(&mut fpk, &mut fpkh)?)
202-
.expect("Translation cannot fail inside Bare"))
187+
Ok(Bare::new(self.ms.translate_pk(t)?).expect("Translation cannot fail inside Bare"))
203188
}
204189
}
205190

@@ -313,13 +298,8 @@ impl<Pk: MiniscriptKey> Liftable<Pk> for Pkh<Pk> {
313298
}
314299
}
315300

316-
impl<Pk> FromTree for Pkh<Pk>
317-
where
318-
Pk: MiniscriptKey + FromStr,
319-
Pk::Hash: FromStr,
320-
<Pk as FromStr>::Err: ToString,
321-
<<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString,
322-
{
301+
impl_from_tree!(
302+
Pkh<Pk>,
323303
fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
324304
if top.name == "pkh" && top.args.len() == 1 {
325305
Ok(Pkh::new(expression::terminal(&top.args[0], |pk| {
@@ -333,23 +313,17 @@ where
333313
)))
334314
}
335315
}
336-
}
337-
338-
impl<Pk> FromStr for Pkh<Pk>
339-
where
340-
Pk: MiniscriptKey + FromStr,
341-
Pk::Hash: FromStr,
342-
<Pk as FromStr>::Err: ToString,
343-
<<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString,
344-
{
345-
type Err = Error;
316+
);
346317

318+
impl_from_str!(
319+
Pkh<Pk>,
320+
type Err = Error;,
347321
fn from_str(s: &str) -> Result<Self, Self::Err> {
348322
let desc_str = verify_checksum(s)?;
349323
let top = expression::Tree::from_str(desc_str)?;
350324
Self::from_tree(&top)
351325
}
352-
}
326+
);
353327

354328
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Pkh<Pk> {
355329
fn for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, mut pred: F) -> bool
@@ -368,11 +342,10 @@ where
368342
{
369343
type Output = Pkh<Q>;
370344

371-
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>
372346
where
373-
Fpk: FnMut(&P) -> Result<Q, E>,
374-
Fpkh: FnMut(&P::Hash) -> Result<Q::Hash, E>,
347+
T: Translator<P, Q, E>,
375348
{
376-
Ok(Pkh::new(fpk(&self.pk)?))
349+
Ok(Pkh::new(t.pk(&self.pk)?))
377350
}
378351
}

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)]

0 commit comments

Comments
 (0)