hyperplonk/subroutines/src/pcs/multilinear_kzg/srs.rs
subroutines/src/pcs/multilinear_kzg/srs.rsRaw
1// Copyright (c) 2022 Espresso Systems (espressosys.com)
2// This file is part of the Jellyfish library.
3
4// You should have received a copy of the MIT License
5// along with the Jellyfish 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_extension, prelude::PCSError, StructuredReferenceString,
10};
11use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve};
12use ark_ff::{Field, PrimeField};
13use ark_poly::DenseMultilinearExtension;
14use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write};
15use ark_std::{
16 collections::LinkedList,
17 end_timer, format,
18 rand::{CryptoRng, RngCore},
19 start_timer,
20 string::ToString,
21 vec::Vec,
22 UniformRand,
23};
24use core::iter::FromIterator;
25
26/// Evaluations over {0,1}^n for G1 or G2
27#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
28pub struct Evaluations<C: AffineCurve> {
29 /// The evaluations.
30 pub evals: Vec<C>,
31}
32
33/// Universal Parameter
34#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
35pub struct MultilinearUniversalParams<E: PairingEngine> {
36 /// prover parameters
37 pub prover_param: MultilinearProverParam<E>,
38 /// h^randomness: h^t1, h^t2, ..., **h^{t_nv}**
39 pub h_mask: Vec<E::G2Affine>,
40}
41
42/// Prover Parameters
43#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
44pub struct MultilinearProverParam<E: PairingEngine> {
45 /// number of variables
46 pub num_vars: usize,
47 /// `pp_{num_vars}`, `pp_{num_vars - 1}`, `pp_{num_vars - 2}`, ..., defined
48 /// by XZZPD19
49 pub powers_of_g: Vec<Evaluations<E::G1Affine>>,
50 /// generator for G1
51 pub g: E::G1Affine,
52 /// generator for G2
53 pub h: E::G2Affine,
54}
55
56/// Verifier Parameters
57#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
58pub struct MultilinearVerifierParam<E: PairingEngine> {
59 /// number of variables
60 pub num_vars: usize,
61 /// generator of G1
62 pub g: E::G1Affine,
63 /// generator of G2
64 pub h: E::G2Affine,
65 /// h^randomness: h^t1, h^t2, ..., **h^{t_nv}**
66 pub h_mask: Vec<E::G2Affine>,
67}
68
69impl<E: PairingEngine> StructuredReferenceString<E> for MultilinearUniversalParams<E> {
70 type ProverParam = MultilinearProverParam<E>;
71 type VerifierParam = MultilinearVerifierParam<E>;
72
73 /// Extract the prover parameters from the public parameters.
74 fn extract_prover_param(&self, supported_num_vars: usize) -> Self::ProverParam {
75 let to_reduce = self.prover_param.num_vars - supported_num_vars;
76
77 Self::ProverParam {
78 powers_of_g: self.prover_param.powers_of_g[to_reduce..].to_vec(),
79 g: self.prover_param.g,
80 h: self.prover_param.h,
81 num_vars: supported_num_vars,
82 }
83 }
84
85 /// Extract the verifier parameters from the public parameters.
86 fn extract_verifier_param(&self, supported_num_vars: usize) -> Self::VerifierParam {
87 let to_reduce = self.prover_param.num_vars - supported_num_vars;
88 Self::VerifierParam {
89 num_vars: supported_num_vars,
90 g: self.prover_param.g,
91 h: self.prover_param.h,
92 h_mask: self.h_mask[to_reduce..].to_vec(),
93 }
94 }
95
96 /// Trim the universal parameters to specialize the public parameters
97 /// for multilinear polynomials to the given `supported_num_vars`, and
98 /// returns committer key and verifier key. `supported_num_vars` should
99 /// be in range `1..=params.num_vars`
100 fn trim(
101 &self,
102 supported_num_vars: usize,
103 ) -> Result<(Self::ProverParam, Self::VerifierParam), PCSError> {
104 if supported_num_vars > self.prover_param.num_vars {
105 return Err(PCSError::InvalidParameters(format!(
106 "SRS does not support target number of vars {}",
107 supported_num_vars
108 )));
109 }
110
111 let to_reduce = self.prover_param.num_vars - supported_num_vars;
112 let ck = Self::ProverParam {
113 powers_of_g: self.prover_param.powers_of_g[to_reduce..].to_vec(),
114 g: self.prover_param.g,
115 h: self.prover_param.h,
116 num_vars: supported_num_vars,
117 };
118 let vk = Self::VerifierParam {
119 num_vars: supported_num_vars,
120 g: self.prover_param.g,
121 h: self.prover_param.h,
122 h_mask: self.h_mask[to_reduce..].to_vec(),
123 };
124 Ok((ck, vk))
125 }
126
127 /// Build SRS for testing.
128 /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY.
129 /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION.
130 fn gen_srs_for_testing<R: RngCore + CryptoRng>(
131 rng: &mut R,
132 num_vars: usize,
133 ) -> Result<Self, PCSError> {
134 if num_vars == 0 {
135 return Err(PCSError::InvalidParameters(
136 "constant polynomial not supported".to_string(),
137 ));
138 }
139
140 let total_timer = start_timer!(|| "SRS generation");
141
142 let pp_generation_timer = start_timer!(|| "Prover Param generation");
143
144 let g = E::G1Projective::rand(rng);
145 let h = E::G2Projective::rand(rng);
146
147 let mut powers_of_g = Vec::new();
148
149 let t: Vec<_> = (0..num_vars).map(|_| E::Fr::rand(rng)).collect();
150 let scalar_bits = E::Fr::size_in_bits();
151
152 let mut eq: LinkedList<DenseMultilinearExtension<E::Fr>> =
153 LinkedList::from_iter(eq_extension(&t).into_iter());
154 let mut eq_arr = LinkedList::new();
155 let mut base = eq.pop_back().unwrap().evaluations;
156
157 for i in (0..num_vars).rev() {
158 eq_arr.push_front(remove_dummy_variable(&base, i)?);
159 if i != 0 {
160 let mul = eq.pop_back().unwrap().evaluations;
161 base = base
162 .into_iter()
163 .zip(mul.into_iter())
164 .map(|(a, b)| a * b)
165 .collect();
166 }
167 }
168
169 let mut pp_powers = Vec::new();
170 let mut total_scalars = 0;
171 for i in 0..num_vars {
172 let eq = eq_arr.pop_front().unwrap();
173 let pp_k_powers = (0..(1 << (num_vars - i))).map(|x| eq[x]);
174 pp_powers.extend(pp_k_powers);
175 total_scalars += 1 << (num_vars - i);
176 }
177 let window_size = FixedBaseMSM::get_mul_window_size(total_scalars);
178 let g_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, g);
179
180 let pp_g = E::G1Projective::batch_normalization_into_affine(
181 &FixedBaseMSM::multi_scalar_mul(scalar_bits, window_size, &g_table, &pp_powers),
182 );
183
184 let mut start = 0;
185 for i in 0..num_vars {
186 let size = 1 << (num_vars - i);
187 let pp_k_g = Evaluations {
188 evals: pp_g[start..(start + size)].to_vec(),
189 };
190 powers_of_g.push(pp_k_g);
191 start += size;
192 }
193
194 let pp = Self::ProverParam {
195 num_vars,
196 g: g.into_affine(),
197 h: h.into_affine(),
198 powers_of_g,
199 };
200
201 end_timer!(pp_generation_timer);
202
203 let vp_generation_timer = start_timer!(|| "VP generation");
204 let h_mask = {
205 let window_size = FixedBaseMSM::get_mul_window_size(num_vars);
206 let h_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, h);
207 E::G2Projective::batch_normalization_into_affine(&FixedBaseMSM::multi_scalar_mul(
208 scalar_bits,
209 window_size,
210 &h_table,
211 &t,
212 ))
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}