mirror of
https://github.com/caulk-crypto/caulk.git
synced 2026-01-08 21:07:56 -05:00
deferring pairing and use pairing-products as final stage
This commit is contained in:
@@ -121,7 +121,7 @@ fn main() {
|
||||
|
||||
let now = Instant::now();
|
||||
for _ in 0..number_of_openings {
|
||||
verify_lookup_proof(&table.c_com, &phi_com, &proof, &unity_proof, &pp);
|
||||
verify_lookup_proof(&table.c_com, &phi_com, &proof, &unity_proof, &pp, &mut rng);
|
||||
}
|
||||
println!(
|
||||
"Time to verify {} times {} multi-openings of table size {:?} = {:?} ",
|
||||
@@ -132,7 +132,7 @@ fn main() {
|
||||
);
|
||||
|
||||
assert!(
|
||||
verify_lookup_proof(&table.c_com, &phi_com, &proof, &unity_proof, &pp),
|
||||
verify_lookup_proof(&table.c_com, &phi_com, &proof, &unity_proof, &pp, &mut rng),
|
||||
"Result does not verify"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -148,7 +148,6 @@ where
|
||||
let input_domain: GeneralEvaluationDomain<F> = EvaluationDomain::new(dom_size).unwrap();
|
||||
let mut l = dom_size / 2;
|
||||
let mut m: usize = 1;
|
||||
let mut dom_fr = F::one();
|
||||
// Stockham FFT
|
||||
let mut xvec = h.to_vec();
|
||||
for _ in 0..p {
|
||||
@@ -165,12 +164,10 @@ where
|
||||
}
|
||||
l /= 2;
|
||||
m *= 2;
|
||||
dom_fr = dom_fr + dom_fr;
|
||||
xvec = xt;
|
||||
}
|
||||
|
||||
let domain_inverse = dom_fr.inverse().unwrap().into_repr();
|
||||
|
||||
let domain_inverse = F::from(1u64 << p).inverse().unwrap().into_repr();
|
||||
let res = xvec.iter().map(|x| x.mul(domain_inverse)).collect();
|
||||
|
||||
end_timer!(timer);
|
||||
@@ -187,7 +184,6 @@ pub fn field_inv_dft<F: PrimeField>(h: &[F], p: usize) -> Vec<F> {
|
||||
let input_domain: GeneralEvaluationDomain<F> = EvaluationDomain::new(dom_size).unwrap();
|
||||
let mut l = dom_size / 2;
|
||||
let mut m: usize = 1;
|
||||
let mut dom_fr = F::one();
|
||||
// Stockham FFT
|
||||
let mut xvec = h.to_vec();
|
||||
for _ in 0..p {
|
||||
@@ -205,11 +201,10 @@ pub fn field_inv_dft<F: PrimeField>(h: &[F], p: usize) -> Vec<F> {
|
||||
}
|
||||
l /= 2;
|
||||
m *= 2;
|
||||
dom_fr = dom_fr + dom_fr;
|
||||
xvec = xt;
|
||||
}
|
||||
|
||||
let domain_inverse = dom_fr.inverse().unwrap();
|
||||
let domain_inverse = F::from(1u64 << p).inverse().unwrap();
|
||||
let res = xvec.iter().map(|&x| x * domain_inverse).collect();
|
||||
|
||||
end_timer!(timer);
|
||||
|
||||
102
src/kzg.rs
102
src/kzg.rs
@@ -241,6 +241,47 @@ impl<E: PairingEngine> KZGCommit<E> {
|
||||
pi: &E::G1Affine, // proof
|
||||
) -> bool {
|
||||
let timer = start_timer!(|| "kzg verify g1");
|
||||
let pairing_inputs = Self::verify_g1_defer_pairing(
|
||||
powers_of_g1,
|
||||
powers_of_g2,
|
||||
c_com,
|
||||
max_deg,
|
||||
points,
|
||||
evals,
|
||||
pi,
|
||||
);
|
||||
|
||||
let pairing_timer = start_timer!(|| "pairing product");
|
||||
let prepared_pairing_inputs = vec![
|
||||
(
|
||||
E::G1Prepared::from(pairing_inputs[0].0.into_affine()),
|
||||
E::G2Prepared::from(pairing_inputs[0].1.into_affine()),
|
||||
),
|
||||
(
|
||||
E::G1Prepared::from(pairing_inputs[1].0.into_affine()),
|
||||
E::G2Prepared::from(pairing_inputs[1].1.into_affine()),
|
||||
),
|
||||
];
|
||||
let res = E::product_of_pairings(prepared_pairing_inputs.iter()).is_one();
|
||||
|
||||
end_timer!(pairing_timer);
|
||||
end_timer!(timer);
|
||||
res
|
||||
}
|
||||
|
||||
// KZG.Verify( srs_KZG, F, deg, (alpha1, alpha2, ..., alphan), (v1, ..., vn), pi
|
||||
// ) Algorithm described in Section 4.6.1, Multiple Openings
|
||||
pub fn verify_g1_defer_pairing(
|
||||
// Verify that @c_com is a commitment to C(X) such that C(x)=z
|
||||
powers_of_g1: &[E::G1Affine], // generator of G1
|
||||
powers_of_g2: &[E::G2Affine], // [1]_2, [x]_2, [x^2]_2, ...
|
||||
c_com: &E::G1Affine, // commitment
|
||||
max_deg: Option<&usize>, // max degree
|
||||
points: &[E::Fr], // x such that eval = C(x)
|
||||
evals: &[E::Fr], // evaluation
|
||||
pi: &E::G1Affine, // proof
|
||||
) -> Vec<(E::G1Projective, E::G2Projective)> {
|
||||
let timer = start_timer!(|| "kzg verify g1 (deferring pairing)");
|
||||
|
||||
// Interpolation set
|
||||
// tau_i(X) = lagrange_tau[i] = polynomial equal to 0 at point[j] for j!= i and
|
||||
@@ -294,18 +335,14 @@ impl<E: PairingEngine> KZGCommit<E> {
|
||||
d += max_deg.unwrap();
|
||||
}
|
||||
|
||||
let pairing_inputs = vec![
|
||||
let res = vec![
|
||||
(
|
||||
E::G1Prepared::from((g1_tau - c_com.into_projective()).into_affine()),
|
||||
E::G2Prepared::from(powers_of_g2[global_max_deg - d]),
|
||||
),
|
||||
(
|
||||
E::G1Prepared::from(*pi),
|
||||
E::G2Prepared::from(g2_z_tau.into_affine()),
|
||||
g1_tau - c_com.into_projective(),
|
||||
powers_of_g2[global_max_deg - d].into_projective(),
|
||||
),
|
||||
(pi.into_projective(), g2_z_tau),
|
||||
];
|
||||
|
||||
let res = E::product_of_pairings(pairing_inputs.iter()).is_one();
|
||||
end_timer!(timer);
|
||||
res
|
||||
}
|
||||
@@ -323,23 +360,50 @@ impl<E: PairingEngine> KZGCommit<E> {
|
||||
pi: &E::G1Affine, // proof
|
||||
) -> bool {
|
||||
let timer = start_timer!(|| "kzg partial verify g1");
|
||||
let pairing_inputs = vec![
|
||||
let pairing_inputs =
|
||||
Self::partial_verify_g1_defer_pairing(srs, c_com, deg_x, point, partial_eval, pi);
|
||||
let pairing_timer = start_timer!(|| "pairing product");
|
||||
let prepared_pairing_inputs = vec![
|
||||
(
|
||||
E::G1Prepared::from(
|
||||
(partial_eval.into_projective() - c_com.into_projective()).into_affine(),
|
||||
),
|
||||
E::G2Prepared::from(srs.g2_powers[0]),
|
||||
E::G1Prepared::from(pairing_inputs[0].0.into_affine()),
|
||||
E::G2Prepared::from(pairing_inputs[0].1.into_affine()),
|
||||
),
|
||||
(
|
||||
E::G1Prepared::from(*pi),
|
||||
E::G2Prepared::from(
|
||||
(srs.g2_powers[deg_x].into_projective() - srs.g2_powers[0].mul(*point))
|
||||
.into_affine(),
|
||||
),
|
||||
E::G1Prepared::from(pairing_inputs[1].0.into_affine()),
|
||||
E::G2Prepared::from(pairing_inputs[1].1.into_affine()),
|
||||
),
|
||||
];
|
||||
|
||||
let res = E::product_of_pairings(pairing_inputs.iter()).is_one();
|
||||
let res = E::product_of_pairings(prepared_pairing_inputs.iter()).is_one();
|
||||
|
||||
end_timer!(pairing_timer);
|
||||
end_timer!(timer);
|
||||
res
|
||||
}
|
||||
|
||||
// KZG.Verify( srs_KZG, F, deg, alpha, F_alpha, pi )
|
||||
// Algorithm described in Section 4.6.2, KZG for Bivariate Polynomials
|
||||
// Be very careful here. Verification is only valid if it is paired with a
|
||||
// degree check.
|
||||
pub fn partial_verify_g1_defer_pairing(
|
||||
srs: &crate::multi::PublicParameters<E>,
|
||||
c_com: &E::G1Affine, // commitment
|
||||
deg_x: usize,
|
||||
point: &E::Fr,
|
||||
partial_eval: &E::G1Affine,
|
||||
pi: &E::G1Affine, // proof
|
||||
) -> Vec<(E::G1Projective, E::G2Projective)> {
|
||||
let timer = start_timer!(|| "kzg partial verify g1 (deferring pairing)");
|
||||
let res = vec![
|
||||
(
|
||||
partial_eval.into_projective() - c_com.into_projective(),
|
||||
srs.g2_powers[0].into_projective(),
|
||||
),
|
||||
(
|
||||
pi.into_projective(),
|
||||
srs.g2_powers[deg_x].into_projective() - srs.g2_powers[0].mul(*point),
|
||||
),
|
||||
];
|
||||
end_timer!(timer);
|
||||
res
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use ark_poly::{
|
||||
GeneralEvaluationDomain, Polynomial, UVPolynomial,
|
||||
};
|
||||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||
use ark_std::{cfg_into_iter, rand::RngCore, One, UniformRand, Zero};
|
||||
use ark_std::{cfg_into_iter, end_timer, rand::RngCore, start_timer, One, UniformRand, Zero};
|
||||
#[cfg(feature = "parallel")]
|
||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||
pub use setup::PublicParameters;
|
||||
@@ -20,10 +20,11 @@ use std::{
|
||||
convert::TryInto,
|
||||
fs::File,
|
||||
io::{Read, Write},
|
||||
ops::MulAssign,
|
||||
time::Instant,
|
||||
vec::Vec,
|
||||
};
|
||||
use unity::{prove_multiunity, verify_multiunity, ProofMultiUnity};
|
||||
use unity::{prove_multiunity, verify_multiunity_defer_pairing, ProofMultiUnity};
|
||||
|
||||
pub struct LookupInstance<C: AffineCurve> {
|
||||
pub c_com: C, // polynomial C(X) that represents a table
|
||||
@@ -150,6 +151,8 @@ pub fn compute_lookup_proof<E: PairingEngine, R: RngCore>(
|
||||
srs: &PublicParameters<E>,
|
||||
rng: &mut R,
|
||||
) -> (LookupProof<E>, ProofMultiUnity<E>) {
|
||||
let timer = start_timer!(|| "lookup proof generation");
|
||||
|
||||
let m = input.positions.len();
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
@@ -269,8 +272,7 @@ pub fn compute_lookup_proof<E: PairingEngine, R: RngCore>(
|
||||
let mut transcript = CaulkTranscript::new();
|
||||
|
||||
// let now = Instant::now();
|
||||
let unity_proof =
|
||||
prove_multiunity(srs, &mut transcript, &u_com, u_vals.clone(), extra_blinder2);
|
||||
let unity_proof = prove_multiunity(srs, &mut transcript, &u_com, &u_vals, extra_blinder2);
|
||||
// println!("Time to prove unity {:?}", now.elapsed());
|
||||
|
||||
// quick test can be uncommented to check if unity proof verifies
|
||||
@@ -437,18 +439,20 @@ pub fn compute_lookup_proof<E: PairingEngine, R: RngCore>(
|
||||
pi2,
|
||||
pi3,
|
||||
};
|
||||
|
||||
end_timer!(timer);
|
||||
(proof, unity_proof)
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn verify_lookup_proof<E: PairingEngine>(
|
||||
pub fn verify_lookup_proof<E: PairingEngine, R: RngCore>(
|
||||
c_com: &E::G1Affine,
|
||||
phi_com: &E::G1Affine,
|
||||
proof: &LookupProof<E>,
|
||||
unity_proof: &ProofMultiUnity<E>,
|
||||
srs: &PublicParameters<E>,
|
||||
rng: &mut R,
|
||||
) -> bool {
|
||||
let timer = start_timer!(|| "lookup proof verification");
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// 1. check unity
|
||||
///////////////////////////////////////////////////////////////////
|
||||
@@ -456,8 +460,8 @@ pub fn verify_lookup_proof<E: PairingEngine>(
|
||||
// hash_input initialised to zero
|
||||
let mut transcript = CaulkTranscript::new();
|
||||
|
||||
let unity_check = verify_multiunity(srs, &mut transcript, &proof.u_com, unity_proof);
|
||||
assert!(unity_check, "failure on unity");
|
||||
let unity_check =
|
||||
verify_multiunity_defer_pairing(srs, &mut transcript, &proof.u_com, unity_proof);
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// 2. Hash outputs to get chi
|
||||
@@ -498,7 +502,7 @@ pub fn verify_lookup_proof<E: PairingEngine>(
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
// KZG.Verify(srs_KZG, [u]_1, deg = bot, alpha, v1, pi1)
|
||||
let check1 = KZGCommit::<E>::verify_g1(
|
||||
let check1 = KZGCommit::<E>::verify_g1_defer_pairing(
|
||||
&srs.poly_ck.powers_of_g,
|
||||
&srs.g2_powers,
|
||||
&proof.u_com,
|
||||
@@ -508,8 +512,6 @@ pub fn verify_lookup_proof<E: PairingEngine>(
|
||||
&proof.pi1,
|
||||
);
|
||||
|
||||
assert!(check1, "failure on pi_1 check");
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// 5. Check pi_2
|
||||
///////////////////////////////////////////////////////////////////
|
||||
@@ -521,7 +523,7 @@ pub fn verify_lookup_proof<E: PairingEngine>(
|
||||
let p1_com = (proof.z_I_com.into_projective() + proof.C_I_com.mul(chi)).into_affine();
|
||||
|
||||
// KZG.Verify(srs_KZG, [P1]_1, deg = bot, v1_id, v2, pi2)
|
||||
let check2 = KZGCommit::<E>::verify_g1(
|
||||
let check2 = KZGCommit::<E>::verify_g1_defer_pairing(
|
||||
&srs.poly_ck.powers_of_g,
|
||||
&srs.g2_powers,
|
||||
&p1_com,
|
||||
@@ -530,7 +532,6 @@ pub fn verify_lookup_proof<E: PairingEngine>(
|
||||
&[proof.v2],
|
||||
&proof.pi2,
|
||||
);
|
||||
assert!(check2, "failure on pi_2 check");
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// 6. Check pi_3
|
||||
@@ -549,7 +550,7 @@ pub fn verify_lookup_proof<E: PairingEngine>(
|
||||
.into_affine();
|
||||
|
||||
// KZG.Verify(srs_KZG, [P2]_1, deg = bot, alpha, 0, pi3)
|
||||
let check3 = KZGCommit::<E>::verify_g1(
|
||||
let check3 = KZGCommit::<E>::verify_g1_defer_pairing(
|
||||
&srs.poly_ck.powers_of_g,
|
||||
&srs.g2_powers,
|
||||
&p2_com,
|
||||
@@ -558,24 +559,58 @@ pub fn verify_lookup_proof<E: PairingEngine>(
|
||||
&[E::Fr::zero()],
|
||||
&proof.pi3,
|
||||
);
|
||||
assert!(check3, "failure on check 3");
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// 7. Check final pairing
|
||||
// 7. prepare final pairing
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
// pairing1 = e([C]_1 - [C_I]_1, [1]_2)
|
||||
let pairing1 = E::pairing(
|
||||
(c_com.into_projective() - proof.C_I_com.into_projective()).into_affine(),
|
||||
srs.g2_powers[0],
|
||||
);
|
||||
let final_pairing = vec![
|
||||
(
|
||||
proof.C_I_com.into_projective() - c_com.into_projective(),
|
||||
srs.g2_powers[0].into_projective(),
|
||||
),
|
||||
(
|
||||
proof.z_I_com.into_projective(),
|
||||
proof.H1_com.into_projective(),
|
||||
),
|
||||
];
|
||||
|
||||
// pairing2 = e([z_I]_1, [H_1]_2)
|
||||
let pairing2 = E::pairing(proof.z_I_com, proof.H1_com);
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// 7. Check pairing products
|
||||
///////////////////////////////////////////////////////////////////
|
||||
let pairing_timer = start_timer!(|| "pairing product");
|
||||
let mut pairing_inputs: Vec<(E::G1Projective, E::G2Projective)> = [
|
||||
unity_check.as_slice(),
|
||||
check1.as_slice(),
|
||||
check2.as_slice(),
|
||||
check3.as_slice(),
|
||||
final_pairing.as_slice(),
|
||||
]
|
||||
.concat();
|
||||
|
||||
assert!(pairing1 == pairing2, "failure on pairing check");
|
||||
let mut zeta = E::Fr::rand(rng);
|
||||
let mut prepared_pairing_inputs = vec![];
|
||||
for i in 0..pairing_inputs.len() / 2 {
|
||||
if i != 0 {
|
||||
pairing_inputs[i * 2].0.mul_assign(zeta);
|
||||
pairing_inputs[i * 2 + 1].0.mul_assign(zeta);
|
||||
}
|
||||
zeta.square_in_place();
|
||||
prepared_pairing_inputs.push((
|
||||
E::G1Prepared::from(pairing_inputs[i * 2].0.into_affine()),
|
||||
E::G2Prepared::from(pairing_inputs[i * 2].1.into_affine()),
|
||||
));
|
||||
prepared_pairing_inputs.push((
|
||||
E::G1Prepared::from(pairing_inputs[i * 2 + 1].0.into_affine()),
|
||||
E::G2Prepared::from(pairing_inputs[i * 2 + 1].1.into_affine()),
|
||||
));
|
||||
}
|
||||
let res = E::product_of_pairings(prepared_pairing_inputs.iter()).is_one();
|
||||
|
||||
true
|
||||
end_timer!(pairing_timer);
|
||||
end_timer!(timer);
|
||||
res
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
@@ -804,7 +839,14 @@ mod tests {
|
||||
compute_lookup_proof::<E, _>(&lookup_instance, &prover_input, &pp, &mut rng);
|
||||
println!("Time to generate proof for = {:?}", now.elapsed());
|
||||
let now = Instant::now();
|
||||
let res = verify_lookup_proof(&table.c_com, &phi_com, &proof, &unity_proof, &pp);
|
||||
let res = verify_lookup_proof(
|
||||
&table.c_com,
|
||||
&phi_com,
|
||||
&proof,
|
||||
&unity_proof,
|
||||
&pp,
|
||||
&mut rng,
|
||||
);
|
||||
println!("Time to verify proof for = {:?}", now.elapsed());
|
||||
assert!(res);
|
||||
println!("Lookup test succeeded");
|
||||
@@ -844,7 +886,7 @@ mod tests {
|
||||
now.elapsed()
|
||||
);
|
||||
let now = Instant::now();
|
||||
let res = verify_lookup_proof(&c_com, &phi_com, &proof, &unity_proof, &srs);
|
||||
let res = verify_lookup_proof(&c_com, &phi_com, &proof, &unity_proof, &srs, &mut rng);
|
||||
println!(
|
||||
"Time to verify proof for n={:?} = {:?}",
|
||||
srs.n,
|
||||
|
||||
@@ -9,7 +9,9 @@ use ark_poly::{
|
||||
univariate::DensePolynomial, EvaluationDomain, Evaluations as EvaluationsOnDomain, Polynomial,
|
||||
UVPolynomial,
|
||||
};
|
||||
use ark_std::{One, Zero};
|
||||
use ark_std::{end_timer, start_timer, One, UniformRand, Zero};
|
||||
use rand::RngCore;
|
||||
use std::ops::MulAssign;
|
||||
|
||||
// output structure of prove_unity
|
||||
pub struct ProofMultiUnity<E: PairingEngine> {
|
||||
@@ -35,43 +37,45 @@ pub fn prove_multiunity<E: PairingEngine>(
|
||||
pp: &PublicParameters<E>,
|
||||
transcript: &mut CaulkTranscript<E::Fr>,
|
||||
g1_u: &E::G1Affine,
|
||||
mut vec_u_evals: Vec<E::Fr>,
|
||||
vec_u_evals: &[E::Fr],
|
||||
u_poly_quotient: DensePolynomial<E::Fr>,
|
||||
) -> ProofMultiUnity<E> {
|
||||
let timer = start_timer!(|| "prove multiunity");
|
||||
// The test_rng is deterministic. Should be replaced with actual random
|
||||
// generator.
|
||||
let rng_arkworks = &mut ark_std::test_rng();
|
||||
|
||||
// let rng_arkworks = &mut ark_std::test_rng();
|
||||
let n = pp.n;
|
||||
let deg_blinders = 11 / n;
|
||||
let z_Vm: DensePolynomial<E::Fr> = pp.domain_m.vanishing_polynomial().into();
|
||||
let mut vec_u_evals = vec_u_evals.to_vec();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 1. Compute polynomials u_s(X) = vec_u_polys[s] such that u_s( nu_i ) =
|
||||
// w_i^{2^s}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
let step1_timer = start_timer!(|| "step 1");
|
||||
let mut vec_u_polys = vec![
|
||||
EvaluationsOnDomain::from_vec_and_domain(vec_u_evals.clone(), pp.domain_m).interpolate()
|
||||
EvaluationsOnDomain::from_vec_and_domain(vec_u_evals.to_vec(), pp.domain_m).interpolate()
|
||||
+ (&z_Vm * &u_poly_quotient),
|
||||
];
|
||||
|
||||
for _ in 1..pp.domain_n.size() {
|
||||
for u_eval in &mut vec_u_evals {
|
||||
for u_eval in vec_u_evals.iter_mut() {
|
||||
*u_eval = u_eval.square();
|
||||
}
|
||||
|
||||
vec_u_polys.push(
|
||||
EvaluationsOnDomain::from_vec_and_domain(vec_u_evals.clone(), pp.domain_m)
|
||||
EvaluationsOnDomain::from_vec_and_domain(vec_u_evals.to_vec(), pp.domain_m)
|
||||
.interpolate()
|
||||
+ (&z_Vm * &DensePolynomial::<E::Fr>::rand(deg_blinders, rng_arkworks)),
|
||||
);
|
||||
}
|
||||
|
||||
end_timer!(step1_timer);
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 2. Compute U_bar(X,Y) = sum_{s= 1}^n u_{s-1} rho_s(Y)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let step2_timer = start_timer!(|| "step 2");
|
||||
// bivariate polynomials such that bipoly_U_bar[j] = a_j(Y) where U_bar(X,Y) =
|
||||
// sum_j X^j a_j(Y)
|
||||
let mut bipoly_U_bar = Vec::new();
|
||||
@@ -85,7 +89,7 @@ pub fn prove_multiunity<E: PairingEngine>(
|
||||
*/
|
||||
let mut temp = DensePolynomial::from_coefficients_slice(&[E::Fr::zero()]);
|
||||
|
||||
for (s, u_poly) in vec_u_polys.iter().enumerate().take(n).skip(1){
|
||||
for (s, u_poly) in vec_u_polys.iter().enumerate().take(n).skip(1) {
|
||||
let u_s_j = DensePolynomial::from_coefficients_slice(&[u_poly[j]]);
|
||||
temp += &(&u_s_j * &pp.lagrange_polynomials_n[s]);
|
||||
}
|
||||
@@ -93,11 +97,11 @@ pub fn prove_multiunity<E: PairingEngine>(
|
||||
// add a_j(X) to U_bar(X,Y)
|
||||
bipoly_U_bar.push(temp);
|
||||
}
|
||||
|
||||
end_timer!(step2_timer);
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 3. Hs(X) = u_{s-1}^2(X) - u_s(X)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let step3_timer = start_timer!(|| "step 3");
|
||||
// id_poly(X) = 1 for omega_m in range and 0 for omega_m not in range.
|
||||
let id_poly = pp.id_poly.clone();
|
||||
|
||||
@@ -118,11 +122,11 @@ pub fn prove_multiunity<E: PairingEngine>(
|
||||
.unwrap();
|
||||
assert!(remainder.is_zero());
|
||||
vec_H_s_polys.push(poly_H_s);
|
||||
|
||||
end_timer!(step3_timer);
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 4. h_2(X,Y) = sum_{s=1}^n rho_s(Y) H_s(X)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let step4_timer = start_timer!(|| "step 4");
|
||||
// h_2[j] = a_j(Y) where h_2(X,Y) = sum_j X^j a_j(Y)
|
||||
let mut bipoly_h_2 = Vec::new();
|
||||
|
||||
@@ -152,25 +156,27 @@ pub fn prove_multiunity<E: PairingEngine>(
|
||||
*coeff += &(&h_s_j * &pp.lagrange_polynomials_n[s]);
|
||||
}
|
||||
}
|
||||
|
||||
end_timer!(step4_timer);
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 5. Commit to U_bar(X^n, X) and h_2(X^n, X)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
let step5_timer = start_timer!(|| "step 5");
|
||||
let g1_u_bar = KZGCommit::<E>::bipoly_commit(pp, &bipoly_U_bar, pp.domain_n.size());
|
||||
let g1_h_2 = KZGCommit::<E>::bipoly_commit(pp, &bipoly_h_2, pp.domain_n.size());
|
||||
|
||||
end_timer!(step5_timer);
|
||||
////////////////////////////
|
||||
// 6. alpha = Hash(g1_u, g1_u_bar, g1_h_2)
|
||||
////////////////////////////
|
||||
let step6_timer = start_timer!(|| "step 6");
|
||||
transcript.append_element(b"u", g1_u);
|
||||
transcript.append_element(b"u_bar", &g1_u_bar);
|
||||
transcript.append_element(b"h2", &g1_h_2);
|
||||
let alpha = transcript.get_and_append_challenge(b"alpha");
|
||||
|
||||
end_timer!(step6_timer);
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 7. Compute h_1(Y)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let step7_timer = start_timer!(|| "step 7");
|
||||
// poly_U_alpha = sum_{s=1}^n u_{s-1}(alpha) rho_s(Y)
|
||||
let mut poly_U_alpha = DensePolynomial::from_coefficients_slice(&[E::Fr::zero()]);
|
||||
|
||||
@@ -192,29 +198,31 @@ pub fn prove_multiunity<E: PairingEngine>(
|
||||
.divide_by_vanishing_poly(pp.domain_n)
|
||||
.unwrap();
|
||||
assert!(remainder.is_zero(), "poly_h_1 does not divide");
|
||||
|
||||
end_timer!(step7_timer);
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 8. Commit to h_1(Y)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
let step8_timer = start_timer!(|| "step 8");
|
||||
assert!(pp.poly_ck.powers_of_g.len() >= poly_h_1.len());
|
||||
let g1_h_1 = VariableBaseMSM::multi_scalar_mul(
|
||||
&pp.poly_ck.powers_of_g,
|
||||
convert_to_bigints(&poly_h_1.coeffs).as_slice(),
|
||||
)
|
||||
.into_affine();
|
||||
|
||||
end_timer!(step8_timer);
|
||||
////////////////////////////
|
||||
// 9. beta = Hash( g1_h_1 )
|
||||
////////////////////////////
|
||||
|
||||
let step9_timer = start_timer!(|| "step 9");
|
||||
transcript.append_element(b"h1", &g1_h_1);
|
||||
let beta = transcript.get_and_append_challenge(b"beta");
|
||||
|
||||
end_timer!(step9_timer);
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 10. Compute p(Y) = (U^2(alpha, beta) - h1(Y) zVn(beta) ) - (u_bar(alpha, beta
|
||||
// sigma^(-1)) + id(alpha) rho_n(Y)) - zVm(alpha )h2(alpha,Y)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let step10_timer = start_timer!(|| "step 10");
|
||||
// p(Y) = U^2(alpha, beta)
|
||||
let u_alpha_beta = poly_U_alpha.evaluate(&beta);
|
||||
let mut poly_p = DensePolynomial::from_coefficients_slice(&[u_alpha_beta.square()]);
|
||||
@@ -259,11 +267,11 @@ pub fn prove_multiunity<E: PairingEngine>(
|
||||
|
||||
// check p(beta) = 0
|
||||
assert!(poly_p.evaluate(&beta) == E::Fr::zero());
|
||||
|
||||
end_timer!(step10_timer);
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 11. Open KZG commitments
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let step11_timer = start_timer!(|| "step 11");
|
||||
// KZG.Open( srs, u(X), deg = bot, X = alpha )
|
||||
let (evals_1, pi_1) = KZGCommit::open_g1_batch(&pp.poly_ck, &vec_u_polys[0], None, &[alpha]);
|
||||
|
||||
@@ -293,7 +301,8 @@ pub fn prove_multiunity<E: PairingEngine>(
|
||||
&[beta],
|
||||
);
|
||||
assert!(evals_3[0] == E::Fr::zero());
|
||||
|
||||
end_timer!(step11_timer);
|
||||
end_timer!(timer);
|
||||
ProofMultiUnity {
|
||||
g1_u_bar,
|
||||
g1_h_1,
|
||||
@@ -314,12 +323,57 @@ pub fn prove_multiunity<E: PairingEngine>(
|
||||
// Verify that the prover knows vec_u_evals such that g1_u = g1^(sum_j u_j
|
||||
// mu_j(x)) and u_j^N = 1
|
||||
#[allow(non_snake_case)]
|
||||
pub fn verify_multiunity<E: PairingEngine>(
|
||||
pub fn verify_multiunity<E: PairingEngine, R: RngCore>(
|
||||
pp: &PublicParameters<E>,
|
||||
transcript: &mut CaulkTranscript<E::Fr>,
|
||||
g1_u: &E::G1Affine,
|
||||
pi_unity: &ProofMultiUnity<E>,
|
||||
rng: &mut R,
|
||||
) -> bool {
|
||||
let timer = start_timer!(|| "verify multiunity");
|
||||
let mut pairing_inputs = verify_multiunity_defer_pairing(pp, transcript, g1_u, pi_unity);
|
||||
assert_eq!(pairing_inputs.len(), 10);
|
||||
|
||||
let pairing_timer = start_timer!(|| "pairing product");
|
||||
let mut zeta = E::Fr::rand(rng);
|
||||
pairing_inputs[2].0.mul_assign(zeta);
|
||||
pairing_inputs[3].0.mul_assign(zeta);
|
||||
zeta.square_in_place();
|
||||
pairing_inputs[4].0.mul_assign(zeta);
|
||||
pairing_inputs[5].0.mul_assign(zeta);
|
||||
zeta.square_in_place();
|
||||
pairing_inputs[6].0.mul_assign(zeta);
|
||||
pairing_inputs[7].0.mul_assign(zeta);
|
||||
zeta.square_in_place();
|
||||
pairing_inputs[8].0.mul_assign(zeta);
|
||||
pairing_inputs[9].0.mul_assign(zeta);
|
||||
|
||||
let prepared_pairing_inputs: Vec<(E::G1Prepared, E::G2Prepared)> = pairing_inputs
|
||||
.iter()
|
||||
.map(|(g1, g2)| {
|
||||
(
|
||||
E::G1Prepared::from(g1.into_affine()),
|
||||
E::G2Prepared::from(g2.into_affine()),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let res = E::product_of_pairings(prepared_pairing_inputs.iter()).is_one();
|
||||
|
||||
end_timer!(pairing_timer);
|
||||
end_timer!(timer);
|
||||
res
|
||||
}
|
||||
|
||||
// Verify that the prover knows vec_u_evals such that g1_u = g1^(sum_j u_j
|
||||
// mu_j(x)) and u_j^N = 1
|
||||
#[allow(non_snake_case)]
|
||||
pub fn verify_multiunity_defer_pairing<E: PairingEngine>(
|
||||
pp: &PublicParameters<E>,
|
||||
transcript: &mut CaulkTranscript<E::Fr>,
|
||||
g1_u: &E::G1Affine,
|
||||
pi_unity: &ProofMultiUnity<E>,
|
||||
) -> Vec<(E::G1Projective, E::G2Projective)> {
|
||||
let timer = start_timer!(|| "verify multiunity (deferring pairing)");
|
||||
////////////////////////////
|
||||
// alpha = Hash(g1_u, g1_u_bar, g1_h_2)
|
||||
////////////////////////////
|
||||
@@ -360,7 +414,7 @@ pub fn verify_multiunity<E: PairingEngine>(
|
||||
// Check the KZG openings
|
||||
////////////////////////////
|
||||
|
||||
let check1 = KZGCommit::<E>::verify_g1(
|
||||
let check1 = KZGCommit::<E>::verify_g1_defer_pairing(
|
||||
&pp.poly_ck.powers_of_g,
|
||||
&pp.g2_powers,
|
||||
g1_u,
|
||||
@@ -369,7 +423,7 @@ pub fn verify_multiunity<E: PairingEngine>(
|
||||
&[pi_unity.v1],
|
||||
&pi_unity.pi_1,
|
||||
);
|
||||
let check2 = KZGCommit::partial_verify_g1(
|
||||
let check2 = KZGCommit::partial_verify_g1_defer_pairing(
|
||||
pp,
|
||||
&pi_unity.g1_u_bar,
|
||||
pp.domain_n.size(),
|
||||
@@ -377,7 +431,7 @@ pub fn verify_multiunity<E: PairingEngine>(
|
||||
&pi_unity.g1_u_bar_alpha,
|
||||
&pi_unity.pi_2,
|
||||
);
|
||||
let check3 = KZGCommit::partial_verify_g1(
|
||||
let check3 = KZGCommit::partial_verify_g1_defer_pairing(
|
||||
pp,
|
||||
&pi_unity.g1_h_2,
|
||||
pp.domain_n.size(),
|
||||
@@ -385,7 +439,7 @@ pub fn verify_multiunity<E: PairingEngine>(
|
||||
&pi_unity.g1_h_2_alpha,
|
||||
&pi_unity.pi_3,
|
||||
);
|
||||
let check4 = KZGCommit::<E>::verify_g1(
|
||||
let check4 = KZGCommit::<E>::verify_g1_defer_pairing(
|
||||
&pp.poly_ck.powers_of_g,
|
||||
&pp.g2_powers,
|
||||
&pi_unity.g1_u_bar_alpha,
|
||||
@@ -394,7 +448,7 @@ pub fn verify_multiunity<E: PairingEngine>(
|
||||
&[E::Fr::zero(), pi_unity.v2, pi_unity.v3],
|
||||
&pi_unity.pi_4,
|
||||
);
|
||||
let check5 = KZGCommit::<E>::verify_g1(
|
||||
let check5 = KZGCommit::<E>::verify_g1_defer_pairing(
|
||||
&pp.poly_ck.powers_of_g,
|
||||
&pp.g2_powers,
|
||||
&g1_P.into_affine(),
|
||||
@@ -404,7 +458,16 @@ pub fn verify_multiunity<E: PairingEngine>(
|
||||
&pi_unity.pi_5,
|
||||
);
|
||||
|
||||
check1 && check2 && check3 && check4 && check5
|
||||
let res = [
|
||||
check1.as_slice(),
|
||||
check2.as_slice(),
|
||||
check3.as_slice(),
|
||||
check4.as_slice(),
|
||||
check5.as_slice(),
|
||||
]
|
||||
.concat();
|
||||
end_timer!(timer);
|
||||
res
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -485,7 +548,7 @@ pub mod tests {
|
||||
&pp,
|
||||
&mut prover_transcript,
|
||||
&g1_u,
|
||||
vec_u_evals.clone(),
|
||||
&vec_u_evals,
|
||||
u_poly_quotient,
|
||||
);
|
||||
|
||||
@@ -495,7 +558,7 @@ pub mod tests {
|
||||
let mut verifier_transcript = CaulkTranscript::new();
|
||||
println!(
|
||||
"unity proof verifies {:?}",
|
||||
verify_multiunity::<E>(&pp, &mut verifier_transcript, &g1_u, &pi_unity)
|
||||
verify_multiunity::<E, _>(&pp, &mut verifier_transcript, &g1_u, &pi_unity, &mut rng)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user