diff --git a/Cargo.toml b/Cargo.toml index e1df872..f3645b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,31 +29,19 @@ name = "libspartan" path = "src/lib.rs" [[bin]] -name = "profiler" -path = "src/profiler.rs" +name = "snark" +path = "profiler/snark.rs" -[[bench]] -name = "commitments" -harness = false - -[[bench]] -name = "dotproduct" -harness = false - -[[bench]] -name = "polycommit" -harness = false - -[[bench]] -name = "r1csproof" -harness = false +[[bin]] +name = "nizk" +path = "profiler/nizk.rs" [[bench]] -name = "spartan" +name = "snark" harness = false [[bench]] -name = "sumcheck" +name = "nizk" harness = false [features] diff --git a/NOTICE.md b/NOTICE.md index 1224a34..43b69c5 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -1,6 +1,6 @@ This repository includes the following third-party open-source code. -* The code in scalar_25519.rs is derived from [bls12-381](https://github.com/zkcrypto/bls12_381). +* The code in src/scalar/ristretto255.rs is derived from [bls12-381](https://github.com/zkcrypto/bls12_381). Specifically, from [src/bls12_381/scalar.rs](https://github.com/zkcrypto/bls12_381/blob/master/src/scalar.rs) and [src/bls12_381/util.rs](https://github.com/zkcrypto/bls12_381/blob/master/src/util.rs), which has the following copyright and license. Permission is hereby granted, free of charge, to any @@ -28,7 +28,7 @@ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -* The invert and batch_invert methods in src/scalar_25519.rs is from [curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek), which has the following copyright and license. +* The invert and batch_invert methods in src/scalar/ristretto255.rs is from [curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek), which has the following copyright and license. Copyright (c) 2016-2019 Isis Agora Lovecruft, Henry de Valence. All rights reserved. @@ -96,7 +96,7 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* The bullet.rs is derived from [bulletproofs](https://github.com/dalek-cryptography/bulletproofs/), which has the following license: +* The src/nizk/bullet.rs is derived from [bulletproofs](https://github.com/dalek-cryptography/bulletproofs/), which has the following license: MIT License diff --git a/benches/commitments.rs b/benches/commitments.rs deleted file mode 100644 index ebc6be2..0000000 --- a/benches/commitments.rs +++ /dev/null @@ -1,47 +0,0 @@ -extern crate byteorder; -extern crate core; -extern crate criterion; -extern crate digest; -extern crate libspartan; -extern crate merlin; -extern crate rand; -extern crate sha3; - -use libspartan::commitments::{Commitments, MultiCommitGens}; -use libspartan::math::Math; -use libspartan::scalar::Scalar; -use rand::rngs::OsRng; - -use criterion::*; - -fn commitment_benchmark(c: &mut Criterion) { - let mut rng = OsRng; - for &s in [20].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("commitment_bools"); - group.plot_config(plot_config); - - let n = (s as usize).pow2(); - let gens = MultiCommitGens::new(n, b"test-m"); - let blind = Scalar::random(&mut rng); - let vec: Vec = vec![true; n]; - let name = format!("commitment_bools_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| vec.commit(black_box(&blind), black_box(&gens))); - }); - group.finish(); - } -} - -fn set_duration() -> Criterion { - Criterion::default().sample_size(10) - // .measurement_time(Duration::new(0, 50000000)) -} - -criterion_group! { -name = benches_commitment; -config = set_duration(); -targets = commitment_benchmark -} - -criterion_main!(benches_commitment); diff --git a/benches/dotproduct.rs b/benches/dotproduct.rs deleted file mode 100644 index 1aa4cd8..0000000 --- a/benches/dotproduct.rs +++ /dev/null @@ -1,85 +0,0 @@ -extern crate byteorder; -extern crate core; -extern crate criterion; -extern crate digest; -extern crate libspartan; -extern crate merlin; -extern crate rand; -extern crate sha3; - -use libspartan::math::Math; -use libspartan::nizk::DotProductProof; -use libspartan::scalar::Scalar; -use libspartan::scalar::ScalarBytes; -use rand::rngs::OsRng; - -use criterion::*; - -fn dotproduct_benchmark_dalek(c: &mut Criterion) { - let mut csprng: OsRng = OsRng; - - for &s in [20].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("dotproduct_benchmark_dalek"); - group.plot_config(plot_config); - - let n = (s as usize).pow2(); - let vec_a = (0..n) - .map(|_i| ScalarBytes::random(&mut csprng)) - .collect::>(); - let vec_b = (0..n) - .map(|_i| ScalarBytes::random(&mut csprng)) - .collect::>(); - - let name = format!("dotproduct_dalek_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| compute_dotproduct(black_box(&vec_a), black_box(&vec_b))); - }); - group.finish(); - } -} - -fn compute_dotproduct(a: &Vec, b: &Vec) -> ScalarBytes { - let mut res = ScalarBytes::zero(); - for i in 0..a.len() { - res = &res + &a[i] * &b[i]; - } - res -} - -fn dotproduct_benchmark_opt(c: &mut Criterion) { - let mut csprng: OsRng = OsRng; - - for &s in [20].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("dotproduct_benchmark_opt"); - group.plot_config(plot_config); - - let n = (s as usize).pow2(); - let vec_a = (0..n) - .map(|_i| Scalar::random(&mut csprng)) - .collect::>(); - let vec_b = (0..n) - .map(|_i| Scalar::random(&mut csprng)) - .collect::>(); - - let name = format!("dotproduct_opt_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| DotProductProof::compute_dotproduct(black_box(&vec_a), black_box(&vec_b))); - }); - group.finish(); - } -} - -fn set_duration() -> Criterion { - Criterion::default().sample_size(10) - // .measurement_time(Duration::new(0, 50000000)) -} - -criterion_group! { -name = benches_dotproduct; -config = set_duration(); -targets = dotproduct_benchmark_dalek, dotproduct_benchmark_opt -} - -criterion_main!(benches_dotproduct); diff --git a/benches/r1csproof.rs b/benches/nizk.rs similarity index 53% rename from benches/r1csproof.rs rename to benches/nizk.rs index d0e087d..10bd0ff 100644 --- a/benches/r1csproof.rs +++ b/benches/nizk.rs @@ -7,89 +7,70 @@ extern crate merlin; extern crate rand; extern crate sha3; -use libspartan::dense_mlpoly::EqPolynomial; -use libspartan::math::Math; use libspartan::r1csinstance::R1CSInstance; -use libspartan::r1csproof::{R1CSGens, R1CSProof}; -use libspartan::random::RandomTape; -use libspartan::scalar::Scalar; -use libspartan::transcript::ProofTranscript; +use libspartan::spartan::{NIZKGens, NIZK}; use merlin::Transcript; -use rand::rngs::OsRng; use criterion::*; -fn prove_benchmark(c: &mut Criterion) { +fn nizk_prove_benchmark(c: &mut Criterion) { for &s in [10, 12, 16].iter() { let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("r1cs_prove_benchmark"); + let mut group = c.benchmark_group("NIZK_prove_benchmark"); group.plot_config(plot_config); - let num_vars = s.pow2(); + let num_vars = (2 as usize).pow(s as u32); let num_cons = num_vars; let num_inputs = 10; + let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); let n = inst.get_num_vars(); - let gens = R1CSGens::new(num_cons, num_vars, b"test-m"); + let gens = NIZKGens::new(num_cons, num_vars); - let name = format!("r1cs_prove_{}", n); + let name = format!("NIZK_prove_{}", n); group.bench_function(&name, move |b| { b.iter(|| { - let mut random_tape = RandomTape::new(b"proof"); let mut prover_transcript = Transcript::new(b"example"); - R1CSProof::prove( + NIZK::prove( black_box(&inst), black_box(vars.clone()), black_box(&input), black_box(&gens), black_box(&mut prover_transcript), - black_box(&mut random_tape), - ) + ); }); }); group.finish(); } } -fn verify_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16, 20].iter() { +fn nizk_verify_benchmark(c: &mut Criterion) { + for &s in [10, 12, 16].iter() { let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("r1cs_verify_benchmark"); + let mut group = c.benchmark_group("NIZK_verify_benchmark"); group.plot_config(plot_config); - let num_vars = s.pow2(); + let num_vars = (2 as usize).pow(s as u32); let num_cons = num_vars; let num_inputs = 10; let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); let n = inst.get_num_vars(); - let gens = R1CSGens::new(num_cons, num_vars, b"test-m"); - let mut random_tape = RandomTape::new(b"proof"); - let mut prover_transcript = Transcript::new(b"example"); - let (proof, rx, ry) = R1CSProof::prove( - &inst, - vars, - &input, - &gens, - &mut prover_transcript, - &mut random_tape, - ); + let gens = NIZKGens::new(num_cons, num_vars); - let eval_table_rx = EqPolynomial::new(rx.clone()).evals(); - let eval_table_ry = EqPolynomial::new(ry.clone()).evals(); - let inst_evals = inst.evaluate_with_tables(&eval_table_rx, &eval_table_ry); + // produce a proof of satisfiability + let mut prover_transcript = Transcript::new(b"example"); + let proof = NIZK::prove(&inst, vars, &input, &gens, &mut prover_transcript); - let name = format!("r1cs_verify_{}", n); + let name = format!("NIZK_verify_{}", n); group.bench_function(&name, move |b| { b.iter(|| { let mut verifier_transcript = Transcript::new(b"example"); assert!(proof .verify( - black_box(num_vars), - black_box(num_cons), + black_box(&inst), black_box(&input), - black_box(&inst_evals), black_box(&mut verifier_transcript), black_box(&gens) ) @@ -102,13 +83,12 @@ fn verify_benchmark(c: &mut Criterion) { fn set_duration() -> Criterion { Criterion::default().sample_size(10) - // .measurement_time(Duration::new(0, 50000000)) } criterion_group! { -name = benches_r1cs; +name = benches_nizk; config = set_duration(); -targets = prove_benchmark, verify_benchmark +targets = nizk_prove_benchmark, nizk_verify_benchmark } -criterion_main!(benches_r1cs); +criterion_main!(benches_nizk); diff --git a/benches/polycommit.rs b/benches/polycommit.rs deleted file mode 100644 index 7905217..0000000 --- a/benches/polycommit.rs +++ /dev/null @@ -1,191 +0,0 @@ -extern crate byteorder; -extern crate core; -extern crate criterion; -extern crate digest; -extern crate libspartan; -extern crate merlin; -extern crate rand; -extern crate sha3; - -use criterion::*; -use libspartan::dense_mlpoly::{DensePolynomial, PolyCommitmentGens, PolyEvalProof}; -use libspartan::math::Math; -use libspartan::random::RandomTape; -use libspartan::scalar::Scalar; -use libspartan::transcript::ProofTranscript; -use merlin::Transcript; -use rand::rngs::OsRng; - -fn commit_benchmark(c: &mut Criterion) { - let mut csprng: OsRng = OsRng; - - for &s in [4, 8, 12, 14, 16, 20].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("commit_benchmark"); - group.plot_config(plot_config); - - let n = (s as usize).pow2(); - let m = n.square_root(); - let z = (0..n) - .map(|_i| Scalar::random(&mut csprng)) - .collect::>(); - assert_eq!(m * m, z.len()); // check if Z's size if a perfect square - - let poly = DensePolynomial::new(z); - let gens = PolyCommitmentGens::new(s, b"test-m"); - let name = format!("polycommit_commit_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| poly.commit(black_box(false), black_box(&gens), black_box(None))); - }); - group.finish(); - } -} - -fn eval_benchmark(c: &mut Criterion) { - let mut csprng: OsRng = OsRng; - - for &s in [4, 8, 12, 14, 16, 20].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("eval_benchmark"); - group.plot_config(plot_config); - - let n = (s as usize).pow2(); - let m = n.square_root(); - let mut z: Vec = Vec::new(); - for _ in 0..n { - z.push(Scalar::random(&mut csprng)); - } - assert_eq!(m * m, z.len()); // check if Z's size if a perfect square - - let poly = DensePolynomial::new(z); - - let mut r: Vec = Vec::new(); - for _ in 0..s { - r.push(Scalar::random(&mut csprng)); - } - - let name = format!("polycommit_eval_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| poly.evaluate(black_box(&r))); - }); - group.finish(); - } -} - -fn evalproof_benchmark(c: &mut Criterion) { - let mut csprng: OsRng = OsRng; - - for &s in [4, 8, 12, 14, 16, 20].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("evalproof_benchmark"); - group.plot_config(plot_config); - - let n = (s as usize).pow2(); - let m = n.square_root(); - let mut z: Vec = Vec::new(); - for _ in 0..n { - z.push(Scalar::random(&mut csprng)); - } - assert_eq!(m * m, z.len()); // check if Z's size if a perfect square - - let poly = DensePolynomial::new(z); - - let gens = PolyCommitmentGens::new(s, b"test-m"); - - let mut r: Vec = Vec::new(); - for _ in 0..s { - r.push(Scalar::random(&mut csprng)); - } - - let eval = poly.evaluate(&r); - - let name = format!("polycommit_evalproof_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| { - let mut random_tape = RandomTape::new(b"proof"); - let mut prover_transcript = Transcript::new(b"example"); - PolyEvalProof::prove( - black_box(&poly), - black_box(None), - black_box(&r), - black_box(&eval), - black_box(None), - black_box(&gens), - black_box(&mut prover_transcript), - black_box(&mut random_tape), - ) - }); - }); - group.finish(); - } -} - -fn evalproofverify_benchmark(c: &mut Criterion) { - let mut csprng: OsRng = OsRng; - - for &s in [4, 8, 12, 14, 16, 20].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("evalproofverify_benchmark"); - group.plot_config(plot_config); - - let n = s.pow2(); - let m = n.square_root(); - let mut z: Vec = Vec::new(); - for _ in 0..n { - z.push(Scalar::random(&mut csprng)); - } - assert_eq!(m * m, z.len()); // check if Z's size if a perfect square - - let poly = DensePolynomial::new(z); - let gens = PolyCommitmentGens::new(s, b"test-m"); - - let mut r: Vec = Vec::new(); - for _ in 0..s { - r.push(Scalar::random(&mut csprng)); - } - - let (poly_commitment, blinds) = poly.commit(false, &gens, None); - let eval = poly.evaluate(&r); - - let mut random_tape = RandomTape::new(b"proof"); - let mut prover_transcript = Transcript::new(b"example"); - let (proof, c_zr) = PolyEvalProof::prove( - black_box(&poly), - black_box(Some(&blinds)), - black_box(&r), - black_box(&eval), - black_box(None), - black_box(&gens), - black_box(&mut prover_transcript), - black_box(&mut random_tape), - ); - let name = format!("polycommit_evalproofverify_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| { - let mut verifier_transcript = Transcript::new(b"example"); - - proof.verify( - black_box(&gens), - black_box(&mut verifier_transcript), - black_box(&r), - black_box(&c_zr), - black_box(&poly_commitment), - ) - }); - }); - group.finish(); - } -} - -fn set_duration() -> Criterion { - Criterion::default().sample_size(10) - // .measurement_time(Duration::new(0, 50000000)) -} - -criterion_group! { -name = benches_polycommit; -config = set_duration(); -targets = commit_benchmark, eval_benchmark, evalproof_benchmark, evalproofverify_benchmark -} - -criterion_main!(benches_polycommit); diff --git a/benches/snark.rs b/benches/snark.rs new file mode 100644 index 0000000..c631534 --- /dev/null +++ b/benches/snark.rs @@ -0,0 +1,130 @@ +extern crate byteorder; +extern crate core; +extern crate criterion; +extern crate digest; +extern crate libspartan; +extern crate merlin; +extern crate rand; +extern crate sha3; + +use libspartan::r1csinstance::R1CSInstance; +use libspartan::spartan::{SNARKGens, SNARK}; +use merlin::Transcript; + +use criterion::*; + +fn snark_encode_benchmark(c: &mut Criterion) { + for &s in [10, 12, 16].iter() { + let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); + let mut group = c.benchmark_group("SNARK_encode_benchmark"); + group.plot_config(plot_config); + + let num_vars = (2 as usize).pow(s as u32); + let num_cons = num_vars; + let num_inputs = 10; + let (inst, _vars, _input) = + R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); + let n = inst.get_num_vars(); + + // produce public parameters + let gens = SNARKGens::new(&inst.size()); + + let name = format!("SNARK_encode_{}", n); + group.bench_function(&name, move |b| { + b.iter(|| { + SNARK::encode(black_box(&inst), black_box(&gens)); + }); + }); + group.finish(); + } +} + +fn snark_prove_benchmark(c: &mut Criterion) { + for &s in [10, 12, 16].iter() { + let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); + let mut group = c.benchmark_group("SNARK_prove_benchmark"); + group.plot_config(plot_config); + + let num_vars = (2 as usize).pow(s as u32); + let num_cons = num_vars; + let num_inputs = 10; + + let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); + let n = inst.get_num_vars(); + + // produce public parameters + let gens = SNARKGens::new(&inst.size()); + + // encode the R1CS instance + let (_comm, decomm) = SNARK::encode(&inst, &gens); + + // produce a proof + let name = format!("SNARK_prove_{}", n); + group.bench_function(&name, move |b| { + b.iter(|| { + let mut prover_transcript = Transcript::new(b"example"); + SNARK::prove( + black_box(&inst), + black_box(&decomm), + black_box(vars.clone()), + black_box(&input), + black_box(&gens), + black_box(&mut prover_transcript), + ); + }); + }); + group.finish(); + } +} + +fn snark_verify_benchmark(c: &mut Criterion) { + for &s in [10, 12, 16].iter() { + let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); + let mut group = c.benchmark_group("SNARK_verify_benchmark"); + group.plot_config(plot_config); + + let num_vars = (2 as usize).pow(s as u32); + let num_cons = num_vars; + let num_inputs = 10; + let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); + let n = inst.get_num_vars(); + + // produce public parameters + let gens = SNARKGens::new(&inst.size()); + + // encode the R1CS instance + let (comm, decomm) = SNARK::encode(&inst, &gens); + + // produce a proof of satisfiability + let mut prover_transcript = Transcript::new(b"example"); + let proof = SNARK::prove(&inst, &decomm, vars, &input, &gens, &mut prover_transcript); + + let name = format!("SNARK_verify_{}", n); + group.bench_function(&name, move |b| { + b.iter(|| { + let mut verifier_transcript = Transcript::new(b"example"); + assert!(proof + .verify( + black_box(&comm), + black_box(&input), + black_box(&mut verifier_transcript), + black_box(&gens) + ) + .is_ok()); + }); + }); + group.finish(); + } +} + +fn set_duration() -> Criterion { + Criterion::default().sample_size(10) +} + +criterion_group! { +name = benches_snark; +config = set_duration(); +targets = snark_encode_benchmark, snark_prove_benchmark, snark_verify_benchmark +} + +criterion_main!(benches_snark); diff --git a/benches/spartan.rs b/benches/spartan.rs deleted file mode 100644 index 9a3db16..0000000 --- a/benches/spartan.rs +++ /dev/null @@ -1,206 +0,0 @@ -extern crate byteorder; -extern crate core; -extern crate criterion; -extern crate digest; -extern crate libspartan; -extern crate merlin; -extern crate rand; -extern crate sha3; - -use libspartan::math::Math; -use libspartan::r1csinstance::{R1CSCommitmentGens, R1CSInstance}; -use libspartan::r1csproof::R1CSGens; -use libspartan::spartan::{NIZKGens, SNARKGens, NIZK, SNARK}; -use merlin::Transcript; - -use criterion::*; - -fn snark_encode_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("SNARK_encode_benchmark"); - group.plot_config(plot_config); - - let num_vars = s.pow2(); - let num_cons = num_vars; - let num_inputs = 10; - let (inst, _vars, _input) = - R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - let n = inst.get_num_vars(); - let r1cs_size = inst.size(); - let gens_r1cs = R1CSCommitmentGens::new(&r1cs_size, b"gens_r1cs"); - - let name = format!("SNARK_encode_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| { - SNARK::encode(black_box(&inst), black_box(&gens_r1cs)); - }); - }); - group.finish(); - } -} - -fn snark_prove_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("SNARK_prove_benchmark"); - group.plot_config(plot_config); - - let num_vars = s.pow2(); - let num_cons = num_vars; - let num_inputs = 10; - - let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - let n = inst.get_num_vars(); - - let r1cs_size = inst.size(); - let gens_r1cs_eval = R1CSCommitmentGens::new(&r1cs_size, b"gens_r1cs_eval"); - let gens_r1cs_sat = R1CSGens::new(num_cons, num_vars, b"gens_r1cs_sat"); - - // produce a proof of satisfiability - let (_comm, decomm) = SNARK::encode(&inst, &gens_r1cs_eval); - let gens = SNARKGens::new(gens_r1cs_sat, gens_r1cs_eval); - - let name = format!("SNARK_prove_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| { - let mut prover_transcript = Transcript::new(b"example"); - SNARK::prove( - black_box(&inst), - black_box(&decomm), - black_box(vars.clone()), - black_box(&input), - black_box(&gens), - black_box(&mut prover_transcript), - ); - }); - }); - group.finish(); - } -} - -fn snark_verify_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("SNARK_verify_benchmark"); - group.plot_config(plot_config); - - let num_vars = s.pow2(); - let num_cons = num_vars; - let num_inputs = 10; - let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - let n = inst.get_num_vars(); - - let r1cs_size = inst.size(); - let gens_r1cs_eval = R1CSCommitmentGens::new(&r1cs_size, b"gens_r1cs_eval"); - - // create a commitment to R1CSInstance - let (comm, decomm) = SNARK::encode(&inst, &gens_r1cs_eval); - - let gens_r1cs_sat = R1CSGens::new(num_cons, num_vars, b"gens_r1cs_sat"); - let gens = SNARKGens::new(gens_r1cs_sat, gens_r1cs_eval); - - // produce a proof of satisfiability - let mut prover_transcript = Transcript::new(b"example"); - let proof = SNARK::prove(&inst, &decomm, vars, &input, &gens, &mut prover_transcript); - - let name = format!("SNARK_verify_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| { - let mut verifier_transcript = Transcript::new(b"example"); - assert!(proof - .verify( - black_box(&comm), - black_box(&input), - black_box(&mut verifier_transcript), - black_box(&gens) - ) - .is_ok()); - }); - }); - group.finish(); - } -} - -fn nizk_prove_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("NIZK_prove_benchmark"); - group.plot_config(plot_config); - - let num_vars = s.pow2(); - let num_cons = num_vars; - let num_inputs = 10; - - let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - let n = inst.get_num_vars(); - - let gens_r1cs_sat = R1CSGens::new(num_cons, num_vars, b"gens_r1cs_sat"); - let gens = NIZKGens::new(gens_r1cs_sat); - - let name = format!("NIZK_prove_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| { - let mut prover_transcript = Transcript::new(b"example"); - NIZK::prove( - black_box(&inst), - black_box(vars.clone()), - black_box(&input), - black_box(&gens), - black_box(&mut prover_transcript), - ); - }); - }); - group.finish(); - } -} - -fn nizk_verify_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("NIZK_verify_benchmark"); - group.plot_config(plot_config); - - let num_vars = s.pow2(); - let num_cons = num_vars; - let num_inputs = 10; - let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - let n = inst.get_num_vars(); - - let gens_r1cs_sat = R1CSGens::new(num_cons, num_vars, b"gens_r1cs_sat"); - let gens = NIZKGens::new(gens_r1cs_sat); - - // produce a proof of satisfiability - let mut prover_transcript = Transcript::new(b"example"); - let proof = NIZK::prove(&inst, vars, &input, &gens, &mut prover_transcript); - - let name = format!("NIZK_verify_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| { - let mut verifier_transcript = Transcript::new(b"example"); - assert!(proof - .verify( - black_box(&inst), - black_box(&input), - black_box(&mut verifier_transcript), - black_box(&gens) - ) - .is_ok()); - }); - }); - group.finish(); - } -} - -fn set_duration() -> Criterion { - Criterion::default().sample_size(10) - // .measurement_time(Duration::new(0, 50000000)) -} - -criterion_group! { -name = benches_spartan; -config = set_duration(); -targets = snark_encode_benchmark, snark_prove_benchmark, snark_verify_benchmark, nizk_prove_benchmark, nizk_verify_benchmark -} - -criterion_main!(benches_spartan); diff --git a/benches/sumcheck.rs b/benches/sumcheck.rs deleted file mode 100644 index 5022a69..0000000 --- a/benches/sumcheck.rs +++ /dev/null @@ -1,152 +0,0 @@ -#![allow(non_snake_case)] - -extern crate byteorder; -extern crate core; -extern crate criterion; -extern crate digest; -extern crate libspartan; -extern crate merlin; -extern crate rand; -extern crate sha3; - -use libspartan::commitments::Commitments; -use libspartan::commitments::MultiCommitGens; -use libspartan::dense_mlpoly::DensePolynomial; -use libspartan::math::Math; -use libspartan::nizk::DotProductProof; -use libspartan::random::RandomTape; -use libspartan::scalar::Scalar; -use libspartan::sumcheck::ZKSumcheckInstanceProof; -use libspartan::transcript::ProofTranscript; -use merlin::Transcript; -use rand::rngs::OsRng; - -use criterion::*; - -fn prove_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16, 20].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("zksumcheck_prove_benchmark"); - group.plot_config(plot_config); - - // produce tables - let gens_n = MultiCommitGens::new(3, b"test-m"); - let gens_1 = MultiCommitGens::new(1, b"test-1"); - let num_rounds = s; - let n = s.pow2(); - - let mut csprng: OsRng = OsRng; - - let vec_A = (0..n) - .map(|_i| Scalar::random(&mut csprng)) - .collect::>(); - let vec_B = (0..n) - .map(|_i| Scalar::random(&mut csprng)) - .collect::>(); - let claim = DotProductProof::compute_dotproduct(&vec_A, &vec_B); - let mut poly_A = DensePolynomial::new(vec_A); - let mut poly_B = DensePolynomial::new(vec_B); - - let blind_claim = Scalar::random(&mut csprng); - let comb_func = - |poly_A_comp: &Scalar, poly_B_comp: &Scalar| -> Scalar { poly_A_comp * poly_B_comp }; - - let name = format!("zksumcheck_prove_{}", n); - group.bench_function(&name, move |b| { - b.iter(|| { - let mut random_tape = RandomTape::new(b"proof"); - let mut prover_transcript = Transcript::new(b"example"); - ZKSumcheckInstanceProof::prove_quad( - black_box(&claim), - black_box(&blind_claim), - black_box(num_rounds), - black_box(&mut poly_A), - black_box(&mut poly_B), - black_box(comb_func), - black_box(&gens_1), - black_box(&gens_n), - black_box(&mut prover_transcript), - black_box(&mut random_tape), - ) - }); - }); - group.finish(); - } -} - -fn verify_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16, 20].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("zksumcheck_verify_benchmark"); - group.plot_config(plot_config); - - // produce tables - let gens_n = MultiCommitGens::new(3, b"test-m"); - let gens_1 = MultiCommitGens::new(1, b"test-1"); - let num_rounds = s; - let n = s.pow2(); - - let mut csprng: OsRng = OsRng; - - let vec_A = (0..n) - .map(|_i| Scalar::random(&mut csprng)) - .collect::>(); - let vec_B = (0..n) - .map(|_i| Scalar::random(&mut csprng)) - .collect::>(); - let claim = DotProductProof::compute_dotproduct(&vec_A, &vec_B); - let mut poly_A = DensePolynomial::new(vec_A); - let mut poly_B = DensePolynomial::new(vec_B); - let blind_claim = Scalar::random(&mut csprng); - let comb_func = - |poly_A_comp: &Scalar, poly_B_comp: &Scalar| -> Scalar { poly_A_comp * poly_B_comp }; - - let mut random_tape = RandomTape::new(b"proof"); - let mut prover_transcript = Transcript::new(b"example"); - let (proof, _r, _v, _blind_post_claim) = ZKSumcheckInstanceProof::prove_quad( - &claim, - &blind_claim, - num_rounds, - &mut poly_A, - &mut poly_B, - comb_func, - &gens_1, - &gens_n, - &mut prover_transcript, - &mut random_tape, - ); - - let name = format!("zksumcheck_verify_{}", n); - let degree_bound = 2; - let comm_claim = claim.commit(&blind_claim, &gens_1).compress(); - group.bench_function(&name, move |b| { - b.iter(|| { - let mut verifier_transcript = Transcript::new(b"example"); - assert!(proof - .verify( - black_box(&comm_claim), - black_box(num_rounds), - black_box(degree_bound), - black_box(&gens_1), - black_box(&gens_n), - black_box(&mut verifier_transcript) - ) - .is_ok()) - }); - }); - group.finish(); - } -} - -fn set_duration() -> Criterion { - Criterion::default().sample_size(10) - // .measurement_time(Duration::new(0, 50000000)) -} - -criterion_group! { -name = benches_r1cs; -config = set_duration(); -targets = verify_benchmark, prove_benchmark -} - -criterion_main!(benches_r1cs); diff --git a/profiler/nizk.rs b/profiler/nizk.rs new file mode 100644 index 0000000..1868b78 --- /dev/null +++ b/profiler/nizk.rs @@ -0,0 +1,51 @@ +#![allow(non_snake_case)] +extern crate flate2; +extern crate libspartan; +extern crate merlin; +extern crate rand; + +use flate2::{write::ZlibEncoder, Compression}; +use libspartan::r1csinstance::R1CSInstance; +use libspartan::spartan::{NIZKGens, NIZK}; +use libspartan::timer::Timer; +use merlin::Transcript; + +pub fn main() { + // the list of number of variables (and constraints) in an R1CS instance + let inst_sizes = vec![12, 16, 20]; + + println!("Profiler:: NIZK"); + for &s in inst_sizes.iter() { + let num_vars = (2 as usize).pow(s as u32); + let num_cons = num_vars; + let num_inputs = 10; + let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); + + Timer::print(&format!("number_of_constraints {}", num_cons)); + + // produce public generators + let gens = NIZKGens::new(num_cons, num_vars); + + // produce a proof of satisfiability + let timer_prove = Timer::new("NIZK::prove"); + let mut prover_transcript = Transcript::new(b"example"); + let proof = NIZK::prove(&inst, vars, &input, &gens, &mut prover_transcript); + timer_prove.stop(); + + let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default()); + bincode::serialize_into(&mut encoder, &proof).unwrap(); + let proof_encoded = encoder.finish().unwrap(); + let msg_proof_len = format!("NIZK::proof_compressed_len {:?}", proof_encoded.len()); + Timer::print(&msg_proof_len); + + // verify the proof of satisfiability + let timer_verify = Timer::new("NIZK::verify"); + let mut verifier_transcript = Transcript::new(b"example"); + assert!(proof + .verify(&inst, &input, &mut verifier_transcript, &gens) + .is_ok()); + timer_verify.stop(); + + println!(); + } +} diff --git a/profiler/snark.rs b/profiler/snark.rs new file mode 100644 index 0000000..c441b49 --- /dev/null +++ b/profiler/snark.rs @@ -0,0 +1,56 @@ +#![allow(non_snake_case)] +extern crate flate2; +extern crate libspartan; +extern crate merlin; +extern crate rand; + +use flate2::{write::ZlibEncoder, Compression}; +use libspartan::r1csinstance::R1CSInstance; +use libspartan::spartan::{SNARKGens, SNARK}; +use libspartan::timer::Timer; +use merlin::Transcript; + +pub fn main() { + // the list of number of variables (and constraints) in an R1CS instance + let inst_sizes = vec![12, 16, 20]; + + println!("Profiler:: SNARK"); + for &s in inst_sizes.iter() { + let num_vars = (2 as usize).pow(s as u32); + let num_cons = num_vars; + let num_inputs = 10; + let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); + + Timer::print(&format!("number_of_constraints {}", num_cons)); + + // produce public generators + let gens = SNARKGens::new(&inst.size()); + + // create a commitment to R1CSInstance + let timer_encode = Timer::new("SNARK::encode"); + let (comm, decomm) = SNARK::encode(&inst, &gens); + timer_encode.stop(); + + // produce a proof of satisfiability + let timer_prove = Timer::new("SNARK::prove"); + let mut prover_transcript = Transcript::new(b"example"); + let proof = SNARK::prove(&inst, &decomm, vars, &input, &gens, &mut prover_transcript); + timer_prove.stop(); + + let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default()); + bincode::serialize_into(&mut encoder, &proof).unwrap(); + let proof_encoded = encoder.finish().unwrap(); + let msg_proof_len = format!("SNARK::proof_compressed_len {:?}", proof_encoded.len()); + Timer::print(&msg_proof_len); + + // verify the proof of satisfiability + let timer_verify = Timer::new("SNARK::verify"); + let mut verifier_transcript = Transcript::new(b"example"); + assert!(proof + .verify(&comm, &input, &mut verifier_transcript, &gens) + .is_ok()); + timer_verify.stop(); + + println!(); + } +} diff --git a/src/dense_mlpoly.rs b/src/dense_mlpoly.rs index f270f6b..f0994da 100644 --- a/src/dense_mlpoly.rs +++ b/src/dense_mlpoly.rs @@ -115,41 +115,6 @@ impl EqPolynomial { } } -pub struct ConstPolynomial { - num_vars: usize, - c: Scalar, -} - -impl ConstPolynomial { - pub fn new(num_vars: usize, c: Scalar) -> Self { - ConstPolynomial { num_vars, c } - } - - pub fn evaluate(&self, rx: &Vec) -> Scalar { - assert_eq!(self.num_vars, rx.len()); - self.c - } - - pub fn get_num_vars(&self) -> usize { - self.num_vars - } - - /// produces a binding commitment - pub fn commit(&self, gens: &PolyCommitmentGens) -> PolyCommitment { - let ell = self.get_num_vars(); - - let (left_num_vars, right_num_vars) = EqPolynomial::compute_factored_lens(ell); - let L_size = left_num_vars.pow2(); - let R_size = right_num_vars.pow2(); - assert_eq!(L_size * R_size, ell.pow2()); - - let vec = vec![self.c; R_size]; - - let c = vec.commit(&Scalar::zero(), &gens.gens.gens_n).compress(); - PolyCommitment { C: vec![c; L_size] } - } -} - pub struct IdentityPolynomial { size_point: usize, } @@ -456,48 +421,6 @@ impl PolyEvalProof { .verify(R.len(), &gens.gens, transcript, &R, &C_LZ, C_Zr) } - pub fn verify_batched( - &self, - gens: &PolyCommitmentGens, - transcript: &mut Transcript, - r: &Vec, // point at which the polynomial is evaluated - C_Zr: &CompressedGroup, // commitment to \widetilde{Z}(r) - comm: &[&PolyCommitment], - coeff: &[&Scalar], - ) -> Result<(), ProofVerifyError> { - transcript.append_protocol_name(PolyEvalProof::protocol_name()); - - // compute L and R - let eq = EqPolynomial::new(r.to_vec()); - let (L, R) = eq.compute_factored_evals(); - - // compute a weighted sum of commitments and L - let C_decompressed: Vec> = (0..comm.len()) - .map(|i| { - comm[i] - .C - .iter() - .map(|pt| pt.decompress().unwrap()) - .collect() - }) - .collect(); - - let C_LZ: Vec = (0..comm.len()) - .map(|i| GroupElement::vartime_multiscalar_mul(&L, &C_decompressed[i])) - .collect(); - - let C_LZ_combined: GroupElement = (0..C_LZ.len()).map(|i| C_LZ[i] * coeff[i]).sum(); - - self.proof.verify( - R.len(), - &gens.gens, - transcript, - &R, - &C_LZ_combined.compress(), - C_Zr, - ) - } - pub fn verify_plain( &self, gens: &PolyCommitmentGens, @@ -511,23 +434,6 @@ impl PolyEvalProof { self.verify(gens, transcript, r, &C_Zr, comm) } - - pub fn verify_plain_batched( - &self, - gens: &PolyCommitmentGens, - transcript: &mut Transcript, - r: &Vec, // point at which the polynomial is evaluated - Zr: &Scalar, // evaluation \widetilde{Z}(r) - comm: &[&PolyCommitment], - coeff: &[&Scalar], - ) -> Result<(), ProofVerifyError> { - // compute a commitment to Zr with a blind of zero - let C_Zr = Zr.commit(&Scalar::zero(), &gens.gens.gens_1).compress(); - - assert_eq!(comm.len(), coeff.len()); - - self.verify_batched(gens, transcript, r, &C_Zr, comm, coeff) - } } #[cfg(test)] diff --git a/src/lib.rs b/src/lib.rs index 1908028..510d016 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,20 +11,20 @@ extern crate rayon; extern crate sha3; extern crate test; -pub mod commitments; -pub mod dense_mlpoly; +mod commitments; +mod dense_mlpoly; mod errors; mod group; -pub mod math; -pub mod nizk; +mod math; +mod nizk; mod product_tree; pub mod r1csinstance; -pub mod r1csproof; -pub mod random; -pub mod scalar; -pub mod sparse_mlpoly; +mod r1csproof; +mod random; +mod scalar; +mod sparse_mlpoly; pub mod spartan; -pub mod sumcheck; +mod sumcheck; pub mod timer; -pub mod transcript; +mod transcript; mod unipoly; diff --git a/src/profiler.rs b/src/profiler.rs deleted file mode 100644 index 92999ec..0000000 --- a/src/profiler.rs +++ /dev/null @@ -1,96 +0,0 @@ -#![allow(non_snake_case)] -extern crate flate2; -extern crate libspartan; -extern crate merlin; -extern crate rand; - -use flate2::{write::ZlibEncoder, Compression}; -use libspartan::math::Math; -use libspartan::r1csinstance::{R1CSCommitmentGens, R1CSInstance}; -use libspartan::r1csproof::R1CSGens; -use libspartan::spartan::{NIZKGens, SNARKGens, NIZK, SNARK}; -use libspartan::timer::Timer; -use merlin::Transcript; - -pub fn main() { - // the list of number of variables (and constraints) in an R1CS instance - let inst_sizes = vec![12, 16, 20]; - - println!("Profiler:: SNARK"); - for &s in inst_sizes.iter() { - let num_vars = (s as usize).pow2(); - let num_cons = num_vars; - let num_inputs = 10; - let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - Timer::print(&format!("number_of_constraints {}", num_cons)); - - let r1cs_size = inst.size(); - let gens_r1cs_eval = R1CSCommitmentGens::new(&r1cs_size, b"gens_r1cs_eval"); - - // create a commitment to R1CSInstance - let timer_encode = Timer::new("SNARK::encode"); - let (comm, decomm) = SNARK::encode(&inst, &gens_r1cs_eval); - timer_encode.stop(); - - let gens_r1cs_sat = R1CSGens::new(num_cons, num_vars, b"gens_r1cs_sat"); - let gens = SNARKGens::new(gens_r1cs_sat, gens_r1cs_eval); - - // produce a proof of satisfiability - let timer_prove = Timer::new("SNARK::prove"); - let mut prover_transcript = Transcript::new(b"example"); - let proof = SNARK::prove(&inst, &decomm, vars, &input, &gens, &mut prover_transcript); - timer_prove.stop(); - - let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default()); - bincode::serialize_into(&mut encoder, &proof).unwrap(); - let proof_encoded = encoder.finish().unwrap(); - let msg_proof_len = format!("SNARK::proof_compressed_len {:?}", proof_encoded.len()); - Timer::print(&msg_proof_len); - - // verify the proof of satisfiability - let timer_verify = Timer::new("SNARK::verify"); - let mut verifier_transcript = Transcript::new(b"example"); - assert!(proof - .verify(&comm, &input, &mut verifier_transcript, &gens) - .is_ok()); - timer_verify.stop(); - - println!(); - } - - println!("Profiler:: NIZK"); - for &s in inst_sizes.iter() { - let num_vars = (s as usize).pow2(); - let num_cons = num_vars; - let num_inputs = 10; - let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - Timer::print(&format!("number_of_constraints {}", num_cons)); - - let gens_r1cs_sat = R1CSGens::new(num_cons, num_vars, b"gens_r1cs_sat"); - let gens = NIZKGens::new(gens_r1cs_sat); - - // produce a proof of satisfiability - let timer_prove = Timer::new("NIZK::prove"); - let mut prover_transcript = Transcript::new(b"example"); - let proof = NIZK::prove(&inst, vars, &input, &gens, &mut prover_transcript); - timer_prove.stop(); - - let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default()); - bincode::serialize_into(&mut encoder, &proof).unwrap(); - let proof_encoded = encoder.finish().unwrap(); - let msg_proof_len = format!("NIZK::proof_compressed_len {:?}", proof_encoded.len()); - Timer::print(&msg_proof_len); - - // verify the proof of satisfiability - let timer_verify = Timer::new("NIZK::verify"); - let mut verifier_transcript = Transcript::new(b"example"); - assert!(proof - .verify(&inst, &input, &mut verifier_transcript, &gens) - .is_ok()); - timer_verify.stop(); - - println!(); - } -} diff --git a/src/r1csinstance.rs b/src/r1csinstance.rs index 663bde5..3a35a6a 100644 --- a/src/r1csinstance.rs +++ b/src/r1csinstance.rs @@ -25,11 +25,28 @@ pub struct R1CSInstance { } pub struct R1CSInstanceSize { + num_cons: usize, + num_vars: usize, + num_inputs: usize, size_A: SparseMatPolynomialSize, size_B: SparseMatPolynomialSize, size_C: SparseMatPolynomialSize, } +impl R1CSInstanceSize { + pub fn get_num_cons(&self) -> usize { + self.num_cons + } + + pub fn get_num_vars(&self) -> usize { + self.num_vars + } + + pub fn get_num_inputs(&self) -> usize { + self.num_inputs + } +} + pub struct R1CSCommitmentGens { gens: SparseMatPolyCommitmentGens, } @@ -124,6 +141,9 @@ impl R1CSInstance { pub fn size(&self) -> R1CSInstanceSize { R1CSInstanceSize { + num_cons: self.num_cons, + num_vars: self.num_vars, + num_inputs: self.num_inputs, size_A: self.A.size(), size_B: self.B.size(), size_C: self.C.size(), diff --git a/src/spartan.rs b/src/spartan.rs index ec996a6..f992f5a 100644 --- a/src/spartan.rs +++ b/src/spartan.rs @@ -2,7 +2,7 @@ use super::dense_mlpoly::EqPolynomial; use super::errors::ProofVerifyError; use super::r1csinstance::{ R1CSCommitment, R1CSCommitmentGens, R1CSDecommitment, R1CSEvalProof, R1CSInstance, - R1CSInstanceEvals, + R1CSInstanceEvals, R1CSInstanceSize, }; use super::r1csproof::{R1CSGens, R1CSProof}; use super::random::RandomTape; @@ -18,7 +18,9 @@ pub struct SNARKGens { } impl SNARKGens { - pub fn new(gens_r1cs_sat: R1CSGens, gens_r1cs_eval: R1CSCommitmentGens) -> Self { + pub fn new(size: &R1CSInstanceSize) -> Self { + let gens_r1cs_sat = R1CSGens::new(size.get_num_cons(), size.get_num_vars(), b"gens_r1cs_sat"); + let gens_r1cs_eval = R1CSCommitmentGens::new(size, b"gens_r1cs_eval"); SNARKGens { gens_r1cs_sat, gens_r1cs_eval, @@ -39,11 +41,8 @@ impl SNARK { } /// A public computation to create a commitment to an R1CS instance - pub fn encode( - inst: &R1CSInstance, - gens: &R1CSCommitmentGens, - ) -> (R1CSCommitment, R1CSDecommitment) { - inst.commit(gens) + pub fn encode(inst: &R1CSInstance, gens: &SNARKGens) -> (R1CSCommitment, R1CSDecommitment) { + inst.commit(&gens.gens_r1cs_eval) } /// A method to produce a proof of the satisfiability of an R1CS instance @@ -158,7 +157,8 @@ pub struct NIZKGens { } impl NIZKGens { - pub fn new(gens_r1cs_sat: R1CSGens) -> Self { + pub fn new(num_cons: usize, num_vars: usize) -> Self { + let gens_r1cs_sat = R1CSGens::new(num_cons, num_vars, b"gens_r1cs_sat"); NIZKGens { gens_r1cs_sat } } } @@ -261,19 +261,19 @@ mod tests { let num_cons = num_vars; let num_inputs = 10; let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - let r1cs_size = inst.size(); - let gens_r1cs_eval = R1CSCommitmentGens::new(&r1cs_size, b"gens_r1cs_eval"); - // create a commitment to R1CSInstance - let (comm, decomm) = SNARK::encode(&inst, &gens_r1cs_eval); + // produce public generators + let gens = SNARKGens::new(&r1cs_size); - let gens_r1cs_sat = R1CSGens::new(num_cons, num_vars, b"gens_r1cs_sat"); - let gens = SNARKGens::new(gens_r1cs_sat, gens_r1cs_eval); + // create a commitment to R1CSInstance + let (comm, decomm) = SNARK::encode(&inst, &gens); + // produce a proof let mut prover_transcript = Transcript::new(b"example"); let proof = SNARK::prove(&inst, &decomm, vars, &input, &gens, &mut prover_transcript); + // verify the proof let mut verifier_transcript = Transcript::new(b"example"); assert!(proof .verify(&comm, &input, &mut verifier_transcript, &gens) diff --git a/src/sumcheck.rs b/src/sumcheck.rs index 1fbc19b..7f5cc1b 100644 --- a/src/sumcheck.rs +++ b/src/sumcheck.rs @@ -176,59 +176,6 @@ impl ZKSumcheckInstanceProof { } impl SumcheckInstanceProof { - pub fn prove_quad( - claim: &Scalar, - num_rounds: usize, - poly_A: &mut DensePolynomial, - poly_B: &mut DensePolynomial, - comb_func: F, - transcript: &mut Transcript, - ) -> (Self, Vec, Vec) - where - F: Fn(&Scalar, &Scalar) -> Scalar, - { - let mut e = *claim; - let mut r: Vec = Vec::new(); - let mut quad_polys: Vec = Vec::new(); - for _j in 0..num_rounds { - let mut eval_point_0 = Scalar::zero(); - let mut eval_point_2 = Scalar::zero(); - - let len = poly_A.len() / 2; - for i in 0..len { - // eval 0: bound_func is A(low) - eval_point_0 = &eval_point_0 + comb_func(&poly_A[i], &poly_B[i]); - - // eval 2: bound_func is -A(low) + 2*A(high) - let poly_A_bound_point = &poly_A[len + i] + &poly_A[len + i] - &poly_A[i]; - let poly_B_bound_point = &poly_B[len + i] + &poly_B[len + i] - &poly_B[i]; - eval_point_2 = &eval_point_2 + comb_func(&poly_A_bound_point, &poly_B_bound_point); - } - - let evals = vec![eval_point_0, e - eval_point_0, eval_point_2]; - let poly = UniPoly::from_evals(&evals); - - // append the prover's message to the transcript - poly.append_to_transcript(b"poly", transcript); - - //derive the verifier's challenge for the next round - let r_j = transcript.challenge_scalar(b"challenge_nextround"); - r.push(r_j); - // bound all tables to the verifier's challenege - poly_A.bound_poly_var_top(&r_j); - poly_B.bound_poly_var_top(&r_j); - - e = poly.evaluate(&r_j); - quad_polys.push(poly.compress()); - } - - ( - SumcheckInstanceProof::new(quad_polys), - r, - vec![poly_A[0], poly_B[0]], - ) - } - pub fn prove_cubic( claim: &Scalar, num_rounds: usize, @@ -302,84 +249,6 @@ impl SumcheckInstanceProof { ) } - pub fn prove_cubic_with_additive_term( - claim: &Scalar, - num_rounds: usize, - poly_A: &mut DensePolynomial, - poly_B: &mut DensePolynomial, - poly_C: &mut DensePolynomial, - poly_D: &mut DensePolynomial, - comb_func: F, - transcript: &mut Transcript, - ) -> (Self, Vec, Vec) - where - F: Fn(&Scalar, &Scalar, &Scalar, &Scalar) -> Scalar, - { - let mut e = *claim; - let mut r: Vec = Vec::new(); - let mut cubic_polys: Vec = Vec::new(); - for _j in 0..num_rounds { - let mut eval_point_0 = Scalar::zero(); - let mut eval_point_2 = Scalar::zero(); - let mut eval_point_3 = Scalar::zero(); - - let len = poly_A.len() / 2; - for i in 0..len { - // eval 0: bound_func is A(low) - eval_point_0 = &eval_point_0 + comb_func(&poly_A[i], &poly_B[i], &poly_C[i], &poly_D[i]); - - // eval 2: bound_func is -A(low) + 2*A(high) - let poly_A_bound_point = &poly_A[len + i] + &poly_A[len + i] - &poly_A[i]; - let poly_B_bound_point = &poly_B[len + i] + &poly_B[len + i] - &poly_B[i]; - let poly_C_bound_point = &poly_C[len + i] + &poly_C[len + i] - &poly_C[i]; - let poly_D_bound_point = &poly_D[len + i] + &poly_D[len + i] - &poly_D[i]; - eval_point_2 = &eval_point_2 - + comb_func( - &poly_A_bound_point, - &poly_B_bound_point, - &poly_C_bound_point, - &poly_D_bound_point, - ); - - // eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2) - let poly_A_bound_point = &poly_A_bound_point + &poly_A[len + i] - &poly_A[i]; - let poly_B_bound_point = &poly_B_bound_point + &poly_B[len + i] - &poly_B[i]; - let poly_C_bound_point = &poly_C_bound_point + &poly_C[len + i] - &poly_C[i]; - let poly_D_bound_point = &poly_D_bound_point + &poly_D[len + i] - &poly_D[i]; - eval_point_3 = &eval_point_3 - + comb_func( - &poly_A_bound_point, - &poly_B_bound_point, - &poly_C_bound_point, - &poly_D_bound_point, - ); - } - - let evals = vec![eval_point_0, e - eval_point_0, eval_point_2, eval_point_3]; - let poly = UniPoly::from_evals(&evals); - - // append the prover's message to the transcript - poly.append_to_transcript(b"poly", transcript); - - //derive the verifier's challenge for the next round - let r_j = transcript.challenge_scalar(b"challenge_nextround"); - r.push(r_j); - // bound all tables to the verifier's challenege - poly_A.bound_poly_var_top(&r_j); - poly_B.bound_poly_var_top(&r_j); - poly_C.bound_poly_var_top(&r_j); - poly_D.bound_poly_var_top(&r_j); - e = poly.evaluate(&r_j); - cubic_polys.push(poly.compress()); - } - - ( - SumcheckInstanceProof::new(cubic_polys), - r, - vec![poly_A[0], poly_B[0], poly_C[0], poly_D[0]], - ) - } - pub fn prove_cubic_batched( claim: &Scalar, num_rounds: usize,