Skip to content

Commit edd15f3

Browse files
committed
tr: implement ForEachKey for Simplicity descriptors
Workaround because we cannot directly implement ForEachKey for simplicity::Policy<Pk>.
1 parent 24b5296 commit edd15f3

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

src/descriptor/tr.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,12 @@ impl<Pk: MiniscriptKey, Ext: Extension> ForEachKey<Pk> for Tr<Pk, Ext> {
711711
{
712712
let script_keys_res = self
713713
.iter_scripts()
714-
.all(|(_d, ms)| ms.as_miniscript().unwrap().for_each_key(&mut pred));
714+
.all(|(_d, script)| {
715+
match script {
716+
TapLeafScript::Miniscript(ms) => ms.for_each_key(&mut pred),
717+
TapLeafScript::Simplicity(sim) => crate::simplicity::for_each_key(sim, &mut pred),
718+
}
719+
});
715720
script_keys_res && pred(&self.internal_key)
716721
}
717722
}

src/simplicity.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,37 @@ impl_from_str!(
9090
}
9191
);
9292

93+
// We cannot implement ForEachKey for Policy<Pk> because it is not defined in this crate
94+
// We cannot use our wrapper because we don't own the Policy (we have a reference)
95+
// Implementing a wrapper of Cow<'a, Policy<Pk>> leads to lifetime issues
96+
// when implementing ForEachKey, because for_each_key() has its own lifetime 'a
97+
pub fn for_each_key<'a, Pk: MiniscriptKey, F: FnMut(&'a Pk) -> bool>(policy: &'a Policy<Pk>, mut pred: F) -> bool
98+
where
99+
Pk: 'a,
100+
{
101+
let mut stack = vec![policy];
102+
103+
while let Some(top) = stack.pop() {
104+
match top {
105+
Policy::Key(key) => {
106+
if !pred(key) {
107+
return false;
108+
}
109+
}
110+
Policy::And { left, right } | Policy::Or { left, right } => {
111+
stack.push(right);
112+
stack.push(left);
113+
}
114+
Policy::Threshold(_, sub_policies) => {
115+
stack.extend(sub_policies.iter());
116+
}
117+
_ => {}
118+
}
119+
}
120+
121+
true
122+
}
123+
93124
#[cfg(test)]
94125
mod tests {
95126
use secp256k1::XOnlyPublicKey;

0 commit comments

Comments
 (0)