Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(nargo): add flag to verify created proofs #737

Merged
merged 9 commits into from
Feb 14, 2023
23 changes: 14 additions & 9 deletions crates/nargo/src/cli/compile_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
use std::path::PathBuf;

use acvm::ProofSystemCompiler;

use clap::ArgMatches;
use std::path::{Path, PathBuf};

use std::path::Path;
use acvm::ProofSystemCompiler;
use noirc_abi::input_parser::Format;

use super::{add_std_lib, create_named_dir, read_inputs_from_file, write_to_file};
use crate::{
cli::execute_cmd::save_witness_to_dir,
constants::{ACIR_EXT, TARGET_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();
Expand Down Expand Up @@ -54,8 +51,16 @@ pub fn generate_circuit_and_witness_to_disk<P: AsRef<Path>>(
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)?;
Expand Down
28 changes: 13 additions & 15 deletions crates/nargo/src/cli/execute_cmd.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -51,23 +49,23 @@ fn execute(
let compiled_program =
super::compile_cmd::compile_circuit(&current_dir, show_ssa, allow_warnings)?;

execute_program(current_dir, &compiled_program)
}

pub(crate) fn execute_program<P: AsRef<Path>>(
inputs_dir: P,
compiled_program: &CompiledProgram,
) -> Result<(Option<InputValue>, 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<InputValue>, 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();
Expand Down
12 changes: 6 additions & 6 deletions crates/nargo/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
TomAFrench marked this conversation as resolved.
Show resolved Hide resolved
.arg(show_ssa.clone())
.arg(allow_warnings.clone()),
)
Expand Down Expand Up @@ -212,21 +213,20 @@ fn write_inputs_to_file<P: AsRef<Path>>(
// 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) {
Expand Down
71 changes: 52 additions & 19 deletions crates/nargo/src/cli/prove_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,41 @@ 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, dedup_public_input_indices, read_inputs_from_file, write_inputs_to_file,
write_to_file,
};
use crate::{
constants::{PROOFS_DIR, PROOF_EXT, VERIFIER_INPUT_FILE},
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,
};

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(())
}
Expand All @@ -36,12 +47,22 @@ pub fn prove_with_path<P: AsRef<Path>>(
proof_name: Option<&str>,
program_dir: P,
proof_dir: P,
check_proof: bool,
show_ssa: bool,
allow_warnings: bool,
) -> Result<Option<PathBuf>, 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)?;
Expand All @@ -50,26 +71,38 @@ pub fn prove_with_path<P: AsRef<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 = {
TomAFrench marked this conversation as resolved.
Show resolved Hide resolved
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 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()));
}
}

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<P: AsRef<Path>>(
proof: Vec<u8>,
proof: &[u8],
proof_name: &str,
proof_dir: P,
) -> Result<PathBuf, CliError> {
Expand Down
10 changes: 5 additions & 5 deletions crates/nargo/src/cli/verify_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub(crate) fn run(args: ArgMatches) -> Result<(), CliError> {

fn verify(proof_name: &str, allow_warnings: bool) -> Result<bool, CliError> {
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);
Expand All @@ -56,15 +56,15 @@ pub fn verify_with_path<P: AsRef<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<u8>,
proof: &[u8],
) -> Result<bool, CliError> {
let public_abi = compiled_program.abi.unwrap().public_abi();
let public_inputs =
Expand All @@ -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)
}
Expand Down
2 changes: 1 addition & 1 deletion crates/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<noirc_abi::Abi>,
Expand Down