Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of the ABPR21 (RO-based) #355

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: check
args: --examples --workspace --target aarch64-unknown-none
args: --examples --workspace --target aarch64-unknown-none --no-default-features

- name: Build
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --target aarch64-unknown-none
args: --workspace --target aarch64-unknown-none --no-default-features
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
members = [
"relations",
"snark",

# concrete SNARKs
"abpr21",
]

[profile.release]
Expand Down
59 changes: 59 additions & 0 deletions abpr21/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
[package]
name = "ark-abpr21"
version = "0.3.0"
authors = [ "arkworks contributors, Oussame Amine, Karim Baghery" ]
description = "An implementation of the ABPR21 zkSNARK proof system"
homepage = "https://arkworks.rs"
repository = "https://github.com/arkworks-rs/snark/abpr21"
documentation = "https://docs.rs/ark-abpr21/"
keywords = ["zero-knowledge", "cryptography", "zkSNARK", "SE-zkSNARK", "simulation-extractability"]
categories = [ "cryptography" ]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"

################################# Dependencies ################################

[dependencies]
ark-ff = { version = "^0.3.0", default-features = false }
ark-ec = { version = "^0.3.0", default-features = false }
ark-serialize = { version = "^0.3.0", default-features = false, features = [ "derive" ] }
ark-poly = { version = "^0.3.0", default-features = false }
ark-std = { version = "^0.3.0", default-features = false }
ark-relations = { version = "^0.3.0", default-features = false }
ark-crypto-primitives = { version = "^0.3.0", default-features = false }
ark-r1cs-std = { version = "^0.3.0", default-features = false, optional = true }

tracing = { version = "0.1", default-features = false, features = [ "attributes" ], optional = true }
derivative = { version = "2.0", features = ["use_core"], optional = true}

rayon = { version = "1", optional = true }
blake2 = { version = "0.9", default-features = false }

[dev-dependencies]
csv = { version = "1" }
ark-bls12-381 = { version = "^0.3.0", default-features = false, features = ["curve"] }
ark-bls12-377 = { version = "^0.3.0", default-features = false, features = ["curve"] }
ark-cp6-782 = { version = "^0.3.0", default-features = false }
ark-mnt4-298 = { version = "^0.3.0", default-features = false, features = ["r1cs", "curve"] }
ark-mnt6-298 = { version = "^0.3.0", default-features = false, features = ["r1cs"] }
ark-mnt4-753 = { version = "^0.3.0", default-features = false, features = ["r1cs", "curve"] }
ark-mnt6-753 = { version = "^0.3.0", default-features = false, features = ["r1cs"] }

[features]
default = ["parallel"]
std = ["ark-ff/std", "ark-ec/std", "ark-poly/std", "ark-relations/std", "ark-crypto-primitives/std", "ark-std/std", "blake2/std" ]
parallel = ["std", "ark-ff/parallel", "ark-poly/parallel", "ark-ec/parallel", "ark-crypto-primitives/parallel", "ark-std/parallel", "rayon"]
r1cs = [ "ark-crypto-primitives/r1cs", "ark-r1cs-std", "tracing", "derivative" ]
print-trace = [ "ark-std/print-trace" ]

[[example]]
name = "abpr21"
path = "examples/snark-scalability/abpr21.rs"
required-features = ["std"]

[[bench]]
name = "abpr21-benches"
path = "benches/bench.rs"
harness = false
required-features = ["std"]
88 changes: 88 additions & 0 deletions abpr21/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<h1 align="center">ark-abpr21 (RO_Based)</h1>

<p align="center">
<img src="https://github.com/arkworks-rs/snark/workflows/CI/badge.svg?branch=master">
<a href="https://github.com/arkworks-rs/groth16/blob/master/LICENSE-APACHE"><img src="https://img.shields.io/badge/license-APACHE-blue.svg"></a>
<a href="https://github.com/arkworks-rs/groth16/blob/master/LICENSE-MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
<a href="https://deps.rs/repo/github/arkworks-rs/snark"><img src="https://deps.rs/repo/github/arkworks-rs/snark/status.svg"></a>
</p>

