Skip to content

Commit

Permalink
Merge branch 'master' into docs/noir-codegen-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
critesjosh authored Apr 1, 2024
2 parents 7a855d5 + a0f7474 commit 6db6dc3
Show file tree
Hide file tree
Showing 96 changed files with 2,751 additions and 709 deletions.
2 changes: 1 addition & 1 deletion .aztec-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
a18288d9b8f3057b9e79362d922da656dacf22a9
bb719200034e3bc6db09fb56538dadca4203abf4
3 changes: 2 additions & 1 deletion .github/Cross.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
passthrough = [
"HOME",
"RUST_BACKTRACE",
"BARRETENBERG_BIN_DIR"
"BARRETENBERG_BIN_DIR",
"BLNS_JSON_PATH"
]
volumes = [
"HOME",
Expand Down
9 changes: 5 additions & 4 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions acvm-repo/acir/src/circuit/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ impl std::fmt::Display for Opcode {
}
Opcode::Call { id, inputs, outputs } => {
write!(f, "CALL func {}: ", id)?;
writeln!(f, "inputs: {:?}", inputs)?;
writeln!(f, "outputs: {:?}", outputs)
write!(f, "inputs: {:?}, ", inputs)?;
write!(f, "outputs: {:?}", outputs)
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions acvm-repo/acir/src/native_types/witness_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ pub struct StackItem {
pub witness: WitnessMap,
}

impl WitnessStack {
pub fn push(&mut self, index: u32, witness: WitnessMap) {
self.stack.push(StackItem { index, witness });
}

pub fn peek(&self) -> Option<&StackItem> {
self.stack.last()
}

pub fn length(&self) -> usize {
self.stack.len()
}
}

impl From<WitnessMap> for WitnessStack {
fn from(witness: WitnessMap) -> Self {
let stack = vec![StackItem { index: 0, witness }];
Expand Down
7 changes: 6 additions & 1 deletion acvm-repo/acvm/src/compiler/transformers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,12 @@ pub(super) fn transform_internal(
new_acir_opcode_positions.push(acir_opcode_positions[index]);
transformed_opcodes.push(opcode);
}
Opcode::Call { .. } => todo!("Handle Call opcodes in the ACVM"),
Opcode::Call { .. } => {
// `Call` does not write values to the `WitnessMap`
// A separate ACIR function should have its own respective `WitnessMap`
new_acir_opcode_positions.push(acir_opcode_positions[index]);
transformed_opcodes.push(opcode);
}
}
}

Expand Down
96 changes: 95 additions & 1 deletion acvm-repo/acvm/src/pwg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ pub enum ACVMStatus {
///
/// Once this is done, the ACVM can be restarted to solve the remaining opcodes.
RequiresForeignCall(ForeignCallWaitInfo),

/// The ACVM has encountered a request for an ACIR [call][acir::circuit::Opcode]
/// to execute a separate ACVM instance. The result of the ACIR call must be passd back to the ACVM.

Check warning on line 54 in acvm-repo/acvm/src/pwg/mod.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (passd)
///
/// Once this is done, the ACVM can be restarted to solve the remaining opcodes.
RequiresAcirCall(AcirCallWaitInfo),
}

impl std::fmt::Display for ACVMStatus {
Expand All @@ -58,6 +64,7 @@ impl std::fmt::Display for ACVMStatus {
ACVMStatus::InProgress => write!(f, "In progress"),
ACVMStatus::Failure(_) => write!(f, "Execution failure"),
ACVMStatus::RequiresForeignCall(_) => write!(f, "Waiting on foreign call"),
ACVMStatus::RequiresAcirCall(_) => write!(f, "Waiting on acir call"),
}
}
}
Expand Down Expand Up @@ -117,6 +124,10 @@ pub enum OpcodeResolutionError {
BlackBoxFunctionFailed(BlackBoxFunc, String),
#[error("Failed to solve brillig function, reason: {message}")]
BrilligFunctionFailed { message: String, call_stack: Vec<OpcodeLocation> },
#[error("Attempted to call `main` with a `Call` opcode")]
AcirMainCallAttempted { opcode_location: ErrorLocation },
#[error("{results_size:?} result values were provided for {outputs_size:?} call output witnesses, most likely due to bad ACIR codegen")]
AcirCallOutputsMismatch { opcode_location: ErrorLocation, results_size: u32, outputs_size: u32 },
}

impl From<BlackBoxResolutionError> for OpcodeResolutionError {
Expand Down Expand Up @@ -147,6 +158,13 @@ pub struct ACVM<'a, B: BlackBoxFunctionSolver> {
witness_map: WitnessMap,

brillig_solver: Option<BrilligSolver<'a, B>>,

/// A counter maintained throughout an ACVM process that determines
/// whether the caller has resolved the results of an ACIR [call][Opcode::Call].
acir_call_counter: usize,
/// Represents the outputs of all ACIR calls during an ACVM process
/// List is appended onto by the caller upon reaching a [ACVMStatus::RequiresAcirCall]
acir_call_results: Vec<Vec<FieldElement>>,
}

impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> {
Expand All @@ -161,6 +179,8 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> {
instruction_pointer: 0,
witness_map: initial_witness,
brillig_solver: None,
acir_call_counter: 0,
acir_call_results: Vec::default(),
}
}

Expand Down Expand Up @@ -244,6 +264,29 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> {
self.status(ACVMStatus::InProgress);
}

/// Sets the status of the VM to `RequiresAcirCall`
/// Indicating that the VM is now waiting for an ACIR call to be resolved
fn wait_for_acir_call(&mut self, acir_call: AcirCallWaitInfo) -> ACVMStatus {
self.status(ACVMStatus::RequiresAcirCall(acir_call))
}

/// Resolves an ACIR call's result (simply a list of fields) using a result calculated by a separate ACVM instance.
///
/// The current ACVM instance can then be restarted to solve the remaining ACIR opcodes.
pub fn resolve_pending_acir_call(&mut self, call_result: Vec<FieldElement>) {
if !matches!(self.status, ACVMStatus::RequiresAcirCall(_)) {
panic!("ACVM is not expecting an ACIR call response as no call was made");
}

if self.acir_call_counter < self.acir_call_results.len() {
panic!("No unresolved ACIR calls");
}
self.acir_call_results.push(call_result);

// Now that the ACIR call has been resolved then we can resume execution.
self.status(ACVMStatus::InProgress);
}

/// Executes the ACVM's circuit until execution halts.
///
/// Execution can halt due to three reasons:
Expand Down Expand Up @@ -281,7 +324,10 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> {
Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call),
res => res.map(|_| ()),
},
Opcode::Call { .. } => todo!("Handle Call opcodes in the ACVM"),
Opcode::Call { .. } => match self.solve_call_opcode() {
Ok(Some(input_values)) => return self.wait_for_acir_call(input_values),
res => res.map(|_| ()),
},
};
self.handle_opcode_resolution(resolution)
}
Expand Down Expand Up @@ -400,6 +446,46 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> {
self.brillig_solver = Some(solver);
self.solve_opcode()
}

