Skip to content

Commit 64488d6

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 3282193 commit 64488d6

File tree

1 file changed

+27
-41
lines changed

1 file changed

+27
-41
lines changed

src/policy/concrete.rs

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -560,50 +560,36 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
560560
T: Translator<Pk, Q, E>,
561561
Q: MiniscriptKey,
562562
{
563-
self._translate_pk(t)
564-
}
563+
use Policy::*;
565564

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

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

0 commit comments

Comments
 (0)