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): Update nargo to use preprocessing interface #765

Merged
merged 27 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
98379a6
initial preprocess cmd to test backend changes
vezenovm Feb 2, 2023
ec07827
merge conflicts
vezenovm Feb 6, 2023
61b0fcb
cargo lock merge conflicts
vezenovm Feb 6, 2023
bb26ce7
initial work using preprocess for nargo proving and verification, sti…
vezenovm Feb 7, 2023
24eff9f
use fixed up aztec_backend for preprocess
vezenovm Feb 9, 2023
37949b2
moving preprocess into compile command
vezenovm Feb 9, 2023
dcee05c
use nargo compile to preprocess no more preprocess cmd
vezenovm Feb 9, 2023
c14b00e
remove preprocess cmd file
vezenovm Feb 9, 2023
5665ffc
remove TODO from nargo cargo.toml
vezenovm Feb 9, 2023
c3f1960
merge conflicts
vezenovm Feb 14, 2023
34e5e65
add checking of acir file in nargo prove
vezenovm Feb 14, 2023
16ee9ac
switch to using circuit_path for pk and vk paths, compare compiled ci…
vezenovm Feb 14, 2023
0e6a44c
add logic to look at checksum of acir rather than the file byte by bte
vezenovm Feb 14, 2023
babe68b
merge conflicts with combined prove and verify cmd
vezenovm Feb 14, 2023
5add0bd
remove debug
vezenovm Feb 15, 2023
e11e29b
cargo update
vezenovm Feb 15, 2023
29d11c4
remove unnecessary comments
vezenovm Feb 15, 2023
57158bb
switch backend reference to updated composer
vezenovm Feb 15, 2023
90b3294
when build artifacts are not provided to nargo prove, preprocess as a…
vezenovm Feb 16, 2023
a1864a5
move fetch_pk_and_vk into main nargo module, also use hash cs method …
vezenovm Feb 16, 2023
5d8db6b
move path specifications to separate method in nargo commands
vezenovm Feb 16, 2023
9ea4cec
comment in compile cmd
vezenovm Feb 16, 2023
3f76f1e
nit comments and cspell
vezenovm Feb 16, 2023
3c9e953
update aztec_backend commit rev
vezenovm Feb 16, 2023
189defd
merge conflicts
vezenovm Feb 16, 2023
eab26bf
merge conflicts
vezenovm Feb 16, 2023
f600459
cargo fmt after merge
vezenovm Feb 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@ pkg/
# Nargo output
*.proof
*.acir
*.acir.sha256
*.tr
*.pk
*.vk
**/Verifier.toml
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions crates/nargo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ termcolor = "1.1.2"
tempdir = "0.3.7"

# Backends
aztec_backend = { optional = true, package = "barretenberg_static_lib", git = "https://github.com/noir-lang/aztec_backend", rev = "d0e1257c22618f98f53781faba3c372ef91a0172" }
aztec_wasm_backend = { optional = true, package = "barretenberg_wasm", git = "https://github.com/noir-lang/aztec_backend", rev = "d0e1257c22618f98f53781faba3c372ef91a0172" }
aztec_backend = { optional = true, package = "barretenberg_static_lib", git = "https://github.com/noir-lang/aztec_backend", rev = "cff757dca7971161e4bd25e7a744d910c37c22be" }
aztec_wasm_backend = { optional = true, package = "barretenberg_wasm", git = "https://github.com/noir-lang/aztec_backend", rev = "cff757dca7971161e4bd25e7a744d910c37c22be" }
marlin_arkworks_backend = { optional = true, git = "https://github.com/noir-lang/marlin_arkworks_backend", rev = "144378edad821bfaa52bf2cacca8ecc87514a4fc" }
color-eyre = "0.6.2"

Expand Down
75 changes: 64 additions & 11 deletions crates/nargo/src/cli/compile_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use clap::ArgMatches;
use std::path::{Path, PathBuf};

use acvm::ProofSystemCompiler;
use acvm::{acir::circuit::Circuit, hash_constraint_system};
use clap::ArgMatches;
use noirc_abi::input_parser::Format;
use std::path::{Path, PathBuf};

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, PROVER_INPUT_FILE, TARGET_DIR},
constants::{ACIR_EXT, PK_EXT, PROVER_INPUT_FILE, TARGET_DIR, VK_EXT},
errors::CliError,
resolver::Resolver,
};
Expand All @@ -33,7 +33,6 @@ pub(crate) fn run(args: ArgMatches) -> Result<(), CliError> {
.map(|_| ())
}