pub fn solve_call_opcode(&mut self) -> Result<Option<AcirCallWaitInfo>, OpcodeResolutionError> {
let Opcode::Call { id, inputs, outputs } = &self.opcodes[self.instruction_pointer] else {
unreachable!("Not executing a Call opcode");
};
if *id == 0 {
return Err(OpcodeResolutionError::AcirMainCallAttempted {
opcode_location: ErrorLocation::Resolved(OpcodeLocation::Acir(
self.instruction_pointer(),
)),
});
}

if self.acir_call_counter >= self.acir_call_results.len() {
let mut initial_witness = WitnessMap::default();
for (i, input_witness) in inputs.iter().enumerate() {
let input_value = *witness_to_value(&self.witness_map, *input_witness)?;
initial_witness.insert(Witness(i as u32), input_value);
}
return Ok(Some(AcirCallWaitInfo { id: *id, initial_witness }));
}

let result_values = &self.acir_call_results[self.acir_call_counter];
if outputs.len() != result_values.len() {
return Err(OpcodeResolutionError::AcirCallOutputsMismatch {
opcode_location: ErrorLocation::Resolved(OpcodeLocation::Acir(
self.instruction_pointer(),
)),
results_size: result_values.len() as u32,
outputs_size: outputs.len() as u32,
});
}

for (output_witness, result_value) in outputs.iter().zip(result_values) {
insert_value(output_witness, *result_value, &mut self.witness_map)?;
}

self.acir_call_counter += 1;
Ok(None)
}
}

