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