Skip to content

Commit 2b11f64

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 4d22908 commit 2b11f64

File tree

1 file changed

+28
-21
lines changed

1 file changed

+28
-21
lines changed

src/policy/concrete.rs

Lines changed: 28 additions & 21 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;
@@ -623,28 +624,34 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
623624

624625
/// Translates `Concrete::Key(key)` to `Concrete::Unsatisfiable` when extracting `TapKey`.
625626
pub fn translate_unsatisfiable_pk(self, key: &Pk) -> Policy<Pk> {
626-
match self {
627-
Policy::Key(ref k) if k.clone() == *key => Policy::Unsatisfiable,
628-
Policy::And(subs) => Policy::And(
629-
subs.into_iter()
630-
.map(|sub| Arc::new(sub.as_ref().clone().translate_unsatisfiable_pk(key)))
631-
.collect::<Vec<_>>(),
632-
),
633-
Policy::Or(subs) => Policy::Or(
634-
subs.into_iter()
635-
.map(|(k, sub)| {
636-
(k, Arc::new(sub.as_ref().clone().translate_unsatisfiable_pk(key)))
637-
})
638-
.collect::<Vec<_>>(),
639-
),
640-
Policy::Threshold(k, subs) => Policy::Threshold(
641-
k,
642-
subs.into_iter()
643-
.map(|sub| Arc::new(sub.as_ref().clone().translate_unsatisfiable_pk(key)))
644-
.collect::<Vec<_>>(),
645-
),
646-
x => x,
627+
use Policy::*;
628+
629+
let mut translated = vec![];
630+
for data in Arc::new(self).post_order_iter() {
631+
let child_n = |n| Arc::clone(&translated[data.child_indices[n]]);
632+
633+
let new_policy = match data.node.as_ref() {
634+
Policy::Key(ref k) if k.clone() == *key => Some(Policy::Unsatisfiable),
635+
Threshold(k, ref subs) => {
636+
Some(Threshold(*k, (0..subs.len()).map(child_n).collect()))
637+
}
638+
And(ref subs) => Some(And((0..subs.len()).map(child_n).collect())),
639+
Or(ref subs) => Some(Or(subs
640+
.iter()
641+
.enumerate()
642+
.map(|(i, (prob, _))| (*prob, child_n(i)))
643+
.collect())),
644+
_ => None,
645+
};
646+
match new_policy {
647+
Some(new_policy) => translated.push(Arc::new(new_policy)),
648+
None => translated.push(Arc::clone(&data.node)),
649+
}
647650
}
651+
// Ok to unwrap because we know we processed at least one node.
652+
let root_node = translated.pop().unwrap();
653+
// Ok to unwrap because we know `root_node` is the only strong reference.
654+
Arc::try_unwrap(root_node).unwrap()
648655
}
649656

650657
/// Gets all keys in the policy.

0 commit comments

Comments
 (0)