Browse Source

implement spartan verifier as a circuit and verify it with groth16

master
Mara Mihali 2 years ago
parent
commit
c76f136006
26 changed files with 1151 additions and 535 deletions
  1. +2
    -0
      .gitignore
  2. +17
    -2
      Cargo.toml
  3. +2
    -2
      README.md
  4. +94
    -47
      benches/nizk.rs
  5. +68
    -0
      benches/r1cs.rs
  6. +2
    -6
      benches/snark.rs
  7. +2
    -8
      examples/cubic.rs
  8. +4
    -5
      profiler/nizk.rs
  9. +6
    -10
      src/commitments.rs
  10. +440
    -0
      src/constraints.rs
  11. +1
    -0
      src/dense_mlpoly.rs
  12. +1
    -1
      src/errors.rs
  13. +1
    -2
      src/group.rs
  14. +90
    -59
      src/lib.rs
  15. +1
    -4
      src/nizk/bullet.rs
  16. +3
    -10
      src/nizk/mod.rs
  17. +142
    -225
      src/parameters.rs
  18. +75
    -0
      src/poseidon_transcript.rs
  19. +0
    -1
      src/product_tree.rs
  20. +11
    -2
      src/r1csinstance.rs
  21. +134
    -98
      src/r1csproof.rs
  22. +2
    -2
      src/random.rs
  23. +19
    -14
      src/sparse_mlpoly.rs
  24. +24
    -30
      src/sumcheck.rs
  25. +3
    -3
      src/transcript.rs
  26. +7
    -4
      src/unipoly.rs

+ 2
- 0
.gitignore

@ -10,3 +10,5 @@ Cargo.lock
**/*.rs.bk **/*.rs.bk
*.txt *.txt
*.csv
*.ipynb

+ 17
- 2
Cargo.toml

@ -38,13 +38,21 @@ ark-r1cs-std = { version = "^0.3.0", default-features = false }
ark-nonnative-field = { version = "0.3.0", default-features = false } ark-nonnative-field = { version = "0.3.0", default-features = false }
ark-relations = { version = "^0.3.0", default-features = false } ark-relations = { version = "^0.3.0", default-features = false }
ark-snark = { version = "^0.3.0", default-features = false } ark-snark = { version = "^0.3.0", default-features = false }
ark-groth16 = { version = "^0.3.0", features = ["r1cs"] }
ark-bw6-761 = { version = "^0.3.0" }
lazy_static = "1.4.0" lazy_static = "1.4.0"
rand = { version = "0.8", features = [ "std", "std_rng" ] } rand = { version = "0.8", features = [ "std", "std_rng" ] }
num-bigint = { version = "0.4" } num-bigint = { version = "0.4" }
tracing = { version = "0.1", default-features = false, features = [ "attributes" ] }
tracing-subscriber = { version = "0.2" }
[dev-dependencies] [dev-dependencies]
criterion = "0.3.1"
serde = { version = "1.0", features = ["derive"] }
csv = "1.1.5"
criterion = "0.3.6"
[lib] [lib]
name = "libspartan" name = "libspartan"
@ -66,10 +74,17 @@ harness = false
name = "nizk" name = "nizk"
harness = false harness = false
[[bench]]
name = "r1cs"
harness = false
debug = true
[features] [features]
default = ["curve25519-dalek/simd_backend"]
multicore = ["rayon"] multicore = ["rayon"]
profile = [] profile = []
default = ["parallel", "std"]
parallel = [ "std", "ark-ff/parallel", "ark-std/parallel", "ark-ec/parallel"]
std = ["ark-ff/std", "ark-ec/std", "ark-std/std", "ark-relations/std", "ark-serialize/std"]
[patch.crates-io] [patch.crates-io]
ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std/", rev = "a2a5ac491ae005ba2afd03fd21b7d3160d794a83"} ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std/", rev = "a2a5ac491ae005ba2afd03fd21b7d3160d794a83"}

+ 2
- 2
README.md

@ -100,12 +100,12 @@ Here is another example to use the NIZK variant of the Spartan proof system:
// produce a proof of satisfiability // produce a proof of satisfiability
let mut prover_transcript = PoseidonTranscript::new(&params); let mut prover_transcript = PoseidonTranscript::new(&params);
let proof = NIZK::prove(&inst, vars, &inputs, &gens, &mut prover_transcript);
let proof = NIZK::prove(&inst, vars, &inputs, &mut prover_transcript);
// verify the proof of satisfiability // verify the proof of satisfiability
let mut verifier_transcript = PoseidonTranscript::new(&params); let mut verifier_transcript = PoseidonTranscript::new(&params);
assert!(proof assert!(proof
.verify(&inst, &inputs, &mut verifier_transcript, &gens)
.verify(&inst, &inputs, &mut verifier_transcript)
.is_ok()); .is_ok());
println!("proof verification successful!"); println!("proof verification successful!");
# } # }

+ 94
- 47
benches/nizk.rs

@ -1,4 +1,3 @@
#![allow(clippy::assertions_on_result_states)]
extern crate byteorder; extern crate byteorder;
extern crate core; extern crate core;
extern crate criterion; extern crate criterion;
@ -7,89 +6,137 @@ extern crate libspartan;
extern crate merlin; extern crate merlin;
extern crate sha3; extern crate sha3;
use std::time::{Duration, SystemTime};
use libspartan::{ use libspartan::{
parameters::poseidon_params, poseidon_transcript::PoseidonTranscript, Instance, NIZKGens, NIZK,
parameters::POSEIDON_PARAMETERS_FR_377, poseidon_transcript::PoseidonTranscript, Instance, NIZK,
}; };
use merlin::Transcript;
use criterion::*; use criterion::*;
fn nizk_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("NIZK_prove_benchmark");
group.plot_config(plot_config);
for &s in [24, 28, 30].iter() {
let mut group = c.benchmark_group("R1CS_prove_benchmark");
let num_vars = (2_usize).pow(s as u32); let num_vars = (2_usize).pow(s as u32);
let num_cons = num_vars; let num_cons = num_vars;
let num_inputs = 10; let num_inputs = 10;
let params = poseidon_params();
let start = SystemTime::now();
let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
let end = SystemTime::now();
let duration = end.duration_since(start).unwrap();
println!(
"Generating r1cs instance with {} constraints took {} ms",
num_cons,
duration.as_millis()
);
let gens = NIZKGens::new(num_cons, num_vars, num_inputs);
let name = format!("NIZK_prove_{}", num_vars);
group.bench_function(&name, move |b| {
b.iter(|| {
let mut prover_transcript = PoseidonTranscript::new(&params);
NIZK::prove(
black_box(&inst),
black_box(vars.clone()),
black_box(&inputs),
black_box(&gens),
black_box(&mut prover_transcript),
);
let name = format!("R1CS_prove_{}", num_vars);
group
.measurement_time(Duration::from_secs(60))
.bench_function(&name, move |b| {
b.iter(|| {
let mut prover_transcript = PoseidonTranscript::new(&POSEIDON_PARAMETERS_FR_377);
NIZK::prove(
black_box(&inst),
black_box(vars.clone()),
black_box(&inputs),
black_box(&mut prover_transcript),
);
});
}); });
});
group.finish(); group.finish();
} }
} }
fn nizk_verify_benchmark(c: &mut Criterion) { 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);
for &s in [4, 6, 8, 10, 12, 16, 20, 24, 28, 30].iter() {
let mut group = c.benchmark_group("R1CS_verify_benchmark");
let num_vars = (2_usize).pow(s as u32); let num_vars = (2_usize).pow(s as u32);
let num_cons = num_vars; let num_cons = num_vars;
// these are the public io
let num_inputs = 10; let num_inputs = 10;
let start = SystemTime::now();
let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
let end = SystemTime::now();
let duration = end.duration_since(start).unwrap();
println!(
"Generating r1cs instance with {} constraints took {} ms",
num_cons,
duration.as_millis()
);
// produce a proof of satisfiability
let mut prover_transcript = PoseidonTranscript::new(&POSEIDON_PARAMETERS_FR_377);
let proof = NIZK::prove(&inst, vars, &inputs, &mut prover_transcript);
let gens = NIZKGens::new(num_cons, num_vars, num_inputs);
let params = poseidon_params();
let name = format!("R1CS_verify_{}", num_cons);
group
.measurement_time(Duration::from_secs(60))
.bench_function(&name, move |b| {
b.iter(|| {
let mut verifier_transcript = PoseidonTranscript::new(&POSEIDON_PARAMETERS_FR_377);
assert!(proof
.verify(
black_box(&inst),
black_box(&inputs),
black_box(&mut verifier_transcript),
)
.is_ok());
});
});
group.finish();
}
}
fn nizk_verify_groth16_benchmark(c: &mut Criterion) {
for &s in [4, 6, 8, 10, 12, 16, 20, 24, 28, 30].iter() {
let mut group = c.benchmark_group("R1CS_verify_groth16_benchmark");
let num_vars = (2_usize).pow(s as u32);
let num_cons = num_vars;
// these are the public io
let num_inputs = 10;
let start = SystemTime::now();
let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
let end = SystemTime::now();
let duration = end.duration_since(start).unwrap();
println!(
"Generating r1cs instance with {} constraints took {} ms",
num_cons,
duration.as_millis()
);
// produce a proof of satisfiability // produce a proof of satisfiability
let mut prover_transcript = PoseidonTranscript::new(&params);
let proof = NIZK::prove(&inst, vars, &inputs, &gens, &mut prover_transcript);
let mut prover_transcript = PoseidonTranscript::new(&POSEIDON_PARAMETERS_FR_377);
let proof = NIZK::prove(&inst, vars, &inputs, &mut prover_transcript);
let name = format!("NIZK_verify_{}", num_cons);
group.bench_function(&name, move |b| {
b.iter(|| {
let mut verifier_transcript = PoseidonTranscript::new(&params);
assert!(proof
.verify(
black_box(&inst),
black_box(&inputs),
black_box(&mut verifier_transcript),
black_box(&gens)
)
.is_ok());
let name = format!("R1CS_verify_groth16_{}", num_cons);
group
.measurement_time(Duration::from_secs(60))
.bench_function(&name, move |b| {
b.iter(|| {
let mut verifier_transcript = PoseidonTranscript::new(&POSEIDON_PARAMETERS_FR_377);
assert!(proof
.verify_groth16(
black_box(&inst),
black_box(&inputs),
black_box(&mut verifier_transcript),
)
.is_ok());
});
}); });
});
group.finish(); group.finish();
} }
} }
fn set_duration() -> Criterion { fn set_duration() -> Criterion {
Criterion::default().sample_size(10)
Criterion::default().sample_size(2)
} }
criterion_group! { criterion_group! {
name = benches_nizk; name = benches_nizk;
config = set_duration(); config = set_duration();
targets = nizk_prove_benchmark, nizk_verify_benchmark
targets = nizk_prove_benchmark, nizk_verify_benchmark, nizk_verify_groth16_benchmark
} }
criterion_main!(benches_nizk); criterion_main!(benches_nizk);

+ 68
- 0
benches/r1cs.rs

@ -0,0 +1,68 @@
use std::time::Instant;
use libspartan::{
parameters::POSEIDON_PARAMETERS_FR_377, poseidon_transcript::PoseidonTranscript, Instance, NIZK,
};
use serde::Serialize;
#[derive(Default, Clone, Serialize)]
struct BenchmarkResults {
power: usize,
input_constraints: usize,
spartan_verifier_circuit_constraints: usize,
r1cs_instance_generation_time: u128,
spartan_proving_time: u128,
groth16_setup_time: u128,
groth16_proving_time: u128,
groth16_verification_time: u128,
testudo_proving_time: u128,
}
fn main() {
let mut writer = csv::Writer::from_path("testudo.csv").expect("unable to open csv writer");
for &s in [
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
]
.iter()
{
println!("Running for {} inputs", s);
let mut br = BenchmarkResults::default();
let num_vars = (2_usize).pow(s as u32);
let num_cons = num_vars;
br.power = s;
br.input_constraints = num_cons;
let num_inputs = 10;
let start = Instant::now();
let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
let duration = start.elapsed().as_millis();
br.r1cs_instance_generation_time = duration;
let mut prover_transcript = PoseidonTranscript::new(&POSEIDON_PARAMETERS_FR_377);
let start = Instant::now();
let proof = NIZK::prove(&inst, vars, &inputs, &mut prover_transcript);
let duration = start.elapsed().as_millis();
println!("{:?}", duration);
br.spartan_proving_time = duration;
let mut verifier_transcript = PoseidonTranscript::new(&POSEIDON_PARAMETERS_FR_377);
let res = proof.verify(&inst, &inputs, &mut verifier_transcript);
assert!(res.is_ok());
br.spartan_verifier_circuit_constraints = res.unwrap();
let mut verifier_transcript = PoseidonTranscript::new(&POSEIDON_PARAMETERS_FR_377);
let res = proof.verify_groth16(&inst, &inputs, &mut verifier_transcript);
assert!(res.is_ok());
let (ds, dp, dv) = res.unwrap();
br.groth16_setup_time = ds;
br.groth16_proving_time = dp;
br.groth16_verification_time = dv;
br.testudo_proving_time = br.spartan_proving_time + br.groth16_proving_time;
writer
.serialize(br)
.expect("unable to write results to csv");
writer.flush().expect("wasn't able to flush");
}
}

+ 2
- 6
benches/snark.rs

