Skip to content

Commit

Permalink
Merge branch 'phated/acvm-0.12.0' into mv/opcode_supported
Browse files Browse the repository at this point in the history
* phated/acvm-0.12.0:
  fix compilation issue
  switch to published acvm and backend
  feat(nargo): Consume CommonReferenceString functions & manage caching (#1348)
  fix(stdlib): Workaround for Field comparison error in EdDSA signature verification (#1372)
  feat!: remove concept of noir fallbacks for foreign functions (#1371)
  feat(ssa refactor): mem2reg opt pass (#1363)
  feat(stdlib): EdDSA sig verification (#1313)
  • Loading branch information
TomAFrench committed May 23, 2023
2 parents 458ed98 + 6a2330c commit 4aba46e
Show file tree
Hide file tree
Showing 34 changed files with 667 additions and 151 deletions.
15 changes: 13 additions & 2 deletions Cargo.lock

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

3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,3 @@ toml = "0.7.2"
url = "2.2.0"
wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] }
wasm-bindgen-test = "0.3.33"

[patch.crates-io]
acvm-backend-barretenberg = { git = "https://github.com/noir-lang/acvm-backend-barretenberg", rev = "4358d3b9e8cd98d88a78dda3337e80e90668378e" }
2 changes: 1 addition & 1 deletion crates/nargo_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ color-eyre = "0.6.2"
tokio = "1.0"

# Backends
acvm-backend-barretenberg = { version = "0.1.2", default-features = false }
acvm-backend-barretenberg = { version = "0.2.0", default-features = false }

[dev-dependencies]
tempdir = "0.3.7"
Expand Down
26 changes: 20 additions & 6 deletions crates/nargo_cli/src/cli/codegen_verifier_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use super::fs::{
common_reference_string::get_common_reference_string, create_named_dir,
program::read_program_from_file, write_to_file,
common_reference_string::{
read_cached_common_reference_string, update_common_reference_string,
write_cached_common_reference_string,
},
create_named_dir,
program::read_program_from_file,
write_to_file,
};
use super::NargoConfig;
use crate::{
Expand Down Expand Up @@ -32,18 +37,25 @@ pub(crate) fn run<B: Backend>(
.circuit_name
.map(|circuit_name| config.program_dir.join(TARGET_DIR).join(circuit_name));

let common_reference_string = read_cached_common_reference_string();

let (common_reference_string, preprocessed_program) = match circuit_build_path {
Some(circuit_build_path) => {
let program = read_program_from_file(circuit_build_path)?;
let common_reference_string = get_common_reference_string(backend, &program.bytecode)
.map_err(CliError::CommonReferenceStringError)?;
let common_reference_string = update_common_reference_string(
backend,
&common_reference_string,
&program.bytecode,
)
.map_err(CliError::CommonReferenceStringError)?;
(common_reference_string, program)
}
None => {
let program =
compile_circuit(backend, config.program_dir.as_ref(), &args.compile_options)?;
let common_reference_string = get_common_reference_string(backend, &program.circuit)
.map_err(CliError::CommonReferenceStringError)?;
let common_reference_string =
update_common_reference_string(backend, &common_reference_string, &program.circuit)
.map_err(CliError::CommonReferenceStringError)?;
let program = preprocess_program(backend, &common_reference_string, program)
.map_err(CliError::ProofSystemCompilerError)?;
(common_reference_string, program)
Expand All @@ -54,6 +66,8 @@ pub(crate) fn run<B: Backend>(
codegen_verifier(backend, &common_reference_string, &preprocessed_program.verification_key)
.map_err(CliError::SmartContractError)?;

write_cached_common_reference_string(&common_reference_string);

let contract_dir = config.program_dir.join(CONTRACT_DIR);
create_named_dir(&contract_dir, "contract");
let contract_path = contract_dir.join("plonk_vk").with_extension("sol");
Expand Down
27 changes: 21 additions & 6 deletions crates/nargo_cli/src/cli/compile_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ use crate::resolver::DependencyResolutionError;
use crate::{constants::TARGET_DIR, errors::CliError, resolver::Resolver};

use super::fs::{
common_reference_string::get_common_reference_string,
common_reference_string::{
read_cached_common_reference_string, update_common_reference_string,
write_cached_common_reference_string,
},
program::{save_contract_to_file, save_program_to_file},
};
use super::NargoConfig;
Expand Down Expand Up @@ -41,22 +44,29 @@ pub(crate) fn run<B: Backend>(
) -> Result<(), CliError<B>> {
let circuit_dir = config.program_dir.join(TARGET_DIR);

let mut common_reference_string = read_cached_common_reference_string();

// If contracts is set we're compiling every function in a 'contract' rather than just 'main'.
if args.contracts {
let mut driver = setup_driver(backend, &config.program_dir)?;
let compiled_contracts = driver
.compile_contracts(&args.compile_options)
.map_err(|_| CliError::CompilationError)?;

// TODO: I wonder if it is incorrect for nargo-core to know anything about contracts.
// As can be seen here, It seems like a leaky abstraction where ContractFunctions (essentially CompiledPrograms)
// are compiled via nargo-core and then the PreprocessedContract is constructed here.
// This is due to EACH function needing it's own CRS, PKey, and VKey from the backend.
let preprocessed_contracts: Result<Vec<PreprocessedContract>, CliError<B>> =
try_vecmap(compiled_contracts, |contract| {
let preprocessed_contract_functions = try_vecmap(contract.functions, |func| {
let common_reference_string =
get_common_reference_string(backend, &func.bytecode)
.map_err(CliError::CommonReferenceStringError)?;
common_reference_string = update_common_reference_string(
backend,
&common_reference_string,
&func.bytecode,
)
.map_err(CliError::CommonReferenceStringError)?;

preprocess_contract_function(backend, &common_reference_string, func)
.map_err(CliError::ProofSystemCompilerError)
})?;
Expand All @@ -76,12 +86,17 @@ pub(crate) fn run<B: Backend>(
}
} else {
let program = compile_circuit(backend, &config.program_dir, &args.compile_options)?;
let common_reference_string = get_common_reference_string(backend, &program.circuit)
.map_err(CliError::CommonReferenceStringError)?;
common_reference_string =
update_common_reference_string(backend, &common_reference_string, &program.circuit)
.map_err(CliError::CommonReferenceStringError)?;

let preprocessed_program = preprocess_program(backend, &common_reference_string, program)
.map_err(CliError::ProofSystemCompilerError)?;
save_program_to_file(&preprocessed_program, &args.circuit_name, circuit_dir);
}

write_cached_common_reference_string(&common_reference_string);

Ok(())
}

Expand Down
37 changes: 25 additions & 12 deletions crates/nargo_cli/src/cli/fs/common_reference_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,47 @@ const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg";
const TRANSCRIPT_NAME: &str = "common-reference-string.bin";

fn common_reference_string_location() -> PathBuf {
let cache_dir = match env::var("BACKEND_CACHE_DIR") {
let cache_dir = match env::var("NARGO_BACKEND_CACHE_DIR") {
Ok(cache_dir) => PathBuf::from(cache_dir),
Err(_) => dirs::home_dir().unwrap().join(".nargo").join("backends"),
};
cache_dir.join(BACKEND_IDENTIFIER).join(TRANSCRIPT_NAME)
}

pub(crate) fn get_common_reference_string<B: CommonReferenceString>(
pub(crate) fn read_cached_common_reference_string() -> Vec<u8> {
let crs_path = common_reference_string_location();

// TODO: Implement checksum
match std::fs::read(crs_path) {
Ok(common_reference_string) => common_reference_string,
Err(_) => vec![],
}
}

pub(crate) fn update_common_reference_string<B: CommonReferenceString>(
backend: &B,
common_reference_string: &[u8],
circuit: &Circuit,
) -> Result<Vec<u8>, B::Error> {
use tokio::runtime::Builder;

let crs_path = common_reference_string_location();

let runtime = Builder::new_current_thread().enable_all().build().unwrap();

// TODO: Implement retries
let crs = match std::fs::read(&crs_path) {
// If the read data is empty, we don't have a CRS and need to generate one
Ok(common_reference_string) if !common_reference_string.is_empty() => runtime
.block_on(backend.update_common_reference_string(common_reference_string, circuit))?,
Ok(_) | Err(_) => runtime.block_on(backend.generate_common_reference_string(circuit))?,
// If the read data is empty, we don't have a CRS and need to generate one
let fut = if common_reference_string.is_empty() {
backend.generate_common_reference_string(circuit)
} else {
backend.update_common_reference_string(common_reference_string.to_vec(), circuit)
};

create_named_dir(crs_path.parent().unwrap(), "crs");
runtime.block_on(fut)
}

write_to_file(crs.as_slice(), &crs_path);
pub(crate) fn write_cached_common_reference_string(common_reference_string: &[u8]) {
let crs_path = common_reference_string_location();

create_named_dir(crs_path.parent().unwrap(), "crs");

Ok(crs)
write_to_file(common_reference_string, &crs_path);
}
22 changes: 17 additions & 5 deletions crates/nargo_cli/src/cli/prove_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use super::NargoConfig;
use super::{
compile_cmd::compile_circuit,
fs::{
common_reference_string::get_common_reference_string,
common_reference_string::{
read_cached_common_reference_string, update_common_reference_string,
write_cached_common_reference_string,
},
inputs::{read_inputs_from_file, write_inputs_to_file},
program::read_program_from_file,
proof::save_proof_to_dir,
Expand Down Expand Up @@ -73,23 +76,32 @@ pub(crate) fn prove_with_path<B: Backend, P: AsRef<Path>>(
check_proof: bool,
compile_options: &CompileOptions,
) -> Result<Option<PathBuf>, CliError<B>> {
let common_reference_string = read_cached_common_reference_string();

let (common_reference_string, preprocessed_program) = match circuit_build_path {
Some(circuit_build_path) => {
let program = read_program_from_file(circuit_build_path)?;
let common_reference_string = get_common_reference_string(backend, &program.bytecode)
.map_err(CliError::CommonReferenceStringError)?;
let common_reference_string = update_common_reference_string(
backend,
&common_reference_string,
&program.bytecode,
)
.map_err(CliError::CommonReferenceStringError)?;
(common_reference_string, program)
}
None => {
let program = compile_circuit(backend, program_dir.as_ref(), compile_options)?;
let common_reference_string = get_common_reference_string(backend, &program.circuit)
.map_err(CliError::CommonReferenceStringError)?;
let common_reference_string =
update_common_reference_string(backend, &common_reference_string, &program.circuit)
.map_err(CliError::CommonReferenceStringError)?;
let program = preprocess_program(backend, &common_reference_string, program)
.map_err(CliError::ProofSystemCompilerError)?;
(common_reference_string, program)
}
};

write_cached_common_reference_string(&common_reference_string);

let PreprocessedProgram { abi, bytecode, proving_key, verification_key, .. } =
preprocessed_program;

Expand Down
26 changes: 20 additions & 6 deletions crates/nargo_cli/src/cli/verify_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
use super::compile_cmd::compile_circuit;
use super::fs::{
common_reference_string::get_common_reference_string, inputs::read_inputs_from_file,
load_hex_data, program::read_program_from_file,
common_reference_string::{
read_cached_common_reference_string, update_common_reference_string,
write_cached_common_reference_string,
},
inputs::read_inputs_from_file,
load_hex_data,
program::read_program_from_file,
};
use super::NargoConfig;
use crate::{
Expand Down Expand Up @@ -58,23 +63,32 @@ fn verify_with_path<B: Backend, P: AsRef<Path>>(
circuit_build_path: Option<P>,
compile_options: &CompileOptions,
) -> Result<(), CliError<B>> {
let common_reference_string = read_cached_common_reference_string();

let (common_reference_string, preprocessed_program) = match circuit_build_path {
Some(circuit_build_path) => {
let program = read_program_from_file(circuit_build_path)?;
let common_reference_string = get_common_reference_string(backend, &program.bytecode)
.map_err(CliError::CommonReferenceStringError)?;
let common_reference_string = update_common_reference_string(
backend,
&common_reference_string,
&program.bytecode,
)
.map_err(CliError::CommonReferenceStringError)?;
(common_reference_string, program)
}
None => {
let program = compile_circuit(backend, program_dir.as_ref(), compile_options)?;
let common_reference_string = get_common_reference_string(backend, &program.circuit)
.map_err(CliError::CommonReferenceStringError)?;
let common_reference_string =
update_common_reference_string(backend, &common_reference_string, &program.circuit)
.map_err(CliError::CommonReferenceStringError)?;
let program = preprocess_program(backend, &common_reference_string, program)
.map_err(CliError::ProofSystemCompilerError)?;
(common_reference_string, program)
}
};

write_cached_common_reference_string(&common_reference_string);

let PreprocessedProgram { abi, bytecode, verification_key, .. } = preprocessed_program;

// Load public inputs (if any) from `VERIFIER_INPUT_FILE`.
Expand Down
5 changes: 5 additions & 0 deletions crates/nargo_cli/tests/test_data/eddsa/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
authors = [""]
compiler_version = "0.3.2"

[dependencies]
3 changes: 3 additions & 0 deletions crates/nargo_cli/tests/test_data/eddsa/Prover.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
_priv_key_a = 123
_priv_key_b = 456
msg = 789
55 changes: 55 additions & 0 deletions crates/nargo_cli/tests/test_data/eddsa/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use dep::std::compat;
use dep::std::ec::consts::te::baby_jubjub;
use dep::std::hash;
use dep::std::eddsa::eddsa_poseidon_verify;
use dep::std;

fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) {
// Skip this test for non-bn254 backends
if compat::is_bn254() {
let bjj = baby_jubjub();

let pub_key_a = bjj.curve.mul(_priv_key_a, bjj.curve.gen);
// let pub_key_b = bjj.curve.mul(_priv_key_b, bjj.curve.gen);

// Manually computed as fields can't use modulo. Importantantly the commitment is within
// the subgroup order. Note that choice of hash is flexible for this step.
// let r_a = hash::pedersen([_priv_key_a, msg])[0] % bjj.suborder; // modulus computed manually
let r_a = 1414770703199880747815475415092878800081323795074043628810774576767372531818;
// let r_b = hash::pedersen([_priv_key_b, msg])[0] % bjj.suborder; // modulus computed manually
let r_b = 571799555715456644614141527517766533395606396271089506978608487688924659618;

let r8_a = bjj.curve.mul(r_a, bjj.base8);
let r8_b = bjj.curve.mul(r_b, bjj.base8);

// let h_a: [Field; 6] = hash::poseidon::bn254::hash_5([
// r8_a.x,
// r8_a.y,
// pub_key_a.x,
// pub_key_a.y,
// msg,
// ]);

// let h_b: [Field; 6] = hash::poseidon::bn254::hash_5([
// r8_b.x,
// r8_b.y,
// pub_key_b.x,
// pub_key_b.y,
// msg,
// ]);

// let s_a = (r_a + _priv_key_a * h_a) % bjj.suborder; // modulus computed manually
let s_a = 30333430637424319196043722294837632681219980330991241982145549329256671548;
// let s_b = (r_b + _priv_key_b * h_b) % bjj.suborder; // modulus computed manually
let s_b = 1646085314320208098241070054368798527940102577261034947654839408482102287019;

// User A verifies their signature over the message
assert(eddsa_poseidon_verify(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg));

// User B's signature over the message can't be used with user A's pub key
assert(!eddsa_poseidon_verify(pub_key_a.x, pub_key_a.y, s_b, r8_b.x, r8_b.y, msg));

// User A's signature over the message can't be used with another message
assert(!eddsa_poseidon_verify(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg + 1));
}
}
Loading

0 comments on commit 4aba46e

Please sign in to comment.