Skip to content

Commit 4ce20d9

Browse files
Limit the number of tap-leaves output by the tr_compiler
1 parent e2e8e77 commit 4ce20d9

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

src/policy/concrete.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ use crate::miniscript::types::extra_props::TimelockInfo;
4242
use crate::prelude::*;
4343
use crate::{errstr, Error, ForEachKey, MiniscriptKey, Translator};
4444

45+
46+
/// Maximum TapLeafs allowed in a compiled TapTree
47+
const MAX_COMPILATION_LEAVES: usize = 10_000;
4548
/// Concrete policy which corresponds directly to a Miniscript structure,
4649
/// and whose disjunctions are annotated with satisfaction probabilities
4750
/// to assist the compiler
@@ -278,6 +281,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
278281
)),
279282
_ => {
280283
let (internal_key, policy) = self.clone().extract_key(unspendable_key)?;
284+
policy.check_num_tapleaves()?;
281285
let tree = Descriptor::new_tr(
282286
internal_key,
283287
match policy {
@@ -501,6 +505,28 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
501505
}
502506
}
503507

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

0 commit comments

Comments
 (0)