diff --git a/acvm-repo/acvm/src/pwg/brillig.rs b/acvm-repo/acvm/src/pwg/brillig.rs index 512c4d6e14a..d1eb04f8285 100644 --- a/acvm-repo/acvm/src/pwg/brillig.rs +++ b/acvm-repo/acvm/src/pwg/brillig.rs @@ -162,19 +162,16 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { VMStatus::Finished { .. } => Ok(BrilligSolverStatus::Finished), VMStatus::InProgress => Ok(BrilligSolverStatus::InProgress), VMStatus::Failure { reason, call_stack } => { - match reason { + let call_stack = call_stack + .iter() + .map(|brillig_index| OpcodeLocation::Brillig { + acir_index: self.acir_index, + brillig_index: *brillig_index, + }) + .collect(); + let (payload, found_trap) = match reason { FailureReason::RuntimeError { message } => { - let call_stack = call_stack - .iter() - .map(|brillig_index| OpcodeLocation::Brillig { - acir_index: self.acir_index, - brillig_index: *brillig_index, - }) - .collect(); - Err(OpcodeResolutionError::BrilligFunctionFailed { - payload: Some(ResolvedAssertionPayload::String(message)), - call_stack, - }) + (Some(ResolvedAssertionPayload::String(message)), false) } FailureReason::Trap { revert_data_offset, revert_data_size } => { @@ -218,13 +215,14 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { } } }; - - Err(OpcodeResolutionError::UnsatisfiedConstrain { - opcode_location: super::ErrorLocation::Unresolved, - payload, - }) + (payload, true) } - } + }; + Err(OpcodeResolutionError::BrilligFunctionFailed { + payload, + call_stack, + found_trap, + }) } VMStatus::ForeignCallWait { function, inputs } => { Ok(BrilligSolverStatus::ForeignCallWait(ForeignCallWaitInfo { function, inputs })) diff --git a/acvm-repo/acvm/src/pwg/mod.rs b/acvm-repo/acvm/src/pwg/mod.rs index 4f88e17d109..f85e4674b41 100644 --- a/acvm-repo/acvm/src/pwg/mod.rs +++ b/acvm-repo/acvm/src/pwg/mod.rs @@ -116,28 +116,53 @@ impl std::fmt::Display for ErrorLocation { } } -#[derive(Clone, PartialEq, Eq, Debug, Error)] +#[derive(Clone, PartialEq, Eq, Debug)] pub enum OpcodeResolutionError { - #[error("Cannot solve opcode: {0}")] - OpcodeNotSolvable(#[from] OpcodeNotSolvable), - #[error("Cannot satisfy constraint")] + OpcodeNotSolvable(OpcodeNotSolvable), UnsatisfiedConstrain { opcode_location: ErrorLocation, payload: Option>, }, - #[error("Index out of bounds, array has size {array_size:?}, but index was {index:?}")] - IndexOutOfBounds { opcode_location: ErrorLocation, index: u32, array_size: u32 }, - #[error("Failed to solve blackbox function: {0}, reason: {1}")] + IndexOutOfBounds { + opcode_location: ErrorLocation, + index: u32, + array_size: u32, + }, BlackBoxFunctionFailed(BlackBoxFunc, String), - #[error("Failed to solve brillig function")] BrilligFunctionFailed { call_stack: Vec, payload: Option>, + found_trap: bool, + }, + AcirMainCallAttempted { + opcode_location: ErrorLocation, + }, + AcirCallOutputsMismatch { + opcode_location: ErrorLocation, + results_size: u32, + outputs_size: u32, }, - #[error("Attempted to call `main` with a `Call` opcode")] - AcirMainCallAttempted { opcode_location: ErrorLocation }, - #[error("{results_size:?} result values were provided for {outputs_size:?} call output witnesses, most likely due to bad ACIR codegen")] - AcirCallOutputsMismatch { opcode_location: ErrorLocation, results_size: u32, outputs_size: u32 }, +} + +impl std::fmt::Display for OpcodeResolutionError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + OpcodeResolutionError::OpcodeNotSolvable(opcode_not_solvable) => write!(f, "Cannot solve opcode: {}", opcode_not_solvable), + OpcodeResolutionError::UnsatisfiedConstrain { .. } => write!(f, "Cannot satisfy constraint"), + OpcodeResolutionError::IndexOutOfBounds { array_size, index, .. } => write!(f, "Index out of bounds, array has size {}, but index was {}", array_size, index), + OpcodeResolutionError::BlackBoxFunctionFailed(func, reason) => write!(f,"Failed to solve blackbox function: {}, reason: {}", func, reason), + OpcodeResolutionError::BrilligFunctionFailed{found_trap: false, .. } => write!(f, "Failed to solve brillig function"), + OpcodeResolutionError::BrilligFunctionFailed{found_trap: true, .. } => write!(f, "Cannot satisfy constraint"), + OpcodeResolutionError::AcirMainCallAttempted{ .. } => write!(f, "Attempted to call `main` with a `Call` opcode"), + OpcodeResolutionError::AcirCallOutputsMismatch {results_size, outputs_size, .. } => write!(f, "{} result values were provided for {} call output witnesses, most likely due to bad ACIR codegen", results_size, outputs_size), + } + } +} + +impl From> for OpcodeResolutionError { + fn from(opcode: OpcodeNotSolvable) -> Self { + OpcodeResolutionError::OpcodeNotSolvable(opcode) + } } impl From for OpcodeResolutionError { @@ -501,7 +526,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { fn map_brillig_error(&self, mut err: OpcodeResolutionError) -> OpcodeResolutionError { match &mut err { - OpcodeResolutionError::BrilligFunctionFailed { call_stack, payload } => { + OpcodeResolutionError::BrilligFunctionFailed { call_stack, payload, .. } => { // Some brillig errors have static strings as payloads, we can resolve them here let last_location = call_stack.last().expect("Call stacks should have at least one item"); diff --git a/acvm-repo/acvm/tests/solver.rs b/acvm-repo/acvm/tests/solver.rs index e55dbb73ae1..69b7b5272da 100644 --- a/acvm-repo/acvm/tests/solver.rs +++ b/acvm-repo/acvm/tests/solver.rs @@ -672,7 +672,8 @@ fn unsatisfied_opcode_resolved_brillig() { solver_status, ACVMStatus::Failure(OpcodeResolutionError::BrilligFunctionFailed { payload: None, - call_stack: vec![OpcodeLocation::Brillig { acir_index: 0, brillig_index: 3 }] + call_stack: vec![OpcodeLocation::Brillig { acir_index: 0, brillig_index: 3 }], + found_trap: true, }), "The first opcode is not satisfiable, expected an error indicating this" ); diff --git a/tooling/debugger/src/context.rs b/tooling/debugger/src/context.rs index 07125616ce9..7b1ad7294c8 100644 --- a/tooling/debugger/src/context.rs +++ b/tooling/debugger/src/context.rs @@ -472,7 +472,7 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { self.handle_foreign_call(foreign_call) } Err(err) => { - if let OpcodeResolutionError::UnsatisfiedConstrain { .. } = err { + if let OpcodeResolutionError::BrilligFunctionFailed { found_trap: true, .. } = err { // return solver ownership so brillig_solver it has the right opcode location self.brillig_solver = Some(solver); }