@@ -24,6 +24,7 @@ use bitcoin::hashes::{hash160, ripemd160};
24
24
#[ cfg( feature = "compiler" ) ]
25
25
use {
26
26
crate :: descriptor:: TapTree ,
27
+ crate :: miniscript:: limits:: MAX_COMPILATION_LEAVES ,
27
28
crate :: miniscript:: ScriptContext ,
28
29
crate :: policy:: compiler:: CompilerError ,
29
30
crate :: policy:: compiler:: OrdF64 ,
@@ -278,6 +279,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
278
279
) ) ,
279
280
_ => {
280
281
let ( internal_key, policy) = self . clone ( ) . extract_key ( unspendable_key) ?;
282
+ policy. check_num_tapleaves ( ) ?;
281
283
let tree = Descriptor :: new_tr (
282
284
internal_key,
283
285
match policy {
@@ -501,6 +503,28 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
501
503
}
502
504
}
503
505
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
+
504
528
/// Check whether the policy contains duplicate public keys
505
529
pub fn check_duplicate_keys ( & self ) -> Result < ( ) , PolicyError > {
506
530
let pks = self . keys ( ) ;
0 commit comments