Skip to content

Commit 269f44d

Browse files
committed
translator: make target pk and error associated types
This is an annoying breaking change for users of the Translator trait but I think it greatly improves the ergonomics of using the trait. Rather than having it be parameterized over 3 types, it is now parameterized over just one (the "source pk type"). This matches how this trait is used in practice -- you typically have a miniscript/policy/whatever with a keytype Pk, and you want to use a translator from Pk to "whatever the translator maps to" with "whatever error the translator yields". So the only type parameter you really need to type is Pk; the others are irrelevant, and making the user name and type them is annoying. Since this eliminates the need to explicitly write out the error types except when actually implementing the trait, this also changes a ton of error types from () to Infallible, which is more efficient and correct.
1 parent d9d43d5 commit 269f44d

File tree

16 files changed

+174
-116
lines changed

16 files changed

+174
-116
lines changed

examples/big.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,15 @@ struct StrPkTranslator {
8282
pk_map: HashMap<String, XOnlyPublicKey>,
8383
}
8484

85-
impl Translator<String, XOnlyPublicKey, ()> for StrPkTranslator {
86-
fn pk(&mut self, pk: &String) -> Result<XOnlyPublicKey, ()> {
85+
impl Translator<String> for StrPkTranslator {
86+
type TargetPk = XOnlyPublicKey;
87+
type Error = ();
88+
89+
fn pk(&mut self, pk: &String) -> Result<XOnlyPublicKey, Self::Error> {
8790
self.pk_map.get(pk).copied().ok_or(())
8891
}
8992

9093
// We don't need to implement these methods as we are not using them in the policy.
9194
// Fail if we encounter any hash fragments. See also translate_hash_clone! macro.
92-
translate_hash_fail!(String, XOnlyPublicKey, ());
95+
translate_hash_fail!(String, XOnlyPublicKey, Self::Error);
9396
}

examples/taproot.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@ struct StrPkTranslator {
1717
pk_map: HashMap<String, XOnlyPublicKey>,
1818
}
1919

20-
impl Translator<String, XOnlyPublicKey, ()> for StrPkTranslator {
21-
fn pk(&mut self, pk: &String) -> Result<XOnlyPublicKey, ()> {
20+
impl Translator<String> for StrPkTranslator {
21+
type TargetPk = XOnlyPublicKey;
22+
type Error = ();
23+
24+
fn pk(&mut self, pk: &String) -> Result<XOnlyPublicKey, Self::Error> {
2225
self.pk_map.get(pk).copied().ok_or(())
2326
}
2427

2528
// We don't need to implement these methods as we are not using them in the policy.
2629
// Fail if we encounter any hash fragments. See also translate_hash_clone! macro.
27-
translate_hash_fail!(String, XOnlyPublicKey, ());
30+
translate_hash_fail!(String, XOnlyPublicKey, Self::Error);
2831
}
2932

3033
fn main() {

src/descriptor/bare.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,9 @@ impl<Pk: MiniscriptKey> Bare<Pk> {
9494
}
9595

9696
/// Converts the keys in the script from one type to another.
97-
pub fn translate_pk<Q, T, E>(&self, t: &mut T) -> Result<Bare<Q>, TranslateErr<E>>
97+
pub fn translate_pk<T>(&self, t: &mut T) -> Result<Bare<T::TargetPk>, TranslateErr<T::Error>>
9898
where
99-
T: Translator<Pk, Q, E>,
100-
Q: MiniscriptKey,
99+
T: Translator<Pk>,
101100
{
102101
Bare::new(self.ms.translate_pk(t)?).map_err(TranslateErr::OuterError)
103102
}
@@ -256,10 +255,9 @@ impl<Pk: MiniscriptKey> Pkh<Pk> {
256255
pub fn max_satisfaction_weight(&self) -> usize { 4 * (1 + 73 + BareCtx::pk_len(&self.pk)) }
257256

258257
/// Converts the keys in a script from one type to another.
259-
pub fn translate_pk<Q, T, E>(&self, t: &mut T) -> Result<Pkh<Q>, TranslateErr<E>>
258+
pub fn translate_pk<T>(&self, t: &mut T) -> Result<Pkh<T::TargetPk>, TranslateErr<T::Error>>
260259
where
261-
T: Translator<Pk, Q, E>,
262-
Q: MiniscriptKey,
260+
T: Translator<Pk>,
263261
{
264262
let res = Pkh::new(t.pk(&self.pk)?);
265263
match res {

src/descriptor/mod.rs

+34-19
Original file line numberDiff line numberDiff line change
@@ -361,10 +361,12 @@ impl<Pk: MiniscriptKey> Descriptor<Pk> {
361361
}
362362

363363
/// Converts a descriptor using one kind of keys to another kind of key.
364-
pub fn translate_pk<T, Q, E>(&self, t: &mut T) -> Result<Descriptor<Q>, TranslateErr<E>>
364+
pub fn translate_pk<T>(
365+
&self,
366+
t: &mut T,
367+
) -> Result<Descriptor<T::TargetPk>, TranslateErr<T::Error>>
365368
where
366-
T: Translator<Pk, Q, E>,
367-
Q: MiniscriptKey,
369+
T: Translator<Pk>,
368370
{
369371
let desc = match *self {
370372
Descriptor::Bare(ref bare) => Descriptor::Bare(bare.translate_pk(t)?),
@@ -600,7 +602,10 @@ impl Descriptor<DescriptorPublicKey> {
600602
) -> Result<Descriptor<DefiniteDescriptorKey>, ConversionError> {
601603
struct Derivator(u32);
602604

603-
impl Translator<DescriptorPublicKey, DefiniteDescriptorKey, ConversionError> for Derivator {
605+
impl Translator<DescriptorPublicKey> for Derivator {
606+
type TargetPk = DefiniteDescriptorKey;
607+
type Error = ConversionError;
608+
604609
fn pk(
605610
&mut self,
606611
pk: &DescriptorPublicKey,
@@ -691,9 +696,10 @@ impl Descriptor<DescriptorPublicKey> {
691696

692697
struct KeyMapWrapper<'a, C: secp256k1::Signing>(KeyMap, &'a secp256k1::Secp256k1<C>);
693698

694-
impl<'a, C: secp256k1::Signing> Translator<String, DescriptorPublicKey, Error>
695-
for KeyMapWrapper<'a, C>
696-
{
699+
impl<'a, C: secp256k1::Signing> Translator<String> for KeyMapWrapper<'a, C> {
700+
type TargetPk = DescriptorPublicKey;
701+
type Error = Error;
702+
697703
fn pk(&mut self, pk: &String) -> Result<DescriptorPublicKey, Error> {
698704
parse_key(pk, &mut self.0, self.1)
699705
}
@@ -738,29 +744,35 @@ impl Descriptor<DescriptorPublicKey> {
738744
pub fn to_string_with_secret(&self, key_map: &KeyMap) -> String {
739745
struct KeyMapLookUp<'a>(&'a KeyMap);
740746

741-
impl<'a> Translator<DescriptorPublicKey, String, ()> for KeyMapLookUp<'a> {
742-
fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<String, ()> {
747+
impl<'a> Translator<DescriptorPublicKey> for KeyMapLookUp<'a> {
748+
type TargetPk = String;
749+
type Error = core::convert::Infallible;
750+
751+
fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<String, Self::Error> {
743752
key_to_string(pk, self.0)
744753
}
745754

746-
fn sha256(&mut self, sha256: &sha256::Hash) -> Result<String, ()> {
755+
fn sha256(&mut self, sha256: &sha256::Hash) -> Result<String, Self::Error> {
747756
Ok(sha256.to_string())
748757
}
749758

750-
fn hash256(&mut self, hash256: &hash256::Hash) -> Result<String, ()> {
759+
fn hash256(&mut self, hash256: &hash256::Hash) -> Result<String, Self::Error> {
751760
Ok(hash256.to_string())
752761
}
753762

754-
fn ripemd160(&mut self, ripemd160: &ripemd160::Hash) -> Result<String, ()> {
763+
fn ripemd160(&mut self, ripemd160: &ripemd160::Hash) -> Result<String, Self::Error> {
755764
Ok(ripemd160.to_string())
756765
}
757766

758-
fn hash160(&mut self, hash160: &hash160::Hash) -> Result<String, ()> {
767+
fn hash160(&mut self, hash160: &hash160::Hash) -> Result<String, Self::Error> {
759768
Ok(hash160.to_string())
760769
}
761770
}
762771

763-
fn key_to_string(pk: &DescriptorPublicKey, key_map: &KeyMap) -> Result<String, ()> {
772+
fn key_to_string(
773+
pk: &DescriptorPublicKey,
774+
key_map: &KeyMap,
775+
) -> Result<String, core::convert::Infallible> {
764776
Ok(match key_map.get(pk) {
765777
Some(secret) => secret.to_string(),
766778
None => pk.to_string(),
@@ -835,7 +847,10 @@ impl Descriptor<DescriptorPublicKey> {
835847

836848
// Now, transform the multipath key of each descriptor into a single-key using each index.
837849
struct IndexChoser(usize);
838-
impl Translator<DescriptorPublicKey, DescriptorPublicKey, Error> for IndexChoser {
850+
impl Translator<DescriptorPublicKey> for IndexChoser {
851+
type TargetPk = DescriptorPublicKey;
852+
type Error = Error;
853+
839854
fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<DescriptorPublicKey, Error> {
840855
match pk {
841856
DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => {
@@ -892,10 +907,10 @@ impl Descriptor<DefiniteDescriptorKey> {
892907
) -> Result<Descriptor<bitcoin::PublicKey>, ConversionError> {
893908
struct Derivator<'a, C: secp256k1::Verification>(&'a secp256k1::Secp256k1<C>);
894909

895-
impl<'a, C: secp256k1::Verification>
896-
Translator<DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError>
897-
for Derivator<'a, C>
898-
{
910+
impl<'a, C: secp256k1::Verification> Translator<DefiniteDescriptorKey> for Derivator<'a, C> {
911+
type TargetPk = bitcoin::PublicKey;
912+
type Error = ConversionError;
913+
899914
fn pk(
900915
&mut self,
901916
pk: &DefiniteDescriptorKey,

src/descriptor/segwitv0.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,9 @@ impl<Pk: MiniscriptKey> Wsh<Pk> {
130130
}
131131

132132
/// Converts the keys in a script from one type to another.
133-
pub fn translate_pk<Q, T, E>(&self, t: &mut T) -> Result<Wsh<Q>, TranslateErr<E>>
133+
pub fn translate_pk<T>(&self, t: &mut T) -> Result<Wsh<T::TargetPk>, TranslateErr<T::Error>>
134134
where
135-
T: Translator<Pk, Q, E>,
136-
Q: MiniscriptKey,
135+
T: Translator<Pk>,
137136
{
138137
let inner = match self.inner {
139138
WshInner::SortedMulti(ref smv) => WshInner::SortedMulti(smv.translate_pk(t)?),
@@ -366,10 +365,9 @@ impl<Pk: MiniscriptKey> Wpkh<Pk> {
366365
pub fn max_satisfaction_weight(&self) -> usize { 4 + 1 + 73 + Segwitv0::pk_len(&self.pk) }
367366

368367
/// Converts the keys in a script from one type to another.
369-
pub fn translate_pk<Q, T, E>(&self, t: &mut T) -> Result<Wpkh<Q>, TranslateErr<E>>
368+
pub fn translate_pk<T>(&self, t: &mut T) -> Result<Wpkh<T::TargetPk>, TranslateErr<T::Error>>
370369
where
371-
T: Translator<Pk, Q, E>,
372-
Q: MiniscriptKey,
370+
T: Translator<Pk>,
373371
{
374372
let res = Wpkh::new(t.pk(&self.pk)?);
375373
match res {

src/descriptor/sh.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,9 @@ impl<Pk: MiniscriptKey> Sh<Pk> {
261261
}
262262

263263
/// Converts the keys in a script from one type to another.
264-
pub fn translate_pk<Q, T, E>(&self, t: &mut T) -> Result<Sh<Q>, TranslateErr<E>>
264+
pub fn translate_pk<T>(&self, t: &mut T) -> Result<Sh<T::TargetPk>, TranslateErr<T::Error>>
265265
where
266-
T: Translator<Pk, Q, E>,
267-
Q: MiniscriptKey,
266+
T: Translator<Pk>,
268267
{
269268
let inner = match self.inner {
270269
ShInner::Wsh(ref wsh) => ShInner::Wsh(wsh.translate_pk(t)?),

src/descriptor/sortedmulti.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,12 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> SortedMultiVec<Pk, Ctx> {
7777
/// This will panic if fpk returns an uncompressed key when
7878
/// converting to a Segwit descriptor. To prevent this panic, ensure
7979
/// fpk returns an error in this case instead.
80-
pub fn translate_pk<T, Q, FuncError>(
80+
pub fn translate_pk<T>(
8181
&self,
8282
t: &mut T,
83-
) -> Result<SortedMultiVec<Q, Ctx>, TranslateErr<FuncError>>
83+
) -> Result<SortedMultiVec<T::TargetPk, Ctx>, TranslateErr<T::Error>>
8484
where
85-
T: Translator<Pk, Q, FuncError>,
86-
Q: MiniscriptKey,
85+
T: Translator<Pk>,
8786
{
8887
let ret = SortedMultiVec {
8988
inner: self.inner.translate_ref(|pk| t.pk(pk))?,

src/descriptor/tr.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,9 @@ impl<Pk: MiniscriptKey> TapTree<Pk> {
132132
pub fn iter(&self) -> TapTreeIter<Pk> { TapTreeIter { stack: vec![(0, self)] } }
133133

134134
// Helper function to translate keys
135-
fn translate_helper<T, Q, E>(&self, t: &mut T) -> Result<TapTree<Q>, TranslateErr<E>>
135+
fn translate_helper<T>(&self, t: &mut T) -> Result<TapTree<T::TargetPk>, TranslateErr<T::Error>>
136136
where
137-
T: Translator<Pk, Q, E>,
138-
Q: MiniscriptKey,
137+
T: Translator<Pk>,
139138
{
140139
let frag = match *self {
141140
TapTree::Tree { ref left, ref right, ref height } => TapTree::Tree {
@@ -353,17 +352,19 @@ impl<Pk: MiniscriptKey> Tr<Pk> {
353352
}
354353

355354
/// Converts keys from one type of public key to another.
356-
pub fn translate_pk<Q, T, E>(&self, translate: &mut T) -> Result<Tr<Q>, TranslateErr<E>>
355+
pub fn translate_pk<T>(
356+
&self,
357+
translate: &mut T,
358+
) -> Result<Tr<T::TargetPk>, TranslateErr<T::Error>>
357359
where
358-
T: Translator<Pk, Q, E>,
359-
Q: MiniscriptKey,
360+
T: Translator<Pk>,
360361
{
361362
let tree = match &self.tree {
362363
Some(tree) => Some(tree.translate_helper(translate)?),
363364
None => None,
364365
};
365-
let translate_desc = Tr::new(translate.pk(&self.internal_key)?, tree)
366-
.map_err(|e| TranslateErr::OuterError(e))?;
366+
let translate_desc =
367+
Tr::new(translate.pk(&self.internal_key)?, tree).map_err(TranslateErr::OuterError)?;
367368
Ok(translate_desc)
368369
}
369370
}

src/interpreter/inner.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,15 @@ impl<Ctx: ScriptContext> ToNoChecks for Miniscript<bitcoin::PublicKey, Ctx> {
356356
fn to_no_checks_ms(&self) -> Miniscript<BitcoinKey, NoChecks> {
357357
struct TranslateFullPk;
358358

359-
impl Translator<bitcoin::PublicKey, BitcoinKey, ()> for TranslateFullPk {
360-
fn pk(&mut self, pk: &bitcoin::PublicKey) -> Result<BitcoinKey, ()> {
359+
impl Translator<bitcoin::PublicKey> for TranslateFullPk {
360+
type TargetPk = BitcoinKey;
361+
type Error = core::convert::Infallible;
362+
363+
fn pk(&mut self, pk: &bitcoin::PublicKey) -> Result<BitcoinKey, Self::Error> {
361364
Ok(BitcoinKey::Fullkey(*pk))
362365
}
363366

364-
translate_hash_clone!(bitcoin::PublicKey, BitcoinKey, ());
367+
translate_hash_clone!(bitcoin::PublicKey, BitcoinKey, Self::Error);
365368
}
366369

367370
self.translate_pk_ctx(&mut TranslateFullPk)
@@ -371,15 +374,17 @@ impl<Ctx: ScriptContext> ToNoChecks for Miniscript<bitcoin::PublicKey, Ctx> {
371374

372375
impl<Ctx: ScriptContext> ToNoChecks for Miniscript<bitcoin::key::XOnlyPublicKey, Ctx> {
373376
fn to_no_checks_ms(&self) -> Miniscript<BitcoinKey, NoChecks> {
374-
// specify the () error type as this cannot error
375377
struct TranslateXOnlyPk;
376378

377-
impl Translator<bitcoin::key::XOnlyPublicKey, BitcoinKey, ()> for TranslateXOnlyPk {
378-
fn pk(&mut self, pk: &bitcoin::key::XOnlyPublicKey) -> Result<BitcoinKey, ()> {
379+
impl Translator<bitcoin::key::XOnlyPublicKey> for TranslateXOnlyPk {
380+
type TargetPk = BitcoinKey;
381+
type Error = core::convert::Infallible;
382+
383+
fn pk(&mut self, pk: &bitcoin::key::XOnlyPublicKey) -> Result<BitcoinKey, Self::Error> {
379384
Ok(BitcoinKey::XOnlyPublicKey(*pk))
380385
}
381386

382-
translate_hash_clone!(bitcoin::key::XOnlyPublicKey, BitcoinKey, ());
387+
translate_hash_clone!(bitcoin::key::XOnlyPublicKey, BitcoinKey, Self::Error);
383388
}
384389
self.translate_pk_ctx(&mut TranslateXOnlyPk)
385390
.expect("Translation should succeed")

src/lib.rs

+32-19
Original file line numberDiff line numberDiff line change
@@ -296,25 +296,38 @@ impl ToPublicKey for bitcoin::secp256k1::XOnlyPublicKey {
296296

297297
/// Describes an object that can translate various keys and hashes from one key to the type
298298
/// associated with the other key. Used by the [`TranslatePk`] trait to do the actual translations.
299-
pub trait Translator<P, Q, E>
300-
where
301-
P: MiniscriptKey,
302-
Q: MiniscriptKey,
303-
{
304-
/// Translates public keys P -> Q.
305-
fn pk(&mut self, pk: &P) -> Result<Q, E>;
306-
307-
/// Provides the translation from P::Sha256 -> Q::Sha256
308-
fn sha256(&mut self, sha256: &P::Sha256) -> Result<Q::Sha256, E>;
309-
310-
/// Provides the translation from P::Hash256 -> Q::Hash256
311-
fn hash256(&mut self, hash256: &P::Hash256) -> Result<Q::Hash256, E>;
312-
313-
/// Translates ripemd160 hashes from P::Ripemd160 -> Q::Ripemd160
314-
fn ripemd160(&mut self, ripemd160: &P::Ripemd160) -> Result<Q::Ripemd160, E>;
315-
316-
/// Translates hash160 hashes from P::Hash160 -> Q::Hash160
317-
fn hash160(&mut self, hash160: &P::Hash160) -> Result<Q::Hash160, E>;
299+
pub trait Translator<P: MiniscriptKey> {
300+
/// The public key (and associated hash types that this translator converts to.
301+
type TargetPk: MiniscriptKey;
302+
/// An error that may occur during transalation.
303+
type Error;
304+
305+
/// Translates keys.
306+
fn pk(&mut self, pk: &P) -> Result<Self::TargetPk, Self::Error>;
307+
308+
/// Translates SHA256 hashes.
309+
fn sha256(
310+
&mut self,
311+
sha256: &P::Sha256,
312+
) -> Result<<Self::TargetPk as MiniscriptKey>::Sha256, Self::Error>;
313+
314+
/// Translates HASH256 hashes.
315+
fn hash256(
316+
&mut self,
317+
hash256: &P::Hash256,
318+
) -> Result<<Self::TargetPk as MiniscriptKey>::Hash256, Self::Error>;
319+
320+
/// Translates RIPEMD160 hashes.
321+
fn ripemd160(
322+
&mut self,
323+
ripemd160: &P::Ripemd160,
324+
) -> Result<<Self::TargetPk as MiniscriptKey>::Ripemd160, Self::Error>;
325+
326+
/// Translates HASH160 hashes.
327+
fn hash160(
328+
&mut self,
329+
hash160: &P::Hash160,
330+
) -> Result<<Self::TargetPk as MiniscriptKey>::Hash160, Self::Error>;
318331
}
319332

320333
/// An enum for representing translation errors

0 commit comments

Comments
 (0)