diff --git a/Cargo.lock b/Cargo.lock index ba21890eaf1..577f53175eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,8 +5,7 @@ version = 3 [[package]] name = "acir" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86577747c44f23e2e8e6d972287d01341c0eea42a78ce15c5efd212a39d0fc27" +source = "git+https://github.com/noir-lang/acvm.git?rev=4b4e8a6a25b27e82bddbfe58caa3d421285b4a82#4b4e8a6a25b27e82bddbfe58caa3d421285b4a82" dependencies = [ "acir_field", "bincode", @@ -19,8 +18,7 @@ dependencies = [ [[package]] name = "acir_field" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4239156a8eddd55b2ae8bd25aa169d012bae70e0fd7c635f08f68ada54a8cb6c" +source = "git+https://github.com/noir-lang/acvm.git?rev=4b4e8a6a25b27e82bddbfe58caa3d421285b4a82#4b4e8a6a25b27e82bddbfe58caa3d421285b4a82" dependencies = [ "ark-bn254", "ark-ff", @@ -33,8 +31,7 @@ dependencies = [ [[package]] name = "acvm" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74351bab6e0fd2ec1bd631abc73260f374cc28d2baf85c0e11300c0c989d5e53" +source = "git+https://github.com/noir-lang/acvm.git?rev=4b4e8a6a25b27e82bddbfe58caa3d421285b4a82#4b4e8a6a25b27e82bddbfe58caa3d421285b4a82" dependencies = [ "acir", "acvm_blackbox_solver", @@ -50,8 +47,7 @@ dependencies = [ [[package]] name = "acvm-backend-barretenberg" version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "438eb3837cfc37e0798e18f4a0ebae595e4cbe32a3f4cecfb47ccc1354180dc8" +source = "git+https://github.com/noir-lang/acvm-backend-barretenberg.git?rev=c80aee4434a2db502ed8b17ddd0b555f8f3e7c4b#c80aee4434a2db502ed8b17ddd0b555f8f3e7c4b" dependencies = [ "acvm", "barretenberg-sys", @@ -70,8 +66,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a362499180c6498acc0ebf77bd919be8ccd9adabc84a695d4af44ca180ba0709" +source = "git+https://github.com/noir-lang/acvm.git?rev=4b4e8a6a25b27e82bddbfe58caa3d421285b4a82#4b4e8a6a25b27e82bddbfe58caa3d421285b4a82" dependencies = [ "acir", "blake2", @@ -85,8 +80,7 @@ dependencies = [ [[package]] name = "acvm_stdlib" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e485b3bc3331eaa10bc92fb092ca14275936c8935c3ae7ec89fb0bd48246ab42" +source = "git+https://github.com/noir-lang/acvm.git?rev=4b4e8a6a25b27e82bddbfe58caa3d421285b4a82#4b4e8a6a25b27e82bddbfe58caa3d421285b4a82" dependencies = [ "acir", ] @@ -537,8 +531,7 @@ dependencies = [ [[package]] name = "brillig" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d64df3df7d2d96fc2519e4dd64bc6bc23eee2949ee86725d9041ef7703c283ab" +source = "git+https://github.com/noir-lang/acvm.git?rev=4b4e8a6a25b27e82bddbfe58caa3d421285b4a82#4b4e8a6a25b27e82bddbfe58caa3d421285b4a82" dependencies = [ "acir_field", "serde", @@ -547,8 +540,7 @@ dependencies = [ [[package]] name = "brillig_vm" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b306b3d79b6da192fd2ed68b94ab07712496f39bb5d50fedce44dac3f4953065" +source = "git+https://github.com/noir-lang/acvm.git?rev=4b4e8a6a25b27e82bddbfe58caa3d421285b4a82#4b4e8a6a25b27e82bddbfe58caa3d421285b4a82" dependencies = [ "acir", "acvm_blackbox_solver", diff --git a/Cargo.toml b/Cargo.toml index 990b4b2e534..eede24785a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,4 +58,8 @@ tower = "0.4" url = "2.2.0" wasm-bindgen = { version = "=0.2.86", features = ["serde-serialize"] } wasm-bindgen-test = "0.3.33" -base64 = "0.21.2" \ No newline at end of file +base64 = "0.21.2" + +[patch.crates-io] +acvm = { git = "https://github.com/noir-lang/acvm.git", rev = "4b4e8a6a25b27e82bddbfe58caa3d421285b4a82" } +acvm-backend-barretenberg = { git = "https://github.com/noir-lang/acvm-backend-barretenberg.git", rev = "c80aee4434a2db502ed8b17ddd0b555f8f3e7c4b" } diff --git a/crates/nargo/src/ops/execute.rs b/crates/nargo/src/ops/execute.rs index 2a126443468..ea1fe04baaf 100644 --- a/crates/nargo/src/ops/execute.rs +++ b/crates/nargo/src/ops/execute.rs @@ -12,7 +12,8 @@ pub fn execute_circuit( initial_witness: WitnessMap, show_output: bool, ) -> Result { - let mut acvm = ACVM::new(B::default(), circuit.opcodes, initial_witness); + let backend = B::default(); + let mut acvm = ACVM::new(&backend, circuit.opcodes, initial_witness); loop { let solver_status = acvm.solve(); diff --git a/crates/nargo_cli/src/cli/execute_cmd.rs b/crates/nargo_cli/src/cli/execute_cmd.rs index 0a391ac71a8..63fb91c807c 100644 --- a/crates/nargo_cli/src/cli/execute_cmd.rs +++ b/crates/nargo_cli/src/cli/execute_cmd.rs @@ -41,7 +41,7 @@ pub(crate) struct ExecuteCommand { compile_options: CompileOptions, } -pub(crate) fn run( +pub(crate) fn run( backend: &B, args: ExecuteCommand, config: NargoConfig, @@ -70,7 +70,7 @@ pub(crate) fn run( Ok(()) } -fn execute_package( +fn execute_package( backend: &B, package: &Package, prover_name: &str, @@ -161,7 +161,7 @@ fn report_error_with_opcode_location( } } -pub(crate) fn execute_program( +pub(crate) fn execute_program( backend: &B, circuit: Circuit, abi: &Abi, diff --git a/crates/nargo_cli/src/cli/prove_cmd.rs b/crates/nargo_cli/src/cli/prove_cmd.rs index e4766828a5b..ae36b930ea4 100644 --- a/crates/nargo_cli/src/cli/prove_cmd.rs +++ b/crates/nargo_cli/src/cli/prove_cmd.rs @@ -51,7 +51,7 @@ pub(crate) struct ProveCommand { compile_options: CompileOptions, } -pub(crate) fn run( +pub(crate) fn run( backend: &B, args: ProveCommand, config: NargoConfig, @@ -82,7 +82,7 @@ pub(crate) fn run( } #[allow(clippy::too_many_arguments)] -pub(crate) fn prove_package( +pub(crate) fn prove_package( backend: &B, package: &Package, prover_name: &str, diff --git a/crates/nargo_cli/src/cli/test_cmd.rs b/crates/nargo_cli/src/cli/test_cmd.rs index 2369e172377..19cf5ab293a 100644 --- a/crates/nargo_cli/src/cli/test_cmd.rs +++ b/crates/nargo_cli/src/cli/test_cmd.rs @@ -42,7 +42,7 @@ pub(crate) struct TestCommand { compile_options: CompileOptions, } -pub(crate) fn run( +pub(crate) fn run( backend: &B, args: TestCommand, config: NargoConfig, @@ -73,7 +73,7 @@ pub(crate) fn run( Ok(()) } -fn run_tests( +fn run_tests( backend: &B, package: &Package, test_name: FunctionNameMatch, diff --git a/crates/nargo_cli/tests/compile_failure/dynamic_index_failure/src/main.nr b/crates/nargo_cli/tests/compile_failure/dynamic_index_failure/src/main.nr index 2665356ccd6..96700105bcd 100644 --- a/crates/nargo_cli/tests/compile_failure/dynamic_index_failure/src/main.nr +++ b/crates/nargo_cli/tests/compile_failure/dynamic_index_failure/src/main.nr @@ -1,23 +1,15 @@ fn main(mut x: [u32; 5], z: Field) { let idx = z + 10; - x[z] = 4; - - // Dynamic index is greater than length of the array + if z == 20 { + x[0] = x[4]; + } else { + // We should not hit out of bounds here as we have a predicate + // that should not be hit + if idx as u32 < 3 { + x[idx] = 10; + } + } + // Error should occur here as an index out of bounds read occurs assert(x[idx] != 0); - - // TODO(#2133): Provide more accurate call stacks for arrays merged in if statements - // if z != 20 { - // x[0] = x[4]; - // } else { - // // TODO: Dynamic predicate still gives index out of bounds error - // if idx as u32 < 3 { - // x[idx] = 10; - // } - // x[idx] = 10; - // for i in 0..5 { - // x[idx] = x[i]; - // } - // } - // assert(x[idx] != 0); } \ No newline at end of file diff --git a/crates/nargo_cli/tests/execution_success/array_dynamic/src/main.nr b/crates/nargo_cli/tests/execution_success/array_dynamic/src/main.nr index db8f10b27e9..bc797f848df 100644 --- a/crates/nargo_cli/tests/execution_success/array_dynamic/src/main.nr +++ b/crates/nargo_cli/tests/execution_success/array_dynamic/src/main.nr @@ -15,6 +15,8 @@ fn main(x: [u32; 5], mut z: u32, t: u32, index: [Field;5], index2: [Field;5], of if 3 < (sublen as u32) { assert(index[offset + 3] == index2[3]); } + + regression_mem_op_predicate(x, idx + 10); } fn dyn_array(mut x: [u32; 5], y: Field, z: Field) { @@ -30,3 +32,12 @@ fn dyn_array(mut x: [u32; 5], y: Field, z: Field) { } assert(x[4] == 109); } + +fn regression_mem_op_predicate(mut x: [u32; 5], idx: Field) { + // We should not hit out of bounds here as we have a predicate + // that should not be hit + if idx as u32 < 3 { + x[idx] = 10; + } + assert(x[4] == 111); +} diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/crates/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index b2e5a0e56e1..46dbc701ff5 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -932,13 +932,13 @@ impl AcirContext { AcirValue::Array(vars) => { let mut var_expressions: Vec = Vec::new(); for var in vars { - self.brillig_array_input(&mut var_expressions, var)?; + self.brillig_array_input(&mut var_expressions, var, predicate)?; } Ok(BrilligInputs::Array(var_expressions)) } AcirValue::DynamicArray(_) => { let mut var_expressions = Vec::new(); - self.brillig_array_input(&mut var_expressions, i)?; + self.brillig_array_input(&mut var_expressions, i, predicate)?; Ok(BrilligInputs::Array(var_expressions)) } })?; @@ -977,6 +977,7 @@ impl AcirContext { &mut self, var_expressions: &mut Vec, input: AcirValue, + predicate: AcirVar, ) -> Result<(), InternalError> { match input { AcirValue::Var(var, _) => { @@ -984,7 +985,7 @@ impl AcirContext { } AcirValue::Array(vars) => { for var in vars { - self.brillig_array_input(var_expressions, var)?; + self.brillig_array_input(var_expressions, var, predicate)?; } } AcirValue::DynamicArray(AcirDynamicArray { block_id, len }) => { @@ -996,13 +997,13 @@ impl AcirContext { ); let index_var = index.into_var()?; - let value_read_var = self.read_from_memory(block_id, &index_var)?; + let value_read_var = self.read_from_memory(block_id, &index_var, &predicate)?; let value_read = AcirValue::Var( value_read_var, AcirType::NumericType(NumericType::NativeField), ); - self.brillig_array_input(var_expressions, value_read)?; + self.brillig_array_input(var_expressions, value_read, predicate)?; } } } @@ -1149,6 +1150,7 @@ impl AcirContext { &mut self, block_id: BlockId, index: &AcirVar, + predicate: &AcirVar, ) -> Result { // Fetch the witness corresponding to the index let index_witness = self.var_to_witness(*index)?; @@ -1157,9 +1159,16 @@ impl AcirContext { let value_read_var = self.add_variable(); let value_read_witness = self.var_to_witness(value_read_var)?; + // Fetch the witness corresponding to the predicate + let predicate_witness = self.var_to_witness(*predicate)?; + // Add the memory read operation to the list of opcodes let op = MemOp::read_at_mem_index(index_witness.into(), value_read_witness); - self.acir_ir.push_opcode(Opcode::MemoryOp { block_id, op }); + self.acir_ir.push_opcode(Opcode::MemoryOp { + block_id, + op, + predicate: Some(predicate_witness.into()), + }); Ok(value_read_var) } @@ -1170,6 +1179,7 @@ impl AcirContext { block_id: BlockId, index: &AcirVar, value: &AcirVar, + predicate: &AcirVar, ) -> Result<(), InternalError> { // Fetch the witness corresponding to the index // @@ -1178,9 +1188,16 @@ impl AcirContext { // Fetch the witness corresponding to the value to be written let value_write_witness = self.var_to_witness(*value)?; + // Fetch the witness corresponding to the predicate + let predicate_witness = self.var_to_witness(*predicate)?; + // Add the memory write operation to the list of opcodes let op = MemOp::write_to_mem_index(index_witness.into(), value_write_witness.into()); - self.acir_ir.push_opcode(Opcode::MemoryOp { block_id, op }); + self.acir_ir.push_opcode(Opcode::MemoryOp { + block_id, + op, + predicate: Some(predicate_witness.into()), + }); Ok(()) } diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/mod.rs b/crates/noirc_evaluator/src/ssa/acir_gen/mod.rs index 313322d5d4f..762b7c8b607 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -378,7 +378,11 @@ impl Context { ); let index_var = index.into_var()?; - self.acir_context.read_from_memory(block_id, &index_var) + self.acir_context.read_from_memory( + block_id, + &index_var, + &self.current_side_effects_enabled_var, + ) }; for (lhs, rhs) in @@ -622,7 +626,11 @@ impl Context { } let index_var = self.convert_value(index, dfg).into_var()?; - let read = self.acir_context.read_from_memory(block_id, &index_var)?; + let read = self.acir_context.read_from_memory( + block_id, + &index_var, + &self.current_side_effects_enabled_var, + )?; let typ = match dfg.type_of_value(array) { Type::Array(typ, _) => { if typ.len() != 1 { @@ -703,7 +711,11 @@ impl Context { AcirType::NumericType(NumericType::NativeField), ); let var = index.into_var()?; - let read = self.acir_context.read_from_memory(block_id, &var)?; + let read = self.acir_context.read_from_memory( + block_id, + &var, + &self.current_side_effects_enabled_var, + )?; Ok(AcirValue::Var(read, AcirType::NumericType(NumericType::NativeField))) })?; self.initialize_array(result_block_id, len, Some(&init_values))?; @@ -712,7 +724,12 @@ impl Context { // Write the new value into the new array at the specified index let index_var = self.convert_value(index, dfg).into_var()?; let value_var = self.convert_value(store_value, dfg).into_var()?; - self.acir_context.write_to_memory(result_block_id, &index_var, &value_var)?; + self.acir_context.write_to_memory( + result_block_id, + &index_var, + &value_var, + &self.current_side_effects_enabled_var, + )?; let result_value = AcirValue::DynamicArray(AcirDynamicArray { block_id: result_block_id, len });