Skip to content

Commit c321bb1

Browse files
committed
feat(stack): remove MyControlFlow enum, use simple Result instead
1 parent 6d6dc19 commit c321bb1

File tree

1 file changed

+37
-43
lines changed

1 file changed

+37
-43
lines changed

stack/src/lib.rs

Lines changed: 37 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -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

411412
fn 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>
467462
where
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>
478473
where
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

Comments
 (0)