The arkworks ecosystem consist of Rust libraries for designing and working with __zero knowledge succinct non-interactive arguments (zkSNARKs)__. This repository contains an efficient Rust implementation of the RO-based simulation extractable variant of [[Groth16]](https://eprint.iacr.org/2016/260) zkSNARK presented in Section 4 of [[ABPR21]](https://eprint.iacr.org/2020/1306), implemented by Oussama Amine (University of Oslo) and Karim Baghery (KU Leuven).

This library is released under the MIT License and the Apache v2 License (see [License](#license)).

**WARNING:** This is an academic proof-of-concept prototype, and in particular has not received careful code review. This implementation is NOT ready for production use.

## Build guide

The library compiles on the `stable` toolchain of the Rust compiler. To install the latest version of Rust, first install `rustup` by following the instructions [here](https://rustup.rs/), or via your platform's package manager. Once `rustup` is installed, install the Rust toolchain by invoking:
```bash
rustup install stable
```

After that, use `cargo`, the standard Rust build tool, to build the library:
```bash
git clone -b RO_Based https://github.com/Baghery/ABPR21.git
cd RO_Based
cargo build --release
```

This library comes with unit tests for each of the provided crates. Run the tests with:
```bash
cargo test
```
and for benchmarking the scheme with `RAYON_NUM_THREADS=4` threads, run the following command,
```bash
RAYON_NUM_THREADS=4 cargo bench --no-default-features --features "std parallel" -- --nocapture
```

## Empirical performance

Below we compare the performance of several weakly- and strongly-simulation-extractable zkSNARKs. Note that Groth's zk-SNARK is proven to achieve weak simulation-extractability [[BKSV20]](https://eprint.iacr.org/2020/811). We benchmark the zkSNARKs on an R1CS instance for different curves and report proving and verifying times for each.
All experiments were performed on a desktop machine running Ubuntu 20.4.2 LTS and equipped with an Intel Core i9-9900 processor at base frequency 3.1 GHz, and 128GB of memory.
Proving was performed in multi-threaded mode, with 16 threads, while proof verification was tested in single-threaded mode.

Key: _SE_ = Simulation-extractable, _RO_ = Random Oracle, _CRH_ = Collision Resistant Hash.

| curve | zkSNARK | security | per-constraint proving time (ns) | proof size (bytes) | verifying time, 1 proof (ms) | verifying time, 100 proofs (s) | verifying time, 1000 proofs (s) |
| :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| BLS12-381 | [Gro16](https://github.com/arkworks-rs/groth16) | Weak SE | 5026 | 127.5 | 1.90 | 0.19 | 1.90|
| BLS12-381 | [GM17](https://github.com/arkworks-rs/gm17) | Strong SE | 11042 | 127.5 | 3.32 | 0.322 | 3.32|
| BLS12-381 | [BG18](https://github.com/Baghery/ABPR21/tree/BG18) | Strong SE | 5052 | 223.1 | 3.52 | 0.352 | 3.52|
| BLS12-381 | [ABPR21-CRH](https://github.com/Baghery/ABPR21/tree/CRH_Based) | Strong SE | 5042 | 223.1 | 4.85 | 0.360 | 3.50|
| BLS12-381 | ABPR21-RO | Strong SE | 5041 | 191.2 | 2.39 | 0.194 | 1.91|
| MNT4-298 | [Gro16](https://github.com/arkworks-rs/groth16) | Weak SE | 4830 | 149.0 | 2.67 | 0.267 | 2.67|
| MNT4-298 | [GM17](https://github.com/arkworks-rs/gm17) | Strong SE | 10025 | 149.0 | 3.80 | 0.380 | 3.80|
| MNT4-298 | [BG18](https://github.com/Baghery/ABPR21/tree/BG18) | Strong SE | 4879 | 260.7 | 4.32 | 0.432 | 4.32|
| MNT4-298 | [ABPR21-CRH](https://github.com/Baghery/ABPR21/tree/CRH_Based) | Strong SE | 4881 | 260.7 | 4.45 | 0.311 | 3.05|
| MNT4-298 | ABPR21-RO | Strong SE | 4875 | 223.5 | 3.33 | 0.271 | 2.68|
| MTN6-298 | [Gro16](https://github.com/arkworks-rs/groth16) | Weak SE | 5794 | 186.2 | 4.94 | 0.494 | 4.91|
| MTN6-298 | [GM17](https://github.com/arkworks-rs/gm17) | Strong SE | 11427 | 186.2 | 7.07 | 0.707 | 7.07|
| MTN6-298 | [BG18](https://github.com/Baghery/ABPR21/tree/BG18) | Strong SE | 5831 | 335.2 | 8.07 | 0.807 | 8.07|
| MTN6-298 | [ABPR21-CRH](https://github.com/Baghery/ABPR21/tree/CRH_Based) | Strong SE | 5824 | 335.2 | 8.34 | 0.582 | 5.72|
| MTN6-298 | ABPR21-RO | Strong SE | 5810 | 298.0 | 6.11 | 0.501 | 4.97|
| MNT4-753 | [Gro16](https://github.com/arkworks-rs/groth16) | Weak SE | 30247 | 376.5 | 29.1 | 2.91 | 29.1|
| MNT4-753 | [GM17](https://github.com/arkworks-rs/gm17) | Strong SE | 83120 | 376.5 | 41.6 | 4.16 | 41.6|
| MNT4-753 | [BG18](https://github.com/Baghery/ABPR21/tree/BG18) | Strong SE | 30863 | 658.8 | 47.3 | 4.73 | 47.3|
| MNT4-753 | [ABPR21-CRH](https://github.com/Baghery/ABPR21/tree/CRH_Based) | Strong SE | 30887 | 658.8 | 45.5 | 3.41 | 33.8|
| MNT4-753 | ABPR21-RO | Strong SE | 30760 | 564.7 | 33.9 | 2.94 | 29.2|
| MTN6-753 | [Gro16](https://github.com/arkworks-rs/groth16) | Weak SE | 33298 | 470.6 | 53.6 | 5.36 | 53.6|
| MTN6-753 | [GM17](https://github.com/arkworks-rs/gm17) | Strong SE | 83121 | 470.6 | 76.9 | 7.69 | 76.9|
| MTN6-753 | [BG18](https://github.com/Baghery/ABPR21/tree/BG18) | Strong SE | 33358 | 847.1 | 88.5 | 8.85 | 88.5|
| MTN6-753 | [ABPR21-CRH](https://github.com/Baghery/ABPR21/tree/CRH_Based) | Strong SE | 33359 | 847.1 | 85.4 | 6.33 | 63.1|
| MTN6-753 | ABPR21-RO | Strong SE | 33345 | 753.0 | 64.4 | 5.42 | 53.8|

## License

This library is licensed under either of the following licenses, at your discretion.

* Apache License Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

Unless you explicitly state otherwise, any contribution submitted for inclusion in this library by you shall be dual licensed as above (as defined in the Apache v2 License), without any additional terms or conditions.

## References

[\[ABPR21\]](https://eprint.iacr.org/2020/1306): Simulation Extractable Versions of Groth’s zk-SNARK Revisited. Oussama Amine, Karim Baghery, Zaira Pindado, and Carla Ràfols. 2021. Note: Full version of \[BPR20\].

[\[BPR20\]](https://eprint.iacr.org/2020/1306): Simulation Extractable Versions of Groth’s zk-SNARK Revisited. Karim Baghery, Zaira Pindado, and Carla Ràfols. CANS'20. 2020.
199 changes: 199 additions & 0 deletions abpr21/benches/bench.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
// For benchmark, run:
// RAYON_NUM_THREADS=N cargo bench --no-default-features --features "std parallel" -- --nocapture
// where N is the number of threads you want to use (N = 1 for single-thread).

use ark_abpr21::ABPR21;
use ark_bls12_381::{Bls12_381, Fr as BlsFr};
use ark_crypto_primitives::SNARK;
use ark_ff::{PrimeField, UniformRand};
use ark_mnt4_298::{Fr as MNT4Fr, MNT4_298};
use ark_mnt4_753::{Fr as MNT4BigFr, MNT4_753};
use ark_mnt6_298::{Fr as MNT6Fr, MNT6_298};
use ark_mnt6_753::{Fr as MNT6BigFr, MNT6_753};
use ark_relations::{
lc,
r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError},
};
use ark_std::ops::Mul;

use ark_abpr21::{vec_verify_proof, Proof};

const NUM_PROVE_REPEATITIONS: usize = 10;
const NUM_VERIFY_REPEATITIONS: usize = 1000;
const NUM_PROVE_REPEATITIONS_AGG: usize = 100;
const NUM_VERIFY_REPEATITIONS_AGG: usize = 2;

#[derive(Copy)]
struct DummyCircuit<F: PrimeField> {
pub a: Option<F>,
pub b: Option<F>,
pub num_variables: usize,
pub num_constraints: usize,
}

impl<F: PrimeField> Clone for DummyCircuit<F> {
fn clone(&self) -> Self {
DummyCircuit {
a: self.a.clone(),
b: self.b.clone(),
num_variables: self.num_variables.clone(),
num_constraints: self.num_constraints.clone(),
}
}
}

impl<F: PrimeField> ConstraintSynthesizer<F> for DummyCircuit<F> {
fn generate_constraints(self, cs: ConstraintSystemRef<F>) -> Result<(), SynthesisError> {
let a = cs.new_witness_variable(|| self.a.ok_or(SynthesisError::AssignmentMissing))?;
let b = cs.new_witness_variable(|| self.b.ok_or(SynthesisError::AssignmentMissing))?;
let c = cs.new_input_variable(|| {
let a = self.a.ok_or(SynthesisError::AssignmentMissing)?;
let b = self.b.ok_or(SynthesisError::AssignmentMissing)?;

Ok(a * b)
})?;

for _ in 0..(self.num_variables - 3) {
let _ = cs.new_witness_variable(|| self.a.ok_or(SynthesisError::AssignmentMissing))?;
}

for _ in 0..self.num_constraints - 1 {
cs.enforce_constraint(lc!() + a, lc!() + b, lc!() + c)?;
}

cs.enforce_constraint(lc!(), lc!(), lc!())?;

Ok(())
}
}

macro_rules! abpr21_prove_bench {
($bench_name:ident, $bench_field:ty, $bench_pairing_engine:ty) => {
let rng = &mut ark_std::test_rng();
let c = DummyCircuit::<$bench_field> {
a: Some(<$bench_field>::rand(rng)),
b: Some(<$bench_field>::rand(rng)),
num_variables: 10,
num_constraints: 65536,
};

let (pk, _) = ABPR21::<$bench_pairing_engine>::circuit_specific_setup(c, rng).unwrap();

let start = ark_std::time::Instant::now();

for _ in 0..NUM_PROVE_REPEATITIONS {
let _ = ABPR21::<$bench_pairing_engine>::prove(&pk, c.clone(), rng).unwrap();
}

println!(
"per-constraint proving time for {}: {} ns/constraint",
stringify!($bench_pairing_engine),
start.elapsed().as_nanos() / NUM_PROVE_REPEATITIONS as u128 / 65536u128
);
};
}

macro_rules! abpr21_verify_bench {
($bench_name:ident, $bench_field:ty, $bench_pairing_engine:ty) => {
let rng = &mut ark_std::test_rng();
let c = DummyCircuit::<$bench_field> {
a: Some(<$bench_field>::rand(rng)),
b: Some(<$bench_field>::rand(rng)),
num_variables: 10,
num_constraints: 64,
};

let (pk, vk) = ABPR21::<$bench_pairing_engine>::circuit_specific_setup(c, rng).unwrap();
let proof = ABPR21::<$bench_pairing_engine>::prove(&pk, c.clone(), rng).unwrap();

let v = c.a.unwrap().mul(c.b.unwrap());

let start = ark_std::time::Instant::now();

for _ in 0..NUM_VERIFY_REPEATITIONS {
let _ = ABPR21::<$bench_pairing_engine>::verify(&vk, &vec![v], &proof).unwrap();
}

println!(
"verifying time for {}: {} ns",
stringify!($bench_pairing_engine),
start.elapsed().as_nanos() / NUM_VERIFY_REPEATITIONS as u128
);
};
}

macro_rules! abpr21_verify_bench_vec {
($bench_name:ident, $bench_field:ty, $bench_pairing_engine:ty) => {
let rng = &mut ark_std::test_rng();
let c = DummyCircuit::<$bench_field> {
a: Some(<$bench_field>::rand(rng)),
b: Some(<$bench_field>::rand(rng)),
num_variables: 10,
num_constraints: 64,
};
let mut proofs: Vec<Proof<_>> = Vec::with_capacity(NUM_PROVE_REPEATITIONS_AGG as usize);
let mut prepared_inputs: Vec<Vec<_>> = Vec::new();
let (pk, vk) = ABPR21::<$bench_pairing_engine>::circuit_specific_setup(c, rng).unwrap();

for _ in 0..NUM_PROVE_REPEATITIONS_AGG {
proofs.push(ABPR21::<$bench_pairing_engine>::prove(&pk, c.clone(), rng).unwrap());
}

let v = c.a.unwrap().mul(c.b.unwrap());

//Now the counter starts
let start = ark_std::time::Instant::now();

//The preprocessing of the inputs
for _ in 0..NUM_PROVE_REPEATITIONS_AGG {
prepared_inputs.push(vec![v]);
}

//Verification starts!
for p in 0..NUM_VERIFY_REPEATITIONS_AGG {
println!("loop number {:?} in verification loops:", p);
vec_verify_proof::<$bench_pairing_engine>(&vk, &proofs, &prepared_inputs).unwrap();
}

println!(
"--> Verifying time for {}: {} ns",
stringify!($bench_pairing_engine),
start.elapsed().as_nanos()
/ NUM_VERIFY_REPEATITIONS_AGG as u128
/ NUM_PROVE_REPEATITIONS_AGG as u128
);
};
}

// Benchmark for prover
fn bench_prove() {
abpr21_prove_bench!(bls, BlsFr, Bls12_381);
abpr21_prove_bench!(mnt4, MNT4Fr, MNT4_298);
abpr21_prove_bench!(mnt6, MNT6Fr, MNT6_298);
abpr21_prove_bench!(mnt4big, MNT4BigFr, MNT4_753);
abpr21_prove_bench!(mnt6big, MNT6BigFr, MNT6_753);
}

// Benchmark for verifier
fn bench_verify() {
abpr21_verify_bench!(bls, BlsFr, Bls12_381);
abpr21_verify_bench!(mnt4, MNT4Fr, MNT4_298);
abpr21_verify_bench!(mnt6, MNT6Fr, MNT6_298);
abpr21_verify_bench!(mnt4big, MNT4BigFr, MNT4_753);
abpr21_verify_bench!(mnt6big, MNT6BigFr, MNT6_753);
}

// Benchmark for aggregated verifier
fn bench_agg_verify() {
abpr21_verify_bench_vec!(bls, BlsFr, Bls12_381);
abpr21_verify_bench_vec!(mnt4, MNT4Fr, MNT4_298);
abpr21_verify_bench_vec!(mnt6, MNT6Fr, MNT6_298);
abpr21_verify_bench_vec!(mnt4big, MNT4BigFr, MNT4_753);
abpr21_verify_bench_vec!(mnt6big, MNT6BigFr, MNT6_753);
}

fn main() {
bench_prove();
bench_verify();
bench_agg_verify();
}
Loading