Skip to content

Commit 48bdf5e

Browse files
committed
Use TreeLike to implement translate_unsatisfiable_pk
We just implemented `TreeLike` for `concrete::Policy`, use it to implement `translate_unsatisfiable_pk`, removing recursive calls from the function.
1 parent 2fb5fbc commit 48bdf5e

File tree

1 file changed

+28
-24
lines changed

1 file changed

+28
-24
lines changed

src/policy/concrete.rs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use {
2323

2424
use super::ENTAILMENT_MAX_TERMINALS;
2525
use crate::expression::{self, FromTree};
26+
use crate::iter::TreeLike;
2627
use crate::miniscript::types::extra_props::TimelockInfo;
2728
use crate::prelude::*;
2829
use crate::sync::Arc;
@@ -635,31 +636,34 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
635636

636637
/// Translates `Concrete::Key(key)` to `Concrete::Unsatisfiable` when extracting `TapKey`.
637638
pub fn translate_unsatisfiable_pk(self, key: &Pk) -> Policy<Pk> {
638-
match self {
639-
Policy::Key(ref k) if k.clone() == *key => Policy::Unsatisfiable,
640-
Policy::And(subs) => Policy::And(
641-
subs.into_iter()
642-
.map(|sub| Arc::new(sub.as_ref().clone().translate_unsatisfiable_pk(key)))
643-
.collect::<Vec<_>>(),
644-
),
645-
Policy::Or(subs) => Policy::Or(
646-
subs.into_iter()
647-
.map(|(k, sub)| {
648-
(
649-
k,
650-
Arc::new(sub.as_ref().clone().translate_unsatisfiable_pk(key)),
651-
)
652-
})
653-
.collect::<Vec<_>>(),
654-
),
655-
Policy::Threshold(k, subs) => Policy::Threshold(
656-
k,
657-
subs.into_iter()
658-
.map(|sub| Arc::new(sub.as_ref().clone().translate_unsatisfiable_pk(key)))
659-
.collect::<Vec<_>>(),
660-
),
661-
x => x,
639+
use Policy::*;
640+
641+
let mut translated = vec![];
642+
for data in Arc::new(self).post_order_iter() {
643+
let child_n = |n| Arc::clone(&translated[data.child_indices[n]]);
644+
645+
let new_policy = match data.node.as_ref() {
646+
Policy::Key(ref k) if k.clone() == *key => Some(Policy::Unsatisfiable),
647+
Threshold(k, ref subs) => {
648+
Some(Threshold(*k, (0..subs.len()).map(child_n).collect()))
649+
}
650+
And(ref subs) => Some(And((0..subs.len()).map(child_n).collect())),
651+
Or(ref subs) => Some(Or(subs
652+
.iter()
653+
.enumerate()
654+
.map(|(i, (prob, _))| (*prob, child_n(i)))
655+
.collect())),
656+
_ => None,
657+
};
658+
match new_policy {
659+
Some(new_policy) => translated.push(Arc::new(new_policy)),
660+
None => translated.push(Arc::clone(&data.node)),
661+
}
662662
}
663+
// Ok to unwrap because we know we processed at least one node.
664+
let root_node = translated.pop().unwrap();
665+
// Ok to unwrap because we know `root_node` is the only strong reference.
666+
Arc::try_unwrap(root_node).unwrap()
663667
}
664668

665669
/// Gets all keys in the policy.

0 commit comments

Comments
 (0)