hyperplonk/subroutines/src/pcs/multilinear_kzg/srs.rs
subroutines/src/pcs/multilinear_kzg/srs.rsRaw
1// Copyright (c) 2023 Espresso Systems (espressosys.com)
2// This file is part of the HyperPlonk library.
3
4// You should have received a copy of the MIT License
5// along with the HyperPlonk library. If not, see <https://mit-license.org/>.
6
7//! Implementing Structured Reference Strings for multilinear polynomial KZG
8use crate::pcs::{
9 multilinear_kzg::util::{eq_eval, eq_extension},
10 prelude::PCSError,
11 StructuredReferenceString,
12};
13use ark_ec::{pairing::Pairing, scalar_mul::fixed_base::FixedBase, AffineRepr, CurveGroup};
14use ark_ff::{Field, PrimeField, Zero};
15use ark_poly::DenseMultilinearExtension;
16use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
17use ark_std::{
18 collections::LinkedList, end_timer, format, rand::Rng, start_timer, string::ToString, vec::Vec,
19 UniformRand,
20};
21use core::iter::FromIterator;
22
23/// Evaluations over {0,1}^n for G1 or G2
24#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
25pub struct Evaluations<C: AffineRepr> {
26 /// The evaluations.
27 pub evals: Vec<C>,
28}
29
30/// Universal Parameter
31#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
32pub struct MultilinearUniversalParams<E: Pairing> {
33 /// prover parameters
34 pub prover_param: MultilinearProverParam<E>,
35 /// h^randomness: h^t1, h^t2, ..., **h^{t_nv}**
36 pub h_mask: Vec<E::G2Affine>,
37}
38
39/// Prover Parameters
40#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
41pub struct MultilinearProverParam<E: Pairing> {
42 /// number of variables
43 pub num_vars: usize,
44 /// `pp_{0}`, `pp_{1}`, ...,pp_{nu_vars} defined
45 /// by XZZPD19 where pp_{nv-0}=g and
46 /// pp_{nv-i}=g^{eq((t_1,..t_i),(X_1,..X_i))}
47 pub powers_of_g: Vec<Evaluations<E::G1Affine>>,
48 /// generator for G1
49 pub g: E::G1Affine,
50 /// generator for G2
51 pub h: E::G2Affine,
52}
53
54/// Verifier Parameters
55#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
56pub struct MultilinearVerifierParam<E: Pairing> {
57 /// number of variables
58 pub num_vars: usize,
59 /// generator of G1
60 pub g: E::G1Affine,
61 /// generator of G2
62 pub h: E::G2Affine,
63 /// h^randomness: h^t1, h^t2, ..., **h^{t_nv}**
64 pub h_mask: Vec<E::G2Affine>,
65}
66
67impl<E: Pairing> StructuredReferenceString<E> for MultilinearUniversalParams<E> {
68 type ProverParam = MultilinearProverParam<E>;
69 type VerifierParam = MultilinearVerifierParam<E>;
70
71 /// Extract the prover parameters from the public parameters.
72 fn extract_prover_param(&self, supported_num_vars: usize) -> Self::ProverParam {
73 let to_reduce = self.prover_param.num_vars - supported_num_vars;
74
75 Self::ProverParam {
76 powers_of_g: self.prover_param.powers_of_g[to_reduce..].to_vec(),
77 g: self.prover_param.g,
78 h: self.prover_param.h,
79 num_vars: supported_num_vars,
80 }
81 }
82
83 /// Extract the verifier parameters from the public parameters.
84 fn extract_verifier_param(&self, supported_num_vars: usize) -> Self::VerifierParam {
85 let to_reduce = self.prover_param.num_vars - supported_num_vars;
86 Self::VerifierParam {
87 num_vars: supported_num_vars,
88 g: self.prover_param.g,
89 h: self.prover_param.h,
90 h_mask: self.h_mask[to_reduce..].to_vec(),
91 }
92 }
93
94 /// Trim the universal parameters to specialize the public parameters
95 /// for multilinear polynomials to the given `supported_num_vars`, and
96 /// returns committer key and verifier key. `supported_num_vars` should
97 /// be in range `1..=params.num_vars`
98 fn trim(
99 &self,
100 supported_num_vars: usize,
101 ) -> Result<(Self::ProverParam, Self::VerifierParam), PCSError> {
102 if supported_num_vars > self.prover_param.num_vars {
103 return Err(PCSError::InvalidParameters(format!(
104 "SRS does not support target number of vars {}",
105 supported_num_vars
106 )));
107 }
108
109 let to_reduce = self.prover_param.num_vars - supported_num_vars;
110 let ck = Self::ProverParam {
111 powers_of_g: self.prover_param.powers_of_g[to_reduce..].to_vec(),
112 g: self.prover_param.g,
113 h: self.prover_param.h,
114 num_vars: supported_num_vars,
115 };
116 let vk = Self::VerifierParam {
117 num_vars: supported_num_vars,
118 g: self.prover_param.g,
119 h: self.prover_param.h,
120 h_mask: self.h_mask[to_reduce..].to_vec(),
121 };
122 Ok((ck, vk))
123 }
124
125 /// Build SRS for testing.
126 /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY.
127 /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION.
128 fn gen_srs_for_testing<R: Rng>(rng: &mut R, num_vars: usize) -> Result<Self, PCSError> {
129 if num_vars == 0 {
130 return Err(PCSError::InvalidParameters(
131 "constant polynomial not supported".to_string(),
132 ));
133 }
134
135 let total_timer = start_timer!(|| "SRS generation");
136
137 let pp_generation_timer = start_timer!(|| "Prover Param generation");
138
139 let g = E::G1::rand(rng);
140 let h = E::G2::rand(rng);
141
142 let mut powers_of_g = Vec::new();
143
144 let t: Vec<_> = (0..num_vars).map(|_| E::ScalarField::rand(rng)).collect();
145 let scalar_bits = E::ScalarField::MODULUS_BIT_SIZE as usize;
146
147 let mut eq: LinkedList<DenseMultilinearExtension<E::ScalarField>> =
148 LinkedList::from_iter(eq_extension(&t).into_iter());
149 let mut eq_arr = LinkedList::new();
150 let mut base = eq.pop_back().unwrap().evaluations;
151
152 for i in (0..num_vars).rev() {
153 eq_arr.push_front(remove_dummy_variable(&base, i)?);
154 if i != 0 {
155 let mul = eq.pop_back().unwrap().evaluations;
156 base = base
157 .into_iter()
158 .zip(mul.into_iter())
159 .map(|(a, b)| a * b)
160 .collect();
161 }
162 }
163
164 let mut pp_powers = Vec::new();
165 let mut total_scalars = 0;
166 for i in 0..num_vars {
167 let eq = eq_arr.pop_front().unwrap();
168 let pp_k_powers = (0..(1 << (num_vars - i))).map(|x| eq[x]);
169 pp_powers.extend(pp_k_powers);
170 total_scalars += 1 << (num_vars - i);
171 }
172 let window_size = FixedBase::get_mul_window_size(total_scalars);
173 let g_table = FixedBase::get_window_table(scalar_bits, window_size, g);
174
175 let pp_g = E::G1::normalize_batch(&FixedBase::msm(
176 scalar_bits,
177 window_size,
178 &g_table,
179 &pp_powers,
180 ));
181
182 let mut start = 0;
183 for i in 0..num_vars {
184 let size = 1 << (num_vars - i);
185 let pp_k_g = Evaluations {
186 evals: pp_g[start..(start + size)].to_vec(),
187 };
188 // check correctness of pp_k_g
189 let t_eval_0 = eq_eval(&vec![E::ScalarField::zero(); num_vars - i], &t[i..num_vars])?;
190 assert_eq!((g * t_eval_0).into(), pp_k_g.evals[0]);
191 powers_of_g.push(pp_k_g);
192 start += size;
193 }
194 let gg = Evaluations {
195 evals: [g.into_affine()].to_vec(),
196 };
197 powers_of_g.push(gg);
198
199 let pp = Self::ProverParam {
200 num_vars,
201 g: g.into_affine(),
202 h: h.into_affine(),
203 powers_of_g,
204 };
205
206 end_timer!(pp_generation_timer);
207
208 let vp_generation_timer = start_timer!(|| "VP generation");
209 let h_mask = {
210 let window_size = FixedBase::get_mul_window_size(num_vars);
211 let h_table = FixedBase::get_window_table(scalar_bits, window_size, h);
212 E::G2::normalize_batch(&FixedBase::msm(scalar_bits, window_size, &h_table, &t))
213 };
214 end_timer!(vp_generation_timer);
215 end_timer!(total_timer);
216 Ok(Self {
217 prover_param: pp,
218 h_mask,
219 })
220 }
221}
222
223/// fix first `pad` variables of `poly` represented in evaluation form to zero
224fn remove_dummy_variable<F: Field>(poly: &[F], pad: usize) -> Result<Vec<F>, PCSError> {
225 if pad == 0 {
226 return Ok(poly.to_vec());
227 }
228 if !poly.len().is_power_of_two() {
229 return Err(PCSError::InvalidParameters(
230 "Size of polynomial should be power of two.".to_string(),
231 ));
232 }
233 let nv = ark_std::log2(poly.len()) as usize - pad;
234 Ok((0..(1 << nv)).map(|x| poly[x << pad]).collect())
235}
236
237#[cfg(test)]
238mod tests {
239 use super::*;
240 use ark_bls12_381::Bls12_381;
241 use ark_std::test_rng;
242 type E = Bls12_381;
243
244 #[test]
245 fn test_srs_gen() -> Result<(), PCSError> {
246 let mut rng = test_rng();
247 for nv in 4..10 {
248 let _ = MultilinearUniversalParams::<E>::gen_srs_for_testing(&mut rng, nv)?;
249 }
250
251 Ok(())
252 }
253}