Skip to content

Commit bfa00f0

Browse files
committed
semantic: Remove recursion in translate_pk
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::translate_pk`.
1 parent 188bfa5 commit bfa00f0

File tree

1 file changed

+23
-16
lines changed

1 file changed

+23
-16
lines changed

src/policy/semantic.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -128,23 +128,30 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
128128
T: Translator<Pk, Q, E>,
129129
Q: MiniscriptKey,
130130
{
131-
match *self {
132-
Policy::Unsatisfiable => Ok(Policy::Unsatisfiable),
133-
Policy::Trivial => Ok(Policy::Trivial),
134-
Policy::Key(ref pk) => t.pk(pk).map(Policy::Key),
135-
Policy::Sha256(ref h) => t.sha256(h).map(Policy::Sha256),
136-
Policy::Hash256(ref h) => t.hash256(h).map(Policy::Hash256),
137-
Policy::Ripemd160(ref h) => t.ripemd160(h).map(Policy::Ripemd160),
138-
Policy::Hash160(ref h) => t.hash160(h).map(Policy::Hash160),
139-
Policy::After(n) => Ok(Policy::After(n)),
140-
Policy::Older(n) => Ok(Policy::Older(n)),
141-
Policy::Threshold(k, ref subs) => {
142-
let new_subs: Result<Vec<Policy<Q>>, _> =
143-
subs.iter().map(|sub| sub._translate_pk(t)).collect();
144-
let new_subs = new_subs?.into_iter().map(|sub| Arc::new(sub)).collect();
145-
Ok(Policy::Threshold(k, new_subs))
146-
}
131+
use Policy::*;
132+
133+
let mut translated = vec![];
134+
for data in self.post_order_iter() {
135+
let child_n = |n| Arc::clone(&translated[data.child_indices[n]]);
136+
137+
let new_policy = match data.node {
138+
Unsatisfiable => Unsatisfiable,
139+
Trivial => Trivial,
140+
Key(ref pk) => t.pk(pk).map(Key)?,
141+
Sha256(ref h) => t.sha256(h).map(Sha256)?,
142+
Hash256(ref h) => t.hash256(h).map(Hash256)?,
143+
Ripemd160(ref h) => t.ripemd160(h).map(Ripemd160)?,
144+
Hash160(ref h) => t.hash160(h).map(Hash160)?,
145+
Older(ref n) => Older(*n),
146+
After(ref n) => After(*n),
147+
Threshold(ref k, ref subs) => Threshold(*k, (0..subs.len()).map(child_n).collect()),
148+
};
149+
translated.push(Arc::new(new_policy));
147150
}
151+
// Unwrap is ok because we know we processed at least one node.
152+
let root_node = translated.pop().unwrap();
153+
// Unwrap is ok because we know `root_node` is the only strong reference.
154+
Ok(Arc::try_unwrap(root_node).unwrap())
148155
}
149156

150157
/// Computes whether the current policy entails the second one.

0 commit comments

Comments
 (0)