@ -1,286 +1,133 @@ 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					// hypernova nimfs verifier circuit
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					// see section 5 in https://eprint.iacr.org/2023/573.pdf
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   crate ::{ ccs ::CCS ,   folding ::circuits ::utils ::EqEvalGadget } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   ark_ec ::CurveGroup ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// Implementation of [HyperNova](https://eprint.iacr.org/2023/573.pdf) NIMFS verifier circuit
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   ark_ff ::PrimeField ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   ark_r1cs_std ::{ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     alloc ::AllocVar , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     fields ::{ fp ::FpVar ,   FieldVar } , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     ToBitsGadget , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   ark_relations ::r1cs ::{ ConstraintSystemRef ,   SynthesisError } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   ark_std ::Zero ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   std ::marker ::PhantomData ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// Gadget to compute $\sum_{j \in [t]} \gamma^{j} \cdot e_1 \cdot \sigma_j + \gamma^{t+1} \cdot e_2 \cdot \sum_{i=1}^{q} c_i * \prod_{j \in S_i} \theta_j$.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// This is the sum computed by the verifier and laid out in section 5, step 5 of "A multi-folding scheme for CCS".
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					pub   struct  ComputeCFromSigmasAndThetasGadget < C : CurveGroup >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     _c : PhantomData < C > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					impl < C : CurveGroup >   ComputeCFromSigmasAndThetasGadget < C >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// Computes the sum $\sum_{j}^{j + n} \gamma^{j} \cdot eq_eval \cdot \sigma_{j}$, where $n$ is the length of the `sigmas` vector 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// It corresponds to the first term of the sum that $\mathcal{V}$ has to compute at section 5, step 5 of "A multi-folding scheme for CCS". 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// # Arguments 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `sigmas`: vector of  $\sigma_j $ values 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `eq_eval`: the value of $\tilde{eq}(x_j, x^{\prime})$ 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `gamma`: value $\gamma$ 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `j`: the power at which we start to compute $\gamma^{j}$. This is needed in the context of multifolding. 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     ///
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// # Notes 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// In the context of multifolding, `j` corresponds to `ccs.t` in `compute_c_from_sigmas_and_thetas` 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     fn  sum_muls_gamma_pows_eq_sigma ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         gamma : FpVar  < C ::Scalar Field > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         eq_eval : FpVar < C ::ScalarField  > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					          sigmas : Vec < FpVar < C ::ScalarField > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         j : FpVar < C ::ScalarField  > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     )   -> Result < FpVar < C ::Scalar Field > ,   SynthesisError >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   result   =   FpVar ::< C ::ScalarField > ::zero ( ) ;  
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   gamma_pow   =   gamma . pow_le ( & j . to_bits_le ( ) ? ) ? ;  
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   sigma   in   sigmas   {  
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             result   + =   gamma_pow . clone ( )   *   eq_eval . clone ( )   *   sigma ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             gamma_pow   * =   gamma . clone  ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         }  
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         Ok ( result ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   crate ::ccs ::CCS ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   crate ::folding ::circuits ::utils ::EqEvalGadget ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// computes c from the step 5 in section 5 of HyperNova, adapted to multiple LCCCS & CCCS
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// instances:
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// $$
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// c = \sum_{i \in [\mu]} \left(\sum_{j \in [t]} \gamma^{i \cdot t + j} \cdot e_i \cdot \sigma_{i,j} \right)
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// + \sum_{k \in [\nu]} \gamma^{\mu \cdot t+k} \cdot e_k \cdot \left( \sum_{i=1}^q c_i \cdot \prod_{j \in S_i} 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// \theta_{k,j} \right) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// $$ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					#[ allow(dead_code) ]   // TMP while the other circuits are not ready 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					#[ allow(clippy::too_many_arguments) ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					fn  compute_c_gadget < F : PrimeField > ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     cs : ConstraintSystemRef < F > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     ccs : & CCS < F > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     vec_ sigmas : Vec < Vec < FpVar < F > > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     vec_thetas : Vec < Vec < FpVar < F > > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     gamma : FpVar < F > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     beta : Vec < FpVar < F > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     vec_r_x : Vec < Vec < FpVar < F > > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     vec_r_x_prime : Vec < FpVar < F > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					)   -> Result < FpVar < F > ,   SynthesisError >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     let   mut   e_lcccs   =   Vec ::new ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     for   r_x   in   vec_r_x . iter ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         e_lcccs . push ( EqEvalGadget ::eq_eval ( r_x ,   & vec_r_x_prime ) ? ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// Computes $\sum_{i=1}^{q} c_i * \prod_{j \in S_i} theta_j$
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     ///
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// # Arguments
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `c_i`: vector of $c_i$ values
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `thetas`: vector of pre-processed $\thetas[j]$ values corresponding to a particular `ccs.S[i]`
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     ///
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// # Notes
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// This is a part of the second term of the sum that $\mathcal{V}$ has to compute at section 5, step 5 of "A multi-folding scheme for CCS".
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// The first term is computed by `SumMulsGammaPowsEqSigmaGadget::sum_muls_gamma_pows_eq_sigma`.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// This is a doct product between a vector of c_i values and a vector of pre-processed $\theta_j$ values, where $j$ is a value from $S_i$.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// Hence, this requires some pre-processing of the $\theta_j$ values, before running this gadget.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     fn  sum_ci_mul_prod_thetaj ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         c_i : Vec < FpVar < C ::ScalarField > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         thetas : Vec < Vec < FpVar < C ::ScalarField > > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     )   -> Result < FpVar < C ::ScalarField > ,   SynthesisError >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   result   =   FpVar ::< C ::ScalarField > ::zero ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   ( i ,   c_i )   in   c_i . iter ( ) . enumerate ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   prod   =   & thetas [ i ] . iter ( ) . fold ( FpVar ::one ( ) ,   | acc ,   e |   acc   *   e ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             result   + =   c_i   *   prod ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     let   mut   c   =   FpVar ::< F > ::zero ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     let   mut   current_gamma   =   FpVar ::< F > ::one ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     for   i   in   0 . . vec_sigmas . len ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   j   in   0 . . ccs . t   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             c   + =   current_gamma . clone ( )   *   e_lcccs [ i ] . clone ( )   *   vec_sigmas [ i ] [ j ] . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             current_gamma   * =   gamma . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         Ok ( result ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// Computes the sum that the verifier has to compute at section 5, step 5 of "A multi-folding scheme for CCS".
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     ///
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// # Arguments
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `cs`: constraint system
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `ccs`: the CCS instance
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `vec_sigmas`: vector of $\sigma_j$ values
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `vec_thetas`: vector of $\theta_j$ values
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `gamma`: value $\gamma$
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `beta`: vector of $\beta_j$ values
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `vec_r_x`: vector of $r_{x_j}$ values
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// - `vec_r_x_prime`: vector of $r_{x_j}^{\prime}$ values
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     ///
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// # Notes
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// Arguments to this function are *almost* the same as the arguments to `compute_c_from_sigmas_and_thetas` in `utils.rs`.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     #[ allow(clippy::too_many_arguments) ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   fn  compute_c_from_sigmas_and_thetas ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         cs : ConstraintSystemRef < C ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         ccs : & CCS < C > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         vec_sigmas : Vec < Vec < FpVar < C ::ScalarField > > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         vec_thetas : Vec < Vec < FpVar < C ::ScalarField > > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         gamma : FpVar < C ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         beta : Vec < FpVar < C ::ScalarField > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         vec_r_x : Vec < Vec < FpVar < C ::ScalarField > > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         vec_r_x_prime : Vec < FpVar < C ::ScalarField > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     )   -> Result < FpVar < C ::ScalarField > ,   SynthesisError >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   c   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             FpVar ::< C ::ScalarField > ::new_witness ( cs . clone ( ) ,   | |   Ok ( C ::ScalarField ::zero ( ) ) ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   t   =   FpVar ::< C ::ScalarField > ::new_witness ( cs . clone ( ) ,   | |   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             Ok ( C ::ScalarField ::from ( ccs . t   as   u64 ) ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   e_lcccs   =   Vec ::new ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   r_x   in   vec_r_x . iter ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   e_1   =   EqEvalGadget ::eq_eval ( r_x . to_vec ( ) ,   vec_r_x_prime . to_vec ( ) ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             e_lcccs . push ( e_1 ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   ( i ,   sigmas )   in   vec_sigmas . iter ( ) . enumerate ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   i_var   =   FpVar ::< C ::ScalarField > ::new_witness ( cs . clone ( ) ,   | |   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 Ok ( C ::ScalarField ::from ( i   as   u64 ) ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             } ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   pow   =   i_var   *   t . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             c   + =   Self ::sum_muls_gamma_pows_eq_sigma ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 gamma . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 e_lcccs [ i ] . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 sigmas . to_vec ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 pow , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mu   =   FpVar ::< C ::ScalarField > ::new_witness ( cs . clone ( ) ,   | |   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             Ok ( C ::ScalarField ::from ( vec_sigmas . len ( )   as   u64 ) ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   e_2   =   EqEvalGadget ::eq_eval ( beta ,   vec_r_x_prime ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   ( k ,   thetas )   in   vec_thetas . iter ( ) . enumerate ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // get prepared thetas. only step different from original `compute_c_from_sigmas_and_thetas`
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   mut   prepared_thetas   =   Vec ::new ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             for   i   in   0 . . ccs . q   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 let   prepared : Vec < FpVar < C ::ScalarField > >   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     ccs . S [ i ] . iter ( ) . map ( | j |   thetas [ * j ] . clone ( ) ) . collect ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 prepared_thetas . push ( prepared . to_vec ( ) ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     let   ccs_c   =   Vec ::< FpVar < F > > ::new_constant ( cs . clone ( ) ,   ccs . c . clone ( ) ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     let   e_k   =   EqEvalGadget ::eq_eval ( & beta ,   & vec_r_x_prime ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     #[ allow(clippy::needless_range_loop) ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     for   k   in   0 . . vec_thetas . len ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   sum   =   FpVar ::< F > ::zero ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   i   in   0 . . ccs . q   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   mut   prod   =   FpVar ::< F > ::one ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             for   j   in   ccs . S [ i ] . clone ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 prod   * =   vec_thetas [ k ] [ j ] . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   c_i   =   Vec ::< FpVar < C ::ScalarField > > ::new_witness ( cs . clone ( ) ,   | |   Ok ( ccs . c . clone ( ) ) ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   lhs   =   Self ::sum_ci_mul_prod_thetaj ( c_i . clone ( ) ,   prepared_thetas . clone ( ) ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // compute gamma^(t+1)
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   pow   =   mu . clone ( )   *   t . clone ( ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 +   FpVar ::< C ::ScalarField > ::new_witness ( cs . clone ( ) ,   | |   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     Ok ( C ::ScalarField ::from ( k   as   u64 ) ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 } ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   gamma_t1   =   gamma . pow_le ( & pow . to_bits_le ( ) ? ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             c   + =   gamma_t1 . clone ( )   *   e_2 . clone ( )   *   lhs . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             sum   + =   ccs_c [ i ] . clone ( )   *   prod ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         Ok ( c ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         c   + =   current_gamma . clone ( )   *   e_k . clone ( )   *   sum ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         current_gamma   * =   gamma . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     Ok ( c ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					#[ cfg(test) ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					mod  tests   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   super ::ComputeCFromSigmasAndThetasGadget ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   ark_pallas ::{ Fr ,   Projective } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   ark_r1cs_std ::{ alloc ::AllocVar ,   fields ::fp ::FpVar ,   R1CSVar } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   ark_relations ::r1cs ::ConstraintSystem ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   ark_std ::{ test_rng ,   UniformRand } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   super ::* ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   crate ::{ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         ccs ::{ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             tests ::{ get_test_ccs ,   get_test_z } , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             CCS , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         commitment ::{ pedersen ::Pedersen ,   CommitmentScheme } , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         folding ::hypernova ::utils ::{ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             compute_c_from_sigmas_and_thetas ,   compute_sigmas_and_thetas ,   sum_ci_mul_prod_thetaj , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             sum_muls_gamma_pows_eq_sigma , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         utils ::virtual_polynomial ::eq_eval , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         folding ::hypernova ::utils ::{ compute_c ,   compute_sigmas_and_thetas } , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   ark_pallas ::{ Fr ,   Projective } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   ark_r1cs_std ::{ alloc ::AllocVar ,   fields ::fp ::FpVar ,   R1CSVar } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   ark_relations ::r1cs ::ConstraintSystem ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   ark_std ::{ test_rng ,   UniformRand } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     #[ test ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   fn  test_sum_muls_gamma_pow_eq_sigma_gadget ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   rng   =   test_rng ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ccs : CCS < Projective >   =   get_test_ccs ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   z1   =   get_test_z ( 3 ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   z2   =   get_test_z ( 4 ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   gamma : Fr   =   Fr ::rand ( & mut   rng ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   r_x_prime : Vec < Fr >   =   ( 0 . . ccs . s ) . map ( | _ |   Fr ::rand ( & mut   rng ) ) . collect ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // Initialize a multifolding object
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( pedersen_params ,   _ )   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             Pedersen ::< Projective > ::setup ( & mut   rng ,   ccs . n   -   ccs . l   -   1 ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( lcccs_instance ,   _ )   =   ccs . to_lcccs ( & mut   rng ,   & pedersen_params ,   & z1 ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   sigmas_thetas   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             compute_sigmas_and_thetas ( & ccs ,   & [ z1 . clone ( ) ] ,   & [ z2 . clone ( ) ] ,   & r_x_prime ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   e_lcccs   =   Vec ::new ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   r_x   in   & vec ! [ lcccs_instance . r_x ]   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             e_lcccs . push ( eq_eval ( r_x ,   & r_x_prime ) . unwrap ( ) ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   fn  test_compute_c_gadget ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // number of LCCCS & CCCS instances to fold in a single step
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mu   =   32 ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   nu   =   42 ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   z_lcccs   =   Vec ::new ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   i   in   0 . . mu   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   z   =   get_test_z ( i   +   3 ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             z_lcccs . push ( z ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // Initialize cs and gamma
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   cs   =   ConstraintSystem ::< Fr > ::new_ref ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   gamma_var   =   FpVar ::< Fr > ::new_witness ( cs . clone ( ) ,   | |   Ok ( gamma ) ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   ( i ,   sigmas )   in   sigmas_thetas . 0. iter ( ) . enumerate ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   expected   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 sum_muls_gamma_pows_eq_sigma ( gamma ,   e_lcccs [ i ] ,   sigmas ,   ( i   *   ccs . t )   as   u64 ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   sigmas_var   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 Vec ::< FpVar < Fr > > ::new_witness ( cs . clone ( ) ,   | |   Ok ( sigmas . clone ( ) ) ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   eq_var   =   FpVar ::< Fr > ::new_witness ( cs . clone ( ) ,   | |   Ok ( e_lcccs [ i ] ) ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   pow   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 FpVar ::< Fr > ::new_witness ( cs . clone ( ) ,   | |   Ok ( Fr ::from ( ( i   *   ccs . t )   as   u64 ) ) ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   computed   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 ComputeCFromSigmasAndThetasGadget ::< Projective > ::sum_muls_gamma_pows_eq_sigma ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     gamma_var . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     eq_var , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     sigmas_var , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     pow , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             assert_eq ! ( expected ,   computed . value ( ) . unwrap ( ) ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   z_cccs   =   Vec ::new ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   i   in   0 . . nu   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   z   =   get_test_z ( i   +   3 ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             z_cccs . push ( z ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     #[ test ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   fn  test_sum_ci_mul_prod_thetaj_gadget ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   rng   =   test_rng ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ccs : CCS < Projective >   =   get_test_ccs ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   z1   =   get_test_z ( 3 ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   z2   =   get_test_z ( 4 ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ccs : CCS < Fr >   =   get_test_ccs ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   rng   =   test_rng ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   gamma : Fr   =   Fr ::rand ( & mut   rng ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   beta : Vec < Fr >   =   ( 0 . . ccs . s ) . map ( | _ |   Fr ::rand ( & mut   rng ) ) . collect ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   r_x_prime : Vec < Fr >   =   ( 0 . . ccs . s ) . map ( | _ |   Fr ::rand ( & mut   rng ) ) . collect ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // Initialize a multifolding object
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( pedersen_params ,   _ )   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             Pedersen ::< Projective > ::setup ( & mut   rng ,   ccs . n   -   ccs . l   -   1 ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( lcccs_instance ,   _ )   =   ccs . to_lcccs ( & mut   rng ,   & pedersen_params ,   & z1 ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   sigmas_thetas   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             compute_sigmas_and_thetas ( & ccs ,   & [ z1 . clone ( ) ] ,   & [ z2 . clone ( ) ] ,   & r_x_prime ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   e_lcccs   =   Vec ::new ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   r_x   in   & vec ! [ lcccs_instance . r_x ]   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             e_lcccs . push ( eq_eval ( r_x ,   & r_x_prime ) . unwrap ( ) ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // Create the LCCCS instances out of z_lcccs
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   lcccs_instances   =   Vec ::new ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   z_i   in   z_lcccs . iter ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   ( inst ,   _ )   =   ccs . to_lcccs ( & mut   rng ,   & pedersen_params ,   z_i ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             lcccs_instances . push ( inst ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // Initialize cs
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   cs   =   ConstraintSystem ::< Fr > ::new_ref ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   vec_thetas   =   sigmas_thetas . 1 ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   thetas   in   vec_thetas . iter ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // sum c_i * prod theta_j
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   expected   =   sum_ci_mul_prod_thetaj ( & ccs ,   thetas ) ;   // from `compute_c_from_sigmas_and_thetas`
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   mut   prepared_thetas   =   Vec ::new ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             for   i   in   0 . . ccs . q   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 let   prepared : Vec < Fr >   =   ccs . S [ i ] . iter ( ) . map ( | j |   thetas [ * j ] ) . collect ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 prepared_thetas 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     . push ( Vec ::< FpVar < Fr > > ::new_witness ( cs . clone ( ) ,   | |   Ok ( prepared ) ) . unwrap ( ) ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   computed   =   ComputeCFromSigmasAndThetasGadget ::< Projective > ::sum_ci_mul_prod_thetaj ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 Vec ::< FpVar < Fr > > ::new_witness ( cs . clone ( ) ,   | |   Ok ( ccs . c . clone ( ) ) ) . unwrap ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 prepared_thetas , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             assert_eq ! ( expected ,   computed . value ( ) . unwrap ( ) ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // Create the CCCS instance out of z_cccs
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   cccs_instances   =   Vec ::new ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   z_i   in   z_cccs . iter ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   ( inst ,   _ )   =   ccs . to_cccs ( & mut   rng ,   & pedersen_params ,   z_i ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cccs_instances . push ( inst ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     #[ test ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   fn  test_compute_c_from_sigmas_and_thetas_gadget ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ccs : CCS < Projective >   =   get_test_ccs ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   z1   =   get_test_z ( 3 ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   z2   =   get_test_z ( 4 ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   rng   =   test_rng ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   gamma : Fr   =   Fr ::rand ( & mut   rng ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   beta : Vec < Fr >   =   ( 0 . . ccs . s ) . map ( | _ |   Fr ::rand ( & mut   rng ) ) . collect ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   r_x_prime : Vec < Fr >   =   ( 0 . . ccs . s ) . map ( | _ |   Fr ::rand ( & mut   rng ) ) . collect ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // Initialize a multifolding object
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( pedersen_params ,   _ )   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             Pedersen ::< Projective > ::setup ( & mut   rng ,   ccs . n   -   ccs . l   -   1 ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( lcccs_instance ,   _ )   =   ccs . to_lcccs ( & mut   rng ,   & pedersen_params ,   & z1 ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   sigmas_thetas   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             compute_sigmas_and_thetas ( & ccs ,   & [ z1 . clone ( ) ] ,   & [ z2 . clone ( ) ] ,   & r_x_prime ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   sigmas_thetas   =   compute_sigmas_and_thetas ( & ccs ,   & z_lcccs ,   & z_cccs ,   & r_x_prime ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   expected_c   =   compute_c_from_sigmas_and_thetas  ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   expected_c   =   compute_c ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             & ccs , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             & sigmas_thetas , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             gamma , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             & beta , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             & vec ! [ lcccs_instance . r_x . clone ( ) ] , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             & lcccs_instances 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 . iter ( ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 . map ( | lcccs |   lcccs . r_x . clone ( ) ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 . collect ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             & r_x_prime , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -295,17 +142,18 @@ mod tests { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             vec_thetas 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 . push ( Vec ::< FpVar < Fr > > ::new_witness ( cs . clone ( ) ,   | |   Ok ( thetas . clone ( ) ) ) . unwrap ( ) ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   vec_r_x   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             vec ! [ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 Vec ::< FpVar < Fr > > ::new_witness ( cs . clone ( ) ,   | |   Ok ( lcccs_instance . r_x . clone ( ) ) ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     . unwrap ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ] ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   vec_r_x : Vec < Vec < FpVar < Fr > > >   =   lcccs_instances 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             . iter ( ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             . map ( | lcccs |   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 Vec ::< FpVar < Fr > > ::new_witness ( cs . clone ( ) ,   | |   Ok ( lcccs . r_x . clone ( ) ) ) . unwrap ( ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             } ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             . collect ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   vec_r_x_prime   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             Vec ::< FpVar < Fr > > ::new_witness ( cs . clone ( ) ,   | |   Ok ( r_x_prime . clone ( ) ) ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   gamma_var   =   FpVar ::< Fr > ::new_witness ( cs . clone ( ) ,   | |   Ok ( gamma ) ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   beta_var   =   Vec ::< FpVar < Fr > > ::new_witness ( cs . clone ( ) ,   | |   Ok ( beta . clone ( ) ) ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   computed_c   =   ComputeCFromSigmasAndThetasGadget ::compute_c_from_sigmas_and_thetas ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cs , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   computed_c   =   compute_c_gadget ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cs . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             & ccs , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             vec_sigmas , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             vec_thetas ,