From 21572d0c90555b1a6b3576cb784ff8836c0c6e11 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Thu, 2 Feb 2023 19:00:28 +0000 Subject: [PATCH 1/6] feat(nargo): add flag to verify created proofs --- crates/nargo/src/cli/compile_cmd.rs | 15 +++++-- crates/nargo/src/cli/execute_cmd.rs | 20 ++++----- crates/nargo/src/cli/mod.rs | 12 ++--- crates/nargo/src/cli/prove_cmd.rs | 70 +++++++++++++++++++++-------- crates/nargo/src/cli/verify_cmd.rs | 10 ++--- crates/noirc_driver/src/lib.rs | 2 +- 6 files changed, 85 insertions(+), 44 deletions(-) diff --git a/crates/nargo/src/cli/compile_cmd.rs b/crates/nargo/src/cli/compile_cmd.rs index 1e109c27f33..acab73b4eb6 100644 --- a/crates/nargo/src/cli/compile_cmd.rs +++ b/crates/nargo/src/cli/compile_cmd.rs @@ -3,12 +3,13 @@ use std::path::PathBuf; use acvm::ProofSystemCompiler; use clap::ArgMatches; +use noirc_abi::input_parser::Format; use std::path::Path; use crate::{ - cli::execute_cmd::save_witness_to_dir, - constants::{ACIR_EXT, TARGET_DIR}, + cli::{execute_cmd::save_witness_to_dir, read_inputs_from_file}, + constants::{ACIR_EXT, PROVER_INPUT_FILE, TARGET_DIR}, errors::CliError, resolver::Resolver, }; @@ -54,8 +55,16 @@ pub fn generate_circuit_and_witness_to_disk>( println!("{:?}", std::fs::canonicalize(&circuit_path)); if generate_witness { + // Parse the initial witness values from Prover.toml + let inputs_map = read_inputs_from_file( + program_dir, + PROVER_INPUT_FILE, + Format::Toml, + compiled_program.abi.as_ref().unwrap().clone(), + )?; + let (_, solved_witness) = - super::execute_cmd::execute_program(program_dir, &compiled_program)?; + super::execute_cmd::execute_program(&compiled_program, &inputs_map)?; circuit_path.pop(); save_witness_to_dir(solved_witness, circuit_name, &circuit_path)?; diff --git a/crates/nargo/src/cli/execute_cmd.rs b/crates/nargo/src/cli/execute_cmd.rs index 61ad940a71d..564b47857b6 100644 --- a/crates/nargo/src/cli/execute_cmd.rs +++ b/crates/nargo/src/cli/execute_cmd.rs @@ -51,23 +51,23 @@ fn execute( let compiled_program = super::compile_cmd::compile_circuit(¤t_dir, show_ssa, allow_warnings)?; - execute_program(current_dir, &compiled_program) -} - -pub(crate) fn execute_program>( - inputs_dir: P, - compiled_program: &CompiledProgram, -) -> Result<(Option, WitnessMap), CliError> { // Parse the initial witness values from Prover.toml - let witness_map = read_inputs_from_file( - inputs_dir, + let inputs_map = read_inputs_from_file( + current_dir, PROVER_INPUT_FILE, Format::Toml, compiled_program.abi.as_ref().unwrap().clone(), )?; + execute_program(&compiled_program, &inputs_map) +} + +pub(crate) fn execute_program( + compiled_program: &CompiledProgram, + inputs_map: &InputMap, +) -> Result<(Option, WitnessMap), CliError> { // Solve the remaining witnesses - let solved_witness = solve_witness(compiled_program, &witness_map)?; + let solved_witness = solve_witness(compiled_program, inputs_map)?; let public_inputs = extract_public_inputs(compiled_program, &solved_witness)?; let return_value = public_inputs.get(MAIN_RETURN_NAME).cloned(); diff --git a/crates/nargo/src/cli/mod.rs b/crates/nargo/src/cli/mod.rs index 8e5028bac5b..4a6cc5147f3 100644 --- a/crates/nargo/src/cli/mod.rs +++ b/crates/nargo/src/cli/mod.rs @@ -82,6 +82,7 @@ pub fn start_cli() { App::new("prove") .about("Create proof for this program") .arg(Arg::with_name("proof_name").help("The name of the proof")) + .arg(Arg::with_name("checked").help("Verify proof after proving")) .arg(show_ssa.clone()) .arg(allow_warnings.clone()), ) @@ -212,21 +213,20 @@ fn write_inputs_to_file>( // helper function which tests noir programs by trying to generate a proof and verify it pub fn prove_and_verify(proof_name: &str, prg_dir: &Path, show_ssa: bool) -> bool { let tmp_dir = TempDir::new("p_and_v_tests").unwrap(); - let proof_path = match prove_cmd::prove_with_path( + match prove_cmd::prove_with_path( Some(proof_name), prg_dir, &tmp_dir.into_path(), + true, show_ssa, false, ) { - Ok(p) => p, + Ok(_) => true, Err(error) => { println!("{error}"); - return false; + false } - }; - - verify_cmd::verify_with_path(prg_dir, &proof_path.unwrap(), show_ssa, false).unwrap() + } } fn add_std_lib(driver: &mut Driver) { diff --git a/crates/nargo/src/cli/prove_cmd.rs b/crates/nargo/src/cli/prove_cmd.rs index 15e855cb7b6..987721771dc 100644 --- a/crates/nargo/src/cli/prove_cmd.rs +++ b/crates/nargo/src/cli/prove_cmd.rs @@ -4,30 +4,40 @@ use acvm::ProofSystemCompiler; use clap::ArgMatches; use noirc_abi::input_parser::Format; -use super::execute_cmd::{execute_program, extract_public_inputs}; -use super::{create_named_dir, write_inputs_to_file, write_to_file}; -use crate::cli::dedup_public_input_indices; +use super::{create_named_dir, read_inputs_from_file, write_inputs_to_file, write_to_file}; + +use crate::cli::{ + dedup_public_input_indices, + execute_cmd::{execute_program, extract_public_inputs}, + verify_cmd::verify_proof, +}; use crate::{ - constants::{PROOFS_DIR, PROOF_EXT, VERIFIER_INPUT_FILE}, + constants::{PROOFS_DIR, PROOF_EXT, PROVER_INPUT_FILE, VERIFIER_INPUT_FILE}, errors::CliError, }; pub(crate) fn run(args: ArgMatches) -> Result<(), CliError> { let args = args.subcommand_matches("prove").unwrap(); let proof_name = args.value_of("proof_name"); + let check_proof = args.is_present("checked"); let show_ssa = args.is_present("show-ssa"); let allow_warnings = args.is_present("allow-warnings"); - prove(proof_name, show_ssa, allow_warnings) + prove(proof_name, check_proof, show_ssa, allow_warnings) } -fn prove(proof_name: Option<&str>, show_ssa: bool, allow_warnings: bool) -> Result<(), CliError> { +fn prove( + proof_name: Option<&str>, + check_proof: bool, + show_ssa: bool, + allow_warnings: bool, +) -> Result<(), CliError> { let current_dir = std::env::current_dir().unwrap(); let mut proof_dir = PathBuf::new(); proof_dir.push(PROOFS_DIR); - prove_with_path(proof_name, current_dir, proof_dir, show_ssa, allow_warnings)?; + prove_with_path(proof_name, current_dir, proof_dir, check_proof, show_ssa, allow_warnings)?; Ok(()) } @@ -36,12 +46,22 @@ pub fn prove_with_path>( proof_name: Option<&str>, program_dir: P, proof_dir: P, + check_proof: bool, show_ssa: bool, allow_warnings: bool, ) -> Result, CliError> { - let mut compiled_program = + let compiled_program = super::compile_cmd::compile_circuit(program_dir.as_ref(), show_ssa, allow_warnings)?; - let (_, solved_witness) = execute_program(&program_dir, &compiled_program)?; + + // Parse the initial witness values from Prover.toml + let inputs_map = read_inputs_from_file( + &program_dir, + PROVER_INPUT_FILE, + Format::Toml, + compiled_program.abi.as_ref().unwrap().clone(), + )?; + + let (_, solved_witness) = execute_program(&compiled_program, &inputs_map)?; // Write public inputs into Verifier.toml let public_inputs = extract_public_inputs(&compiled_program, &solved_witness)?; @@ -50,26 +70,38 @@ pub fn prove_with_path>( // Since the public outputs are added onto the public inputs list, there can be duplicates. // We keep the duplicates for when one is encoding the return values into the Verifier.toml, // however we must remove these duplicates when creating a proof. - compiled_program.circuit.public_inputs = - dedup_public_input_indices(compiled_program.circuit.public_inputs); + let proof = { + let mut prover_circuit = compiled_program.circuit.clone(); + prover_circuit.public_inputs = dedup_public_input_indices(prover_circuit.public_inputs); - let backend = crate::backends::ConcreteBackend; - let proof = backend.prove_with_meta(compiled_program.circuit, solved_witness); + let backend = crate::backends::ConcreteBackend; + backend.prove_with_meta(prover_circuit, solved_witness) + }; println!("Proof successfully created"); - if let Some(proof_name) = proof_name { - let proof_path = save_proof_to_dir(proof, proof_name, proof_dir)?; + if check_proof { + let result = verify_proof(compiled_program, public_inputs, &proof)?; + println!("Proof verified : {result}"); + if !result { + return Err(CliError::Generic("Could not verify generated proof".to_owned())); + } + } + + let proof_path = if let Some(proof_name) = proof_name { + let proof_path = save_proof_to_dir(&proof, proof_name, proof_dir)?; println!("Proof saved to {}", proof_path.display()); - Ok(Some(proof_path)) + Some(proof_path) } else { println!("{}", hex::encode(&proof)); - Ok(None) - } + None + }; + + Ok(proof_path) } fn save_proof_to_dir>( - proof: Vec, + proof: &[u8], proof_name: &str, proof_dir: P, ) -> Result { diff --git a/crates/nargo/src/cli/verify_cmd.rs b/crates/nargo/src/cli/verify_cmd.rs index 0ba85a089b1..962f9a09ea6 100644 --- a/crates/nargo/src/cli/verify_cmd.rs +++ b/crates/nargo/src/cli/verify_cmd.rs @@ -31,7 +31,7 @@ pub(crate) fn run(args: ArgMatches) -> Result<(), CliError> { fn verify(proof_name: &str, allow_warnings: bool) -> Result { let current_dir = std::env::current_dir().unwrap(); - let mut proof_path = PathBuf::new(); //or cur_dir? + let mut proof_path = PathBuf::new(); // or current_dir? proof_path.push(PROOFS_DIR); proof_path.push(Path::new(proof_name)); proof_path.set_extension(PROOF_EXT); @@ -56,15 +56,15 @@ pub fn verify_with_path>( read_inputs_from_file(current_dir, VERIFIER_INPUT_FILE, Format::Toml, public_abi)?; } - let valid_proof = verify_proof(compiled_program, public_inputs_map, load_proof(proof_path)?)?; + let valid_proof = verify_proof(compiled_program, public_inputs_map, &load_proof(proof_path)?)?; Ok(valid_proof) } -fn verify_proof( +pub(crate) fn verify_proof( mut compiled_program: CompiledProgram, public_inputs_map: InputMap, - proof: Vec, + proof: &[u8], ) -> Result { let public_abi = compiled_program.abi.unwrap().public_abi(); let public_inputs = @@ -82,7 +82,7 @@ fn verify_proof( compiled_program.circuit.public_inputs = dedup_public_indices; let backend = crate::backends::ConcreteBackend; - let valid_proof = backend.verify_from_cs(&proof, dedup_public_values, compiled_program.circuit); + let valid_proof = backend.verify_from_cs(proof, dedup_public_values, compiled_program.circuit); Ok(valid_proof) } diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index 19814f27c28..737d496918d 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -17,7 +17,7 @@ pub struct Driver { context: Context, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct CompiledProgram { pub circuit: Circuit, pub abi: Option, From 3e5a24897e236328b52e17f7af4a8df9076996f8 Mon Sep 17 00:00:00 2001 From: Tom French Date: Mon, 6 Feb 2023 12:15:30 +0000 Subject: [PATCH 2/6] chore: rename variable --- crates/nargo/src/cli/prove_cmd.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/nargo/src/cli/prove_cmd.rs b/crates/nargo/src/cli/prove_cmd.rs index 987721771dc..a78d390356b 100644 --- a/crates/nargo/src/cli/prove_cmd.rs +++ b/crates/nargo/src/cli/prove_cmd.rs @@ -80,9 +80,9 @@ pub fn prove_with_path>( println!("Proof successfully created"); if check_proof { - let result = verify_proof(compiled_program, public_inputs, &proof)?; - println!("Proof verified : {result}"); - if !result { + let valid_proof = verify_proof(compiled_program, public_inputs, &proof)?; + println!("Proof verified : {valid_proof}"); + if !valid_proof { return Err(CliError::Generic("Could not verify generated proof".to_owned())); } } From d2c70b290891a6bfa73261319c915c4043a15cd8 Mon Sep 17 00:00:00 2001 From: Tom French Date: Mon, 6 Feb 2023 12:20:07 +0000 Subject: [PATCH 3/6] chore(nargo): cleanup imports --- crates/nargo/src/cli/compile_cmd.rs | 12 ++++-------- crates/nargo/src/cli/execute_cmd.rs | 8 +++----- crates/nargo/src/cli/prove_cmd.rs | 13 +++++++------ 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/crates/nargo/src/cli/compile_cmd.rs b/crates/nargo/src/cli/compile_cmd.rs index acab73b4eb6..5f335e4ac8a 100644 --- a/crates/nargo/src/cli/compile_cmd.rs +++ b/crates/nargo/src/cli/compile_cmd.rs @@ -1,21 +1,17 @@ -use std::path::PathBuf; +use clap::ArgMatches; +use std::path::{Path, PathBuf}; use acvm::ProofSystemCompiler; - -use clap::ArgMatches; use noirc_abi::input_parser::Format; -use std::path::Path; - +use super::{add_std_lib, create_named_dir, read_inputs_from_file, write_to_file}; use crate::{ - cli::{execute_cmd::save_witness_to_dir, read_inputs_from_file}, + cli::execute_cmd::save_witness_to_dir, constants::{ACIR_EXT, PROVER_INPUT_FILE, TARGET_DIR}, errors::CliError, resolver::Resolver, }; -use super::{add_std_lib, create_named_dir, write_to_file}; - pub(crate) fn run(args: ArgMatches) -> Result<(), CliError> { let args = args.subcommand_matches("compile").unwrap(); let circuit_name = args.value_of("circuit_name").unwrap(); diff --git a/crates/nargo/src/cli/execute_cmd.rs b/crates/nargo/src/cli/execute_cmd.rs index 564b47857b6..ba444b57bb2 100644 --- a/crates/nargo/src/cli/execute_cmd.rs +++ b/crates/nargo/src/cli/execute_cmd.rs @@ -1,16 +1,14 @@ +use clap::ArgMatches; use std::path::{Path, PathBuf}; use acvm::acir::native_types::Witness; -use acvm::FieldElement; -use acvm::PartialWitnessGenerator; -use clap::ArgMatches; +use acvm::{FieldElement, PartialWitnessGenerator}; use noirc_abi::errors::AbiError; use noirc_abi::input_parser::{Format, InputValue}; use noirc_abi::{Abi, MAIN_RETURN_NAME}; use noirc_driver::CompiledProgram; -use super::{create_named_dir, read_inputs_from_file, write_to_file}; -use super::{InputMap, WitnessMap}; +use super::{create_named_dir, read_inputs_from_file, write_to_file, InputMap, WitnessMap}; use crate::{ constants::{PROVER_INPUT_FILE, TARGET_DIR, WITNESS_EXT}, errors::CliError, diff --git a/crates/nargo/src/cli/prove_cmd.rs b/crates/nargo/src/cli/prove_cmd.rs index a78d390356b..f3285d5217e 100644 --- a/crates/nargo/src/cli/prove_cmd.rs +++ b/crates/nargo/src/cli/prove_cmd.rs @@ -4,14 +4,15 @@ use acvm::ProofSystemCompiler; use clap::ArgMatches; use noirc_abi::input_parser::Format; -use super::{create_named_dir, read_inputs_from_file, write_inputs_to_file, write_to_file}; - -use crate::cli::{ - dedup_public_input_indices, - execute_cmd::{execute_program, extract_public_inputs}, - verify_cmd::verify_proof, +use super::{ + create_named_dir, dedup_public_input_indices, read_inputs_from_file, write_inputs_to_file, + write_to_file, }; use crate::{ + cli::{ + execute_cmd::{execute_program, extract_public_inputs}, + verify_cmd::verify_proof, + }, constants::{PROOFS_DIR, PROOF_EXT, PROVER_INPUT_FILE, VERIFIER_INPUT_FILE}, errors::CliError, }; From 7c1cb4a593edc37bd9b54b79ed55385be90ff6a1 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Thu, 9 Feb 2023 11:30:56 +0000 Subject: [PATCH 4/6] chore: rename `checked` arg to `verify` --- crates/nargo/src/cli/mod.rs | 2 +- crates/nargo/src/cli/prove_cmd.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/nargo/src/cli/mod.rs b/crates/nargo/src/cli/mod.rs index 4a6cc5147f3..fc68615c88a 100644 --- a/crates/nargo/src/cli/mod.rs +++ b/crates/nargo/src/cli/mod.rs @@ -82,7 +82,7 @@ pub fn start_cli() { App::new("prove") .about("Create proof for this program") .arg(Arg::with_name("proof_name").help("The name of the proof")) - .arg(Arg::with_name("checked").help("Verify proof after proving")) + .arg(Arg::with_name("verify").help("Verify proof after proving")) .arg(show_ssa.clone()) .arg(allow_warnings.clone()), ) diff --git a/crates/nargo/src/cli/prove_cmd.rs b/crates/nargo/src/cli/prove_cmd.rs index f3285d5217e..d6e3f0db477 100644 --- a/crates/nargo/src/cli/prove_cmd.rs +++ b/crates/nargo/src/cli/prove_cmd.rs @@ -20,7 +20,7 @@ use crate::{ pub(crate) fn run(args: ArgMatches) -> Result<(), CliError> { let args = args.subcommand_matches("prove").unwrap(); let proof_name = args.value_of("proof_name"); - let check_proof = args.is_present("checked"); + let check_proof = args.is_present("verify"); let show_ssa = args.is_present("show-ssa"); let allow_warnings = args.is_present("allow-warnings"); From f4d6eaef69b87992e0e4c0ea31562aaccfe283b7 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Thu, 9 Feb 2023 11:32:11 +0000 Subject: [PATCH 5/6] chore: make verify arg named rather than positional --- crates/nargo/src/cli/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/nargo/src/cli/mod.rs b/crates/nargo/src/cli/mod.rs index fc68615c88a..8753fa6241e 100644 --- a/crates/nargo/src/cli/mod.rs +++ b/crates/nargo/src/cli/mod.rs @@ -82,7 +82,7 @@ pub fn start_cli() { App::new("prove") .about("Create proof for this program") .arg(Arg::with_name("proof_name").help("The name of the proof")) - .arg(Arg::with_name("verify").help("Verify proof after proving")) + .arg(Arg::with_name("verify").long("verify").help("Verify proof after proving")) .arg(show_ssa.clone()) .arg(allow_warnings.clone()), ) From 023fe9b0ea423b79066b2816d249c036463ca0ae Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Thu, 9 Feb 2023 11:33:18 +0000 Subject: [PATCH 6/6] chore: remove scope around `prover_circuit` --- crates/nargo/src/cli/prove_cmd.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/nargo/src/cli/prove_cmd.rs b/crates/nargo/src/cli/prove_cmd.rs index d6e3f0db477..eb4fc5e5b22 100644 --- a/crates/nargo/src/cli/prove_cmd.rs +++ b/crates/nargo/src/cli/prove_cmd.rs @@ -71,13 +71,11 @@ pub fn prove_with_path>( // Since the public outputs are added onto the public inputs list, there can be duplicates. // We keep the duplicates for when one is encoding the return values into the Verifier.toml, // however we must remove these duplicates when creating a proof. - let proof = { - let mut prover_circuit = compiled_program.circuit.clone(); - prover_circuit.public_inputs = dedup_public_input_indices(prover_circuit.public_inputs); + let mut prover_circuit = compiled_program.circuit.clone(); + prover_circuit.public_inputs = dedup_public_input_indices(prover_circuit.public_inputs); - let backend = crate::backends::ConcreteBackend; - backend.prove_with_meta(prover_circuit, solved_witness) - }; + let backend = crate::backends::ConcreteBackend; + let proof = backend.prove_with_meta(prover_circuit, solved_witness); println!("Proof successfully created"); if check_proof {