1use super::structs::{
8 BatchProof, Challenges, PlookupProof, ProofEvaluations, ScalarsAndBases, VerifyingKey,
9};
10use crate::{
11 constants::*,
12 errors::{PlonkError, SnarkError::ParameterError},
13 lagrange::LagrangeCoeffs,
14 proof_system::structs::{eval_merged_lookup_witness, eval_merged_table, OpenKey},
15 transcript::*,
16};
17use ark_ec::{
18 pairing::Pairing,
19 short_weierstrass::{Affine, SWCurveConfig},
20};
21use ark_ff::{Field, One, Zero};
22use ark_poly::{EvaluationDomain, Radix2EvaluationDomain};
23use ark_std::{format, vec, vec::Vec};
24use core::ops::Neg;
25use jf_pcs::prelude::Commitment;
26use jf_relation::{constants::GATE_WIDTH, gadgets::ecc::SWToTEConParam};
27use jf_rescue::RescueParameter;
28use jf_utils::multi_pairing;
29
30#[derive(Debug)]
42pub(crate) struct PcsInfo<E: Pairing> {
43 pub(crate) u: E::ScalarField,
44 pub(crate) eval_point: E::ScalarField,
45 pub(crate) next_eval_point: E::ScalarField,
46 pub(crate) eval: E::ScalarField,
47 pub(crate) comm_scalars_and_bases: ScalarsAndBases<E>,
48 pub(crate) opening_proof: Commitment<E>,
49 pub(crate) shifted_opening_proof: Commitment<E>,
50}
51
52pub(crate) struct Verifier<E: Pairing> {
53 pub(crate) domain: Radix2EvaluationDomain<E::ScalarField>,
54}
55
56impl<E, F, P> Verifier<E>
57where
58 E: Pairing<BaseField = F, G1Affine = Affine<P>>,
59 F: RescueParameter + SWToTEConParam,
60 P: SWCurveConfig<BaseField = F>,
61{
62 pub(crate) fn new(domain_size: usize) -> Result<Self, PlonkError> {
64 let domain = Radix2EvaluationDomain::<E::ScalarField>::new(domain_size)
65 .ok_or(PlonkError::DomainCreationError)?;
66 Ok(Self { domain })
67 }
68
69 pub(crate) fn prepare_pcs_info<T>(
71 &self,
72 verify_keys: &[&VerifyingKey<E>],
73 public_inputs: &[&[E::ScalarField]],
74 batch_proof: &BatchProof<E>,
75 extra_transcript_init_msg: &Option<Vec<u8>>,
76 ) -> Result<PcsInfo<E>, PlonkError>
77 where
78 T: PlonkTranscript<F>,
79 {
80 if verify_keys.len() != batch_proof.len()
81 || verify_keys.len() != public_inputs.len()
82 || verify_keys.is_empty()
83 {
84 return Err(ParameterError(format!(
85 "the number of verification keys = {}; the number of instances = {}; the number of public inputs = {}",
86 verify_keys.len(),
87 batch_proof.len(),
88 public_inputs.len(),
89 ))
90 .into());
91 }
92 for (i, (&pub_input, &vk)) in public_inputs.iter().zip(verify_keys.iter()).enumerate() {
93 if pub_input.len() != vk.num_inputs {
94 return Err(ParameterError(
95 format!("the circuit public input length {} != the {}-th verification key public input length {}", pub_input.len(), i, vk.num_inputs)
96 )
97 .into());
98 }
99 if vk.plookup_vk.is_some() != batch_proof.plookup_proofs_vec[i].is_some() {
100 return Err(ParameterError(format!(
101 "Mismatched proof type and verification key type for the {i}-th instance",
102 ))
103 .into());
104 }
105 if vk.domain_size != self.domain.size() {
106 return Err(ParameterError(format!(
107 "the domain size {} of the {}-th verification key is different from {}",
108 vk.domain_size,
109 i,
110 self.domain.size(),
111 ))
112 .into());
113 }
114 }
115
116 let challenges = Self::compute_challenges::<T>(
118 verify_keys,
119 public_inputs,
120 batch_proof,
121 extra_transcript_init_msg,
122 )?;
123
124 let alpha_2 = challenges.alpha.square();
126 let alpha_3 = alpha_2 * challenges.alpha;
127 let alpha_4 = alpha_2 * alpha_2;
128 let alpha_5 = alpha_2 * alpha_3;
129 let alpha_6 = alpha_4 * alpha_2;
130 let alpha_7 = alpha_3 * alpha_4;
131 let alpha_powers = vec![alpha_2, alpha_3, alpha_4, alpha_5, alpha_6];
132 let mut alpha_bases = vec![E::ScalarField::one()];
133
134 let mut tmp = if verify_keys[0].plookup_vk.is_some() {
135 alpha_7
136 } else {
137 alpha_3
138 };
139 if verify_keys.len() > 1 {
140 for _ in 0..verify_keys.len() - 1 {
141 alpha_bases.push(tmp);
142 tmp *= alpha_bases[1];
143 }
144 }
145
146 let vanish_eval = self.evaluate_vanishing_poly(&challenges.zeta);
147 let (lagrange_1_eval, lagrange_n_eval) =
148 self.domain.first_and_last_lagrange_coeffs(challenges.zeta);
149
150 let lin_poly_constant = self.compute_lin_poly_constant_term(
152 &challenges,
153 verify_keys,
154 public_inputs,
155 batch_proof,
156 &lagrange_1_eval,
157 &lagrange_n_eval,
158 &alpha_powers,
159 &alpha_bases,
160 )?;
161
162 let (comm_scalars_and_bases, buffer_v_and_uv_basis) = self.aggregate_poly_commitments(
164 verify_keys,
165 &challenges,
166 &vanish_eval,
167 &lagrange_1_eval,
168 &lagrange_n_eval,
169 batch_proof,
170 &alpha_powers,
171 &alpha_bases,
172 )?;
173 let eval = Self::aggregate_evaluations(
174 &lin_poly_constant,
175 &batch_proof.poly_evals_vec,
176 &batch_proof.plookup_proofs_vec,
177 &buffer_v_and_uv_basis,
178 )?;
179
180 Ok(PcsInfo {
181 u: challenges.u,
182 eval_point: challenges.zeta,
183 next_eval_point: challenges.zeta * self.domain.group_gen,
184 comm_scalars_and_bases,
185 eval,
186 opening_proof: batch_proof.opening_proof,
187 shifted_opening_proof: batch_proof.shifted_opening_proof,
188 })
189 }
190
191 pub(crate) fn batch_verify_opening_proofs<T>(
202 open_key: &OpenKey<E>,
203 pcs_infos: &[PcsInfo<E>],
204 ) -> Result<bool, PlonkError>
205 where
206 T: PlonkTranscript<F>,
207 {
208 let r = if pcs_infos.len() == 1 {
210 E::ScalarField::one()
212 } else {
213 let mut transcript = T::new(b"batch verify");
214 for pcs_info in pcs_infos {
218 transcript.append_field_elem::<E>(b"u", &pcs_info.u)?;
219 }
220 transcript.get_challenge::<E>(b"r")?
221 };
222
223 let mut inners = ScalarsAndBases::<E>::new();
225 let mut r_base = E::ScalarField::one();
226 for pcs_info in pcs_infos.iter() {
227 inners.push(r_base, pcs_info.opening_proof.0);
228 inners.push(r_base * pcs_info.u, pcs_info.shifted_opening_proof.0);
229 r_base *= r;
230 }
231 let inner = inners.multi_scalar_mul();
232 let mut g1_elems: Vec<<E as Pairing>::G1Affine> = vec![inner.into()];
234 let mut g2_elems = vec![open_key.beta_h];
235
236 let mut inners = ScalarsAndBases::new();
238 let mut r_base = E::ScalarField::one();
239 let mut sum_evals = E::ScalarField::zero();
240 for pcs_info in pcs_infos.iter() {
241 inners.merge(r_base, &pcs_info.comm_scalars_and_bases);
242 inners.push(r_base * pcs_info.eval_point, pcs_info.opening_proof.0);
243 inners.push(
244 r_base * pcs_info.u * pcs_info.next_eval_point,
245 pcs_info.shifted_opening_proof.0,
246 );
247 sum_evals += r_base * pcs_info.eval;
248 r_base *= r;
249 }
250 inners.push(-sum_evals, open_key.g);
251 let inner = inners.multi_scalar_mul();
252 g1_elems.push(-inner.into());
254 g2_elems.push(open_key.h);
255 Ok(multi_pairing::<E>(&g1_elems, &g2_elems).0 == E::TargetField::one())
257 }
258
259 #[inline]
262 pub(crate) fn compute_challenges<T>(
263 verify_keys: &[&VerifyingKey<E>],
264 public_inputs: &[&[E::ScalarField]],
265 batch_proof: &BatchProof<E>,
266 extra_transcript_init_msg: &Option<Vec<u8>>,
267 ) -> Result<Challenges<E::ScalarField>, PlonkError>
268 where
269 T: PlonkTranscript<F>,
270 {
271 if verify_keys.len() != batch_proof.len() || verify_keys.len() != public_inputs.len() {
272 return Err(ParameterError(format!(
273 "the number of verification keys = {}; the number of instances = {}; the number of public inputs = {}",
274 verify_keys.len(),
275 batch_proof.len(),
276 public_inputs.len(),
277 ))
278 .into());
279 }
280 let mut transcript = T::new(b"PlonkProof");
281 if let Some(msg) = extra_transcript_init_msg {
282 transcript.append_message(EXTRA_TRANSCRIPT_MSG_LABEL, msg)?;
283 }
284 for (&vk, &pi) in verify_keys.iter().zip(public_inputs.iter()) {
285 transcript.append_vk_and_pub_input(vk, pi)?;
286 }
287 for wires_poly_comms in batch_proof.wires_poly_comms_vec.iter() {
288 transcript.append_commitments(b"witness_poly_comms", wires_poly_comms)?;
289 }
290 let tau = if verify_keys.iter().any(|vk| vk.plookup_vk.is_some()) {
291 Some(transcript.get_challenge::<E>(b"tau")?)
292 } else {
293 None
294 };
295
296 for plookup_proof in batch_proof.plookup_proofs_vec.iter() {
297 if let Some(proof_lkup) = plookup_proof.as_ref() {
298 transcript.append_commitments(b"h_poly_comms", &proof_lkup.h_poly_comms)?;
299 }
300 }
301
302 let beta = transcript.get_challenge::<E>(b"beta")?;
303 let gamma = transcript.get_challenge::<E>(b"gamma")?;
304 for prod_perm_poly_comm in batch_proof.prod_perm_poly_comms_vec.iter() {
305 transcript.append_commitment(b"perm_poly_comms", prod_perm_poly_comm)?;
306 }
307 for plookup_proof in batch_proof.plookup_proofs_vec.iter() {
308 if let Some(proof_lkup) = plookup_proof.as_ref() {
309 transcript
310 .append_commitment(b"plookup_poly_comms", &proof_lkup.prod_lookup_poly_comm)?;
311 }
312 }
313
314 let alpha = transcript.get_challenge::<E>(b"alpha")?;
315 transcript.append_commitments(b"quot_poly_comms", &batch_proof.split_quot_poly_comms)?;
316 let zeta = transcript.get_challenge::<E>(b"zeta")?;
317 for poly_evals in batch_proof.poly_evals_vec.iter() {
318 transcript.append_proof_evaluations::<E>(poly_evals)?;
319 }
320 for plookup_proof in batch_proof.plookup_proofs_vec.iter() {
321 if let Some(proof_lkup) = plookup_proof.as_ref() {
322 transcript.append_plookup_evaluations::<E>(&proof_lkup.poly_evals)?;
323 }
324 }
325
326 let v = transcript.get_challenge::<E>(b"v")?;
327 transcript.append_commitment(b"open_proof", &batch_proof.opening_proof)?;
328 transcript.append_commitment(b"shifted_open_proof", &batch_proof.shifted_opening_proof)?;
329 let u = transcript.get_challenge::<E>(b"u")?;
330 Ok(Challenges {
331 tau,
332 alpha,
333 beta,
334 gamma,
335 zeta,
336 v,
337 u,
338 })
339 }
340
341 #[allow(clippy::too_many_arguments)]
358 pub(crate) fn compute_lin_poly_constant_term(
359 &self,
360 challenges: &Challenges<E::ScalarField>,
361 verify_keys: &[&VerifyingKey<E>],
362 public_inputs: &[&[E::ScalarField]],
363 batch_proof: &BatchProof<E>,
364 lagrange_1_eval: &E::ScalarField,
365 lagrange_n_eval: &E::ScalarField,
366 alpha_powers: &[E::ScalarField],
367 alpha_bases: &[E::ScalarField],
368 ) -> Result<E::ScalarField, PlonkError> {
369 if verify_keys.len() != batch_proof.len()
370 || verify_keys.len() != public_inputs.len()
371 || verify_keys.len() != alpha_bases.len()
372 {
373 return Err(ParameterError(format!(
374 "the number of verification keys = {}; the number of instances = {}; the number of public inputs = {}; the number of alpha bases = {}",
375 verify_keys.len(),
376 batch_proof.len(),
377 public_inputs.len(),
378 alpha_bases.len()
379 ))
380 .into());
381 }
382
383 let mut result = E::ScalarField::zero();
384 for (poly_evals, (plookup_proof, (&pi, (&vk, ¤t_alpha_bases)))) in
385 batch_proof.poly_evals_vec.iter().zip(
386 batch_proof.plookup_proofs_vec.iter().zip(
387 public_inputs
388 .iter()
389 .zip(verify_keys.iter().zip(alpha_bases.iter())),
390 ),
391 )
392 {
393 let mut tmp = self.evaluate_pi_poly(pi, &challenges.zeta, vk.is_merged)?
394 - alpha_powers[0] * lagrange_1_eval;
395 let num_wire_types = GATE_WIDTH
396 + 1
397 + match plookup_proof.is_some() {
398 true => 1,
399 false => 0,
400 };
401 let first_w_evals = &poly_evals.wires_evals[..num_wire_types - 1];
402 let last_w_eval = &poly_evals.wires_evals[num_wire_types - 1];
403 let sigma_evals = &poly_evals.wire_sigma_evals[..];
404 tmp -= first_w_evals.iter().zip(sigma_evals.iter()).fold(
405 challenges.alpha * poly_evals.perm_next_eval * (challenges.gamma + last_w_eval),
406 |acc, (w_eval, sigma_eval)| {
407 acc * (challenges.gamma + w_eval + challenges.beta * sigma_eval)
408 },
409 );
410
411 if let Some(proof_lk) = plookup_proof {
412 let gamma_mul_beta_plus_one =
413 challenges.gamma * (E::ScalarField::one() + challenges.beta);
414 let evals = &proof_lk.poly_evals;
415
416 let plookup_constant = *lagrange_n_eval
417 * (evals.h_1_eval - evals.h_2_next_eval - alpha_powers[0])
418 - challenges.alpha * lagrange_1_eval
419 - alpha_powers[1]
420 * (challenges.zeta - self.domain.group_gen_inv)
421 * evals.prod_next_eval
422 * (gamma_mul_beta_plus_one
423 + evals.h_1_eval
424 + challenges.beta * evals.h_1_next_eval)
425 * (gamma_mul_beta_plus_one + challenges.beta * evals.h_2_next_eval);
426 tmp += alpha_powers[1] * plookup_constant;
427 }
428
429 result += current_alpha_bases * tmp;
430 }
431 Ok(result)
432 }
433
434 #[allow(clippy::too_many_arguments)]
439 pub(crate) fn aggregate_poly_commitments(
440 &self,
441 vks: &[&VerifyingKey<E>],
442 challenges: &Challenges<E::ScalarField>,
443 vanish_eval: &E::ScalarField,
444 lagrange_1_eval: &E::ScalarField,
445 lagrange_n_eval: &E::ScalarField,
446 batch_proof: &BatchProof<E>,
447 alpha_powers: &[E::ScalarField],
448 alpha_bases: &[E::ScalarField],
449 ) -> Result<(ScalarsAndBases<E>, Vec<E::ScalarField>), PlonkError> {
450 if vks.len() != batch_proof.len() {
451 return Err(ParameterError(format!(
452 "the number of verification keys {} != the number of instances {}",
453 vks.len(),
454 batch_proof.len()
455 ))
456 .into());
457 }
458
459 let mut scalars_and_bases = self.linearization_scalars_and_bases(
461 vks,
462 challenges,
463 vanish_eval,
464 lagrange_1_eval,
465 lagrange_n_eval,
466 batch_proof,
467 alpha_powers,
468 alpha_bases,
469 )?;
470
471 let mut v_base = challenges.v;
473 let mut uv_base = challenges.u;
475
476 let mut buffer_v_and_uv_basis = vec![];
478
479 for (i, vk) in vks.iter().enumerate() {
480 for &poly_comm in batch_proof.wires_poly_comms_vec[i].iter() {
483 buffer_v_and_uv_basis.push(v_base);
484 Self::add_poly_comm(
485 &mut scalars_and_bases,
486 &mut v_base,
487 poly_comm.0,
488 challenges.v,
489 );
490 }
491 let num_wire_types = batch_proof.wires_poly_comms_vec[i].len();
493 for &poly_comm in vk.sigma_comms.iter().take(num_wire_types - 1) {
494 buffer_v_and_uv_basis.push(v_base);
495 Self::add_poly_comm(
496 &mut scalars_and_bases,
497 &mut v_base,
498 poly_comm.0,
499 challenges.v,
500 );
501 }
502
503 buffer_v_and_uv_basis.push(uv_base);
505 Self::add_poly_comm(
506 &mut scalars_and_bases,
507 &mut uv_base,
508 batch_proof.prod_perm_poly_comms_vec[i].0,
509 challenges.v,
510 );
511
512 if let Some(proof_lkup) = batch_proof.plookup_proofs_vec[i].as_ref() {
514 let plookup_comms = Self::plookup_open_poly_comms(proof_lkup, vk)?;
516 for &comm in plookup_comms.iter() {
517 buffer_v_and_uv_basis.push(v_base);
518 Self::add_poly_comm(&mut scalars_and_bases, &mut v_base, comm.0, challenges.v);
519 }
520
521 let plookup_shifted_comms = Self::plookup_shifted_open_poly_comms(
523 proof_lkup,
524 vk,
525 &batch_proof.wires_poly_comms_vec[i],
526 )?;
527 for &comm in plookup_shifted_comms.iter() {
528 buffer_v_and_uv_basis.push(uv_base);
529 Self::add_poly_comm(&mut scalars_and_bases, &mut uv_base, comm.0, challenges.v);
530 }
531 }
532 }
533
534 Ok((scalars_and_bases, buffer_v_and_uv_basis))
535 }
536
537 #[allow(clippy::too_many_arguments)]
541 pub(crate) fn linearization_scalars_and_bases(
542 &self,
543 vks: &[&VerifyingKey<E>],
544 challenges: &Challenges<E::ScalarField>,
545 vanish_eval: &E::ScalarField,
546 lagrange_1_eval: &E::ScalarField,
547 lagrange_n_eval: &E::ScalarField,
548 batch_proof: &BatchProof<E>,
549 alpha_powers: &[E::ScalarField],
550 alpha_bases: &[E::ScalarField],
551 ) -> Result<ScalarsAndBases<E>, PlonkError> {
552 if vks.len() != batch_proof.len() || alpha_bases.len() != vks.len() {
553 return Err(ParameterError(format!(
554 "the number of verification keys {} != the number of instances {} or alpha bases {}",
555 vks.len(),
556 batch_proof.len(),
557 alpha_bases.len()
558 ))
559 .into());
560 }
561
562 let beta_plus_one = E::ScalarField::one() + challenges.beta;
564 let gamma_mul_beta_plus_one = beta_plus_one * challenges.gamma;
565
566 let mut scalars_and_bases = ScalarsAndBases::new();
567
568 for (i, (vk, ¤t_alpha_bases)) in vks.iter().zip(alpha_bases).enumerate() {
569 let mut coeff = alpha_powers[0] * lagrange_1_eval;
577 let w_evals = &batch_proof.poly_evals_vec[i].wires_evals;
578 coeff += w_evals
579 .iter()
580 .zip(vk.k.iter())
581 .fold(challenges.alpha, |acc, (w_eval, k)| {
582 acc * (challenges.beta * k * challenges.zeta + challenges.gamma + w_eval)
583 });
584 coeff *= current_alpha_bases;
585 scalars_and_bases.push(coeff, batch_proof.prod_perm_poly_comms_vec[i].0);
587
588 let num_wire_types = batch_proof.wires_poly_comms_vec[i].len();
590 let sigma_evals = &batch_proof.poly_evals_vec[i].wire_sigma_evals;
591 let coeff = w_evals
592 .iter()
593 .take(num_wire_types - 1)
594 .zip(sigma_evals.iter())
595 .fold(
596 challenges.alpha
597 * challenges.beta
598 * batch_proof.poly_evals_vec[i].perm_next_eval,
599 |acc, (w_eval, sigma_eval)| {
600 acc * (challenges.beta * sigma_eval + challenges.gamma + w_eval)
601 },
602 )
603 * current_alpha_bases;
604 scalars_and_bases.push(
606 -coeff,
607 vk.sigma_comms.last().ok_or(PlonkError::IndexError)?.0,
608 );
609
610 let mut q_scalars = [E::ScalarField::zero(); 2 * GATE_WIDTH + 5];
615 q_scalars[0] = w_evals[0];
616 q_scalars[1] = w_evals[1];
617 q_scalars[2] = w_evals[2];
618 q_scalars[3] = w_evals[3];
619 q_scalars[4] = w_evals[0] * w_evals[1];
620 q_scalars[5] = w_evals[2] * w_evals[3];
621 q_scalars[6] = w_evals[0].pow([5]);
622 q_scalars[7] = w_evals[1].pow([5]);
623 q_scalars[8] = w_evals[2].pow([5]);
624 q_scalars[9] = w_evals[3].pow([5]);
625 q_scalars[10] = -w_evals[4];
626 q_scalars[11] = E::ScalarField::one();
627 q_scalars[12] = w_evals[0] * w_evals[1] * w_evals[2] * w_evals[3] * w_evals[4];
628 for (&s, poly) in q_scalars.iter().zip(vk.selector_comms.iter()) {
629 scalars_and_bases.push(s * current_alpha_bases, poly.0);
630 }
631
632 if let Some(lookup_proof) = batch_proof.plookup_proofs_vec[i].as_ref() {
634 let lookup_evals = &lookup_proof.poly_evals;
635 let merged_lookup_x = eval_merged_lookup_witness::<E>(
636 challenges.tau.unwrap(),
637 w_evals[5],
638 w_evals[0],
639 w_evals[1],
640 w_evals[2],
641 lookup_evals.q_lookup_eval,
642 lookup_evals.q_dom_sep_eval,
643 );
644 let merged_table_x = eval_merged_table::<E>(
645 challenges.tau.unwrap(),
646 lookup_evals.range_table_eval,
647 lookup_evals.key_table_eval,
648 lookup_evals.q_lookup_eval,
649 w_evals[3],
650 w_evals[4],
651 lookup_evals.table_dom_sep_eval,
652 );
653 let merged_table_xw = eval_merged_table::<E>(
654 challenges.tau.unwrap(),
655 lookup_evals.range_table_next_eval,
656 lookup_evals.key_table_next_eval,
657 lookup_evals.q_lookup_next_eval,
658 lookup_evals.w_3_next_eval,
659 lookup_evals.w_4_next_eval,
660 lookup_evals.table_dom_sep_next_eval,
661 );
662
663 let mut coeff = alpha_powers[2] * lagrange_1_eval
669 + alpha_powers[3] * lagrange_n_eval
670 + alpha_powers[4]
671 * (challenges.zeta - self.domain.group_gen_inv)
672 * beta_plus_one
673 * (challenges.gamma + merged_lookup_x)
674 * (gamma_mul_beta_plus_one
675 + merged_table_x
676 + challenges.beta * merged_table_xw);
677 coeff = current_alpha_bases * coeff;
678 scalars_and_bases.push(coeff, lookup_proof.prod_lookup_poly_comm.0);
679
680 let coeff = current_alpha_bases
685 * alpha_powers[4]
686 * (self.domain.group_gen_inv - challenges.zeta)
687 * lookup_evals.prod_next_eval
688 * (gamma_mul_beta_plus_one
689 + lookup_evals.h_1_eval
690 + challenges.beta * lookup_evals.h_1_next_eval);
691 scalars_and_bases.push(coeff, lookup_proof.h_poly_comms[1].0);
692 }
693 }
694
695 let zeta_to_n_plus_2 =
697 (E::ScalarField::one() + vanish_eval) * challenges.zeta * challenges.zeta;
698 let mut coeff = vanish_eval.neg();
699 scalars_and_bases.push(
700 coeff,
701 batch_proof
702 .split_quot_poly_comms
703 .first()
704 .ok_or(PlonkError::IndexError)?
705 .0,
706 );
707 for poly in batch_proof.split_quot_poly_comms.iter().skip(1) {
708 coeff *= zeta_to_n_plus_2;
709 scalars_and_bases.push(coeff, poly.0);
710 }
711
712 Ok(scalars_and_bases)
713 }
714
715 pub(crate) fn aggregate_evaluations(
719 lin_poly_constant: &E::ScalarField,
720 poly_evals_vec: &[ProofEvaluations<E::ScalarField>],
721 plookup_proofs_vec: &[Option<PlookupProof<E>>],
722 buffer_v_and_uv_basis: &[E::ScalarField],
723 ) -> Result<E::ScalarField, PlonkError> {
724 assert_eq!(poly_evals_vec.len(), plookup_proofs_vec.len());
725
726 let mut result: E::ScalarField = lin_poly_constant.neg();
727 let mut v_and_uv_basis = buffer_v_and_uv_basis.iter();
728
729 for (poly_evals, plookup_proof) in poly_evals_vec.iter().zip(plookup_proofs_vec.iter()) {
730 for &wire_eval in poly_evals.wires_evals.iter() {
732 Self::add_pcs_eval(
733 &mut result,
734 v_and_uv_basis
735 .next()
736 .ok_or(PlonkError::IteratorOutOfRange)?,
737 wire_eval,
738 );
739 }
740 for &sigma_eval in poly_evals.wire_sigma_evals.iter() {
741 Self::add_pcs_eval(
742 &mut result,
743 v_and_uv_basis
744 .next()
745 .ok_or(PlonkError::IteratorOutOfRange)?,
746 sigma_eval,
747 );
748 }
749 Self::add_pcs_eval(
751 &mut result,
752 v_and_uv_basis
753 .next()
754 .ok_or(PlonkError::IteratorOutOfRange)?,
755 poly_evals.perm_next_eval,
756 );
757
758 if let Some(proof_lk) = plookup_proof {
760 let evals = &proof_lk.poly_evals;
761 for &eval in evals.evals_vec().iter() {
763 Self::add_pcs_eval(
764 &mut result,
765 v_and_uv_basis
766 .next()
767 .ok_or(PlonkError::IteratorOutOfRange)?,
768 eval,
769 );
770 }
771 for &next_eval in evals.next_evals_vec().iter() {
773 Self::add_pcs_eval(
774 &mut result,
775 v_and_uv_basis
776 .next()
777 .ok_or(PlonkError::IteratorOutOfRange)?,
778 next_eval,
779 );
780 }
781 }
782 }
783 if v_and_uv_basis.next().is_some() {
785 return Err(PlonkError::IteratorOutOfRange);
786 }
787 Ok(result)
788 }
789}
790
791impl<E, F, P> Verifier<E>
793where
794 E: Pairing<BaseField = F, G1Affine = Affine<P>>,
795 F: RescueParameter + SWToTEConParam,
796 P: SWCurveConfig<BaseField = F>,
797{
798 #[inline]
801 fn add_poly_comm(
802 scalar_and_bases: &mut ScalarsAndBases<E>,
803 random_combiner: &mut E::ScalarField,
804 comm: E::G1Affine,
805 r: E::ScalarField,
806 ) {
807 scalar_and_bases.push(*random_combiner, comm);
808 *random_combiner *= r;
809 }
810
811 #[inline]
814 fn add_pcs_eval(
815 result: &mut E::ScalarField,
816 random_combiner: &E::ScalarField,
817 eval: E::ScalarField,
818 ) {
819 *result += eval * (*random_combiner);
820 }
821
822 #[inline]
824 pub(crate) fn evaluate_vanishing_poly(&self, zeta: &E::ScalarField) -> E::ScalarField {
825 self.domain.evaluate_vanishing_polynomial(*zeta)
826 }
827
828 #[inline]
829 fn plookup_open_poly_comms(
832 proof: &PlookupProof<E>,
833 vk: &VerifyingKey<E>,
834 ) -> Result<Vec<Commitment<E>>, PlonkError> {
835 Ok(vec![
836 vk.plookup_vk.as_ref().unwrap().range_table_comm,
837 vk.plookup_vk.as_ref().unwrap().key_table_comm,
838 proof.h_poly_comms[0],
839 *vk.q_lookup_comm()?,
840 vk.plookup_vk.as_ref().unwrap().table_dom_sep_comm,
841 vk.plookup_vk.as_ref().unwrap().q_dom_sep_comm,
842 ])
843 }
844
845 #[inline]
846 fn plookup_shifted_open_poly_comms(
849 proof: &PlookupProof<E>,
850 vk: &VerifyingKey<E>,
851 wires_poly_comms: &[Commitment<E>],
852 ) -> Result<Vec<Commitment<E>>, PlonkError> {
853 Ok(vec![
854 proof.prod_lookup_poly_comm,
855 vk.plookup_vk.as_ref().unwrap().range_table_comm,
856 vk.plookup_vk.as_ref().unwrap().key_table_comm,
857 proof.h_poly_comms[0],
858 proof.h_poly_comms[1],
859 *vk.q_lookup_comm()?,
860 wires_poly_comms[3],
861 wires_poly_comms[4],
862 vk.plookup_vk.as_ref().unwrap().table_dom_sep_comm,
863 ])
864 }
865
866 pub(crate) fn evaluate_pi_poly(
884 &self,
885 pub_input: &[E::ScalarField],
886 z: &E::ScalarField,
887 circuit_is_merged: bool,
888 ) -> Result<E::ScalarField, PlonkError> {
889 let len = match circuit_is_merged {
890 false => pub_input.len(),
891 true => pub_input.len() / 2,
892 };
893
894 let mut result = E::ScalarField::zero();
895 let lagrange_coeffs = self.domain.lagrange_coeffs_for_range(0..len, *z);
896 for (val, lagrange_i) in pub_input.iter().take(len).zip(lagrange_coeffs) {
897 result += lagrange_i * val;
898 }
899
900 if circuit_is_merged {
901 let n = self.domain.size();
902 let last_l_lagrange_coeff = self.domain.lagrange_coeffs_for_range(n - len..n, *z);
903 for (val, lagrange_n_minus_i) in pub_input
904 .iter()
905 .skip(len)
906 .zip(last_l_lagrange_coeff.iter().rev())
907 {
908 result += *lagrange_n_minus_i * *val;
909 }
910 }
911 Ok(result)
912 }
913}