22
33#![ cfg_attr( fuzzing, no_main) ]
44
5- #[ cfg( any( fuzzing, test) ) ]
6- use std:: sync:: Arc ;
7-
8- #[ cfg( any( fuzzing, test) ) ]
9- use old_simplicity:: { types:: Final as OldFinal , Value as OldValue } ;
10- #[ cfg( any( fuzzing, test) ) ]
11- use simplicity:: types:: Final ;
12-
13- #[ cfg( any( fuzzing, test) ) ]
14- fn convert_ty ( new : & Final ) -> Option < Arc < OldFinal > > {
15- /// Our stack of tasks describing “what we need to do next.”
16- enum Task < ' a > {
17- /// Convert this `Final` into an `OldFinal`.
18- NeedType ( & ' a Final ) ,
19- Binary {
20- is_sum : bool ,
21- dupe : bool ,
22- } ,
23- }
24-
25- // We'll push tasks onto this stack until everything is converted.
26- let mut task_stack = vec ! [ Task :: NeedType ( new) ] ;
27- // As we finish conversion of subtrees, we store them here along with
28- // a count of units. Because the released version of 0.3.0 does not
29- // have any typeskip optimization we need to bail out if there are
30- // too many units, since otherwise we will OOM in from_compact_bits.
31- let mut result_stack: Vec < ( usize , Arc < OldFinal > ) > = vec ! [ ] ;
32- const MAX_UNITS : usize = 1024 * 1024 ;
33-
34- // Process tasks in LIFO order
35- while let Some ( task) = task_stack. pop ( ) {
36- match task {
37- Task :: NeedType ( final_ty) => {
38- if final_ty. is_unit ( ) {
39- result_stack. push ( ( 1 , OldFinal :: unit ( ) ) ) ;
40- } else if let Some ( ( left, right) ) = final_ty. as_sum ( ) {
41- let dupe = Arc :: ptr_eq ( left, right) ;
42- task_stack. push ( Task :: Binary { is_sum : true , dupe } ) ;
43- if !dupe {
44- task_stack. push ( Task :: NeedType ( right) ) ;
45- }
46- task_stack. push ( Task :: NeedType ( left) ) ;
47- } else if let Some ( ( left, right) ) = final_ty. as_product ( ) {
48- let dupe = Arc :: ptr_eq ( left, right) ;
49- task_stack. push ( Task :: Binary {
50- is_sum : false ,
51- dupe,
52- } ) ;
53- if !dupe {
54- task_stack. push ( Task :: NeedType ( right) ) ;
55- }
56- task_stack. push ( Task :: NeedType ( left) ) ;
57- } else {
58- unreachable ! ( ) ;
59- }
60- }
61- Task :: Binary { is_sum, dupe } => {
62- let right = result_stack. pop ( ) . expect ( "right type missing" ) ;
63- let left = if dupe {
64- ( right. 0 , Arc :: clone ( & right. 1 ) )
65- } else {
66- result_stack. pop ( ) . expect ( "left type missing" )
67- } ;
68- let new_total = left. 0 + right. 0 ;
69- if new_total > MAX_UNITS {
70- return None ;
71- }
72- if is_sum {
73- result_stack. push ( ( new_total, OldFinal :: sum ( left. 1 , right. 1 ) ) ) ;
74- } else {
75- result_stack. push ( ( new_total, OldFinal :: product ( left. 1 , right. 1 ) ) ) ;
76- }
77- }
78- }
79- }
80-
81- // At the end, we should have exactly one final type.
82- assert_eq ! ( result_stack. len( ) , 1 , "Internal conversion error" ) ;
83- let ( _, res) = result_stack. pop ( ) . unwrap ( ) ;
84- Some ( res)
85- }
86-
875#[ cfg( any( fuzzing, test) ) ]
886fn do_test ( data : & [ u8 ] ) {
897 let mut extractor_1 = simplicity_fuzz:: Extractor :: new ( data) ;
@@ -95,8 +13,8 @@ fn do_test(data: &[u8]) {
9513 ) {
9614 ( Some ( val) , Some ( old_val) ) => ( val, old_val) ,
9715 ( None , None ) => return ,
98- ( Some ( val ) , None ) => panic ! ( "Could extract new value but not old." ) ,
99- ( None , Some ( val ) ) => panic ! ( "Could extract old value but not new." ) ,
16+ ( Some ( _ ) , None ) => panic ! ( "Could extract new value but not old." ) ,
17+ ( None , Some ( _ ) ) => panic ! ( "Could extract old value but not new." ) ,
10018 } ;
10119
10220 assert ! ( val. iter_compact( ) . eq( old_val. iter_compact( ) ) ) ;
0 commit comments