Skip to content

Commit 61a89a2

Browse files
committed
policy: make Semantic::from_tree non-recursive
1 parent 8a78025 commit 61a89a2

File tree

1 file changed

+92
-67
lines changed

1 file changed

+92
-67
lines changed

src/policy/semantic.rs

Lines changed: 92 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -284,79 +284,104 @@ impl<Pk: FromStrKey> str::FromStr for Policy<Pk> {
284284
serde_string_impl_pk!(Policy, "a miniscript semantic policy");
285285

286286
impl<Pk: FromStrKey> expression::FromTree for Policy<Pk> {
287-
fn from_tree(top: expression::TreeIterItem) -> Result<Policy<Pk>, Error> {
288-
match top.name() {
289-
"UNSATISFIABLE" => {
290-
top.verify_n_children("UNSATISFIABLE", 0..=0)
291-
.map_err(From::from)
292-
.map_err(Error::Parse)?;
293-
Ok(Policy::Unsatisfiable)
294-
}
295-
"TRIVIAL" => {
296-
top.verify_n_children("TRIVIAL", 0..=0)
297-
.map_err(From::from)
298-
.map_err(Error::Parse)?;
299-
Ok(Policy::Trivial)
300-
}
301-
"pk" => top
302-
.verify_terminal_parent("pk", "public key")
303-
.map(Policy::Key)
304-
.map_err(Error::Parse),
305-
"after" => top.verify_after().map_err(Error::Parse).map(Policy::After),
306-
"older" => top.verify_older().map_err(Error::Parse).map(Policy::Older),
307-
"sha256" => top
308-
.verify_terminal_parent("sha256", "hash")
309-
.map(Policy::Sha256)
310-
.map_err(Error::Parse),
311-
"hash256" => top
312-
.verify_terminal_parent("hash256", "hash")
313-
.map(Policy::Hash256)
314-
.map_err(Error::Parse),
315-
"ripemd160" => top
316-
.verify_terminal_parent("ripemd160", "hash")
317-
.map(Policy::Ripemd160)
318-
.map_err(Error::Parse),
319-
"hash160" => top
320-
.verify_terminal_parent("hash160", "hash")
321-
.map(Policy::Hash160)
322-
.map_err(Error::Parse),
323-
"and" => {
324-
top.verify_n_children("and", 2..)
325-
.map_err(From::from)
326-
.map_err(Error::Parse)?;
327-
let subs = top
328-
.children()
329-
.map(|arg| Self::from_tree(arg).map(Arc::new))
330-
.collect::<Result<Vec<_>, Error>>()?;
331-
Ok(Policy::Thresh(Threshold::new(subs.len(), subs).map_err(Error::Threshold)?))
332-
}
333-
"or" => {
334-
top.verify_n_children("or", 2..)
335-
.map_err(From::from)
336-
.map_err(Error::Parse)?;
337-
let subs = top
338-
.children()
339-
.map(|arg| Self::from_tree(arg).map(Arc::new))
340-
.collect::<Result<Vec<_>, Error>>()?;
341-
Ok(Policy::Thresh(Threshold::new(1, subs).map_err(Error::Threshold)?))
287+
fn from_tree(root: expression::TreeIterItem) -> Result<Policy<Pk>, Error> {
288+
root.verify_no_curly_braces()
289+
.map_err(From::from)
290+
.map_err(Error::Parse)?;
291+
292+
let mut stack = Vec::with_capacity(128);
293+
for node in root.pre_order_iter().rev() {
294+
// Before doing anything else, check if this is the inner value of a terminal.
295+
// In that case, just skip the node. Conveniently, there are no combinators
296+
// in policy that have a single child that these might be confused with (we
297+
// require and, or and thresholds to all have >1 child).
298+
if let Some(parent) = node.parent() {
299+
if parent.n_children() == 1 {
300+
continue;
301+
}
302+
if node.is_first_child() && parent.name() == "thresh" {
303+
continue;
304+
}
342305
}
343-
"thresh" => {
344-
let thresh = top.verify_threshold(|sub| Self::from_tree(sub).map(Arc::new))?;
345306

346-
// thresh(1) and thresh(n) are disallowed in semantic policies
347-
if thresh.is_or() {
348-
return Err(Error::ParseThreshold(crate::ParseThresholdError::IllegalOr));
307+
let new = match node.name() {
308+
"UNSATISFIABLE" => {
309+
node.verify_n_children("UNSATISFIABLE", 0..=0)
310+
.map_err(From::from)
311+
.map_err(Error::Parse)?;
312+
Ok(Policy::Unsatisfiable)
313+
}
314+
"TRIVIAL" => {
315+
node.verify_n_children("TRIVIAL", 0..=0)
316+
.map_err(From::from)
317+
.map_err(Error::Parse)?;
318+
Ok(Policy::Trivial)
349319
}
350-
if thresh.is_and() {
351-
return Err(Error::ParseThreshold(crate::ParseThresholdError::IllegalAnd));
320+
"pk" => node
321+
.verify_terminal_parent("pk", "public key")
322+
.map(Policy::Key)
323+
.map_err(Error::Parse),
324+
"after" => node.verify_after().map_err(Error::Parse).map(Policy::After),
325+
"older" => node.verify_older().map_err(Error::Parse).map(Policy::Older),
326+
"sha256" => node
327+
.verify_terminal_parent("sha256", "hash")
328+
.map(Policy::Sha256)
329+
.map_err(Error::Parse),
330+
"hash256" => node
331+
.verify_terminal_parent("hash256", "hash")
332+
.map(Policy::Hash256)
333+
.map_err(Error::Parse),
334+
"ripemd160" => node
335+
.verify_terminal_parent("ripemd160", "hash")
336+
.map(Policy::Ripemd160)
337+
.map_err(Error::Parse),
338+
"hash160" => node
339+
.verify_terminal_parent("hash160", "hash")
340+
.map(Policy::Hash160)
341+
.map_err(Error::Parse),
342+
"and" => {
343+
node.verify_n_children("and", 2..)
344+
.map_err(From::from)
345+
.map_err(Error::Parse)?;
346+
347+
let child_iter = (0..node.n_children()).map(|_| stack.pop().unwrap());
348+
let thresh = Threshold::from_iter(node.n_children(), child_iter)
349+
.map_err(Error::Threshold)?;
350+
Ok(Policy::Thresh(thresh))
352351
}
352+
"or" => {
353+
node.verify_n_children("or", 2..)
354+
.map_err(From::from)
355+
.map_err(Error::Parse)?;
356+
let child_iter = (0..node.n_children()).map(|_| stack.pop().unwrap());
357+
let thresh = Threshold::from_iter(1, child_iter).map_err(Error::Threshold)?;
358+
Ok(Policy::Thresh(thresh))
359+
}
360+
"thresh" => {
361+
let thresh = node.verify_threshold(|_| Ok::<_, Error>(stack.pop().unwrap()))?;
353362

354-
Ok(Policy::Thresh(thresh))
355-
}
356-
x => Err(Error::Parse(crate::ParseError::Tree(crate::ParseTreeError::UnknownName {
357-
name: x.to_owned(),
358-
}))),
363+
// thresh(1) and thresh(n) are disallowed in semantic policies
364+
if thresh.is_or() {
365+
return Err(Error::ParseThreshold(crate::ParseThresholdError::IllegalOr));
366+
}
367+
if thresh.is_and() {
368+
return Err(Error::ParseThreshold(crate::ParseThresholdError::IllegalAnd));
369+
}
370+
371+
Ok(Policy::Thresh(thresh))
372+
}
373+
x => {
374+
Err(Error::Parse(crate::ParseError::Tree(crate::ParseTreeError::UnknownName {
375+
name: x.to_owned(),
376+
})))
377+
}
378+
}?;
379+
380+
stack.push(Arc::new(new));
359381
}
382+
383+
assert_eq!(stack.len(), 1);
384+
Ok(Arc::try_unwrap(stack.pop().unwrap()).unwrap())
360385
}
361386
}
362387

0 commit comments

Comments
 (0)