1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

Merge pull request #1071 from Zokrates/ark-groth16

Support groth16 implementation from ark
This commit is contained in:
Thibaut Schaeffer 2022-01-19 15:30:45 +01:00 committed by GitHub
commit 1b0386b72d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 499 additions and 160 deletions

19
Cargo.lock generated
View file

@ -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",

View file

@ -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

View file

@ -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`

View file

@ -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(()),

View file

@ -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) => {

View file

@ -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")]

View file

@ -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::<Bn128Field, Marlin, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bls12_381, SchemeParameter::MARLIN) => {
cli_universal_setup::<Bls12_381Field, Marlin, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::MARLIN) => {
cli_universal_setup::<Bls12_377Field, Marlin, Ark>(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::<Bw6_761Field, Marlin, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::MARLIN) => {
cli_universal_setup::<Bn128Field, Marlin, Ark>(sub_matches)
}
_ => unreachable!(),
}
}

View file

@ -78,6 +78,30 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
cli_verify::<Bls12_381Field, G16, Bellman>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::G16) => {
cli_verify::<Bn128Field, G16, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bls12_381, SchemeParameter::G16) => {
cli_verify::<Bls12_381Field, G16, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::G16) => {
cli_verify::<Bls12_377Field, G16, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::G16) => {
cli_verify::<Bw6_761Field, G16, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::GM17) => {
cli_verify::<Bn128Field, GM17, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bls12_381, SchemeParameter::GM17) => {
cli_verify::<Bls12_381Field, GM17, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::GM17) => {
cli_verify::<Bls12_377Field, GM17, Ark>(sub_matches)
}
@ -86,8 +110,12 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
cli_verify::<Bw6_761Field, GM17, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::GM17) => {
cli_verify::<Bn128Field, GM17, Ark>(sub_matches)
Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::MARLIN) => {
cli_verify::<Bn128Field, Marlin, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bls12_381, SchemeParameter::MARLIN) => {
cli_verify::<Bls12_381Field, Marlin, Ark>(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::<Bw6_761Field, Marlin, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::MARLIN) => {
cli_verify::<Bn128Field, Marlin, Ark>(sub_matches)
}
#[cfg(feature = "libsnark")]
Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => {
cli_verify::<Bn128Field, GM17, Libsnark>(sub_matches)

View file

@ -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

View file

@ -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]

View file

@ -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<T: Field + ArkFieldExtensions + NotBw6_761Field> NonUniversalBackend<T, GM17> for Ark {
fn setup<I: IntoIterator<Item = Statement<T>>>(
program: ProgIterator<T, I>,
) -> SetupKeypair<<GM17 as Scheme<T>>::VerificationKey> {
let parameters = Computation::without_witness(program).setup();
let computation = Computation::without_witness(program);
let mut pk: Vec<u8> = Vec::new();
parameters.serialize_uncompressed(&mut pk).unwrap();
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
let (pk, vk) = ArkGM17::<T::ArkEngine>::circuit_specific_setup(computation, rng).unwrap();
let mut pk_vec: Vec<u8> = Vec::new();
pk.serialize_uncompressed(&mut pk_vec).unwrap();
let vk = VerificationKey {
h: parse_g2::<T>(&parameters.vk.h_g2),
g_alpha: parse_g1::<T>(&parameters.vk.g_alpha_g1),
h_beta: parse_g2::<T>(&parameters.vk.h_beta_g2),
g_gamma: parse_g1::<T>(&parameters.vk.g_gamma_g1),
h_gamma: parse_g2::<T>(&parameters.vk.h_gamma_g2),
query: parameters
.vk
.query
.iter()
.map(|g1| parse_g1::<T>(g1))
.collect(),
h: parse_g2::<T>(&vk.h_g2),
g_alpha: parse_g1::<T>(&vk.g_alpha_g1),
h_beta: parse_g2::<T>(&vk.h_beta_g2),
g_gamma: parse_g1::<T>(&vk.g_gamma_g1),
h_gamma: parse_g2::<T>(&vk.h_gamma_g2),
query: vk.query.iter().map(|g1| parse_g1::<T>(g1)).collect(),
};
SetupKeypair::new(vk, pk)
SetupKeypair::new(vk, pk_vec)
}
}
@ -55,12 +55,14 @@ impl<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, GM17> for Ark {
.map(parse_fr::<T>)
.collect::<Vec<_>>();
let params = ProvingKey::<<T as ArkFieldExtensions>::ArkEngine>::deserialize_uncompressed(
let pk = ProvingKey::<<T as ArkFieldExtensions>::ArkEngine>::deserialize_uncompressed(
&mut proving_key.as_slice(),
)
.unwrap();
let proof = computation.prove(&params);
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
let proof = ArkGM17::<T::ArkEngine>::prove(&pk, computation, rng).unwrap();
let proof_points = ProofPoints {
a: parse_g1::<T>(&proof.a),
b: parse_g2::<T>(&proof.b),
@ -114,26 +116,24 @@ impl NonUniversalBackend<Bw6_761Field, GM17> for Ark {
fn setup<I: IntoIterator<Item = Statement<Bw6_761Field>>>(
program: ProgIterator<Bw6_761Field, I>,
) -> SetupKeypair<<GM17 as Scheme<Bw6_761Field>>::VerificationKey> {
let parameters = Computation::without_witness(program).setup();
let computation = Computation::without_witness(program);
let mut pk: Vec<u8> = Vec::new();
parameters.serialize_uncompressed(&mut pk).unwrap();
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
let (pk, vk) = ArkGM17::<BW6_761>::circuit_specific_setup(computation, rng).unwrap();
let mut pk_vec: Vec<u8> = Vec::new();
pk.serialize_uncompressed(&mut pk_vec).unwrap();
let vk = VerificationKey {
h: parse_g2_fq::<Bw6_761Field>(&parameters.vk.h_g2),
g_alpha: parse_g1::<Bw6_761Field>(&parameters.vk.g_alpha_g1),
h_beta: parse_g2_fq::<Bw6_761Field>(&parameters.vk.h_beta_g2),
g_gamma: parse_g1::<Bw6_761Field>(&parameters.vk.g_gamma_g1),
h_gamma: parse_g2_fq::<Bw6_761Field>(&parameters.vk.h_gamma_g2),
query: parameters
.vk
.query
.iter()
.map(parse_g1::<Bw6_761Field>)
.collect(),
h: parse_g2_fq::<Bw6_761Field>(&vk.h_g2),
g_alpha: parse_g1::<Bw6_761Field>(&vk.g_alpha_g1),
h_beta: parse_g2_fq::<Bw6_761Field>(&vk.h_beta_g2),
g_gamma: parse_g1::<Bw6_761Field>(&vk.g_gamma_g1),
h_gamma: parse_g2_fq::<Bw6_761Field>(&vk.h_gamma_g2),
query: vk.query.iter().map(parse_g1::<Bw6_761Field>).collect(),
};
SetupKeypair::new(vk, pk)
SetupKeypair::new(vk, pk_vec)
}
}
@ -151,13 +151,15 @@ impl Backend<Bw6_761Field, GM17> for Ark {
.map(parse_fr::<Bw6_761Field>)
.collect::<Vec<_>>();
let params =
let pk =
ProvingKey::<<Bw6_761Field as ArkFieldExtensions>::ArkEngine>::deserialize_uncompressed(
&mut proving_key.as_slice(),
)
.unwrap();
let proof = computation.prove(&params);
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
let proof = ArkGM17::<BW6_761>::prove(&pk, computation, rng).unwrap();
let proof_points = ProofPoints {
a: parse_g1::<Bw6_761Field>(&proof.a),
b: parse_g2_fq::<Bw6_761Field>(&proof.b),
@ -207,51 +209,6 @@ impl Backend<Bw6_761Field, GM17> 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<u8> {
let mut bytes = hex::decode(value.strip_prefix("0x").unwrap()).unwrap();
bytes.reverse();
bytes
}
pub fn to_g1<T: ArkFieldExtensions>(g1: G1Affine) -> <T::ArkEngine as PairingEngine>::G1Affine {
let mut bytes = vec![];
bytes.append(&mut decode_hex(g1.0));
bytes.append(&mut decode_hex(g1.1));
bytes.push(0u8); // infinity flag
<T::ArkEngine as PairingEngine>::G1Affine::read(&*bytes).unwrap()
}
pub fn to_g2<T: ArkFieldExtensions>(g2: G2Affine) -> <T::ArkEngine as PairingEngine>::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
<T::ArkEngine as PairingEngine>::G2Affine::read(&*bytes).unwrap()
}
pub fn to_g2_fq<T: ArkFieldExtensions>(
g2: G2AffineFq,
) -> <T::ArkEngine as PairingEngine>::G2Affine {
let mut bytes = vec![];
bytes.append(&mut decode_hex(g2.0));
bytes.append(&mut decode_hex(g2.1));
bytes.push(0u8); // infinity flag
<T::ArkEngine as PairingEngine>::G2Affine::read(&*bytes).unwrap()
}
}
#[cfg(test)]
mod tests {
use crate::flat_absy::{FlatParameter, FlatVariable};

View file

@ -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<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, G16> for Ark {
fn generate_proof<I: IntoIterator<Item = Statement<T>>>(
program: ProgIterator<T, I>,
witness: Witness<T>,
proving_key: Vec<u8>,
) -> Proof<<G16 as Scheme<T>>::ProofPoints> {
println!("{}", G16_WARNING);
let computation = Computation::with_witness(program, witness);
let inputs = computation
.public_inputs_values()
.iter()
.map(parse_fr::<T>)
.collect::<Vec<_>>();
let pk = ProvingKey::<<T as ArkFieldExtensions>::ArkEngine>::deserialize_uncompressed(
&mut proving_key.as_slice(),
)
.unwrap();
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
let proof = Groth16::<T::ArkEngine>::prove(&pk, computation, rng).unwrap();
let proof_points = ProofPoints {
a: parse_g1::<T>(&proof.a),
b: parse_g2::<T>(&proof.b),
c: parse_g1::<T>(&proof.c),
};
Proof::new(proof_points, inputs)
}
fn verify(
vk: <G16 as Scheme<T>>::VerificationKey,
proof: Proof<<G16 as Scheme<T>>::ProofPoints>,
) -> bool {
let vk = VerifyingKey {
alpha_g1: serialization::to_g1::<T>(vk.alpha),
beta_g2: serialization::to_g2::<T>(vk.beta),
gamma_g2: serialization::to_g2::<T>(vk.gamma),
delta_g2: serialization::to_g2::<T>(vk.delta),
gamma_abc_g1: vk
.gamma_abc
.into_iter()
.map(serialization::to_g1::<T>)
.collect(),
};
let pvk: PreparedVerifyingKey<T::ArkEngine> = prepare_verifying_key(&vk);
let ark_proof = ArkProof {
a: serialization::to_g1::<T>(proof.proof.a),
b: serialization::to_g2::<T>(proof.proof.b),
c: serialization::to_g1::<T>(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::<Vec<_>>();
verify_proof(&pvk, &ark_proof, &public_inputs).unwrap()
}
}
impl<T: Field + ArkFieldExtensions + NotBw6_761Field> NonUniversalBackend<T, G16> for Ark {
fn setup<I: IntoIterator<Item = Statement<T>>>(
program: ProgIterator<T, I>,
) -> SetupKeypair<<G16 as Scheme<T>>::VerificationKey> {
println!("{}", G16_WARNING);
let computation = Computation::without_witness(program);
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
let (pk, vk) = Groth16::<T::ArkEngine>::circuit_specific_setup(computation, rng).unwrap();
let mut pk_vec: Vec<u8> = Vec::new();
pk.serialize_uncompressed(&mut pk_vec).unwrap();
let vk = VerificationKey {
alpha: parse_g1::<T>(&vk.alpha_g1),
beta: parse_g2::<T>(&vk.beta_g2),
gamma: parse_g2::<T>(&vk.gamma_g2),
delta: parse_g2::<T>(&vk.delta_g2),
gamma_abc: vk.gamma_abc_g1.iter().map(|g1| parse_g1::<T>(g1)).collect(),
};
SetupKeypair::new(vk, pk_vec)
}
}
impl Backend<Bw6_761Field, G16> for Ark {
fn generate_proof<I: IntoIterator<Item = Statement<Bw6_761Field>>>(
program: ProgIterator<Bw6_761Field, I>,
witness: Witness<Bw6_761Field>,
proving_key: Vec<u8>,
) -> Proof<<G16 as Scheme<Bw6_761Field>>::ProofPoints> {
println!("{}", G16_WARNING);
let computation = Computation::with_witness(program, witness);
let inputs = computation
.public_inputs_values()
.iter()
.map(parse_fr::<Bw6_761Field>)
.collect::<Vec<_>>();
let pk =
ProvingKey::<BW6_761>::deserialize_uncompressed(&mut proving_key.as_slice()).unwrap();
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
let proof = Groth16::<BW6_761>::prove(&pk, computation, rng).unwrap();
let proof_points = ProofPoints {
a: parse_g1::<Bw6_761Field>(&proof.a),
b: parse_g2::<Bw6_761Field>(&proof.b),
c: parse_g1::<Bw6_761Field>(&proof.c),
};
Proof::new(proof_points, inputs)
}
fn verify(
vk: <G16 as Scheme<Bw6_761Field>>::VerificationKey,
proof: Proof<<G16 as Scheme<Bw6_761Field>>::ProofPoints>,
) -> bool {
let vk = VerifyingKey {
alpha_g1: serialization::to_g1::<Bw6_761Field>(vk.alpha),
beta_g2: serialization::to_g2::<Bw6_761Field>(vk.beta),
gamma_g2: serialization::to_g2::<Bw6_761Field>(vk.gamma),
delta_g2: serialization::to_g2::<Bw6_761Field>(vk.delta),
gamma_abc_g1: vk
.gamma_abc
.into_iter()
.map(serialization::to_g1::<Bw6_761Field>)
.collect(),
};
let pvk: PreparedVerifyingKey<BW6_761> = prepare_verifying_key(&vk);
let ark_proof = ArkProof {
a: serialization::to_g1::<Bw6_761Field>(proof.proof.a),
b: serialization::to_g2::<Bw6_761Field>(proof.proof.b),
c: serialization::to_g1::<Bw6_761Field>(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::<Vec<_>>();
verify_proof(&pvk, &ark_proof, &public_inputs).unwrap()
}
}
impl NonUniversalBackend<Bw6_761Field, G16> for Ark {
fn setup<I: IntoIterator<Item = Statement<Bw6_761Field>>>(
program: ProgIterator<Bw6_761Field, I>,
) -> SetupKeypair<<G16 as Scheme<Bw6_761Field>>::VerificationKey> {
println!("{}", G16_WARNING);
let computation = Computation::without_witness(program);
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
let (pk, vk) = Groth16::<BW6_761>::circuit_specific_setup(computation, rng).unwrap();
let mut pk_vec: Vec<u8> = Vec::new();
pk.serialize_uncompressed(&mut pk_vec).unwrap();
let vk = VerificationKey {
alpha: parse_g1::<Bw6_761Field>(&vk.alpha_g1),
beta: parse_g2::<Bw6_761Field>(&vk.beta_g2),
gamma: parse_g2::<Bw6_761Field>(&vk.gamma_g2),
delta: parse_g2::<Bw6_761Field>(&vk.delta_g2),
gamma_abc: vk
.gamma_abc_g1
.iter()
.map(parse_g1::<Bw6_761Field>)
.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<Bls12_377Field> = Prog {
arguments: vec![FlatParameter::public(FlatVariable::new(0))],
return_count: 1,
statements: vec![Statement::constraint(
FlatVariable::new(0),
FlatVariable::public(0),
)],
};
let keypair = <Ark as NonUniversalBackend<Bls12_377Field, G16>>::setup(program.clone());
let interpreter = Interpreter::default();
let witness = interpreter
.execute(program.clone(), &[Bls12_377Field::from(42)])
.unwrap();
let proof = <Ark as Backend<Bls12_377Field, G16>>::generate_proof(
program.into(),
witness,
keypair.pk,
);
let ans = <Ark as Backend<Bls12_377Field, G16>>::verify(keypair.vk, proof);
assert!(ans);
}
#[test]
fn verify_bw6_761_field() {
let program: Prog<Bw6_761Field> = Prog {
arguments: vec![FlatParameter::public(FlatVariable::new(0))],
return_count: 1,
statements: vec![Statement::constraint(
FlatVariable::new(0),
FlatVariable::public(0),
)],
};
let keypair = <Ark as NonUniversalBackend<Bw6_761Field, G16>>::setup(program.clone());
let interpreter = Interpreter::default();
let witness = interpreter
.execute(program.clone(), &[Bw6_761Field::from(42)])
.unwrap();
let proof =
<Ark as Backend<Bw6_761Field, G16>>::generate_proof(program, witness, keypair.pk);
let ans = <Ark as Backend<Bw6_761Field, G16>>::verify(keypair.vk, proof);
assert!(ans);
}
}

View file

@ -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<T: Field + ArkFieldExtensions, I: IntoIterator<Item = Statement<T>>> ProgIt
}
impl<T: Field + ArkFieldExtensions, I: IntoIterator<Item = Statement<T>>> Computation<T, I> {
pub fn prove(self, params: &ProvingKey<T::ArkEngine>) -> Proof<T::ArkEngine> {
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(&params.vk);
assert!(verify_proof(&pvk, &proof, &public_inputs).unwrap());
proof
}
pub fn public_inputs_values(&self) -> Vec<<T::ArkEngine as PairingEngine>::Fr> {
self.program
.public_inputs(self.witness.as_ref().unwrap())
@ -170,13 +149,6 @@ impl<T: Field + ArkFieldExtensions, I: IntoIterator<Item = Statement<T>>> Comput
.map(|v| v.clone().into_ark())
.collect()
}
pub fn setup(self) -> ProvingKey<T::ArkEngine> {
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
// run setup phase
generate_random_parameters(self, rng).unwrap()
}
}
impl<T: Field + ArkFieldExtensions, I: IntoIterator<Item = Statement<T>>>
@ -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<u8> {
let mut bytes = hex::decode(value.strip_prefix("0x").unwrap()).unwrap();
bytes.reverse();
bytes
}
pub fn to_g1<T: ArkFieldExtensions>(g1: G1Affine) -> <T::ArkEngine as PairingEngine>::G1Affine {
let mut bytes = vec![];
bytes.append(&mut decode_hex(g1.0));
bytes.append(&mut decode_hex(g1.1));
bytes.push(0u8); // infinity flag
<T::ArkEngine as PairingEngine>::G1Affine::read(&*bytes).unwrap()
}
pub fn to_g2<T: ArkFieldExtensions>(g2: G2Affine) -> <T::ArkEngine as PairingEngine>::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
<T::ArkEngine as PairingEngine>::G2Affine::read(&*bytes).unwrap()
}
pub fn to_g2_fq<T: ArkFieldExtensions>(
g2: G2AffineFq,
) -> <T::ArkEngine as PairingEngine>::G2Affine {
let mut bytes = vec![];
bytes.append(&mut decode_hex(g2.0));
bytes.append(&mut decode_hex(g2.1));
bytes.push(0u8); // infinity flag
<T::ArkEngine as PairingEngine>::G2Affine::read(&*bytes).unwrap()
}
}

View file

@ -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<V> {

View file

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