#[allow(deprecated)]
pub fn generate_circuit_and_witness_to_disk<P: AsRef<Path>>(
circuit_name: &str,
program_dir: P,
Expand All @@ -42,13 +41,12 @@ pub fn generate_circuit_and_witness_to_disk<P: AsRef<Path>>(
allow_warnings: bool,
) -> Result<PathBuf, CliError> {
let compiled_program = compile_circuit(program_dir.as_ref(), false, allow_warnings)?;
let serialized = compiled_program.circuit.to_bytes();

let mut circuit_path = create_named_dir(circuit_dir.as_ref(), "build");
circuit_path.push(circuit_name);
circuit_path.set_extension(ACIR_EXT);
let path = write_to_file(serialized.as_slice(), &circuit_path);
println!("Generated ACIR code into {path}");
preprocess_with_path(circuit_name, circuit_dir.as_ref(), compiled_program.circuit.clone())?;

let mut circuit_path =
save_acir_to_dir(compiled_program.circuit.clone(), circuit_name, circuit_dir.as_ref());
println!("Generated ACIR code into {}", circuit_path.display());

if generate_witness {
// Parse the initial witness values from Prover.toml
Expand Down Expand Up @@ -82,3 +80,58 @@ pub fn compile_circuit<P: AsRef<Path>>(
.into_compiled_program(backend.np_language(), show_ssa, allow_warnings)
.map_err(|_| std::process::exit(1))
}

pub fn preprocess_with_path<P: AsRef<Path>>(
key_name: &str,
preprocess_dir: P,
circuit: Circuit,
) -> Result<(PathBuf, PathBuf), CliError> {
let backend = crate::backends::ConcreteBackend;

let (proving_key, verification_key) = backend.preprocess(circuit);

let pk_path = save_key_to_dir(proving_key, key_name, &preprocess_dir, true)?;
println!("Proving key saved to {}", pk_path.display());
let vk_path = save_key_to_dir(verification_key, key_name, preprocess_dir, false)?;
println!("Verification key saved to {}", vk_path.display());

Ok((pk_path, vk_path))
}

fn save_acir_to_dir<P: AsRef<Path>>(
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);

// 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);

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);

circuit_path
}

fn save_key_to_dir<P: AsRef<Path>>(
key: Vec<u8>,
key_name: &str,
key_dir: P,
is_proving_key: bool,
) -> Result<PathBuf, CliError> {
let mut key_path = create_named_dir(key_dir.as_ref(), key_name);
key_path.push(key_name);
let extension = if is_proving_key { PK_EXT } else { VK_EXT };
key_path.set_extension(extension);

write_to_file(hex::encode(key).as_bytes(), &key_path);

Ok(key_path)
}
79 changes: 75 additions & 4 deletions crates/nargo/src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use acvm::{
acir::{circuit::PublicInputs, native_types::Witness},
FieldElement,
acir::{
circuit::{Circuit, PublicInputs},
native_types::Witness,
},
hash_constraint_system, FieldElement, ProofSystemCompiler,
};
pub use check_cmd::check_from_path;
use clap::{App, AppSettings, Arg};
Expand All @@ -20,7 +23,10 @@ use std::{
extern crate tempdir;
use tempdir::TempDir;

use crate::errors::CliError;
use crate::{
constants::{ACIR_EXT, PK_EXT, VK_EXT},
errors::CliError,
};

mod check_cmd;
mod compile_cmd;
Expand Down Expand Up @@ -79,6 +85,9 @@ pub fn start_cli() {
App::new("verify")
.about("Given a proof and a program, verify whether the proof is valid")
.arg(Arg::with_name("proof").help("The proof to verify").required(true))
.arg(Arg::with_name("circuit_name").help(
"The name of the circuit build files (ACIR, proving and verification keys)",
))
.arg(allow_warnings.clone()),
)
.subcommand(
Expand All @@ -87,6 +96,9 @@ pub fn start_cli() {
"Create proof for this program. The proof is returned as a hex encoded string.",
)
.arg(Arg::with_name("proof_name").help("The name of the proof"))
.arg(Arg::with_name("circuit_name").help(
"The name of the circuit build files (ACIR, proving and verification keys)",
))
.arg(Arg::with_name("verify").long("verify").help("Verify proof after proving"))
.arg(show_ssa.clone())
.arg(allow_warnings.clone()),
Expand Down Expand Up @@ -134,7 +146,7 @@ pub fn start_cli() {
.takes_value(true),
)
.arg(show_ssa)
.arg(allow_warnings),
.arg(allow_warnings.clone()),
)
.setting(AppSettings::SubcommandRequiredElseHelp)
.get_matches();
Expand Down Expand Up @@ -228,6 +240,7 @@ pub fn prove_and_verify(proof_name: &str, prg_dir: &Path, show_ssa: bool) -> boo
Some(proof_name),
prg_dir,
&tmp_dir.into_path(),
None,
true,
show_ssa,
false,
Expand Down Expand Up @@ -289,6 +302,64 @@ pub(crate) fn dedup_public_input_indices_values(
)
}

pub fn load_hex_data<P: AsRef<Path>>(path: P) -> Result<Vec<u8>, CliError> {
let hex_data: Vec<_> =
std::fs::read(&path).map_err(|_| CliError::PathNotValid(path.as_ref().to_path_buf()))?;

let raw_bytes = hex::decode(hex_data).map_err(CliError::HexArtifactNotValid)?;

Ok(raw_bytes)
}

fn fetch_pk_and_vk<P: AsRef<Path>>(
TomAFrench marked this conversation as resolved.
Show resolved Hide resolved
circuit: Circuit,
circuit_build_path: Option<P>,
prove_circuit: bool,
check_proof: bool,
) -> Result<(Vec<u8>, Vec<u8>), CliError> {
let backend = crate::backends::ConcreteBackend;
if let Some(circuit_build_path) = circuit_build_path {
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 expected_acir_hash = load_hex_data(acir_hash_path.clone())?;

let new_acir_hash = hash_constraint_system(&circuit);

if new_acir_hash[..] != expected_acir_hash {
return Err(CliError::MismatchedAcir(acir_hash_path));
}

// This flag exists to avoid an unnecessary read of the proving key during verification
// as this method is used by both `nargo prove` and `nargo verify`
let proving_key = if prove_circuit {
let mut proving_key_path = PathBuf::new();
proving_key_path.push(circuit_build_path.as_ref());
proving_key_path.set_extension(PK_EXT);
load_hex_data(proving_key_path)?
} else {
// We can return an empty Vec here as `prove_circuit` should only be false when running `nargo verify`
vec![]
};

let verification_key = if check_proof {
let mut verification_key_path = PathBuf::new();
verification_key_path.push(circuit_build_path);
verification_key_path.set_extension(VK_EXT);
load_hex_data(verification_key_path)?
} else {
// We can return an empty Vec here as the verification key is used only is `check_proof` is true
vec![]
};

Ok((proving_key, verification_key))
} else {
// If a path to the circuit's build dir has not been provided, run preprocess and generate the proving and verification keys
let (proving_key, verification_key) = backend.preprocess(circuit);
Ok((proving_key, verification_key))
}
}

// FIXME: I not sure that this is the right place for this tests.
#[cfg(test)]
mod tests {
Expand Down
37 changes: 31 additions & 6 deletions crates/nargo/src/cli/prove_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@ use clap::ArgMatches;
use noirc_abi::input_parser::Format;

use super::{
create_named_dir, dedup_public_input_indices, read_inputs_from_file, write_inputs_to_file,
write_to_file,
create_named_dir, dedup_public_input_indices, fetch_pk_and_vk, 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},
constants::{PROOFS_DIR, PROOF_EXT, PROVER_INPUT_FILE, TARGET_DIR, 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 circuit_name = args.value_of("circuit_name");
let check_proof = args.is_present("verify");
let show_ssa = args.is_present("show-ssa");
let allow_warnings = args.is_present("allow-warnings");
Expand All @@ -30,7 +31,24 @@ pub(crate) fn run(args: ArgMatches) -> Result<(), CliError> {
let mut proof_dir = program_dir.clone();
proof_dir.push(PROOFS_DIR);

prove_with_path(proof_name, program_dir, proof_dir, check_proof, show_ssa, allow_warnings)?;
let circuit_build_path = if let Some(circuit_name) = circuit_name {
let mut circuit_build_path = program_dir.clone();
circuit_build_path.push(TARGET_DIR);
circuit_build_path.push(circuit_name);
Some(circuit_build_path)
} else {
None
};

prove_with_path(
proof_name,
program_dir,
proof_dir,
circuit_build_path,
check_proof,
show_ssa,
allow_warnings,
)?;

Ok(())
}
Expand All @@ -39,12 +57,19 @@ pub fn prove_with_path<P: AsRef<Path>>(
proof_name: Option<&str>,
program_dir: P,
proof_dir: P,
circuit_build_path: Option<P>,
check_proof: bool,
show_ssa: bool,
allow_warnings: bool,
) -> Result<Option<PathBuf>, CliError> {
let compiled_program =
super::compile_cmd::compile_circuit(program_dir.as_ref(), show_ssa, allow_warnings)?;
let (proving_key, verification_key) = fetch_pk_and_vk(
compiled_program.circuit.clone(),
circuit_build_path.as_ref(),
true,
check_proof,
)?;

// Parse the initial witness values from Prover.toml
let inputs_map = read_inputs_from_file(
Expand All @@ -67,11 +92,11 @@ pub fn prove_with_path<P: AsRef<Path>>(
prover_circuit.public_inputs = dedup_public_input_indices(prover_circuit.public_inputs);

let backend = crate::backends::ConcreteBackend;
let proof = backend.prove_with_meta(prover_circuit, solved_witness);
let proof = backend.prove_with_pk(prover_circuit, solved_witness, proving_key);

println!("Proof successfully created");
if check_proof {
let valid_proof = verify_proof(compiled_program, public_inputs, &proof)?;
let valid_proof = verify_proof(compiled_program, public_inputs, &proof, verification_key)?;
println!("Proof verified : {valid_proof}");
if !valid_proof {
return Err(CliError::Generic("Could not verify generated proof".to_owned()));
Expand Down
Loading