Skip to content

Commit

Permalink
feat!: update to ACVM 0.16.0
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench committed Jul 5, 2023
1 parent e55b5a8 commit 753e52f
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 107 deletions.
22 changes: 10 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,6 @@ wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] }
wasm-bindgen-test = "0.3.33"

[patch.crates-io]
acvm = { git = "https://github.com/noir-lang/acvm", rev = "f1c7940f4ac618c7b440b6ed30199f85cbe72cca" }
acvm-backend-barretenberg = { git = "https://github.com/noir-lang/acvm-backend-barretenberg", rev = "c1575d20d9e7c664e71a79512ad3329c0d8a6a4d" }
async-lsp = { git = "https://github.com/oxalica/async-lsp", rev = "09dbcc11046f7a188a80137f8d36484d86c78c78" }
90 changes: 43 additions & 47 deletions crates/nargo/src/ops/execute.rs
Original file line number Diff line number Diff line change
@@ -1,64 +1,60 @@
use acvm::acir::circuit::Opcode;
use acvm::pwg::{solve, Blocks, PartialWitnessGeneratorStatus, UnresolvedBrilligCall};
use acvm::PartialWitnessGenerator;
use acvm::acir::brillig_vm::ForeignCallResult;
use acvm::pwg::{ForeignCallWaitInfo, PartialWitnessGeneratorStatus, 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<B: BlackBoxFunctionSolver + Default>(
_backend: &B,
circuit: Circuit,
mut initial_witness: WitnessMap,
initial_witness: WitnessMap,
) -> Result<WitnessMap, NargoError> {
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());
}
}
// 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());
match solver_status {
PartialWitnessGeneratorStatus::Solved => break,
PartialWitnessGeneratorStatus::RequiresForeignCall => {
let foreign_call =
acvm.get_pending_foreign_call().expect("Should be waiting on a foreign call");

let foreign_call_result = execute_foreign_call(foreign_call);
acvm.resolve_pending_foreign_call(foreign_call_result);
}
}
}

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): "oracle_print_impl" and "oracle_print_array_impl" are just identity funcs
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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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")
}
Expand Down
6 changes: 3 additions & 3 deletions crates/noirc_evaluator/src/brillig/brillig_ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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(
Expand Down
12 changes: 7 additions & 5 deletions crates/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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())
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
48 changes: 20 additions & 28 deletions crates/noirc_evaluator/src/ssa/acir_gen/operations/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{OpcodeResolutionError, PartialWitnessGeneratorStatus, ACVM},
BlackBoxFunctionSolver, FieldElement,
};

use crate::{
Expand All @@ -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<OpcodeResolution, OpcodeResolutionError> {
_public_key_x: &FieldElement,
_public_key_y: &FieldElement,
_signature: &[u8],
_message: &[u8],
) -> Result<bool, OpcodeResolutionError> {
panic!("Path not trodden by this test")
}
fn pedersen(
&self,
_initial_witness: &mut WitnessMap,
_inputs: &[FunctionInput],
_inputs: &[FieldElement],
_domain_separator: u32,
_outputs: &[Witness],
) -> Result<OpcodeResolution, OpcodeResolutionError> {
) -> 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<OpcodeResolution, OpcodeResolutionError> {
_input: &FieldElement,
) -> Result<(FieldElement, FieldElement), OpcodeResolutionError> {
panic!("Path not trodden by this test")
}
}
Expand All @@ -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();
Expand All @@ -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");
let acvm = ACVM::new(backend, eval.opcodes.clone(), initial_witness);
let solver_status = acvm.solve().expect("Could not solve permutation constraints");
assert_eq!(solver_status, PartialWitnessGeneratorStatus::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]]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 }
Expand Down Expand Up @@ -346,10 +347,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));
Expand Down
Loading

0 comments on commit 753e52f

Please sign in to comment.