From dceced4a57f5f74d3bd777fe81756fea46940a5f Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 11 Oct 2023 14:16:26 +1100 Subject: [PATCH] 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`. --- src/policy/semantic.rs | 46 ++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/policy/semantic.rs b/src/policy/semantic.rs index a6147faba..50b36bd42 100644 --- a/src/policy/semantic.rs +++ b/src/policy/semantic.rs @@ -619,28 +619,34 @@ impl Policy { /// /// Returns `None` if the policy is not satisfiable. pub fn minimum_n_keys(&self) -> Option { - match *self { - Policy::Unsatisfiable => None, - Policy::Trivial => Some(0), - Policy::Key(..) => Some(1), - Policy::After(..) - | Policy::Older(..) - | Policy::Sha256(..) - | Policy::Hash256(..) - | Policy::Ripemd160(..) - | Policy::Hash160(..) => Some(0), - Policy::Threshold(k, ref subs) => { - let mut sublens: Vec = - subs.iter().filter_map(|p| p.minimum_n_keys()).collect(); - if sublens.len() < k { - // Not enough branches are satisfiable - None - } else { - sublens.sort_unstable(); - Some(sublens[0..k].iter().cloned().sum::()) + use Policy::*; + + let mut minimum_n_keys = vec![]; + for data in Arc::new(self).post_order_iter() { + let minimum_n_keys_for_child_n = |n| minimum_n_keys[data.child_indices[n]]; + + let minimum_n_key = match data.node { + Unsatisfiable => None, + Trivial | After(..) | Older(..) | Sha256(..) | Hash256(..) | Ripemd160(..) + | Hash160(..) => Some(0), + Key(..) => Some(1), + Threshold(k, ref subs) => { + let mut sublens = (0..subs.len()) + .filter_map(minimum_n_keys_for_child_n) + .collect::>(); + if sublens.len() < *k { + // Not enough branches are satisfiable + None + } else { + sublens.sort_unstable(); + Some(sublens[0..*k].iter().cloned().sum::()) + } } - } + }; + minimum_n_keys.push(minimum_n_key); } + // Ok to unwrap because we know we processed at least one node. + minimum_n_keys.pop().unwrap() } }