refactoring multiple_open

This commit is contained in:
zhenfei
2022-05-31 20:44:24 -04:00
parent ea0f98a49c
commit 9d76c71a0c
8 changed files with 90 additions and 96 deletions

View File

@@ -6,7 +6,6 @@ use ark_poly_commit::kzg10::KZG10;
use ark_std::test_rng;
use ark_std::UniformRand;
use caulk_single_opening::caulk_single_setup;
use caulk_single_opening::multiple_open;
use caulk_single_opening::CaulkTranscript;
use caulk_single_opening::KZGCommit;
use caulk_single_opening::{caulk_single_prove, caulk_single_verify};
@@ -95,7 +94,7 @@ fn main() {
//compute all openings
let now = Instant::now();
let g1_qs = multiple_open(&c_poly, &pp.poly_ck, p);
let g1_qs = KZGCommit::multiple_open(&c_poly, &pp.poly_ck, p);
g1_q = g1_qs[position];
println!("Time to compute all KZG openings {:?}", now.elapsed());
}

View File

@@ -16,6 +16,7 @@ use ark_poly::{EvaluationDomain, GeneralEvaluationDomain};
use ark_std::rand::RngCore;
use ark_std::UniformRand;
use ark_std::{One, Zero};
use std::ops::Neg;
// Structure of opening proofs output by prove.
#[allow(non_snake_case)]
@@ -131,12 +132,7 @@ pub fn caulk_single_verify<E: PairingEngine>(
// check that e( - C + cm, [1]_2) + e( [T]_1, [z]_2 ) + e( [h]_1, [S]_2 ) = 1
let eq1: Vec<(E::G1Prepared, E::G2Prepared)> = vec![
(
(g1_C.mul(-E::Fr::one()) + cm.into_projective())
.into_affine()
.into(),
vk.poly_vk.prepared_h.clone(),
),
((g1_C.neg() + *cm).into(), vk.poly_vk.prepared_h.clone()),
((proof.g1_T).into(), proof.g2_z.into()),
(vk.pedersen_param.h.into(), proof.g2_S.into()),
];
@@ -165,17 +161,7 @@ pub fn caulk_single_verify<E: PairingEngine>(
transcript.append_element(b"t1", &proof.pi_ped.t1);
transcript.append_element(b"t2", &proof.pi_ped.t2);
let vk_unity = VerifierPublicParametersUnity {
poly_vk: vk.poly_vk.clone(),
gxpen: vk.poly_ck_pen,
g1: vk.pedersen_param.g,
g1_x: vk.g1_x,
lagrange_scalars_Vn: vk.lagrange_scalars_Vn.clone(),
poly_prod: vk.poly_prod.clone(),
logN: vk.logN,
domain_Vn: vk.domain_Vn,
powers_of_g2: vk.powers_of_g2.clone(),
};
let vk_unity = VerifierPublicParametersUnity::from(vk);
// Verify that g2_z = [ ax - b ]_1 for (a/b)**N = 1
let check3 = caulk_single_unity_verify(&vk_unity, transcript, &proof.g2_z, &proof.pi_unity);

View File

@@ -50,10 +50,10 @@ fn trim<E: PairingEngine, P: UVPolynomial<E::Fr>>(
if supported_degree == 1 {
supported_degree += 1;
}
let pp = srs.clone();
let powers_of_g = pp.powers_of_g[..=supported_degree].to_vec();
let powers_of_g = srs.powers_of_g[..=supported_degree].to_vec();
let powers_of_gamma_g = (0..=supported_degree)
.map(|i| pp.powers_of_gamma_g[&i])
.map(|i| srs.powers_of_gamma_g[&i])
.collect();
let powers = Powers {
@@ -61,12 +61,12 @@ fn trim<E: PairingEngine, P: UVPolynomial<E::Fr>>(
powers_of_gamma_g: ark_std::borrow::Cow::Owned(powers_of_gamma_g),
};
let vk = VerifierKey {
g: pp.powers_of_g[0],
gamma_g: pp.powers_of_gamma_g[&0],
h: pp.h,
beta_h: pp.beta_h,
prepared_h: pp.prepared_h.clone(),
prepared_beta_h: pp.prepared_beta_h.clone(),
g: srs.powers_of_g[0],
gamma_g: srs.powers_of_gamma_g[&0],
h: srs.h,
beta_h: srs.beta_h,
prepared_h: srs.prepared_h.clone(),
prepared_beta_h: srs.prepared_beta_h.clone(),
};
(powers, vk)
}

View File

@@ -3,7 +3,7 @@ This file includes the Caulk's unity prover and verifier for single openings.
The protocol is described in Figure 2.
*/
use crate::caulk_single_setup::PublicParameters;
use crate::caulk_single_setup::{PublicParameters, VerifierPublicParameters};
use crate::kzg::KZGCommit;
use crate::CaulkTranscript;
use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve};
@@ -69,6 +69,22 @@ impl<E: PairingEngine> From<&PublicParameters<E>> for PublicParametersUnity<E> {
}
}
impl<E: PairingEngine> From<&VerifierPublicParameters<E>> for VerifierPublicParametersUnity<E> {
fn from(vk: &VerifierPublicParameters<E>) -> Self {
Self {
poly_vk: vk.poly_vk.clone(),
gxpen: vk.poly_ck_pen,
g1: vk.pedersen_param.g,
g1_x: vk.g1_x,
lagrange_scalars_Vn: vk.lagrange_scalars_Vn.clone(),
poly_prod: vk.poly_prod.clone(),
logN: vk.logN,
domain_Vn: vk.domain_Vn,
powers_of_g2: vk.powers_of_g2.clone(),
}
}
}
// Prove knowledge of a, b such that g2_z = [ax - b]_2 and a^n = b^n
#[allow(non_snake_case)]
pub fn caulk_single_unity_prove<E: PairingEngine, R: RngCore>(
@@ -185,12 +201,11 @@ pub fn caulk_single_unity_prove<E: PairingEngine, R: RngCore>(
////////////////////////////
// Commit to f(X) and h(X)
////////////////////////////
let (g1_F, _) = KZG10::commit(&pp.poly_ck, &f_poly, None, None).unwrap();
let g1_F: E::G1Affine = g1_F.0;
let (h_hat_com, _) = KZG10::commit(&pp.poly_ck, &h_hat_poly, None, None).unwrap();
let g1_F = KZGCommit::<E>::commit(&pp.poly_ck, &f_poly);
let h_hat_com = KZGCommit::<E>::commit(&pp.poly_ck, &h_hat_poly);
// g1_H is a commitment to h_hat_poly + X^(d-1) z(X)
let g1_H = h_hat_com.0 + (pp.gxd.mul(-*a) + pp.gxpen.mul(*b)).into_affine();
let g1_H = (h_hat_com.into_projective() + pp.gxd.mul(-*a) + pp.gxpen.mul(*b)).into_affine();
////////////////////////////
// alpha = Hash([z]_2, [F]_1, [H]_1)
@@ -392,7 +407,7 @@ pub fn caulk_single_unity_verify<E: PairingEngine>(
),
(
((vk.g1.mul(-rho0 - rho1) + vk.gxpen.mul(-zalpha)).into_affine()).into(),
g2_z.into_projective().into_affine().into(),
(*g2_z).into(),
),
((-g1_q).into(), vk.poly_vk.prepared_beta_h.clone()),
];

View File

@@ -5,16 +5,15 @@ It is useful for preprocessing.
The full algorithm is described here https://github.com/khovratovich/Kate/blob/master/Kate_amortized.pdf
*/
use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{Field, PrimeField};
use ark_poly::univariate::DensePolynomial;
use ark_poly::{EvaluationDomain, GeneralEvaluationDomain, UVPolynomial};
use ark_poly_commit::kzg10::*;
use ark_std::One;
use ark_std::Zero;
use std::vec::Vec;
use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve};
use ark_poly::{EvaluationDomain, GeneralEvaluationDomain, UVPolynomial};
use ark_poly_commit::kzg10::*;
//compute all pre-proofs using DFT
// h_i= c_d[x^{d-i-1}]+c_{d-1}[x^{d-i-2}]+c_{d-2}[x^{d-i-3}]+\cdots + c_{i+2}[x]+c_{i+1}[1]
pub fn compute_h<E: PairingEngine>(
@@ -29,12 +28,14 @@ pub fn compute_h<E: PairingEngine>(
//let now = Instant::now();
//1. x_ext = [[x^(d-1)], [x^{d-2},...,[x],[1], d+2 [0]'s]
let mut x_ext = vec![];
for i in 0..=dom_size - 2 {
x_ext.push(poly_ck.powers_of_g[dom_size - 2 - i].into_projective());
}
let g1inf = poly_ck.powers_of_g[0].mul(fpzero);
x_ext.resize(2 * dom_size, g1inf); //filling 2d+2 neutral elements
let mut x_ext: Vec<E::G1Projective> = poly_ck
.powers_of_g
.iter()
.take(dom_size - 1)
.rev()
.map(|x| x.into_projective())
.collect();
x_ext.resize(2 * dom_size, E::G1Projective::zero()); //filling 2d+2 neutral elements
let y = dft_g1::<E>(&x_ext, p + 1);
//println!("Step 1 computed in {:?}", now.elapsed());
@@ -125,39 +126,6 @@ pub fn dft_opt<E: PairingEngine>(h: &[E::Fr], p: usize) -> Vec<E::Fr> {
xvec
}
//compute all openings to c_poly using a smart formula
pub fn multiple_open<E: PairingEngine>(
c_poly: &DensePolynomial<E::Fr>, //c(X)
poly_ck: &Powers<E>, //SRS
p: usize,
) -> Vec<E::G1Affine> {
let degree = c_poly.coeffs.len() - 1;
let input_domain: GeneralEvaluationDomain<E::Fr> = EvaluationDomain::new(degree).unwrap();
//let now = Instant::now();
let h2 = compute_h(c_poly, poly_ck, p);
//println!("H2 computed in {:?}", now.elapsed());
//assert_eq!(h,h2);
let dom_size = input_domain.size();
assert_eq!(1 << p, dom_size);
assert_eq!(degree + 1, dom_size);
/*let now = Instant::now();
let q = DFTG1(&h,p);
println!("Q computed in {:?}", now.elapsed());*/
//let now = Instant::now();
let q2 = dft_g1::<E>(&h2, p);
//println!("Q2 computed in {:?}", now.elapsed());
//assert_eq!(q,q2);
let mut res: Vec<E::G1Affine> = vec![];
for e in q2.iter() {
res.push(e.into_affine());
}
res
}
//compute idft of size @dom_size over vector of G1 elements
//q_i = (h_0 + h_1w^-i + h_2w^{-2i}+\cdots + h_{dom_size-1}w^{-(dom_size-1)i})/dom_size for 0<= i< dom_size=2^p
pub fn idft_g1<E: PairingEngine>(h: &[E::G1Projective], p: usize) -> Vec<E::G1Projective> {
@@ -194,8 +162,9 @@ pub fn idft_g1<E: PairingEngine>(h: &[E::G1Projective], p: usize) -> Vec<E::G1Pr
#[cfg(test)]
pub mod tests {
use super::*;
use crate::caulk_single_setup::caulk_single_setup;
use crate::multiopen::*;
use crate::KZGCommit;
use ark_bls12_377::Bls12_377;
use ark_bls12_381::Bls12_381;
use ark_ec::PairingEngine;
@@ -395,7 +364,7 @@ pub mod tests {
println!("Multi naive computed in {:?}", now.elapsed());
let now = Instant::now();
let q2 = multiple_open(&c_poly, &pp.poly_ck, p);
let q2 = KZGCommit::multiple_open(&c_poly, &pp.poly_ck, p);
println!("Multi advanced computed in {:?}", now.elapsed());
assert_eq!(q, q2);
}

View File

@@ -7,11 +7,13 @@ This file includes backend tools:
(5) random_field is for generating random field elements
*/
use crate::{compute_h, dft_g1};
use ark_ec::{msm::VariableBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{Field, PrimeField};
use ark_poly::{univariate::DensePolynomial, Polynomial, UVPolynomial};
use ark_poly::{EvaluationDomain, GeneralEvaluationDomain};
use ark_poly_commit::kzg10::*;
use ark_std::rand::RngCore;
use ark_std::{end_timer, start_timer};
use ark_std::{One, Zero};
#[cfg(feature = "parallel")]
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
@@ -36,14 +38,44 @@ pub struct KZGCommit<E: PairingEngine> {
}
impl<E: PairingEngine> KZGCommit<E> {
pub fn commit<R: RngCore>(
powers: &Powers<E>,
polynomial: &DensePolynomial<E::Fr>,
) -> E::G1Affine {
pub fn commit(powers: &Powers<E>, polynomial: &DensePolynomial<E::Fr>) -> E::G1Affine {
let (com, _randomness) = KZG10::<E, _>::commit(powers, polynomial, None, None).unwrap();
com.0
}
// compute all openings to c_poly using a smart formula
// This Code implements an algorithm for calculating n openings of a KZG vector commitment of size n in n log(n) time.
// The algorithm is by Feist and Khovratovich.
// It is useful for preprocessing.
// The full algorithm is described here https://github.com/khovratovich/Kate/blob/master/Kate_amortized.pdf
pub fn multiple_open(
c_poly: &DensePolynomial<E::Fr>, //c(X)
poly_ck: &Powers<E>, //SRS
p: usize,
) -> Vec<E::G1Affine> {
let timer = start_timer!(|| "multiple open");
let degree = c_poly.coeffs.len() - 1;
let input_domain: GeneralEvaluationDomain<E::Fr> = EvaluationDomain::new(degree).unwrap();
let h_timer = start_timer!(|| "compute h");
let h2 = compute_h(c_poly, poly_ck, p);
end_timer!(h_timer);
let dom_size = input_domain.size();
assert_eq!(1 << p, dom_size);
assert_eq!(degree + 1, dom_size);
let dft_timer = start_timer!(|| "G1 dft");
let q2 = dft_g1::<E>(&h2, p);
end_timer!(dft_timer);
let res = E::G1Projective::batch_normalization_into_affine(q2.as_ref());
end_timer!(timer);
res
}
/*
KZG.Open( srs_KZG, f(X), deg, (alpha1, alpha2, ..., alphan) )
returns ([f(alpha1), ..., f(alphan)], pi)
@@ -63,7 +95,7 @@ impl<E: PairingEngine> KZGCommit<E> {
proofs.push(pi);
}
let mut res: E::G1Projective = E::G1Projective::zero(); //default value
let mut res = E::G1Projective::zero(); //default value
for j in 0..points.len() {
let w_j = points[j];

View File

@@ -1,15 +1,15 @@
mod caulk_single;
mod caulk_single_setup;
mod caulk_single_unity;
mod dft;
mod kzg;
mod multiopen;
mod pedersen;
mod transcript;
pub use caulk_single::{caulk_single_prove, caulk_single_verify};
pub use caulk_single_setup::caulk_single_setup;
pub use dft::*;
pub use kzg::KZGCommit;
pub use multiopen::multiple_open;
pub use pedersen::PedersenParam;
pub use transcript::CaulkTranscript;
@@ -17,7 +17,6 @@ pub use transcript::CaulkTranscript;
mod tests {
use crate::caulk_single_setup;
use crate::multiple_open;
use crate::CaulkTranscript;
use crate::KZGCommit;
use crate::{caulk_single_prove, caulk_single_verify};
@@ -97,7 +96,7 @@ mod tests {
}
// compute all openings
{
let g1_qs = multiple_open(&c_poly, &pp.poly_ck, p);
let g1_qs = KZGCommit::multiple_open(&c_poly, &pp.poly_ck, p);
let g1_q = g1_qs[position];
// run the prover

View File

@@ -6,7 +6,6 @@ The protocol is informally described in Appendix A.2, Proof of Opening of a Pede
use crate::CaulkTranscript;
use ark_ec::{AffineCurve, ProjectiveCurve};
use ark_ff::PrimeField;
use ark_std::Zero;
use ark_std::{rand::RngCore, UniformRand};
use std::marker::PhantomData;
@@ -67,11 +66,6 @@ impl<C: AffineCurve> PedersenCommit<C> {
let c = transcript.get_and_append_challenge(b"get c");
// check that R g^(-t1) h^(-t2) cm^(c) = 1
let check = proof.g1_r.into_projective()
+ param.g.mul(-proof.t1)
+ param.h.mul(-proof.t2)
+ cm.mul(c);
check.is_zero()
proof.g1_r.into_projective() + cm.mul(c) == param.g.mul(proof.t1) + param.h.mul(proof.t2)
}
}