Update multiopen APIs to reflect changes made to Transcript APIs

This commit is contained in:
Sean Bowe 2020-12-21 15:59:41 -07:00
parent d30c6b62e4
commit 5be7d9525d
No known key found for this signature in database
GPG key ID: 95684257D8F8B031
3 changed files with 212 additions and 244 deletions

View file

@ -15,6 +15,9 @@ use crate::{
mod prover; mod prover;
mod verifier; mod verifier;
pub use prover::create_proof;
pub use verifier::verify_proof;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
struct X1 {} struct X1 {}
/// Challenge for compressing openings at the same point sets together. /// Challenge for compressing openings at the same point sets together.
@ -36,19 +39,6 @@ struct X4 {}
/// together. /// together.
type ChallengeX4<F> = ChallengeScalar<F, X4>; type ChallengeX4<F> = ChallengeScalar<F, X4>;
/// This is a multi-point opening proof used in the polynomial commitment scheme opening.
#[derive(Debug, Clone)]
pub struct Proof<C: CurveAffine> {
// A vector of evaluations at each set of query points
q_evals: Vec<C::Scalar>,
// Commitment to final polynomial
f_commitment: C,
// Commitment proof
opening: commitment::Proof<C>,
}
/// A polynomial query at a point /// A polynomial query at a point
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ProverQuery<'a, C: CurveAffine> { pub struct ProverQuery<'a, C: CurveAffine> {

View file

@ -1,18 +1,19 @@
use super::super::{ use super::super::{
commitment::{self, Blind, Params}, commitment::{self, Blind, Params},
Coeff, Error, Polynomial, Coeff, Polynomial,
}; };
use super::{ use super::{
construct_intermediate_sets, ChallengeX1, ChallengeX2, ChallengeX3, ChallengeX4, Proof, construct_intermediate_sets, ChallengeX1, ChallengeX2, ChallengeX3, ChallengeX4, ProverQuery,
ProverQuery, Query, Query,
}; };
use crate::arithmetic::{ use crate::arithmetic::{
eval_polynomial, kate_division, lagrange_interpolate, Curve, CurveAffine, FieldExt, eval_polynomial, kate_division, lagrange_interpolate, Curve, CurveAffine, FieldExt,
}; };
use crate::transcript::{Hasher, Transcript}; use crate::transcript::TranscriptWrite;
use ff::Field; use ff::Field;
use std::io::{self, Write};
use std::marker::PhantomData; use std::marker::PhantomData;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -23,16 +24,15 @@ struct CommitmentData<C: CurveAffine> {
evals: Vec<C::Scalar>, evals: Vec<C::Scalar>,
} }
impl<C: CurveAffine> Proof<C> { /// Create a multi-opening proof
/// Create a multi-opening proof pub fn create_proof<'a, I, C: CurveAffine, W: Write, T: TranscriptWrite<W, C>>(
pub fn create<'a, I, HBase: Hasher<C::Base>, HScalar: Hasher<C::Scalar>>(
params: &Params<C>, params: &Params<C>,
transcript: &mut Transcript<C, HBase, HScalar>, transcript: &mut T,
queries: I, queries: I,
) -> Result<Self, Error> ) -> io::Result<()>
where where
I: IntoIterator<Item = ProverQuery<'a, C>> + Clone, I: IntoIterator<Item = ProverQuery<'a, C>> + Clone,
{ {
let x_1 = ChallengeX1::get(transcript); let x_1 = ChallengeX1::get(transcript);
let x_2 = ChallengeX2::get(transcript); let x_2 = ChallengeX2::get(transcript);
@ -65,7 +65,7 @@ impl<C: CurveAffine> Proof<C> {
// Each polynomial is evaluated at a set of points. For each set, // Each polynomial is evaluated at a set of points. For each set,
// we collapse each polynomial's evals pointwise. // we collapse each polynomial's evals pointwise.
for (eval, set_eval) in evals.iter().zip(q_eval_sets[set_idx].iter_mut()) { for (eval, set_eval) in evals.iter().zip(q_eval_sets[set_idx].iter_mut()) {
*set_eval *= &*x_1; *set_eval *= &x_1;
*set_eval += eval; *set_eval += eval;
} }
}; };
@ -107,16 +107,12 @@ impl<C: CurveAffine> Proof<C> {
}) })
.unwrap(); .unwrap();
let mut f_blind = Blind(C::Scalar::rand()); let f_blind = Blind(C::Scalar::rand());
let mut f_commitment = params.commit(&f_poly, f_blind).to_affine(); let f_commitment = params.commit(&f_poly, f_blind).to_affine();
let (opening, q_evals) = loop { transcript.write_point(f_commitment)?;
let mut transcript = transcript.clone();
transcript
.absorb_point(&f_commitment)
.map_err(|_| Error::SamplingError)?;
let x_3 = ChallengeX3::get(&mut transcript); let x_3 = ChallengeX3::get(transcript);
let q_evals: Vec<C::Scalar> = q_polys let q_evals: Vec<C::Scalar> = q_polys
.iter() .iter()
@ -124,37 +120,22 @@ impl<C: CurveAffine> Proof<C> {
.collect(); .collect();
for eval in q_evals.iter() { for eval in q_evals.iter() {
transcript.absorb_scalar(*eval); transcript.write_scalar(*eval)?;
} }
let x_4 = ChallengeX4::get(&mut transcript); let x_4 = ChallengeX4::get(transcript);
let (f_poly, f_blind_try) = q_polys.iter().zip(q_blinds.iter()).fold( let (f_poly, f_blind_try) = q_polys.iter().zip(q_blinds.iter()).fold(
(f_poly.clone(), f_blind), (f_poly.clone(), f_blind),
|(f_poly, f_blind), (poly, blind)| { |(f_poly, f_blind), (poly, blind)| {
( (
f_poly * *x_4 + poly.as_ref().unwrap(), f_poly * *x_4 + poly.as_ref().unwrap(),
Blind((f_blind.0 * &*x_4) + &blind.0), Blind((f_blind.0 * &x_4) + &blind.0),
) )
}, },
); );
if let Ok(opening) = commitment::create_proof(&params, transcript, &f_poly, f_blind_try, *x_3)
commitment::Proof::create(&params, &mut transcript, &f_poly, f_blind_try, *x_3)
{
break (opening, q_evals);
} else {
f_blind += C::Scalar::one();
f_commitment = (f_commitment + params.h).to_affine();
}
};
Ok(Proof {
q_evals,
f_commitment,
opening,
})
}
} }
#[doc(hidden)] #[doc(hidden)]

