diff --git a/Cargo.lock b/Cargo.lock index 1afa62d6..f364b2ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -190,6 +190,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "ark-groth16" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba848e856c96bc15eb3f68359cd8ea92747eb2be35a177a25e780d307069f38" +dependencies = [ + "ark-crypto-primitives", + "ark-ec", + "ark-ff", + "ark-poly", + "ark-relations", + "ark-serialize", + "ark-std", +] + [[package]] name = "ark-marlin" version = "0.2.0" @@ -1096,8 +1111,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if 1.0.0", + "js-sys", "libc", "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -2546,9 +2563,11 @@ dependencies = [ "ark-bls12-377", "ark-bn254", "ark-bw6-761", + "ark-crypto-primitives", "ark-ec", "ark-ff", "ark-gm17", + "ark-groth16", "ark-marlin", "ark-poly", "ark-poly-commit", diff --git a/changelogs/unreleased/1071-dark64 b/changelogs/unreleased/1071-dark64 new file mode 100644 index 00000000..d875abc7 --- /dev/null +++ b/changelogs/unreleased/1071-dark64 @@ -0,0 +1 @@ +Support for the `groth16` scheme using the ark backend, support the usage of the `bls12_381` curve with the `gm17` and `marlin` scheme \ No newline at end of file diff --git a/zokrates_book/src/toolbox/proving_schemes.md b/zokrates_book/src/toolbox/proving_schemes.md index f1b58063..a5274c8c 100644 --- a/zokrates_book/src/toolbox/proving_schemes.md +++ b/zokrates_book/src/toolbox/proving_schemes.md @@ -23,12 +23,12 @@ When not using the default, the CLI flag has to be provided for the following co ZoKrates supports different proving schemes. We identify the schemes by the reference to the paper that introduced them. Currently the options available are: -| Scheme | CLI flag | Curves | Universal | -| ---- | -------- | ------ | ------------| -| [G16](https://eprint.iacr.org/2016/260) | `--proving-scheme g16` | ALTBN_128, BLS12_381 | No | -| [GM17](https://eprint.iacr.org/2017/540) | `--proving-scheme gm17` | ALTBN_128, BLS12_377, BW6_761 | No | -| [Marlin](https://eprint.iacr.org/2019/1047) | `--proving-scheme marlin` | ALTBN_128, BLS12_377, BW6_761 | Yes | -| [PGHR13](https://eprint.iacr.org/2013/279) | `--proving-scheme pghr13` | ALTBN_128 | No | +| Scheme | CLI flag | Curves | Universal | +| ---- | -------- |------------------------------------------| ------------| +| [G16](https://eprint.iacr.org/2016/260) | `--proving-scheme g16` | ALTBN_128, BLS12_381 | No | +| [GM17](https://eprint.iacr.org/2017/540) | `--proving-scheme gm17` | ALTBN_128, BLS12_381, BLS12_377, BW6_761 | No | +| [Marlin](https://eprint.iacr.org/2019/1047) | `--proving-scheme marlin` | ALTBN_128, BLS12_381, BLS12_377, BW6_761 | Yes | +| [PGHR13](https://eprint.iacr.org/2013/279) | `--proving-scheme pghr13` | ALTBN_128 | No | All schemes have a circuit-specific setup phase called `setup`. Universal schemes also feature a preliminary, circuit-agnostic step called `universal-setup`. The advantage of universal schemes is that only the `universal-setup` step requires trust, so that it can be run a single time and reused trustlessly for many programs. @@ -45,11 +45,11 @@ When not using the default, the CLI flag has to be provided for the following co ZoKrates supports multiple backends. The options are the following: -| Backend | CLI flag | Proving schemes | Curves | -| ---- | -------- | --------------- | ------ | -| Bellman | `--backend bellman` | G16 | ALTBN_128, BLS12_381 | -| Libsnark | `--backend libsnark` | GM17, PGHR13 | ALTBN_128 | -| Ark | `--backend ark` | GM17, MARLIN | ALTBN_128, BLS12_377, BW6_761 | +| Backend | CLI flag | Proving schemes | Curves | +| ---- | -------- |-------------------|------------------------------------------| +| Bellman | `--backend bellman` | G16 | ALTBN_128, BLS12_381 | +| Libsnark | `--backend libsnark` | GM17, PGHR13 | ALTBN_128 | +| Ark | `--backend ark` | G16, GM17, MARLIN | ALTBN_128, BLS12_381, BLS12_377, BW6_761 | Default: `bellman` diff --git a/zokrates_cli/src/helpers.rs b/zokrates_cli/src/helpers.rs index 8eb17339..bb29f548 100644 --- a/zokrates_cli/src/helpers.rs +++ b/zokrates_cli/src/helpers.rs @@ -93,16 +93,28 @@ impl TryFrom<(&str, &str, &str)> for Parameters { #[cfg(feature = "bellman")] (BackendParameter::Bellman, CurveParameter::Bls12_381, SchemeParameter::G16) => Ok(()), #[cfg(feature = "ark")] - (BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::GM17) => Ok(()), + (BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::G16) => Ok(()), #[cfg(feature = "ark")] - (BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::GM17) => Ok(()), + (BackendParameter::Ark, CurveParameter::Bls12_381, SchemeParameter::G16) => Ok(()), + #[cfg(feature = "ark")] + (BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::G16) => Ok(()), + #[cfg(feature = "ark")] + (BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::G16) => Ok(()), #[cfg(feature = "ark")] (BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::GM17) => Ok(()), #[cfg(feature = "ark")] - (BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::MARLIN) => Ok(()), + (BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::GM17) => Ok(()), + #[cfg(feature = "ark")] + (BackendParameter::Ark, CurveParameter::Bls12_381, SchemeParameter::GM17) => Ok(()), + #[cfg(feature = "ark")] + (BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::GM17) => Ok(()), #[cfg(feature = "ark")] (BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::MARLIN) => Ok(()), #[cfg(feature = "ark")] + (BackendParameter::Ark, CurveParameter::Bls12_381, SchemeParameter::MARLIN) => Ok(()), + #[cfg(feature = "ark")] + (BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::MARLIN) => Ok(()), + #[cfg(feature = "ark")] (BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::MARLIN) => Ok(()), #[cfg(feature = "libsnark")] (BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => Ok(()), diff --git a/zokrates_cli/src/ops/generate_proof.rs b/zokrates_cli/src/ops/generate_proof.rs index f7c94ffe..eb5082ce 100644 --- a/zokrates_cli/src/ops/generate_proof.rs +++ b/zokrates_cli/src/ops/generate_proof.rs @@ -112,20 +112,29 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { _ => unreachable!(), }, #[cfg(feature = "ark")] + Parameters(BackendParameter::Ark, _, SchemeParameter::G16) => match prog { + ProgEnum::Bn128Program(p) => cli_generate_proof::<_, _, G16, Ark>(p, sub_matches), + ProgEnum::Bls12_381Program(p) => cli_generate_proof::<_, _, G16, Ark>(p, sub_matches), + ProgEnum::Bls12_377Program(p) => cli_generate_proof::<_, _, G16, Ark>(p, sub_matches), + ProgEnum::Bw6_761Program(p) => cli_generate_proof::<_, _, G16, Ark>(p, sub_matches), + }, + #[cfg(feature = "ark")] Parameters(BackendParameter::Ark, _, SchemeParameter::GM17) => match prog { + ProgEnum::Bn128Program(p) => cli_generate_proof::<_, _, GM17, Ark>(p, sub_matches), + ProgEnum::Bls12_381Program(p) => cli_generate_proof::<_, _, GM17, Ark>(p, sub_matches), ProgEnum::Bls12_377Program(p) => cli_generate_proof::<_, _, GM17, Ark>(p, sub_matches), ProgEnum::Bw6_761Program(p) => cli_generate_proof::<_, _, GM17, Ark>(p, sub_matches), - ProgEnum::Bn128Program(p) => cli_generate_proof::<_, _, GM17, Ark>(p, sub_matches), - _ => unreachable!(), }, #[cfg(feature = "ark")] Parameters(BackendParameter::Ark, _, SchemeParameter::MARLIN) => match prog { + ProgEnum::Bn128Program(p) => cli_generate_proof::<_, _, Marlin, Ark>(p, sub_matches), + ProgEnum::Bls12_381Program(p) => { + cli_generate_proof::<_, _, Marlin, Ark>(p, sub_matches) + } ProgEnum::Bls12_377Program(p) => { cli_generate_proof::<_, _, Marlin, Ark>(p, sub_matches) } ProgEnum::Bw6_761Program(p) => cli_generate_proof::<_, _, Marlin, Ark>(p, sub_matches), - ProgEnum::Bn128Program(p) => cli_generate_proof::<_, _, Marlin, Ark>(p, sub_matches), - _ => unreachable!(), }, #[cfg(feature = "libsnark")] Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => { diff --git a/zokrates_cli/src/ops/setup.rs b/zokrates_cli/src/ops/setup.rs index 0d179bc4..0a407334 100644 --- a/zokrates_cli/src/ops/setup.rs +++ b/zokrates_cli/src/ops/setup.rs @@ -114,15 +114,30 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { _ => unreachable!(), }, #[cfg(feature = "ark")] + Parameters(BackendParameter::Ark, _, SchemeParameter::G16) => match prog { + ProgEnum::Bn128Program(p) => cli_setup_non_universal::<_, _, G16, Ark>(p, sub_matches), + ProgEnum::Bls12_381Program(p) => { + cli_setup_non_universal::<_, _, G16, Ark>(p, sub_matches) + } + ProgEnum::Bls12_377Program(p) => { + cli_setup_non_universal::<_, _, G16, Ark>(p, sub_matches) + } + ProgEnum::Bw6_761Program(p) => { + cli_setup_non_universal::<_, _, G16, Ark>(p, sub_matches) + } + }, + #[cfg(feature = "ark")] Parameters(BackendParameter::Ark, _, SchemeParameter::GM17) => match prog { + ProgEnum::Bn128Program(p) => cli_setup_non_universal::<_, _, GM17, Ark>(p, sub_matches), + ProgEnum::Bls12_381Program(p) => { + cli_setup_non_universal::<_, _, GM17, Ark>(p, sub_matches) + } ProgEnum::Bls12_377Program(p) => { cli_setup_non_universal::<_, _, GM17, Ark>(p, sub_matches) } ProgEnum::Bw6_761Program(p) => { cli_setup_non_universal::<_, _, GM17, Ark>(p, sub_matches) } - ProgEnum::Bn128Program(p) => cli_setup_non_universal::<_, _, GM17, Ark>(p, sub_matches), - _ => unreachable!(), }, #[cfg(feature = "ark")] Parameters(BackendParameter::Ark, _, SchemeParameter::MARLIN) => { @@ -140,16 +155,18 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { .map_err(|_| "Cannot read universal setup".to_string())?; match prog { - ProgEnum::Bls12_377Program(p) => { + ProgEnum::Bn128Program(p) => { cli_setup_universal::<_, _, Marlin, Ark>(p, setup, sub_matches) } - ProgEnum::Bn128Program(p) => { + ProgEnum::Bls12_381Program(p) => { + cli_setup_universal::<_, _, Marlin, Ark>(p, setup, sub_matches) + } + ProgEnum::Bls12_377Program(p) => { cli_setup_universal::<_, _, Marlin, Ark>(p, setup, sub_matches) } ProgEnum::Bw6_761Program(p) => { cli_setup_universal::<_, _, Marlin, Ark>(p, setup, sub_matches) } - _ => unreachable!(), } } #[cfg(feature = "libsnark")] diff --git a/zokrates_cli/src/ops/universal_setup.rs b/zokrates_cli/src/ops/universal_setup.rs index 9e7674ce..f2ce57f7 100644 --- a/zokrates_cli/src/ops/universal_setup.rs +++ b/zokrates_cli/src/ops/universal_setup.rs @@ -9,7 +9,7 @@ use std::path::Path; use zokrates_core::proof_system::ark::Ark; #[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] use zokrates_core::proof_system::*; -use zokrates_field::{Bls12_377Field, Bn128Field, Bw6_761Field, Field}; +use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field, Bw6_761Field, Field}; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("universal-setup") @@ -63,6 +63,14 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { ))?; match parameters { + #[cfg(feature = "ark")] + Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::MARLIN) => { + cli_universal_setup::(sub_matches) + } + #[cfg(feature = "ark")] + Parameters(BackendParameter::Ark, CurveParameter::Bls12_381, SchemeParameter::MARLIN) => { + cli_universal_setup::(sub_matches) + } #[cfg(feature = "ark")] Parameters(BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::MARLIN) => { cli_universal_setup::(sub_matches) @@ -71,10 +79,6 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { Parameters(BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::MARLIN) => { cli_universal_setup::(sub_matches) } - #[cfg(feature = "ark")] - Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::MARLIN) => { - cli_universal_setup::(sub_matches) - } _ => unreachable!(), } } diff --git a/zokrates_cli/src/ops/verify.rs b/zokrates_cli/src/ops/verify.rs index 4a2cde55..2e174f5c 100644 --- a/zokrates_cli/src/ops/verify.rs +++ b/zokrates_cli/src/ops/verify.rs @@ -78,6 +78,30 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { cli_verify::(sub_matches) } #[cfg(feature = "ark")] + Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::G16) => { + cli_verify::(sub_matches) + } + #[cfg(feature = "ark")] + Parameters(BackendParameter::Ark, CurveParameter::Bls12_381, SchemeParameter::G16) => { + cli_verify::(sub_matches) + } + #[cfg(feature = "ark")] + Parameters(BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::G16) => { + cli_verify::(sub_matches) + } + #[cfg(feature = "ark")] + Parameters(BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::G16) => { + cli_verify::(sub_matches) + } + #[cfg(feature = "ark")] + Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::GM17) => { + cli_verify::(sub_matches) + } + #[cfg(feature = "ark")] + Parameters(BackendParameter::Ark, CurveParameter::Bls12_381, SchemeParameter::GM17) => { + cli_verify::(sub_matches) + } + #[cfg(feature = "ark")] Parameters(BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::GM17) => { cli_verify::(sub_matches) } @@ -86,8 +110,12 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { cli_verify::(sub_matches) } #[cfg(feature = "ark")] - Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::GM17) => { - cli_verify::(sub_matches) + Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::MARLIN) => { + cli_verify::(sub_matches) + } + #[cfg(feature = "ark")] + Parameters(BackendParameter::Ark, CurveParameter::Bls12_381, SchemeParameter::MARLIN) => { + cli_verify::(sub_matches) } #[cfg(feature = "ark")] Parameters(BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::MARLIN) => { @@ -97,10 +125,6 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { Parameters(BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::MARLIN) => { cli_verify::(sub_matches) } - #[cfg(feature = "ark")] - Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::MARLIN) => { - cli_verify::(sub_matches) - } #[cfg(feature = "libsnark")] Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => { cli_verify::(sub_matches) diff --git a/zokrates_cli/tests/integration.rs b/zokrates_cli/tests/integration.rs index 6c3e93e4..d218bc34 100644 --- a/zokrates_cli/tests/integration.rs +++ b/zokrates_cli/tests/integration.rs @@ -215,13 +215,13 @@ mod integration { let backends = map! { "bellman" => vec!["g16"], "libsnark" => vec!["pghr13"], - "ark" => vec!["gm17", "marlin"] + "ark" => vec!["g16", "gm17", "marlin"] }; #[cfg(not(feature = "libsnark"))] let backends = map! { "bellman" => vec!["g16"], - "ark" => vec!["gm17", "marlin"] + "ark" => vec!["g16", "gm17", "marlin"] }; // GENERATE A UNIVERSAL SETUP diff --git a/zokrates_core/Cargo.toml b/zokrates_core/Cargo.toml index 07184a7e..9a4de1e3 100644 --- a/zokrates_core/Cargo.toml +++ b/zokrates_core/Cargo.toml @@ -13,7 +13,7 @@ libsnark = ["cc", "cmake", "git2"] bellman = ["bellman_ce", "pairing_ce", "ff_ce", "zokrates_field/bellman"] wasm = ["bellman_ce/nolog", "bellman_ce/wasm"] multicore = ["bellman_ce/multicore", "phase2/multicore"] -ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-serialize", "ark-relations", "ark-marlin", "ark-poly", "ark-poly-commit", "sha2"] +ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-groth16", "ark-crypto-primitives", "ark-serialize", "ark-relations", "ark-marlin", "ark-poly", "ark-poly-commit", "sha2"] [dependencies] log = "0.4" @@ -35,7 +35,7 @@ zokrates_common = { path = "../zokrates_common" } zokrates_embed = { version = "0.1.0", path = "../zokrates_embed" } getrandom = { version = "0.2", features = ["js"] } rand_0_4 = { version = "0.4", package = "rand" } -rand_0_7 = { version = "0.7", package = "rand" } +rand_0_7 = { version = "0.7", package = "rand", features = ["wasm-bindgen"] } csv = "1" phase2 = { git = "https://github.com/Zokrates/phase2", default-features = false } @@ -51,11 +51,13 @@ ark-bn254 = { version = "^0.2.0", features = ["curve"], default-features = false ark-bls12-377 = { version = "^0.2.0", features = ["curve"], default-features = false, optional = true } ark-bw6-761 = { version = "^0.2.0", default-features = false, optional = true } ark-gm17 = { version = "^0.2.0", default-features = false, optional = true } +ark-groth16 = { version = "^0.2.0", default-features = false, optional = true } ark-serialize = { version = "^0.2.0", default-features = false, optional = true } ark-relations = { version = "^0.2.0", default-features = false, optional = true } ark-marlin = { version = "^0.2.0", default-features = false, optional = true } ark-poly = { version = "^0.2.0", default-features = false, optional = true } ark-poly-commit = { version = "^0.2.0", default-features = false, optional = true } +ark-crypto-primitives = { version = "^0.2.0", default-features = false, optional = true } sha2 = { version = "0.9.3", optional = true } [dev-dependencies] diff --git a/zokrates_core/src/proof_system/ark/gm17.rs b/zokrates_core/src/proof_system/ark/gm17.rs index 9f59b590..2cf5f5c3 100644 --- a/zokrates_core/src/proof_system/ark/gm17.rs +++ b/zokrates_core/src/proof_system/ark/gm17.rs @@ -1,43 +1,43 @@ +use ark_crypto_primitives::SNARK; use ark_gm17::{ prepare_verifying_key, verify_proof, PreparedVerifyingKey, Proof as ArkProof, ProvingKey, - VerifyingKey, + VerifyingKey, GM17 as ArkGM17, }; - use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use zokrates_field::{ArkFieldExtensions, Bw6_761Field, Field}; use crate::ir::{ProgIterator, Statement, Witness}; -use crate::proof_system::ark::Ark; use crate::proof_system::ark::Computation; use crate::proof_system::ark::{parse_fr, parse_g1, parse_g2, parse_g2_fq}; -use crate::proof_system::gm17::{NotBw6_761Field, ProofPoints, VerificationKey, GM17}; -use crate::proof_system::Scheme; +use crate::proof_system::ark::{serialization, Ark}; +use crate::proof_system::gm17::{ProofPoints, VerificationKey, GM17}; use crate::proof_system::{Backend, NonUniversalBackend, Proof, SetupKeypair}; +use crate::proof_system::{NotBw6_761Field, Scheme}; +use ark_bw6_761::BW6_761; +use rand_0_7::SeedableRng; impl NonUniversalBackend for Ark { fn setup>>( program: ProgIterator, ) -> SetupKeypair<>::VerificationKey> { - let parameters = Computation::without_witness(program).setup(); + let computation = Computation::without_witness(program); - let mut pk: Vec = Vec::new(); - parameters.serialize_uncompressed(&mut pk).unwrap(); + let rng = &mut rand_0_7::rngs::StdRng::from_entropy(); + let (pk, vk) = ArkGM17::::circuit_specific_setup(computation, rng).unwrap(); + + let mut pk_vec: Vec = Vec::new(); + pk.serialize_uncompressed(&mut pk_vec).unwrap(); let vk = VerificationKey { - h: parse_g2::(¶meters.vk.h_g2), - g_alpha: parse_g1::(¶meters.vk.g_alpha_g1), - h_beta: parse_g2::(¶meters.vk.h_beta_g2), - g_gamma: parse_g1::(¶meters.vk.g_gamma_g1), - h_gamma: parse_g2::(¶meters.vk.h_gamma_g2), - query: parameters - .vk - .query - .iter() - .map(|g1| parse_g1::(g1)) - .collect(), + h: parse_g2::(&vk.h_g2), + g_alpha: parse_g1::(&vk.g_alpha_g1), + h_beta: parse_g2::(&vk.h_beta_g2), + g_gamma: parse_g1::(&vk.g_gamma_g1), + h_gamma: parse_g2::(&vk.h_gamma_g2), + query: vk.query.iter().map(|g1| parse_g1::(g1)).collect(), }; - SetupKeypair::new(vk, pk) + SetupKeypair::new(vk, pk_vec) } } @@ -55,12 +55,14 @@ impl Backend for Ark { .map(parse_fr::) .collect::>(); - let params = ProvingKey::<::ArkEngine>::deserialize_uncompressed( + let pk = ProvingKey::<::ArkEngine>::deserialize_uncompressed( &mut proving_key.as_slice(), ) .unwrap(); - let proof = computation.prove(¶ms); + let rng = &mut rand_0_7::rngs::StdRng::from_entropy(); + let proof = ArkGM17::::prove(&pk, computation, rng).unwrap(); + let proof_points = ProofPoints { a: parse_g1::(&proof.a), b: parse_g2::(&proof.b), @@ -114,26 +116,24 @@ impl NonUniversalBackend for Ark { fn setup>>( program: ProgIterator, ) -> SetupKeypair<>::VerificationKey> { - let parameters = Computation::without_witness(program).setup(); + let computation = Computation::without_witness(program); - let mut pk: Vec = Vec::new(); - parameters.serialize_uncompressed(&mut pk).unwrap(); + let rng = &mut rand_0_7::rngs::StdRng::from_entropy(); + let (pk, vk) = ArkGM17::::circuit_specific_setup(computation, rng).unwrap(); + + let mut pk_vec: Vec = Vec::new(); + pk.serialize_uncompressed(&mut pk_vec).unwrap(); let vk = VerificationKey { - h: parse_g2_fq::(¶meters.vk.h_g2), - g_alpha: parse_g1::(¶meters.vk.g_alpha_g1), - h_beta: parse_g2_fq::(¶meters.vk.h_beta_g2), - g_gamma: parse_g1::(¶meters.vk.g_gamma_g1), - h_gamma: parse_g2_fq::(¶meters.vk.h_gamma_g2), - query: parameters - .vk - .query - .iter() - .map(parse_g1::) - .collect(), + h: parse_g2_fq::(&vk.h_g2), + g_alpha: parse_g1::(&vk.g_alpha_g1), + h_beta: parse_g2_fq::(&vk.h_beta_g2), + g_gamma: parse_g1::(&vk.g_gamma_g1), + h_gamma: parse_g2_fq::(&vk.h_gamma_g2), + query: vk.query.iter().map(parse_g1::).collect(), }; - SetupKeypair::new(vk, pk) + SetupKeypair::new(vk, pk_vec) } } @@ -151,13 +151,15 @@ impl Backend for Ark { .map(parse_fr::) .collect::>(); - let params = + let pk = ProvingKey::<::ArkEngine>::deserialize_uncompressed( &mut proving_key.as_slice(), ) .unwrap(); - let proof = computation.prove(¶ms); + let rng = &mut rand_0_7::rngs::StdRng::from_entropy(); + let proof = ArkGM17::::prove(&pk, computation, rng).unwrap(); + let proof_points = ProofPoints { a: parse_g1::(&proof.a), b: parse_g2_fq::(&proof.b), @@ -207,51 +209,6 @@ impl Backend for Ark { } } -pub mod serialization { - use crate::proof_system::{G1Affine, G2Affine, G2AffineFq}; - use ark_ec::PairingEngine; - use ark_ff::FromBytes; - use zokrates_field::ArkFieldExtensions; - - #[inline] - fn decode_hex(value: String) -> Vec { - let mut bytes = hex::decode(value.strip_prefix("0x").unwrap()).unwrap(); - bytes.reverse(); - bytes - } - - pub fn to_g1(g1: G1Affine) -> ::G1Affine { - let mut bytes = vec![]; - bytes.append(&mut decode_hex(g1.0)); - bytes.append(&mut decode_hex(g1.1)); - bytes.push(0u8); // infinity flag - - ::G1Affine::read(&*bytes).unwrap() - } - - pub fn to_g2(g2: G2Affine) -> ::G2Affine { - let mut bytes = vec![]; - bytes.append(&mut decode_hex((g2.0).0)); - bytes.append(&mut decode_hex((g2.0).1)); - bytes.append(&mut decode_hex((g2.1).0)); - bytes.append(&mut decode_hex((g2.1).1)); - bytes.push(0u8); // infinity flag - - ::G2Affine::read(&*bytes).unwrap() - } - - pub fn to_g2_fq( - g2: G2AffineFq, - ) -> ::G2Affine { - let mut bytes = vec![]; - bytes.append(&mut decode_hex(g2.0)); - bytes.append(&mut decode_hex(g2.1)); - bytes.push(0u8); // infinity flag - - ::G2Affine::read(&*bytes).unwrap() - } -} - #[cfg(test)] mod tests { use crate::flat_absy::{FlatParameter, FlatVariable}; diff --git a/zokrates_core/src/proof_system/ark/groth16.rs b/zokrates_core/src/proof_system/ark/groth16.rs new file mode 100644 index 00000000..bccfd66b --- /dev/null +++ b/zokrates_core/src/proof_system/ark/groth16.rs @@ -0,0 +1,276 @@ +use crate::proof_system::{Backend, NonUniversalBackend, NotBw6_761Field, Proof, SetupKeypair}; +use ark_crypto_primitives::SNARK; +use ark_groth16::{ + prepare_verifying_key, verify_proof, Groth16, PreparedVerifyingKey, Proof as ArkProof, + ProvingKey, VerifyingKey, +}; +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use zokrates_field::Field; +use zokrates_field::{ArkFieldExtensions, Bw6_761Field}; + +use crate::ir::{ProgIterator, Statement, Witness}; +use crate::proof_system::ark::Computation; +use crate::proof_system::ark::{parse_fr, serialization, Ark}; +use crate::proof_system::ark::{parse_g1, parse_g2}; +use crate::proof_system::groth16::{ProofPoints, VerificationKey, G16}; +use crate::proof_system::Scheme; +use ark_bw6_761::BW6_761; +use rand_0_7::SeedableRng; + +const G16_WARNING: &str = "WARNING: You are using the G16 scheme which is subject to malleability. See zokrates.github.io/toolbox/proving_schemes.html#g16-malleability for implications."; + +impl Backend for Ark { + fn generate_proof>>( + program: ProgIterator, + witness: Witness, + proving_key: Vec, + ) -> Proof<>::ProofPoints> { + println!("{}", G16_WARNING); + + let computation = Computation::with_witness(program, witness); + + let inputs = computation + .public_inputs_values() + .iter() + .map(parse_fr::) + .collect::>(); + + let pk = ProvingKey::<::ArkEngine>::deserialize_uncompressed( + &mut proving_key.as_slice(), + ) + .unwrap(); + + let rng = &mut rand_0_7::rngs::StdRng::from_entropy(); + let proof = Groth16::::prove(&pk, computation, rng).unwrap(); + + let proof_points = ProofPoints { + a: parse_g1::(&proof.a), + b: parse_g2::(&proof.b), + c: parse_g1::(&proof.c), + }; + + Proof::new(proof_points, inputs) + } + + fn verify( + vk: >::VerificationKey, + proof: Proof<>::ProofPoints>, + ) -> bool { + let vk = VerifyingKey { + alpha_g1: serialization::to_g1::(vk.alpha), + beta_g2: serialization::to_g2::(vk.beta), + gamma_g2: serialization::to_g2::(vk.gamma), + delta_g2: serialization::to_g2::(vk.delta), + gamma_abc_g1: vk + .gamma_abc + .into_iter() + .map(serialization::to_g1::) + .collect(), + }; + + let pvk: PreparedVerifyingKey = prepare_verifying_key(&vk); + let ark_proof = ArkProof { + a: serialization::to_g1::(proof.proof.a), + b: serialization::to_g2::(proof.proof.b), + c: serialization::to_g1::(proof.proof.c), + }; + + let public_inputs: Vec<_> = proof + .inputs + .iter() + .map(|s| { + T::try_from_str(s.trim_start_matches("0x"), 16) + .unwrap() + .into_ark() + }) + .collect::>(); + + verify_proof(&pvk, &ark_proof, &public_inputs).unwrap() + } +} + +impl NonUniversalBackend for Ark { + fn setup>>( + program: ProgIterator, + ) -> SetupKeypair<>::VerificationKey> { + println!("{}", G16_WARNING); + + let computation = Computation::without_witness(program); + + let rng = &mut rand_0_7::rngs::StdRng::from_entropy(); + let (pk, vk) = Groth16::::circuit_specific_setup(computation, rng).unwrap(); + + let mut pk_vec: Vec = Vec::new(); + pk.serialize_uncompressed(&mut pk_vec).unwrap(); + + let vk = VerificationKey { + alpha: parse_g1::(&vk.alpha_g1), + beta: parse_g2::(&vk.beta_g2), + gamma: parse_g2::(&vk.gamma_g2), + delta: parse_g2::(&vk.delta_g2), + gamma_abc: vk.gamma_abc_g1.iter().map(|g1| parse_g1::(g1)).collect(), + }; + + SetupKeypair::new(vk, pk_vec) + } +} + +impl Backend for Ark { + fn generate_proof>>( + program: ProgIterator, + witness: Witness, + proving_key: Vec, + ) -> Proof<>::ProofPoints> { + println!("{}", G16_WARNING); + + let computation = Computation::with_witness(program, witness); + + let inputs = computation + .public_inputs_values() + .iter() + .map(parse_fr::) + .collect::>(); + + let pk = + ProvingKey::::deserialize_uncompressed(&mut proving_key.as_slice()).unwrap(); + + let rng = &mut rand_0_7::rngs::StdRng::from_entropy(); + let proof = Groth16::::prove(&pk, computation, rng).unwrap(); + + let proof_points = ProofPoints { + a: parse_g1::(&proof.a), + b: parse_g2::(&proof.b), + c: parse_g1::(&proof.c), + }; + + Proof::new(proof_points, inputs) + } + + fn verify( + vk: >::VerificationKey, + proof: Proof<>::ProofPoints>, + ) -> bool { + let vk = VerifyingKey { + alpha_g1: serialization::to_g1::(vk.alpha), + beta_g2: serialization::to_g2::(vk.beta), + gamma_g2: serialization::to_g2::(vk.gamma), + delta_g2: serialization::to_g2::(vk.delta), + gamma_abc_g1: vk + .gamma_abc + .into_iter() + .map(serialization::to_g1::) + .collect(), + }; + + let pvk: PreparedVerifyingKey = prepare_verifying_key(&vk); + let ark_proof = ArkProof { + a: serialization::to_g1::(proof.proof.a), + b: serialization::to_g2::(proof.proof.b), + c: serialization::to_g1::(proof.proof.c), + }; + + let public_inputs: Vec<_> = proof + .inputs + .iter() + .map(|s| { + Bw6_761Field::try_from_str(s.trim_start_matches("0x"), 16) + .unwrap() + .into_ark() + }) + .collect::>(); + + verify_proof(&pvk, &ark_proof, &public_inputs).unwrap() + } +} + +impl NonUniversalBackend for Ark { + fn setup>>( + program: ProgIterator, + ) -> SetupKeypair<>::VerificationKey> { + println!("{}", G16_WARNING); + + let computation = Computation::without_witness(program); + + let rng = &mut rand_0_7::rngs::StdRng::from_entropy(); + let (pk, vk) = Groth16::::circuit_specific_setup(computation, rng).unwrap(); + + let mut pk_vec: Vec = Vec::new(); + pk.serialize_uncompressed(&mut pk_vec).unwrap(); + + let vk = VerificationKey { + alpha: parse_g1::(&vk.alpha_g1), + beta: parse_g2::(&vk.beta_g2), + gamma: parse_g2::(&vk.gamma_g2), + delta: parse_g2::(&vk.delta_g2), + gamma_abc: vk + .gamma_abc_g1 + .iter() + .map(parse_g1::) + .collect(), + }; + + SetupKeypair::new(vk, pk_vec) + } +} + +#[cfg(test)] +mod tests { + use crate::flat_absy::{FlatParameter, FlatVariable}; + use crate::ir::{Interpreter, Prog, Statement}; + + use super::*; + use zokrates_field::{Bls12_377Field, Bw6_761Field}; + + #[test] + fn verify_bls12_377_field() { + let program: Prog = Prog { + arguments: vec![FlatParameter::public(FlatVariable::new(0))], + return_count: 1, + statements: vec![Statement::constraint( + FlatVariable::new(0), + FlatVariable::public(0), + )], + }; + + let keypair = >::setup(program.clone()); + let interpreter = Interpreter::default(); + + let witness = interpreter + .execute(program.clone(), &[Bls12_377Field::from(42)]) + .unwrap(); + + let proof = >::generate_proof( + program.into(), + witness, + keypair.pk, + ); + let ans = >::verify(keypair.vk, proof); + + assert!(ans); + } + + #[test] + fn verify_bw6_761_field() { + let program: Prog = Prog { + arguments: vec![FlatParameter::public(FlatVariable::new(0))], + return_count: 1, + statements: vec![Statement::constraint( + FlatVariable::new(0), + FlatVariable::public(0), + )], + }; + + let keypair = >::setup(program.clone()); + let interpreter = Interpreter::default(); + + let witness = interpreter + .execute(program.clone(), &[Bw6_761Field::from(42)]) + .unwrap(); + + let proof = + >::generate_proof(program, witness, keypair.pk); + let ans = >::verify(keypair.vk, proof); + + assert!(ans); + } +} diff --git a/zokrates_core/src/proof_system/ark/mod.rs b/zokrates_core/src/proof_system/ark/mod.rs index a0569591..192d7303 100644 --- a/zokrates_core/src/proof_system/ark/mod.rs +++ b/zokrates_core/src/proof_system/ark/mod.rs @@ -1,14 +1,9 @@ pub mod gm17; +pub mod groth16; pub mod marlin; -use crate::ir::{CanonicalLinComb, ProgIterator, Statement, Witness}; -use ark_gm17::Proof; -use ark_gm17::{ - create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, - ProvingKey, -}; - use crate::flat_absy::FlatVariable; +use crate::ir::{CanonicalLinComb, ProgIterator, Statement, Witness}; use ark_ec::PairingEngine; use ark_relations::r1cs::{ ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, LinearCombination, @@ -19,8 +14,6 @@ use zokrates_field::{ArkFieldExtensions, Field}; pub use self::parse::*; -use rand_0_7::SeedableRng; - pub struct Ark; #[derive(Clone)] @@ -149,20 +142,6 @@ impl>> ProgIt } impl>> Computation { - pub fn prove(self, params: &ProvingKey) -> Proof { - let rng = &mut rand_0_7::rngs::StdRng::from_entropy(); - - let public_inputs = self.public_inputs_values(); - - let proof = create_random_proof(self, params, rng).unwrap(); - - let pvk = prepare_verifying_key(¶ms.vk); - - assert!(verify_proof(&pvk, &proof, &public_inputs).unwrap()); - - proof - } - pub fn public_inputs_values(&self) -> Vec<::Fr> { self.program .public_inputs(self.witness.as_ref().unwrap()) @@ -170,13 +149,6 @@ impl>> Comput .map(|v| v.clone().into_ark()) .collect() } - - pub fn setup(self) -> ProvingKey { - let rng = &mut rand_0_7::rngs::StdRng::from_entropy(); - - // run setup phase - generate_random_parameters(self, rng).unwrap() - } } impl>> @@ -276,3 +248,48 @@ mod parse { format!("0x{}", hex::encode(&bytes)) } } + +pub mod serialization { + use crate::proof_system::{G1Affine, G2Affine, G2AffineFq}; + use ark_ec::PairingEngine; + use ark_ff::FromBytes; + use zokrates_field::ArkFieldExtensions; + + #[inline] + fn decode_hex(value: String) -> Vec { + let mut bytes = hex::decode(value.strip_prefix("0x").unwrap()).unwrap(); + bytes.reverse(); + bytes + } + + pub fn to_g1(g1: G1Affine) -> ::G1Affine { + let mut bytes = vec![]; + bytes.append(&mut decode_hex(g1.0)); + bytes.append(&mut decode_hex(g1.1)); + bytes.push(0u8); // infinity flag + + ::G1Affine::read(&*bytes).unwrap() + } + + pub fn to_g2(g2: G2Affine) -> ::G2Affine { + let mut bytes = vec![]; + bytes.append(&mut decode_hex((g2.0).0)); + bytes.append(&mut decode_hex((g2.0).1)); + bytes.append(&mut decode_hex((g2.1).0)); + bytes.append(&mut decode_hex((g2.1).1)); + bytes.push(0u8); // infinity flag + + ::G2Affine::read(&*bytes).unwrap() + } + + pub fn to_g2_fq( + g2: G2AffineFq, + ) -> ::G2Affine { + let mut bytes = vec![]; + bytes.append(&mut decode_hex(g2.0)); + bytes.append(&mut decode_hex(g2.1)); + bytes.push(0u8); // infinity flag + + ::G2Affine::read(&*bytes).unwrap() + } +} diff --git a/zokrates_core/src/proof_system/mod.rs b/zokrates_core/src/proof_system/mod.rs index 7d52a9bf..a9285edd 100644 --- a/zokrates_core/src/proof_system/mod.rs +++ b/zokrates_core/src/proof_system/mod.rs @@ -18,7 +18,12 @@ use serde::{Deserialize, Serialize}; use std::io::{Read, Write}; #[cfg(feature = "bellman")] use zokrates_field::BellmanFieldExtensions; -use zokrates_field::Field; +use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field, Field}; + +pub trait NotBw6_761Field {} +impl NotBw6_761Field for Bls12_377Field {} +impl NotBw6_761Field for Bls12_381Field {} +impl NotBw6_761Field for Bn128Field {} #[derive(Serialize)] pub struct SetupKeypair { diff --git a/zokrates_core/src/proof_system/scheme/gm17.rs b/zokrates_core/src/proof_system/scheme/gm17.rs index 94c1aeaf..e2c7869c 100644 --- a/zokrates_core/src/proof_system/scheme/gm17.rs +++ b/zokrates_core/src/proof_system/scheme/gm17.rs @@ -1,16 +1,12 @@ use crate::proof_system::scheme::{NonUniversalScheme, Scheme}; use crate::proof_system::solidity::{solidity_pairing_lib, SOLIDITY_G2_ADDITION_LIB}; use crate::proof_system::{ - G1Affine, G2Affine, G2AffineFq, SolidityCompatibleField, SolidityCompatibleScheme, + G1Affine, G2Affine, G2AffineFq, NotBw6_761Field, SolidityCompatibleField, + SolidityCompatibleScheme, }; use regex::Regex; use serde::{Deserialize, Serialize}; -use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field, Bw6_761Field, Field}; - -pub trait NotBw6_761Field {} -impl NotBw6_761Field for Bls12_377Field {} -impl NotBw6_761Field for Bls12_381Field {} -impl NotBw6_761Field for Bn128Field {} +use zokrates_field::{Bw6_761Field, Field}; #[allow(clippy::upper_case_acronyms)] pub struct GM17;