1use super::*;
2use crypto_primitives::{ConstIntSemiring, FromPrimitiveWithConfig, FromWithConfig};
3use num_traits::Zero;
4use std::{collections::HashMap, io::Cursor};
5use zinc_piop::{
6 combined_poly_resolver::{self, CombinedPolyResolver},
7 ideal_check::{self, IdealCheckProtocol},
8 multipoint_eval::{self, MultipointEval},
9 projections::{
10 ProjectedTrace, project_scalars, project_scalars_to_field, project_trace_coeffs_row_major,
11 },
12 sumcheck::multi_degree::MultiDegreeSumcheck,
13};
14use zinc_poly::{EvaluatablePolynomial, univariate::dynamic::over_field::DynamicPolynomialF};
15use zinc_transcript::{
16 Blake3Transcript,
17 traits::{ConstTranscribable, Transcript},
18};
19use zinc_uair::{
20 Uair, UairSignature, UairTrace,
21 constraint_counter::count_constraints,
22 ideal::{Ideal, IdealCheck},
23 ideal_collector::IdealOrZero,
24};
25use zinc_utils::{
26 add, from_ref::FromRef, inner_transparent_field::InnerTransparentField,
27 mul_by_scalar::MulByScalar, projectable_to_field::ProjectableToField,
28};
29use zip_plus::{
30 pcs::structs::{ZipPlus, ZipPlusParams, ZipTypes},
31 pcs_transcript::PcsVerifierTranscript,
32};
33
34#[derive(Clone, Debug)]
40pub struct VerifierBase<'a, Zt: ZincTypes<D>, const D: usize> {
41 num_vars: usize,
42 uair_signature: UairSignature,
43 pcs_transcript: PcsVerifierTranscript,
44 public_trace: &'a UairTrace<'a, Zt::Int, Zt::Int, D>,
45
46 vp_bin: &'a ZipPlusParams<Zt::BinaryZt, Zt::BinaryLc>,
48 vp_arb: &'a ZipPlusParams<Zt::ArbitraryZt, Zt::ArbitraryLc>,
49 vp_int: &'a ZipPlusParams<Zt::IntZt, Zt::IntLc>,
50}
51
52#[derive(Clone, Debug)]
58pub struct VerifierTranscriptReconstructed<
59 'a,
60 Zt: ZincTypes<D>,
61 U: Uair,
62 F: PrimeField,
63 IdealOverF,
64 const D: usize,
65> {
66 base: VerifierBase<'a, Zt, D>,
67
68 proof_commitments: (ZipPlusCommitment, ZipPlusCommitment, ZipPlusCommitment),
70 proof_ideal_check: IdealCheckProof<F>,
71 proof_resolver: CombinedPolyResolverProof<F>,
72 proof_combined_sumcheck: MultiDegreeSumcheckProof<F>,
73 proof_multipoint_eval: MultipointEvalProof<F>,
74 proof_witness_lifted_evals: Vec<DynamicPolynomialF<F>>,
75 proof_lookup_proof: Option<BatchedLookupProof<F>>,
76 _phantom: PhantomData<(U, IdealOverF)>,
77}
78
79#[derive(Clone, Debug)]
81pub struct VerifierPrimeProjected<
82 'a,
83 Zt: ZincTypes<D>,
84 U: Uair,
85 F: PrimeField,
86 IdealOverF,
87 const D: usize,
88> {
89 base: VerifierBase<'a, Zt, D>,
90 field_cfg: F::Config,
91
92 proof_commitments: (ZipPlusCommitment, ZipPlusCommitment, ZipPlusCommitment),
94 proof_ideal_check: IdealCheckProof<F>,
95 proof_resolver: CombinedPolyResolverProof<F>,
96 proof_combined_sumcheck: MultiDegreeSumcheckProof<F>,
97 proof_multipoint_eval: MultipointEvalProof<F>,
98 proof_witness_lifted_evals: Vec<DynamicPolynomialF<F>>,
99 proof_lookup_proof: Option<BatchedLookupProof<F>>,
100 _phantom: PhantomData<(U, IdealOverF)>,
101}
102
103#[derive(Clone, Debug)]
105pub struct VerifierIdealChecked<
106 'a,
107 Zt: ZincTypes<D>,
108 U: Uair,
109 F: PrimeField,
110 IdealOverF,
111 const D: usize,
112> {
113 base: VerifierBase<'a, Zt, D>,
114 field_cfg: F::Config,
115 ic_subclaim: ideal_check::VerifierSubclaim<F>,
116
117 proof_commitments: (ZipPlusCommitment, ZipPlusCommitment, ZipPlusCommitment),
119 proof_resolver: CombinedPolyResolverProof<F>,
120 proof_combined_sumcheck: MultiDegreeSumcheckProof<F>,
121 proof_multipoint_eval: MultipointEvalProof<F>,
122 proof_witness_lifted_evals: Vec<DynamicPolynomialF<F>>,
123 proof_lookup_proof: Option<BatchedLookupProof<F>>,
124 _phantom: PhantomData<(U, IdealOverF)>,
125}
126
127#[derive(Clone, Debug)]
129pub struct VerifierEvalProjected<
130 'a,
131 Zt: ZincTypes<D>,
132 U: Uair,
133 F: PrimeField,
134 IdealOverF,
135 const D: usize,
136> {
137 base: VerifierBase<'a, Zt, D>,
138 field_cfg: F::Config,
139 ic_subclaim: ideal_check::VerifierSubclaim<F>,
140 projecting_element_f: F,
141 projected_scalars_f: HashMap<U::Scalar, F>,
142
143 proof_commitments: (ZipPlusCommitment, ZipPlusCommitment, ZipPlusCommitment),
145 proof_resolver: CombinedPolyResolverProof<F>,
146 proof_combined_sumcheck: MultiDegreeSumcheckProof<F>,
147 proof_multipoint_eval: MultipointEvalProof<F>,
148 proof_witness_lifted_evals: Vec<DynamicPolynomialF<F>>,
149 proof_lookup_proof: Option<BatchedLookupProof<F>>,
150 _phantom: PhantomData<(U, IdealOverF)>,
151}
152
153#[derive(Clone, Debug)]
155pub struct VerifierSumchecked<'a, Zt: ZincTypes<D>, F: PrimeField, IdealOverF, const D: usize> {
156 base: VerifierBase<'a, Zt, D>,
157 field_cfg: F::Config,
158 projecting_element_f: F,
159 cpr_subclaim: combined_poly_resolver::VerifierSubclaim<F>,
160
161 proof_commitments: (ZipPlusCommitment, ZipPlusCommitment, ZipPlusCommitment),
163 proof_multipoint_eval: MultipointEvalProof<F>,
164 proof_witness_lifted_evals: Vec<DynamicPolynomialF<F>>,
165 proof_lookup_proof: Option<BatchedLookupProof<F>>,
166 _phantom: PhantomData<IdealOverF>,
167}
168
169#[derive(Clone, Debug)]
171pub struct VerifierMultipointEvaled<'a, Zt: ZincTypes<D>, F: PrimeField, IdealOverF, const D: usize>
172{
173 base: VerifierBase<'a, Zt, D>,
174 field_cfg: F::Config,
175 projecting_element_f: F,
176 mp_subclaim: multipoint_eval::Subclaim<F>,
177
178 proof_commitments: (ZipPlusCommitment, ZipPlusCommitment, ZipPlusCommitment),
180 proof_witness_lifted_evals: Vec<DynamicPolynomialF<F>>,
181 proof_lookup_proof: Option<BatchedLookupProof<F>>,
182 _phantom: PhantomData<IdealOverF>,
183}
184
185#[derive(Clone, Debug)]
187#[allow(dead_code)]
188pub struct VerifierLiftedEvalsChecked<
189 'a,
190 Zt: ZincTypes<D>,
191 F: PrimeField,
192 IdealOverF,
193 const D: usize,
194> {
195 base: VerifierBase<'a, Zt, D>,
196 field_cfg: F::Config,
197 mp_subclaim: multipoint_eval::Subclaim<F>,
198 all_lifted_evals: Vec<DynamicPolynomialF<F>>,
199
200 proof_commitments: (ZipPlusCommitment, ZipPlusCommitment, ZipPlusCommitment),
202 proof_lookup_proof: Option<BatchedLookupProof<F>>,
203 _phantom: PhantomData<IdealOverF>,
204}
205
206#[derive(Clone, Debug)]
209pub struct VerifierPcsVerified<IdealOverF> {
210 _phantom: PhantomData<IdealOverF>,
211}
212
213impl<Zt, U, F, const D: usize> ZincPlusPiop<Zt, U, F, D>
218where
219 Zt: ZincTypes<D>,
220 U: Uair,
221 F: PrimeField,
222 F::Inner: ConstTranscribable,
223{
224 #[allow(clippy::type_complexity)]
227 pub fn step0_reconstruct_transcript<'a, IdealOverF>(
228 (vp_bin, vp_arb, vp_int): &'a (
229 ZipPlusParams<Zt::BinaryZt, Zt::BinaryLc>,
230 ZipPlusParams<Zt::ArbitraryZt, Zt::ArbitraryLc>,
231 ZipPlusParams<Zt::IntZt, Zt::IntLc>,
232 ),
233 mut proof: Proof<F>,
234 public_trace: &'a UairTrace<'a, Zt::Int, Zt::Int, D>,
235 num_vars: usize,
236 ) -> Result<
237 VerifierTranscriptReconstructed<'a, Zt, U, F, IdealOverF, D>,
238 ProtocolError<F, IdealOverF>,
239 >
240 where
241 IdealOverF: Ideal,
242 {
243 let zip_proof = std::mem::take(&mut proof.zip);
244 let mut base = VerifierBase {
245 num_vars,
246 uair_signature: U::signature(),
247 public_trace,
248 pcs_transcript: PcsVerifierTranscript {
249 fs_transcript: Blake3Transcript::default(),
250 stream: Cursor::new(zip_proof),
251 },
252 vp_bin,
253 vp_arb,
254 vp_int,
255 };
256
257 for comm in [
258 &proof.commitments.0,
259 &proof.commitments.1,
260 &proof.commitments.2,
261 ] {
262 base.pcs_transcript.fs_transcript.absorb_slice(&comm.root);
263 }
264
265 absorb_public_columns(
266 &mut base.pcs_transcript.fs_transcript,
267 &base.public_trace.binary_poly,
268 );
269 absorb_public_columns(
270 &mut base.pcs_transcript.fs_transcript,
271 &base.public_trace.arbitrary_poly,
272 );
273 absorb_public_columns(
274 &mut base.pcs_transcript.fs_transcript,
275 &base.public_trace.int,
276 );
277
278 Ok(VerifierTranscriptReconstructed {
279 base,
280 proof_commitments: proof.commitments,
281 proof_ideal_check: proof.ideal_check,
282 proof_resolver: proof.resolver,
283 proof_combined_sumcheck: proof.combined_sumcheck,
284 proof_multipoint_eval: proof.multipoint_eval,
285 proof_witness_lifted_evals: proof.witness_lifted_evals,
286 proof_lookup_proof: proof.lookup_proof,
287 _phantom: PhantomData,
288 })
289 }
290}
291
292impl<'a, Zt, U, F, IdealOverF, const D: usize>
293 VerifierTranscriptReconstructed<'a, Zt, U, F, IdealOverF, D>
294where
295 Zt: ZincTypes<D>,
296 F: InnerTransparentField + FromPrimitiveWithConfig + FromRef<F> + Send + Sync + 'static,
297 F::Inner: ConstIntSemiring + ConstTranscribable + Send + Sync + Zero + Default,
298 F::Modulus: ConstTranscribable + FromRef<Zt::Fmod>,
299 U: Uair,
300 IdealOverF: Ideal,
301{
302 #[allow(clippy::type_complexity)]
304 pub fn step1_prime_projection(
305 mut self,
306 ) -> Result<VerifierPrimeProjected<'a, Zt, U, F, IdealOverF, D>, ProtocolError<F, IdealOverF>>
307 {
308 let field_cfg = self
309 .base
310 .pcs_transcript
311 .fs_transcript
312 .get_random_field_cfg::<F, Zt::Fmod, Zt::PrimeTest>();
313
314 Ok(VerifierPrimeProjected {
315 base: self.base,
316 field_cfg,
317 proof_commitments: self.proof_commitments,
318 proof_ideal_check: self.proof_ideal_check,
319 proof_resolver: self.proof_resolver,
320 proof_combined_sumcheck: self.proof_combined_sumcheck,
321 proof_multipoint_eval: self.proof_multipoint_eval,
322 proof_witness_lifted_evals: self.proof_witness_lifted_evals,
323 proof_lookup_proof: self.proof_lookup_proof,
324 _phantom: PhantomData,
325 })
326 }
327}
328
329impl<'a, Zt, U, F, IdealOverF, const D: usize> VerifierPrimeProjected<'a, Zt, U, F, IdealOverF, D>
330where
331 Zt: ZincTypes<D>,
332 Zt::Int: ProjectableToField<F>,
333 <Zt::ArbitraryZt as ZipTypes>::Eval: ProjectableToField<F>,
334 F: InnerTransparentField
335 + FromPrimitiveWithConfig
336 + for<'b> FromWithConfig<&'b Zt::Int>
337 + for<'b> FromWithConfig<&'b Zt::CombR>
338 + for<'b> FromWithConfig<&'b Zt::Chal>
339 + for<'b> MulByScalar<&'b F>
340 + FromRef<F>
341 + Send
342 + Sync
343 + 'static,
344 F::Inner: ConstIntSemiring + ConstTranscribable + Send + Sync + Zero + Default,
345 F::Modulus: ConstTranscribable + FromRef<Zt::Fmod>,
346 U: Uair + 'static,
347 IdealOverF: Ideal + IdealCheck<DynamicPolynomialF<F>>,
348{
349 #[allow(clippy::type_complexity)]
351 pub fn step2_ideal_check(
352 mut self,
353 project_ideal: impl Fn(&IdealOrZero<U::Ideal>, &F::Config) -> IdealOverF,
354 ) -> Result<VerifierIdealChecked<'a, Zt, U, F, IdealOverF, D>, ProtocolError<F, IdealOverF>>
355 {
356 let num_constraints = count_constraints::<U>();
357
358 let ic_subclaim = U::verify_as_subprotocol::<_, IdealOverF, _>(
359 &mut self.base.pcs_transcript.fs_transcript,
360 self.proof_ideal_check,
361 num_constraints,
362 self.base.num_vars,
363 |ideal| project_ideal(ideal, &self.field_cfg),
364 &self.field_cfg,
365 )?;
366
367 Ok(VerifierIdealChecked {
368 base: self.base,
369 field_cfg: self.field_cfg,
370 ic_subclaim,
371 proof_commitments: self.proof_commitments,
372 proof_resolver: self.proof_resolver,
373 proof_combined_sumcheck: self.proof_combined_sumcheck,
374 proof_multipoint_eval: self.proof_multipoint_eval,
375 proof_witness_lifted_evals: self.proof_witness_lifted_evals,
376 proof_lookup_proof: self.proof_lookup_proof,
377 _phantom: PhantomData,
378 })
379 }
380}
381
382impl<'a, Zt, U, F, IdealOverF, const D: usize> VerifierIdealChecked<'a, Zt, U, F, IdealOverF, D>
383where
384 Zt: ZincTypes<D>,
385 F: InnerTransparentField
386 + for<'b> FromWithConfig<&'b Zt::Chal>
387 + FromRef<F>
388 + Send
389 + Sync
390 + 'static,
391 F::Inner: ConstIntSemiring + ConstTranscribable + Send + Sync + Zero + Default,
392 F::Modulus: ConstTranscribable + FromRef<Zt::Fmod>,
393 U: Uair + 'static,
394 IdealOverF: Ideal,
395{
396 pub fn step3_eval_projection(
398 mut self,
399 project_scalar: impl Fn(&U::Scalar, &F::Config) -> DynamicPolynomialF<F>,
400 ) -> Result<VerifierEvalProjected<'a, Zt, U, F, IdealOverF, D>, ProtocolError<F, IdealOverF>>
401 {
402 let projecting_element: Zt::Chal = self.base.pcs_transcript.fs_transcript.get_challenge();
403 let projecting_element_f: F = F::from_with_cfg(&projecting_element, &self.field_cfg);
404
405 let projected_scalars_fx = project_scalars::<F, U>(|s| project_scalar(s, &self.field_cfg));
406 let projected_scalars_f =
407 project_scalars_to_field(projected_scalars_fx, &projecting_element_f)
408 .map_err(|(_s, _f, e)| ProtocolError::ScalarProjection(e))?;
409
410 Ok(VerifierEvalProjected {
411 base: self.base,
412 field_cfg: self.field_cfg,
413 ic_subclaim: self.ic_subclaim,
414 projecting_element_f,
415 projected_scalars_f,
416 proof_commitments: self.proof_commitments,
417 proof_resolver: self.proof_resolver,
418 proof_combined_sumcheck: self.proof_combined_sumcheck,
419 proof_multipoint_eval: self.proof_multipoint_eval,
420 proof_witness_lifted_evals: self.proof_witness_lifted_evals,
421 proof_lookup_proof: self.proof_lookup_proof,
422 _phantom: PhantomData,
423 })
424 }
425}
426
427impl<'a, Zt, U, F, IdealOverF, const D: usize> VerifierEvalProjected<'a, Zt, U, F, IdealOverF, D>
428where
429 Zt: ZincTypes<D>,
430 Zt::Int: ProjectableToField<F>,
431 <Zt::ArbitraryZt as ZipTypes>::Eval: ProjectableToField<F>,
432 F: InnerTransparentField
433 + FromPrimitiveWithConfig
434 + for<'b> FromWithConfig<&'b Zt::Int>
435 + for<'b> FromWithConfig<&'b Zt::CombR>
436 + for<'b> FromWithConfig<&'b Zt::Chal>
437 + for<'b> MulByScalar<&'b F>
438 + FromRef<F>
439 + Send
440 + Sync
441 + 'static,
442 F::Inner: ConstIntSemiring + ConstTranscribable + Send + Sync + Zero + Default,
443 F::Modulus: ConstTranscribable + FromRef<Zt::Fmod>,
444 U: Uair + 'static,
445 IdealOverF: Ideal,
446{
447 pub fn step4_sumcheck_verify(
449 mut self,
450 ) -> Result<VerifierSumchecked<'a, Zt, F, IdealOverF, D>, ProtocolError<F, IdealOverF>> {
451 let num_constraints = count_constraints::<U>();
452
453 let cpr_verifier_ancillary = CombinedPolyResolver::prepare_verifier::<U>(
454 &mut self.base.pcs_transcript.fs_transcript,
455 &self.proof_resolver,
456 self.proof_combined_sumcheck.claimed_sums()[0].clone(),
457 &self.ic_subclaim,
458 num_constraints,
459 self.base.num_vars,
460 &self.projecting_element_f,
461 &self.field_cfg,
462 )?;
463
464 let md_subclaims = MultiDegreeSumcheck::verify_as_subprotocol(
465 &mut self.base.pcs_transcript.fs_transcript,
466 self.base.num_vars,
467 &self.proof_combined_sumcheck,
468 &self.field_cfg,
469 )
470 .map_err(CombinedPolyResolverError::SumcheckError)?;
471
472 let cpr_subclaim = CombinedPolyResolver::finalize_verifier::<U>(
473 &mut self.base.pcs_transcript.fs_transcript,
474 self.proof_resolver,
475 md_subclaims.point().to_vec(),
476 md_subclaims.expected_evaluations()[0].clone(),
477 cpr_verifier_ancillary,
478 &self.projected_scalars_f,
479 &self.field_cfg,
480 )?;
481
482 let _ = &self.proof_lookup_proof;
483
484 Ok(VerifierSumchecked {
485 base: self.base,
486 field_cfg: self.field_cfg,
487 projecting_element_f: self.projecting_element_f,
488 cpr_subclaim,
489 proof_commitments: self.proof_commitments,
490 proof_multipoint_eval: self.proof_multipoint_eval,
491 proof_witness_lifted_evals: self.proof_witness_lifted_evals,
492 proof_lookup_proof: self.proof_lookup_proof,
493 _phantom: PhantomData,
494 })
495 }
496}
497
498impl<'a, Zt, F, IdealOverF, const D: usize> VerifierSumchecked<'a, Zt, F, IdealOverF, D>
499where
500 Zt: ZincTypes<D>,
501 F: InnerTransparentField + FromPrimitiveWithConfig + FromRef<F> + Send + Sync + 'static,
502 F::Inner: ConstIntSemiring + ConstTranscribable + Send + Sync + Zero + Default,
503 F::Modulus: ConstTranscribable + FromRef<Zt::Fmod>,
504 IdealOverF: Ideal,
505{
506 pub fn step5_multipoint_eval<U: Uair>(
508 mut self,
509 ) -> Result<VerifierMultipointEvaled<'a, Zt, F, IdealOverF, D>, ProtocolError<F, IdealOverF>>
510 {
511 let mp_subclaim = MultipointEval::verify_as_subprotocol(
512 &mut self.base.pcs_transcript.fs_transcript,
513 self.proof_multipoint_eval,
514 &self.cpr_subclaim.evaluation_point,
515 &self.cpr_subclaim.up_evals,
516 &self.cpr_subclaim.down_evals,
517 self.base.uair_signature.shifts(),
518 self.base.num_vars,
519 &self.field_cfg,
520 )?;
521
522 Ok(VerifierMultipointEvaled {
523 base: self.base,
524 field_cfg: self.field_cfg,
525 projecting_element_f: self.projecting_element_f,
526 mp_subclaim,
527 proof_commitments: self.proof_commitments,
528 proof_witness_lifted_evals: self.proof_witness_lifted_evals,
529 proof_lookup_proof: self.proof_lookup_proof,
530 _phantom: PhantomData,
531 })
532 }
533}
534
535impl<'a, Zt, F, IdealOverF, const D: usize> VerifierMultipointEvaled<'a, Zt, F, IdealOverF, D>
536where
537 Zt: ZincTypes<D>,
538 Zt::Int: ProjectableToField<F>,
539 <Zt::ArbitraryZt as ZipTypes>::Eval: ProjectableToField<F>,
540 F: InnerTransparentField
541 + FromPrimitiveWithConfig
542 + for<'b> FromWithConfig<&'b Zt::Int>
543 + for<'b> FromWithConfig<&'b Zt::Chal>
544 + for<'b> MulByScalar<&'b F>
545 + FromRef<F>
546 + Send
547 + Sync
548 + 'static,
549 F::Inner: ConstIntSemiring + ConstTranscribable + Send + Sync + Zero + Default,
550 F::Modulus: ConstTranscribable + FromRef<Zt::Fmod>,
551 IdealOverF: Ideal,
552{
553 pub fn step6_lifted_evals<U: Uair>(
556 mut self,
557 ) -> Result<VerifierLiftedEvalsChecked<'a, Zt, F, IdealOverF, D>, ProtocolError<F, IdealOverF>>
558 {
559 let r_0 = &self.mp_subclaim.sumcheck_subclaim.point;
560
561 let pub_cols = self.base.uair_signature.public_cols();
562 let num_pub_bin = pub_cols.num_binary_poly_cols();
563 let num_pub_arb = pub_cols.num_arbitrary_poly_cols();
564 let num_pub_int = pub_cols.num_int_cols();
565
566 let wit_cols = self.base.uair_signature.witness_cols();
567 let num_wit_bin = wit_cols.num_binary_poly_cols();
568 let num_wit_arb = wit_cols.num_arbitrary_poly_cols();
569
570 let public_lifted = if add!(add!(num_pub_bin, num_pub_arb), num_pub_int) > 0 {
571 let projected_public = project_trace_coeffs_row_major::<F, Zt::Int, Zt::Int, D>(
572 self.base.public_trace,
573 &self.field_cfg,
574 );
575 compute_lifted_evals::<F, D>(
576 r_0,
577 &self.base.public_trace.binary_poly,
578 &ProjectedTrace::RowMajor(projected_public),
579 &self.field_cfg,
580 )
581 } else {
582 Vec::new()
583 };
584
585 let witness_lifted_evals = &self.proof_witness_lifted_evals;
586
587 let all_lifted_evals: Vec<_> = public_lifted[..num_pub_bin]
588 .iter()
589 .chain(&witness_lifted_evals[..num_wit_bin])
590 .chain(&public_lifted[num_pub_bin..add!(num_pub_bin, num_pub_arb)])
591 .chain(&witness_lifted_evals[num_wit_bin..add!(num_wit_bin, num_wit_arb)])
592 .chain(&public_lifted[add!(num_pub_bin, num_pub_arb)..])
593 .chain(&witness_lifted_evals[add!(num_wit_bin, num_wit_arb)..])
594 .cloned()
595 .collect();
596
597 let open_evals: Vec<F> = all_lifted_evals
598 .iter()
599 .map(|bar_u| bar_u.evaluate_at_point(&self.projecting_element_f))
600 .collect::<Result<Vec<_>, _>>()
601 .map_err(ProtocolError::LiftedEvalProjection)?;
602
603 MultipointEval::verify_subclaim(
604 &self.mp_subclaim,
605 &open_evals,
606 self.base.uair_signature.shifts(),
607 &self.field_cfg,
608 )?;
609
610 let mut transcription_buf: Vec<u8> = vec![0; F::Inner::NUM_BYTES];
611 for bar_u in &all_lifted_evals {
612 self.base
613 .pcs_transcript
614 .fs_transcript
615 .absorb_random_field_slice(&bar_u.coeffs, &mut transcription_buf);
616 }
617
618 Ok(VerifierLiftedEvalsChecked {
619 base: self.base,
620 field_cfg: self.field_cfg,
621 mp_subclaim: self.mp_subclaim,
622 all_lifted_evals,
623 proof_commitments: self.proof_commitments,
624 proof_lookup_proof: self.proof_lookup_proof,
625 _phantom: PhantomData,
626 })
627 }
628}
629
630impl<'a, Zt, F, IdealOverF, const D: usize> VerifierLiftedEvalsChecked<'a, Zt, F, IdealOverF, D>
631where
632 Zt: ZincTypes<D>,
633 Zt::Int: ProjectableToField<F>,
634 <Zt::BinaryZt as ZipTypes>::Cw: ProjectableToField<F>,
635 <Zt::ArbitraryZt as ZipTypes>::Eval: ProjectableToField<F>,
636 <Zt::ArbitraryZt as ZipTypes>::Cw: ProjectableToField<F>,
637 <Zt::IntZt as ZipTypes>::Cw: ProjectableToField<F>,
638 F: InnerTransparentField
639 + FromPrimitiveWithConfig
640 + for<'b> FromWithConfig<&'b Zt::Int>
641 + for<'b> FromWithConfig<&'b Zt::CombR>
642 + for<'b> FromWithConfig<&'b Zt::Chal>
643 + for<'b> MulByScalar<&'b F>
644 + FromRef<F>
645 + Send
646 + Sync
647 + 'static,
648 F::Inner: ConstIntSemiring + ConstTranscribable + Send + Sync + Zero + Default,
649 F::Modulus: ConstTranscribable + FromRef<Zt::Fmod>,
650 IdealOverF: Ideal,
651{
652 pub fn step7_pcs_verify<U: Uair, const CHECK_FOR_OVERFLOW: bool>(
654 mut self,
655 ) -> Result<VerifierPcsVerified<IdealOverF>, ProtocolError<F, IdealOverF>> {
656 let r_0 = &self.mp_subclaim.sumcheck_subclaim.point;
657 let commitments = &self.proof_commitments;
658
659 let pub_cols = self.base.uair_signature.public_cols();
660 let num_pub_bin = pub_cols.num_binary_poly_cols();
661 let num_pub_arb = pub_cols.num_arbitrary_poly_cols();
662 let num_pub_int = pub_cols.num_int_cols();
663
664 let total = self.base.uair_signature.total_cols();
665 let num_total_bin = total.num_binary_poly_cols();
666 let num_total_arb = total.num_arbitrary_poly_cols();
667
668 let pcs_transcript = &mut self.base.pcs_transcript;
669 let field_cfg = &self.field_cfg;
670 let all_lifted_evals = &self.all_lifted_evals;
671
672 macro_rules! verify_pcs_batch {
673 ($Zt:ty, $Lc:ty, $vp:expr, $idx:tt, [$evals_range:expr]) => {{
674 let comm = &commitments.$idx;
675 if comm.batch_size > 0 {
676 let per_poly_alphas = ZipPlus::<$Zt, $Lc>::sample_alphas(
677 &mut pcs_transcript.fs_transcript,
678 comm.batch_size,
679 );
680 let mut eval_f = F::zero_with_cfg(field_cfg);
681 for (bar_u, alphas) in all_lifted_evals[$evals_range]
682 .iter()
683 .zip(per_poly_alphas.iter())
684 {
685 for (coeff, alpha) in bar_u.coeffs.iter().zip(alphas.iter()) {
686 let mut term = F::from_with_cfg(alpha, field_cfg);
687 term *= coeff;
688 eval_f += &term;
689 }
690 }
691 ZipPlus::<$Zt, $Lc>::verify_with_alphas::<F, CHECK_FOR_OVERFLOW>(
692 pcs_transcript,
693 $vp,
694 comm,
695 field_cfg,
696 r_0,
697 &eval_f,
698 &per_poly_alphas,
699 )
700 .map_err(|e| ProtocolError::PcsVerification($idx, e))?;
701 }
702 }};
703 }
704
705 verify_pcs_batch!(
706 Zt::BinaryZt,
707 Zt::BinaryLc,
708 self.base.vp_bin,
709 0,
710 [num_pub_bin..num_total_bin]
711 );
712 verify_pcs_batch!(
713 Zt::ArbitraryZt,
714 Zt::ArbitraryLc,
715 self.base.vp_arb,
716 1,
717 [add!(num_total_bin, num_pub_arb)..add!(num_total_bin, num_total_arb)]
718 );
719 verify_pcs_batch!(
720 Zt::IntZt,
721 Zt::IntLc,
722 self.base.vp_int,
723 2,
724 [add!(add!(num_total_bin, num_total_arb), num_pub_int)..]
725 );
726
727 Ok(VerifierPcsVerified {
728 _phantom: PhantomData,
729 })
730 }
731}
732
733impl<IdealOverF: Ideal> VerifierPcsVerified<IdealOverF> {
734 pub fn finish<F: PrimeField>(self) -> Result<(), ProtocolError<F, IdealOverF>> {
736 Ok(())
737 }
738}
739
740impl<Zt, U, F, const D: usize> ZincPlusPiop<Zt, U, F, D>
743where
744 Zt: ZincTypes<D>,
745 Zt::Int: ProjectableToField<F>,
746 <Zt::BinaryZt as ZipTypes>::Cw: ProjectableToField<F>,
747 <Zt::ArbitraryZt as ZipTypes>::Eval: ProjectableToField<F>,
748 <Zt::ArbitraryZt as ZipTypes>::Cw: ProjectableToField<F>,
749 <Zt::IntZt as ZipTypes>::Cw: ProjectableToField<F>,
750 F: InnerTransparentField
751 + FromPrimitiveWithConfig
752 + for<'a> FromWithConfig<&'a Zt::Int>
753 + for<'a> FromWithConfig<&'a Zt::CombR>
754 + for<'a> FromWithConfig<&'a Zt::Chal>
755 + for<'a> MulByScalar<&'a F>
756 + FromRef<F>
757 + Send
758 + Sync
759 + 'static,
760 F::Inner: ConstIntSemiring + ConstTranscribable + Send + Sync + Zero + Default,
761 F::Modulus: ConstTranscribable + FromRef<Zt::Fmod>,
762 U: Uair + 'static,
763{
764 #[allow(clippy::too_many_arguments, clippy::type_complexity)]
771 pub fn verify<IdealOverF, const CHECK_FOR_OVERFLOW: bool>(
772 vp: &(
773 ZipPlusParams<Zt::BinaryZt, Zt::BinaryLc>,
774 ZipPlusParams<Zt::ArbitraryZt, Zt::ArbitraryLc>,
775 ZipPlusParams<Zt::IntZt, Zt::IntLc>,
776 ),
777 proof: Proof<F>,
778 public_trace: &UairTrace<Zt::Int, Zt::Int, D>,
779 num_vars: usize,
780 project_scalar: impl Fn(&U::Scalar, &F::Config) -> DynamicPolynomialF<F>,
781 project_ideal: impl Fn(&IdealOrZero<U::Ideal>, &F::Config) -> IdealOverF,
782 ) -> Result<(), ProtocolError<F, IdealOverF>>
783 where
784 IdealOverF: Ideal + IdealCheck<DynamicPolynomialF<F>>,
785 {
786 ZincPlusPiop::<Zt, U, F, D>::step0_reconstruct_transcript::<IdealOverF>(
787 vp,
788 proof,
789 public_trace,
790 num_vars,
791 )?
792 .step1_prime_projection()?
793 .step2_ideal_check(project_ideal)?
794 .step3_eval_projection(project_scalar)?
795 .step4_sumcheck_verify()?
796 .step5_multipoint_eval::<U>()?
797 .step6_lifted_evals::<U>()?
798 .step7_pcs_verify::<U, CHECK_FOR_OVERFLOW>()?
799 .finish::<F>()
800 }
801}