diff --git a/Cargo.lock b/Cargo.lock index 1cc8bc4a8c5..03bf41c73dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "acir" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0f4d70cd78f13cc17b2b16953af71d1a4fd0aa923cc35e6741c1f810eccdad" +checksum = "bed559b3e6e10a04b2a1af7a8b0f23d4bbaf4a87a6c8ac9946583f8945c53ce5" dependencies = [ "acir_field", "brillig_vm", @@ -18,9 +18,9 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74a1bdec0ba9ddb54d3337bb487a889dd212211a7daf6fe9fb175adf107eecdc" +checksum = "29adbffe34f7ae42e080833364f66ea0e933ca4aa3880e12444780538e1f6767" dependencies = [ "ark-bn254", "ark-ff", @@ -32,9 +32,9 @@ dependencies = [ [[package]] name = "acvm" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e27004072f628c96c5666068c0d9efae134423331859b60923265a017a5920b" +checksum = "c4808764cc92ba018210ec2f276f6d90908263af33f9a8abea6ae4139ba49aa0" dependencies = [ "acir", "acvm_stdlib", @@ -51,9 +51,9 @@ dependencies = [ [[package]] name = "acvm-backend-barretenberg" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a378e1d68ed47b4ed1af4533b455e01836d21bf27bde482e977edea0869f0b21" +checksum = "ca6b0dcd4fb93738eeb51a4558247c4dbacea4d3d5fd72842349638688d00ed6" dependencies = [ "acvm", "barretenberg-sys", @@ -71,9 +71,9 @@ dependencies = [ [[package]] name = "acvm_stdlib" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a16b18f0dc47de9c3f60eb320dda05b31355d7d4f76239f75852cc5a518db69e" +checksum = "57b0fea96f9ddc8866782636f1317aa0ac958ab7bc628fa9620a4915cc667edc" dependencies = [ "acir", ] @@ -513,12 +513,16 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae057025d1898257631c65c63071209dc41093cf9c0d77cdaae976798fa18b93" +checksum = "a9400d1493af661cba05923a5b4a78e3aeaeb4210b321831fc0461b01203191e" dependencies = [ "acir_field", + "blake2", + "k256", "serde", + "sha2", + "sha3", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index d720888dcde..4f2bc75528e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ edition = "2021" rust-version = "1.66" [workspace.dependencies] -acvm = "0.15.1" +acvm = "0.16.0" arena = { path = "crates/arena" } fm = { path = "crates/fm" } iter-extended = { path = "crates/iter-extended" } diff --git a/crates/nargo/src/ops/execute.rs b/crates/nargo/src/ops/execute.rs index c83d57beb4f..34c6105eb37 100644 --- a/crates/nargo/src/ops/execute.rs +++ b/crates/nargo/src/ops/execute.rs @@ -1,64 +1,62 @@ -use acvm::acir::circuit::Opcode; -use acvm::pwg::{solve, Blocks, PartialWitnessGeneratorStatus, UnresolvedBrilligCall}; -use acvm::PartialWitnessGenerator; +use acvm::acir::brillig_vm::ForeignCallResult; +use acvm::pwg::{ACVMStatus, ForeignCallWaitInfo, ACVM}; +use acvm::BlackBoxFunctionSolver; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; use crate::NargoError; -pub fn execute_circuit( - backend: &impl PartialWitnessGenerator, +pub fn execute_circuit( + _backend: &B, circuit: Circuit, - mut initial_witness: WitnessMap, + initial_witness: WitnessMap, ) -> Result { - let mut blocks = Blocks::default(); - let solver_status = solve(backend, &mut initial_witness, &mut blocks, circuit.opcodes)?; + let mut acvm = ACVM::new(B::default(), circuit.opcodes, initial_witness); - // TODO(#1615): Nargo only supports "oracle_print_**_impl" functions that print a singular value or an array and nothing else - // This should be expanded in a general logging refactor - if let PartialWitnessGeneratorStatus::RequiresOracleData { - unresolved_brillig_calls, - required_oracle_data, - unsolved_opcodes, - } = solver_status - { - if !required_oracle_data.is_empty() { - unreachable!("oracles are not supported by nargo execute") - } - for unresolved_brillig_call in unresolved_brillig_calls { - let UnresolvedBrilligCall { foreign_call_wait_info, mut brillig } = - unresolved_brillig_call; + loop { + let solver_status = acvm.solve(); - // Execute foreign calls - // TODO(#1615): "oracle_print_impl" and "oracle_print_array_impl" are just identity funcs - if foreign_call_wait_info.function == "oracle_print_impl" { - let values = &foreign_call_wait_info.inputs[0]; - println!("{:?}", values[0].to_field().to_hex()); - brillig.foreign_call_results.push(foreign_call_wait_info.inputs[0][0].into()); - } else if foreign_call_wait_info.function == "oracle_print_array_impl" { - let mut outputs_hex = Vec::new(); - for values in foreign_call_wait_info.inputs.clone() { - for value in values { - outputs_hex.push(value.to_field().to_hex()); - } + match solver_status { + ACVMStatus::Solved => break, + ACVMStatus::InProgress => { + unreachable!("Execution should not stop while in `InProgress` state.") + } + ACVMStatus::Failure(error) => return Err(error.into()), + ACVMStatus::RequiresForeignCall => { + while let Some(foreign_call) = acvm.get_pending_foreign_call() { + let foreign_call_result = execute_foreign_call(foreign_call); + acvm.resolve_pending_foreign_call(foreign_call_result); } - // Join all of the hex strings using a comma - let comma_separated_elements = outputs_hex.join(", "); - let output_witnesses_string = "[".to_owned() + &comma_separated_elements + "]"; - println!("{output_witnesses_string}"); - brillig.foreign_call_results.push(foreign_call_wait_info.inputs[0][0].into()); } + } + } - let mut next_opcodes_for_solving = vec![Opcode::Brillig(brillig)]; - next_opcodes_for_solving.extend_from_slice(&unsolved_opcodes[..]); + let solved_witness = acvm.finalize(); + Ok(solved_witness) +} - let solver_status = - solve(backend, &mut initial_witness, &mut blocks, next_opcodes_for_solving)?; - if matches!(solver_status, PartialWitnessGeneratorStatus::RequiresOracleData { .. }) { - todo!("Add multiple foreign call support to nargo execute") - // TODO 1557 +fn execute_foreign_call(foreign_call: &ForeignCallWaitInfo) -> ForeignCallResult { + // TODO(#1615): Nargo only supports "oracle_print_**_impl" functions that print a singular value or an array and nothing else + // This should be expanded in a general logging refactor + match foreign_call.function.as_str() { + "oracle_print_impl" => { + let values = &foreign_call.inputs[0]; + println!("{:?}", values[0].to_field().to_hex()); + values[0].into() + } + "oracle_print_array_impl" => { + let mut outputs_hex = Vec::new(); + for values in &foreign_call.inputs { + for value in values { + outputs_hex.push(value.to_field().to_hex()); + } } + // Join all of the hex strings using a comma + let comma_separated_elements = outputs_hex.join(", "); + let output_witnesses_string = "[".to_owned() + &comma_separated_elements + "]"; + println!("{output_witnesses_string}"); + + foreign_call.inputs[0][0].into() } + _ => panic!("unexpected foreign call type"), } - - Ok(initial_witness) } diff --git a/crates/nargo_cli/Cargo.toml b/crates/nargo_cli/Cargo.toml index f07f9677621..a6943695846 100644 --- a/crates/nargo_cli/Cargo.toml +++ b/crates/nargo_cli/Cargo.toml @@ -43,7 +43,7 @@ color-eyre = "0.6.2" tokio = { version = "1.0", features = ["io-std"] } # Backends -acvm-backend-barretenberg = { version = "0.5.1", default-features = false } +acvm-backend-barretenberg = { version = "0.6.0", default-features = false } [dev-dependencies] tempdir = "0.3.7" diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index 720f0f59ef4..3049fd4eef9 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -248,13 +248,7 @@ impl Driver { let mut errors = warnings; for contract in contracts { - match self.compile_contract( - contract, - // TODO: Remove clone when it implements Copy - np_language.clone(), - is_opcode_supported, - options, - ) { + match self.compile_contract(contract, np_language, is_opcode_supported, options) { Ok(contract) => compiled_contracts.push(contract), Err(mut more_errors) => errors.append(&mut more_errors), } @@ -303,8 +297,7 @@ impl Driver { let function = match self.compile_no_check( options, *function_id, - // TODO: Remove clone when it implements Copy - np_language.clone(), + np_language, is_opcode_supported, ) { Ok(function) => function, diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 7b6ac3ee1eb..acf490d74a0 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -10,7 +10,9 @@ use crate::ssa_refactor::ir::{ types::{NumericType, Type}, value::{Value, ValueId}, }; -use acvm::acir::brillig_vm::{BinaryFieldOp, BinaryIntOp, RegisterIndex, RegisterOrMemory}; +use acvm::acir::brillig_vm::{ + BinaryFieldOp, BinaryIntOp, HeapArray, RegisterIndex, RegisterOrMemory, +}; use acvm::FieldElement; use iter_extended::vecmap; @@ -440,7 +442,9 @@ impl<'block> BrilligBlock<'block> { let typ = dfg[value_id].get_type(); match typ { Type::Numeric(_) => RegisterOrMemory::RegisterIndex(register_index), - Type::Array(_, size) => RegisterOrMemory::HeapArray(register_index, size), + Type::Array(_, size) => { + RegisterOrMemory::HeapArray(HeapArray { pointer: register_index, size }) + } _ => { unreachable!("type not supported for conversion into brillig register") } diff --git a/crates/noirc_evaluator/src/brillig/brillig_ir.rs b/crates/noirc_evaluator/src/brillig/brillig_ir.rs index 439bf7220c2..f96d163703e 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_ir.rs @@ -714,8 +714,8 @@ mod tests { use std::vec; use acvm::acir::brillig_vm::{ - BinaryIntOp, ForeignCallOutput, ForeignCallResult, RegisterIndex, RegisterOrMemory, - Registers, VMStatus, Value, VM, + BinaryIntOp, ForeignCallOutput, ForeignCallResult, HeapVector, RegisterIndex, + RegisterOrMemory, Registers, VMStatus, Value, VM, }; use crate::brillig::brillig_ir::{BrilligContext, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE}; @@ -749,7 +749,7 @@ mod tests { context.foreign_call_instruction( "make_number_sequence".into(), &[RegisterOrMemory::RegisterIndex(r_input_size)], - &[RegisterOrMemory::HeapVector(r_stack, r_output_size)], + &[RegisterOrMemory::HeapVector(HeapVector { pointer: r_stack, size: r_output_size })], ); // push stack frame by r_returned_size context.binary_instruction( diff --git a/crates/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs b/crates/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs index d67e8d7b714..5c7cc6f4911 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs @@ -1,7 +1,9 @@ ///! This module contains functions for producing a higher level view disassembler of Brillig. use super::BrilligBinaryOp; use crate::brillig::brillig_ir::{ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE}; -use acvm::acir::brillig_vm::{BinaryFieldOp, BinaryIntOp, RegisterIndex, RegisterOrMemory, Value}; +use acvm::acir::brillig_vm::{ + BinaryFieldOp, BinaryIntOp, HeapArray, HeapVector, RegisterIndex, RegisterOrMemory, Value, +}; /// Controls whether debug traces are enabled const ENABLE_DEBUG_TRACE: bool = true; @@ -100,11 +102,11 @@ impl DebugToString for RegisterOrMemory { fn debug_to_string(&self) -> String { match self { RegisterOrMemory::RegisterIndex(index) => index.debug_to_string(), - RegisterOrMemory::HeapArray(index, size) => { - format!("{}[0..{}]", index.debug_to_string(), size) + RegisterOrMemory::HeapArray(HeapArray { pointer, size }) => { + format!("{}[0..{}]", pointer.debug_to_string(), size) } - RegisterOrMemory::HeapVector(index, size_register) => { - format!("{}[0..*{}]", index.debug_to_string(), size_register.debug_to_string()) + RegisterOrMemory::HeapVector(HeapVector { pointer, size }) => { + format!("{}[0..*{}]", pointer.debug_to_string(), size.debug_to_string()) } } } diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs index 829a48fef9d..142fb9e3479 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/intrinsics.rs @@ -130,13 +130,13 @@ pub(crate) fn evaluate( ctx.get_as_constant(args[1]).expect("domain separator to be comptime"); BlackBoxFuncCall::Pedersen { inputs: resolve_array(&args[0], acir_gen, ctx, evaluator), - outputs: outputs.to_vec(), + outputs: (outputs[0], outputs[1]), domain_separator: separator.to_u128() as u32, } } BlackBoxFunc::FixedBaseScalarMul => BlackBoxFuncCall::FixedBaseScalarMul { input: resolve_variable(&args[0], acir_gen, ctx, evaluator).unwrap(), - outputs: outputs.to_vec(), + outputs: (outputs[0], outputs[1]), }, BlackBoxFunc::SchnorrVerify => BlackBoxFuncCall::SchnorrVerify { public_key_x: resolve_variable(&args[0], acir_gen, ctx, evaluator).unwrap(), diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/operations/sort.rs b/crates/noirc_evaluator/src/ssa/acir_gen/operations/sort.rs index 535779b3bab..5ff717ae657 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/operations/sort.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/operations/sort.rs @@ -114,11 +114,9 @@ fn permutation_layer( #[cfg(test)] mod test { use acvm::{ - acir::{circuit::opcodes::FunctionInput, native_types::Witness, native_types::WitnessMap}, - pwg::{ - solve, Blocks, OpcodeResolution, OpcodeResolutionError, PartialWitnessGeneratorStatus, - }, - FieldElement, PartialWitnessGenerator, + acir::native_types::WitnessMap, + pwg::{ACVMStatus, OpcodeResolutionError, ACVM}, + BlackBoxFunctionSolver, FieldElement, }; use crate::{ @@ -128,33 +126,27 @@ mod test { use rand::prelude::*; struct MockBackend {} - impl PartialWitnessGenerator for MockBackend { + impl BlackBoxFunctionSolver for MockBackend { fn schnorr_verify( &self, - _initial_witness: &mut WitnessMap, - _public_key_x: &FunctionInput, - _public_key_y: &FunctionInput, - _signature: &[FunctionInput], - _message: &[FunctionInput], - _output: &Witness, - ) -> Result { + _public_key_x: &FieldElement, + _public_key_y: &FieldElement, + _signature: &[u8], + _message: &[u8], + ) -> Result { panic!("Path not trodden by this test") } fn pedersen( &self, - _initial_witness: &mut WitnessMap, - _inputs: &[FunctionInput], + _inputs: &[FieldElement], _domain_separator: u32, - _outputs: &[Witness], - ) -> Result { + ) -> Result<(FieldElement, FieldElement), OpcodeResolutionError> { panic!("Path not trodden by this test") } fn fixed_base_scalar_mul( &self, - _initial_witness: &mut WitnessMap, - _input: &FunctionInput, - _outputs: &[Witness], - ) -> Result { + _input: &FieldElement, + ) -> Result<(FieldElement, FieldElement), OpcodeResolutionError> { panic!("Path not trodden by this test") } } @@ -170,12 +162,12 @@ mod test { let mut input = Vec::new(); let mut a_val = Vec::new(); let mut b_wit = Vec::new(); - let mut solved_witness = WitnessMap::new(); + let mut initial_witness = WitnessMap::new(); for i in 0..n { let w = eval.add_witness_to_cs(); input.push(w.into()); a_val.push(FieldElement::from(rng.next_u32() as i128)); - solved_witness.insert(w, a_val[i]); + initial_witness.insert(w, a_val[i]); } let mut output = Vec::new(); @@ -196,15 +188,15 @@ mod test { } // initialize bits for i in 0..w.len() { - solved_witness.insert(w[i], FieldElement::from(c[i] as i128)); + initial_witness.insert(w[i], FieldElement::from(c[i] as i128)); } // compute the network output by solving the constraints let backend = MockBackend {}; - let mut blocks = Blocks::default(); - let solver_status = - solve(&backend, &mut solved_witness, &mut blocks, eval.opcodes.clone()) - .expect("Could not solve permutation constraints"); - assert_eq!(solver_status, PartialWitnessGeneratorStatus::Solved, "Incomplete solution"); + let mut acvm = ACVM::new(backend, eval.opcodes.clone(), initial_witness); + let solver_status = acvm.solve(); + assert_eq!(solver_status, ACVMStatus::Solved, "Incomplete solution"); + let solved_witness = acvm.finalize(); + let mut b_val = Vec::new(); for i in 0..output.len() { b_val.push(solved_witness[&b_wit[i]]); diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/generated_acir.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/generated_acir.rs index 73bb310eba9..174475bb5eb 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/generated_acir.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/generated_acir.rs @@ -231,7 +231,7 @@ impl GeneratedAcir { }, BlackBoxFunc::Pedersen => BlackBoxFuncCall::Pedersen { inputs, - outputs, + outputs: (outputs[0], outputs[1]), domain_separator: constants[0].to_u128() as u32, }, BlackBoxFunc::EcdsaSecp256k1 => BlackBoxFuncCall::EcdsaSecp256k1 { @@ -244,9 +244,10 @@ impl GeneratedAcir { hashed_message: inputs[128..].to_vec(), output: outputs[0], }, - BlackBoxFunc::FixedBaseScalarMul => { - BlackBoxFuncCall::FixedBaseScalarMul { input: inputs[0], outputs } - } + BlackBoxFunc::FixedBaseScalarMul => BlackBoxFuncCall::FixedBaseScalarMul { + input: inputs[0], + outputs: (outputs[0], outputs[1]), + }, BlackBoxFunc::Keccak256 => { let var_message_size = inputs.pop().expect("ICE: Missing message_size arg"); BlackBoxFuncCall::Keccak256VariableLength { inputs, var_message_size, outputs } @@ -319,7 +320,7 @@ impl GeneratedAcir { let max_power_of_two = FieldElement::from(2_i128).pow(&FieldElement::from(max_bit_size as i128 - 1)); let inter = &(&Expression::from_field(max_power_of_two) - lhs) * &leading.into(); - lhs.add_mul(FieldElement::from(2_i128), &inter) + lhs.add_mul(FieldElement::from(2_i128), &inter.unwrap()) } /// Signed division lhs / rhs @@ -374,7 +375,7 @@ impl GeneratedAcir { // Quotient sign is lhs sign * rhs sign, whose resulting sign bit is the XOR of the sign bits let q_sign = (&Expression::from(lhs_leading) + &Expression::from(rhs_leading)).add_mul( -FieldElement::from(2_i128), - &(&Expression::from(lhs_leading) * &Expression::from(rhs_leading)), + &(&Expression::from(lhs_leading) * &Expression::from(rhs_leading)).unwrap(), ); let q_sign_witness = self.get_or_create_witness(&q_sign); let quotient = self.two_complement(&q1.into(), q_sign_witness, max_bit_size); @@ -421,10 +422,10 @@ impl GeneratedAcir { // When the predicate is 0, the equation always passes. // When the predicate is 1, the euclidean division needs to be // true. - let mut rhs_constraint = rhs * &Expression::from(q_witness); + let mut rhs_constraint = (rhs * &Expression::from(q_witness)).unwrap(); rhs_constraint = &rhs_constraint + r_witness; - rhs_constraint = &rhs_constraint * predicate; - let lhs_constraint = lhs * predicate; + rhs_constraint = (&rhs_constraint * predicate).unwrap(); + let lhs_constraint = (lhs * predicate).unwrap(); let div_euclidean = &lhs_constraint - &rhs_constraint; self.push_opcode(AcirOpcode::Arithmetic(div_euclidean)); diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/sort.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/sort.rs index 02898bacde4..d645f683666 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/sort.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/sort.rs @@ -96,6 +96,6 @@ impl GeneratedAcir { } else { b }; - a_arith * b_arith + (a_arith * b_arith).expect("Both expressions are reduced to be degree<=1") } } diff --git a/crates/wasm/src/compile.rs b/crates/wasm/src/compile.rs index 18c9722e8ff..70b2c12f7c7 100644 --- a/crates/wasm/src/compile.rs +++ b/crates/wasm/src/compile.rs @@ -89,8 +89,7 @@ pub fn compile(args: JsValue) -> JsValue { if options.contracts { let compiled_contracts = driver .compile_contracts( - // TODO: Remove clone when it implements Copy - language.clone(), + language, #[allow(deprecated)] &acvm::pwg::default_is_opcode_supported(language), &options.compile_options, @@ -105,8 +104,7 @@ pub fn compile(args: JsValue) -> JsValue { .compile_no_check( &options.compile_options, main, - // TODO: Remove clone when it implements Copy - language.clone(), + language, #[allow(deprecated)] &acvm::pwg::default_is_opcode_supported(language), )