Skip to content

Commit

Permalink
Merge pull request #1197 from 0xPolygonMiden/andrew-on-assert-failed
Browse files Browse the repository at this point in the history
Add `on_assert_failed()` method to the Host trait
  • Loading branch information
bobbinth authored Jan 15, 2024
2 parents d30d508 + 5bf3cc2 commit 2662639
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 35 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- Updated Winterfell dependency to v0.7 (#1121).
- Added methods `StackOutputs::get_stack_item()` and `StackOutputs::get_stack_word()` (#1155).
- Added [Tracing](https://crates.io/crates/tracing) logger to the VM (#1139).
- Added `on_assert_failed()` method to the Host trait (#1197).

#### CLI
- Introduced the `!use` command for the Miden REPL (#1162).
Expand Down
2 changes: 1 addition & 1 deletion air/src/constraints/stack/op_flags/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ impl<E: FieldElement> OpFlags<E> {
/// Operation Flag of ASSERT operation.
#[inline(always)]
pub fn assert(&self) -> E {
self.degree7_op_flags[get_op_index(Operation::Assert(ZERO).op_code())]
self.degree7_op_flags[get_op_index(Operation::Assert(0).op_code())]
}

/// Operation Flag of EQ operation.
Expand Down
2 changes: 1 addition & 1 deletion air/src/constraints/stack/system_ops/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub fn get_fmpupdate_test_frame(a: u64) -> EvaluationFrame<Felt> {
/// returns an EvaluationFrame for testing.
pub fn get_assert_test_frame() -> EvaluationFrame<Felt> {
// frame initialized with a fmpupdate operation using it's unique opcode.
let mut frame = generate_evaluation_frame(Operation::Assert(ZERO).op_code() as usize);
let mut frame = generate_evaluation_frame(Operation::Assert(0).op_code() as usize);

// Set the output. The top element in the current frame of the stack should be ONE.
frame.current_mut()[STACK_TRACE_OFFSET] = ONE;
Expand Down
10 changes: 5 additions & 5 deletions assembly/src/assembler/instruction/ext2_ops.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{AssemblyError, CodeBlock, Operation::*, SpanBuilder, ZERO};
use super::{AssemblyError, CodeBlock, Operation::*, SpanBuilder};
use vm_core::AdviceInjector::Ext2Inv;

/// Given a stack in the following initial configuration [b1, b0, a1, a0, ...] where a = (a0, a1)
Expand Down Expand Up @@ -60,9 +60,9 @@ pub fn ext2_div(span: &mut SpanBuilder) -> Result<Option<CodeBlock>, AssemblyErr
Ext2Mul, // [b1', b0', 0, 1, a1, a0, ...]
MovUp2, // [0, b1', b0', 1, a1, a0, ...]
Eqz, // [1, b1', b0', 1, a1, a0, ...]
Assert(ZERO), // [b1', b0', 1, a1, a0, ...]
Assert(0), // [b1', b0', 1, a1, a0, ...]
MovUp2, // [1, b1', b0', a1, a0, ...]
Assert(ZERO), // [b1', b0', a1, a0, ...]
Assert(0), // [b1', b0', a1, a0, ...]
Ext2Mul, // [b1', b0', a1*b1', a0*b0', ...]
Drop, // [b0', a1*b1', a0*b0'...]
Drop // [a1*b1', a0*b0'...]
Expand Down Expand Up @@ -120,9 +120,9 @@ pub fn ext2_inv(span: &mut SpanBuilder) -> Result<Option<CodeBlock>, AssemblyErr
Ext2Mul, // [a1', a0', 0, 1, ...]
MovUp2, // [0, a1', a0', 1, ...]
Eqz, // [1, a1', a0', 1, ...]
Assert(ZERO), // [a1', a0', 1, ...]
Assert(0), // [a1', a0', 1, ...]
MovUp2, // [1, a1', a0', ...]
Assert(ZERO), // [a1', a0', ...]
Assert(0), // [a1', a0', ...]
];
span.add_ops(ops)
}
6 changes: 3 additions & 3 deletions assembly/src/assembler/instruction/field_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const TWO: Felt = Felt::new(2);
/// Asserts that the top two words in the stack are equal.
///
/// VM cycles: 11 cycles
pub fn assertw(span: &mut SpanBuilder, err_code: Felt) -> Result<Option<CodeBlock>, AssemblyError> {
pub fn assertw(span: &mut SpanBuilder, err_code: u32) -> Result<Option<CodeBlock>, AssemblyError> {
span.add_ops([
MovUp4,
Eq,
Expand Down Expand Up @@ -122,7 +122,7 @@ pub fn append_pow2_op(span: &mut SpanBuilder) {
// drop the top two elements bit and exp value of the latest bit.
span.push_ops([Drop, Drop]);
// taking `b` to the top and asserting if it's equal to ZERO after all the right shifts.
span.push_ops([Swap, Eqz, Assert(ZERO)]);
span.push_ops([Swap, Eqz, Assert(0)]);
}

// EXPONENTIATION OPERATION
Expand Down Expand Up @@ -151,7 +151,7 @@ pub fn exp(span: &mut SpanBuilder, num_pow_bits: u8) -> Result<Option<CodeBlock>
span.push_ops([Drop, Drop]);

// taking `b` to the top and asserting if it's equal to ZERO after all the right shifts.
span.push_ops([Swap, Eqz, Assert(ZERO)]);
span.push_ops([Swap, Eqz, Assert(0)]);
Ok(None)
}

Expand Down
22 changes: 8 additions & 14 deletions assembly/src/assembler/instruction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,14 @@ impl Assembler {
}

let result = match instruction {
Instruction::Assert => span.add_op(Assert(ZERO)),
Instruction::AssertWithError(err_code) => span.add_op(Assert(Felt::from(*err_code))),
Instruction::AssertEq => span.add_ops([Eq, Assert(ZERO)]),
Instruction::AssertEqWithError(err_code) => {
span.add_ops([Eq, Assert(Felt::from(*err_code))])
}
Instruction::AssertEqw => field_ops::assertw(span, ZERO),
Instruction::AssertEqwWithError(err_code) => {
field_ops::assertw(span, Felt::from(*err_code))
}
Instruction::Assertz => span.add_ops([Eqz, Assert(ZERO)]),
Instruction::AssertzWithError(err_code) => {
span.add_ops([Eqz, Assert(Felt::from(*err_code))])
}
Instruction::Assert => span.add_op(Assert(0)),
Instruction::AssertWithError(err_code) => span.add_op(Assert(*err_code)),
Instruction::AssertEq => span.add_ops([Eq, Assert(0)]),
Instruction::AssertEqWithError(err_code) => span.add_ops([Eq, Assert(*err_code)]),
Instruction::AssertEqw => field_ops::assertw(span, 0),
Instruction::AssertEqwWithError(err_code) => field_ops::assertw(span, *err_code),
Instruction::Assertz => span.add_ops([Eqz, Assert(0)]),
Instruction::AssertzWithError(err_code) => span.add_ops([Eqz, Assert(*err_code)]),

Instruction::Add => span.add_op(Add),
Instruction::AddImm(imm) => field_ops::add_imm(span, *imm),
Expand Down
2 changes: 1 addition & 1 deletion core/src/operations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub enum Operation {
///
/// The internal value specifies an error code associated with the error in case when the
/// execution fails.
Assert(Felt),
Assert(u32),

/// Pops an element off the stack, adds the current value of the `fmp` register to it, and
/// pushes the result back onto the stack.
Expand Down
2 changes: 1 addition & 1 deletion miden/tests/integration/operations/sys_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn assert_with_code() {
test.expect_stack(&[]);

// triggered assertion captures both the VM cycle and error code
let expected_err = "FailedAssertion(1, 123)";
let expected_err = "FailedAssertion { clk: 1, err_code: 123, err_msg: None }";
let test = build_op_test!(asm_op, &[0]);
test.expect_error(TestError::ExecutionError(&expected_err));
}
Expand Down
35 changes: 29 additions & 6 deletions processor/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,27 @@ pub enum ExecutionError {
DivideByZero(u32),
EventError(String),
Ext2InttError(Ext2InttError),
FailedAssertion(u32, Felt),
FailedAssertion {
clk: u32,
err_code: u32,
err_msg: Option<String>,
},
InvalidFmpValue(Felt, Felt),
InvalidFriDomainSegment(u64),
InvalidFriLayerFolding(QuadFelt, QuadFelt),
InvalidMemoryRange { start_addr: u64, end_addr: u64 },
InvalidMemoryRange {
start_addr: u64,
end_addr: u64,
},
InvalidStackDepthOnReturn(usize),
InvalidStackWordOffset(usize),
InvalidTreeDepth { depth: Felt },
InvalidTreeNodeIndex { depth: Felt, value: Felt },
InvalidTreeDepth {
depth: Felt,
},
InvalidTreeNodeIndex {
depth: Felt,
value: Felt,
},
MemoryAddressOutOfBounds(u64),
MerkleStoreMergeFailed(MerkleError),
MerkleStoreLookupFailed(MerkleError),
Expand Down Expand Up @@ -90,8 +102,19 @@ impl Display for ExecutionError {
DivideByZero(clk) => write!(f, "Division by zero at clock cycle {clk}"),
EventError(error) => write!(f, "Failed to process event - {error}"),
Ext2InttError(err) => write!(f, "Failed to execute Ext2Intt operation: {err}"),
FailedAssertion(clk, err_code) => {
write!(f, "Assertion failed at clock cycle {clk} with error code {err_code}")
FailedAssertion {
clk,
err_code,
err_msg,
} => {
if let Some(err_msg) = err_msg {
write!(
f,
"Assertion failed at clock cycle {clk} with error code {err_code}: {err_msg}"
)
} else {
write!(f, "Assertion failed at clock cycle {clk} with error code {err_code}")
}
}
InvalidFmpValue(old, new) => {
write!(f, "Updating FMP register from {old} to {new} failed because {new} is outside of {FMP_MIN}..{FMP_MAX}")
Expand Down
13 changes: 13 additions & 0 deletions processor/src/host/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ pub trait Host {
Ok(HostResponse::None)
}

/// Handles the failure of the assertion instruction.
fn on_assert_failed<S: ProcessState>(&mut self, process: &S, err_code: u32) -> ExecutionError {
ExecutionError::FailedAssertion {
clk: process.clk(),
err_code,
err_msg: None,
}
}

/// Pops an element from the advice stack and returns it.
///
/// # Errors
Expand Down Expand Up @@ -172,6 +181,10 @@ where
) -> Result<HostResponse, ExecutionError> {
H::on_event(self, process, event_id)
}

fn on_assert_failed<S: ProcessState>(&mut self, process: &S, err_code: u32) -> ExecutionError {
H::on_assert_failed(self, process, err_code)
}
}

// HOST RESPONSE
Expand Down
6 changes: 3 additions & 3 deletions processor/src/operations/sys_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ where
///
/// # Errors
/// Returns an error if the popped value is not ONE.
pub(super) fn op_assert(&mut self, err_code: Felt) -> Result<(), ExecutionError> {
pub(super) fn op_assert(&mut self, err_code: u32) -> Result<(), ExecutionError> {
if self.stack.get(0) != ONE {
return Err(ExecutionError::FailedAssertion(self.system.clk(), err_code));
return Err(self.host.borrow_mut().on_assert_failed(self, err_code));
}
self.stack.shift_left(1);
Ok(())
Expand Down Expand Up @@ -128,7 +128,7 @@ mod tests {
process.execute_op(Operation::Swap).unwrap();
process.execute_op(Operation::Drop).unwrap();

assert!(process.execute_op(Operation::Assert(ZERO)).is_ok());
assert!(process.execute_op(Operation::Assert(0)).is_ok());
}

#[test]
Expand Down

0 comments on commit 2662639

Please sign in to comment.