From da473685524fc6e5e17f9c3eb95116378ac41fb8 Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Fri, 12 May 2023 06:23:19 +0100 Subject: [PATCH] chore!: Update to acvm 0.11.0 (#1322) * chore!: Update to acvm 0.11.0 * chore: Update nargo core to return backend errors * chore: Make CliError generic over a Backend chore!: Split filesystem errors off from CliError chore!: Make all run functions take a backend and pass it from the CLI entry * update to latest commit * chore: replace long `Backend` type parameters with `B` * fix grep problems * remove unneeded import * latest master * chore: update `acvm-backend-barretenberg` to 0.1.0 commit * chore: use `try_vecmap` in old `vecmap` locations * chore: add missing `?` * official release of backend --------- Co-authored-by: Tom French --- Cargo.lock | 24 +++++++------ Cargo.toml | 2 +- crates/nargo/src/ops/codegen_verifier.rs | 10 +++--- crates/nargo/src/ops/preprocess.rs | 35 +++++++++---------- crates/nargo/src/ops/prove.rs | 12 +++---- crates/nargo/src/ops/verify.rs | 12 +++---- crates/nargo_cli/Cargo.toml | 2 +- crates/nargo_cli/src/cli/check_cmd.rs | 27 +++++++++----- .../nargo_cli/src/cli/codegen_verifier_cmd.rs | 17 +++++---- crates/nargo_cli/src/cli/compile_cmd.rs | 32 +++++++++-------- crates/nargo_cli/src/cli/execute_cmd.rs | 27 +++++++------- crates/nargo_cli/src/cli/fs/inputs.rs | 8 ++--- crates/nargo_cli/src/cli/fs/mod.rs | 10 +++--- crates/nargo_cli/src/cli/fs/program.rs | 7 ++-- crates/nargo_cli/src/cli/fs/proof.rs | 4 +-- crates/nargo_cli/src/cli/fs/witness.rs | 4 +-- crates/nargo_cli/src/cli/gates_cmd.rs | 23 +++++++----- crates/nargo_cli/src/cli/mod.rs | 25 +++++++------ crates/nargo_cli/src/cli/new_cmd.rs | 10 ++++-- crates/nargo_cli/src/cli/print_acir_cmd.rs | 18 ++++++---- crates/nargo_cli/src/cli/prove_cmd.rs | 29 +++++++++------ crates/nargo_cli/src/cli/test_cmd.rs | 28 ++++++++------- crates/nargo_cli/src/cli/verify_cmd.rs | 23 +++++++----- crates/nargo_cli/src/errors.rs | 35 ++++++++++++++----- 24 files changed, 244 insertions(+), 180 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 176a8450b3f..c7a30e3adc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "acir" -version = "0.10.3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "510b65efd4d20bf266185ce0a5dc7d29bcdd196a6a1835c20908fd88040de76c" +checksum = "084577e67b44c72d1cdfabe286d48adac6f5e0ad441ef134c5c467f4b6eee291" dependencies = [ "acir_field", "flate2", @@ -16,9 +16,9 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.10.3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f032e710c67fd146caedc8fe1dea6e95f01ab59453e42d59b604a51fef3dfe" +checksum = "a267ef529f4b132293199ecdf8c232ade817f01d916039f2d34562cab39e75e9" dependencies = [ "ark-bn254", "ark-ff", @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "acvm" -version = "0.10.3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2611266039740ffd1978f23258bd6ce3166c22cf15b8227685c2f3bb20ae2ee0" +checksum = "4e1d6795105b50b13fa0dd1779b5191c4d8e9cd98b357b0b9a0b04a847baacf0" dependencies = [ "acir", "acvm_stdlib", @@ -43,13 +43,15 @@ dependencies = [ "num-bigint", "num-traits", "sha2 0.9.9", + "sha3", "thiserror", ] [[package]] name = "acvm-backend-barretenberg" -version = "0.0.0" -source = "git+https://github.com/noir-lang/aztec_backend?rev=677f10e07011849f8aa0d75fe80390bb3081b1e5#677f10e07011849f8aa0d75fe80390bb3081b1e5" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf493c97da8c528c21353452aa10f7972f4870a3aab90919bcc08ba56a8cd8" dependencies = [ "acvm", "barretenberg-sys", @@ -61,16 +63,16 @@ dependencies = [ "pkg-config", "reqwest", "rust-embed", - "sha3", + "thiserror", "tokio", "wasmer", ] [[package]] name = "acvm_stdlib" -version = "0.10.3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ec51160c66eba75dc15a028a2391675386fd395b3897478d89a386c64a48dd" +checksum = "3131af53d17ac12340c0ff50f8555d8e040321f8078b8ee3cd8846560b6a44a9" dependencies = [ "acir", ] diff --git a/Cargo.toml b/Cargo.toml index badaab032ce..4169aa9b6eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ edition = "2021" rust-version = "1.66" [workspace.dependencies] -acvm = "0.10.3" +acvm = "0.11.0" arena = { path = "crates/arena" } fm = { path = "crates/fm" } iter-extended = { path = "crates/iter-extended" } diff --git a/crates/nargo/src/ops/codegen_verifier.rs b/crates/nargo/src/ops/codegen_verifier.rs index ead125699b4..2a0b54df865 100644 --- a/crates/nargo/src/ops/codegen_verifier.rs +++ b/crates/nargo/src/ops/codegen_verifier.rs @@ -1,10 +1,8 @@ use acvm::SmartContract; -use crate::NargoError; - -pub fn codegen_verifier( - backend: &impl SmartContract, +pub fn codegen_verifier( + backend: &B, verification_key: &[u8], -) -> Result { - Ok(backend.eth_contract_from_vk(verification_key)) +) -> Result { + backend.eth_contract_from_vk(verification_key) } diff --git a/crates/nargo/src/ops/preprocess.rs b/crates/nargo/src/ops/preprocess.rs index f8d4eb5a825..3be8151f9c9 100644 --- a/crates/nargo/src/ops/preprocess.rs +++ b/crates/nargo/src/ops/preprocess.rs @@ -1,26 +1,23 @@ use acvm::ProofSystemCompiler; -use iter_extended::vecmap; +use iter_extended::try_vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; -use crate::{ - artifacts::{ - contract::{PreprocessedContract, PreprocessedContractFunction}, - program::PreprocessedProgram, - }, - NargoError, +use crate::artifacts::{ + contract::{PreprocessedContract, PreprocessedContractFunction}, + program::PreprocessedProgram, }; // TODO: pull this from backend. const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg"; -pub fn preprocess_program( - backend: &impl ProofSystemCompiler, +pub fn preprocess_program( + backend: &B, compiled_program: CompiledProgram, -) -> Result { +) -> Result { // 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(&optimized_bytecode)?; Ok(PreprocessedProgram { backend: String::from(BACKEND_IDENTIFIER), @@ -31,17 +28,17 @@ pub fn preprocess_program( }) } -pub fn preprocess_contract( - backend: &impl ProofSystemCompiler, +pub fn preprocess_contract( + backend: &B, compiled_contract: CompiledContract, -) -> Result { - let preprocessed_contract_functions = vecmap(compiled_contract.functions, |func| { +) -> Result { + 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); + let (proving_key, verification_key) = backend.preprocess(&optimized_bytecode)?; - PreprocessedContractFunction { + Ok(PreprocessedContractFunction { name: func.name, function_type: func.function_type, abi: func.abi, @@ -49,8 +46,8 @@ pub fn preprocess_contract( bytecode: optimized_bytecode, proving_key, verification_key, - } - }); + }) + })?; Ok(PreprocessedContract { name: compiled_contract.name, diff --git a/crates/nargo/src/ops/prove.rs b/crates/nargo/src/ops/prove.rs index 376220a8a74..80771bc9cb7 100644 --- a/crates/nargo/src/ops/prove.rs +++ b/crates/nargo/src/ops/prove.rs @@ -2,15 +2,11 @@ use acvm::acir::circuit::Circuit; use acvm::ProofSystemCompiler; use noirc_abi::WitnessMap; -use crate::NargoError; - -pub fn prove_execution( - backend: &impl ProofSystemCompiler, +pub fn prove_execution( + backend: &B, circuit: &Circuit, solved_witness: WitnessMap, proving_key: &[u8], -) -> Result, NargoError> { - let proof = backend.prove_with_pk(circuit, solved_witness, proving_key); - - Ok(proof) +) -> Result, B::Error> { + backend.prove_with_pk(circuit, solved_witness, proving_key) } diff --git a/crates/nargo/src/ops/verify.rs b/crates/nargo/src/ops/verify.rs index 5109d2291db..cd76fbd430e 100644 --- a/crates/nargo/src/ops/verify.rs +++ b/crates/nargo/src/ops/verify.rs @@ -2,16 +2,12 @@ use acvm::acir::circuit::Circuit; use acvm::ProofSystemCompiler; use noirc_abi::WitnessMap; -use crate::NargoError; - -pub fn verify_proof( - backend: &impl ProofSystemCompiler, +pub fn verify_proof( + backend: &B, circuit: &Circuit, proof: &[u8], public_inputs: WitnessMap, verification_key: &[u8], -) -> Result { - let valid_proof = backend.verify_with_vk(proof, public_inputs, circuit, verification_key); - - Ok(valid_proof) +) -> Result { + backend.verify_with_vk(proof, public_inputs, circuit, verification_key) } diff --git a/crates/nargo_cli/Cargo.toml b/crates/nargo_cli/Cargo.toml index 6e8801301b1..74db54c8ef7 100644 --- a/crates/nargo_cli/Cargo.toml +++ b/crates/nargo_cli/Cargo.toml @@ -37,7 +37,7 @@ termcolor = "1.1.2" color-eyre = "0.6.2" # Backends -acvm-backend-barretenberg = { git = "https://github.com/noir-lang/aztec_backend", rev = "677f10e07011849f8aa0d75fe80390bb3081b1e5", default-features = false } +acvm-backend-barretenberg = { version = "0.1.2", default-features = false } [dev-dependencies] tempdir = "0.3.7" diff --git a/crates/nargo_cli/src/cli/check_cmd.rs b/crates/nargo_cli/src/cli/check_cmd.rs index 3049c830def..9664930466b 100644 --- a/crates/nargo_cli/src/cli/check_cmd.rs +++ b/crates/nargo_cli/src/cli/check_cmd.rs @@ -1,5 +1,5 @@ use crate::{errors::CliError, resolver::Resolver}; -use acvm::ProofSystemCompiler; +use acvm::Backend; use clap::Args; use iter_extended::btree_map; use noirc_abi::{AbiParameter, AbiType, MAIN_RETURN_NAME}; @@ -17,15 +17,21 @@ pub(crate) struct CheckCommand { compile_options: CompileOptions, } -pub(crate) fn run(args: CheckCommand, config: NargoConfig) -> Result<(), CliError> { - check_from_path(config.program_dir, &args.compile_options)?; +pub(crate) fn run( + backend: &B, + args: CheckCommand, + config: NargoConfig, +) -> Result<(), CliError> { + check_from_path(backend, config.program_dir, &args.compile_options)?; println!("Constraint system successfully built!"); Ok(()) } -fn check_from_path>(p: P, compile_options: &CompileOptions) -> Result<(), CliError> { - let backend = crate::backends::ConcreteBackend::default(); - +fn check_from_path>( + backend: &B, + p: P, + compile_options: &CompileOptions, +) -> Result<(), CliError> { let mut driver = Resolver::resolve_root_manifest(p.as_ref(), backend.np_language())?; driver.check_crate(compile_options).map_err(|_| CliError::CompilationError)?; @@ -148,12 +154,13 @@ d2 = ["", "", ""] let pass_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(format!("{TEST_DATA_DIR}/pass")); + let backend = crate::backends::ConcreteBackend::default(); let config = CompileOptions::default(); let paths = std::fs::read_dir(pass_dir).unwrap(); for path in paths.flatten() { let path = path.path(); assert!( - super::check_from_path(path.clone(), &config).is_ok(), + super::check_from_path(&backend, path.clone(), &config).is_ok(), "path: {}", path.display() ); @@ -166,12 +173,13 @@ d2 = ["", "", ""] let fail_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(format!("{TEST_DATA_DIR}/fail")); + let backend = crate::backends::ConcreteBackend::default(); let config = CompileOptions::default(); let paths = std::fs::read_dir(fail_dir).unwrap(); for path in paths.flatten() { let path = path.path(); assert!( - super::check_from_path(path.clone(), &config).is_err(), + super::check_from_path(&backend, path.clone(), &config).is_err(), "path: {}", path.display() ); @@ -183,13 +191,14 @@ d2 = ["", "", ""] let pass_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join(format!("{TEST_DATA_DIR}/pass_dev_mode")); + let backend = crate::backends::ConcreteBackend::default(); let config = CompileOptions { allow_warnings: true, ..Default::default() }; let paths = std::fs::read_dir(pass_dir).unwrap(); for path in paths.flatten() { let path = path.path(); assert!( - super::check_from_path(path.clone(), &config).is_ok(), + super::check_from_path(&backend, path.clone(), &config).is_ok(), "path: {}", path.display() ); diff --git a/crates/nargo_cli/src/cli/codegen_verifier_cmd.rs b/crates/nargo_cli/src/cli/codegen_verifier_cmd.rs index f23502a15b5..d38433e2d1c 100644 --- a/crates/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/crates/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -4,6 +4,7 @@ use crate::{ cli::compile_cmd::compile_circuit, constants::CONTRACT_DIR, constants::TARGET_DIR, errors::CliError, }; +use acvm::Backend; use clap::Args; use nargo::ops::{codegen_verifier, preprocess_program}; use noirc_driver::CompileOptions; @@ -18,9 +19,11 @@ pub(crate) struct CodegenVerifierCommand { compile_options: CompileOptions, } -pub(crate) fn run(args: CodegenVerifierCommand, config: NargoConfig) -> Result<(), CliError> { - let backend = crate::backends::ConcreteBackend::default(); - +pub(crate) fn run( + backend: &B, + args: CodegenVerifierCommand, + config: NargoConfig, +) -> Result<(), CliError> { // TODO(#1201): Should this be a utility function? let circuit_build_path = args .circuit_name @@ -30,12 +33,14 @@ pub(crate) fn run(args: CodegenVerifierCommand, config: NargoConfig) -> Result<( Some(circuit_build_path) => read_program_from_file(circuit_build_path)?, None => { let compiled_program = - compile_circuit(&backend, config.program_dir.as_ref(), &args.compile_options)?; - preprocess_program(&backend, compiled_program)? + compile_circuit(backend, config.program_dir.as_ref(), &args.compile_options)?; + preprocess_program(backend, compiled_program) + .map_err(CliError::ProofSystemCompilerError)? } }; - let smart_contract_string = codegen_verifier(&backend, &preprocessed_program.verification_key)?; + let smart_contract_string = codegen_verifier(backend, &preprocessed_program.verification_key) + .map_err(CliError::SmartContractError)?; let contract_dir = config.program_dir.join(CONTRACT_DIR); create_named_dir(&contract_dir, "contract"); diff --git a/crates/nargo_cli/src/cli/compile_cmd.rs b/crates/nargo_cli/src/cli/compile_cmd.rs index 78b52003166..531560b87db 100644 --- a/crates/nargo_cli/src/cli/compile_cmd.rs +++ b/crates/nargo_cli/src/cli/compile_cmd.rs @@ -1,4 +1,4 @@ -use acvm::ProofSystemCompiler; +use acvm::Backend; use iter_extended::try_vecmap; use noirc_driver::{CompileOptions, CompiledProgram, Driver}; use std::path::Path; @@ -27,19 +27,22 @@ pub(crate) struct CompileCommand { compile_options: CompileOptions, } -pub(crate) fn run(args: CompileCommand, config: NargoConfig) -> Result<(), CliError> { +pub(crate) fn run( + backend: &B, + args: CompileCommand, + config: NargoConfig, +) -> Result<(), CliError> { let circuit_dir = config.program_dir.join(TARGET_DIR); - let backend = crate::backends::ConcreteBackend::default(); - // 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 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))?; + let preprocessed_contracts = try_vecmap(compiled_contracts, |contract| { + preprocess_contract(backend, contract).map_err(CliError::ProofSystemCompilerError) + })?; for contract in preprocessed_contracts { save_contract_to_file( &contract, @@ -48,25 +51,26 @@ pub(crate) fn run(args: CompileCommand, config: NargoConfig) -> Result<(), CliEr ); } } else { - let program = compile_circuit(&backend, &config.program_dir, &args.compile_options)?; - let preprocessed_program = preprocess_program(&backend, program)?; + let program = compile_circuit(backend, &config.program_dir, &args.compile_options)?; + let preprocessed_program = + preprocess_program(backend, program).map_err(CliError::ProofSystemCompilerError)?; save_program_to_file(&preprocessed_program, &args.circuit_name, circuit_dir); } Ok(()) } -fn setup_driver( - backend: &impl ProofSystemCompiler, +fn setup_driver( + backend: &B, program_dir: &Path, ) -> Result { Resolver::resolve_root_manifest(program_dir, backend.np_language()) } -pub(crate) fn compile_circuit( - backend: &impl ProofSystemCompiler, +pub(crate) fn compile_circuit( + backend: &B, program_dir: &Path, compile_options: &CompileOptions, -) -> Result { +) -> Result> { let mut driver = setup_driver(backend, program_dir)?; driver.compile_main(compile_options).map_err(|_| CliError::CompilationError) } diff --git a/crates/nargo_cli/src/cli/execute_cmd.rs b/crates/nargo_cli/src/cli/execute_cmd.rs index b9b2be3febf..855fea04cb3 100644 --- a/crates/nargo_cli/src/cli/execute_cmd.rs +++ b/crates/nargo_cli/src/cli/execute_cmd.rs @@ -1,7 +1,7 @@ use std::path::Path; use acvm::acir::circuit::Circuit; -use acvm::PartialWitnessGenerator; +use acvm::Backend; use clap::Args; use noirc_abi::input_parser::{Format, InputValue}; use noirc_abi::{Abi, InputMap, WitnessMap}; @@ -25,9 +25,13 @@ pub(crate) struct ExecuteCommand { compile_options: CompileOptions, } -pub(crate) fn run(args: ExecuteCommand, config: NargoConfig) -> Result<(), CliError> { +pub(crate) fn run( + backend: &B, + args: ExecuteCommand, + config: NargoConfig, +) -> Result<(), CliError> { let (return_value, solved_witness) = - execute_with_path(&config.program_dir, &args.compile_options)?; + execute_with_path(backend, &config.program_dir, &args.compile_options)?; println!("Circuit witness successfully solved"); if let Some(return_value) = return_value { @@ -43,19 +47,18 @@ pub(crate) fn run(args: ExecuteCommand, config: NargoConfig) -> Result<(), CliEr Ok(()) } -fn execute_with_path( +fn execute_with_path( + backend: &B, program_dir: &Path, compile_options: &CompileOptions, -) -> Result<(Option, WitnessMap), CliError> { - let backend = crate::backends::ConcreteBackend::default(); - - let CompiledProgram { abi, circuit } = compile_circuit(&backend, program_dir, compile_options)?; +) -> Result<(Option, WitnessMap), CliError> { + let CompiledProgram { abi, circuit } = compile_circuit(backend, program_dir, compile_options)?; // Parse the initial witness values from Prover.toml let (inputs_map, _) = read_inputs_from_file(program_dir, PROVER_INPUT_FILE, Format::Toml, &abi)?; - let solved_witness = execute_program(&backend, circuit, &abi, &inputs_map)?; + let solved_witness = execute_program(backend, circuit, &abi, &inputs_map)?; let public_abi = abi.public_abi(); let (_, return_value) = public_abi.decode(&solved_witness)?; @@ -63,12 +66,12 @@ fn execute_with_path( Ok((return_value, solved_witness)) } -pub(crate) fn execute_program( - backend: &impl PartialWitnessGenerator, +pub(crate) fn execute_program( + backend: &B, circuit: Circuit, abi: &Abi, inputs_map: &InputMap, -) -> Result { +) -> Result> { let initial_witness = abi.encode(inputs_map, None)?; let solved_witness = nargo::ops::execute_circuit(backend, circuit, initial_witness)?; diff --git a/crates/nargo_cli/src/cli/fs/inputs.rs b/crates/nargo_cli/src/cli/fs/inputs.rs index dd9ce199720..eaf94cc22fd 100644 --- a/crates/nargo_cli/src/cli/fs/inputs.rs +++ b/crates/nargo_cli/src/cli/fs/inputs.rs @@ -4,7 +4,7 @@ use noirc_abi::{ }; use std::{collections::BTreeMap, path::Path}; -use crate::errors::CliError; +use crate::errors::FilesystemError; use super::write_to_file; @@ -20,14 +20,14 @@ pub(crate) fn read_inputs_from_file>( file_name: &str, format: Format, abi: &Abi, -) -> Result<(InputMap, Option), CliError> { +) -> Result<(InputMap, Option), FilesystemError> { if abi.is_empty() { return Ok((BTreeMap::new(), None)); } let file_path = path.as_ref().join(file_name).with_extension(format.ext()); if !file_path.exists() { - return Err(CliError::MissingTomlFile(file_name.to_owned(), file_path)); + return Err(FilesystemError::MissingTomlFile(file_name.to_owned(), file_path)); } let input_string = std::fs::read_to_string(file_path).unwrap(); @@ -43,7 +43,7 @@ pub(crate) fn write_inputs_to_file>( path: P, file_name: &str, format: Format, -) -> Result<(), CliError> { +) -> Result<(), FilesystemError> { let file_path = path.as_ref().join(file_name).with_extension(format.ext()); // We must insert the return value into the `InputMap` in order for it to be written to file. diff --git a/crates/nargo_cli/src/cli/fs/mod.rs b/crates/nargo_cli/src/cli/fs/mod.rs index d860f722fd1..4ebce3b3325 100644 --- a/crates/nargo_cli/src/cli/fs/mod.rs +++ b/crates/nargo_cli/src/cli/fs/mod.rs @@ -4,7 +4,7 @@ use std::{ path::{Path, PathBuf}, }; -use crate::errors::CliError; +use crate::errors::FilesystemError; pub(super) mod inputs; pub(super) mod program; @@ -32,11 +32,11 @@ pub(super) fn write_to_file(bytes: &[u8], path: &Path) -> String { } } -pub(super) fn load_hex_data>(path: P) -> Result, CliError> { - let hex_data: Vec<_> = - std::fs::read(&path).map_err(|_| CliError::PathNotValid(path.as_ref().to_path_buf()))?; +pub(super) fn load_hex_data>(path: P) -> Result, FilesystemError> { + let hex_data: Vec<_> = std::fs::read(&path) + .map_err(|_| FilesystemError::PathNotValid(path.as_ref().to_path_buf()))?; - let raw_bytes = hex::decode(hex_data).map_err(CliError::HexArtifactNotValid)?; + let raw_bytes = hex::decode(hex_data).map_err(FilesystemError::HexArtifactNotValid)?; Ok(raw_bytes) } diff --git a/crates/nargo_cli/src/cli/fs/program.rs b/crates/nargo_cli/src/cli/fs/program.rs index a3b5f4026bd..871a6023837 100644 --- a/crates/nargo_cli/src/cli/fs/program.rs +++ b/crates/nargo_cli/src/cli/fs/program.rs @@ -2,7 +2,7 @@ use std::path::{Path, PathBuf}; use nargo::artifacts::{contract::PreprocessedContract, program::PreprocessedProgram}; -use crate::errors::CliError; +use crate::errors::FilesystemError; use super::{create_named_dir, write_to_file}; @@ -35,10 +35,11 @@ fn save_build_artifact_to_file, T: ?Sized + serde::Serialize>( pub(crate) fn read_program_from_file>( circuit_path: P, -) -> Result { +) -> Result { let file_path = circuit_path.as_ref().with_extension("json"); - let input_string = std::fs::read(&file_path).map_err(|_| CliError::PathNotValid(file_path))?; + let input_string = + std::fs::read(&file_path).map_err(|_| FilesystemError::PathNotValid(file_path))?; let program = serde_json::from_slice(&input_string).expect("could not deserialize program"); diff --git a/crates/nargo_cli/src/cli/fs/proof.rs b/crates/nargo_cli/src/cli/fs/proof.rs index 4a77595a54b..3a54aa908f8 100644 --- a/crates/nargo_cli/src/cli/fs/proof.rs +++ b/crates/nargo_cli/src/cli/fs/proof.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use crate::{constants::PROOF_EXT, errors::CliError}; +use crate::{constants::PROOF_EXT, errors::FilesystemError}; use super::{create_named_dir, write_to_file}; @@ -8,7 +8,7 @@ pub(crate) fn save_proof_to_dir>( proof: &[u8], proof_name: &str, proof_dir: P, -) -> Result { +) -> Result { create_named_dir(proof_dir.as_ref(), "proof"); let proof_path = proof_dir.as_ref().join(proof_name).with_extension(PROOF_EXT); diff --git a/crates/nargo_cli/src/cli/fs/witness.rs b/crates/nargo_cli/src/cli/fs/witness.rs index f3a5d3ea469..d41123e74fa 100644 --- a/crates/nargo_cli/src/cli/fs/witness.rs +++ b/crates/nargo_cli/src/cli/fs/witness.rs @@ -4,13 +4,13 @@ use acvm::acir::native_types::Witness; use noirc_abi::WitnessMap; use super::{create_named_dir, write_to_file}; -use crate::{constants::WITNESS_EXT, errors::CliError}; +use crate::{constants::WITNESS_EXT, errors::FilesystemError}; pub(crate) fn save_witness_to_dir>( witness: WitnessMap, witness_name: &str, witness_dir: P, -) -> Result { +) -> Result { create_named_dir(witness_dir.as_ref(), "witness"); let witness_path = witness_dir.as_ref().join(witness_name).with_extension(WITNESS_EXT); diff --git a/crates/nargo_cli/src/cli/gates_cmd.rs b/crates/nargo_cli/src/cli/gates_cmd.rs index 9fe9f5c7a53..88e11c683eb 100644 --- a/crates/nargo_cli/src/cli/gates_cmd.rs +++ b/crates/nargo_cli/src/cli/gates_cmd.rs @@ -1,4 +1,4 @@ -use acvm::ProofSystemCompiler; +use acvm::Backend; use clap::Args; use noirc_driver::CompileOptions; use std::path::Path; @@ -15,17 +15,20 @@ pub(crate) struct GatesCommand { compile_options: CompileOptions, } -pub(crate) fn run(args: GatesCommand, config: NargoConfig) -> Result<(), CliError> { - count_gates_with_path(config.program_dir, &args.compile_options) +pub(crate) fn run( + backend: &B, + args: GatesCommand, + config: NargoConfig, +) -> Result<(), CliError> { + count_gates_with_path(backend, config.program_dir, &args.compile_options) } -fn count_gates_with_path>( +fn count_gates_with_path>( + backend: &B, program_dir: P, compile_options: &CompileOptions, -) -> Result<(), CliError> { - let backend = crate::backends::ConcreteBackend::default(); - - let compiled_program = compile_circuit(&backend, program_dir.as_ref(), compile_options)?; +) -> Result<(), CliError> { + let compiled_program = compile_circuit(backend, program_dir.as_ref(), compile_options)?; let num_opcodes = compiled_program.circuit.opcodes.len(); println!( @@ -34,7 +37,9 @@ fn count_gates_with_path>( num_opcodes ); - let exact_circuit_size = backend.get_exact_circuit_size(&compiled_program.circuit); + let exact_circuit_size = backend + .get_exact_circuit_size(&compiled_program.circuit) + .map_err(CliError::ProofSystemCompilerError)?; println!("Backend circuit size: {exact_circuit_size}"); Ok(()) diff --git a/crates/nargo_cli/src/cli/mod.rs b/crates/nargo_cli/src/cli/mod.rs index 5450bb39660..d41dc1a815a 100644 --- a/crates/nargo_cli/src/cli/mod.rs +++ b/crates/nargo_cli/src/cli/mod.rs @@ -67,17 +67,19 @@ pub fn start_cli() -> eyre::Result<()> { config.program_dir = find_package_root(&config.program_dir)?; } + let backend = crate::backends::ConcreteBackend::default(); + match command { - NargoCommand::New(args) => new_cmd::run(args, config), - NargoCommand::Check(args) => check_cmd::run(args, config), - NargoCommand::Compile(args) => compile_cmd::run(args, config), - NargoCommand::Execute(args) => execute_cmd::run(args, config), - NargoCommand::Prove(args) => prove_cmd::run(args, config), - NargoCommand::Verify(args) => verify_cmd::run(args, config), - NargoCommand::Test(args) => test_cmd::run(args, config), - NargoCommand::Gates(args) => gates_cmd::run(args, config), - NargoCommand::CodegenVerifier(args) => codegen_verifier_cmd::run(args, config), - NargoCommand::PrintAcir(args) => print_acir_cmd::run(args, config), + NargoCommand::New(args) => new_cmd::run(&backend, args, config), + NargoCommand::Check(args) => check_cmd::run(&backend, args, config), + NargoCommand::Compile(args) => compile_cmd::run(&backend, args, config), + NargoCommand::Execute(args) => execute_cmd::run(&backend, args, config), + NargoCommand::Prove(args) => prove_cmd::run(&backend, args, config), + NargoCommand::Verify(args) => verify_cmd::run(&backend, args, config), + NargoCommand::Test(args) => test_cmd::run(&backend, args, config), + NargoCommand::Gates(args) => gates_cmd::run(&backend, args, config), + NargoCommand::CodegenVerifier(args) => codegen_verifier_cmd::run(&backend, args, config), + NargoCommand::PrintAcir(args) => print_acir_cmd::run(&backend, args, config), }?; Ok(()) @@ -85,6 +87,8 @@ pub fn start_cli() -> eyre::Result<()> { // helper function which tests noir programs by trying to generate a proof and verify it pub fn prove_and_verify(proof_name: &str, program_dir: &Path, show_ssa: bool) -> bool { + let backend = crate::backends::ConcreteBackend::default(); + let compile_options = CompileOptions { show_ssa, allow_warnings: false, @@ -94,6 +98,7 @@ pub fn prove_and_verify(proof_name: &str, program_dir: &Path, show_ssa: bool) -> let proof_dir = program_dir.join(PROOFS_DIR); match prove_cmd::prove_with_path( + &backend, Some(proof_name.to_owned()), program_dir, &proof_dir, diff --git a/crates/nargo_cli/src/cli/new_cmd.rs b/crates/nargo_cli/src/cli/new_cmd.rs index 36146028454..5868c1e820e 100644 --- a/crates/nargo_cli/src/cli/new_cmd.rs +++ b/crates/nargo_cli/src/cli/new_cmd.rs @@ -5,6 +5,7 @@ use crate::{ use super::fs::{create_named_dir, write_to_file}; use super::{NargoConfig, CARGO_PKG_VERSION}; +use acvm::Backend; use clap::Args; use const_format::formatcp; use std::path::{Path, PathBuf}; @@ -33,13 +34,18 @@ const EXAMPLE: &str = r#"fn main(x : Field, y : pub Field) { #[test] fn test_main() { main(1, 2); - + // Uncomment to make test fail // main(1, 1); } "#; -pub(crate) fn run(args: NewCommand, config: NargoConfig) -> Result<(), CliError> { +pub(crate) fn run( + // Backend is currently unused, but we might want to use it to inform the "new" template in the future + _backend: &B, + args: NewCommand, + config: NargoConfig, +) -> Result<(), CliError> { let package_dir = config.program_dir.join(args.package_name); if package_dir.exists() { diff --git a/crates/nargo_cli/src/cli/print_acir_cmd.rs b/crates/nargo_cli/src/cli/print_acir_cmd.rs index 38b841121bc..420c57c6a08 100644 --- a/crates/nargo_cli/src/cli/print_acir_cmd.rs +++ b/crates/nargo_cli/src/cli/print_acir_cmd.rs @@ -1,3 +1,4 @@ +use acvm::Backend; use clap::Args; use noirc_driver::CompileOptions; use std::path::Path; @@ -14,17 +15,20 @@ pub(crate) struct PrintAcirCommand { compile_options: CompileOptions, } -pub(crate) fn run(args: PrintAcirCommand, config: NargoConfig) -> Result<(), CliError> { - print_acir_with_path(config.program_dir, &args.compile_options) +pub(crate) fn run( + backend: &B, + args: PrintAcirCommand, + config: NargoConfig, +) -> Result<(), CliError> { + print_acir_with_path(backend, config.program_dir, &args.compile_options) } -fn print_acir_with_path>( +fn print_acir_with_path>( + backend: &B, program_dir: P, compile_options: &CompileOptions, -) -> Result<(), CliError> { - let backend = crate::backends::ConcreteBackend::default(); - - let compiled_program = compile_circuit(&backend, program_dir.as_ref(), compile_options)?; +) -> Result<(), CliError> { + let compiled_program = compile_circuit(backend, program_dir.as_ref(), compile_options)?; println!("{}", compiled_program.circuit); Ok(()) diff --git a/crates/nargo_cli/src/cli/prove_cmd.rs b/crates/nargo_cli/src/cli/prove_cmd.rs index 2b9ed4b067a..d2adc8d4af1 100644 --- a/crates/nargo_cli/src/cli/prove_cmd.rs +++ b/crates/nargo_cli/src/cli/prove_cmd.rs @@ -1,5 +1,6 @@ use std::path::{Path, PathBuf}; +use acvm::Backend; use clap::Args; use nargo::artifacts::program::PreprocessedProgram; use nargo::ops::{preprocess_program, prove_execution, verify_proof}; @@ -38,7 +39,11 @@ pub(crate) struct ProveCommand { compile_options: CompileOptions, } -pub(crate) fn run(args: ProveCommand, config: NargoConfig) -> Result<(), CliError> { +pub(crate) fn run( + backend: &B, + args: ProveCommand, + config: NargoConfig, +) -> Result<(), CliError> { let proof_dir = config.program_dir.join(PROOFS_DIR); let circuit_build_path = args @@ -46,6 +51,7 @@ pub(crate) fn run(args: ProveCommand, config: NargoConfig) -> Result<(), CliErro .map(|circuit_name| config.program_dir.join(TARGET_DIR).join(circuit_name)); prove_with_path( + backend, args.proof_name, config.program_dir, proof_dir, @@ -57,22 +63,21 @@ pub(crate) fn run(args: ProveCommand, config: NargoConfig) -> Result<(), CliErro Ok(()) } -pub(crate) fn prove_with_path>( +pub(crate) fn prove_with_path>( + backend: &B, proof_name: Option, program_dir: P, proof_dir: P, circuit_build_path: Option, check_proof: bool, compile_options: &CompileOptions, -) -> Result, CliError> { - let backend = crate::backends::ConcreteBackend::default(); - +) -> Result, CliError> { let preprocessed_program = match circuit_build_path { Some(circuit_build_path) => read_program_from_file(circuit_build_path)?, None => { - let compiled_program = - compile_circuit(&backend, program_dir.as_ref(), compile_options)?; - preprocess_program(&backend, compiled_program)? + let compiled_program = compile_circuit(backend, program_dir.as_ref(), compile_options)?; + preprocess_program(backend, compiled_program) + .map_err(CliError::ProofSystemCompilerError)? } }; @@ -83,7 +88,7 @@ pub(crate) fn prove_with_path>( let (inputs_map, _) = read_inputs_from_file(&program_dir, PROVER_INPUT_FILE, Format::Toml, &abi)?; - let solved_witness = execute_program(&backend, bytecode.clone(), &abi, &inputs_map)?; + let solved_witness = execute_program(backend, bytecode.clone(), &abi, &inputs_map)?; // Write public inputs into Verifier.toml let public_abi = abi.public_abi(); @@ -97,12 +102,14 @@ pub(crate) fn prove_with_path>( Format::Toml, )?; - let proof = prove_execution(&backend, &bytecode, solved_witness, &proving_key)?; + let proof = prove_execution(backend, &bytecode, solved_witness, &proving_key) + .map_err(CliError::ProofSystemCompilerError)?; if check_proof { let public_inputs = public_abi.encode(&public_inputs, return_value)?; let valid_proof = - verify_proof(&backend, &bytecode, &proof, public_inputs, &verification_key)?; + verify_proof(backend, &bytecode, &proof, public_inputs, &verification_key) + .map_err(CliError::ProofSystemCompilerError)?; if !valid_proof { return Err(CliError::InvalidProof("".into())); diff --git a/crates/nargo_cli/src/cli/test_cmd.rs b/crates/nargo_cli/src/cli/test_cmd.rs index 65f8265a862..139d33b6c3d 100644 --- a/crates/nargo_cli/src/cli/test_cmd.rs +++ b/crates/nargo_cli/src/cli/test_cmd.rs @@ -1,6 +1,6 @@ use std::{collections::BTreeMap, io::Write, path::Path}; -use acvm::ProofSystemCompiler; +use acvm::Backend; use clap::Args; use nargo::ops::execute_circuit; use noirc_driver::{CompileOptions, Driver}; @@ -21,19 +21,22 @@ pub(crate) struct TestCommand { compile_options: CompileOptions, } -pub(crate) fn run(args: TestCommand, config: NargoConfig) -> Result<(), CliError> { +pub(crate) fn run( + backend: &B, + args: TestCommand, + config: NargoConfig, +) -> Result<(), CliError> { let test_name: String = args.test_name.unwrap_or_else(|| "".to_owned()); - run_tests(&config.program_dir, &test_name, &args.compile_options) + run_tests(backend, &config.program_dir, &test_name, &args.compile_options) } -fn run_tests( +fn run_tests( + backend: &B, program_dir: &Path, test_name: &str, compile_options: &CompileOptions, -) -> Result<(), CliError> { - let backend = crate::backends::ConcreteBackend::default(); - +) -> Result<(), CliError> { let mut driver = Resolver::resolve_root_manifest(program_dir, backend.np_language())?; driver.check_crate(compile_options).map_err(|_| CliError::CompilationError)?; @@ -50,7 +53,7 @@ fn run_tests( writeln!(writer, "Testing {test_name}...").expect("Failed to write to stdout"); writer.flush().ok(); - match run_test(test_name, test_function, &driver, compile_options) { + match run_test(backend, test_name, test_function, &driver, compile_options) { Ok(_) => { writer.set_color(ColorSpec::new().set_fg(Some(Color::Green))).ok(); writeln!(writer, "ok").ok(); @@ -73,21 +76,20 @@ fn run_tests( Ok(()) } -fn run_test( +fn run_test( + backend: &B, test_name: &str, main: FuncId, driver: &Driver, config: &CompileOptions, -) -> Result<(), CliError> { - let backend = crate::backends::ConcreteBackend::default(); - +) -> Result<(), CliError> { let program = driver .compile_no_check(config, main) .map_err(|_| CliError::Generic(format!("Test '{test_name}' failed to compile")))?; // Run the backend to ensure the PWG evaluates functions like std::hash::pedersen, // otherwise constraints involving these expressions will not error. - match execute_circuit(&backend, program.circuit, BTreeMap::new()) { + match execute_circuit(backend, program.circuit, BTreeMap::new()) { Ok(_) => Ok(()), Err(error) => { let writer = StandardStream::stderr(ColorChoice::Always); diff --git a/crates/nargo_cli/src/cli/verify_cmd.rs b/crates/nargo_cli/src/cli/verify_cmd.rs index 84a6416d44e..07ba12d3899 100644 --- a/crates/nargo_cli/src/cli/verify_cmd.rs +++ b/crates/nargo_cli/src/cli/verify_cmd.rs @@ -6,6 +6,7 @@ use crate::{ errors::CliError, }; +use acvm::Backend; use clap::Args; use nargo::artifacts::program::PreprocessedProgram; use nargo::ops::preprocess_program; @@ -26,7 +27,11 @@ pub(crate) struct VerifyCommand { compile_options: CompileOptions, } -pub(crate) fn run(args: VerifyCommand, config: NargoConfig) -> Result<(), CliError> { +pub(crate) fn run( + backend: &B, + args: VerifyCommand, + config: NargoConfig, +) -> Result<(), CliError> { let proof_path = config.program_dir.join(PROOFS_DIR).join(&args.proof).with_extension(PROOF_EXT); @@ -35,6 +40,7 @@ pub(crate) fn run(args: VerifyCommand, config: NargoConfig) -> Result<(), CliErr .map(|circuit_name| config.program_dir.join(TARGET_DIR).join(circuit_name)); verify_with_path( + backend, &config.program_dir, proof_path, circuit_build_path.as_ref(), @@ -42,20 +48,20 @@ pub(crate) fn run(args: VerifyCommand, config: NargoConfig) -> Result<(), CliErr ) } -fn verify_with_path>( +fn verify_with_path>( + backend: &B, program_dir: P, proof_path: PathBuf, circuit_build_path: Option

, compile_options: CompileOptions, -) -> Result<(), CliError> { - let backend = crate::backends::ConcreteBackend::default(); - +) -> Result<(), CliError> { let preprocessed_program = match circuit_build_path { Some(circuit_build_path) => read_program_from_file(circuit_build_path)?, None => { let compiled_program = - compile_circuit(&backend, program_dir.as_ref(), &compile_options)?; - preprocess_program(&backend, compiled_program)? + compile_circuit(backend, program_dir.as_ref(), &compile_options)?; + preprocess_program(backend, compiled_program) + .map_err(CliError::ProofSystemCompilerError)? } }; @@ -70,7 +76,8 @@ fn verify_with_path>( let proof = load_hex_data(&proof_path)?; let valid_proof = - nargo::ops::verify_proof(&backend, &bytecode, &proof, public_inputs, &verification_key)?; + nargo::ops::verify_proof(backend, &bytecode, &proof, public_inputs, &verification_key) + .map_err(CliError::ProofSystemCompilerError)?; if valid_proof { Ok(()) diff --git a/crates/nargo_cli/src/errors.rs b/crates/nargo_cli/src/errors.rs index f6537b550ea..15d1917a5d6 100644 --- a/crates/nargo_cli/src/errors.rs +++ b/crates/nargo_cli/src/errors.rs @@ -1,3 +1,4 @@ +use acvm::{Backend, ProofSystemCompiler, SmartContract}; use hex::FromHexError; use nargo::NargoError; use noirc_abi::errors::{AbiError, InputParserError}; @@ -7,11 +8,7 @@ use thiserror::Error; use crate::resolver::DependencyResolutionError; #[derive(Debug, Error)] -pub(crate) enum CliError { - #[error("{0}")] - Generic(String), - #[error("Error: destination {} already exists", .0.display())] - DestinationAlreadyExists(PathBuf), +pub(crate) enum FilesystemError { #[error("Error: {} is not a valid path\nRun either `nargo compile` to generate missing build artifacts or `nargo prove` to construct a proof", .0.display())] PathNotValid(PathBuf), #[error("Error: could not parse hex build artifact (proof, proving and/or verification keys, ACIR checksum) ({0})")] @@ -21,6 +18,18 @@ pub(crate) enum CliError { )] MissingTomlFile(String, PathBuf), + /// Input parsing error + #[error(transparent)] + InputParserError(#[from] InputParserError), +} + +#[derive(Debug, Error)] +pub(crate) enum CliError { + #[error("{0}")] + Generic(String), + #[error("Error: destination {} already exists", .0.display())] + DestinationAlreadyExists(PathBuf), + #[error("Failed to verify proof {}", .0.display())] InvalidProof(PathBuf), @@ -31,15 +40,23 @@ pub(crate) enum CliError { #[error("Failed to compile circuit")] CompilationError, - /// Input parsing error - #[error(transparent)] - InputParserError(#[from] InputParserError), - /// ABI encoding/decoding error #[error(transparent)] AbiError(#[from] AbiError), + /// Filesystem errors + #[error(transparent)] + FilesystemError(#[from] FilesystemError), + /// Error from Nargo #[error(transparent)] NargoError(#[from] NargoError), + + /// Backend error caused by a function on the SmartContract trait + #[error(transparent)] + SmartContractError(::Error), // Unfortunately, Rust won't let us `impl From` over an Associated Type on a generic + + /// Backend error caused by a function on the ProofSystemCompiler trait + #[error(transparent)] + ProofSystemCompilerError(::Error), // Unfortunately, Rust won't let us `impl From` over an Associated Type on a generic }