1use crate::{
9 constants::{compute_coset_representatives, GATE_WIDTH, N_MUL_SELECTORS},
10 gates::*,
11 CircuitError,
12 CircuitError::*,
13};
14use ark_ff::{FftField, Field, PrimeField};
15use ark_poly::{
16 domain::Radix2EvaluationDomain, univariate::DensePolynomial, DenseUVPolynomial,
17 EvaluationDomain,
18};
19use ark_std::{boxed::Box, cmp::max, format, string::ToString, vec, vec::Vec};
20use hashbrown::{HashMap, HashSet};
21use jf_utils::par_utils::parallelizable_slice_iter;
22#[cfg(feature = "parallel")]
23use rayon::prelude::*;
24
25pub type GateId = usize;
27pub type WireId = usize;
32pub type Variable = usize;
34#[derive(Debug, Clone, Copy)]
36pub struct BoolVar(pub usize);
37
38impl From<BoolVar> for Variable {
39 fn from(bv: BoolVar) -> Self {
40 bv.0
41 }
42}
43
44impl BoolVar {
45 pub(crate) fn new_unchecked(inner: usize) -> Self {
50 Self(inner)
51 }
52}
53
54#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
55pub enum PlonkType {
57 TurboPlonk,
59 UltraPlonk,
61}
62
63#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
64pub enum MergeableCircuitType {
67 TypeA,
69 TypeB,
71}
72
73pub trait Circuit<F: Field> {
75 fn num_gates(&self) -> usize;
77
78 fn num_vars(&self) -> usize;
80
81 fn num_inputs(&self) -> usize;
83
84 fn num_wire_types(&self) -> usize;
88
89 fn public_input(&self) -> Result<Vec<F>, CircuitError>;
91
92 fn check_circuit_satisfiability(&self, pub_input: &[F]) -> Result<(), CircuitError>;
94
95 fn create_constant_variable(&mut self, val: F) -> Result<Variable, CircuitError>;
98
99 fn create_variable(&mut self, val: F) -> Result<Variable, CircuitError>;
101
102 fn create_boolean_variable(&mut self, val: bool) -> Result<BoolVar, CircuitError> {
104 let val_scalar = if val { F::one() } else { F::zero() };
105 let var = self.create_variable(val_scalar)?;
106 self.enforce_bool(var)?;
107 Ok(BoolVar(var))
108 }
109
110 fn create_public_variable(&mut self, val: F) -> Result<Variable, CircuitError>;
112
113 fn create_public_boolean_variable(&mut self, val: bool) -> Result<BoolVar, CircuitError> {
116 let val_scalar = if val { F::one() } else { F::zero() };
117 let var = self.create_public_variable(val_scalar)?;
118 Ok(BoolVar(var))
119 }
120
121 fn set_variable_public(&mut self, var: Variable) -> Result<(), CircuitError>;
123
124 fn zero(&self) -> Variable;
126
127 fn one(&self) -> Variable;
129
130 fn false_var(&self) -> BoolVar {
132 BoolVar::new_unchecked(self.zero())
133 }
134
135 fn true_var(&self) -> BoolVar {
137 BoolVar::new_unchecked(self.one())
138 }
139
140 fn witness(&self, idx: Variable) -> Result<F, CircuitError>;
143
144 fn enforce_constant(&mut self, var: Variable, constant: F) -> Result<(), CircuitError>;
149
150 fn add_gate(&mut self, a: Variable, b: Variable, c: Variable) -> Result<(), CircuitError>;
153
154 fn add(&mut self, a: Variable, b: Variable) -> Result<Variable, CircuitError>;
158
159 fn sub_gate(&mut self, a: Variable, b: Variable, c: Variable) -> Result<(), CircuitError>;
162
163 fn sub(&mut self, a: Variable, b: Variable) -> Result<Variable, CircuitError>;
167
168 fn mul_gate(&mut self, a: Variable, b: Variable, c: Variable) -> Result<(), CircuitError>;
171
172 fn mul(&mut self, a: Variable, b: Variable) -> Result<Variable, CircuitError>;
176
177 fn enforce_bool(&mut self, a: Variable) -> Result<(), CircuitError>;
180
181 fn enforce_equal(&mut self, a: Variable, b: Variable) -> Result<(), CircuitError>;
184
185 fn pad_gates(&mut self, n: usize);
187
188 fn support_lookup(&self) -> bool;
191}
192
193pub(crate) type SortedLookupVecAndPolys<F> = (Vec<F>, DensePolynomial<F>, DensePolynomial<F>);
197
198pub trait Arithmetization<F: FftField>: Circuit<F> {
201 fn srs_size(&self) -> Result<usize, CircuitError>;
203
204 fn eval_domain_size(&self) -> Result<usize, CircuitError>;
207
208 fn compute_selector_polynomials(&self) -> Result<Vec<DensePolynomial<F>>, CircuitError>;
211
212 fn compute_extended_permutation_polynomials(
215 &self,
216 ) -> Result<Vec<DensePolynomial<F>>, CircuitError>;
217
218 fn compute_prod_permutation_polynomial(
221 &self,
222 beta: &F,
223 gamma: &F,
224 ) -> Result<DensePolynomial<F>, CircuitError>;
225
226 fn compute_wire_polynomials(&self) -> Result<Vec<DensePolynomial<F>>, CircuitError>;
229
230 fn compute_pub_input_polynomial(&self) -> Result<DensePolynomial<F>, CircuitError>;
234
235 fn compute_range_table_polynomial(&self) -> Result<DensePolynomial<F>, CircuitError> {
243 Err(CircuitError::LookupUnsupported)
244 }
245
246 fn compute_key_table_polynomial(&self) -> Result<DensePolynomial<F>, CircuitError> {
250 Err(CircuitError::LookupUnsupported)
251 }
252
253 fn compute_table_dom_sep_polynomial(&self) -> Result<DensePolynomial<F>, CircuitError> {
257 Err(CircuitError::LookupUnsupported)
258 }
259
260 fn compute_q_dom_sep_polynomial(&self) -> Result<DensePolynomial<F>, CircuitError> {
264 Err(CircuitError::LookupUnsupported)
265 }
266
267 fn compute_merged_lookup_table(&self, _tau: F) -> Result<Vec<F>, CircuitError> {
270 Err(CircuitError::LookupUnsupported)
271 }
272
273 fn compute_lookup_sorted_vec_polynomials(
279 &self,
280 _tau: F,
281 _lookup_table: &[F],
282 ) -> Result<SortedLookupVecAndPolys<F>, CircuitError> {
283 Err(CircuitError::LookupUnsupported)
284 }
285
286 fn compute_lookup_prod_polynomial(
292 &self,
293 _tau: &F,
294 _beta: &F,
295 _gamma: &F,
296 _lookup_table: &[F],
297 _sorted_vec: &[F],
298 ) -> Result<DensePolynomial<F>, CircuitError> {
299 Err(CircuitError::LookupUnsupported)
300 }
301}
302
303const RANGE_WIRE_ID: usize = 5;
305const LOOKUP_KEY_WIRE_ID: usize = 0;
307const LOOKUP_VAL_1_WIRE_ID: usize = 1;
309const LOOKUP_VAL_2_WIRE_ID: usize = 2;
310const TABLE_VAL_1_WIRE_ID: usize = 3;
312const TABLE_VAL_2_WIRE_ID: usize = 4;
313
314#[derive(Debug, Clone, Copy)]
316struct PlonkParams {
317 plonk_type: PlonkType,
319
320 range_bit_len: Option<usize>,
322}
323
324impl PlonkParams {
325 fn init(plonk_type: PlonkType, range_bit_len: Option<usize>) -> Result<Self, CircuitError> {
326 if plonk_type == PlonkType::TurboPlonk {
327 return Ok(Self {
328 plonk_type,
329 range_bit_len: None,
330 });
331 }
332 if range_bit_len.is_none() {
333 return Err(ParameterError(
334 "range bit len cannot be none for UltraPlonk".to_string(),
335 ));
336 }
337
338 Ok(Self {
339 plonk_type,
340 range_bit_len,
341 })
342 }
343}
344
345#[derive(Debug, Clone)]
347pub struct PlonkCircuit<F>
348where
349 F: FftField,
350{
351 num_vars: usize,
353
354 gates: Vec<Box<dyn Gate<F>>>,
356 wire_variables: [Vec<Variable>; GATE_WIDTH + 2],
358 pub_input_gate_ids: Vec<GateId>,
360 witness: Vec<F>,
362
363 wire_permutation: Vec<(WireId, GateId)>,
376 extended_id_permutation: Vec<F>,
378 num_wire_types: usize,
380
381 eval_domain: Radix2EvaluationDomain<F>,
386
387 plonk_params: PlonkParams,
389
390 num_table_elems: usize,
392
393 table_gate_ids: Vec<(GateId, usize)>,
397}
398
399impl<F: FftField> Default for PlonkCircuit<F> {
400 fn default() -> Self {
401 let params = PlonkParams::init(PlonkType::TurboPlonk, None).unwrap();
402 Self::new(params)
403 }
404}
405
406impl<F: FftField> PlonkCircuit<F> {
407 fn new(plonk_params: PlonkParams) -> Self {
409 let zero = F::zero();
410 let one = F::one();
411 let mut circuit = Self {
412 num_vars: 2,
413 witness: vec![zero, one],
414 gates: vec![],
415 wire_variables: [vec![], vec![], vec![], vec![], vec![], vec![]],
417 pub_input_gate_ids: vec![],
418
419 wire_permutation: vec![],
420 extended_id_permutation: vec![],
421 num_wire_types: GATE_WIDTH
422 + 1
423 + match plonk_params.plonk_type {
424 PlonkType::TurboPlonk => 0,
425 PlonkType::UltraPlonk => 1,
426 },
427 eval_domain: Radix2EvaluationDomain::new(1).unwrap(),
428 plonk_params,
429 num_table_elems: 0,
430 table_gate_ids: vec![],
431 };
432 circuit.enforce_constant(0, zero).unwrap(); circuit.enforce_constant(1, one).unwrap(); circuit
436 }
437
438 pub fn new_turbo_plonk() -> Self {
440 let plonk_params = PlonkParams::init(PlonkType::TurboPlonk, None).unwrap(); Self::new(plonk_params)
442 }
443
444 pub fn new_ultra_plonk(range_bit_len: usize) -> Self {
446 let plonk_params = PlonkParams::init(PlonkType::UltraPlonk, Some(range_bit_len)).unwrap(); Self::new(plonk_params)
448 }
449
450 pub fn insert_gate(
455 &mut self,
456 wire_vars: &[Variable; GATE_WIDTH + 1],
457 gate: Box<dyn Gate<F>>,
458 ) -> Result<(), CircuitError> {
459 self.check_finalize_flag(false)?;
460
461 for (wire_var, wire_variable) in wire_vars
462 .iter()
463 .zip(self.wire_variables.iter_mut().take(GATE_WIDTH + 1))
464 {
465 wire_variable.push(*wire_var)
466 }
467
468 self.gates.push(gate);
469 Ok(())
470 }
471
472 pub fn add_range_check_variable(&mut self, var: Variable) -> Result<(), CircuitError> {
476 self.check_plonk_type(PlonkType::UltraPlonk)?;
477 self.check_finalize_flag(false)?;
478 self.check_var_bound(var)?;
479 self.wire_variables[RANGE_WIRE_ID].push(var);
480 Ok(())
481 }
482
483 #[inline]
484 pub fn check_var_bound(&self, var: Variable) -> Result<(), CircuitError> {
491 if var >= self.num_vars {
492 return Err(VarIndexOutOfBound(var, self.num_vars));
493 }
494 Ok(())
495 }
496
497 pub fn check_vars_bound(&self, vars: &[Variable]) -> Result<(), CircuitError> {
503 for &var in vars {
504 self.check_var_bound(var)?
505 }
506 Ok(())
507 }
508
509 pub fn witness_mut(&mut self, idx: Variable) -> &mut F {
512 &mut self.witness[idx]
513 }
514
515 pub(crate) fn table_gate_ids_mut(&mut self) -> &mut Vec<(GateId, usize)> {
517 &mut self.table_gate_ids
518 }
519
520 pub(crate) fn num_table_elems_mut(&mut self) -> &mut usize {
522 &mut self.num_table_elems
523 }
524
525 pub(crate) fn num_table_elems(&self) -> usize {
527 self.num_table_elems
528 }
529
530 pub fn range_bit_len(&self) -> Result<usize, CircuitError> {
532 if self.plonk_params.plonk_type != PlonkType::UltraPlonk {
533 return Err(ParameterError(
534 "call range_bit_len() with non-ultraplonk circuit".to_string(),
535 ));
536 }
537 Ok(self.plonk_params.range_bit_len.unwrap()) }
539
540 pub fn range_size(&self) -> Result<usize, CircuitError> {
542 Ok(1 << self.range_bit_len()?)
543 }
544
545 pub(crate) fn create_boolean_variable_unchecked(
550 &mut self,
551 a: F,
552 ) -> Result<BoolVar, CircuitError> {
553 let var = self.create_variable(a)?;
554 Ok(BoolVar::new_unchecked(var))
555 }
556}
557
558impl<F: FftField> Circuit<F> for PlonkCircuit<F> {
559 fn num_gates(&self) -> usize {
560 self.gates.len()
561 }
562
563 fn num_vars(&self) -> usize {
564 self.num_vars
565 }
566
567 fn num_inputs(&self) -> usize {
568 self.pub_input_gate_ids.len()
569 }
570
571 fn num_wire_types(&self) -> usize {
572 self.num_wire_types
573 }
574
575 fn public_input(&self) -> Result<Vec<F>, CircuitError> {
576 self.pub_input_gate_ids
577 .iter()
578 .map(|&gate_id| -> Result<F, CircuitError> {
579 let var = self.wire_variables[GATE_WIDTH][gate_id];
580 self.witness(var)
581 })
582 .collect::<Result<Vec<F>, CircuitError>>()
583 }
584
585 fn check_circuit_satisfiability(&self, pub_input: &[F]) -> Result<(), CircuitError> {
586 if pub_input.len() != self.num_inputs() {
587 return Err(PubInputLenMismatch(
588 pub_input.len(),
589 self.pub_input_gate_ids.len(),
590 ));
591 }
592 for (i, gate_id) in self.pub_input_gate_ids.iter().enumerate() {
594 let pi = pub_input[i];
595 self.check_gate(*gate_id, &pi)?;
596 }
597 for gate_id in 0..self.num_gates() {
599 if !self.is_io_gate(gate_id) {
600 let pi = F::zero();
601 self.check_gate(gate_id, &pi)?;
602 }
603 }
604 if self.plonk_params.plonk_type == PlonkType::UltraPlonk {
606 for idx in 0..self.wire_variables[RANGE_WIRE_ID].len() {
608 self.check_range_gate(idx)?
609 }
610 let mut key_val_table = HashSet::new();
612 key_val_table.insert((F::zero(), F::zero(), F::zero(), F::zero()));
613 let q_lookup_vec = self.q_lookup();
614 let q_dom_sep_vec = self.q_dom_sep();
615 let table_key_vec = self.table_key_vec();
616 let table_dom_sep_vec = self.table_dom_sep_vec();
617 for (gate_id, ((&q_lookup, &table_dom_sep), &table_key)) in q_lookup_vec
619 .iter()
620 .zip(table_dom_sep_vec.iter())
621 .zip(table_key_vec.iter())
622 .enumerate()
623 {
624 if q_lookup != F::zero() {
625 let val0 = self.witness(self.wire_variable(TABLE_VAL_1_WIRE_ID, gate_id))?;
626 let val1 = self.witness(self.wire_variable(TABLE_VAL_2_WIRE_ID, gate_id))?;
627 key_val_table.insert((table_dom_sep, table_key, val0, val1));
628 }
629 }
630 for (gate_id, (&q_lookup, &q_dom_sep)) in
632 q_lookup_vec.iter().zip(q_dom_sep_vec.iter()).enumerate()
633 {
634 if q_lookup != F::zero() {
635 let key = self.witness(self.wire_variable(LOOKUP_KEY_WIRE_ID, gate_id))?;
636 let val0 = self.witness(self.wire_variable(LOOKUP_VAL_1_WIRE_ID, gate_id))?;
637 let val1 = self.witness(self.wire_variable(LOOKUP_VAL_2_WIRE_ID, gate_id))?;
638 if !key_val_table.contains(&(q_dom_sep, key, val0, val1)) {
639 return Err(GateCheckFailure(
640 gate_id,
641 format!(
642 "Lookup gate failed: ({q_dom_sep}, {key}, {val0}, {val1}) not in the table",
643 ),
644 ));
645 }
646 }
647 }
648 }
649 Ok(())
650 }
651
652 fn create_constant_variable(&mut self, val: F) -> Result<Variable, CircuitError> {
653 let var = self.create_variable(val)?;
654 self.enforce_constant(var, val)?;
655 Ok(var)
656 }
657
658 fn create_variable(&mut self, val: F) -> Result<Variable, CircuitError> {
659 self.check_finalize_flag(false)?;
660 self.witness.push(val);
661 self.num_vars += 1;
662 Ok(self.num_vars - 1)
664 }
665
666 fn create_public_variable(&mut self, val: F) -> Result<Variable, CircuitError> {
667 let var = self.create_variable(val)?;
668 self.set_variable_public(var)?;
669 Ok(var)
670 }
671
672 fn set_variable_public(&mut self, var: Variable) -> Result<(), CircuitError> {
673 self.check_finalize_flag(false)?;
674 self.pub_input_gate_ids.push(self.num_gates());
675
676 let wire_vars = &[0, 0, 0, 0, var];
678 self.insert_gate(wire_vars, Box::new(IoGate))?;
679 Ok(())
680 }
681
682 fn zero(&self) -> Variable {
684 0
685 }
686
687 fn one(&self) -> Variable {
689 1
690 }
691
692 fn witness(&self, idx: Variable) -> Result<F, CircuitError> {
693 self.check_var_bound(idx)?;
694 Ok(self.witness[idx])
695 }
696
697 fn enforce_constant(&mut self, var: Variable, constant: F) -> Result<(), CircuitError> {
698 self.check_var_bound(var)?;
699
700 let wire_vars = &[0, 0, 0, 0, var];
701 self.insert_gate(wire_vars, Box::new(ConstantGate(constant)))?;
702 Ok(())
703 }
704
705 fn add_gate(&mut self, a: Variable, b: Variable, c: Variable) -> Result<(), CircuitError> {
706 self.check_var_bound(a)?;
707 self.check_var_bound(b)?;
708 self.check_var_bound(c)?;
709
710 let wire_vars = &[a, b, 0, 0, c];
711 self.insert_gate(wire_vars, Box::new(AdditionGate))?;
712 Ok(())
713 }
714
715 fn add(&mut self, a: Variable, b: Variable) -> Result<Variable, CircuitError> {
716 self.check_var_bound(a)?;
717 self.check_var_bound(b)?;
718 let val = self.witness(a)? + self.witness(b)?;
719 let c = self.create_variable(val)?;
720 self.add_gate(a, b, c)?;
721 Ok(c)
722 }
723
724 fn sub_gate(&mut self, a: Variable, b: Variable, c: Variable) -> Result<(), CircuitError> {
725 self.check_var_bound(a)?;
726 self.check_var_bound(b)?;
727 self.check_var_bound(c)?;
728
729 let wire_vars = &[a, b, 0, 0, c];
730 self.insert_gate(wire_vars, Box::new(SubtractionGate))?;
731 Ok(())
732 }
733
734 fn sub(&mut self, a: Variable, b: Variable) -> Result<Variable, CircuitError> {
735 self.check_var_bound(a)?;
736 self.check_var_bound(b)?;
737 let val = self.witness(a)? - self.witness(b)?;
738 let c = self.create_variable(val)?;
739 self.sub_gate(a, b, c)?;
740 Ok(c)
741 }
742
743 fn mul_gate(&mut self, a: Variable, b: Variable, c: Variable) -> Result<(), CircuitError> {
744 self.check_var_bound(a)?;
745 self.check_var_bound(b)?;
746 self.check_var_bound(c)?;
747
748 let wire_vars = &[a, b, 0, 0, c];
749 self.insert_gate(wire_vars, Box::new(MultiplicationGate))?;
750 Ok(())
751 }
752
753 fn mul(&mut self, a: Variable, b: Variable) -> Result<Variable, CircuitError> {
754 self.check_var_bound(a)?;
755 self.check_var_bound(b)?;
756 let val = self.witness(a)? * self.witness(b)?;
757 let c = self.create_variable(val)?;
758 self.mul_gate(a, b, c)?;
759 Ok(c)
760 }
761
762 fn enforce_bool(&mut self, a: Variable) -> Result<(), CircuitError> {
763 self.check_var_bound(a)?;
764
765 let wire_vars = &[a, a, 0, 0, a];
766 self.insert_gate(wire_vars, Box::new(BoolGate))?;
767 Ok(())
768 }
769
770 fn enforce_equal(&mut self, a: Variable, b: Variable) -> Result<(), CircuitError> {
771 self.check_var_bound(a)?;
772 self.check_var_bound(b)?;
773
774 let wire_vars = &[a, b, 0, 0, 0];
775 self.insert_gate(wire_vars, Box::new(EqualityGate))?;
776 Ok(())
777 }
778
779 fn pad_gates(&mut self, n: usize) {
780 let wire_vars = &[self.zero(), self.zero(), 0, 0, 0];
787 for _ in 0..n {
788 self.insert_gate(wire_vars, Box::new(EqualityGate)).unwrap();
789 }
790 }
791
792 fn support_lookup(&self) -> bool {
795 self.plonk_params.plonk_type == PlonkType::UltraPlonk
796 }
797}
798
799impl<F: FftField> PlonkCircuit<F> {
801 fn check_range_gate(&self, idx: usize) -> Result<(), CircuitError> {
804 self.check_plonk_type(PlonkType::UltraPlonk)?;
805 if idx >= self.wire_variables[RANGE_WIRE_ID].len() {
806 return Err(IndexError);
807 }
808 let range_size = self.range_size()?;
809 if self.witness[self.wire_variables[RANGE_WIRE_ID][idx]] >= F::from(range_size as u32) {
810 return Err(GateCheckFailure(
811 idx,
812 format!(
813 "Range gate failed: {} >= {}",
814 self.witness[self.wire_variables[RANGE_WIRE_ID][idx]], range_size
815 ),
816 ));
817 }
818 Ok(())
819 }
820
821 fn is_finalized(&self) -> bool {
822 self.eval_domain.size() != 1
823 }
824
825 fn rearrange_gates(&mut self) -> Result<(), CircuitError> {
832 self.check_finalize_flag(true)?;
833 for (gate_id, io_gate_id) in self.pub_input_gate_ids.iter_mut().enumerate() {
834 if *io_gate_id > gate_id {
835 self.gates.swap(gate_id, *io_gate_id);
837 for i in 0..GATE_WIDTH + 1 {
839 self.wire_variables[i].swap(gate_id, *io_gate_id);
840 }
841 *io_gate_id = gate_id;
843 }
844 }
845 if self.support_lookup() {
846 let n = self.eval_domain.size();
849 let mut cur_gate_id = n - 2;
851 for &(table_gate_id, table_size) in self.table_gate_ids.iter().rev() {
852 for gate_id in (table_gate_id..table_gate_id + table_size).rev() {
853 if gate_id < cur_gate_id {
854 self.gates.swap(gate_id, cur_gate_id);
856 for j in 0..GATE_WIDTH + 1 {
858 self.wire_variables[j].swap(gate_id, cur_gate_id);
859 }
860 cur_gate_id -= 1;
861 }
862 }
863 }
864 }
865 Ok(())
866 }
867 fn is_io_gate(&self, gate_id: GateId) -> bool {
869 self.gates[gate_id].as_any().is::<IoGate>()
870 }
871
872 fn pad(&mut self) -> Result<(), CircuitError> {
875 self.check_finalize_flag(true)?;
876 let n = self.eval_domain.size();
877 for _ in self.num_gates()..n {
878 self.gates.push(Box::new(PaddingGate));
879 }
880 for wire_id in 0..self.num_wire_types() {
881 self.wire_variables[wire_id].resize(n, self.zero());
882 }
883 Ok(())
884 }
885
886 fn check_gate(&self, gate_id: Variable, pub_input: &F) -> Result<(), CircuitError> {
895 let w_vals: Vec<F> = (0..GATE_WIDTH + 1)
898 .map(|i| self.witness[self.wire_variables[i][gate_id]])
899 .collect();
900 let q_lc: [F; GATE_WIDTH] = self.gates[gate_id].q_lc();
902 let q_mul: [F; N_MUL_SELECTORS] = self.gates[gate_id].q_mul();
903 let q_hash: [F; GATE_WIDTH] = self.gates[gate_id].q_hash();
904 let q_c = self.gates[gate_id].q_c();
905 let q_o = self.gates[gate_id].q_o();
906 let q_ecc = self.gates[gate_id].q_ecc();
907
908 let expected_gate_output = *pub_input
910 + q_lc[0] * w_vals[0]
911 + q_lc[1] * w_vals[1]
912 + q_lc[2] * w_vals[2]
913 + q_lc[3] * w_vals[3]
914 + q_mul[0] * w_vals[0] * w_vals[1]
915 + q_mul[1] * w_vals[2] * w_vals[3]
916 + q_ecc * w_vals[0] * w_vals[1] * w_vals[2] * w_vals[3] * w_vals[4]
917 + q_hash[0] * w_vals[0].pow([5])
918 + q_hash[1] * w_vals[1].pow([5])
919 + q_hash[2] * w_vals[2].pow([5])
920 + q_hash[3] * w_vals[3].pow([5])
921 + q_c;
922 let gate_output = q_o * w_vals[4];
923 if expected_gate_output != gate_output {
924 return Err(
925 GateCheckFailure(
926 gate_id,
927 format!(
928 "gate: {:?}, wire values: {:?}, pub_input: {}, expected_gate_output: {}, gate_output: {}",
929 self.gates[gate_id],
930 w_vals,
931 pub_input,
932 expected_gate_output,
933 gate_output
934 )
935 ));
936 }
937 Ok(())
938 }
939
940 #[inline]
943 fn compute_wire_permutation(&mut self) {
944 assert!(self.is_finalized());
945 let n = self.eval_domain.size();
946 let m = self.num_vars();
947
948 let mut variable_wires_map = vec![vec![]; m];
955 for (gate_wire_id, variables) in self
956 .wire_variables
957 .iter()
958 .take(self.num_wire_types())
959 .enumerate()
960 {
961 for (gate_id, &var) in variables.iter().enumerate() {
962 variable_wires_map[var].push((gate_wire_id, gate_id));
963 }
964 }
965
966 self.wire_permutation = vec![(0usize, 0usize); self.num_wire_types * n];
968 for wires_vec in variable_wires_map.iter_mut() {
969 if !wires_vec.is_empty() {
971 wires_vec.push(wires_vec[0]);
974 for window in wires_vec.windows(2) {
975 self.wire_permutation[window[0].0 * n + window[0].1] = window[1];
976 }
977 wires_vec.pop();
979 }
980 }
981 }
982
983 #[inline]
986 fn check_finalize_flag(&self, expect_finalized: bool) -> Result<(), CircuitError> {
987 if !self.is_finalized() && expect_finalized {
988 return Err(UnfinalizedCircuit);
989 }
990 if self.is_finalized() && !expect_finalized {
991 return Err(ModifyFinalizedCircuit);
992 }
993 Ok(())
994 }
995
996 #[inline]
999 fn check_plonk_type(&self, expect_type: PlonkType) -> Result<(), CircuitError> {
1000 if self.plonk_params.plonk_type != expect_type {
1001 return Err(WrongPlonkType);
1002 }
1003 Ok(())
1004 }
1005
1006 #[inline]
1010 fn wire_variable(&self, i: WireId, j: GateId) -> Variable {
1011 match j < self.wire_variables[i].len() {
1012 true => self.wire_variables[i][j],
1013 false => self.zero(),
1014 }
1015 }
1016
1017 #[inline]
1019 fn q_lc(&self) -> [Vec<F>; GATE_WIDTH] {
1020 let mut result = [vec![], vec![], vec![], vec![]];
1021 for gate in &self.gates {
1022 let q_lc_vec = gate.q_lc();
1023 result[0].push(q_lc_vec[0]);
1024 result[1].push(q_lc_vec[1]);
1025 result[2].push(q_lc_vec[2]);
1026 result[3].push(q_lc_vec[3]);
1027 }
1028 result
1029 }
1030 #[inline]
1032 fn q_mul(&self) -> [Vec<F>; N_MUL_SELECTORS] {
1033 let mut result = [vec![], vec![]];
1034 for gate in &self.gates {
1035 let q_mul_vec = gate.q_mul();
1036 result[0].push(q_mul_vec[0]);
1037 result[1].push(q_mul_vec[1]);
1038 }
1039 result
1040 }
1041 #[inline]
1043 fn q_hash(&self) -> [Vec<F>; GATE_WIDTH] {
1044 let mut result = [vec![], vec![], vec![], vec![]];
1045 for gate in &self.gates {
1046 let q_hash_vec = gate.q_hash();
1047 result[0].push(q_hash_vec[0]);
1048 result[1].push(q_hash_vec[1]);
1049 result[2].push(q_hash_vec[2]);
1050 result[3].push(q_hash_vec[3]);
1051 }
1052 result
1053 }
1054 #[inline]
1056 fn q_o(&self) -> Vec<F> {
1057 self.gates.iter().map(|g| g.q_o()).collect()
1058 }
1059 #[inline]
1061 fn q_c(&self) -> Vec<F> {
1062 self.gates.iter().map(|g| g.q_c()).collect()
1063 }
1064 #[inline]
1066 fn q_ecc(&self) -> Vec<F> {
1067 self.gates.iter().map(|g| g.q_ecc()).collect()
1068 }
1069 #[inline]
1071 fn q_lookup(&self) -> Vec<F> {
1072 self.gates.iter().map(|g| g.q_lookup()).collect()
1073 }
1074 #[inline]
1076 fn q_dom_sep(&self) -> Vec<F> {
1077 self.gates.iter().map(|g| g.q_dom_sep()).collect()
1078 }
1079 #[inline]
1081 fn table_key_vec(&self) -> Vec<F> {
1082 self.gates.iter().map(|g| g.table_key()).collect()
1083 }
1084 #[inline]
1086 fn table_dom_sep_vec(&self) -> Vec<F> {
1087 self.gates.iter().map(|g| g.table_dom_sep()).collect()
1088 }
1089 #[inline]
1093 fn all_selectors(&self) -> Vec<Vec<F>> {
1094 let mut selectors = vec![];
1095 self.q_lc()
1096 .as_ref()
1097 .iter()
1098 .chain(self.q_mul().as_ref().iter())
1099 .chain(self.q_hash().as_ref().iter())
1100 .for_each(|s| selectors.push(s.clone()));
1101 selectors.push(self.q_o());
1102 selectors.push(self.q_c());
1103 selectors.push(self.q_ecc());
1104 if self.support_lookup() {
1105 selectors.push(self.q_lookup());
1106 }
1107 selectors
1108 }
1109}
1110
1111impl<F: PrimeField> PlonkCircuit<F> {
1113 #[inline]
1116 fn compute_extended_id_permutation(&mut self) {
1117 assert!(self.is_finalized());
1118 let n = self.eval_domain.size();
1119
1120 let k: Vec<F> = compute_coset_representatives(self.num_wire_types, Some(n));
1123 let group_elems: Vec<F> = self.eval_domain.elements().collect();
1125 self.extended_id_permutation = vec![F::zero(); self.num_wire_types * n];
1127 for (i, &coset_repr) in k.iter().enumerate() {
1128 for (j, &group_elem) in group_elems.iter().enumerate() {
1129 self.extended_id_permutation[i * n + j] = coset_repr * group_elem;
1130 }
1131 }
1132 }
1133
1134 #[inline]
1135 fn compute_extended_permutation(&self) -> Result<Vec<F>, CircuitError> {
1136 assert!(self.is_finalized());
1137 let n = self.eval_domain.size();
1138
1139 let extended_perm: Vec<F> = self
1142 .wire_permutation
1143 .iter()
1144 .map(|&(wire_id, gate_id)| {
1145 if wire_id >= self.num_wire_types {
1147 F::zero()
1148 } else {
1149 self.extended_id_permutation[wire_id * n + gate_id]
1150 }
1151 })
1152 .collect();
1153 if extended_perm.len() != self.num_wire_types * n {
1154 return Err(ParameterError(
1155 "Length of the extended permutation vector should be number of gate \
1156 (including padded dummy gates) * number of wire types"
1157 .to_string(),
1158 ));
1159 }
1160 Ok(extended_perm)
1161 }
1162}
1163
1164impl<F: PrimeField> PlonkCircuit<F> {
1166 pub fn finalize_for_arithmetization(&mut self) -> Result<(), CircuitError> {
1168 if self.is_finalized() {
1169 return Ok(());
1170 }
1171 let num_slots_needed = match self.support_lookup() {
1172 false => self.num_gates(),
1173 true => max(
1174 self.num_gates(),
1175 max(self.range_size()?, self.wire_variables[RANGE_WIRE_ID].len())
1176 + self.num_table_elems()
1177 + 1,
1178 ), };
1180 self.eval_domain = Radix2EvaluationDomain::new(num_slots_needed)
1181 .ok_or(CircuitError::DomainCreationError)?;
1182 self.pad()?;
1183 self.rearrange_gates()?;
1184 self.compute_wire_permutation();
1185 self.compute_extended_id_permutation();
1186 Ok(())
1187 }
1188
1189 pub fn finalize_for_mergeable_circuit(
1193 &mut self,
1194 circuit_type: MergeableCircuitType,
1195 ) -> Result<(), CircuitError> {
1196 if self.plonk_params.plonk_type != PlonkType::TurboPlonk {
1197 return Err(WrongPlonkType);
1198 }
1199 self.finalize_for_arithmetization()?;
1200 let n = self.eval_domain_size()?;
1202 self.eval_domain =
1203 Radix2EvaluationDomain::new(2 * n).ok_or(CircuitError::DomainCreationError)?;
1204 for _ in 0..n {
1206 self.gates.push(Box::new(PaddingGate));
1207 }
1208 for wire_id in 0..self.num_wire_types() {
1209 self.wire_variables[wire_id].resize(2 * n, self.zero());
1210 }
1211 if circuit_type == MergeableCircuitType::TypeA {
1212 let mut wire_perm = vec![(self.num_wire_types, 0usize); self.num_wire_types * 2 * n];
1214 for i in 0..self.num_wire_types {
1215 for j in 0..n {
1216 wire_perm[i * 2 * n + j] = self.wire_permutation[i * n + j];
1217 }
1218 }
1219 self.wire_permutation = wire_perm;
1220 } else {
1221 self.gates.reverse();
1223 for wire_id in 0..self.num_wire_types() {
1224 self.wire_variables[wire_id].reverse();
1225 }
1226 for io_gate in self.pub_input_gate_ids.iter_mut() {
1227 *io_gate = 2 * n - 1 - *io_gate;
1228 }
1229 let mut wire_perm = vec![(self.num_wire_types, 0usize); self.num_wire_types * 2 * n];
1231 for i in 0..self.num_wire_types {
1232 for j in 0..n {
1233 let (wire_id, gate_id) = self.wire_permutation[i * n + j];
1234 let gate_id = 2 * n - 1 - gate_id;
1236 wire_perm[i * 2 * n + 2 * n - 1 - j] = (wire_id, gate_id);
1237 }
1238 }
1239 self.wire_permutation = wire_perm;
1240 }
1241 self.compute_extended_id_permutation();
1243 Ok(())
1244 }
1245
1246 #[allow(dead_code)]
1250 pub fn merge(&self, other: &Self) -> Result<Self, CircuitError> {
1251 self.check_finalize_flag(true)?;
1252 other.check_finalize_flag(true)?;
1253 if self.eval_domain_size()? != other.eval_domain_size()? {
1254 return Err(ParameterError(format!(
1255 "cannot merge circuits with different domain sizes: {}, {}",
1256 self.eval_domain_size()?,
1257 other.eval_domain_size()?
1258 )));
1259 }
1260 if self.plonk_params.plonk_type != PlonkType::TurboPlonk
1261 || other.plonk_params.plonk_type != PlonkType::TurboPlonk
1262 {
1263 return Err(ParameterError(
1264 "do not support merging non-TurboPlonk circuits.".to_string(),
1265 ));
1266 }
1267 if self.num_inputs() != other.num_inputs() {
1268 return Err(ParameterError(format!(
1269 "self.num_inputs = {} different from other.num_inputs = {}",
1270 self.num_inputs(),
1271 other.num_inputs()
1272 )));
1273 }
1274 if self.pub_input_gate_ids[0] != 0 {
1275 return Err(ParameterError(
1276 "the first circuit is not type A".to_string(),
1277 ));
1278 }
1279 if other.pub_input_gate_ids[0] != other.eval_domain_size()? - 1 {
1280 return Err(ParameterError(
1281 "the second circuit is not type B".to_string(),
1282 ));
1283 }
1284 let num_vars = self.num_vars + other.num_vars;
1285 let witness: Vec<F> = [self.witness.as_slice(), other.witness.as_slice()].concat();
1286 let pub_input_gate_ids: Vec<usize> = [
1287 self.pub_input_gate_ids.as_slice(),
1288 other.pub_input_gate_ids.as_slice(),
1289 ]
1290 .concat();
1291
1292 let n = self.eval_domain_size()? / 2;
1296 let mut gates = vec![];
1297 let mut wire_variables = [vec![], vec![], vec![], vec![], vec![], vec![]];
1298 for (j, gate) in self.gates.iter().take(n).enumerate() {
1299 gates.push((*gate).clone());
1300 for (i, wire_vars) in wire_variables
1301 .iter_mut()
1302 .enumerate()
1303 .take(self.num_wire_types)
1304 {
1305 wire_vars.push(self.wire_variable(i, j));
1306 }
1307 }
1308 for (j, gate) in other.gates.iter().skip(n).enumerate() {
1309 gates.push((*gate).clone());
1310 for (i, wire_vars) in wire_variables
1311 .iter_mut()
1312 .enumerate()
1313 .take(self.num_wire_types)
1314 {
1315 wire_vars.push(other.wire_variable(i, n + j) + self.num_vars);
1316 }
1317 }
1318
1319 let mut wire_permutation = vec![(0usize, 0usize); self.num_wire_types * 2 * n];
1321 for i in 0..self.num_wire_types {
1322 for j in 0..n {
1323 wire_permutation[i * 2 * n + j] = self.wire_permutation[i * 2 * n + j];
1324 wire_permutation[i * 2 * n + n + j] = other.wire_permutation[i * 2 * n + n + j];
1325 }
1326 }
1327
1328 Ok(Self {
1329 num_vars,
1330 witness,
1331 gates,
1332 wire_variables,
1333 pub_input_gate_ids,
1334 wire_permutation,
1335 extended_id_permutation: self.extended_id_permutation.clone(),
1336 num_wire_types: self.num_wire_types,
1337 eval_domain: self.eval_domain,
1338 plonk_params: self.plonk_params,
1339 num_table_elems: 0,
1340 table_gate_ids: vec![],
1341 })
1342 }
1343}
1344
1345impl<F> Arithmetization<F> for PlonkCircuit<F>
1346where
1347 F: PrimeField,
1348{
1349 fn srs_size(&self) -> Result<usize, CircuitError> {
1350 Ok(self.eval_domain_size()? + 2)
1352 }
1353
1354 fn eval_domain_size(&self) -> Result<usize, CircuitError> {
1355 self.check_finalize_flag(true)?;
1356 Ok(self.eval_domain.size())
1357 }
1358
1359 fn compute_selector_polynomials(&self) -> Result<Vec<DensePolynomial<F>>, CircuitError> {
1360 self.check_finalize_flag(true)?;
1361 let domain = &self.eval_domain;
1362 if domain.size() < self.num_gates() {
1363 return Err(ParameterError(
1364 "Domain size should be bigger than number of constraint".to_string(),
1365 ));
1366 }
1367 let selector_polys = parallelizable_slice_iter(&self.all_selectors())
1369 .map(|selector| DensePolynomial::from_coefficients_vec(domain.ifft(selector)))
1370 .collect();
1371 Ok(selector_polys)
1372 }
1373
1374 fn compute_extended_permutation_polynomials(
1375 &self,
1376 ) -> Result<Vec<DensePolynomial<F>>, CircuitError> {
1377 self.check_finalize_flag(true)?;
1378 let domain = &self.eval_domain;
1379 let n = domain.size();
1380 let extended_perm = self.compute_extended_permutation()?;
1381
1382 let extended_perm_polys: Vec<DensePolynomial<F>> =
1383 parallelizable_slice_iter(&(0..self.num_wire_types).collect::<Vec<_>>()) .map(|i| {
1385 DensePolynomial::from_coefficients_vec(
1386 domain.ifft(&extended_perm[i * n..(i + 1) * n]),
1387 )
1388 })
1389 .collect();
1390
1391 Ok(extended_perm_polys)
1392 }
1393
1394 fn compute_prod_permutation_polynomial(
1395 &self,
1396 beta: &F,
1397 gamma: &F,
1398 ) -> Result<DensePolynomial<F>, CircuitError> {
1399 self.check_finalize_flag(true)?;
1400 let mut product_vec = vec![F::one()];
1401 let domain = &self.eval_domain;
1402 let n = domain.size();
1403 for j in 0..(n - 1) {
1404 let mut a = F::one();
1406 let mut b = F::one();
1408 for i in 0..self.num_wire_types {
1409 let wire_value = self.witness[self.wire_variable(i, j)];
1410 let tmp = wire_value + gamma;
1411 a *= tmp + *beta * self.extended_id_permutation[i * n + j];
1412 let (perm_i, perm_j) = self.wire_permutation[i * n + j];
1413 b *= tmp + *beta * self.extended_id_permutation[perm_i * n + perm_j];
1414 }
1415 let prev_prod = *product_vec.last().ok_or(CircuitError::IndexError)?;
1416 product_vec.push(prev_prod * a / b);
1417 }
1418 domain.ifft_in_place(&mut product_vec);
1419 Ok(DensePolynomial::from_coefficients_vec(product_vec))
1420 }
1421
1422 fn compute_wire_polynomials(&self) -> Result<Vec<DensePolynomial<F>>, CircuitError> {
1423 self.check_finalize_flag(true)?;
1424 let domain = &self.eval_domain;
1425 if domain.size() < self.num_gates() {
1426 return Err(ParameterError(format!(
1427 "Domain size {} should be bigger than number of constraint {}",
1428 domain.size(),
1429 self.num_gates()
1430 )));
1431 }
1432 let witness = &self.witness;
1433 let wire_polys: Vec<DensePolynomial<F>> = parallelizable_slice_iter(&self.wire_variables)
1434 .take(self.num_wire_types())
1435 .map(|wire_vars| {
1436 let mut wire_vec: Vec<F> = wire_vars.iter().map(|&var| witness[var]).collect();
1437 domain.ifft_in_place(&mut wire_vec);
1438 DensePolynomial::from_coefficients_vec(wire_vec)
1439 })
1440 .collect();
1441
1442 assert_eq!(wire_polys.len(), self.num_wire_types());
1443 Ok(wire_polys)
1444 }
1445
1446 fn compute_pub_input_polynomial(&self) -> Result<DensePolynomial<F>, CircuitError> {
1447 self.check_finalize_flag(true)?;
1448 let domain = &self.eval_domain;
1449 let mut pub_input_vec = vec![F::zero(); domain.size()];
1450 self.pub_input_gate_ids.iter().for_each(|&io_gate_id| {
1451 let var = self.wire_variables[GATE_WIDTH][io_gate_id];
1452 pub_input_vec[io_gate_id] = self.witness[var];
1453 });
1454 domain.ifft_in_place(&mut pub_input_vec);
1455 Ok(DensePolynomial::from_coefficients_vec(pub_input_vec))
1456 }
1457
1458 fn compute_range_table_polynomial(&self) -> Result<DensePolynomial<F>, CircuitError> {
1461 let range_table = self.compute_range_table()?;
1462 let domain = &self.eval_domain;
1463 Ok(DensePolynomial::from_coefficients_vec(
1464 domain.ifft(&range_table),
1465 ))
1466 }
1467
1468 fn compute_key_table_polynomial(&self) -> Result<DensePolynomial<F>, CircuitError> {
1469 self.check_plonk_type(PlonkType::UltraPlonk)?;
1470 self.check_finalize_flag(true)?;
1471 let domain = &self.eval_domain;
1472 Ok(DensePolynomial::from_coefficients_vec(
1473 domain.ifft(&self.table_key_vec()),
1474 ))
1475 }
1476
1477 fn compute_table_dom_sep_polynomial(&self) -> Result<DensePolynomial<F>, CircuitError> {
1478 self.check_plonk_type(PlonkType::UltraPlonk)?;
1479 self.check_finalize_flag(true)?;
1480 let domain = &self.eval_domain;
1481 Ok(DensePolynomial::from_coefficients_vec(
1482 domain.ifft(&self.table_dom_sep_vec()),
1483 ))
1484 }
1485
1486 fn compute_q_dom_sep_polynomial(&self) -> Result<DensePolynomial<F>, CircuitError> {
1487 self.check_plonk_type(PlonkType::UltraPlonk)?;
1488 self.check_finalize_flag(true)?;
1489 let domain = &self.eval_domain;
1490 Ok(DensePolynomial::from_coefficients_vec(
1491 domain.ifft(&self.q_dom_sep()),
1492 ))
1493 }
1494
1495 fn compute_merged_lookup_table(&self, tau: F) -> Result<Vec<F>, CircuitError> {
1496 let range_table = self.compute_range_table()?;
1497 let table_key_vec = self.table_key_vec();
1498 let table_dom_sep_vec = self.table_dom_sep_vec();
1499 let q_lookup_vec = self.q_lookup();
1500
1501 let mut merged_lookup_table = vec![];
1502 for i in 0..self.eval_domain_size()? {
1503 merged_lookup_table.push(self.merged_table_value(
1504 tau,
1505 &range_table,
1506 &table_key_vec,
1507 &table_dom_sep_vec,
1508 &q_lookup_vec,
1509 i,
1510 )?);
1511 }
1512
1513 Ok(merged_lookup_table)
1514 }
1515
1516 fn compute_lookup_prod_polynomial(
1517 &self,
1518 tau: &F,
1519 beta: &F,
1520 gamma: &F,
1521 merged_lookup_table: &[F],
1522 sorted_vec: &[F],
1523 ) -> Result<DensePolynomial<F>, CircuitError> {
1524 self.check_plonk_type(PlonkType::UltraPlonk)?;
1525 self.check_finalize_flag(true)?;
1526 let domain = &self.eval_domain;
1527 let n = domain.size();
1528 if n != self.wire_variables[RANGE_WIRE_ID].len() {
1529 return Err(ParameterError(
1530 "Domain size should match the size of the padded lookup variables vector"
1531 .to_string(),
1532 ));
1533 }
1534 if n != merged_lookup_table.len() {
1535 return Err(ParameterError(
1536 "Domain size should match the size of the padded lookup table".to_string(),
1537 ));
1538 }
1539 if 2 * n - 1 != sorted_vec.len() {
1540 return Err(ParameterError(
1541 "The sorted vector has wrong length".to_string(),
1542 ));
1543 }
1544
1545 let mut product_vec = vec![F::one()];
1546 let beta_plus_one = F::one() + *beta;
1547 let gamma_mul_beta_plus_one = *gamma * beta_plus_one;
1548 let q_lookup_vec = self.q_lookup();
1549 let q_dom_sep_vec = self.q_dom_sep();
1550 for j in 0..(n - 2) {
1551 let lookup_wire_val =
1553 self.merged_lookup_wire_value(*tau, j, &q_lookup_vec, &q_dom_sep_vec)?;
1554 let table_val = merged_lookup_table[j];
1555 let table_next_val = merged_lookup_table[j + 1];
1556 let h1_val = sorted_vec[j];
1557 let h1_next_val = sorted_vec[j + 1];
1558 let h2_val = sorted_vec[n - 1 + j];
1559 let h2_next_val = sorted_vec[n + j];
1560
1561 let a = beta_plus_one
1563 * (*gamma + lookup_wire_val)
1564 * (gamma_mul_beta_plus_one + table_val + *beta * table_next_val);
1565 let b = (gamma_mul_beta_plus_one + h1_val + *beta * h1_next_val)
1567 * (gamma_mul_beta_plus_one + h2_val + *beta * h2_next_val);
1568
1569 let prev_prod = *product_vec.last().ok_or(CircuitError::IndexError)?;
1570 product_vec.push(prev_prod * a / b);
1571 }
1572 product_vec.push(F::one());
1573 domain.ifft_in_place(&mut product_vec);
1574 Ok(DensePolynomial::from_coefficients_vec(product_vec))
1575 }
1576
1577 fn compute_lookup_sorted_vec_polynomials(
1578 &self,
1579 tau: F,
1580 merged_lookup_table: &[F],
1581 ) -> Result<SortedLookupVecAndPolys<F>, CircuitError> {
1582 self.check_plonk_type(PlonkType::UltraPlonk)?;
1583 self.check_finalize_flag(true)?;
1584 let domain = &self.eval_domain;
1585 let n = domain.size();
1586 if n != self.wire_variables[RANGE_WIRE_ID].len() {
1587 return Err(ParameterError(
1588 "Domain size should match the size of the padded lookup variables vector"
1589 .to_string(),
1590 ));
1591 }
1592 if n != merged_lookup_table.len() {
1593 return Err(ParameterError(
1594 "Domain size should match the size of the padded lookup table".to_string(),
1595 ));
1596 }
1597 let mut lookup_map = HashMap::<F, usize>::new();
1599 let q_lookup_vec = self.q_lookup();
1600 let q_dom_sep_vec = self.q_dom_sep();
1601 for i in 0..(n - 1) {
1602 let elem = self.merged_lookup_wire_value(tau, i, &q_lookup_vec, &q_dom_sep_vec)?;
1603 let n_lookups = lookup_map.entry(elem).or_insert(0);
1604 *n_lookups += 1;
1605 }
1606 let mut sorted_vec = vec![];
1609 for elem in merged_lookup_table.iter() {
1610 if let Some(n_lookup) = lookup_map.get(elem) {
1611 sorted_vec.extend(vec![*elem; 1 + n_lookup]);
1612 lookup_map.remove(elem);
1613 } else {
1614 sorted_vec.push(*elem);
1615 }
1616 }
1617
1618 if sorted_vec.len() != 2 * n - 1 {
1619 return Err(ParameterError("The sorted vector has wrong length, some lookup variables might be outside the table".to_string()));
1620 }
1621 let h1_poly = DensePolynomial::from_coefficients_vec(domain.ifft(&sorted_vec[..n]));
1622 let h2_poly = DensePolynomial::from_coefficients_vec(domain.ifft(&sorted_vec[n - 1..]));
1623 Ok((sorted_vec, h1_poly, h2_poly))
1624 }
1625}
1626
1627impl<F: PrimeField> PlonkCircuit<F> {
1629 #[inline]
1630 fn compute_range_table(&self) -> Result<Vec<F>, CircuitError> {
1631 self.check_plonk_type(PlonkType::UltraPlonk)?;
1632 self.check_finalize_flag(true)?;
1633 let domain = &self.eval_domain;
1634 let range_size = self.range_size()?;
1635 if domain.size() < range_size {
1636 return Err(ParameterError(format!(
1637 "Domain size {} < range size {}",
1638 domain.size(),
1639 range_size
1640 )));
1641 }
1642 let mut range_table: Vec<F> = (0..range_size).map(|i| F::from(i as u32)).collect();
1643 range_table.resize(domain.size(), F::zero());
1644 Ok(range_table)
1645 }
1646
1647 #[inline]
1648 fn merged_table_value(
1649 &self,
1650 tau: F,
1651 range_table: &[F],
1652 table_key_vec: &[F],
1653 table_dom_sep_vec: &[F],
1654 q_lookup_vec: &[F],
1655 i: usize,
1656 ) -> Result<F, CircuitError> {
1657 let range_val = range_table[i];
1658 let key_val = table_key_vec[i];
1659 let dom_sep_val = table_dom_sep_vec[i];
1660 let q_lookup_val = q_lookup_vec[i];
1661 let table_val_1 = self.witness(self.wire_variable(TABLE_VAL_1_WIRE_ID, i))?;
1662 let table_val_2 = self.witness(self.wire_variable(TABLE_VAL_2_WIRE_ID, i))?;
1663 Ok(range_val
1664 + q_lookup_val
1665 * tau
1666 * (dom_sep_val + tau * (key_val + tau * (table_val_1 + tau * table_val_2))))
1667 }
1668
1669 #[inline]
1670 fn merged_lookup_wire_value(
1671 &self,
1672 tau: F,
1673 i: usize,
1674 q_lookup_vec: &[F],
1675 q_dom_sep_vec: &[F],
1676 ) -> Result<F, CircuitError> {
1677 let w_range_val = self.witness(self.wire_variable(RANGE_WIRE_ID, i))?;
1678 let lookup_key = self.witness(self.wire_variable(LOOKUP_KEY_WIRE_ID, i))?;
1679 let lookup_val_1 = self.witness(self.wire_variable(LOOKUP_VAL_1_WIRE_ID, i))?;
1680 let lookup_val_2 = self.witness(self.wire_variable(LOOKUP_VAL_2_WIRE_ID, i))?;
1681 let q_lookup_val = q_lookup_vec[i];
1682 let q_dom_sep_val = q_dom_sep_vec[i];
1683 Ok(w_range_val
1684 + q_lookup_val
1685 * tau
1686 * (q_dom_sep_val + tau * (lookup_key + tau * (lookup_val_1 + tau * lookup_val_2))))
1687 }
1688}
1689
1690#[cfg(test)]
1691pub(crate) mod test {
1692 use super::{Arithmetization, Circuit, PlonkCircuit};
1693 use crate::{constants::compute_coset_representatives, CircuitError};
1694 use ark_bls12_377::Fq as Fq377;
1695 use ark_ed_on_bls12_377::Fq as FqEd377;
1696 use ark_ed_on_bls12_381::Fq as FqEd381;
1697 use ark_ed_on_bn254::Fq as FqEd254;
1698 use ark_ff::PrimeField;
1699 use ark_poly::{domain::Radix2EvaluationDomain, univariate::DensePolynomial, EvaluationDomain};
1700 use ark_std::{vec, vec::Vec};
1701 use jf_utils::test_rng;
1702
1703 #[test]
1704 fn test_circuit_trait() -> Result<(), CircuitError> {
1705 test_circuit_trait_helper::<FqEd254>()?;
1706 test_circuit_trait_helper::<FqEd377>()?;
1707 test_circuit_trait_helper::<FqEd381>()?;
1708 test_circuit_trait_helper::<Fq377>()
1709 }
1710
1711 fn test_circuit_trait_helper<F: PrimeField>() -> Result<(), CircuitError> {
1712 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_turbo_plonk();
1713 let a = circuit.create_variable(F::from(3u32))?;
1715 let b = circuit.create_variable(F::from(1u32))?;
1716 circuit.enforce_constant(a, F::from(3u32))?;
1718 circuit.enforce_bool(b)?;
1720 let c = circuit.add(a, b)?;
1722 let d = circuit.sub(a, b)?;
1724 let e = circuit.mul(c, d)?;
1726 let f = circuit.create_public_variable(F::from(8u32))?;
1728 circuit.enforce_equal(e, f)?;
1730
1731 assert_eq!(circuit.num_gates(), 9);
1734 assert_eq!(circuit.num_vars(), 8);
1736 assert_eq!(circuit.num_inputs(), 1);
1738
1739 let pub_input = &[F::from(8u32)];
1741 let verify = circuit.check_circuit_satisfiability(pub_input);
1742 assert!(verify.is_ok(), "{:?}", verify.unwrap_err());
1743 let bad_pub_input = &[F::from(0u32)];
1744 assert!(circuit.check_circuit_satisfiability(bad_pub_input).is_err());
1745 let bad_pub_input = &[F::from(8u32), F::from(8u32)];
1747 assert!(circuit.check_circuit_satisfiability(bad_pub_input).is_err());
1748
1749 Ok(())
1750 }
1751
1752 #[test]
1753 fn test_add() -> Result<(), CircuitError> {
1754 test_add_helper::<FqEd254>()?;
1755 test_add_helper::<FqEd377>()?;
1756 test_add_helper::<FqEd381>()?;
1757 test_add_helper::<Fq377>()
1758 }
1759
1760 fn test_add_helper<F: PrimeField>() -> Result<(), CircuitError> {
1761 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_turbo_plonk();
1762 let a = circuit.create_variable(F::from(3u32))?;
1763 let b = circuit.create_variable(F::from(1u32))?;
1764 let c = circuit.add(a, b)?;
1765
1766 assert_eq!(circuit.witness(c)?, F::from(4u32));
1768 assert!(circuit.check_circuit_satisfiability(&[]).is_ok());
1769 *circuit.witness_mut(c) = F::from(1u32);
1770 assert!(circuit.check_circuit_satisfiability(&[]).is_err());
1771
1772 assert!(circuit.add(circuit.num_vars(), a).is_err());
1774
1775 Ok(())
1776 }
1777
1778 #[test]
1779 fn test_sub() -> Result<(), CircuitError> {
1780 test_sub_helper::<FqEd254>()?;
1781 test_sub_helper::<FqEd377>()?;
1782 test_sub_helper::<FqEd381>()?;
1783 test_sub_helper::<Fq377>()
1784 }
1785
1786 fn test_sub_helper<F: PrimeField>() -> Result<(), CircuitError> {
1787 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_turbo_plonk();
1788 let a = circuit.create_variable(F::from(3u32))?;
1789 let b = circuit.create_variable(F::from(1u32))?;
1790 let c = circuit.sub(a, b)?;
1791
1792 assert_eq!(circuit.witness(c)?, F::from(2u32));
1794 assert!(circuit.check_circuit_satisfiability(&[]).is_ok());
1795 *circuit.witness_mut(c) = F::from(1u32);
1796 assert!(circuit.check_circuit_satisfiability(&[]).is_err());
1797
1798 assert!(circuit.sub(circuit.num_vars(), a).is_err());
1800
1801 Ok(())
1802 }
1803
1804 #[test]
1805 fn test_mul() -> Result<(), CircuitError> {
1806 test_mul_helper::<FqEd254>()?;
1807 test_mul_helper::<FqEd377>()?;
1808 test_mul_helper::<FqEd381>()?;
1809 test_mul_helper::<Fq377>()
1810 }
1811
1812 fn test_mul_helper<F: PrimeField>() -> Result<(), CircuitError> {
1813 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_turbo_plonk();
1814 let a = circuit.create_variable(F::from(3u32))?;
1815 let b = circuit.create_variable(F::from(2u32))?;
1816 let c = circuit.mul(a, b)?;
1817
1818 assert_eq!(circuit.witness(c)?, F::from(6u32));
1820 assert!(circuit.check_circuit_satisfiability(&[]).is_ok());
1821 *circuit.witness_mut(c) = F::from(1u32);
1822 assert!(circuit.check_circuit_satisfiability(&[]).is_err());
1823
1824 assert!(circuit.mul(circuit.num_vars(), a).is_err());
1826
1827 Ok(())
1828 }
1829
1830 #[test]
1831 fn test_equal_gate() -> Result<(), CircuitError> {
1832 test_equal_gate_helper::<FqEd254>()?;
1833 test_equal_gate_helper::<FqEd377>()?;
1834 test_equal_gate_helper::<FqEd381>()?;
1835 test_equal_gate_helper::<Fq377>()
1836 }
1837 fn test_equal_gate_helper<F: PrimeField>() -> Result<(), CircuitError> {
1838 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_turbo_plonk();
1839 let a = circuit.create_variable(F::from(3u32))?;
1840 let b = circuit.create_variable(F::from(3u32))?;
1841 circuit.enforce_equal(a, b)?;
1842
1843 assert!(circuit.check_circuit_satisfiability(&[]).is_ok());
1845 *circuit.witness_mut(b) = F::from(1u32);
1846 assert!(circuit.check_circuit_satisfiability(&[]).is_err());
1847
1848 assert!(circuit.enforce_equal(circuit.num_vars(), a).is_err());
1850
1851 Ok(())
1852 }
1853
1854 #[test]
1855 fn test_bool() -> Result<(), CircuitError> {
1856 test_bool_helper::<FqEd254>()?;
1857 test_bool_helper::<FqEd377>()?;
1858 test_bool_helper::<FqEd381>()?;
1859 test_bool_helper::<Fq377>()
1860 }
1861
1862 fn test_bool_helper<F: PrimeField>() -> Result<(), CircuitError> {
1863 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_turbo_plonk();
1864 let a = circuit.create_variable(F::from(0u32))?;
1865 circuit.enforce_bool(a)?;
1866
1867 assert!(circuit.check_circuit_satisfiability(&[]).is_ok());
1869 *circuit.witness_mut(a) = F::from(2u32);
1870 assert!(circuit.check_circuit_satisfiability(&[]).is_err());
1871
1872 assert!(circuit.enforce_bool(circuit.num_vars()).is_err());
1874
1875 Ok(())
1876 }
1877
1878 #[test]
1879 fn test_constant() -> Result<(), CircuitError> {
1880 test_constant_helper::<FqEd254>()?;
1881 test_constant_helper::<FqEd377>()?;
1882 test_constant_helper::<FqEd381>()?;
1883 test_constant_helper::<Fq377>()
1884 }
1885 fn test_constant_helper<F: PrimeField>() -> Result<(), CircuitError> {
1886 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_turbo_plonk();
1887 let a = circuit.create_variable(F::from(10u32))?;
1888 circuit.enforce_constant(a, F::from(10u32))?;
1889
1890 assert!(circuit.check_circuit_satisfiability(&[]).is_ok());
1892 *circuit.witness_mut(a) = F::from(2u32);
1893 assert!(circuit.check_circuit_satisfiability(&[]).is_err());
1894
1895 assert!(circuit
1897 .enforce_constant(circuit.num_vars(), F::from(0u32))
1898 .is_err());
1899
1900 Ok(())
1901 }
1902
1903 #[test]
1904 fn test_io_gate() -> Result<(), CircuitError> {
1905 test_io_gate_helper::<FqEd254>()?;
1906 test_io_gate_helper::<FqEd377>()?;
1907 test_io_gate_helper::<FqEd381>()?;
1908 test_io_gate_helper::<Fq377>()
1909 }
1910
1911 fn test_io_gate_helper<F: PrimeField>() -> Result<(), CircuitError> {
1912 let mut circuit = PlonkCircuit::<F>::new_turbo_plonk();
1913 let b = circuit.create_variable(F::from(0u32))?;
1914 let a = circuit.create_public_variable(F::from(1u32))?;
1915 circuit.enforce_bool(a)?;
1916 circuit.enforce_bool(b)?;
1917 circuit.set_variable_public(b)?;
1918
1919 assert!(circuit
1921 .check_circuit_satisfiability(&[F::from(1u32), F::from(0u32)])
1922 .is_ok());
1923 *circuit.witness_mut(a) = F::from(0u32);
1924 assert!(circuit
1925 .check_circuit_satisfiability(&[F::from(0u32), F::from(0u32)])
1926 .is_ok());
1927 *circuit.witness_mut(b) = F::from(1u32);
1928 assert!(circuit
1929 .check_circuit_satisfiability(&[F::from(0u32), F::from(1u32)])
1930 .is_ok());
1931
1932 assert!(circuit
1934 .check_circuit_satisfiability(&[F::from(2u32), F::from(1u32)])
1935 .is_err());
1936 *circuit.witness_mut(a) = F::from(2u32);
1937 assert!(circuit
1938 .check_circuit_satisfiability(&[F::from(2u32), F::from(1u32)])
1939 .is_err());
1940 *circuit.witness_mut(a) = F::from(0u32);
1941 assert!(circuit
1942 .check_circuit_satisfiability(&[F::from(0u32), F::from(2u32)])
1943 .is_err());
1944 *circuit.witness_mut(b) = F::from(2u32);
1945 assert!(circuit
1946 .check_circuit_satisfiability(&[F::from(0u32), F::from(2u32)])
1947 .is_err());
1948
1949 Ok(())
1950 }
1951
1952 #[test]
1953 fn test_io_gate_multi_inputs() -> Result<(), CircuitError> {
1954 test_io_gate_multi_inputs_helper::<FqEd254>()?;
1955 test_io_gate_multi_inputs_helper::<FqEd377>()?;
1956 test_io_gate_multi_inputs_helper::<FqEd381>()?;
1957 test_io_gate_multi_inputs_helper::<Fq377>()
1958 }
1959 fn test_io_gate_multi_inputs_helper<F: PrimeField>() -> Result<(), CircuitError> {
1960 let mut circuit = PlonkCircuit::<F>::new_turbo_plonk();
1961 let a = circuit.create_public_variable(F::from(1u32))?;
1962 let b = circuit.create_public_variable(F::from(2u32))?;
1963 let c = circuit.create_public_variable(F::from(3u32))?;
1964 circuit.add_gate(a, b, c)?;
1965
1966 assert!(circuit
1968 .check_circuit_satisfiability(&[F::from(1u32), F::from(2u32), F::from(3u32)])
1969 .is_ok());
1970 assert!(circuit
1972 .check_circuit_satisfiability(&[F::from(2u32), F::from(1u32), F::from(3u32)])
1973 .is_err());
1974 *circuit.witness_mut(a) = F::from(4u32);
1976 *circuit.witness_mut(b) = F::from(8u32);
1977 *circuit.witness_mut(c) = F::from(12u32);
1978 assert!(circuit
1979 .check_circuit_satisfiability(&[F::from(4u32), F::from(8u32), F::from(12u32)])
1980 .is_ok());
1981 *circuit.witness_mut(a) = F::from(2u32);
1983 assert!(circuit
1984 .check_circuit_satisfiability(&[F::from(2u32), F::from(8u32), F::from(12u32)])
1985 .is_err());
1986
1987 Ok(())
1988 }
1989
1990 fn create_turbo_plonk_instance<F: PrimeField>(
1991 ) -> Result<(PlonkCircuit<F>, Vec<F>), CircuitError> {
1992 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_turbo_plonk();
1993 let a = circuit.create_variable(F::from(3u32))?;
1994 let b = circuit.create_public_variable(F::from(1u32))?;
1995 circuit.enforce_constant(a, F::from(3u32))?;
1996 circuit.enforce_bool(b)?;
1997 let c = circuit.add(a, b)?;
1998 let d = circuit.sub(a, b)?;
1999 let e = circuit.mul(c, d)?;
2000 let f = circuit.create_public_variable(F::from(8u32))?;
2001 circuit.enforce_equal(e, f)?;
2002
2003 Ok((circuit, vec![F::from(1u32), F::from(8u32)]))
2004 }
2005
2006 fn create_ultra_plonk_instance<F: PrimeField>(
2007 ) -> Result<(PlonkCircuit<F>, Vec<F>), CircuitError> {
2008 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_ultra_plonk(4);
2009 let a = circuit.create_variable(F::from(3u32))?;
2010 let b = circuit.create_public_variable(F::from(1u32))?;
2011 circuit.enforce_constant(a, F::from(3u32))?;
2012 circuit.enforce_bool(b)?;
2013 let c = circuit.add(a, b)?;
2014 let d = circuit.sub(a, b)?;
2015 let e = circuit.mul(c, d)?;
2016 let f = circuit.create_public_variable(F::from(8u32))?;
2017 circuit.enforce_equal(e, f)?;
2018
2019 circuit.add_range_check_variable(b)?;
2021 circuit.add_range_check_variable(c)?;
2022 circuit.add_range_check_variable(e)?;
2023 circuit.add_range_check_variable(f)?;
2024 circuit.add_range_check_variable(circuit.zero())?;
2025
2026 let table_vars = [(a, b), (c, d), (e, f)];
2029 let x = circuit.create_variable(F::from(3u8))?;
2031 let y = circuit.create_variable(F::from(8u8))?;
2032 let key1 = circuit.create_variable(F::from(2u8))?;
2033 let lookup_vars = [(circuit.zero(), x, circuit.one()), (key1, y, y)];
2034 circuit.create_table_and_lookup_variables(&lookup_vars, &table_vars)?;
2035
2036 Ok((circuit, vec![F::from(1u32), F::from(8u32)]))
2037 }
2038
2039 #[test]
2041 fn test_compute_extended_permutation() -> Result<(), CircuitError> {
2042 test_compute_extended_permutation_helper::<FqEd254>()?;
2043 test_compute_extended_permutation_helper::<FqEd377>()?;
2044 test_compute_extended_permutation_helper::<FqEd381>()?;
2045 test_compute_extended_permutation_helper::<Fq377>()
2046 }
2047
2048 fn test_compute_extended_permutation_helper<F: PrimeField>() -> Result<(), CircuitError> {
2049 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_turbo_plonk();
2050 let a = circuit.create_variable(F::from(2u32))?;
2051 let b = circuit.create_public_variable(F::from(3u32))?;
2052 let c = circuit.add(a, b)?;
2053 let d = circuit.add(circuit.one(), a)?;
2054 let _ = circuit.mul(c, d)?;
2055
2056 let (mut circuit, _) = create_ultra_plonk_instance::<F>()?;
2058 check_wire_permutation_and_extended_id_permutation(&mut circuit)?;
2059
2060 Ok(())
2061 }
2062
2063 fn check_wire_permutation_and_extended_id_permutation<F: PrimeField>(
2064 circuit: &mut PlonkCircuit<F>,
2065 ) -> Result<(), CircuitError> {
2066 let domain = Radix2EvaluationDomain::<F>::new(circuit.num_gates())
2067 .ok_or(CircuitError::DomainCreationError)?;
2068 let n = domain.size();
2069 circuit.eval_domain = domain;
2070
2071 circuit.pad()?;
2073 circuit.compute_wire_permutation();
2074 let mut visit_wire = vec![false; circuit.num_wire_types * n];
2075 let mut visit_variable = vec![false; circuit.num_vars()];
2076
2077 for i in 0..circuit.num_wire_types {
2078 for j in 0..n {
2079 if visit_wire[i * n + j] {
2080 continue;
2081 }
2082 let cycle_var = circuit.wire_variable(i, j);
2084 assert!(!visit_variable[cycle_var]);
2086 visit_variable[cycle_var] = true;
2087
2088 let mut wire_id = i;
2090 let mut gate_id = j;
2091 visit_wire[i * n + j] = true;
2092 loop {
2093 let (next_wire_id, next_gate_id) =
2094 circuit.wire_permutation[wire_id * n + gate_id];
2095 if next_wire_id == i && next_gate_id == j {
2097 break;
2098 }
2099 let next_var = circuit.wire_variable(next_wire_id, next_gate_id);
2100 assert_eq!(cycle_var, next_var);
2102 assert!(!visit_wire[next_wire_id * n + next_gate_id]);
2104 visit_wire[next_wire_id * n + next_gate_id] = true;
2105 wire_id = next_wire_id;
2106 gate_id = next_gate_id;
2107 }
2108 }
2109 }
2110
2111 circuit.compute_extended_id_permutation();
2113 let k: Vec<F> = compute_coset_representatives(circuit.num_wire_types, Some(n));
2115 let group_elems: Vec<F> = domain.elements().collect();
2116 (0..circuit.num_wire_types).for_each(|i| {
2117 (0..n).for_each(|j| {
2118 assert_eq!(
2119 k[i] * group_elems[j],
2120 circuit.extended_id_permutation[i * n + j]
2121 )
2122 });
2123 });
2124
2125 Ok(())
2126 }
2127
2128 #[test]
2132 fn test_ultra_plonk_flag() -> Result<(), CircuitError> {
2133 test_ultra_plonk_flag_helper::<FqEd254>()?;
2134 test_ultra_plonk_flag_helper::<FqEd377>()?;
2135 test_ultra_plonk_flag_helper::<FqEd381>()?;
2136 test_ultra_plonk_flag_helper::<Fq377>()
2137 }
2138
2139 fn test_ultra_plonk_flag_helper<F: PrimeField>() -> Result<(), CircuitError> {
2140 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_turbo_plonk();
2141 assert!(circuit.add_range_check_variable(0).is_err());
2143 circuit.finalize_for_arithmetization()?;
2144 assert!(circuit.compute_range_table_polynomial().is_err());
2145 assert!(circuit.compute_key_table_polynomial().is_err());
2146 assert!(circuit.compute_merged_lookup_table(F::one()).is_err());
2147 assert!(circuit
2148 .compute_lookup_sorted_vec_polynomials(F::one(), &[])
2149 .is_err());
2150 assert!(circuit
2151 .compute_lookup_prod_polynomial(&F::one(), &F::one(), &F::one(), &[], &[])
2152 .is_err());
2153
2154 Ok(())
2155 }
2156
2157 #[test]
2158 fn test_finalized_flag() -> Result<(), CircuitError> {
2159 test_finalized_flag_helper::<FqEd254>()?;
2160 test_finalized_flag_helper::<FqEd377>()?;
2161 test_finalized_flag_helper::<FqEd381>()?;
2162 test_finalized_flag_helper::<Fq377>()
2163 }
2164
2165 fn test_finalized_flag_helper<F: PrimeField>() -> Result<(), CircuitError> {
2166 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_turbo_plonk();
2167 assert!(circuit.compute_selector_polynomials().is_err());
2169 assert!(circuit.compute_extended_permutation_polynomials().is_err());
2170 assert!(circuit.compute_pub_input_polynomial().is_err());
2171 assert!(circuit.compute_wire_polynomials().is_err());
2172 assert!(circuit
2173 .compute_prod_permutation_polynomial(&F::one(), &F::one())
2174 .is_err());
2175
2176 circuit.finalize_for_arithmetization()?;
2178 assert!(circuit.create_variable(F::one()).is_err());
2179 assert!(circuit.create_public_variable(F::one()).is_err());
2180 assert!(circuit.add_gate(0, 0, 0).is_err());
2181 assert!(circuit.sub_gate(0, 0, 0).is_err());
2182 assert!(circuit.mul_gate(0, 0, 0).is_err());
2183 assert!(circuit.enforce_constant(0, F::one()).is_err());
2184 assert!(circuit.enforce_bool(0).is_err());
2185 assert!(circuit.enforce_equal(0, 0).is_err());
2186
2187 Ok(())
2188 }
2189
2190 #[test]
2191
2192 fn test_ultra_plonk_finalized_flag() -> Result<(), CircuitError> {
2193 test_ultra_plonk_finalized_flag_helper::<FqEd254>()?;
2194 test_ultra_plonk_finalized_flag_helper::<FqEd377>()?;
2195 test_ultra_plonk_finalized_flag_helper::<FqEd381>()?;
2196 test_ultra_plonk_finalized_flag_helper::<Fq377>()
2197 }
2198
2199 fn test_ultra_plonk_finalized_flag_helper<F: PrimeField>() -> Result<(), CircuitError> {
2200 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_ultra_plonk(1);
2201 assert!(circuit.compute_selector_polynomials().is_err());
2203 assert!(circuit.compute_extended_permutation_polynomials().is_err());
2204 assert!(circuit.compute_pub_input_polynomial().is_err());
2205 assert!(circuit.compute_wire_polynomials().is_err());
2206 assert!(circuit
2207 .compute_prod_permutation_polynomial(&F::one(), &F::one())
2208 .is_err());
2209 assert!(circuit.compute_range_table_polynomial().is_err());
2210 assert!(circuit.compute_key_table_polynomial().is_err());
2211 assert!(circuit.compute_merged_lookup_table(F::one()).is_err());
2212 assert!(circuit
2213 .compute_lookup_sorted_vec_polynomials(F::one(), &[])
2214 .is_err());
2215 assert!(circuit
2216 .compute_lookup_prod_polynomial(&F::one(), &F::one(), &F::one(), &[], &[])
2217 .is_err());
2218
2219 circuit.finalize_for_arithmetization()?;
2221 assert!(circuit.create_variable(F::one()).is_err());
2222 assert!(circuit.create_public_variable(F::one()).is_err());
2223 assert!(circuit.add_gate(0, 0, 0).is_err());
2224 assert!(circuit.sub_gate(0, 0, 0).is_err());
2225 assert!(circuit.mul_gate(0, 0, 0).is_err());
2226 assert!(circuit.enforce_constant(0, F::one()).is_err());
2227 assert!(circuit.enforce_bool(0).is_err());
2228 assert!(circuit.enforce_equal(0, 0).is_err());
2229 assert!(circuit.add_range_check_variable(0).is_err());
2231
2232 Ok(())
2233 }
2234
2235 #[test]
2238 fn test_arithmetization() -> Result<(), CircuitError> {
2239 test_arithmetization_helper::<FqEd254>()?;
2240 test_arithmetization_helper::<FqEd377>()?;
2241 test_arithmetization_helper::<FqEd381>()?;
2242 test_arithmetization_helper::<Fq377>()
2243 }
2244
2245 fn test_arithmetization_helper<F: PrimeField>() -> Result<(), CircuitError> {
2246 let (mut circuit, pub_inputs) = create_turbo_plonk_instance::<F>()?;
2248 circuit.finalize_for_arithmetization()?;
2249 test_arithmetization_for_circuit(circuit, pub_inputs)?;
2250
2251 let (mut circuit, pub_inputs) = create_ultra_plonk_instance::<F>()?;
2253 circuit.finalize_for_arithmetization()?;
2254 test_arithmetization_for_lookup_circuit(&circuit)?;
2255 test_arithmetization_for_circuit(circuit, pub_inputs)?;
2256
2257 Ok(())
2258 }
2259
2260 fn check_polynomial<F: PrimeField>(poly: &DensePolynomial<F>, evals: &[F]) {
2263 let domain = Radix2EvaluationDomain::new(evals.len()).unwrap();
2264 let poly_eval = poly.evaluate_over_domain_by_ref(domain);
2265 for (&a, &b) in poly_eval.evals.iter().zip(evals.iter()) {
2266 assert_eq!(a, b);
2267 }
2268 }
2269
2270 pub(crate) fn test_arithmetization_for_lookup_circuit<F: PrimeField>(
2271 circuit: &PlonkCircuit<F>,
2272 ) -> Result<(), CircuitError> {
2273 let n = circuit.eval_domain.size();
2274
2275 let range_table_poly = circuit.compute_range_table_polynomial()?;
2277 let range_table = circuit.compute_range_table()?;
2278 check_polynomial(&range_table_poly, &range_table);
2279
2280 let key_table_poly = circuit.compute_key_table_polynomial()?;
2282 let key_table = circuit.table_key_vec();
2283 check_polynomial(&key_table_poly, &key_table);
2284
2285 let rng = &mut test_rng();
2287 let tau = F::rand(rng);
2288 let merged_lookup_table = circuit.compute_merged_lookup_table(tau)?;
2289 let (sorted_vec, h1_poly, h2_poly) =
2290 circuit.compute_lookup_sorted_vec_polynomials(tau, &merged_lookup_table)?;
2291 assert_eq!(sorted_vec.len(), 2 * n - 1);
2292 assert_eq!(sorted_vec[0], merged_lookup_table[0]);
2295 let mut ptr = 1;
2296 for slice in sorted_vec.windows(2) {
2297 if slice[0] == slice[1] {
2299 continue;
2300 }
2301 while ptr < n && merged_lookup_table[ptr] == merged_lookup_table[ptr - 1] {
2303 ptr += 1;
2304 }
2305 assert!(ptr < n);
2306 assert_eq!(merged_lookup_table[ptr], slice[1]);
2307 ptr += 1;
2308 }
2309 assert_eq!(ptr, n);
2311
2312 check_polynomial(&h1_poly, &sorted_vec[..n]);
2313 check_polynomial(&h2_poly, &sorted_vec[n - 1..]);
2314
2315 let beta = F::rand(rng);
2317 let gamma = F::rand(rng);
2318 let prod_poly = circuit.compute_lookup_prod_polynomial(
2319 &tau,
2320 &beta,
2321 &gamma,
2322 &merged_lookup_table,
2323 &sorted_vec,
2324 )?;
2325 let mut prod_evals = vec![F::one()];
2326 let one_plus_beta = F::one() + beta;
2327 let gamma_mul_one_plus_beta = gamma * one_plus_beta;
2328 let q_lookup_vec = circuit.q_lookup();
2329 let q_dom_sep = circuit.q_dom_sep();
2330 for j in 0..(n - 2) {
2331 let lookup_wire_val =
2332 circuit.merged_lookup_wire_value(tau, j, &q_lookup_vec, &q_dom_sep)?;
2333 let table_val = merged_lookup_table[j];
2334 let table_next_val = merged_lookup_table[j + 1];
2335 let h1_val = sorted_vec[j];
2336 let h1_next_val = sorted_vec[j + 1];
2337 let h2_val = sorted_vec[n - 1 + j];
2338 let h2_next_val = sorted_vec[n + j];
2339
2340 let a = one_plus_beta
2342 * (gamma + lookup_wire_val)
2343 * (gamma_mul_one_plus_beta + table_val + beta * table_next_val);
2344 let b = (gamma_mul_one_plus_beta + h1_val + beta * h1_next_val)
2346 * (gamma_mul_one_plus_beta + h2_val + beta * h2_next_val);
2347 let prod = prod_evals[j] * a / b;
2348 prod_evals.push(prod);
2349 }
2350 prod_evals.push(F::one());
2351 check_polynomial(&prod_poly, &prod_evals);
2352
2353 Ok(())
2354 }
2355
2356 pub(crate) fn test_arithmetization_for_circuit<F: PrimeField>(
2357 circuit: PlonkCircuit<F>,
2358 pub_inputs: Vec<F>,
2359 ) -> Result<(), CircuitError> {
2360 let n = circuit.eval_domain.size();
2362
2363 let selector_polys = circuit.compute_selector_polynomials()?;
2365 selector_polys
2366 .iter()
2367 .zip(circuit.all_selectors().iter())
2368 .for_each(|(poly, evals)| check_polynomial(poly, evals));
2369
2370 let wire_polys = circuit.compute_wire_polynomials()?;
2372 for (poly, wire_vars) in wire_polys
2373 .iter()
2374 .zip(circuit.wire_variables.iter().take(circuit.num_wire_types()))
2375 {
2376 let wire_evals: Vec<F> = wire_vars.iter().map(|&var| circuit.witness[var]).collect();
2377 check_polynomial(poly, &wire_evals);
2378 }
2379
2380 let pi_poly = circuit.compute_pub_input_polynomial()?;
2382 let mut pi_evals = pub_inputs;
2383 pi_evals.extend(vec![F::zero(); n - 2]);
2384 check_polynomial(&pi_poly, &pi_evals);
2385
2386 let sigma_polys = circuit.compute_extended_permutation_polynomials()?;
2388 let extended_perm: Vec<F> = circuit
2389 .wire_permutation
2390 .iter()
2391 .map(|&(i, j)| circuit.extended_id_permutation[i * n + j])
2392 .collect();
2393 for (i, poly) in sigma_polys.iter().enumerate() {
2394 check_polynomial(poly, &extended_perm[i * n..(i + 1) * n]);
2395 }
2396
2397 let rng = &mut test_rng();
2399 let beta = F::rand(rng);
2400 let gamma = F::rand(rng);
2401 let prod_poly = circuit.compute_prod_permutation_polynomial(&beta, &gamma)?;
2402 let mut prod_evals = vec![F::one()];
2403 for j in 0..(n - 1) {
2404 let mut a = F::one();
2406 let mut b = F::one();
2408 for i in 0..circuit.num_wire_types {
2409 let wire_value = circuit.witness[circuit.wire_variable(i, j)];
2410 a *= wire_value + beta * circuit.extended_id_permutation[i * n + j] + gamma;
2411 b *= wire_value + beta * extended_perm[i * n + j] + gamma;
2412 }
2413 let prod = prod_evals[j] * a / b;
2414 prod_evals.push(prod);
2415 }
2416 check_polynomial(&prod_poly, &prod_evals);
2417
2418 Ok(())
2419 }
2420}