Skip to content

Commit ffe3668

Browse files
committed
Replace misc uses of Pk: FromStr bound with impl_block_str!
The benefits of these will be obivious in the subsequent overhaul commits
1 parent 2eff96f commit ffe3668

File tree

4 files changed

+72
-63
lines changed

4 files changed

+72
-63
lines changed

src/descriptor/tr.rs

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -388,36 +388,31 @@ where
388388
}
389389
}
390390

391-
impl_from_tree!(
391+
impl_block_str!(
392392
Tr<Pk>,
393-
fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
394-
// Helper function to parse taproot script path
395-
fn parse_tr_script_spend<Pk: MiniscriptKey>(
396-
tree: &expression::Tree,
397-
) -> Result<TapTree<Pk>, Error>
398-
where
399-
Pk: MiniscriptKey + FromStr,
400-
Pk::Hash: FromStr,
401-
<Pk as FromStr>::Err: ToString,
402-
<<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString,
403-
{
404-
match tree {
405-
expression::Tree { name, args } if !name.is_empty() && args.is_empty() => {
406-
let script = Miniscript::<Pk, Tap>::from_str(name)?;
407-
Ok(TapTree::Leaf(Arc::new(script)))
408-
}
409-
expression::Tree { name, args } if name.is_empty() && args.len() == 2 => {
410-
let left = parse_tr_script_spend(&args[0])?;
411-
let right = parse_tr_script_spend(&args[1])?;
412-
Ok(TapTree::Tree(Arc::new(left), Arc::new(right)))
413-
}
414-
_ => Err(Error::Unexpected(
415-
"unknown format for script spending paths while parsing taproot descriptor"
416-
.to_string(),
417-
)),
393+
// Helper function to parse taproot script path
394+
fn parse_tr_script_spend(tree: &expression::Tree) -> Result<TapTree<Pk>, Error> {
395+
match tree {
396+
expression::Tree { name, args } if !name.is_empty() && args.is_empty() => {
397+
let script = Miniscript::<Pk, Tap>::from_str(name)?;
398+
Ok(TapTree::Leaf(Arc::new(script)))
399+
}
400+
expression::Tree { name, args } if name.is_empty() && args.len() == 2 => {
401+
let left = Self::parse_tr_script_spend(&args[0])?;
402+
let right = Self::parse_tr_script_spend(&args[1])?;
403+
Ok(TapTree::Tree(Arc::new(left), Arc::new(right)))
418404
}
405+
_ => Err(Error::Unexpected(
406+
"unknown format for script spending paths while parsing taproot descriptor"
407+
.to_string(),
408+
)),
419409
}
410+
}
411+
);
420412

413+
impl_from_tree!(
414+
Tr<Pk>,
415+
fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
421416
if top.name == "tr" {
422417
match top.args.len() {
423418
1 => {
@@ -443,7 +438,7 @@ impl_from_tree!(
443438
)));
444439
}
445440
let tree = &top.args[1];
446-
let ret = parse_tr_script_spend(tree)?;
441+
let ret = Self::parse_tr_script_spend(tree)?;
447442
Ok(Tr {
448443
internal_key: expression::terminal(key, Pk::from_str)?,
449444
tree: Some(ret),

src/macros.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,23 @@ macro_rules! impl_from_str {
5050
};
5151
}
5252

53+
/// Macro for implementing FromTree trait. This avoids copying all the Pk::Associated type bounds
54+
/// throughout the codebase.
55+
macro_rules! impl_block_str {
56+
($(;$gen:ident; $gen_con:ident, )* $name: ty $(, $it: item)*) => {
57+
impl<Pk $(, $gen)*> $name
58+
where
59+
Pk: MiniscriptKey + std::str::FromStr,
60+
Pk::Hash : std::str::FromStr,
61+
<Pk as std::str::FromStr>::Err: std::string::ToString,
62+
<<Pk as MiniscriptKey>::Hash as std::str::FromStr>::Err: std::string::ToString,
63+
$($gen : $gen_con,)*
64+
{
65+
$($it)*
66+
}
67+
};
68+
}
69+
5370
/// A macro that implements serde serialization and deserialization using the
5471
/// `fmt::Display` and `str::FromStr` traits.
5572
macro_rules! serde_string_impl_pk {

src/miniscript/mod.rs

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,11 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
338338
};
339339
Ok(ms)
340340
}
341+
}
341342

343+
impl_block_str!(
344+
;Ctx; ScriptContext,
345+
Miniscript<Pk, Ctx>,
342346
/// Attempt to parse an insane(scripts don't clear sanity checks)
343347
/// from string into a Miniscript representation.
344348
/// Use this to parse scripts with repeated pubkeys, timelock mixing, malleable
@@ -347,11 +351,6 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
347351
/// insane scripts. In general, in a multi-party setting users should only
348352
/// accept sane scripts.
349353
pub fn from_str_insane(s: &str) -> Result<Miniscript<Pk, Ctx>, Error>
350-
where
351-
Pk: str::FromStr,
352-
Pk::Hash: str::FromStr,
353-
<Pk as str::FromStr>::Err: ToString,
354-
<<Pk as MiniscriptKey>::Hash as str::FromStr>::Err: ToString,
355354
{
356355
// This checks for invalid ASCII chars
357356
let top = expression::Tree::from_str(s)?;
@@ -363,7 +362,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
363362
Ok(ms)
364363
}
365364
}
366-
}
365+
);
367366

368367
impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
369368
/// Attempt to produce non-malleable satisfying witness for the
@@ -475,8 +474,7 @@ mod tests {
475474
use crate::policy::Liftable;
476475
use crate::prelude::*;
477476
use crate::{
478-
hex_script, DummyKey, DummyKeyHash, MiniscriptKey, Satisfier, ToPublicKey, TranslatePk,
479-
TranslatePk1, TranslatePk2,
477+
hex_script, DummyKey, DummyKeyHash, Satisfier, ToPublicKey, TranslatePk, TranslatePk2,
480478
};
481479

482480
type Segwitv0Script = Miniscript<bitcoin::PublicKey, Segwitv0>;
@@ -503,19 +501,11 @@ mod tests {
503501
ret
504502
}
505503

506-
fn string_rtt<Pk, Ctx, Str1, Str2>(
507-
script: Miniscript<Pk, Ctx>,
508-
expected_debug: Str1,
509-
expected_display: Str2,
510-
) where
511-
Pk: MiniscriptKey + str::FromStr,
512-
Pk::Hash: str::FromStr,
513-
Ctx: ScriptContext,
514-
<Pk as str::FromStr>::Err: ToString,
515-
<<Pk as MiniscriptKey>::Hash as str::FromStr>::Err: ToString,
516-
Str1: Into<Option<&'static str>>,
517-
Str2: Into<Option<&'static str>>,
518-
{
504+
fn string_rtt<Ctx: ScriptContext>(
505+
script: Miniscript<bitcoin::PublicKey, Ctx>,
506+
expected_debug: &str,
507+
expected_display: &str,
508+
) {
519509
assert_eq!(script.ty.corr.base, types::Base::B);
520510
let debug = format!("{:?}", script);
521511
let display = format!("{}", script);
@@ -527,12 +517,24 @@ mod tests {
527517
}
528518
let roundtrip = Miniscript::from_str(&display).expect("parse string serialization");
529519
assert_eq!(roundtrip, script);
520+
}
530521

531-
let translated = script.translate_pk_infallible(Pk::clone, Pk::Hash::clone);
532-
assert_eq!(translated, script);
533-
534-
let translated = script.translate_pk1_infallible(Pk::clone);
535-
assert_eq!(translated, script);
522+
fn dummy_string_rtt<Ctx: ScriptContext>(
523+
script: Miniscript<DummyKey, Ctx>,
524+
expected_debug: &str,
525+
expected_display: &str,
526+
) {
527+
assert_eq!(script.ty.corr.base, types::Base::B);
528+
let debug = format!("{:?}", script);
529+
let display = format!("{}", script);
530+
if let Some(expected) = expected_debug.into() {
531+
assert_eq!(debug, expected);
532+
}
533+
if let Some(expected) = expected_display.into() {
534+
assert_eq!(display, expected);
535+
}
536+
let roundtrip = Miniscript::from_str(&display).expect("parse string serialization");
537+
assert_eq!(roundtrip, script);
536538
}
537539

538540
fn script_rtt<Str1: Into<Option<&'static str>>>(script: Segwitv0Script, expected_hex: Str1) {
@@ -648,7 +650,7 @@ mod tests {
648650
ext: ExtData::cast_check(ExtData::from_pk_k::<Segwitv0>()).unwrap(),
649651
phantom: PhantomData,
650652
};
651-
string_rtt(pkk_ms, "[B/onduesm]c:[K/onduesm]pk_k(DummyKey)", "pk()");
653+
dummy_string_rtt(pkk_ms, "[B/onduesm]c:[K/onduesm]pk_k(DummyKey)", "pk()");
652654

653655
let pkh_ms: Miniscript<DummyKey, Segwitv0> = Miniscript {
654656
node: Terminal::Check(Arc::new(Miniscript {
@@ -661,7 +663,7 @@ mod tests {
661663
ext: ExtData::cast_check(ExtData::from_pk_h::<Segwitv0>()).unwrap(),
662664
phantom: PhantomData,
663665
};
664-
string_rtt(pkh_ms, "[B/nduesm]c:[K/nduesm]pk_h(DummyKeyHash)", "pkh()");
666+
dummy_string_rtt(pkh_ms, "[B/nduesm]c:[K/nduesm]pk_h(DummyKeyHash)", "pkh()");
665667

666668
let pkk_ms: Segwitv0Script = Miniscript {
667669
node: Terminal::Check(Arc::new(Miniscript {

src/policy/concrete.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -698,13 +698,8 @@ impl_from_str!(
698698

699699
serde_string_impl_pk!(Policy, "a miniscript concrete policy");
700700

701-
impl<Pk> Policy<Pk>
702-
where
703-
Pk: MiniscriptKey + str::FromStr,
704-
Pk::Hash: str::FromStr,
705-
<Pk as str::FromStr>::Err: ToString,
706-
<<Pk as MiniscriptKey>::Hash as str::FromStr>::Err: ToString,
707-
{
701+
impl_block_str!(
702+
Policy<Pk>,
708703
/// Helper function for `from_tree` to parse subexpressions with
709704
/// names of the form x@y
710705
fn from_tree_prob(
@@ -808,7 +803,7 @@ where
808803
}
809804
.map(|res| (frag_prob, res))
810805
}
811-
}
806+
);
812807

813808
impl_from_tree!(
814809
Policy<Pk>,

0 commit comments

Comments
 (0)