Skip to content

Commit fb4d1bd

Browse files
Limit the number of tap-leaves output by the tr_compiler
1 parent c7c39f1 commit fb4d1bd

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
@@ -40,6 +40,9 @@ 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+
const MAX_COMPILATION_LEAVES: usize = 10_000;
45+
4346
/// Concrete policy which corresponds directly to a Miniscript structure,
4447
/// and whose disjunctions are annotated with satisfaction probabilities
4548
/// to assist the compiler
@@ -276,6 +279,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
276279
)),
277280
_ => {
278281
let (internal_key, policy) = self.clone().extract_key(unspendable_key)?;
282+
policy.check_num_tapleaves()?;
279283
let tree = Descriptor::new_tr(
280284
internal_key,
281285
match policy {
@@ -507,6 +511,28 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
507511
}
508512
}
509513

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

0 commit comments

Comments
 (0)