@@ -775,17 +775,13 @@ impl Property for ExtData {
775775 let mut ops_count = 0 ;
776776 let mut ops_count_sat_vec = Vec :: with_capacity ( n) ;
777777 let mut ops_count_nsat_sum = 0 ;
778- let mut op_count_sat = Some ( 0 ) ;
779778 let mut timelocks = Vec :: with_capacity ( n) ;
780779 let mut stack_elem_count_sat_vec = Vec :: with_capacity ( n) ;
781- let mut stack_elem_count_sat = Some ( 0 ) ;
782780 let mut stack_elem_count_dissat = Some ( 0 ) ;
783781 let mut max_sat_size_vec = Vec :: with_capacity ( n) ;
784- let mut max_sat_size = Some ( ( 0 , 0 ) ) ;
785782 let mut max_dissat_size = Some ( ( 0 , 0 ) ) ;
786783 // the max element count is same as max sat element count when satisfying one element + 1
787784 let mut exec_stack_elem_count_sat_vec = Vec :: with_capacity ( n) ;
788- let mut exec_stack_elem_count_sat = Some ( 0 ) ;
789785 let mut exec_stack_elem_count_dissat = Some ( 0 ) ;
790786
791787 for i in 0 ..n {
@@ -822,61 +818,60 @@ impl Property for ExtData {
822818 ) ;
823819 }
824820
825- // We sort by [satisfaction cost - dissatisfaction cost] to make a worst-case (the most
826- // costy satisfaction are satisfied, the most costy dissatisfactions are dissatisfied)
827- // sum of the cost by iterating through the sorted vector *backward*.
828- stack_elem_count_sat_vec. sort_by ( |a, b| {
829- a. 0 . map ( |x| a. 1 . map ( |y| x as isize - y as isize ) )
830- . cmp ( & b. 0 . map ( |x| b. 1 . map ( |y| x as isize - y as isize ) ) )
831- } ) ;
832- for ( i, & ( x, y) ) in stack_elem_count_sat_vec. iter ( ) . rev ( ) . enumerate ( ) {
833- stack_elem_count_sat = if i <= k {
834- x. and_then ( |x| stack_elem_count_sat. map ( |count| count + x) )
835- } else {
836- y. and_then ( |y| stack_elem_count_sat. map ( |count| count + y) )
837- } ;
838- }
821+ stack_elem_count_sat_vec. sort_by ( sat_minus_option_dissat) ;
822+ let stack_elem_count_sat =
823+ stack_elem_count_sat_vec
824+ . iter ( )
825+ . rev ( )
826+ . enumerate ( )
827+ . fold ( Some ( 0 ) , |acc, ( i, & ( x, y) ) | {
828+ if i <= k {
829+ opt_add ( acc, x)
830+ } else {
831+ opt_add ( acc, y)
832+ }
833+ } ) ;
839834
840- // Same logic as above
841- exec_stack_elem_count_sat_vec . sort_by ( |a , b| {
842- a . 0 . map ( |x| a . 1 . map ( |y| x as isize - y as isize ) )
843- . cmp ( & b . 0 . map ( |x| b . 1 . map ( |y| x as isize - y as isize ) ) )
844- } ) ;
845- for ( i, & ( x, y) ) in exec_stack_elem_count_sat_vec . iter ( ) . rev ( ) . enumerate ( ) {
846- exec_stack_elem_count_sat = if i <= k {
847- opt_max ( exec_stack_elem_count_sat , x)
848- } else {
849- opt_max ( exec_stack_elem_count_sat , y)
850- } ;
851- }
835+ exec_stack_elem_count_sat_vec . sort_by ( sat_minus_option_dissat ) ;
836+ let exec_stack_elem_count_sat = exec_stack_elem_count_sat_vec
837+ . iter ( )
838+ . rev ( )
839+ . enumerate ( )
840+ . fold ( Some ( 0 ) , |acc , ( i, & ( x, y) ) | {
841+ if i <= k {
842+ opt_max ( acc , x)
843+ } else {
844+ opt_max ( acc , y)
845+ }
846+ } ) ;
852847
853- // Same for the size cost. A bit more intricated as we need to account for both the witness
854- // and scriptSig cost, so we end up with a tuple of Options of tuples. We use the witness
855- // cost (first element of the mentioned tuple) here.
856848 // FIXME: Maybe make the ExtData struct aware of Ctx and add a one_cost() method here ?
857- max_sat_size_vec. sort_by ( |a, b| {
858- a. 0 . map ( |x| a. 1 . map ( |y| x. 0 as isize - y. 0 as isize ) )
859- . cmp ( & b. 0 . map ( |x| b. 1 . map ( |y| x. 0 as isize - y. 0 as isize ) ) )
860- } ) ;
861- for ( i, & ( x, y) ) in max_sat_size_vec. iter ( ) . enumerate ( ) {
862- max_sat_size = if i <= k {
863- x. and_then ( |x| max_sat_size. map ( |( w, s) | ( w + x. 0 , s + x. 1 ) ) )
864- } else {
865- y. and_then ( |y| max_sat_size. map ( |( w, s) | ( w + y. 0 , s + y. 1 ) ) )
866- } ;
867- }
849+ max_sat_size_vec. sort_by ( sat_minus_dissat_witness) ;
850+ let max_sat_size =
851+ max_sat_size_vec
852+ . iter ( )
853+ . enumerate ( )
854+ . fold ( Some ( ( 0 , 0 ) ) , |acc, ( i, & ( x, y) ) | {
855+ if i <= k {
856+ opt_tuple_add ( acc, x)
857+ } else {
858+ opt_tuple_add ( acc, y)
859+ }
860+ } ) ;
861+
862+ ops_count_sat_vec. sort_by ( sat_minus_dissat) ;
863+ let op_count_sat =
864+ ops_count_sat_vec
865+ . iter ( )
866+ . enumerate ( )
867+ . fold ( Some ( 0 ) , |acc, ( i, & ( x, y) ) | {
868+ if i <= k {
869+ opt_add ( acc, x)
870+ } else {
871+ opt_add ( acc, Some ( y) )
872+ }
873+ } ) ;
868874
869- ops_count_sat_vec. sort_by ( |a, b| {
870- a. 0 . map ( |x| x as isize - a. 1 as isize )
871- . cmp ( & b. 0 . map ( |x| x as isize - b. 1 as isize ) )
872- } ) ;
873- for ( i, & ( x, y) ) in ops_count_sat_vec. iter ( ) . enumerate ( ) {
874- op_count_sat = if i <= k {
875- opt_add ( op_count_sat, x)
876- } else {
877- opt_add ( op_count_sat, Some ( y) )
878- } ;
879- }
880875 Ok ( ExtData {
881876 pk_cost : pk_cost + n - 1 , //all pk cost + (n-1)*ADD
882877 has_free_verify : true ,
@@ -1034,7 +1029,47 @@ impl Property for ExtData {
10341029 }
10351030}
10361031
1037- // Returns Some(max(x,y)) is both x and y are Some. Otherwise, return none
1032+ // Function to pass to sort_by. Sort by (satisfaction cost - dissatisfaction cost).
1033+ //
1034+ // We sort by (satisfaction cost - dissatisfaction cost) to make a worst-case (the most
1035+ // costy satisfactions are satisfied, the most costy dissatisfactions are dissatisfied).
1036+ //
1037+ // Args are of form: (<count_sat>, <count_dissat>)
1038+ fn sat_minus_dissat < ' r , ' s > (
1039+ a : & ' r ( Option < usize > , usize ) ,
1040+ b : & ' s ( Option < usize > , usize ) ,
1041+ ) -> std:: cmp:: Ordering {
1042+ a. 0 . map ( |x| x as isize - a. 1 as isize )
1043+ . cmp ( & b. 0 . map ( |x| x as isize - b. 1 as isize ) )
1044+ }
1045+
1046+ // Function to pass to sort_by. Sort by (satisfaction cost - dissatisfaction cost).
1047+ //
1048+ // We sort by (satisfaction cost - dissatisfaction cost) to make a worst-case (the most
1049+ // costy satisfactions are satisfied, the most costy dissatisfactions are dissatisfied).
1050+ //
1051+ // Args are of form: (<count_sat>, <count_dissat>)
1052+ fn sat_minus_option_dissat < ' r , ' s > (
1053+ a : & ' r ( Option < usize > , Option < usize > ) ,
1054+ b : & ' s ( Option < usize > , Option < usize > ) ,
1055+ ) -> std:: cmp:: Ordering {
1056+ a. 0 . map ( |x| a. 1 . map ( |y| x as isize - y as isize ) )
1057+ . cmp ( & b. 0 . map ( |x| b. 1 . map ( |y| x as isize - y as isize ) ) )
1058+ }
1059+
1060+ // Function to pass to sort_by. Sort by (satisfaction cost - dissatisfaction cost) of cost of witness.
1061+ //
1062+ // Args are of form: (<max_sat_size>, <count_dissat_size>)
1063+ // max_[dis]sat_size of form: (<cost_of_witness>, <cost_of_sciptsig>)
1064+ fn sat_minus_dissat_witness < ' r , ' s > (
1065+ a : & ' r ( Option < ( usize , usize ) > , Option < ( usize , usize ) > ) ,
1066+ b : & ' s ( Option < ( usize , usize ) > , Option < ( usize , usize ) > ) ,
1067+ ) -> std:: cmp:: Ordering {
1068+ a. 0 . map ( |x| a. 1 . map ( |y| x. 0 as isize - y. 0 as isize ) )
1069+ . cmp ( & b. 0 . map ( |x| b. 1 . map ( |y| x. 0 as isize - y. 0 as isize ) ) )
1070+ }
1071+
1072+ /// Returns Some(max(x,y)) is both x and y are Some. Otherwise, returns `None`.
10381073fn opt_max < T : Ord > ( a : Option < T > , b : Option < T > ) -> Option < T > {
10391074 if let ( Some ( x) , Some ( y) ) = ( a, b) {
10401075 Some ( cmp:: max ( x, y) )
@@ -1043,7 +1078,12 @@ fn opt_max<T: Ord>(a: Option<T>, b: Option<T>) -> Option<T> {
10431078 }
10441079}
10451080
1046- // Returns Some(x+y) is both x and y are Some. Otherwise, return none
1081+ /// Returns Some(x+y) is both x and y are Some. Otherwise, returns `None`.
10471082fn opt_add ( a : Option < usize > , b : Option < usize > ) -> Option < usize > {
10481083 a. and_then ( |x| b. map ( |y| x + y) )
10491084}
1085+
1086+ /// Returns Some((x0+y0, x1+y1)) is both x and y are Some. Otherwise, returns `None`.
1087+ fn opt_tuple_add ( a : Option < ( usize , usize ) > , b : Option < ( usize , usize ) > ) -> Option < ( usize , usize ) > {
1088+ a. and_then ( |x| b. map ( |( w, s) | ( w + x. 0 , s + x. 1 ) ) )
1089+ }
0 commit comments