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