diff --git a/Cargo.toml b/Cargo.toml index 6e63c15eb..018fb2c5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "miniscript" -version = "7.0.1" +version = "7.0.2" authors = ["Andrew Poelstra , Sanket Kanjalkar "] repository = "https://github.com/apoelstra/miniscript" description = "Miniscript: a subset of Bitcoin Script designed for analysis" diff --git a/src/policy/concrete.rs b/src/policy/concrete.rs index 4fe42d11a..94fd85301 100644 --- a/src/policy/concrete.rs +++ b/src/policy/concrete.rs @@ -146,6 +146,12 @@ impl ForEachKey for Policy { Pk: 'a, Pk::Hash: 'a, { + self.real_for_each_key(&mut pred) + } +} + +impl Policy { + fn real_for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, pred: &mut F) -> bool { match *self { Policy::Unsatisfiable | Policy::Trivial => true, Policy::Key(ref pk) => pred(ForEach::Key(pk)), @@ -156,9 +162,9 @@ impl ForEachKey for Policy { | Policy::After(..) | Policy::Older(..) => true, Policy::Threshold(_, ref subs) | Policy::And(ref subs) => { - subs.iter().all(|sub| sub.for_each_key(&mut pred)) + subs.iter().all(|sub| sub.real_for_each_key(&mut *pred)) } - Policy::Or(ref subs) => subs.iter().all(|(_, sub)| sub.for_each_key(&mut pred)), + Policy::Or(ref subs) => subs.iter().all(|(_, sub)| sub.real_for_each_key(&mut *pred)), } } } @@ -654,3 +660,19 @@ where Policy::from_tree_prob(top, false).map(|(_, result)| result) } } + +#[cfg(test)] +mod tests { + use super::*; + use std::str::FromStr; + + #[test] + fn for_each_key() { + let liquid_pol = Policy::::from_str( + "or(and(older(4096),thresh(2,pk(A),pk(B),pk(C))),thresh(11,pk(F1),pk(F2),pk(F3),pk(F4),pk(F5),pk(F6),pk(F7),pk(F8),pk(F9),pk(F10),pk(F11),pk(F12),pk(F13),pk(F14)))").unwrap(); + let mut count = 0; + assert!(liquid_pol.for_each_key(|_| { count +=1; true })); + assert_eq!(count, 17); + } +} + diff --git a/src/policy/semantic.rs b/src/policy/semantic.rs index 5f8aa0eb8..be140b9a8 100644 --- a/src/policy/semantic.rs +++ b/src/policy/semantic.rs @@ -59,6 +59,16 @@ pub enum Policy { impl ForEachKey for Policy { fn for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, mut pred: F) -> bool + where + Pk: 'a, + Pk::Hash: 'a, + { + self.real_for_each_key(&mut pred) + } +} + +impl Policy { + fn real_for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, pred: &mut F) -> bool where Pk: 'a, Pk::Hash: 'a, @@ -72,12 +82,10 @@ impl ForEachKey for Policy { | Policy::Hash160(..) | Policy::After(..) | Policy::Older(..) => true, - Policy::Threshold(_, ref subs) => subs.iter().all(|sub| sub.for_each_key(&mut pred)), + Policy::Threshold(_, ref subs) => subs.iter().all(|sub| sub.real_for_each_key(&mut *pred)), } } -} -impl Policy { /// Convert a policy using one kind of public key to another /// type of public key /// @@ -855,4 +863,13 @@ mod tests { assert!(auth_alice.entails(htlc_pol.clone()).unwrap()); assert!(htlc_pol.entails(control_alice).unwrap()); } + + #[test] + fn for_each_key() { + let liquid_pol = StringPolicy::from_str( + "or(and(older(4096),thresh(2,pkh(A),pkh(B),pkh(C))),thresh(11,pkh(F1),pkh(F2),pkh(F3),pkh(F4),pkh(F5),pkh(F6),pkh(F7),pkh(F8),pkh(F9),pkh(F10),pkh(F11),pkh(F12),pkh(F13),pkh(F14)))").unwrap(); + let mut count = 0; + assert!(liquid_pol.for_each_key(|_| { count +=1; true })); + assert_eq!(count, 17); + } }