@@ -40,6 +40,9 @@ use crate::miniscript::types::extra_props::TimelockInfo;
40
40
use crate :: prelude:: * ;
41
41
use crate :: { errstr, Error , ForEachKey , MiniscriptKey , Translator } ;
42
42
43
+ /// Maximum TapLeafs allowed in a compiled TapTree
44
+ const MAX_COMPILATION_LEAVES : usize = 10_000 ;
45
+
43
46
/// Concrete policy which corresponds directly to a Miniscript structure,
44
47
/// and whose disjunctions are annotated with satisfaction probabilities
45
48
/// to assist the compiler
@@ -276,6 +279,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
276
279
) ) ,
277
280
_ => {
278
281
let ( internal_key, policy) = self . clone ( ) . extract_key ( unspendable_key) ?;
282
+ policy. check_num_tapleaves ( ) ?;
279
283
let tree = Descriptor :: new_tr (
280
284
internal_key,
281
285
match policy {
@@ -507,6 +511,28 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
507
511
}
508
512
}
509
513
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
+
510
536
/// Check whether the policy contains duplicate public keys
511
537
pub fn check_duplicate_keys ( & self ) -> Result < ( ) , PolicyError > {
512
538
let pks = self . keys ( ) ;
0 commit comments