1use rand_core::RngCore;
2use std::ops::{AddAssign, MulAssign};
3use std::sync::Arc;
4
5use ff::{Field, PrimeField};
6use group::{prime::PrimeCurveAffine, Curve, Group, Wnaf, WnafGroup};
7use pairing::Engine;
8
9use super::{Parameters, VerifyingKey};
10
11use bellman::{Circuit, ConstraintSystem, Index, LinearCombination, SynthesisError, Variable};
12
13use bellman::domain::{EvaluationDomain, Scalar};
14
15use bellman::multicore::Worker;
16
17pub fn generate_random_parameters<E, C, R>(
20 circuit: C,
21 mut rng: &mut R,
22) -> Result<Parameters<E>, SynthesisError>
23where
24 E: Engine,
25 E::G1: WnafGroup,
26 E::G2: WnafGroup,
27 C: Circuit<E::Fr>,
28 R: RngCore,
29{
30 let g1 = E::G1::random(&mut rng);
31 let g2 = E::G2::random(&mut rng);
32 let alpha = E::Fr::random(&mut rng);
33 let beta = E::Fr::random(&mut rng);
34 let gamma = E::Fr::random(&mut rng);
35 let delta = E::Fr::random(&mut rng);
36 let tau = E::Fr::random(&mut rng);
37
38 generate_parameters::<E, C>(circuit, g1, g2, alpha, beta, gamma, delta, tau)
39}
40
41struct KeypairAssembly<Scalar: PrimeField> {
44 num_inputs: usize,
45 num_aux: usize,
46 num_constraints: usize,
47 at_inputs: Vec<Vec<(Scalar, usize)>>,
48 bt_inputs: Vec<Vec<(Scalar, usize)>>,
49 ct_inputs: Vec<Vec<(Scalar, usize)>>,
50 at_aux: Vec<Vec<(Scalar, usize)>>,
51 bt_aux: Vec<Vec<(Scalar, usize)>>,
52 ct_aux: Vec<Vec<(Scalar, usize)>>,
53}
54
55impl<Scalar: PrimeField> ConstraintSystem<Scalar> for KeypairAssembly<Scalar> {
56 type Root = Self;
57
58 fn alloc<F, A, AR>(&mut self, _: A, _: F) -> Result<Variable, SynthesisError>
59 where
60 F: FnOnce() -> Result<Scalar, SynthesisError>,
61 A: FnOnce() -> AR,
62 AR: Into<String>,
63 {
64 let index = self.num_aux;
68 self.num_aux += 1;
69
70 self.at_aux.push(vec![]);
71 self.bt_aux.push(vec![]);
72 self.ct_aux.push(vec![]);
73
74 Ok(Variable::new_unchecked(Index::Aux(index)))
75 }
76
77 fn alloc_input<F, A, AR>(&mut self, _: A, _: F) -> Result<Variable, SynthesisError>
78 where
79 F: FnOnce() -> Result<Scalar, SynthesisError>,
80 A: FnOnce() -> AR,
81 AR: Into<String>,
82 {
83 let index = self.num_inputs;
87 self.num_inputs += 1;
88
89 self.at_inputs.push(vec![]);
90 self.bt_inputs.push(vec![]);
91 self.ct_inputs.push(vec![]);
92
93 Ok(Variable::new_unchecked(Index::Input(index)))
94 }
95
96 fn enforce<A, AR, LA, LB, LC>(&mut self, _: A, a: LA, b: LB, c: LC)
97 where
98 A: FnOnce() -> AR,
99 AR: Into<String>,
100 LA: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
101 LB: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
102 LC: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
103 {
104 fn eval<Scalar: PrimeField>(
105 l: LinearCombination<Scalar>,
106 inputs: &mut [Vec<(Scalar, usize)>],
107 aux: &mut [Vec<(Scalar, usize)>],
108 this_constraint: usize,
109 ) {
110 for (index, coeff) in l.as_ref() {
111 match index.get_unchecked() {
112 Index::Input(id) => inputs[id].push((*coeff, this_constraint)),
113 Index::Aux(id) => aux[id].push((*coeff, this_constraint)),
114 }
115 }
116 }
117
118 eval(
119 a(LinearCombination::zero()),
120 &mut self.at_inputs,
121 &mut self.at_aux,
122 self.num_constraints,
123 );
124 eval(
125 b(LinearCombination::zero()),
126 &mut self.bt_inputs,
127 &mut self.bt_aux,
128 self.num_constraints,
129 );
130 eval(
131 c(LinearCombination::zero()),
132 &mut self.ct_inputs,
133 &mut self.ct_aux,
134 self.num_constraints,
135 );
136
137 self.num_constraints += 1;
138 }
139
140 fn push_namespace<NR, N>(&mut self, _: N)
141 where
142 NR: Into<String>,
143 N: FnOnce() -> NR,
144 {
145 }
147
148 fn pop_namespace(&mut self) {
149 }
151
152 fn get_root(&mut self) -> &mut Self::Root {
153 self
154 }
155}
156
157#[allow(clippy::too_many_arguments)]
159pub fn generate_parameters<E, C>(
160 circuit: C,
161 g1: E::G1,
162 g2: E::G2,
163 alpha: E::Fr,
164 beta: E::Fr,
165 gamma: E::Fr,
166 delta: E::Fr,
167 tau: E::Fr,
168) -> Result<Parameters<E>, SynthesisError>
169where
170 E: Engine,
171 E::G1: WnafGroup,
172 E::G2: WnafGroup,
173 C: Circuit<E::Fr>,
174{
175 let mut assembly = KeypairAssembly {
176 num_inputs: 0,
177 num_aux: 0,
178 num_constraints: 0,
179 at_inputs: vec![],
180 bt_inputs: vec![],
181 ct_inputs: vec![],
182 at_aux: vec![],
183 bt_aux: vec![],
184 ct_aux: vec![],
185 };
186
187 assembly.alloc_input(|| "", || Ok(E::Fr::ONE))?;
189
190 circuit.synthesize(&mut assembly)?;
192
193 for i in 0..assembly.num_inputs {
196 assembly.enforce(
197 || "",
198 |lc| lc + Variable::new_unchecked(Index::Input(i)),
199 |lc| lc,
200 |lc| lc,
201 );
202 }
203
204 let powers_of_tau = vec![Scalar::<E::Fr>(E::Fr::ZERO); assembly.num_constraints];
206 let mut powers_of_tau = EvaluationDomain::from_coeffs(powers_of_tau)?;
207
208 let mut g1_wnaf = Wnaf::new();
210 let g1_wnaf = g1_wnaf.base(g1, {
211 (powers_of_tau.as_ref().len() - 1)
213 + assembly.num_inputs + assembly.num_aux
215 + assembly.num_inputs + assembly.num_aux
217 + assembly.num_inputs + assembly.num_aux
219 });
220
221 let mut g2_wnaf = Wnaf::new();
223 let g2_wnaf = g2_wnaf.base(g2, {
224 assembly.num_inputs + assembly.num_aux
226 });
227
228 let gamma_inverse = {
229 let inverse = gamma.invert();
230 if bool::from(inverse.is_some()) {
231 Ok(inverse.unwrap())
232 } else {
233 Err(SynthesisError::UnexpectedIdentity)
234 }
235 }?;
236 let delta_inverse = {
237 let inverse = delta.invert();
238 if bool::from(inverse.is_some()) {
239 Ok(inverse.unwrap())
240 } else {
241 Err(SynthesisError::UnexpectedIdentity)
242 }
243 }?;
244
245 let worker = Worker::new();
246
247 let mut h = vec![E::G1Affine::identity(); powers_of_tau.as_ref().len() - 1];
248 {
249 {
251 let powers_of_tau = powers_of_tau.as_mut();
252 worker.scope(powers_of_tau.len(), |scope, chunk| {
253 for (i, powers_of_tau) in powers_of_tau.chunks_mut(chunk).enumerate() {
254 scope.spawn(move |_scope| {
255 let mut current_tau_power = tau.pow_vartime(&[(i * chunk) as u64]);
256
257 for p in powers_of_tau {
258 p.0 = current_tau_power;
259 current_tau_power.mul_assign(&tau);
260 }
261 });
262 }
263 });
264 }
265
266 let mut coeff = powers_of_tau.z(&tau);
268 coeff.mul_assign(&delta_inverse);
269
270 worker.scope(h.len(), |scope, chunk| {
272 for (h, p) in h
273 .chunks_mut(chunk)
274 .zip(powers_of_tau.as_ref().chunks(chunk))
275 {
276 let mut g1_wnaf = g1_wnaf.shared();
277
278 scope.spawn(move |_scope| {
279 let h_proj: Vec<_> = p[..h.len()]
281 .iter()
282 .map(|p| {
283 let mut exp = p.0;
285 exp.mul_assign(&coeff);
286
287 g1_wnaf.scalar(&exp)
289 })
290 .collect();
291
292 E::G1::batch_normalize(&h_proj, h);
294 });
295 }
296 });
297 }
298
299 powers_of_tau.ifft(&worker);
301 let powers_of_tau = powers_of_tau.into_coeffs();
302
303 let mut a = vec![E::G1Affine::identity(); assembly.num_inputs + assembly.num_aux];
304 let mut b_g1 = vec![E::G1Affine::identity(); assembly.num_inputs + assembly.num_aux];
305 let mut b_g2 = vec![E::G2Affine::identity(); assembly.num_inputs + assembly.num_aux];
306 let mut ic = vec![E::G1Affine::identity(); assembly.num_inputs];
307 let mut l = vec![E::G1Affine::identity(); assembly.num_aux];
308
309 #[allow(clippy::too_many_arguments)]
310 fn eval<E: Engine>(
311 g1_wnaf: &Wnaf<usize, &[E::G1], &mut Vec<i64>>,
313 g2_wnaf: &Wnaf<usize, &[E::G2], &mut Vec<i64>>,
314
315 powers_of_tau: &[Scalar<E::Fr>],
317
318 at: &[Vec<(E::Fr, usize)>],
320 bt: &[Vec<(E::Fr, usize)>],
321 ct: &[Vec<(E::Fr, usize)>],
322
323 a: &mut [E::G1Affine],
325 b_g1: &mut [E::G1Affine],
326 b_g2: &mut [E::G2Affine],
327 ext: &mut [E::G1Affine],
328
329 inv: &E::Fr,
331
332 alpha: &E::Fr,
334 beta: &E::Fr,
335
336 worker: &Worker,
338 ) {
339 assert_eq!(a.len(), at.len());
341 assert_eq!(a.len(), bt.len());
342 assert_eq!(a.len(), ct.len());
343 assert_eq!(a.len(), b_g1.len());
344 assert_eq!(a.len(), b_g2.len());
345 assert_eq!(a.len(), ext.len());
346
347 worker.scope(a.len(), |scope, chunk| {
349 for ((((((a, b_g1), b_g2), ext), at), bt), ct) in a
350 .chunks_mut(chunk)
351 .zip(b_g1.chunks_mut(chunk))
352 .zip(b_g2.chunks_mut(chunk))
353 .zip(ext.chunks_mut(chunk))
354 .zip(at.chunks(chunk))
355 .zip(bt.chunks(chunk))
356 .zip(ct.chunks(chunk))
357 {
358 let mut g1_wnaf = g1_wnaf.shared();
359 let mut g2_wnaf = g2_wnaf.shared();
360
361 scope.spawn(move |_scope| {
362 let mut a_proj = vec![E::G1::identity(); a.len()];
363 let mut b_g1_proj = vec![E::G1::identity(); b_g1.len()];
364 let mut b_g2_proj = vec![E::G2::identity(); b_g2.len()];
365 let mut ext_proj = vec![E::G1::identity(); ext.len()];
366
367 for ((((((a, b_g1), b_g2), ext), at), bt), ct) in a_proj
368 .iter_mut()
369 .zip(b_g1_proj.iter_mut())
370 .zip(b_g2_proj.iter_mut())
371 .zip(ext_proj.iter_mut())
372 .zip(at.iter())
373 .zip(bt.iter())
374 .zip(ct.iter())
375 {
376 fn eval_at_tau<S: PrimeField>(
377 powers_of_tau: &[Scalar<S>],
378 p: &[(S, usize)],
379 ) -> S {
380 let mut acc = S::ZERO;
381
382 for &(ref coeff, index) in p {
383 let mut n = powers_of_tau[index].0;
384 n.mul_assign(coeff);
385 acc.add_assign(&n);
386 }
387
388 acc
389 }
390
391 let mut at = eval_at_tau(powers_of_tau, at);
393 let mut bt = eval_at_tau(powers_of_tau, bt);
394 let ct = eval_at_tau(powers_of_tau, ct);
395
396 if !at.is_zero_vartime() {
398 *a = g1_wnaf.scalar(&at);
399 }
400
401 if !bt.is_zero_vartime() {
403 *b_g1 = g1_wnaf.scalar(&bt);
404 *b_g2 = g2_wnaf.scalar(&bt);
405 }
406
407 at *= beta;
408 bt *= alpha;
409
410 let mut e = at;
411 e.add_assign(&bt);
412 e.add_assign(&ct);
413 e.mul_assign(inv);
414
415 *ext = g1_wnaf.scalar(&e);
416 }
417
418 E::G1::batch_normalize(&a_proj, a);
420 E::G1::batch_normalize(&b_g1_proj, b_g1);
421 E::G2::batch_normalize(&b_g2_proj, b_g2);
422 E::G1::batch_normalize(&ext_proj, ext);
423 });
424 }
425 });
426 }
427
428 eval::<E>(
430 &g1_wnaf,
431 &g2_wnaf,
432 &powers_of_tau,
433 &assembly.at_inputs,
434 &assembly.bt_inputs,
435 &assembly.ct_inputs,
436 &mut a[0..assembly.num_inputs],
437 &mut b_g1[0..assembly.num_inputs],
438 &mut b_g2[0..assembly.num_inputs],
439 &mut ic,
440 &gamma_inverse,
441 &alpha,
442 &beta,
443 &worker,
444 );
445
446 eval::<E>(
448 &g1_wnaf,
449 &g2_wnaf,
450 &powers_of_tau,
451 &assembly.at_aux,
452 &assembly.bt_aux,
453 &assembly.ct_aux,
454 &mut a[assembly.num_inputs..],
455 &mut b_g1[assembly.num_inputs..],
456 &mut b_g2[assembly.num_inputs..],
457 &mut l,
458 &delta_inverse,
459 &alpha,
460 &beta,
461 &worker,
462 );
463
464 for e in l.iter() {
467 if e.is_identity().into() {
468 return Err(SynthesisError::UnconstrainedVariable);
469 }
470 }
471
472 let g1 = g1.to_affine();
473 let g2 = g2.to_affine();
474
475 let vk = VerifyingKey::<E> {
476 alpha_g1: (g1 * alpha).to_affine(),
477 beta_g1: (g1 * beta).to_affine(),
478 beta_g2: (g2 * beta).to_affine(),
479 gamma_g2: (g2 * gamma).to_affine(),
480 delta_g1: (g1 * delta).to_affine(),
481 delta_g2: (g2 * delta).to_affine(),
482 ic,
483 };
484
485 Ok(Parameters {
486 vk,
487 h: Arc::new(h),
488 l: Arc::new(l),
489
490 a: Arc::new(
492 a.into_iter()
493 .filter(|e| bool::from(!e.is_identity()))
494 .collect(),
495 ),
496 b_g1: Arc::new(
497 b_g1.into_iter()
498 .filter(|e| bool::from(!e.is_identity()))
499 .collect(),
500 ),
501 b_g2: Arc::new(
502 b_g2.into_iter()
503 .filter(|e| bool::from(!e.is_identity()))
504 .collect(),
505 ),
506 })
507}