halo2_axiom/poly/kzg/multiopen/gwc/
prover.rs

1use super::{construct_intermediate_sets, ChallengeV, Query};
2use crate::arithmetic::{kate_division, powers};
3use crate::helpers::SerdeCurveAffine;
4use crate::poly::commitment::ParamsProver;
5use crate::poly::commitment::Prover;
6use crate::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG};
7use crate::poly::query::ProverQuery;
8use crate::poly::{commitment::Blind, Polynomial};
9use crate::transcript::{EncodedChallenge, TranscriptWrite};
10
11use group::Curve;
12use pairing::Engine;
13use rand_core::RngCore;
14use std::fmt::Debug;
15use std::io;
16use std::marker::PhantomData;
17
18/// Concrete KZG prover with GWC variant
19#[derive(Debug)]
20pub struct ProverGWC<'params, E: Engine> {
21    params: &'params ParamsKZG<E>,
22}
23
24/// Create a multi-opening proof
25impl<'params, E: Engine + Debug> Prover<'params, KZGCommitmentScheme<E>> for ProverGWC<'params, E>
26where
27    E::G1Affine: SerdeCurveAffine<ScalarExt = E::Fr, CurveExt = E::G1>,
28    E::G2Affine: SerdeCurveAffine,
29{
30    const QUERY_INSTANCE: bool = false;
31
32    fn new(params: &'params ParamsKZG<E>) -> Self {
33        Self { params }
34    }
35
36    /// Create a multi-opening proof
37    fn create_proof<
38        'com,
39        Ch: EncodedChallenge<E::G1Affine>,
40        T: TranscriptWrite<E::G1Affine, Ch>,
41        R,
42        I,
43    >(
44        &self,
45        _: R,
46        transcript: &mut T,
47        queries: I,
48    ) -> io::Result<()>
49    where
50        I: IntoIterator<Item = ProverQuery<'com, E::G1Affine>> + Clone,
51        R: RngCore,
52    {
53        let v: ChallengeV<_> = transcript.squeeze_challenge_scalar();
54        let commitment_data = construct_intermediate_sets(queries).ok_or_else(|| {
55            io::Error::new(
56                io::ErrorKind::InvalidInput,
57                "queries iterator contains mismatching evaluations",
58            )
59        })?;
60
61        for commitment_at_a_point in commitment_data.iter() {
62            let z = commitment_at_a_point.point;
63            let (poly_batch, eval_batch) = commitment_at_a_point
64                .queries
65                .iter()
66                .zip(powers(*v))
67                .map(|(query, power_of_v)| {
68                    assert_eq!(query.get_point(), z);
69
70                    let poly = query.get_commitment().poly;
71                    let eval = query.get_eval();
72
73                    (poly.clone() * power_of_v, eval * power_of_v)
74                })
75                .reduce(|(poly_acc, eval_acc), (poly, eval)| (poly_acc + &poly, eval_acc + eval))
76                .unwrap();
77
78            let poly_batch = &poly_batch - eval_batch;
79            let witness_poly = Polynomial {
80                values: kate_division(&poly_batch.values, z),
81                _marker: PhantomData,
82            };
83            let w = self
84                .params
85                .commit(&witness_poly, Blind::default())
86                .to_affine();
87
88            transcript.write_point(w)?;
89        }
90        Ok(())
91    }
92}