Skip to content

Commit 8373269

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 c2ced8a commit 8373269

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
@@ -574,52 +574,36 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
574574
T: Translator<Pk, Q, E>,
575575
Q: MiniscriptKey,
576576
{
577-
self._translate_pk(t)
578-
}
577+
use Policy::*;
579578

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

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

0 commit comments

Comments
 (0)