Skip to content

Commit 38308c6

Browse files
committed
Use TreeLike to implement translate_pk
Remove recursive calls and use `TreeLike`'s post order iterator to implement `translate_pk` for the `concrete::Policy`. Note, no additional unit tests added for this code path, this is a familiar code pattern now.
1 parent 6870d6f commit 38308c6

File tree

1 file changed

+27
-43
lines changed

1 file changed

+27
-43
lines changed

src/policy/concrete.rs

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -570,52 +570,36 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
570570
T: Translator<Pk, Q, E>,
571571
Q: MiniscriptKey,
572572
{
573-
self._translate_pk(t)
574-
}
573+
use Policy::*;
575574

576-
fn _translate_pk<Q, E, T>(&self, t: &mut T) -> Result<Policy<Q>, E>
577-
where
578-
T: Translator<Pk, Q, E>,
579-
Q: MiniscriptKey,
580-
{
581-
match *self {
582-
Policy::Unsatisfiable => Ok(Policy::Unsatisfiable),
583-
Policy::Trivial => Ok(Policy::Trivial),
584-
Policy::Key(ref pk) => t.pk(pk).map(Policy::Key),
585-
Policy::Sha256(ref h) => t.sha256(h).map(Policy::Sha256),
586-
Policy::Hash256(ref h) => t.hash256(h).map(Policy::Hash256),
587-
Policy::Ripemd160(ref h) => t.ripemd160(h).map(Policy::Ripemd160),
588-
Policy::Hash160(ref h) => t.hash160(h).map(Policy::Hash160),
589-
Policy::Older(n) => Ok(Policy::Older(n)),
590-
Policy::After(n) => Ok(Policy::After(n)),
591-
Policy::Threshold(k, ref subs) => {
592-
let new_subs: Result<Vec<Policy<Q>>, _> =
593-
subs.iter().map(|sub| sub._translate_pk(t)).collect();
594-
new_subs
595-
.map(|ok| Policy::Threshold(k, ok.into_iter().map(|p| Arc::new(p)).collect()))
596-
}
597-
Policy::And(ref subs) => {
598-
let new_subs = subs
599-
.iter()
600-
.map(|sub| sub._translate_pk(t))
601-
.collect::<Result<Vec<Policy<Q>>, E>>()?;
602-
Ok(Policy::And(
603-
new_subs.into_iter().map(|p| Arc::new(p)).collect(),
604-
))
605-
}
606-
Policy::Or(ref subs) => {
607-
let new_subs = subs
575+
let mut translated = vec![];
576+
for data in self.post_order_iter() {
577+
let child_n = |n| Arc::clone(&translated[data.child_indices[n]]);
578+
579+
let new_policy = match data.node {
580+
Unsatisfiable => Unsatisfiable,
581+
Trivial => Trivial,
582+
Key(ref pk) => t.pk(pk).map(Key)?,
583+
Sha256(ref h) => t.sha256(h).map(Sha256)?,
584+
Hash256(ref h) => t.hash256(h).map(Hash256)?,
585+
Ripemd160(ref h) => t.ripemd160(h).map(Ripemd160)?,
586+
Hash160(ref h) => t.hash160(h).map(Hash160)?,
587+
Older(ref n) => Older(*n),
588+
After(ref n) => After(*n),
589+
Threshold(ref k, ref subs) => Threshold(*k, (0..subs.len()).map(child_n).collect()),
590+
And(ref subs) => And((0..subs.len()).map(child_n).collect()),
591+
Or(ref subs) => Or(subs
608592
.iter()
609-
.map(|(prob, sub)| Ok((*prob, sub._translate_pk(t)?)))
610-
.collect::<Result<Vec<(usize, Policy<Q>)>, E>>()?;
611-
Ok(Policy::Or(
612-
new_subs
613-
.into_iter()
614-
.map(|(prob, sub)| (prob, Arc::new(sub)))
615-
.collect(),
616-
))
617-
}
593+
.enumerate()
594+
.map(|(i, (prob, _))| (*prob, child_n(i)))
595+
.collect()),
596+
};
597+
translated.push(Arc::new(new_policy));
618598
}
599+
// Unwrap is ok because we know we processed at least one node.
600+
let root_node = translated.pop().unwrap();
601+
// Unwrap is ok because we know `root_node` is the only strong reference.
602+
Ok(Arc::try_unwrap(root_node).unwrap())
619603
}
620604

621605
/// Translates `Concrete::Key(key)` to `Concrete::Unsatisfiable` when extracting `TapKey`.

0 commit comments

Comments
 (0)