Merge branch 'develop' of github.com:Zokrates/ZoKrates into u8-playground
This commit is contained in:
commit
959e7e5991
31 changed files with 1116 additions and 960 deletions
|
@ -3,6 +3,6 @@
|
|||
|
||||
dir=$1
|
||||
|
||||
for file in $dir/*.cpp $dir/*.hpp; do
|
||||
for file in $dir/*.cpp $dir/*.hpp $dir/*.tcc; do
|
||||
clang-format -i -style=WebKit -verbose $file
|
||||
done
|
|
@ -5,19 +5,27 @@
|
|||
// @date 2017
|
||||
|
||||
mod constants;
|
||||
mod helpers;
|
||||
|
||||
use constants::*;
|
||||
use helpers::*;
|
||||
|
||||
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
|
||||
use serde_json::{from_reader, to_writer_pretty, Value};
|
||||
use std::convert::TryFrom;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::{stdin, BufReader, BufWriter, Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::string::String;
|
||||
use zokrates_abi::Encode;
|
||||
use zokrates_core::compile::{check, compile, CompilationArtifacts, CompileError};
|
||||
use zokrates_core::compile::{check, compile, CompilationArtifacts, CompileConfig, CompileError};
|
||||
use zokrates_core::ir::{self, ProgEnum};
|
||||
use zokrates_core::proof_system::bellman::groth16::G16;
|
||||
#[cfg(feature = "libsnark")]
|
||||
use zokrates_core::proof_system::libsnark::gm17::GM17;
|
||||
#[cfg(feature = "libsnark")]
|
||||
use zokrates_core::proof_system::libsnark::pghr13::PGHR13;
|
||||
use zokrates_core::proof_system::*;
|
||||
use zokrates_core::typed_absy::abi::Abi;
|
||||
use zokrates_core::typed_absy::{types::Signature, Type};
|
||||
|
@ -62,12 +70,13 @@ fn cli_generate_proof<T: Field, P: ProofSystem<T>>(
|
|||
let proof = P::generate_proof(program, witness, pk);
|
||||
let mut proof_file = File::create(proof_path).unwrap();
|
||||
|
||||
proof_file
|
||||
.write(proof.as_ref())
|
||||
.map_err(|why| format!("Couldn't write to {}: {}", proof_path.display(), why))?;
|
||||
|
||||
let proof = serde_json::to_string_pretty(&proof).unwrap();
|
||||
println!("Proof:\n{}", format!("{}", proof));
|
||||
|
||||
proof_file
|
||||
.write(proof.as_bytes())
|
||||
.map_err(|why| format!("Couldn't write to {}: {}", proof_path.display(), why))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -80,14 +89,13 @@ fn cli_export_verifier<T: Field, P: ProofSystem<T>>(
|
|||
let input_path = Path::new(sub_matches.value_of("input").unwrap());
|
||||
let input_file = File::open(&input_path)
|
||||
.map_err(|why| format!("Couldn't open {}: {}", input_path.display(), why))?;
|
||||
let mut reader = BufReader::new(input_file);
|
||||
let reader = BufReader::new(input_file);
|
||||
|
||||
let mut vk = String::new();
|
||||
reader
|
||||
.read_to_string(&mut vk)
|
||||
.map_err(|why| format!("Couldn't read {}: {}", input_path.display(), why))?;
|
||||
let vk = serde_json::from_reader(reader)
|
||||
.map_err(|why| format!("Couldn't deserialize verifying key: {}", why))?;
|
||||
|
||||
let abi = SolidityAbi::from(sub_matches.value_of("solidity-abi").unwrap())?;
|
||||
|
||||
let verifier = P::export_solidity_verifier(vk, abi);
|
||||
|
||||
//write output file
|
||||
|
@ -100,6 +108,7 @@ fn cli_export_verifier<T: Field, P: ProofSystem<T>>(
|
|||
writer
|
||||
.write_all(&verifier.as_bytes())
|
||||
.map_err(|_| "Failed writing output to file.".to_string())?;
|
||||
|
||||
println!("Finished exporting verifier.");
|
||||
Ok(())
|
||||
}
|
||||
|
@ -126,7 +135,11 @@ fn cli_setup<T: Field, P: ProofSystem<T>>(
|
|||
let mut vk_file = File::create(vk_path)
|
||||
.map_err(|why| format!("couldn't create {}: {}", vk_path.display(), why))?;
|
||||
vk_file
|
||||
.write(keypair.vk.as_ref())
|
||||
.write(
|
||||
serde_json::to_string_pretty(&keypair.vk)
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.map_err(|why| format!("couldn't write to {}: {}", vk_path.display(), why))?;
|
||||
|
||||
// write proving key
|
||||
|
@ -261,6 +274,8 @@ fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
|
|||
|
||||
let hr_output_path = bin_output_path.to_path_buf().with_extension("ztf");
|
||||
|
||||
let is_release = sub_matches.occurrences_of("release") > 0;
|
||||
|
||||
let file = File::open(path.clone())
|
||||
.map_err(|why| format!("Couldn't open input file {}: {}", path.display(), why))?;
|
||||
|
||||
|
@ -269,21 +284,21 @@ fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
|
|||
reader.read_to_string(&mut source).unwrap();
|
||||
|
||||
let fmt_error = |e: &CompileError| {
|
||||
let file = e.file().canonicalize().unwrap();
|
||||
format!(
|
||||
"{}:{}",
|
||||
e.file()
|
||||
.canonicalize()
|
||||
.unwrap()
|
||||
.strip_prefix(std::env::current_dir().unwrap())
|
||||
.unwrap()
|
||||
file.strip_prefix(std::env::current_dir().unwrap())
|
||||
.unwrap_or(file.as_path())
|
||||
.display(),
|
||||
e.value()
|
||||
)
|
||||
};
|
||||
|
||||
let compilation_config = CompileConfig::default().with_is_release(is_release);
|
||||
|
||||
let resolver = FileSystemResolver::new();
|
||||
let artifacts: CompilationArtifacts<T> =
|
||||
compile(source, path, Some(&resolver)).map_err(|e| {
|
||||
compile(source, path, Some(&resolver), &compilation_config).map_err(|e| {
|
||||
format!(
|
||||
"Compilation failed:\n\n{}",
|
||||
e.0.iter()
|
||||
|
@ -356,13 +371,11 @@ fn cli_check<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
|
|||
reader.read_to_string(&mut source).unwrap();
|
||||
|
||||
let fmt_error = |e: &CompileError| {
|
||||
let file = e.file().canonicalize().unwrap();
|
||||
format!(
|
||||
"{}:{}",
|
||||
e.file()
|
||||
.canonicalize()
|
||||
.unwrap()
|
||||
.strip_prefix(std::env::current_dir().unwrap())
|
||||
.unwrap()
|
||||
file.strip_prefix(std::env::current_dir().unwrap())
|
||||
.unwrap_or(file.as_path())
|
||||
.display(),
|
||||
e.value()
|
||||
)
|
||||
|
@ -386,12 +399,20 @@ fn cli_check<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
|
|||
|
||||
fn cli_verify<T: Field, P: ProofSystem<T>>(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
let vk_path = Path::new(sub_matches.value_of("verification-key-path").unwrap());
|
||||
let vk = std::fs::read_to_string(vk_path)
|
||||
.map_err(|why| format!("Couldn't read {}: {}", vk_path.display(), why))?;
|
||||
let vk_file = File::open(&vk_path)
|
||||
.map_err(|why| format!("Couldn't open {}: {}", vk_path.display(), why))?;
|
||||
|
||||
let vk_reader = BufReader::new(vk_file);
|
||||
let vk = serde_json::from_reader(vk_reader)
|
||||
.map_err(|why| format!("Couldn't deserialize verification key: {}", why))?;
|
||||
|
||||
let proof_path = Path::new(sub_matches.value_of("proof-path").unwrap());
|
||||
let proof = std::fs::read_to_string(proof_path)
|
||||
.map_err(|why| format!("Couldn't read {}: {}", proof_path.display(), why))?;
|
||||
let proof_file = File::open(&proof_path)
|
||||
.map_err(|why| format!("Couldn't open {}: {}", proof_path.display(), why))?;
|
||||
|
||||
let proof_reader = BufReader::new(proof_file);
|
||||
let proof = serde_json::from_reader(proof_reader)
|
||||
.map_err(|why| format!("Couldn't deserialize proof: {}", why))?;
|
||||
|
||||
println!("Performing verification...");
|
||||
println!(
|
||||
|
@ -414,6 +435,7 @@ fn cli() -> Result<(), String> {
|
|||
const WITNESS_DEFAULT_PATH: &str = "witness";
|
||||
const JSON_PROOF_PATH: &str = "proof.json";
|
||||
let default_curve = env::var("ZOKRATES_CURVE").unwrap_or(constants::BN128.into());
|
||||
let default_backend = env::var("ZOKRATES_BACKEND").unwrap_or(constants::BELLMAN.into());
|
||||
let default_scheme = env::var("ZOKRATES_PROVING_SCHEME").unwrap_or(constants::G16.into());
|
||||
let default_solidity_abi = "v1";
|
||||
|
||||
|
@ -460,6 +482,10 @@ fn cli() -> Result<(), String> {
|
|||
.long("light")
|
||||
.help("Skip logs and human readable output")
|
||||
.required(false)
|
||||
).arg(Arg::with_name("release")
|
||||
.long("release")
|
||||
.help("Apply release optimisations to minimise constraint count. This increases compilation time.")
|
||||
.required(false)
|
||||
)
|
||||
)
|
||||
.subcommand(SubCommand::with_name("check")
|
||||
|
@ -507,11 +533,18 @@ fn cli() -> Result<(), String> {
|
|||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(VERIFICATION_KEY_DEFAULT_PATH)
|
||||
).arg(Arg::with_name("backend")
|
||||
.short("b")
|
||||
.long("backend")
|
||||
.help("Backend to use")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(BACKENDS)
|
||||
.default_value(&default_backend)
|
||||
).arg(Arg::with_name("proving-scheme")
|
||||
.short("s")
|
||||
.long("proving-scheme")
|
||||
.help("Proving scheme to use in the setup")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(SCHEMES)
|
||||
|
@ -548,6 +581,14 @@ fn cli() -> Result<(), String> {
|
|||
.required(false)
|
||||
.possible_values(CURVES)
|
||||
.default_value(&default_curve)
|
||||
).arg(Arg::with_name("backend")
|
||||
.short("b")
|
||||
.long("backend")
|
||||
.help("Backend to use")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(BACKENDS)
|
||||
.default_value(&default_backend)
|
||||
).arg(Arg::with_name("proving-scheme")
|
||||
.short("s")
|
||||
.long("proving-scheme")
|
||||
|
@ -649,6 +690,14 @@ fn cli() -> Result<(), String> {
|
|||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(FLATTENED_CODE_DEFAULT_PATH)
|
||||
).arg(Arg::with_name("backend")
|
||||
.short("b")
|
||||
.long("backend")
|
||||
.help("Backend to use")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(BACKENDS)
|
||||
.default_value(&default_backend)
|
||||
).arg(Arg::with_name("proving-scheme")
|
||||
.short("s")
|
||||
.long("proving-scheme")
|
||||
|
@ -698,6 +747,14 @@ fn cli() -> Result<(), String> {
|
|||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(VERIFICATION_KEY_DEFAULT_PATH)
|
||||
).arg(Arg::with_name("backend")
|
||||
.short("b")
|
||||
.long("backend")
|
||||
.help("Backend to use")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(BACKENDS)
|
||||
.default_value(&default_backend)
|
||||
).arg(Arg::with_name("proving-scheme")
|
||||
.short("s")
|
||||
.long("proving-scheme")
|
||||
|
@ -720,12 +777,10 @@ fn cli() -> Result<(), String> {
|
|||
|
||||
match matches.subcommand() {
|
||||
("compile", Some(sub_matches)) => {
|
||||
let curve = sub_matches.value_of("curve").unwrap();
|
||||
|
||||
let curve = Curve::try_from(sub_matches.value_of("curve").unwrap())?;
|
||||
match curve {
|
||||
constants::BN128 => cli_compile::<Bn128Field>(sub_matches)?,
|
||||
constants::BLS12_381 => cli_compile::<Bls12Field>(sub_matches)?,
|
||||
_ => unreachable!(),
|
||||
Curve::Bn128 => cli_compile::<Bn128Field>(sub_matches)?,
|
||||
Curve::Bls12 => cli_compile::<Bls12Field>(sub_matches)?,
|
||||
}
|
||||
}
|
||||
("check", Some(sub_matches)) => {
|
||||
|
@ -738,8 +793,6 @@ fn cli() -> Result<(), String> {
|
|||
}
|
||||
}
|
||||
("compute-witness", Some(sub_matches)) => {
|
||||
println!("Computing witness...");
|
||||
|
||||
// read compiled program
|
||||
let path = Path::new(sub_matches.value_of("input").unwrap());
|
||||
let file = File::open(&path)
|
||||
|
@ -753,90 +806,106 @@ fn cli() -> Result<(), String> {
|
|||
}
|
||||
}
|
||||
("setup", Some(sub_matches)) => {
|
||||
let proof_system = sub_matches.value_of("proving-scheme").unwrap();
|
||||
|
||||
// read compiled program
|
||||
let path = Path::new(sub_matches.value_of("input").unwrap());
|
||||
let file = File::open(&path)
|
||||
.map_err(|why| format!("Couldn't open {}: {}", path.display(), why))?;
|
||||
|
||||
let mut reader = BufReader::new(file);
|
||||
|
||||
let prog = ProgEnum::deserialize(&mut reader)?;
|
||||
|
||||
match proof_system {
|
||||
constants::G16 => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_setup::<_, G16>(p, sub_matches)?,
|
||||
ProgEnum::Bls12Program(p) => cli_setup::<_, G16>(p, sub_matches)?,
|
||||
let dimensions = Dimensions::try_from((
|
||||
sub_matches.value_of("backend").unwrap(),
|
||||
match prog {
|
||||
ProgEnum::Bn128Program(_) => constants::BN128,
|
||||
ProgEnum::Bls12Program(_) => constants::BLS12_381,
|
||||
},
|
||||
sub_matches.value_of("proving-scheme").unwrap(),
|
||||
))?;
|
||||
|
||||
match dimensions {
|
||||
Dimensions(Backend::Bellman, _, ProvingScheme::G16) => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_setup::<_, G16>(p, sub_matches),
|
||||
ProgEnum::Bls12Program(p) => cli_setup::<_, G16>(p, sub_matches),
|
||||
},
|
||||
#[cfg(feature = "libsnark")]
|
||||
constants::PGHR13 => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_setup::<_, PGHR13>(p, sub_matches)?,
|
||||
_ => unimplemented!(),
|
||||
Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::GM17) => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_setup::<_, GM17>(p, sub_matches),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
#[cfg(feature = "libsnark")]
|
||||
constants::GM17 => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_setup::<_, GM17>(p, sub_matches)?,
|
||||
_ => unimplemented!(),
|
||||
Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::PGHR13) => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_setup::<_, PGHR13>(p, sub_matches),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
#[cfg(feature = "libsnark")]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}?
|
||||
}
|
||||
("export-verifier", Some(sub_matches)) => {
|
||||
let curve = sub_matches.value_of("curve").unwrap();
|
||||
let proof_system = sub_matches.value_of("proving-scheme").unwrap();
|
||||
let dimensions = Dimensions::try_from((
|
||||
sub_matches.value_of("backend").unwrap(),
|
||||
sub_matches.value_of("curve").unwrap(),
|
||||
sub_matches.value_of("proving-scheme").unwrap(),
|
||||
))?;
|
||||
|
||||
match proof_system {
|
||||
constants::G16 => match curve {
|
||||
constants::BN128 => cli_export_verifier::<Bn128Field, G16>(sub_matches)?,
|
||||
constants::BLS12_381 => cli_export_verifier::<Bls12Field, G16>(sub_matches)?,
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
match dimensions {
|
||||
Dimensions(Backend::Bellman, Curve::Bn128, ProvingScheme::G16) => {
|
||||
cli_export_verifier::<Bn128Field, G16>(sub_matches)
|
||||
}
|
||||
Dimensions(Backend::Bellman, Curve::Bls12, ProvingScheme::G16) => {
|
||||
cli_export_verifier::<Bls12Field, G16>(sub_matches)
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
constants::PGHR13 => match curve {
|
||||
constants::BN128 => cli_export_verifier::<Bn128Field, PGHR13>(sub_matches)?,
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::GM17) => {
|
||||
cli_export_verifier::<Bn128Field, GM17>(sub_matches)
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::PGHR13) => {
|
||||
cli_export_verifier::<Bn128Field, PGHR13>(sub_matches)
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
constants::GM17 => match curve {
|
||||
constants::BN128 => cli_export_verifier::<Bn128Field, GM17>(sub_matches)?,
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}?
|
||||
}
|
||||
("generate-proof", Some(sub_matches)) => {
|
||||
let proof_system = sub_matches.value_of("proving-scheme").unwrap();
|
||||
|
||||
let program_path = Path::new(sub_matches.value_of("input").unwrap());
|
||||
let program_file = File::open(&program_path)
|
||||
.map_err(|why| format!("Couldn't open {}: {}", program_path.display(), why))?;
|
||||
|
||||
let mut reader = BufReader::new(program_file);
|
||||
|
||||
let prog = ProgEnum::deserialize(&mut reader)?;
|
||||
|
||||
match proof_system {
|
||||
constants::G16 => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_generate_proof::<_, G16>(p, sub_matches)?,
|
||||
ProgEnum::Bls12Program(p) => cli_generate_proof::<_, G16>(p, sub_matches)?,
|
||||
let dimensions = Dimensions::try_from((
|
||||
sub_matches.value_of("backend").unwrap(),
|
||||
match prog {
|
||||
ProgEnum::Bn128Program(_) => constants::BN128,
|
||||
ProgEnum::Bls12Program(_) => constants::BLS12_381,
|
||||
},
|
||||
sub_matches.value_of("proving-scheme").unwrap(),
|
||||
))?;
|
||||
|
||||
match dimensions {
|
||||
Dimensions(Backend::Bellman, _, ProvingScheme::G16) => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_generate_proof::<_, G16>(p, sub_matches),
|
||||
ProgEnum::Bls12Program(p) => cli_generate_proof::<_, G16>(p, sub_matches),
|
||||
},
|
||||
#[cfg(feature = "libsnark")]
|
||||
constants::PGHR13 => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_generate_proof::<_, PGHR13>(p, sub_matches)?,
|
||||
_ => unimplemented!(),
|
||||
Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::GM17) => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_generate_proof::<_, GM17>(p, sub_matches),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
#[cfg(feature = "libsnark")]
|
||||
constants::GM17 => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_generate_proof::<_, GM17>(p, sub_matches)?,
|
||||
_ => unimplemented!(),
|
||||
Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::PGHR13) => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_generate_proof::<_, PGHR13>(p, sub_matches),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
#[cfg(feature = "libsnark")]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}?
|
||||
}
|
||||
("print-proof", Some(sub_matches)) => {
|
||||
let format = sub_matches.value_of("format").unwrap();
|
||||
|
||||
let path = Path::new(sub_matches.value_of("proof-path").unwrap());
|
||||
|
||||
let file = File::open(&path)
|
||||
|
@ -872,27 +941,30 @@ fn cli() -> Result<(), String> {
|
|||
}
|
||||
}
|
||||
("verify", Some(sub_matches)) => {
|
||||
let curve = sub_matches.value_of("curve").unwrap();
|
||||
let proof_system = sub_matches.value_of("proving-scheme").unwrap();
|
||||
let dimensions = Dimensions::try_from((
|
||||
sub_matches.value_of("backend").unwrap(),
|
||||
sub_matches.value_of("curve").unwrap(),
|
||||
sub_matches.value_of("proving-scheme").unwrap(),
|
||||
))?;
|
||||
|
||||
match proof_system {
|
||||
constants::G16 => match curve {
|
||||
constants::BN128 => cli_verify::<Bn128Field, G16>(sub_matches)?,
|
||||
constants::BLS12_381 => cli_verify::<Bls12Field, G16>(sub_matches)?,
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
match dimensions {
|
||||
Dimensions(Backend::Bellman, Curve::Bn128, ProvingScheme::G16) => {
|
||||
cli_verify::<Bn128Field, G16>(sub_matches)
|
||||
}
|
||||
Dimensions(Backend::Bellman, Curve::Bls12, ProvingScheme::G16) => {
|
||||
cli_verify::<Bls12Field, G16>(sub_matches)
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
constants::PGHR13 => match curve {
|
||||
constants::BN128 => cli_verify::<Bn128Field, PGHR13>(sub_matches)?,
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::GM17) => {
|
||||
cli_verify::<Bn128Field, GM17>(sub_matches)
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::PGHR13) => {
|
||||
cli_verify::<Bn128Field, PGHR13>(sub_matches)
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
constants::GM17 => match curve {
|
||||
constants::BN128 => cli_verify::<Bn128Field, GM17>(sub_matches)?,
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}?
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
@ -934,7 +1006,7 @@ mod tests {
|
|||
|
||||
let resolver = FileSystemResolver::new();
|
||||
let _: CompilationArtifacts<Bn128Field> =
|
||||
compile(source, path, Some(&resolver)).unwrap();
|
||||
compile(source, path, Some(&resolver), &CompileConfig::default()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -956,7 +1028,7 @@ mod tests {
|
|||
|
||||
let resolver = FileSystemResolver::new();
|
||||
let artifacts: CompilationArtifacts<Bn128Field> =
|
||||
compile(source, path, Some(&resolver)).unwrap();
|
||||
compile(source, path, Some(&resolver), &CompileConfig::default()).unwrap();
|
||||
|
||||
let interpreter = ir::Interpreter::default();
|
||||
|
||||
|
@ -985,7 +1057,7 @@ mod tests {
|
|||
|
||||
let resolver = FileSystemResolver::new();
|
||||
let artifacts: CompilationArtifacts<Bn128Field> =
|
||||
compile(source, path, Some(&resolver)).unwrap();
|
||||
compile(source, path, Some(&resolver), &CompileConfig::default()).unwrap();
|
||||
|
||||
let interpreter = ir::Interpreter::default();
|
||||
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
pub const BELLMAN: &str = "bellman";
|
||||
#[cfg(feature = "libsnark")]
|
||||
pub const LIBSNARK: &str = "libsnark";
|
||||
#[cfg(feature = "libsnark")]
|
||||
pub const BACKENDS: &[&str] = &[BELLMAN, LIBSNARK];
|
||||
#[cfg(not(feature = "libsnark"))]
|
||||
pub const BACKENDS: &[&str] = &[BELLMAN];
|
||||
|
||||
pub const BN128: &str = "bn128";
|
||||
pub const BLS12_381: &str = "bls12_381";
|
||||
pub const CURVES: &[&str] = &[BN128, BLS12_381];
|
||||
|
|
96
zokrates_cli/src/helpers.rs
Normal file
96
zokrates_cli/src/helpers.rs
Normal file
|
@ -0,0 +1,96 @@
|
|||
use core::convert::TryFrom;
|
||||
|
||||
use crate::constants::*;
|
||||
|
||||
pub enum Curve {
|
||||
Bn128,
|
||||
Bls12,
|
||||
}
|
||||
|
||||
pub enum Backend {
|
||||
Bellman,
|
||||
#[cfg(feature = "libsnark")]
|
||||
Libsnark,
|
||||
}
|
||||
|
||||
pub enum ProvingScheme {
|
||||
G16,
|
||||
#[cfg(feature = "libsnark")]
|
||||
GM17,
|
||||
#[cfg(feature = "libsnark")]
|
||||
PGHR13,
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Curve {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
match s {
|
||||
BN128 => Ok(Curve::Bn128),
|
||||
BLS12_381 => Ok(Curve::Bls12),
|
||||
_ => Err(format!("Unknown curve {}", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Backend {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
match s {
|
||||
BELLMAN => Ok(Backend::Bellman),
|
||||
#[cfg(feature = "libsnark")]
|
||||
LIBSNARK => Ok(Backend::Libsnark),
|
||||
_ => Err(format!("Unknown backend {}", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for ProvingScheme {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
match s {
|
||||
G16 => Ok(ProvingScheme::G16),
|
||||
#[cfg(feature = "libsnark")]
|
||||
GM17 => Ok(ProvingScheme::GM17),
|
||||
#[cfg(feature = "libsnark")]
|
||||
PGHR13 => Ok(ProvingScheme::PGHR13),
|
||||
_ => Err(format!("Unknown proving scheme {}", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Dimensions(pub Backend, pub Curve, pub ProvingScheme);
|
||||
|
||||
impl TryFrom<(&str, &str, &str)> for Dimensions {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(s: (&str, &str, &str)) -> Result<Dimensions, Self::Error> {
|
||||
let backend = Backend::try_from(s.0)?;
|
||||
let curve = Curve::try_from(s.1)?;
|
||||
let proving_scheme = ProvingScheme::try_from(s.2)?;
|
||||
|
||||
match (&backend, &curve, &proving_scheme) {
|
||||
(Backend::Bellman, Curve::Bn128, ProvingScheme::G16) => {
|
||||
Ok(Dimensions(backend, curve, proving_scheme))
|
||||
}
|
||||
(Backend::Bellman, Curve::Bls12, ProvingScheme::G16) => {
|
||||
Ok(Dimensions(backend, curve, proving_scheme))
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
(Backend::Libsnark, Curve::Bn128, ProvingScheme::GM17) => {
|
||||
Ok(Dimensions(backend, curve, proving_scheme))
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
(Backend::Libsnark, Curve::Bn128, ProvingScheme::PGHR13) => {
|
||||
Ok(Dimensions(backend, curve, proving_scheme))
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
_ => Err(format!(
|
||||
"Unsupported combination of dimensions (backend: {}, curve: {}, proving scheme: {})",
|
||||
s.0, s.1, s.2
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,17 @@ mod integration {
|
|||
use zokrates_abi::{parse_strict, Encode};
|
||||
use zokrates_core::typed_absy::abi::Abi;
|
||||
|
||||
macro_rules! map(
|
||||
{
|
||||
$($key:expr => $value:expr),+ } => {
|
||||
{
|
||||
let mut m = ::std::collections::HashMap::new();
|
||||
$(m.insert($key, $value);)+
|
||||
m
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_compile_and_witness_dir() {
|
||||
|
@ -194,72 +205,84 @@ mod integration {
|
|||
}
|
||||
|
||||
#[cfg(feature = "libsnark")]
|
||||
let schemes = ["pghr13", "gm17", "g16"];
|
||||
let backends = map! {
|
||||
"bellman" => ["g16"],
|
||||
"libsnark" => ["gm17", "pghr13"]
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "libsnark"))]
|
||||
let schemes = ["g16"];
|
||||
let backends = map! {"bellman" => ["g16"]};
|
||||
|
||||
for scheme in &schemes {
|
||||
// SETUP
|
||||
assert_cli::Assert::command(&[
|
||||
"../target/release/zokrates",
|
||||
"setup",
|
||||
"-i",
|
||||
flattened_path.to_str().unwrap(),
|
||||
"-p",
|
||||
proving_key_path.to_str().unwrap(),
|
||||
"-v",
|
||||
verification_key_path.to_str().unwrap(),
|
||||
"--proving-scheme",
|
||||
scheme,
|
||||
])
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
for (backend, schemes) in backends {
|
||||
for scheme in &schemes {
|
||||
// SETUP
|
||||
assert_cli::Assert::command(&[
|
||||
"../target/release/zokrates",
|
||||
"setup",
|
||||
"-i",
|
||||
flattened_path.to_str().unwrap(),
|
||||
"-p",
|
||||
proving_key_path.to_str().unwrap(),
|
||||
"-v",
|
||||
verification_key_path.to_str().unwrap(),
|
||||
"--backend",
|
||||
backend,
|
||||
"--proving-scheme",
|
||||
scheme,
|
||||
])
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
|
||||
// EXPORT-VERIFIER
|
||||
assert_cli::Assert::command(&[
|
||||
"../target/release/zokrates",
|
||||
"export-verifier",
|
||||
"-i",
|
||||
verification_key_path.to_str().unwrap(),
|
||||
"-o",
|
||||
verification_contract_path.to_str().unwrap(),
|
||||
"--proving-scheme",
|
||||
scheme,
|
||||
])
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
// EXPORT-VERIFIER
|
||||
assert_cli::Assert::command(&[
|
||||
"../target/release/zokrates",
|
||||
"export-verifier",
|
||||
"-i",
|
||||
verification_key_path.to_str().unwrap(),
|
||||
"-o",
|
||||
verification_contract_path.to_str().unwrap(),
|
||||
"--backend",
|
||||
backend,
|
||||
"--proving-scheme",
|
||||
scheme,
|
||||
])
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
|
||||
// GENERATE-PROOF
|
||||
assert_cli::Assert::command(&[
|
||||
"../target/release/zokrates",
|
||||
"generate-proof",
|
||||
"-i",
|
||||
flattened_path.to_str().unwrap(),
|
||||
"-w",
|
||||
witness_path.to_str().unwrap(),
|
||||
"-p",
|
||||
proving_key_path.to_str().unwrap(),
|
||||
"--proving-scheme",
|
||||
scheme,
|
||||
"-j",
|
||||
proof_path.to_str().unwrap(),
|
||||
])
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
// GENERATE-PROOF
|
||||
assert_cli::Assert::command(&[
|
||||
"../target/release/zokrates",
|
||||
"generate-proof",
|
||||
"-i",
|
||||
flattened_path.to_str().unwrap(),
|
||||
"-w",
|
||||
witness_path.to_str().unwrap(),
|
||||
"-p",
|
||||
proving_key_path.to_str().unwrap(),
|
||||
"--backend",
|
||||
backend,
|
||||
"--proving-scheme",
|
||||
scheme,
|
||||
"-j",
|
||||
proof_path.to_str().unwrap(),
|
||||
])
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
|
||||
// TEST VERIFIER
|
||||
// TEST VERIFIER
|
||||
|
||||
assert_cli::Assert::command(&[
|
||||
"node",
|
||||
"test.js",
|
||||
verification_contract_path.to_str().unwrap(),
|
||||
proof_path.to_str().unwrap(),
|
||||
scheme,
|
||||
"v1",
|
||||
])
|
||||
.current_dir(concat!(env!("OUT_DIR"), "/contract"))
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
assert_cli::Assert::command(&[
|
||||
"node",
|
||||
"test.js",
|
||||
verification_contract_path.to_str().unwrap(),
|
||||
proof_path.to_str().unwrap(),
|
||||
scheme,
|
||||
"v1",
|
||||
])
|
||||
.current_dir(concat!(env!("OUT_DIR"), "/contract"))
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,6 @@ fn main() {
|
|||
.include(libsnark_source_path.join("depends/libfqfft"))
|
||||
.define("CURVE_ALT_BN128", None)
|
||||
.file("lib/ffi.cpp")
|
||||
.file("lib/util.cpp")
|
||||
.file("lib/gm17.cpp")
|
||||
.file("lib/pghr13.cpp")
|
||||
.compile("libsnark_wrapper.a");
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
#include "gm17.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
@ -17,203 +17,173 @@
|
|||
// contains required interfaces and types (keypair, proof, generator, prover, verifier)
|
||||
#include <libsnark/zk_proof_systems/ppzksnark/r1cs_se_ppzksnark/r1cs_se_ppzksnark.hpp>
|
||||
|
||||
typedef long integer_coeff_t;
|
||||
|
||||
using namespace libsnark;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
#include "util.tcc"
|
||||
|
||||
namespace gm17 {
|
||||
r1cs_se_ppzksnark_constraint_system<libff::alt_bn128_pp> createConstraintSystem(const uint8_t* a, const uint8_t* b, const uint8_t* c, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs)
|
||||
{
|
||||
r1cs_se_ppzksnark_constraint_system<libff::alt_bn128_pp> cs;
|
||||
cs.primary_input_size = inputs;
|
||||
cs.auxiliary_input_size = variables - inputs - 1; // ~one not included
|
||||
|
||||
cout << "num variables: " << variables << endl;
|
||||
cout << "num constraints: " << constraints << endl;
|
||||
cout << "num inputs: " << inputs << endl;
|
||||
|
||||
struct VariableValueMapping {
|
||||
int constraint_id;
|
||||
int variable_id;
|
||||
uint8_t variable_value[32];
|
||||
};
|
||||
|
||||
const VariableValueMapping* a_vvmap = (VariableValueMapping*)a;
|
||||
const VariableValueMapping* b_vvmap = (VariableValueMapping*)b;
|
||||
const VariableValueMapping* c_vvmap = (VariableValueMapping*)c;
|
||||
|
||||
int a_id = 0;
|
||||
int b_id = 0;
|
||||
int c_id = 0;
|
||||
|
||||
// initialize curve parameters
|
||||
libff::alt_bn128_pp::init_public_params();
|
||||
|
||||
for (int row = 0; row < constraints; row++) {
|
||||
linear_combination<libff::Fr<libff::alt_bn128_pp>> lin_comb_a, lin_comb_b, lin_comb_c;
|
||||
while (a_id < a_len && a_vvmap[a_id].constraint_id == row) {
|
||||
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(a_vvmap[a_id].variable_value);
|
||||
if (!value.is_zero()) {
|
||||
lin_comb_a.add_term(a_vvmap[a_id].variable_id, value);
|
||||
}
|
||||
a_id++;
|
||||
}
|
||||
while (b_id < b_len && b_vvmap[b_id].constraint_id == row) {
|
||||
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(b_vvmap[b_id].variable_value);
|
||||
if (!value.is_zero()) {
|
||||
lin_comb_b.add_term(b_vvmap[b_id].variable_id, value);
|
||||
}
|
||||
b_id++;
|
||||
}
|
||||
while (c_id < c_len && c_vvmap[c_id].constraint_id == row) {
|
||||
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(c_vvmap[c_id].variable_value);
|
||||
if (!value.is_zero()) {
|
||||
lin_comb_c.add_term(c_vvmap[c_id].variable_id, value);
|
||||
}
|
||||
c_id++;
|
||||
}
|
||||
cs.add_constraint(r1cs_constraint<libff::Fr<libff::alt_bn128_pp>>(lin_comb_a, lin_comb_b, lin_comb_c));
|
||||
}
|
||||
return cs;
|
||||
}
|
||||
|
||||
r1cs_se_ppzksnark_keypair<libff::alt_bn128_pp> generateKeypair(const r1cs_se_ppzksnark_constraint_system<libff::alt_bn128_pp>& cs)
|
||||
{
|
||||
return r1cs_se_ppzksnark_generator<libff::alt_bn128_pp>(cs); //from r1cs_se_ppzksnark.hpp
|
||||
}
|
||||
|
||||
std::string serializeVerificationKey(r1cs_se_ppzksnark_verification_key<libff::alt_bn128_pp>* vk)
|
||||
template <mp_size_t Q, typename ppT, typename G1, typename G2>
|
||||
std::string serializeVerificationKey(r1cs_se_ppzksnark_verification_key<ppT>* vk)
|
||||
{
|
||||
std::stringstream ss;
|
||||
unsigned queryLength = vk->query.size();
|
||||
|
||||
ss << "vk.h=" << outputPointG2AffineAsHex(vk->H) << endl;
|
||||
ss << "vk.g_alpha=" << outputPointG1AffineAsHex(vk->G_alpha) << endl;
|
||||
ss << "vk.h_beta=" << outputPointG2AffineAsHex(vk->H_beta) << endl;
|
||||
ss << "vk.g_gamma=" << outputPointG1AffineAsHex(vk->G_gamma) << endl;
|
||||
ss << "vk.h_gamma=" << outputPointG2AffineAsHex(vk->H_gamma) << endl;
|
||||
ss << "vk.query.len()=" << queryLength << endl;
|
||||
ss << "{";
|
||||
ss << "\"h\":" << outputPointG2AffineAsHexJson<Q, G2>(vk->H) << ",";
|
||||
ss << "\"g_alpha\":" << outputPointG1AffineAsHexJson<Q, G1>(vk->G_alpha) << ",";
|
||||
ss << "\"h_beta\":" << outputPointG2AffineAsHexJson<Q, G2>(vk->H_beta) << ",";
|
||||
ss << "\"g_gamma\":" << outputPointG1AffineAsHexJson<Q, G1>(vk->G_gamma) << ",";
|
||||
ss << "\"h_gamma\":" << outputPointG2AffineAsHexJson<Q, G2>(vk->H_gamma) << ",";
|
||||
ss << "\"query\":[";
|
||||
for (size_t i = 0; i < queryLength; ++i) {
|
||||
auto vk_query_i = outputPointG1AffineAsHex(vk->query[i]);
|
||||
ss << "vk.query[" << i << "]=" << vk_query_i << endl;
|
||||
if (i != 0)
|
||||
ss << ",";
|
||||
ss << outputPointG1AffineAsHexJson<Q, G1>(vk->query[i]);
|
||||
}
|
||||
ss << "vk.raw=" << toHexString(serialize(*vk)) << endl;
|
||||
ss << "],";
|
||||
ss << "\"raw\":\"" << encodeToHexString<2>(serialize(*vk)) << "\"";
|
||||
ss << "}";
|
||||
std::string str = ss.str();
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string serializeProof(r1cs_se_ppzksnark_proof<libff::alt_bn128_pp>* proof, const uint8_t* public_inputs, int32_t public_inputs_length)
|
||||
template <mp_size_t Q, mp_size_t R, typename ppT, typename G1, typename G2>
|
||||
std::string serializeProof(r1cs_se_ppzksnark_proof<ppT>* proof, const uint8_t* public_inputs, int32_t public_inputs_length)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
<< "\n";
|
||||
ss << "\t\"proof\": {"
|
||||
<< "\n";
|
||||
ss << "\t\t\"a\": " << outputPointG1AffineAsHexJson(proof->A) << ",\n";
|
||||
ss << "\t\t\"b\": " << outputPointG2AffineAsHexJson(proof->B) << ",\n";
|
||||
ss << "\t\t\"c\": " << outputPointG1AffineAsHexJson(proof->C) << "\n";
|
||||
ss << "\t},"
|
||||
<< "\n";
|
||||
ss << "\t\"inputs\": "
|
||||
<< "[";
|
||||
ss << "{";
|
||||
ss << "\"proof\":{";
|
||||
ss << "\"a\":" << outputPointG1AffineAsHexJson<Q, G1>(proof->A) << ",";
|
||||
ss << "\"b\":" << outputPointG2AffineAsHexJson<Q, G2>(proof->B) << ",";
|
||||
ss << "\"c\":" << outputPointG1AffineAsHexJson<Q, G1>(proof->C);
|
||||
ss << "},";
|
||||
ss << "\"inputs\":[";
|
||||
for (int i = 1; i < public_inputs_length; i++) {
|
||||
if (i != 1) {
|
||||
ss << ",";
|
||||
}
|
||||
ss << outputInputAsHex(libsnarkBigintFromBytes(public_inputs + i * 32));
|
||||
ss << outputInputAsHex<R>(libsnarkBigintFromBytes<R>(public_inputs + (i * R * sizeof(mp_limb_t))));
|
||||
}
|
||||
ss << "],\n";
|
||||
ss << "\t\"raw\": \"" << toHexString(serialize(*proof)) << "\"\n";
|
||||
ss << "}"
|
||||
<< "\n";
|
||||
ss << "],";
|
||||
ss << "\"raw\":\"" << encodeToHexString<2>(serialize(*proof)) << "\"";
|
||||
ss << "}";
|
||||
std::string str = ss.str();
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
setup_result_t gm17_setup(const uint8_t* A, const uint8_t* B, const uint8_t* C, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs)
|
||||
template <mp_size_t Q, mp_size_t R, typename ppT, typename G1, typename G2>
|
||||
setup_result_t setup(const uint8_t* a, const uint8_t* b, const uint8_t* c, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs)
|
||||
{
|
||||
libff::inhibit_profiling_info = true;
|
||||
libff::inhibit_profiling_counters = true;
|
||||
|
||||
// initialize curve parameters
|
||||
libff::alt_bn128_pp::init_public_params();
|
||||
ppT::init_public_params();
|
||||
|
||||
auto cs = gm17::createConstraintSystem(A, B, C, a_len, b_len, c_len, constraints, variables, inputs);
|
||||
auto cs = createConstraintSystem<r1cs_se_ppzksnark_constraint_system, R, ppT>(a, b, c, a_len, b_len, c_len, constraints, variables, inputs);
|
||||
assert(cs.num_variables() >= (unsigned)inputs);
|
||||
assert(cs.num_inputs() == (unsigned)inputs);
|
||||
assert(cs.num_constraints() == (unsigned)constraints);
|
||||
|
||||
// create keypair
|
||||
auto keypair = r1cs_se_ppzksnark_generator<libff::alt_bn128_pp>(cs);
|
||||
auto vk = gm17::serializeVerificationKey(&keypair.vk);
|
||||
r1cs_se_ppzksnark_keypair<ppT> keypair = r1cs_se_ppzksnark_generator<ppT>(cs);
|
||||
auto vk = serializeVerificationKey<Q, ppT, G1, G2>(&keypair.vk);
|
||||
|
||||
buffer_t vk_buf = create_buffer(vk);
|
||||
buffer_t pk_buf = create_buffer(keypair.pk);
|
||||
buffer_t vk_buf = createBuffer(vk);
|
||||
buffer_t pk_buf = createBuffer(keypair.pk);
|
||||
|
||||
setup_result_t result(vk_buf, pk_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
proof_result_t gm17_generate_proof(buffer_t* pk_buf, const uint8_t* public_inputs, int32_t public_inputs_length, const uint8_t* private_inputs, int32_t private_inputs_length)
|
||||
{
|
||||
libff::inhibit_profiling_info = true;
|
||||
libff::inhibit_profiling_counters = true;
|
||||
|
||||
//initialize curve parameters
|
||||
libff::alt_bn128_pp::init_public_params();
|
||||
|
||||
r1cs_se_ppzksnark_proving_key<libff::alt_bn128_pp> proving_key;
|
||||
from_buffer<r1cs_se_ppzksnark_proving_key<libff::alt_bn128_pp>>(pk_buf, proving_key);
|
||||
|
||||
// assign variables based on witness values, excludes ~one
|
||||
r1cs_variable_assignment<libff::Fr<libff::alt_bn128_pp>> full_variable_assignment;
|
||||
for (int i = 1; i < public_inputs_length; i++) {
|
||||
full_variable_assignment.push_back(libff::Fr<libff::alt_bn128_pp>(libsnarkBigintFromBytes(public_inputs + i * 32)));
|
||||
}
|
||||
for (int i = 0; i < private_inputs_length; i++) {
|
||||
full_variable_assignment.push_back(libff::Fr<libff::alt_bn128_pp>(libsnarkBigintFromBytes(private_inputs + i * 32)));
|
||||
}
|
||||
|
||||
// split up variables into primary and auxiliary inputs. Does *NOT* include the constant 1
|
||||
// Public variables belong to primary input, private variables are auxiliary input.
|
||||
r1cs_primary_input<libff::Fr<libff::alt_bn128_pp>> primary_input(full_variable_assignment.begin(), full_variable_assignment.begin() + public_inputs_length - 1);
|
||||
r1cs_primary_input<libff::Fr<libff::alt_bn128_pp>> auxiliary_input(full_variable_assignment.begin() + public_inputs_length - 1, full_variable_assignment.end());
|
||||
|
||||
// for debugging
|
||||
// cout << "full variable assignment:" << endl << full_variable_assignment;
|
||||
// cout << "primary input:" << endl << primary_input;
|
||||
// cout << "auxiliary input:" << endl << auxiliary_input;
|
||||
|
||||
// Proof Generation
|
||||
auto proof = r1cs_se_ppzksnark_prover<libff::alt_bn128_pp>(proving_key, primary_input, auxiliary_input);
|
||||
auto proof_json = gm17::serializeProof(&proof, public_inputs, public_inputs_length);
|
||||
|
||||
buffer_t proof_buf = create_buffer(proof_json);
|
||||
proof_result_t result(proof_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool gm17_verify(buffer_t* vk_buf, buffer_t* proof_buf, const uint8_t* public_inputs, int32_t public_inputs_length)
|
||||
template <mp_size_t Q, mp_size_t R, typename ppT, typename G1, typename G2>
|
||||
proof_result_t generateProof(buffer_t* pk_buf, const uint8_t* public_inputs, int32_t public_inputs_length, const uint8_t* private_inputs, int32_t private_inputs_length)
|
||||
{
|
||||
libff::inhibit_profiling_info = true;
|
||||
libff::inhibit_profiling_counters = true;
|
||||
|
||||
// initialize curve parameters
|
||||
libff::alt_bn128_pp::init_public_params();
|
||||
ppT::init_public_params();
|
||||
|
||||
r1cs_se_ppzksnark_verification_key<libff::alt_bn128_pp> vk;
|
||||
r1cs_se_ppzksnark_proof<libff::alt_bn128_pp> proof;
|
||||
r1cs_se_ppzksnark_proving_key<ppT> proving_key;
|
||||
fromBuffer<r1cs_se_ppzksnark_proving_key<ppT>>(pk_buf, proving_key);
|
||||
|
||||
from_buffer<r1cs_se_ppzksnark_verification_key<libff::alt_bn128_pp>>(vk_buf, vk);
|
||||
from_buffer<r1cs_se_ppzksnark_proof<libff::alt_bn128_pp>>(proof_buf, proof);
|
||||
|
||||
r1cs_primary_input<libff::Fr<libff::alt_bn128_pp>> primary_input;
|
||||
for (int i = 0; i < public_inputs_length; i++) {
|
||||
primary_input.push_back(libff::Fr<libff::alt_bn128_pp>(libsnarkBigintFromBytes(public_inputs + i * 32)));
|
||||
r1cs_variable_assignment<libff::Fr<ppT>> full_variable_assignment;
|
||||
for (int i = 1; i < public_inputs_length; i++) {
|
||||
full_variable_assignment.push_back(libff::Fr<ppT>(libsnarkBigintFromBytes<R>(public_inputs + (i * R * sizeof(mp_limb_t)))));
|
||||
}
|
||||
for (int i = 0; i < private_inputs_length; i++) {
|
||||
full_variable_assignment.push_back(libff::Fr<ppT>(libsnarkBigintFromBytes<R>(private_inputs + (i * R * sizeof(mp_limb_t)))));
|
||||
}
|
||||
|
||||
return r1cs_se_ppzksnark_verifier_strong_IC<libff::alt_bn128_pp>(vk, primary_input, proof);
|
||||
r1cs_primary_input<libff::Fr<ppT>> primary_input(
|
||||
full_variable_assignment.begin(),
|
||||
full_variable_assignment.begin() + public_inputs_length - 1);
|
||||
|
||||
r1cs_primary_input<libff::Fr<ppT>> auxiliary_input(
|
||||
full_variable_assignment.begin() + public_inputs_length - 1,
|
||||
full_variable_assignment.end());
|
||||
|
||||
r1cs_se_ppzksnark_proof<ppT> proof = r1cs_se_ppzksnark_prover<ppT>(proving_key, primary_input, auxiliary_input);
|
||||
std::string json = serializeProof<Q, R, ppT, G1, G2>(&proof, public_inputs, public_inputs_length);
|
||||
|
||||
buffer_t proof_buf = createBuffer(json);
|
||||
proof_result_t result(proof_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <mp_size_t R, typename ppT>
|
||||
bool verify(buffer_t* vk_buf, buffer_t* proof_buf, const uint8_t* public_inputs, int32_t public_inputs_length)
|
||||
{
|
||||
libff::inhibit_profiling_info = true;
|
||||
libff::inhibit_profiling_counters = true;
|
||||
|
||||
// initialize curve parameters
|
||||
ppT::init_public_params();
|
||||
|
||||
r1cs_se_ppzksnark_verification_key<ppT> vk;
|
||||
r1cs_se_ppzksnark_proof<ppT> proof;
|
||||
|
||||
fromBuffer<r1cs_se_ppzksnark_verification_key<ppT>>(vk_buf, vk);
|
||||
fromBuffer<r1cs_se_ppzksnark_proof<ppT>>(proof_buf, proof);
|
||||
|
||||
r1cs_primary_input<libff::Fr<ppT>> primary_input;
|
||||
for (int i = 0; i < public_inputs_length; i++) {
|
||||
primary_input.push_back(libff::Fr<ppT>(libsnarkBigintFromBytes<R>(public_inputs + (i * R * sizeof(mp_limb_t)))));
|
||||
}
|
||||
|
||||
return r1cs_se_ppzksnark_verifier_strong_IC<ppT>(vk, primary_input, proof);
|
||||
}
|
||||
}
|
||||
|
||||
setup_result_t gm17_bn128_setup(const uint8_t* a, const uint8_t* b, const uint8_t* c, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs)
|
||||
{
|
||||
return gm17::setup<libff::alt_bn128_q_limbs,
|
||||
libff::alt_bn128_r_limbs,
|
||||
libff::alt_bn128_pp,
|
||||
libff::alt_bn128_G1,
|
||||
libff::alt_bn128_G2>(a, b, c, a_len, b_len, c_len, constraints, variables, inputs);
|
||||
}
|
||||
|
||||
proof_result_t gm17_bn128_generate_proof(buffer_t* pk_buf,
|
||||
const uint8_t* public_inputs,
|
||||
int32_t public_inputs_length,
|
||||
const uint8_t* private_inputs,
|
||||
int32_t private_inputs_length)
|
||||
{
|
||||
return gm17::generateProof<libff::alt_bn128_q_limbs,
|
||||
libff::alt_bn128_r_limbs,
|
||||
libff::alt_bn128_pp,
|
||||
libff::alt_bn128_G1,
|
||||
libff::alt_bn128_G2>(pk_buf,
|
||||
public_inputs,
|
||||
public_inputs_length,
|
||||
private_inputs,
|
||||
private_inputs_length);
|
||||
}
|
||||
|
||||
bool gm17_bn128_verify(buffer_t* vk_buf, buffer_t* proof_buf, const uint8_t* public_inputs, int32_t public_inputs_length)
|
||||
{
|
||||
return gm17::verify<libff::alt_bn128_r_limbs,
|
||||
libff::alt_bn128_pp>(vk_buf, proof_buf, public_inputs, public_inputs_length);
|
||||
}
|
|
@ -13,7 +13,7 @@ extern "C" {
|
|||
|
||||
#include "ffi.hpp"
|
||||
|
||||
setup_result_t gm17_setup(
|
||||
setup_result_t gm17_bn128_setup(
|
||||
const uint8_t* a,
|
||||
const uint8_t* b,
|
||||
const uint8_t* c,
|
||||
|
@ -24,14 +24,14 @@ setup_result_t gm17_setup(
|
|||
int32_t variables,
|
||||
int32_t inputs);
|
||||
|
||||
proof_result_t gm17_generate_proof(
|
||||
proof_result_t gm17_bn128_generate_proof(
|
||||
buffer_t* pk_buf,
|
||||
const uint8_t* public_inputs,
|
||||
int32_t public_inputs_length,
|
||||
const uint8_t* private_inputs,
|
||||
int32_t private_inputs_length);
|
||||
|
||||
bool gm17_verify(
|
||||
bool gm17_bn128_verify(
|
||||
buffer_t* vk_buf,
|
||||
buffer_t* proof_buf,
|
||||
const uint8_t* public_inputs,
|
||||
|
|
|
@ -6,223 +6,190 @@
|
|||
*/
|
||||
|
||||
#include "pghr13.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
// contains definitions of alt_bn128 ec public parameters
|
||||
// contains definition of alt_bn128 ec public parameters
|
||||
#include "libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp"
|
||||
|
||||
// contains required interfaces and types (keypair, proof, generator, prover, verifier)
|
||||
#include <libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp>
|
||||
|
||||
typedef long integer_coeff_t;
|
||||
|
||||
using namespace libsnark;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
#include "util.tcc"
|
||||
|
||||
namespace pghr13 {
|
||||
r1cs_ppzksnark_constraint_system<libff::alt_bn128_pp> createConstraintSystem(const uint8_t* a, const uint8_t* b, const uint8_t* c, int a_len, int b_len, int c_len, int constraints, int variables, int inputs)
|
||||
{
|
||||
r1cs_ppzksnark_constraint_system<libff::alt_bn128_pp> cs;
|
||||
cs.primary_input_size = inputs;
|
||||
cs.auxiliary_input_size = variables - inputs - 1; // ~one not included
|
||||
|
||||
cout << "num variables: " << variables << endl;
|
||||
cout << "num constraints: " << constraints << endl;
|
||||
cout << "num inputs: " << inputs << endl;
|
||||
|
||||
struct VariableValueMapping {
|
||||
int constraint_id;
|
||||
int variable_id;
|
||||
uint8_t variable_value[32];
|
||||
};
|
||||
|
||||
const VariableValueMapping* a_vvmap = (VariableValueMapping*)a;
|
||||
const VariableValueMapping* b_vvmap = (VariableValueMapping*)b;
|
||||
const VariableValueMapping* c_vvmap = (VariableValueMapping*)c;
|
||||
|
||||
int a_id = 0;
|
||||
int b_id = 0;
|
||||
int c_id = 0;
|
||||
|
||||
// initialize curve parameters
|
||||
libff::alt_bn128_pp::init_public_params();
|
||||
|
||||
for (int row = 0; row < constraints; row++) {
|
||||
linear_combination<libff::Fr<libff::alt_bn128_pp>> lin_comb_a, lin_comb_b, lin_comb_c;
|
||||
while (a_id < a_len && a_vvmap[a_id].constraint_id == row) {
|
||||
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(a_vvmap[a_id].variable_value);
|
||||
if (!value.is_zero()) {
|
||||
lin_comb_a.add_term(a_vvmap[a_id].variable_id, value);
|
||||
}
|
||||
a_id++;
|
||||
}
|
||||
while (b_id < b_len && b_vvmap[b_id].constraint_id == row) {
|
||||
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(b_vvmap[b_id].variable_value);
|
||||
if (!value.is_zero()) {
|
||||
lin_comb_b.add_term(b_vvmap[b_id].variable_id, value);
|
||||
}
|
||||
b_id++;
|
||||
}
|
||||
while (c_id < c_len && c_vvmap[c_id].constraint_id == row) {
|
||||
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(c_vvmap[c_id].variable_value);
|
||||
if (!value.is_zero()) {
|
||||
lin_comb_c.add_term(c_vvmap[c_id].variable_id, value);
|
||||
}
|
||||
c_id++;
|
||||
}
|
||||
cs.add_constraint(r1cs_constraint<libff::Fr<libff::alt_bn128_pp>>(lin_comb_a, lin_comb_b, lin_comb_c));
|
||||
}
|
||||
return cs;
|
||||
}
|
||||
|
||||
r1cs_ppzksnark_keypair<libff::alt_bn128_pp> generateKeypair(const r1cs_ppzksnark_constraint_system<libff::alt_bn128_pp>& cs)
|
||||
{
|
||||
return r1cs_ppzksnark_generator<libff::alt_bn128_pp>(cs); // from r1cs_ppzksnark.hpp
|
||||
}
|
||||
|
||||
std::string serializeVerificationKey(r1cs_ppzksnark_verification_key<libff::alt_bn128_pp>* vk)
|
||||
template <mp_size_t Q, typename ppT, typename G1, typename G2>
|
||||
std::string serializeVerificationKey(r1cs_ppzksnark_verification_key<ppT>* vk)
|
||||
{
|
||||
std::stringstream ss;
|
||||
unsigned icLength = vk->encoded_IC_query.rest.indices.size() + 1;
|
||||
unsigned icLength = vk->encoded_IC_query.rest.indices.size();
|
||||
|
||||
ss << "vk.a=" << outputPointG2AffineAsHex(vk->alphaA_g2) << endl;
|
||||
ss << "vk.b=" << outputPointG1AffineAsHex(vk->alphaB_g1) << endl;
|
||||
ss << "vk.c=" << outputPointG2AffineAsHex(vk->alphaC_g2) << endl;
|
||||
ss << "vk.gamma=" << outputPointG2AffineAsHex(vk->gamma_g2) << endl;
|
||||
ss << "vk.gamma_beta_1=" << outputPointG1AffineAsHex(vk->gamma_beta_g1) << endl;
|
||||
ss << "vk.gamma_beta_2=" << outputPointG2AffineAsHex(vk->gamma_beta_g2) << endl;
|
||||
ss << "vk.z=" << outputPointG2AffineAsHex(vk->rC_Z_g2) << endl;
|
||||
ss << "vk.ic.len()=" << icLength << endl;
|
||||
ss << "vk.ic[0]=" << outputPointG1AffineAsHex(vk->encoded_IC_query.first) << endl;
|
||||
for (size_t i = 1; i < icLength; ++i) {
|
||||
auto vk_ic_i = outputPointG1AffineAsHex(vk->encoded_IC_query.rest.values[i - 1]);
|
||||
ss << "vk.ic[" << i << "]=" << vk_ic_i << endl;
|
||||
ss << "{";
|
||||
ss << "\"a\":" << outputPointG2AffineAsHexJson<Q, G2>(vk->alphaA_g2) << ",";
|
||||
ss << "\"b\":" << outputPointG1AffineAsHexJson<Q, G1>(vk->alphaB_g1) << ",";
|
||||
ss << "\"c\":" << outputPointG2AffineAsHexJson<Q, G2>(vk->alphaC_g2) << ",";
|
||||
ss << "\"gamma\":" << outputPointG2AffineAsHexJson<Q, G2>(vk->gamma_g2) << ",";
|
||||
ss << "\"gamma_beta_1\":" << outputPointG1AffineAsHexJson<Q, G1>(vk->gamma_beta_g1) << ",";
|
||||
ss << "\"gamma_beta_2\":" << outputPointG2AffineAsHexJson<Q, G2>(vk->gamma_beta_g2) << ",";
|
||||
ss << "\"z\":" << outputPointG2AffineAsHexJson<Q, G2>(vk->rC_Z_g2) << ",";
|
||||
ss << "\"ic\":[";
|
||||
ss << outputPointG1AffineAsHexJson<Q, G1>(vk->encoded_IC_query.first);
|
||||
for (size_t i = 0; i < icLength; ++i) {
|
||||
ss << ",";
|
||||
ss << outputPointG1AffineAsHexJson<Q, G1>(vk->encoded_IC_query.rest.values[i]);
|
||||
}
|
||||
ss << "vk.raw=" << toHexString(serialize(*vk)) << endl;
|
||||
ss << "],";
|
||||
ss << "\"raw\":\"" << encodeToHexString<2>(serialize(*vk)) << "\"";
|
||||
ss << "}";
|
||||
std::string str = ss.str();
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string serializeProof(r1cs_ppzksnark_proof<libff::alt_bn128_pp>* proof, const uint8_t* public_inputs, int public_inputs_length)
|
||||
template <mp_size_t Q, mp_size_t R, typename ppT, typename G1, typename G2>
|
||||
std::string serializeProof(r1cs_ppzksnark_proof<ppT>* proof, const uint8_t* public_inputs, int public_inputs_length)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
<< "\n";
|
||||
ss << "\t\"proof\": {"
|
||||
<< "\n";
|
||||
ss << "\t\t\"a\": " << outputPointG1AffineAsHexJson(proof->g_A.g) << ",\n";
|
||||
ss << "\t\t\"a_p\": " << outputPointG1AffineAsHexJson(proof->g_A.h) << ",\n";
|
||||
ss << "\t\t\"b\": " << outputPointG2AffineAsHexJson(proof->g_B.g) << ",\n";
|
||||
ss << "\t\t\"b_p\": " << outputPointG1AffineAsHexJson(proof->g_B.h) << ",\n";
|
||||
ss << "\t\t\"c\": " << outputPointG1AffineAsHexJson(proof->g_C.g) << ",\n";
|
||||
ss << "\t\t\"c_p\": " << outputPointG1AffineAsHexJson(proof->g_C.h) << ",\n";
|
||||
ss << "\t\t\"h\": " << outputPointG1AffineAsHexJson(proof->g_H) << ",\n";
|
||||
ss << "\t\t\"k\": " << outputPointG1AffineAsHexJson(proof->g_K) << "\n";
|
||||
ss << "\t},"
|
||||
<< "\n";
|
||||
ss << "\t\"inputs\": "
|
||||
<< "[";
|
||||
ss << "{";
|
||||
ss << "\"proof\":{";
|
||||
ss << "\"a\":" << outputPointG1AffineAsHexJson<Q, G1>(proof->g_A.g) << ",";
|
||||
ss << "\"a_p\":" << outputPointG1AffineAsHexJson<Q, G1>(proof->g_A.h) << ",";
|
||||
ss << "\"b\":" << outputPointG2AffineAsHexJson<Q, G2>(proof->g_B.g) << ",";
|
||||
ss << "\"b_p\":" << outputPointG1AffineAsHexJson<Q, G1>(proof->g_B.h) << ",";
|
||||
ss << "\"c\":" << outputPointG1AffineAsHexJson<Q, G1>(proof->g_C.g) << ",";
|
||||
ss << "\"c_p\":" << outputPointG1AffineAsHexJson<Q, G1>(proof->g_C.h) << ",";
|
||||
ss << "\"h\":" << outputPointG1AffineAsHexJson<Q, G1>(proof->g_H) << ",";
|
||||
ss << "\"k\":" << outputPointG1AffineAsHexJson<Q, G1>(proof->g_K);
|
||||
ss << "},";
|
||||
ss << "\"inputs\":[";
|
||||
for (int i = 1; i < public_inputs_length; i++) {
|
||||
if (i != 1) {
|
||||
ss << ",";
|
||||
}
|
||||
ss << outputInputAsHex(libsnarkBigintFromBytes(public_inputs + i * 32));
|
||||
ss << outputInputAsHex<R>(libsnarkBigintFromBytes<R>(public_inputs + (i * R * sizeof(mp_limb_t))));
|
||||
}
|
||||
ss << "],\n";
|
||||
ss << "\t\"raw\": \"" << toHexString(serialize(*proof)) << "\"\n";
|
||||
ss << "}"
|
||||
<< "\n";
|
||||
ss << "],";
|
||||
ss << "\"raw\":\"" << encodeToHexString<2>(serialize(*proof)) << "\"";
|
||||
ss << "}";
|
||||
std::string str = ss.str();
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
setup_result_t pghr13_setup(const uint8_t* A, const uint8_t* B, const uint8_t* C, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs)
|
||||
template <mp_size_t Q, mp_size_t R, typename ppT, typename G1, typename G2>
|
||||
setup_result_t setup(const uint8_t* a, const uint8_t* b, const uint8_t* c, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs)
|
||||
{
|
||||
libff::inhibit_profiling_info = true;
|
||||
libff::inhibit_profiling_counters = true;
|
||||
|
||||
// initialize curve parameters
|
||||
libff::alt_bn128_pp::init_public_params();
|
||||
|
||||
auto cs = pghr13::createConstraintSystem(A, B, C, a_len, b_len, c_len, constraints, variables, inputs);
|
||||
ppT::init_public_params();
|
||||
|
||||
auto cs = createConstraintSystem<r1cs_ppzksnark_constraint_system, R, ppT>(a, b, c, a_len, b_len, c_len, constraints, variables, inputs);
|
||||
assert(cs.num_variables() >= (unsigned)inputs);
|
||||
assert(cs.num_inputs() == (unsigned)inputs);
|
||||
assert(cs.num_constraints() == (unsigned)constraints);
|
||||
|
||||
// create keypair
|
||||
auto keypair = r1cs_ppzksnark_generator<libff::alt_bn128_pp>(cs);
|
||||
auto vk = pghr13::serializeVerificationKey(&keypair.vk);
|
||||
r1cs_ppzksnark_keypair<ppT> keypair = r1cs_ppzksnark_generator<ppT>(cs);
|
||||
auto vk = serializeVerificationKey<Q, ppT, G1, G2>(&keypair.vk);
|
||||
|
||||
buffer_t vk_buf = create_buffer(vk);
|
||||
buffer_t pk_buf = create_buffer(keypair.pk);
|
||||
buffer_t vk_buf = createBuffer(vk);
|
||||
buffer_t pk_buf = createBuffer(keypair.pk);
|
||||
|
||||
setup_result_t result(vk_buf, pk_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
proof_result_t pghr13_generate_proof(buffer_t* pk_buf, const uint8_t* public_inputs, int32_t public_inputs_length, const uint8_t* private_inputs, int32_t private_inputs_length)
|
||||
template <mp_size_t Q, mp_size_t R, typename ppT, typename G1, typename G2>
|
||||
proof_result_t generateProof(buffer_t* pk_buf, const uint8_t* public_inputs, int32_t public_inputs_length, const uint8_t* private_inputs, int32_t private_inputs_length)
|
||||
{
|
||||
libff::inhibit_profiling_info = true;
|
||||
libff::inhibit_profiling_counters = true;
|
||||
|
||||
// initialize curve parameters
|
||||
libff::alt_bn128_pp::init_public_params();
|
||||
ppT::init_public_params();
|
||||
|
||||
r1cs_ppzksnark_proving_key<libff::alt_bn128_pp> proving_key;
|
||||
from_buffer<r1cs_ppzksnark_proving_key<libff::alt_bn128_pp>>(pk_buf, proving_key);
|
||||
r1cs_ppzksnark_proving_key<ppT> proving_key;
|
||||
fromBuffer<r1cs_ppzksnark_proving_key<ppT>>(pk_buf, proving_key);
|
||||
|
||||
// assign variables based on witness values, excludes ~one
|
||||
r1cs_variable_assignment<libff::Fr<libff::alt_bn128_pp>> full_variable_assignment;
|
||||
r1cs_variable_assignment<libff::Fr<ppT>> full_variable_assignment;
|
||||
for (int i = 1; i < public_inputs_length; i++) {
|
||||
full_variable_assignment.push_back(libff::Fr<libff::alt_bn128_pp>(libsnarkBigintFromBytes(public_inputs + i * 32)));
|
||||
full_variable_assignment.push_back(libff::Fr<ppT>(libsnarkBigintFromBytes<R>(public_inputs + (i * R * sizeof(mp_limb_t)))));
|
||||
}
|
||||
for (int i = 0; i < private_inputs_length; i++) {
|
||||
full_variable_assignment.push_back(libff::Fr<libff::alt_bn128_pp>(libsnarkBigintFromBytes(private_inputs + i * 32)));
|
||||
full_variable_assignment.push_back(libff::Fr<ppT>(libsnarkBigintFromBytes<R>(private_inputs + (i * R * sizeof(mp_limb_t)))));
|
||||
}
|
||||
|
||||
// split up variables into primary and auxiliary inputs. Does *NOT* include the constant 1
|
||||
// Public variables belong to primary input, private variables are auxiliary input.
|
||||
r1cs_primary_input<libff::Fr<libff::alt_bn128_pp>> primary_input(full_variable_assignment.begin(), full_variable_assignment.begin() + public_inputs_length - 1);
|
||||
r1cs_primary_input<libff::Fr<libff::alt_bn128_pp>> auxiliary_input(full_variable_assignment.begin() + public_inputs_length - 1, full_variable_assignment.end());
|
||||
r1cs_primary_input<libff::Fr<ppT>> primary_input(
|
||||
full_variable_assignment.begin(),
|
||||
full_variable_assignment.begin() + public_inputs_length - 1);
|
||||
|
||||
// for debugging
|
||||
// cout << "full variable assignment:" << endl << full_variable_assignment;
|
||||
// cout << "primary input:" << endl << primary_input;
|
||||
// cout << "auxiliary input:" << endl << auxiliary_input;
|
||||
r1cs_primary_input<libff::Fr<ppT>> auxiliary_input(
|
||||
full_variable_assignment.begin() + public_inputs_length - 1,
|
||||
full_variable_assignment.end());
|
||||
|
||||
// Proof Generation
|
||||
auto proof = r1cs_ppzksnark_prover<libff::alt_bn128_pp>(proving_key, primary_input, auxiliary_input);
|
||||
auto proof_json = pghr13::serializeProof(&proof, public_inputs, public_inputs_length);
|
||||
r1cs_ppzksnark_proof<ppT> proof = r1cs_ppzksnark_prover<ppT>(proving_key, primary_input, auxiliary_input);
|
||||
std::string json = serializeProof<Q, R, ppT, G1, G2>(&proof, public_inputs, public_inputs_length);
|
||||
|
||||
buffer_t proof_buf = create_buffer(proof_json);
|
||||
buffer_t proof_buf = createBuffer(json);
|
||||
proof_result_t result(proof_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool pghr13_verify(buffer_t* vk_buf, buffer_t* proof_buf, const uint8_t* public_inputs, int32_t public_inputs_length)
|
||||
template <mp_size_t R, typename ppT>
|
||||
bool verify(buffer_t* vk_buf, buffer_t* proof_buf, const uint8_t* public_inputs, int32_t public_inputs_length)
|
||||
{
|
||||
libff::inhibit_profiling_info = true;
|
||||
libff::inhibit_profiling_counters = true;
|
||||
|
||||
// initialize curve parameters
|
||||
libff::alt_bn128_pp::init_public_params();
|
||||
ppT::init_public_params();
|
||||
|
||||
r1cs_ppzksnark_verification_key<libff::alt_bn128_pp> vk;
|
||||
r1cs_ppzksnark_proof<libff::alt_bn128_pp> proof;
|
||||
r1cs_ppzksnark_verification_key<ppT> vk;
|
||||
r1cs_ppzksnark_proof<ppT> proof;
|
||||
|
||||
from_buffer<r1cs_ppzksnark_verification_key<libff::alt_bn128_pp>>(vk_buf, vk);
|
||||
from_buffer<r1cs_ppzksnark_proof<libff::alt_bn128_pp>>(proof_buf, proof);
|
||||
fromBuffer<r1cs_ppzksnark_verification_key<ppT>>(vk_buf, vk);
|
||||
fromBuffer<r1cs_ppzksnark_proof<ppT>>(proof_buf, proof);
|
||||
|
||||
r1cs_primary_input<libff::Fr<libff::alt_bn128_pp>> primary_input;
|
||||
r1cs_primary_input<libff::Fr<ppT>> primary_input;
|
||||
for (int i = 0; i < public_inputs_length; i++) {
|
||||
primary_input.push_back(libff::Fr<libff::alt_bn128_pp>(libsnarkBigintFromBytes(public_inputs + i * 32)));
|
||||
primary_input.push_back(libff::Fr<ppT>(libsnarkBigintFromBytes<R>(public_inputs + (i * R * sizeof(mp_limb_t)))));
|
||||
}
|
||||
|
||||
return r1cs_ppzksnark_verifier_strong_IC<libff::alt_bn128_pp>(vk, primary_input, proof);
|
||||
return r1cs_ppzksnark_verifier_strong_IC<ppT>(vk, primary_input, proof);
|
||||
}
|
||||
}
|
||||
|
||||
setup_result_t pghr13_bn128_setup(const uint8_t* a, const uint8_t* b, const uint8_t* c, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs)
|
||||
{
|
||||
return pghr13::setup<libff::alt_bn128_q_limbs,
|
||||
libff::alt_bn128_r_limbs,
|
||||
libff::alt_bn128_pp,
|
||||
libff::alt_bn128_G1,
|
||||
libff::alt_bn128_G2>(a, b, c, a_len, b_len, c_len, constraints, variables, inputs);
|
||||
}
|
||||
|
||||
proof_result_t pghr13_bn128_generate_proof(buffer_t* pk_buf,
|
||||
const uint8_t* public_inputs,
|
||||
int32_t public_inputs_length,
|
||||
const uint8_t* private_inputs,
|
||||
int32_t private_inputs_length)
|
||||
{
|
||||
return pghr13::generateProof<libff::alt_bn128_q_limbs,
|
||||
libff::alt_bn128_r_limbs,
|
||||
libff::alt_bn128_pp,
|
||||
libff::alt_bn128_G1,
|
||||
libff::alt_bn128_G2>(pk_buf,
|
||||
public_inputs,
|
||||
public_inputs_length,
|
||||
private_inputs,
|
||||
private_inputs_length);
|
||||
}
|
||||
|
||||
bool pghr13_bn128_verify(buffer_t* vk_buf, buffer_t* proof_buf, const uint8_t* public_inputs, int32_t public_inputs_length)
|
||||
{
|
||||
return pghr13::verify<libff::alt_bn128_r_limbs,
|
||||
libff::alt_bn128_pp>(vk_buf, proof_buf, public_inputs, public_inputs_length);
|
||||
}
|
|
@ -13,7 +13,7 @@ extern "C" {
|
|||
|
||||
#include "ffi.hpp"
|
||||
|
||||
setup_result_t pghr13_setup(
|
||||
setup_result_t pghr13_bn128_setup(
|
||||
const uint8_t* a,
|
||||
const uint8_t* b,
|
||||
const uint8_t* c,
|
||||
|
@ -24,14 +24,14 @@ setup_result_t pghr13_setup(
|
|||
int32_t variables,
|
||||
int32_t inputs);
|
||||
|
||||
proof_result_t pghr13_generate_proof(
|
||||
proof_result_t pghr13_bn128_generate_proof(
|
||||
buffer_t* pk_buf,
|
||||
const uint8_t* public_inputs,
|
||||
int32_t public_inputs_length,
|
||||
const uint8_t* private_inputs,
|
||||
int32_t private_inputs_length);
|
||||
|
||||
bool pghr13_verify(
|
||||
bool pghr13_bn128_verify(
|
||||
buffer_t* vk_buf,
|
||||
buffer_t* proof_buf,
|
||||
const uint8_t* public_inputs,
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
/**
|
||||
* @file util.cpp
|
||||
* @author Jacob Eberhardt <jacob.eberhardt@tu-berlin.de
|
||||
* @author Dennis Kuhnert <dennis.kuhnert@campus.tu-berlin.de>
|
||||
* @date 2017
|
||||
*/
|
||||
|
||||
#include "util.hpp"
|
||||
|
||||
// conversion byte[32] <-> libsnark bigint.
|
||||
libff::bigint<libff::alt_bn128_r_limbs> libsnarkBigintFromBytes(const uint8_t* _x)
|
||||
{
|
||||
libff::bigint<libff::alt_bn128_r_limbs> x;
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
for (unsigned j = 0; j < 8; j++) {
|
||||
x.data[3 - i] |= uint64_t(_x[i * 8 + j]) << (8 * (7 - j));
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
std::string toHexString(const std::string& in)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << std::setfill('0');
|
||||
for (unsigned char const& c : in) {
|
||||
out << std::hex << std::setw(2) << static_cast<unsigned int>(c);
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string HexStringFromLibsnarkBigint(libff::bigint<libff::alt_bn128_r_limbs> _x)
|
||||
{
|
||||
uint8_t x[32];
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
for (unsigned j = 0; j < 8; j++) {
|
||||
x[i * 8 + j] = uint8_t(uint64_t(_x.data[3 - i]) >> (8 * (7 - j)));
|
||||
}
|
||||
}
|
||||
std::string tmp((char*)x, 32);
|
||||
return toHexString(tmp);
|
||||
}
|
||||
|
||||
std::string outputInputAsHex(libff::bigint<libff::alt_bn128_r_limbs> _x)
|
||||
{
|
||||
return "\"0x" + HexStringFromLibsnarkBigint(_x) + "\"";
|
||||
}
|
||||
|
||||
std::string outputPointG1AffineAsHex(libff::alt_bn128_G1 _p)
|
||||
{
|
||||
libff::alt_bn128_G1 aff = _p;
|
||||
aff.to_affine_coordinates();
|
||||
return "0x" + HexStringFromLibsnarkBigint(aff.X.as_bigint()) + ", 0x" + HexStringFromLibsnarkBigint(aff.Y.as_bigint());
|
||||
}
|
||||
|
||||
std::string outputPointG1AffineAsHexJson(libff::alt_bn128_G1 _p)
|
||||
{
|
||||
libff::alt_bn128_G1 aff = _p;
|
||||
aff.to_affine_coordinates();
|
||||
return "[\"0x" + HexStringFromLibsnarkBigint(aff.X.as_bigint()) + "\", \"0x" + HexStringFromLibsnarkBigint(aff.Y.as_bigint()) + "\"]";
|
||||
}
|
||||
|
||||
std::string outputPointG2AffineAsHex(libff::alt_bn128_G2 _p)
|
||||
{
|
||||
libff::alt_bn128_G2 aff = _p;
|
||||
aff.to_affine_coordinates();
|
||||
return "[0x" + HexStringFromLibsnarkBigint(aff.X.c1.as_bigint()) + ", 0x" + HexStringFromLibsnarkBigint(aff.X.c0.as_bigint()) + "], [0x" + HexStringFromLibsnarkBigint(aff.Y.c1.as_bigint()) + ", 0x" + HexStringFromLibsnarkBigint(aff.Y.c0.as_bigint()) + "]";
|
||||
}
|
||||
|
||||
std::string outputPointG2AffineAsHexJson(libff::alt_bn128_G2 _p)
|
||||
{
|
||||
libff::alt_bn128_G2 aff = _p;
|
||||
aff.to_affine_coordinates();
|
||||
return "[[\"0x" + HexStringFromLibsnarkBigint(aff.X.c1.as_bigint()) + "\", \"0x" + HexStringFromLibsnarkBigint(aff.X.c0.as_bigint()) + "\"], [\"0x" + HexStringFromLibsnarkBigint(aff.Y.c1.as_bigint()) + "\", \"0x" + HexStringFromLibsnarkBigint(aff.Y.c0.as_bigint()) + "\"]]";
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
// contains definitions of alt_bn128 ec public parameters
|
||||
#include "ffi.hpp"
|
||||
#include "libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
libff::bigint<libff::alt_bn128_r_limbs> libsnarkBigintFromBytes(const uint8_t* _x);
|
||||
std::string toHexString(const std::string& s);
|
||||
std::string HexStringFromLibsnarkBigint(libff::bigint<libff::alt_bn128_r_limbs> _x);
|
||||
std::string outputInputAsHex(libff::bigint<libff::alt_bn128_r_limbs> _x);
|
||||
std::string outputPointG1AffineAsHex(libff::alt_bn128_G1 _p);
|
||||
std::string outputPointG1AffineAsHexJson(libff::alt_bn128_G1 _p);
|
||||
std::string outputPointG2AffineAsHex(libff::alt_bn128_G2 _p);
|
||||
std::string outputPointG2AffineAsHexJson(libff::alt_bn128_G2 _p);
|
||||
|
||||
template <typename T>
|
||||
inline void from_buffer(buffer_t* buffer, T& t)
|
||||
{
|
||||
std::string tmp((char*)buffer->data, buffer->length);
|
||||
std::stringstream ss(tmp);
|
||||
ss >> t;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::string serialize(const T& t)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << t;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline buffer_t create_buffer(T& t)
|
||||
{
|
||||
std::string tmp = serialize(t);
|
||||
size_t length = tmp.length();
|
||||
|
||||
buffer_t buffer;
|
||||
buffer.data = (uint8_t*)malloc(length);
|
||||
buffer.length = length;
|
||||
|
||||
tmp.copy(reinterpret_cast<char*>(buffer.data), buffer.length);
|
||||
return buffer;
|
||||
}
|
159
zokrates_core/lib/util.tcc
Normal file
159
zokrates_core/lib/util.tcc
Normal file
|
@ -0,0 +1,159 @@
|
|||
#pragma once
|
||||
|
||||
#include "ffi.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
template <int W>
|
||||
std::string encodeToHexString(const std::string& in)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << std::setfill('0');
|
||||
for (unsigned char const& c : in) {
|
||||
out << std::hex << std::setw(W) << static_cast<unsigned int>(c);
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
// conversion byte[N] <-> libsnark bigint.
|
||||
template <mp_size_t N>
|
||||
libff::bigint<N> libsnarkBigintFromBytes(const uint8_t* _x)
|
||||
{
|
||||
libff::bigint<N> x;
|
||||
for (unsigned i = 0; i < N; i++) {
|
||||
for (unsigned j = 0; j < 8; j++) {
|
||||
x.data[N - 1 - i] |= uint64_t(_x[i * 8 + j]) << (8 * (7 - j));
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
template <mp_size_t N>
|
||||
std::string hexStringFromLibsnarkBigint(libff::bigint<N> _x)
|
||||
{
|
||||
uint8_t x[N * sizeof(mp_limb_t)];
|
||||
for (unsigned i = 0; i < N; i++) {
|
||||
for (unsigned j = 0; j < 8; j++) {
|
||||
x[i * 8 + j] = uint8_t(uint64_t(_x.data[N - 1 - i]) >> (8 * (7 - j)));
|
||||
}
|
||||
}
|
||||
std::string tmp((char*)x, N * sizeof(mp_limb_t));
|
||||
return encodeToHexString<2>(tmp);
|
||||
}
|
||||
|
||||
template <mp_size_t Q>
|
||||
std::string outputInputAsHex(libff::bigint<Q> _x)
|
||||
{
|
||||
return "\"0x" + hexStringFromLibsnarkBigint<Q>(_x) + "\"";
|
||||
}
|
||||
|
||||
template <mp_size_t Q, typename G1>
|
||||
std::string outputPointG1AffineAsHexJson(G1 _p)
|
||||
{
|
||||
G1 aff = _p;
|
||||
aff.to_affine_coordinates();
|
||||
return "[\"0x" + hexStringFromLibsnarkBigint<Q>(aff.X.as_bigint()) + "\",\"0x" + hexStringFromLibsnarkBigint<Q>(aff.Y.as_bigint()) + "\"]";
|
||||
}
|
||||
|
||||
template <mp_size_t Q, typename G2>
|
||||
std::string outputPointG2AffineAsHexJson(G2 _p)
|
||||
{
|
||||
G2 aff = _p;
|
||||
aff.to_affine_coordinates();
|
||||
return "[[\"0x" + hexStringFromLibsnarkBigint<Q>(aff.X.c1.as_bigint()) + "\",\"0x" + hexStringFromLibsnarkBigint<Q>(aff.X.c0.as_bigint()) + "\"], [\"0x" + hexStringFromLibsnarkBigint<Q>(aff.Y.c1.as_bigint()) + "\", \"0x" + hexStringFromLibsnarkBigint<Q>(aff.Y.c0.as_bigint()) + "\"]]";
|
||||
}
|
||||
|
||||
template <template <typename ppT> class ConstraintSystem, mp_size_t R, typename ppT>
|
||||
ConstraintSystem<ppT> createConstraintSystem(const uint8_t* a,
|
||||
const uint8_t* b,
|
||||
const uint8_t* c,
|
||||
int32_t a_len,
|
||||
int32_t b_len,
|
||||
int32_t c_len,
|
||||
int32_t constraints,
|
||||
int32_t variables,
|
||||
int32_t inputs)
|
||||
{
|
||||
ConstraintSystem<ppT> cs;
|
||||
cs.primary_input_size = inputs;
|
||||
cs.auxiliary_input_size = variables - inputs - 1; // ~one not included
|
||||
|
||||
std::cout << "num variables: " << variables << std::endl;
|
||||
std::cout << "num constraints: " << constraints << std::endl;
|
||||
std::cout << "num inputs: " << inputs << std::endl;
|
||||
|
||||
struct VariableValueMapping {
|
||||
int constraint_id;
|
||||
int variable_id;
|
||||
uint8_t variable_value[R * sizeof(mp_limb_t)];
|
||||
};
|
||||
|
||||
const VariableValueMapping* a_vvmap = (VariableValueMapping*)a;
|
||||
const VariableValueMapping* b_vvmap = (VariableValueMapping*)b;
|
||||
const VariableValueMapping* c_vvmap = (VariableValueMapping*)c;
|
||||
|
||||
int a_id = 0;
|
||||
int b_id = 0;
|
||||
int c_id = 0;
|
||||
|
||||
for (int row = 0; row < constraints; row++) {
|
||||
linear_combination<libff::Fr<ppT>> lin_comb_a, lin_comb_b, lin_comb_c;
|
||||
while (a_id < a_len && a_vvmap[a_id].constraint_id == row) {
|
||||
libff::bigint<R> value = libsnarkBigintFromBytes<R>(a_vvmap[a_id].variable_value);
|
||||
if (!value.is_zero()) {
|
||||
lin_comb_a.add_term(a_vvmap[a_id].variable_id, value);
|
||||
}
|
||||
a_id++;
|
||||
}
|
||||
while (b_id < b_len && b_vvmap[b_id].constraint_id == row) {
|
||||
libff::bigint<R> value = libsnarkBigintFromBytes<R>(b_vvmap[b_id].variable_value);
|
||||
if (!value.is_zero()) {
|
||||
lin_comb_b.add_term(b_vvmap[b_id].variable_id, value);
|
||||
}
|
||||
b_id++;
|
||||
}
|
||||
while (c_id < c_len && c_vvmap[c_id].constraint_id == row) {
|
||||
libff::bigint<R> value = libsnarkBigintFromBytes<R>(c_vvmap[c_id].variable_value);
|
||||
if (!value.is_zero()) {
|
||||
lin_comb_c.add_term(c_vvmap[c_id].variable_id, value);
|
||||
}
|
||||
c_id++;
|
||||
}
|
||||
cs.add_constraint(r1cs_constraint<libff::Fr<ppT>>(lin_comb_a, lin_comb_b, lin_comb_c));
|
||||
}
|
||||
return cs;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void fromBuffer(buffer_t* buffer, T& t)
|
||||
{
|
||||
std::string tmp((char*)buffer->data, buffer->length);
|
||||
std::stringstream ss(tmp);
|
||||
ss >> t;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::string serialize(const T& t)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << t;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline buffer_t createBuffer(T& t)
|
||||
{
|
||||
std::string tmp = serialize(t);
|
||||
size_t length = tmp.length();
|
||||
|
||||
buffer_t buffer;
|
||||
buffer.data = (uint8_t*)malloc(length);
|
||||
buffer.length = length;
|
||||
|
||||
tmp.copy(reinterpret_cast<char*>(buffer.data), buffer.length);
|
||||
return buffer;
|
||||
}
|
|
@ -9,7 +9,6 @@ use imports::{self, Importer};
|
|||
use ir;
|
||||
use macros;
|
||||
use macros::process_macros;
|
||||
use optimizer::Optimize;
|
||||
use semantics::{self, Checker};
|
||||
use static_analysis::Analyse;
|
||||
use std::collections::HashMap;
|
||||
|
@ -141,12 +140,29 @@ impl fmt::Display for CompileErrorInner {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CompileConfig {
|
||||
is_release: bool,
|
||||
}
|
||||
|
||||
impl CompileConfig {
|
||||
pub fn with_is_release(mut self, is_release: bool) -> Self {
|
||||
self.is_release = is_release;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn is_release(&self) -> bool {
|
||||
self.is_release
|
||||
}
|
||||
}
|
||||
|
||||
type FilePath = PathBuf;
|
||||
|
||||
pub fn compile<T: Field, E: Into<imports::Error>>(
|
||||
source: String,
|
||||
location: FilePath,
|
||||
resolver: Option<&dyn Resolver<E>>,
|
||||
config: &CompileConfig,
|
||||
) -> Result<CompilationArtifacts<T>, CompileErrors> {
|
||||
let arena = Arena::new();
|
||||
|
||||
|
@ -162,7 +178,7 @@ pub fn compile<T: Field, E: Into<imports::Error>>(
|
|||
let ir_prog = ir::Prog::from(program_flattened);
|
||||
|
||||
// optimize
|
||||
let optimized_ir_prog = ir_prog.optimize();
|
||||
let optimized_ir_prog = ir_prog.optimize(config);
|
||||
|
||||
// analyse (check for unused constraints)
|
||||
let optimized_ir_prog = optimized_ir_prog.analyse();
|
||||
|
@ -264,6 +280,7 @@ mod test {
|
|||
source,
|
||||
"./path/to/file".into(),
|
||||
None::<&dyn Resolver<io::Error>>,
|
||||
&CompileConfig::default(),
|
||||
);
|
||||
assert!(res.unwrap_err().0[0]
|
||||
.value()
|
||||
|
@ -282,6 +299,7 @@ mod test {
|
|||
source,
|
||||
"./path/to/file".into(),
|
||||
None::<&dyn Resolver<io::Error>>,
|
||||
&CompileConfig::default(),
|
||||
);
|
||||
assert!(res.is_ok());
|
||||
}
|
||||
|
@ -362,6 +380,7 @@ struct Bar { field a }
|
|||
main.to_string(),
|
||||
"main".into(),
|
||||
Some(&CustomResolver),
|
||||
&CompileConfig::default(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -13,18 +13,19 @@ use self::directive::DirectiveOptimizer;
|
|||
use self::duplicate::DuplicateOptimizer;
|
||||
use self::redefinition::RedefinitionOptimizer;
|
||||
use self::tautology::TautologyOptimizer;
|
||||
use compile::CompileConfig;
|
||||
|
||||
use crate::ir::Prog;
|
||||
use zokrates_field::Field;
|
||||
|
||||
pub trait Optimize {
|
||||
fn optimize(self) -> Self;
|
||||
}
|
||||
|
||||
impl<T: Field> Optimize for Prog<T> {
|
||||
fn optimize(self) -> Self {
|
||||
// remove redefinitions
|
||||
let r = RedefinitionOptimizer::optimize(self);
|
||||
impl<T: Field> Prog<T> {
|
||||
pub fn optimize(self, config: &CompileConfig) -> Self {
|
||||
let r = if config.is_release() {
|
||||
// remove redefinitions
|
||||
RedefinitionOptimizer::optimize(self)
|
||||
} else {
|
||||
self
|
||||
};
|
||||
// remove constraints that are always satisfied
|
||||
let r = TautologyOptimizer::optimize(r);
|
||||
// // deduplicate directives which take the same input
|
||||
|
|
|
@ -7,55 +7,73 @@ use regex::Regex;
|
|||
use zokrates_field::Field;
|
||||
|
||||
use crate::ir;
|
||||
use crate::proof_system::bn128::utils::bellman::Computation;
|
||||
use crate::proof_system::bn128::utils::bellman::{
|
||||
parse_fr, parse_g1, parse_g1_hex, parse_g2, parse_g2_hex,
|
||||
};
|
||||
use crate::proof_system::bn128::utils::parser::parse_vk;
|
||||
use crate::proof_system::bn128::utils::solidity::{
|
||||
use crate::proof_system::bellman::Computation;
|
||||
use crate::proof_system::bellman::{parse_fr, parse_g1, parse_g2};
|
||||
use crate::proof_system::solidity::{
|
||||
SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2,
|
||||
};
|
||||
use crate::proof_system::{ProofSystem, SetupKeypair};
|
||||
use proof_system::bn128::{G1PairingPoint, G2PairingPoint, Proof};
|
||||
use proof_system::SolidityAbi;
|
||||
use proof_system::{G1Affine, G2Affine, Proof, ProofSystem, SetupKeypair, SolidityAbi};
|
||||
|
||||
const G16_WARNING: &str = "WARNING: You are using the G16 scheme which is subject to malleability. See zokrates.github.io/reference/proving_schemes.html#g16-malleability for implications.";
|
||||
|
||||
pub struct G16 {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct G16ProofPoints {
|
||||
a: G1PairingPoint,
|
||||
b: G2PairingPoint,
|
||||
c: G1PairingPoint,
|
||||
pub struct ProofPoints {
|
||||
a: G1Affine,
|
||||
b: G2Affine,
|
||||
c: G1Affine,
|
||||
}
|
||||
|
||||
impl G16ProofPoints {
|
||||
fn new(a: G1PairingPoint, b: G2PairingPoint, c: G1PairingPoint) -> Self {
|
||||
G16ProofPoints { a, b, c }
|
||||
}
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct VerificationKey {
|
||||
alpha: G1Affine,
|
||||
beta: G2Affine,
|
||||
gamma: G2Affine,
|
||||
delta: G2Affine,
|
||||
gamma_abc: Vec<G1Affine>,
|
||||
raw: String,
|
||||
}
|
||||
|
||||
impl<T: Field> ProofSystem<T> for G16 {
|
||||
fn setup(program: ir::Prog<T>) -> SetupKeypair {
|
||||
type VerificationKey = VerificationKey;
|
||||
type ProofPoints = ProofPoints;
|
||||
|
||||
fn setup(program: ir::Prog<T>) -> SetupKeypair<VerificationKey> {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
std::env::set_var("BELLMAN_VERBOSE", "0");
|
||||
println!("{}", G16_WARNING);
|
||||
|
||||
let parameters = Computation::without_witness(program).setup();
|
||||
let vk = serialize_vk::<T>(¶meters.vk);
|
||||
|
||||
let mut pk: Vec<u8> = Vec::new();
|
||||
parameters.write(&mut pk).unwrap();
|
||||
let mut vk_raw: Vec<u8> = Vec::new();
|
||||
|
||||
SetupKeypair::from(vk, pk)
|
||||
parameters.write(&mut pk).unwrap();
|
||||
parameters.vk.write(&mut vk_raw).unwrap();
|
||||
|
||||
let vk = VerificationKey {
|
||||
alpha: parse_g1::<T>(¶meters.vk.alpha_g1),
|
||||
beta: parse_g2::<T>(¶meters.vk.beta_g2),
|
||||
gamma: parse_g2::<T>(¶meters.vk.gamma_g2),
|
||||
delta: parse_g2::<T>(¶meters.vk.delta_g2),
|
||||
gamma_abc: parameters
|
||||
.vk
|
||||
.ic
|
||||
.iter()
|
||||
.map(|g1| parse_g1::<T>(g1))
|
||||
.collect(),
|
||||
raw: hex::encode(vk_raw),
|
||||
};
|
||||
|
||||
SetupKeypair::new(vk, pk)
|
||||
}
|
||||
|
||||
fn generate_proof(
|
||||
program: ir::Prog<T>,
|
||||
witness: ir::Witness<T>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> String {
|
||||
) -> Proof<ProofPoints> {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
std::env::set_var("BELLMAN_VERBOSE", "0");
|
||||
|
||||
|
@ -65,11 +83,12 @@ impl<T: Field> ProofSystem<T> for G16 {
|
|||
let params = Parameters::read(proving_key.as_slice(), true).unwrap();
|
||||
|
||||
let proof = computation.clone().prove(¶ms);
|
||||
let proof_points = G16ProofPoints::new(
|
||||
parse_g1::<T>(&proof.a),
|
||||
parse_g2::<T>(&proof.b),
|
||||
parse_g1::<T>(&proof.c),
|
||||
);
|
||||
|
||||
let proof_points = ProofPoints {
|
||||
a: parse_g1::<T>(&proof.a),
|
||||
b: parse_g2::<T>(&proof.b),
|
||||
c: parse_g1::<T>(&proof.c),
|
||||
};
|
||||
|
||||
let inputs = computation
|
||||
.public_inputs_values()
|
||||
|
@ -80,11 +99,10 @@ impl<T: Field> ProofSystem<T> for G16 {
|
|||
let mut raw: Vec<u8> = Vec::new();
|
||||
proof.write(&mut raw).unwrap();
|
||||
|
||||
Proof::<G16ProofPoints>::new(proof_points, inputs, hex::encode(&raw)).to_json_pretty()
|
||||
Proof::<ProofPoints>::new(proof_points, inputs, hex::encode(&raw))
|
||||
}
|
||||
|
||||
fn export_solidity_verifier(vk: String, abi: SolidityAbi) -> String {
|
||||
let vk_map = parse_vk(vk).unwrap();
|
||||
fn export_solidity_verifier(vk: VerificationKey, abi: SolidityAbi) -> String {
|
||||
let (mut template_text, solidity_pairing_lib) = match abi {
|
||||
SolidityAbi::V1 => (
|
||||
String::from(CONTRACT_TEMPLATE),
|
||||
|
@ -101,14 +119,23 @@ impl<T: Field> ProofSystem<T> for G16 {
|
|||
let vk_gamma_abc_repeat_regex = Regex::new(r#"(<%vk_gamma_abc_pts%>)"#).unwrap();
|
||||
let vk_input_len_regex = Regex::new(r#"(<%vk_input_length%>)"#).unwrap();
|
||||
|
||||
let keys = vec!["vk.alpha", "vk.beta", "vk.gamma", "vk.delta"];
|
||||
for key in keys.iter() {
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk_map.get(*key).unwrap().as_str())
|
||||
.into_owned();
|
||||
}
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.alpha.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
let gamma_abc_count: usize = vk_map.get("vk.gamma_abc.len()").unwrap().parse().unwrap();
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.beta.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.gamma.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.delta.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
let gamma_abc_count: usize = vk.gamma_abc.len();
|
||||
template_text = vk_gamma_abc_len_regex
|
||||
.replace(
|
||||
template_text.as_str(),
|
||||
|
@ -124,19 +151,16 @@ impl<T: Field> ProofSystem<T> for G16 {
|
|||
.into_owned();
|
||||
|
||||
let mut gamma_abc_repeat_text = String::new();
|
||||
for x in 0..gamma_abc_count {
|
||||
for (i, g1) in vk.gamma_abc.iter().enumerate() {
|
||||
gamma_abc_repeat_text.push_str(
|
||||
format!(
|
||||
"vk.gamma_abc[{}] = Pairing.G1Point({});",
|
||||
x,
|
||||
vk_map
|
||||
.get(format!("vk.gamma_abc[{}]", x).as_str())
|
||||
.unwrap()
|
||||
.as_str()
|
||||
i,
|
||||
g1.to_string().as_str()
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
if x < gamma_abc_count - 1 {
|
||||
if i < gamma_abc_count - 1 {
|
||||
gamma_abc_repeat_text.push_str("\n ");
|
||||
}
|
||||
}
|
||||
|
@ -154,20 +178,18 @@ impl<T: Field> ProofSystem<T> for G16 {
|
|||
)
|
||||
}
|
||||
|
||||
fn verify(vk: String, proof: String) -> bool {
|
||||
let map = parse_vk(vk).unwrap();
|
||||
let vk_raw = hex::decode(map.get("vk.raw").unwrap()).unwrap();
|
||||
fn verify(vk: VerificationKey, proof: Proof<ProofPoints>) -> bool {
|
||||
let vk_raw = hex::decode(vk.raw.clone()).unwrap();
|
||||
let proof_raw = hex::decode(proof.raw.clone()).unwrap();
|
||||
|
||||
let vk: VerifyingKey<T::BellmanEngine> = VerifyingKey::read(vk_raw.as_slice()).unwrap();
|
||||
|
||||
let pvk: PreparedVerifyingKey<T::BellmanEngine> = prepare_verifying_key(&vk);
|
||||
|
||||
let g16_proof = Proof::<G16ProofPoints>::from_str(proof.as_str());
|
||||
let bellman_proof: BellmanProof<T::BellmanEngine> =
|
||||
BellmanProof::read(proof_raw.as_slice()).unwrap();
|
||||
|
||||
let raw_proof = hex::decode(g16_proof.raw).unwrap();
|
||||
let proof: BellmanProof<T::BellmanEngine> =
|
||||
BellmanProof::read(raw_proof.as_slice()).unwrap();
|
||||
|
||||
let public_inputs: Vec<_> = g16_proof
|
||||
let public_inputs: Vec<_> = proof
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|s| {
|
||||
|
@ -177,51 +199,10 @@ impl<T: Field> ProofSystem<T> for G16 {
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
verify_proof(&pvk, &proof, &public_inputs).unwrap()
|
||||
verify_proof(&pvk, &bellman_proof, &public_inputs).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_vk<T: Field>(vk: &VerifyingKey<T::BellmanEngine>) -> String {
|
||||
let mut writer = csv::WriterBuilder::new()
|
||||
.delimiter(b'=')
|
||||
.from_writer(vec![]);
|
||||
|
||||
writer
|
||||
.write_record(&["vk.alpha", parse_g1_hex::<T>(&vk.alpha_g1).as_str()])
|
||||
.unwrap();
|
||||
writer
|
||||
.write_record(&["vk.beta", parse_g2_hex::<T>(&vk.beta_g2).as_str()])
|
||||
.unwrap();
|
||||
writer
|
||||
.write_record(&["vk.gamma", parse_g2_hex::<T>(&vk.gamma_g2).as_str()])
|
||||
.unwrap();
|
||||
writer
|
||||
.write_record(&["vk.delta", parse_g2_hex::<T>(&vk.delta_g2).as_str()])
|
||||
.unwrap();
|
||||
writer
|
||||
.write_record(&["vk.gamma_abc.len()", vk.ic.len().to_string().as_str()])
|
||||
.unwrap();
|
||||
|
||||
let mut e = vk.ic.iter().enumerate();
|
||||
while let Some((i, x)) = e.next() {
|
||||
writer
|
||||
.write_record(&[
|
||||
format!("vk.gamma_abc[{}]", i).as_str(),
|
||||
parse_g1_hex::<T>(x).as_str(),
|
||||
])
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
let mut raw: Vec<u8> = Vec::new();
|
||||
vk.write(&mut raw).unwrap();
|
||||
|
||||
writer
|
||||
.write_record(&["vk.raw", hex::encode(&raw).as_str()])
|
||||
.unwrap();
|
||||
|
||||
String::from_utf8(writer.into_inner().unwrap()).unwrap()
|
||||
}
|
||||
|
||||
const CONTRACT_TEMPLATE_V2: &str = r#"
|
||||
contract Verifier {
|
||||
using Pairing for *;
|
|
@ -1,3 +1,5 @@
|
|||
pub mod groth16;
|
||||
|
||||
extern crate rand;
|
||||
|
||||
use crate::ir::{CanonicalLinComb, Prog, Statement, Witness};
|
||||
|
@ -209,6 +211,7 @@ mod parse {
|
|||
use lazy_static::lazy_static;
|
||||
|
||||
use super::*;
|
||||
use proof_system::{G1Affine, G2Affine};
|
||||
use regex::Regex;
|
||||
|
||||
lazy_static! {
|
||||
|
@ -227,10 +230,10 @@ mod parse {
|
|||
|
||||
pub fn parse_g1<T: Field>(
|
||||
e: &<T::BellmanEngine as bellman::pairing::Engine>::G1Affine,
|
||||
) -> (String, String) {
|
||||
) -> G1Affine {
|
||||
let raw_e = e.to_string();
|
||||
let captures = G1_REGEX.captures(&raw_e).unwrap();
|
||||
(
|
||||
G1Affine(
|
||||
captures.name(&"x").unwrap().as_str().to_string(),
|
||||
captures.name(&"y").unwrap().as_str().to_string(),
|
||||
)
|
||||
|
@ -238,15 +241,15 @@ mod parse {
|
|||
|
||||
pub fn parse_g2<T: Field>(
|
||||
e: &<T::BellmanEngine as bellman::pairing::Engine>::G2Affine,
|
||||
) -> ((String, String), (String, String)) {
|
||||
) -> G2Affine {
|
||||
let raw_e = e.to_string();
|
||||
let captures = G2_REGEX.captures(&raw_e).unwrap();
|
||||
(
|
||||
(
|
||||
G2Affine(
|
||||
G1Affine(
|
||||
captures.name(&"x1").unwrap().as_str().to_string(),
|
||||
captures.name(&"x0").unwrap().as_str().to_string(),
|
||||
),
|
||||
(
|
||||
G1Affine(
|
||||
captures.name(&"y1").unwrap().as_str().to_string(),
|
||||
captures.name(&"y0").unwrap().as_str().to_string(),
|
||||
),
|
||||
|
@ -258,26 +261,6 @@ mod parse {
|
|||
let captures = FR_REGEX.captures(&raw_e).unwrap();
|
||||
captures.name(&"x").unwrap().as_str().to_string()
|
||||
}
|
||||
|
||||
pub fn parse_g1_hex<T: Field>(
|
||||
e: &<T::BellmanEngine as bellman::pairing::Engine>::G1Affine,
|
||||
) -> String {
|
||||
let parsed = parse_g1::<T>(e);
|
||||
format!("{}, {}", parsed.0, parsed.1)
|
||||
}
|
||||
|
||||
pub fn parse_g2_hex<T: Field>(
|
||||
e: &<T::BellmanEngine as bellman::pairing::Engine>::G2Affine,
|
||||
) -> String {
|
||||
let parsed = parse_g2::<T>(e);
|
||||
format!(
|
||||
"[{}, {}], [{}, {}]",
|
||||
(parsed.0).0,
|
||||
(parsed.0).1,
|
||||
(parsed.1).0,
|
||||
(parsed.1).1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
|
@ -1,36 +0,0 @@
|
|||
mod g16;
|
||||
#[cfg(feature = "libsnark")]
|
||||
mod gm17;
|
||||
#[cfg(feature = "libsnark")]
|
||||
mod pghr13;
|
||||
|
||||
mod utils;
|
||||
|
||||
pub use self::g16::G16;
|
||||
#[cfg(feature = "libsnark")]
|
||||
pub use self::gm17::GM17;
|
||||
#[cfg(feature = "libsnark")]
|
||||
pub use self::pghr13::PGHR13;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
type G1PairingPoint = (String, String);
|
||||
type G2PairingPoint = (G1PairingPoint, G1PairingPoint);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Proof<T> {
|
||||
proof: T,
|
||||
inputs: Vec<String>,
|
||||
raw: String,
|
||||
}
|
||||
|
||||
impl<'a, T: Serialize + Deserialize<'a>> Proof<T> {
|
||||
fn new(proof: T, inputs: Vec<String>, raw: String) -> Self {
|
||||
Proof { proof, inputs, raw }
|
||||
}
|
||||
fn from_str(proof: &'a str) -> Proof<T> {
|
||||
serde_json::from_str(proof).expect("Invalid proof json format")
|
||||
}
|
||||
fn to_json_pretty(&self) -> String {
|
||||
serde_json::to_string_pretty(self).unwrap()
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
pub mod bellman;
|
||||
#[cfg(feature = "libsnark")]
|
||||
pub mod ffi;
|
||||
#[cfg(feature = "libsnark")]
|
||||
pub mod libsnark;
|
||||
pub mod parser;
|
||||
pub mod solidity;
|
|
@ -1,60 +0,0 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
pub fn parse_vk(vk: String) -> Result<HashMap<String, String>, csv::Error> {
|
||||
let mut reader = csv::ReaderBuilder::new()
|
||||
.delimiter(b'=')
|
||||
.has_headers(false)
|
||||
.trim(csv::Trim::All)
|
||||
.flexible(false)
|
||||
.from_reader(vk.trim().as_bytes());
|
||||
|
||||
let mut map = HashMap::new();
|
||||
let mut iterator = reader.deserialize::<(String, String)>();
|
||||
|
||||
while let Some(r) = iterator.next() {
|
||||
let r = r?;
|
||||
map.insert(r.0, r.1);
|
||||
}
|
||||
Ok(map)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use proof_system::bn128::utils::parser::parse_vk;
|
||||
|
||||
#[test]
|
||||
fn parse_valid_input() {
|
||||
let example: String = r#"
|
||||
a = 1
|
||||
b = 2
|
||||
"#
|
||||
.to_string();
|
||||
|
||||
let map = parse_vk(example).unwrap();
|
||||
assert_eq!("1", map.get("a").unwrap());
|
||||
assert_eq!("2", map.get("b").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn panic_on_invalid_delimiter() {
|
||||
parse_vk("a , 1".to_string()).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn panic_on_unequal_lengths() {
|
||||
let example: String = r#"
|
||||
a = 1
|
||||
b = 2 = 3
|
||||
"#
|
||||
.to_string();
|
||||
parse_vk(example).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_empty() {
|
||||
let map = parse_vk(String::new()).unwrap();
|
||||
assert!(map.is_empty());
|
||||
}
|
||||
}
|
|
@ -1,14 +1,10 @@
|
|||
use ir;
|
||||
use proof_system::bn128::utils::ffi::{Buffer, ProofResult, SetupResult};
|
||||
use proof_system::bn128::utils::libsnark::{
|
||||
prepare_generate_proof, prepare_public_inputs, prepare_setup,
|
||||
};
|
||||
use proof_system::bn128::utils::parser::parse_vk;
|
||||
use proof_system::bn128::utils::solidity::{
|
||||
use proof_system::libsnark::ffi::{Buffer, ProofResult, SetupResult};
|
||||
use proof_system::libsnark::{prepare_generate_proof, prepare_public_inputs, prepare_setup};
|
||||
use proof_system::solidity::{
|
||||
SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2,
|
||||
};
|
||||
use proof_system::bn128::{G1PairingPoint, G2PairingPoint, Proof};
|
||||
use proof_system::{ProofSystem, SetupKeypair, SolidityAbi};
|
||||
use proof_system::{G1Affine, G2Affine, Proof, ProofSystem, SetupKeypair, SolidityAbi};
|
||||
use regex::Regex;
|
||||
|
||||
use zokrates_field::Bn128Field;
|
||||
|
@ -17,14 +13,25 @@ use zokrates_field::Field;
|
|||
pub struct GM17 {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct GM17ProofPoints {
|
||||
a: G1PairingPoint,
|
||||
b: G2PairingPoint,
|
||||
c: G1PairingPoint,
|
||||
pub struct VerificationKey {
|
||||
h: G2Affine,
|
||||
g_alpha: G1Affine,
|
||||
h_beta: G2Affine,
|
||||
g_gamma: G1Affine,
|
||||
h_gamma: G2Affine,
|
||||
query: Vec<G1Affine>,
|
||||
raw: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ProofPoints {
|
||||
a: G1Affine,
|
||||
b: G2Affine,
|
||||
c: G1Affine,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn gm17_setup(
|
||||
fn gm17_bn128_setup(
|
||||
a: *const u8,
|
||||
b: *const u8,
|
||||
c: *const u8,
|
||||
|
@ -36,7 +43,7 @@ extern "C" {
|
|||
inputs: i32,
|
||||
) -> SetupResult;
|
||||
|
||||
fn gm17_generate_proof(
|
||||
fn gm17_bn128_generate_proof(
|
||||
pk_buf: *mut Buffer,
|
||||
public_query_inputs: *const u8,
|
||||
public_query_inputs_length: i32,
|
||||
|
@ -44,7 +51,7 @@ extern "C" {
|
|||
private_inputs_length: i32,
|
||||
) -> ProofResult;
|
||||
|
||||
fn gm17_verify(
|
||||
fn gm17_bn128_verify(
|
||||
vk_buf: *mut Buffer,
|
||||
proof_buf: *mut Buffer,
|
||||
public_inputs: *const u8,
|
||||
|
@ -53,12 +60,15 @@ extern "C" {
|
|||
}
|
||||
|
||||
impl ProofSystem<Bn128Field> for GM17 {
|
||||
fn setup(program: ir::Prog<Bn128Field>) -> SetupKeypair {
|
||||
type VerificationKey = VerificationKey;
|
||||
type ProofPoints = ProofPoints;
|
||||
|
||||
fn setup(program: ir::Prog<Bn128Field>) -> SetupKeypair<VerificationKey> {
|
||||
let (a_arr, b_arr, c_arr, a_vec, b_vec, c_vec, num_constraints, num_variables, num_inputs) =
|
||||
prepare_setup(program);
|
||||
|
||||
let keypair = unsafe {
|
||||
let result: SetupResult = gm17_setup(
|
||||
let result: SetupResult = gm17_bn128_setup(
|
||||
a_arr.as_ptr(),
|
||||
b_arr.as_ptr(),
|
||||
c_arr.as_ptr(),
|
||||
|
@ -83,21 +93,22 @@ impl ProofSystem<Bn128Field> for GM17 {
|
|||
(vk, pk)
|
||||
};
|
||||
|
||||
SetupKeypair::from(String::from_utf8(keypair.0).unwrap(), keypair.1)
|
||||
let vk = serde_json::from_str(String::from_utf8(keypair.0).unwrap().as_str()).unwrap();
|
||||
SetupKeypair::new(vk, keypair.1)
|
||||
}
|
||||
|
||||
fn generate_proof(
|
||||
program: ir::Prog<Bn128Field>,
|
||||
witness: ir::Witness<Bn128Field>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> String {
|
||||
) -> Proof<ProofPoints> {
|
||||
let (public_inputs_arr, public_inputs_length, private_inputs_arr, private_inputs_length) =
|
||||
prepare_generate_proof(program, witness);
|
||||
|
||||
let mut pk_buffer = Buffer::from_vec(&proving_key);
|
||||
|
||||
let proof = unsafe {
|
||||
let result = gm17_generate_proof(
|
||||
let result = gm17_bn128_generate_proof(
|
||||
&mut pk_buffer as *mut _,
|
||||
public_inputs_arr[0].as_ptr(),
|
||||
public_inputs_length as i32,
|
||||
|
@ -118,11 +129,10 @@ impl ProofSystem<Bn128Field> for GM17 {
|
|||
proof
|
||||
};
|
||||
|
||||
String::from_utf8(proof).unwrap()
|
||||
serde_json::from_str(String::from_utf8(proof).unwrap().as_str()).unwrap()
|
||||
}
|
||||
|
||||
fn export_solidity_verifier(vk: String, abi: SolidityAbi) -> String {
|
||||
let vk_map = parse_vk(vk).unwrap();
|
||||
fn export_solidity_verifier(vk: VerificationKey, abi: SolidityAbi) -> String {
|
||||
let (mut template_text, solidity_pairing_lib) = match abi {
|
||||
SolidityAbi::V1 => (
|
||||
String::from(CONTRACT_TEMPLATE),
|
||||
|
@ -140,21 +150,27 @@ impl ProofSystem<Bn128Field> for GM17 {
|
|||
let vk_query_repeat_regex = Regex::new(r#"(<%vk_query_pts%>)"#).unwrap();
|
||||
let vk_input_len_regex = Regex::new(r#"(<%vk_input_length%>)"#).unwrap();
|
||||
|
||||
let keys = vec![
|
||||
"vk.h",
|
||||
"vk.g_alpha",
|
||||
"vk.h_beta",
|
||||
"vk.g_gamma",
|
||||
"vk.h_gamma",
|
||||
];
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.h.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
for key in keys.iter() {
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk_map.get(*key).unwrap().as_str())
|
||||
.into_owned();
|
||||
}
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.g_alpha.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
let query_count: usize = vk_map.get("vk.query.len()").unwrap().parse().unwrap();
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.h_beta.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.g_gamma.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.h_gamma.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
let query_count: usize = vk.query.len();
|
||||
template_text = vk_query_len_regex
|
||||
.replace(template_text.as_str(), format!("{}", query_count).as_str())
|
||||
.into_owned();
|
||||
|
@ -167,19 +183,16 @@ impl ProofSystem<Bn128Field> for GM17 {
|
|||
.into_owned();
|
||||
|
||||
let mut query_repeat_text = String::new();
|
||||
for x in 0..query_count {
|
||||
for (i, g1) in vk.query.iter().enumerate() {
|
||||
query_repeat_text.push_str(
|
||||
format!(
|
||||
"vk.query[{}] = Pairing.G1Point({});",
|
||||
x,
|
||||
vk_map
|
||||
.get(format!("vk.query[{}]", x).as_str())
|
||||
.unwrap()
|
||||
.as_str()
|
||||
i,
|
||||
g1.to_string().as_str()
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
if x < query_count - 1 {
|
||||
if i < query_count - 1 {
|
||||
query_repeat_text.push_str("\n ");
|
||||
}
|
||||
}
|
||||
|
@ -197,12 +210,9 @@ impl ProofSystem<Bn128Field> for GM17 {
|
|||
)
|
||||
}
|
||||
|
||||
fn verify(vk: String, proof: String) -> bool {
|
||||
let map = parse_vk(vk).unwrap();
|
||||
let vk_raw = hex::decode(map.get("vk.raw").unwrap()).unwrap();
|
||||
|
||||
let proof = Proof::<GM17ProofPoints>::from_str(proof.as_str());
|
||||
let proof_raw = hex::decode(proof.raw).unwrap();
|
||||
fn verify(vk: VerificationKey, proof: Proof<ProofPoints>) -> bool {
|
||||
let vk_raw = hex::decode(vk.raw.clone()).unwrap();
|
||||
let proof_raw = hex::decode(proof.raw.clone()).unwrap();
|
||||
|
||||
let public_inputs: Vec<_> = proof
|
||||
.inputs
|
||||
|
@ -219,7 +229,7 @@ impl ProofSystem<Bn128Field> for GM17 {
|
|||
let mut proof_buffer = Buffer::from_vec(&proof_raw);
|
||||
|
||||
unsafe {
|
||||
let ans = gm17_verify(
|
||||
let ans = gm17_bn128_verify(
|
||||
&mut vk_buffer as *mut _,
|
||||
&mut proof_buffer as *mut _,
|
||||
public_inputs_arr[0].as_ptr(),
|
|
@ -1,3 +1,7 @@
|
|||
mod ffi;
|
||||
pub mod gm17;
|
||||
pub mod pghr13;
|
||||
|
||||
use flat_absy::FlatVariable;
|
||||
use ir::{self, Statement};
|
||||
use std::cmp::max;
|
||||
|
@ -293,7 +297,7 @@ pub fn r1cs_program<T: Field>(
|
|||
let mut variables_list = vec![FlatVariable::new(0); variables.len()];
|
||||
for (k, v) in variables.drain() {
|
||||
assert_eq!(variables_list[v], FlatVariable::new(0));
|
||||
std::mem::replace(&mut variables_list[v], k);
|
||||
variables_list[v] = k;
|
||||
}
|
||||
(variables_list, private_inputs_offset, a, b, c)
|
||||
}
|
|
@ -1,14 +1,10 @@
|
|||
use ir;
|
||||
use proof_system::bn128::utils::ffi::{Buffer, ProofResult, SetupResult};
|
||||
use proof_system::bn128::utils::libsnark::{
|
||||
prepare_generate_proof, prepare_public_inputs, prepare_setup,
|
||||
};
|
||||
use proof_system::bn128::utils::parser::parse_vk;
|
||||
use proof_system::bn128::utils::solidity::{
|
||||
use proof_system::libsnark::ffi::{Buffer, ProofResult, SetupResult};
|
||||
use proof_system::libsnark::{prepare_generate_proof, prepare_public_inputs, prepare_setup};
|
||||
use proof_system::solidity::{
|
||||
SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2,
|
||||
};
|
||||
use proof_system::bn128::{G1PairingPoint, G2PairingPoint, Proof};
|
||||
use proof_system::{ProofSystem, SetupKeypair, SolidityAbi};
|
||||
use proof_system::{G1Affine, G2Affine, Proof, ProofSystem, SetupKeypair, SolidityAbi};
|
||||
use regex::Regex;
|
||||
|
||||
use zokrates_field::Bn128Field;
|
||||
|
@ -17,19 +13,32 @@ use zokrates_field::Field;
|
|||
pub struct PGHR13 {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PGHR13ProofPoints {
|
||||
a: G1PairingPoint,
|
||||
a_p: G1PairingPoint,
|
||||
b: G2PairingPoint,
|
||||
b_p: G1PairingPoint,
|
||||
c: G1PairingPoint,
|
||||
c_p: G1PairingPoint,
|
||||
h: G1PairingPoint,
|
||||
k: G1PairingPoint,
|
||||
pub struct VerificationKey {
|
||||
a: G2Affine,
|
||||
b: G1Affine,
|
||||
c: G2Affine,
|
||||
gamma: G2Affine,
|
||||
gamma_beta_1: G1Affine,
|
||||
gamma_beta_2: G2Affine,
|
||||
z: G2Affine,
|
||||
ic: Vec<G1Affine>,
|
||||
raw: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ProofPoints {
|
||||
a: G1Affine,
|
||||
a_p: G1Affine,
|
||||
b: G2Affine,
|
||||
b_p: G1Affine,
|
||||
c: G1Affine,
|
||||
c_p: G1Affine,
|
||||
h: G1Affine,
|
||||
k: G1Affine,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn pghr13_setup(
|
||||
fn pghr13_bn128_setup(
|
||||
a: *const u8,
|
||||
b: *const u8,
|
||||
c: *const u8,
|
||||
|
@ -41,7 +50,7 @@ extern "C" {
|
|||
inputs: i32,
|
||||
) -> SetupResult;
|
||||
|
||||
fn pghr13_generate_proof(
|
||||
fn pghr13_bn128_generate_proof(
|
||||
pk_buf: *mut Buffer,
|
||||
public_query_inputs: *const u8,
|
||||
public_query_inputs_length: i32,
|
||||
|
@ -49,7 +58,7 @@ extern "C" {
|
|||
private_inputs_length: i32,
|
||||
) -> ProofResult;
|
||||
|
||||
fn pghr13_verify(
|
||||
fn pghr13_bn128_verify(
|
||||
vk_buf: *mut Buffer,
|
||||
proof_buf: *mut Buffer,
|
||||
public_inputs: *const u8,
|
||||
|
@ -58,12 +67,15 @@ extern "C" {
|
|||
}
|
||||
|
||||
impl ProofSystem<Bn128Field> for PGHR13 {
|
||||
fn setup(program: ir::Prog<Bn128Field>) -> SetupKeypair {
|
||||
type VerificationKey = VerificationKey;
|
||||
type ProofPoints = ProofPoints;
|
||||
|
||||
fn setup(program: ir::Prog<Bn128Field>) -> SetupKeypair<VerificationKey> {
|
||||
let (a_arr, b_arr, c_arr, a_vec, b_vec, c_vec, num_constraints, num_variables, num_inputs) =
|
||||
prepare_setup(program);
|
||||
|
||||
let keypair = unsafe {
|
||||
let result: SetupResult = pghr13_setup(
|
||||
let result: SetupResult = pghr13_bn128_setup(
|
||||
a_arr.as_ptr(),
|
||||
b_arr.as_ptr(),
|
||||
c_arr.as_ptr(),
|
||||
|
@ -88,21 +100,22 @@ impl ProofSystem<Bn128Field> for PGHR13 {
|
|||
(vk, pk)
|
||||
};
|
||||
|
||||
SetupKeypair::from(String::from_utf8(keypair.0).unwrap(), keypair.1)
|
||||
let vk = serde_json::from_str(String::from_utf8(keypair.0).unwrap().as_str()).unwrap();
|
||||
SetupKeypair::new(vk, keypair.1)
|
||||
}
|
||||
|
||||
fn generate_proof(
|
||||
program: ir::Prog<Bn128Field>,
|
||||
witness: ir::Witness<Bn128Field>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> String {
|
||||
) -> Proof<ProofPoints> {
|
||||
let (public_inputs_arr, public_inputs_length, private_inputs_arr, private_inputs_length) =
|
||||
prepare_generate_proof(program, witness);
|
||||
|
||||
let mut pk_buf = Buffer::from_vec(&proving_key);
|
||||
|
||||
let proof_vec = unsafe {
|
||||
let result = pghr13_generate_proof(
|
||||
let proof = unsafe {
|
||||
let result = pghr13_bn128_generate_proof(
|
||||
&mut pk_buf as *mut _,
|
||||
public_inputs_arr[0].as_ptr(),
|
||||
public_inputs_length as i32,
|
||||
|
@ -112,7 +125,7 @@ impl ProofSystem<Bn128Field> for PGHR13 {
|
|||
|
||||
pk_buf.drop(); // drop the buffer manually
|
||||
|
||||
let proof_vec: Vec<u8> =
|
||||
let proof: Vec<u8> =
|
||||
std::slice::from_raw_parts(result.proof.data, result.proof.length as usize)
|
||||
.to_vec();
|
||||
|
||||
|
@ -120,14 +133,13 @@ impl ProofSystem<Bn128Field> for PGHR13 {
|
|||
// free the memory.
|
||||
result.proof.free();
|
||||
|
||||
proof_vec
|
||||
proof
|
||||
};
|
||||
|
||||
String::from_utf8(proof_vec).unwrap()
|
||||
serde_json::from_str(String::from_utf8(proof).unwrap().as_str()).unwrap()
|
||||
}
|
||||
|
||||
fn export_solidity_verifier(vk: String, abi: SolidityAbi) -> String {
|
||||
let vk_map = parse_vk(vk).unwrap();
|
||||
fn export_solidity_verifier(vk: VerificationKey, abi: SolidityAbi) -> String {
|
||||
let (mut template_text, solidity_pairing_lib) = match abi {
|
||||
SolidityAbi::V1 => (
|
||||
String::from(CONTRACT_TEMPLATE),
|
||||
|
@ -145,23 +157,35 @@ impl ProofSystem<Bn128Field> for PGHR13 {
|
|||
let vk_ic_repeat_regex = Regex::new(r#"(<%vk_ic_pts%>)"#).unwrap();
|
||||
let vk_input_len_regex = Regex::new(r#"(<%vk_input_length%>)"#).unwrap();
|
||||
|
||||
let keys = vec![
|
||||
"vk.a",
|
||||
"vk.b",
|
||||
"vk.c",
|
||||
"vk.gamma",
|
||||
"vk.gamma_beta_1",
|
||||
"vk.gamma_beta_2",
|
||||
"vk.z",
|
||||
];
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.a.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
for key in keys.iter() {
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk_map.get(*key).unwrap().as_str())
|
||||
.into_owned();
|
||||
}
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.b.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
let ic_count: usize = vk_map.get("vk.ic.len()").unwrap().parse().unwrap();
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.c.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.gamma.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.gamma_beta_1.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.gamma_beta_2.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
template_text = vk_regex
|
||||
.replace(template_text.as_str(), vk.z.to_string().as_str())
|
||||
.into_owned();
|
||||
|
||||
let ic_count: usize = vk.ic.len();
|
||||
template_text = vk_ic_len_regex
|
||||
.replace(template_text.as_str(), format!("{}", ic_count).as_str())
|
||||
.into_owned();
|
||||
|
@ -171,19 +195,16 @@ impl ProofSystem<Bn128Field> for PGHR13 {
|
|||
.into_owned();
|
||||
|
||||
let mut ic_repeat_text = String::new();
|
||||
for x in 0..ic_count {
|
||||
for (i, g1) in vk.ic.iter().enumerate() {
|
||||
ic_repeat_text.push_str(
|
||||
format!(
|
||||
"vk.ic[{}] = Pairing.G1Point({});",
|
||||
x,
|
||||
vk_map
|
||||
.get(format!("vk.ic[{}]", x).as_str())
|
||||
.unwrap()
|
||||
.as_str()
|
||||
i,
|
||||
g1.to_string().as_str()
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
if x < ic_count - 1 {
|
||||
if i < ic_count - 1 {
|
||||
ic_repeat_text.push_str("\n ");
|
||||
}
|
||||
}
|
||||
|
@ -201,12 +222,9 @@ impl ProofSystem<Bn128Field> for PGHR13 {
|
|||
)
|
||||
}
|
||||
|
||||
fn verify(vk: String, proof: String) -> bool {
|
||||
let map = parse_vk(vk).unwrap();
|
||||
let vk_raw = hex::decode(map.get("vk.raw").unwrap()).unwrap();
|
||||
|
||||
let proof = Proof::<PGHR13ProofPoints>::from_str(proof.as_str());
|
||||
let proof_raw = hex::decode(proof.raw).unwrap();
|
||||
fn verify(vk: VerificationKey, proof: Proof<ProofPoints>) -> bool {
|
||||
let vk_raw = hex::decode(vk.raw.clone()).unwrap();
|
||||
let proof_raw = hex::decode(proof.raw.clone()).unwrap();
|
||||
|
||||
let public_inputs: Vec<_> = proof
|
||||
.inputs
|
||||
|
@ -223,7 +241,7 @@ impl ProofSystem<Bn128Field> for PGHR13 {
|
|||
let mut proof_buffer = Buffer::from_vec(&proof_raw);
|
||||
|
||||
unsafe {
|
||||
let ans = pghr13_verify(
|
||||
let ans = pghr13_bn128_verify(
|
||||
&mut vk_buffer as *mut _,
|
||||
&mut proof_buffer as *mut _,
|
||||
public_inputs_arr[0].as_ptr(),
|
|
@ -1,24 +1,24 @@
|
|||
mod bn128;
|
||||
pub mod bellman;
|
||||
#[cfg(feature = "libsnark")]
|
||||
pub mod libsnark;
|
||||
|
||||
pub use self::bn128::G16;
|
||||
#[cfg(feature = "libsnark")]
|
||||
pub use self::bn128::GM17;
|
||||
#[cfg(feature = "libsnark")]
|
||||
pub use self::bn128::PGHR13;
|
||||
mod solidity;
|
||||
|
||||
use crate::ir;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use zokrates_field::Field;
|
||||
|
||||
// We only need to serialize this struct, there is no need for deserialization as keys are
|
||||
// used separately in other use cases
|
||||
#[derive(Serialize)]
|
||||
pub struct SetupKeypair {
|
||||
pub vk: String,
|
||||
pub struct SetupKeypair<V> {
|
||||
pub vk: V,
|
||||
pub pk: Vec<u8>,
|
||||
}
|
||||
|
||||
impl SetupKeypair {
|
||||
pub fn from(vk: String, pk: Vec<u8>) -> SetupKeypair {
|
||||
impl<V: Serialize + DeserializeOwned> SetupKeypair<V> {
|
||||
pub fn new(vk: V, pk: Vec<u8>) -> SetupKeypair<V> {
|
||||
SetupKeypair { vk, pk }
|
||||
}
|
||||
}
|
||||
|
@ -38,16 +38,54 @@ impl SolidityAbi {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait ProofSystem<T: Field> {
|
||||
fn setup(program: ir::Prog<T>) -> SetupKeypair;
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Proof<T> {
|
||||
proof: T,
|
||||
inputs: Vec<String>,
|
||||
raw: String,
|
||||
}
|
||||
|
||||
impl<T: Serialize + DeserializeOwned> Proof<T> {
|
||||
fn new(proof: T, inputs: Vec<String>, raw: String) -> Self {
|
||||
Proof { proof, inputs, raw }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct G1Affine(String, String);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct G2Affine(G1Affine, G1Affine);
|
||||
|
||||
impl ToString for G1Affine {
|
||||
fn to_string(&self) -> String {
|
||||
format!("{}, {}", self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for G2Affine {
|
||||
fn to_string(&self) -> String {
|
||||
format!("[{}], [{}]", self.0.to_string(), self.1.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ProofSystem<T: Field>
|
||||
where
|
||||
Self::VerificationKey: Serialize + DeserializeOwned,
|
||||
Self::ProofPoints: Serialize + DeserializeOwned,
|
||||
{
|
||||
type VerificationKey;
|
||||
type ProofPoints;
|
||||
|
||||
fn setup(program: ir::Prog<T>) -> SetupKeypair<Self::VerificationKey>;
|
||||
|
||||
fn generate_proof(
|
||||
program: ir::Prog<T>,
|
||||
witness: ir::Witness<T>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> String;
|
||||
) -> Proof<Self::ProofPoints>;
|
||||
|
||||
fn export_solidity_verifier(vk: String, abi: SolidityAbi) -> String;
|
||||
fn export_solidity_verifier(vk: Self::VerificationKey, abi: SolidityAbi) -> String;
|
||||
|
||||
fn verify(vk: String, proof: String) -> bool;
|
||||
fn verify(vk: Self::VerificationKey, proof: Proof<Self::ProofPoints>) -> bool;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ extern crate zokrates_field;
|
|||
use std::io;
|
||||
use zokrates_common::Resolver;
|
||||
use zokrates_core::{
|
||||
compile::{compile, CompilationArtifacts},
|
||||
compile::{compile, CompilationArtifacts, CompileConfig},
|
||||
ir::Interpreter,
|
||||
};
|
||||
use zokrates_field::Bn128Field;
|
||||
|
@ -28,6 +28,7 @@ fn out_of_range() {
|
|||
source,
|
||||
"./path/to/file".into(),
|
||||
None::<&dyn Resolver<io::Error>>,
|
||||
&CompileConfig::default(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use zokrates_core::ir::{Function, Interpreter, Prog, Statement};
|
|||
use zokrates_core::proof_system::ProofSystem;
|
||||
use zokrates_field::Bn128Field;
|
||||
|
||||
use zokrates_core::proof_system::G16;
|
||||
use zokrates_core::proof_system::bellman::groth16::G16;
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn generate_proof() {
|
||||
|
|
33
zokrates_js/index.d.ts
vendored
33
zokrates_js/index.d.ts
vendored
|
@ -1,5 +1,30 @@
|
|||
declare module 'zokrates-js' {
|
||||
|
||||
export type G1Affine = [string, string];
|
||||
export type G2Affine = [G1Affine, G1Affine];
|
||||
export type ProvingKey = Uint8Array;
|
||||
|
||||
export interface VerificationKey {
|
||||
alpha: G1Affine,
|
||||
beta: G2Affine,
|
||||
gamma: G2Affine,
|
||||
delta: G2Affine,
|
||||
gamma_abc: G1Affine[],
|
||||
raw: string,
|
||||
}
|
||||
|
||||
export interface ProofPoints {
|
||||
a: G1Affine,
|
||||
b: G2Affine,
|
||||
c: G1Affine
|
||||
}
|
||||
|
||||
export interface Proof {
|
||||
proof: ProofPoints,
|
||||
inputs: string[],
|
||||
raw: string
|
||||
}
|
||||
|
||||
export interface ResolverResult {
|
||||
source: string,
|
||||
location: string
|
||||
|
@ -16,8 +41,8 @@ declare module 'zokrates-js' {
|
|||
}
|
||||
|
||||
export interface SetupKeypair {
|
||||
vk: string,
|
||||
pk: Uint8Array,
|
||||
vk: VerificationKey,
|
||||
pk: ProvingKey,
|
||||
}
|
||||
|
||||
export type SolidityAbi = "v1" | "v2";
|
||||
|
@ -27,8 +52,8 @@ declare module 'zokrates-js' {
|
|||
compile(source: string, location: string, callback: ResolveCallback): CompilationArtifacts;
|
||||
setup(program: Uint8Array): SetupKeypair;
|
||||
computeWitness(artifacts: CompilationArtifacts, args: any[]): ComputationResult;
|
||||
exportSolidityVerifier(verifyingKey: string, abi: SolidityAbi): string;
|
||||
generateProof(program: Uint8Array, witness: string, provingKey: Uint8Array): string;
|
||||
exportSolidityVerifier(verifyingKey: VerificationKey, abi: SolidityAbi): string;
|
||||
generateProof(program: Uint8Array, witness: string, provingKey: Uint8Array): Proof;
|
||||
}
|
||||
|
||||
export function initialize(): Promise<ZoKratesProvider>;
|
||||
|
|
|
@ -5,10 +5,13 @@ use std::path::PathBuf;
|
|||
use wasm_bindgen::prelude::*;
|
||||
use zokrates_abi::{parse_strict, Decode, Encode, Inputs};
|
||||
use zokrates_common::Resolver;
|
||||
use zokrates_core::compile::{compile as core_compile, CompilationArtifacts, CompileError};
|
||||
use zokrates_core::compile::{
|
||||
compile as core_compile, CompilationArtifacts, CompileConfig, CompileError,
|
||||
};
|
||||
use zokrates_core::imports::Error;
|
||||
use zokrates_core::ir;
|
||||
use zokrates_core::proof_system::{self, ProofSystem, SolidityAbi};
|
||||
use zokrates_core::proof_system::{ProofSystem, SolidityAbi};
|
||||
use zokrates_core::proof_system::bellman::groth16::G16;
|
||||
use zokrates_core::typed_absy::abi::Abi;
|
||||
use zokrates_core::typed_absy::types::Signature;
|
||||
use zokrates_field::Bn128Field;
|
||||
|
@ -104,6 +107,7 @@ pub fn compile(
|
|||
source.as_string().unwrap(),
|
||||
PathBuf::from(location.as_string().unwrap()),
|
||||
Some(&resolver),
|
||||
&CompileConfig::default().with_is_release(true),
|
||||
)
|
||||
.map_err(|ce| {
|
||||
JsValue::from_str(&format!(
|
||||
|
@ -159,7 +163,7 @@ pub fn compute_witness(artifacts: JsValue, args: JsValue) -> Result<JsValue, JsV
|
|||
pub fn setup(program: JsValue) -> Result<JsValue, JsValue> {
|
||||
let input: Vec<u8> = program.into_serde().unwrap();
|
||||
let program_flattened = deserialize_program(&input)?;
|
||||
let keypair = proof_system::G16::setup(program_flattened);
|
||||
let keypair = G16::setup(program_flattened);
|
||||
Ok(JsValue::from_serde(&keypair).unwrap())
|
||||
}
|
||||
|
||||
|
@ -168,8 +172,8 @@ pub fn export_solidity_verifier(vk: JsValue, abi_version: JsValue) -> Result<JsV
|
|||
let abi_version = SolidityAbi::from(abi_version.as_string().unwrap().as_str())
|
||||
.map_err(|err| JsValue::from_str(err))?;
|
||||
|
||||
let verifier = <proof_system::G16 as ProofSystem<Bn128Field>>::export_solidity_verifier(
|
||||
vk.as_string().unwrap(),
|
||||
let verifier = <G16 as ProofSystem<Bn128Field>>::export_solidity_verifier(
|
||||
vk.into_serde().unwrap(),
|
||||
abi_version,
|
||||
);
|
||||
|
||||
|
@ -186,9 +190,9 @@ pub fn generate_proof(program: JsValue, witness: JsValue, pk: JsValue) -> Result
|
|||
.map_err(|err| JsValue::from_str(&format!("Could not read witness: {}", err)))?;
|
||||
|
||||
let proving_key: Vec<u8> = pk.into_serde().unwrap();
|
||||
let proof = proof_system::G16::generate_proof(program_flattened, ir_witness, proving_key);
|
||||
let proof = G16::generate_proof(program_flattened, ir_witness, proving_key);
|
||||
|
||||
Ok(JsValue::from_str(proof.as_str()))
|
||||
Ok(JsValue::from_serde(&proof).unwrap())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(start)]
|
||||
|
|
|
@ -83,7 +83,7 @@ fn compare<T: Field>(result: ir::ExecutionResult<T>, expected: TestResult) -> Re
|
|||
}
|
||||
|
||||
use std::io::{BufReader, Read};
|
||||
use zokrates_core::compile::compile;
|
||||
use zokrates_core::compile::{compile, CompileConfig};
|
||||
use zokrates_fs_resolver::FileSystemResolver;
|
||||
|
||||
pub fn test_inner(test_path: &str) {
|
||||
|
@ -104,7 +104,13 @@ fn compile_and_run<T: Field>(t: Tests) {
|
|||
let code = std::fs::read_to_string(&t.entry_point).unwrap();
|
||||
|
||||
let resolver = FileSystemResolver::new();
|
||||
let artifacts = compile::<T, _>(code, t.entry_point.clone(), Some(&resolver)).unwrap();
|
||||
let artifacts = compile::<T, _>(
|
||||
code,
|
||||
t.entry_point.clone(),
|
||||
Some(&resolver),
|
||||
&CompileConfig::default().with_is_release(true),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let bin = artifacts.prog();
|
||||
|
||||
|
|
Loading…
Reference in a new issue