diff --git a/crates/noirc_evaluator/src/ssa_refactor.rs b/crates/noirc_evaluator/src/ssa_refactor.rs index fa3b7f05a86..6326b45554d 100644 --- a/crates/noirc_evaluator/src/ssa_refactor.rs +++ b/crates/noirc_evaluator/src/ssa_refactor.rs @@ -77,10 +77,16 @@ pub fn create_circuit( show_output: bool, ) -> Result<(Circuit, DebugInfo, Abi), RuntimeError> { let func_sig = program.main_function_signature.clone(); - let GeneratedAcir { current_witness_index, opcodes, return_witnesses, locations, .. } = - optimize_into_acir(program, show_output, enable_ssa_logging, enable_brillig_logging)?; + let GeneratedAcir { + current_witness_index, + opcodes, + return_witnesses, + locations, + input_witnesses, + .. + } = optimize_into_acir(program, show_output, enable_ssa_logging, enable_brillig_logging)?; - let abi = gen_abi(func_sig, return_witnesses.clone()); + let abi = gen_abi(func_sig, &input_witnesses, return_witnesses.clone()); let public_abi = abi.clone().public_abi(); let public_parameters = diff --git a/crates/noirc_evaluator/src/ssa_refactor/abi_gen/mod.rs b/crates/noirc_evaluator/src/ssa_refactor/abi_gen/mod.rs index db39b1c8110..778d8aba8d5 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/abi_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/abi_gen/mod.rs @@ -1,14 +1,18 @@ use std::collections::BTreeMap; use acvm::acir::native_types::Witness; -use iter_extended::{btree_map, vecmap}; +use iter_extended::btree_map; use noirc_abi::{Abi, AbiParameter, FunctionSignature}; /// Arranges a function signature and a generated circuit's return witnesses into a /// `noirc_abi::Abi`. -pub(crate) fn gen_abi(func_sig: FunctionSignature, return_witnesses: Vec) -> Abi { +pub(crate) fn gen_abi( + func_sig: FunctionSignature, + input_witnesses: &[Witness], + return_witnesses: Vec, +) -> Abi { let (parameters, return_type) = func_sig; - let param_witnesses = param_witnesses_from_abi_param(¶meters); + let param_witnesses = param_witnesses_from_abi_param(¶meters, input_witnesses); Abi { parameters, return_type, param_witnesses, return_witnesses } } @@ -16,14 +20,17 @@ pub(crate) fn gen_abi(func_sig: FunctionSignature, return_witnesses: Vec, + input_witnesses: &[Witness], ) -> BTreeMap> { - let mut offset = 1; + let mut idx = 0_usize; + btree_map(abi_params, |param| { let num_field_elements_needed = param.typ.field_count(); - let idx_start = offset; - let idx_end = idx_start + num_field_elements_needed; - let witnesses = vecmap(idx_start..idx_end, Witness); - offset += num_field_elements_needed; - (param.name.clone(), witnesses) + let mut wit = Vec::new(); + for _ in 0..num_field_elements_needed { + wit.push(input_witnesses[idx]); + idx += 1; + } + (param.name.clone(), wit) }) } diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/acir_variable.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/acir_variable.rs index 8c7fe1e9b6a..d953322e567 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/acir_variable.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/acir_variable.rs @@ -110,6 +110,26 @@ pub(crate) struct AcirContext { } impl AcirContext { + pub(crate) fn current_witness_index(&self) -> Witness { + self.acir_ir.current_witness_index() + } + + pub(crate) fn extract_witness(&self, inputs: &[AcirValue]) -> Vec { + inputs + .iter() + .flat_map(|value| value.clone().flatten()) + .map(|value| { + self.vars + .get(&value.0) + .expect("ICE: undeclared AcirVar") + .to_expression() + .to_witness() + .expect("ICE - cannot extract a witness") + .0 + }) + .collect() + } + /// Adds a constant to the context and assigns a Variable to represent it pub(crate) fn add_constant(&mut self, constant: FieldElement) -> AcirVar { let constant_data = AcirVarData::Const(constant); @@ -808,7 +828,8 @@ impl AcirContext { } /// Terminates the context and takes the resulting `GeneratedAcir` - pub(crate) fn finish(self) -> GeneratedAcir { + pub(crate) fn finish(mut self, inputs: Vec) -> GeneratedAcir { + self.acir_ir.input_witnesses = vecmap(inputs, Witness); self.acir_ir } 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 d80537a074a..459458fc03e 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 @@ -40,6 +40,9 @@ pub(crate) struct GeneratedAcir { /// abi's return type. pub(crate) return_witnesses: Vec, + /// All witness indices which are inputs to the main function + pub(crate) input_witnesses: Vec, + /// Correspondance between an opcode index (in opcodes) and the source code location which generated it pub(crate) locations: HashMap, diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs index 3bf18a2d86a..ad10bed96f9 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs @@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet}; use std::fmt::Debug; +use std::ops::RangeInclusive; use crate::brillig::brillig_ir::BrilligContext; use crate::{ @@ -172,8 +173,7 @@ impl Context { ) -> Result { let dfg = &main_func.dfg; let entry_block = &dfg[main_func.entry_block()]; - - self.convert_ssa_block_params(entry_block.parameters(), dfg)?; + let input_witness = self.convert_ssa_block_params(entry_block.parameters(), dfg)?; for instruction_id in entry_block.instructions() { self.convert_ssa_instruction(*instruction_id, dfg, ssa, &brillig, allow_log_ops)?; @@ -181,7 +181,7 @@ impl Context { self.convert_ssa_return(entry_block.unwrap_terminator(), dfg); - Ok(self.acir_context.finish()) + Ok(self.acir_context.finish(input_witness.collect())) } fn convert_brillig_main( @@ -195,6 +195,7 @@ impl Context { let typ = dfg.type_of_value(*param_id); self.create_value_from_type(&typ, &mut |this, _| Ok(this.acir_context.add_variable())) })?; + let witness_inputs = self.acir_context.extract_witness(&inputs); let outputs: Vec = vecmap(main_func.returns(), |result_id| dfg.type_of_value(*result_id).into()); @@ -213,7 +214,7 @@ impl Context { self.acir_context.return_var(acir_var); } - Ok(self.acir_context.finish()) + Ok(self.acir_context.finish(witness_inputs)) } /// Adds and binds `AcirVar`s for each numeric block parameter or block parameter array element. @@ -221,7 +222,9 @@ impl Context { &mut self, params: &[ValueId], dfg: &DataFlowGraph, - ) -> Result<(), AcirGenError> { + ) -> Result, AcirGenError> { + // The first witness (if any) is the next one + let start_witness = self.acir_context.current_witness_index().0 + 1; for param_id in params { let typ = dfg.type_of_value(*param_id); let value = self.convert_ssa_block_param(&typ)?; @@ -238,7 +241,8 @@ impl Context { } self.ssa_values.insert(*param_id, value); } - Ok(()) + let end_witness = self.acir_context.current_witness_index().0; + Ok(start_witness..=end_witness) } fn convert_ssa_block_param(&mut self, param_type: &Type) -> Result {