1use crate::{
9 prelude::PCSError,
10 univariate_kzg::srs::{
11 UnivariateProverParam, UnivariateUniversalParams, UnivariateVerifierParam,
12 },
13 StructuredReferenceString,
14};
15use ark_ec::{pairing::Pairing, AffineRepr};
16use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
17use ark_std::{format, vec::Vec};
18
19#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
21pub struct Evaluations<C: AffineRepr> {
22 pub evals: Vec<C>,
24}
25
26#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
28pub struct MultilinearUniversalParams<E: Pairing> {
29 pub prover_param: MultilinearProverParam<E>,
31 pub h_mask: Vec<E::G2Affine>,
33}
34
35#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
37pub struct MultilinearProverParam<E: Pairing> {
38 pub num_vars: usize,
40 pub powers_of_g: Vec<Evaluations<E::G1Affine>>,
44 pub g: E::G1Affine,
46 pub h: E::G2Affine,
48}
49
50#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
52pub struct MultilinearVerifierParam<E: Pairing> {
53 pub num_vars: usize,
55 pub g: E::G1Affine,
57 pub h: E::G2Affine,
59 pub h_mask: Vec<E::G2Affine>,
61}
62
63impl<E: Pairing> StructuredReferenceString for MultilinearUniversalParams<E> {
64 type ProverParam = MultilinearProverParam<E>;
65 type VerifierParam = MultilinearVerifierParam<E>;
66
67 fn extract_prover_param(&self, supported_num_vars: usize) -> Self::ProverParam {
69 let to_reduce = self.prover_param.num_vars - supported_num_vars;
70
71 Self::ProverParam {
72 powers_of_g: self.prover_param.powers_of_g[to_reduce..].to_vec(),
73 g: self.prover_param.g,
74 h: self.prover_param.h,
75 num_vars: supported_num_vars,
76 }
77 }
78
79 fn extract_verifier_param(&self, supported_num_vars: usize) -> Self::VerifierParam {
81 let to_reduce = self.prover_param.num_vars - supported_num_vars;
82 Self::VerifierParam {
83 num_vars: supported_num_vars,
84 g: self.prover_param.g,
85 h: self.prover_param.h,
86 h_mask: self.h_mask[to_reduce..].to_vec(),
87 }
88 }
89
90 fn trim(
95 &self,
96 supported_num_vars: usize,
97 ) -> Result<(Self::ProverParam, Self::VerifierParam), PCSError> {
98 if supported_num_vars > self.prover_param.num_vars {
99 return Err(PCSError::InvalidParameters(format!(
100 "SRS does not support target number of vars {supported_num_vars}"
101 )));
102 }
103
104 let to_reduce = self.prover_param.num_vars - supported_num_vars;
105 let ck = Self::ProverParam {
106 powers_of_g: self.prover_param.powers_of_g[to_reduce..].to_vec(),
107 g: self.prover_param.g,
108 h: self.prover_param.h,
109 num_vars: supported_num_vars,
110 };
111 let vk = Self::VerifierParam {
112 num_vars: supported_num_vars,
113 g: self.prover_param.g,
114 h: self.prover_param.h,
115 h_mask: self.h_mask[to_reduce..].to_vec(),
116 };
117 Ok((ck, vk))
118 }
119
120 fn trim_with_verifier_degree(
122 &self,
123 prover_supported_num_vars: usize,
124 _verifier_supported_num_vars: usize,
125 ) -> Result<(Self::ProverParam, Self::VerifierParam), PCSError> {
126 self.trim(prover_supported_num_vars)
127 }
128
129 #[cfg(any(test, feature = "test-srs"))]
130 fn gen_srs_for_testing<R>(rng: &mut R, num_vars: usize) -> Result<Self, PCSError>
131 where
132 R: ark_std::rand::RngCore + ark_std::rand::CryptoRng,
133 {
134 tests::gen_srs_for_testing(rng, num_vars)
135 }
136
137 #[cfg(any(test, feature = "test-srs"))]
139 fn gen_srs_for_testing_with_verifier_degree<R>(
140 rng: &mut R,
141 prover_num_vars: usize,
142 _verifier_num_vars: usize,
143 ) -> Result<Self, PCSError>
144 where
145 R: ark_std::rand::RngCore + ark_std::rand::CryptoRng,
146 {
147 tests::gen_srs_for_testing(rng, prover_num_vars)
148 }
149}
150
151impl<E: Pairing> StructuredReferenceString
154 for (MultilinearUniversalParams<E>, UnivariateUniversalParams<E>)
155{
156 type ProverParam = (MultilinearProverParam<E>, UnivariateProverParam<E>);
157 type VerifierParam = (MultilinearVerifierParam<E>, UnivariateVerifierParam<E>);
158
159 fn trim(
160 &self,
161 supported_degree: usize,
162 ) -> Result<(Self::ProverParam, Self::VerifierParam), PCSError> {
163 let ml_pp = <MultilinearUniversalParams<E> as StructuredReferenceString>::trim(
164 &self.0,
165 supported_degree,
166 )?;
167 let uni_pp = <UnivariateUniversalParams<E> as StructuredReferenceString>::trim(
168 &self.1,
169 supported_degree,
170 )?;
171
172 Ok(((ml_pp.0, uni_pp.0), (ml_pp.1, uni_pp.1)))
173 }
174
175 fn trim_with_verifier_degree(
177 &self,
178 prover_supported_num_vars: usize,
179 _verifier_supported_num_vars: usize,
180 ) -> Result<(Self::ProverParam, Self::VerifierParam), PCSError> {
181 self.trim(prover_supported_num_vars)
182 }
183
184 fn extract_prover_param(&self, supported_degree: usize) -> Self::ProverParam {
185 let ml_prover_param =
186 <MultilinearUniversalParams<E> as StructuredReferenceString>::extract_prover_param(
187 &self.0,
188 supported_degree,
189 );
190 let uni_prover_param =
191 <UnivariateUniversalParams<E> as StructuredReferenceString>::extract_prover_param(
192 &self.1,
193 supported_degree,
194 );
195
196 (ml_prover_param, uni_prover_param)
197 }
198
199 fn extract_verifier_param(&self, supported_degree: usize) -> Self::VerifierParam {
200 let ml_verifier_param =
201 <MultilinearUniversalParams<E> as StructuredReferenceString>::extract_verifier_param(
202 &self.0,
203 supported_degree,
204 );
205 let uni_verifier_param =
206 <UnivariateUniversalParams<E> as StructuredReferenceString>::extract_verifier_param(
207 &self.1,
208 supported_degree,
209 );
210
211 (ml_verifier_param, uni_verifier_param)
212 }
213
214 #[cfg(any(test, feature = "test-srs"))]
215 fn gen_srs_for_testing<R>(rng: &mut R, supported_degree: usize) -> Result<Self, PCSError>
216 where
217 R: ark_std::rand::RngCore + ark_std::rand::CryptoRng,
218 {
219 let ml_pp =
220 <MultilinearUniversalParams<E> as StructuredReferenceString>::gen_srs_for_testing(
221 rng,
222 supported_degree,
223 )?;
224 let uni_pp =
225 <UnivariateUniversalParams<E> as StructuredReferenceString>::gen_srs_for_testing(
226 rng,
227 supported_degree,
228 )?;
229 Ok((ml_pp, uni_pp))
230 }
231
232 #[cfg(any(test, feature = "test-srs"))]
234 fn gen_srs_for_testing_with_verifier_degree<R>(
235 rng: &mut R,
236 prover_num_vars: usize,
237 _verifier_num_vars: usize,
238 ) -> Result<Self, PCSError>
239 where
240 R: ark_std::rand::RngCore + ark_std::rand::CryptoRng,
241 {
242 Self::gen_srs_for_testing(rng, prover_num_vars)
243 }
244}
245
246#[cfg(any(test, feature = "test-srs"))]
247mod tests {
248 use super::*;
249 use crate::multilinear_kzg::util::eq_eval;
250 use ark_ec::{scalar_mul::fixed_base::FixedBase, CurveGroup};
251 use ark_ff::{Field, PrimeField, Zero};
252 use ark_poly::DenseMultilinearExtension;
253 use ark_std::{
254 collections::LinkedList,
255 end_timer,
256 rand::{CryptoRng, RngCore},
257 start_timer,
258 string::ToString,
259 vec, UniformRand,
260 };
261
262 fn remove_dummy_variable<F: Field>(poly: &[F], pad: usize) -> Result<Vec<F>, PCSError> {
264 if pad == 0 {
265 return Ok(poly.to_vec());
266 }
267 if !poly.len().is_power_of_two() {
268 return Err(PCSError::InvalidParameters(
269 "Size of polynomial should be power of two.".to_string(),
270 ));
271 }
272 let nv = ark_std::log2(poly.len()) as usize - pad;
273
274 Ok((0..(1 << nv)).map(|x| poly[x << pad]).collect())
275 }
276
277 fn eq_extension<F: PrimeField>(t: &[F]) -> Vec<DenseMultilinearExtension<F>> {
281 let start = start_timer!(|| "eq extension");
282
283 let dim = t.len();
284 let mut result = Vec::new();
285 for (i, &ti) in t.iter().enumerate().take(dim) {
286 let mut poly = Vec::with_capacity(1 << dim);
287 for x in 0..(1 << dim) {
288 let xi = if x >> i & 1 == 1 { F::one() } else { F::zero() };
289 let ti_xi = ti * xi;
290 poly.push(ti_xi + ti_xi - xi - ti + F::one());
291 }
292 result.push(DenseMultilinearExtension::from_evaluations_vec(dim, poly));
293 }
294
295 end_timer!(start);
296 result
297 }
298
299 pub(crate) fn gen_srs_for_testing<E: Pairing, R: RngCore + CryptoRng>(
300 rng: &mut R,
301 num_vars: usize,
302 ) -> Result<MultilinearUniversalParams<E>, PCSError> {
303 if num_vars == 0 {
304 return Err(PCSError::InvalidParameters(
305 "constant polynomial not supported".to_string(),
306 ));
307 }
308
309 let total_timer = start_timer!(|| "SRS generation");
310
311 let pp_generation_timer = start_timer!(|| "Prover Param generation");
312
313 let g = E::G1::rand(rng);
314 let h = E::G2::rand(rng);
315
316 let mut powers_of_g = Vec::new();
317
318 let t: Vec<_> = (0..num_vars).map(|_| E::ScalarField::rand(rng)).collect();
319 let scalar_bits = E::ScalarField::MODULUS_BIT_SIZE as usize;
320
321 let mut eq: LinkedList<DenseMultilinearExtension<E::ScalarField>> =
322 LinkedList::from_iter(eq_extension(&t));
323 let mut eq_arr = LinkedList::new();
324 let mut base = eq.pop_back().unwrap().evaluations;
325
326 for i in (0..num_vars).rev() {
327 eq_arr.push_front(remove_dummy_variable(&base, i)?);
328 if i != 0 {
329 let mul = eq.pop_back().unwrap().evaluations;
330 base = base
331 .into_iter()
332 .zip(mul.into_iter())
333 .map(|(a, b)| a * b)
334 .collect();
335 }
336 }
337
338 let mut pp_powers = Vec::new();
339 let mut total_scalars = 0;
340 for i in 0..num_vars {
341 let eq = eq_arr.pop_front().unwrap();
342 let pp_k_powers = (0..(1 << (num_vars - i))).map(|x| eq[x]);
343 pp_powers.extend(pp_k_powers);
344 total_scalars += 1 << (num_vars - i);
345 }
346 let window_size = FixedBase::get_mul_window_size(total_scalars);
347 let g_table = FixedBase::get_window_table(scalar_bits, window_size, g);
348
349 let pp_g = E::G1::normalize_batch(&FixedBase::msm(
350 scalar_bits,
351 window_size,
352 &g_table,
353 &pp_powers,
354 ));
355
356 let mut start = 0;
357 for i in 0..num_vars {
358 let size = 1 << (num_vars - i);
359 let pp_k_g = Evaluations {
360 evals: pp_g[start..(start + size)].to_vec(),
361 };
362 let t_eval_0 = eq_eval(&vec![E::ScalarField::zero(); num_vars - i], &t[i..num_vars])?;
364 assert_eq!((g * t_eval_0).into_affine(), pp_k_g.evals[0]);
365
366 powers_of_g.push(pp_k_g);
367 start += size;
368 }
369 let gg = Evaluations {
370 evals: [g.into_affine()].to_vec(),
371 };
372 powers_of_g.push(gg);
373
374 let pp = MultilinearProverParam {
375 num_vars,
376 g: g.into_affine(),
377 h: h.into_affine(),
378 powers_of_g,
379 };
380
381 end_timer!(pp_generation_timer);
382
383 let vp_generation_timer = start_timer!(|| "VP generation");
384 let h_mask = {
385 let window_size = FixedBase::get_mul_window_size(num_vars);
386 let h_table = FixedBase::get_window_table(scalar_bits, window_size, h);
387 E::G2::normalize_batch(&FixedBase::msm(scalar_bits, window_size, &h_table, &t))
388 };
389 end_timer!(vp_generation_timer);
390 end_timer!(total_timer);
391 Ok(MultilinearUniversalParams {
392 prover_param: pp,
393 h_mask,
394 })
395 }
396
397 #[test]
398 fn test_srs_gen() -> Result<(), PCSError> {
399 use ark_bls12_381::Bls12_381;
400 use jf_utils::test_rng;
401 type E = Bls12_381;
402
403 let mut rng = test_rng();
404 for nv in 4..10 {
405 let _ = MultilinearUniversalParams::<E>::gen_srs_for_testing(&mut rng, nv)?;
406 }
407
408 Ok(())
409 }
410}