kimchi/
proof.rs

1//! This module implements the data structures of a proof.
2
3use crate::circuits::{
4    berkeley_columns::Column,
5    gate::GateType,
6    lookup::lookups::LookupPattern,
7    wires::{COLUMNS, PERMUTS},
8};
9use ark_ec::AffineRepr;
10use ark_ff::{FftField, One, Zero};
11use ark_poly::univariate::DensePolynomial;
12use core::array;
13use o1_utils::ExtendedDensePolynomial;
14use poly_commitment::{
15    commitment::{b_poly, b_poly_coefficients, CommitmentCurve, PolyComm},
16    OpenProof,
17};
18use serde::{Deserialize, Serialize};
19use serde_with::serde_as;
20
21//~ spec:startcode
22/// Evaluations of a polynomial at 2 points
23#[serde_as]
24#[derive(Copy, Clone, Serialize, Deserialize, Default, Debug, PartialEq)]
25#[cfg_attr(
26    feature = "ocaml_types",
27    derive(ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)
28)]
29#[serde(bound(
30    serialize = "Vec<o1_utils::serialization::SerdeAs>: serde_with::SerializeAs<Evals>",
31    deserialize = "Vec<o1_utils::serialization::SerdeAs>: serde_with::DeserializeAs<'de, Evals>"
32))]
33pub struct PointEvaluations<Evals> {
34    /// Evaluation at the challenge point zeta.
35    #[serde_as(as = "Vec<o1_utils::serialization::SerdeAs>")]
36    pub zeta: Evals,
37    /// Evaluation at `zeta . omega`, the product of the challenge point and the group generator.
38    #[serde_as(as = "Vec<o1_utils::serialization::SerdeAs>")]
39    pub zeta_omega: Evals,
40}
41
42// TODO: this should really be vectors here, perhaps create another type for chunked evaluations?
43/// Polynomial evaluations contained in a `ProverProof`.
44/// - **Chunked evaluations** `Field` is instantiated with vectors with a length
45/// that equals the length of the chunk
46/// - **Non chunked evaluations** `Field` is instantiated with a field, so they
47/// are single-sized#[serde_as]
48#[serde_as]
49#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
50pub struct ProofEvaluations<Evals> {
51    /// public input polynomials
52    pub public: Option<Evals>,
53    /// witness polynomials
54    pub w: [Evals; COLUMNS],
55    /// permutation polynomial
56    pub z: Evals,
57    /// permutation polynomials
58    /// (PERMUTS-1 evaluations because the last permutation is only used in
59    /// commitment form)
60    pub s: [Evals; PERMUTS - 1],
61    /// coefficient polynomials
62    pub coefficients: [Evals; COLUMNS],
63    /// evaluation of the generic selector polynomial
64    pub generic_selector: Evals,
65    /// evaluation of the poseidon selector polynomial
66    pub poseidon_selector: Evals,
67    /// evaluation of the elliptic curve addition selector polynomial
68    pub complete_add_selector: Evals,
69    /// evaluation of the elliptic curve variable base scalar multiplication
70    /// selector polynomial
71    pub mul_selector: Evals,
72    /// evaluation of the endoscalar multiplication selector polynomial
73    pub emul_selector: Evals,
74    /// evaluation of the endoscalar multiplication scalar computation selector
75    /// polynomial
76    pub endomul_scalar_selector: Evals,
77
78    // Optional gates
79    /// evaluation of the RangeCheck0 selector polynomial
80    pub range_check0_selector: Option<Evals>,
81    /// evaluation of the RangeCheck1 selector polynomial
82    pub range_check1_selector: Option<Evals>,
83    /// evaluation of the ForeignFieldAdd selector polynomial
84    pub foreign_field_add_selector: Option<Evals>,
85    /// evaluation of the ForeignFieldMul selector polynomial
86    pub foreign_field_mul_selector: Option<Evals>,
87    /// evaluation of the Xor selector polynomial
88    pub xor_selector: Option<Evals>,
89    /// evaluation of the Rot selector polynomial
90    pub rot_selector: Option<Evals>,
91
92    // lookup-related evaluations
93    /// evaluation of lookup aggregation polynomial
94    pub lookup_aggregation: Option<Evals>,
95    /// evaluation of lookup table polynomial
96    pub lookup_table: Option<Evals>,
97    /// evaluation of lookup sorted polynomials
98    pub lookup_sorted: [Option<Evals>; 5],
99    /// evaluation of runtime lookup table polynomial
100    pub runtime_lookup_table: Option<Evals>,
101
102    // lookup selectors
103    /// evaluation of the runtime lookup table selector polynomial
104    pub runtime_lookup_table_selector: Option<Evals>,
105    /// evaluation of the Xor range check pattern selector polynomial
106    pub xor_lookup_selector: Option<Evals>,
107    /// evaluation of the Lookup range check pattern selector polynomial
108    pub lookup_gate_lookup_selector: Option<Evals>,
109    /// evaluation of the RangeCheck range check pattern selector polynomial
110    pub range_check_lookup_selector: Option<Evals>,
111    /// evaluation of the ForeignFieldMul range check pattern selector
112    /// polynomial
113    pub foreign_field_mul_lookup_selector: Option<Evals>,
114}
115
116/// Commitments linked to the lookup feature
117#[serde_as]
118#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
119#[serde(bound = "G: ark_serialize::CanonicalDeserialize + ark_serialize::CanonicalSerialize")]
120pub struct LookupCommitments<G: AffineRepr> {
121    /// Commitments to the sorted lookup table polynomial (may have chunks)
122    pub sorted: Vec<PolyComm<G>>,
123    /// Commitment to the lookup aggregation polynomial
124    pub aggreg: PolyComm<G>,
125    /// Optional commitment to concatenated runtime tables
126    pub runtime: Option<PolyComm<G>>,
127}
128
129/// All the commitments that the prover creates as part of the proof.
130#[serde_as]
131#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
132#[serde(bound = "G: ark_serialize::CanonicalDeserialize + ark_serialize::CanonicalSerialize")]
133pub struct ProverCommitments<G: AffineRepr> {
134    /// The commitments to the witness (execution trace)
135    pub w_comm: [PolyComm<G>; COLUMNS],
136    /// The commitment to the permutation polynomial
137    pub z_comm: PolyComm<G>,
138    /// The commitment to the quotient polynomial
139    pub t_comm: PolyComm<G>,
140    /// Commitments related to the lookup argument
141    pub lookup: Option<LookupCommitments<G>>,
142}
143
144/// The proof that the prover creates from a
145/// [ProverIndex](super::prover_index::ProverIndex) and a `witness`.
146#[serde_as]
147#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
148#[serde(bound = "G: ark_serialize::CanonicalDeserialize + ark_serialize::CanonicalSerialize")]
149pub struct ProverProof<G, OpeningProof, const FULL_ROUNDS: usize>
150where
151    G: CommitmentCurve,
152    OpeningProof: OpenProof<G, FULL_ROUNDS>,
153{
154    /// All the polynomial commitments required in the proof
155    pub commitments: ProverCommitments<G>,
156
157    /// batched commitment opening proof
158    #[serde(bound(
159        serialize = "OpeningProof: Serialize",
160        deserialize = "OpeningProof: Deserialize<'de>"
161    ))]
162    pub proof: OpeningProof,
163
164    /// Two evaluations over a number of committed polynomials
165    pub evals: ProofEvaluations<PointEvaluations<Vec<G::ScalarField>>>,
166
167    /// Required evaluation for [Maller's
168    /// optimization](https://o1-labs.github.io/proof-systems/kimchi/maller_15.html#the-evaluation-of-l)
169    #[serde_as(as = "o1_utils::serialization::SerdeAs")]
170    pub ft_eval1: G::ScalarField,
171
172    /// The challenges underlying the optional polynomials folded into the proof
173    pub prev_challenges: Vec<RecursionChallenge<G>>,
174}
175
176/// A struct to store the challenges inside a `ProverProof`
177#[serde_as]
178#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
179#[serde(bound = "G: ark_serialize::CanonicalDeserialize + ark_serialize::CanonicalSerialize")]
180pub struct RecursionChallenge<G>
181where
182    G: AffineRepr,
183{
184    /// Vector of scalar field elements
185    #[serde_as(as = "Vec<o1_utils::serialization::SerdeAs>")]
186    pub chals: Vec<G::ScalarField>,
187    /// Polynomial commitment
188    pub comm: PolyComm<G>,
189}
190
191//~ spec:endcode
192
193impl<Evals> PointEvaluations<Evals> {
194    pub fn map<Evals2, FN: Fn(Evals) -> Evals2>(self, f: &FN) -> PointEvaluations<Evals2> {
195        let PointEvaluations { zeta, zeta_omega } = self;
196        PointEvaluations {
197            zeta: f(zeta),
198            zeta_omega: f(zeta_omega),
199        }
200    }
201
202    pub fn map_ref<Evals2, FN: Fn(&Evals) -> Evals2>(&self, f: &FN) -> PointEvaluations<Evals2> {
203        let PointEvaluations { zeta, zeta_omega } = self;
204        PointEvaluations {
205            zeta: f(zeta),
206            zeta_omega: f(zeta_omega),
207        }
208    }
209}
210
211impl<Eval> ProofEvaluations<Eval> {
212    pub fn map<Eval2, FN: Fn(Eval) -> Eval2>(self, f: &FN) -> ProofEvaluations<Eval2> {
213        let ProofEvaluations {
214            public,
215            w,
216            z,
217            s,
218            coefficients,
219            generic_selector,
220            poseidon_selector,
221            complete_add_selector,
222            mul_selector,
223            emul_selector,
224            endomul_scalar_selector,
225            range_check0_selector,
226            range_check1_selector,
227            foreign_field_add_selector,
228            foreign_field_mul_selector,
229            xor_selector,
230            rot_selector,
231            lookup_aggregation,
232            lookup_table,
233            lookup_sorted,
234            runtime_lookup_table,
235            runtime_lookup_table_selector,
236            xor_lookup_selector,
237            lookup_gate_lookup_selector,
238            range_check_lookup_selector,
239            foreign_field_mul_lookup_selector,
240        } = self;
241        ProofEvaluations {
242            public: public.map(f),
243            w: w.map(f),
244            z: f(z),
245            s: s.map(f),
246            coefficients: coefficients.map(f),
247            generic_selector: f(generic_selector),
248            poseidon_selector: f(poseidon_selector),
249            complete_add_selector: f(complete_add_selector),
250            mul_selector: f(mul_selector),
251            emul_selector: f(emul_selector),
252            endomul_scalar_selector: f(endomul_scalar_selector),
253            range_check0_selector: range_check0_selector.map(f),
254            range_check1_selector: range_check1_selector.map(f),
255            foreign_field_add_selector: foreign_field_add_selector.map(f),
256            foreign_field_mul_selector: foreign_field_mul_selector.map(f),
257            xor_selector: xor_selector.map(f),
258            rot_selector: rot_selector.map(f),
259            lookup_aggregation: lookup_aggregation.map(f),
260            lookup_table: lookup_table.map(f),
261            lookup_sorted: lookup_sorted.map(|x| x.map(f)),
262            runtime_lookup_table: runtime_lookup_table.map(f),
263            runtime_lookup_table_selector: runtime_lookup_table_selector.map(f),
264            xor_lookup_selector: xor_lookup_selector.map(f),
265            lookup_gate_lookup_selector: lookup_gate_lookup_selector.map(f),
266            range_check_lookup_selector: range_check_lookup_selector.map(f),
267            foreign_field_mul_lookup_selector: foreign_field_mul_lookup_selector.map(f),
268        }
269    }
270
271    pub fn map_ref<Eval2, FN: Fn(&Eval) -> Eval2>(&self, f: &FN) -> ProofEvaluations<Eval2> {
272        let ProofEvaluations {
273            public,
274            w: [w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14],
275            z,
276            s: [s0, s1, s2, s3, s4, s5],
277            coefficients: [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14],
278            generic_selector,
279            poseidon_selector,
280            complete_add_selector,
281            mul_selector,
282            emul_selector,
283            endomul_scalar_selector,
284            range_check0_selector,
285            range_check1_selector,
286            foreign_field_add_selector,
287            foreign_field_mul_selector,
288            xor_selector,
289            rot_selector,
290            lookup_aggregation,
291            lookup_table,
292            lookup_sorted,
293            runtime_lookup_table,
294            runtime_lookup_table_selector,
295            xor_lookup_selector,
296            lookup_gate_lookup_selector,
297            range_check_lookup_selector,
298            foreign_field_mul_lookup_selector,
299        } = self;
300        ProofEvaluations {
301            public: public.as_ref().map(f),
302            w: [
303                f(w0),
304                f(w1),
305                f(w2),
306                f(w3),
307                f(w4),
308                f(w5),
309                f(w6),
310                f(w7),
311                f(w8),
312                f(w9),
313                f(w10),
314                f(w11),
315                f(w12),
316                f(w13),
317                f(w14),
318            ],
319            z: f(z),
320            s: [f(s0), f(s1), f(s2), f(s3), f(s4), f(s5)],
321            coefficients: [
322                f(c0),
323                f(c1),
324                f(c2),
325                f(c3),
326                f(c4),
327                f(c5),
328                f(c6),
329                f(c7),
330                f(c8),
331                f(c9),
332                f(c10),
333                f(c11),
334                f(c12),
335                f(c13),
336                f(c14),
337            ],
338            generic_selector: f(generic_selector),
339            poseidon_selector: f(poseidon_selector),
340            complete_add_selector: f(complete_add_selector),
341            mul_selector: f(mul_selector),
342            emul_selector: f(emul_selector),
343            endomul_scalar_selector: f(endomul_scalar_selector),
344            range_check0_selector: range_check0_selector.as_ref().map(f),
345            range_check1_selector: range_check1_selector.as_ref().map(f),
346            foreign_field_add_selector: foreign_field_add_selector.as_ref().map(f),
347            foreign_field_mul_selector: foreign_field_mul_selector.as_ref().map(f),
348            xor_selector: xor_selector.as_ref().map(f),
349            rot_selector: rot_selector.as_ref().map(f),
350            lookup_aggregation: lookup_aggregation.as_ref().map(f),
351            lookup_table: lookup_table.as_ref().map(f),
352            lookup_sorted: array::from_fn(|i| lookup_sorted[i].as_ref().map(f)),
353            runtime_lookup_table: runtime_lookup_table.as_ref().map(f),
354            runtime_lookup_table_selector: runtime_lookup_table_selector.as_ref().map(f),
355            xor_lookup_selector: xor_lookup_selector.as_ref().map(f),
356            lookup_gate_lookup_selector: lookup_gate_lookup_selector.as_ref().map(f),
357            range_check_lookup_selector: range_check_lookup_selector.as_ref().map(f),
358            foreign_field_mul_lookup_selector: foreign_field_mul_lookup_selector.as_ref().map(f),
359        }
360    }
361}
362
363impl<G: AffineRepr> RecursionChallenge<G> {
364    pub fn new(chals: Vec<G::ScalarField>, comm: PolyComm<G>) -> RecursionChallenge<G> {
365        RecursionChallenge { chals, comm }
366    }
367
368    pub fn evals(
369        &self,
370        max_poly_size: usize,
371        evaluation_points: &[G::ScalarField],
372        powers_of_eval_points_for_chunks: &[G::ScalarField],
373    ) -> Vec<Vec<G::ScalarField>> {
374        let RecursionChallenge { chals, comm: _ } = self;
375        // No need to check the correctness of poly explicitly. Its correctness is assured by the
376        // checking of the inner product argument.
377        let b_len = 1 << chals.len();
378        let mut b: Option<Vec<G::ScalarField>> = None;
379
380        (0..2)
381            .map(|i| {
382                let full = b_poly(chals, evaluation_points[i]);
383                if max_poly_size == b_len {
384                    return vec![full];
385                }
386                let mut betaacc = G::ScalarField::one();
387                let diff = (max_poly_size..b_len)
388                    .map(|j| {
389                        let b_j = match &b {
390                            None => {
391                                let t = b_poly_coefficients(chals);
392                                let res = t[j];
393                                b = Some(t);
394                                res
395                            }
396                            Some(b) => b[j],
397                        };
398
399                        let ret = betaacc * b_j;
400                        betaacc *= &evaluation_points[i];
401                        ret
402                    })
403                    .fold(G::ScalarField::zero(), |x, y| x + y);
404                vec![full - (diff * powers_of_eval_points_for_chunks[i]), diff]
405            })
406            .collect()
407    }
408}
409
410impl<F: Zero + Copy> ProofEvaluations<PointEvaluations<F>> {
411    pub fn dummy_with_witness_evaluations(
412        curr: [F; COLUMNS],
413        next: [F; COLUMNS],
414    ) -> ProofEvaluations<PointEvaluations<F>> {
415        let pt = |curr, next| PointEvaluations {
416            zeta: curr,
417            zeta_omega: next,
418        };
419        ProofEvaluations {
420            public: Some(pt(F::zero(), F::zero())),
421            w: array::from_fn(|i| pt(curr[i], next[i])),
422            z: pt(F::zero(), F::zero()),
423            s: array::from_fn(|_| pt(F::zero(), F::zero())),
424            coefficients: array::from_fn(|_| pt(F::zero(), F::zero())),
425            generic_selector: pt(F::zero(), F::zero()),
426            poseidon_selector: pt(F::zero(), F::zero()),
427            complete_add_selector: pt(F::zero(), F::zero()),
428            mul_selector: pt(F::zero(), F::zero()),
429            emul_selector: pt(F::zero(), F::zero()),
430            endomul_scalar_selector: pt(F::zero(), F::zero()),
431            range_check0_selector: None,
432            range_check1_selector: None,
433            foreign_field_add_selector: None,
434            foreign_field_mul_selector: None,
435            xor_selector: None,
436            rot_selector: None,
437            lookup_aggregation: None,
438            lookup_table: None,
439            lookup_sorted: array::from_fn(|_| None),
440            runtime_lookup_table: None,
441            runtime_lookup_table_selector: None,
442            xor_lookup_selector: None,
443            lookup_gate_lookup_selector: None,
444            range_check_lookup_selector: None,
445            foreign_field_mul_lookup_selector: None,
446        }
447    }
448}
449
450impl<F: FftField> ProofEvaluations<PointEvaluations<Vec<F>>> {
451    pub fn combine(&self, pt: &PointEvaluations<F>) -> ProofEvaluations<PointEvaluations<F>> {
452        self.map_ref(&|evals| PointEvaluations {
453            zeta: DensePolynomial::eval_polynomial(&evals.zeta, pt.zeta),
454            zeta_omega: DensePolynomial::eval_polynomial(&evals.zeta_omega, pt.zeta_omega),
455        })
456    }
457}
458
459impl<F> ProofEvaluations<F> {
460    pub fn get_column(&self, col: Column) -> Option<&F> {
461        match col {
462            Column::Witness(i) => Some(&self.w[i]),
463            Column::Z => Some(&self.z),
464            Column::LookupSorted(i) => self.lookup_sorted[i].as_ref(),
465            Column::LookupAggreg => self.lookup_aggregation.as_ref(),
466            Column::LookupTable => self.lookup_table.as_ref(),
467            Column::LookupKindIndex(LookupPattern::Xor) => self.xor_lookup_selector.as_ref(),
468            Column::LookupKindIndex(LookupPattern::Lookup) => {
469                self.lookup_gate_lookup_selector.as_ref()
470            }
471            Column::LookupKindIndex(LookupPattern::RangeCheck) => {
472                self.range_check_lookup_selector.as_ref()
473            }
474            Column::LookupKindIndex(LookupPattern::ForeignFieldMul) => {
475                self.foreign_field_mul_lookup_selector.as_ref()
476            }
477            Column::LookupRuntimeSelector => self.runtime_lookup_table_selector.as_ref(),
478            Column::LookupRuntimeTable => self.runtime_lookup_table.as_ref(),
479            Column::Index(GateType::Generic) => Some(&self.generic_selector),
480            Column::Index(GateType::Poseidon) => Some(&self.poseidon_selector),
481            Column::Index(GateType::CompleteAdd) => Some(&self.complete_add_selector),
482            Column::Index(GateType::VarBaseMul) => Some(&self.mul_selector),
483            Column::Index(GateType::EndoMul) => Some(&self.emul_selector),
484            Column::Index(GateType::EndoMulScalar) => Some(&self.endomul_scalar_selector),
485            Column::Index(GateType::RangeCheck0) => self.range_check0_selector.as_ref(),
486            Column::Index(GateType::RangeCheck1) => self.range_check1_selector.as_ref(),
487            Column::Index(GateType::ForeignFieldAdd) => self.foreign_field_add_selector.as_ref(),
488            Column::Index(GateType::ForeignFieldMul) => self.foreign_field_mul_selector.as_ref(),
489            Column::Index(GateType::Xor16) => self.xor_selector.as_ref(),
490            Column::Index(GateType::Rot64) => self.rot_selector.as_ref(),
491            Column::Index(_) => None,
492            Column::Coefficient(i) => Some(&self.coefficients[i]),
493            Column::Permutation(i) => Some(&self.s[i]),
494        }
495    }
496}
497
498//
499// OCaml types
500//
501
502#[cfg(feature = "ocaml_types")]
503pub mod caml {
504    use super::*;
505    use poly_commitment::commitment::caml::CamlPolyComm;
506
507    //
508    // CamlRecursionChallenge<CamlG, CamlF>
509    //
510
511    #[derive(Clone, ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)]
512    pub struct CamlRecursionChallenge<CamlG, CamlF> {
513        pub chals: Vec<CamlF>,
514        pub comm: CamlPolyComm<CamlG>,
515    }
516
517    //
518    // CamlRecursionChallenge<CamlG, CamlF> <-> RecursionChallenge<G>
519    //
520
521    impl<G, CamlG, CamlF> From<RecursionChallenge<G>> for CamlRecursionChallenge<CamlG, CamlF>
522    where
523        G: AffineRepr,
524        CamlG: From<G>,
525        CamlF: From<G::ScalarField>,
526    {
527        fn from(ch: RecursionChallenge<G>) -> Self {
528            Self {
529                chals: ch.chals.into_iter().map(Into::into).collect(),
530                comm: ch.comm.into(),
531            }
532        }
533    }
534
535    impl<G, CamlG, CamlF> From<CamlRecursionChallenge<CamlG, CamlF>> for RecursionChallenge<G>
536    where
537        G: AffineRepr + From<CamlG>,
538        G::ScalarField: From<CamlF>,
539    {
540        fn from(caml_ch: CamlRecursionChallenge<CamlG, CamlF>) -> RecursionChallenge<G> {
541            RecursionChallenge {
542                chals: caml_ch.chals.into_iter().map(Into::into).collect(),
543                comm: caml_ch.comm.into(),
544            }
545        }
546    }
547
548    //
549    // CamlProofEvaluations<CamlF>
550    //
551
552    #[allow(clippy::type_complexity)]
553    #[derive(Clone, ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)]
554    pub struct CamlProofEvaluations<CamlF> {
555        pub w: (
556            PointEvaluations<Vec<CamlF>>,
557            PointEvaluations<Vec<CamlF>>,
558            PointEvaluations<Vec<CamlF>>,
559            PointEvaluations<Vec<CamlF>>,
560            PointEvaluations<Vec<CamlF>>,
561            PointEvaluations<Vec<CamlF>>,
562            PointEvaluations<Vec<CamlF>>,
563            PointEvaluations<Vec<CamlF>>,
564            PointEvaluations<Vec<CamlF>>,
565            PointEvaluations<Vec<CamlF>>,
566            PointEvaluations<Vec<CamlF>>,
567            PointEvaluations<Vec<CamlF>>,
568            PointEvaluations<Vec<CamlF>>,
569            PointEvaluations<Vec<CamlF>>,
570            PointEvaluations<Vec<CamlF>>,
571        ),
572        pub z: PointEvaluations<Vec<CamlF>>,
573        pub s: (
574            PointEvaluations<Vec<CamlF>>,
575            PointEvaluations<Vec<CamlF>>,
576            PointEvaluations<Vec<CamlF>>,
577            PointEvaluations<Vec<CamlF>>,
578            PointEvaluations<Vec<CamlF>>,
579            PointEvaluations<Vec<CamlF>>,
580        ),
581        pub coefficients: (
582            PointEvaluations<Vec<CamlF>>,
583            PointEvaluations<Vec<CamlF>>,
584            PointEvaluations<Vec<CamlF>>,
585            PointEvaluations<Vec<CamlF>>,
586            PointEvaluations<Vec<CamlF>>,
587            PointEvaluations<Vec<CamlF>>,
588            PointEvaluations<Vec<CamlF>>,
589            PointEvaluations<Vec<CamlF>>,
590            PointEvaluations<Vec<CamlF>>,
591            PointEvaluations<Vec<CamlF>>,
592            PointEvaluations<Vec<CamlF>>,
593            PointEvaluations<Vec<CamlF>>,
594            PointEvaluations<Vec<CamlF>>,
595            PointEvaluations<Vec<CamlF>>,
596            PointEvaluations<Vec<CamlF>>,
597        ),
598
599        pub generic_selector: PointEvaluations<Vec<CamlF>>,
600        pub poseidon_selector: PointEvaluations<Vec<CamlF>>,
601        pub complete_add_selector: PointEvaluations<Vec<CamlF>>,
602        pub mul_selector: PointEvaluations<Vec<CamlF>>,
603        pub emul_selector: PointEvaluations<Vec<CamlF>>,
604        pub endomul_scalar_selector: PointEvaluations<Vec<CamlF>>,
605
606        pub range_check0_selector: Option<PointEvaluations<Vec<CamlF>>>,
607        pub range_check1_selector: Option<PointEvaluations<Vec<CamlF>>>,
608        pub foreign_field_add_selector: Option<PointEvaluations<Vec<CamlF>>>,
609        pub foreign_field_mul_selector: Option<PointEvaluations<Vec<CamlF>>>,
610        pub xor_selector: Option<PointEvaluations<Vec<CamlF>>>,
611        pub rot_selector: Option<PointEvaluations<Vec<CamlF>>>,
612        pub lookup_aggregation: Option<PointEvaluations<Vec<CamlF>>>,
613        pub lookup_table: Option<PointEvaluations<Vec<CamlF>>>,
614        pub lookup_sorted: Vec<Option<PointEvaluations<Vec<CamlF>>>>,
615        pub runtime_lookup_table: Option<PointEvaluations<Vec<CamlF>>>,
616
617        pub runtime_lookup_table_selector: Option<PointEvaluations<Vec<CamlF>>>,
618        pub xor_lookup_selector: Option<PointEvaluations<Vec<CamlF>>>,
619        pub lookup_gate_lookup_selector: Option<PointEvaluations<Vec<CamlF>>>,
620        pub range_check_lookup_selector: Option<PointEvaluations<Vec<CamlF>>>,
621        pub foreign_field_mul_lookup_selector: Option<PointEvaluations<Vec<CamlF>>>,
622    }
623
624    //
625    // ProofEvaluations<Vec<F>> <-> CamlProofEvaluations<CamlF>
626    //
627
628    impl<F, CamlF> From<ProofEvaluations<PointEvaluations<Vec<F>>>>
629        for (
630            Option<PointEvaluations<Vec<CamlF>>>,
631            CamlProofEvaluations<CamlF>,
632        )
633    where
634        F: Clone,
635        CamlF: From<F>,
636    {
637        fn from(pe: ProofEvaluations<PointEvaluations<Vec<F>>>) -> Self {
638            let first = pe.public.map(|x: PointEvaluations<Vec<F>>| {
639                // map both fields of each evaluation.
640                x.map(&|x: Vec<F>| {
641                    let y: Vec<CamlF> = x.into_iter().map(Into::into).collect();
642                    y
643                })
644            });
645            let w = (
646                pe.w[0]
647                    .clone()
648                    .map(&|x| x.into_iter().map(Into::into).collect()),
649                pe.w[1]
650                    .clone()
651                    .map(&|x| x.into_iter().map(Into::into).collect()),
652                pe.w[2]
653                    .clone()
654                    .map(&|x| x.into_iter().map(Into::into).collect()),
655                pe.w[3]
656                    .clone()
657                    .map(&|x| x.into_iter().map(Into::into).collect()),
658                pe.w[4]
659                    .clone()
660                    .map(&|x| x.into_iter().map(Into::into).collect()),
661                pe.w[5]
662                    .clone()
663                    .map(&|x| x.into_iter().map(Into::into).collect()),
664                pe.w[6]
665                    .clone()
666                    .map(&|x| x.into_iter().map(Into::into).collect()),
667                pe.w[7]
668                    .clone()
669                    .map(&|x| x.into_iter().map(Into::into).collect()),
670                pe.w[8]
671                    .clone()
672                    .map(&|x| x.into_iter().map(Into::into).collect()),
673                pe.w[9]
674                    .clone()
675                    .map(&|x| x.into_iter().map(Into::into).collect()),
676                pe.w[10]
677                    .clone()
678                    .map(&|x| x.into_iter().map(Into::into).collect()),
679                pe.w[11]
680                    .clone()
681                    .map(&|x| x.into_iter().map(Into::into).collect()),
682                pe.w[12]
683                    .clone()
684                    .map(&|x| x.into_iter().map(Into::into).collect()),
685                pe.w[13]
686                    .clone()
687                    .map(&|x| x.into_iter().map(Into::into).collect()),
688                pe.w[14]
689                    .clone()
690                    .map(&|x| x.into_iter().map(Into::into).collect()),
691            );
692            let coefficients = (
693                pe.coefficients[0]
694                    .clone()
695                    .map(&|x| x.into_iter().map(Into::into).collect()),
696                pe.coefficients[1]
697                    .clone()
698                    .map(&|x| x.into_iter().map(Into::into).collect()),
699                pe.coefficients[2]
700                    .clone()
701                    .map(&|x| x.into_iter().map(Into::into).collect()),
702                pe.coefficients[3]
703                    .clone()
704                    .map(&|x| x.into_iter().map(Into::into).collect()),
705                pe.coefficients[4]
706                    .clone()
707                    .map(&|x| x.into_iter().map(Into::into).collect()),
708                pe.coefficients[5]
709                    .clone()
710                    .map(&|x| x.into_iter().map(Into::into).collect()),
711                pe.coefficients[6]
712                    .clone()
713                    .map(&|x| x.into_iter().map(Into::into).collect()),
714                pe.coefficients[7]
715                    .clone()
716                    .map(&|x| x.into_iter().map(Into::into).collect()),
717                pe.coefficients[8]
718                    .clone()
719                    .map(&|x| x.into_iter().map(Into::into).collect()),
720                pe.coefficients[9]
721                    .clone()
722                    .map(&|x| x.into_iter().map(Into::into).collect()),
723                pe.coefficients[10]
724                    .clone()
725                    .map(&|x| x.into_iter().map(Into::into).collect()),
726                pe.coefficients[11]
727                    .clone()
728                    .map(&|x| x.into_iter().map(Into::into).collect()),
729                pe.coefficients[12]
730                    .clone()
731                    .map(&|x| x.into_iter().map(Into::into).collect()),
732                pe.coefficients[13]
733                    .clone()
734                    .map(&|x| x.into_iter().map(Into::into).collect()),
735                pe.coefficients[14]
736                    .clone()
737                    .map(&|x| x.into_iter().map(Into::into).collect()),
738            );
739            let s = (
740                pe.s[0]
741                    .clone()
742                    .map(&|x| x.into_iter().map(Into::into).collect()),
743                pe.s[1]
744                    .clone()
745                    .map(&|x| x.into_iter().map(Into::into).collect()),
746                pe.s[2]
747                    .clone()
748                    .map(&|x| x.into_iter().map(Into::into).collect()),
749                pe.s[3]
750                    .clone()
751                    .map(&|x| x.into_iter().map(Into::into).collect()),
752                pe.s[4]
753                    .clone()
754                    .map(&|x| x.into_iter().map(Into::into).collect()),
755                pe.s[5]
756                    .clone()
757                    .map(&|x| x.into_iter().map(Into::into).collect()),
758            );
759
760            let second = CamlProofEvaluations {
761                w,
762                coefficients,
763                z: pe.z.map(&|x| x.into_iter().map(Into::into).collect()),
764                s,
765                generic_selector: pe
766                    .generic_selector
767                    .map(&|x| x.into_iter().map(Into::into).collect()),
768                poseidon_selector: pe
769                    .poseidon_selector
770                    .map(&|x| x.into_iter().map(Into::into).collect()),
771                complete_add_selector: pe
772                    .complete_add_selector
773                    .map(&|x| x.into_iter().map(Into::into).collect()),
774                mul_selector: pe
775                    .mul_selector
776                    .map(&|x| x.into_iter().map(Into::into).collect()),
777                emul_selector: pe
778                    .emul_selector
779                    .map(&|x| x.into_iter().map(Into::into).collect()),
780                endomul_scalar_selector: pe
781                    .endomul_scalar_selector
782                    .map(&|x| x.into_iter().map(Into::into).collect()),
783                range_check0_selector: pe
784                    .range_check0_selector
785                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
786                range_check1_selector: pe
787                    .range_check1_selector
788                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
789                foreign_field_add_selector: pe
790                    .foreign_field_add_selector
791                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
792                foreign_field_mul_selector: pe
793                    .foreign_field_mul_selector
794                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
795                xor_selector: pe
796                    .xor_selector
797                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
798                rot_selector: pe
799                    .rot_selector
800                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
801                lookup_aggregation: pe
802                    .lookup_aggregation
803                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
804                lookup_table: pe
805                    .lookup_table
806                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
807                lookup_sorted: pe
808                    .lookup_sorted
809                    .iter()
810                    .map(|x| {
811                        x.as_ref().map(|x| {
812                            x.map_ref(&|x| x.clone().into_iter().map(Into::into).collect())
813                        })
814                    })
815                    .collect::<Vec<_>>(),
816                runtime_lookup_table: pe
817                    .runtime_lookup_table
818                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
819                runtime_lookup_table_selector: pe
820                    .runtime_lookup_table_selector
821                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
822                xor_lookup_selector: pe
823                    .xor_lookup_selector
824                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
825                lookup_gate_lookup_selector: pe
826                    .lookup_gate_lookup_selector
827                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
828                range_check_lookup_selector: pe
829                    .range_check_lookup_selector
830                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
831                foreign_field_mul_lookup_selector: pe
832                    .foreign_field_mul_lookup_selector
833                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
834            };
835
836            (first, second)
837        }
838    }
839
840    impl<F, CamlF>
841        From<(
842            Option<PointEvaluations<Vec<CamlF>>>,
843            CamlProofEvaluations<CamlF>,
844        )> for ProofEvaluations<PointEvaluations<Vec<F>>>
845    where
846        F: Clone,
847        CamlF: Clone,
848        F: From<CamlF>,
849    {
850        fn from(
851            (public, cpe): (
852                Option<PointEvaluations<Vec<CamlF>>>,
853                CamlProofEvaluations<CamlF>,
854            ),
855        ) -> Self {
856            let w = [
857                cpe.w.0.map(&|x| x.into_iter().map(Into::into).collect()),
858                cpe.w.1.map(&|x| x.into_iter().map(Into::into).collect()),
859                cpe.w.2.map(&|x| x.into_iter().map(Into::into).collect()),
860                cpe.w.3.map(&|x| x.into_iter().map(Into::into).collect()),
861                cpe.w.4.map(&|x| x.into_iter().map(Into::into).collect()),
862                cpe.w.5.map(&|x| x.into_iter().map(Into::into).collect()),
863                cpe.w.6.map(&|x| x.into_iter().map(Into::into).collect()),
864                cpe.w.7.map(&|x| x.into_iter().map(Into::into).collect()),
865                cpe.w.8.map(&|x| x.into_iter().map(Into::into).collect()),
866                cpe.w.9.map(&|x| x.into_iter().map(Into::into).collect()),
867                cpe.w.10.map(&|x| x.into_iter().map(Into::into).collect()),
868                cpe.w.11.map(&|x| x.into_iter().map(Into::into).collect()),
869                cpe.w.12.map(&|x| x.into_iter().map(Into::into).collect()),
870                cpe.w.13.map(&|x| x.into_iter().map(Into::into).collect()),
871                cpe.w.14.map(&|x| x.into_iter().map(Into::into).collect()),
872            ];
873            let coefficients = [
874                cpe.coefficients
875                    .0
876                    .map(&|x| x.into_iter().map(Into::into).collect()),
877                cpe.coefficients
878                    .1
879                    .map(&|x| x.into_iter().map(Into::into).collect()),
880                cpe.coefficients
881                    .2
882                    .map(&|x| x.into_iter().map(Into::into).collect()),
883                cpe.coefficients
884                    .3
885                    .map(&|x| x.into_iter().map(Into::into).collect()),
886                cpe.coefficients
887                    .4
888                    .map(&|x| x.into_iter().map(Into::into).collect()),
889                cpe.coefficients
890                    .5
891                    .map(&|x| x.into_iter().map(Into::into).collect()),
892                cpe.coefficients
893                    .6
894                    .map(&|x| x.into_iter().map(Into::into).collect()),
895                cpe.coefficients
896                    .7
897                    .map(&|x| x.into_iter().map(Into::into).collect()),
898                cpe.coefficients
899                    .8
900                    .map(&|x| x.into_iter().map(Into::into).collect()),
901                cpe.coefficients
902                    .9
903                    .map(&|x| x.into_iter().map(Into::into).collect()),
904                cpe.coefficients
905                    .10
906                    .map(&|x| x.into_iter().map(Into::into).collect()),
907                cpe.coefficients
908                    .11
909                    .map(&|x| x.into_iter().map(Into::into).collect()),
910                cpe.coefficients
911                    .12
912                    .map(&|x| x.into_iter().map(Into::into).collect()),
913                cpe.coefficients
914                    .13
915                    .map(&|x| x.into_iter().map(Into::into).collect()),
916                cpe.coefficients
917                    .14
918                    .map(&|x| x.into_iter().map(Into::into).collect()),
919            ];
920            let s = [
921                cpe.s.0.map(&|x| x.into_iter().map(Into::into).collect()),
922                cpe.s.1.map(&|x| x.into_iter().map(Into::into).collect()),
923                cpe.s.2.map(&|x| x.into_iter().map(Into::into).collect()),
924                cpe.s.3.map(&|x| x.into_iter().map(Into::into).collect()),
925                cpe.s.4.map(&|x| x.into_iter().map(Into::into).collect()),
926                cpe.s.5.map(&|x| x.into_iter().map(Into::into).collect()),
927            ];
928
929            Self {
930                public: public.map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
931                w,
932                coefficients,
933                z: cpe.z.map(&|x| x.into_iter().map(Into::into).collect()),
934                s,
935                generic_selector: cpe
936                    .generic_selector
937                    .map(&|x| x.into_iter().map(Into::into).collect()),
938                poseidon_selector: cpe
939                    .poseidon_selector
940                    .map(&|x| x.into_iter().map(Into::into).collect()),
941                complete_add_selector: cpe
942                    .complete_add_selector
943                    .map(&|x| x.into_iter().map(Into::into).collect()),
944                mul_selector: cpe
945                    .mul_selector
946                    .map(&|x| x.into_iter().map(Into::into).collect()),
947                emul_selector: cpe
948                    .emul_selector
949                    .map(&|x| x.into_iter().map(Into::into).collect()),
950                endomul_scalar_selector: cpe
951                    .endomul_scalar_selector
952                    .map(&|x| x.into_iter().map(Into::into).collect()),
953                range_check0_selector: cpe
954                    .range_check0_selector
955                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
956                range_check1_selector: cpe
957                    .range_check1_selector
958                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
959                foreign_field_add_selector: cpe
960                    .foreign_field_add_selector
961                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
962                foreign_field_mul_selector: cpe
963                    .foreign_field_mul_selector
964                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
965                xor_selector: cpe
966                    .xor_selector
967                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
968                rot_selector: cpe
969                    .rot_selector
970                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
971                lookup_aggregation: cpe
972                    .lookup_aggregation
973                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
974                lookup_table: cpe
975                    .lookup_table
976                    .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
977                lookup_sorted: {
978                    assert_eq!(cpe.lookup_sorted.len(), 5); // Invalid proof
979                    array::from_fn(|i| {
980                        cpe.lookup_sorted[i]
981                            .as_ref()
982                            .map(|x| x.clone().map(&|x| x.into_iter().map(Into::into).collect()))
983                    })
984                },
985                runtime_lookup_table: cpe
986                    .runtime_lookup_table
987                    .map(|x| x.map(&|x| x.iter().map(|x| x.clone().into()).collect())),
988                runtime_lookup_table_selector: cpe
989                    .runtime_lookup_table_selector
990                    .map(|x| x.map(&|x| x.iter().map(|x| x.clone().into()).collect())),
991                xor_lookup_selector: cpe
992                    .xor_lookup_selector
993                    .map(|x| x.map(&|x| x.iter().map(|x| x.clone().into()).collect())),
994                lookup_gate_lookup_selector: cpe
995                    .lookup_gate_lookup_selector
996                    .map(|x| x.map(&|x| x.iter().map(|x| x.clone().into()).collect())),
997                range_check_lookup_selector: cpe
998                    .range_check_lookup_selector
999                    .map(|x| x.map(&|x| x.iter().map(|x| x.clone().into()).collect())),
1000                foreign_field_mul_lookup_selector: cpe
1001                    .foreign_field_mul_lookup_selector
1002                    .map(|x| x.map(&|x| x.iter().map(|x| x.clone().into()).collect())),
1003            }
1004        }
1005    }
1006}