Skip to content

Commit a2f39e9

Browse files
Limit the number of tap-leaves output by the tr_compiler
1 parent 9fd9aa4 commit a2f39e9

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

src/policy/concrete.rs

+27
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ use crate::miniscript::types::extra_props::TimelockInfo;
4040
use crate::prelude::*;
4141
use crate::{errstr, Error, ForEachKey, MiniscriptKey, Translator};
4242

43+
/// Maximum TapLeafs allowed in a compiled TapTree
44+
#[cfg(feature = "compiler")]
45+
const MAX_COMPILATION_LEAVES: usize = 1024;
46+
4347
/// Concrete policy which corresponds directly to a Miniscript structure,
4448
/// and whose disjunctions are annotated with satisfaction probabilities
4549
/// to assist the compiler
@@ -276,6 +280,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
276280
)),
277281
_ => {
278282
let (internal_key, policy) = self.clone().extract_key(unspendable_key)?;
283+
policy.check_num_tapleaves()?;
279284
let tree = Descriptor::new_tr(
280285
internal_key,
281286
match policy {
@@ -507,6 +512,28 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
507512
}
508513
}
509514

515+
/// Get the number of [TapLeaf][`TapTree::Leaf`] considering exhaustive root-level [OR][`Policy::Or`]
516+
/// and [Thresh][`Policy::Threshold`] disjunctions for the TapTree.
517+
#[cfg(feature = "compiler")]
518+
fn num_tap_leaves(&self) -> usize {
519+
match self {
520+
Policy::Or(subs) => subs.iter().map(|(_prob, pol)| pol.num_tap_leaves()).sum(),
521+
Policy::Threshold(k, subs) if *k == 1 => {
522+
subs.iter().map(|pol| pol.num_tap_leaves()).sum()
523+
}
524+
_ => 1,
525+
}
526+
}
527+
528+
/// Check on the number of TapLeaves
529+
#[cfg(feature = "compiler")]
530+
fn check_num_tapleaves(&self) -> Result<(), Error> {
531+
if self.num_tap_leaves() > MAX_COMPILATION_LEAVES {
532+
return Err(errstr("Too many Tapleaves"));
533+
}
534+
Ok(())
535+
}
536+
510537
/// Check whether the policy contains duplicate public keys
511538
pub fn check_duplicate_keys(&self) -> Result<(), PolicyError> {
512539
let pks = self.keys();

0 commit comments

Comments
 (0)