From cb2f2ebf5d8d78d54ebdb18db3c4f72b1031d9a9 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 31 Aug 2023 17:32:59 +0100 Subject: [PATCH 1/7] chore: only install `tokio-util` dependency on windows (#2425) --- crates/nargo_cli/Cargo.toml | 4 +++- crates/nargo_cli/src/main.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/nargo_cli/Cargo.toml b/crates/nargo_cli/Cargo.toml index da3eac653c5..e10fde13d7b 100644 --- a/crates/nargo_cli/Cargo.toml +++ b/crates/nargo_cli/Cargo.toml @@ -46,11 +46,13 @@ hex = "0.4.2" termcolor = "1.1.2" color-eyre = "0.6.2" tokio = { version = "1.0", features = ["io-std"] } -tokio-util = { version = "0.7.8", features = ["compat"] } # Backends acvm-backend-barretenberg = { path = "../acvm_backend_barretenberg" } +[target.'cfg(not(unix))'.dependencies] +tokio-util = { version = "0.7.8", features = ["compat"] } + [dev-dependencies] tempdir = "0.3.7" assert_cmd = "2.0.8" diff --git a/crates/nargo_cli/src/main.rs b/crates/nargo_cli/src/main.rs index 734dbdca2e7..f4d1e1862fc 100644 --- a/crates/nargo_cli/src/main.rs +++ b/crates/nargo_cli/src/main.rs @@ -1,7 +1,7 @@ #![forbid(unsafe_code)] -#![warn(unused_extern_crates)] #![warn(unreachable_pub)] #![warn(clippy::semicolon_if_nothing_returned)] +#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] //! Nargo is the package manager for Noir //! This name was used because it sounds like `cargo` and From 3a7c2e83c837cf0aff92d2fb22f1f3baf88c28d7 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 31 Aug 2023 23:48:54 +0100 Subject: [PATCH 2/7] chore: Remove dead code from `acvm_backend_barretenberg` (#2512) --- crates/acvm_backend_barretenberg/src/lib.rs | 15 --------------- .../acvm_backend_barretenberg/src/proof_system.rs | 14 ++++++-------- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/crates/acvm_backend_barretenberg/src/lib.rs b/crates/acvm_backend_barretenberg/src/lib.rs index 46867a6aeb4..704d2b4c7b0 100644 --- a/crates/acvm_backend_barretenberg/src/lib.rs +++ b/crates/acvm_backend_barretenberg/src/lib.rs @@ -1,25 +1,10 @@ #![warn(unused_crate_dependencies, unused_extern_crates)] #![warn(unreachable_pub)] -// `acvm-backend-barretenberg` can either interact with the Barretenberg backend through a static library -// or through an embedded wasm binary. It does not make sense to include both of these backends at the same time. -// We then throw a compilation error if both flags are set. -#[cfg(all(feature = "native", feature = "wasm"))] -compile_error!("feature \"native\" and feature \"wasm\" cannot be enabled at the same time"); - -#[cfg(all(feature = "native", target_arch = "wasm32"))] -compile_error!("feature \"native\" cannot be enabled for a \"wasm32\" target"); - -#[cfg(all(feature = "wasm", target_arch = "wasm32"))] -compile_error!("feature \"wasm\" cannot be enabled for a \"wasm32\" target"); - mod bb; mod proof_system; mod smart_contract; -/// The number of bytes necessary to store a `FieldElement`. -const FIELD_BYTES: usize = 32; - #[derive(Debug, Default)] pub struct Barretenberg; diff --git a/crates/acvm_backend_barretenberg/src/proof_system.rs b/crates/acvm_backend_barretenberg/src/proof_system.rs index 33ec8457a43..6b5916c7def 100644 --- a/crates/acvm_backend_barretenberg/src/proof_system.rs +++ b/crates/acvm_backend_barretenberg/src/proof_system.rs @@ -9,7 +9,7 @@ use acvm::{Language, ProofSystemCompiler}; use tempfile::tempdir; use crate::bb::{GatesCommand, ProveCommand, VerifyCommand, WriteVkCommand}; -use crate::{BackendError, Barretenberg, FIELD_BYTES}; +use crate::{BackendError, Barretenberg}; impl ProofSystemCompiler for Barretenberg { type Error = BackendError; @@ -76,9 +76,8 @@ impl ProofSystemCompiler for Barretenberg { let temp_dir_path_str = temp_directory.to_str().unwrap(); // Create a temporary file for the witness - let serialized_witnesses: Vec = witness_values - .try_into() - .expect("could not serialize witness map"); + let serialized_witnesses: Vec = + witness_values.try_into().expect("could not serialize witness map"); let witness_path = temp_directory.join("witness").with_extension("tr"); write_to_file(&serialized_witnesses, &witness_path); @@ -222,7 +221,7 @@ pub(super) fn read_bytes_from_file(path: &str) -> std::io::Result> { fn remove_public_inputs(num_pub_inputs: usize, proof: &[u8]) -> Vec { // Barretenberg prepends the public inputs onto the proof so we need to remove // the first `num_pub_inputs` field elements. - let num_bytes_to_remove = num_pub_inputs * FIELD_BYTES; + let num_bytes_to_remove = num_pub_inputs * (FieldElement::max_num_bytes() as usize); proof[num_bytes_to_remove..].to_vec() } @@ -232,9 +231,8 @@ fn prepend_public_inputs(proof: Vec, public_inputs: Vec) -> Ve return proof; } - let public_inputs_bytes = public_inputs - .into_iter() - .flat_map(|assignment| assignment.to_be_bytes()); + let public_inputs_bytes = + public_inputs.into_iter().flat_map(|assignment| assignment.to_be_bytes()); public_inputs_bytes.chain(proof.into_iter()).collect() } From 3157a544ad4c937aa693161765daae6e7c5569ee Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 1 Sep 2023 00:29:41 +0100 Subject: [PATCH 3/7] chore: delete `ProveAndVerifyCommand` (#2520) --- .../acvm_backend_barretenberg/src/bb/mod.rs | 1 - .../src/bb/prove_and_verify.rs | 65 ------------------- 2 files changed, 66 deletions(-) delete mode 100644 crates/acvm_backend_barretenberg/src/bb/prove_and_verify.rs diff --git a/crates/acvm_backend_barretenberg/src/bb/mod.rs b/crates/acvm_backend_barretenberg/src/bb/mod.rs index 3f80c538bf5..7eed61154d7 100644 --- a/crates/acvm_backend_barretenberg/src/bb/mod.rs +++ b/crates/acvm_backend_barretenberg/src/bb/mod.rs @@ -3,7 +3,6 @@ mod contract; mod gates; mod prove; -mod prove_and_verify; mod verify; mod write_vk; diff --git a/crates/acvm_backend_barretenberg/src/bb/prove_and_verify.rs b/crates/acvm_backend_barretenberg/src/bb/prove_and_verify.rs deleted file mode 100644 index 08fe0f10ea9..00000000000 --- a/crates/acvm_backend_barretenberg/src/bb/prove_and_verify.rs +++ /dev/null @@ -1,65 +0,0 @@ -use super::{assert_binary_exists, get_binary_path}; - -/// ProveAndVerifyCommand will call the barretenberg binary -/// to create a proof and then verify the proof once created. -/// -/// Note: Functions like this are useful for testing. In a real workflow, -/// ProveCommand and VerifyCommand will be used separately. -#[allow(dead_code)] -struct ProveAndVerifyCommand { - verbose: bool, - path_to_crs: String, - is_recursive: bool, - path_to_bytecode: String, - path_to_witness: String, -} - -#[allow(dead_code)] -impl ProveAndVerifyCommand { - fn run(self) -> bool { - assert_binary_exists(); - let mut command = std::process::Command::new(get_binary_path()); - - command - .arg("prove_and_verify") - .arg("-c") - .arg(self.path_to_crs) - .arg("-b") - .arg(self.path_to_bytecode) - .arg("-w") - .arg(self.path_to_witness); - if self.verbose { - command.arg("-v"); - } - if self.is_recursive { - command.arg("-r"); - } - - command.output().expect("Failed to execute command").status.success() - } -} - -#[test] -#[serial_test::serial] -fn prove_and_verify_command() { - use tempfile::tempdir; - - let path_to_1_mul = "./src/1_mul.bytecode"; - let path_to_1_mul_witness = "./src/witness.tr"; - - let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory_path = temp_directory.path(); - let path_to_crs = temp_directory_path.join("crs"); - - let prove_and_verify_command = ProveAndVerifyCommand { - verbose: true, - path_to_crs: path_to_crs.to_str().unwrap().to_string(), - is_recursive: false, - path_to_bytecode: path_to_1_mul.to_string(), - path_to_witness: path_to_1_mul_witness.to_string(), - }; - - let output = prove_and_verify_command.run(); - assert!(output); - drop(temp_directory); -} From f1d09ca1ebfff6944b41ea5a397e2b83ac840455 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 1 Sep 2023 00:44:22 +0100 Subject: [PATCH 4/7] chore: remove usage of `Backend` trait (#2514) --- crates/acvm_backend_barretenberg/src/lib.rs | 21 +++++----- .../src/proof_system.rs | 42 +++++-------------- .../src/smart_contract.rs | 33 +++++---------- crates/nargo_cli/src/backends.rs | 2 +- crates/nargo_cli/src/cli/check_cmd.rs | 9 ++-- .../nargo_cli/src/cli/codegen_verifier_cmd.rs | 20 ++++----- crates/nargo_cli/src/cli/compile_cmd.rs | 27 ++++++------ crates/nargo_cli/src/cli/execute_cmd.rs | 20 ++++----- crates/nargo_cli/src/cli/info_cmd.rs | 37 ++++++++-------- crates/nargo_cli/src/cli/init_cmd.rs | 8 ++-- crates/nargo_cli/src/cli/lsp_cmd.rs | 8 ++-- crates/nargo_cli/src/cli/mod.rs | 2 +- crates/nargo_cli/src/cli/new_cmd.rs | 8 ++-- crates/nargo_cli/src/cli/prove_cmd.rs | 22 ++++------ crates/nargo_cli/src/cli/test_cmd.rs | 14 +++---- crates/nargo_cli/src/cli/verify_cmd.rs | 19 ++++----- crates/nargo_cli/src/errors.rs | 13 +++--- 17 files changed, 130 insertions(+), 175 deletions(-) diff --git a/crates/acvm_backend_barretenberg/src/lib.rs b/crates/acvm_backend_barretenberg/src/lib.rs index 704d2b4c7b0..e5da8577406 100644 --- a/crates/acvm_backend_barretenberg/src/lib.rs +++ b/crates/acvm_backend_barretenberg/src/lib.rs @@ -6,20 +6,19 @@ mod proof_system; mod smart_contract; #[derive(Debug, Default)] -pub struct Barretenberg; +pub struct Backend {} -impl Barretenberg { - pub fn new() -> Barretenberg { - Barretenberg +impl Backend { + pub fn new() -> Backend { + Backend {} } } -impl acvm::Backend for Barretenberg {} - #[derive(Debug, thiserror::Error)] -#[error(transparent)] -pub struct BackendError(#[from] Error); +pub struct BackendError(String); -#[allow(clippy::upper_case_acronyms)] -#[derive(Debug, thiserror::Error)] -enum Error {} +impl std::fmt::Display for BackendError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} diff --git a/crates/acvm_backend_barretenberg/src/proof_system.rs b/crates/acvm_backend_barretenberg/src/proof_system.rs index 6b5916c7def..93f40666f6c 100644 --- a/crates/acvm_backend_barretenberg/src/proof_system.rs +++ b/crates/acvm_backend_barretenberg/src/proof_system.rs @@ -5,20 +5,18 @@ use std::path::Path; use acvm::acir::circuit::Opcode; use acvm::acir::{circuit::Circuit, native_types::WitnessMap, BlackBoxFunc}; use acvm::FieldElement; -use acvm::{Language, ProofSystemCompiler}; +use acvm::Language; use tempfile::tempdir; use crate::bb::{GatesCommand, ProveCommand, VerifyCommand, WriteVkCommand}; -use crate::{BackendError, Barretenberg}; +use crate::{Backend, BackendError}; -impl ProofSystemCompiler for Barretenberg { - type Error = BackendError; - - fn np_language(&self) -> Language { +impl Backend { + pub fn np_language(&self) -> Language { Language::PLONKCSat { width: 3 } } - fn get_exact_circuit_size(&self, circuit: &Circuit) -> Result { + pub fn get_exact_circuit_size(&self, circuit: &Circuit) -> Result { let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory = temp_directory.path(); let temp_dir_path_str = temp_directory.to_str().unwrap(); @@ -38,7 +36,7 @@ impl ProofSystemCompiler for Barretenberg { Ok(number_of_gates_needed) } - fn supports_opcode(&self, opcode: &Opcode) -> bool { + pub fn supports_opcode(&self, opcode: &Opcode) -> bool { match opcode { Opcode::Arithmetic(_) => true, Opcode::Directive(_) => true, @@ -63,14 +61,12 @@ impl ProofSystemCompiler for Barretenberg { } } - fn prove_with_pk( + pub fn prove( &self, - _common_reference_string: &[u8], circuit: &Circuit, witness_values: WitnessMap, - _proving_key: &[u8], is_recursive: bool, - ) -> Result, Self::Error> { + ) -> Result, BackendError> { let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory = temp_directory.path(); let temp_dir_path_str = temp_directory.to_str().unwrap(); @@ -116,15 +112,13 @@ impl ProofSystemCompiler for Barretenberg { Ok(proof) } - fn verify_with_vk( + pub fn verify( &self, - _common_reference_string: &[u8], proof: &[u8], public_inputs: WitnessMap, circuit: &Circuit, - _verification_key: &[u8], is_recursive: bool, - ) -> Result { + ) -> Result { let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory = temp_directory.path(); let temp_dir_path = temp_directory.to_str().unwrap(); @@ -172,22 +166,6 @@ impl ProofSystemCompiler for Barretenberg { } .run()) } - - fn proof_as_fields( - &self, - _proof: &[u8], - _public_inputs: WitnessMap, - ) -> Result, Self::Error> { - panic!("vk_as_fields not supported in this backend"); - } - - fn vk_as_fields( - &self, - _common_reference_string: &[u8], - _verification_key: &[u8], - ) -> Result<(Vec, FieldElement), Self::Error> { - panic!("vk_as_fields not supported in this backend"); - } } pub(super) fn write_to_file(bytes: &[u8], path: &Path) -> String { diff --git a/crates/acvm_backend_barretenberg/src/smart_contract.rs b/crates/acvm_backend_barretenberg/src/smart_contract.rs index 167a00e9cd2..29633ef6bfc 100644 --- a/crates/acvm_backend_barretenberg/src/smart_contract.rs +++ b/crates/acvm_backend_barretenberg/src/smart_contract.rs @@ -2,23 +2,16 @@ use super::proof_system::{serialize_circuit, write_to_file}; use crate::{ bb::{ContractCommand, WriteVkCommand}, proof_system::read_bytes_from_file, - BackendError, Barretenberg, + Backend, BackendError, }; -use acvm::{acir::circuit::Circuit, SmartContract}; +use acvm::acir::circuit::Circuit; use tempfile::tempdir; /// Embed the Solidity verifier file const ULTRA_VERIFIER_CONTRACT: &str = include_str!("contract.sol"); -impl SmartContract for Barretenberg { - type Error = BackendError; - - fn eth_contract_from_vk( - &self, - _common_reference_string: &[u8], - circuit: &Circuit, - _verification_key: &[u8], - ) -> Result { +impl Backend { + pub fn eth_contract(&self, circuit: &Circuit) -> Result { let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory_path = temp_directory.path(); let temp_dir_path = temp_directory_path.to_str().unwrap(); @@ -62,18 +55,15 @@ impl SmartContract for Barretenberg { mod tests { use std::collections::BTreeSet; - use acvm::{ - acir::{ - circuit::{Circuit, Opcode, PublicInputs}, - native_types::{Expression, Witness}, - }, - SmartContract, + use acvm::acir::{ + circuit::{Circuit, Opcode, PublicInputs}, + native_types::{Expression, Witness}, }; #[test] #[serial_test::serial] fn test_smart_contract() { - use crate::Barretenberg; + use crate::Backend; let expression = &(Witness(1) + Witness(2)) - &Expression::from(Witness(3)); let constraint = Opcode::Arithmetic(expression); @@ -86,12 +76,9 @@ mod tests { return_values: PublicInputs::default(), }; - let bb = Barretenberg; + let bb = Backend::default(); - let common_reference_string = Vec::new(); - let verification_key = Vec::new(); - let contract = - bb.eth_contract_from_vk(&common_reference_string, &circuit, &verification_key).unwrap(); + let contract = bb.eth_contract(&circuit).unwrap(); assert!(contract.contains("contract BaseUltraVerifier")); assert!(contract.contains("contract UltraVerifier")); diff --git a/crates/nargo_cli/src/backends.rs b/crates/nargo_cli/src/backends.rs index 71ff5a0c73a..feaded3971d 100644 --- a/crates/nargo_cli/src/backends.rs +++ b/crates/nargo_cli/src/backends.rs @@ -1 +1 @@ -pub(crate) use acvm_backend_barretenberg::Barretenberg as ConcreteBackend; +pub(crate) use acvm_backend_barretenberg::Backend; diff --git a/crates/nargo_cli/src/cli/check_cmd.rs b/crates/nargo_cli/src/cli/check_cmd.rs index 29864521380..955687da9de 100644 --- a/crates/nargo_cli/src/cli/check_cmd.rs +++ b/crates/nargo_cli/src/cli/check_cmd.rs @@ -1,5 +1,6 @@ +use crate::backends::Backend; use crate::errors::{CliError, CompileError}; -use acvm::Backend; + use clap::Args; use iter_extended::btree_map; use nargo::{package::Package, prepare_package}; @@ -29,11 +30,11 @@ pub(crate) struct CheckCommand { compile_options: CompileOptions, } -pub(crate) fn run( - _backend: &B, +pub(crate) fn run( + _backend: &Backend, args: CheckCommand, config: NargoConfig, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; diff --git a/crates/nargo_cli/src/cli/codegen_verifier_cmd.rs b/crates/nargo_cli/src/cli/codegen_verifier_cmd.rs index 04c7114a565..15e8b236bc8 100644 --- a/crates/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/crates/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -5,11 +5,12 @@ use super::{ compile_cmd::compile_package, fs::{create_named_dir, program::read_program_from_file, write_to_file}, }; +use crate::backends::Backend; use crate::errors::CliError; -use acvm::Backend; + use clap::Args; use nargo::artifacts::program::PreprocessedProgram; -use nargo::{ops::codegen_verifier, package::Package}; +use nargo::package::Package; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::CompileOptions; use noirc_frontend::graph::CrateName; @@ -32,11 +33,11 @@ pub(crate) struct CodegenVerifierCommand { compile_options: CompileOptions, } -pub(crate) fn run( - backend: &B, +pub(crate) fn run( + backend: &Backend, args: CodegenVerifierCommand, config: NargoConfig, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -64,12 +65,12 @@ pub(crate) fn run( Ok(()) } -fn smart_contract_for_package( - backend: &B, +fn smart_contract_for_package( + backend: &Backend, package: &Package, circuit_build_path: PathBuf, compile_options: &CompileOptions, -) -> Result> { +) -> Result { let preprocessed_program = if circuit_build_path.exists() { read_program_from_file(circuit_build_path)? } else { @@ -82,8 +83,7 @@ fn smart_contract_for_package( } }; - let smart_contract_string = codegen_verifier(backend, &preprocessed_program.bytecode) - .map_err(CliError::SmartContractError)?; + let smart_contract_string = backend.eth_contract(&preprocessed_program.bytecode)?; Ok(smart_contract_string) } diff --git a/crates/nargo_cli/src/cli/compile_cmd.rs b/crates/nargo_cli/src/cli/compile_cmd.rs index ba6da305721..906e65ae353 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::{acir::circuit::Circuit, compiler::AcirTransformationMap, Backend}; +use acvm::{acir::circuit::Circuit, compiler::AcirTransformationMap}; use iter_extended::{try_vecmap, vecmap}; use nargo::artifacts::contract::PreprocessedContractFunction; use nargo::artifacts::debug::DebugArtifact; @@ -17,6 +17,7 @@ use noirc_frontend::hir::Context; use clap::Args; +use crate::backends::Backend; use crate::errors::{CliError, CompileError}; use super::fs::program::{ @@ -50,11 +51,11 @@ pub(crate) struct CompileCommand { compile_options: CompileOptions, } -pub(crate) fn run( - backend: &B, +pub(crate) fn run( + backend: &Backend, args: CompileCommand, config: NargoConfig, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -141,8 +142,8 @@ pub(crate) fn run( Ok(()) } -pub(crate) fn compile_package( - backend: &B, +pub(crate) fn compile_package( + backend: &Backend, package: &Package, compile_options: &CompileOptions, ) -> Result<(Context, CompiledProgram), CompileError> { @@ -164,10 +165,10 @@ pub(crate) fn compile_package( Ok((context, program)) } -pub(super) fn optimize_circuit( - backend: &B, +pub(super) fn optimize_circuit( + backend: &Backend, circuit: Circuit, -) -> Result<(Circuit, AcirTransformationMap), CliError> { +) -> Result<(Circuit, AcirTransformationMap), CliError> { let result = acvm::compiler::compile(circuit, backend.np_language(), |opcode| { backend.supports_opcode(opcode) }) @@ -176,15 +177,15 @@ pub(super) fn optimize_circuit( Ok(result) } -pub(super) fn optimize_contract( - backend: &B, +pub(super) fn optimize_contract( + backend: &Backend, contract: CompiledContract, -) -> Result> { +) -> Result { let functions = try_vecmap(contract.functions, |mut func| { let (optimized_bytecode, location_map) = optimize_circuit(backend, func.bytecode)?; func.bytecode = optimized_bytecode; func.debug.update_acir(location_map); - Ok::<_, CliError>(func) + Ok::<_, CliError>(func) })?; Ok(CompiledContract { functions, ..contract }) diff --git a/crates/nargo_cli/src/cli/execute_cmd.rs b/crates/nargo_cli/src/cli/execute_cmd.rs index 30ba6e28322..159e7987992 100644 --- a/crates/nargo_cli/src/cli/execute_cmd.rs +++ b/crates/nargo_cli/src/cli/execute_cmd.rs @@ -1,7 +1,6 @@ use acvm::acir::circuit::OpcodeLocation; use acvm::acir::{circuit::Circuit, native_types::WitnessMap}; use acvm::pwg::ErrorLocation; -use acvm::Backend; use clap::Args; use nargo::constants::PROVER_INPUT_FILE; use nargo::package::Package; @@ -17,6 +16,7 @@ use noirc_frontend::hir::Context; use super::compile_cmd::compile_package; use super::fs::{inputs::read_inputs_from_file, witness::save_witness_to_dir}; use super::NargoConfig; +use crate::backends::Backend; use crate::errors::CliError; /// Executes a circuit to calculate its return value @@ -41,11 +41,11 @@ pub(crate) struct ExecuteCommand { compile_options: CompileOptions, } -pub(crate) fn run( - backend: &B, +pub(crate) fn run( + backend: &Backend, args: ExecuteCommand, config: NargoConfig, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -70,12 +70,12 @@ pub(crate) fn run( Ok(()) } -fn execute_package( - backend: &B, +fn execute_package( + backend: &Backend, package: &Package, prover_name: &str, compile_options: &CompileOptions, -) -> Result<(Option, WitnessMap), CliError> { +) -> Result<(Option, WitnessMap), CliError> { let (context, compiled_program) = compile_package(backend, package, compile_options)?; let CompiledProgram { abi, circuit, debug } = compiled_program; @@ -161,13 +161,13 @@ fn report_error_with_opcode_location( } } -pub(crate) fn execute_program( - _backend: &B, +pub(crate) fn execute_program( + _backend: &Backend, circuit: Circuit, abi: &Abi, inputs_map: &InputMap, debug_data: Option<(DebugInfo, Context)>, -) -> Result> { +) -> Result { #[allow(deprecated)] let blackbox_solver = acvm::blackbox_solver::BarretenbergSolver::new(); diff --git a/crates/nargo_cli/src/cli/info_cmd.rs b/crates/nargo_cli/src/cli/info_cmd.rs index a761c376973..bc652636d82 100644 --- a/crates/nargo_cli/src/cli/info_cmd.rs +++ b/crates/nargo_cli/src/cli/info_cmd.rs @@ -1,4 +1,4 @@ -use acvm::Backend; +use acvm_backend_barretenberg::BackendError; use clap::Args; use iter_extended::try_vecmap; use nargo::{package::Package, prepare_package}; @@ -7,6 +7,7 @@ use noirc_driver::{compile_contracts, CompileOptions}; use noirc_frontend::graph::CrateName; use prettytable::{row, Table}; +use crate::backends::Backend; use crate::{cli::compile_cmd::compile_package, errors::CliError}; use super::{ @@ -33,11 +34,11 @@ pub(crate) struct InfoCommand { compile_options: CompileOptions, } -pub(crate) fn run( - backend: &B, +pub(crate) fn run( + backend: &Backend, args: InfoCommand, config: NargoConfig, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -85,18 +86,16 @@ pub(crate) fn run( Ok(()) } -fn count_opcodes_and_gates_in_package( - backend: &B, +fn count_opcodes_and_gates_in_package( + backend: &Backend, package: &Package, compile_options: &CompileOptions, table: &mut Table, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let (_, compiled_program) = compile_package(backend, package, compile_options)?; let num_opcodes = compiled_program.circuit.opcodes.len(); - let exact_circuit_size = backend - .get_exact_circuit_size(&compiled_program.circuit) - .map_err(CliError::ProofSystemCompilerError)?; + let exact_circuit_size = backend.get_exact_circuit_size(&compiled_program.circuit)?; table.add_row(row![ Fm->format!("{}", package.name), @@ -108,12 +107,12 @@ fn count_opcodes_and_gates_in_package( Ok(()) } -fn count_opcodes_and_gates_in_contracts( - backend: &B, +fn count_opcodes_and_gates_in_contracts( + backend: &Backend, package: &Package, compile_options: &CompileOptions, table: &mut Table, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let (mut context, crate_id) = prepare_package(package); let result = compile_contracts(&mut context, crate_id, compile_options); let contracts = report_errors(result, &context, compile_options.deny_warnings)?; @@ -121,13 +120,13 @@ fn count_opcodes_and_gates_in_contracts( try_vecmap(contracts, |contract| optimize_contract(backend, contract))?; for contract in optimized_contracts { - let function_info: Vec<(String, usize, u32)> = try_vecmap(contract.functions, |function| { - let num_opcodes = function.bytecode.opcodes.len(); - let exact_circuit_size = backend.get_exact_circuit_size(&function.bytecode)?; + let function_info: Vec<(String, usize, u32)> = + try_vecmap(contract.functions, |function| { + let num_opcodes = function.bytecode.opcodes.len(); + let exact_circuit_size = backend.get_exact_circuit_size(&function.bytecode)?; - Ok((function.name, num_opcodes, exact_circuit_size)) - }) - .map_err(CliError::ProofSystemCompilerError)?; + Ok::<_, BackendError>((function.name, num_opcodes, exact_circuit_size)) + })?; for info in function_info { table.add_row(row![ diff --git a/crates/nargo_cli/src/cli/init_cmd.rs b/crates/nargo_cli/src/cli/init_cmd.rs index e6020e3cfd9..2091ac89f9c 100644 --- a/crates/nargo_cli/src/cli/init_cmd.rs +++ b/crates/nargo_cli/src/cli/init_cmd.rs @@ -1,8 +1,8 @@ +use crate::backends::Backend; use crate::errors::CliError; use super::fs::{create_named_dir, write_to_file}; use super::{NargoConfig, CARGO_PKG_VERSION}; -use acvm::Backend; use clap::Args; use nargo::constants::{PKG_FILE, SRC_DIR}; use nargo::package::PackageType; @@ -62,12 +62,12 @@ fn test_my_util() { } "#; -pub(crate) fn run( +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, + _backend: &Backend, args: InitCommand, config: NargoConfig, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let package_name = match args.name { Some(name) => name, None => { diff --git a/crates/nargo_cli/src/cli/lsp_cmd.rs b/crates/nargo_cli/src/cli/lsp_cmd.rs index ac15f4f8a9f..7350c5c3099 100644 --- a/crates/nargo_cli/src/cli/lsp_cmd.rs +++ b/crates/nargo_cli/src/cli/lsp_cmd.rs @@ -1,4 +1,3 @@ -use acvm::Backend; use async_lsp::{ client_monitor::ClientProcessMonitorLayer, concurrency::ConcurrencyLayer, panic::CatchUnwindLayer, server::LifecycleLayer, tracing::TracingLayer, @@ -8,6 +7,7 @@ use noir_lsp::NargoLspService; use tower::ServiceBuilder; use super::NargoConfig; +use crate::backends::Backend; use crate::errors::CliError; /// Starts the Noir LSP server @@ -18,12 +18,12 @@ use crate::errors::CliError; #[derive(Debug, Clone, Args)] pub(crate) struct LspCommand; -pub(crate) fn run( +pub(crate) fn run( // Backend is currently unused, but we might want to use it to inform the lsp in the future - _backend: &B, + _backend: &Backend, _args: LspCommand, _config: NargoConfig, -) -> Result<(), CliError> { +) -> Result<(), CliError> { use tokio::runtime::Builder; let runtime = Builder::new_current_thread().enable_all().build().unwrap(); diff --git a/crates/nargo_cli/src/cli/mod.rs b/crates/nargo_cli/src/cli/mod.rs index 030eb114541..0a1fc059ff4 100644 --- a/crates/nargo_cli/src/cli/mod.rs +++ b/crates/nargo_cli/src/cli/mod.rs @@ -74,7 +74,7 @@ pub(crate) fn start_cli() -> eyre::Result<()> { config.program_dir = find_package_root(&config.program_dir)?; } - let backend = crate::backends::ConcreteBackend; + let backend = crate::backends::Backend::default(); match command { NargoCommand::New(args) => new_cmd::run(&backend, args, config), diff --git a/crates/nargo_cli/src/cli/new_cmd.rs b/crates/nargo_cli/src/cli/new_cmd.rs index d6a9d00257b..b4c823d0c1e 100644 --- a/crates/nargo_cli/src/cli/new_cmd.rs +++ b/crates/nargo_cli/src/cli/new_cmd.rs @@ -1,7 +1,7 @@ +use crate::backends::Backend; use crate::errors::CliError; use super::{init_cmd::initialize_project, NargoConfig}; -use acvm::Backend; use clap::Args; use nargo::package::PackageType; use noirc_frontend::graph::CrateName; @@ -30,12 +30,12 @@ pub(crate) struct NewCommand { pub(crate) contract: bool, } -pub(crate) fn run( +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, + _backend: &Backend, args: NewCommand, config: NargoConfig, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let package_dir = config.program_dir.join(&args.path); if package_dir.exists() { diff --git a/crates/nargo_cli/src/cli/prove_cmd.rs b/crates/nargo_cli/src/cli/prove_cmd.rs index 2ec1df2fdd4..5a7cff62078 100644 --- a/crates/nargo_cli/src/cli/prove_cmd.rs +++ b/crates/nargo_cli/src/cli/prove_cmd.rs @@ -1,10 +1,8 @@ use std::path::{Path, PathBuf}; -use acvm::Backend; use clap::Args; use nargo::artifacts::program::PreprocessedProgram; use nargo::constants::{PROVER_INPUT_FILE, VERIFIER_INPUT_FILE}; -use nargo::ops::{prove_execution, verify_proof}; use nargo::package::Package; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::Format; @@ -18,7 +16,7 @@ use super::fs::{ proof::save_proof_to_dir, }; use super::NargoConfig; -use crate::{cli::execute_cmd::execute_program, errors::CliError}; +use crate::{backends::Backend, cli::execute_cmd::execute_program, errors::CliError}; // TODO(#1388): pull this from backend. const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg"; @@ -50,11 +48,11 @@ pub(crate) struct ProveCommand { compile_options: CompileOptions, } -pub(crate) fn run( - backend: &B, +pub(crate) fn run( + backend: &Backend, args: ProveCommand, config: NargoConfig, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -81,8 +79,8 @@ pub(crate) fn run( } #[allow(clippy::too_many_arguments)] -pub(crate) fn prove_package( - backend: &B, +pub(crate) fn prove_package( + backend: &Backend, package: &Package, prover_name: &str, verifier_name: &str, @@ -90,7 +88,7 @@ pub(crate) fn prove_package( circuit_build_path: PathBuf, check_proof: bool, compile_options: &CompileOptions, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let (preprocessed_program, debug_data) = if circuit_build_path.exists() { let program = read_program_from_file(circuit_build_path)?; @@ -126,13 +124,11 @@ pub(crate) fn prove_package( Format::Toml, )?; - let proof = prove_execution(backend, &bytecode, solved_witness) - .map_err(CliError::ProofSystemCompilerError)?; + let proof = backend.prove(&bytecode, solved_witness, false)?; if check_proof { let public_inputs = public_abi.encode(&public_inputs, return_value)?; - let valid_proof = verify_proof(backend, &bytecode, &proof, public_inputs) - .map_err(CliError::ProofSystemCompilerError)?; + let valid_proof = backend.verify(&proof, public_inputs, &bytecode, false)?; 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 a37766ad152..1b4f37a4528 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::io::Write; -use acvm::{Backend, BlackBoxFunctionSolver}; +use acvm::BlackBoxFunctionSolver; use clap::Args; use nargo::{ ops::{run_test, TestStatus}, @@ -12,7 +12,7 @@ use noirc_driver::CompileOptions; use noirc_frontend::{graph::CrateName, hir::FunctionNameMatch}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; -use crate::{cli::check_cmd::check_crate_and_report_errors, errors::CliError}; +use crate::{backends::Backend, cli::check_cmd::check_crate_and_report_errors, errors::CliError}; use super::NargoConfig; @@ -42,11 +42,11 @@ pub(crate) struct TestCommand { compile_options: CompileOptions, } -pub(crate) fn run( - _backend: &B, +pub(crate) fn run( + _backend: &Backend, args: TestCommand, config: NargoConfig, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -75,13 +75,13 @@ pub(crate) fn run( Ok(()) } -fn run_tests( +fn run_tests( blackbox_solver: &S, package: &Package, test_name: FunctionNameMatch, show_output: bool, compile_options: &CompileOptions, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let (mut context, crate_id) = prepare_package(package); check_crate_and_report_errors(&mut context, crate_id, compile_options.deny_warnings)?; diff --git a/crates/nargo_cli/src/cli/verify_cmd.rs b/crates/nargo_cli/src/cli/verify_cmd.rs index dfae743c0c7..187b24123f6 100644 --- a/crates/nargo_cli/src/cli/verify_cmd.rs +++ b/crates/nargo_cli/src/cli/verify_cmd.rs @@ -3,12 +3,10 @@ use super::{ compile_cmd::compile_package, fs::{inputs::read_inputs_from_file, load_hex_data, program::read_program_from_file}, }; -use crate::errors::CliError; +use crate::{backends::Backend, errors::CliError}; -use acvm::Backend; use clap::Args; use nargo::constants::{PROOF_EXT, VERIFIER_INPUT_FILE}; -use nargo::ops::verify_proof; use nargo::{artifacts::program::PreprocessedProgram, package::Package}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::Format; @@ -38,11 +36,11 @@ pub(crate) struct VerifyCommand { compile_options: CompileOptions, } -pub(crate) fn run( - backend: &B, +pub(crate) fn run( + backend: &Backend, args: VerifyCommand, config: NargoConfig, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -68,14 +66,14 @@ pub(crate) fn run( Ok(()) } -fn verify_package( - backend: &B, +fn verify_package( + backend: &Backend, package: &Package, proof_path: &Path, circuit_build_path: PathBuf, verifier_name: &str, compile_options: &CompileOptions, -) -> Result<(), CliError> { +) -> Result<(), CliError> { let preprocessed_program = if circuit_build_path.exists() { read_program_from_file(circuit_build_path)? } else { @@ -98,8 +96,7 @@ fn verify_package( let public_inputs = public_abi.encode(&public_inputs_map, return_value)?; let proof = load_hex_data(proof_path)?; - let valid_proof = verify_proof(backend, &bytecode, &proof, public_inputs) - .map_err(CliError::ProofSystemCompilerError)?; + let valid_proof = backend.verify(&proof, public_inputs, &bytecode, false)?; if valid_proof { Ok(()) diff --git a/crates/nargo_cli/src/errors.rs b/crates/nargo_cli/src/errors.rs index ac59576692b..24faff632b1 100644 --- a/crates/nargo_cli/src/errors.rs +++ b/crates/nargo_cli/src/errors.rs @@ -1,4 +1,5 @@ -use acvm::{acir::native_types::WitnessMapError, Backend, ProofSystemCompiler, SmartContract}; +use acvm::acir::native_types::WitnessMapError; +use acvm_backend_barretenberg::BackendError; use hex::FromHexError; use nargo::NargoError; use nargo_toml::ManifestError; @@ -29,7 +30,7 @@ pub(crate) enum FilesystemError { } #[derive(Debug, Error)] -pub(crate) enum CliError { +pub(crate) enum CliError { #[error("{0}")] Generic(String), #[error("Error: destination {} already exists", .0.display())] @@ -64,13 +65,9 @@ pub(crate) enum CliError { #[error(transparent)] CompileError(#[from] CompileError), - /// Backend error caused by a function on the SmartContract trait + /// Backend error #[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 + SmartContractError(#[from] BackendError), } /// Errors covering situations where a package cannot be compiled. From 0fcc1b7941e68cd3bb33f9c863398f728ab727ea Mon Sep 17 00:00:00 2001 From: Tom French Date: Fri, 1 Sep 2023 00:34:39 +0100 Subject: [PATCH 5/7] chore: remove usage of `expect` in `Backend` --- crates/acvm_backend_barretenberg/src/proof_system.rs | 6 ++---- crates/acvm_backend_barretenberg/src/smart_contract.rs | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/crates/acvm_backend_barretenberg/src/proof_system.rs b/crates/acvm_backend_barretenberg/src/proof_system.rs index 504f4653ec6..765004a1d0a 100644 --- a/crates/acvm_backend_barretenberg/src/proof_system.rs +++ b/crates/acvm_backend_barretenberg/src/proof_system.rs @@ -87,8 +87,7 @@ impl Backend { witness_path, proof_path: proof_path.clone(), } - .run(&binary_path) - .expect("prove command failed"); + .run(&binary_path)?; let proof_with_public_inputs = read_bytes_from_file(&proof_path).unwrap(); @@ -146,8 +145,7 @@ impl Backend { bytecode_path, vk_path_output: vk_path.clone(), } - .run(&binary_path) - .expect("write vk command failed"); + .run(&binary_path)?; // Verify the proof let valid_proof = VerifyCommand { diff --git a/crates/acvm_backend_barretenberg/src/smart_contract.rs b/crates/acvm_backend_barretenberg/src/smart_contract.rs index a881fb18beb..f4b16f1f027 100644 --- a/crates/acvm_backend_barretenberg/src/smart_contract.rs +++ b/crates/acvm_backend_barretenberg/src/smart_contract.rs @@ -32,8 +32,7 @@ impl Backend { bytecode_path, vk_path_output: vk_path.clone(), } - .run(&binary_path) - .expect("write vk command failed"); + .run(&binary_path)?; let contract_path = temp_directory_path.join("contract"); ContractCommand { @@ -42,8 +41,7 @@ impl Backend { vk_path, contract_path: contract_path.clone(), } - .run(&binary_path) - .expect("contract command failed"); + .run(&binary_path)?; let verification_key_library_bytes = read_bytes_from_file(&contract_path).unwrap(); let verification_key_library = String::from_utf8(verification_key_library_bytes).unwrap(); From 2668ac2a8380ac362de34e7b8f1c231608d3606a Mon Sep 17 00:00:00 2001 From: Maddiaa <47148561+Maddiaa0@users.noreply.github.com> Date: Fri, 1 Sep 2023 11:55:05 +0100 Subject: [PATCH 6/7] feat(aztec_noir): abstract kernel return types (#2521) --- .../src/hir/def_map/aztec_library.rs | 175 ++++++++++++++++-- 1 file changed, 162 insertions(+), 13 deletions(-) diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_library.rs b/crates/noirc_frontend/src/hir/def_map/aztec_library.rs index 12aa60276ce..38a45bc16c4 100644 --- a/crates/noirc_frontend/src/hir/def_map/aztec_library.rs +++ b/crates/noirc_frontend/src/hir/def_map/aztec_library.rs @@ -5,8 +5,9 @@ use crate::graph::CrateId; use crate::{ hir::Context, token::Attribute, BlockExpression, CallExpression, CastExpression, Distinctness, Expression, ExpressionKind, ForExpression, FunctionReturnType, Ident, ImportStatement, - IndexExpression, LetStatement, Literal, MethodCallExpression, NoirFunction, ParsedModule, Path, - PathKind, Pattern, Statement, UnresolvedType, UnresolvedTypeData, Visibility, + IndexExpression, LetStatement, Literal, MemberAccessExpression, MethodCallExpression, + NoirFunction, ParsedModule, Path, PathKind, Pattern, Statement, UnresolvedType, + UnresolvedTypeData, Visibility, }; use noirc_errors::FileDiagnostic; @@ -33,6 +34,10 @@ fn variable(name: &str) -> Expression { expression(ExpressionKind::Variable(ident_path(name))) } +fn variable_ident(identifier: Ident) -> Expression { + expression(ExpressionKind::Variable(path(identifier))) +} + fn variable_path(path: Path) -> Expression { expression(ExpressionKind::Variable(path)) } @@ -61,6 +66,13 @@ fn mutable_assignment(name: &str, assigned_to: Expression) -> Statement { }) } +fn member_access(lhs: &str, rhs: &str) -> Expression { + expression(ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { + lhs: variable(lhs), + rhs: ident(rhs), + }))) +} + macro_rules! chained_path { ( $base:expr $(, $tail:expr)* ) => { { @@ -101,6 +113,13 @@ fn index_array(array: Ident, index: &str) -> Expression { }))) } +fn index_array_variable(array: Expression, index: &str) -> Expression { + expression(ExpressionKind::Index(Box::new(IndexExpression { + collection: array, + index: variable(index), + }))) +} + fn import(path: Path) -> ImportStatement { ImportStatement { path, alias: None } } @@ -203,6 +222,11 @@ fn transform_function(ty: &str, func: &mut NoirFunction) { let input = create_inputs(&inputs_name); func.def.parameters.insert(0, input); + // Abstract return types such that they get added to the kernel's return_values + if let Some(return_values) = abstract_return_values(func) { + func.def.body.0.push(return_values); + } + // Push the finish method call to the end of the function let finish_def = create_context_finish(); func.def.body.0.push(finish_def); @@ -332,6 +356,124 @@ fn create_context(ty: &str, params: &[(Pattern, UnresolvedType, Visibility)]) -> injected_expressions } +/// Abstract Return Type +/// +/// This function intercepts the function's current return type and replaces it with pushes +/// To the kernel +/// +/// The replaced code: +/// ```noir +/// /// Before +/// #[aztec(private)] +/// fn foo() -> abi::PrivateCircuitPublicInputs { +/// // ... +/// let my_return_value: Field = 10; +/// context.return_values.push(my_return_value); +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() -> Field { +/// // ... +/// let my_return_value: Field = 10; +/// my_return_value +/// } +/// ``` +/// Similarly; Structs will be pushed to the context, after serialize() is called on them. +/// Arrays will be iterated over and each element will be pushed to the context. +/// Any primitive type that can be cast will be casted to a field and pushed to the context. +fn abstract_return_values(func: &mut NoirFunction) -> Option { + let current_return_type = func.return_type().typ; + let len = func.def.body.len(); + let last_statement = &func.def.body.0[len - 1]; + + // TODO: (length, type) => We can limit the size of the array returned to be limited by kernel size + // Doesnt need done until we have settled on a kernel size + // TODO: support tuples here and in inputs -> convert into an issue + + // Check if the return type is an expression, if it is, we can handle it + match last_statement { + Statement::Expression(expression) => match current_return_type { + // Call serialize on structs, push the whole array, calling push_array + UnresolvedTypeData::Named(..) => Some(make_struct_return_type(expression.clone())), + UnresolvedTypeData::Array(..) => Some(make_array_return_type(expression.clone())), + // Cast these types to a field before pushing + UnresolvedTypeData::Bool | UnresolvedTypeData::Integer(..) => { + Some(make_castable_return_type(expression.clone())) + } + UnresolvedTypeData::FieldElement => Some(make_return_push(expression.clone())), + _ => None, + }, + _ => None, + } +} + +/// Context Return Values +/// +/// Creates an instance to the context return values +/// ```noir +/// `context.return_values` +/// ``` +fn context_return_values() -> Expression { + member_access("context", "return_values") +} + +/// Make return Push +/// +/// Translates to: +/// `context.return_values.push({push_value})` +fn make_return_push(push_value: Expression) -> Statement { + Statement::Semi(method_call(context_return_values(), "push", vec![push_value])) +} + +/// Make Return push array +/// +/// Translates to: +/// `context.return_values.push_array({push_value})` +fn make_return_push_array(push_value: Expression) -> Statement { + Statement::Semi(method_call(context_return_values(), "push_array", vec![push_value])) +} + +/// Make struct return type +/// +/// Translates to: +/// ```noir +/// `context.return_values.push_array({push_value}.serialize())` +fn make_struct_return_type(expression: Expression) -> Statement { + let serialised_call = method_call( + expression.clone(), // variable + "serialize", // method name + vec![], // args + ); + make_return_push_array(serialised_call) +} + +/// Make array return type +/// +/// Translates to: +/// ```noir +/// for i in 0..{ident}.len() { +/// context.return_values.push({ident}[i] as Field) +/// } +/// ``` +fn make_array_return_type(expression: Expression) -> Statement { + let inner_cast_expression = + cast(index_array_variable(expression.clone(), "i"), UnresolvedTypeData::FieldElement); + create_loop_over(expression.clone(), vec![inner_cast_expression]) +} + +/// Castable return type +/// +/// Translates to: +/// ```noir +/// context.return_values.push({ident} as Field) +/// ``` +fn make_castable_return_type(expression: Expression) -> Statement { + // Cast these types to a field before pushing + let cast_expression = cast(expression.clone(), UnresolvedTypeData::FieldElement); + make_return_push(cast_expression) +} + /// Create Return Type /// /// Public functions return abi::PublicCircuitPublicInputs while @@ -407,30 +549,24 @@ fn add_struct_to_hasher(identifier: &Ident) -> Statement { )) } -fn add_array_to_hasher(identifier: &Ident) -> Statement { +fn create_loop_over(var: Expression, loop_body: Vec) -> Statement { // If this is an array of primitive types (integers / fields) we can add them each to the hasher // casted to a field // `array.len()` let end_range_expression = method_call( - variable_path(path(identifier.clone())), // variable - "len", // method name - vec![], // args + var.clone(), // variable + "len", // method name + vec![], // args ); - // Wrap in the semi thing - does that mean ended with semi colon? - // `hasher.add({ident}[i] as Field)` - let cast_expression = cast( - index_array(identifier.clone(), "i"), // lhs - `ident[i]` - UnresolvedTypeData::FieldElement, // cast to - `as Field` - ); // What will be looped over // - `hasher.add({ident}[i] as Field)` let for_loop_block = expression(ExpressionKind::Block(BlockExpression(vec![Statement::Semi(method_call( variable("hasher"), // variable "add", // method name - vec![cast_expression], + loop_body, ))]))); // `for i in 0..{ident}.len()` @@ -444,6 +580,19 @@ fn add_array_to_hasher(identifier: &Ident) -> Statement { })))) } +fn add_array_to_hasher(identifier: &Ident) -> Statement { + // If this is an array of primitive types (integers / fields) we can add them each to the hasher + // casted to a field + + // Wrap in the semi thing - does that mean ended with semi colon? + // `hasher.add({ident}[i] as Field)` + let cast_expression = cast( + index_array(identifier.clone(), "i"), // lhs - `ident[i]` + UnresolvedTypeData::FieldElement, // cast to - `as Field` + ); + create_loop_over(variable_ident(identifier.clone()), vec![cast_expression]) +} + fn add_field_to_hasher(identifier: &Ident) -> Statement { // `hasher.add({ident})` let iden = variable_path(path(identifier.clone())); From 92af05a8f4219eb7e41348df8c5877b9d7ddb6db Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 1 Sep 2023 12:17:05 +0100 Subject: [PATCH 7/7] chore: improve types in `acvm-backend-barretenberg` (#2516) --- .../src/bb/contract.rs | 35 ++++++------- .../acvm_backend_barretenberg/src/bb/gates.rs | 19 ++++--- .../acvm_backend_barretenberg/src/bb/prove.rs | 34 +++++++------ .../src/bb/verify.rs | 44 ++++++++-------- .../src/bb/write_vk.rs | 26 +++++----- .../src/proof_system.rs | 50 ++++++++----------- .../src/smart_contract.rs | 25 +++++----- 7 files changed, 113 insertions(+), 120 deletions(-) diff --git a/crates/acvm_backend_barretenberg/src/bb/contract.rs b/crates/acvm_backend_barretenberg/src/bb/contract.rs index d84a8daa44a..49edefafb1b 100644 --- a/crates/acvm_backend_barretenberg/src/bb/contract.rs +++ b/crates/acvm_backend_barretenberg/src/bb/contract.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use super::{assert_binary_exists, get_binary_path, CliShimError}; /// VerifyCommand will call the barretenberg binary @@ -9,9 +11,9 @@ use super::{assert_binary_exists, get_binary_path, CliShimError}; /// remaining logic that is missing. pub(crate) struct ContractCommand { pub(crate) verbose: bool, - pub(crate) path_to_crs: String, - pub(crate) path_to_vk: String, - pub(crate) path_to_contract: String, + pub(crate) crs_path: PathBuf, + pub(crate) vk_path: PathBuf, + pub(crate) contract_path: PathBuf, } impl ContractCommand { @@ -22,11 +24,11 @@ impl ContractCommand { command .arg("contract") .arg("-c") - .arg(self.path_to_crs) + .arg(self.crs_path) .arg("-k") - .arg(self.path_to_vk) + .arg(self.vk_path) .arg("-o") - .arg(self.path_to_contract); + .arg(self.contract_path); if self.verbose { command.arg("-v"); @@ -46,30 +48,25 @@ impl ContractCommand { fn contract_command() { use tempfile::tempdir; - let path_to_1_mul = "./src/1_mul.bytecode"; + let bytecode_path = PathBuf::from("./src/1_mul.bytecode"); let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory_path = temp_directory.path(); - let path_to_crs = temp_directory_path.join("crs"); - let path_to_vk = temp_directory_path.join("vk"); - let path_to_contract = temp_directory_path.join("contract"); + let crs_path = temp_directory_path.join("crs"); + let vk_path = temp_directory_path.join("vk"); + let contract_path = temp_directory_path.join("contract"); let write_vk_command = super::WriteVkCommand { verbose: true, - path_to_bytecode: path_to_1_mul.to_string(), - path_to_vk_output: path_to_vk.to_str().unwrap().to_string(), + bytecode_path, + vk_path_output: vk_path.clone(), is_recursive: false, - path_to_crs: path_to_crs.to_str().unwrap().to_string(), + crs_path: crs_path.clone(), }; assert!(write_vk_command.run().is_ok()); - let contract_command = ContractCommand { - verbose: true, - path_to_vk: path_to_vk.to_str().unwrap().to_string(), - path_to_crs: path_to_crs.to_str().unwrap().to_string(), - path_to_contract: path_to_contract.to_str().unwrap().to_string(), - }; + let contract_command = ContractCommand { verbose: true, vk_path, crs_path, contract_path }; assert!(contract_command.run().is_ok()); drop(temp_directory); diff --git a/crates/acvm_backend_barretenberg/src/bb/gates.rs b/crates/acvm_backend_barretenberg/src/bb/gates.rs index 38cfb9b135d..eaa631bd076 100644 --- a/crates/acvm_backend_barretenberg/src/bb/gates.rs +++ b/crates/acvm_backend_barretenberg/src/bb/gates.rs @@ -1,11 +1,13 @@ +use std::path::PathBuf; + use super::{assert_binary_exists, get_binary_path}; /// GatesCommand will call the barretenberg binary /// to return the number of gates needed to create a proof /// for the given bytecode. pub(crate) struct GatesCommand { - pub(crate) path_to_crs: String, - pub(crate) path_to_bytecode: String, + pub(crate) crs_path: PathBuf, + pub(crate) bytecode_path: PathBuf, } impl GatesCommand { @@ -14,9 +16,9 @@ impl GatesCommand { let output = std::process::Command::new(get_binary_path()) .arg("gates") .arg("-c") - .arg(self.path_to_crs) + .arg(self.crs_path) .arg("-b") - .arg(self.path_to_bytecode) + .arg(self.bytecode_path) .output() .expect("Failed to execute command"); @@ -55,16 +57,13 @@ impl GatesCommand { fn gate_command() { use tempfile::tempdir; - let path_to_1_mul = "./src/1_mul.bytecode"; + let bytecode_path = PathBuf::from("./src/1_mul.bytecode"); let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory_path = temp_directory.path(); - let path_to_crs = temp_directory_path.join("crs"); + let crs_path = temp_directory_path.join("crs"); - let gate_command = GatesCommand { - path_to_crs: path_to_crs.to_str().unwrap().to_string(), - path_to_bytecode: path_to_1_mul.to_string(), - }; + let gate_command = GatesCommand { crs_path, bytecode_path }; let output = gate_command.run(); assert_eq!(output, 2775); diff --git a/crates/acvm_backend_barretenberg/src/bb/prove.rs b/crates/acvm_backend_barretenberg/src/bb/prove.rs index 481748e291a..a2cad1c9811 100644 --- a/crates/acvm_backend_barretenberg/src/bb/prove.rs +++ b/crates/acvm_backend_barretenberg/src/bb/prove.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use super::{assert_binary_exists, get_binary_path, CliShimError}; /// ProveCommand will call the barretenberg binary @@ -9,11 +11,11 @@ use super::{assert_binary_exists, get_binary_path, CliShimError}; /// The proof will be written to the specified output file. pub(crate) struct ProveCommand { pub(crate) verbose: bool, - pub(crate) path_to_crs: String, + pub(crate) crs_path: PathBuf, pub(crate) is_recursive: bool, - pub(crate) path_to_bytecode: String, - pub(crate) path_to_witness: String, - pub(crate) path_to_proof: String, + pub(crate) bytecode_path: PathBuf, + pub(crate) witness_path: PathBuf, + pub(crate) proof_path: PathBuf, } impl ProveCommand { @@ -24,13 +26,13 @@ impl ProveCommand { command .arg("prove") .arg("-c") - .arg(self.path_to_crs) + .arg(self.crs_path) .arg("-b") - .arg(self.path_to_bytecode) + .arg(self.bytecode_path) .arg("-w") - .arg(self.path_to_witness) + .arg(self.witness_path) .arg("-o") - .arg(self.path_to_proof); + .arg(self.proof_path); if self.verbose { command.arg("-v"); @@ -54,22 +56,22 @@ impl ProveCommand { fn prove_command() { use tempfile::tempdir; - let path_to_1_mul = "./src/1_mul.bytecode"; - let path_to_1_mul_witness = "./src/witness.tr"; + let bytecode_path = PathBuf::from("./src/1_mul.bytecode"); + let witness_path = PathBuf::from("./src/witness.tr"); let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory_path = temp_directory.path(); - let path_to_crs = temp_directory_path.join("crs"); - let path_to_proof = temp_directory_path.join("1_mul").with_extension("proof"); + let crs_path = temp_directory_path.join("crs"); + let proof_path = temp_directory_path.join("1_mul").with_extension("proof"); let prove_command = ProveCommand { verbose: true, - path_to_crs: path_to_crs.to_str().unwrap().to_string(), + crs_path, + bytecode_path, + witness_path, is_recursive: false, - path_to_bytecode: path_to_1_mul.to_string(), - path_to_witness: path_to_1_mul_witness.to_string(), - path_to_proof: path_to_proof.to_str().unwrap().to_string(), + proof_path, }; let proof_created = prove_command.run(); diff --git a/crates/acvm_backend_barretenberg/src/bb/verify.rs b/crates/acvm_backend_barretenberg/src/bb/verify.rs index f7352fa232f..77e356a98c5 100644 --- a/crates/acvm_backend_barretenberg/src/bb/verify.rs +++ b/crates/acvm_backend_barretenberg/src/bb/verify.rs @@ -1,13 +1,15 @@ +use std::path::PathBuf; + use super::{assert_binary_exists, get_binary_path}; /// VerifyCommand will call the barretenberg binary /// to verify a proof pub(crate) struct VerifyCommand { pub(crate) verbose: bool, - pub(crate) path_to_crs: String, + pub(crate) crs_path: PathBuf, pub(crate) is_recursive: bool, - pub(crate) path_to_proof: String, - pub(crate) path_to_vk: String, + pub(crate) proof_path: PathBuf, + pub(crate) vk_path: PathBuf, } impl VerifyCommand { @@ -18,11 +20,11 @@ impl VerifyCommand { command .arg("verify") .arg("-c") - .arg(self.path_to_crs) + .arg(self.crs_path) .arg("-p") - .arg(self.path_to_proof) + .arg(self.proof_path) .arg("-k") - .arg(self.path_to_vk); + .arg(self.vk_path); if self.verbose { command.arg("-v"); @@ -43,22 +45,22 @@ fn verify_command() { use crate::bb::{ProveCommand, WriteVkCommand}; - let path_to_1_mul = "./src/1_mul.bytecode"; - let path_to_1_mul_witness = "./src/witness.tr"; + let bytecode_path = PathBuf::from("./src/1_mul.bytecode"); + let witness_path = PathBuf::from("./src/witness.tr"); let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory_path = temp_directory.path(); - let path_to_crs = temp_directory_path.join("crs"); - let path_to_proof = temp_directory_path.join("1_mul").with_extension("proof"); - let path_to_vk = temp_directory_path.join("vk"); + let crs_path = temp_directory_path.join("crs"); + let proof_path = temp_directory_path.join("1_mul").with_extension("proof"); + let vk_path_output = temp_directory_path.join("vk"); let write_vk_command = WriteVkCommand { verbose: true, - path_to_bytecode: path_to_1_mul.to_string(), - path_to_crs: path_to_crs.to_str().unwrap().to_string(), + bytecode_path: bytecode_path.clone(), + crs_path: crs_path.clone(), is_recursive: false, - path_to_vk_output: path_to_vk.to_str().unwrap().to_string(), + vk_path_output: vk_path_output.clone(), }; let vk_written = write_vk_command.run(); @@ -66,20 +68,20 @@ fn verify_command() { let prove_command = ProveCommand { verbose: true, - path_to_crs: path_to_crs.to_str().unwrap().to_string(), + crs_path: crs_path.clone(), is_recursive: false, - path_to_bytecode: path_to_1_mul.to_string(), - path_to_witness: path_to_1_mul_witness.to_string(), - path_to_proof: path_to_proof.to_str().unwrap().to_string(), + bytecode_path, + witness_path, + proof_path: proof_path.clone(), }; prove_command.run().unwrap(); let verify_command = VerifyCommand { verbose: true, - path_to_crs: path_to_crs.to_str().unwrap().to_string(), + crs_path, is_recursive: false, - path_to_proof: path_to_proof.to_str().unwrap().to_string(), - path_to_vk: path_to_vk.to_str().unwrap().to_string(), + proof_path, + vk_path: vk_path_output, }; let verified = verify_command.run(); diff --git a/crates/acvm_backend_barretenberg/src/bb/write_vk.rs b/crates/acvm_backend_barretenberg/src/bb/write_vk.rs index 67706632185..01473ea4ef3 100644 --- a/crates/acvm_backend_barretenberg/src/bb/write_vk.rs +++ b/crates/acvm_backend_barretenberg/src/bb/write_vk.rs @@ -1,13 +1,15 @@ +use std::path::PathBuf; + use super::{assert_binary_exists, get_binary_path, CliShimError}; /// WriteCommand will call the barretenberg binary /// to write a verification key to a file pub(crate) struct WriteVkCommand { pub(crate) verbose: bool, - pub(crate) path_to_crs: String, + pub(crate) crs_path: PathBuf, pub(crate) is_recursive: bool, - pub(crate) path_to_bytecode: String, - pub(crate) path_to_vk_output: String, + pub(crate) bytecode_path: PathBuf, + pub(crate) vk_path_output: PathBuf, } impl WriteVkCommand { @@ -18,11 +20,11 @@ impl WriteVkCommand { command .arg("write_vk") .arg("-c") - .arg(self.path_to_crs) + .arg(self.crs_path) .arg("-b") - .arg(self.path_to_bytecode) + .arg(self.bytecode_path) .arg("-o") - .arg(self.path_to_vk_output); + .arg(self.vk_path_output); if self.verbose { command.arg("-v"); @@ -46,19 +48,19 @@ impl WriteVkCommand { fn write_vk_command() { use tempfile::tempdir; - let path_to_1_mul = "./src/1_mul.bytecode"; + let bytecode_path = PathBuf::from("./src/1_mul.bytecode"); let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory_path = temp_directory.path(); - let path_to_crs = temp_directory_path.join("crs"); - let path_to_vk = temp_directory_path.join("vk"); + let crs_path = temp_directory_path.join("crs"); + let vk_path_output = temp_directory_path.join("vk"); let write_vk_command = WriteVkCommand { verbose: true, - path_to_bytecode: path_to_1_mul.to_string(), - path_to_crs: path_to_crs.to_str().unwrap().to_string(), + bytecode_path, + crs_path, is_recursive: false, - path_to_vk_output: path_to_vk.to_str().unwrap().to_string(), + vk_path_output, }; let vk_written = write_vk_command.run(); diff --git a/crates/acvm_backend_barretenberg/src/proof_system.rs b/crates/acvm_backend_barretenberg/src/proof_system.rs index 93f40666f6c..fa6952b947f 100644 --- a/crates/acvm_backend_barretenberg/src/proof_system.rs +++ b/crates/acvm_backend_barretenberg/src/proof_system.rs @@ -18,20 +18,15 @@ impl Backend { pub fn get_exact_circuit_size(&self, circuit: &Circuit) -> Result { let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory = temp_directory.path(); - let temp_dir_path_str = temp_directory.to_str().unwrap(); + let temp_directory = temp_directory.path().to_path_buf(); // Create a temporary file for the circuit - // let circuit_path = temp_directory.join("circuit").with_extension("bytecode"); let serialized_circuit = serialize_circuit(circuit); write_to_file(serialized_circuit.as_bytes(), &circuit_path); - let number_of_gates_needed = GatesCommand { - path_to_crs: temp_dir_path_str.to_string(), - path_to_bytecode: circuit_path.as_os_str().to_str().unwrap().to_string(), - } - .run(); + let number_of_gates_needed = + GatesCommand { crs_path: temp_directory, bytecode_path: circuit_path }.run(); Ok(number_of_gates_needed) } @@ -68,8 +63,7 @@ impl Backend { is_recursive: bool, ) -> Result, BackendError> { let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory = temp_directory.path(); - let temp_dir_path_str = temp_directory.to_str().unwrap(); + let temp_directory = temp_directory.path().to_path_buf(); // Create a temporary file for the witness let serialized_witnesses: Vec = @@ -79,26 +73,25 @@ impl Backend { // Create a temporary file for the circuit // - let circuit_path = temp_directory.join("circuit").with_extension("bytecode"); + let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); let serialized_circuit = serialize_circuit(circuit); - write_to_file(serialized_circuit.as_bytes(), &circuit_path); + write_to_file(serialized_circuit.as_bytes(), &bytecode_path); let proof_path = temp_directory.join("proof").with_extension("proof"); // Create proof and store it in the specified path ProveCommand { verbose: true, - path_to_crs: temp_dir_path_str.to_string(), + crs_path: temp_directory, is_recursive, - path_to_bytecode: circuit_path.as_os_str().to_str().unwrap().to_string(), - path_to_witness: witness_path.as_os_str().to_str().unwrap().to_string(), - path_to_proof: proof_path.as_os_str().to_str().unwrap().to_string(), + bytecode_path, + witness_path, + proof_path: proof_path.clone(), } .run() .expect("prove command failed"); - let proof_with_public_inputs = - read_bytes_from_file(proof_path.as_os_str().to_str().unwrap()).unwrap(); + let proof_with_public_inputs = read_bytes_from_file(&proof_path).unwrap(); // Barretenberg return the proof prepended with the public inputs. // @@ -120,8 +113,7 @@ impl Backend { is_recursive: bool, ) -> Result { let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory = temp_directory.path(); - let temp_dir_path = temp_directory.to_str().unwrap(); + let temp_directory = temp_directory.path().to_path_buf(); // Unlike when proving, we omit any unassigned witnesses. // Witness values should be ordered by their index but we skip over any indices without an assignment. @@ -140,18 +132,18 @@ impl Backend { write_to_file(&proof_with_public_inputs, &proof_path); // Create a temporary file for the circuit - let circuit_path = temp_directory.join("circuit").with_extension("bytecode"); + let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); let serialized_circuit = serialize_circuit(circuit); - write_to_file(serialized_circuit.as_bytes(), &circuit_path); + write_to_file(serialized_circuit.as_bytes(), &bytecode_path); // Create the verification key and write it to the specified path let vk_path = temp_directory.join("vk"); WriteVkCommand { verbose: false, - path_to_crs: temp_dir_path.to_string(), + crs_path: temp_directory.clone(), is_recursive, - path_to_bytecode: circuit_path.as_os_str().to_str().unwrap().to_string(), - path_to_vk_output: vk_path.as_os_str().to_str().unwrap().to_string(), + bytecode_path, + vk_path_output: vk_path.clone(), } .run() .expect("write vk command failed"); @@ -159,10 +151,10 @@ impl Backend { // Verify the proof Ok(VerifyCommand { verbose: false, - path_to_crs: temp_dir_path.to_string(), + crs_path: temp_directory, is_recursive, - path_to_proof: proof_path.as_os_str().to_str().unwrap().to_string(), - path_to_vk: vk_path.as_os_str().to_str().unwrap().to_string(), + proof_path, + vk_path, } .run()) } @@ -182,7 +174,7 @@ pub(super) fn write_to_file(bytes: &[u8], path: &Path) -> String { } } -pub(super) fn read_bytes_from_file(path: &str) -> std::io::Result> { +pub(super) fn read_bytes_from_file(path: &Path) -> std::io::Result> { // Open the file for reading. let mut file = File::open(path)?; diff --git a/crates/acvm_backend_barretenberg/src/smart_contract.rs b/crates/acvm_backend_barretenberg/src/smart_contract.rs index 29633ef6bfc..cde89647cdd 100644 --- a/crates/acvm_backend_barretenberg/src/smart_contract.rs +++ b/crates/acvm_backend_barretenberg/src/smart_contract.rs @@ -13,37 +13,36 @@ const ULTRA_VERIFIER_CONTRACT: &str = include_str!("contract.sol"); impl Backend { pub fn eth_contract(&self, circuit: &Circuit) -> Result { let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory_path = temp_directory.path(); - let temp_dir_path = temp_directory_path.to_str().unwrap(); + let temp_directory_path = temp_directory.path().to_path_buf(); // Create a temporary file for the circuit - let circuit_path = temp_directory_path.join("circuit").with_extension("bytecode"); + let bytecode_path = temp_directory_path.join("circuit").with_extension("bytecode"); let serialized_circuit = serialize_circuit(circuit); - write_to_file(serialized_circuit.as_bytes(), &circuit_path); + write_to_file(serialized_circuit.as_bytes(), &bytecode_path); // Create the verification key and write it to the specified path - let vk_path = temp_directory_path.join("vk").to_str().unwrap().to_string(); + let vk_path = temp_directory_path.join("vk"); WriteVkCommand { verbose: false, - path_to_crs: temp_dir_path.to_string(), + crs_path: temp_directory_path.clone(), is_recursive: false, - path_to_bytecode: circuit_path.as_os_str().to_str().unwrap().to_string(), - path_to_vk_output: vk_path.clone(), + bytecode_path, + vk_path_output: vk_path.clone(), } .run() .expect("write vk command failed"); - let path_to_contract = temp_directory_path.join("contract").to_str().unwrap().to_string(); + let contract_path = temp_directory_path.join("contract"); ContractCommand { verbose: false, - path_to_crs: temp_dir_path.to_string(), - path_to_vk: vk_path, - path_to_contract: path_to_contract.clone(), + crs_path: temp_directory_path, + vk_path, + contract_path: contract_path.clone(), } .run() .expect("contract command failed"); - let verification_key_library_bytes = read_bytes_from_file(&path_to_contract).unwrap(); + let verification_key_library_bytes = read_bytes_from_file(&contract_path).unwrap(); let verification_key_library = String::from_utf8(verification_key_library_bytes).unwrap(); drop(temp_directory);