diff --git a/Cargo.lock b/Cargo.lock index 1ab81187e3e..0b421ab9de6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2157,6 +2157,7 @@ dependencies = [ "noirc_frontend", "rustc_version 0.4.0", "serde", + "serde_json", "tempdir", "termcolor", "thiserror", diff --git a/crates/nargo/Cargo.toml b/crates/nargo/Cargo.toml index 069508d01c4..92146850827 100644 --- a/crates/nargo/Cargo.toml +++ b/crates/nargo/Cargo.toml @@ -28,6 +28,7 @@ thiserror.workspace = true clap = { version = "4.1.4", features = ["derive"]} const_format = "0.2.30" hex = "0.4.2" +serde_json = "1.0" termcolor = "1.1.2" tempdir = "0.3.7" diff --git a/crates/nargo/src/cli/compile_cmd.rs b/crates/nargo/src/cli/compile_cmd.rs index 8b5a376ee5e..252e808926b 100644 --- a/crates/nargo/src/cli/compile_cmd.rs +++ b/crates/nargo/src/cli/compile_cmd.rs @@ -6,7 +6,7 @@ use clap::Args; use crate::{constants::TARGET_DIR, errors::CliError, resolver::Resolver}; -use super::fs::{acir::save_acir_to_dir, keys::save_key_to_dir}; +use super::fs::{keys::save_key_to_dir, program::save_program_to_file}; use super::{add_std_lib, NargoConfig}; /// Compile the program and its secret execution trace into ACIR format @@ -43,7 +43,7 @@ fn compile_and_preprocess_circuit>( allow_warnings: bool, ) -> Result { let compiled_program = compile_circuit(program_dir, false, allow_warnings)?; - let circuit_path = save_acir_to_dir(&compiled_program.circuit, circuit_name, &circuit_dir); + let circuit_path = save_program_to_file(&compiled_program, circuit_name, &circuit_dir); preprocess_with_path(circuit_name, circuit_dir, &compiled_program.circuit)?; diff --git a/crates/nargo/src/cli/fs/acir.rs b/crates/nargo/src/cli/fs/acir.rs deleted file mode 100644 index 988b97f05ae..00000000000 --- a/crates/nargo/src/cli/fs/acir.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::path::{Path, PathBuf}; - -use acvm::{acir::circuit::Circuit, hash_constraint_system}; - -use crate::constants::ACIR_EXT; - -use super::{create_named_dir, write_to_file}; - -pub(crate) fn save_acir_to_dir>( - circuit: &Circuit, - circuit_name: &str, - circuit_dir: P, -) -> PathBuf { - let mut circuit_path = create_named_dir(circuit_dir.as_ref(), "target"); - circuit_path.push(circuit_name); - - let mut serialized = Vec::new(); - circuit.write(&mut serialized).expect("could not serialize circuit"); - - circuit_path.set_extension(ACIR_EXT); - write_to_file(serialized.as_slice(), &circuit_path); - - // Save a checksum of the circuit to compare against during proving and verification - let acir_hash = hash_constraint_system(circuit); - circuit_path.set_extension(ACIR_EXT.to_owned() + ".sha256"); - write_to_file(hex::encode(acir_hash).as_bytes(), &circuit_path); - - circuit_path -} diff --git a/crates/nargo/src/cli/fs/keys.rs b/crates/nargo/src/cli/fs/keys.rs index e47b28ea68f..0051ef1b045 100644 --- a/crates/nargo/src/cli/fs/keys.rs +++ b/crates/nargo/src/cli/fs/keys.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; use acvm::{acir::circuit::Circuit, hash_constraint_system}; use crate::{ - constants::{ACIR_EXT, PK_EXT, VK_EXT}, + constants::{PK_EXT, VK_EXT}, errors::CliError, }; @@ -31,9 +31,9 @@ pub(crate) fn fetch_pk_and_vk>( prove_circuit: bool, check_proof: bool, ) -> Result<(Vec, Vec), CliError> { - let mut acir_hash_path = PathBuf::new(); - acir_hash_path.push(circuit_build_path.as_ref()); - acir_hash_path.set_extension(ACIR_EXT.to_owned() + ".sha256"); + let mut acir_hash_path = PathBuf::from(circuit_build_path.as_ref()); + acir_hash_path.set_extension("json.checksum"); + let expected_acir_hash = load_hex_data(acir_hash_path.clone())?; let new_acir_hash = hash_constraint_system(circuit); diff --git a/crates/nargo/src/cli/fs/mod.rs b/crates/nargo/src/cli/fs/mod.rs index e8bed13d7a8..b1c859745b6 100644 --- a/crates/nargo/src/cli/fs/mod.rs +++ b/crates/nargo/src/cli/fs/mod.rs @@ -6,9 +6,9 @@ use std::{ use crate::errors::CliError; -pub(super) mod acir; pub(super) mod inputs; pub(super) mod keys; +pub(super) mod program; pub(super) mod proof; pub(super) mod witness; diff --git a/crates/nargo/src/cli/fs/program.rs b/crates/nargo/src/cli/fs/program.rs new file mode 100644 index 00000000000..dce26d6cfdb --- /dev/null +++ b/crates/nargo/src/cli/fs/program.rs @@ -0,0 +1,39 @@ +use std::path::{Path, PathBuf}; + +use acvm::hash_constraint_system; +use noirc_driver::CompiledProgram; + +use crate::errors::CliError; + +use super::{create_named_dir, write_to_file}; + +pub(crate) fn save_program_to_file>( + compiled_program: &CompiledProgram, + circuit_name: &str, + circuit_dir: P, +) -> PathBuf { + let mut circuit_path = create_named_dir(circuit_dir.as_ref(), "target"); + circuit_path.push(circuit_name); + circuit_path.set_extension("json"); + + write_to_file(&serde_json::to_vec(compiled_program).unwrap(), &circuit_path); + + // Save a checksum of the circuit to compare against during proving and verification + let acir_hash = hash_constraint_system(&compiled_program.circuit); + circuit_path.set_extension("json.checksum"); + write_to_file(hex::encode(acir_hash).as_bytes(), &circuit_path); + + circuit_path +} + +pub(crate) fn read_program_from_file>( + circuit_path: P, +) -> 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 program = serde_json::from_slice(&input_string).expect("could not deserialize program"); + + Ok(program) +} diff --git a/crates/nargo/src/cli/prove_cmd.rs b/crates/nargo/src/cli/prove_cmd.rs index c05c0d0eca8..1f6561d4f72 100644 --- a/crates/nargo/src/cli/prove_cmd.rs +++ b/crates/nargo/src/cli/prove_cmd.rs @@ -7,6 +7,7 @@ use noirc_abi::input_parser::Format; use super::fs::{ inputs::{read_inputs_from_file, write_inputs_to_file}, keys::fetch_pk_and_vk, + program::read_program_from_file, proof::save_proof_to_dir, }; use super::NargoConfig; @@ -68,20 +69,29 @@ pub(crate) fn prove_with_path>( proof_name: Option, program_dir: P, proof_dir: P, - circuit_build_path: Option

, + circuit_build_path: Option, check_proof: bool, show_ssa: bool, allow_warnings: bool, ) -> Result, CliError> { - let compiled_program = - super::compile_cmd::compile_circuit(program_dir.as_ref(), show_ssa, allow_warnings)?; - let (proving_key, verification_key) = match circuit_build_path { + let (compiled_program, proving_key, verification_key) = match circuit_build_path { Some(circuit_build_path) => { - fetch_pk_and_vk(&compiled_program.circuit, circuit_build_path, true, true)? + let compiled_program = read_program_from_file(&circuit_build_path)?; + + let (proving_key, verification_key) = + fetch_pk_and_vk(&compiled_program.circuit, circuit_build_path, true, true)?; + (compiled_program, proving_key, verification_key) } None => { + let compiled_program = super::compile_cmd::compile_circuit( + program_dir.as_ref(), + show_ssa, + allow_warnings, + )?; + let backend = crate::backends::ConcreteBackend; - backend.preprocess(&compiled_program.circuit) + let (proving_key, verification_key) = backend.preprocess(&compiled_program.circuit); + (compiled_program, proving_key, verification_key) } }; diff --git a/crates/nargo/src/cli/verify_cmd.rs b/crates/nargo/src/cli/verify_cmd.rs index ab1f8468b2c..829f1ee61f7 100644 --- a/crates/nargo/src/cli/verify_cmd.rs +++ b/crates/nargo/src/cli/verify_cmd.rs @@ -1,4 +1,7 @@ -use super::fs::{inputs::read_inputs_from_file, keys::fetch_pk_and_vk, load_hex_data}; +use super::fs::{ + inputs::read_inputs_from_file, keys::fetch_pk_and_vk, load_hex_data, + program::read_program_from_file, +}; use super::{compile_cmd::compile_circuit, InputMap, NargoConfig}; use crate::{ constants::{PROOFS_DIR, PROOF_EXT, TARGET_DIR, VERIFIER_INPUT_FILE}, @@ -47,14 +50,20 @@ fn verify_with_path>( show_ssa: bool, allow_warnings: bool, ) -> Result<(), CliError> { - let compiled_program = compile_circuit(program_dir.as_ref(), show_ssa, allow_warnings)?; - let (_, verification_key) = match circuit_build_path { + let (compiled_program, verification_key) = match circuit_build_path { Some(circuit_build_path) => { - fetch_pk_and_vk(&compiled_program.circuit, circuit_build_path, false, true)? + let compiled_program = read_program_from_file(&circuit_build_path)?; + + let (_, verification_key) = + fetch_pk_and_vk(&compiled_program.circuit, circuit_build_path, false, true)?; + (compiled_program, verification_key) } None => { + let compiled_program = compile_circuit(program_dir.as_ref(), show_ssa, allow_warnings)?; + let backend = crate::backends::ConcreteBackend; - backend.preprocess(&compiled_program.circuit) + let (_, verification_key) = backend.preprocess(&compiled_program.circuit); + (compiled_program, verification_key) } }; diff --git a/crates/nargo/src/constants.rs b/crates/nargo/src/constants.rs index a06369352b3..3e5b75eb6cd 100644 --- a/crates/nargo/src/constants.rs +++ b/crates/nargo/src/constants.rs @@ -19,8 +19,6 @@ pub(crate) const PKG_FILE: &str = "Nargo.toml"; // Extensions /// The extension for files containing circuit proofs. pub(crate) const PROOF_EXT: &str = "proof"; -/// The extension for files containing circuit ACIR representations. -pub(crate) const ACIR_EXT: &str = "acir"; /// The extension for files containing proof witnesses. pub(crate) const WITNESS_EXT: &str = "tr"; /// The extension for proving keys. diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index ff241bd45cd..a034128307e 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -2,8 +2,6 @@ #![warn(unused_crate_dependencies, unused_extern_crates)] #![warn(unreachable_pub)] -use acvm::acir::circuit::Circuit; - use acvm::Language; use fm::FileType; use noirc_abi::Abi; @@ -14,20 +12,16 @@ use noirc_frontend::hir::def_map::CrateDefMap; use noirc_frontend::hir::Context; use noirc_frontend::monomorphization::monomorphize; use noirc_frontend::node_interner::FuncId; -use serde::{Deserialize, Serialize}; use std::path::{Path, PathBuf}; +mod program; +pub use program::CompiledProgram; + pub struct Driver { context: Context, language: Language, } -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct CompiledProgram { - pub circuit: Circuit, - pub abi: noirc_abi::Abi, -} - impl Driver { pub fn new(np_language: &Language) -> Self { let mut driver = Driver { context: Context::default(), language: np_language.clone() }; diff --git a/crates/noirc_driver/src/program.rs b/crates/noirc_driver/src/program.rs new file mode 100644 index 00000000000..06b11d860dc --- /dev/null +++ b/crates/noirc_driver/src/program.rs @@ -0,0 +1,29 @@ +use acvm::acir::circuit::Circuit; + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct CompiledProgram { + #[serde(serialize_with = "serialize_circuit", deserialize_with = "deserialize_circuit")] + pub circuit: Circuit, + pub abi: noirc_abi::Abi, +} + +fn serialize_circuit(circuit: &Circuit, s: S) -> Result +where + S: Serializer, +{ + let mut circuit_bytes: Vec = Vec::new(); + circuit.write(&mut circuit_bytes).unwrap(); + + circuit_bytes.serialize(s) +} + +fn deserialize_circuit<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let circuit_bytes = Vec::::deserialize(deserializer)?; + let circuit = Circuit::read(&*circuit_bytes).unwrap(); + Ok(circuit) +}