1use super::{
9 BatchProofVar, ChallengesFpElemVar, NonNativeFieldInfo, ScalarsAndBasesVar, VerifyingKeyVar,
10};
11use crate::errors::PlonkError;
12use ark_ec::pairing::Pairing;
13use ark_ff::PrimeField;
14use ark_poly::{EvaluationDomain, Radix2EvaluationDomain};
15use ark_std::{format, string::ToString, vec, vec::Vec, One};
16use jf_relation::{
17 constants::GATE_WIDTH,
18 gadgets::ultraplonk::mod_arith::{FpElem, FpElemVar},
19 CircuitError,
20 CircuitError::ParameterError,
21 PlonkCircuit,
22};
23use jf_utils::field_switching;
24
25pub(super) fn evaluate_poly_helper<E, F>(
42 circuit: &mut PlonkCircuit<F>,
43 zeta_fp_elem_var: &FpElemVar<F>,
44 domain_size: usize,
45 non_native_field_info: NonNativeFieldInfo<F>,
46) -> Result<[FpElemVar<F>; 3], CircuitError>
47where
48 E: Pairing<BaseField = F>,
49 F: PrimeField,
50{
51 let domain_size_fp_elem = FpElem::new(
53 &F::from(domain_size as u64),
54 non_native_field_info.m,
55 non_native_field_info.two_power_m,
56 )?;
57
58 let zeta = zeta_fp_elem_var.witness(circuit)?;
60 let zeta_fr = field_switching::<_, E::ScalarField>(&zeta);
61
62 let mut ctr = 1;
68 let mut zeta_n_fp_elem_var = *zeta_fp_elem_var;
69 while ctr < domain_size {
70 ctr <<= 1;
71 zeta_n_fp_elem_var = circuit.mod_mul(
72 &zeta_n_fp_elem_var,
73 &zeta_n_fp_elem_var,
74 &non_native_field_info.modulus_fp_elem,
75 )?;
76 }
77
78 let zeta_n = zeta_n_fp_elem_var.witness(circuit)?;
99 let zeta_n_minus_one = field_switching::<_, F>(
100 &(field_switching::<_, E::ScalarField>(&zeta_n) - E::ScalarField::one()),
101 );
102 let zeta_n_minus_one_fp_elem_var = FpElemVar::new_from_field_element(
103 circuit,
104 &zeta_n_minus_one,
105 non_native_field_info.m,
106 non_native_field_info.two_power_m,
107 )?;
108 let one_fp_elem = FpElem::new(
109 &F::one(),
110 non_native_field_info.m,
111 non_native_field_info.two_power_m,
112 )?;
113 let zeta_n_fp_elem_var_rec = circuit.mod_add_constant(
114 &zeta_n_minus_one_fp_elem_var,
115 &one_fp_elem,
116 &non_native_field_info.modulus_fp_elem,
117 )?;
118 zeta_n_fp_elem_var.enforce_equal(circuit, &zeta_n_fp_elem_var_rec)?;
119
120 let zeta_n_minus_one = field_switching::<_, E::ScalarField>(&zeta_n_minus_one);
130 let divisor = E::ScalarField::from(domain_size as u64) * (zeta_fr - E::ScalarField::one());
131 let lagrange_1_eval = zeta_n_minus_one / divisor;
132 let lagrange_1_eval_fp_elem_var = FpElemVar::new_from_field_element(
133 circuit,
134 &field_switching(&lagrange_1_eval),
135 non_native_field_info.m,
136 non_native_field_info.two_power_m,
137 )?;
138
139 let zeta_minus_one_fr = zeta_fr - E::ScalarField::one();
141 let zeta_minus_one_fp_elem_var = FpElemVar::new_from_field_element(
142 circuit,
143 &field_switching(&zeta_minus_one_fr),
144 non_native_field_info.m,
145 non_native_field_info.two_power_m,
146 )?;
147 let zeta_fp_elem_var_rec = circuit.mod_add_constant(
148 &zeta_minus_one_fp_elem_var,
149 &one_fp_elem,
150 &non_native_field_info.modulus_fp_elem,
151 )?;
152 zeta_fp_elem_var.enforce_equal(circuit, &zeta_fp_elem_var_rec)?;
153
154 let mut left = circuit.mod_mul_constant(
156 &lagrange_1_eval_fp_elem_var,
157 &domain_size_fp_elem,
158 &non_native_field_info.modulus_fp_elem,
159 )?;
160 left = circuit.mod_mul(
161 &left,
162 &zeta_minus_one_fp_elem_var,
163 &non_native_field_info.modulus_fp_elem,
164 )?;
165 left.enforce_equal(circuit, &zeta_n_minus_one_fp_elem_var)?;
166
167 Ok([
168 zeta_n_fp_elem_var,
169 zeta_n_minus_one_fp_elem_var,
170 lagrange_1_eval_fp_elem_var,
171 ])
172}
173
174pub(super) fn evaluate_pi_poly_circuit<E, F>(
187 circuit: &mut PlonkCircuit<F>,
188 domain_size: usize,
189 pub_inputs_fp_elem_var: &[FpElemVar<F>],
190 zeta_fp_elem_var: &FpElemVar<F>,
191 vanish_eval_fp_elem_var: &FpElemVar<F>,
192 circuit_is_merged: bool,
193 non_native_field_info: NonNativeFieldInfo<F>,
194) -> Result<FpElemVar<F>, CircuitError>
195where
196 E: Pairing<BaseField = F>,
197 F: PrimeField,
198{
199 if !circuit_is_merged {
201 return Err(CircuitError::ParameterError(
202 "Circuit should already been merged".to_string(),
203 ));
204 }
205 let len = pub_inputs_fp_elem_var.len() >> 1;
206
207 let zeta = field_switching::<_, E::ScalarField>(&zeta_fp_elem_var.witness(circuit)?);
209 let vanish_eval =
210 field_switching::<_, E::ScalarField>(&vanish_eval_fp_elem_var.witness(circuit)?);
211
212 let domain = Radix2EvaluationDomain::<E::ScalarField>::new(domain_size).unwrap();
214 let v_i: Vec<E::ScalarField> = (0..domain_size)
215 .map(|x| domain.element(x) / E::ScalarField::from(domain_size as u64))
216 .collect();
217
218 let mut lagrange_eval_fp_elem_var: Vec<FpElemVar<F>> = Vec::new();
222 let range = (0..len).chain(domain_size - len..domain_size);
223
224 for i in range {
225 let v_i_fp_elem = FpElem::<F>::new(
227 &field_switching(&v_i[i]),
228 non_native_field_info.m,
229 non_native_field_info.two_power_m,
230 )?;
231 let g_i_fp_elem = FpElem::<F>::new(
232 &field_switching(&domain.element(i)),
233 non_native_field_info.m,
234 non_native_field_info.two_power_m,
235 )?;
236 let zeta_minus_gi = zeta - domain.element(i);
237 let eval_i = vanish_eval * v_i[i] / zeta_minus_gi;
238
239 let zeta_minus_gi_elem_var = FpElemVar::new_from_field_element(
241 circuit,
242 &field_switching(&zeta_minus_gi),
243 non_native_field_info.m,
244 non_native_field_info.two_power_m,
245 )?;
246 let zeta_fp_elem_var_rec = circuit.mod_add_constant(
247 &zeta_minus_gi_elem_var,
248 &g_i_fp_elem,
249 &non_native_field_info.modulus_fp_elem,
250 )?;
251 zeta_fp_elem_var.enforce_equal(circuit, &zeta_fp_elem_var_rec)?;
252
253 let eval_i_fp_elem_var = FpElemVar::new_from_field_element(
255 circuit,
256 &field_switching(&eval_i),
257 non_native_field_info.m,
258 non_native_field_info.two_power_m,
259 )?;
260 let left = circuit.mod_mul(
261 &eval_i_fp_elem_var,
262 &zeta_minus_gi_elem_var,
263 &non_native_field_info.modulus_fp_elem,
264 )?;
265 let right = circuit.mod_mul_constant(
266 vanish_eval_fp_elem_var,
267 &v_i_fp_elem,
268 &non_native_field_info.modulus_fp_elem,
269 )?;
270 left.enforce_equal(circuit, &right)?;
271
272 lagrange_eval_fp_elem_var.push(eval_i_fp_elem_var);
274 }
275
276 let mut res_i_fp_elem_var = Vec::new();
279 for i in 0..len {
280 let first_term = circuit.mod_mul(
281 &lagrange_eval_fp_elem_var[i],
282 &pub_inputs_fp_elem_var[i],
283 &non_native_field_info.modulus_fp_elem,
284 )?;
285 let second_term = circuit.mod_mul(
286 &lagrange_eval_fp_elem_var[(len << 1) - i - 1],
287 &pub_inputs_fp_elem_var[len + i],
288 &non_native_field_info.modulus_fp_elem,
289 )?;
290 res_i_fp_elem_var.push(first_term);
291 res_i_fp_elem_var.push(second_term);
292 }
293 let res = circuit.mod_add_vec(&res_i_fp_elem_var, &non_native_field_info.modulus_fp_elem)?;
294
295 Ok(res)
296}
297
298#[allow(clippy::too_many_arguments)]
314pub(super) fn compute_lin_poly_constant_term_circuit<E, F>(
315 circuit: &mut PlonkCircuit<F>,
316 domain_size: usize,
317 challenges: &ChallengesFpElemVar<F>,
318 verify_keys: &[&VerifyingKeyVar<E>],
319 public_inputs: &[&[FpElemVar<F>]],
320 batch_proof: &BatchProofVar<F>,
321 evals: &[FpElemVar<F>; 3],
322 alpha_bases: &[FpElemVar<F>],
323 non_native_field_info: NonNativeFieldInfo<F>,
324) -> Result<FpElemVar<F>, CircuitError>
325where
326 E: Pairing<BaseField = F>,
327 F: PrimeField,
328{
329 if verify_keys.len() != batch_proof.len() || verify_keys.len() != public_inputs.len() {
330 return Err(ParameterError(format!(
331 "the number of verification keys = {}; the number of instances = {}; the number of public inputs = {}",
332 verify_keys.len(),
333 batch_proof.len(),
334 public_inputs.len(),
335 )));
336 }
337
338 let zeta_fp_elem_var = challenges.zeta;
339
340 let mut alpha_bases_elem_var = alpha_bases.iter();
341 let mut r_0_components = Vec::new();
342
343 let pi = public_inputs[0];
345 for &pi_i in public_inputs.iter().skip(1) {
346 if pi != pi_i {
347 Err(PlonkError::PublicInputsDoNotMatch)?;
348 }
349 }
350
351 let pi_fp_elem_var = evaluate_pi_poly_circuit::<E, F>(
353 circuit,
354 domain_size,
355 pi,
356 &zeta_fp_elem_var,
357 &evals[1],
358 true,
359 non_native_field_info,
360 )?;
361 let pi_fr = field_switching::<_, E::ScalarField>(&pi_fp_elem_var.witness(circuit)?);
362
363 let l1_mul_alpha_2_fp_elem_var = circuit.mod_mul(
365 &evals[2],
366 &challenges.alphas[1],
367 &non_native_field_info.modulus_fp_elem,
368 )?;
369
370 let l1_mul_alpha_2_fr =
371 field_switching::<_, E::ScalarField>(&l1_mul_alpha_2_fp_elem_var.witness(circuit)?);
372
373 for poly_evals in batch_proof.poly_evals_vec.iter() {
386 let mut prod = FpElemVar::one(
395 circuit,
396 non_native_field_info.m,
397 non_native_field_info.two_power_m,
398 );
399 for (w_j_i_var, sigma_j_i_var) in poly_evals.wires_evals[..GATE_WIDTH]
400 .iter()
401 .zip(poly_evals.wire_sigma_evals.iter())
402 {
403 let beta_sigma_j_i = circuit.mod_mul(
404 &challenges.beta,
405 sigma_j_i_var,
406 &non_native_field_info.modulus_fp_elem,
407 )?;
408 let sum = circuit.mod_add_vec(
409 &[*w_j_i_var, beta_sigma_j_i, challenges.gamma],
410 &non_native_field_info.modulus_fp_elem,
411 )?;
412 prod = circuit.mod_mul(&prod, &sum, &non_native_field_info.modulus_fp_elem)?;
413 }
414
415 let mut tmp = circuit.mod_add(
417 &poly_evals.wires_evals[GATE_WIDTH],
418 &challenges.gamma,
419 &non_native_field_info.modulus_fp_elem,
420 )?;
421 tmp = circuit.mod_mul(
422 &tmp,
423 &poly_evals.perm_next_eval,
424 &non_native_field_info.modulus_fp_elem,
425 )?;
426
427 tmp = circuit.mod_mul(
431 &tmp,
432 &challenges.alphas[0],
433 &non_native_field_info.modulus_fp_elem,
434 )?;
435 tmp = circuit.mod_mul(&tmp, &prod, &non_native_field_info.modulus_fp_elem)?;
436 let tmp_fr = field_switching::<_, E::ScalarField>(&tmp.witness(circuit)?);
437
438 let r_plonk_j_fr = pi_fr - l1_mul_alpha_2_fr - tmp_fr;
440 let r_plonk_j_fp_elem_var = FpElemVar::new_from_field_element(
441 circuit,
442 &field_switching(&r_plonk_j_fr),
443 non_native_field_info.m,
444 non_native_field_info.two_power_m,
445 )?;
446
447 let mut left = circuit.mod_add(
449 &r_plonk_j_fp_elem_var,
450 &l1_mul_alpha_2_fp_elem_var,
451 &non_native_field_info.modulus_fp_elem,
452 )?;
453 left = circuit.mod_add(&left, &tmp, &non_native_field_info.modulus_fp_elem)?;
454 left.enforce_equal(circuit, &pi_fp_elem_var)?;
455
456 let r_0_component = circuit.mod_mul(
458 alpha_bases_elem_var
459 .next()
460 .ok_or(PlonkError::IteratorOutOfRange)?,
461 &r_plonk_j_fp_elem_var,
462 &non_native_field_info.modulus_fp_elem,
463 )?;
464
465 r_0_components.push(r_0_component);
466 }
467 if alpha_bases_elem_var.next().is_some() {
469 Err(PlonkError::IteratorOutOfRange)?;
470 }
471 let res_elem_var =
476 circuit.mod_add_vec(&r_0_components, &non_native_field_info.modulus_fp_elem)?;
477
478 Ok(res_elem_var)
479}
480
481pub(super) fn linearization_scalars_and_bases_circuit<E, F>(
489 circuit: &mut PlonkCircuit<F>,
490 vks: &[&VerifyingKeyVar<E>],
491 challenges: &ChallengesFpElemVar<F>,
492 poly_evals: &[FpElemVar<F>; 3],
493 batch_proof: &BatchProofVar<F>,
494 alpha_bases: &[FpElemVar<F>],
495 non_native_field_info: NonNativeFieldInfo<F>,
496) -> Result<ScalarsAndBasesVar<F>, CircuitError>
497where
498 E: Pairing<BaseField = F>,
499 F: PrimeField,
500{
501 let beta_times_zeta_fp_elem_var = circuit.mod_mul(
502 &challenges.beta,
503 &challenges.zeta,
504 &non_native_field_info.modulus_fp_elem,
505 )?;
506 let alpha_times_beta_fp_elem_var = circuit.mod_mul(
507 &challenges.alphas[0],
508 &challenges.beta,
509 &non_native_field_info.modulus_fp_elem,
510 )?;
511
512 let alpha_2_mul_l1 = circuit.mod_mul(
513 &challenges.alphas[1],
514 &poly_evals[2],
515 &non_native_field_info.modulus_fp_elem,
516 )?;
517
518 let mut alpha_bases_elem_var = alpha_bases.iter();
519
520 let mut scalars_and_bases = ScalarsAndBasesVar::new();
521 for (i, vk) in vks.iter().enumerate() {
522 let current_alpha_bases = alpha_bases_elem_var
535 .next()
536 .ok_or(PlonkError::IteratorOutOfRange)?;
537
538 let mut coeff_fp_elem_var = alpha_2_mul_l1;
539 let w_evals = &batch_proof.poly_evals_vec[i].wires_evals;
540 let mut prod = challenges.alphas[0];
541 for (&x_bar, k_i) in w_evals.iter().zip(vk.k.iter()) {
542 let beta_k_zeta_fp_elem_var = circuit.mod_mul_constant(
543 &beta_times_zeta_fp_elem_var,
544 &FpElem::new(
545 &field_switching::<_, F>(k_i),
546 non_native_field_info.m,
547 non_native_field_info.two_power_m,
548 )?,
549 &non_native_field_info.modulus_fp_elem,
550 )?;
551
552 let sum = circuit.mod_add_vec(
553 &[beta_k_zeta_fp_elem_var, x_bar, challenges.gamma],
554 &non_native_field_info.modulus_fp_elem,
555 )?;
556 prod = circuit.mod_mul(&prod, &sum, &non_native_field_info.modulus_fp_elem)?;
557 }
558 coeff_fp_elem_var = circuit.mod_add(
559 &coeff_fp_elem_var,
560 &prod,
561 &non_native_field_info.modulus_fp_elem,
562 )?;
563 coeff_fp_elem_var = circuit.mod_mul(
565 &coeff_fp_elem_var,
566 current_alpha_bases,
567 &non_native_field_info.modulus_fp_elem,
568 )?;
569 scalars_and_bases.scalars.push(coeff_fp_elem_var);
571 scalars_and_bases
572 .bases
573 .push(batch_proof.prod_perm_poly_comms_vec[i]);
574
575 let num_wire_types = batch_proof.wires_poly_comms_vec[i].len();
582 let sigma_evals = &batch_proof.poly_evals_vec[i].wire_sigma_evals;
583 let mut coeff_fp_elem_var = circuit.mod_mul(
584 &alpha_times_beta_fp_elem_var,
585 &batch_proof.poly_evals_vec[i].perm_next_eval,
586 &non_native_field_info.modulus_fp_elem,
587 )?;
588
589 for (&x_bar, sigma_i) in w_evals
590 .iter()
591 .take(num_wire_types - 1)
592 .zip(sigma_evals.iter())
593 {
594 let beta_times_s_bar_sigma_1 = circuit.mod_mul(
595 &challenges.beta,
596 sigma_i,
597 &non_native_field_info.modulus_fp_elem,
598 )?;
599 let sum = circuit.mod_add_vec(
600 &[x_bar, challenges.gamma, beta_times_s_bar_sigma_1],
601 &non_native_field_info.modulus_fp_elem,
602 )?;
603
604 coeff_fp_elem_var = circuit.mod_mul(
605 &coeff_fp_elem_var,
606 &sum,
607 &non_native_field_info.modulus_fp_elem,
608 )?;
609 }
610
611 coeff_fp_elem_var = circuit.mod_mul(
613 &coeff_fp_elem_var,
614 current_alpha_bases,
615 &non_native_field_info.modulus_fp_elem,
616 )?;
617
618 scalars_and_bases.scalars.push(coeff_fp_elem_var);
620 let tmp = circuit.inverse_point(vk.sigma_comms.last().ok_or(CircuitError::IndexError)?)?;
621
622 scalars_and_bases.bases.push(tmp);
623
624 let mut q_scalars_fp_elem_vars = vec![w_evals[0], w_evals[1], w_evals[2], w_evals[3]];
631 q_scalars_fp_elem_vars.push(circuit.mod_mul(
633 &w_evals[0],
634 &w_evals[1],
635 &non_native_field_info.modulus_fp_elem,
636 )?);
637 q_scalars_fp_elem_vars.push(circuit.mod_mul(
639 &w_evals[2],
640 &w_evals[3],
641 &non_native_field_info.modulus_fp_elem,
642 )?);
643 q_scalars_fp_elem_vars.push(circuit.non_native_power_5_gen::<E::ScalarField>(&w_evals[0])?);
645 q_scalars_fp_elem_vars.push(circuit.non_native_power_5_gen::<E::ScalarField>(&w_evals[1])?);
647 q_scalars_fp_elem_vars.push(circuit.non_native_power_5_gen::<E::ScalarField>(&w_evals[2])?);
649 q_scalars_fp_elem_vars.push(circuit.non_native_power_5_gen::<E::ScalarField>(&w_evals[3])?);
651 q_scalars_fp_elem_vars.push(w_evals[4]);
654 q_scalars_fp_elem_vars.push(FpElemVar::one(
657 circuit,
658 non_native_field_info.m,
659 non_native_field_info.two_power_m,
660 ));
661 let mut tmp = circuit.mod_mul(
664 &w_evals[0],
665 &w_evals[1],
666 &non_native_field_info.modulus_fp_elem,
667 )?;
668 tmp = circuit.mod_mul(&tmp, &w_evals[2], &non_native_field_info.modulus_fp_elem)?;
669 tmp = circuit.mod_mul(&tmp, &w_evals[3], &non_native_field_info.modulus_fp_elem)?;
670 tmp = circuit.mod_mul(&tmp, &w_evals[4], &non_native_field_info.modulus_fp_elem)?;
671 q_scalars_fp_elem_vars.push(tmp);
672
673 for (i, (s, &poly)) in q_scalars_fp_elem_vars
674 .iter()
675 .zip(vk.selector_comms.iter())
676 .enumerate()
677 {
678 let bases = if i == 10 {
680 circuit.inverse_point(&poly)?
681 } else {
682 poly
683 };
684
685 let tmp = circuit.mod_mul(
686 s,
687 current_alpha_bases,
688 &non_native_field_info.modulus_fp_elem,
689 )?;
690 scalars_and_bases.scalars.push(tmp);
691 scalars_and_bases.bases.push(bases);
692 }
693 }
694
695 if alpha_bases_elem_var.next().is_some() {
697 Err(PlonkError::IteratorOutOfRange)?;
698 }
699 let zeta_square_fp_elem_var = circuit.mod_mul(
703 &challenges.zeta,
704 &challenges.zeta,
705 &non_native_field_info.modulus_fp_elem,
706 )?;
707 let zeta_to_n_plus_2 = circuit.mod_mul(
708 &zeta_square_fp_elem_var,
709 &poly_evals[0],
710 &non_native_field_info.modulus_fp_elem,
711 )?;
712
713 let mut coeff = poly_evals[1];
714 let tmp = circuit.inverse_point(
715 batch_proof
716 .split_quot_poly_comms
717 .first()
718 .ok_or(CircuitError::IndexError)?,
719 )?;
720 scalars_and_bases.scalars.push(poly_evals[1]);
721 scalars_and_bases.bases.push(tmp);
722
723 for &poly in batch_proof.split_quot_poly_comms.iter().skip(1) {
724 coeff = circuit.mod_mul(
725 &coeff,
726 &zeta_to_n_plus_2,
727 &non_native_field_info.modulus_fp_elem,
728 )?;
729 let poly = circuit.inverse_point(&poly)?;
730 scalars_and_bases.scalars.push(coeff);
731 scalars_and_bases.bases.push(poly);
732 }
733
734 Ok(scalars_and_bases)
735}
736
737#[cfg(test)]
738mod test {
739 use super::*;
740 use ark_bls12_377::Bls12_377;
741 use ark_ff::{BigInteger as _, Field};
742 use ark_std::UniformRand;
743 use jf_relation::Circuit;
744 use jf_utils::test_rng;
745
746 const RANGE_BIT_LEN_FOR_TEST: usize = 16;
747
748 #[test]
749 fn test_evaluate_poly() {
750 test_evaluate_poly_helper::<Bls12_377>();
751 }
752
753 fn test_evaluate_poly_helper<E: Pairing>() {
754 let mut rng = test_rng();
755
756 let mut circuit = PlonkCircuit::<E::BaseField>::new_ultra_plonk(RANGE_BIT_LEN_FOR_TEST);
757 let zeta = E::ScalarField::rand(&mut rng);
758 let zeta_var = circuit.create_variable(field_switching(&zeta)).unwrap();
759
760 for domain_size in [64, 128, 256, 512, 1024] {
761 let domain = Radix2EvaluationDomain::<E::ScalarField>::new(domain_size).unwrap();
763 let vanish_eval = domain.evaluate_vanishing_polynomial(zeta);
764 let zeta_n = vanish_eval + E::ScalarField::one();
765 let divisor = E::ScalarField::from(domain_size as u32) * (zeta - E::ScalarField::one());
766 let lagrange_1_eval = vanish_eval / divisor;
767
768 let m = 128;
770 let two_power_m = Some(E::BaseField::from(2u8).pow([m as u64]));
772
773 let fr_modulus_bits = <E::ScalarField as PrimeField>::MODULUS.to_bytes_le();
774 let modulus_in_f = E::BaseField::from_le_bytes_mod_order(&fr_modulus_bits);
775 let modulus_fp_elem = FpElem::new(&modulus_in_f, m, two_power_m).unwrap();
776
777 let non_native_field_info = NonNativeFieldInfo::<E::BaseField> {
778 m,
779 two_power_m,
780 modulus_in_f,
781 modulus_fp_elem,
782 };
783
784 let zeta_fp_elem_var =
785 FpElemVar::new_unchecked(&mut circuit, zeta_var, m, None).unwrap();
786 let eval_results = evaluate_poly_helper::<E, _>(
787 &mut circuit,
788 &zeta_fp_elem_var,
789 domain_size,
790 non_native_field_info,
791 )
792 .unwrap();
793
794 let tmp = eval_results[0].convert_to_var(&mut circuit).unwrap();
796 assert_eq!(
797 field_switching::<_, E::BaseField>(&zeta_n),
798 circuit.witness(tmp).unwrap(),
799 );
800
801 let tmp = eval_results[1].convert_to_var(&mut circuit).unwrap();
802 assert_eq!(
803 field_switching::<_, E::BaseField>(&vanish_eval),
804 circuit.witness(tmp).unwrap(),
805 );
806
807 let tmp = eval_results[2].convert_to_var(&mut circuit).unwrap();
808 assert_eq!(
809 field_switching::<_, E::BaseField>(&lagrange_1_eval),
810 circuit.witness(tmp).unwrap(),
811 );
812 }
813 }
814}