Skip to content

Commit

Permalink
feat(nargo): add flag to verify created proofs
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench committed Feb 4, 2023
1 parent 9d6be60 commit 21572d0
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 44 deletions.
15 changes: 12 additions & 3 deletions crates/nargo/src/cli/compile_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -54,8 +55,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
20 changes: 10 additions & 10 deletions crates/nargo/src/cli/execute_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,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"))
.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
70 changes: 51 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,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(())
}
Expand All @@ -36,12 +46,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 +70,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 = {
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<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

0 comments on commit 21572d0

Please sign in to comment.