Skip to content

Commit

Permalink
chore!: Update to ACVM 0.12.0 (#1339)
Browse files Browse the repository at this point in the history
* chore!: Update to ACVM 0.12.0

* feat: adapted to heterogeneous bb calls

* chore: update cargo tomls

* test: re enabled sort test

* fix: improve variable resolution

* feat: use dummy constructor for bb call

* updates for latest

* feat!: Move WitnessMap type into ACVM to avoid leaking BTreeMap type

* feat(nargo): Consume CommonReferenceString functions & manage caching (#1348)

* switch to published acvm and backend

* fix compilation issue

* chore: Remove usage of `acvm::default_is_opcode_supported` (#1366)

Co-authored-by: Blaine Bublitz <blaine.bublitz@gmail.com>
Co-authored-by: Tom French <tom@tomfren.ch>

* add issue numbers to TODOs

* chore: deduplicate driver setup logic

* chore: clippy

---------

Co-authored-by: sirasistant <sirasistant@gmail.com>
Co-authored-by: Tom French <tom@tomfren.ch>
Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
Co-authored-by: Maxim Vezenov <mvezenov@gmail.com>
  • Loading branch information
5 people committed May 24, 2023
1 parent a21b251 commit b938c7e
Show file tree
Hide file tree
Showing 31 changed files with 666 additions and 393 deletions.
267 changes: 102 additions & 165 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ edition = "2021"
rust-version = "1.66"

[workspace.dependencies]
acvm = "0.11.0"
acvm = "0.12.0"
arena = { path = "crates/arena" }
fm = { path = "crates/fm" }
iter-extended = { path = "crates/iter-extended" }
Expand Down
1 change: 0 additions & 1 deletion crates/nargo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ rustc_version = "0.4.0"
acvm.workspace = true
noirc_abi.workspace = true
noirc_driver.workspace = true
iter-extended.workspace = true
toml.workspace = true
serde.workspace = true
thiserror.workspace = true
3 changes: 2 additions & 1 deletion crates/nargo/src/ops/codegen_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use acvm::SmartContract;

pub fn codegen_verifier<B: SmartContract>(
backend: &B,
common_reference_string: &[u8],
verification_key: &[u8],
) -> Result<String, B::Error> {
backend.eth_contract_from_vk(verification_key)
backend.eth_contract_from_vk(common_reference_string, verification_key)
}
8 changes: 4 additions & 4 deletions crates/nargo/src/ops/execute.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use acvm::{acir::circuit::Circuit, pwg::block::Blocks};
use acvm::{PartialWitnessGenerator, PartialWitnessGeneratorStatus};
use noirc_abi::WitnessMap;
use acvm::pwg::{solve, PartialWitnessGeneratorStatus};
use acvm::PartialWitnessGenerator;
use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap, pwg::block::Blocks};

use crate::NargoError;

Expand All @@ -10,7 +10,7 @@ pub fn execute_circuit(
mut initial_witness: WitnessMap,
) -> Result<WitnessMap, NargoError> {
let mut blocks = Blocks::default();
let solver_status = backend.solve(&mut initial_witness, &mut blocks, circuit.opcodes)?;
let solver_status = solve(backend, &mut initial_witness, &mut blocks, circuit.opcodes)?;
if matches!(solver_status, PartialWitnessGeneratorStatus::RequiresOracleData { .. }) {
todo!("Add oracle support to nargo execute")
}
Expand Down
2 changes: 1 addition & 1 deletion crates/nargo/src/ops/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub use self::codegen_verifier::codegen_verifier;
pub use self::execute::execute_circuit;
pub use self::preprocess::{preprocess_contract, preprocess_program};
pub use self::preprocess::{preprocess_contract_function, preprocess_program};
pub use self::prove::prove_execution;
pub use self::verify::verify_proof;

Expand Down
52 changes: 22 additions & 30 deletions crates/nargo/src/ops/preprocess.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
use acvm::ProofSystemCompiler;
use iter_extended::try_vecmap;
use noirc_driver::{CompiledContract, CompiledProgram};
use noirc_driver::{CompiledProgram, ContractFunction};

use crate::artifacts::{
contract::{PreprocessedContract, PreprocessedContractFunction},
program::PreprocessedProgram,
};
use crate::artifacts::{contract::PreprocessedContractFunction, program::PreprocessedProgram};

// TODO: pull this from backend.
// TODO(#1388): pull this from backend.
const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg";

pub fn preprocess_program<B: ProofSystemCompiler>(
backend: &B,
common_reference_string: &[u8],
compiled_program: CompiledProgram,
) -> Result<PreprocessedProgram, B::Error> {
// TODO: currently `compiled_program`'s bytecode is already optimized for the backend.
// In future we'll need to apply those optimizations here.
let optimized_bytecode = compiled_program.circuit;
let (proving_key, verification_key) = backend.preprocess(&optimized_bytecode)?;
let (proving_key, verification_key) =
backend.preprocess(common_reference_string, &optimized_bytecode)?;

Ok(PreprocessedProgram {
backend: String::from(BACKEND_IDENTIFIER),
Expand All @@ -28,30 +26,24 @@ pub fn preprocess_program<B: ProofSystemCompiler>(
})
}

pub fn preprocess_contract<B: ProofSystemCompiler>(
pub fn preprocess_contract_function<B: ProofSystemCompiler>(
backend: &B,
compiled_contract: CompiledContract,
) -> Result<PreprocessedContract, B::Error> {
let preprocessed_contract_functions = try_vecmap(compiled_contract.functions, |func| {
// TODO: currently `func`'s bytecode is already optimized for the backend.
// In future we'll need to apply those optimizations here.
let optimized_bytecode = func.bytecode;
let (proving_key, verification_key) = backend.preprocess(&optimized_bytecode)?;

Ok(PreprocessedContractFunction {
name: func.name,
function_type: func.function_type,
abi: func.abi,
common_reference_string: &[u8],
func: ContractFunction,
) -> Result<PreprocessedContractFunction, B::Error> {
// TODO: currently `func`'s bytecode is already optimized for the backend.
// In future we'll need to apply those optimizations here.
let optimized_bytecode = func.bytecode;
let (proving_key, verification_key) =
backend.preprocess(common_reference_string, &optimized_bytecode)?;

bytecode: optimized_bytecode,
proving_key,
verification_key,
})
})?;
Ok(PreprocessedContractFunction {
name: func.name,
function_type: func.function_type,
abi: func.abi,

Ok(PreprocessedContract {
name: compiled_contract.name,
backend: String::from(BACKEND_IDENTIFIER),
functions: preprocessed_contract_functions,
bytecode: optimized_bytecode,
proving_key,
verification_key,
})
}
6 changes: 3 additions & 3 deletions crates/nargo/src/ops/prove.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use acvm::acir::circuit::Circuit;
use acvm::acir::{circuit::Circuit, native_types::WitnessMap};
use acvm::ProofSystemCompiler;
use noirc_abi::WitnessMap;

pub fn prove_execution<B: ProofSystemCompiler>(
backend: &B,
common_reference_string: &[u8],
circuit: &Circuit,
solved_witness: WitnessMap,
proving_key: &[u8],
) -> Result<Vec<u8>, B::Error> {
backend.prove_with_pk(circuit, solved_witness, proving_key)
backend.prove_with_pk(common_reference_string, circuit, solved_witness, proving_key)
}
6 changes: 3 additions & 3 deletions crates/nargo/src/ops/verify.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use acvm::acir::circuit::Circuit;
use acvm::acir::{circuit::Circuit, native_types::WitnessMap};
use acvm::ProofSystemCompiler;
use noirc_abi::WitnessMap;

pub fn verify_proof<B: ProofSystemCompiler>(
backend: &B,
common_reference_string: &[u8],
circuit: &Circuit,
proof: &[u8],
public_inputs: WitnessMap,
verification_key: &[u8],
) -> Result<bool, B::Error> {
backend.verify_with_vk(proof, public_inputs, circuit, verification_key)
backend.verify_with_vk(common_reference_string, proof, public_inputs, circuit, verification_key)
}
3 changes: 2 additions & 1 deletion crates/nargo_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ hex = "0.4.2"
serde_json = "1.0"
termcolor = "1.1.2"
color-eyre = "0.6.2"
tokio = "1.0"

# Backends
acvm-backend-barretenberg = { version = "0.1.2", default-features = false }
acvm-backend-barretenberg = { version = "0.2.0", default-features = false }

[dev-dependencies]
tempdir = "0.3.7"
Expand Down
15 changes: 5 additions & 10 deletions crates/nargo_cli/src/cli/check_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::{errors::CliError, resolver::Resolver};
use crate::errors::CliError;
use acvm::Backend;
use clap::Args;
use iter_extended::btree_map;
use noirc_abi::{AbiParameter, AbiType, MAIN_RETURN_NAME};
use noirc_driver::CompileOptions;
use std::path::{Path, PathBuf};

use super::fs::write_to_file;
use super::NargoConfig;
use super::{compile_cmd::setup_driver, fs::write_to_file};
use crate::constants::{PROVER_INPUT_FILE, VERIFIER_INPUT_FILE};

/// Checks the constraint system for errors
Expand All @@ -29,15 +29,10 @@ pub(crate) fn run<B: Backend>(

fn check_from_path<B: Backend, P: AsRef<Path>>(
backend: &B,
p: P,
program_dir: P,
compile_options: &CompileOptions,
) -> Result<(), CliError<B>> {
let mut driver = Resolver::resolve_root_manifest(
p.as_ref(),
backend.np_language(),
#[allow(deprecated)]
Box::new(acvm::default_is_opcode_supported(backend.np_language())),
)?;
let mut driver = setup_driver(backend, program_dir.as_ref())?;

driver.check_crate(compile_options).map_err(|_| CliError::CompilationError)?;

Expand All @@ -47,7 +42,7 @@ fn check_from_path<B: Backend, P: AsRef<Path>>(
// For now it is hard-coded to be toml.
//
// Check for input.toml and verifier.toml
let path_to_root = PathBuf::from(p.as_ref());
let path_to_root = PathBuf::from(program_dir.as_ref());
let path_to_prover_input = path_to_root.join(format!("{PROVER_INPUT_FILE}.toml"));
let path_to_verifier_input = path_to_root.join(format!("{VERIFIER_INPUT_FILE}.toml"));

Expand Down
42 changes: 34 additions & 8 deletions crates/nargo_cli/src/cli/codegen_verifier_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
use super::fs::{create_named_dir, program::read_program_from_file, write_to_file};
use super::fs::{
common_reference_string::{
read_cached_common_reference_string, update_common_reference_string,
write_cached_common_reference_string,
},
create_named_dir,
program::read_program_from_file,
write_to_file,
};
use super::NargoConfig;
use crate::{
cli::compile_cmd::compile_circuit, constants::CONTRACT_DIR, constants::TARGET_DIR,
Expand Down Expand Up @@ -29,18 +37,36 @@ pub(crate) fn run<B: Backend>(
.circuit_name
.map(|circuit_name| config.program_dir.join(TARGET_DIR).join(circuit_name));

let preprocessed_program = match circuit_build_path {
Some(circuit_build_path) => read_program_from_file(circuit_build_path)?,
let common_reference_string = read_cached_common_reference_string();

let (common_reference_string, preprocessed_program) = match circuit_build_path {
Some(circuit_build_path) => {
let program = read_program_from_file(circuit_build_path)?;
let common_reference_string = update_common_reference_string(
backend,
&common_reference_string,
&program.bytecode,
)
.map_err(CliError::CommonReferenceStringError)?;
(common_reference_string, program)
}
None => {
let compiled_program =
let program =
compile_circuit(backend, config.program_dir.as_ref(), &args.compile_options)?;
preprocess_program(backend, compiled_program)
.map_err(CliError::ProofSystemCompilerError)?
let common_reference_string =
update_common_reference_string(backend, &common_reference_string, &program.circuit)
.map_err(CliError::CommonReferenceStringError)?;
let program = preprocess_program(backend, &common_reference_string, program)
.map_err(CliError::ProofSystemCompilerError)?;
(common_reference_string, program)
}
};

let smart_contract_string = codegen_verifier(backend, &preprocessed_program.verification_key)
.map_err(CliError::SmartContractError)?;
let smart_contract_string =
codegen_verifier(backend, &common_reference_string, &preprocessed_program.verification_key)
.map_err(CliError::SmartContractError)?;

write_cached_common_reference_string(&common_reference_string);

let contract_dir = config.program_dir.join(CONTRACT_DIR);
create_named_dir(&contract_dir, "contract");
Expand Down
63 changes: 52 additions & 11 deletions crates/nargo_cli/src/cli/compile_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
use acvm::Backend;
use iter_extended::try_vecmap;
use nargo::artifacts::contract::PreprocessedContract;
use noirc_driver::{CompileOptions, CompiledProgram, Driver};
use std::path::Path;

use clap::Args;

use nargo::ops::{preprocess_contract, preprocess_program};
use nargo::ops::{preprocess_contract_function, preprocess_program};

use crate::resolver::DependencyResolutionError;
use crate::{constants::TARGET_DIR, errors::CliError, resolver::Resolver};

use super::fs::program::{save_contract_to_file, save_program_to_file};
use super::fs::{
common_reference_string::{
read_cached_common_reference_string, update_common_reference_string,
write_cached_common_reference_string,
},
program::{save_contract_to_file, save_program_to_file},
};
use super::NargoConfig;

// TODO(#1388): pull this from backend.
const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg";

/// Compile the program and its secret execution trace into ACIR format
#[derive(Debug, Clone, Args)]
pub(crate) struct CompileCommand {
Expand All @@ -34,16 +44,40 @@ pub(crate) fn run<B: Backend>(
) -> Result<(), CliError<B>> {
let circuit_dir = config.program_dir.join(TARGET_DIR);

let mut common_reference_string = read_cached_common_reference_string();

// If contracts is set we're compiling every function in a 'contract' rather than just 'main'.
if args.contracts {
let mut driver = setup_driver(backend, &config.program_dir)?;
let compiled_contracts = driver
.compile_contracts(&args.compile_options)
.map_err(|_| CliError::CompilationError)?;
let preprocessed_contracts = try_vecmap(compiled_contracts, |contract| {
preprocess_contract(backend, contract).map_err(CliError::ProofSystemCompilerError)
})?;
for contract in preprocessed_contracts {

// TODO(#1389): I wonder if it is incorrect for nargo-core to know anything about contracts.
// As can be seen here, It seems like a leaky abstraction where ContractFunctions (essentially CompiledPrograms)
// are compiled via nargo-core and then the PreprocessedContract is constructed here.
// This is due to EACH function needing it's own CRS, PKey, and VKey from the backend.
let preprocessed_contracts: Result<Vec<PreprocessedContract>, CliError<B>> =
try_vecmap(compiled_contracts, |contract| {
let preprocessed_contract_functions = try_vecmap(contract.functions, |func| {
common_reference_string = update_common_reference_string(
backend,
&common_reference_string,
&func.bytecode,
)
.map_err(CliError::CommonReferenceStringError)?;

preprocess_contract_function(backend, &common_reference_string, func)
.map_err(CliError::ProofSystemCompilerError)
})?;

Ok(PreprocessedContract {
name: contract.name,
backend: String::from(BACKEND_IDENTIFIER),
functions: preprocessed_contract_functions,
})
});
for contract in preprocessed_contracts? {
save_contract_to_file(
&contract,
&format!("{}-{}", &args.circuit_name, contract.name),
Expand All @@ -52,22 +86,29 @@ pub(crate) fn run<B: Backend>(
}
} else {
let program = compile_circuit(backend, &config.program_dir, &args.compile_options)?;
let preprocessed_program =
preprocess_program(backend, program).map_err(CliError::ProofSystemCompilerError)?;
common_reference_string =
update_common_reference_string(backend, &common_reference_string, &program.circuit)
.map_err(CliError::CommonReferenceStringError)?;

let preprocessed_program = preprocess_program(backend, &common_reference_string, program)
.map_err(CliError::ProofSystemCompilerError)?;
save_program_to_file(&preprocessed_program, &args.circuit_name, circuit_dir);
}

write_cached_common_reference_string(&common_reference_string);

Ok(())
}

fn setup_driver<B: Backend>(
pub(super) fn setup_driver<B: Backend>(
backend: &B,
program_dir: &Path,
) -> Result<Driver, DependencyResolutionError> {
Resolver::resolve_root_manifest(
program_dir,
backend.np_language(),
#[allow(deprecated)]
Box::new(acvm::default_is_opcode_supported(backend.np_language())),
// TODO(#1102): Remove need for driver to be aware of backend.
Box::new(|op| B::default().supports_opcode(op)),
)
}

Expand Down
Loading

0 comments on commit b938c7e

Please sign in to comment.