View file

@ -5,11 +5,13 @@ use super::super::{
Error, Error,
}; };
use super::{ use super::{
construct_intermediate_sets, ChallengeX1, ChallengeX2, ChallengeX3, ChallengeX4, Proof, Query, construct_intermediate_sets, ChallengeX1, ChallengeX2, ChallengeX3, ChallengeX4, Query,
VerifierQuery, VerifierQuery,
}; };
use crate::arithmetic::{eval_polynomial, lagrange_interpolate, CurveAffine, FieldExt}; use crate::arithmetic::{eval_polynomial, lagrange_interpolate, CurveAffine, FieldExt};
use crate::transcript::{Hasher, Transcript}; use crate::transcript::TranscriptRead;
use std::io::Read;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct CommitmentData<C: CurveAffine> { struct CommitmentData<C: CurveAffine> {
@ -18,18 +20,16 @@ struct CommitmentData<C: CurveAffine> {
evals: Vec<C::Scalar>, evals: Vec<C::Scalar>,
} }
impl<C: CurveAffine> Proof<C> { /// Verify a multi-opening proof
/// Verify a multi-opening proof pub fn verify_proof<'a, I, C: CurveAffine, R: Read, T: TranscriptRead<R, C>>(
pub fn verify<'a, I, HBase: Hasher<C::Base>, HScalar: Hasher<C::Scalar>>(
&self,
params: &'a Params<C>, params: &'a Params<C>,
transcript: &mut Transcript<C, HBase, HScalar>, transcript: &mut T,
queries: I, queries: I,
mut msm: MSM<'a, C>, mut msm: MSM<'a, C>,
) -> Result<Guard<'a, C>, Error> ) -> Result<Guard<'a, C>, Error>
where where
I: IntoIterator<Item = VerifierQuery<'a, C>> + Clone, I: IntoIterator<Item = VerifierQuery<'a, C>> + Clone,
{ {
// Scale the MSM by a random factor to ensure that if the existing MSM // 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 // has is_zero() == false then this argument won't be able to interfere
// with it to make it true, with high probability. // with it to make it true, with high probability.
@ -40,7 +40,7 @@ impl<C: CurveAffine> Proof<C> {
// Sample a challenge x_2 for keeping the multi-point quotient // Sample a challenge x_2 for keeping the multi-point quotient
// polynomial terms linearly independent. // polynomial terms linearly independent.
let x_2 = ChallengeX2::<C::Scalar>::get(transcript); let x_2 = ChallengeX2::get(transcript);
let (commitment_map, point_sets) = construct_intermediate_sets(queries); let (commitment_map, point_sets) = construct_intermediate_sets(queries);
@ -59,7 +59,7 @@ impl<C: CurveAffine> Proof<C> {
q_commitments[set_idx].scale(*x_1); q_commitments[set_idx].scale(*x_1);
q_commitments[set_idx].append_term(C::Scalar::one(), new_commitment); q_commitments[set_idx].append_term(C::Scalar::one(), new_commitment);
for (eval, set_eval) in evals.iter().zip(q_eval_sets[set_idx].iter_mut()) { for (eval, set_eval) in evals.iter().zip(q_eval_sets[set_idx].iter_mut()) {
*set_eval *= &*x_1; *set_eval *= &x_1;
*set_eval += eval; *set_eval += eval;
} }
}; };
@ -76,16 +76,15 @@ impl<C: CurveAffine> Proof<C> {
} }
// Obtain the commitment to the multi-point quotient polynomial f(X). // Obtain the commitment to the multi-point quotient polynomial f(X).
transcript let f_commitment = transcript.read_point().map_err(|_| Error::SamplingError)?;
.absorb_point(&self.f_commitment)
.map_err(|_| Error::SamplingError)?;
// Sample a challenge x_3 for checking that f(X) was committed to // Sample a challenge x_3 for checking that f(X) was committed to
// correctly. // correctly.
let x_3 = ChallengeX3::get(transcript); let x_3 = ChallengeX3::get(transcript);
for eval in self.q_evals.iter() { let mut q_evals = Vec::with_capacity(q_eval_sets.len());
transcript.absorb_scalar(*eval); for _ in 0..q_eval_sets.len() {
q_evals.push(transcript.read_scalar().map_err(|_| Error::SamplingError)?);
} }
// We can compute the expected msm_eval at x_3 using the q_evals provided // We can compute the expected msm_eval at x_3 using the q_evals provided
@ -93,7 +92,7 @@ impl<C: CurveAffine> Proof<C> {
let msm_eval = point_sets let msm_eval = point_sets
.iter() .iter()
.zip(q_eval_sets.iter()) .zip(q_eval_sets.iter())
.zip(self.q_evals.iter()) .zip(q_evals.iter())
.fold( .fold(
C::Scalar::zero(), C::Scalar::zero(),
|msm_eval, ((points, evals), proof_eval)| { |msm_eval, ((points, evals), proof_eval)| {
@ -102,7 +101,7 @@ impl<C: CurveAffine> Proof<C> {
let eval = points.iter().fold(*proof_eval - &r_eval, |eval, point| { let eval = points.iter().fold(*proof_eval - &r_eval, |eval, point| {
eval * &(*x_3 - point).invert().unwrap() eval * &(*x_3 - point).invert().unwrap()
}); });
msm_eval * &*x_2 + &eval msm_eval * &x_2 + &eval
}, },
); );
@ -112,20 +111,18 @@ impl<C: CurveAffine> Proof<C> {
// Compute the final commitment that has to be opened // Compute the final commitment that has to be opened
let mut commitment_msm = params.empty_msm(); let mut commitment_msm = params.empty_msm();
commitment_msm.append_term(C::Scalar::one(), self.f_commitment); commitment_msm.append_term(C::Scalar::one(), f_commitment);
let (commitment_msm, msm_eval) = q_commitments.into_iter().zip(self.q_evals.iter()).fold( let (commitment_msm, msm_eval) = q_commitments.into_iter().zip(q_evals.iter()).fold(
(commitment_msm, msm_eval), (commitment_msm, msm_eval),
|(mut commitment_msm, msm_eval), (q_commitment, q_eval)| { |(mut commitment_msm, msm_eval), (q_commitment, q_eval)| {
commitment_msm.scale(*x_4); commitment_msm.scale(*x_4);
commitment_msm.add_msm(&q_commitment); commitment_msm.add_msm(&q_commitment);
(commitment_msm, msm_eval * &*x_4 + q_eval) (commitment_msm, msm_eval * &x_4 + q_eval)
}, },
); );
// Verify the opening proof // Verify the opening proof
self.opening super::commitment::verify_proof(params, msm, transcript, *x_3, commitment_msm, msm_eval)
.verify(params, msm, transcript, *x_3, commitment_msm, msm_eval)
}
} }
#[doc(hidden)] #[doc(hidden)]