Skip to content

Commit

Permalink
chore: Rename NpLanguage to ExpressionWidth (#3834)
Browse files Browse the repository at this point in the history
# Description


NpLanguage does not encapsulate what we want to describe here. We simply
want to specify an expression width and a particular backend will need
to decide as to what configuration their backend supports.

To elaborate, imagine a new np language came out which was popular;
before this PR, we may need to add in another variant. However, with
this change, the new backend will just target whatever width makes sense
for this new proving system.

## Problem\*

Resolves <!-- Link to GitHub Issue -->

## Summary\*



## Additional Context



## Documentation\*

Check one:
- [ ] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[Exceptional Case]** Documentation to be submitted in a separate
PR.

# PR Checklist\*

- [ ] I have tested the changes locally.
- [ ] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
  • Loading branch information
kevaundray authored Dec 18, 2023
1 parent 3fae4a0 commit 426fc34
Show file tree
Hide file tree
Showing 18 changed files with 118 additions and 95 deletions.
9 changes: 6 additions & 3 deletions acvm-repo/acvm/src/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::HashMap;

use acir::circuit::{Circuit, OpcodeLocation};

use crate::Language;
use crate::ExpressionWidth;

// The various passes that we can use over ACIR
mod optimizers;
Expand Down Expand Up @@ -69,11 +69,14 @@ fn transform_assert_messages(
}

/// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`].
pub fn compile(acir: Circuit, np_language: Language) -> (Circuit, AcirTransformationMap) {
pub fn compile(
acir: Circuit,
expression_width: ExpressionWidth,
) -> (Circuit, AcirTransformationMap) {
let (acir, acir_opcode_positions) = optimize_internal(acir);

let (mut acir, acir_opcode_positions) =
transform_internal(acir, np_language, acir_opcode_positions);
transform_internal(acir, expression_width, acir_opcode_positions);

let transformation_map = AcirTransformationMap::new(acir_opcode_positions);

Expand Down
2 changes: 1 addition & 1 deletion acvm-repo/acvm/src/compiler/transformers/csat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use indexmap::IndexMap;
/// A transformer which processes any [`Expression`]s to break them up such that they
/// fit within the [`ProofSystemCompiler`][crate::ProofSystemCompiler]'s width.
///
/// This transformer is only used when targetting the [`PLONKCSat`][crate::Language::PLONKCSat] language.
/// This transformer is only used when targeting the [`Bounded`][crate::ExpressionWidth::Bounded] configuration.
///
/// This is done by creating intermediate variables to hold partial calculations and then combining them
/// to calculate the original expression.
Expand Down
17 changes: 10 additions & 7 deletions acvm-repo/acvm/src/compiler/transformers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use acir::{
};
use indexmap::IndexMap;

use crate::Language;
use crate::ExpressionWidth;

mod csat;
mod r1cs;
Expand All @@ -16,13 +16,16 @@ pub(crate) use r1cs::R1CSTransformer;
use super::{transform_assert_messages, AcirTransformationMap};

/// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`].
pub fn transform(acir: Circuit, np_language: Language) -> (Circuit, AcirTransformationMap) {
pub fn transform(
acir: Circuit,
expression_width: ExpressionWidth,
) -> (Circuit, AcirTransformationMap) {
// Track original acir opcode positions throughout the transformation passes of the compilation
// by applying the modifications done to the circuit opcodes and also to the opcode_positions (delete and insert)
let acir_opcode_positions = acir.opcodes.iter().enumerate().map(|(i, _)| i).collect();

let (mut acir, acir_opcode_positions) =
transform_internal(acir, np_language, acir_opcode_positions);
transform_internal(acir, expression_width, acir_opcode_positions);

let transformation_map = AcirTransformationMap::new(acir_opcode_positions);

Expand All @@ -36,17 +39,17 @@ pub fn transform(acir: Circuit, np_language: Language) -> (Circuit, AcirTransfor
/// Accepts an injected `acir_opcode_positions` to allow transformations to be applied directly after optimizations.
pub(super) fn transform_internal(
acir: Circuit,
np_language: Language,
expression_width: ExpressionWidth,
acir_opcode_positions: Vec<usize>,
) -> (Circuit, Vec<usize>) {
log::trace!("Start circuit transformation");

let mut transformer = match &np_language {
crate::Language::R1CS => {
let mut transformer = match &expression_width {
crate::ExpressionWidth::Unbounded => {
let transformer = R1CSTransformer::new(acir);
return (transformer.transform(), acir_opcode_positions);
}
crate::Language::PLONKCSat { width } => {
crate::ExpressionWidth::Bounded { width } => {
let mut csat = CSatTransformer::new(*width);
for value in acir.circuit_arguments() {
csat.mark_solvable(value);
Expand Down
16 changes: 11 additions & 5 deletions acvm-repo/acvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@ pub use brillig_vm;
// re-export blackbox solver
pub use acvm_blackbox_solver as blackbox_solver;

/// Supported NP complete languages
/// This might need to be in ACIR instead
/// Specifies the maximum width of the expressions which will be constrained.
///
/// Unbounded Expressions are useful if you are eventually going to pass the ACIR
/// into a proving system which supports R1CS.
///
/// Bounded Expressions are useful if you are eventually going to pass the ACIR
/// into a proving system which supports PLONK, where arithmetic expressions have a
/// finite fan-in.
#[derive(Debug, Clone, Copy)]
pub enum Language {
R1CS,
PLONKCSat { width: usize },
pub enum ExpressionWidth {
Unbounded,
Bounded { width: usize },
}
8 changes: 4 additions & 4 deletions compiler/wasm/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ pub fn compile(

let compile_options = CompileOptions::default();

// For now we default to plonk width = 3, though we can add it as a parameter
let np_language = acvm::Language::PLONKCSat { width: 3 };
// For now we default to a bounded width of 3, though we can add it as a parameter
let expression_width = acvm::ExpressionWidth::Bounded { width: 3 };

if contracts.unwrap_or_default() {
let compiled_contract = compile_contract(&mut context, crate_id, &compile_options)
Expand All @@ -192,7 +192,7 @@ pub fn compile(
})?
.0;

let optimized_contract = nargo::ops::optimize_contract(compiled_contract, np_language);
let optimized_contract = nargo::ops::optimize_contract(compiled_contract, expression_width);

let compile_output = preprocess_contract(optimized_contract);
Ok(JsCompileResult::new(compile_output))
Expand All @@ -207,7 +207,7 @@ pub fn compile(
})?
.0;

let optimized_program = nargo::ops::optimize_program(compiled_program, np_language);
let optimized_program = nargo::ops::optimize_program(compiled_program, expression_width);

let compile_output = preprocess_program(optimized_program);
Ok(JsCompileResult::new(compile_output))
Expand Down
4 changes: 2 additions & 2 deletions compiler/wasm/src/compile_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl CompilerContext {
program_width: usize,
) -> Result<JsCompileResult, JsCompileError> {
let compile_options = CompileOptions::default();
let np_language = acvm::Language::PLONKCSat { width: program_width };
let np_language = acvm::ExpressionWidth::Bounded { width: program_width };

let root_crate_id = *self.context.root_crate_id();

Expand All @@ -115,7 +115,7 @@ impl CompilerContext {
program_width: usize,
) -> Result<JsCompileResult, JsCompileError> {
let compile_options = CompileOptions::default();
let np_language = acvm::Language::PLONKCSat { width: program_width };
let np_language = acvm::ExpressionWidth::Bounded { width: program_width };
let root_crate_id = *self.context.root_crate_id();

let compiled_contract =
Expand Down
18 changes: 9 additions & 9 deletions tooling/backend_interface/src/cli/info.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use acvm::Language;
use acvm::ExpressionWidth;
use serde::Deserialize;
use std::path::{Path, PathBuf};

Expand Down Expand Up @@ -28,7 +28,7 @@ struct LanguageResponse {
}

impl InfoCommand {
pub(crate) fn run(self, binary_path: &Path) -> Result<Language, BackendError> {
pub(crate) fn run(self, binary_path: &Path) -> Result<ExpressionWidth, BackendError> {
let mut command = std::process::Command::new(binary_path);

command.arg("info").arg("-c").arg(self.crs_path).arg("-o").arg("-");
Expand All @@ -41,16 +41,16 @@ impl InfoCommand {

let backend_info: InfoResponse =
serde_json::from_slice(&output.stdout).expect("Backend should return valid json");
let language: Language = match backend_info.language.name.as_str() {
let expression_width: ExpressionWidth = match backend_info.language.name.as_str() {
"PLONK-CSAT" => {
let width = backend_info.language.width.unwrap();
Language::PLONKCSat { width }
ExpressionWidth::Bounded { width }
}
"R1CS" => Language::R1CS,
_ => panic!("Unknown langauge"),
"R1CS" => ExpressionWidth::Unbounded,
_ => panic!("Unknown Expression width configuration"),
};

Ok(language)
Ok(expression_width)
}
}

Expand All @@ -59,9 +59,9 @@ fn info_command() -> Result<(), BackendError> {
let backend = crate::get_mock_backend()?;
let crs_path = backend.backend_directory();

let language = InfoCommand { crs_path }.run(backend.binary_path())?;
let expression_width = InfoCommand { crs_path }.run(backend.binary_path())?;

assert!(matches!(language, Language::PLONKCSat { width: 3 }));
assert!(matches!(expression_width, ExpressionWidth::Bounded { width: 3 }));

Ok(())
}
18 changes: 10 additions & 8 deletions tooling/backend_interface/src/proof_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::io::Write;
use std::path::Path;

use acvm::acir::{circuit::Circuit, native_types::WitnessMap};
use acvm::ExpressionWidth;
use acvm::FieldElement;
use acvm::Language;
use tempfile::tempdir;

use crate::cli::{
Expand All @@ -30,20 +30,22 @@ impl Backend {
.run(binary_path)
}

pub fn get_backend_info(&self) -> Result<Language, BackendError> {
pub fn get_backend_info(&self) -> Result<ExpressionWidth, BackendError> {
let binary_path = self.assert_binary_exists()?;
self.assert_correct_version()?;
InfoCommand { crs_path: self.crs_directory() }.run(binary_path)
}

/// If we cannot get a valid backend, returns Plonk with width 3
/// If we cannot get a valid backend, returns `ExpressionWidth::Bound { width: 3 }``
/// The function also prints a message saying we could not find a backend
pub fn get_backend_info_or_default(&self) -> Language {
if let Ok(language) = self.get_backend_info() {
language
pub fn get_backend_info_or_default(&self) -> ExpressionWidth {
if let Ok(expression_width) = self.get_backend_info() {
expression_width
} else {
log::warn!("No valid backend found, defaulting to Plonk with width 3");
Language::PLONKCSat { width: 3 }
log::warn!(
"No valid backend found, ExpressionWidth defaulting to Bounded with a width of 3"
);
ExpressionWidth::Bounded { width: 3 }
}
}

Expand Down
6 changes: 3 additions & 3 deletions tooling/lsp/src/requests/profile_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{
future::{self, Future},
};

use acvm::Language;
use acvm::ExpressionWidth;
use async_lsp::{ErrorCode, ResponseError};
use nargo::artifacts::debug::DebugArtifact;
use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection};
Expand Down Expand Up @@ -57,13 +57,13 @@ fn on_profile_run_request_inner(
.cloned()
.partition(|package| package.is_binary());

let np_language = Language::PLONKCSat { width: 3 };
let expression_width = ExpressionWidth::Bounded { width: 3 };

let (compiled_programs, compiled_contracts) = nargo::ops::compile_workspace(
&workspace,
&binary_packages,
&contract_packages,
np_language,
expression_width,
&CompileOptions::default(),
)
.map_err(|err| ResponseError::new(ErrorCode::REQUEST_FAILED, err))?;
Expand Down
16 changes: 8 additions & 8 deletions tooling/nargo/src/ops/compile.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use acvm::Language;
use acvm::ExpressionWidth;
use fm::FileManager;
use noirc_driver::{CompilationResult, CompileOptions, CompiledContract, CompiledProgram};

Expand All @@ -17,18 +17,18 @@ pub fn compile_workspace(
workspace: &Workspace,
binary_packages: &[Package],
contract_packages: &[Package],
np_language: Language,
expression_width: ExpressionWidth,
compile_options: &CompileOptions,
) -> Result<(Vec<CompiledProgram>, Vec<CompiledContract>), CompileError> {
// Compile all of the packages in parallel.
let program_results: Vec<(FileManager, CompilationResult<CompiledProgram>)> = binary_packages
.par_iter()
.map(|package| compile_program(workspace, package, compile_options, np_language))
.map(|package| compile_program(workspace, package, compile_options, expression_width))
.collect();
let contract_results: Vec<(FileManager, CompilationResult<CompiledContract>)> =
contract_packages
.par_iter()
.map(|package| compile_contract(package, compile_options, np_language))
.map(|package| compile_contract(package, compile_options, expression_width))
.collect();

// Report any warnings/errors which were encountered during compilation.
Expand Down Expand Up @@ -62,7 +62,7 @@ pub fn compile_program(
workspace: &Workspace,
package: &Package,
compile_options: &CompileOptions,
np_language: Language,
expression_width: ExpressionWidth,
) -> (FileManager, CompilationResult<CompiledProgram>) {
let (mut context, crate_id) = prepare_package(package);

Expand All @@ -79,15 +79,15 @@ pub fn compile_program(
};

// Apply backend specific optimizations.
let optimized_program = crate::ops::optimize_program(program, np_language);
let optimized_program = crate::ops::optimize_program(program, expression_width);

(context.file_manager, Ok((optimized_program, warnings)))
}

fn compile_contract(
package: &Package,
compile_options: &CompileOptions,
np_language: Language,
expression_width: ExpressionWidth,
) -> (FileManager, CompilationResult<CompiledContract>) {
let (mut context, crate_id) = prepare_package(package);
let (contract, warnings) =
Expand All @@ -98,7 +98,7 @@ fn compile_contract(
}
};

let optimized_contract = crate::ops::optimize_contract(contract, np_language);
let optimized_contract = crate::ops::optimize_contract(contract, expression_width);

(context.file_manager, Ok((optimized_contract, warnings)))
}
Expand Down
17 changes: 12 additions & 5 deletions tooling/nargo/src/ops/optimize.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
use acvm::Language;
use acvm::ExpressionWidth;
use iter_extended::vecmap;
use noirc_driver::{CompiledContract, CompiledProgram};

pub fn optimize_program(mut program: CompiledProgram, np_language: Language) -> CompiledProgram {
let (optimized_circuit, location_map) = acvm::compiler::compile(program.circuit, np_language);
pub fn optimize_program(
mut program: CompiledProgram,
expression_width: ExpressionWidth,
) -> CompiledProgram {
let (optimized_circuit, location_map) =
acvm::compiler::compile(program.circuit, expression_width);

program.circuit = optimized_circuit;
program.debug.update_acir(location_map);
program
}

pub fn optimize_contract(contract: CompiledContract, np_language: Language) -> CompiledContract {
pub fn optimize_contract(
contract: CompiledContract,
expression_width: ExpressionWidth,
) -> CompiledContract {
let functions = vecmap(contract.functions, |mut func| {
let (optimized_bytecode, location_map) =
acvm::compiler::compile(func.bytecode, np_language);
acvm::compiler::compile(func.bytecode, expression_width);
func.bytecode = optimized_bytecode;
func.debug.update_acir(location_map);
func
Expand Down
Loading

0 comments on commit 426fc34

Please sign in to comment.