From 3535574d2b25cc3de7defa90e47f7ee5526168e2 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 29 Apr 2020 19:34:24 +0200 Subject: [PATCH 01/14] proof system refactor --- zokrates_cli/src/bin.rs | 41 +++-- zokrates_core/lib/gm17.cpp | 26 +-- zokrates_core/lib/pghr13.cpp | 34 ++-- zokrates_core/src/proof_system/bn128/g16.rs | 167 ++++++++---------- zokrates_core/src/proof_system/bn128/gm17.rs | 91 ++++++---- zokrates_core/src/proof_system/bn128/mod.rs | 29 ++- .../src/proof_system/bn128/pghr13.rs | 125 ++++++++----- .../src/proof_system/bn128/utils/bellman.rs | 15 +- .../src/proof_system/bn128/utils/mod.rs | 1 - .../src/proof_system/bn128/utils/parser.rs | 60 ------- zokrates_core/src/proof_system/mod.rs | 46 ++++- zokrates_js/index.d.ts | 33 +++- zokrates_js/src/lib.rs | 4 +- 13 files changed, 354 insertions(+), 318 deletions(-) delete mode 100644 zokrates_core/src/proof_system/bn128/utils/parser.rs diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index fd526ea3..e2639428 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -62,12 +62,13 @@ fn cli_generate_proof>( 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 +81,13 @@ fn cli_export_verifier>( 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 +100,7 @@ fn cli_export_verifier>( writer .write_all(&verifier.as_bytes()) .map_err(|_| "Failed writing output to file.".to_string())?; + println!("Finished exporting verifier."); Ok(()) } @@ -126,7 +127,11 @@ fn cli_setup>( 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 @@ -344,12 +349,20 @@ fn cli_compile(sub_matches: &ArgMatches) -> Result<(), String> { fn cli_verify>(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!( diff --git a/zokrates_core/lib/gm17.cpp b/zokrates_core/lib/gm17.cpp index bda5d1f8..4b7c0aef 100644 --- a/zokrates_core/lib/gm17.cpp +++ b/zokrates_core/lib/gm17.cpp @@ -88,18 +88,22 @@ std::string serializeVerificationKey(r1cs_se_ppzksnark_verification_keyquery.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 << "{\n"; + ss << "\t\"h\": " << outputPointG2AffineAsHexJson(vk->H) << ",\n"; + ss << "\t\"g_alpha\": " << outputPointG1AffineAsHexJson(vk->G_alpha) << ",\n"; + ss << "\t\"h_beta\": " << outputPointG2AffineAsHexJson(vk->H_beta) << ",\n"; + ss << "\t\"g_gamma\": " << outputPointG1AffineAsHexJson(vk->G_gamma) << ",\n"; + ss << "\t\"h_gamma\": " << outputPointG2AffineAsHexJson(vk->H_gamma) << ",\n"; + ss << "\t\"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(vk->query[i]); } - ss << "vk.raw=" << toHexString(serialize(*vk)) << endl; + ss << "],\n"; + ss << "\t\"raw\": \"" << toHexString(serialize(*vk)) << "\"\n"; + ss << "}\n"; std::string str = ss.str(); return str; } @@ -109,7 +113,7 @@ std::string serializeProof(r1cs_se_ppzksnark_proof* proof, std::stringstream ss; ss << "{" << "\n"; - ss << "\t\"proof\": {" + ss << "\t\"points\": {" << "\n"; ss << "\t\t\"a\": " << outputPointG1AffineAsHexJson(proof->A) << ",\n"; ss << "\t\t\"b\": " << outputPointG2AffineAsHexJson(proof->B) << ",\n"; diff --git a/zokrates_core/lib/pghr13.cpp b/zokrates_core/lib/pghr13.cpp index 88f03570..ee1184f0 100644 --- a/zokrates_core/lib/pghr13.cpp +++ b/zokrates_core/lib/pghr13.cpp @@ -89,20 +89,26 @@ std::string serializeVerificationKey(r1cs_ppzksnark_verification_keyencoded_IC_query.rest.indices.size() + 1; - 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 << "{\n"; + ss << "\t\"a\": " << outputPointG2AffineAsHexJson(vk->alphaA_g2) << ",\n"; + ss << "\t\"b\": " << outputPointG1AffineAsHexJson(vk->alphaB_g1) << ",\n"; + ss << "\t\"c\": " << outputPointG2AffineAsHexJson(vk->alphaC_g2) << ",\n"; + ss << "\t\"gamma\": " << outputPointG2AffineAsHexJson(vk->gamma_g2) << ",\n"; + ss << "\t\"gamma_beta_1\": " << outputPointG1AffineAsHexJson(vk->gamma_beta_g1) << ",\n"; + ss << "\t\"gamma_beta_2\": " << outputPointG2AffineAsHexJson(vk->gamma_beta_g2) << ",\n"; + ss << "\t\"z\": " << outputPointG2AffineAsHexJson(vk->rC_Z_g2) << ",\n"; + ss << "\t\"ic\": ["; + for (size_t i = 0; i < icLength; ++i) { + if (i == 0) { + ss << outputPointG1AffineAsHexJson(vk->encoded_IC_query.first); + continue; + } + ss << ", "; + ss << outputPointG1AffineAsHexJson(vk->encoded_IC_query.rest.values[i]); } - ss << "vk.raw=" << toHexString(serialize(*vk)) << endl; + ss << "],\n"; + ss << "\t\"raw\": \"" << toHexString(serialize(*vk)) << "\"\n"; + ss << "}\n"; std::string str = ss.str(); return str; } @@ -112,7 +118,7 @@ std::string serializeProof(r1cs_ppzksnark_proof* proof, con std::stringstream ss; ss << "{" << "\n"; - ss << "\t\"proof\": {" + ss << "\t\"points\": {" << "\n"; ss << "\t\t\"a\": " << outputPointG1AffineAsHexJson(proof->g_A.g) << ",\n"; ss << "\t\t\"a_p\": " << outputPointG1AffineAsHexJson(proof->g_A.h) << ",\n"; diff --git a/zokrates_core/src/proof_system/bn128/g16.rs b/zokrates_core/src/proof_system/bn128/g16.rs index cba12f87..7f5ffc58 100644 --- a/zokrates_core/src/proof_system/bn128/g16.rs +++ b/zokrates_core/src/proof_system/bn128/g16.rs @@ -8,54 +8,74 @@ 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::bellman::{parse_fr, parse_g1, parse_g2}; use crate::proof_system::bn128::utils::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::bn128::{G1Affine, G2Affine}; +use proof_system::{Proof, 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, + raw: String, } impl ProofSystem for G16 { - fn setup(program: ir::Prog) -> SetupKeypair { + type VerificationKey = VerificationKey; + type ProofPoints = ProofPoints; + + fn setup(program: ir::Prog) -> SetupKeypair { #[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::(¶meters.vk); let mut pk: Vec = Vec::new(); - parameters.write(&mut pk).unwrap(); + let mut vk_raw: Vec = Vec::new(); - SetupKeypair::from(vk, pk) + parameters.write(&mut pk).unwrap(); + parameters.vk.write(&mut vk_raw).unwrap(); + + let vk = VerificationKey { + alpha: parse_g1::(¶meters.vk.alpha_g1), + beta: parse_g2::(¶meters.vk.beta_g2), + gamma: parse_g2::(¶meters.vk.gamma_g2), + delta: parse_g2::(¶meters.vk.delta_g2), + gamma_abc: parameters + .vk + .ic + .iter() + .map(|g1| parse_g1::(g1)) + .collect(), + raw: hex::encode(vk_raw), + }; + + SetupKeypair::new(vk, pk) } fn generate_proof( program: ir::Prog, witness: ir::Witness, proving_key: Vec, - ) -> String { + ) -> Proof { #[cfg(not(target_arch = "wasm32"))] std::env::set_var("BELLMAN_VERBOSE", "0"); @@ -65,11 +85,12 @@ impl ProofSystem 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::(&proof.a), - parse_g2::(&proof.b), - parse_g1::(&proof.c), - ); + + let proof_points = ProofPoints { + a: parse_g1::(&proof.a), + b: parse_g2::(&proof.b), + c: parse_g1::(&proof.c), + }; let inputs = computation .public_inputs_values() @@ -80,11 +101,10 @@ impl ProofSystem for G16 { let mut raw: Vec = Vec::new(); proof.write(&mut raw).unwrap(); - Proof::::new(proof_points, inputs, hex::encode(&raw)).to_json_pretty() + Proof::::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 +121,23 @@ impl ProofSystem 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(), format!("{}", vk.alpha).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(), format!("{}", vk.beta).as_str()) + .into_owned(); + + template_text = vk_regex + .replace(template_text.as_str(), format!("{}", vk.gamma).as_str()) + .into_owned(); + + template_text = vk_regex + .replace(template_text.as_str(), format!("{}", vk.delta).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 +153,16 @@ impl ProofSystem for G16 { .into_owned(); let mut gamma_abc_repeat_text = String::new(); - for x in 0..gamma_abc_count { + for (i, x) 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, + format!("{}", x).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 +180,18 @@ impl ProofSystem 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) -> bool { + let vk_raw = hex::decode(vk.raw.clone()).unwrap(); + let proof_raw = hex::decode(proof.raw.clone()).unwrap(); let vk: VerifyingKey = VerifyingKey::read(vk_raw.as_slice()).unwrap(); + let pvk: PreparedVerifyingKey = prepare_verifying_key(&vk); - let g16_proof = Proof::::from_str(proof.as_str()); + let bellman_proof: BellmanProof = + BellmanProof::read(proof_raw.as_slice()).unwrap(); - let raw_proof = hex::decode(g16_proof.raw).unwrap(); - let proof: BellmanProof = - BellmanProof::read(raw_proof.as_slice()).unwrap(); - - let public_inputs: Vec<_> = g16_proof + let public_inputs: Vec<_> = proof .inputs .iter() .map(|s| { @@ -177,51 +201,10 @@ impl ProofSystem for G16 { }) .collect::>(); - verify_proof(&pvk, &proof, &public_inputs).unwrap() + verify_proof(&pvk, &bellman_proof, &public_inputs).unwrap() } } -fn serialize_vk(vk: &VerifyingKey) -> String { - let mut writer = csv::WriterBuilder::new() - .delimiter(b'=') - .from_writer(vec![]); - - writer - .write_record(&["vk.alpha", parse_g1_hex::(&vk.alpha_g1).as_str()]) - .unwrap(); - writer - .write_record(&["vk.beta", parse_g2_hex::(&vk.beta_g2).as_str()]) - .unwrap(); - writer - .write_record(&["vk.gamma", parse_g2_hex::(&vk.gamma_g2).as_str()]) - .unwrap(); - writer - .write_record(&["vk.delta", parse_g2_hex::(&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::(x).as_str(), - ]) - .unwrap() - } - - let mut raw: Vec = 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 *; diff --git a/zokrates_core/src/proof_system/bn128/gm17.rs b/zokrates_core/src/proof_system/bn128/gm17.rs index a9748b19..937001f4 100644 --- a/zokrates_core/src/proof_system/bn128/gm17.rs +++ b/zokrates_core/src/proof_system/bn128/gm17.rs @@ -3,12 +3,11 @@ 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::{ 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::bn128::{G1Affine, G2Affine}; +use proof_system::{Proof, ProofSystem, SetupKeypair, SolidityAbi}; use regex::Regex; use zokrates_field::Bn128Field; @@ -17,10 +16,21 @@ 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, + raw: String, +} + +#[derive(Serialize, Deserialize)] +pub struct ProofPoints { + a: G1Affine, + b: G2Affine, + c: G1Affine, } extern "C" { @@ -53,7 +63,10 @@ extern "C" { } impl ProofSystem for GM17 { - fn setup(program: ir::Prog) -> SetupKeypair { + type VerificationKey = VerificationKey; + type ProofPoints = ProofPoints; + + fn setup(program: ir::Prog) -> SetupKeypair { let (a_arr, b_arr, c_arr, a_vec, b_vec, c_vec, num_constraints, num_variables, num_inputs) = prepare_setup(program); @@ -83,14 +96,15 @@ impl ProofSystem 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, witness: ir::Witness, proving_key: Vec, - ) -> String { + ) -> Proof { let (public_inputs_arr, public_inputs_length, private_inputs_arr, private_inputs_length) = prepare_generate_proof(program, witness); @@ -118,11 +132,10 @@ impl ProofSystem 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 +153,27 @@ impl ProofSystem 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(), format!("{}", vk.h).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(), format!("{}", vk.g_alpha).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(), format!("{}", vk.h_beta).as_str()) + .into_owned(); + + template_text = vk_regex + .replace(template_text.as_str(), format!("{}", vk.g_gamma).as_str()) + .into_owned(); + + template_text = vk_regex + .replace(template_text.as_str(), format!("{}", vk.h_gamma).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 +186,16 @@ impl ProofSystem for GM17 { .into_owned(); let mut query_repeat_text = String::new(); - for x in 0..query_count { + for (i, x) 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, + format!("{}", x).as_str() ) .as_str(), ); - if x < query_count - 1 { + if i < query_count - 1 { query_repeat_text.push_str("\n "); } } @@ -197,12 +213,9 @@ impl ProofSystem 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::::from_str(proof.as_str()); - let proof_raw = hex::decode(proof.raw).unwrap(); + fn verify(vk: VerificationKey, proof: Proof) -> 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 diff --git a/zokrates_core/src/proof_system/bn128/mod.rs b/zokrates_core/src/proof_system/bn128/mod.rs index b18ef9ec..c9bf63d5 100644 --- a/zokrates_core/src/proof_system/bn128/mod.rs +++ b/zokrates_core/src/proof_system/bn128/mod.rs @@ -11,26 +11,21 @@ pub use self::g16::G16; 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 { - proof: T, - inputs: Vec, - raw: String, +pub struct G1Affine(String, String); + +#[derive(Serialize, Deserialize)] +pub struct G2Affine(G1Affine, G1Affine); + +impl std::fmt::Display for G1Affine { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}, {}", self.0, self.1) + } } -impl<'a, T: Serialize + Deserialize<'a>> Proof { - fn new(proof: T, inputs: Vec, raw: String) -> Self { - Proof { proof, inputs, raw } - } - fn from_str(proof: &'a str) -> Proof { - serde_json::from_str(proof).expect("Invalid proof json format") - } - fn to_json_pretty(&self) -> String { - serde_json::to_string_pretty(self).unwrap() +impl std::fmt::Display for G2Affine { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "[{}], [{}]", self.0, self.1) } } diff --git a/zokrates_core/src/proof_system/bn128/pghr13.rs b/zokrates_core/src/proof_system/bn128/pghr13.rs index 79724d23..49edfcbc 100644 --- a/zokrates_core/src/proof_system/bn128/pghr13.rs +++ b/zokrates_core/src/proof_system/bn128/pghr13.rs @@ -3,12 +3,11 @@ 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::{ 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::bn128::{G1Affine, G2Affine}; +use proof_system::{Proof, ProofSystem, SetupKeypair, SolidityAbi}; use regex::Regex; use zokrates_field::Bn128Field; @@ -17,15 +16,28 @@ 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, + 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" { @@ -58,7 +70,10 @@ extern "C" { } impl ProofSystem for PGHR13 { - fn setup(program: ir::Prog) -> SetupKeypair { + type VerificationKey = VerificationKey; + type ProofPoints = ProofPoints; + + fn setup(program: ir::Prog) -> SetupKeypair { let (a_arr, b_arr, c_arr, a_vec, b_vec, c_vec, num_constraints, num_variables, num_inputs) = prepare_setup(program); @@ -88,20 +103,21 @@ impl ProofSystem 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, witness: ir::Witness, proving_key: Vec, - ) -> String { + ) -> Proof { 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 proof = unsafe { let result = pghr13_generate_proof( &mut pk_buf as *mut _, public_inputs_arr[0].as_ptr(), @@ -112,7 +128,7 @@ impl ProofSystem for PGHR13 { pk_buf.drop(); // drop the buffer manually - let proof_vec: Vec = + let proof: Vec = std::slice::from_raw_parts(result.proof.data, result.proof.length as usize) .to_vec(); @@ -120,14 +136,13 @@ impl ProofSystem 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 +160,41 @@ impl ProofSystem 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(), format!("{}", vk.a).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(), format!("{}", vk.b).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(), format!("{}", vk.c).as_str()) + .into_owned(); + + template_text = vk_regex + .replace(template_text.as_str(), format!("{}", vk.gamma).as_str()) + .into_owned(); + + template_text = vk_regex + .replace( + template_text.as_str(), + format!("{}", vk.gamma_beta_1).as_str(), + ) + .into_owned(); + + template_text = vk_regex + .replace( + template_text.as_str(), + format!("{}", vk.gamma_beta_2).as_str(), + ) + .into_owned(); + + template_text = vk_regex + .replace(template_text.as_str(), format!("{}", vk.z).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 +204,16 @@ impl ProofSystem for PGHR13 { .into_owned(); let mut ic_repeat_text = String::new(); - for x in 0..ic_count { + for (i, x) 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, + format!("{}", x).as_str() ) .as_str(), ); - if x < ic_count - 1 { + if i < ic_count - 1 { ic_repeat_text.push_str("\n "); } } @@ -201,12 +231,9 @@ impl ProofSystem 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::::from_str(proof.as_str()); - let proof_raw = hex::decode(proof.raw).unwrap(); + fn verify(vk: VerificationKey, proof: Proof) -> 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 diff --git a/zokrates_core/src/proof_system/bn128/utils/bellman.rs b/zokrates_core/src/proof_system/bn128/utils/bellman.rs index bdb47716..5f7c1bb2 100644 --- a/zokrates_core/src/proof_system/bn128/utils/bellman.rs +++ b/zokrates_core/src/proof_system/bn128/utils/bellman.rs @@ -209,6 +209,7 @@ mod parse { use lazy_static::lazy_static; use super::*; + use proof_system::bn128::{G1Affine, G2Affine}; use regex::Regex; lazy_static! { @@ -227,10 +228,10 @@ mod parse { pub fn parse_g1( e: &::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 +239,15 @@ mod parse { pub fn parse_g2( e: &::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(), ), @@ -259,6 +260,7 @@ mod parse { captures.name(&"x").unwrap().as_str().to_string() } + /* pub fn parse_g1_hex( e: &::G1Affine, ) -> String { @@ -278,6 +280,7 @@ mod parse { (parsed.1).1 ) } + */ } #[cfg(test)] diff --git a/zokrates_core/src/proof_system/bn128/utils/mod.rs b/zokrates_core/src/proof_system/bn128/utils/mod.rs index 3c09c3ac..1aa80a4e 100644 --- a/zokrates_core/src/proof_system/bn128/utils/mod.rs +++ b/zokrates_core/src/proof_system/bn128/utils/mod.rs @@ -3,5 +3,4 @@ pub mod bellman; pub mod ffi; #[cfg(feature = "libsnark")] pub mod libsnark; -pub mod parser; pub mod solidity; diff --git a/zokrates_core/src/proof_system/bn128/utils/parser.rs b/zokrates_core/src/proof_system/bn128/utils/parser.rs deleted file mode 100644 index 3ccad811..00000000 --- a/zokrates_core/src/proof_system/bn128/utils/parser.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::collections::HashMap; - -pub fn parse_vk(vk: String) -> Result, 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()); - } -} diff --git a/zokrates_core/src/proof_system/mod.rs b/zokrates_core/src/proof_system/mod.rs index 1078d9c1..c2a9a070 100644 --- a/zokrates_core/src/proof_system/mod.rs +++ b/zokrates_core/src/proof_system/mod.rs @@ -1,24 +1,28 @@ mod bn128; pub use self::bn128::G16; + #[cfg(feature = "libsnark")] pub use self::bn128::GM17; + #[cfg(feature = "libsnark")] pub use self::bn128::PGHR13; use crate::ir; +use serde::de::DeserializeOwned; +use serde::{Deserialize, 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 { + pub vk: V, pub pk: Vec, } -impl SetupKeypair { - pub fn from(vk: String, pk: Vec) -> SetupKeypair { +impl<'a, V: Serialize + Deserialize<'a>> SetupKeypair { + pub fn new(vk: V, pk: Vec) -> SetupKeypair { SetupKeypair { vk, pk } } } @@ -38,16 +42,40 @@ impl SolidityAbi { } } -pub trait ProofSystem { - fn setup(program: ir::Prog) -> SetupKeypair; +#[derive(Serialize, Deserialize)] +pub struct Proof { + points: T, + inputs: Vec, + raw: String, +} + +impl Proof { + fn new(points: T, inputs: Vec, raw: String) -> Self { + Proof { + points, + inputs, + raw, + } + } +} + +pub trait ProofSystem +where + Self::VerificationKey: Serialize + DeserializeOwned, + Self::ProofPoints: Serialize + DeserializeOwned, +{ + type VerificationKey; + type ProofPoints; + + fn setup(program: ir::Prog) -> SetupKeypair; fn generate_proof( program: ir::Prog, witness: ir::Witness, proving_key: Vec, - ) -> String; + ) -> Proof; - 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) -> bool; } diff --git a/zokrates_js/index.d.ts b/zokrates_js/index.d.ts index db6808fa..71ac30a5 100644 --- a/zokrates_js/index.d.ts +++ b/zokrates_js/index.d.ts @@ -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 { + points: 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; diff --git a/zokrates_js/src/lib.rs b/zokrates_js/src/lib.rs index 7fb82c4c..f3410e47 100644 --- a/zokrates_js/src/lib.rs +++ b/zokrates_js/src/lib.rs @@ -167,7 +167,7 @@ pub fn export_solidity_verifier(vk: JsValue, abi_version: JsValue) -> Result>::export_solidity_verifier( - vk.as_string().unwrap(), + vk.into_serde().unwrap(), abi_version, ); @@ -186,7 +186,7 @@ pub fn generate_proof(program: JsValue, witness: JsValue, pk: JsValue) -> Result let proving_key: Vec = pk.into_serde().unwrap(); let proof = proof_system::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)] From 98f5edb7a3fbf35bc4301229babb796b915e14d2 Mon Sep 17 00:00:00 2001 From: dark64 Date: Thu, 30 Apr 2020 18:17:18 +0200 Subject: [PATCH 02/14] cleanup --- zokrates_cli/src/bin.rs | 4 +- zokrates_core/lib/gm17.cpp | 49 ++++++------- zokrates_core/lib/pghr13.cpp | 68 ++++++++----------- zokrates_core/lib/util.cpp | 18 +---- zokrates_core/lib/util.hpp | 2 - zokrates_core/src/proof_system/bn128/g16.rs | 12 ++-- zokrates_core/src/proof_system/bn128/gm17.rs | 14 ++-- zokrates_core/src/proof_system/bn128/mod.rs | 12 ++-- .../src/proof_system/bn128/pghr13.rs | 24 +++---- zokrates_core/src/proof_system/mod.rs | 6 +- zokrates_js/index.d.ts | 2 +- 11 files changed, 86 insertions(+), 125 deletions(-) diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index e2639428..c5c8acec 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -792,7 +792,7 @@ fn cli() -> Result<(), String> { "json" => { println!("~~~~~~~~ Copy the output below for valid ABIv2 format ~~~~~~~~"); println!(); - print!("{}", proof_object["proof"]); + print!("{}", proof_object["points"]); print!(","); println!("{}", proof_object["inputs"]); println!(); @@ -802,7 +802,7 @@ fn cli() -> Result<(), String> { println!("~~~~~~~~ Copy the output below for valid ABIv1 format ~~~~~~~~"); println!(); - for (_, value) in proof_object["proof"].as_object().unwrap().iter() { + for (_, value) in proof_object["points"].as_object().unwrap().iter() { print!("{}", value); print!(","); } diff --git a/zokrates_core/lib/gm17.cpp b/zokrates_core/lib/gm17.cpp index 4b7c0aef..32065e26 100644 --- a/zokrates_core/lib/gm17.cpp +++ b/zokrates_core/lib/gm17.cpp @@ -88,22 +88,20 @@ std::string serializeVerificationKey(r1cs_se_ppzksnark_verification_keyquery.size(); - ss << "{\n"; - ss << "\t\"h\": " << outputPointG2AffineAsHexJson(vk->H) << ",\n"; - ss << "\t\"g_alpha\": " << outputPointG1AffineAsHexJson(vk->G_alpha) << ",\n"; - ss << "\t\"h_beta\": " << outputPointG2AffineAsHexJson(vk->H_beta) << ",\n"; - ss << "\t\"g_gamma\": " << outputPointG1AffineAsHexJson(vk->G_gamma) << ",\n"; - ss << "\t\"h_gamma\": " << outputPointG2AffineAsHexJson(vk->H_gamma) << ",\n"; - ss << "\t\"query\": ["; + ss << "{"; + ss << "\"h\":" << outputPointG2AffineAsHexJson(vk->H) << ","; + ss << "\"g_alpha\":" << outputPointG1AffineAsHexJson(vk->G_alpha) << ","; + ss << "\"h_beta\":" << outputPointG2AffineAsHexJson(vk->H_beta) << ","; + ss << "\"g_gamma\":" << outputPointG1AffineAsHexJson(vk->G_gamma) << ","; + ss << "\"h_gamma\":" << outputPointG2AffineAsHexJson(vk->H_gamma) << ","; + ss << "\"query\":["; for (size_t i = 0; i < queryLength; ++i) { - if (i != 0) { - ss << ", "; - } + if (i != 0) ss << ","; ss << outputPointG1AffineAsHexJson(vk->query[i]); } - ss << "],\n"; - ss << "\t\"raw\": \"" << toHexString(serialize(*vk)) << "\"\n"; - ss << "}\n"; + ss << "],"; + ss << "\"raw\":\"" << toHexString(serialize(*vk)) << "\""; + ss << "}"; std::string str = ss.str(); return str; } @@ -111,27 +109,22 @@ std::string serializeVerificationKey(r1cs_se_ppzksnark_verification_key* proof, const uint8_t* public_inputs, int32_t public_inputs_length) { std::stringstream ss; - ss << "{" - << "\n"; - ss << "\t\"points\": {" - << "\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 << "\"points\":{"; + ss << "\"a\":" << outputPointG1AffineAsHexJson(proof->A) << ","; + ss << "\"b\":" << outputPointG2AffineAsHexJson(proof->B) << ","; + ss << "\"c\":" << outputPointG1AffineAsHexJson(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 << "],\n"; - ss << "\t\"raw\": \"" << toHexString(serialize(*proof)) << "\"\n"; - ss << "}" - << "\n"; + ss << "],"; + ss << "\"raw\":\"" << toHexString(serialize(*proof)) << "\""; + ss << "}"; std::string str = ss.str(); return str; } diff --git a/zokrates_core/lib/pghr13.cpp b/zokrates_core/lib/pghr13.cpp index ee1184f0..c791caba 100644 --- a/zokrates_core/lib/pghr13.cpp +++ b/zokrates_core/lib/pghr13.cpp @@ -87,28 +87,25 @@ r1cs_ppzksnark_keypair generateKeypair(const r1cs_ppzksnark std::string serializeVerificationKey(r1cs_ppzksnark_verification_key* vk) { std::stringstream ss; - unsigned icLength = vk->encoded_IC_query.rest.indices.size() + 1; + unsigned icLength = vk->encoded_IC_query.rest.indices.size(); - ss << "{\n"; - ss << "\t\"a\": " << outputPointG2AffineAsHexJson(vk->alphaA_g2) << ",\n"; - ss << "\t\"b\": " << outputPointG1AffineAsHexJson(vk->alphaB_g1) << ",\n"; - ss << "\t\"c\": " << outputPointG2AffineAsHexJson(vk->alphaC_g2) << ",\n"; - ss << "\t\"gamma\": " << outputPointG2AffineAsHexJson(vk->gamma_g2) << ",\n"; - ss << "\t\"gamma_beta_1\": " << outputPointG1AffineAsHexJson(vk->gamma_beta_g1) << ",\n"; - ss << "\t\"gamma_beta_2\": " << outputPointG2AffineAsHexJson(vk->gamma_beta_g2) << ",\n"; - ss << "\t\"z\": " << outputPointG2AffineAsHexJson(vk->rC_Z_g2) << ",\n"; - ss << "\t\"ic\": ["; + ss << "{"; + ss << "\"a\":" << outputPointG2AffineAsHexJson(vk->alphaA_g2) << ","; + ss << "\"b\":" << outputPointG1AffineAsHexJson(vk->alphaB_g1) << ","; + ss << "\"c\":" << outputPointG2AffineAsHexJson(vk->alphaC_g2) << ","; + ss << "\"gamma\":" << outputPointG2AffineAsHexJson(vk->gamma_g2) << ","; + ss << "\"gamma_beta_1\":" << outputPointG1AffineAsHexJson(vk->gamma_beta_g1) << ","; + ss << "\"gamma_beta_2\":" << outputPointG2AffineAsHexJson(vk->gamma_beta_g2) << ","; + ss << "\"z\":" << outputPointG2AffineAsHexJson(vk->rC_Z_g2) << ","; + ss << "\"ic\":["; + ss << outputPointG1AffineAsHexJson(vk->encoded_IC_query.first); for (size_t i = 0; i < icLength; ++i) { - if (i == 0) { - ss << outputPointG1AffineAsHexJson(vk->encoded_IC_query.first); - continue; - } - ss << ", "; + ss << ","; ss << outputPointG1AffineAsHexJson(vk->encoded_IC_query.rest.values[i]); } - ss << "],\n"; - ss << "\t\"raw\": \"" << toHexString(serialize(*vk)) << "\"\n"; - ss << "}\n"; + ss << "],"; + ss << "\"raw\":\"" << toHexString(serialize(*vk)) << "\""; + ss << "}"; std::string str = ss.str(); return str; } @@ -116,32 +113,27 @@ std::string serializeVerificationKey(r1cs_ppzksnark_verification_key* proof, const uint8_t* public_inputs, int public_inputs_length) { std::stringstream ss; - ss << "{" - << "\n"; - ss << "\t\"points\": {" - << "\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 << "\"points\":{"; + ss << "\"a\":" << outputPointG1AffineAsHexJson(proof->g_A.g) << ","; + ss << "\"a_p\":" << outputPointG1AffineAsHexJson(proof->g_A.h) << ","; + ss << "\"b\":" << outputPointG2AffineAsHexJson(proof->g_B.g) << ","; + ss << "\"b_p\":" << outputPointG1AffineAsHexJson(proof->g_B.h) << ","; + ss << "\"c\":" << outputPointG1AffineAsHexJson(proof->g_C.g) << ","; + ss << "\"c_p\":" << outputPointG1AffineAsHexJson(proof->g_C.h) << ","; + ss << "\"h\":" << outputPointG1AffineAsHexJson(proof->g_H) << ","; + ss << "\"k\":" << outputPointG1AffineAsHexJson(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 << "],\n"; - ss << "\t\"raw\": \"" << toHexString(serialize(*proof)) << "\"\n"; - ss << "}" - << "\n"; + ss << "],"; + ss << "\"raw\":\"" << toHexString(serialize(*proof)) << "\""; + ss << "}"; std::string str = ss.str(); return str; } diff --git a/zokrates_core/lib/util.cpp b/zokrates_core/lib/util.cpp index 5a380d50..4d92f439 100644 --- a/zokrates_core/lib/util.cpp +++ b/zokrates_core/lib/util.cpp @@ -46,30 +46,16 @@ std::string outputInputAsHex(libff::bigint _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()) + "]"; + return "[\"0x" + HexStringFromLibsnarkBigint(aff.X.as_bigint()) + "\",\"0x" + HexStringFromLibsnarkBigint(aff.Y.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()) + "\"]]"; + 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()) + "\"]]"; } \ No newline at end of file diff --git a/zokrates_core/lib/util.hpp b/zokrates_core/lib/util.hpp index d1722b94..0edcd9a0 100644 --- a/zokrates_core/lib/util.hpp +++ b/zokrates_core/lib/util.hpp @@ -14,9 +14,7 @@ libff::bigint libsnarkBigintFromBytes(const uint8_t* _ std::string toHexString(const std::string& s); std::string HexStringFromLibsnarkBigint(libff::bigint _x); std::string outputInputAsHex(libff::bigint _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 diff --git a/zokrates_core/src/proof_system/bn128/g16.rs b/zokrates_core/src/proof_system/bn128/g16.rs index 7f5ffc58..ce592a9e 100644 --- a/zokrates_core/src/proof_system/bn128/g16.rs +++ b/zokrates_core/src/proof_system/bn128/g16.rs @@ -122,19 +122,19 @@ impl ProofSystem for G16 { let vk_input_len_regex = Regex::new(r#"(<%vk_input_length%>)"#).unwrap(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.alpha).as_str()) + .replace(template_text.as_str(), vk.alpha.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.beta).as_str()) + .replace(template_text.as_str(), vk.beta.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.gamma).as_str()) + .replace(template_text.as_str(), vk.gamma.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.delta).as_str()) + .replace(template_text.as_str(), vk.delta.to_string().as_str()) .into_owned(); let gamma_abc_count: usize = vk.gamma_abc.len(); @@ -153,12 +153,12 @@ impl ProofSystem for G16 { .into_owned(); let mut gamma_abc_repeat_text = String::new(); - for (i, x) in vk.gamma_abc.iter().enumerate() { + for (i, g1) in vk.gamma_abc.iter().enumerate() { gamma_abc_repeat_text.push_str( format!( "vk.gamma_abc[{}] = Pairing.G1Point({});", i, - format!("{}", x).as_str() + g1.to_string().as_str() ) .as_str(), ); diff --git a/zokrates_core/src/proof_system/bn128/gm17.rs b/zokrates_core/src/proof_system/bn128/gm17.rs index 937001f4..cba4ca37 100644 --- a/zokrates_core/src/proof_system/bn128/gm17.rs +++ b/zokrates_core/src/proof_system/bn128/gm17.rs @@ -154,23 +154,23 @@ impl ProofSystem for GM17 { let vk_input_len_regex = Regex::new(r#"(<%vk_input_length%>)"#).unwrap(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.h).as_str()) + .replace(template_text.as_str(), vk.h.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.g_alpha).as_str()) + .replace(template_text.as_str(), vk.g_alpha.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.h_beta).as_str()) + .replace(template_text.as_str(), vk.h_beta.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.g_gamma).as_str()) + .replace(template_text.as_str(), vk.g_gamma.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.h_gamma).as_str()) + .replace(template_text.as_str(), vk.h_gamma.to_string().as_str()) .into_owned(); let query_count: usize = vk.query.len(); @@ -186,12 +186,12 @@ impl ProofSystem for GM17 { .into_owned(); let mut query_repeat_text = String::new(); - for (i, x) in vk.query.iter().enumerate() { + for (i, g1) in vk.query.iter().enumerate() { query_repeat_text.push_str( format!( "vk.query[{}] = Pairing.G1Point({});", i, - format!("{}", x).as_str() + g1.to_string().as_str() ) .as_str(), ); diff --git a/zokrates_core/src/proof_system/bn128/mod.rs b/zokrates_core/src/proof_system/bn128/mod.rs index c9bf63d5..33b6c57f 100644 --- a/zokrates_core/src/proof_system/bn128/mod.rs +++ b/zokrates_core/src/proof_system/bn128/mod.rs @@ -18,14 +18,14 @@ pub struct G1Affine(String, String); #[derive(Serialize, Deserialize)] pub struct G2Affine(G1Affine, G1Affine); -impl std::fmt::Display for G1Affine { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}, {}", self.0, self.1) +impl ToString for G1Affine { + fn to_string(&self) -> String { + format!("{}, {}", self.0, self.1) } } -impl std::fmt::Display for G2Affine { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "[{}], [{}]", self.0, self.1) +impl ToString for G2Affine { + fn to_string(&self) -> String { + format!("[{}], [{}]", self.0.to_string(), self.1.to_string()) } } diff --git a/zokrates_core/src/proof_system/bn128/pghr13.rs b/zokrates_core/src/proof_system/bn128/pghr13.rs index 49edfcbc..e42a9130 100644 --- a/zokrates_core/src/proof_system/bn128/pghr13.rs +++ b/zokrates_core/src/proof_system/bn128/pghr13.rs @@ -161,37 +161,31 @@ impl ProofSystem for PGHR13 { let vk_input_len_regex = Regex::new(r#"(<%vk_input_length%>)"#).unwrap(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.a).as_str()) + .replace(template_text.as_str(), vk.a.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.b).as_str()) + .replace(template_text.as_str(), vk.b.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.c).as_str()) + .replace(template_text.as_str(), vk.c.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.gamma).as_str()) + .replace(template_text.as_str(), vk.gamma.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace( - template_text.as_str(), - format!("{}", vk.gamma_beta_1).as_str(), - ) + .replace(template_text.as_str(), vk.gamma_beta_1.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace( - template_text.as_str(), - format!("{}", vk.gamma_beta_2).as_str(), - ) + .replace(template_text.as_str(), vk.gamma_beta_2.to_string().as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), format!("{}", vk.z).as_str()) + .replace(template_text.as_str(), vk.z.to_string().as_str()) .into_owned(); let ic_count: usize = vk.ic.len(); @@ -204,12 +198,12 @@ impl ProofSystem for PGHR13 { .into_owned(); let mut ic_repeat_text = String::new(); - for (i, x) in vk.ic.iter().enumerate() { + for (i, g1) in vk.ic.iter().enumerate() { ic_repeat_text.push_str( format!( "vk.ic[{}] = Pairing.G1Point({});", i, - format!("{}", x).as_str() + g1.to_string().as_str() ) .as_str(), ); diff --git a/zokrates_core/src/proof_system/mod.rs b/zokrates_core/src/proof_system/mod.rs index c2a9a070..0f9e1243 100644 --- a/zokrates_core/src/proof_system/mod.rs +++ b/zokrates_core/src/proof_system/mod.rs @@ -1,16 +1,14 @@ mod bn128; pub use self::bn128::G16; - #[cfg(feature = "libsnark")] pub use self::bn128::GM17; - #[cfg(feature = "libsnark")] pub use self::bn128::PGHR13; use crate::ir; use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; +use serde::Serialize; use zokrates_field::Field; // We only need to serialize this struct, there is no need for deserialization as keys are @@ -21,7 +19,7 @@ pub struct SetupKeypair { pub pk: Vec, } -impl<'a, V: Serialize + Deserialize<'a>> SetupKeypair { +impl SetupKeypair { pub fn new(vk: V, pk: Vec) -> SetupKeypair { SetupKeypair { vk, pk } } diff --git a/zokrates_js/index.d.ts b/zokrates_js/index.d.ts index 71ac30a5..e6164936 100644 --- a/zokrates_js/index.d.ts +++ b/zokrates_js/index.d.ts @@ -46,7 +46,7 @@ declare module 'zokrates-js' { } export type SolidityAbi = "v1" | "v2"; - export type ResolveCallback = (location: string, path: string) => ResolverResult; + export type ResolveCallback = (location: string, path: string) => ResolverResult;krat export interface ZoKratesProvider { compile(source: string, location: string, callback: ResolveCallback): CompilationArtifacts; From 793c0b143f77fdae10ce8a7c360f371c7420cc59 Mon Sep 17 00:00:00 2001 From: dark64 Date: Tue, 12 May 2020 13:39:56 +0200 Subject: [PATCH 03/14] remove commented code --- .../src/proof_system/bn128/utils/bellman.rs | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/zokrates_core/src/proof_system/bn128/utils/bellman.rs b/zokrates_core/src/proof_system/bn128/utils/bellman.rs index 5f7c1bb2..f1b9668c 100644 --- a/zokrates_core/src/proof_system/bn128/utils/bellman.rs +++ b/zokrates_core/src/proof_system/bn128/utils/bellman.rs @@ -259,28 +259,6 @@ mod parse { let captures = FR_REGEX.captures(&raw_e).unwrap(); captures.name(&"x").unwrap().as_str().to_string() } - - /* - pub fn parse_g1_hex( - e: &::G1Affine, - ) -> String { - let parsed = parse_g1::(e); - format!("{}, {}", parsed.0, parsed.1) - } - - pub fn parse_g2_hex( - e: &::G2Affine, - ) -> String { - let parsed = parse_g2::(e); - format!( - "[{}, {}], [{}, {}]", - (parsed.0).0, - (parsed.0).1, - (parsed.1).0, - (parsed.1).1 - ) - } - */ } #[cfg(test)] From 17c51ba500c03b0bc085564db925b2e8767a2fd8 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 13 May 2020 15:46:53 +0200 Subject: [PATCH 04/14] fix cpp format, change proof system folder structure --- zokrates_cli/src/bin.rs | 5 +-- zokrates_core/lib/gm17.cpp | 3 +- .../{bn128/g16.rs => bellman/groth16.rs} | 10 +++--- .../utils/bellman.rs => bellman/mod.rs} | 4 ++- zokrates_core/src/proof_system/bn128/mod.rs | 31 ------------------- .../src/proof_system/bn128/utils/mod.rs | 6 ---- .../{bn128/utils => libsnark}/ffi.rs | 0 .../proof_system/{bn128 => libsnark}/gm17.rs | 11 +++---- .../utils/libsnark.rs => libsnark/mod.rs} | 4 +++ .../{bn128 => libsnark}/pghr13.rs | 11 +++---- zokrates_core/src/proof_system/mod.rs | 28 +++++++++++++---- .../{bn128/utils => }/solidity.rs | 0 12 files changed, 46 insertions(+), 67 deletions(-) rename zokrates_core/src/proof_system/{bn128/g16.rs => bellman/groth16.rs} (97%) rename zokrates_core/src/proof_system/{bn128/utils/bellman.rs => bellman/mod.rs} (99%) delete mode 100644 zokrates_core/src/proof_system/bn128/mod.rs delete mode 100644 zokrates_core/src/proof_system/bn128/utils/mod.rs rename zokrates_core/src/proof_system/{bn128/utils => libsnark}/ffi.rs (100%) rename zokrates_core/src/proof_system/{bn128 => libsnark}/gm17.rs (97%) rename zokrates_core/src/proof_system/{bn128/utils/libsnark.rs => libsnark/mod.rs} (99%) rename zokrates_core/src/proof_system/{bn128 => libsnark}/pghr13.rs (97%) rename zokrates_core/src/proof_system/{bn128/utils => }/solidity.rs (100%) diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index c5c8acec..fb8da229 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -18,6 +18,9 @@ use std::string::String; use zokrates_abi::Encode; use zokrates_core::compile::{compile, CompilationArtifacts, CompileError}; use zokrates_core::ir::{self, ProgEnum}; +use zokrates_core::proof_system::bellman::groth16::G16; +use zokrates_core::proof_system::libsnark::gm17::GM17; +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}; @@ -681,8 +684,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) diff --git a/zokrates_core/lib/gm17.cpp b/zokrates_core/lib/gm17.cpp index 32065e26..60248db8 100644 --- a/zokrates_core/lib/gm17.cpp +++ b/zokrates_core/lib/gm17.cpp @@ -96,7 +96,8 @@ std::string serializeVerificationKey(r1cs_se_ppzksnark_verification_keyH_gamma) << ","; ss << "\"query\":["; for (size_t i = 0; i < queryLength; ++i) { - if (i != 0) ss << ","; + if (i != 0) + ss << ","; ss << outputPointG1AffineAsHexJson(vk->query[i]); } ss << "],"; diff --git a/zokrates_core/src/proof_system/bn128/g16.rs b/zokrates_core/src/proof_system/bellman/groth16.rs similarity index 97% rename from zokrates_core/src/proof_system/bn128/g16.rs rename to zokrates_core/src/proof_system/bellman/groth16.rs index ce592a9e..5e4eedca 100644 --- a/zokrates_core/src/proof_system/bn128/g16.rs +++ b/zokrates_core/src/proof_system/bellman/groth16.rs @@ -7,14 +7,12 @@ 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_g2}; -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::{G1Affine, G2Affine}; -use proof_system::{Proof, 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."; diff --git a/zokrates_core/src/proof_system/bn128/utils/bellman.rs b/zokrates_core/src/proof_system/bellman/mod.rs similarity index 99% rename from zokrates_core/src/proof_system/bn128/utils/bellman.rs rename to zokrates_core/src/proof_system/bellman/mod.rs index f1b9668c..54e9a1c4 100644 --- a/zokrates_core/src/proof_system/bn128/utils/bellman.rs +++ b/zokrates_core/src/proof_system/bellman/mod.rs @@ -1,3 +1,5 @@ +pub mod groth16; + extern crate rand; use crate::ir::{CanonicalLinComb, Prog, Statement, Witness}; @@ -209,7 +211,7 @@ mod parse { use lazy_static::lazy_static; use super::*; - use proof_system::bn128::{G1Affine, G2Affine}; + use proof_system::{G1Affine, G2Affine}; use regex::Regex; lazy_static! { diff --git a/zokrates_core/src/proof_system/bn128/mod.rs b/zokrates_core/src/proof_system/bn128/mod.rs deleted file mode 100644 index 33b6c57f..00000000 --- a/zokrates_core/src/proof_system/bn128/mod.rs +++ /dev/null @@ -1,31 +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; - -#[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()) - } -} diff --git a/zokrates_core/src/proof_system/bn128/utils/mod.rs b/zokrates_core/src/proof_system/bn128/utils/mod.rs deleted file mode 100644 index 1aa80a4e..00000000 --- a/zokrates_core/src/proof_system/bn128/utils/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod bellman; -#[cfg(feature = "libsnark")] -pub mod ffi; -#[cfg(feature = "libsnark")] -pub mod libsnark; -pub mod solidity; diff --git a/zokrates_core/src/proof_system/bn128/utils/ffi.rs b/zokrates_core/src/proof_system/libsnark/ffi.rs similarity index 100% rename from zokrates_core/src/proof_system/bn128/utils/ffi.rs rename to zokrates_core/src/proof_system/libsnark/ffi.rs diff --git a/zokrates_core/src/proof_system/bn128/gm17.rs b/zokrates_core/src/proof_system/libsnark/gm17.rs similarity index 97% rename from zokrates_core/src/proof_system/bn128/gm17.rs rename to zokrates_core/src/proof_system/libsnark/gm17.rs index cba4ca37..90e36360 100644 --- a/zokrates_core/src/proof_system/bn128/gm17.rs +++ b/zokrates_core/src/proof_system/libsnark/gm17.rs @@ -1,13 +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::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::{G1Affine, G2Affine}; -use proof_system::{Proof, ProofSystem, SetupKeypair, SolidityAbi}; +use proof_system::{G1Affine, G2Affine, Proof, ProofSystem, SetupKeypair, SolidityAbi}; use regex::Regex; use zokrates_field::Bn128Field; diff --git a/zokrates_core/src/proof_system/bn128/utils/libsnark.rs b/zokrates_core/src/proof_system/libsnark/mod.rs similarity index 99% rename from zokrates_core/src/proof_system/bn128/utils/libsnark.rs rename to zokrates_core/src/proof_system/libsnark/mod.rs index 1297488c..e7f5af82 100644 --- a/zokrates_core/src/proof_system/bn128/utils/libsnark.rs +++ b/zokrates_core/src/proof_system/libsnark/mod.rs @@ -1,3 +1,7 @@ +mod ffi; +pub mod gm17; +pub mod pghr13; + use flat_absy::FlatVariable; use ir::{self, Statement}; use std::cmp::max; diff --git a/zokrates_core/src/proof_system/bn128/pghr13.rs b/zokrates_core/src/proof_system/libsnark/pghr13.rs similarity index 97% rename from zokrates_core/src/proof_system/bn128/pghr13.rs rename to zokrates_core/src/proof_system/libsnark/pghr13.rs index e42a9130..c8d1a679 100644 --- a/zokrates_core/src/proof_system/bn128/pghr13.rs +++ b/zokrates_core/src/proof_system/libsnark/pghr13.rs @@ -1,13 +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::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::{G1Affine, G2Affine}; -use proof_system::{Proof, ProofSystem, SetupKeypair, SolidityAbi}; +use proof_system::{G1Affine, G2Affine, Proof, ProofSystem, SetupKeypair, SolidityAbi}; use regex::Regex; use zokrates_field::Bn128Field; diff --git a/zokrates_core/src/proof_system/mod.rs b/zokrates_core/src/proof_system/mod.rs index 0f9e1243..e0fde479 100644 --- a/zokrates_core/src/proof_system/mod.rs +++ b/zokrates_core/src/proof_system/mod.rs @@ -1,10 +1,8 @@ -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; @@ -57,6 +55,24 @@ impl Proof { } } +#[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 where Self::VerificationKey: Serialize + DeserializeOwned, diff --git a/zokrates_core/src/proof_system/bn128/utils/solidity.rs b/zokrates_core/src/proof_system/solidity.rs similarity index 100% rename from zokrates_core/src/proof_system/bn128/utils/solidity.rs rename to zokrates_core/src/proof_system/solidity.rs From c81f1fe629ff0191edc1cc7ab64e8a040d502918 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 13 May 2020 18:07:06 +0200 Subject: [PATCH 05/14] fix imports --- zokrates_cli/src/bin.rs | 2 ++ zokrates_core/src/proof_system/libsnark/mod.rs | 2 +- zokrates_core/tests/wasm.rs | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index fb8da229..88695ee3 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -19,7 +19,9 @@ use zokrates_abi::Encode; use zokrates_core::compile::{compile, CompilationArtifacts, 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; diff --git a/zokrates_core/src/proof_system/libsnark/mod.rs b/zokrates_core/src/proof_system/libsnark/mod.rs index e7f5af82..d67baada 100644 --- a/zokrates_core/src/proof_system/libsnark/mod.rs +++ b/zokrates_core/src/proof_system/libsnark/mod.rs @@ -1,4 +1,4 @@ -mod ffi; +pub mod ffi; pub mod gm17; pub mod pghr13; diff --git a/zokrates_core/tests/wasm.rs b/zokrates_core/tests/wasm.rs index b5e9a692..c68e34c1 100644 --- a/zokrates_core/tests/wasm.rs +++ b/zokrates_core/tests/wasm.rs @@ -9,7 +9,7 @@ use zokrates_core::ir::{Function, 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() { From ef2c4468951f45222c3f5c0af65d2242ce0d303f Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 13 May 2020 18:38:19 +0200 Subject: [PATCH 06/14] fix naming in proof --- zokrates_cli/src/bin.rs | 4 ++-- zokrates_cli/tests/contract/test.js | 1 + zokrates_core/lib/gm17.cpp | 2 +- zokrates_core/lib/pghr13.cpp | 2 +- zokrates_core/src/proof_system/libsnark/mod.rs | 2 +- zokrates_core/src/proof_system/mod.rs | 10 +++------- zokrates_js/index.d.ts | 4 ++-- zokrates_js/src/lib.rs | 9 +++++---- 8 files changed, 16 insertions(+), 18 deletions(-) diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index 88695ee3..42fb9add 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -795,7 +795,7 @@ fn cli() -> Result<(), String> { "json" => { println!("~~~~~~~~ Copy the output below for valid ABIv2 format ~~~~~~~~"); println!(); - print!("{}", proof_object["points"]); + print!("{}", proof_object["proof"]); print!(","); println!("{}", proof_object["inputs"]); println!(); @@ -805,7 +805,7 @@ fn cli() -> Result<(), String> { println!("~~~~~~~~ Copy the output below for valid ABIv1 format ~~~~~~~~"); println!(); - for (_, value) in proof_object["points"].as_object().unwrap().iter() { + for (_, value) in proof_object["proof"].as_object().unwrap().iter() { print!("{}", value); print!(","); } diff --git a/zokrates_cli/tests/contract/test.js b/zokrates_cli/tests/contract/test.js index cb222406..9b27f921 100644 --- a/zokrates_cli/tests/contract/test.js +++ b/zokrates_cli/tests/contract/test.js @@ -64,6 +64,7 @@ let jsonInterface = JSON.parse(solc.compile(jsonContractSource)); function makeTransaction(account, correct) { let proof = getProof(correct); + console.log(proof) function handleReceipt(tx) { if (tx.status == true && !correct) { diff --git a/zokrates_core/lib/gm17.cpp b/zokrates_core/lib/gm17.cpp index 60248db8..7421aa55 100644 --- a/zokrates_core/lib/gm17.cpp +++ b/zokrates_core/lib/gm17.cpp @@ -111,7 +111,7 @@ std::string serializeProof(r1cs_se_ppzksnark_proof* proof, { std::stringstream ss; ss << "{"; - ss << "\"points\":{"; + ss << "\"proof\":{"; ss << "\"a\":" << outputPointG1AffineAsHexJson(proof->A) << ","; ss << "\"b\":" << outputPointG2AffineAsHexJson(proof->B) << ","; ss << "\"c\":" << outputPointG1AffineAsHexJson(proof->C); diff --git a/zokrates_core/lib/pghr13.cpp b/zokrates_core/lib/pghr13.cpp index c791caba..5fa03840 100644 --- a/zokrates_core/lib/pghr13.cpp +++ b/zokrates_core/lib/pghr13.cpp @@ -114,7 +114,7 @@ std::string serializeProof(r1cs_ppzksnark_proof* proof, con { std::stringstream ss; ss << "{"; - ss << "\"points\":{"; + ss << "\"proof\":{"; ss << "\"a\":" << outputPointG1AffineAsHexJson(proof->g_A.g) << ","; ss << "\"a_p\":" << outputPointG1AffineAsHexJson(proof->g_A.h) << ","; ss << "\"b\":" << outputPointG2AffineAsHexJson(proof->g_B.g) << ","; diff --git a/zokrates_core/src/proof_system/libsnark/mod.rs b/zokrates_core/src/proof_system/libsnark/mod.rs index d67baada..e7f5af82 100644 --- a/zokrates_core/src/proof_system/libsnark/mod.rs +++ b/zokrates_core/src/proof_system/libsnark/mod.rs @@ -1,4 +1,4 @@ -pub mod ffi; +mod ffi; pub mod gm17; pub mod pghr13; diff --git a/zokrates_core/src/proof_system/mod.rs b/zokrates_core/src/proof_system/mod.rs index e0fde479..c5eb20fd 100644 --- a/zokrates_core/src/proof_system/mod.rs +++ b/zokrates_core/src/proof_system/mod.rs @@ -40,18 +40,14 @@ impl SolidityAbi { #[derive(Serialize, Deserialize)] pub struct Proof { - points: T, + proof: T, inputs: Vec, raw: String, } impl Proof { - fn new(points: T, inputs: Vec, raw: String) -> Self { - Proof { - points, - inputs, - raw, - } + fn new(proof: T, inputs: Vec, raw: String) -> Self { + Proof { proof, inputs, raw } } } diff --git a/zokrates_js/index.d.ts b/zokrates_js/index.d.ts index e6164936..8728c4bf 100644 --- a/zokrates_js/index.d.ts +++ b/zokrates_js/index.d.ts @@ -20,7 +20,7 @@ declare module 'zokrates-js' { } export interface Proof { - points: ProofPoints, + proof: ProofPoints, inputs: string[], raw: string } @@ -46,7 +46,7 @@ declare module 'zokrates-js' { } export type SolidityAbi = "v1" | "v2"; - export type ResolveCallback = (location: string, path: string) => ResolverResult;krat + export type ResolveCallback = (location: string, path: string) => ResolverResult; export interface ZoKratesProvider { compile(source: string, location: string, callback: ResolveCallback): CompilationArtifacts; diff --git a/zokrates_js/src/lib.rs b/zokrates_js/src/lib.rs index f3410e47..2b6ab4bb 100644 --- a/zokrates_js/src/lib.rs +++ b/zokrates_js/src/lib.rs @@ -8,7 +8,8 @@ use zokrates_common::Resolver; use zokrates_core::compile::{compile as core_compile, CompilationArtifacts, 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; @@ -157,7 +158,7 @@ pub fn compute_witness(artifacts: JsValue, args: JsValue) -> Result Result { let input: Vec = 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()) } @@ -166,7 +167,7 @@ pub fn export_solidity_verifier(vk: JsValue, abi_version: JsValue) -> Result>::export_solidity_verifier( + let verifier = >::export_solidity_verifier( vk.into_serde().unwrap(), abi_version, ); @@ -184,7 +185,7 @@ 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 = 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_serde(&proof).unwrap()) } From 1ae0856b75dba042211e9fcfda4cc373a0e4e1db Mon Sep 17 00:00:00 2001 From: dark64 Date: Fri, 15 May 2020 18:05:06 +0200 Subject: [PATCH 07/14] add backend flag to cli --- zokrates_cli/src/bin.rs | 184 +++++++++++++++++++++--------- zokrates_cli/src/constants.rs | 8 ++ zokrates_cli/tests/integration.rs | 144 +++++++++++++---------- 3 files changed, 219 insertions(+), 117 deletions(-) diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index 42fb9add..ed7504fa 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -390,6 +390,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"; @@ -464,11 +465,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) @@ -505,6 +513,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") @@ -606,6 +622,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") @@ -655,6 +679,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") @@ -699,6 +731,7 @@ fn cli() -> Result<(), String> { } } ("setup", Some(sub_matches)) => { + let backend = sub_matches.value_of("backend").unwrap(); let proof_system = sub_matches.value_of("proving-scheme").unwrap(); // read compiled program @@ -707,51 +740,70 @@ fn cli() -> Result<(), String> { .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)?, + match backend { + constants::BELLMAN => { + 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), + }, + _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), + }? }, #[cfg(feature = "libsnark")] - constants::PGHR13 => match prog { - ProgEnum::Bn128Program(p) => cli_setup::<_, PGHR13>(p, sub_matches)?, - _ => unimplemented!(), + constants::LIBSNARK => { + match proof_system { + constants::PGHR13 => match prog { + ProgEnum::Bn128Program(p) => cli_setup::<_, PGHR13>(p, sub_matches), + _ => unimplemented!(), + }, + constants::GM17 => match prog { + ProgEnum::Bn128Program(p) => cli_setup::<_, GM17>(p, sub_matches), + _ => unimplemented!(), + }, + _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), + }? }, - #[cfg(feature = "libsnark")] - constants::GM17 => match prog { - ProgEnum::Bn128Program(p) => cli_setup::<_, GM17>(p, sub_matches)?, - _ => unimplemented!(), - }, - _ => unreachable!(), + _ => unreachable!() } } ("export-verifier", Some(sub_matches)) => { let curve = sub_matches.value_of("curve").unwrap(); + let backend = sub_matches.value_of("backend").unwrap(); let proof_system = sub_matches.value_of("proving-scheme").unwrap(); - match proof_system { - constants::G16 => match curve { - constants::BN128 => cli_export_verifier::(sub_matches)?, - constants::BLS12_381 => cli_export_verifier::(sub_matches)?, - _ => unimplemented!(), + match backend { + constants::BELLMAN => { + match proof_system { + constants::G16 => match curve { + constants::BN128 => cli_export_verifier::(sub_matches), + constants::BLS12_381 => cli_export_verifier::(sub_matches), + _ => unimplemented!(), + }, + _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), + }? }, #[cfg(feature = "libsnark")] - constants::PGHR13 => match curve { - constants::BN128 => cli_export_verifier::(sub_matches)?, - _ => unimplemented!(), + constants::LIBSNARK => { + match proof_system { + constants::PGHR13 => match curve { + constants::BN128 => cli_export_verifier::(sub_matches), + _ => unimplemented!(), + }, + constants::GM17 => match curve { + constants::BN128 => cli_export_verifier::(sub_matches), + _ => unimplemented!(), + }, + _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), + }? }, - #[cfg(feature = "libsnark")] - constants::GM17 => match curve { - constants::BN128 => cli_export_verifier::(sub_matches)?, - _ => unimplemented!(), - }, - _ => unreachable!(), + _ => unreachable!() } } ("generate-proof", Some(sub_matches)) => { + let backend = sub_matches.value_of("backend").unwrap(); let proof_system = sub_matches.value_of("proving-scheme").unwrap(); let program_path = Path::new(sub_matches.value_of("input").unwrap()); @@ -759,25 +811,33 @@ fn cli() -> Result<(), String> { .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)?, + match backend { + constants::BELLMAN => { + 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), + }, + _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), + }? }, #[cfg(feature = "libsnark")] - constants::PGHR13 => match prog { - ProgEnum::Bn128Program(p) => cli_generate_proof::<_, PGHR13>(p, sub_matches)?, - _ => unimplemented!(), + constants::LIBSNARK => { + match proof_system { + constants::PGHR13 => match prog { + ProgEnum::Bn128Program(p) => cli_generate_proof::<_, PGHR13>(p, sub_matches), + _ => unimplemented!(), + }, + constants::GM17 => match prog { + ProgEnum::Bn128Program(p) => cli_generate_proof::<_, GM17>(p, sub_matches), + _ => unimplemented!(), + }, + _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), + }? }, - #[cfg(feature = "libsnark")] - constants::GM17 => match prog { - ProgEnum::Bn128Program(p) => cli_generate_proof::<_, GM17>(p, sub_matches)?, - _ => unimplemented!(), - }, - _ => unreachable!(), + _ => unreachable!() } } ("print-proof", Some(sub_matches)) => { @@ -819,25 +879,35 @@ fn cli() -> Result<(), String> { } ("verify", Some(sub_matches)) => { let curve = sub_matches.value_of("curve").unwrap(); + let backend = sub_matches.value_of("backend").unwrap(); let proof_system = sub_matches.value_of("proving-scheme").unwrap(); - match proof_system { - constants::G16 => match curve { - constants::BN128 => cli_verify::(sub_matches)?, - constants::BLS12_381 => cli_verify::(sub_matches)?, - _ => unimplemented!(), + match backend { + constants::BELLMAN => { + match proof_system { + constants::G16 => match curve { + constants::BN128 => cli_verify::(sub_matches), + constants::BLS12_381 => cli_verify::(sub_matches), + _ => unimplemented!(), + }, + _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), + }? }, #[cfg(feature = "libsnark")] - constants::PGHR13 => match curve { - constants::BN128 => cli_verify::(sub_matches)?, - _ => unimplemented!(), + constants::LIBSNARK => { + match proof_system { + constants::PGHR13 => match curve { + constants::BN128 => cli_verify::(sub_matches), + _ => unimplemented!(), + }, + constants::GM17 => match curve { + constants::BN128 => cli_verify::(sub_matches), + _ => unimplemented!(), + }, + _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), + }? }, - #[cfg(feature = "libsnark")] - constants::GM17 => match curve { - constants::BN128 => cli_verify::(sub_matches)?, - _ => unimplemented!(), - }, - _ => unreachable!(), + _ => unreachable!() } } _ => unreachable!(), diff --git a/zokrates_cli/src/constants.rs b/zokrates_cli/src/constants.rs index 1b51a4fc..5ffa8c43 100644 --- a/zokrates_cli/src/constants.rs +++ b/zokrates_cli/src/constants.rs @@ -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]; diff --git a/zokrates_cli/tests/integration.rs b/zokrates_cli/tests/integration.rs index 60c0a4d9..a039e05c 100644 --- a/zokrates_cli/tests/integration.rs +++ b/zokrates_cli/tests/integration.rs @@ -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,85 @@ 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(); + } } + } } From 8286587eb57c7204ad02ee1ad5093d1bdb16958c Mon Sep 17 00:00:00 2001 From: dark64 Date: Fri, 15 May 2020 18:06:08 +0200 Subject: [PATCH 08/14] format --- zokrates_cli/src/bin.rs | 198 ++++++++++++++++-------------- zokrates_cli/tests/integration.rs | 5 +- 2 files changed, 106 insertions(+), 97 deletions(-) diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index ed7504fa..4119bcaa 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -743,30 +743,32 @@ fn cli() -> Result<(), String> { let prog = ProgEnum::deserialize(&mut reader)?; match backend { - constants::BELLMAN => { - 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), - }, - _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), - }? - }, + constants::BELLMAN => 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), + }, + _ => Err(format!( + "Proving scheme {} is not supported by {} backend", + proof_system, backend + )), + }?, #[cfg(feature = "libsnark")] - constants::LIBSNARK => { - match proof_system { - constants::PGHR13 => match prog { - ProgEnum::Bn128Program(p) => cli_setup::<_, PGHR13>(p, sub_matches), - _ => unimplemented!(), - }, - constants::GM17 => match prog { - ProgEnum::Bn128Program(p) => cli_setup::<_, GM17>(p, sub_matches), - _ => unimplemented!(), - }, - _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), - }? - }, - _ => unreachable!() + constants::LIBSNARK => match proof_system { + constants::PGHR13 => match prog { + ProgEnum::Bn128Program(p) => cli_setup::<_, PGHR13>(p, sub_matches), + _ => unimplemented!(), + }, + constants::GM17 => match prog { + ProgEnum::Bn128Program(p) => cli_setup::<_, GM17>(p, sub_matches), + _ => unimplemented!(), + }, + _ => Err(format!( + "Proving scheme {} is not supported by {} backend", + proof_system, backend + )), + }?, + _ => unreachable!(), } } ("export-verifier", Some(sub_matches)) => { @@ -775,31 +777,33 @@ fn cli() -> Result<(), String> { let proof_system = sub_matches.value_of("proving-scheme").unwrap(); match backend { - constants::BELLMAN => { - match proof_system { - constants::G16 => match curve { - constants::BN128 => cli_export_verifier::(sub_matches), - constants::BLS12_381 => cli_export_verifier::(sub_matches), - _ => unimplemented!(), - }, - _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), - }? - }, + constants::BELLMAN => match proof_system { + constants::G16 => match curve { + constants::BN128 => cli_export_verifier::(sub_matches), + constants::BLS12_381 => cli_export_verifier::(sub_matches), + _ => unimplemented!(), + }, + _ => Err(format!( + "Proving scheme {} is not supported by {} backend", + proof_system, backend + )), + }?, #[cfg(feature = "libsnark")] - constants::LIBSNARK => { - match proof_system { - constants::PGHR13 => match curve { - constants::BN128 => cli_export_verifier::(sub_matches), - _ => unimplemented!(), - }, - constants::GM17 => match curve { - constants::BN128 => cli_export_verifier::(sub_matches), - _ => unimplemented!(), - }, - _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), - }? - }, - _ => unreachable!() + constants::LIBSNARK => match proof_system { + constants::PGHR13 => match curve { + constants::BN128 => cli_export_verifier::(sub_matches), + _ => unimplemented!(), + }, + constants::GM17 => match curve { + constants::BN128 => cli_export_verifier::(sub_matches), + _ => unimplemented!(), + }, + _ => Err(format!( + "Proving scheme {} is not supported by {} backend", + proof_system, backend + )), + }?, + _ => unreachable!(), } } ("generate-proof", Some(sub_matches)) => { @@ -814,30 +818,34 @@ fn cli() -> Result<(), String> { let prog = ProgEnum::deserialize(&mut reader)?; match backend { - constants::BELLMAN => { - 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), - }, - _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), - }? - }, + constants::BELLMAN => 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), + }, + _ => Err(format!( + "Proving scheme {} is not supported by {} backend", + proof_system, backend + )), + }?, #[cfg(feature = "libsnark")] - constants::LIBSNARK => { - match proof_system { - constants::PGHR13 => match prog { - ProgEnum::Bn128Program(p) => cli_generate_proof::<_, PGHR13>(p, sub_matches), - _ => unimplemented!(), - }, - constants::GM17 => match prog { - ProgEnum::Bn128Program(p) => cli_generate_proof::<_, GM17>(p, sub_matches), - _ => unimplemented!(), - }, - _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), - }? - }, - _ => unreachable!() + constants::LIBSNARK => match proof_system { + constants::PGHR13 => match prog { + ProgEnum::Bn128Program(p) => { + cli_generate_proof::<_, PGHR13>(p, sub_matches) + } + _ => unimplemented!(), + }, + constants::GM17 => match prog { + ProgEnum::Bn128Program(p) => cli_generate_proof::<_, GM17>(p, sub_matches), + _ => unimplemented!(), + }, + _ => Err(format!( + "Proving scheme {} is not supported by {} backend", + proof_system, backend + )), + }?, + _ => unreachable!(), } } ("print-proof", Some(sub_matches)) => { @@ -883,31 +891,33 @@ fn cli() -> Result<(), String> { let proof_system = sub_matches.value_of("proving-scheme").unwrap(); match backend { - constants::BELLMAN => { - match proof_system { - constants::G16 => match curve { - constants::BN128 => cli_verify::(sub_matches), - constants::BLS12_381 => cli_verify::(sub_matches), - _ => unimplemented!(), - }, - _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), - }? - }, + constants::BELLMAN => match proof_system { + constants::G16 => match curve { + constants::BN128 => cli_verify::(sub_matches), + constants::BLS12_381 => cli_verify::(sub_matches), + _ => unimplemented!(), + }, + _ => Err(format!( + "Proving scheme {} is not supported by {} backend", + proof_system, backend + )), + }?, #[cfg(feature = "libsnark")] - constants::LIBSNARK => { - match proof_system { - constants::PGHR13 => match curve { - constants::BN128 => cli_verify::(sub_matches), - _ => unimplemented!(), - }, - constants::GM17 => match curve { - constants::BN128 => cli_verify::(sub_matches), - _ => unimplemented!(), - }, - _ => Err(format!("Proving scheme {} is not supported by {} backend", proof_system, backend)), - }? - }, - _ => unreachable!() + constants::LIBSNARK => match proof_system { + constants::PGHR13 => match curve { + constants::BN128 => cli_verify::(sub_matches), + _ => unimplemented!(), + }, + constants::GM17 => match curve { + constants::BN128 => cli_verify::(sub_matches), + _ => unimplemented!(), + }, + _ => Err(format!( + "Proving scheme {} is not supported by {} backend", + proof_system, backend + )), + }?, + _ => unreachable!(), } } _ => unreachable!(), diff --git a/zokrates_cli/tests/integration.rs b/zokrates_cli/tests/integration.rs index a039e05c..1266d60b 100644 --- a/zokrates_cli/tests/integration.rs +++ b/zokrates_cli/tests/integration.rs @@ -205,13 +205,13 @@ mod integration { } #[cfg(feature = "libsnark")] - let backends = map!{ + let backends = map! { "bellman" => ["g16"], "libsnark" => ["gm17", "pghr13"] }; #[cfg(not(feature = "libsnark"))] - let backends = map!{"bellman" => ["g16"]}; + let backends = map! {"bellman" => ["g16"]}; for (backend, schemes) in backends { for scheme in &schemes { @@ -284,6 +284,5 @@ mod integration { .unwrap(); } } - } } From c8966a309d6d9c296d788d9a3a9e7ab0ac961cc3 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 20 May 2020 14:46:46 +0200 Subject: [PATCH 09/14] add enums for backend, curve and proving scheme dimension --- zokrates_cli/src/bin.rs | 224 ++++++++---------- zokrates_cli/src/helpers.rs | 96 ++++++++ zokrates_cli/tests/contract/test.js | 1 - .../src/proof_system/libsnark/mod.rs | 2 +- 4 files changed, 195 insertions(+), 128 deletions(-) create mode 100644 zokrates_cli/src/helpers.rs diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index 4119bcaa..11ad5b8f 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -5,11 +5,14 @@ // @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}; @@ -709,12 +712,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::(sub_matches)?, - constants::BLS12_381 => cli_compile::(sub_matches)?, - _ => unreachable!(), + Curve::Bn128 => cli_compile::(sub_matches)?, + Curve::Bls12 => cli_compile::(sub_matches)?, } } ("compute-witness", Some(sub_matches)) => { @@ -731,9 +732,6 @@ fn cli() -> Result<(), String> { } } ("setup", Some(sub_matches)) => { - let backend = sub_matches.value_of("backend").unwrap(); - 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) @@ -742,74 +740,61 @@ fn cli() -> Result<(), String> { let mut reader = BufReader::new(file); let prog = ProgEnum::deserialize(&mut reader)?; - match backend { - constants::BELLMAN => 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), - }, - _ => Err(format!( - "Proving scheme {} is not supported by {} backend", - proof_system, backend - )), - }?, + 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")] + Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::GM17) => match prog { + ProgEnum::Bn128Program(p) => cli_setup::<_, GM17>(p, sub_matches), + _ => unreachable!(), + }, + #[cfg(feature = "libsnark")] + Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::PGHR13) => match prog { + ProgEnum::Bn128Program(p) => cli_setup::<_, PGHR13>(p, sub_matches), + _ => unreachable!(), + }, #[cfg(feature = "libsnark")] - constants::LIBSNARK => match proof_system { - constants::PGHR13 => match prog { - ProgEnum::Bn128Program(p) => cli_setup::<_, PGHR13>(p, sub_matches), - _ => unimplemented!(), - }, - constants::GM17 => match prog { - ProgEnum::Bn128Program(p) => cli_setup::<_, GM17>(p, sub_matches), - _ => unimplemented!(), - }, - _ => Err(format!( - "Proving scheme {} is not supported by {} backend", - proof_system, backend - )), - }?, _ => unreachable!(), - } + }? } ("export-verifier", Some(sub_matches)) => { - let curve = sub_matches.value_of("curve").unwrap(); - let backend = sub_matches.value_of("backend").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 backend { - constants::BELLMAN => match proof_system { - constants::G16 => match curve { - constants::BN128 => cli_export_verifier::(sub_matches), - constants::BLS12_381 => cli_export_verifier::(sub_matches), - _ => unimplemented!(), - }, - _ => Err(format!( - "Proving scheme {} is not supported by {} backend", - proof_system, backend - )), - }?, + match dimensions { + Dimensions(Backend::Bellman, Curve::Bn128, ProvingScheme::G16) => { + cli_export_verifier::(sub_matches) + } + Dimensions(Backend::Bellman, Curve::Bls12, ProvingScheme::G16) => { + cli_export_verifier::(sub_matches) + } + #[cfg(feature = "libsnark")] + Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::GM17) => { + cli_export_verifier::(sub_matches) + } + #[cfg(feature = "libsnark")] + Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::PGHR13) => { + cli_export_verifier::(sub_matches) + } #[cfg(feature = "libsnark")] - constants::LIBSNARK => match proof_system { - constants::PGHR13 => match curve { - constants::BN128 => cli_export_verifier::(sub_matches), - _ => unimplemented!(), - }, - constants::GM17 => match curve { - constants::BN128 => cli_export_verifier::(sub_matches), - _ => unimplemented!(), - }, - _ => Err(format!( - "Proving scheme {} is not supported by {} backend", - proof_system, backend - )), - }?, _ => unreachable!(), - } + }? } ("generate-proof", Some(sub_matches)) => { - let backend = sub_matches.value_of("backend").unwrap(); - 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))?; @@ -817,40 +802,36 @@ fn cli() -> Result<(), String> { let mut reader = BufReader::new(program_file); let prog = ProgEnum::deserialize(&mut reader)?; - match backend { - constants::BELLMAN => 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), - }, - _ => Err(format!( - "Proving scheme {} is not supported by {} backend", - proof_system, backend - )), - }?, + 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")] + Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::GM17) => match prog { + ProgEnum::Bn128Program(p) => cli_generate_proof::<_, GM17>(p, sub_matches), + _ => unreachable!(), + }, + #[cfg(feature = "libsnark")] + Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::PGHR13) => match prog { + ProgEnum::Bn128Program(p) => cli_generate_proof::<_, PGHR13>(p, sub_matches), + _ => unreachable!(), + }, #[cfg(feature = "libsnark")] - constants::LIBSNARK => match proof_system { - constants::PGHR13 => match prog { - ProgEnum::Bn128Program(p) => { - cli_generate_proof::<_, PGHR13>(p, sub_matches) - } - _ => unimplemented!(), - }, - constants::GM17 => match prog { - ProgEnum::Bn128Program(p) => cli_generate_proof::<_, GM17>(p, sub_matches), - _ => unimplemented!(), - }, - _ => Err(format!( - "Proving scheme {} is not supported by {} backend", - proof_system, backend - )), - }?, _ => 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) @@ -886,39 +867,30 @@ fn cli() -> Result<(), String> { } } ("verify", Some(sub_matches)) => { - let curve = sub_matches.value_of("curve").unwrap(); - let backend = sub_matches.value_of("backend").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 backend { - constants::BELLMAN => match proof_system { - constants::G16 => match curve { - constants::BN128 => cli_verify::(sub_matches), - constants::BLS12_381 => cli_verify::(sub_matches), - _ => unimplemented!(), - }, - _ => Err(format!( - "Proving scheme {} is not supported by {} backend", - proof_system, backend - )), - }?, + match dimensions { + Dimensions(Backend::Bellman, Curve::Bn128, ProvingScheme::G16) => { + cli_verify::(sub_matches) + } + Dimensions(Backend::Bellman, Curve::Bls12, ProvingScheme::G16) => { + cli_verify::(sub_matches) + } + #[cfg(feature = "libsnark")] + Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::GM17) => { + cli_verify::(sub_matches) + } + #[cfg(feature = "libsnark")] + Dimensions(Backend::Libsnark, Curve::Bn128, ProvingScheme::PGHR13) => { + cli_verify::(sub_matches) + } #[cfg(feature = "libsnark")] - constants::LIBSNARK => match proof_system { - constants::PGHR13 => match curve { - constants::BN128 => cli_verify::(sub_matches), - _ => unimplemented!(), - }, - constants::GM17 => match curve { - constants::BN128 => cli_verify::(sub_matches), - _ => unimplemented!(), - }, - _ => Err(format!( - "Proving scheme {} is not supported by {} backend", - proof_system, backend - )), - }?, _ => unreachable!(), - } + }? } _ => unreachable!(), } diff --git a/zokrates_cli/src/helpers.rs b/zokrates_cli/src/helpers.rs new file mode 100644 index 00000000..08f7a534 --- /dev/null +++ b/zokrates_cli/src/helpers.rs @@ -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 { + 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 { + 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 { + 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 { + 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: {}, proof system: {})", + s.0, s.1, s.2 + )), + } + } +} diff --git a/zokrates_cli/tests/contract/test.js b/zokrates_cli/tests/contract/test.js index 9b27f921..cb222406 100644 --- a/zokrates_cli/tests/contract/test.js +++ b/zokrates_cli/tests/contract/test.js @@ -64,7 +64,6 @@ let jsonInterface = JSON.parse(solc.compile(jsonContractSource)); function makeTransaction(account, correct) { let proof = getProof(correct); - console.log(proof) function handleReceipt(tx) { if (tx.status == true && !correct) { diff --git a/zokrates_core/src/proof_system/libsnark/mod.rs b/zokrates_core/src/proof_system/libsnark/mod.rs index e7f5af82..4868ec46 100644 --- a/zokrates_core/src/proof_system/libsnark/mod.rs +++ b/zokrates_core/src/proof_system/libsnark/mod.rs @@ -297,7 +297,7 @@ pub fn r1cs_program( 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) } From 41b361e6c4ceabefe87e8128c24fca5361dc39de Mon Sep 17 00:00:00 2001 From: Darko Date: Thu, 21 May 2020 16:41:06 +0200 Subject: [PATCH 10/14] refactor libsnark cpp --- scripts/clang-format.sh | 2 +- zokrates_core/build.rs | 1 - zokrates_core/lib/gm17.cpp | 248 ++++++++---------- zokrates_core/lib/gm17.hpp | 6 +- zokrates_core/lib/pghr13.cpp | 225 +++++++--------- zokrates_core/lib/pghr13.hpp | 6 +- zokrates_core/lib/util.cpp | 61 ----- zokrates_core/lib/util.hpp | 48 ---- zokrates_core/lib/util.tcc | 159 +++++++++++ .../src/proof_system/libsnark/gm17.rs | 12 +- .../src/proof_system/libsnark/pghr13.rs | 12 +- 11 files changed, 387 insertions(+), 393 deletions(-) delete mode 100644 zokrates_core/lib/util.cpp delete mode 100644 zokrates_core/lib/util.hpp create mode 100644 zokrates_core/lib/util.tcc diff --git a/scripts/clang-format.sh b/scripts/clang-format.sh index 9d2c05ca..9a3eaf1d 100755 --- a/scripts/clang-format.sh +++ b/scripts/clang-format.sh @@ -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 \ No newline at end of file diff --git a/zokrates_core/build.rs b/zokrates_core/build.rs index eb4ff4dd..151b2a54 100644 --- a/zokrates_core/build.rs +++ b/zokrates_core/build.rs @@ -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"); diff --git a/zokrates_core/lib/gm17.cpp b/zokrates_core/lib/gm17.cpp index 7421aa55..4833145e 100644 --- a/zokrates_core/lib/gm17.cpp +++ b/zokrates_core/lib/gm17.cpp @@ -6,7 +6,7 @@ */ #include "gm17.hpp" -#include "util.hpp" + #include #include #include @@ -17,201 +17,175 @@ // contains required interfaces and types (keypair, proof, generator, prover, verifier) #include -typedef long integer_coeff_t; - using namespace libsnark; -using std::cout; -using std::endl; + +#include "util.tcc" namespace gm17 { -r1cs_se_ppzksnark_constraint_system 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 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> lin_comb_a, lin_comb_b, lin_comb_c; - while (a_id < a_len && a_vvmap[a_id].constraint_id == row) { - libff::bigint 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 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 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>(lin_comb_a, lin_comb_b, lin_comb_c)); - } - return cs; -} - -r1cs_se_ppzksnark_keypair generateKeypair(const r1cs_se_ppzksnark_constraint_system& cs) -{ - return r1cs_se_ppzksnark_generator(cs); //from r1cs_se_ppzksnark.hpp -} - -std::string serializeVerificationKey(r1cs_se_ppzksnark_verification_key* vk) +template +std::string serializeVerificationKey(r1cs_se_ppzksnark_verification_key* vk) { std::stringstream ss; unsigned queryLength = vk->query.size(); + ss << "{"; - ss << "\"h\":" << outputPointG2AffineAsHexJson(vk->H) << ","; - ss << "\"g_alpha\":" << outputPointG1AffineAsHexJson(vk->G_alpha) << ","; - ss << "\"h_beta\":" << outputPointG2AffineAsHexJson(vk->H_beta) << ","; - ss << "\"g_gamma\":" << outputPointG1AffineAsHexJson(vk->G_gamma) << ","; - ss << "\"h_gamma\":" << outputPointG2AffineAsHexJson(vk->H_gamma) << ","; + ss << "\"h\":" << outputPointG2AffineAsHexJson(vk->H) << ","; + ss << "\"g_alpha\":" << outputPointG1AffineAsHexJson(vk->G_alpha) << ","; + ss << "\"h_beta\":" << outputPointG2AffineAsHexJson(vk->H_beta) << ","; + ss << "\"g_gamma\":" << outputPointG1AffineAsHexJson(vk->G_gamma) << ","; + ss << "\"h_gamma\":" << outputPointG2AffineAsHexJson(vk->H_gamma) << ","; ss << "\"query\":["; for (size_t i = 0; i < queryLength; ++i) { if (i != 0) ss << ","; - ss << outputPointG1AffineAsHexJson(vk->query[i]); + ss << outputPointG1AffineAsHexJson(vk->query[i]); } ss << "],"; - ss << "\"raw\":\"" << toHexString(serialize(*vk)) << "\""; + ss << "\"raw\":\"" << encodeToHexString<2>(serialize(*vk)) << "\""; ss << "}"; std::string str = ss.str(); return str; } -std::string serializeProof(r1cs_se_ppzksnark_proof* proof, const uint8_t* public_inputs, int32_t public_inputs_length) +template +std::string serializeProof(r1cs_se_ppzksnark_proof* proof, const uint8_t* public_inputs, int32_t public_inputs_length) { std::stringstream ss; ss << "{"; ss << "\"proof\":{"; - ss << "\"a\":" << outputPointG1AffineAsHexJson(proof->A) << ","; - ss << "\"b\":" << outputPointG2AffineAsHexJson(proof->B) << ","; - ss << "\"c\":" << outputPointG1AffineAsHexJson(proof->C); + ss << "\"a\":" << outputPointG1AffineAsHexJson(proof->A) << ","; + ss << "\"b\":" << outputPointG2AffineAsHexJson(proof->B) << ","; + ss << "\"c\":" << outputPointG1AffineAsHexJson(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(libsnarkBigintFromBytes(public_inputs + (i * R * sizeof(mp_limb_t)))); } ss << "],"; - ss << "\"raw\":\"" << toHexString(serialize(*proof)) << "\""; + 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 +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(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(cs); - auto vk = gm17::serializeVerificationKey(&keypair.vk); + r1cs_se_ppzksnark_keypair keypair = r1cs_se_ppzksnark_generator(cs); + auto vk = serializeVerificationKey(&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 proving_key; - from_buffer>(pk_buf, proving_key); - - // assign variables based on witness values, excludes ~one - r1cs_variable_assignment> full_variable_assignment; - for (int i = 1; i < public_inputs_length; i++) { - full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(public_inputs + i * 32))); - } - for (int i = 0; i < private_inputs_length; i++) { - full_variable_assignment.push_back(libff::Fr(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> primary_input(full_variable_assignment.begin(), full_variable_assignment.begin() + public_inputs_length - 1); - r1cs_primary_input> 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(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 +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 vk; - r1cs_se_ppzksnark_proof proof; + r1cs_se_ppzksnark_proving_key proving_key; + fromBuffer>(pk_buf, proving_key); - from_buffer>(vk_buf, vk); - from_buffer>(proof_buf, proof); - - r1cs_primary_input> primary_input; - for (int i = 0; i < public_inputs_length; i++) { - primary_input.push_back(libff::Fr(libsnarkBigintFromBytes(public_inputs + i * 32))); + r1cs_variable_assignment> full_variable_assignment; + for (int i = 1; i < public_inputs_length; i++) { + full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(public_inputs + (i * R * sizeof(mp_limb_t))))); + } + for (int i = 0; i < private_inputs_length; i++) { + full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(private_inputs + (i * R * sizeof(mp_limb_t))))); } - return r1cs_se_ppzksnark_verifier_strong_IC(vk, primary_input, proof); + r1cs_primary_input> primary_input( + full_variable_assignment.begin(), + full_variable_assignment.begin() + public_inputs_length - 1); + + r1cs_primary_input> auxiliary_input( + full_variable_assignment.begin() + public_inputs_length - 1, + full_variable_assignment.end()); + + r1cs_se_ppzksnark_proof proof = r1cs_se_ppzksnark_prover(proving_key, primary_input, auxiliary_input); + std::string json = serializeProof(&proof, public_inputs, public_inputs_length); + + buffer_t proof_buf = createBuffer(json); + proof_result_t result(proof_buf); + return result; +} + +template +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 vk; + r1cs_se_ppzksnark_proof proof; + + fromBuffer>(vk_buf, vk); + fromBuffer>(proof_buf, proof); + + r1cs_primary_input> primary_input; + for (int i = 0; i < public_inputs_length; i++) { + primary_input.push_back(libff::Fr(libsnarkBigintFromBytes(public_inputs + (i * R * sizeof(mp_limb_t))))); + } + + return r1cs_se_ppzksnark_verifier_strong_IC(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(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(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(vk_buf, proof_buf, public_inputs, public_inputs_length); } \ No newline at end of file diff --git a/zokrates_core/lib/gm17.hpp b/zokrates_core/lib/gm17.hpp index 3437fc3b..96e8cf97 100644 --- a/zokrates_core/lib/gm17.hpp +++ b/zokrates_core/lib/gm17.hpp @@ -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, diff --git a/zokrates_core/lib/pghr13.cpp b/zokrates_core/lib/pghr13.cpp index 5fa03840..1681c316 100644 --- a/zokrates_core/lib/pghr13.cpp +++ b/zokrates_core/lib/pghr13.cpp @@ -6,221 +6,192 @@ */ #include "pghr13.hpp" -#include "util.hpp" + #include #include #include -// 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 -typedef long integer_coeff_t; - using namespace libsnark; -using std::cout; -using std::endl; + +#include "util.tcc" namespace pghr13 { -r1cs_ppzksnark_constraint_system 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 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> lin_comb_a, lin_comb_b, lin_comb_c; - while (a_id < a_len && a_vvmap[a_id].constraint_id == row) { - libff::bigint 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 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 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>(lin_comb_a, lin_comb_b, lin_comb_c)); - } - return cs; -} - -r1cs_ppzksnark_keypair generateKeypair(const r1cs_ppzksnark_constraint_system& cs) -{ - return r1cs_ppzksnark_generator(cs); // from r1cs_ppzksnark.hpp -} - -std::string serializeVerificationKey(r1cs_ppzksnark_verification_key* vk) +template +std::string serializeVerificationKey(r1cs_ppzksnark_verification_key* vk) { std::stringstream ss; unsigned icLength = vk->encoded_IC_query.rest.indices.size(); ss << "{"; - ss << "\"a\":" << outputPointG2AffineAsHexJson(vk->alphaA_g2) << ","; - ss << "\"b\":" << outputPointG1AffineAsHexJson(vk->alphaB_g1) << ","; - ss << "\"c\":" << outputPointG2AffineAsHexJson(vk->alphaC_g2) << ","; - ss << "\"gamma\":" << outputPointG2AffineAsHexJson(vk->gamma_g2) << ","; - ss << "\"gamma_beta_1\":" << outputPointG1AffineAsHexJson(vk->gamma_beta_g1) << ","; - ss << "\"gamma_beta_2\":" << outputPointG2AffineAsHexJson(vk->gamma_beta_g2) << ","; - ss << "\"z\":" << outputPointG2AffineAsHexJson(vk->rC_Z_g2) << ","; + ss << "\"a\":" << outputPointG2AffineAsHexJson(vk->alphaA_g2) << ","; + ss << "\"b\":" << outputPointG1AffineAsHexJson(vk->alphaB_g1) << ","; + ss << "\"c\":" << outputPointG2AffineAsHexJson(vk->alphaC_g2) << ","; + ss << "\"gamma\":" << outputPointG2AffineAsHexJson(vk->gamma_g2) << ","; + ss << "\"gamma_beta_1\":" << outputPointG1AffineAsHexJson(vk->gamma_beta_g1) << ","; + ss << "\"gamma_beta_2\":" << outputPointG2AffineAsHexJson(vk->gamma_beta_g2) << ","; + ss << "\"z\":" << outputPointG2AffineAsHexJson(vk->rC_Z_g2) << ","; ss << "\"ic\":["; - ss << outputPointG1AffineAsHexJson(vk->encoded_IC_query.first); + ss << outputPointG1AffineAsHexJson(vk->encoded_IC_query.first); for (size_t i = 0; i < icLength; ++i) { ss << ","; - ss << outputPointG1AffineAsHexJson(vk->encoded_IC_query.rest.values[i]); + ss << outputPointG1AffineAsHexJson(vk->encoded_IC_query.rest.values[i]); } ss << "],"; - ss << "\"raw\":\"" << toHexString(serialize(*vk)) << "\""; + ss << "\"raw\":\"" << encodeToHexString<2>(serialize(*vk)) << "\""; ss << "}"; std::string str = ss.str(); return str; } -std::string serializeProof(r1cs_ppzksnark_proof* proof, const uint8_t* public_inputs, int public_inputs_length) +template +std::string serializeProof(r1cs_ppzksnark_proof* proof, const uint8_t* public_inputs, int public_inputs_length) { std::stringstream ss; ss << "{"; ss << "\"proof\":{"; - ss << "\"a\":" << outputPointG1AffineAsHexJson(proof->g_A.g) << ","; - ss << "\"a_p\":" << outputPointG1AffineAsHexJson(proof->g_A.h) << ","; - ss << "\"b\":" << outputPointG2AffineAsHexJson(proof->g_B.g) << ","; - ss << "\"b_p\":" << outputPointG1AffineAsHexJson(proof->g_B.h) << ","; - ss << "\"c\":" << outputPointG1AffineAsHexJson(proof->g_C.g) << ","; - ss << "\"c_p\":" << outputPointG1AffineAsHexJson(proof->g_C.h) << ","; - ss << "\"h\":" << outputPointG1AffineAsHexJson(proof->g_H) << ","; - ss << "\"k\":" << outputPointG1AffineAsHexJson(proof->g_K); + ss << "\"a\":" << outputPointG1AffineAsHexJson(proof->g_A.g) << ","; + ss << "\"a_p\":" << outputPointG1AffineAsHexJson(proof->g_A.h) << ","; + ss << "\"b\":" << outputPointG2AffineAsHexJson(proof->g_B.g) << ","; + ss << "\"b_p\":" << outputPointG1AffineAsHexJson(proof->g_B.h) << ","; + ss << "\"c\":" << outputPointG1AffineAsHexJson(proof->g_C.g) << ","; + ss << "\"c_p\":" << outputPointG1AffineAsHexJson(proof->g_C.h) << ","; + ss << "\"h\":" << outputPointG1AffineAsHexJson(proof->g_H) << ","; + ss << "\"k\":" << outputPointG1AffineAsHexJson(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(libsnarkBigintFromBytes(public_inputs + (i * R * sizeof(mp_limb_t)))); } ss << "],"; - ss << "\"raw\":\"" << toHexString(serialize(*proof)) << "\""; + 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 +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(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(cs); - auto vk = pghr13::serializeVerificationKey(&keypair.vk); + r1cs_ppzksnark_keypair keypair = r1cs_ppzksnark_generator(cs); + auto vk = serializeVerificationKey(&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 +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 proving_key; - from_buffer>(pk_buf, proving_key); + r1cs_ppzksnark_proving_key proving_key; + fromBuffer>(pk_buf, proving_key); // assign variables based on witness values, excludes ~one - r1cs_variable_assignment> full_variable_assignment; + r1cs_variable_assignment> full_variable_assignment; for (int i = 1; i < public_inputs_length; i++) { - full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(public_inputs + i * 32))); + full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(public_inputs + (i * R * sizeof(mp_limb_t))))); } for (int i = 0; i < private_inputs_length; i++) { - full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(private_inputs + i * 32))); + full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(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> primary_input(full_variable_assignment.begin(), full_variable_assignment.begin() + public_inputs_length - 1); - r1cs_primary_input> auxiliary_input(full_variable_assignment.begin() + public_inputs_length - 1, full_variable_assignment.end()); + r1cs_primary_input> 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> auxiliary_input( + full_variable_assignment.begin() + public_inputs_length - 1, + full_variable_assignment.end()); - // Proof Generation - auto proof = r1cs_ppzksnark_prover(proving_key, primary_input, auxiliary_input); - auto proof_json = pghr13::serializeProof(&proof, public_inputs, public_inputs_length); + r1cs_ppzksnark_proof proof = r1cs_ppzksnark_prover(proving_key, primary_input, auxiliary_input); + std::string json = serializeProof(&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 +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 vk; - r1cs_ppzksnark_proof proof; + r1cs_ppzksnark_verification_key vk; + r1cs_ppzksnark_proof proof; - from_buffer>(vk_buf, vk); - from_buffer>(proof_buf, proof); + fromBuffer>(vk_buf, vk); + fromBuffer>(proof_buf, proof); - r1cs_primary_input> primary_input; + r1cs_primary_input> primary_input; for (int i = 0; i < public_inputs_length; i++) { - primary_input.push_back(libff::Fr(libsnarkBigintFromBytes(public_inputs + i * 32))); + primary_input.push_back(libff::Fr(libsnarkBigintFromBytes(public_inputs + (i * R * sizeof(mp_limb_t))))); } - - return r1cs_ppzksnark_verifier_strong_IC(vk, primary_input, proof); + return r1cs_ppzksnark_verifier_strong_IC(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(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(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(vk_buf, proof_buf, public_inputs, public_inputs_length); +} \ No newline at end of file diff --git a/zokrates_core/lib/pghr13.hpp b/zokrates_core/lib/pghr13.hpp index e34b299c..9f88cc56 100644 --- a/zokrates_core/lib/pghr13.hpp +++ b/zokrates_core/lib/pghr13.hpp @@ -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, diff --git a/zokrates_core/lib/util.cpp b/zokrates_core/lib/util.cpp deleted file mode 100644 index 4d92f439..00000000 --- a/zokrates_core/lib/util.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @file util.cpp - * @author Jacob Eberhardt - * @date 2017 - */ - -#include "util.hpp" - -// conversion byte[32] <-> libsnark bigint. -libff::bigint libsnarkBigintFromBytes(const uint8_t* _x) -{ - libff::bigint 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(c); - } - return out.str(); -} - -std::string HexStringFromLibsnarkBigint(libff::bigint _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 _x) -{ - return "\"0x" + HexStringFromLibsnarkBigint(_x) + "\""; -} - -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 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()) + "\"]]"; -} \ No newline at end of file diff --git a/zokrates_core/lib/util.hpp b/zokrates_core/lib/util.hpp deleted file mode 100644 index 0edcd9a0..00000000 --- a/zokrates_core/lib/util.hpp +++ /dev/null @@ -1,48 +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 -#include -#include -#include -#include - -libff::bigint libsnarkBigintFromBytes(const uint8_t* _x); -std::string toHexString(const std::string& s); -std::string HexStringFromLibsnarkBigint(libff::bigint _x); -std::string outputInputAsHex(libff::bigint _x); -std::string outputPointG1AffineAsHexJson(libff::alt_bn128_G1 _p); -std::string outputPointG2AffineAsHexJson(libff::alt_bn128_G2 _p); - -template -inline void from_buffer(buffer_t* buffer, T& t) -{ - std::string tmp((char*)buffer->data, buffer->length); - std::stringstream ss(tmp); - ss >> t; -} - -template -inline std::string serialize(const T& t) -{ - std::stringstream ss; - ss << t; - return ss.str(); -} - -template -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(buffer.data), buffer.length); - return buffer; -} \ No newline at end of file diff --git a/zokrates_core/lib/util.tcc b/zokrates_core/lib/util.tcc new file mode 100644 index 00000000..4392b1f4 --- /dev/null +++ b/zokrates_core/lib/util.tcc @@ -0,0 +1,159 @@ +#pragma once + +#include "ffi.hpp" + +#include +#include +#include +#include +#include + +template +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(c); + } + return out.str(); +} + +// conversion byte[N] <-> libsnark bigint. +template +libff::bigint libsnarkBigintFromBytes(const uint8_t* _x) +{ + libff::bigint 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 +std::string hexStringFromLibsnarkBigint(libff::bigint _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 +std::string outputInputAsHex(libff::bigint _x) +{ + return "\"0x" + hexStringFromLibsnarkBigint(_x) + "\""; +} + +template +std::string outputPointG1AffineAsHexJson(G1 _p) +{ + G1 aff = _p; + aff.to_affine_coordinates(); + return "[\"0x" + hexStringFromLibsnarkBigint(aff.X.as_bigint()) + "\",\"0x" + hexStringFromLibsnarkBigint(aff.Y.as_bigint()) + "\"]"; +} + +template +std::string outputPointG2AffineAsHexJson(G2 _p) +{ + 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()) + "\"]]"; +} + +template