mirror of
https://github.com/arnaucube/testudo.git
synced 2026-01-12 16:51:28 +01:00
@@ -115,41 +115,6 @@ impl EqPolynomial {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConstPolynomial {
|
||||
num_vars: usize,
|
||||
c: Scalar,
|
||||
}
|
||||
|
||||
impl ConstPolynomial {
|
||||
pub fn new(num_vars: usize, c: Scalar) -> Self {
|
||||
ConstPolynomial { num_vars, c }
|
||||
}
|
||||
|
||||
pub fn evaluate(&self, rx: &Vec<Scalar>) -> Scalar {
|
||||
assert_eq!(self.num_vars, rx.len());
|
||||
self.c
|
||||
}
|
||||
|
||||
pub fn get_num_vars(&self) -> usize {
|
||||
self.num_vars
|
||||
}
|
||||
|
||||
/// produces a binding commitment
|
||||
pub fn commit(&self, gens: &PolyCommitmentGens) -> PolyCommitment {
|
||||
let ell = self.get_num_vars();
|
||||
|
||||
let (left_num_vars, right_num_vars) = EqPolynomial::compute_factored_lens(ell);
|
||||
let L_size = left_num_vars.pow2();
|
||||
let R_size = right_num_vars.pow2();
|
||||
assert_eq!(L_size * R_size, ell.pow2());
|
||||
|
||||
let vec = vec![self.c; R_size];
|
||||
|
||||
let c = vec.commit(&Scalar::zero(), &gens.gens.gens_n).compress();
|
||||
PolyCommitment { C: vec![c; L_size] }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IdentityPolynomial {
|
||||
size_point: usize,
|
||||
}
|
||||
@@ -456,48 +421,6 @@ impl PolyEvalProof {
|
||||
.verify(R.len(), &gens.gens, transcript, &R, &C_LZ, C_Zr)
|
||||
}
|
||||
|
||||
pub fn verify_batched(
|
||||
&self,
|
||||
gens: &PolyCommitmentGens,
|
||||
transcript: &mut Transcript,
|
||||
r: &Vec<Scalar>, // point at which the polynomial is evaluated
|
||||
C_Zr: &CompressedGroup, // commitment to \widetilde{Z}(r)
|
||||
comm: &[&PolyCommitment],
|
||||
coeff: &[&Scalar],
|
||||
) -> Result<(), ProofVerifyError> {
|
||||
transcript.append_protocol_name(PolyEvalProof::protocol_name());
|
||||
|
||||
// compute L and R
|
||||
let eq = EqPolynomial::new(r.to_vec());
|
||||
let (L, R) = eq.compute_factored_evals();
|
||||
|
||||
// compute a weighted sum of commitments and L
|
||||
let C_decompressed: Vec<Vec<GroupElement>> = (0..comm.len())
|
||||
.map(|i| {
|
||||
comm[i]
|
||||
.C
|
||||
.iter()
|
||||
.map(|pt| pt.decompress().unwrap())
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let C_LZ: Vec<GroupElement> = (0..comm.len())
|
||||
.map(|i| GroupElement::vartime_multiscalar_mul(&L, &C_decompressed[i]))
|
||||
.collect();
|
||||
|
||||
let C_LZ_combined: GroupElement = (0..C_LZ.len()).map(|i| C_LZ[i] * coeff[i]).sum();
|
||||
|
||||
self.proof.verify(
|
||||
R.len(),
|
||||
&gens.gens,
|
||||
transcript,
|
||||
&R,
|
||||
&C_LZ_combined.compress(),
|
||||
C_Zr,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn verify_plain(
|
||||
&self,
|
||||
gens: &PolyCommitmentGens,
|
||||
@@ -511,23 +434,6 @@ impl PolyEvalProof {
|
||||
|
||||
self.verify(gens, transcript, r, &C_Zr, comm)
|
||||
}
|
||||
|
||||
pub fn verify_plain_batched(
|
||||
&self,
|
||||
gens: &PolyCommitmentGens,
|
||||
transcript: &mut Transcript,
|
||||
r: &Vec<Scalar>, // point at which the polynomial is evaluated
|
||||
Zr: &Scalar, // evaluation \widetilde{Z}(r)
|
||||
comm: &[&PolyCommitment],
|
||||
coeff: &[&Scalar],
|
||||
) -> Result<(), ProofVerifyError> {
|
||||
// compute a commitment to Zr with a blind of zero
|
||||
let C_Zr = Zr.commit(&Scalar::zero(), &gens.gens.gens_1).compress();
|
||||
|
||||
assert_eq!(comm.len(), coeff.len());
|
||||
|
||||
self.verify_batched(gens, transcript, r, &C_Zr, comm, coeff)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
20
src/lib.rs
20
src/lib.rs
@@ -11,20 +11,20 @@ extern crate rayon;
|
||||
extern crate sha3;
|
||||
extern crate test;
|
||||
|
||||
pub mod commitments;
|
||||
pub mod dense_mlpoly;
|
||||
mod commitments;
|
||||
mod dense_mlpoly;
|
||||
mod errors;
|
||||
mod group;
|
||||
pub mod math;
|
||||
pub mod nizk;
|
||||
mod math;
|
||||
mod nizk;
|
||||
mod product_tree;
|
||||
pub mod r1csinstance;
|
||||
pub mod r1csproof;
|
||||
pub mod random;
|
||||
pub mod scalar;
|
||||
pub mod sparse_mlpoly;
|
||||
mod r1csproof;
|
||||
mod random;
|
||||
mod scalar;
|
||||
mod sparse_mlpoly;
|
||||
pub mod spartan;
|
||||
pub mod sumcheck;
|
||||
mod sumcheck;
|
||||
pub mod timer;
|
||||
pub mod transcript;
|
||||
mod transcript;
|
||||
mod unipoly;
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
#![allow(non_snake_case)]
|
||||
extern crate flate2;
|
||||
extern crate libspartan;
|
||||
extern crate merlin;
|
||||
extern crate rand;
|
||||
|
||||
use flate2::{write::ZlibEncoder, Compression};
|
||||
use libspartan::math::Math;
|
||||
use libspartan::r1csinstance::{R1CSCommitmentGens, R1CSInstance};
|
||||
use libspartan::r1csproof::R1CSGens;
|
||||
use libspartan::spartan::{NIZKGens, SNARKGens, NIZK, SNARK};
|
||||
use libspartan::timer::Timer;
|
||||
use merlin::Transcript;
|
||||
|
||||
pub fn main() {
|
||||
// the list of number of variables (and constraints) in an R1CS instance
|
||||
let inst_sizes = vec![12, 16, 20];
|
||||
|
||||
println!("Profiler:: SNARK");
|
||||
for &s in inst_sizes.iter() {
|
||||
let num_vars = (s as usize).pow2();
|
||||
let num_cons = num_vars;
|
||||
let num_inputs = 10;
|
||||
let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
|
||||
|
||||
Timer::print(&format!("number_of_constraints {}", num_cons));
|
||||
|
||||
let r1cs_size = inst.size();
|
||||
let gens_r1cs_eval = R1CSCommitmentGens::new(&r1cs_size, b"gens_r1cs_eval");
|
||||
|
||||
// create a commitment to R1CSInstance
|
||||
let timer_encode = Timer::new("SNARK::encode");
|
||||
let (comm, decomm) = SNARK::encode(&inst, &gens_r1cs_eval);
|
||||
timer_encode.stop();
|
||||
|
||||
let gens_r1cs_sat = R1CSGens::new(num_cons, num_vars, b"gens_r1cs_sat");
|
||||
let gens = SNARKGens::new(gens_r1cs_sat, gens_r1cs_eval);
|
||||
|
||||
// produce a proof of satisfiability
|
||||
let timer_prove = Timer::new("SNARK::prove");
|
||||
let mut prover_transcript = Transcript::new(b"example");
|
||||
let proof = SNARK::prove(&inst, &decomm, vars, &input, &gens, &mut prover_transcript);
|
||||
timer_prove.stop();
|
||||
|
||||
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
|
||||
bincode::serialize_into(&mut encoder, &proof).unwrap();
|
||||
let proof_encoded = encoder.finish().unwrap();
|
||||
let msg_proof_len = format!("SNARK::proof_compressed_len {:?}", proof_encoded.len());
|
||||
Timer::print(&msg_proof_len);
|
||||
|
||||
// verify the proof of satisfiability
|
||||
let timer_verify = Timer::new("SNARK::verify");
|
||||
let mut verifier_transcript = Transcript::new(b"example");
|
||||
assert!(proof
|
||||
.verify(&comm, &input, &mut verifier_transcript, &gens)
|
||||
.is_ok());
|
||||
timer_verify.stop();
|
||||
|
||||
println!();
|
||||
}
|
||||
|
||||
println!("Profiler:: NIZK");
|
||||
for &s in inst_sizes.iter() {
|
||||
let num_vars = (s as usize).pow2();
|
||||
let num_cons = num_vars;
|
||||
let num_inputs = 10;
|
||||
let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
|
||||
|
||||
Timer::print(&format!("number_of_constraints {}", num_cons));
|
||||
|
||||
let gens_r1cs_sat = R1CSGens::new(num_cons, num_vars, b"gens_r1cs_sat");
|
||||
let gens = NIZKGens::new(gens_r1cs_sat);
|
||||
|
||||
// produce a proof of satisfiability
|
||||
let timer_prove = Timer::new("NIZK::prove");
|
||||
let mut prover_transcript = Transcript::new(b"example");
|
||||
let proof = NIZK::prove(&inst, vars, &input, &gens, &mut prover_transcript);
|
||||
timer_prove.stop();
|
||||
|
||||
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
|
||||
bincode::serialize_into(&mut encoder, &proof).unwrap();
|
||||
let proof_encoded = encoder.finish().unwrap();
|
||||
let msg_proof_len = format!("NIZK::proof_compressed_len {:?}", proof_encoded.len());
|
||||
Timer::print(&msg_proof_len);
|
||||
|
||||
// verify the proof of satisfiability
|
||||
let timer_verify = Timer::new("NIZK::verify");
|
||||
let mut verifier_transcript = Transcript::new(b"example");
|
||||
assert!(proof
|
||||
.verify(&inst, &input, &mut verifier_transcript, &gens)
|
||||
.is_ok());
|
||||
timer_verify.stop();
|
||||
|
||||
println!();
|
||||
}
|
||||
}
|
||||
@@ -25,11 +25,28 @@ pub struct R1CSInstance {
|
||||
}
|
||||
|
||||
pub struct R1CSInstanceSize {
|
||||
num_cons: usize,
|
||||
num_vars: usize,
|
||||
num_inputs: usize,
|
||||
size_A: SparseMatPolynomialSize,
|
||||
size_B: SparseMatPolynomialSize,
|
||||
size_C: SparseMatPolynomialSize,
|
||||
}
|
||||
|
||||
impl R1CSInstanceSize {
|
||||
pub fn get_num_cons(&self) -> usize {
|
||||
self.num_cons
|
||||
}
|
||||
|
||||
pub fn get_num_vars(&self) -> usize {
|
||||
self.num_vars
|
||||
}
|
||||
|
||||
pub fn get_num_inputs(&self) -> usize {
|
||||
self.num_inputs
|
||||
}
|
||||
}
|
||||
|
||||
pub struct R1CSCommitmentGens {
|
||||
gens: SparseMatPolyCommitmentGens,
|
||||
}
|
||||
@@ -124,6 +141,9 @@ impl R1CSInstance {
|
||||
|
||||
pub fn size(&self) -> R1CSInstanceSize {
|
||||
R1CSInstanceSize {
|
||||
num_cons: self.num_cons,
|
||||
num_vars: self.num_vars,
|
||||
num_inputs: self.num_inputs,
|
||||
size_A: self.A.size(),
|
||||
size_B: self.B.size(),
|
||||
size_C: self.C.size(),
|
||||
|
||||
@@ -2,7 +2,7 @@ use super::dense_mlpoly::EqPolynomial;
|
||||
use super::errors::ProofVerifyError;
|
||||
use super::r1csinstance::{
|
||||
R1CSCommitment, R1CSCommitmentGens, R1CSDecommitment, R1CSEvalProof, R1CSInstance,
|
||||
R1CSInstanceEvals,
|
||||
R1CSInstanceEvals, R1CSInstanceSize,
|
||||
};
|
||||
use super::r1csproof::{R1CSGens, R1CSProof};
|
||||
use super::random::RandomTape;
|
||||
@@ -18,7 +18,9 @@ pub struct SNARKGens {
|
||||
}
|
||||
|
||||
impl SNARKGens {
|
||||
pub fn new(gens_r1cs_sat: R1CSGens, gens_r1cs_eval: R1CSCommitmentGens) -> Self {
|
||||
pub fn new(size: &R1CSInstanceSize) -> Self {
|
||||
let gens_r1cs_sat = R1CSGens::new(size.get_num_cons(), size.get_num_vars(), b"gens_r1cs_sat");
|
||||
let gens_r1cs_eval = R1CSCommitmentGens::new(size, b"gens_r1cs_eval");
|
||||
SNARKGens {
|
||||
gens_r1cs_sat,
|
||||
gens_r1cs_eval,
|
||||
@@ -39,11 +41,8 @@ impl SNARK {
|
||||
}
|
||||
|
||||
/// A public computation to create a commitment to an R1CS instance
|
||||
pub fn encode(
|
||||
inst: &R1CSInstance,
|
||||
gens: &R1CSCommitmentGens,
|
||||
) -> (R1CSCommitment, R1CSDecommitment) {
|
||||
inst.commit(gens)
|
||||
pub fn encode(inst: &R1CSInstance, gens: &SNARKGens) -> (R1CSCommitment, R1CSDecommitment) {
|
||||
inst.commit(&gens.gens_r1cs_eval)
|
||||
}
|
||||
|
||||
/// A method to produce a proof of the satisfiability of an R1CS instance
|
||||
@@ -158,7 +157,8 @@ pub struct NIZKGens {
|
||||
}
|
||||
|
||||
impl NIZKGens {
|
||||
pub fn new(gens_r1cs_sat: R1CSGens) -> Self {
|
||||
pub fn new(num_cons: usize, num_vars: usize) -> Self {
|
||||
let gens_r1cs_sat = R1CSGens::new(num_cons, num_vars, b"gens_r1cs_sat");
|
||||
NIZKGens { gens_r1cs_sat }
|
||||
}
|
||||
}
|
||||
@@ -261,19 +261,19 @@ mod tests {
|
||||
let num_cons = num_vars;
|
||||
let num_inputs = 10;
|
||||
let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
|
||||
|
||||
let r1cs_size = inst.size();
|
||||
let gens_r1cs_eval = R1CSCommitmentGens::new(&r1cs_size, b"gens_r1cs_eval");
|
||||
|
||||
// produce public generators
|
||||
let gens = SNARKGens::new(&r1cs_size);
|
||||
|
||||
// create a commitment to R1CSInstance
|
||||
let (comm, decomm) = SNARK::encode(&inst, &gens_r1cs_eval);
|
||||
|
||||
let gens_r1cs_sat = R1CSGens::new(num_cons, num_vars, b"gens_r1cs_sat");
|
||||
let gens = SNARKGens::new(gens_r1cs_sat, gens_r1cs_eval);
|
||||
let (comm, decomm) = SNARK::encode(&inst, &gens);
|
||||
|
||||
// produce a proof
|
||||
let mut prover_transcript = Transcript::new(b"example");
|
||||
let proof = SNARK::prove(&inst, &decomm, vars, &input, &gens, &mut prover_transcript);
|
||||
|
||||
// verify the proof
|
||||
let mut verifier_transcript = Transcript::new(b"example");
|
||||
assert!(proof
|
||||
.verify(&comm, &input, &mut verifier_transcript, &gens)
|
||||
|
||||
131
src/sumcheck.rs
131
src/sumcheck.rs
@@ -176,59 +176,6 @@ impl ZKSumcheckInstanceProof {
|
||||
}
|
||||
|
||||
impl SumcheckInstanceProof {
|
||||
pub fn prove_quad<F>(
|
||||
claim: &Scalar,
|
||||
num_rounds: usize,
|
||||
poly_A: &mut DensePolynomial,
|
||||
poly_B: &mut DensePolynomial,
|
||||
comb_func: F,
|
||||
transcript: &mut Transcript,
|
||||
) -> (Self, Vec<Scalar>, Vec<Scalar>)
|
||||
where
|
||||
F: Fn(&Scalar, &Scalar) -> Scalar,
|
||||
{
|
||||
let mut e = *claim;
|
||||
let mut r: Vec<Scalar> = Vec::new();
|
||||
let mut quad_polys: Vec<CompressedUniPoly> = Vec::new();
|
||||
for _j in 0..num_rounds {
|
||||
let mut eval_point_0 = Scalar::zero();
|
||||
let mut eval_point_2 = Scalar::zero();
|
||||
|
||||
let len = poly_A.len() / 2;
|
||||
for i in 0..len {
|
||||
// eval 0: bound_func is A(low)
|
||||
eval_point_0 = &eval_point_0 + comb_func(&poly_A[i], &poly_B[i]);
|
||||
|
||||
// eval 2: bound_func is -A(low) + 2*A(high)
|
||||
let poly_A_bound_point = &poly_A[len + i] + &poly_A[len + i] - &poly_A[i];
|
||||
let poly_B_bound_point = &poly_B[len + i] + &poly_B[len + i] - &poly_B[i];
|
||||
eval_point_2 = &eval_point_2 + comb_func(&poly_A_bound_point, &poly_B_bound_point);
|
||||
}
|
||||
|
||||
let evals = vec![eval_point_0, e - eval_point_0, eval_point_2];
|
||||
let poly = UniPoly::from_evals(&evals);
|
||||
|
||||
// append the prover's message to the transcript
|
||||
poly.append_to_transcript(b"poly", transcript);
|
||||
|
||||
//derive the verifier's challenge for the next round
|
||||
let r_j = transcript.challenge_scalar(b"challenge_nextround");
|
||||
r.push(r_j);
|
||||
// bound all tables to the verifier's challenege
|
||||
poly_A.bound_poly_var_top(&r_j);
|
||||
poly_B.bound_poly_var_top(&r_j);
|
||||
|
||||
e = poly.evaluate(&r_j);
|
||||
quad_polys.push(poly.compress());
|
||||
}
|
||||
|
||||
(
|
||||
SumcheckInstanceProof::new(quad_polys),
|
||||
r,
|
||||
vec![poly_A[0], poly_B[0]],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn prove_cubic<F>(
|
||||
claim: &Scalar,
|
||||
num_rounds: usize,
|
||||
@@ -302,84 +249,6 @@ impl SumcheckInstanceProof {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn prove_cubic_with_additive_term<F>(
|
||||
claim: &Scalar,
|
||||
num_rounds: usize,
|
||||
poly_A: &mut DensePolynomial,
|
||||
poly_B: &mut DensePolynomial,
|
||||
poly_C: &mut DensePolynomial,
|
||||
poly_D: &mut DensePolynomial,
|
||||
comb_func: F,
|
||||
transcript: &mut Transcript,
|
||||
) -> (Self, Vec<Scalar>, Vec<Scalar>)
|
||||
where
|
||||
F: Fn(&Scalar, &Scalar, &Scalar, &Scalar) -> Scalar,
|
||||
{
|
||||
let mut e = *claim;
|
||||
let mut r: Vec<Scalar> = Vec::new();
|
||||
let mut cubic_polys: Vec<CompressedUniPoly> = Vec::new();
|
||||
for _j in 0..num_rounds {
|
||||
let mut eval_point_0 = Scalar::zero();
|
||||
let mut eval_point_2 = Scalar::zero();
|
||||
let mut eval_point_3 = Scalar::zero();
|
||||
|
||||
let len = poly_A.len() / 2;
|
||||
for i in 0..len {
|
||||
// eval 0: bound_func is A(low)
|
||||
eval_point_0 = &eval_point_0 + comb_func(&poly_A[i], &poly_B[i], &poly_C[i], &poly_D[i]);
|
||||
|
||||
// eval 2: bound_func is -A(low) + 2*A(high)
|
||||
let poly_A_bound_point = &poly_A[len + i] + &poly_A[len + i] - &poly_A[i];
|
||||
let poly_B_bound_point = &poly_B[len + i] + &poly_B[len + i] - &poly_B[i];
|
||||
let poly_C_bound_point = &poly_C[len + i] + &poly_C[len + i] - &poly_C[i];
|
||||
let poly_D_bound_point = &poly_D[len + i] + &poly_D[len + i] - &poly_D[i];
|
||||
eval_point_2 = &eval_point_2
|
||||
+ comb_func(
|
||||
&poly_A_bound_point,
|
||||
&poly_B_bound_point,
|
||||
&poly_C_bound_point,
|
||||
&poly_D_bound_point,
|
||||
);
|
||||
|
||||
// eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2)
|
||||
let poly_A_bound_point = &poly_A_bound_point + &poly_A[len + i] - &poly_A[i];
|
||||
let poly_B_bound_point = &poly_B_bound_point + &poly_B[len + i] - &poly_B[i];
|
||||
let poly_C_bound_point = &poly_C_bound_point + &poly_C[len + i] - &poly_C[i];
|
||||
let poly_D_bound_point = &poly_D_bound_point + &poly_D[len + i] - &poly_D[i];
|
||||
eval_point_3 = &eval_point_3
|
||||
+ comb_func(
|
||||
&poly_A_bound_point,
|
||||
&poly_B_bound_point,
|
||||
&poly_C_bound_point,
|
||||
&poly_D_bound_point,
|
||||
);
|
||||
}
|
||||
|
||||
let evals = vec![eval_point_0, e - eval_point_0, eval_point_2, eval_point_3];
|
||||
let poly = UniPoly::from_evals(&evals);
|
||||
|
||||
// append the prover's message to the transcript
|
||||
poly.append_to_transcript(b"poly", transcript);
|
||||
|
||||
//derive the verifier's challenge for the next round
|
||||
let r_j = transcript.challenge_scalar(b"challenge_nextround");
|
||||
r.push(r_j);
|
||||
// bound all tables to the verifier's challenege
|
||||
poly_A.bound_poly_var_top(&r_j);
|
||||
poly_B.bound_poly_var_top(&r_j);
|
||||
poly_C.bound_poly_var_top(&r_j);
|
||||
poly_D.bound_poly_var_top(&r_j);
|
||||
e = poly.evaluate(&r_j);
|
||||
cubic_polys.push(poly.compress());
|
||||
}
|
||||
|
||||
(
|
||||
SumcheckInstanceProof::new(cubic_polys),
|
||||
r,
|
||||
vec![poly_A[0], poly_B[0], poly_C[0], poly_D[0]],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn prove_cubic_batched<F>(
|
||||
claim: &Scalar,
|
||||
num_rounds: usize,
|
||||
|
||||
Reference in New Issue
Block a user