1use super::*;
2use crypto_primitives::{ConstIntSemiring, FromPrimitiveWithConfig, FromWithConfig};
3use num_traits::Zero;
4use std::{borrow::Cow, collections::HashMap, fmt::Debug};
5use zinc_piop::{
6 combined_poly_resolver::CombinedPolyResolver,
7 ideal_check::IdealCheckProtocol,
8 lookup::booleanity::{self, BooleanityChecker, BooleanityProof},
9 multipoint_eval::{MultipointEval, Proof as MultipointEvalProof},
10 projections::{
11 ColumnMajorTrace, ProjectedTrace, RowMajorTrace, evaluate_trace_to_column_mles,
12 project_scalars, project_scalars_to_field, project_trace_coeffs_column_major,
13 project_trace_coeffs_row_major,
14 },
15 sumcheck::multi_degree::MultiDegreeSumcheck,
16};
17use zinc_poly::univariate::dynamic::over_field::DynamicPolynomialF;
18use zinc_transcript::traits::{ConstTranscribable, Transcript};
19use zinc_uair::{
20 Uair, UairSignature, UairTrace, constraint_counter::count_constraints,
21 degree_counter::count_max_degree,
22};
23use zinc_utils::{
24 add, cfg_join, from_ref::FromRef, inner_transparent_field::InnerTransparentField,
25 mul_by_scalar::MulByScalar, projectable_to_field::ProjectableToField,
26};
27use zip_plus::{
28 pcs::structs::{ZipPlus, ZipPlusHint, ZipPlusParams, ZipTypes},
29 pcs_transcript::PcsProverTranscript,
30};
31
32#[derive(Clone, Debug)]
40pub struct ProverFolded<
41 'a,
42 Zt: ZincTypes<D, FD>,
43 U: Uair,
44 F: PrimeField,
45 const D: usize,
46 const FD: usize,
47> {
48 uair_signature: UairSignature,
49 original_trace: &'a UairTrace<'static, Zt::Int, Zt::Int, D, D>,
50 folded_witness_trace: UairTrace<'a, Zt::Int, Zt::Int, FD, D>,
51
52 _phantom: PhantomData<(&'a u8, U, F)>,
53}
54
55#[derive(Clone, Debug)]
60pub struct ProverCommitted<
61 'a,
62 Zt: ZincTypes<D, FD>,
63 U: Uair,
64 F: PrimeField,
65 const D: usize,
66 const FD: usize,
67> {
68 num_vars: usize,
69 uair_signature: UairSignature,
70 original_trace: &'a UairTrace<'static, Zt::Int, Zt::Int, D, D>,
71 folded_witness_trace: UairTrace<'a, Zt::Int, Zt::Int, FD, D>,
72 pcs_transcript: PcsProverTranscript,
73
74 pp_bin: &'a ZipPlusParams<Zt::BinaryZt, Zt::BinaryLc>,
76 pp_arb: &'a ZipPlusParams<Zt::ArbitraryZt, Zt::ArbitraryLc>,
77 pp_int: &'a ZipPlusParams<Zt::IntZt, Zt::IntLc>,
78 hint_bin: Option<ZipPlusHint<<Zt::BinaryZt as ZipTypes>::Cw>>,
79 hint_arb: Option<ZipPlusHint<<Zt::ArbitraryZt as ZipTypes>::Cw>>,
80 hint_int: Option<ZipPlusHint<<Zt::IntZt as ZipTypes>::Cw>>,
81 commitment_bin: ZipPlusCommitment,
82 commitment_arb: ZipPlusCommitment,
83 commitment_int: ZipPlusCommitment,
84
85 _phantom: PhantomData<(U, F)>,
86}
87
88#[derive(Clone, Debug)]
91pub struct ProverProjectedCombined<
92 'a,
93 Zt: ZincTypes<D, FD>,
94 U: Uair,
95 F: PrimeField,
96 const D: usize,
97 const FD: usize,
98> {
99 base: ProverCommitted<'a, Zt, U, F, D, FD>,
100 field_cfg: F::Config,
101 projected_trace: RowMajorTrace<F>,
102 projected_scalars_fx: HashMap<U::Scalar, DynamicPolynomialF<F>>,
103}
104
105#[derive(Clone, Debug)]
108pub struct ProverProjectedMleFirst<
109 'a,
110 Zt: ZincTypes<D, FD>,
111 U: Uair,
112 F: PrimeField,
113 const D: usize,
114 const FD: usize,
115> {
116 base: ProverCommitted<'a, Zt, U, F, D, FD>,
117 field_cfg: F::Config,
118 projected_trace: ColumnMajorTrace<F>,
119 projected_scalars_fx: HashMap<U::Scalar, DynamicPolynomialF<F>>,
120}
121
122#[derive(Clone, Debug)]
124pub struct ProverIdealChecked<
125 'a,
126 Zt: ZincTypes<D, FD>,
127 U: Uair,
128 F: PrimeField,
129 const D: usize,
130 const FD: usize,
131> {
132 base: ProverCommitted<'a, Zt, U, F, D, FD>,
133 field_cfg: F::Config,
134 projected_trace: ProjectedTrace<F>,
135 projected_scalars_fx: HashMap<U::Scalar, DynamicPolynomialF<F>>,
136
137 ic_proof: IdealCheckProof<F>,
139 ic_eval_point: Vec<F>,
140}
141
142#[derive(Clone, Debug)]
144pub struct ProverEvalProjected<
145 'a,
146 Zt: ZincTypes<D, FD>,
147 U: Uair,
148 F: PrimeField,
149 const D: usize,
150 const FD: usize,
151> {
152 base: ProverCommitted<'a, Zt, U, F, D, FD>,
153 field_cfg: F::Config,
154 projected_trace: ProjectedTrace<F>,
155 ic_proof: IdealCheckProof<F>,
156 ic_eval_point: Vec<F>,
157
158 projected_trace_f: Vec<DenseMultilinearExtension<F::Inner>>,
160 projected_scalars_f: HashMap<U::Scalar, F>,
161}
162
163#[allow(clippy::type_complexity)]
165#[derive(Clone, Debug)]
166pub struct ProverSumchecked<
167 'a,
168 Zt: ZincTypes<D, FD>,
169 U: Uair,
170 F: PrimeField,
171 const D: usize,
172 const FD: usize,
173> {
174 base: ProverCommitted<'a, Zt, U, F, D, FD>,
175 field_cfg: F::Config,
176 projected_trace: ProjectedTrace<F>,
177 ic_proof: IdealCheckProof<F>,
178 projected_trace_f: Vec<DenseMultilinearExtension<F::Inner>>,
179
180 cpr_proof: CombinedPolyResolverProof<F>,
182 cpr_eval_point: Vec<F>,
183 combined_sumcheck: MultiDegreeSumcheckProof<F>,
184 lookup_proof: Option<BatchedLookupProof<F>>,
185 booleanity_proof: Option<BooleanityProof<F>>,
186}
187
188#[derive(Clone, Debug)]
190pub struct ProverMultipointEvaled<
191 'a,
192 Zt: ZincTypes<D, FD>,
193 U: Uair,
194 F: PrimeField,
195 const D: usize,
196 const FD: usize,
197> {
198 base: ProverCommitted<'a, Zt, U, F, D, FD>,
199 field_cfg: F::Config,
200 projected_trace: ProjectedTrace<F>,
201 ic_proof: IdealCheckProof<F>,
202 cpr_proof: CombinedPolyResolverProof<F>,
203 combined_sumcheck: MultiDegreeSumcheckProof<F>,
204 lookup_proof: Option<BatchedLookupProof<F>>,
205 booleanity_proof: Option<BooleanityProof<F>>,
206
207 mp_proof: MultipointEvalProof<F>,
209 r_0: Vec<F>,
210}
211
212#[derive(Clone, Debug)]
214pub struct ProverLifted<
215 'a,
216 Zt: ZincTypes<D, FD>,
217 U: Uair,
218 F: PrimeField,
219 const D: usize,
220 const FD: usize,
221> {
222 base: ProverCommitted<'a, Zt, U, F, D, FD>,
223 field_cfg: F::Config,
224 ic_proof: IdealCheckProof<F>,
225 cpr_proof: CombinedPolyResolverProof<F>,
226 combined_sumcheck: MultiDegreeSumcheckProof<F>,
227 lookup_proof: Option<BatchedLookupProof<F>>,
228 booleanity_proof: Option<BooleanityProof<F>>,
229 mp_proof: MultipointEvalProof<F>,
230 r_0: Vec<F>,
231
232 lifted_evals: Vec<DynamicPolynomialF<F>>,
234}
235
236#[derive(Clone, Debug)]
241pub struct ProverPcsOpened<
242 'a,
243 Zt: ZincTypes<D, FD>,
244 U: Uair,
245 F: PrimeField,
246 const D: usize,
247 const FD: usize,
248> {
249 base: ProverCommitted<'a, Zt, U, F, D, FD>,
250 ic_proof: IdealCheckProof<F>,
251 cpr_proof: CombinedPolyResolverProof<F>,
252 combined_sumcheck: MultiDegreeSumcheckProof<F>,
253 lookup_proof: Option<BatchedLookupProof<F>>,
254 booleanity_proof: Option<BooleanityProof<F>>,
255 mp_proof: MultipointEvalProof<F>,
256 lifted_evals: Vec<DynamicPolynomialF<F>>,
257}
258
259macro_rules! impl_with_type_bounds {
266 ($type_name:ident { $($code:tt)* }) => {
267 impl<'a, Zt, U, F, const D: usize, const FD: usize> $type_name<'a, Zt, U, F, D, FD>
268 where
269 Zt: ZincTypes<D, FD>,
270 Zt::Int: ProjectableToField<F>,
271 <Zt::ArbitraryZt as ZipTypes>::Eval: ProjectableToField<F>,
272 U: Uair + 'static,
273 F: InnerTransparentField
274 + FromPrimitiveWithConfig
275 + for<'b> FromWithConfig<&'b Zt::Int>
276 + for<'b> FromWithConfig<&'b Zt::CombR>
277 + for<'b> FromWithConfig<&'b Zt::Chal>
278 + for<'b> MulByScalar<&'b F>
279 + FromRef<F>
280 + Send
281 + Sync
282 + 'static,
283 F::Inner:
284 ConstIntSemiring + ConstTranscribable + FromRef<Zt::Fmod> + Send + Sync + Zero + Default,
285 F::Modulus: ConstTranscribable + FromRef<Zt::Fmod>,
286 {
287 $($code)*
288 }
289 };
290}
291
292impl<Zt, U, F, const D: usize, const FD: usize> ZincPlusPiop<Zt, U, F, D, FD>
293where
294 Zt: ZincTypes<D, FD>,
295 U: Uair,
296 F: PrimeField,
297 F::Inner: ConstTranscribable,
298{
299 #[allow(clippy::type_complexity)]
301 pub fn step0_fold<'a>(
302 trace: &'a UairTrace<'static, Zt::Int, Zt::Int, D, D>,
303 ) -> Result<ProverFolded<'a, Zt, U, F, D, FD>, ProtocolError<F, U::Ideal>> {
304 let uair_signature = U::signature();
305 let witness_trace = trace.witness(&uair_signature);
306
307 let folded_bin_witness_trace = cfg_iter!(witness_trace.binary_poly)
308 .map(Zt::BinaryFold::fold_trace_mle)
309 .collect();
310
311 let folded_witness_trace = UairTrace {
312 binary_poly: Cow::Owned(folded_bin_witness_trace),
313 arbitrary_poly: witness_trace.arbitrary_poly.clone(),
314 int: witness_trace.int.clone(),
315 };
316
317 Ok(ProverFolded {
318 uair_signature,
319 original_trace: trace,
320 folded_witness_trace,
321 _phantom: PhantomData,
322 })
323 }
324}
325
326impl_with_type_bounds!(ProverFolded
327{
328 #[allow(clippy::type_complexity)]
332 pub fn step1_commit(
333 self,
334 (pp_bin, pp_arb, pp_int): &'a (
335 ZipPlusParams<Zt::BinaryZt, Zt::BinaryLc>,
336 ZipPlusParams<Zt::ArbitraryZt, Zt::ArbitraryLc>,
337 ZipPlusParams<Zt::IntZt, Zt::IntLc>,
338 ),
339 num_vars: usize,
340 ) -> Result<ProverCommitted<'a, Zt, U, F, D, FD>, ProtocolError<F, U::Ideal>> {
341 let sig = &self.uair_signature;
342 let public_trace = self.original_trace.public(sig);
343
344 let (res_bin, (res_arb, res_int)) = cfg_join!(
345 commit_optionally(pp_bin, &self.folded_witness_trace.binary_poly),
346 commit_optionally(pp_arb, &self.folded_witness_trace.arbitrary_poly),
347 commit_optionally(pp_int, &self.folded_witness_trace.int),
348 );
349 let (hint_bin, commitment_bin) = res_bin?;
350 let (hint_arb, commitment_arb) = res_arb?;
351 let (hint_int, commitment_int) = res_int?;
352
353 let mut pcs_transcript = PcsProverTranscript::new_from_commitments(
354 [&commitment_bin, &commitment_arb, &commitment_int].into_iter(),
355 );
356
357 absorb_public_columns(&mut pcs_transcript.fs_transcript, &public_trace.binary_poly);
358 absorb_public_columns(
359 &mut pcs_transcript.fs_transcript,
360 &public_trace.arbitrary_poly,
361 );
362 absorb_public_columns(&mut pcs_transcript.fs_transcript, &public_trace.int);
363
364 Ok(ProverCommitted {
365 num_vars,
366 uair_signature: self.uair_signature,
367 original_trace: self.original_trace,
368 folded_witness_trace: self.folded_witness_trace,
369 pcs_transcript,
370 pp_bin,
371 pp_arb,
372 pp_int,
373 hint_bin,
374 hint_arb,
375 hint_int,
376 commitment_bin,
377 commitment_arb,
378 commitment_int,
379 _phantom: PhantomData,
380 })
381 }
382});
383
384impl_with_type_bounds!(ProverCommitted
385{
386 #[allow(clippy::type_complexity)]
387 fn project_common<S: Fn(&U::Scalar, &F::Config) -> DynamicPolynomialF<F>>(
388 &mut self,
389 project_scalar: S,
390 ) -> Result<(F::Config, HashMap<U::Scalar, DynamicPolynomialF<F>>), ProtocolError<F, U::Ideal>>
391 {
392 let field_cfg = self
393 .pcs_transcript
394 .fs_transcript
395 .get_random_field_cfg::<F, Zt::Fmod, Zt::PrimeTest>();
396
397 let projected_scalars_fx = project_scalars::<F, U>(|s| project_scalar(s, &field_cfg));
398 Ok((field_cfg, projected_scalars_fx))
399 }
400
401 pub fn step2_combined<S: Fn(&U::Scalar, &F::Config) -> DynamicPolynomialF<F>>(
406 mut self,
407 project_scalar: S,
408 ) -> Result<ProverProjectedCombined<'a, Zt, U, F, D, FD>, ProtocolError<F, U::Ideal>> {
409 let (field_cfg, projected_scalars_fx) = self.project_common(project_scalar)?;
410
411 let projected_trace = project_trace_coeffs_row_major(self.original_trace, &field_cfg);
412 Ok(ProverProjectedCombined {
413 base: self,
414 field_cfg,
415 projected_trace,
416 projected_scalars_fx,
417 })
418 }
419
420 pub fn step2_mle_first<S: Fn(&U::Scalar, &F::Config) -> DynamicPolynomialF<F>>(
424 mut self,
425 project_scalar: S,
426 ) -> Result<ProverProjectedMleFirst<'a, Zt, U, F, D, FD>, ProtocolError<F, U::Ideal>> {
427 let (field_cfg, projected_scalars_fx) = self.project_common(project_scalar)?;
428
429 let projected_trace = project_trace_coeffs_column_major(self.original_trace, &field_cfg);
430 Ok(ProverProjectedMleFirst {
431 base: self,
432 field_cfg,
433 projected_trace,
434 projected_scalars_fx,
435 })
436 }
437});
438
439impl_with_type_bounds!(ProverProjectedCombined
440{
441 pub fn step3_ideal_check(
444 mut self,
445 ) -> Result<ProverIdealChecked<'a, Zt, U, F, D, FD>, ProtocolError<F, U::Ideal>> {
446 let num_constraints = count_constraints::<U>();
447
448 let (ic_proof, ic_prover_state) = U::prove_combined(
449 &mut self.base.pcs_transcript.fs_transcript,
450 &self.projected_trace,
451 &self.projected_scalars_fx,
452 num_constraints,
453 self.base.num_vars,
454 &self.field_cfg,
455 )?;
456
457 Ok(ProverIdealChecked {
458 base: self.base,
459 field_cfg: self.field_cfg,
460 projected_trace: ProjectedTrace::RowMajor(self.projected_trace),
461 projected_scalars_fx: self.projected_scalars_fx,
462 ic_proof,
463 ic_eval_point: ic_prover_state.evaluation_point,
464 })
465 }
466});
467
468impl_with_type_bounds!(ProverProjectedMleFirst
469{
470 pub fn step3_ideal_check(
477 mut self,
478 ) -> Result<ProverIdealChecked<'a, Zt, U, F, D, FD>, ProtocolError<F, U::Ideal>> {
479 let num_constraints = count_constraints::<U>();
480
481 let (ic_proof, ic_prover_state) = U::prove_mle_first(
482 &mut self.base.pcs_transcript.fs_transcript,
483 &self.projected_trace,
484 &self.projected_scalars_fx,
485 num_constraints,
486 self.base.num_vars,
487 &self.field_cfg,
488 )?;
489
490 Ok(ProverIdealChecked {
491 base: self.base,
492 field_cfg: self.field_cfg,
493 projected_trace: ProjectedTrace::ColumnMajor(self.projected_trace),
494 projected_scalars_fx: self.projected_scalars_fx,
495 ic_proof,
496 ic_eval_point: ic_prover_state.evaluation_point,
497 })
498 }
499});
500
501impl_with_type_bounds!(ProverIdealChecked
502{
503 pub fn step4_eval_projection(
506 mut self,
507 ) -> Result<ProverEvalProjected<'a, Zt, U, F, D, FD>, ProtocolError<F, U::Ideal>> {
508 let projecting_element: Zt::Chal = self.base.pcs_transcript.fs_transcript.get_challenge();
509 let projecting_element_f: F = F::from_with_cfg(&projecting_element, &self.field_cfg);
510
511 let projected_trace_f =
512 evaluate_trace_to_column_mles(&self.projected_trace, &projecting_element_f);
513
514 let projected_scalars_f =
515 project_scalars_to_field(self.projected_scalars_fx, &projecting_element_f)
516 .map_err(|(_s, _f, e)| ProtocolError::ScalarProjection(e))?;
517
518 Ok(ProverEvalProjected {
519 base: self.base,
520 field_cfg: self.field_cfg,
521 projected_trace: self.projected_trace,
522 ic_proof: self.ic_proof,
523 ic_eval_point: self.ic_eval_point,
524 projected_trace_f,
525 projected_scalars_f,
526 })
527 }
528});
529
530impl_with_type_bounds!(ProverEvalProjected
531{
532 pub fn step5_sumcheck(
539 mut self,
540 ) -> Result<ProverSumchecked<'a, Zt, U, F, D, FD>, ProtocolError<F, U::Ideal>> {
541 let num_constraints = count_constraints::<U>();
542 let max_degree = count_max_degree::<U>();
543
544 let (cpr_group, cpr_ancillary) = CombinedPolyResolver::prepare_sumcheck_group::<U>(
545 &mut self.base.pcs_transcript.fs_transcript,
546 self.projected_trace_f.clone(),
547 &self.ic_eval_point,
548 &self.projected_scalars_f,
549 num_constraints,
550 self.base.num_vars,
551 max_degree,
552 &self.field_cfg,
553 )?;
554
555 let mut groups = vec![cpr_group];
556
557 let trace_wit_bin_poly = {
559 let sig = &self.base.uair_signature;
560 let num_pub_bin = sig.public_cols().num_binary_poly_cols();
561 let num_total_bin = sig.total_cols().num_binary_poly_cols();
562 &self.base.original_trace.binary_poly[num_pub_bin..num_total_bin]
563 };
564
565 let bool_ancillary = if !trace_wit_bin_poly.is_empty() {
566 let (bool_group, anc) = BooleanityChecker::prepare_sumcheck_group::<D>(
567 &mut self.base.pcs_transcript.fs_transcript,
568 trace_wit_bin_poly,
569 self.base.num_vars,
570 &self.field_cfg,
571 )
572 .map_err(ProtocolError::Booleanity)?;
573 groups.push(bool_group);
574 Some(anc)
575 } else {
576 None
577 };
578
579 let (combined_sumcheck, md_states) = MultiDegreeSumcheck::prove_as_subprotocol(
585 &mut self.base.pcs_transcript.fs_transcript,
586 groups,
587 self.base.num_vars,
588 &self.field_cfg,
589 );
590
591 let mut md_iter = md_states.into_iter();
592
593 let (cpr_proof, cpr_prover_state) = CombinedPolyResolver::finalize_prover(
594 &mut self.base.pcs_transcript.fs_transcript,
595 md_iter.next().expect("CPR group always present"),
596 cpr_ancillary,
597 &self.field_cfg,
598 )?;
599
600 let booleanity_proof = if let Some(anc) = bool_ancillary {
601 let state = md_iter.next().expect("booleanity group present");
602 Some(
603 BooleanityChecker::finalize_prover(
604 &mut self.base.pcs_transcript.fs_transcript,
605 state,
606 anc,
607 &self.field_cfg,
608 )
609 .map_err(ProtocolError::Booleanity)?,
610 )
611 } else {
612 None
613 };
614
615 let lookup_proof = None;
617
618 Ok(ProverSumchecked {
619 base: self.base,
620 field_cfg: self.field_cfg,
621 projected_trace: self.projected_trace,
622 ic_proof: self.ic_proof,
623 projected_trace_f: self.projected_trace_f,
624 cpr_proof,
625 cpr_eval_point: cpr_prover_state.evaluation_point,
626 combined_sumcheck,
627 lookup_proof,
628 booleanity_proof,
629 })
630 }
631});
632
633impl_with_type_bounds!(ProverSumchecked
634{
635 pub fn step6_multipoint_eval(
644 mut self,
645 ) -> Result<ProverMultipointEvaled<'a, Zt, U, F, D, FD>, ProtocolError<F, U::Ideal>> {
646 let (extended_trace_mles, extended_up_evals) = if let Some(bp) = &self.booleanity_proof {
650 let trace_wit_bin_poly = {
651 let sig = &self.base.uair_signature;
652 let num_pub_bin = sig.public_cols().num_binary_poly_cols();
653 let num_total_bin = sig.total_cols().num_binary_poly_cols();
654 &self.base.original_trace.binary_poly[num_pub_bin..num_total_bin]
655 };
656
657 let mut trace_mles = self.projected_trace_f.clone();
658 trace_mles.extend(booleanity::build_witness_bit_slice_mles::<F, D>(
659 trace_wit_bin_poly,
660 &self.field_cfg,
661 ));
662
663 let mut up_evals = self.cpr_proof.up_evals.clone();
664 up_evals.extend_from_slice(&bp.bit_slice_evals);
665 (trace_mles, up_evals)
666 } else {
667 (self.projected_trace_f.clone(), self.cpr_proof.up_evals.clone())
668 };
669
670 let (mp_proof, mp_prover_state) = MultipointEval::prove_as_subprotocol(
671 &mut self.base.pcs_transcript.fs_transcript,
672 &extended_trace_mles,
673 &self.cpr_eval_point,
674 &extended_up_evals,
675 &self.cpr_proof.down_evals,
676 self.base.uair_signature.shifts(),
677 &self.field_cfg,
678 )?;
679
680 Ok(ProverMultipointEvaled {
681 base: self.base,
682 field_cfg: self.field_cfg,
683 projected_trace: self.projected_trace,
684 ic_proof: self.ic_proof,
685 cpr_proof: self.cpr_proof,
686 combined_sumcheck: self.combined_sumcheck,
687 lookup_proof: self.lookup_proof,
688 booleanity_proof: self.booleanity_proof,
689 mp_proof,
690 r_0: mp_prover_state.eval_point,
691 })
692 }
693});
694
695impl_with_type_bounds!(ProverMultipointEvaled
696{
697 pub fn step7_lift_and_project(
700 mut self,
701 ) -> Result<ProverLifted<'a, Zt, U, F, D, FD>, ProtocolError<F, U::Ideal>> {
702 let lifted_evals = compute_lifted_evals(
707 &self.r_0,
708 &self.base.original_trace.binary_poly,
709 &self.projected_trace,
710 &self.field_cfg,
711 );
712
713 let mut transcription_buf: Vec<u8> = vec![0; F::Inner::NUM_BYTES];
714 for bar_u in &lifted_evals {
715 self.base
716 .pcs_transcript
717 .fs_transcript
718 .absorb_random_field_slice(&bar_u.coeffs, &mut transcription_buf);
719 }
720
721 Ok(ProverLifted {
722 base: self.base,
723 field_cfg: self.field_cfg,
724 ic_proof: self.ic_proof,
725 cpr_proof: self.cpr_proof,
726 combined_sumcheck: self.combined_sumcheck,
727 lookup_proof: self.lookup_proof,
728 booleanity_proof: self.booleanity_proof,
729 mp_proof: self.mp_proof,
730 r_0: self.r_0,
731 lifted_evals,
732 })
733 }
734});
735
736impl_with_type_bounds!(ProverLifted
737{
738 pub fn step8_pcs_open<const CHECK_FOR_OVERFLOW: bool>(
740 mut self,
741 ) -> Result<ProverPcsOpened<'a, Zt, U, F, D, FD>, ProtocolError<F, U::Ideal>> {
742 let witness_trace = &self.base.folded_witness_trace;
743
744 let mut r_0_ext = self.r_0.clone();
747 let num_folding_challenges = Zt::BinaryFold::FOLDING_FACTOR.ilog2();
748 (0..num_folding_challenges).for_each(|_| {
749 let g_chal: Zt::Chal = self.base.pcs_transcript.fs_transcript.get_challenge();
750 let gamma = F::from_with_cfg(&g_chal, &self.field_cfg);
751 r_0_ext.push(gamma);
752 });
753
754 if let Some(hint_bin) = &self.base.hint_bin {
755 let _ = ZipPlus::<Zt::BinaryZt, Zt::BinaryLc>::prove_f::<_, CHECK_FOR_OVERFLOW>(
756 &mut self.base.pcs_transcript,
757 self.base.pp_bin,
758 &witness_trace.binary_poly,
759 &r_0_ext,
760 hint_bin,
761 &self.field_cfg,
762 )?;
763 }
764 if let Some(hint_arb) = &self.base.hint_arb {
765 let _ = ZipPlus::<Zt::ArbitraryZt, Zt::ArbitraryLc>::prove_f::<_, CHECK_FOR_OVERFLOW>(
766 &mut self.base.pcs_transcript,
767 self.base.pp_arb,
768 &witness_trace.arbitrary_poly,
769 &self.r_0,
770 hint_arb,
771 &self.field_cfg,
772 )?;
773 }
774 if let Some(hint_int) = &self.base.hint_int {
775 let _ = ZipPlus::<Zt::IntZt, Zt::IntLc>::prove_f::<_, CHECK_FOR_OVERFLOW>(
776 &mut self.base.pcs_transcript,
777 self.base.pp_int,
778 &witness_trace.int,
779 &self.r_0,
780 hint_int,
781 &self.field_cfg,
782 )?;
783 }
784
785 Ok(ProverPcsOpened {
786 base: self.base,
787 ic_proof: self.ic_proof,
788 cpr_proof: self.cpr_proof,
789 combined_sumcheck: self.combined_sumcheck,
790 lookup_proof: self.lookup_proof,
791 booleanity_proof: self.booleanity_proof,
792 mp_proof: self.mp_proof,
793 lifted_evals: self.lifted_evals,
794 })
795 }
796});
797
798impl_with_type_bounds!(ProverPcsOpened
799{
800 pub fn finish(self) -> Result<Proof<F>, ProtocolError<F, U::Ideal>> {
802 let sig = self.base.uair_signature;
803 let zip_proof = self.base.pcs_transcript.stream.into_inner();
804 let commitments = (
805 self.base.commitment_bin,
806 self.base.commitment_arb,
807 self.base.commitment_int,
808 );
809
810 let lifted_evals = self.lifted_evals;
811
812 let pub_cols = sig.public_cols();
814 let num_pub_bin = pub_cols.num_binary_poly_cols();
815 let num_pub_arb = pub_cols.num_arbitrary_poly_cols();
816 let num_pub_int = pub_cols.num_int_cols();
817 let total = sig.total_cols();
818 let num_total_bin = total.num_binary_poly_cols();
819 let num_total_arb = total.num_arbitrary_poly_cols();
820 let witness = sig.witness_cols();
821 let witness_arb_offset = add!(num_total_bin, num_pub_arb);
822 let witness_arb_end = add!(witness_arb_offset, witness.num_arbitrary_poly_cols());
823 let witness_int_offset = add!(add!(num_total_bin, num_total_arb), num_pub_int);
824 let witness_lifted_evals: Vec<_> = lifted_evals[num_pub_bin..num_total_bin]
825 .iter()
826 .chain(&lifted_evals[witness_arb_offset..witness_arb_end])
827 .chain(&lifted_evals[witness_int_offset..])
828 .cloned()
829 .collect();
830
831 Ok(Proof {
832 commitments,
833 ideal_check: self.ic_proof,
834 resolver: self.cpr_proof,
835 combined_sumcheck: self.combined_sumcheck,
836 multipoint_eval: self.mp_proof,
837 zip: zip_proof,
838 witness_lifted_evals,
839 lookup_proof: self.lookup_proof,
840 booleanity_proof: self.booleanity_proof,
841 })
842 }
843});
844
845impl<Zt, U, F, const D: usize, const FD: usize> ZincPlusPiop<Zt, U, F, D, FD>
850where
851 Zt: ZincTypes<D, FD>,
852 Zt::Int: ProjectableToField<F>,
853 <Zt::ArbitraryZt as ZipTypes>::Eval: ProjectableToField<F>,
854 F: InnerTransparentField
855 + FromPrimitiveWithConfig
856 + for<'a> FromWithConfig<&'a Zt::Int>
857 + for<'a> FromWithConfig<&'a Zt::CombR>
858 + for<'a> FromWithConfig<&'a Zt::Chal>
859 + for<'a> FromWithConfig<&'a Zt::Pt>
860 + for<'a> MulByScalar<&'a F>
861 + FromRef<F>
862 + Send
863 + Sync
864 + 'static,
865 F::Inner:
866 ConstIntSemiring + ConstTranscribable + FromRef<Zt::Fmod> + Send + Sync + Zero + Default,
867 F::Modulus: ConstTranscribable + FromRef<Zt::Fmod>,
868 U: Uair + 'static,
869{
870 #[allow(clippy::too_many_arguments, clippy::type_complexity)]
876 pub fn prove<const MLE_FIRST: bool, const CHECK_FOR_OVERFLOW: bool>(
877 pp: &(
878 ZipPlusParams<Zt::BinaryZt, Zt::BinaryLc>,
879 ZipPlusParams<Zt::ArbitraryZt, Zt::ArbitraryLc>,
880 ZipPlusParams<Zt::IntZt, Zt::IntLc>,
881 ),
882 trace: &UairTrace<'static, Zt::Int, Zt::Int, D, D>,
883 num_vars: usize,
884 project_scalar: impl Fn(&U::Scalar, &F::Config) -> DynamicPolynomialF<F>,
885 ) -> Result<Proof<F>, ProtocolError<F, U::Ideal>> {
886 let committed = Self::step0_fold(trace)?.step1_commit(pp, num_vars)?;
887
888 let ideal_checked = if MLE_FIRST {
889 committed
890 .step2_mle_first(project_scalar)?
891 .step3_ideal_check()?
892 } else {
893 committed
894 .step2_combined(project_scalar)?
895 .step3_ideal_check()?
896 };
897
898 ideal_checked
899 .step4_eval_projection()?
900 .step5_sumcheck()?
901 .step6_multipoint_eval()?
902 .step7_lift_and_project()?
903 .step8_pcs_open::<CHECK_FOR_OVERFLOW>()?
904 .finish()
905 }
906}
907
908#[allow(clippy::type_complexity)]
909fn commit_optionally<Zt: ZipTypes, Lc: LinearCode<Zt>>(
910 pp: &ZipPlusParams<Zt, Lc>,
911 trace: &[DenseMultilinearExtension<Zt::Eval>],
912) -> Result<(Option<ZipPlusHint<Zt::Cw>>, ZipPlusCommitment), ZipError> {
913 if trace.is_empty() {
914 Ok((
915 None,
916 ZipPlusCommitment {
917 root: Default::default(),
918 batch_size: 0,
919 },
920 ))
921 } else {
922 let (hint, commitment) = ZipPlus::commit(pp, trace)?;
923 Ok((Some(hint), commitment))
924 }
925}