2020-11-13 00:08:08 +00:00
|
|
|
use ff::Field;
|
|
|
|
|
|
2020-10-07 16:20:00 +00:00
|
|
|
use super::super::{
|
2020-11-25 19:26:31 +00:00
|
|
|
commitment::{ChallengeScalar, ChallengeX6, Guard, Params, MSM},
|
2020-10-07 16:20:00 +00:00
|
|
|
Error,
|
|
|
|
|
};
|
2020-10-15 23:01:30 +00:00
|
|
|
use super::{construct_intermediate_sets, Proof, Query, VerifierQuery};
|
2020-11-25 19:26:31 +00:00
|
|
|
use crate::arithmetic::{eval_polynomial, lagrange_interpolate, CurveAffine, FieldExt};
|
2020-10-14 23:35:06 +00:00
|
|
|
use crate::transcript::{Hasher, Transcript};
|
2020-09-29 07:23:41 +00:00
|
|
|
|
2020-10-07 13:57:54 +00:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
struct CommitmentData<C: CurveAffine> {
|
|
|
|
|
set_index: usize,
|
|
|
|
|
point_indices: Vec<usize>,
|
|
|
|
|
evals: Vec<C::Scalar>,
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-13 17:08:03 +00:00
|
|
|
impl<C: CurveAffine> Proof<C> {
|
2020-09-29 07:23:41 +00:00
|
|
|
/// Verify a multi-opening proof
|
2020-10-13 17:08:03 +00:00
|
|
|
pub fn verify<'a, I, HBase: Hasher<C::Base>, HScalar: Hasher<C::Scalar>>(
|
2020-09-29 07:23:41 +00:00
|
|
|
&self,
|
|
|
|
|
params: &'a Params<C>,
|
2020-10-14 23:35:06 +00:00
|
|
|
transcript: &mut Transcript<C, HBase, HScalar>,
|
2020-10-07 16:20:00 +00:00
|
|
|
queries: I,
|
2020-10-09 04:21:06 +00:00
|
|
|
mut msm: MSM<'a, C>,
|
2020-10-07 16:20:00 +00:00
|
|
|
) -> Result<Guard<'a, C>, Error>
|
2020-09-29 07:23:41 +00:00
|
|
|
where
|
2020-10-07 16:20:00 +00:00
|
|
|
I: IntoIterator<Item = VerifierQuery<'a, C>> + Clone,
|
2020-09-29 07:23:41 +00:00
|
|
|
{
|
2020-10-09 04:21:06 +00:00
|
|
|
// Scale the MSM by a random factor to ensure that if the existing MSM
|
|
|
|
|
// has is_zero() == false then this argument won't be able to interfere
|
|
|
|
|
// with it to make it true, with high probability.
|
2020-11-13 00:08:08 +00:00
|
|
|
msm.scale(C::Scalar::rand());
|
2020-10-09 04:21:06 +00:00
|
|
|
|
2020-10-15 23:11:06 +00:00
|
|
|
// Sample x_4 for compressing openings at the same point sets together
|
2020-11-25 19:26:31 +00:00
|
|
|
let x_4 = ChallengeScalar::<_, ()>::get(transcript);
|
2020-09-29 07:23:41 +00:00
|
|
|
|
2020-10-15 23:11:06 +00:00
|
|
|
// Sample a challenge x_5 for keeping the multi-point quotient
|
|
|
|
|
// polynomial terms linearly independent.
|
2020-11-25 19:26:31 +00:00
|
|
|
let x_5 = ChallengeScalar::<_, ()>::get(transcript);
|
2020-10-15 23:11:06 +00:00
|
|
|
|
2020-10-15 23:01:30 +00:00
|
|
|
let (commitment_map, point_sets) = construct_intermediate_sets(queries);
|
2020-10-07 16:20:00 +00:00
|
|
|
|
2020-11-25 19:26:31 +00:00
|
|
|
// Compress the commitments and expected evaluations at x together.
|
2020-09-29 07:23:41 +00:00
|
|
|
// using the challenge x_4
|
2020-10-07 16:20:00 +00:00
|
|
|
let mut q_commitments: Vec<_> = vec![params.empty_msm(); point_sets.len()];
|
2020-10-13 17:08:03 +00:00
|
|
|
|
|
|
|
|
// A vec of vecs of evals. The outer vec corresponds to the point set,
|
|
|
|
|
// while the inner vec corresponds to the points in a particular set.
|
2020-10-16 00:43:41 +00:00
|
|
|
let mut q_eval_sets = Vec::with_capacity(point_sets.len());
|
|
|
|
|
for point_set in point_sets.iter() {
|
|
|
|
|
q_eval_sets.push(vec![C::Scalar::zero(); point_set.len()]);
|
2020-10-07 16:20:00 +00:00
|
|
|
}
|
2020-09-29 07:23:41 +00:00
|
|
|
{
|
2020-10-07 16:20:00 +00:00
|
|
|
let mut accumulate = |set_idx: usize, new_commitment, evals: Vec<C::Scalar>| {
|
2020-11-25 19:26:31 +00:00
|
|
|
q_commitments[set_idx].scale(*x_4);
|
2020-11-12 06:14:01 +00:00
|
|
|
q_commitments[set_idx].append_term(C::Scalar::one(), new_commitment);
|
2020-10-15 20:18:02 +00:00
|
|
|
for (eval, set_eval) in evals.iter().zip(q_eval_sets[set_idx].iter_mut()) {
|
|
|
|
|
*set_eval *= &x_4;
|
|
|
|
|
*set_eval += eval;
|
2020-10-07 16:20:00 +00:00
|
|
|
}
|
2020-09-29 07:23:41 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-13 17:08:03 +00:00
|
|
|
// Each commitment corresponds to evaluations at a set of points.
|
|
|
|
|
// For each set, we collapse each commitment's evals pointwise.
|
2020-10-15 23:01:30 +00:00
|
|
|
for commitment_data in commitment_map.into_iter() {
|
2020-09-29 07:23:41 +00:00
|
|
|
accumulate(
|
2020-10-15 23:01:30 +00:00
|
|
|
commitment_data.set_index, // set_idx,
|
|
|
|
|
*commitment_data.commitment.0, // commitment,
|
|
|
|
|
commitment_data.evals, // evals
|
2020-09-29 07:23:41 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Obtain the commitment to the multi-point quotient polynomial f(X).
|
2020-10-14 23:35:06 +00:00
|
|
|
transcript
|
|
|
|
|
.absorb_point(&self.f_commitment)
|
|
|
|
|
.map_err(|_| Error::SamplingError)?;
|
2020-09-29 07:23:41 +00:00
|
|
|
|
|
|
|
|
// Sample a challenge x_6 for checking that f(X) was committed to
|
|
|
|
|
// correctly.
|
2020-11-25 19:26:31 +00:00
|
|
|
let x_6 = ChallengeX6::get(transcript);
|
2020-09-29 07:23:41 +00:00
|
|
|
|
|
|
|
|
for eval in self.q_evals.iter() {
|
2020-10-14 23:35:06 +00:00
|
|
|
transcript.absorb_scalar(*eval);
|
2020-09-29 07:23:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We can compute the expected msm_eval at x_6 using the q_evals provided
|
|
|
|
|
// by the prover and from x_5
|
2020-10-09 13:34:53 +00:00
|
|
|
let msm_eval = point_sets
|
|
|
|
|
.iter()
|
|
|
|
|
.zip(q_eval_sets.iter())
|
|
|
|
|
.zip(self.q_evals.iter())
|
|
|
|
|
.fold(
|
|
|
|
|
C::Scalar::zero(),
|
|
|
|
|
|msm_eval, ((points, evals), proof_eval)| {
|
|
|
|
|
let r_poly = lagrange_interpolate(points, evals);
|
2020-11-25 19:26:31 +00:00
|
|
|
let r_eval = eval_polynomial(&r_poly, *x_6);
|
2020-10-09 13:34:53 +00:00
|
|
|
let eval = points.iter().fold(*proof_eval - &r_eval, |eval, point| {
|
2020-11-25 19:26:31 +00:00
|
|
|
eval * &(*x_6 - point).invert().unwrap()
|
2020-10-09 13:34:53 +00:00
|
|
|
});
|
|
|
|
|
msm_eval * &x_5 + &eval
|
|
|
|
|
},
|
|
|
|
|
);
|
2020-09-29 07:23:41 +00:00
|
|
|
|
|
|
|
|
// Sample a challenge x_7 that we will use to collapse the openings of
|
|
|
|
|
// the various remaining polynomials at x_6 together.
|
2020-11-25 19:26:31 +00:00
|
|
|
let x_7 = ChallengeScalar::<_, ()>::get(transcript);
|
2020-09-29 07:23:41 +00:00
|
|
|
|
|
|
|
|
// Compute the final commitment that has to be opened
|
|
|
|
|
let mut commitment_msm = params.empty_msm();
|
2020-11-12 06:14:01 +00:00
|
|
|
commitment_msm.append_term(C::Scalar::one(), self.f_commitment);
|
2020-10-16 00:43:41 +00:00
|
|
|
let (commitment_msm, msm_eval) = q_commitments.into_iter().zip(self.q_evals.iter()).fold(
|
2020-10-09 13:34:53 +00:00
|
|
|
(commitment_msm, msm_eval),
|
|
|
|
|
|(mut commitment_msm, msm_eval), (q_commitment, q_eval)| {
|
2020-11-25 19:26:31 +00:00
|
|
|
commitment_msm.scale(*x_7);
|
2020-10-09 13:34:53 +00:00
|
|
|
commitment_msm.add_msm(&q_commitment);
|
2020-10-30 01:21:09 +00:00
|
|
|
(commitment_msm, msm_eval * &x_7 + q_eval)
|
2020-10-09 13:34:53 +00:00
|
|
|
},
|
|
|
|
|
);
|
2020-09-29 07:23:41 +00:00
|
|
|
|
2020-10-07 16:20:00 +00:00
|
|
|
// Verify the opening proof
|
|
|
|
|
self.opening
|
|
|
|
|
.verify(params, msm, transcript, x_6, commitment_msm, msm_eval)
|
2020-09-29 07:23:41 +00:00
|
|
|
}
|
|
|
|
|
}
|
2020-10-07 13:59:55 +00:00
|
|
|
|
2020-10-15 23:01:30 +00:00
|
|
|
#[doc(hidden)]
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
|
pub struct CommitmentPointer<'a, C>(&'a C);
|
2020-10-07 13:59:55 +00:00
|
|
|
|
2020-10-15 23:01:30 +00:00
|
|
|
impl<'a, C> PartialEq for CommitmentPointer<'a, C> {
|
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
|
std::ptr::eq(self.0, other.0)
|
2020-10-07 13:59:55 +00:00
|
|
|
}
|
2020-10-15 23:01:30 +00:00
|
|
|
}
|
2020-10-07 13:59:55 +00:00
|
|
|
|
2020-10-15 23:01:30 +00:00
|
|
|
impl<'a, C: CurveAffine> Query<C::Scalar> for VerifierQuery<'a, C> {
|
|
|
|
|
type Commitment = CommitmentPointer<'a, C>;
|
2020-10-07 13:59:55 +00:00
|
|
|
|
2020-10-15 23:01:30 +00:00
|
|
|
fn get_point(&self) -> C::Scalar {
|
|
|
|
|
self.point
|
2020-10-07 13:59:55 +00:00
|
|
|
}
|
2020-10-15 23:01:30 +00:00
|
|
|
fn get_eval(&self) -> C::Scalar {
|
|
|
|
|
self.eval
|
2020-10-07 13:59:55 +00:00
|
|
|
}
|
2020-10-15 23:01:30 +00:00
|
|
|
fn get_commitment(&self) -> Self::Commitment {
|
|
|
|
|
CommitmentPointer(self.commitment)
|
2020-10-07 13:59:55 +00:00
|
|
|
}
|
|
|
|
|
}
|