@ -1,13 +1,9 @@
#![allow(clippy::assertions_on_result_states)]
extern crate libspartan; extern crate libspartan;
extern crate merlin; extern crate merlin;
use libspartan::{ use libspartan::{
parameters::poseidon_params,
poseidon_transcript::{self, PoseidonTranscript},
Instance, SNARKGens, SNARK,
parameters::poseidon_params, poseidon_transcript::PoseidonTranscript, Instance, SNARKGens, SNARK,
}; };
use merlin::Transcript;
use criterion::*; use criterion::*;
@ -133,7 +129,7 @@ fn set_duration() -> Criterion {
criterion_group! { criterion_group! {
name = benches_snark; name = benches_snark;
config = set_duration(); config = set_duration();
targets = snark_encode_benchmark, snark_prove_benchmark, snark_verify_benchmark
targets = snark_verify_benchmark
} }
criterion_main!(benches_snark); criterion_main!(benches_snark);

+ 2
- 8
examples/cubic.rs

@ -11,16 +11,10 @@
use ark_bls12_377::Fr as Scalar; use ark_bls12_377::Fr as Scalar;
use ark_ff::{BigInteger, PrimeField}; use ark_ff::{BigInteger, PrimeField};
use ark_std::{One, UniformRand, Zero}; use ark_std::{One, UniformRand, Zero};
<<<<<<< HEAD
use libspartan::{InputsAssignment, Instance, SNARKGens, VarsAssignment, SNARK};
=======
use libspartan::{ use libspartan::{
parameters::poseidon_params,
poseidon_transcript::{self, PoseidonTranscript},
InputsAssignment, Instance, SNARKGens, VarsAssignment, SNARK,
parameters::poseidon_params, poseidon_transcript::PoseidonTranscript, InputsAssignment, Instance,
SNARKGens, VarsAssignment, SNARK,
}; };
>>>>>>> implement alternative transcript with poseidon backend
use merlin::Transcript;
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn produce_r1cs() -> ( fn produce_r1cs() -> (

+ 4
- 5
profiler/nizk.rs

@ -9,8 +9,7 @@ extern crate rand;
use ark_serialize::*; use ark_serialize::*;
use libspartan::parameters::poseidon_params; use libspartan::parameters::poseidon_params;
use libspartan::poseidon_transcript::PoseidonTranscript; use libspartan::poseidon_transcript::PoseidonTranscript;
use libspartan::{Instance, NIZKGens, NIZK};
use merlin::Transcript;
use libspartan::{Instance, NIZK};
fn print(msg: &str) { fn print(msg: &str) {
let star = "* "; let star = "* ";
@ -31,12 +30,12 @@ pub fn main() {
let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
// produce public generators // produce public generators
let gens = NIZKGens::new(num_cons, num_vars, num_inputs);
// let gens = NIZKGens::new(num_cons, num_vars, num_inputs);
let params = poseidon_params(); let params = poseidon_params();
// produce a proof of satisfiability // produce a proof of satisfiability
let mut prover_transcript = PoseidonTranscript::new(&params); let mut prover_transcript = PoseidonTranscript::new(&params);
let proof = NIZK::prove(&inst, vars, &inputs, &gens, &mut prover_transcript);
let proof = NIZK::prove(&inst, vars, &inputs, &mut prover_transcript);
let mut proof_encoded = Vec::new(); let mut proof_encoded = Vec::new();
proof.serialize(&mut proof_encoded).unwrap(); proof.serialize(&mut proof_encoded).unwrap();
@ -46,7 +45,7 @@ pub fn main() {
// verify the proof of satisfiability // verify the proof of satisfiability
let mut verifier_transcript = PoseidonTranscript::new(&params); let mut verifier_transcript = PoseidonTranscript::new(&params);
assert!(proof assert!(proof
.verify(&inst, &inputs, &mut verifier_transcript, &gens)
.verify(&inst, &inputs, &mut verifier_transcript)
.is_ok()); .is_ok());
println!(); println!();

+ 6
- 10
src/commitments.rs

@ -1,18 +1,14 @@
use super::group::{Fq, GroupElement, GroupElementAffine, VartimeMultiscalarMul, GROUP_BASEPOINT};
use super::group::{GroupElement, GroupElementAffine, VartimeMultiscalarMul, GROUP_BASEPOINT};
use super::scalar::Scalar; use super::scalar::Scalar;
use crate::group::{CompressGroupElement, DecompressGroupElement};
use crate::group::CompressGroupElement;
use crate::parameters::*; use crate::parameters::*;
use ark_ec::{AffineCurve, ProjectiveCurve}; use ark_ec::{AffineCurve, ProjectiveCurve};
use ark_ff::PrimeField; use ark_ff::PrimeField;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_sponge::poseidon::{PoseidonParameters, PoseidonSponge};
use ark_sponge::poseidon::PoseidonSponge;
use ark_sponge::CryptographicSponge; use ark_sponge::CryptographicSponge;
use digest::{ExtendableOutput, Input};
use sha3::Shake256;
use std::io::Read;
use std::str::FromStr;
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct MultiCommitGens { pub struct MultiCommitGens {
pub n: usize, pub n: usize,
pub G: Vec<GroupElement>, pub G: Vec<GroupElement>,
@ -24,7 +20,7 @@ impl MultiCommitGens {
let params = poseidon_params(); let params = poseidon_params();
let mut sponge = PoseidonSponge::new(&params); let mut sponge = PoseidonSponge::new(&params);
sponge.absorb(&label); sponge.absorb(&label);
sponge.absorb(&GROUP_BASEPOINT.into_affine());
sponge.absorb(&GROUP_BASEPOINT.compress().0);
let mut gens: Vec<GroupElement> = Vec::new(); let mut gens: Vec<GroupElement> = Vec::new();
for _ in 0..n + 1 { for _ in 0..n + 1 {

+ 440
- 0
src/constraints.rs

@ -0,0 +1,440 @@
use std::{borrow::Borrow, vec};
use super::scalar::Scalar;
use crate::{
group::Fq,
math::Math,
sparse_mlpoly::{SparsePolyEntry, SparsePolynomial},
unipoly::UniPoly,
};
use ark_bls12_377::{constraints::PairingVar as IV, Bls12_377 as I, Fr};
use ark_crypto_primitives::{
snark::BooleanInputVar, CircuitSpecificSetupSNARK, SNARKGadget, SNARK,
};
use ark_ff::{BitIteratorLE, PrimeField, Zero};
use ark_groth16::{
constraints::{Groth16VerifierGadget, PreparedVerifyingKeyVar, ProofVar},
Groth16, PreparedVerifyingKey, Proof as GrothProof,
};
use ark_r1cs_std::{
alloc::{AllocVar, AllocationMode},
fields::fp::FpVar,
prelude::{Boolean, EqGadget, FieldVar},
};
use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError};
use ark_sponge::{
constraints::CryptographicSpongeVar,
poseidon::{constraints::PoseidonSpongeVar, PoseidonParameters},
};
use rand::{CryptoRng, Rng};
pub struct PoseidonTranscripVar {
pub cs: ConstraintSystemRef<Fr>,
pub sponge: PoseidonSpongeVar<Fr>,
pub params: PoseidonParameters<Fr>,
}
impl PoseidonTranscripVar {
fn new(
cs: ConstraintSystemRef<Fr>,
params: &PoseidonParameters<Fr>,
challenge: Option<Fr>,
) -> Self {
let mut sponge = PoseidonSpongeVar::new(cs.clone(), params);
if let Some(c) = challenge {
let c_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(c)).unwrap();
sponge.absorb(&c_var);
}
Self {
cs: cs,
sponge: sponge,
params: params.clone(),
}
}
fn append(&mut self, input: &FpVar<Fr>) -> Result<(), SynthesisError> {
self.sponge.absorb(&input)
}
fn append_vector(&mut self, input_vec: &Vec<FpVar<Fr>>) -> Result<(), SynthesisError> {
for input in input_vec.iter() {
self.append(input)?;
}
Ok(())
}
fn challenge(&mut self) -> Result<FpVar<Fr>, SynthesisError> {
let c_var = self.sponge.squeeze_field_elements(1).unwrap().remove(0);
Ok(c_var)
}
fn challenge_vector(&mut self, len: usize) -> Result<Vec<FpVar<Fr>>, SynthesisError> {
let c_vars = self.sponge.squeeze_field_elements(len).unwrap();
Ok(c_vars)
}
}
#[derive(Clone)]
pub struct UniPolyVar {
pub coeffs: Vec<FpVar<Fr>>,
}
impl AllocVar<UniPoly, Fr> for UniPolyVar {
fn new_variable<T: Borrow<UniPoly>>(
cs: impl Into<Namespace<Fr>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
mode: AllocationMode,
) -> Result<Self, SynthesisError> {
f().and_then(|c| {
let cs = cs.into();
let cp: &UniPoly = c.borrow();
let mut coeffs_var = Vec::new();
for coeff in cp.coeffs.iter() {
let coeff_var = FpVar::<Fr>::new_variable(cs.clone(), || Ok(coeff.clone()), mode)?;
coeffs_var.push(coeff_var);
}
Ok(Self { coeffs: coeffs_var })
})
}
}
impl UniPolyVar {
pub fn eval_at_zero(&self) -> FpVar<Fr> {
self.coeffs[0].clone()
}
pub fn eval_at_one(&self) -> FpVar<Fr> {
let mut res = self.coeffs[0].clone();
for i in 1..self.coeffs.len() {
res = &res + &self.coeffs[i];
}
res
}
// mul without reduce
pub fn evaluate(&self, r: &FpVar<Fr>) -> FpVar<Fr> {
let mut eval = self.coeffs[0].clone();
let mut power = r.clone();
for i in 1..self.coeffs.len() {
eval += &power * &self.coeffs[i];
power *= r;
}
eval
}
}
#[derive(Clone)]
pub struct SumcheckVerificationCircuit {
pub polys: Vec<UniPoly>,
}
impl SumcheckVerificationCircuit {
fn verifiy_sumcheck(
&self,
poly_vars: &Vec<UniPolyVar>,
claim_var: &FpVar<Fr>,
transcript_var: &mut PoseidonTranscripVar,
) -> Result<(FpVar<Fr>, Vec<FpVar<Fr>>), SynthesisError> {
let mut e_var = claim_var.clone();
let mut r_vars: Vec<FpVar<Fr>> = Vec::new();
for (poly_var, _poly) in poly_vars.iter().zip(self.polys.iter()) {
let res = poly_var.eval_at_one() + poly_var.eval_at_zero();
res.enforce_equal(&e_var)?;
transcript_var.append_vector(&poly_var.coeffs)?;
let r_i_var = transcript_var.challenge()?;
r_vars.push(r_i_var.clone());
e_var = poly_var.evaluate(&r_i_var.clone());
}
Ok((e_var, r_vars))
}
}
#[derive(Clone)]
pub struct SparsePolyEntryVar {
idx: usize,
val_var: FpVar<Fr>,
}
impl AllocVar<SparsePolyEntry, Fr> for SparsePolyEntryVar {
fn new_variable<T: Borrow<SparsePolyEntry>>(
cs: impl Into<Namespace<Fr>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
_mode: AllocationMode,
) -> Result<Self, SynthesisError> {
f().and_then(|s| {
let cs = cs.into();
let spe: &SparsePolyEntry = s.borrow();
let val_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(spe.val))?;
Ok(Self {
idx: spe.idx,
val_var,
})
})
}
}
#[derive(Clone)]
pub struct SparsePolynomialVar {
num_vars: usize,
Z_var: Vec<SparsePolyEntryVar>,
}
impl AllocVar<SparsePolynomial, Fr> for SparsePolynomialVar {
fn new_variable<T: Borrow<SparsePolynomial>>(
cs: impl Into<Namespace<Fr>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
mode: AllocationMode,
) -> Result<Self, SynthesisError> {
f().and_then(|s| {
let cs = cs.into();
let sp: &SparsePolynomial = s.borrow();
let mut Z_var = Vec::new();
for spe in sp.Z.iter() {
let spe_var = SparsePolyEntryVar::new_variable(cs.clone(), || Ok(spe), mode)?;
Z_var.push(spe_var);
}
Ok(Self {
num_vars: sp.num_vars,
Z_var,
})
})
}
}
impl SparsePolynomialVar {
fn compute_chi(a: &[bool], r_vars: &Vec<FpVar<Fr>>) -> FpVar<Fr> {
let mut chi_i_var = FpVar::<Fr>::one();
let one = FpVar::<Fr>::one();
for (i, r_var) in r_vars.iter().enumerate() {
if a[i] {
chi_i_var *= r_var;
} else {
chi_i_var *= &one - r_var;
}
}
chi_i_var
}
pub fn evaluate(&self, r_var: &Vec<FpVar<Fr>>) -> FpVar<Fr> {
let mut sum = FpVar::<Fr>::zero();
for spe_var in self.Z_var.iter() {
// potential problem
let bits = &spe_var.idx.get_bits(r_var.len());
sum += SparsePolynomialVar::compute_chi(&bits, r_var) * &spe_var.val_var;
}
sum
}
}
#[derive(Clone)]
pub struct R1CSVerificationCircuit {
pub num_vars: usize,
pub num_cons: usize,
pub input: Vec<Fr>,
pub input_as_sparse_poly: SparsePolynomial,
pub evals: (Fr, Fr, Fr),
pub params: PoseidonParameters<Fr>,
pub prev_challenge: Fr,
pub claims_phase2: (Scalar, Scalar, Scalar, Scalar),
pub eval_vars_at_ry: Fr,
pub sc_phase1: SumcheckVerificationCircuit,
pub sc_phase2: SumcheckVerificationCircuit,
}
impl R1CSVerificationCircuit {
fn new(config: &VerifierConfig) -> Self {
Self {
num_vars: config.num_vars,
num_cons: config.num_cons,
input: config.input.clone(),
input_as_sparse_poly: config.input_as_sparse_poly.clone(),
evals: config.evals,
params: config.params.clone(),
prev_challenge: config.prev_challenge,
claims_phase2: config.claims_phase2,
eval_vars_at_ry: config.eval_vars_at_ry,
sc_phase1: SumcheckVerificationCircuit {
polys: config.polys_sc1.clone(),
},
sc_phase2: SumcheckVerificationCircuit {
polys: config.polys_sc2.clone(),
},
}
}
}
impl ConstraintSynthesizer<Fr> for R1CSVerificationCircuit {
fn generate_constraints(self, cs: ConstraintSystemRef<Fr>) -> ark_relations::r1cs::Result<()> {
let mut transcript_var =
PoseidonTranscripVar::new(cs.clone(), &self.params, Some(self.prev_challenge));
let poly_sc1_vars = self
.sc_phase1
.polys
.iter()
.map(|p| UniPolyVar::new_variable(cs.clone(), || Ok(p), AllocationMode::Witness).unwrap())
.collect::<Vec<UniPolyVar>>();
let poly_sc2_vars = self
.sc_phase2
.polys
.iter()
.map(|p| UniPolyVar::new_variable(cs.clone(), || Ok(p), AllocationMode::Witness).unwrap())
.collect::<Vec<UniPolyVar>>();
let input_vars = self
.input
.iter()
.map(|i| FpVar::<Fr>::new_input(cs.clone(), || Ok(i)).unwrap())
.collect::<Vec<FpVar<Fr>>>();
transcript_var.append_vector(&input_vars)?;
let num_rounds_x = self.num_cons.log_2();
let _num_rounds_y = (2 * self.num_vars).log_2();
let tau_vars = transcript_var.challenge_vector(num_rounds_x)?;
let claim_phase1_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(Fr::zero()))?;
let (claim_post_phase1_var, rx_var) =
self
.sc_phase1
.verifiy_sumcheck(&poly_sc1_vars, &claim_phase1_var, &mut transcript_var)?;
let (Az_claim, Bz_claim, Cz_claim, prod_Az_Bz_claims) = &self.claims_phase2;
let Az_claim_var = FpVar::<Fr>::new_input(cs.clone(), || Ok(Az_claim))?;
let Bz_claim_var = FpVar::<Fr>::new_input(cs.clone(), || Ok(Bz_claim))?;
let Cz_claim_var = FpVar::<Fr>::new_input(cs.clone(), || Ok(Cz_claim))?;
let prod_Az_Bz_claim_var = FpVar::<Fr>::new_input(cs.clone(), || Ok(prod_Az_Bz_claims))?;
let one = FpVar::<Fr>::one();
let prod_vars: Vec<FpVar<Fr>> = (0..rx_var.len())
.map(|i| (&rx_var[i] * &tau_vars[i]) + (&one - &rx_var[i]) * (&one - &tau_vars[i]))
.collect();
let mut taus_bound_rx_var = FpVar::<Fr>::one();
for p_var in prod_vars.iter() {
taus_bound_rx_var *= p_var;
}
let expected_claim_post_phase1_var =
(&prod_Az_Bz_claim_var - &Cz_claim_var) * &taus_bound_rx_var;
claim_post_phase1_var.enforce_equal(&expected_claim_post_phase1_var)?;
let r_A_var = transcript_var.challenge()?;
let r_B_var = transcript_var.challenge()?;
let r_C_var = transcript_var.challenge()?;
let claim_phase2_var =
&r_A_var * &Az_claim_var + &r_B_var * &Bz_claim_var + &r_C_var * &Cz_claim_var;
let (claim_post_phase2_var, ry_var) =
self
.sc_phase2
.verifiy_sumcheck(&poly_sc2_vars, &claim_phase2_var, &mut transcript_var)?;
let input_as_sparse_poly_var = SparsePolynomialVar::new_variable(
cs.clone(),
|| Ok(&self.input_as_sparse_poly),
AllocationMode::Witness,
)?;
let poly_input_eval_var = input_as_sparse_poly_var.evaluate(&ry_var[1..].to_vec());
let eval_vars_at_ry_var = FpVar::<Fr>::new_input(cs.clone(), || Ok(&self.eval_vars_at_ry))?;
let eval_Z_at_ry_var =
(FpVar::<Fr>::one() - &ry_var[0]) * &eval_vars_at_ry_var + &ry_var[0] * &poly_input_eval_var;
let (eval_A_r, eval_B_r, eval_C_r) = self.evals;
let eval_A_r_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(eval_A_r))?;
let eval_B_r_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(eval_B_r))?;
let eval_C_r_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(eval_C_r))?;
let scalar_var = &r_A_var * &eval_A_r_var + &r_B_var * &eval_B_r_var + &r_C_var * &eval_C_r_var;
let expected_claim_post_phase2_var = eval_Z_at_ry_var * scalar_var;
claim_post_phase2_var.enforce_equal(&expected_claim_post_phase2_var)?;
Ok(())
}
}
#[derive(Clone)]
pub struct VerifierConfig {
pub num_vars: usize,
pub num_cons: usize,
pub input: Vec<Fr>,
pub input_as_sparse_poly: SparsePolynomial,
pub evals: (Fr, Fr, Fr),
pub params: PoseidonParameters<Fr>,
pub prev_challenge: Fr,
pub claims_phase2: (Fr, Fr, Fr, Fr),
pub eval_vars_at_ry: Fr,
pub polys_sc1: Vec<UniPoly>,
pub polys_sc2: Vec<UniPoly>,
}
#[derive(Clone)]
pub struct VerifierCircuit {
pub inner_circuit: R1CSVerificationCircuit,
pub inner_proof: GrothProof<I>,
pub inner_vk: PreparedVerifyingKey<I>,
pub evals_var_at_ry: Fr,
pub claims_phase2: (Fr, Fr, Fr, Fr),
pub input: Vec<Fr>,
}
impl VerifierCircuit {
pub fn new<R: Rng + CryptoRng>(
config: &VerifierConfig,
mut rng: &mut R,
) -> Result<Self, SynthesisError> {
let inner_circuit = R1CSVerificationCircuit::new(config);
let (pk, vk) = Groth16::<I>::setup(inner_circuit.clone(), &mut rng).unwrap();
let proof = Groth16::<I>::prove(&pk, inner_circuit.clone(), &mut rng)?;
let pvk = Groth16::<I>::process_vk(&vk).unwrap();
Ok(Self {
inner_circuit: inner_circuit,
inner_proof: proof,
inner_vk: pvk,
evals_var_at_ry: config.eval_vars_at_ry,
claims_phase2: config.claims_phase2,
input: config.input.clone(),
})
}
}
impl ConstraintSynthesizer<Fq> for VerifierCircuit {
fn generate_constraints(self, cs: ConstraintSystemRef<Fq>) -> ark_relations::r1cs::Result<()> {
let proof_var = ProofVar::<I, IV>::new_witness(cs.clone(), || Ok(self.inner_proof.clone()))?;
let (v_A, v_B, v_C, v_AB) = self.claims_phase2;
let mut pubs = self.input.clone();
pubs.extend(vec![v_A, v_B, v_C, v_AB, self.evals_var_at_ry]);
let bits = pubs
.iter()
.map(|c| {
let bits: Vec<bool> = BitIteratorLE::new(c.into_repr().as_ref().to_vec()).collect();
Vec::new_witness(cs.clone(), || Ok(bits))
})
.collect::<Result<Vec<_>, _>>()?;
let input_var = BooleanInputVar::<Fr, Fq>::new(bits);
let vk_var = PreparedVerifyingKeyVar::new_witness(cs.clone(), || Ok(self.inner_vk.clone()))?;
Groth16VerifierGadget::verify_with_processed_vk(&vk_var, &input_var, &proof_var)?
.enforce_equal(&Boolean::constant(true))?;
Ok(())
}
}

+ 1
- 0
src/dense_mlpoly.rs

@ -27,6 +27,7 @@ pub struct DensePolynomial {
Z: Vec<Scalar>, // evaluations of the polynomial in all the 2^num_vars Boolean inputs Z: Vec<Scalar>, // evaluations of the polynomial in all the 2^num_vars Boolean inputs
} }
#[derive(Clone)]
pub struct PolyCommitmentGens { pub struct PolyCommitmentGens {
pub gens: DotProductProofGens, pub gens: DotProductProofGens,
} }

+ 1
- 1
src/errors.rs

@ -12,7 +12,7 @@ pub enum ProofVerifyError {
impl Default for ProofVerifyError { impl Default for ProofVerifyError {
fn default() -> Self { fn default() -> Self {
ProofVerifyError::InternalError ProofVerifyError::InternalError
}
}
} }
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]

+ 1
- 2
src/group.rs

@ -2,11 +2,10 @@ use crate::errors::ProofVerifyError;
use ark_ec::msm::VariableBaseMSM; use ark_ec::msm::VariableBaseMSM;
use ark_ff::PrimeField; use ark_ff::PrimeField;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use num_bigint::BigInt;
use super::scalar::Scalar; use super::scalar::Scalar;
use ark_ec::{AffineCurve, ProjectiveCurve}; use ark_ec::{AffineCurve, ProjectiveCurve};
use ark_serialize::*; use ark_serialize::*;
use core::borrow::Borrow; use core::borrow::Borrow;

+ 90
- 59
src/lib.rs

@ -1,6 +1,5 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
#![deny(missing_docs)]
#![feature(test)] #![feature(test)]
#![allow(clippy::assertions_on_result_states)] #![allow(clippy::assertions_on_result_states)]
@ -37,17 +36,17 @@ mod timer;
mod transcript; mod transcript;
mod unipoly; mod unipoly;
/// TODO
pub mod parameters; pub mod parameters;
/// TODO
mod constraints;
pub mod poseidon_transcript; pub mod poseidon_transcript;
use ark_ff::{BigInteger, Field, PrimeField};
use ark_ff::Field;
use ark_serialize::*; use ark_serialize::*;
use ark_std::{One, UniformRand, Zero};
use ark_std::Zero;
use core::cmp::max; use core::cmp::max;
use errors::{ProofVerifyError, R1CSError}; use errors::{ProofVerifyError, R1CSError};
use merlin::Transcript;
use poseidon_transcript::{AppendToPoseidon, PoseidonTranscript}; use poseidon_transcript::{AppendToPoseidon, PoseidonTranscript};
use r1csinstance::{ use r1csinstance::{
R1CSCommitment, R1CSCommitmentGens, R1CSDecommitment, R1CSEvalProof, R1CSInstance, R1CSCommitment, R1CSCommitmentGens, R1CSDecommitment, R1CSEvalProof, R1CSInstance,
@ -55,9 +54,9 @@ use r1csinstance::{
use r1csproof::{R1CSGens, R1CSProof}; use r1csproof::{R1CSGens, R1CSProof};
use random::RandomTape; use random::RandomTape;
use scalar::Scalar; use scalar::Scalar;
use std::borrow::Borrow;
use timer::Timer; use timer::Timer;
use transcript::{AppendToTranscript, ProofTranscript};
use transcript::ProofTranscript;
/// `ComputationCommitment` holds a public preprocessed NP statement (e.g., R1CS) /// `ComputationCommitment` holds a public preprocessed NP statement (e.g., R1CS)
pub struct ComputationCommitment { pub struct ComputationCommitment {
@ -387,9 +386,9 @@ impl SNARK {
&inst.inst, &inst.inst,
padded_vars.assignment, padded_vars.assignment,
&inputs.assignment, &inputs.assignment,
&gens.gens_r1cs_sat,
// &gens.gens_r1cs_sat,
transcript, transcript,
&mut random_tape,
// &mut random_tape,
) )
}; };
@ -443,9 +442,9 @@ impl SNARK {
comm: &ComputationCommitment, comm: &ComputationCommitment,
input: &InputsAssignment, input: &InputsAssignment,
transcript: &mut PoseidonTranscript, transcript: &mut PoseidonTranscript,
gens: &SNARKGens,
_gens: &SNARKGens,
) -> Result<(), ProofVerifyError> { ) -> Result<(), ProofVerifyError> {
let timer_verify = Timer::new("SNARK::verify");
let _timer_verify = Timer::new("SNARK::verify");
// transcript.append_protocol_name(SNARK::protocol_name()); // transcript.append_protocol_name(SNARK::protocol_name());
// append a commitment to the computation to the transcript // append a commitment to the computation to the transcript
@ -453,38 +452,40 @@ impl SNARK {
let timer_sat_proof = Timer::new("verify_sat_proof"); let timer_sat_proof = Timer::new("verify_sat_proof");
assert_eq!(input.assignment.len(), comm.comm.get_num_inputs()); assert_eq!(input.assignment.len(), comm.comm.get_num_inputs());
let (rx, ry) = self.r1cs_sat_proof.verify(
// let (rx, ry) =
self.r1cs_sat_proof.circuit_size(
comm.comm.get_num_vars(), comm.comm.get_num_vars(),
comm.comm.get_num_cons(), comm.comm.get_num_cons(),
&input.assignment, &input.assignment,
&self.inst_evals, &self.inst_evals,
transcript, transcript,
&gens.gens_r1cs_sat,
// &gens.gens_r1cs_sat,
)?; )?;
timer_sat_proof.stop(); timer_sat_proof.stop();
let timer_eval_proof = Timer::new("verify_eval_proof");
let (Ar, Br, Cr) = &self.inst_evals;
// Ar.append_to_transcript(b"Ar_claim", transcript);
// Br.append_to_transcript(b"Br_claim", transcript);
// Cr.append_to_transcript(b"Cr_claim", transcript);
transcript.append_scalar(&Ar);
transcript.append_scalar(&Br);
transcript.append_scalar(&Cr);
self.r1cs_eval_proof.verify(
&comm.comm,
&rx,
&ry,
&self.inst_evals,
&gens.gens_r1cs_eval,
transcript,
)?;
timer_eval_proof.stop();
timer_verify.stop();
// let timer_eval_proof = Timer::new("verify_eval_proof");
// let (Ar, Br, Cr) = &self.inst_evals;
// // Ar.append_to_transcript(b"Ar_claim", transcript);
// // Br.append_to_transcript(b"Br_claim", transcript);
// // Cr.append_to_transcript(b"Cr_claim", transcript);
// transcript.append_scalar(&Ar);
// transcript.append_scalar(&Br);
// transcript.append_scalar(&Cr);
// self.r1cs_eval_proof.verify(
// &comm.comm,
// &rx,
// &ry,
// &self.inst_evals,
// &gens.gens_r1cs_eval,
// transcript,
// )?;
// timer_eval_proof.stop();
// timer_verify.stop();
Ok(()) Ok(())
} }
} }
#[derive(Clone)]
/// `NIZKGens` holds public parameters for producing and verifying proofs with the Spartan NIZK /// `NIZKGens` holds public parameters for producing and verifying proofs with the Spartan NIZK
pub struct NIZKGens { pub struct NIZKGens {
gens_r1cs_sat: R1CSGens, gens_r1cs_sat: R1CSGens,
@ -523,21 +524,16 @@ impl NIZK {
inst: &Instance, inst: &Instance,
vars: VarsAssignment, vars: VarsAssignment,
input: &InputsAssignment, input: &InputsAssignment,
gens: &NIZKGens,
// gens: &NIZKGens,
transcript: &mut PoseidonTranscript, transcript: &mut PoseidonTranscript,
) -> Self { ) -> Self {
let timer_prove = Timer::new("NIZK::prove"); let timer_prove = Timer::new("NIZK::prove");
// we create a Transcript object seeded with a random Scalar // we create a Transcript object seeded with a random Scalar
// to aid the prover produce its randomness // to aid the prover produce its randomness
let mut random_tape = RandomTape::new(b"proof");
let _random_tape = RandomTape::new(b"proof");
<<<<<<< HEAD
transcript.append_protocol_name(NIZK::protocol_name());
transcript.append_message(b"R1CSInstanceDigest", &inst.digest);
=======
// transcript.append_protocol_name(NIZK::protocol_name()); // transcript.append_protocol_name(NIZK::protocol_name());
inst.inst.append_to_poseidon(transcript);
>>>>>>> simplify transcript and change merlin backend to poseidon
transcript.append_bytes(&inst.digest);
let (r1cs_sat_proof, rx, ry) = { let (r1cs_sat_proof, rx, ry) = {
// we might need to pad variables // we might need to pad variables
@ -555,9 +551,9 @@ impl NIZK {
&inst.inst, &inst.inst,
padded_vars.assignment, padded_vars.assignment,
&input.assignment, &input.assignment,
&gens.gens_r1cs_sat,
// &gens.gens_r1cs_sat,
transcript, transcript,
&mut random_tape,
// &mut random_tape,
); );
let mut proof_encoded = Vec::new(); let mut proof_encoded = Vec::new();
proof.serialize(&mut proof_encoded).unwrap(); proof.serialize(&mut proof_encoded).unwrap();
@ -578,17 +574,51 @@ impl NIZK {
inst: &Instance, inst: &Instance,
input: &InputsAssignment, input: &InputsAssignment,
transcript: &mut PoseidonTranscript, transcript: &mut PoseidonTranscript,
gens: &NIZKGens,
) -> Result<(), ProofVerifyError> {
// gens: &NIZKGens,
) -> Result<usize, ProofVerifyError> {
let timer_verify = Timer::new("NIZK::verify");
transcript.append_bytes(&inst.digest);
// We send evaluations of A, B, C at r = (rx, ry) as claims
// to enable the verifier complete the first sum-check
let timer_eval = Timer::new("eval_sparse_polys");
let (claimed_rx, claimed_ry) = &self.r;
let inst_evals = inst.inst.evaluate(claimed_rx, claimed_ry);
timer_eval.stop();
let timer_sat_proof = Timer::new("verify_sat_proof");
assert_eq!(input.assignment.len(), inst.inst.get_num_inputs());
// let (rx, ry) =
let nc = self.r1cs_sat_proof.circuit_size(
inst.inst.get_num_vars(),
inst.inst.get_num_cons(),
&input.assignment,
&inst_evals,
transcript,
// &gens.gens_r1cs_sat,
)?;
// verify if claimed rx and ry are correct
// assert_eq!(rx, *claimed_rx);
// assert_eq!(ry, *claimed_ry);
timer_sat_proof.stop();
timer_verify.stop();
Ok(nc)
}
/// A method to verify a NIZK proof of the satisfiability of an R1CS instance with Groth16
pub fn verify_groth16(
&self,
inst: &Instance,
input: &InputsAssignment,
transcript: &mut PoseidonTranscript,
) -> Result<(u128, u128, u128), ProofVerifyError> {
let timer_verify = Timer::new("NIZK::verify"); let timer_verify = Timer::new("NIZK::verify");
<<<<<<< HEAD
transcript.append_protocol_name(NIZK::protocol_name());
transcript.append_message(b"R1CSInstanceDigest", &inst.digest);
=======
// transcript.append_protocol_name(NIZK::protocol_name()); // transcript.append_protocol_name(NIZK::protocol_name());
inst.inst.append_to_poseidon(transcript);
>>>>>>> simplify transcript and change merlin backend to poseidon
transcript.append_bytes(&inst.digest);
// We send evaluations of A, B, C at r = (rx, ry) as claims // We send evaluations of A, B, C at r = (rx, ry) as claims
// to enable the verifier complete the first sum-check // to enable the verifier complete the first sum-check
@ -599,22 +629,23 @@ impl NIZK {
let timer_sat_proof = Timer::new("verify_sat_proof"); let timer_sat_proof = Timer::new("verify_sat_proof");
assert_eq!(input.assignment.len(), inst.inst.get_num_inputs()); assert_eq!(input.assignment.len(), inst.inst.get_num_inputs());
let (rx, ry) = self.r1cs_sat_proof.verify(
// let (rx, ry) =
let (ds, dp, dv) = self.r1cs_sat_proof.verify_groth16(
inst.inst.get_num_vars(), inst.inst.get_num_vars(),
inst.inst.get_num_cons(), inst.inst.get_num_cons(),
&input.assignment, &input.assignment,
&inst_evals, &inst_evals,
transcript, transcript,
&gens.gens_r1cs_sat,
// &gens.gens_r1cs_sat,
)?; )?;
// verify if claimed rx and ry are correct // verify if claimed rx and ry are correct
assert_eq!(rx, *claimed_rx);
assert_eq!(ry, *claimed_ry);
// assert_eq!(rx, *claimed_rx);
// assert_eq!(ry, *claimed_ry);
timer_sat_proof.stop(); timer_sat_proof.stop();
timer_verify.stop(); timer_verify.stop();
Ok(())
Ok((ds, dp, dv))
} }
} }
@ -623,7 +654,7 @@ mod tests {
use crate::parameters::poseidon_params; use crate::parameters::poseidon_params;
use super::*; use super::*;
use ark_ff::PrimeField;
use ark_ff::{BigInteger, One, PrimeField};
#[test] #[test]
pub fn check_snark() { pub fn check_snark() {
@ -775,7 +806,7 @@ mod tests {
.is_ok()); .is_ok());
// NIZK public params // NIZK public params
let gens = NIZKGens::new(num_cons, num_vars, num_inputs);
let _gens = NIZKGens::new(num_cons, num_vars, num_inputs);
let params = poseidon_params(); let params = poseidon_params();
@ -785,14 +816,14 @@ mod tests {
&inst, &inst,
assignment_vars, assignment_vars,
&assignment_inputs, &assignment_inputs,
&gens,
// &gens,
&mut prover_transcript, &mut prover_transcript,
); );
// verify the NIZK // verify the NIZK
let mut verifier_transcript = PoseidonTranscript::new(&params); let mut verifier_transcript = PoseidonTranscript::new(&params);
assert!(proof assert!(proof
.verify(&inst, &assignment_inputs, &mut verifier_transcript, &gens)
.verify(&inst, &assignment_inputs, &mut verifier_transcript)
.is_ok()); .is_ok());
} }
} }

+ 1
- 4
src/nizk/bullet.rs

@ -11,14 +11,11 @@ use super::super::group::{
CompressGroupElement, CompressedGroup, DecompressGroupElement, GroupElement, CompressGroupElement, CompressedGroup, DecompressGroupElement, GroupElement,
VartimeMultiscalarMul, VartimeMultiscalarMul,
}; };
use super::super::math::Math;
use super::super::scalar::Scalar; use super::super::scalar::Scalar;
use super::super::transcript::ProofTranscript;
use ark_ff::{fields, Field};
use ark_ff::Field;
use ark_serialize::*; use ark_serialize::*;
use ark_std::{One, Zero}; use ark_std::{One, Zero};
use core::iter; use core::iter;
use merlin::Transcript;
use std::ops::MulAssign; use std::ops::MulAssign;
#[derive(Debug, CanonicalSerialize, CanonicalDeserialize)] #[derive(Debug, CanonicalSerialize, CanonicalDeserialize)]

+ 3
- 10
src/nizk/mod.rs

@ -5,18 +5,13 @@ use crate::poseidon_transcript::{AppendToPoseidon, PoseidonTranscript};
use super::commitments::{Commitments, MultiCommitGens}; use super::commitments::{Commitments, MultiCommitGens};
use super::errors::ProofVerifyError; use super::errors::ProofVerifyError;
use super::group::{ use super::group::{
CompressGroupElement, CompressedGroup, DecompressGroupElement, GroupElement, GroupElementAffine,
UnpackGroupElement,
CompressGroupElement, CompressedGroup, DecompressGroupElement, GroupElement, UnpackGroupElement,
}; };
use super::math::Math;
use super::random::RandomTape; use super::random::RandomTape;
use super::scalar::Scalar; use super::scalar::Scalar;
use super::transcript::{AppendToTranscript, ProofTranscript};
use ark_ec::group::Group;
use ark_ec::ProjectiveCurve; use ark_ec::ProjectiveCurve;
use ark_ff::PrimeField; use ark_ff::PrimeField;
use ark_serialize::*; use ark_serialize::*;
use merlin::Transcript;
mod bullet; mod bullet;
use bullet::BulletReductionProof; use bullet::BulletReductionProof;
@ -423,6 +418,7 @@ impl DotProductProof {
} }
} }
#[derive(Clone)]
pub struct DotProductProofGens { pub struct DotProductProofGens {
n: usize, n: usize,
pub gens_n: MultiCommitGens, pub gens_n: MultiCommitGens,
@ -595,13 +591,10 @@ impl DotProductProofLog {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::marker::PhantomData;
use crate::{group::VartimeMultiscalarMul, parameters::poseidon_params};
use crate::parameters::poseidon_params;
use super::*; use super::*;
use ark_bls12_377::{Fq, FqParameters, G1Affine};
use ark_ff::{BigInteger384, Fp384};
use ark_std::UniformRand; use ark_std::UniformRand;
#[test] #[test]
fn check_knowledgeproof() { fn check_knowledgeproof() {

+ 142
- 225
src/parameters.rs

@ -5,225 +5,138 @@ use ark_sponge::poseidon::PoseidonParameters;
use json::JsonValue; use json::JsonValue;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use crate::group::Fq;
use crate::group::Fr;
lazy_static! { lazy_static! {
/// bls12377_rate2_constraints:
pub static ref P1: JsonValue = object! {
// bls12377_rate2_constraints_fr:
pub static ref FR: JsonValue = object! {
"ark" => array![ "ark" => array![
array![
"123249878756453098914639601843199176451997132612914162343590671120179979107846114348064675842753496966502226470504",
"53905766173893895260794869709237214385817399454448711667759505042599362214601718682151848385057179500606557721647",
"69894258097921391480299485244196654800484322255007476002974737215216019155108287854575586445309048623300976500186"
],
array![
"199269668121875174262570566455689951380204776091573924798659006690560053061129973379838694860592058095048653996886",
"238380155638054426865611280966399840311283670977656700124343990049337832223435242290330416091629395326468367200694",
"212599814638151740594239938840408336056840064513659388805072396583467200575230295920880684207605497942975271963482"
],
array![
"168914555474650585865140636066457509664822869961119817085015902784107763611497575013588473080216753361935154707010",
"53776337623194839368137436133474167179306472987260969806083684345990583528478024243778418311781192352786333037262",
"248867522100291115924418017563087071912585010573958563496624003376931076896846052799391847772671448846373554213551"
],
array![
"35631741058397496924366231156673935881565943972602937094522045989256363839293709188784238224940964750407897277330",
"7156811532468409927576845751990203959972794842929038664826572233020786824205198784067484739611297952558975673525",
"15979461281492123433122857594463244790261784547146673175073000444677214597242748768087325039007316516299176001509"
],
array![
"49754305211992756860291736450940496115500536038609822532547985566439150683219315252172063528174877535028115611426",
"216949553183571701463265648286619401188451882876550757881148401346730830975776784112086074385527611896268776861443",
"154083689848809196835533626226861291475925228965341568449375421928198779718328545609801450631059855774468437183675"
],
array![
"29502137502944860067241987089780210878930586459241857665873534227953181087265906053919742367508518196418106799806",
"132373035808136518827992049261301947450498154936614023679388954300081661784851944028690271115929087672833323628947",
"215747065685210104280208334912564361804699328020235674942496660758226155688200145092731052953352829033676863042630"
],
array![
"199648585544625597282043439398719700409246757664428471828724582419530290323495031580337339234017647369916547108958",
"249575928844995465269738608819476286372884074177639142297081916221358214871660642843838074316560663218386973740173",
"74982114655706235696493453220768307411520767156884132118410225505977592728838652389837915751053304413004683265639"
],
array![
"106210893563839260576304917669354671677368166928359922623554581531406088660838991706361575276657684361659801532597",
"11585440423875492387746565618452234080951922019833673083821688269701182965167436520603220148800340540649190539129",
"37259364694251003983990539546703073907090415386678577600390274977885009271501265285951467194762590248232970812844"
],
array![
"55837576930986823158863800928077105077853280536700135646766922885911998320579725325719074294029609849816879406734",
"116196118812458208678900768001429737210506949071720002979523997962887466062064707950742955679705357069634209515723",
"24815444638034932833671809997597970940772642987124330190627003560135207315166813788012165972582101193880572012425"
],
array![
"8273799170260651595038492091530332589844019793817674372861920239816475852471908767091347071442643736888815451573",
"136990111822759715389631392741048451444971543778803264358207793191138912342988121207664006283186301023235486962908",
"18927153358572748727167231887593945930709178220781358813059367890606662567925981344966823750216495960065937779382"
],
array![
"14853717798346258618706074618305350695598054492875071420312670809589654546598863746625188519698040835608660556159",
"176244718044988586163620753193829773891006448729185890339575543133809251309372861124810944047181141986328457412271",
"110233743777966819273995158642051347290508079434162581354613179685804039325709118867348142870653771761630005888307"
],
array![
"161450408187838611032909671423510614052593225149162808041124828019352169325631782682210492475825053268732766729188",
"98500573657597535150392453836987141880178711694344573271124963035313026654066107879785978599420939724454330812177",
"215876031358183401857867635719035351422270130594078940310356834104879903855422762837568172975859284057413791888463"
],
array![
"204131296462104965227188513952192358580161695271034405933269755582850293970852406144296664401269366372941792250467",
"249055944105228847655227995674839790690527612872758434023675475202902983562708467495202781909125241976893640769485",
"229583286868130259500413761228235662329364304128164289006746728927752301094007770574061957905615623121952293733410"
],
array![
"97517137752483519086795583001379387731583152856232248443468839338330057977841917349007821334306740790291136905974",
"123488479251161582154755930609622851433258511862463208593787895860046694339616550157942520077460765622263030118175",
"71432639825611523000280189495110508914555485498103026713477936527348359478511563831157563324853527351478004088468"
],
array![
"91036072174315573792700064386146501824720160045153964050728880763049550271037560479809028105202996773568857740730",
"22543564450401763754262340909190687557385187274502421381039682479049063587284520644182139148382788770792136350730",
"142332951471076179551307567596387601171650552060403080229506160329597397458669457278907083453911143048367692807957"
],
array![
"132220734042377172239294549962805515211262743615319266088172915692615455860531484953442975677793502323549653807013",
"93545141080589996877640088231346264823743396787843686206971590288437291906435217842171096954488932034021955982341",
"240853888813002049402641151657197764532471620278969626757294146309548064471722973918761650243980940919903584631021"
],
array![
"213503951761453329038225269663723790274543267128942326856880800168236861547603473591480303861374397603917184363409",
"89903237953544441905563167047407202265037317870234905464628470820413104873403912116742106741939288646681955585592",
"227121824801807544842683518849178395477499272684097761652696447845872786929195257751449337349649535876783186356932"
],
array![
"146971666607035715052553690155718843961663952406456998981945817009558492075030732771578449344145496025583596767529",
"134089029253068479750825302615074040106242441439845487647903191411265000857473209669062720892950980761449114307448",
"240876825504060088346683291079269022914405381209699533928214418428379986520457497863030431018122239809907227823545"
],
array![
"198679995161578152944752940670334322637799809857648522826858388680172266023884005933440419287476164086770000386213",
"80453254513068178946616210391952329341738228131537630777936072121633132376974015675425930731821852982135052772824",
"51768068183070369841309308465744117994964313769378589398952388439182600629247824076033474616974680361718264496789"
],
array![
"243786304512064454489442716415645262128218178912097043568997297339729319251009514316482045843945939785873311024862",
"132173037488875105639933852791191619959134471035456041997878656537714362390384670197604289467581846432000497395848",
"138604002173172705882182745730007697550901886293221788738303534900559003963900219115006541529324886578352274293799"
],
array![
"81783919742603431816536303551235523053319325628680028340677898253811841771498386894771134375242031554657528159968",
"89996400559826291686063370272745776928773053585174906250124744120004601102635457051808673956966087024872962073778",
"12344123991576028812375373502965766640863831483294590816896451707123374600150201588149068234468387476695336142872"
],
array![
"126658015711577921340966771989453650175842088716604137911295183366663485409400992312567694787591845600554914654115",
"164573749458837881364642242529191795392373682411872943164652677729048094673511958737424619008331062199862267652935",
"143664707544522749631081019060087611028964440272897357239195964754781588855456478370128855886667526444876450715220"
],
array![
"190063502426458192727293662114673159337018305482738016082798402909947909388433256561924969169284825978832455579368",
"200570271046622734241692574928890759512247601848653772722076665026354776331148830989844078413438205377226077381532",
"138002415082423685424410551811447526297743243297262932785520614237184932570821640271043572260989269814779470761461"
],
array![
"16788676705864143878780230479765282864054741033672656690224477402805235181341884274547412331727211099012342081859",
"204290600886783875333612666138119904239583082229871768433568000092203989815186589303588884701205693229512519768754",
"87038987841167673770859932175226012933997089943393502222169060963262863845214906568997443646438042896398425595517"
],
array![
"36339730403510893807656584803012696279422432037251730189319369181711761371163710757212065138707754369092877655154",
"23719136079159372599286451744989936807954969964666516807332295420486880070514166596679589399139358707568583760908",
"56393335057571631799160728164218189604902690263179612889078150181027528679320914138536210530501845237163318197428"
],
array![
"205825956035491267343111682188790766922328411605275469211275484195313659964988531094479492782154028581379936224444",
"14251323509232608512846002255486393977548730149242264667463070512925839406395836441387775340864744223546556498715",
"78428895560820169309169428677090706087502853851935641954584167534512067284012881590143110425966068532035695668777"
],
array![
"75494383501361595510879099604200999089073272552094921752996800680267084650818676639185519371499429119407927521694",
"71654751419236499966546173490894599834311797714598165686807217633186393301928260640596079166780877531085221325785",
"200578082042519003217027186194032673613554519507662494009516442239977006673663941756393116663841297396793491871200"
],
array![
"120280384146306862951854508424447098979618461682025441151850969362942271625861150381428890843919546149633622105768",
"227475425496153223669855864055613669014065977392917058770175352117179491094064142348157299350182313499504389083442",
"251127263423734302912203519333198755054413799582445749881827904612771493287021107263113755730642765378206506332728"
],
array![
"83702595636895308967051271584382753663326775825724154674461807131791275318302215831042606082449545102374950849149",
"72457985217378059985209058682320070298806205003882947360107581077425648268857982638575115120572096951096305132848",
"12116600973201943572988978934130839409963908949941838392365368398743958008280031214900074753572240221871297157796"
],
array![
"240872572144156225455781664515486127362275317595363215915293841253269790726868349873274949641462036923410553640448",
"145005621445512968320023394688234446061157047306027479183225589915851108312974841851900985683181027983777819469749",
"223934906758737028193582875327881601162900418521869327818828928797111524239009182764598636421899745113893918838102"
],
array![
"16041135858962966773434394701665023495889307936385789447051685789622713476233465453520183391926457145978975456780",
"100995326650741809373350376300291093265611246694300366918949313510272548230989953212376186670081618363334860819266",
"198113061836041953087296741499457296947901762958345262407373960882722071735229745555760175641534017765920249851403"
],
array![
"160310964282803191210156178260469498817686363777861893444880694842806130876775742977058740003184226096711472502332",
"188713129639597187156378905515616933770775761286091242780337441914651066308540192205692023798450603034519453279164",
"144177371846162732968346932904974285173557315948314203099016729242538001323624139665700501564547696462348047085475"
],
array![
"79270873425284875854185620699109770597921524227459035513636651263949603822776268395349011178814936290604749327216",
"66634508562919326060253106867724866375414704994924403132729353386392729560099833340809999504328104294822126690206",
"153929451747036516277146884279088023240503545576502622475104547924498837499332163003522743849174380874173903478589"
],
array![
"65951591639970943843478787167093376292485300299245482252716091066831460583153445126961516774641242644059740963631",
"218283324593072992330537678366612521138133713936527225314279366375484764183384762101590493464257294993736058798003",
"255801326343293104028075157882719596846119525365262151647658801094843254475907908556215545683201236013153654096091"
],
array![
"226255389453600272835601278226928175590352392261397636954040403683064727971365284972741836048745971086673805312770",
"30094566584570359029617856208266980210102789615056943080637739339632299082666382408767896640283618386400863011377",
"171014403954507192635907791911496156579477488568451453501143540559952206171633891640382019016227963532953321760176"
],
array![
"166057204219683871752892448206953243424627338207417177280506199576386068200127812837156087933305873775343563022702",
"189980739384556361714711372786771245267076300911771323385655044819119270337048535106665515768517077503660696853087",
"160509966668023670725615598656132311085788181242287915812481624013950278259314541983309947248633680202474798784113"
],
array![
"121604680206118278311858973633579806987780447456690173958929756615242378735587345162043644789250322132552405934838",
"162490787868836358365957714904092588505217178719637049967797863955517541278871433068812149053958672871873339777657",
"186725839885149672835245872626306502017366920295670132626156737796246154714707858273955752031344539280320214023217"
],
array![
"1595442381035683601009655514607864917155264882908420917897267779293136954609652688808389170558528873507396022657",
"136133658372771228168254201060050291177683595113705517331628662542619211285959494716428905546778127973286832435248",
"235707281471584662954139438770000959801075760015072690205031932435280838811659817426504701946918628382850116491607"
],
array![
"218394064516331833020386245120198448098388776182164066507039096886784654454748249393443008924076322437744672962940",
"171630003249069743969583651512237853143542592922081517495872510118379411011409238640358871094120884164999614012",
"106352495811714591674517100311841383873861724084673517408579093193910563925812357978278276551276192431523493134802"
]
],
"mds" => array![
array![
"35463799792750972803746014831251318629433070651916394903137949221437209577677273605833717469941575569104741526451",
"18525374364661750307440824350340771293424609245159218207409253749617918442029080961367157063966182839254983576724",
"96313611821735511449591580163083975587347120205529218061849469348716252837177987500111192232021055962542059542412"
],
array![
"184610826894298373826952030256215485452556494530798726246415694794196222735666067140505346074672032818873376193660",
"169170114062164939552104715979827042386033829996509029655899361104098442853225147615546393356393444238242438049980",
"24177241132903335121524689415818818107920151023402250200813429563196326173884815770339346817801446861279643703952"
],
array![
"17228430949886884828033371768349883299641066192821547195081333400086665473981454169936377873256566147576607049992",
"35113533023170247280272066588387614578863541036869539331927201531038853371598133096624809442419922813566246641442",
"225762263795139846379155325981635321549752796953252150370574780810431415761301654496442331322761087421338650655933"
]
],
array!["1370773116404421539888881648821194629032979299946048429076387284005101684675",
"4673035637825817609038514733539555185313791666023633961663352080665830654830",
"3476986714632640194314485873881082667866912997891863048915892042674874286264"],
array!["1082495278266482754833562621758308632581366365108718780801560341752506567697",
"4949432510532674124503328437030614426007112126335799011165573383397503068558",
"1330731268421256836250705136567442317504087954921291231955447229193812596308"],
array!["2649505161225663922316999879032136225486779063673300240621719420078616600331",
"4969420587703679612645522006695883166296724515300508402438681500077273342102",
"205635712587803026777585519450868615715404988831679984758308345484658244699"],
array!["6145772648854219628629735661952781083869402744236565775495743574991105198727",
"5694971131555029816374722311330556638260056256238039903705739439184187043937",
"5741725876337992913741719090196370235271299497940404104226910654118627348231"],
array!["6469638413629030129780219709477213488269112947492045389237429028620220258446",
"3701595212702118832843766258638566924918883592466668319824165091176624488470",
"3788264172113320071929375505654410621672880197708720070568683533593741188367"],
array!["7440115096888436553805393179190448787187286166192882400220572931865568317182",
"792346028642694686435936057983036575794551345818605100013220351237266490211",
"3512073197867644095949820682768614757198377867832806840119595329029395413419"],
array!["3327088580126882425803902509250293076948968718390152099056814690231480975540",
"7158369207426751973498757672315193862013926247640641608613447343948389969907",
"6576114422707630183258306285876174832535448513519868242206479550748199028650"],
array!["1750441329216804285131573838407988974537000108919914117251383215390240334007",
"6643642586767682146943021170325866479407987761019956931934065669737733844970",
"4106833857706706417652949425395842926674588555313556065852954705212767334548"],
array!["5196247641080157421214976259470019902011109253162446920598369271583914387912",
"6360624992789526556614108772011303405529807087502693775123890278812066474754",
"8425833359837698797187325575646708254811496588866812335451071326764069753553"],
array!["7571765444928048488636382364785227388831860339901373587410494373985769122100",
"1146560176939543249528183531911179059346379826648787355971780563762045417939",
"7065673187452873657602174269205792331276819829797382751854008973390840650347"],
array!["2996886232144394882237600400269759049381836612341075168714674419715424495381",
"7668744387648470169368229696434415530109096020857128629089289952099341334341",
"936627698981026919732496023789041288394375500602254911470718843646602645053"],
array!["6199749224785668013863210092063343076018531979597999604829468825162260274190",
"1653132234679858820482383205271489733007453315887823778464537322543673289375",
"7939359542319254103812635759696217625861967838748888560647186882218141754398"],
array!["5250147394211818178524181700154433748053992647055590962793825894928645733326",
"235902753941634492088451291363018081809625358810315316265161104829935550542",
"6608963137139961850002639926351347514621255004982055637993898513250013620207"],
array!["686840635267965663175276645211808051025823527505028096239338481540935993835",
"6836915689880452140045500520891176609600850753468429607484223074627863622754",
"4411311036661487117682008390277121256586135166845650218368031395328640568455"],
array!["7765580651637884064091086941299831107821005732883926779656422881469118342677",
"332549754384827539552516583331436482626027168628972328124682073094327566178",
"8438579169602499403531276834153862236681805902767396281885988675130427183942"],
array!["4371224392051444141538216717830171873522813314722974453159288159086172590441",
"4471819188266525256545603690402039960553559029943278641513107103995534212653",
"7934285249368611074358220926618133755594116808280441387064776330233673680433"],
array!["3296929004083914338419828203502973195235748568216135964056267831058260996338",
"7828705062628438916991665037339807083733865061668384262916273779860279371794",
"6313358380505257639005175768394745400256528068580776946435054333930810425918"],
array!["7673091158517942236320201239127705985446414040558434294512441355493079388101",
"3589839431787481799335476281766961640592432750884680804513596535388211513959",
"3497309798506406648010286927425548038594271991920637549888387014860982947288"],
array!["3598928531842189258027744661377220155690961099878644839237443661252156892627",
"8323476545439527339398168929351847585459351691146904838200536423836775797722",
"2525233425021205371462807301191193452372106809085080242885832543937723343824"],
array!["1670123541208150697178760793866430341950571765422973242642698972122650175931",
"2615994352824306042392204336460002628039562926557752567316988279659549764738",
"3845612285742795068547496524855308821681721826554794539870518271238257264872"],
array!["8111729937113136682593516470591971173110681064547090000686075778488505769131",
"8396009887088699712099390488777898295472002649026341742255474271675851100167",
"7414449034416524223782013238252312102346828190465700203171291370882467344947"],
array!["3778308769422683143427677977866154704853508570989688082271648398982585170107",
"2565370813801956884760401215151019368813258954878221563399238313359761598300",
"7277843344904687178893605017520459777796065293383180828267621160222576167983"],
array!["6533305346353864830435743885484797433819452357103761181561861553139604158691",
"7023616807188225486961828699414844137821383541366139971758751915067616890468",
"6455936034448761051686329703810283225146169133435552271890713431685063292826"],
array!["2781819771186595572605878483518345975589831093852202671865373784050027047498",
"7768920898267371999735782676903681841500678447293607126814923973294043875457",
"6463549363657422809088424260159871142005366302883731565233242485772646214776"],
array!["4269033939844383336636476360431731618619965524039119758847937142713481376709",
"5618036788017776315188246458501777138795420885496187406031735668173200947333",
"1128431213282240763420656004648057492974288942591424362188971631793337713791"],
array!["6900739195883338461228609955335408882714240356250551921341894223851444718631",
"3771335365721990684607605930021444592509300370948450043449389607062564762590",
"4101659620264578558029808267598816776989279597141521237379858078563415422176"],
array!["7265965499850925058171553371274334440963706378337393611300731052328159723420",
"4766078774636290635629565607286497839044156826339894416138410680627572132174",
"6432220484581857509344049161489739648526811837695982886809250552529276108059"],
array!["6361365189519422980433504384140223138978192212838226387265114914908491362931",
"7610377774980016354219333532677870219839779550900332138169496134065793623856",
"363180943030113865942993953461474483659264066502549823448101062593623940092"],
array!["3562244767885763851343292605940116818317029725206904934994049890929589055395",
"7782549227482772885045540707357099585281118980712854335622177919009966444948",
"1275552603578693917501370061277948491143012995771911804618466157236333967239"],
array!["5104148721380689096094143534135757186465840305075873333902995773940524349076",
"3827555903928560008785730325772720209567461775844698712063218244346202837926",
"6537952092752701292661689328736100739363623229800800023575262375504637794811"],
array!["2625555787287768315537311869809801184270047957788564515280996906803464172085",
"2268046926631224821219360422346148209575446526490776085639666316914303207343",
"8301985790233975096406293902798523168400755923104779849614021896827941122062"],
array!["6186410907907226666421909877388154922245464592386712702411681535145025981542",
"1570197114753247526703806268420919303949793186535455032181860083077073573260",
"6433616921731463425493337442585921501113569311931762833956390491384184622184"],
array!["3730715929874541583946502538607860277000019933547155277889700636306045698678",
"4162712607911623590542516061947062496983700183068013598513127619182396118738",
"4885581468925689451043482261642022591161185334411569876922526171563347772487"],
array!["679010986662603253067780482929422410547319947222192616893132766589997651700",
"7045332371454775389874918027434858274122123892961682451412342124928285105115",
"796483939088841221822094384379289433804847199444006131260701274900329521826"],
array!["6930777873598706215302735286927888271122111082058406024378887982572264481712",
"3833261336312955683233981899122259611841384124139797023838966596495768744423",
"6081952172694136481884686958014712088378824178559544670607383857565862846284"],
array!["3816381396460078181431529965953560061945407168453302734314638292833792891390",
"56734387980297685686110088096585973744605712015961903089771968507489169889",
"1528381975769046861077120384272922840572114805411576866912148437940560430592"],
array!["4051427337822729290390706006634045761150954597129823553613464074823819976689",
"928801883926308717594921627141285880564599719525707838888160095066522021660",
"2575814441780474908465005749689528467553680700052052921662671958906858409792"],
array!["4188482005041843983756841875722811236284873807578170011114849822278345286775",
"2055640774204777367415844703991682482137697203553277498227758201416424138567",
"4575553062307433825409075011087260276527850105624870927391350382554634786094"],
array!["1854996916655462786356197865726500413712215270951193953965916926815164398288",
"4106990062567081635175461840146829007165341060131472749713325730182145598945",
"4440684113159162228103294475409844107272920293202271745070427054893404635089"]],
"mds" => array![array!["6093452032963406658309134825240609333033222270199073508119142384975416392638",
"5968273173562867837210008744966745230923761158428968101807573098840850097286",
"1100466639266852149977689148055725793531897994956807001704693611715839541982"],
array!["3160983601532844171864802850648492289862147997874094785600836495095965353712",
"2338351297827692414112631814274572996809824929139580588221558887342663769892",
"3177005087903404343485399282920555615020488967881372266904325860698809358885"],
array!["2285176219817854683696635383059984246218458246545520061123961933072089703485",
"84377861777946561525373172505381054389617879929776365352216307785104476701",
"8280884008678095605415834125731826663585461281789631237939546251146561093166"]],
"rate" => 2, "rate" => 2,
"alpha"=> 17, "alpha"=> 17,
"full_rounds" => 8, "full_rounds" => 8,
@ -232,29 +145,33 @@ lazy_static! {
} }
/// TODO /// TODO
pub fn poseidon_params() -> PoseidonParameters<Fq> {
let arks = P1["ark"]
pub fn poseidon_params() -> PoseidonParameters<Fr> {
let arks = FR["ark"]
.members() .members()
.map(|ark| { .map(|ark| {
ark ark
.members() .members()
.map(|v| Fq::from_str(v.as_str().unwrap()).unwrap())
.map(|v| Fr::from_str(v.as_str().unwrap()).unwrap())
.collect::<Vec<_>>() .collect::<Vec<_>>()
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mds = P1["mds"]
let mds = FR["mds"]
.members() .members()
.map(|m| { .map(|m| {
m.members() m.members()
.map(|v| Fq::from_str(v.as_str().unwrap()).unwrap())
.map(|v| Fr::from_str(v.as_str().unwrap()).unwrap())
.collect::<Vec<_>>() .collect::<Vec<_>>()
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
PoseidonParameters::new( PoseidonParameters::new(
P1["full_rounds"].as_u32().unwrap(),
P1["partial_rounds"].as_u32().unwrap(),
P1["alpha"].as_u64().unwrap(),
FR["full_rounds"].as_u32().unwrap(),
FR["partial_rounds"].as_u32().unwrap(),
FR["alpha"].as_u64().unwrap(),
mds, mds,
arks, arks,
) )
} }
lazy_static! {
pub static ref POSEIDON_PARAMETERS_FR_377: PoseidonParameters<Fr> = poseidon_params();
}

+ 75
- 0
src/poseidon_transcript.rs

@ -0,0 +1,75 @@
use crate::group::{CompressedGroup, Fr};
use super::scalar::Scalar;
// use ark_r1cs_std::prelude::*;
use ark_sponge::{
constraints::CryptographicSpongeVar,
poseidon::{PoseidonParameters, PoseidonSponge},
CryptographicSponge,
};
#[derive(Clone)]
/// TODO
pub struct PoseidonTranscript {
sponge: PoseidonSponge<Fr>,
params: PoseidonParameters<Fr>,
}
impl PoseidonTranscript {
/// create a new transcript
pub fn new(params: &PoseidonParameters<Fr>) -> Self {
let sponge = PoseidonSponge::new(params);
PoseidonTranscript {
sponge: sponge,
params: params.clone(),
}
}
pub fn new_from_state(&mut self, challenge: &Scalar) {
self.sponge = PoseidonSponge::new(&self.params);
self.append_scalar(&challenge);
}
pub fn append_u64(&mut self, x: u64) {
self.sponge.absorb(&x);
}
pub fn append_bytes(&mut self, x: &Vec<u8>) {
self.sponge.absorb(x);
}
pub fn append_scalar(&mut self, scalar: &Scalar) {
self.sponge.absorb(&scalar);
}
pub fn append_point(&mut self, point: &CompressedGroup) {
self.sponge.absorb(&point.0);
}
pub fn append_scalar_vector(&mut self, scalars: &Vec<Scalar>) {
for scalar in scalars.iter() {
self.append_scalar(&scalar);
}
}
pub fn challenge_scalar(&mut self) -> Scalar {
let scalar = self.sponge.squeeze_field_elements(1).remove(0);
scalar
}
pub fn challenge_vector(&mut self, len: usize) -> Vec<Scalar> {
let challenges = self.sponge.squeeze_field_elements(len);
challenges
}
}
pub trait AppendToPoseidon {
fn append_to_poseidon(&self, transcript: &mut PoseidonTranscript);
}
impl AppendToPoseidon for CompressedGroup {
fn append_to_poseidon(&self, transcript: &mut PoseidonTranscript) {
transcript.append_point(self);
}
}

+ 0
- 1
src/product_tree.rs

@ -9,7 +9,6 @@ use super::sumcheck::SumcheckInstanceProof;
use super::transcript::ProofTranscript; use super::transcript::ProofTranscript;
use ark_serialize::*; use ark_serialize::*;
use ark_std::One; use ark_std::One;
use merlin::Transcript;
#[derive(Debug)] #[derive(Debug)]
pub struct ProductCircuit { pub struct ProductCircuit {

+ 11
- 2
src/r1csinstance.rs

@ -14,9 +14,13 @@ use super::timer::Timer;
use ark_ff::Field; use ark_ff::Field;
use ark_serialize::*; use ark_serialize::*;
use ark_std::{One, UniformRand, Zero}; use ark_std::{One, UniformRand, Zero};
use digest::{ExtendableOutput, Input};
use merlin::Transcript; use merlin::Transcript;
use serde::Serialize;
use sha3::Shake256;
#[derive(Debug, CanonicalSerialize, CanonicalDeserialize)]
#[derive(Debug, CanonicalSerialize, CanonicalDeserialize, Clone)]
pub struct R1CSInstance { pub struct R1CSInstance {
num_cons: usize, num_cons: usize,
num_vars: usize, num_vars: usize,
@ -159,7 +163,12 @@ impl R1CSInstance {
pub fn get_digest(&self) -> Vec<u8> { pub fn get_digest(&self) -> Vec<u8> {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
self.serialize(&mut bytes).unwrap(); self.serialize(&mut bytes).unwrap();
bytes
let mut shake = Shake256::default();
shake.input(bytes);
let mut reader = shake.xof_result();
let mut buf = [0u8; 256];
reader.read(&mut buf).unwrap();
buf.to_vec()
} }
pub fn produce_synthetic_r1cs( pub fn produce_synthetic_r1cs(

+ 134
- 98
src/r1csproof.rs

@ -1,29 +1,31 @@
#![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_arguments)]
use crate::group::CompressedGroup;
use crate::constraints::{VerifierCircuit, VerifierConfig};
use crate::group::{Fq, Fr};
use crate::math::Math;
use crate::parameters::poseidon_params;
use crate::poseidon_transcript::PoseidonTranscript;
use crate::sumcheck::SumcheckInstanceProof; use crate::sumcheck::SumcheckInstanceProof;
use super::commitments::{Commitments, MultiCommitGens};
use super::dense_mlpoly::{
DensePolynomial, EqPolynomial, PolyCommitment, PolyCommitmentGens, PolyEvalProof,
};
use ark_bw6_761::BW6_761 as P;
use super::commitments::MultiCommitGens;
use super::dense_mlpoly::{DensePolynomial, EqPolynomial, PolyCommitmentGens};
use super::errors::ProofVerifyError; use super::errors::ProofVerifyError;
use super::group::{
CompressGroupElement, DecompressGroupElement, GroupElement, VartimeMultiscalarMul,
};
use super::math::Math;
use super::nizk::{EqualityProof, KnowledgeProof, ProductProof};
use super::r1csinstance::R1CSInstance; use super::r1csinstance::R1CSInstance;
use super::random::RandomTape;
use super::scalar::Scalar; use super::scalar::Scalar;
use super::sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}; use super::sparse_mlpoly::{SparsePolyEntry, SparsePolynomial};
use super::timer::Timer; use super::timer::Timer;
use super::transcript::{AppendToTranscript, ProofTranscript};
use ark_ec::ProjectiveCurve;
use ark_ff::PrimeField;
use super::transcript::ProofTranscript;
use ark_crypto_primitives::{CircuitSpecificSetupSNARK, SNARK};
use ark_groth16::Groth16;
use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem};
use ark_serialize::*; use ark_serialize::*;
use ark_std::{One, Zero}; use ark_std::{One, Zero};
use core::iter;
use merlin::Transcript;
use std::time::Instant;
#[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] #[derive(CanonicalSerialize, CanonicalDeserialize, Debug)]
pub struct R1CSProof { pub struct R1CSProof {
@ -36,7 +38,7 @@ pub struct R1CSProof {
// proof_eval_vars_at_ry: PolyEvalProof, // proof_eval_vars_at_ry: PolyEvalProof,
// proof_eq_sc_phase2: EqualityProof, // proof_eq_sc_phase2: EqualityProof,
} }
#[derive(Clone)]
pub struct R1CSSumcheckGens { pub struct R1CSSumcheckGens {
gens_1: MultiCommitGens, gens_1: MultiCommitGens,
gens_3: MultiCommitGens, gens_3: MultiCommitGens,
@ -58,6 +60,7 @@ impl R1CSSumcheckGens {
} }
} }
#[derive(Clone)]
pub struct R1CSGens { pub struct R1CSGens {
gens_sc: R1CSSumcheckGens, gens_sc: R1CSSumcheckGens,
gens_pc: PolyCommitmentGens, gens_pc: PolyCommitmentGens,
@ -126,14 +129,15 @@ impl R1CSProof {
inst: &R1CSInstance, inst: &R1CSInstance,
vars: Vec<Scalar>, vars: Vec<Scalar>,
input: &[Scalar], input: &[Scalar],
gens: &R1CSGens,
transcript: &mut PoseidonTranscript, transcript: &mut PoseidonTranscript,
random_tape: &mut RandomTape,
) -> (R1CSProof, Vec<Scalar>, Vec<Scalar>) { ) -> (R1CSProof, Vec<Scalar>, Vec<Scalar>) {
let timer_prove = Timer::new("R1CSProof::prove"); let timer_prove = Timer::new("R1CSProof::prove");
// we currently require the number of |inputs| + 1 to be at most number of vars // we currently require the number of |inputs| + 1 to be at most number of vars
assert!(input.len() < vars.len()); assert!(input.len() < vars.len());
let c = transcript.challenge_scalar();
transcript.new_from_state(&c);
transcript.append_scalar_vector(&input.to_vec()); transcript.append_scalar_vector(&input.to_vec());
let poly_vars = DensePolynomial::new(vars.clone()); let poly_vars = DensePolynomial::new(vars.clone());
@ -152,8 +156,7 @@ impl R1CSProof {
}; };
// derive the verifier's challenge tau // derive the verifier's challenge tau
let (num_rounds_x, num_rounds_y) =
(inst.get_num_cons().log2() as usize, z.len().log2() as usize);
let (num_rounds_x, num_rounds_y) = (inst.get_num_cons().log_2(), z.len().log_2());
let tau = transcript.challenge_vector(num_rounds_x); let tau = transcript.challenge_vector(num_rounds_x);
// compute the initial evaluation table for R(\tau, x) // compute the initial evaluation table for R(\tau, x)
let mut poly_tau = DensePolynomial::new(EqPolynomial::new(tau).evals()); let mut poly_tau = DensePolynomial::new(EqPolynomial::new(tau).evals());
@ -180,7 +183,7 @@ impl R1CSProof {
// prove the final step of sum-check #1 // prove the final step of sum-check #1
let taus_bound_rx = tau_claim; let taus_bound_rx = tau_claim;
let claim_post_phase1 = ((*Az_claim) * Bz_claim - Cz_claim) * taus_bound_rx;
let _claim_post_phase1 = ((*Az_claim) * Bz_claim - Cz_claim) * taus_bound_rx;
let timer_sc_proof_phase2 = Timer::new("prove_sc_phase_two"); let timer_sc_proof_phase2 = Timer::new("prove_sc_phase_two");
// combine the three claims into a single claim // combine the three claims into a single claim
@ -203,7 +206,7 @@ impl R1CSProof {
}; };
// another instance of the sum-check protocol // another instance of the sum-check protocol
let (sc_proof_phase2, ry, claims_phase2) = R1CSProof::prove_phase_two(
let (sc_proof_phase2, ry, _claims_phase2) = R1CSProof::prove_phase_two(
num_rounds_y, num_rounds_y,
&claim_phase2, &claim_phase2,
&mut DensePolynomial::new(z), &mut DensePolynomial::new(z),
@ -230,91 +233,134 @@ impl R1CSProof {
) )
} }
pub fn verify(
pub fn verify_groth16(
&self, &self,
num_vars: usize, num_vars: usize,
num_cons: usize, num_cons: usize,
input: &[Scalar], input: &[Scalar],
evals: &(Scalar, Scalar, Scalar), evals: &(Scalar, Scalar, Scalar),
transcript: &mut PoseidonTranscript, transcript: &mut PoseidonTranscript,
gens: &R1CSGens,
) -> Result<(Vec<Scalar>, Vec<Scalar>), ProofVerifyError> {
// transcript.append_protocol_name(R1CSProof::protocol_name());
for i in 0..input.len() {
transcript.append_scalar(&input[i]);
}
) -> Result<(u128, u128, u128), ProofVerifyError> {
let c = transcript.challenge_scalar();
let mut input_as_sparse_poly_entries = vec![SparsePolyEntry::new(0, Scalar::one())];
//remaining inputs
input_as_sparse_poly_entries.extend(
(0..input.len())
.map(|i| SparsePolyEntry::new(i + 1, input[i]))
.collect::<Vec<SparsePolyEntry>>(),
);
let n = num_vars; let n = num_vars;
let input_as_sparse_poly =
SparsePolynomial::new(n.log_2() as usize, input_as_sparse_poly_entries);
let config = VerifierConfig {
num_vars: num_vars,
num_cons: num_cons,
input: input.to_vec(),
evals: *evals,
params: poseidon_params(),
prev_challenge: c,
claims_phase2: self.claims_phase2,
polys_sc1: self.sc_proof_phase1.polys.clone(),
polys_sc2: self.sc_proof_phase2.polys.clone(),
eval_vars_at_ry: self.eval_vars_at_ry,
input_as_sparse_poly: input_as_sparse_poly,
};
let (num_rounds_x, num_rounds_y) = (num_cons.log_2(), (2 * num_vars).log_2());
// derive the verifier's challenge tau
let tau = transcript.challenge_vector(num_rounds_x);
// verify the first sum-check instance
let claim_phase1 = Scalar::zero();
let (claim_post_phase1, rx) =
self
.sc_proof_phase1
.verify(claim_phase1, num_rounds_x, 3, transcript)?;
let mut rng = ark_std::test_rng();
// perform the intermediate sum-check test with claimed Az, Bz, and Cz
let (Az_claim, Bz_claim, Cz_claim, prod_Az_Bz_claims) = &self.claims_phase2;
let start = Instant::now();
let circuit = VerifierCircuit::new(&config, &mut rng).unwrap();
let dp1 = start.elapsed().as_millis();
let taus_bound_rx: Scalar = (0..rx.len())
.map(|i| rx[i] * tau[i] + (Scalar::one() - rx[i]) * (Scalar::one() - tau[i]))
.product();
let start = Instant::now();
let (pk, vk) = Groth16::<P>::setup(circuit.clone(), &mut rng).unwrap();
let ds = start.elapsed().as_millis();
let expected_claim_post_phase1 = (*prod_Az_Bz_claims - *Cz_claim) * (taus_bound_rx);
let start = Instant::now();
let proof = Groth16::<P>::prove(&pk, circuit.clone(), &mut rng).unwrap();
let dp2 = start.elapsed().as_millis();
assert_eq!(claim_post_phase1, expected_claim_post_phase1);
let start = Instant::now();
let is_verified = Groth16::<P>::verify(&vk, &[], &proof).unwrap();
let dv = start.elapsed().as_millis();
assert!(is_verified);
// derive three public challenges and then derive a joint claim
let r_A = transcript.challenge_scalar();
let r_B = transcript.challenge_scalar();
let r_C = transcript.challenge_scalar();
Ok((ds, dp1 + dp2, dv))
}
let claim_phase2 = r_A * Az_claim + r_B * Bz_claim + r_C * Cz_claim;
pub fn circuit_size(
&self,
num_vars: usize,
num_cons: usize,
input: &[Scalar],
evals: &(Scalar, Scalar, Scalar),
transcript: &mut PoseidonTranscript,
) -> Result<usize, ProofVerifyError> {
let c = transcript.challenge_scalar();
let mut input_as_sparse_poly_entries = vec![SparsePolyEntry::new(0, Scalar::one())];
//remaining inputs
input_as_sparse_poly_entries.extend(
(0..input.len())
.map(|i| SparsePolyEntry::new(i + 1, input[i]))
.collect::<Vec<SparsePolyEntry>>(),
);
// verify the joint claim with a sum-check protocol
let (claim_post_phase2, ry) =
self
.sc_proof_phase2
.verify(claim_phase2, num_rounds_y, 2, transcript)?;
let poly_input_eval = {
// constant term
let mut input_as_sparse_poly_entries = vec![SparsePolyEntry::new(0, Scalar::one())];
//remaining inputs
input_as_sparse_poly_entries.extend(
(0..input.len())
.map(|i| SparsePolyEntry::new(i + 1, input[i]))
.collect::<Vec<SparsePolyEntry>>(),
);
SparsePolynomial::new(n.log_2(), input_as_sparse_poly_entries).evaluate(&ry[1..])
let n = num_vars;
let input_as_sparse_poly =
SparsePolynomial::new(n.log_2() as usize, input_as_sparse_poly_entries);
let config = VerifierConfig {
num_vars: num_vars,
num_cons: num_cons,
input: input.to_vec(),
evals: *evals,
params: poseidon_params(),
prev_challenge: c,
claims_phase2: self.claims_phase2,
polys_sc1: self.sc_proof_phase1.polys.clone(),
polys_sc2: self.sc_proof_phase2.polys.clone(),
eval_vars_at_ry: self.eval_vars_at_ry,
input_as_sparse_poly: input_as_sparse_poly,
}; };
let eval_Z_at_ry = (Scalar::one() - ry[0]) * self.eval_vars_at_ry + ry[0] * poly_input_eval;
let mut rng = ark_std::test_rng();
let circuit = VerifierCircuit::new(&config, &mut rng).unwrap();
// perform the final check in the second sum-check protocol
let (eval_A_r, eval_B_r, eval_C_r) = evals;
let scalar = r_A * eval_A_r + r_B * eval_B_r + r_C * eval_C_r;
let expected_claim_post_phase2 = eval_Z_at_ry * scalar;
let nc_inner = verify_constraints_inner(circuit.clone(), &num_cons);
assert_eq!(expected_claim_post_phase2, claim_post_phase2);
Ok((rx, ry))
let nc_outer = verify_constraints_outer(circuit.clone(), &num_cons);
Ok(nc_inner + nc_outer)
} }
} }
fn verify_constraints_outer(circuit: VerifierCircuit, _num_cons: &usize) -> usize {
let cs = ConstraintSystem::<Fq>::new_ref();
circuit.generate_constraints(cs.clone()).unwrap();
assert!(cs.is_satisfied().unwrap());
cs.num_constraints()
}
fn verify_constraints_inner(circuit: VerifierCircuit, _num_cons: &usize) -> usize {
let cs = ConstraintSystem::<Fr>::new_ref();
circuit
.inner_circuit
.generate_constraints(cs.clone())
.unwrap();
assert!(cs.is_satisfied().unwrap());
cs.num_constraints()
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::parameters::poseidon_params; use crate::parameters::poseidon_params;
use super::*; use super::*;
use ark_std::UniformRand; use ark_std::UniformRand;
use test::Bencher;
fn produce_tiny_r1cs() -> (R1CSInstance, Vec<Scalar>, Vec<Scalar>) { fn produce_tiny_r1cs() -> (R1CSInstance, Vec<Scalar>, Vec<Scalar>) {
// three constraints over five variables Z1, Z2, Z3, Z4, and Z5 // three constraints over five variables Z1, Z2, Z3, Z4, and Z5
@ -394,39 +440,29 @@ mod tests {
let num_inputs = 10; let num_inputs = 10;
let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
let gens = R1CSGens::new(b"test-m", num_cons, num_vars);
// let gens = R1CSGens::new(b"test-m", num_cons, num_vars);
let params = poseidon_params(); let params = poseidon_params();
let mut random_tape = RandomTape::new(b"proof");
// let mut prover_transcript = PoseidonTranscript::new(&params);
// let mut random_tape = RandomTape::new(b"proof");
let mut prover_transcript = PoseidonTranscript::new(&params); let mut prover_transcript = PoseidonTranscript::new(&params);
let (proof, rx, ry) = R1CSProof::prove(
&inst,
vars,
&input,
&gens,
&mut prover_transcript,
&mut random_tape,
);
let (proof, rx, ry) = R1CSProof::prove(&inst, vars, &input, &mut prover_transcript);
let inst_evals = inst.evaluate(&rx, &ry); let inst_evals = inst.evaluate(&rx, &ry);
// let mut verifier_transcript = PoseidonTranscript::new(&params);
let mut verifier_transcript = PoseidonTranscript::new(&params); let mut verifier_transcript = PoseidonTranscript::new(&params);
// if you want to check the test fails
// input[0] = Scalar::zero();
assert!(proof assert!(proof
.verify(
.verify_groth16(
inst.get_num_vars(), inst.get_num_vars(),
inst.get_num_cons(), inst.get_num_cons(),
&input, &input,
&inst_evals, &inst_evals,
&mut verifier_transcript, &mut verifier_transcript,
&gens,
) )
.is_ok()); .is_ok());
} }
#[bench]
fn bench_r1cs_proof(b: &mut Bencher) {
b.iter(|| check_r1cs_proof());
}
} }

+ 2
- 2
src/random.rs

@ -1,7 +1,7 @@
use super::scalar::Scalar; use super::scalar::Scalar;
use super::transcript::ProofTranscript; use super::transcript::ProofTranscript;
use ark_std::UniformRand;
use merlin::Transcript; use merlin::Transcript;
use ark_std::{UniformRand};
pub struct RandomTape { pub struct RandomTape {
tape: Transcript, tape: Transcript,
@ -10,7 +10,7 @@ pub struct RandomTape {
impl RandomTape { impl RandomTape {
pub fn new(name: &'static [u8]) -> Self { pub fn new(name: &'static [u8]) -> Self {
let tape = { let tape = {
let mut rng = ark_std::rand::thread_rng();
let mut rng = ark_std::rand::thread_rng();
let mut tape = Transcript::new(name); let mut tape = Transcript::new(name);
tape.append_scalar(b"init_randomness", &Scalar::rand(&mut rng)); tape.append_scalar(b"init_randomness", &Scalar::rand(&mut rng));
tape tape

+ 19
- 14
src/sparse_mlpoly.rs

@ -18,8 +18,9 @@ use ark_ff::{Field, One, Zero};
use ark_serialize::*; use ark_serialize::*;
use core::cmp::Ordering; use core::cmp::Ordering;
use merlin::Transcript; use merlin::Transcript;
use serde::Serialize;
#[derive(Debug, CanonicalSerialize, CanonicalDeserialize)]
#[derive(Debug, CanonicalSerialize, CanonicalDeserialize, Clone)]
pub struct SparseMatEntry { pub struct SparseMatEntry {
row: usize, row: usize,
col: usize, col: usize,
@ -32,7 +33,7 @@ impl SparseMatEntry {
} }
} }
#[derive(Debug, CanonicalSerialize, CanonicalDeserialize)]
#[derive(Debug, CanonicalSerialize, CanonicalDeserialize, Clone)]
pub struct SparseMatPolynomial { pub struct SparseMatPolynomial {
num_vars_x: usize, num_vars_x: usize,
num_vars_y: usize, num_vars_y: usize,
@ -100,7 +101,7 @@ impl DerefsEvalProof {
// n-to-1 reduction // n-to-1 reduction
let (r_joint, eval_joint) = { let (r_joint, eval_joint) = {
let challenges = transcript.challenge_vector(evals.len().log2());
let challenges = transcript.challenge_vector(evals.len().log_2());
let mut poly_evals = DensePolynomial::new(evals); let mut poly_evals = DensePolynomial::new(evals);
for i in (0..challenges.len()).rev() { for i in (0..challenges.len()).rev() {
poly_evals.bound_poly_var_bot(&challenges[i]); poly_evals.bound_poly_var_bot(&challenges[i]);
@ -166,7 +167,7 @@ impl DerefsEvalProof {
transcript.append_scalar_vector(&evals); transcript.append_scalar_vector(&evals);
// n-to-1 reduction // n-to-1 reduction
let challenges = transcript.challenge_vector(evals.len().log2());
let challenges = transcript.challenge_vector(evals.len().log_2());
let mut poly_evals = DensePolynomial::new(evals); let mut poly_evals = DensePolynomial::new(evals);
for i in (0..challenges.len()).rev() { for i in (0..challenges.len()).rev() {
poly_evals.bound_poly_var_bot(&challenges[i]); poly_evals.bound_poly_var_bot(&challenges[i]);
@ -794,7 +795,7 @@ impl HashLayerProof {
evals_ops.extend(&eval_val_vec); evals_ops.extend(&eval_val_vec);
evals_ops.resize(evals_ops.len().next_power_of_two(), Scalar::zero()); evals_ops.resize(evals_ops.len().next_power_of_two(), Scalar::zero());
transcript.append_scalar_vector(&evals_ops); transcript.append_scalar_vector(&evals_ops);
let challenges_ops = transcript.challenge_vector(evals_ops.len().log2());
let challenges_ops = transcript.challenge_vector(evals_ops.len().log_2());
let mut poly_evals_ops = DensePolynomial::new(evals_ops); let mut poly_evals_ops = DensePolynomial::new(evals_ops);
for i in (0..challenges_ops.len()).rev() { for i in (0..challenges_ops.len()).rev() {
@ -821,7 +822,7 @@ impl HashLayerProof {
let evals_mem: Vec<Scalar> = vec![eval_row_audit_ts, eval_col_audit_ts]; let evals_mem: Vec<Scalar> = vec![eval_row_audit_ts, eval_col_audit_ts];
// evals_mem.append_to_transcript(b"claim_evals_mem", transcript); // evals_mem.append_to_transcript(b"claim_evals_mem", transcript);
transcript.append_scalar_vector(&evals_mem); transcript.append_scalar_vector(&evals_mem);
let challenges_mem = transcript.challenge_vector(evals_mem.len().log2());
let challenges_mem = transcript.challenge_vector(evals_mem.len().log_2());
let mut poly_evals_mem = DensePolynomial::new(evals_mem); let mut poly_evals_mem = DensePolynomial::new(evals_mem);
for i in (0..challenges_mem.len()).rev() { for i in (0..challenges_mem.len()).rev() {
@ -964,7 +965,7 @@ impl HashLayerProof {
evals_ops.resize(evals_ops.len().next_power_of_two(), Scalar::zero()); evals_ops.resize(evals_ops.len().next_power_of_two(), Scalar::zero());
transcript.append_scalar_vector(&evals_ops); transcript.append_scalar_vector(&evals_ops);
// evals_ops.append_to_transcript(b"claim_evals_ops", transcript); // evals_ops.append_to_transcript(b"claim_evals_ops", transcript);
let challenges_ops = transcript.challenge_vector(evals_ops.len().log2());
let challenges_ops = transcript.challenge_vector(evals_ops.len().log_2());
let mut poly_evals_ops = DensePolynomial::new(evals_ops); let mut poly_evals_ops = DensePolynomial::new(evals_ops);
for i in (0..challenges_ops.len()).rev() { for i in (0..challenges_ops.len()).rev() {
@ -991,7 +992,7 @@ impl HashLayerProof {
let evals_mem: Vec<Scalar> = vec![*eval_row_audit_ts, *eval_col_audit_ts]; let evals_mem: Vec<Scalar> = vec![*eval_row_audit_ts, *eval_col_audit_ts];
// evals_mem.append_to_transcript(b"claim_evals_mem", transcript); // evals_mem.append_to_transcript(b"claim_evals_mem", transcript);
transcript.append_scalar_vector(&evals_mem); transcript.append_scalar_vector(&evals_mem);
let challenges_mem = transcript.challenge_vector(evals_mem.len().log2());
let challenges_mem = transcript.challenge_vector(evals_mem.len().log_2());
let mut poly_evals_mem = DensePolynomial::new(evals_mem); let mut poly_evals_mem = DensePolynomial::new(evals_mem);
for i in (0..challenges_mem.len()).rev() { for i in (0..challenges_mem.len()).rev() {
@ -1596,9 +1597,10 @@ impl SparseMatPolyEvalProof {
} }
} }
#[derive(Clone)]
pub struct SparsePolyEntry { pub struct SparsePolyEntry {
idx: usize,
val: Scalar,
pub idx: usize,
pub val: Scalar,
} }
impl SparsePolyEntry { impl SparsePolyEntry {
@ -1606,10 +1608,10 @@ impl SparsePolyEntry {
SparsePolyEntry { idx, val } SparsePolyEntry { idx, val }
} }
} }
#[derive(Clone)]
pub struct SparsePolynomial { pub struct SparsePolynomial {
num_vars: usize,
Z: Vec<SparsePolyEntry>,
pub num_vars: usize,
pub Z: Vec<SparsePolyEntry>,
} }
impl SparsePolynomial { impl SparsePolynomial {
@ -1617,6 +1619,8 @@ impl SparsePolynomial {
SparsePolynomial { num_vars, Z } SparsePolynomial { num_vars, Z }
} }
// TF IS THIS??
fn compute_chi(a: &[bool], r: &[Scalar]) -> Scalar { fn compute_chi(a: &[bool], r: &[Scalar]) -> Scalar {
assert_eq!(a.len(), r.len()); assert_eq!(a.len(), r.len());
let mut chi_i = Scalar::one(); let mut chi_i = Scalar::one();
@ -1637,6 +1641,7 @@ impl SparsePolynomial {
(0..self.Z.len()) (0..self.Z.len())
.map(|i| { .map(|i| {
let bits = self.Z[i].idx.get_bits(r.len()); let bits = self.Z[i].idx.get_bits(r.len());
println!("{:?}", bits);
SparsePolynomial::compute_chi(&bits, r) * self.Z[i].val SparsePolynomial::compute_chi(&bits, r) * self.Z[i].val
}) })
.sum() .sum()
@ -1645,7 +1650,7 @@ impl SparsePolynomial {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{commitments::MultiCommitGens, parameters::poseidon_params};
use crate::parameters::poseidon_params;
use super::*; use super::*;
use ark_std::UniformRand; use ark_std::UniformRand;

+ 24
- 30
src/sumcheck.rs

@ -2,32 +2,26 @@
#![allow(clippy::type_complexity)] #![allow(clippy::type_complexity)]
use crate::poseidon_transcript::{AppendToPoseidon, PoseidonTranscript}; use crate::poseidon_transcript::{AppendToPoseidon, PoseidonTranscript};
use super::commitments::{Commitments, MultiCommitGens};
use super::dense_mlpoly::DensePolynomial; use super::dense_mlpoly::DensePolynomial;
use super::errors::ProofVerifyError; use super::errors::ProofVerifyError;
use super::group::{
CompressGroupElement, CompressedGroup, DecompressGroupElement, GroupElement,
VartimeMultiscalarMul,
};
use super::nizk::DotProductProof;
use super::random::RandomTape;
use super::scalar::Scalar; use super::scalar::Scalar;
use super::transcript::{AppendToTranscript, ProofTranscript};
use super::unipoly::{CompressedUniPoly, UniPoly};
use ark_ff::{One, Zero};
use super::transcript::ProofTranscript;
use super::unipoly::UniPoly;
use ark_ff::Zero;
use ark_serialize::*; use ark_serialize::*;
use core::iter;
use itertools::izip; use itertools::izip;
use merlin::Transcript;
#[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] #[derive(CanonicalSerialize, CanonicalDeserialize, Debug)]
pub struct SumcheckInstanceProof { pub struct SumcheckInstanceProof {
compressed_polys: Vec<CompressedUniPoly>,
pub polys: Vec<UniPoly>,
} }
impl SumcheckInstanceProof { impl SumcheckInstanceProof {
pub fn new(compressed_polys: Vec<CompressedUniPoly>) -> SumcheckInstanceProof {
SumcheckInstanceProof { compressed_polys }
pub fn new(polys: Vec<UniPoly>) -> SumcheckInstanceProof {
SumcheckInstanceProof { polys }
} }
pub fn verify( pub fn verify(
@ -41,14 +35,14 @@ impl SumcheckInstanceProof {
let mut r: Vec<Scalar> = Vec::new(); let mut r: Vec<Scalar> = Vec::new();
// verify that there is a univariate polynomial for each round // verify that there is a univariate polynomial for each round
assert_eq!(self.compressed_polys.len(), num_rounds);
for i in 0..self.compressed_polys.len() {
let poly = self.compressed_polys[i].decompress(&e);
assert_eq!(self.polys.len(), num_rounds);
for i in 0..self.polys.len() {
let poly = self.polys[i].clone();
// verify degree bound // verify degree bound
assert_eq!(poly.degree(), degree_bound); assert_eq!(poly.degree(), degree_bound);
// check if G_k(0) + G_k(1) = e // check if G_k(0) + G_k(1) = e
assert_eq!(poly.eval_at_zero() + poly.eval_at_one(), e); assert_eq!(poly.eval_at_zero() + poly.eval_at_one(), e);
// append the prover's message to the transcript // append the prover's message to the transcript
@ -202,8 +196,8 @@ impl SumcheckInstanceProof {
{ {
let mut e = *claim; let mut e = *claim;
let mut r: Vec<Scalar> = Vec::new(); let mut r: Vec<Scalar> = Vec::new();
let mut cubic_polys: Vec<CompressedUniPoly> = Vec::new();
for j in 0..num_rounds {
let mut cubic_polys: Vec<UniPoly> = Vec::new();
for _j in 0..num_rounds {
let mut eval_point_0 = Scalar::zero(); let mut eval_point_0 = Scalar::zero();
let mut eval_point_2 = Scalar::zero(); let mut eval_point_2 = Scalar::zero();
let mut eval_point_3 = Scalar::zero(); let mut eval_point_3 = Scalar::zero();
@ -256,7 +250,7 @@ impl SumcheckInstanceProof {
poly_C.bound_poly_var_top(&r_j); poly_C.bound_poly_var_top(&r_j);
e = poly.evaluate(&r_j); e = poly.evaluate(&r_j);
cubic_polys.push(poly.compress());
cubic_polys.push(poly);
} }
( (
SumcheckInstanceProof::new(cubic_polys), SumcheckInstanceProof::new(cubic_polys),
@ -278,7 +272,7 @@ impl SumcheckInstanceProof {
{ {
let mut e = *claim; let mut e = *claim;
let mut r: Vec<Scalar> = Vec::new(); let mut r: Vec<Scalar> = Vec::new();
let mut cubic_polys: Vec<CompressedUniPoly> = Vec::new();
let mut cubic_polys: Vec<UniPoly> = Vec::new();
for _j in 0..num_rounds { for _j in 0..num_rounds {
let mut eval_point_0 = Scalar::zero(); let mut eval_point_0 = Scalar::zero();
let mut eval_point_2 = Scalar::zero(); let mut eval_point_2 = Scalar::zero();
@ -325,7 +319,7 @@ impl SumcheckInstanceProof {
poly_B.bound_poly_var_top(&r_j); poly_B.bound_poly_var_top(&r_j);
poly_C.bound_poly_var_top(&r_j); poly_C.bound_poly_var_top(&r_j);
e = poly.evaluate(&r_j); e = poly.evaluate(&r_j);
cubic_polys.push(poly.compress());
cubic_polys.push(poly);
} }
( (
@ -366,7 +360,7 @@ impl SumcheckInstanceProof {
//let (poly_A_vec_seq, poly_B_vec_seq, poly_C_vec_seq) = poly_vec_seq; //let (poly_A_vec_seq, poly_B_vec_seq, poly_C_vec_seq) = poly_vec_seq;
let mut e = *claim; let mut e = *claim;
let mut r: Vec<Scalar> = Vec::new(); let mut r: Vec<Scalar> = Vec::new();
let mut cubic_polys: Vec<CompressedUniPoly> = Vec::new();
let mut cubic_polys: Vec<UniPoly> = Vec::new();
for _j in 0..num_rounds { for _j in 0..num_rounds {
let mut evals: Vec<(Scalar, Scalar, Scalar)> = Vec::new(); let mut evals: Vec<(Scalar, Scalar, Scalar)> = Vec::new();
@ -477,7 +471,7 @@ impl SumcheckInstanceProof {
} }
e = poly.evaluate(&r_j); e = poly.evaluate(&r_j);
cubic_polys.push(poly.compress());
cubic_polys.push(poly);
} }
let poly_A_par_final = (0..poly_A_vec_par.len()) let poly_A_par_final = (0..poly_A_vec_par.len())
@ -520,9 +514,9 @@ impl SumcheckInstanceProof {
{ {
let mut e = *claim; let mut e = *claim;
let mut r: Vec<Scalar> = Vec::new(); let mut r: Vec<Scalar> = Vec::new();
let mut quad_polys: Vec<CompressedUniPoly> = Vec::new();
let mut quad_polys: Vec<UniPoly> = Vec::new();
for j in 0..num_rounds {
for _j in 0..num_rounds {
let mut eval_point_0 = Scalar::zero(); let mut eval_point_0 = Scalar::zero();
let mut eval_point_2 = Scalar::zero(); let mut eval_point_2 = Scalar::zero();
@ -551,7 +545,7 @@ impl SumcheckInstanceProof {
poly_A.bound_poly_var_top(&r_j); poly_A.bound_poly_var_top(&r_j);
poly_B.bound_poly_var_top(&r_j); poly_B.bound_poly_var_top(&r_j);
e = poly.evaluate(&r_j); e = poly.evaluate(&r_j);
quad_polys.push(poly.compress());
quad_polys.push(poly);
} }
( (
@ -586,7 +580,7 @@ impl SumcheckInstanceProof {
// let mut comm_claim_per_round = claim_per_round.commit(blind_claim, gens_1).compress(); // let mut comm_claim_per_round = claim_per_round.commit(blind_claim, gens_1).compress();
// let mut r: Vec<Scalar> = Vec::new(); // let mut r: Vec<Scalar> = Vec::new();
// let mut comm_polys: Vec<CompressedGroup> = Vec::new();
// let mut comm_polys: Vec<Group> = Vec::new();
// let mut comm_evals: Vec<CompressedGroup> = Vec::new(); // let mut comm_evals: Vec<CompressedGroup> = Vec::new();
// let mut proofs: Vec<DotProductProof> = Vec::new(); // let mut proofs: Vec<DotProductProof> = Vec::new();

+ 3
- 3
src/transcript.rs

@ -1,8 +1,8 @@
use crate::group::CompressedGroup;
use super::scalar::Scalar; use super::scalar::Scalar;
use crate::group::CompressedGroup;
use ark_ff::{BigInteger, PrimeField};
use ark_serialize::CanonicalSerialize;
use merlin::Transcript; use merlin::Transcript;
use ark_ff::{PrimeField, BigInteger};
use ark_serialize::{CanonicalSerialize};
pub trait ProofTranscript { pub trait ProofTranscript {
fn append_protocol_name(&mut self, protocol_name: &'static [u8]); fn append_protocol_name(&mut self, protocol_name: &'static [u8]);

+ 7
- 4
src/unipoly.rs

@ -4,21 +4,22 @@ use super::commitments::{Commitments, MultiCommitGens};
use super::group::GroupElement; use super::group::GroupElement;
use super::scalar::Scalar; use super::scalar::Scalar;
use super::transcript::{AppendToTranscript, ProofTranscript}; use super::transcript::{AppendToTranscript, ProofTranscript};
use ark_ff::{Field, One, Zero};
use ark_ff::Field;
use ark_serialize::*; use ark_serialize::*;
use merlin::Transcript; use merlin::Transcript;
// ax^2 + bx + c stored as vec![c,b,a] // ax^2 + bx + c stored as vec![c,b,a]
// ax^3 + bx^2 + cx + d stored as vec![d,c,b,a] // ax^3 + bx^2 + cx + d stored as vec![d,c,b,a]
#[derive(Debug)]
#[derive(Debug, CanonicalDeserialize, CanonicalSerialize, Clone)]
pub struct UniPoly { pub struct UniPoly {
coeffs: Vec<Scalar>,
pub coeffs: Vec<Scalar>,
// pub coeffs_fq: Vec<Fq>,
} }
// ax^2 + bx + c stored as vec![c,a] // ax^2 + bx + c stored as vec![c,a]
// ax^3 + bx^2 + cx + d stored as vec![d,b,a] // ax^3 + bx^2 + cx + d stored as vec![d,b,a]
#[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] #[derive(CanonicalSerialize, CanonicalDeserialize, Debug)]
pub struct CompressedUniPoly { pub struct CompressedUniPoly {
coeffs_except_linear_term: Vec<Scalar>,
pub coeffs_except_linear_term: Vec<Scalar>,
} }
impl UniPoly { impl UniPoly {
@ -134,6 +135,8 @@ impl AppendToTranscript for UniPoly {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use ark_ff::One;
use super::*; use super::*;
#[test] #[test]

Loading…
Cancel
Save