snark_verifier/pcs/kzg/multiopen/
gwc19.rs
1use crate::{
2 cost::{Cost, CostEstimation},
3 loader::{LoadedScalar, Loader},
4 pcs::{
5 kzg::{KzgAccumulator, KzgAs, KzgSuccinctVerifyingKey},
6 PolynomialCommitmentScheme, Query,
7 },
8 util::{
9 arithmetic::{CurveAffine, MultiMillerLoop, Rotation},
10 msm::Msm,
11 transcript::TranscriptRead,
12 Itertools,
13 },
14 Error,
15};
16
17#[derive(Clone, Debug)]
21pub struct Gwc19;
22
23impl<M, L> PolynomialCommitmentScheme<M::G1Affine, L> for KzgAs<M, Gwc19>
24where
25 M: MultiMillerLoop,
26 M::G1Affine: CurveAffine<ScalarExt = M::Fr, CurveExt = M::G1>,
27 L: Loader<M::G1Affine>,
28{
29 type VerifyingKey = KzgSuccinctVerifyingKey<M::G1Affine>;
30 type Proof = Gwc19Proof<M::G1Affine, L>;
31 type Output = KzgAccumulator<M::G1Affine, L>;
32
33 fn read_proof<T>(
34 _: &Self::VerifyingKey,
35 queries: &[Query<Rotation>],
36 transcript: &mut T,
37 ) -> Result<Self::Proof, Error>
38 where
39 T: TranscriptRead<M::G1Affine, L>,
40 {
41 Gwc19Proof::read(queries, transcript)
42 }
43
44 fn verify(
45 svk: &Self::VerifyingKey,
46 commitments: &[Msm<M::G1Affine, L>],
47 z: &L::LoadedScalar,
48 queries: &[Query<Rotation, L::LoadedScalar>],
49 proof: &Self::Proof,
50 ) -> Result<Self::Output, Error> {
51 let sets = query_sets(queries);
52 let powers_of_u = &proof.u.powers(sets.len());
53 let f = {
54 let powers_of_v = proof.v.powers(sets.iter().map(|set| set.polys.len()).max().unwrap());
55 sets.iter()
56 .map(|set| set.msm(commitments, &powers_of_v))
57 .zip(powers_of_u.iter())
58 .map(|(msm, power_of_u)| msm * power_of_u)
59 .sum::<Msm<_, _>>()
60 };
61 let z_omegas = sets.iter().map(|set| {
62 let loaded_shift = set.loaded_shift.clone();
63 loaded_shift * z
64 });
65
66 let rhs = proof
67 .ws
68 .iter()
69 .zip(powers_of_u.iter())
70 .map(|(w, power_of_u)| Msm::base(w) * power_of_u)
71 .collect_vec();
72 let lhs = f + rhs.iter().zip(z_omegas).map(|(uw, z_omega)| uw.clone() * &z_omega).sum();
73
74 Ok(KzgAccumulator::new(
75 lhs.evaluate(Some(svk.g)),
76 rhs.into_iter().sum::<Msm<_, _>>().evaluate(Some(svk.g)),
77 ))
78 }
79}
80
81#[derive(Clone, Debug)]
83pub struct Gwc19Proof<C, L>
84where
85 C: CurveAffine,
86 L: Loader<C>,
87{
88 v: L::LoadedScalar,
89 ws: Vec<L::LoadedEcPoint>,
90 u: L::LoadedScalar,
91}
92
93impl<C, L> Gwc19Proof<C, L>
94where
95 C: CurveAffine,
96 L: Loader<C>,
97{
98 fn read<T>(queries: &[Query<Rotation>], transcript: &mut T) -> Result<Self, Error>
99 where
100 T: TranscriptRead<C, L>,
101 {
102 let v = transcript.squeeze_challenge();
103 let ws = transcript.read_n_ec_points(query_sets(queries).len())?;
104 let u = transcript.squeeze_challenge();
105 Ok(Gwc19Proof { v, ws, u })
106 }
107}
108
109struct QuerySet<'a, S, T> {
110 shift: S,
111 loaded_shift: T,
112 polys: Vec<usize>,
113 evals: Vec<&'a T>,
114}
115
116impl<'a, S, T> QuerySet<'a, S, T>
117where
118 T: Clone,
119{
120 fn msm<C: CurveAffine, L: Loader<C, LoadedScalar = T>>(
121 &self,
122 commitments: &[Msm<'a, C, L>],
123 powers_of_v: &[L::LoadedScalar],
124 ) -> Msm<C, L>
125 where
126 T: LoadedScalar<C::Scalar>,
127 {
128 self.polys
129 .iter()
130 .zip(self.evals.iter().cloned())
131 .map(|(poly, eval)| {
132 let commitment = commitments[*poly].clone();
133 commitment - Msm::constant(eval.clone())
134 })
135 .zip(powers_of_v.iter())
136 .map(|(msm, power_of_v)| msm * power_of_v)
137 .sum()
138 }
139}
140
141fn query_sets<S, T>(queries: &[Query<S, T>]) -> Vec<QuerySet<S, T>>
142where
143 S: PartialEq + Copy,
144 T: Clone + PartialEq,
145{
146 queries.iter().fold(Vec::new(), |mut sets, query| {
147 if let Some(pos) = sets.iter().position(|set| set.shift == query.shift) {
148 sets[pos].polys.push(query.poly);
149 sets[pos].evals.push(&query.eval);
150 } else {
151 sets.push(QuerySet {
152 shift: query.shift,
153 loaded_shift: query.loaded_shift.clone(),
154 polys: vec![query.poly],
155 evals: vec![&query.eval],
156 });
157 }
158 sets
159 })
160}
161
162impl<M> CostEstimation<M::G1Affine> for KzgAs<M, Gwc19>
163where
164 M: MultiMillerLoop,
165{
166 type Input = Vec<Query<Rotation>>;
167
168 fn estimate_cost(queries: &Vec<Query<Rotation>>) -> Cost {
169 let num_w = query_sets(queries).len();
170 Cost { num_commitment: num_w, num_msm: num_w, ..Default::default() }
171 }
172}