1use crate::pairing::ff::{Field, PrimeField};
2use crate::pairing::Engine;
3
4use crate::SynthesisError;
5use std::marker::PhantomData;
6
7use crate::plonk::cs::gates::*;
8use crate::plonk::cs::*;
9
10use crate::plonk::commitments::*;
11use crate::plonk::domains::*;
12use crate::plonk::polynomials::*;
13use crate::plonk::utils::*;
14use crate::worker::*;
15
16use super::prover::ProvingAssembly;
17
18#[derive(Debug)]
19pub struct GeneratorAssembly<E: Engine> {
20 pub(crate) m: usize,
21 pub(crate) n: usize,
22 pub(crate) input_gates: Vec<Gate<E::Fr>>,
23 pub(crate) aux_gates: Vec<Gate<E::Fr>>,
24
25 pub(crate) num_inputs: usize,
26 pub(crate) num_aux: usize,
27
28 pub(crate) inputs_map: Vec<usize>,
29
30 pub(crate) is_finalized: bool,
31}
32
33impl<E: Engine> ConstraintSystem<E> for GeneratorAssembly<E> {
34 fn alloc<F>(&mut self, _value: F) -> Result<Variable, SynthesisError>
39 where
40 F: FnOnce() -> Result<E::Fr, SynthesisError>,
41 {
42 self.num_aux += 1;
43 let index = self.num_aux;
44
45 Ok(Variable(Index::Aux(index)))
46 }
47
48 fn alloc_input<F>(&mut self, _value: F) -> Result<Variable, SynthesisError>
50 where
51 F: FnOnce() -> Result<E::Fr, SynthesisError>,
52 {
53 self.num_inputs += 1;
54 let index = self.num_inputs;
55
56 let input_var = Variable(Index::Input(index));
57
58 let gate = Gate::<E::Fr>::new_enforce_constant_gate(input_var, Some(E::Fr::zero()), self.dummy_variable());
59 self.input_gates.push(gate);
60
61 Ok(input_var)
62 }
63
64 fn enforce_boolean(&mut self, variable: Variable) -> Result<(), SynthesisError> {
66 let gate = Gate::<E::Fr>::new_enforce_boolean_gate(variable, self.dummy_variable());
67 self.aux_gates.push(gate);
68 self.n += 1;
69
70 Ok(())
71 }
72
73 fn new_gate(&mut self, variables: (Variable, Variable, Variable), coeffs: (E::Fr, E::Fr, E::Fr, E::Fr, E::Fr)) -> Result<(), SynthesisError> {
75 let gate = Gate::<E::Fr>::new_gate(variables, coeffs);
76 self.aux_gates.push(gate);
77 self.n += 1;
78
79 Ok(())
80 }
81
82 fn enforce_constant(&mut self, variable: Variable, constant: E::Fr) -> Result<(), SynthesisError> {
84 let gate = Gate::<E::Fr>::new_enforce_constant_gate(variable, Some(constant), self.dummy_variable());
85 self.aux_gates.push(gate);
86 self.n += 1;
87
88 Ok(())
89 }
90
91 fn enforce_mul_2(&mut self, variables: (Variable, Variable)) -> Result<(), SynthesisError> {
93 let (v_0, v_1) = variables;
95 let zero = E::Fr::zero();
96 let one = E::Fr::one();
97
98 let gate = Gate::<E::Fr>::new_gate((v_0, v_1, self.dummy_variable()), (zero, zero, zero, one, zero));
99 self.aux_gates.push(gate);
100 self.n += 1;
101
102 Ok(())
103 }
104
105 fn enforce_mul_3(&mut self, variables: (Variable, Variable, Variable)) -> Result<(), SynthesisError> {
107 let gate = Gate::<E::Fr>::new_multiplication_gate(variables);
108 self.aux_gates.push(gate);
109 self.n += 1;
110
111 Ok(())
112 }
113
114 fn enforce_zero_2(&mut self, variables: (Variable, Variable), coeffs: (E::Fr, E::Fr)) -> Result<(), SynthesisError> {
116 let (v_0, v_1) = variables;
117 let (c_0, c_1) = coeffs;
118 let zero = E::Fr::zero();
119
120 let gate = Gate::<E::Fr>::new_gate((v_0, v_1, self.dummy_variable()), (c_0, c_1, zero, zero, zero));
121 self.aux_gates.push(gate);
122 self.n += 1;
123
124 Ok(())
125 }
126
127 fn enforce_zero_3(&mut self, variables: (Variable, Variable, Variable), coeffs: (E::Fr, E::Fr, E::Fr)) -> Result<(), SynthesisError> {
129 let gate = Gate::<E::Fr>::new_enforce_zero_gate(variables, coeffs);
130 self.aux_gates.push(gate);
131 self.n += 1;
132
133 Ok(())
134 }
135
136 fn get_dummy_variable(&self) -> Variable {
137 self.dummy_variable()
138 }
139}
140
141impl<E: Engine> GeneratorAssembly<E> {
142 fn new_empty_gate(&mut self) -> usize {
143 self.n += 1;
144 let index = self.n;
145
146 self.aux_gates.push(Gate::<E::Fr>::empty());
147
148 index
149 }
150
151 fn set_gate(&mut self, gate: Gate<E::Fr>, index: usize) {
152 self.aux_gates[index - 1] = gate;
153 }
154
155 pub fn new() -> Self {
156 let mut tmp = Self {
157 n: 0,
158 m: 0,
159 input_gates: vec![],
160 aux_gates: vec![],
161
162 num_inputs: 0,
163 num_aux: 0,
164
165 inputs_map: vec![],
166
167 is_finalized: false,
168 };
169
170 let zero = tmp.alloc(|| Ok(E::Fr::zero())).expect("should have no issues");
171 tmp.enforce_constant(zero, E::Fr::zero()).expect("should have no issues");
172
173 match (tmp.dummy_variable(), zero) {
187 (Variable(Index::Aux(1)), Variable(Index::Aux(1))) => {}
188 _ => panic!("zero variable is incorrect"),
189 }
190
191 assert_eq!(tmp.num_inputs, 0);
192 assert_eq!(tmp.num_aux, 1);
193
194 tmp
195 }
196
197 fn dummy_variable(&self) -> Variable {
199 Variable(Index::Aux(1))
201 }
202
203 pub(crate) fn make_circuit_description_polynomials(
204 &self,
205 worker: &Worker,
206 ) -> Result<
207 (
208 Polynomial<E::Fr, Values>,
209 Polynomial<E::Fr, Values>,
210 Polynomial<E::Fr, Values>,
211 Polynomial<E::Fr, Values>,
212 Polynomial<E::Fr, Values>,
213 ),
214 SynthesisError,
215 > {
216 assert!(self.is_finalized);
217 let total_num_gates = self.input_gates.len() + self.aux_gates.len();
218 let mut q_l = vec![E::Fr::zero(); total_num_gates];
219 let mut q_r = vec![E::Fr::zero(); total_num_gates];
220 let mut q_o = vec![E::Fr::zero(); total_num_gates];
221 let mut q_m = vec![E::Fr::zero(); total_num_gates];
222 let mut q_c = vec![E::Fr::zero(); total_num_gates];
223
224 fn coeff_into_field_element<F: PrimeField>(coeff: &Coeff<F>) -> F {
225 match coeff {
226 Coeff::Zero => F::zero(),
227 Coeff::One => F::one(),
228 Coeff::NegativeOne => {
229 let mut tmp = F::one();
230 tmp.negate();
231
232 tmp
233 }
234 Coeff::Full(c) => *c,
235 }
236 }
237
238 for (((((gate, q_l), q_r), q_o), q_m), q_c) in self
240 .input_gates
241 .iter()
242 .zip(q_l.iter_mut())
243 .zip(q_r.iter_mut())
244 .zip(q_o.iter_mut())
245 .zip(q_m.iter_mut())
246 .zip(q_c.iter_mut())
247 {
248 *q_l = coeff_into_field_element::<E::Fr>(&gate.q_l);
249 *q_r = coeff_into_field_element::<E::Fr>(&gate.q_r);
250 *q_o = coeff_into_field_element::<E::Fr>(&gate.q_o);
251 *q_m = coeff_into_field_element::<E::Fr>(&gate.q_m);
252 *q_c = coeff_into_field_element::<E::Fr>(&gate.q_c);
253 }
254
255 let num_input_gates = self.input_gates.len();
256 let q_l_aux = &mut q_l[num_input_gates..];
257 let q_r_aux = &mut q_r[num_input_gates..];
258 let q_o_aux = &mut q_o[num_input_gates..];
259 let q_m_aux = &mut q_m[num_input_gates..];
260 let q_c_aux = &mut q_c[num_input_gates..];
261
262 debug_assert!(self.aux_gates.len() == q_l_aux.len());
263
264 worker.scope(self.aux_gates.len(), |scope, chunk| {
265 for (((((gate, q_l), q_r), q_o), q_m), q_c) in self
266 .aux_gates
267 .chunks(chunk)
268 .zip(q_l_aux.chunks_mut(chunk))
269 .zip(q_r_aux.chunks_mut(chunk))
270 .zip(q_o_aux.chunks_mut(chunk))
271 .zip(q_m_aux.chunks_mut(chunk))
272 .zip(q_c_aux.chunks_mut(chunk))
273 {
274 scope.spawn(move |_| {
275 for (((((gate, q_l), q_r), q_o), q_m), q_c) in gate.iter().zip(q_l.iter_mut()).zip(q_r.iter_mut()).zip(q_o.iter_mut()).zip(q_m.iter_mut()).zip(q_c.iter_mut()) {
276 *q_l = coeff_into_field_element(&gate.q_l);
277 *q_r = coeff_into_field_element(&gate.q_r);
278 *q_o = coeff_into_field_element(&gate.q_o);
279 *q_m = coeff_into_field_element(&gate.q_m);
280 *q_c = coeff_into_field_element(&gate.q_c);
281 }
282 });
283 }
284 });
285
286 let q_l = Polynomial::from_values(q_l)?;
287 let q_r = Polynomial::from_values(q_r)?;
288 let q_o = Polynomial::from_values(q_o)?;
289 let q_m = Polynomial::from_values(q_m)?;
290 let q_c = Polynomial::from_values(q_c)?;
291
292 Ok((q_l, q_r, q_o, q_m, q_c))
293 }
294
295 pub(crate) fn calculate_permutations_as_in_a_paper(&self) -> (Vec<usize>, Vec<usize>, Vec<usize>) {
296 assert!(self.is_finalized);
297
298 let num_gates = self.input_gates.len() + self.aux_gates.len();
299 let num_partitions = self.num_inputs + self.num_aux;
300 let num_inputs = self.num_inputs;
301 let mut partitions = vec![vec![]; num_partitions + 1];
303
304 for (j, gate) in self.input_gates.iter().chain(&self.aux_gates).enumerate() {
305 match gate.a_wire() {
306 Variable(Index::Input(index)) => {
307 let i = *index;
308 partitions[i].push(j + 1);
309 }
310 Variable(Index::Aux(index)) => {
311 if *index != 0 {
312 let i = index + num_inputs;
313 partitions[i].push(j + 1);
314 }
315 }
316 }
317
318 match gate.b_wire() {
319 Variable(Index::Input(index)) => {
320 let i = *index;
321 partitions[i].push(j + 1 + num_gates);
322 }
323 Variable(Index::Aux(index)) => {
324 if *index != 0 {
325 let i = index + num_inputs;
326 partitions[i].push(j + 1 + num_gates);
327 }
328 }
329 }
330
331 match gate.c_wire() {
332 Variable(Index::Input(index)) => {
333 let i = *index;
334 partitions[i].push(j + 1 + 2 * num_gates);
335 }
336 Variable(Index::Aux(index)) => {
337 if *index != 0 {
338 let i = index + num_inputs;
339 partitions[i].push(j + 1 + 2 * num_gates);
340 }
341 }
342 }
343 }
344
345 let mut sigma_1: Vec<_> = (1..=num_gates).collect();
346 let mut sigma_2: Vec<_> = ((num_gates + 1)..=(2 * num_gates)).collect();
347 let mut sigma_3: Vec<_> = ((2 * num_gates + 1)..=(3 * num_gates)).collect();
348
349 let mut permutations = vec![vec![]; num_partitions + 1];
350
351 fn rotate(mut vec: Vec<usize>) -> Vec<usize> {
352 if vec.len() > 0 {
353 let els: Vec<_> = vec.drain(0..1).collect();
354 vec.push(els[0]);
355 }
356
357 vec
358 }
359
360 for (i, partition) in partitions.into_iter().enumerate().skip(1) {
361 let permutation = rotate(partition.clone());
364 permutations[i] = permutation.clone();
365
366 for (original, new) in partition.into_iter().zip(permutation.into_iter()) {
367 if original <= num_gates {
368 debug_assert!(sigma_1[original - 1] == original);
369 sigma_1[original - 1] = new;
370 } else if original <= 2 * num_gates {
371 debug_assert!(sigma_2[original - num_gates - 1] == original);
372 sigma_2[original - num_gates - 1] = new;
373 } else {
374 debug_assert!(sigma_3[original - 2 * num_gates - 1] == original);
375 sigma_3[original - 2 * num_gates - 1] = new;
376 }
377 }
378 }
379
380 (sigma_1, sigma_2, sigma_3)
381 }
382
383 fn make_s_id(&self) -> Vec<usize> {
384 assert!(self.is_finalized);
385
386 let size = self.input_gates.len() + self.aux_gates.len();
387 let result: Vec<_> = (1..=size).collect();
388
389 result
390 }
391
392 pub(crate) fn output_setup_polynomials(
393 &self,
394 worker: &Worker,
395 ) -> Result<
396 (
397 Polynomial<E::Fr, Coefficients>, Polynomial<E::Fr, Coefficients>, Polynomial<E::Fr, Coefficients>, Polynomial<E::Fr, Coefficients>, Polynomial<E::Fr, Coefficients>, Polynomial<E::Fr, Coefficients>, Polynomial<E::Fr, Coefficients>, Polynomial<E::Fr, Coefficients>, Polynomial<E::Fr, Coefficients>, ),
407 SynthesisError,
408 > {
409 assert!(self.is_finalized);
410
411 let s_id = self.make_s_id();
412 let (sigma_1, sigma_2, sigma_3) = self.calculate_permutations_as_in_a_paper();
413
414 let s_id = convert_to_field_elements::<E::Fr>(&s_id, &worker);
415 let sigma_1 = convert_to_field_elements::<E::Fr>(&sigma_1, &worker);
416 let sigma_2 = convert_to_field_elements::<E::Fr>(&sigma_2, &worker);
417 let sigma_3 = convert_to_field_elements::<E::Fr>(&sigma_3, &worker);
418
419 let s_id = Polynomial::from_values(s_id)?;
420 let sigma_1 = Polynomial::from_values(sigma_1)?;
421 let sigma_2 = Polynomial::from_values(sigma_2)?;
422 let sigma_3 = Polynomial::from_values(sigma_3)?;
423
424 let (q_l, q_r, q_o, q_m, q_c) = self.make_circuit_description_polynomials(&worker)?;
425
426 let s_id = s_id.ifft(&worker);
427 let sigma_1 = sigma_1.ifft(&worker);
428 let sigma_2 = sigma_2.ifft(&worker);
429 let sigma_3 = sigma_3.ifft(&worker);
430
431 let q_l = q_l.ifft(&worker);
432 let q_r = q_r.ifft(&worker);
433 let q_o = q_o.ifft(&worker);
434 let q_m = q_m.ifft(&worker);
435 let q_c = q_c.ifft(&worker);
436
437 Ok((q_l, q_r, q_o, q_m, q_c, s_id, sigma_1, sigma_2, sigma_3))
438 }
439
440 pub fn num_gates(&self) -> usize {
441 self.input_gates.len() + self.aux_gates.len()
442 }
443
444 pub fn finalize(&mut self) {
445 if self.is_finalized {
446 return;
447 }
448
449 let n = self.input_gates.len() + self.aux_gates.len();
450 if (n + 1).is_power_of_two() {
451 self.is_finalized = true;
452 return;
453 }
454
455 let empty_gate = Gate::<E::Fr>::new_empty_gate(self.dummy_variable());
456
457 let new_aux_len = (n + 1).next_power_of_two() - 1 - self.input_gates.len();
458
459 self.aux_gates.resize(new_aux_len, empty_gate);
460
461 let n = self.input_gates.len() + self.aux_gates.len();
462 assert!((n + 1).is_power_of_two());
463
464 self.is_finalized = true;
465 }
466}
467
468use super::prover::*;
469use crate::plonk::fft::cooley_tukey_ntt::CTPrecomputations;
470
471use crate::pairing::CurveAffine;
472
473pub fn setup_with_precomputations<E: Engine, C: Circuit<E>, CP: CTPrecomputations<E::Fr>>(
474 circuit: &C,
475 omegas_bitreversed: &CP,
476 bases: &[E::G1Affine],
477) -> Result<(PlonkSetup<E>, PlonkSetupPrecomputation<E>), SynthesisError> {
478 let mut assembly = GeneratorAssembly::<E>::new();
479 circuit.synthesize(&mut assembly)?;
480 assembly.finalize();
481
482 let n = assembly.num_gates();
483
484 let worker = Worker::new();
485
486 let (q_l, q_r, q_o, q_m, q_c, s_id, sigma_1, sigma_2, sigma_3) = assembly.output_setup_polynomials(&worker)?;
487
488 let q_l_commitment_data = ProvingAssembly::<E>::commit_single_poly(&q_l, &bases, &worker)?;
489 let q_r_commitment_data = ProvingAssembly::<E>::commit_single_poly(&q_r, &bases, &worker)?;
490 let q_o_commitment_data = ProvingAssembly::<E>::commit_single_poly(&q_o, &bases, &worker)?;
491 let q_m_commitment_data = ProvingAssembly::<E>::commit_single_poly(&q_m, &bases, &worker)?;
492 let q_c_commitment_data = ProvingAssembly::<E>::commit_single_poly(&q_c, &bases, &worker)?;
493 let s_id_commitment_data = ProvingAssembly::<E>::commit_single_poly(&s_id, &bases, &worker)?;
494 let sigma_1_commitment_data = ProvingAssembly::<E>::commit_single_poly(&sigma_1, &bases, &worker)?;
495 let sigma_2_commitment_data = ProvingAssembly::<E>::commit_single_poly(&sigma_2, &bases, &worker)?;
496 let sigma_3_commitment_data = ProvingAssembly::<E>::commit_single_poly(&sigma_3, &bases, &worker)?;
497
498 let setup = PlonkSetup::<E> {
499 n: n,
500 q_l: q_l_commitment_data,
501 q_r: q_r_commitment_data,
502 q_o: q_o_commitment_data,
503 q_m: q_m_commitment_data,
504 q_c: q_c_commitment_data,
505 s_id: s_id_commitment_data,
506 sigma_1: sigma_1_commitment_data,
507 sigma_2: sigma_2_commitment_data,
508 sigma_3: sigma_3_commitment_data,
509 };
510
511 let coset_generator = E::Fr::multiplicative_generator();
512
513 let q_l_lde = q_l.bitreversed_lde_using_bitreversed_ntt(&worker, 4, omegas_bitreversed, &coset_generator)?;
514 let q_r_lde = q_r.bitreversed_lde_using_bitreversed_ntt(&worker, 4, omegas_bitreversed, &coset_generator)?;
515 let q_o_lde = q_o.bitreversed_lde_using_bitreversed_ntt(&worker, 4, omegas_bitreversed, &coset_generator)?;
516 let q_m_lde = q_m.bitreversed_lde_using_bitreversed_ntt(&worker, 4, omegas_bitreversed, &coset_generator)?;
517 let q_c_lde = q_c.bitreversed_lde_using_bitreversed_ntt(&worker, 4, omegas_bitreversed, &coset_generator)?;
518
519 let s_id_lde = s_id.bitreversed_lde_using_bitreversed_ntt(&worker, 4, omegas_bitreversed, &coset_generator)?;
520
521 let sigma_1_lde = sigma_1.bitreversed_lde_using_bitreversed_ntt(&worker, 4, omegas_bitreversed, &coset_generator)?;
522 let sigma_2_lde = sigma_2.bitreversed_lde_using_bitreversed_ntt(&worker, 4, omegas_bitreversed, &coset_generator)?;
523 let sigma_3_lde = sigma_3.bitreversed_lde_using_bitreversed_ntt(&worker, 4, omegas_bitreversed, &coset_generator)?;
524
525 let precomputation = PlonkSetupPrecomputation::<E> {
526 q_l_aux: q_l_lde,
527 q_r_aux: q_r_lde,
528 q_o_aux: q_o_lde,
529 q_m_aux: q_m_lde,
530 q_c_aux: q_c_lde,
531 s_id_aux: s_id_lde,
532 sigma_1_aux: sigma_1_lde,
533 sigma_2_aux: sigma_2_lde,
534 sigma_3_aux: sigma_3_lde,
535 };
536
537 Ok((setup, precomputation))
538}