// Returns the concrete value for a particular witness
Expand Down Expand Up @@ -469,3 +555,11 @@ fn any_witness_from_expression(expr: &Expression) -> Option<Witness> {
Some(expr.linear_combinations[0].1)
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct AcirCallWaitInfo {
/// Index in the list of ACIR function's that should be called
pub id: u32,
/// Initial witness for the given circuit to be called
pub initial_witness: WitnessMap,
}
3 changes: 3 additions & 0 deletions acvm-repo/acvm_js/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ pub async fn execute_circuit_with_black_box_solver(

acvm.resolve_pending_foreign_call(result);
}
ACVMStatus::RequiresAcirCall(_) => {
todo!("Handle acir calls in acvm JS");
}
}
}

Expand Down
21 changes: 14 additions & 7 deletions compiler/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,22 @@
#![warn(unreachable_pub)]
#![warn(clippy::semicolon_if_nothing_returned)]

use acvm::acir::circuit::{ExpressionWidth, Program};
use acvm::acir::circuit::ExpressionWidth;
use clap::Args;
use fm::{FileId, FileManager};
use iter_extended::vecmap;
use noirc_abi::{AbiParameter, AbiType, ContractEvent};
use noirc_errors::{CustomDiagnostic, FileDiagnostic};
use noirc_evaluator::create_circuit;
use noirc_evaluator::create_program;
use noirc_evaluator::errors::RuntimeError;
use noirc_frontend::debug::build_debug_crate_file;
use noirc_frontend::graph::{CrateId, CrateName};
use noirc_frontend::hir::def_map::{Contract, CrateDefMap};
use noirc_frontend::hir::Context;
use noirc_frontend::macros_api::MacroProcessor;
use noirc_frontend::monomorphization::{monomorphize, monomorphize_debug, MonomorphizationError};
use noirc_frontend::monomorphization::{
errors::MonomorphizationError, monomorphize, monomorphize_debug,
};
use noirc_frontend::node_interner::FuncId;
use noirc_frontend::token::SecondaryAttribute;
use std::path::Path;
Expand Down Expand Up @@ -482,7 +484,8 @@ pub fn compile_no_check(
return Ok(cached_program.expect("cache must exist for hashes to match"));
}
let visibility = program.return_visibility;
let (circuit, debug, input_witnesses, return_witnesses, warnings) = create_circuit(

let (program, debug, warnings, input_witnesses, return_witnesses) = create_program(
program,
options.show_ssa,
options.show_brillig,
Expand All @@ -492,13 +495,17 @@ pub fn compile_no_check(

let abi =
abi_gen::gen_abi(context, &main_function, input_witnesses, return_witnesses, visibility);
let file_map = filter_relevant_files(&[debug.clone()], &context.file_manager);
let file_map = filter_relevant_files(&debug, &context.file_manager);

Ok(CompiledProgram {
hash,
// TODO(https://github.com/noir-lang/noir/issues/4428)
program: Program { functions: vec![circuit] },
debug,
program,
// TODO(https://github.com/noir-lang/noir/issues/4428)
// Debug info is only relevant for errors at execution time which is not yet supported
// The CompileProgram `debug` field is used in multiple places and is better
// left to be updated once execution of multiple ACIR functions is enabled
debug: debug[0].clone(),
abi,
file_map,
noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,8 +373,9 @@ mod tests {
use crate::ssa::ssa_gen::Ssa;

fn create_test_environment() -> (Ssa, FunctionContext, BrilligContext) {
let builder =
FunctionBuilder::new("main".to_string(), Id::test_new(0), RuntimeType::Brillig);
let mut builder = FunctionBuilder::new("main".to_string(), Id::test_new(0));
builder.set_runtime(RuntimeType::Brillig);

let ssa = builder.finish();
let mut brillig_context = create_context();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,8 @@ mod test {
// }

let main_id = Id::test_new(1);
let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Brillig);
let mut builder = FunctionBuilder::new("main".into(), main_id);
builder.set_runtime(RuntimeType::Brillig);

let b1 = builder.insert_block();
let b2 = builder.insert_block();
Expand Down Expand Up @@ -425,7 +426,8 @@ mod test {
// }

let main_id = Id::test_new(1);
let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Brillig);
let mut builder = FunctionBuilder::new("main".into(), main_id);
builder.set_runtime(RuntimeType::Brillig);

let b1 = builder.insert_block();
let b2 = builder.insert_block();
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ pub mod ssa;

pub mod brillig;

pub use ssa::create_circuit;
pub use ssa::create_program;
Loading

0 comments on commit 6db6dc3

Please sign in to comment.