Skip to content

Commit 7593458

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

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

src/miniscript/limits.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,6 @@ pub const MAX_BLOCK_WEIGHT: usize = 4000000;
5050
/// Maximum pubkeys as arguments to CHECKMULTISIG
5151
// https://github.com/bitcoin/bitcoin/blob/6acda4b00b3fc1bfac02f5de590e1a5386cbc779/src/script/script.h#L30
5252
pub const MAX_PUBKEYS_PER_MULTISIG: usize = 20;
53+
54+
/// Maximum TapLeafs allowed in a compiled TapTree
55+
pub(crate) const MAX_COMPILATION_LEAVES: usize = 10_000;

src/policy/concrete.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use bitcoin::hashes::{hash160, ripemd160};
2424
#[cfg(feature = "compiler")]
2525
use {
2626
crate::descriptor::TapTree,
27+
crate::miniscript::limits::MAX_COMPILATION_LEAVES,
2728
crate::miniscript::ScriptContext,
2829
crate::policy::compiler::CompilerError,
2930
crate::policy::compiler::OrdF64,
@@ -278,6 +279,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
278279
)),
279280
_ => {
280281
let (internal_key, policy) = self.clone().extract_key(unspendable_key)?;
282+
policy.check_num_tapleaves()?;
281283
let tree = Descriptor::new_tr(
282284
internal_key,
283285
match policy {
@@ -501,6 +503,28 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
501503
}
502504
}
503505

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

0 commit comments

Comments
 (0)