1use alloc::{vec, vec::Vec};
3
4use crate::circuits::{
5 berkeley_columns::Column,
6 gate::GateType,
7 lookup::lookups::LookupPattern,
8 wires::{COLUMNS, PERMUTS},
9};
10use ark_ec::AffineRepr;
11use ark_ff::{FftField, One, Zero};
12use ark_poly::univariate::DensePolynomial;
13use core::array;
14use o1_utils::ExtendedDensePolynomial;
15use poly_commitment::{
16 commitment::{b_poly, b_poly_coefficients, CommitmentCurve, PolyComm},
17 OpenProof,
18};
19use serde::{Deserialize, Serialize};
20use serde_with::serde_as;
21
22#[serde_as]
25#[derive(Copy, Clone, Serialize, Deserialize, Default, Debug, PartialEq)]
26#[cfg_attr(
27 feature = "ocaml_types",
28 derive(ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)
29)]
30#[serde(bound(
31 serialize = "Vec<o1_utils::serialization::SerdeAs>: serde_with::SerializeAs<Evals>",
32 deserialize = "Vec<o1_utils::serialization::SerdeAs>: serde_with::DeserializeAs<'de, Evals>"
33))]
34pub struct PointEvaluations<Evals> {
35 #[serde_as(as = "Vec<o1_utils::serialization::SerdeAs>")]
37 pub zeta: Evals,
38 #[serde_as(as = "Vec<o1_utils::serialization::SerdeAs>")]
40 pub zeta_omega: Evals,
41}
42
43#[serde_as]
50#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
51pub struct ProofEvaluations<Evals> {
52 pub public: Option<Evals>,
54 pub w: [Evals; COLUMNS],
56 pub z: Evals,
58 pub s: [Evals; PERMUTS - 1],
62 pub coefficients: [Evals; COLUMNS],
64 pub generic_selector: Evals,
66 pub poseidon_selector: Evals,
68 pub complete_add_selector: Evals,
70 pub mul_selector: Evals,
73 pub emul_selector: Evals,
75 pub endomul_scalar_selector: Evals,
78
79 pub range_check0_selector: Option<Evals>,
82 pub range_check1_selector: Option<Evals>,
84 pub foreign_field_add_selector: Option<Evals>,
86 pub foreign_field_mul_selector: Option<Evals>,
88 pub xor_selector: Option<Evals>,
90 pub rot_selector: Option<Evals>,
92
93 pub lookup_aggregation: Option<Evals>,
96 pub lookup_table: Option<Evals>,
98 pub lookup_sorted: [Option<Evals>; 5],
100 pub runtime_lookup_table: Option<Evals>,
102
103 pub runtime_lookup_table_selector: Option<Evals>,
106 pub xor_lookup_selector: Option<Evals>,
108 pub lookup_gate_lookup_selector: Option<Evals>,
110 pub range_check_lookup_selector: Option<Evals>,
112 pub foreign_field_mul_lookup_selector: Option<Evals>,
115}
116
117#[serde_as]
119#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
120#[serde(bound = "G: ark_serialize::CanonicalDeserialize + ark_serialize::CanonicalSerialize")]
121pub struct LookupCommitments<G: AffineRepr> {
122 pub sorted: Vec<PolyComm<G>>,
124 pub aggreg: PolyComm<G>,
126 pub runtime: Option<PolyComm<G>>,
128}
129
130#[serde_as]
132#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
133#[serde(bound = "G: ark_serialize::CanonicalDeserialize + ark_serialize::CanonicalSerialize")]
134pub struct ProverCommitments<G: AffineRepr> {
135 pub w_comm: [PolyComm<G>; COLUMNS],
137 pub z_comm: PolyComm<G>,
139 pub t_comm: PolyComm<G>,
141 pub lookup: Option<LookupCommitments<G>>,
143}
144
145#[serde_as]
148#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
149#[serde(bound = "G: ark_serialize::CanonicalDeserialize + ark_serialize::CanonicalSerialize")]
150pub struct ProverProof<G, OpeningProof, const FULL_ROUNDS: usize>
151where
152 G: CommitmentCurve,
153 OpeningProof: OpenProof<G, FULL_ROUNDS>,
154{
155 pub commitments: ProverCommitments<G>,
157
158 #[serde(bound(
160 serialize = "OpeningProof: Serialize",
161 deserialize = "OpeningProof: Deserialize<'de>"
162 ))]
163 pub proof: OpeningProof,
164
165 pub evals: ProofEvaluations<PointEvaluations<Vec<G::ScalarField>>>,
167
168 #[serde_as(as = "o1_utils::serialization::SerdeAs")]
171 pub ft_eval1: G::ScalarField,
172
173 pub prev_challenges: Vec<RecursionChallenge<G>>,
195}
196
197#[serde_as]
223#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
224#[serde(bound = "G: ark_serialize::CanonicalDeserialize + ark_serialize::CanonicalSerialize")]
225pub struct RecursionChallenge<G>
226where
227 G: AffineRepr,
228{
229 #[serde_as(as = "Vec<o1_utils::serialization::SerdeAs>")]
232 pub chals: Vec<G::ScalarField>,
233 pub comm: PolyComm<G>,
242}
243
244impl<Evals> PointEvaluations<Evals> {
247 pub fn map<Evals2, FN: Fn(Evals) -> Evals2>(self, f: &FN) -> PointEvaluations<Evals2> {
248 let PointEvaluations { zeta, zeta_omega } = self;
249 PointEvaluations {
250 zeta: f(zeta),
251 zeta_omega: f(zeta_omega),
252 }
253 }
254
255 pub fn map_ref<Evals2, FN: Fn(&Evals) -> Evals2>(&self, f: &FN) -> PointEvaluations<Evals2> {
256 let PointEvaluations { zeta, zeta_omega } = self;
257 PointEvaluations {
258 zeta: f(zeta),
259 zeta_omega: f(zeta_omega),
260 }
261 }
262}
263
264impl<Eval> ProofEvaluations<Eval> {
265 pub fn map<Eval2, FN: Fn(Eval) -> Eval2>(self, f: &FN) -> ProofEvaluations<Eval2> {
266 let ProofEvaluations {
267 public,
268 w,
269 z,
270 s,
271 coefficients,
272 generic_selector,
273 poseidon_selector,
274 complete_add_selector,
275 mul_selector,
276 emul_selector,
277 endomul_scalar_selector,
278 range_check0_selector,
279 range_check1_selector,
280 foreign_field_add_selector,
281 foreign_field_mul_selector,
282 xor_selector,
283 rot_selector,
284 lookup_aggregation,
285 lookup_table,
286 lookup_sorted,
287 runtime_lookup_table,
288 runtime_lookup_table_selector,
289 xor_lookup_selector,
290 lookup_gate_lookup_selector,
291 range_check_lookup_selector,
292 foreign_field_mul_lookup_selector,
293 } = self;
294 ProofEvaluations {
295 public: public.map(f),
296 w: w.map(f),
297 z: f(z),
298 s: s.map(f),
299 coefficients: coefficients.map(f),
300 generic_selector: f(generic_selector),
301 poseidon_selector: f(poseidon_selector),
302 complete_add_selector: f(complete_add_selector),
303 mul_selector: f(mul_selector),
304 emul_selector: f(emul_selector),
305 endomul_scalar_selector: f(endomul_scalar_selector),
306 range_check0_selector: range_check0_selector.map(f),
307 range_check1_selector: range_check1_selector.map(f),
308 foreign_field_add_selector: foreign_field_add_selector.map(f),
309 foreign_field_mul_selector: foreign_field_mul_selector.map(f),
310 xor_selector: xor_selector.map(f),
311 rot_selector: rot_selector.map(f),
312 lookup_aggregation: lookup_aggregation.map(f),
313 lookup_table: lookup_table.map(f),
314 lookup_sorted: lookup_sorted.map(|x| x.map(f)),
315 runtime_lookup_table: runtime_lookup_table.map(f),
316 runtime_lookup_table_selector: runtime_lookup_table_selector.map(f),
317 xor_lookup_selector: xor_lookup_selector.map(f),
318 lookup_gate_lookup_selector: lookup_gate_lookup_selector.map(f),
319 range_check_lookup_selector: range_check_lookup_selector.map(f),
320 foreign_field_mul_lookup_selector: foreign_field_mul_lookup_selector.map(f),
321 }
322 }
323
324 pub fn map_ref<Eval2, FN: Fn(&Eval) -> Eval2>(&self, f: &FN) -> ProofEvaluations<Eval2> {
325 let ProofEvaluations {
326 public,
327 w: [w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14],
328 z,
329 s: [s0, s1, s2, s3, s4, s5],
330 coefficients: [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14],
331 generic_selector,
332 poseidon_selector,
333 complete_add_selector,
334 mul_selector,
335 emul_selector,
336 endomul_scalar_selector,
337 range_check0_selector,
338 range_check1_selector,
339 foreign_field_add_selector,
340 foreign_field_mul_selector,
341 xor_selector,
342 rot_selector,
343 lookup_aggregation,
344 lookup_table,
345 lookup_sorted,
346 runtime_lookup_table,
347 runtime_lookup_table_selector,
348 xor_lookup_selector,
349 lookup_gate_lookup_selector,
350 range_check_lookup_selector,
351 foreign_field_mul_lookup_selector,
352 } = self;
353 ProofEvaluations {
354 public: public.as_ref().map(f),
355 w: [
356 f(w0),
357 f(w1),
358 f(w2),
359 f(w3),
360 f(w4),
361 f(w5),
362 f(w6),
363 f(w7),
364 f(w8),
365 f(w9),
366 f(w10),
367 f(w11),
368 f(w12),
369 f(w13),
370 f(w14),
371 ],
372 z: f(z),
373 s: [f(s0), f(s1), f(s2), f(s3), f(s4), f(s5)],
374 coefficients: [
375 f(c0),
376 f(c1),
377 f(c2),
378 f(c3),
379 f(c4),
380 f(c5),
381 f(c6),
382 f(c7),
383 f(c8),
384 f(c9),
385 f(c10),
386 f(c11),
387 f(c12),
388 f(c13),
389 f(c14),
390 ],
391 generic_selector: f(generic_selector),
392 poseidon_selector: f(poseidon_selector),
393 complete_add_selector: f(complete_add_selector),
394 mul_selector: f(mul_selector),
395 emul_selector: f(emul_selector),
396 endomul_scalar_selector: f(endomul_scalar_selector),
397 range_check0_selector: range_check0_selector.as_ref().map(f),
398 range_check1_selector: range_check1_selector.as_ref().map(f),
399 foreign_field_add_selector: foreign_field_add_selector.as_ref().map(f),
400 foreign_field_mul_selector: foreign_field_mul_selector.as_ref().map(f),
401 xor_selector: xor_selector.as_ref().map(f),
402 rot_selector: rot_selector.as_ref().map(f),
403 lookup_aggregation: lookup_aggregation.as_ref().map(f),
404 lookup_table: lookup_table.as_ref().map(f),
405 lookup_sorted: array::from_fn(|i| lookup_sorted[i].as_ref().map(f)),
406 runtime_lookup_table: runtime_lookup_table.as_ref().map(f),
407 runtime_lookup_table_selector: runtime_lookup_table_selector.as_ref().map(f),
408 xor_lookup_selector: xor_lookup_selector.as_ref().map(f),
409 lookup_gate_lookup_selector: lookup_gate_lookup_selector.as_ref().map(f),
410 range_check_lookup_selector: range_check_lookup_selector.as_ref().map(f),
411 foreign_field_mul_lookup_selector: foreign_field_mul_lookup_selector.as_ref().map(f),
412 }
413 }
414}
415
416impl<G: AffineRepr> RecursionChallenge<G> {
417 pub fn new(chals: Vec<G::ScalarField>, comm: PolyComm<G>) -> RecursionChallenge<G> {
418 RecursionChallenge { chals, comm }
419 }
420
421 pub fn evals(
456 &self,
457 max_poly_size: usize,
458 evaluation_points: &[G::ScalarField],
459 powers_of_eval_points_for_chunks: &[G::ScalarField],
460 ) -> Vec<Vec<G::ScalarField>> {
461 let RecursionChallenge { chals, comm: _ } = self;
462 let b_len = 1 << chals.len();
465 let mut b: Option<Vec<G::ScalarField>> = None;
466
467 (0..2)
468 .map(|i| {
469 let full = b_poly(chals, evaluation_points[i]);
470 if max_poly_size == b_len {
471 return vec![full];
472 }
473 let mut betaacc = G::ScalarField::one();
474 let diff = (max_poly_size..b_len)
475 .map(|j| {
476 let b_j = match &b {
477 None => {
478 let t = b_poly_coefficients(chals);
479 let res = t[j];
480 b = Some(t);
481 res
482 }
483 Some(b) => b[j],
484 };
485
486 let ret = betaacc * b_j;
487 betaacc *= &evaluation_points[i];
488 ret
489 })
490 .fold(G::ScalarField::zero(), |x, y| x + y);
491 vec![full - (diff * powers_of_eval_points_for_chunks[i]), diff]
492 })
493 .collect()
494 }
495}
496
497impl<F: Zero + Copy> ProofEvaluations<PointEvaluations<F>> {
498 pub fn dummy_with_witness_evaluations(
499 curr: [F; COLUMNS],
500 next: [F; COLUMNS],
501 ) -> ProofEvaluations<PointEvaluations<F>> {
502 let pt = |curr, next| PointEvaluations {
503 zeta: curr,
504 zeta_omega: next,
505 };
506 ProofEvaluations {
507 public: Some(pt(F::zero(), F::zero())),
508 w: array::from_fn(|i| pt(curr[i], next[i])),
509 z: pt(F::zero(), F::zero()),
510 s: array::from_fn(|_| pt(F::zero(), F::zero())),
511 coefficients: array::from_fn(|_| pt(F::zero(), F::zero())),
512 generic_selector: pt(F::zero(), F::zero()),
513 poseidon_selector: pt(F::zero(), F::zero()),
514 complete_add_selector: pt(F::zero(), F::zero()),
515 mul_selector: pt(F::zero(), F::zero()),
516 emul_selector: pt(F::zero(), F::zero()),
517 endomul_scalar_selector: pt(F::zero(), F::zero()),
518 range_check0_selector: None,
519 range_check1_selector: None,
520 foreign_field_add_selector: None,
521 foreign_field_mul_selector: None,
522 xor_selector: None,
523 rot_selector: None,
524 lookup_aggregation: None,
525 lookup_table: None,
526 lookup_sorted: array::from_fn(|_| None),
527 runtime_lookup_table: None,
528 runtime_lookup_table_selector: None,
529 xor_lookup_selector: None,
530 lookup_gate_lookup_selector: None,
531 range_check_lookup_selector: None,
532 foreign_field_mul_lookup_selector: None,
533 }
534 }
535}
536
537impl<F: FftField> ProofEvaluations<PointEvaluations<Vec<F>>> {
538 pub fn combine(&self, pt: &PointEvaluations<F>) -> ProofEvaluations<PointEvaluations<F>> {
539 self.map_ref(&|evals| PointEvaluations {
540 zeta: DensePolynomial::eval_polynomial(&evals.zeta, pt.zeta),
541 zeta_omega: DensePolynomial::eval_polynomial(&evals.zeta_omega, pt.zeta_omega),
542 })
543 }
544}
545
546impl<F> ProofEvaluations<F> {
547 pub fn get_column(&self, col: Column) -> Option<&F> {
548 match col {
549 Column::Witness(i) => Some(&self.w[i]),
550 Column::Z => Some(&self.z),
551 Column::LookupSorted(i) => self.lookup_sorted[i].as_ref(),
552 Column::LookupAggreg => self.lookup_aggregation.as_ref(),
553 Column::LookupTable => self.lookup_table.as_ref(),
554 Column::LookupKindIndex(LookupPattern::Xor) => self.xor_lookup_selector.as_ref(),
555 Column::LookupKindIndex(LookupPattern::Lookup) => {
556 self.lookup_gate_lookup_selector.as_ref()
557 }
558 Column::LookupKindIndex(LookupPattern::RangeCheck) => {
559 self.range_check_lookup_selector.as_ref()
560 }
561 Column::LookupKindIndex(LookupPattern::ForeignFieldMul) => {
562 self.foreign_field_mul_lookup_selector.as_ref()
563 }
564 Column::LookupRuntimeSelector => self.runtime_lookup_table_selector.as_ref(),
565 Column::LookupRuntimeTable => self.runtime_lookup_table.as_ref(),
566 Column::Index(GateType::Generic) => Some(&self.generic_selector),
567 Column::Index(GateType::Poseidon) => Some(&self.poseidon_selector),
568 Column::Index(GateType::CompleteAdd) => Some(&self.complete_add_selector),
569 Column::Index(GateType::VarBaseMul) => Some(&self.mul_selector),
570 Column::Index(GateType::EndoMul) => Some(&self.emul_selector),
571 Column::Index(GateType::EndoMulScalar) => Some(&self.endomul_scalar_selector),
572 Column::Index(GateType::RangeCheck0) => self.range_check0_selector.as_ref(),
573 Column::Index(GateType::RangeCheck1) => self.range_check1_selector.as_ref(),
574 Column::Index(GateType::ForeignFieldAdd) => self.foreign_field_add_selector.as_ref(),
575 Column::Index(GateType::ForeignFieldMul) => self.foreign_field_mul_selector.as_ref(),
576 Column::Index(GateType::Xor16) => self.xor_selector.as_ref(),
577 Column::Index(GateType::Rot64) => self.rot_selector.as_ref(),
578 Column::Index(_) => None,
579 Column::Coefficient(i) => Some(&self.coefficients[i]),
580 Column::Permutation(i) => Some(&self.s[i]),
581 }
582 }
583}
584
585#[cfg(feature = "ocaml_types")]
590pub mod caml {
591 use super::*;
592 use poly_commitment::commitment::caml::CamlPolyComm;
593
594 #[derive(Clone, ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)]
599 pub struct CamlRecursionChallenge<CamlG, CamlF> {
600 pub chals: Vec<CamlF>,
601 pub comm: CamlPolyComm<CamlG>,
602 }
603
604 impl<G, CamlG, CamlF> From<RecursionChallenge<G>> for CamlRecursionChallenge<CamlG, CamlF>
609 where
610 G: AffineRepr,
611 CamlG: From<G>,
612 CamlF: From<G::ScalarField>,
613 {
614 fn from(ch: RecursionChallenge<G>) -> Self {
615 Self {
616 chals: ch.chals.into_iter().map(Into::into).collect(),
617 comm: ch.comm.into(),
618 }
619 }
620 }
621
622 impl<G, CamlG, CamlF> From<CamlRecursionChallenge<CamlG, CamlF>> for RecursionChallenge<G>
623 where
624 G: AffineRepr + From<CamlG>,
625 G::ScalarField: From<CamlF>,
626 {
627 fn from(caml_ch: CamlRecursionChallenge<CamlG, CamlF>) -> RecursionChallenge<G> {
628 RecursionChallenge {
629 chals: caml_ch.chals.into_iter().map(Into::into).collect(),
630 comm: caml_ch.comm.into(),
631 }
632 }
633 }
634
635 #[allow(clippy::type_complexity)]
640 #[derive(Clone, ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)]
641 pub struct CamlProofEvaluations<CamlF> {
642 pub w: (
643 PointEvaluations<Vec<CamlF>>,
644 PointEvaluations<Vec<CamlF>>,
645 PointEvaluations<Vec<CamlF>>,
646 PointEvaluations<Vec<CamlF>>,
647 PointEvaluations<Vec<CamlF>>,
648 PointEvaluations<Vec<CamlF>>,
649 PointEvaluations<Vec<CamlF>>,
650 PointEvaluations<Vec<CamlF>>,
651 PointEvaluations<Vec<CamlF>>,
652 PointEvaluations<Vec<CamlF>>,
653 PointEvaluations<Vec<CamlF>>,
654 PointEvaluations<Vec<CamlF>>,
655 PointEvaluations<Vec<CamlF>>,
656 PointEvaluations<Vec<CamlF>>,
657 PointEvaluations<Vec<CamlF>>,
658 ),
659 pub z: PointEvaluations<Vec<CamlF>>,
660 pub s: (
661 PointEvaluations<Vec<CamlF>>,
662 PointEvaluations<Vec<CamlF>>,
663 PointEvaluations<Vec<CamlF>>,
664 PointEvaluations<Vec<CamlF>>,
665 PointEvaluations<Vec<CamlF>>,
666 PointEvaluations<Vec<CamlF>>,
667 ),
668 pub coefficients: (
669 PointEvaluations<Vec<CamlF>>,
670 PointEvaluations<Vec<CamlF>>,
671 PointEvaluations<Vec<CamlF>>,
672 PointEvaluations<Vec<CamlF>>,
673 PointEvaluations<Vec<CamlF>>,
674 PointEvaluations<Vec<CamlF>>,
675 PointEvaluations<Vec<CamlF>>,
676 PointEvaluations<Vec<CamlF>>,
677 PointEvaluations<Vec<CamlF>>,
678 PointEvaluations<Vec<CamlF>>,
679 PointEvaluations<Vec<CamlF>>,
680 PointEvaluations<Vec<CamlF>>,
681 PointEvaluations<Vec<CamlF>>,
682 PointEvaluations<Vec<CamlF>>,
683 PointEvaluations<Vec<CamlF>>,
684 ),
685
686 pub generic_selector: PointEvaluations<Vec<CamlF>>,
687 pub poseidon_selector: PointEvaluations<Vec<CamlF>>,
688 pub complete_add_selector: PointEvaluations<Vec<CamlF>>,
689 pub mul_selector: PointEvaluations<Vec<CamlF>>,
690 pub emul_selector: PointEvaluations<Vec<CamlF>>,
691 pub endomul_scalar_selector: PointEvaluations<Vec<CamlF>>,
692
693 pub range_check0_selector: Option<PointEvaluations<Vec<CamlF>>>,
694 pub range_check1_selector: Option<PointEvaluations<Vec<CamlF>>>,
695 pub foreign_field_add_selector: Option<PointEvaluations<Vec<CamlF>>>,
696 pub foreign_field_mul_selector: Option<PointEvaluations<Vec<CamlF>>>,
697 pub xor_selector: Option<PointEvaluations<Vec<CamlF>>>,
698 pub rot_selector: Option<PointEvaluations<Vec<CamlF>>>,
699 pub lookup_aggregation: Option<PointEvaluations<Vec<CamlF>>>,
700 pub lookup_table: Option<PointEvaluations<Vec<CamlF>>>,
701 pub lookup_sorted: Vec<Option<PointEvaluations<Vec<CamlF>>>>,
702 pub runtime_lookup_table: Option<PointEvaluations<Vec<CamlF>>>,
703
704 pub runtime_lookup_table_selector: Option<PointEvaluations<Vec<CamlF>>>,
705 pub xor_lookup_selector: Option<PointEvaluations<Vec<CamlF>>>,
706 pub lookup_gate_lookup_selector: Option<PointEvaluations<Vec<CamlF>>>,
707 pub range_check_lookup_selector: Option<PointEvaluations<Vec<CamlF>>>,
708 pub foreign_field_mul_lookup_selector: Option<PointEvaluations<Vec<CamlF>>>,
709 }
710
711 impl<F, CamlF> From<ProofEvaluations<PointEvaluations<Vec<F>>>>
716 for (
717 Option<PointEvaluations<Vec<CamlF>>>,
718 CamlProofEvaluations<CamlF>,
719 )
720 where
721 F: Clone,
722 CamlF: From<F>,
723 {
724 fn from(pe: ProofEvaluations<PointEvaluations<Vec<F>>>) -> Self {
725 let first = pe.public.map(|x: PointEvaluations<Vec<F>>| {
726 x.map(&|x: Vec<F>| {
728 let y: Vec<CamlF> = x.into_iter().map(Into::into).collect();
729 y
730 })
731 });
732 let w = (
733 pe.w[0]
734 .clone()
735 .map(&|x| x.into_iter().map(Into::into).collect()),
736 pe.w[1]
737 .clone()
738 .map(&|x| x.into_iter().map(Into::into).collect()),
739 pe.w[2]
740 .clone()
741 .map(&|x| x.into_iter().map(Into::into).collect()),
742 pe.w[3]
743 .clone()
744 .map(&|x| x.into_iter().map(Into::into).collect()),
745 pe.w[4]
746 .clone()
747 .map(&|x| x.into_iter().map(Into::into).collect()),
748 pe.w[5]
749 .clone()
750 .map(&|x| x.into_iter().map(Into::into).collect()),
751 pe.w[6]
752 .clone()
753 .map(&|x| x.into_iter().map(Into::into).collect()),
754 pe.w[7]
755 .clone()
756 .map(&|x| x.into_iter().map(Into::into).collect()),
757 pe.w[8]
758 .clone()
759 .map(&|x| x.into_iter().map(Into::into).collect()),
760 pe.w[9]
761 .clone()
762 .map(&|x| x.into_iter().map(Into::into).collect()),
763 pe.w[10]
764 .clone()
765 .map(&|x| x.into_iter().map(Into::into).collect()),
766 pe.w[11]
767 .clone()
768 .map(&|x| x.into_iter().map(Into::into).collect()),
769 pe.w[12]
770 .clone()
771 .map(&|x| x.into_iter().map(Into::into).collect()),
772 pe.w[13]
773 .clone()
774 .map(&|x| x.into_iter().map(Into::into).collect()),
775 pe.w[14]
776 .clone()
777 .map(&|x| x.into_iter().map(Into::into).collect()),
778 );
779 let coefficients = (
780 pe.coefficients[0]
781 .clone()
782 .map(&|x| x.into_iter().map(Into::into).collect()),
783 pe.coefficients[1]
784 .clone()
785 .map(&|x| x.into_iter().map(Into::into).collect()),
786 pe.coefficients[2]
787 .clone()
788 .map(&|x| x.into_iter().map(Into::into).collect()),
789 pe.coefficients[3]
790 .clone()
791 .map(&|x| x.into_iter().map(Into::into).collect()),
792 pe.coefficients[4]
793 .clone()
794 .map(&|x| x.into_iter().map(Into::into).collect()),
795 pe.coefficients[5]
796 .clone()
797 .map(&|x| x.into_iter().map(Into::into).collect()),
798 pe.coefficients[6]
799 .clone()
800 .map(&|x| x.into_iter().map(Into::into).collect()),
801 pe.coefficients[7]
802 .clone()
803 .map(&|x| x.into_iter().map(Into::into).collect()),
804 pe.coefficients[8]
805 .clone()
806 .map(&|x| x.into_iter().map(Into::into).collect()),
807 pe.coefficients[9]
808 .clone()
809 .map(&|x| x.into_iter().map(Into::into).collect()),
810 pe.coefficients[10]
811 .clone()
812 .map(&|x| x.into_iter().map(Into::into).collect()),
813 pe.coefficients[11]
814 .clone()
815 .map(&|x| x.into_iter().map(Into::into).collect()),
816 pe.coefficients[12]
817 .clone()
818 .map(&|x| x.into_iter().map(Into::into).collect()),
819 pe.coefficients[13]
820 .clone()
821 .map(&|x| x.into_iter().map(Into::into).collect()),
822 pe.coefficients[14]
823 .clone()
824 .map(&|x| x.into_iter().map(Into::into).collect()),
825 );
826 let s = (
827 pe.s[0]
828 .clone()
829 .map(&|x| x.into_iter().map(Into::into).collect()),
830 pe.s[1]
831 .clone()
832 .map(&|x| x.into_iter().map(Into::into).collect()),
833 pe.s[2]
834 .clone()
835 .map(&|x| x.into_iter().map(Into::into).collect()),
836 pe.s[3]
837 .clone()
838 .map(&|x| x.into_iter().map(Into::into).collect()),
839 pe.s[4]
840 .clone()
841 .map(&|x| x.into_iter().map(Into::into).collect()),
842 pe.s[5]
843 .clone()
844 .map(&|x| x.into_iter().map(Into::into).collect()),
845 );
846
847 let second = CamlProofEvaluations {
848 w,
849 coefficients,
850 z: pe.z.map(&|x| x.into_iter().map(Into::into).collect()),
851 s,
852 generic_selector: pe
853 .generic_selector
854 .map(&|x| x.into_iter().map(Into::into).collect()),
855 poseidon_selector: pe
856 .poseidon_selector
857 .map(&|x| x.into_iter().map(Into::into).collect()),
858 complete_add_selector: pe
859 .complete_add_selector
860 .map(&|x| x.into_iter().map(Into::into).collect()),
861 mul_selector: pe
862 .mul_selector
863 .map(&|x| x.into_iter().map(Into::into).collect()),
864 emul_selector: pe
865 .emul_selector
866 .map(&|x| x.into_iter().map(Into::into).collect()),
867 endomul_scalar_selector: pe
868 .endomul_scalar_selector
869 .map(&|x| x.into_iter().map(Into::into).collect()),
870 range_check0_selector: pe
871 .range_check0_selector
872 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
873 range_check1_selector: pe
874 .range_check1_selector
875 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
876 foreign_field_add_selector: pe
877 .foreign_field_add_selector
878 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
879 foreign_field_mul_selector: pe
880 .foreign_field_mul_selector
881 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
882 xor_selector: pe
883 .xor_selector
884 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
885 rot_selector: pe
886 .rot_selector
887 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
888 lookup_aggregation: pe
889 .lookup_aggregation
890 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
891 lookup_table: pe
892 .lookup_table
893 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
894 lookup_sorted: pe
895 .lookup_sorted
896 .iter()
897 .map(|x| {
898 x.as_ref().map(|x| {
899 x.map_ref(&|x| x.clone().into_iter().map(Into::into).collect())
900 })
901 })
902 .collect::<Vec<_>>(),
903 runtime_lookup_table: pe
904 .runtime_lookup_table
905 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
906 runtime_lookup_table_selector: pe
907 .runtime_lookup_table_selector
908 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
909 xor_lookup_selector: pe
910 .xor_lookup_selector
911 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
912 lookup_gate_lookup_selector: pe
913 .lookup_gate_lookup_selector
914 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
915 range_check_lookup_selector: pe
916 .range_check_lookup_selector
917 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
918 foreign_field_mul_lookup_selector: pe
919 .foreign_field_mul_lookup_selector
920 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
921 };
922
923 (first, second)
924 }
925 }
926
927 impl<F, CamlF>
928 From<(
929 Option<PointEvaluations<Vec<CamlF>>>,
930 CamlProofEvaluations<CamlF>,
931 )> for ProofEvaluations<PointEvaluations<Vec<F>>>
932 where
933 F: Clone,
934 CamlF: Clone,
935 F: From<CamlF>,
936 {
937 fn from(
938 (public, cpe): (
939 Option<PointEvaluations<Vec<CamlF>>>,
940 CamlProofEvaluations<CamlF>,
941 ),
942 ) -> Self {
943 let w = [
944 cpe.w.0.map(&|x| x.into_iter().map(Into::into).collect()),
945 cpe.w.1.map(&|x| x.into_iter().map(Into::into).collect()),
946 cpe.w.2.map(&|x| x.into_iter().map(Into::into).collect()),
947 cpe.w.3.map(&|x| x.into_iter().map(Into::into).collect()),
948 cpe.w.4.map(&|x| x.into_iter().map(Into::into).collect()),
949 cpe.w.5.map(&|x| x.into_iter().map(Into::into).collect()),
950 cpe.w.6.map(&|x| x.into_iter().map(Into::into).collect()),
951 cpe.w.7.map(&|x| x.into_iter().map(Into::into).collect()),
952 cpe.w.8.map(&|x| x.into_iter().map(Into::into).collect()),
953 cpe.w.9.map(&|x| x.into_iter().map(Into::into).collect()),
954 cpe.w.10.map(&|x| x.into_iter().map(Into::into).collect()),
955 cpe.w.11.map(&|x| x.into_iter().map(Into::into).collect()),
956 cpe.w.12.map(&|x| x.into_iter().map(Into::into).collect()),
957 cpe.w.13.map(&|x| x.into_iter().map(Into::into).collect()),
958 cpe.w.14.map(&|x| x.into_iter().map(Into::into).collect()),
959 ];
960 let coefficients = [
961 cpe.coefficients
962 .0
963 .map(&|x| x.into_iter().map(Into::into).collect()),
964 cpe.coefficients
965 .1
966 .map(&|x| x.into_iter().map(Into::into).collect()),
967 cpe.coefficients
968 .2
969 .map(&|x| x.into_iter().map(Into::into).collect()),
970 cpe.coefficients
971 .3
972 .map(&|x| x.into_iter().map(Into::into).collect()),
973 cpe.coefficients
974 .4
975 .map(&|x| x.into_iter().map(Into::into).collect()),
976 cpe.coefficients
977 .5
978 .map(&|x| x.into_iter().map(Into::into).collect()),
979 cpe.coefficients
980 .6
981 .map(&|x| x.into_iter().map(Into::into).collect()),
982 cpe.coefficients
983 .7
984 .map(&|x| x.into_iter().map(Into::into).collect()),
985 cpe.coefficients
986 .8
987 .map(&|x| x.into_iter().map(Into::into).collect()),
988 cpe.coefficients
989 .9
990 .map(&|x| x.into_iter().map(Into::into).collect()),
991 cpe.coefficients
992 .10
993 .map(&|x| x.into_iter().map(Into::into).collect()),
994 cpe.coefficients
995 .11
996 .map(&|x| x.into_iter().map(Into::into).collect()),
997 cpe.coefficients
998 .12
999 .map(&|x| x.into_iter().map(Into::into).collect()),
1000 cpe.coefficients
1001 .13
1002 .map(&|x| x.into_iter().map(Into::into).collect()),
1003 cpe.coefficients
1004 .14
1005 .map(&|x| x.into_iter().map(Into::into).collect()),
1006 ];
1007 let s = [
1008 cpe.s.0.map(&|x| x.into_iter().map(Into::into).collect()),
1009 cpe.s.1.map(&|x| x.into_iter().map(Into::into).collect()),
1010 cpe.s.2.map(&|x| x.into_iter().map(Into::into).collect()),
1011 cpe.s.3.map(&|x| x.into_iter().map(Into::into).collect()),
1012 cpe.s.4.map(&|x| x.into_iter().map(Into::into).collect()),
1013 cpe.s.5.map(&|x| x.into_iter().map(Into::into).collect()),
1014 ];
1015
1016 Self {
1017 public: public.map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
1018 w,
1019 coefficients,
1020 z: cpe.z.map(&|x| x.into_iter().map(Into::into).collect()),
1021 s,
1022 generic_selector: cpe
1023 .generic_selector
1024 .map(&|x| x.into_iter().map(Into::into).collect()),
1025 poseidon_selector: cpe
1026 .poseidon_selector
1027 .map(&|x| x.into_iter().map(Into::into).collect()),
1028 complete_add_selector: cpe
1029 .complete_add_selector
1030 .map(&|x| x.into_iter().map(Into::into).collect()),
1031 mul_selector: cpe
1032 .mul_selector
1033 .map(&|x| x.into_iter().map(Into::into).collect()),
1034 emul_selector: cpe
1035 .emul_selector
1036 .map(&|x| x.into_iter().map(Into::into).collect()),
1037 endomul_scalar_selector: cpe
1038 .endomul_scalar_selector
1039 .map(&|x| x.into_iter().map(Into::into).collect()),
1040 range_check0_selector: cpe
1041 .range_check0_selector
1042 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
1043 range_check1_selector: cpe
1044 .range_check1_selector
1045 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
1046 foreign_field_add_selector: cpe
1047 .foreign_field_add_selector
1048 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
1049 foreign_field_mul_selector: cpe
1050 .foreign_field_mul_selector
1051 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
1052 xor_selector: cpe
1053 .xor_selector
1054 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
1055 rot_selector: cpe
1056 .rot_selector
1057 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
1058 lookup_aggregation: cpe
1059 .lookup_aggregation
1060 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
1061 lookup_table: cpe
1062 .lookup_table
1063 .map(|x| x.map(&|x| x.into_iter().map(Into::into).collect())),
1064 lookup_sorted: {
1065 assert_eq!(cpe.lookup_sorted.len(), 5); array::from_fn(|i| {
1067 cpe.lookup_sorted[i]
1068 .as_ref()
1069 .map(|x| x.clone().map(&|x| x.into_iter().map(Into::into).collect()))
1070 })
1071 },
1072 runtime_lookup_table: cpe
1073 .runtime_lookup_table
1074 .map(|x| x.map(&|x| x.iter().map(|x| x.clone().into()).collect())),
1075 runtime_lookup_table_selector: cpe
1076 .runtime_lookup_table_selector
1077 .map(|x| x.map(&|x| x.iter().map(|x| x.clone().into()).collect())),
1078 xor_lookup_selector: cpe
1079 .xor_lookup_selector
1080 .map(|x| x.map(&|x| x.iter().map(|x| x.clone().into()).collect())),
1081 lookup_gate_lookup_selector: cpe
1082 .lookup_gate_lookup_selector
1083 .map(|x| x.map(&|x| x.iter().map(|x| x.clone().into()).collect())),
1084 range_check_lookup_selector: cpe
1085 .range_check_lookup_selector
1086 .map(|x| x.map(&|x| x.iter().map(|x| x.clone().into()).collect())),
1087 foreign_field_mul_lookup_selector: cpe
1088 .foreign_field_mul_lookup_selector
1089 .map(|x| x.map(&|x| x.iter().map(|x| x.clone().into()).collect())),
1090 }
1091 }
1092 }
1093}
1094
1095#[cfg(all(test, feature = "std"))]
1096mod tests {
1097 use super::*;
1098 use ark_ec::{CurveGroup, VariableBaseMSM};
1099 use ark_ff::Field;
1100 use mina_curves::pasta::{Fp, Fq, Vesta, VestaParameters};
1101 use poly_commitment::PolyComm;
1102 use std::str::FromStr;
1103
1104 type VestaGroup = ark_ec::short_weierstrass::Projective<VestaParameters>;
1105
1106 #[test]
1115 fn test_recursion_challenge_evals_regression() {
1116 let chals: Vec<Fp> = (2..=16).map(|i| Fp::from(i as u64)).collect();
1118
1119 let comm = PolyComm::<Vesta> {
1120 chunks: vec![Vesta::generator()],
1121 };
1122
1123 let rec_chal = RecursionChallenge::<Vesta>::new(chals.clone(), comm);
1124
1125 let zeta = Fp::from(17u64);
1126 let zeta_omega = Fp::from(19u64);
1127 let evaluation_points = [zeta, zeta_omega];
1128
1129 let max_poly_size = 1 << 15;
1130 let powers_of_eval_points_for_chunks = [
1131 zeta.pow([max_poly_size as u64]),
1132 zeta_omega.pow([max_poly_size as u64]),
1133 ];
1134
1135 let evals = rec_chal.evals(
1136 max_poly_size,
1137 &evaluation_points,
1138 &powers_of_eval_points_for_chunks,
1139 );
1140
1141 let expected_eval_zeta = Fp::from_str(
1143 "21115683812642620361045381629886583866877919362491419134086003378733605776328",
1144 )
1145 .unwrap();
1146 let expected_eval_zeta_omega = Fp::from_str(
1147 "2298325069360593860729719174291433577456794311517767070156020442825391962511",
1148 )
1149 .unwrap();
1150
1151 assert_eq!(evals[0].len(), 1, "Should have single chunk");
1152 assert_eq!(evals[1].len(), 1, "Should have single chunk");
1153 assert_eq!(evals[0][0], expected_eval_zeta, "b(zeta) mismatch");
1154 assert_eq!(
1155 evals[1][0], expected_eval_zeta_omega,
1156 "b(zeta*omega) mismatch"
1157 );
1158
1159 assert_eq!(evals[0][0], b_poly(&chals, zeta));
1161 assert_eq!(evals[1][0], b_poly(&chals, zeta_omega));
1162 }
1163
1164 #[test]
1170 fn test_recursion_challenge_commitment_regression() {
1171 let chals: Vec<Fp> = vec![
1173 Fp::from(2u64),
1174 Fp::from(3u64),
1175 Fp::from(5u64),
1176 Fp::from(7u64),
1177 ];
1178
1179 let coeffs = b_poly_coefficients(&chals);
1181 assert_eq!(coeffs.len(), 16);
1182
1183 let g = Vesta::generator();
1185 let basis: Vec<Vesta> = (1..=16)
1186 .map(|i| (g * Fp::from(i as u64)).into_affine())
1187 .collect();
1188
1189 let accumulated_comm = VestaGroup::msm(&basis, &coeffs).unwrap().into_affine();
1191
1192 let expected_x = Fq::from_str(
1194 "3756288960823668761746459900985719106126835112055076922409498125279524024429",
1195 )
1196 .unwrap();
1197 let expected_y = Fq::from_str(
1198 "7540929664328976141648477194277016811781677917189411360504995258251130097840",
1199 )
1200 .unwrap();
1201
1202 assert_eq!(accumulated_comm.x, expected_x, "commitment x mismatch");
1203 assert_eq!(accumulated_comm.y, expected_y, "commitment y mismatch");
1204 }
1205}