@@ -176,28 +176,26 @@ fn my_operator_system(
176176 operator : & MyOperator ,
177177 if_stack : & mut ConditionStack ,
178178 context : & ScriptContext ,
179- ) -> MyControlFlow {
179+ ) -> Result < ( ) , ( ) > {
180180 if !if_stack. all_true ( ) {
181181 match operator {
182182 MyOperator :: If => {
183183 if_stack. push_back ( false ) ;
184184 }
185185 MyOperator :: Else => {
186186 if if_stack. toggle_top ( ) . is_none ( ) {
187- stack. push ( MyValue :: Boolean ( false ) ) ;
188- return MyControlFlow :: Break ;
187+ return Err ( ( ) ) ;
189188 }
190189 }
191190 MyOperator :: EndIf => {
192191 if if_stack. pop_back ( ) . is_none ( ) {
193- stack. push ( MyValue :: Boolean ( false ) ) ;
194- return MyControlFlow :: Break ;
192+ return Err ( ( ) ) ;
195193 }
196194 }
197195 _ => { }
198196 }
199197
200- return MyControlFlow :: Continue ;
198+ return Ok ( ( ) ) ;
201199 }
202200
203201 match operator {
@@ -209,37 +207,30 @@ fn my_operator_system(
209207 MyOperator :: Verify => {
210208 let top = stack. pop ( ) ;
211209 if top != MyValue :: Boolean ( true ) {
212- // Push the element back because there is a check in execute_script that needs a
213- // false value to mark the script execution as failed, otherwise it may be marked as
214- // success
215- stack. push ( top) ;
216- return MyControlFlow :: Break ;
210+ return Err ( ( ) ) ;
217211 }
218212 }
219213 MyOperator :: If => {
220214 let top = stack. pop ( ) ;
221215 if let MyValue :: Boolean ( b) = top {
222216 if_stack. push_back ( b) ;
223217 } else {
224- stack. push ( MyValue :: Boolean ( false ) ) ;
225- return MyControlFlow :: Break ;
218+ return Err ( ( ) ) ;
226219 }
227220 }
228221 MyOperator :: Else => {
229222 if if_stack. toggle_top ( ) . is_none ( ) {
230- stack. push ( MyValue :: Boolean ( false ) ) ;
231- return MyControlFlow :: Break ;
223+ return Err ( ( ) ) ;
232224 }
233225 }
234226 MyOperator :: EndIf => {
235227 if if_stack. pop_back ( ) . is_none ( ) {
236- stack. push ( MyValue :: Boolean ( false ) ) ;
237- return MyControlFlow :: Break ;
228+ return Err ( ( ) ) ;
238229 }
239230 }
240231 }
241232
242- MyControlFlow :: Continue
233+ Ok ( ( ) )
243234}
244235
245236// ConditionStack implementation from bitcoin-core
@@ -405,7 +396,17 @@ fn execute_script(script: Script<MyOperator, MyValue>, context: &ScriptContext)
405396 let mut machine = Machine2 :: new ( |a, b, c| my_operator_system ( a, b, c, context) ) ;
406397 let result = machine. run_script ( & script) ;
407398
408- result == None || result == Some ( & MyValue :: Boolean ( true ) )
399+ match result {
400+ Ok ( res) => {
401+ // Script execution is considered successful if the stack is empty or if the top-most
402+ // element of the stack is "true".
403+ res == None || res == Some ( & MyValue :: Boolean ( true ) )
404+ }
405+ Err ( _e) => {
406+ // TODO: return cause of script execution failure
407+ false
408+ }
409+ }
409410}
410411
411412fn execute_locking_script (
@@ -457,28 +458,22 @@ pub fn execute_complete_script(
457458 execute_redeem_script ( witness_bytes, redeem_bytes, context)
458459}
459460
460- // TODO: use control flow enum from scriptful library when ready
461- pub enum MyControlFlow {
462- Continue ,
463- Break ,
464- }
465-
466- pub struct Machine2 < Op , Val , F >
461+ pub struct Machine2 < Op , Val , F , E >
467462where
468463 Val : core:: fmt:: Debug + core:: cmp:: PartialEq ,
469- F : FnMut ( & mut Stack < Val > , & Op , & mut ConditionStack ) -> MyControlFlow ,
464+ F : FnMut ( & mut Stack < Val > , & Op , & mut ConditionStack ) -> Result < ( ) , E > ,
470465{
471466 op_sys : F ,
472467 stack : Stack < Val > ,
473468 if_stack : ConditionStack ,
474469 phantom_op : PhantomData < fn ( & Op ) > ,
475470}
476471
477- impl < Op , Val , F > Machine2 < Op , Val , F >
472+ impl < Op , Val , F , E > Machine2 < Op , Val , F , E >
478473where
479474 Op : core:: fmt:: Debug + core:: cmp:: Eq ,
480475 Val : core:: fmt:: Debug + core:: cmp:: PartialEq + core:: clone:: Clone ,
481- F : FnMut ( & mut Stack < Val > , & Op , & mut ConditionStack ) -> MyControlFlow ,
476+ F : FnMut ( & mut Stack < Val > , & Op , & mut ConditionStack ) -> Result < ( ) , E > ,
482477{
483478 pub fn new ( op_sys : F ) -> Self {
484479 Self {
@@ -489,7 +484,7 @@ where
489484 }
490485 }
491486
492- pub fn operate ( & mut self , item : & Item < Op , Val > ) -> MyControlFlow {
487+ pub fn operate ( & mut self , item : & Item < Op , Val > ) -> Result < Option < & Val > , E > {
493488 match item {
494489 Item :: Operator ( operator) => {
495490 ( self . op_sys ) ( & mut self . stack , operator, & mut self . if_stack )
@@ -499,24 +494,18 @@ where
499494 self . stack . push ( ( * value) . clone ( ) ) ;
500495 }
501496
502- MyControlFlow :: Continue
497+ Ok ( ( ) )
503498 }
504499 }
500+ . map ( |( ) | self . stack . topmost ( ) )
505501 }
506502
507- pub fn run_script ( & mut self , script : ScriptRef < Op , Val > ) -> Option < & Val > {
503+ pub fn run_script ( & mut self , script : ScriptRef < Op , Val > ) -> Result < Option < & Val > , E > {
508504 for item in script {
509- match self . operate ( item) {
510- MyControlFlow :: Continue => {
511- continue ;
512- }
513- MyControlFlow :: Break => {
514- break ;
515- }
516- }
505+ self . operate ( item) ?;
517506 }
518507
519- self . stack . topmost ( )
508+ Ok ( self . stack . topmost ( ) )
520509 }
521510}
522511
@@ -806,9 +795,14 @@ mod tests {
806795 let mut m = Machine2 :: new ( |_stack : & mut Stack < ( ) > , operator, _if_stack| {
807796 v. push ( * operator) ;
808797
809- MyControlFlow :: Continue
798+ if * operator == 0 {
799+ return Err ( ( ) ) ;
800+ }
801+
802+ Ok ( ( ) )
810803 } ) ;
811- m. run_script ( & [ Item :: Operator ( 1 ) , Item :: Operator ( 3 ) , Item :: Operator ( 2 ) ] ) ;
804+ m. run_script ( & [ Item :: Operator ( 1 ) , Item :: Operator ( 3 ) , Item :: Operator ( 2 ) ] )
805+ . unwrap ( ) ;
812806
813807 assert_eq ! ( v, vec![ 0 , 1 , 3 , 2 ] ) ;
814808 }
0 commit comments