zksync_bellman/plonk/plonk/
generator.rs

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    // const ZERO: Variable = Variable(Index::Aux(1));
35    // const ONE: Variable = Variable(Index::Aux(2));
36
37    // allocate a variable
38    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    // allocate an input variable
49    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    // enforce variable as boolean
65    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    // allocate an abstract gate
74    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    // allocate a constant
83    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    // allocate a multiplication gate
92    fn enforce_mul_2(&mut self, variables: (Variable, Variable)) -> Result<(), SynthesisError> {
93        // q_l, q_r, q_o, q_c = 0, q_m = 1
94        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    // allocate a multiplication gate
106    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    // allocate a linear combination gate
115    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    // allocate a linear combination gate
128    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        // let one = tmp.alloc(|| Ok(E::Fr::one())).expect("should have no issues");
174        // tmp.enforce_constant(one, E::Fr::one()).expect("should have no issues");
175
176        // match (zero, <Self as ConstraintSystem<E>>::ZERO) {
177        //     (Variable(Index::Aux(1)), Variable(Index::Aux(1))) => {},
178        //     _ => panic!("zero variable is incorrect")
179        // }
180
181        // match (one, <Self as ConstraintSystem<E>>::ONE) {
182        //     (Variable(Index::Aux(2)), Variable(Index::Aux(2))) => {},
183        //     _ => panic!("one variable is incorrect")
184        // }
185
186        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    // return variable that is not in a constraint formally, but has some value
198    fn dummy_variable(&self) -> Variable {
199        // <Self as ConstraintSystem<E>>::ZERO
200        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        // expect a small number of inputs
239        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        // in the partition number i there is a set of indexes in V = (a, b, c) such that V_j = i
302        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            // copy-permutation should have a cycle around the partition
362
363            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>, // q_l
398            Polynomial<E::Fr, Coefficients>, // q_r
399            Polynomial<E::Fr, Coefficients>, // q_o
400            Polynomial<E::Fr, Coefficients>, // q_m
401            Polynomial<E::Fr, Coefficients>, // q_c
402            Polynomial<E::Fr, Coefficients>, // s_id
403            Polynomial<E::Fr, Coefficients>, // sigma_1
404            Polynomial<E::Fr, Coefficients>, // sigma_2
405            Polynomial<E::Fr, Coefficients>, // sigma_3
406        ),
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}