Skip to content

Commit 625077e

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

File tree

1 file changed

+29
-1
lines changed

1 file changed

+29
-1
lines changed

src/policy/concrete.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
278278
)),
279279
_ => {
280280
let (internal_key, policy) = self.clone().extract_key(unspendable_key)?;
281+
policy.check_tapleaf()?;
281282
let tree = Descriptor::new_tr(
282283
internal_key,
283284
match policy {
@@ -501,6 +502,26 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
501502
}
502503
}
503504

505+
/// Get the number of [TapLeaf][`TapTree::Leaf`] considering exhaustive root-level [OR][`Policy::Or`]
506+
/// and [Thresh][`Policy::Threshold`] disjunctions for the TapTree.
507+
#[cfg(feature = "compiler")]
508+
fn num_tap_leaves(&self) -> usize {
509+
match self {
510+
Policy::Or(subs) => subs.iter().map(|(_prob, pol)| pol.num_tap_leaves()).sum(),
511+
Policy::Threshold(k, subs) if *k == 1 => combination(subs.len(), *k),
512+
_ => 1,
513+
}
514+
}
515+
516+
/// Check on the number of TapLeaves
517+
#[cfg(feature = "compiler")]
518+
fn check_tapleaf(&self) -> Result<(), Error> {
519+
if self.num_tap_leaves() > 100_000 {
520+
return Err(errstr("Too many Tapleaves"));
521+
}
522+
Ok(())
523+
}
524+
504525
/// Check whether the policy contains duplicate public keys
505526
pub fn check_duplicate_keys(&self) -> Result<(), PolicyError> {
506527
let pks = self.keys();
@@ -918,5 +939,12 @@ fn with_huffman_tree<Pk: MiniscriptKey>(
918939
.pop()
919940
.expect("huffman tree algorithm is broken")
920941
.1;
921-
Ok(node)
942+
943+
#[cfg(feature = "compiler")]
944+
fn combination(n: usize, k: usize) -> usize {
945+
if k == 0 {
946+
1
947+
} else {
948+
n * combination(n - 1, k - 1) / k
949+
}
922950
}

0 commit comments

Comments
 (0)