Skip to content

Commit 5e2b235

Browse files
committed
semantic: Remove recursion in minimum_n_keys
Done as part of the effort to remove all the recursion crate wide. Use the `TreeLike` trait to iterate over policy nodes and remove the recursive call in `semantic::Policy::minimum_n_keys`.
1 parent a76d3e1 commit 5e2b235

File tree

1 file changed

+26
-20
lines changed

1 file changed

+26
-20
lines changed

src/policy/semantic.rs

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -620,28 +620,34 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
620620
///
621621
/// Returns `None` if the policy is not satisfiable.
622622
pub fn minimum_n_keys(&self) -> Option<usize> {
623-
match *self {
624-
Policy::Unsatisfiable => None,
625-
Policy::Trivial => Some(0),
626-
Policy::Key(..) => Some(1),
627-
Policy::After(..)
628-
| Policy::Older(..)
629-
| Policy::Sha256(..)
630-
| Policy::Hash256(..)
631-
| Policy::Ripemd160(..)
632-
| Policy::Hash160(..) => Some(0),
633-
Policy::Threshold(k, ref subs) => {
634-
let mut sublens: Vec<usize> =
635-
subs.iter().filter_map(|p| p.minimum_n_keys()).collect();
636-
if sublens.len() < k {
637-
// Not enough branches are satisfiable
638-
None
639-
} else {
640-
sublens.sort_unstable();
641-
Some(sublens[0..k].iter().cloned().sum::<usize>())
623+
use Policy::*;
624+
625+
let mut minimum_n_keys = vec![];
626+
for data in Arc::new(self).post_order_iter() {
627+
let minimum_n_keys_for_child_n = |n| minimum_n_keys[data.child_indices[n]];
628+
629+
let minimum_n_key = match data.node {
630+
Unsatisfiable => None,
631+
Trivial | After(..) | Older(..) | Sha256(..) | Hash256(..) | Ripemd160(..)
632+
| Hash160(..) => Some(0),
633+
Key(..) => Some(1),
634+
Threshold(k, ref subs) => {
635+
let mut sublens = (0..subs.len())
636+
.filter_map(minimum_n_keys_for_child_n)
637+
.collect::<Vec<usize>>();
638+
if sublens.len() < *k {
639+
// Not enough branches are satisfiable
640+
None
641+
} else {
642+
sublens.sort_unstable();
643+
Some(sublens[0..*k].iter().cloned().sum::<usize>())
644+
}
642645
}
643-
}
646+
};
647+
minimum_n_keys.push(minimum_n_key);
644648
}
649+
// Ok to unwrap because we know we processed at least one node.
650+
minimum_n_keys.pop().unwrap()
645651
}
646652
}
647653

0 commit comments

Comments
 (0)