Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,16 +292,16 @@ mod tests {
};
use std::collections::BTreeSet;

fn check_circuit(circuit: Circuit<FieldElement>) -> Circuit<FieldElement> {
assert!(CircuitSimulator::default().check_circuit(&circuit));
fn must_check_circuit(circuit: Circuit<FieldElement>) -> Circuit<FieldElement> {
assert!(CircuitSimulator::default().check_circuit(&circuit).is_none());
let mut merge_optimizer = MergeExpressionsOptimizer::new();
let acir_opcode_positions = vec![0; 20];
let (opcodes, _) =
merge_optimizer.eliminate_intermediate_variable(&circuit, acir_opcode_positions);
let mut optimized_circuit = circuit;
optimized_circuit.opcodes = opcodes;
// check that the circuit is still valid after optimization
assert!(CircuitSimulator::default().check_circuit(&optimized_circuit));
assert!(CircuitSimulator::default().check_circuit(&optimized_circuit).is_none());
optimized_circuit
}

Expand Down Expand Up @@ -346,7 +346,7 @@ mod tests {
return_values: PublicInputs::default(),
assert_messages: Default::default(),
};
check_circuit(circuit);
must_check_circuit(circuit);
}

#[test]
Expand Down Expand Up @@ -442,7 +442,7 @@ mod tests {
return_values: PublicInputs::default(),
assert_messages: Default::default(),
};
check_circuit(circuit);
must_check_circuit(circuit);
}

#[test]
Expand Down Expand Up @@ -487,7 +487,7 @@ mod tests {
..Default::default()
};

let new_circuit = check_circuit(circuit.clone());
let new_circuit = must_check_circuit(circuit.clone());
assert_eq!(circuit, new_circuit);
}
}
20 changes: 10 additions & 10 deletions acvm-repo/acvm/src/compiler/simulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ pub struct CircuitSimulator {

impl CircuitSimulator {
/// Simulate a symbolic solve for a circuit by keeping track of the witnesses that can be solved.
/// Returns false if the circuit cannot be solved
/// Returns the index of the opcode that cannot be solved, if any.
#[tracing::instrument(level = "trace", skip_all)]
pub fn check_circuit<F: AcirField>(&mut self, circuit: &Circuit<F>) -> bool {
pub fn check_circuit<F: AcirField>(&mut self, circuit: &Circuit<F>) -> Option<usize> {
let circuit_inputs = circuit.circuit_arguments();
self.solvable_witness.extend(circuit_inputs.iter());
for op in &circuit.opcodes {
for (i, op) in circuit.opcodes.iter().enumerate() {
if !self.try_solve(op) {
return false;
return Some(i);
}
}
true
None
}

/// Check if the Opcode can be solved, and if yes, add the solved witness to set of solvable witness
Expand Down Expand Up @@ -227,7 +227,7 @@ mod tests {
fn reports_true_for_empty_circuit() {
let empty_circuit = test_circuit(vec![], BTreeSet::default(), PublicInputs::default());

assert!(CircuitSimulator::default().check_circuit(&empty_circuit));
assert!(CircuitSimulator::default().check_circuit(&empty_circuit).is_none());
}

#[test]
Expand All @@ -245,7 +245,7 @@ mod tests {
PublicInputs::default(),
);

assert!(CircuitSimulator::default().check_circuit(&connected_circuit));
assert!(CircuitSimulator::default().check_circuit(&connected_circuit).is_none());
}

#[test]
Expand Down Expand Up @@ -273,7 +273,7 @@ mod tests {
PublicInputs::default(),
);

assert!(!CircuitSimulator::default().check_circuit(&disconnected_circuit));
assert!(CircuitSimulator::default().check_circuit(&disconnected_circuit).is_some());
}

#[test]
Expand Down Expand Up @@ -313,7 +313,7 @@ mod tests {
PublicInputs::default(),
);

assert!(!CircuitSimulator::default().check_circuit(&circuit));
assert!(CircuitSimulator::default().check_circuit(&circuit).is_some());
}

#[test]
Expand All @@ -335,6 +335,6 @@ mod tests {
PublicInputs::default(),
);

assert!(!CircuitSimulator::default().check_circuit(&circuit));
assert!(CircuitSimulator::default().check_circuit(&circuit).is_some());
}
}
4 changes: 3 additions & 1 deletion compiler/noirc_evaluator/src/acir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1299,7 +1299,9 @@ impl<'a> Context<'a> {
}
Intrinsic::ArrayLen => {
let len = match self.convert_value(arguments[0], dfg) {
AcirValue::Var(_, _) => unreachable!("Non-array passed to array.len() method"),
AcirValue::Var(_, _) => {
unreachable!("Non-array passed to array.len() method")
}
AcirValue::Array(values) => values.len(),
AcirValue::DynamicArray(array) => array.len,
};
Expand Down
27 changes: 21 additions & 6 deletions tooling/nargo/src/ops/check.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use acvm::compiler::CircuitSimulator;
use acvm::{acir::circuit::AcirOpcodeLocation, compiler::CircuitSimulator};
use noirc_driver::{CompiledProgram, ErrorsAndWarnings};
use noirc_errors::CustomDiagnostic;

Expand All @@ -7,11 +7,26 @@ use noirc_errors::CustomDiagnostic;
pub fn check_program(compiled_program: &CompiledProgram) -> Result<(), ErrorsAndWarnings> {
for (i, circuit) in compiled_program.program.functions.iter().enumerate() {
let mut simulator = CircuitSimulator::default();
if !simulator.check_circuit(circuit) {
let diag = CustomDiagnostic::from_message(
&format!("Circuit \"{}\" is not solvable", compiled_program.names[i]),
fm::FileId::dummy(),
);
if let Some(opcode) = simulator.check_circuit(circuit) {
let diag = if let Some(call_stack) =
compiled_program.debug[i].acir_locations.get(&AcirOpcodeLocation::new(opcode))
{
let call_stack =
compiled_program.debug[i].location_tree.get_call_stack(*call_stack);
CustomDiagnostic::from_message(
&format!("Circuit \"{}\" is not solvable", compiled_program.names[i]),
call_stack[0].file,
)
.with_call_stack(call_stack)
} else {
CustomDiagnostic::from_message(
&format!(
"Circuit \"{}\" is not solvable for opcode \"{}\"",
compiled_program.names[i], opcode
),
fm::FileId::dummy(),
)
};
return Err(vec![diag]);
}
}
Expand Down
Loading