55//! Optimizing compiler from concrete policies to Miniscript
66//!
77
8- #![ allow( dead_code) ] // will be removed in next commit
9- #![ allow( unused_variables) ] // will be removed in next commit
10-
118use core:: num:: NonZeroU32 ;
129use core:: { f64, fmt, mem} ;
1310#[ cfg( feature = "std" ) ]
@@ -374,10 +371,6 @@ impl CompilationKey {
374371
375372#[ derive( Copy , Clone , Debug ) ]
376373struct CompilerExtData {
377- /// If this node is the direct child of a disjunction, this field must
378- /// have the probability of its branch being taken. Otherwise it is ignored.
379- /// All functions initialize it to `None`.
380- branch_prob : Option < f64 > ,
381374 /// The number of bytes needed to satisfy the fragment in segwit format
382375 /// (total length of all witness pushes, plus their own length prefixes)
383376 sat_cost : f64 ,
@@ -388,13 +381,12 @@ struct CompilerExtData {
388381}
389382
390383impl CompilerExtData {
391- const TRUE : Self = Self { branch_prob : None , sat_cost : 0.0 , dissat_cost : None } ;
384+ const TRUE : Self = Self { sat_cost : 0.0 , dissat_cost : None } ;
392385
393- const FALSE : Self = Self { branch_prob : None , sat_cost : f64:: MAX , dissat_cost : Some ( 0.0 ) } ;
386+ const FALSE : Self = Self { sat_cost : f64:: MAX , dissat_cost : Some ( 0.0 ) } ;
394387
395388 fn pk_k < Ctx : ScriptContext > ( ) -> Self {
396389 Self {
397- branch_prob : None ,
398390 sat_cost : match Ctx :: sig_type ( ) {
399391 SigType :: Ecdsa => 73.0 ,
400392 SigType :: Schnorr => 1.0 /* <var_int> */ + 64.0 /* sig */ + 1.0 , /* <sighash_type> */
@@ -405,7 +397,6 @@ impl CompilerExtData {
405397
406398 fn pk_h < Ctx : ScriptContext > ( ) -> Self {
407399 Self {
408- branch_prob : None ,
409400 sat_cost : match Ctx :: sig_type ( ) {
410401 SigType :: Ecdsa => 73.0 + 34.0 ,
411402 SigType :: Schnorr => 66.0 + 33.0 ,
@@ -420,68 +411,46 @@ impl CompilerExtData {
420411 }
421412
422413 fn multi ( k : usize ) -> Self {
423- Self {
424- branch_prob : None ,
425- sat_cost : 1.0 + 73.0 * k as f64 ,
426- dissat_cost : Some ( 1.0 * ( k + 1 ) as f64 ) ,
427- }
414+ Self { sat_cost : 1.0 + 73.0 * k as f64 , dissat_cost : Some ( 1.0 * ( k + 1 ) as f64 ) }
428415 }
429416
430417 fn multi_a ( k : usize , n : usize ) -> Self {
431418 Self {
432- branch_prob : None ,
433419 sat_cost : 66.0 * k as f64 + ( n - k) as f64 ,
434420 dissat_cost : Some ( n as f64 ) , /* <w_n> ... <w_1> := 0x00 ... 0x00 (n times) */
435421 }
436422 }
437423
438- fn hash ( ) -> Self { Self { branch_prob : None , sat_cost : 33.0 , dissat_cost : Some ( 33.0 ) } }
424+ fn hash ( ) -> Self { Self { sat_cost : 33.0 , dissat_cost : Some ( 33.0 ) } }
439425
440- fn time ( ) -> Self { Self { branch_prob : None , sat_cost : 0.0 , dissat_cost : None } }
426+ fn time ( ) -> Self { Self { sat_cost : 0.0 , dissat_cost : None } }
441427
442- fn cast_alt ( self ) -> Self {
443- Self { branch_prob : None , sat_cost : self . sat_cost , dissat_cost : self . dissat_cost }
444- }
428+ fn cast_alt ( self ) -> Self { Self { sat_cost : self . sat_cost , dissat_cost : self . dissat_cost } }
445429
446- fn cast_swap ( self ) -> Self {
447- Self { branch_prob : None , sat_cost : self . sat_cost , dissat_cost : self . dissat_cost }
448- }
430+ fn cast_swap ( self ) -> Self { Self { sat_cost : self . sat_cost , dissat_cost : self . dissat_cost } }
449431
450- fn cast_check ( self ) -> Self {
451- Self { branch_prob : None , sat_cost : self . sat_cost , dissat_cost : self . dissat_cost }
452- }
432+ fn cast_check ( self ) -> Self { Self { sat_cost : self . sat_cost , dissat_cost : self . dissat_cost } }
453433
454- fn cast_dupif ( self ) -> Self {
455- Self { branch_prob : None , sat_cost : 2.0 + self . sat_cost , dissat_cost : Some ( 1.0 ) }
456- }
434+ fn cast_dupif ( self ) -> Self { Self { sat_cost : 2.0 + self . sat_cost , dissat_cost : Some ( 1.0 ) } }
457435
458- fn cast_verify ( self ) -> Self {
459- Self { branch_prob : None , sat_cost : self . sat_cost , dissat_cost : None }
460- }
436+ fn cast_verify ( self ) -> Self { Self { sat_cost : self . sat_cost , dissat_cost : None } }
461437
462- fn cast_nonzero ( self ) -> Self {
463- Self { branch_prob : None , sat_cost : self . sat_cost , dissat_cost : Some ( 1.0 ) }
464- }
438+ fn cast_nonzero ( self ) -> Self { Self { sat_cost : self . sat_cost , dissat_cost : Some ( 1.0 ) } }
465439
466440 fn cast_zeronotequal ( self ) -> Self {
467- Self { branch_prob : None , sat_cost : self . sat_cost , dissat_cost : self . dissat_cost }
441+ Self { sat_cost : self . sat_cost , dissat_cost : self . dissat_cost }
468442 }
469443
470- fn cast_true ( self ) -> Self {
471- Self { branch_prob : None , sat_cost : self . sat_cost , dissat_cost : None }
472- }
444+ fn cast_true ( self ) -> Self { Self { sat_cost : self . sat_cost , dissat_cost : None } }
473445
474446 fn cast_unlikely ( self ) -> Self {
475- Self { branch_prob : None , sat_cost : 2.0 + self . sat_cost , dissat_cost : Some ( 1.0 ) }
447+ Self { sat_cost : 2.0 + self . sat_cost , dissat_cost : Some ( 1.0 ) }
476448 }
477449
478- fn cast_likely ( self ) -> Self {
479- Self { branch_prob : None , sat_cost : 1.0 + self . sat_cost , dissat_cost : Some ( 2.0 ) }
480- }
450+ fn cast_likely ( self ) -> Self { Self { sat_cost : 1.0 + self . sat_cost , dissat_cost : Some ( 2.0 ) } }
481451
482452 fn and_b ( left : Self , right : Self ) -> Self {
483453 Self {
484- branch_prob : None ,
485454 sat_cost : left. sat_cost + right. sat_cost ,
486455 dissat_cost : match ( left. dissat_cost , right. dissat_cost ) {
487456 ( Some ( l) , Some ( r) ) => Some ( l + r) ,
@@ -491,12 +460,11 @@ impl CompilerExtData {
491460 }
492461
493462 fn and_v ( left : Self , right : Self ) -> Self {
494- Self { branch_prob : None , sat_cost : left. sat_cost + right. sat_cost , dissat_cost : None }
463+ Self { sat_cost : left. sat_cost + right. sat_cost , dissat_cost : None }
495464 }
496465
497466 fn or_b ( l : Self , r : Self , lprob : f64 , rprob : f64 ) -> Self {
498467 Self {
499- branch_prob : None ,
500468 sat_cost : lprob * ( l. sat_cost + r. dissat_cost . unwrap ( ) )
501469 + rprob * ( r. sat_cost + l. dissat_cost . unwrap ( ) ) ,
502470 dissat_cost : Some ( l. dissat_cost . unwrap ( ) + r. dissat_cost . unwrap ( ) ) ,
@@ -505,15 +473,13 @@ impl CompilerExtData {
505473
506474 fn or_d ( l : Self , r : Self , lprob : f64 , rprob : f64 ) -> Self {
507475 Self {
508- branch_prob : None ,
509476 sat_cost : lprob * l. sat_cost + rprob * ( r. sat_cost + l. dissat_cost . unwrap ( ) ) ,
510477 dissat_cost : r. dissat_cost . map ( |rd| l. dissat_cost . unwrap ( ) + rd) ,
511478 }
512479 }
513480
514481 fn or_c ( l : Self , r : Self , lprob : f64 , rprob : f64 ) -> Self {
515482 Self {
516- branch_prob : None ,
517483 sat_cost : lprob * l. sat_cost + rprob * ( r. sat_cost + l. dissat_cost . unwrap ( ) ) ,
518484 dissat_cost : None ,
519485 }
@@ -522,7 +488,6 @@ impl CompilerExtData {
522488 #[ allow( clippy:: manual_map) ] // Complex if/let is better as is.
523489 fn or_i ( l : Self , r : Self , lprob : f64 , rprob : f64 ) -> Self {
524490 Self {
525- branch_prob : None ,
526491 sat_cost : lprob * ( 2.0 + l. sat_cost ) + rprob * ( 1.0 + r. sat_cost ) ,
527492 dissat_cost : if let ( Some ( ldis) , Some ( rdis) ) = ( l. dissat_cost , r. dissat_cost ) {
528493 if ( 2.0 + ldis) > ( 1.0 + rdis) {
@@ -545,7 +510,6 @@ impl CompilerExtData {
545510 . dissat_cost
546511 . expect ( "BUG: and_or first arg(a) must be dissatisfiable" ) ;
547512 Self {
548- branch_prob : None ,
549513 sat_cost : lprob * ( a. sat_cost + b. sat_cost ) + rprob * ( adis + c. sat_cost ) ,
550514 dissat_cost : c. dissat_cost . map ( |cdis| adis + cdis) ,
551515 }
@@ -564,39 +528,12 @@ impl CompilerExtData {
564528 dissat_cost += sub. dissat_cost . unwrap ( ) ;
565529 }
566530 Self {
567- branch_prob : None ,
568531 sat_cost : sat_cost * k_over_n + dissat_cost * ( 1.0 - k_over_n) ,
569532 dissat_cost : Some ( dissat_cost) ,
570533 }
571534 }
572535}
573536
574- impl CompilerExtData {
575- /// Compute the type of a fragment, given a function to look up
576- /// the types of its children.
577- fn type_check_with_child < Pk , Ctx , C > ( fragment : & Terminal < Pk , Ctx > , child : C ) -> Self
578- where
579- C : Fn ( usize ) -> Self ,
580- Pk : MiniscriptKey ,
581- Ctx : ScriptContext ,
582- {
583- let get_child = |_sub, n| child ( n) ;
584- Self :: type_check_common ( fragment, get_child)
585- }
586-
587- /// Compute the type of a fragment, given a function to look up
588- /// the types of its children, if available and relevant for the
589- /// given fragment
590- fn type_check_common < ' a , Pk , Ctx , C > ( fragment : & ' a Terminal < Pk , Ctx > , get_child : C ) -> Self
591- where
592- C : Fn ( & ' a Terminal < Pk , Ctx > , usize ) -> Self ,
593- Pk : MiniscriptKey ,
594- Ctx : ScriptContext ,
595- {
596- unreachable ! ( )
597- }
598- }
599-
600537/// Miniscript AST fragment with additional data needed by the compiler
601538#[ derive( Clone , Debug ) ]
602539struct AstElemExt < Pk : MiniscriptKey , Ctx : ScriptContext > {
@@ -816,24 +753,6 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> AstElemExt<Pk, Ctx> {
816753 ) ,
817754 } )
818755 }
819-
820- fn ternary ( ast : Terminal < Pk , Ctx > , a : & Self , b : & Self , c : & Self ) -> Result < Self , types:: Error > {
821- let lookup_ext = |n| match n {
822- 0 => a. comp_ext_data ,
823- 1 => b. comp_ext_data ,
824- 2 => c. comp_ext_data ,
825- _ => unreachable ! ( ) ,
826- } ;
827- //Types and ExtData are already cached and stored in children. So, we can
828- //type_check without cache. For Compiler extra data, we supply a cache.
829- let ty = types:: Type :: type_check ( & ast) ?;
830- let ext = types:: ExtData :: type_check ( & ast) ;
831- let comp_ext_data = CompilerExtData :: type_check_with_child ( & ast, lookup_ext) ;
832- Ok ( Self {
833- ms : Arc :: new ( Miniscript :: from_components_unchecked ( ast, ty, ext) ) ,
834- comp_ext_data,
835- } )
836- }
837756}
838757
839758/// Different types of casts possible for each node.
@@ -1290,40 +1209,6 @@ where
12901209 }
12911210}
12921211
1293- /// Helper function to compile different order of and_or fragments.
1294- /// `sat_prob` and `dissat_prob` represent the sat and dissat probabilities of
1295- /// root and_or node. `weights` represent the odds for taking each sub branch
1296- #[ allow( clippy:: too_many_arguments) ]
1297- fn compile_tern < Pk : MiniscriptKey , Ctx : ScriptContext > (
1298- policy_cache : & mut PolicyCache < Pk , Ctx > ,
1299- policy : & Concrete < Pk > ,
1300- ret : & mut BTreeMap < CompilationKey , AstElemExt < Pk , Ctx > > ,
1301- a_comp : & mut BTreeMap < CompilationKey , AstElemExt < Pk , Ctx > > ,
1302- b_comp : & mut BTreeMap < CompilationKey , AstElemExt < Pk , Ctx > > ,
1303- c_comp : & mut BTreeMap < CompilationKey , AstElemExt < Pk , Ctx > > ,
1304- weights : [ f64 ; 2 ] ,
1305- sat_prob : f64 ,
1306- dissat_prob : Option < f64 > ,
1307- ) -> Result < ( ) , CompilerError > {
1308- for a in a_comp. values_mut ( ) {
1309- let aref = Arc :: clone ( & a. ms ) ;
1310- for b in b_comp. values_mut ( ) {
1311- let bref = Arc :: clone ( & b. ms ) ;
1312- for c in c_comp. values_mut ( ) {
1313- let cref = Arc :: clone ( & c. ms ) ;
1314- let ast = Terminal :: AndOr ( Arc :: clone ( & aref) , Arc :: clone ( & bref) , Arc :: clone ( & cref) ) ;
1315- a. comp_ext_data . branch_prob = Some ( weights[ 0 ] ) ;
1316- b. comp_ext_data . branch_prob = Some ( weights[ 0 ] ) ;
1317- c. comp_ext_data . branch_prob = Some ( weights[ 1 ] ) ;
1318- if let Ok ( new_ext) = AstElemExt :: ternary ( ast, a, b, c) {
1319- insert_best_wrapped ( policy_cache, policy, ret, new_ext, sat_prob, dissat_prob) ?;
1320- }
1321- }
1322- }
1323- }
1324- Ok ( ( ) )
1325- }
1326-
13271212/// Obtain the best compilation of for p=1.0 and q=0
13281213pub fn best_compilation < Pk : MiniscriptKey , Ctx : ScriptContext > (
13291214 policy : & Concrete < Pk > ,
0 commit comments