Skip to content

Commit 54497be

Browse files
committed
impl PkTranslate trait for Miniscript and Terminal
1 parent c68f410 commit 54497be

File tree

2 files changed

+85
-45
lines changed

2 files changed

+85
-45
lines changed

src/miniscript/astelem.rs

Lines changed: 60 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use bitcoin::blockdata::{opcodes, script};
2525
use bitcoin::hashes::hex::FromHex;
2626
use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
2727

28+
use descriptor::PkTranslate;
2829
use errstr;
2930
use expression;
3031
use miniscript::types::{self, Property};
@@ -59,11 +60,29 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
5960
}
6061
}
6162

62-
impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
63+
impl<Pk: MiniscriptKey, Q: MiniscriptKey, Ctx: ScriptContext> PkTranslate<Pk, Q>
64+
for Terminal<Pk, Ctx>
65+
{
66+
type Output = Terminal<Q, Ctx>;
67+
6368
/// Convert an AST element with one public key type to one of another
6469
/// public key type .This will panic while converting to
6570
/// Segwit Miniscript using uncompressed public keys
66-
pub fn translate_pk<FPk, FPkh, Q, Error>(
71+
fn translate_pk<FPk, FPkh, FuncError>(
72+
&self,
73+
mut translatefpk: FPk,
74+
mut translatefpkh: FPkh,
75+
) -> Result<Self::Output, FuncError>
76+
where
77+
FPk: FnMut(&Pk) -> Result<Q, FuncError>,
78+
FPkh: FnMut(&Pk::Hash) -> Result<Q::Hash, FuncError>,
79+
{
80+
self.real_translate_pk(&mut translatefpk, &mut translatefpkh)
81+
}
82+
}
83+
84+
impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
85+
pub(super) fn real_translate_pk<FPk, FPkh, Q, Error>(
6786
&self,
6887
translatefpk: &mut FPk,
6988
translatefpkh: &mut FPkh,
@@ -84,61 +103,63 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
84103
Terminal::Hash160(x) => Terminal::Hash160(x),
85104
Terminal::True => Terminal::True,
86105
Terminal::False => Terminal::False,
87-
Terminal::Alt(ref sub) => {
88-
Terminal::Alt(Arc::new(sub.translate_pk(translatefpk, translatefpkh)?))
89-
}
90-
Terminal::Swap(ref sub) => {
91-
Terminal::Swap(Arc::new(sub.translate_pk(translatefpk, translatefpkh)?))
92-
}
93-
Terminal::Check(ref sub) => {
94-
Terminal::Check(Arc::new(sub.translate_pk(translatefpk, translatefpkh)?))
95-
}
96-
Terminal::DupIf(ref sub) => {
97-
Terminal::DupIf(Arc::new(sub.translate_pk(translatefpk, translatefpkh)?))
98-
}
99-
Terminal::Verify(ref sub) => {
100-
Terminal::Verify(Arc::new(sub.translate_pk(translatefpk, translatefpkh)?))
101-
}
102-
Terminal::NonZero(ref sub) => {
103-
Terminal::NonZero(Arc::new(sub.translate_pk(translatefpk, translatefpkh)?))
104-
}
105-
Terminal::ZeroNotEqual(ref sub) => {
106-
Terminal::ZeroNotEqual(Arc::new(sub.translate_pk(translatefpk, translatefpkh)?))
107-
}
106+
Terminal::Alt(ref sub) => Terminal::Alt(Arc::new(
107+
sub.real_translate_pk(translatefpk, translatefpkh)?,
108+
)),
109+
Terminal::Swap(ref sub) => Terminal::Swap(Arc::new(
110+
sub.real_translate_pk(translatefpk, translatefpkh)?,
111+
)),
112+
Terminal::Check(ref sub) => Terminal::Check(Arc::new(
113+
sub.real_translate_pk(translatefpk, translatefpkh)?,
114+
)),
115+
Terminal::DupIf(ref sub) => Terminal::DupIf(Arc::new(
116+
sub.real_translate_pk(translatefpk, translatefpkh)?,
117+
)),
118+
Terminal::Verify(ref sub) => Terminal::Verify(Arc::new(
119+
sub.real_translate_pk(translatefpk, translatefpkh)?,
120+
)),
121+
Terminal::NonZero(ref sub) => Terminal::NonZero(Arc::new(
122+
sub.real_translate_pk(translatefpk, translatefpkh)?,
123+
)),
124+
Terminal::ZeroNotEqual(ref sub) => Terminal::ZeroNotEqual(Arc::new(
125+
sub.real_translate_pk(translatefpk, translatefpkh)?,
126+
)),
108127
Terminal::AndV(ref left, ref right) => Terminal::AndV(
109-
Arc::new(left.translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
110-
Arc::new(right.translate_pk(translatefpk, translatefpkh)?),
128+
Arc::new(left.real_translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
129+
Arc::new(right.real_translate_pk(translatefpk, translatefpkh)?),
111130
),
112131
Terminal::AndB(ref left, ref right) => Terminal::AndB(
113-
Arc::new(left.translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
114-
Arc::new(right.translate_pk(translatefpk, translatefpkh)?),
132+
Arc::new(left.real_translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
133+
Arc::new(right.real_translate_pk(translatefpk, translatefpkh)?),
115134
),
116135
Terminal::AndOr(ref a, ref b, ref c) => Terminal::AndOr(
117-
Arc::new(a.translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
118-
Arc::new(b.translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
119-
Arc::new(c.translate_pk(translatefpk, translatefpkh)?),
136+
Arc::new(a.real_translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
137+
Arc::new(b.real_translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
138+
Arc::new(c.real_translate_pk(translatefpk, translatefpkh)?),
120139
),
121140
Terminal::OrB(ref left, ref right) => Terminal::OrB(
122-
Arc::new(left.translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
123-
Arc::new(right.translate_pk(translatefpk, translatefpkh)?),
141+
Arc::new(left.real_translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
142+
Arc::new(right.real_translate_pk(translatefpk, translatefpkh)?),
124143
),
125144
Terminal::OrD(ref left, ref right) => Terminal::OrD(
126-
Arc::new(left.translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
127-
Arc::new(right.translate_pk(translatefpk, translatefpkh)?),
145+
Arc::new(left.real_translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
146+
Arc::new(right.real_translate_pk(translatefpk, translatefpkh)?),
128147
),
129148
Terminal::OrC(ref left, ref right) => Terminal::OrC(
130-
Arc::new(left.translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
131-
Arc::new(right.translate_pk(translatefpk, translatefpkh)?),
149+
Arc::new(left.real_translate_pk(&mut *translatefpk, &mut *translatefpkh)?),
150+
Arc::new(right.real_translate_pk(translatefpk, translatefpkh)?),
132151
),
133152
Terminal::OrI(ref left, ref right) => Terminal::OrI(
134-
Arc::new(left.translate_pk(&mut *&mut *translatefpk, &mut *&mut *translatefpkh)?),
135-
Arc::new(right.translate_pk(translatefpk, translatefpkh)?),
153+
Arc::new(
154+
left.real_translate_pk(&mut *&mut *translatefpk, &mut *&mut *translatefpkh)?,
155+
),
156+
Arc::new(right.real_translate_pk(translatefpk, translatefpkh)?),
136157
),
137158
Terminal::Thresh(k, ref subs) => {
138159
let subs: Result<Vec<Arc<Miniscript<Q, _>>>, _> = subs
139160
.iter()
140161
.map(|s| {
141-
s.translate_pk(&mut *translatefpk, &mut *translatefpkh)
162+
s.real_translate_pk(&mut *translatefpk, &mut *translatefpkh)
142163
.and_then(|x| Ok(Arc::new(x)))
143164
})
144165
.collect();

src/miniscript/mod.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub mod types;
4444

4545
use self::lex::{lex, TokenIter};
4646
use self::types::Property;
47+
use descriptor::PkTranslate;
4748
pub use miniscript::context::ScriptContext;
4849
use miniscript::decode::Terminal;
4950
use miniscript::types::extra_props::ExtData;
@@ -232,11 +233,29 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
232233
}
233234
}
234235

235-
impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
236+
impl<Pk: MiniscriptKey, Q: MiniscriptKey, Ctx: ScriptContext> PkTranslate<Pk, Q>
237+
for Miniscript<Pk, Ctx>
238+
{
239+
type Output = Miniscript<Q, Ctx>;
240+
236241
/// This will panic if translatefpk returns an uncompressed key when
237242
/// converting to a Segwit descriptor. To prevent this panic, ensure
238243
/// translatefpk returns an error in this case instead.
239-
pub fn translate_pk<FPk, FPkh, Q, FuncError>(
244+
fn translate_pk<FPk, FPkh, FuncError>(
245+
&self,
246+
mut translatefpk: FPk,
247+
mut translatefpkh: FPkh,
248+
) -> Result<Self::Output, FuncError>
249+
where
250+
FPk: FnMut(&Pk) -> Result<Q, FuncError>,
251+
FPkh: FnMut(&Pk::Hash) -> Result<Q::Hash, FuncError>,
252+
{
253+
self.real_translate_pk(&mut translatefpk, &mut translatefpkh)
254+
}
255+
}
256+
257+
impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
258+
fn real_translate_pk<FPk, FPkh, Q, FuncError>(
240259
&self,
241260
translatefpk: &mut FPk,
242261
translatefpkh: &mut FPkh,
@@ -246,7 +265,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
246265
FPkh: FnMut(&Pk::Hash) -> Result<Q::Hash, FuncError>,
247266
Q: MiniscriptKey,
248267
{
249-
let inner = self.node.translate_pk(translatefpk, translatefpkh)?;
268+
let inner = self.node.real_translate_pk(translatefpk, translatefpkh)?;
250269
let ms = Miniscript {
251270
//directly copying the type and ext is safe because translating public
252271
//key should not change any properties
@@ -397,6 +416,7 @@ serde_string_impl_pk!(Miniscript, "a miniscript", Ctx; ScriptContext);
397416
mod tests {
398417
use super::Segwitv0;
399418
use super::{Miniscript, ScriptContext};
419+
use descriptor::PkTranslate;
400420
use hex_script;
401421
use miniscript::types::{self, ExtData, Property, Type};
402422
use miniscript::Terminal;
@@ -460,9 +480,8 @@ mod tests {
460480
let roundtrip = Miniscript::from_str(&display).expect("parse string serialization");
461481
assert_eq!(roundtrip, script);
462482

463-
let translated: Result<_, ()> =
464-
script.translate_pk(&mut |k| Ok(k.clone()), &mut |h| Ok(h.clone()));
465-
assert_eq!(translated, Ok(script));
483+
let translated = script.translate_pk_infallible(Pk::clone, Pk::Hash::clone);
484+
assert_eq!(translated, script);
466485
}
467486

468487
fn script_rtt<Str1: Into<Option<&'static str>>>(script: Segwitv0Script, expected_hex: Str1) {

0 commit comments

Comments
 (0)