1use crate::proof_system::{structs::VerifyingKey, verifier::Verifier};
9use ark_ec::{
10 pairing::Pairing,
11 short_weierstrass::{Affine, SWCurveConfig as SWParam},
12 twisted_edwards::TECurveConfig as TEParam,
13};
14use ark_ff::{BigInteger, PrimeField};
15use ark_std::{format, string::ToString, vec, vec::Vec};
16use jf_relation::{
17 gadgets::{
18 ecc::{MultiScalarMultiplicationCircuit, PointVariable, SWToTEConParam, TEPoint},
19 ultraplonk::mod_arith::{FpElem, FpElemVar},
20 },
21 Circuit, CircuitError,
22 CircuitError::ParameterError,
23 PlonkCircuit, Variable,
24};
25use jf_rescue::RescueParameter;
26
27mod gadgets;
28mod poly;
29mod structs;
30
31use gadgets::*;
32pub use structs::*;
33
34#[derive(Debug, Clone, Eq, PartialEq)]
35pub struct VerifyingKeyVar<E: Pairing> {
37 pub(crate) sigma_comms: Vec<PointVariable>,
39 pub(crate) selector_comms: Vec<PointVariable>,
41 is_merged: bool,
43
44 domain_size: usize,
46
47 num_inputs: usize,
49
50 k: Vec<E::ScalarField>,
53}
54
55impl<E: Pairing> VerifyingKeyVar<E> {
56 pub fn new<F, P>(
58 circuit: &mut PlonkCircuit<F>,
59 verify_key: &VerifyingKey<E>,
60 ) -> Result<Self, CircuitError>
61 where
62 E: Pairing<BaseField = F, G1Affine = Affine<P>>,
63 F: PrimeField + SWToTEConParam,
64 P: SWParam<BaseField = F>,
65 {
66 let sigma_comms = verify_key
67 .sigma_comms
68 .iter()
69 .map(|comm| circuit.create_point_variable(TEPoint::from(comm.0)))
70 .collect::<Result<Vec<_>, CircuitError>>()?;
71 let selector_comms = verify_key
72 .selector_comms
73 .iter()
74 .map(|comm| circuit.create_point_variable(TEPoint::from(comm.0)))
75 .collect::<Result<Vec<_>, CircuitError>>()?;
76 Ok(Self {
77 sigma_comms,
78 selector_comms,
79 is_merged: verify_key.is_merged,
80 domain_size: verify_key.domain_size,
81 num_inputs: verify_key.num_inputs,
82 k: verify_key.k.clone(),
83 })
84 }
85
86 pub fn to_vec(&self) -> Vec<Variable> {
88 let mut res = vec![];
89 for sigma_comm in self.sigma_comms.iter() {
90 res.push(sigma_comm.get_x());
91 res.push(sigma_comm.get_y());
92 }
93 for selector_comm in self.selector_comms.iter() {
94 res.push(selector_comm.get_x());
95 res.push(selector_comm.get_y());
96 }
97 res
98 }
99
100 pub(crate) fn merge<F, P>(
102 &self,
103 circuit: &mut PlonkCircuit<F>,
104 other: &Self,
105 ) -> Result<Self, CircuitError>
106 where
107 F: PrimeField,
108 P: TEParam<BaseField = F>,
109 {
110 if self.is_merged || other.is_merged {
111 return Err(ParameterError(
112 "cannot merge a merged key again".to_string(),
113 ));
114 }
115 if self.domain_size != other.domain_size {
116 return Err(ParameterError(
117 "cannot merge a verifying key with different domain size".to_string(),
118 ));
119 }
120 if self.num_inputs != other.num_inputs {
121 return Err(ParameterError(
122 "cannot merge a verifying key with different public input length".to_string(),
123 ));
124 }
125 let sigma_comms = self
126 .sigma_comms
127 .iter()
128 .zip(other.sigma_comms.iter())
129 .map(|(com1, com2)| circuit.ecc_add::<P>(com1, com2))
130 .collect::<Result<Vec<_>, CircuitError>>()?;
131 let selector_comms = self
132 .selector_comms
133 .iter()
134 .zip(other.selector_comms.iter())
135 .map(|(com1, com2)| circuit.ecc_add::<P>(com1, com2))
136 .collect::<Result<Vec<_>, CircuitError>>()?;
137 Ok(Self {
138 sigma_comms,
139 selector_comms,
140 is_merged: true,
141 domain_size: self.domain_size,
142 num_inputs: self.num_inputs + other.num_inputs,
143 k: self.k.clone(),
144 })
145 }
146
147 pub fn partial_verify_circuit<F, P>(
152 circuit: &mut PlonkCircuit<F>,
153 beta_g: &TEPoint<F>,
154 generator_g: &TEPoint<F>,
155 merged_vks: &[Self],
156 shared_public_input_vars: &[FpElemVar<F>],
157 batch_proof: &BatchProofVar<F>,
158 blinding_factor: Variable,
159 ) -> Result<(PointVariable, PointVariable), CircuitError>
160 where
161 E: Pairing<BaseField = F, G1Affine = Affine<P>>,
162 F: RescueParameter + SWToTEConParam,
163 P: SWParam<BaseField = F> + TEParam,
164 {
165 if merged_vks.is_empty() {
166 return Err(ParameterError("empty merged verification keys".to_string()));
167 }
168 if merged_vks.len() != batch_proof.len() {
169 return Err(ParameterError(format!(
170 "the number of verification keys {} is different from the number of instances {}.",
171 merged_vks.len(),
172 batch_proof.len()
173 )));
174 }
175
176 let domain_size = merged_vks[0].domain_size;
177 for (i, vk) in merged_vks.iter().skip(1).enumerate() {
178 if vk.domain_size != domain_size {
179 return Err(ParameterError(format!(
180 "the {}-th verification key's domain size {} is different from {}.",
181 i, vk.domain_size, domain_size
182 )));
183 }
184 }
185
186 let range_bit_len = circuit.range_bit_len()?;
187 let m2 = (<E::ScalarField as PrimeField>::MODULUS_BIT_SIZE as usize + 1) >> 1;
188 let m = (m2 - 1) / range_bit_len * range_bit_len + range_bit_len;
190
191 let two_power_m = Some(E::BaseField::from(2u8).pow([m as u64]));
193
194 let fr_modulus_bits = <E::ScalarField as PrimeField>::MODULUS.to_bytes_le();
195 let modulus_in_f = F::from_le_bytes_mod_order(&fr_modulus_bits);
196 let modulus_fp_elem = FpElem::new(&modulus_in_f, m, two_power_m)?;
197
198 let non_native_field_info = NonNativeFieldInfo::<F> {
199 m,
200 two_power_m,
201 modulus_in_f,
202 modulus_fp_elem,
203 };
204
205 let verifier = Verifier::<E>::new(domain_size)?;
206 let domain = verifier.domain;
207
208 let shared_public_input_vars =
210 [shared_public_input_vars, shared_public_input_vars].concat();
211 let public_inputs = vec![&shared_public_input_vars[..]; merged_vks.len()];
212 let merged_vks_ref: Vec<&VerifyingKeyVar<E>> = merged_vks.iter().collect();
213
214 let pcs_info_var = prepare_pcs_info_var(
216 circuit,
217 &merged_vks_ref,
218 &public_inputs,
219 batch_proof,
220 &None,
221 domain,
222 non_native_field_info,
223 )?;
224
225 let generator_g_var = circuit.create_constant_point_variable(*generator_g)?;
230 let bases = [
231 pcs_info_var.opening_proof,
232 pcs_info_var.shifted_opening_proof,
233 generator_g_var,
234 ];
235 let u_var = pcs_info_var.u.convert_to_var(circuit)?;
236 let scalars = [circuit.one(), u_var, blinding_factor];
237
238 let inner1 = MultiScalarMultiplicationCircuit::<_, P>::msm(circuit, &bases, &scalars)?;
239
240 let mut scalars_and_bases = pcs_info_var.comm_scalars_and_bases;
247 scalars_and_bases.scalars.push(pcs_info_var.eval_point);
248 scalars_and_bases.bases.push(pcs_info_var.opening_proof);
249
250 let tmp = circuit.mod_mul(
251 &pcs_info_var.next_eval_point,
252 &pcs_info_var.u,
253 &modulus_fp_elem,
254 )?;
255 scalars_and_bases.scalars.push(tmp);
256 scalars_and_bases
257 .bases
258 .push(pcs_info_var.shifted_opening_proof);
259
260 let generator_g_inv_var = circuit.create_constant_point_variable(generator_g.inverse())?;
261 scalars_and_bases.scalars.push(pcs_info_var.eval);
262 scalars_and_bases.bases.push(generator_g_inv_var);
263
264 let mut scalars = scalars_and_bases
265 .scalars
266 .iter()
267 .map(|x| x.convert_to_var(circuit))
268 .collect::<Result<Vec<_>, _>>()?;
269 scalars.push(blinding_factor);
270
271 let mut bases = scalars_and_bases.bases;
272 let beta_g = circuit.create_constant_point_variable(*beta_g)?;
273 bases.push(beta_g);
274 let inner2 = MultiScalarMultiplicationCircuit::<_, P>::msm(circuit, &bases, &scalars)?;
275
276 Ok((inner1, inner2))
277 }
278}
279
280pub trait BatchableCircuit<F> {
282 fn aggregate_verify_keys<E, P>(
284 &mut self,
285 vk_type_a_vars: &[VerifyingKeyVar<E>],
286 vk_type_b_vars: &[VerifyingKeyVar<E>],
287 ) -> Result<Vec<VerifyingKeyVar<E>>, CircuitError>
288 where
289 E: Pairing,
290 P: TEParam<BaseField = F>;
291}
292
293impl<F> BatchableCircuit<F> for PlonkCircuit<F>
295where
296 F: PrimeField,
297{
298 fn aggregate_verify_keys<E, P>(
299 &mut self,
300 vk_type_a_vars: &[VerifyingKeyVar<E>],
301 vk_type_b_vars: &[VerifyingKeyVar<E>],
302 ) -> Result<Vec<VerifyingKeyVar<E>>, CircuitError>
303 where
304 E: Pairing,
305 P: TEParam<BaseField = F>,
306 {
307 if vk_type_a_vars.len() != vk_type_b_vars.len() {
308 return Err(ParameterError(format!(
309 "the number of type A verification key variables {} is different from the number of type B verification key variables {}.",
310 vk_type_a_vars.len(),
311 vk_type_b_vars.len())
312 ));
313 }
314 vk_type_a_vars
315 .iter()
316 .zip(vk_type_b_vars.iter())
317 .map(|(vk_b, vk_d)| vk_b.merge::<F, P>(self, vk_d))
318 .collect::<Result<Vec<_>, CircuitError>>()
319 }
320}
321
322#[cfg(test)]
323mod test {
324 use super::*;
325 use crate::{
326 proof_system::{
327 batch_arg::{new_mergeable_circuit_for_test, BatchArgument},
328 structs::BatchProof,
329 PlonkKzgSnark, UniversalSNARK,
330 },
331 transcript::{PlonkTranscript, RescueTranscript},
332 };
333 use ark_bls12_377::{g1::Config as Param377, Bls12_377, Fq as Fq377};
334 use ark_ec::{short_weierstrass::SWCurveConfig, twisted_edwards::TECurveConfig, CurveGroup};
335 use ark_std::{vec, UniformRand};
336 use jf_relation::{
337 gadgets::test_utils::test_variable_independence_for_circuit, MergeableCircuitType,
338 };
339 use jf_utils::{field_switching, test_rng};
340
341 const RANGE_BIT_LEN_FOR_TEST: usize = 16;
342
343 #[test]
344 fn test_aggregate_vks() -> Result<(), CircuitError> {
345 test_aggregate_vks_helper::<Bls12_377, Fq377, _, Param377>()
346 }
347
348 fn test_aggregate_vks_helper<E, F, P, Q>() -> Result<(), CircuitError>
349 where
350 E: Pairing<BaseField = F, G1Affine = Affine<P>>,
351 F: PrimeField + RescueParameter + SWToTEConParam,
352 P: SWParam<BaseField = F>,
353 Q: TEParam<BaseField = F>,
354 {
355 let rng = &mut test_rng();
357 let n = 32;
358 let max_degree = n + 2;
359 let srs = PlonkKzgSnark::<E>::universal_setup_for_testing(max_degree, rng)?;
360
361 let mut vks_type_a = vec![];
363 let mut vks_type_b = vec![];
364 let shared_public_input = E::ScalarField::rand(rng);
365 for i in 0..5 {
366 let circuit = new_mergeable_circuit_for_test::<E>(
367 shared_public_input,
368 i,
369 MergeableCircuitType::TypeA,
370 )?;
371 let instance =
372 BatchArgument::setup_instance(&srs, circuit, MergeableCircuitType::TypeA)?;
373 vks_type_a.push(instance.verify_key_ref().clone());
374
375 let circuit = new_mergeable_circuit_for_test::<E>(
376 shared_public_input,
377 i,
378 MergeableCircuitType::TypeB,
379 )?;
380 let instance =
381 BatchArgument::setup_instance(&srs, circuit, MergeableCircuitType::TypeB)?;
382 vks_type_b.push(instance.verify_key_ref().clone());
383 }
384 let vks_type_a_ref: Vec<&VerifyingKey<E>> = vks_type_a.iter().collect();
386 let vks_type_b_ref: Vec<&VerifyingKey<E>> = vks_type_b.iter().collect();
387 let merged_vks = BatchArgument::aggregate_verify_keys(&vks_type_a_ref, &vks_type_b_ref)?;
388
389 let mut circuit: PlonkCircuit<F> = PlonkCircuit::new_ultra_plonk(RANGE_BIT_LEN_FOR_TEST);
391 let vk_type_a_vars = vks_type_a
392 .iter()
393 .map(|vk| VerifyingKeyVar::new(&mut circuit, vk))
394 .collect::<Result<Vec<_>, CircuitError>>()?;
395 for (vk_var, vk) in vk_type_a_vars.iter().zip(vks_type_a.iter()) {
396 check_vk_equality(&circuit, vk_var, vk);
397 }
398
399 let vk_type_b_vars = vks_type_b
400 .iter()
401 .map(|vk| VerifyingKeyVar::new(&mut circuit, vk))
402 .collect::<Result<Vec<_>, CircuitError>>()?;
403 for (vk_var, vk) in vk_type_b_vars.iter().zip(vks_type_b.iter()) {
404 check_vk_equality(&circuit, vk_var, vk);
405 }
406
407 let merged_vk_vars =
408 circuit.aggregate_verify_keys::<E, Q>(&vk_type_a_vars, &vk_type_b_vars)?;
409 for (vk_var, vk) in merged_vk_vars.iter().zip(merged_vks.iter()) {
410 check_vk_equality(&circuit, vk_var, vk);
411 }
412
413 assert!(circuit.check_circuit_satisfiability(&[]).is_ok());
414
415 let tmp = circuit.witness(merged_vk_vars[0].sigma_comms[0].get_x())?;
418 *circuit.witness_mut(merged_vk_vars[0].sigma_comms[0].get_x()) = F::from(0u8);
419 assert!(circuit.check_circuit_satisfiability(&[]).is_err());
420 *circuit.witness_mut(merged_vk_vars[0].sigma_comms[0].get_x()) = tmp;
421
422 assert!(circuit
424 .aggregate_verify_keys::<E, Q>(&vk_type_a_vars[1..], &vk_type_b_vars)
425 .is_err());
426
427 let mut bad_vk_vars = vk_type_a_vars.clone();
429 bad_vk_vars[0].is_merged = true;
430 assert!(circuit
431 .aggregate_verify_keys::<E, Q>(&bad_vk_vars, &vk_type_b_vars)
432 .is_err());
433
434 Ok(())
435 }
436
437 fn check_vk_equality<E, F, P>(
438 circuit: &PlonkCircuit<F>,
439 vk_var: &VerifyingKeyVar<E>,
440 vk: &VerifyingKey<E>,
441 ) where
442 E: Pairing<BaseField = F, G1Affine = Affine<P>>,
443 F: PrimeField + SWToTEConParam,
444 P: SWParam<BaseField = F>,
445 {
446 for (comm_var, comm) in vk_var.sigma_comms.iter().zip(vk.sigma_comms.iter()) {
447 let expected_comm = TEPoint::from(comm.0);
448 assert_eq!(circuit.point_witness(comm_var).unwrap(), expected_comm);
449 }
450 for (comm_var, comm) in vk_var.selector_comms.iter().zip(vk.selector_comms.iter()) {
451 let expected_comm = TEPoint::from(comm.0);
452 assert_eq!(circuit.point_witness(comm_var).unwrap(), expected_comm);
453 }
454 assert_eq!(vk_var.is_merged, vk.is_merged);
455 }
456
457 #[test]
458 fn test_partial_verification_circuit() -> Result<(), CircuitError> {
459 test_partial_verification_circuit_helper::<Bls12_377, _, _, RescueTranscript<_>>()
460 }
461
462 fn test_partial_verification_circuit_helper<E, F, P, T>() -> Result<(), CircuitError>
463 where
464 E: Pairing<BaseField = F, G1Affine = Affine<P>>,
465 F: RescueParameter + SWToTEConParam,
466 P: SWCurveConfig<BaseField = F> + TECurveConfig,
467 T: PlonkTranscript<F>,
468 {
469 let rng = &mut test_rng();
470
471 for log_circuit_size in 8..12 {
472 let n = 1 << log_circuit_size;
478 let max_degree = n + 2;
479 let srs = PlonkKzgSnark::<E>::universal_setup_for_testing(max_degree, rng)?;
480
481 let shared_public_input = E::ScalarField::rand(rng);
483 let mut instances_type_a = vec![];
484 let mut instances_type_b = vec![];
485 for i in 32..50 {
486 let circuit = new_mergeable_circuit_for_test::<E>(
487 shared_public_input,
488 i,
489 MergeableCircuitType::TypeA,
490 )?;
491 let instance =
492 BatchArgument::setup_instance(&srs, circuit, MergeableCircuitType::TypeA)?;
493 instances_type_a.push(instance);
494
495 let circuit = new_mergeable_circuit_for_test::<E>(
496 shared_public_input,
497 i,
498 MergeableCircuitType::TypeB,
499 )?;
500 let instance =
501 BatchArgument::setup_instance(&srs, circuit, MergeableCircuitType::TypeB)?;
502 instances_type_b.push(instance);
503 }
504 let batch_proof =
506 BatchArgument::batch_prove::<_, T>(rng, &instances_type_a, &instances_type_b)?;
507
508 let vks_type_a: Vec<&VerifyingKey<E>> = instances_type_a
510 .iter()
511 .map(|pred| pred.verify_key_ref())
512 .collect();
513 let vks_type_b: Vec<&VerifyingKey<E>> = instances_type_b
514 .iter()
515 .map(|pred| pred.verify_key_ref())
516 .collect();
517 let merged_vks = BatchArgument::aggregate_verify_keys(&vks_type_a, &vks_type_b)?;
518 assert!(BatchArgument::aggregate_verify_keys(&vks_type_a[1..], &vks_type_b).is_err());
520
521 let open_key_ref = &vks_type_a[0].open_key;
523 let beta_g_ref = &srs.powers_of_g[1];
524 let blinding_factor = E::ScalarField::rand(rng);
525 let (inner1, inner2) = BatchArgument::partial_verify::<T>(
526 beta_g_ref,
527 &open_key_ref.g,
528 &merged_vks,
529 &[shared_public_input],
530 &batch_proof,
531 blinding_factor,
532 )?;
533 assert!(BatchArgument::decide(open_key_ref, inner1, inner2)?);
534
535 {
536 let public_inputs = [[field_switching(&shared_public_input)].as_ref()].concat();
540
541 let (mut circuit, partial_verify_points) = build_circuit::<E, F, P>(
542 &shared_public_input,
543 &merged_vks,
544 &batch_proof,
545 beta_g_ref,
546 &open_key_ref.g,
547 &blinding_factor,
548 )?;
549
550 assert!(
551 circuit.check_circuit_satisfiability(&public_inputs).is_ok(),
552 "{:?}",
553 circuit.check_circuit_satisfiability(&public_inputs)
554 );
555 assert_eq!(
556 circuit.point_witness(&partial_verify_points.0)?,
557 TEPoint::<F>::from(inner1.into_affine())
558 );
559 assert_eq!(
560 circuit.point_witness(&partial_verify_points.1)?,
561 TEPoint::<F>::from(inner2.into_affine())
562 );
563
564 let wrong_public_inputs = [[F::rand(rng)].as_ref()].concat();
572 assert!(circuit
573 .check_circuit_satisfiability(&wrong_public_inputs)
574 .is_err(),);
575
576 let wrong_public_inputs =
580 [[field_switching(&shared_public_input); 3].as_ref()].concat();
581 assert!(circuit
582 .check_circuit_satisfiability(&wrong_public_inputs)
583 .is_err(),);
584
585 *circuit.witness_mut(10) = F::from(0u32);
589 assert!(circuit
590 .check_circuit_satisfiability(&public_inputs)
591 .is_err());
592 }
593 {
597 let mut wrong_merge_vks = merged_vks.clone();
600 let tmp = wrong_merge_vks.pop().unwrap();
601 assert!(build_circuit::<E, F, P>(
602 &shared_public_input,
603 &wrong_merge_vks,
604 &batch_proof,
605 beta_g_ref,
606 &open_key_ref.g,
607 &blinding_factor,
608 )
609 .is_err());
610
611 let mut wrong_merge_vks = merged_vks.clone();
614 wrong_merge_vks.push(tmp);
615 assert!(build_circuit::<E, F, P>(
616 &shared_public_input,
617 &wrong_merge_vks,
618 &batch_proof,
619 beta_g_ref,
620 &open_key_ref.g,
621 &blinding_factor,
622 )
623 .is_err());
624 }
625
626 {
630 let public_inputs = [[field_switching(&shared_public_input)].as_ref()].concat();
633 let wrong_shared_public_input = E::ScalarField::rand(rng);
634 let (circuit, partial_verify_points) = build_circuit::<E, F, P>(
635 &wrong_shared_public_input,
636 &merged_vks,
637 &batch_proof,
638 beta_g_ref,
639 &open_key_ref.g,
640 &blinding_factor,
641 )?;
642
643 assert!(
644 circuit
645 .check_circuit_satisfiability(&public_inputs)
646 .is_err(),
647 "{:?}",
648 circuit.check_circuit_satisfiability(public_inputs.as_ref())
649 );
650 assert_ne!(
651 circuit.point_witness(&partial_verify_points.0)?,
652 TEPoint::<F>::from(inner1.into_affine())
653 );
654 assert_ne!(
655 circuit.point_witness(&partial_verify_points.1)?,
656 TEPoint::<F>::from(inner2.into_affine())
657 );
658
659 let wrong_public_inputs =
665 [[field_switching(&wrong_shared_public_input)].as_ref()].concat();
666 assert!(
667 circuit
668 .check_circuit_satisfiability(&wrong_public_inputs)
669 .is_ok(),
670 "{:?}",
671 circuit.check_circuit_satisfiability(wrong_public_inputs.as_ref())
672 );
673 assert_ne!(
674 circuit.point_witness(&partial_verify_points.0)?,
675 TEPoint::<F>::from(inner1.into_affine())
676 );
677 assert_ne!(
678 circuit.point_witness(&partial_verify_points.1)?,
679 TEPoint::<F>::from(inner2.into_affine())
680 );
681 }
682 }
683
684 Ok(())
685 }
686
687 fn build_circuit<E, F, P>(
688 shared_public_input: &E::ScalarField,
689 merged_vks: &[VerifyingKey<E>],
690 batch_proof: &BatchProof<E>,
691 beta_g_ref: &Affine<P>,
692 generator_g: &Affine<P>,
693 blinding_factor: &E::ScalarField,
694 ) -> Result<(PlonkCircuit<F>, (PointVariable, PointVariable)), CircuitError>
695 where
696 E: Pairing<BaseField = F, G1Affine = Affine<P>>,
697 F: RescueParameter + SWToTEConParam,
698 P: SWCurveConfig<BaseField = F> + TECurveConfig,
699 {
700 let mut circuit = PlonkCircuit::<E::BaseField>::new_ultra_plonk(RANGE_BIT_LEN_FOR_TEST);
701
702 let m = 128;
704 let two_power_m = Some(E::BaseField::from(2u8).pow([m as u64]));
705
706 let shared_public_input_var =
708 circuit.create_public_variable(field_switching(shared_public_input))?;
709 let shared_public_input_fp_elem_var =
710 FpElemVar::new_unchecked(&mut circuit, shared_public_input_var, m, two_power_m)?;
711
712 let vk_vars = merged_vks
714 .iter()
715 .map(|x| VerifyingKeyVar::new(&mut circuit, x))
716 .collect::<Result<Vec<_>, _>>()?;
717
718 let batch_proof_vars = (*batch_proof).create_variables(&mut circuit, m, two_power_m)?;
720
721 let beta_g: TEPoint<F> = (*beta_g_ref).into();
722 let generator_g = &(*generator_g).into();
723 let blinding_factor_var = circuit.create_variable(field_switching(blinding_factor))?;
724
725 let partial_verify_points = VerifyingKeyVar::partial_verify_circuit(
726 &mut circuit,
727 &beta_g,
728 generator_g,
729 &vk_vars,
730 &[shared_public_input_fp_elem_var],
731 &batch_proof_vars,
732 blinding_factor_var,
733 )?;
734
735 Ok((circuit, partial_verify_points))
736 }
737
738 #[test]
739 fn test_variable_independence_for_partial_verification_circuit() -> Result<(), CircuitError> {
740 test_variable_independence_for_partial_verification_circuit_helper::<
741 Bls12_377,
742 _,
743 _,
744 RescueTranscript<_>,
745 >()
746 }
747
748 fn test_variable_independence_for_partial_verification_circuit_helper<E, F, P, T>(
749 ) -> Result<(), CircuitError>
750 where
751 E: Pairing<BaseField = F, G1Affine = Affine<P>>,
752 F: RescueParameter + SWToTEConParam,
753 P: SWCurveConfig<BaseField = F> + TECurveConfig,
754 T: PlonkTranscript<F>,
755 {
756 let rng = &mut test_rng();
757 let i = 8;
758 let mut circuits = vec![];
759
760 let n = 1 << i;
762 let max_degree = n + 2;
763 let srs = PlonkKzgSnark::<E>::universal_setup_for_testing(max_degree, rng)?;
764
765 for _ in 0..2 {
766 let shared_public_input = E::ScalarField::rand(rng);
772 let mut instances_type_a = vec![];
773 let mut instances_type_b = vec![];
774
775 let circuit = new_mergeable_circuit_for_test::<E>(
776 shared_public_input,
777 i,
778 MergeableCircuitType::TypeA,
779 )?;
780 let instance =
781 BatchArgument::setup_instance(&srs, circuit, MergeableCircuitType::TypeA)?;
782 instances_type_a.push(instance);
783
784 let circuit = new_mergeable_circuit_for_test::<E>(
785 shared_public_input,
786 i,
787 MergeableCircuitType::TypeB,
788 )?;
789 let instance =
790 BatchArgument::setup_instance(&srs, circuit, MergeableCircuitType::TypeB)?;
791 instances_type_b.push(instance);
792
793 let batch_proof =
795 BatchArgument::batch_prove::<_, T>(rng, &instances_type_a, &instances_type_b)?;
796
797 let vks_type_a: Vec<&VerifyingKey<E>> = instances_type_a
799 .iter()
800 .map(|pred| pred.verify_key_ref())
801 .collect();
802 let vks_type_b: Vec<&VerifyingKey<E>> = instances_type_b
803 .iter()
804 .map(|pred| pred.verify_key_ref())
805 .collect();
806 let merged_vks = BatchArgument::aggregate_verify_keys(&vks_type_a, &vks_type_b)?;
807
808 let open_key_ref = &vks_type_a[0].open_key;
810 let beta_g_ref = &srs.powers_of_g[1];
811 let blinding_factor = E::ScalarField::rand(rng);
812
813 let (mut circuit, _partial_verify_points) = build_circuit::<E, F, P>(
814 &shared_public_input,
815 &merged_vks,
816 &batch_proof,
817 beta_g_ref,
818 &open_key_ref.g,
819 &blinding_factor,
820 )?;
821
822 circuit.finalize_for_arithmetization()?;
823 circuits.push(circuit);
824 }
825
826 test_variable_independence_for_circuit(circuits[0].clone(), circuits[1].clone())?;
827
828 Ok(())
829 }
830}