@@ -42,6 +42,9 @@ use crate::miniscript::types::extra_props::TimelockInfo;
42
42
use crate :: prelude:: * ;
43
43
use crate :: { errstr, Error , ForEachKey , MiniscriptKey , Translator } ;
44
44
45
+
46
+ /// Maximum TapLeafs allowed in a compiled TapTree
47
+ const MAX_COMPILATION_LEAVES : usize = 10_000 ;
45
48
/// Concrete policy which corresponds directly to a Miniscript structure,
46
49
/// and whose disjunctions are annotated with satisfaction probabilities
47
50
/// to assist the compiler
@@ -278,6 +281,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
278
281
) ) ,
279
282
_ => {
280
283
let ( internal_key, policy) = self . clone ( ) . extract_key ( unspendable_key) ?;
284
+ policy. check_num_tapleaves ( ) ?;
281
285
let tree = Descriptor :: new_tr (
282
286
internal_key,
283
287
match policy {
@@ -501,6 +505,28 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
501
505
}
502
506
}
503
507
508
+ /// Get the number of [TapLeaf][`TapTree::Leaf`] considering exhaustive root-level [OR][`Policy::Or`]
509
+ /// and [Thresh][`Policy::Threshold`] disjunctions for the TapTree.
510
+ #[ cfg( feature = "compiler" ) ]
511
+ fn num_tap_leaves ( & self ) -> usize {
512
+ match self {
513
+ Policy :: Or ( subs) => subs. iter ( ) . map ( |( _prob, pol) | pol. num_tap_leaves ( ) ) . sum ( ) ,
514
+ Policy :: Threshold ( k, subs) if * k == 1 => {
515
+ subs. iter ( ) . map ( |pol| pol. num_tap_leaves ( ) ) . sum ( )
516
+ }
517
+ _ => 1 ,
518
+ }
519
+ }
520
+
521
+ /// Check on the number of TapLeaves
522
+ #[ cfg( feature = "compiler" ) ]
523
+ fn check_num_tapleaves ( & self ) -> Result < ( ) , Error > {
524
+ if self . num_tap_leaves ( ) > MAX_COMPILATION_LEAVES {
525
+ return Err ( errstr ( "Too many Tapleaves" ) ) ;
526
+ }
527
+ Ok ( ( ) )
528
+ }
529
+
504
530
/// Check whether the policy contains duplicate public keys
505
531
pub fn check_duplicate_keys ( & self ) -> Result < ( ) , PolicyError > {
506
532
let pks = self . keys ( ) ;
0 commit comments