Skip to content

Commit 7d5374f

Browse files
Limit the number of tap-leaves output by the tr_compiler
1 parent b6daa97 commit 7d5374f

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

src/policy/concrete.rs

Lines changed: 27 additions & 0 deletions
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
@@ -293,6 +297,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
293297
)),
294298
_ => {
295299
let (internal_key, policy) = self.clone().extract_key(unspendable_key)?;
300+
policy.check_num_tapleaves()?;
296301
let tree = Descriptor::new_tr(
297302
internal_key,
298303
match policy {
@@ -524,6 +529,28 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
524529
}
525530
}
526531

532+
/// Get the number of [TapLeaf][`TapTree::Leaf`] considering exhaustive root-level [OR][`Policy::Or`]
533+
/// and [Thresh][`Policy::Threshold`] disjunctions for the TapTree.
534+
#[cfg(feature = "compiler")]
535+
fn num_tap_leaves(&self) -> usize {
536+
match self {
537+
Policy::Or(subs) => subs.iter().map(|(_prob, pol)| pol.num_tap_leaves()).sum(),
538+
Policy::Threshold(k, subs) if *k == 1 => {
539+
subs.iter().map(|pol| pol.num_tap_leaves()).sum()
540+
}
541+
_ => 1,
542+
}
543+
}
544+
545+
/// Check on the number of TapLeaves
546+
#[cfg(feature = "compiler")]
547+
fn check_num_tapleaves(&self) -> Result<(), Error> {
548+
if self.num_tap_leaves() > MAX_COMPILATION_LEAVES {
549+
return Err(errstr("Too many Tapleaves"));
550+
}
551+
Ok(())
552+
}
553+
527554
/// Check whether the policy contains duplicate public keys
528555
pub fn check_duplicate_keys(&self) -> Result<(), PolicyError> {
529556
let pks = self.keys();

0 commit comments

Comments
 (0)