Skip to content

Commit 36b0659

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 c330d0b commit 36b0659

File tree

17 files changed

+192
-128
lines changed

17 files changed

+192
-128
lines changed

bitcoind-tests/tests/setup/test_util.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,11 @@ pub fn parse_insane_ms<Ctx: ScriptContext>(
155155
#[derive(Debug, Clone)]
156156
struct StrDescPubKeyTranslator<'a>(usize, &'a PubData);
157157

158-
impl<'a> Translator<String, DescriptorPublicKey, ()> for StrDescPubKeyTranslator<'a> {
159-
fn pk(&mut self, pk_str: &String) -> Result<DescriptorPublicKey, ()> {
158+
impl<'a> Translator<String> for StrDescPubKeyTranslator<'a> {
159+
type TargetPk = DescriptorPublicKey;
160+
type Error = core::convert::Infallible;
161+
162+
fn pk(&mut self, pk_str: &String) -> Result<Self::TargetPk, Self::Error> {
160163
let avail = !pk_str.ends_with('!');
161164
if avail {
162165
self.0 += 1;
@@ -181,22 +184,22 @@ impl<'a> Translator<String, DescriptorPublicKey, ()> for StrDescPubKeyTranslator
181184
}
182185
}
183186

184-
fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, ()> {
187+
fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, Self::Error> {
185188
let sha = sha256::Hash::from_str(sha256).unwrap();
186189
Ok(sha)
187190
}
188191

189-
fn hash256(&mut self, hash256: &String) -> Result<hash256::Hash, ()> {
192+
fn hash256(&mut self, hash256: &String) -> Result<hash256::Hash, Self::Error> {
190193
let hash256 = hash256::Hash::from_str(hash256).unwrap();
191194
Ok(hash256)
192195
}
193196

194-
fn ripemd160(&mut self, ripemd160: &String) -> Result<ripemd160::Hash, ()> {
197+
fn ripemd160(&mut self, ripemd160: &String) -> Result<ripemd160::Hash, Self::Error> {
195198
let ripemd160 = ripemd160::Hash::from_str(ripemd160).unwrap();
196199
Ok(ripemd160)
197200
}
198201

199-
fn hash160(&mut self, hash160: &String) -> Result<hash160::Hash, ()> {
202+
fn hash160(&mut self, hash160: &String) -> Result<hash160::Hash, Self::Error> {
200203
let hash160 = hash160::Hash::from_str(hash160).unwrap();
201204
Ok(hash160)
202205
}
@@ -208,8 +211,11 @@ impl<'a> Translator<String, DescriptorPublicKey, ()> for StrDescPubKeyTranslator
208211
#[derive(Debug, Clone)]
209212
struct StrTranslatorLoose<'a>(usize, &'a PubData);
210213

211-
impl<'a> Translator<String, DescriptorPublicKey, ()> for StrTranslatorLoose<'a> {
212-
fn pk(&mut self, pk_str: &String) -> Result<DescriptorPublicKey, ()> {
214+
impl<'a> Translator<String> for StrTranslatorLoose<'a> {
215+
type TargetPk = DescriptorPublicKey;
216+
type Error = core::convert::Infallible;
217+
218+
fn pk(&mut self, pk_str: &String) -> Result<Self::TargetPk, Self::Error> {
213219
let avail = !pk_str.ends_with('!');
214220
if avail {
215221
self.0 += 1;
@@ -238,22 +244,22 @@ impl<'a> Translator<String, DescriptorPublicKey, ()> for StrTranslatorLoose<'a>
238244
}
239245
}
240246

241-
fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, ()> {
247+
fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, Self::Error> {
242248
let sha = sha256::Hash::from_str(sha256).unwrap();
243249
Ok(sha)
244250
}
245251

246-
fn hash256(&mut self, hash256: &String) -> Result<hash256::Hash, ()> {
252+
fn hash256(&mut self, hash256: &String) -> Result<hash256::Hash, Self::Error> {
247253
let hash256 = hash256::Hash::from_str(hash256).unwrap();
248254
Ok(hash256)
249255
}
250256

251-
fn ripemd160(&mut self, ripemd160: &String) -> Result<ripemd160::Hash, ()> {
257+
fn ripemd160(&mut self, ripemd160: &String) -> Result<ripemd160::Hash, Self::Error> {
252258
let ripemd160 = ripemd160::Hash::from_str(ripemd160).unwrap();
253259
Ok(ripemd160)
254260
}
255261

256-
fn hash160(&mut self, hash160: &String) -> Result<hash160::Hash, ()> {
262+
fn hash160(&mut self, hash160: &String) -> Result<hash160::Hash, Self::Error> {
257263
let hash160 = hash160::Hash::from_str(hash160).unwrap();
258264
Ok(hash160)
259265
}

examples/big.rs

Lines changed: 6 additions & 3 deletions
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

Lines changed: 6 additions & 3 deletions
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

Lines changed: 4 additions & 6 deletions
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

Lines changed: 34 additions & 19 deletions
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

Lines changed: 4 additions & 6 deletions
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

Lines changed: 2 additions & 3 deletions
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

Lines changed: 3 additions & 4 deletions
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

Lines changed: 9 additions & 8 deletions
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

Lines changed: 12 additions & 7 deletions
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")

0 commit comments

Comments
 (0)