@ -1,12 +1,42 @@ 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// Implements the scheme described in [HyperNova](https://eprint.iacr.org/2023/573.pdf)
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   crate ::ccs ::CCS ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   ark_ff ::PrimeField ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   ark_crypto_primitives ::sponge ::{ poseidon ::PoseidonConfig ,   Absorb } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   ark_ec ::{ CurveGroup ,   Group } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   ark_ff ::{ BigInteger ,   PrimeField } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   ark_r1cs_std ::{ groups ::GroupOpsBounds ,   prelude ::CurveVar ,   ToConstraintFieldGadget } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   ark_std ::rand ::RngCore ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   ark_std ::{ One ,   Zero } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   core ::marker ::PhantomData ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   std ::fmt ::Debug ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					pub   mod  cccs ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					pub   mod  circuits ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   circuits ::AugmentedFCircuit ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					pub   mod  lcccs ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					pub   mod  nimfs ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					pub   mod  utils ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   cccs ::CCCS ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   lcccs ::LCCCS ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   nimfs ::NIMFS ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   crate ::commitment ::CommitmentScheme ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   crate ::folding ::circuits ::{ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     cyclefold ::{ fold_cyclefold_circuit ,   CycleFoldCircuit } , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     CF2 , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   crate ::folding ::nova ::{ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     get_r1cs_from_cs ,   traits ::NovaR1CS ,   CommittedInstance ,   Witness   as   NovaWitness , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   crate ::frontend ::FCircuit ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   crate ::utils ::get_cm_coordinates ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   crate ::Error ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   crate ::FoldingScheme ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					use   crate ::{ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     ccs ::{ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         r1cs ::{ extract_w_x ,   R1CS } , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         CCS , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     transcript ::{ poseidon ::PoseidonTranscript ,   Transcript } , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// Witness for the LCCCS & CCCS, containing the w vector, and the r_w used as randomness in the Pedersen commitment.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					#[ derive(Debug, Clone, Eq, PartialEq) ] 
  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -25,3 +55,556 @@ impl Witness {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         Witness ::< F > ::new ( vec ! [ F ::zero ( ) ;   ccs . n   -   ccs . l   -   1 ] ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					#[ derive(Debug, Clone) ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					pub   struct  PreprocessorParam < C1 ,   C2 ,   FC ,   CS1 ,   CS2 > 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					where 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     C1 : CurveGroup , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     C2 : CurveGroup , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     FC : FCircuit < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     CS1 : CommitmentScheme < C1 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     CS2 : CommitmentScheme < C2 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   poseidon_config : PoseidonConfig < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   F : FC , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     // cs_params & cf_cs_params: if not provided, will be generated at the preprocess method
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   cs_params : Option < CS1 ::ProverParams > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   cf_cs_params : Option < CS2 ::ProverParams > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					#[ derive(Debug, Clone) ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					pub   struct  ProverParams < C1 ,   C2 ,   CS1 ,   CS2 > 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					where 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     C1 : CurveGroup , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     C2 : CurveGroup , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     CS1 : CommitmentScheme < C1 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     CS2 : CommitmentScheme < C2 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   poseidon_config : PoseidonConfig < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   cs_params : CS1 ::ProverParams , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   cf_cs_params : CS2 ::ProverParams , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     // if ccs is set, it will be used, if not, it will be computed at runtime
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   ccs : Option < CCS < C1 ::ScalarField > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					#[ derive(Debug, Clone) ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					pub   struct  VerifierParams < 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     C1 : CurveGroup , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     C2 : CurveGroup , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     CS1 : CommitmentScheme < C1 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     CS2 : CommitmentScheme < C2 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					>   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   poseidon_config : PoseidonConfig < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   ccs : CCS < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   cf_r1cs : R1CS < C2 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   cs_params : CS1 ::ProverParams , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   cf_cs_params : CS2 ::ProverParams , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// Implements HyperNova+CycleFold's IVC, described in
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// [HyperNova](https://eprint.iacr.org/2023/573.pdf) and
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/// [CycleFold](https://eprint.iacr.org/2023/1192.pdf), following the FoldingScheme trait
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					#[ derive(Clone, Debug) ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					pub   struct  HyperNova < C1 ,   GC1 ,   C2 ,   GC2 ,   FC ,   CS1 ,   CS2 > 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					where 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     C1 : CurveGroup , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     GC1 : CurveVar < C1 ,   CF2 < C1 > >   +   ToConstraintFieldGadget < CF2 < C1 > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     C2 : CurveGroup , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     GC2 : CurveVar < C2 ,   CF2 < C2 > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     FC : FCircuit < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     CS1 : CommitmentScheme < C1 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     CS2 : CommitmentScheme < C2 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     _gc1 : PhantomData < GC1 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     _c2 : PhantomData < C2 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     _gc2 : PhantomData < GC2 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// CCS of the Augmented Function circuit
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   ccs : CCS < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// R1CS of the CycleFold circuit
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   cf_r1cs : R1CS < C2 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   poseidon_config : PoseidonConfig < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// CommitmentScheme::ProverParams over C1
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   cs_params : CS1 ::ProverParams , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// CycleFold CommitmentScheme::ProverParams, over C2
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   cf_cs_params : CS2 ::ProverParams , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// F circuit, the circuit that is being folded
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   F : FC , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   i : C1 ::ScalarField , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// initial state
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   z_0 : Vec < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// current i-th state
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   z_i : Vec < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// HyperNova instances
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   W_i : Witness < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   U_i : LCCCS < C1 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   w_i : Witness < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   u_i : CCCS < C1 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// CycleFold running instance
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   cf_W_i : NovaWitness < C2 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   cf_U_i : CommittedInstance < C2 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					impl < C1 ,   GC1 ,   C2 ,   GC2 ,   FC ,   CS1 ,   CS2 >   FoldingScheme < C1 ,   C2 ,   FC > 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     for   HyperNova < C1 ,   GC1 ,   C2 ,   GC2 ,   FC ,   CS1 ,   CS2 > 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					where 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     C1 : CurveGroup , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     GC1 : CurveVar < C1 ,   CF2 < C1 > >   +   ToConstraintFieldGadget < CF2 < C1 > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     C2 : CurveGroup , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     GC2 : CurveVar < C2 ,   CF2 < C2 > >   +   ToConstraintFieldGadget < CF2 < C2 > > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     FC : FCircuit < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     CS1 : CommitmentScheme < C1 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     CS2 : CommitmentScheme < C2 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     < C1   as   CurveGroup > ::BaseField : PrimeField , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     < C2   as   CurveGroup > ::BaseField : PrimeField , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     < C1   as   Group > ::ScalarField : Absorb , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     < C2   as   Group > ::ScalarField : Absorb , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     C1 : CurveGroup < BaseField   =   C2 ::ScalarField ,   ScalarField   =   C2 ::BaseField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     for < 'a >   & 'a   GC1 : GroupOpsBounds < 'a ,   C1 ,   GC1 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     for < 'a >   & 'a   GC2 : GroupOpsBounds < 'a ,   C2 ,   GC2 > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     type  PreprocessorParam   =   PreprocessorParam < C1 ,   C2 ,   FC ,   CS1 ,   CS2 > ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     type  ProverParam   =   ProverParams < C1 ,   C2 ,   CS1 ,   CS2 > ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     type  VerifierParam   =   VerifierParams < C1 ,   C2 ,   CS1 ,   CS2 > ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     type  RunningInstance   =   ( LCCCS < C1 > ,   Witness < C1 ::ScalarField > ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     type  IncomingInstance   =   ( CCCS < C1 > ,   Witness < C1 ::ScalarField > ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     type  CFInstance   =   ( CommittedInstance < C2 > ,   NovaWitness < C2 > ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     fn  preprocess ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         mut   rng : impl   RngCore , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         prep_param : & Self ::PreprocessorParam , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     )   -> Result < ( Self ::ProverParam ,   Self ::VerifierParam ) ,   Error >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   augmented_f_circuit   =   AugmentedFCircuit ::< C1 ,   C2 ,   GC2 ,   FC > ::empty ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             & prep_param . poseidon_config , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             prep_param . F . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             None , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ccs   =   augmented_f_circuit . ccs . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   cf_circuit   =   CycleFoldCircuit ::< C1 ,   GC1 > ::empty ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   cf_r1cs   =   get_r1cs_from_cs ::< C2 ::ScalarField > ( cf_circuit ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // if cs_params & cf_cs_params exist, use them, if not, generate new ones
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   cs_params : CS1 ::ProverParams ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   cf_cs_params : CS2 ::ProverParams ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         if   prep_param . cs_params . is_some ( )   & &   prep_param . cf_cs_params . is_some ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cs_params   =   prep_param . clone ( ) . cs_params . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_cs_params   =   prep_param . clone ( ) . cf_cs_params . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         }   else   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ( cs_params ,   _ )   =   CS1 ::setup ( & mut   rng ,   ccs . n   -   ccs . l   -   1 ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ( cf_cs_params ,   _ )   =   CS2 ::setup ( & mut   rng ,   cf_r1cs . A . n_cols   -   cf_r1cs . l   -   1 ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   pp   =   ProverParams ::< C1 ,   C2 ,   CS1 ,   CS2 >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             poseidon_config : prep_param . poseidon_config . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cs_params : cs_params . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_cs_params : cf_cs_params . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ccs : Some ( ccs . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   vp   =   VerifierParams ::< C1 ,   C2 ,   CS1 ,   CS2 >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             poseidon_config : prep_param . poseidon_config . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ccs , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_r1cs , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cs_params : cs_params . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_cs_params : cf_cs_params . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         Ok ( ( pp ,   vp ) ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// Initializes the HyperNova+CycleFold's IVC for the given parameters and initial state `z_0`.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     fn  init ( pp : & Self ::ProverParam ,   F : FC ,   z_0 : Vec < C1 ::ScalarField > )   -> Result < Self ,   Error >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // prepare the HyperNova's AugmentedFCircuit and CycleFold's circuits and obtain its CCS
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // and R1CS respectively
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   augmented_f_circuit   =   AugmentedFCircuit ::< C1 ,   C2 ,   GC2 ,   FC > ::empty ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             & pp . poseidon_config , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             F . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             pp . ccs . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ccs   =   augmented_f_circuit . ccs . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   cf_circuit   =   CycleFoldCircuit ::< C1 ,   GC1 > ::empty ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   cf_r1cs   =   get_r1cs_from_cs ::< C2 ::ScalarField > ( cf_circuit ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // setup the dummy instances
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   W_dummy   =   Witness ::< C1 ::ScalarField > ::dummy ( & ccs ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   U_dummy   =   LCCCS ::< C1 > ::dummy ( ccs . l ,   ccs . t ,   ccs . s ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   w_dummy   =   W_dummy . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   u_dummy   =   CCCS ::< C1 > ::dummy ( ccs . l ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( cf_W_dummy ,   cf_U_dummy ) : ( NovaWitness < C2 > ,   CommittedInstance < C2 > )   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_r1cs . dummy_instance ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         u_dummy . x   =   vec ! [ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             U_dummy . hash ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 & pp . poseidon_config , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 C1 ::ScalarField ::zero ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 z_0 . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 z_0 . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ) ? , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_U_dummy . hash_cyclefold ( & pp . poseidon_config ) ? , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         ] ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // W_dummy=W_0 is a 'dummy witness', all zeroes, but with the size corresponding to the
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // R1CS that we're working with.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         Ok ( Self   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             _gc1 : PhantomData , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             _c2 : PhantomData , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             _gc2 : PhantomData , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ccs , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_r1cs , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             poseidon_config : pp . poseidon_config . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cs_params : pp . cs_params . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_cs_params : pp . cf_cs_params . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             F , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             i : C1 ::ScalarField ::zero ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             z_0 : z_0 . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             z_i : z_0 , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             W_i : W_dummy , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             U_i : U_dummy , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             w_i : w_dummy , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             u_i : u_dummy , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // cyclefold running instance
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_W_i : cf_W_dummy , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_U_i : cf_U_dummy , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// Implements IVC.P of HyperNova+CycleFold
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     fn  prove_step ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         & mut   self , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         mut   rng : impl   RngCore , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         external_inputs : Vec < C1 ::ScalarField > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     )   -> Result < ( ) ,   Error >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   augmented_f_circuit : AugmentedFCircuit < C1 ,   C2 ,   GC2 ,   FC > ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         if   self . z_i . len ( )   ! =   self . F . state_len ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             return   Err ( Error ::NotSameLength ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 "z_i.len()" . to_string ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 self . z_i . len ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 "F.state_len()" . to_string ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 self . F . state_len ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ) ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         if   external_inputs . len ( )   ! =   self . F . external_inputs_len ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             return   Err ( Error ::NotSameLength ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 "F.external_inputs_len()" . to_string ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 self . F . external_inputs_len ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 "external_inputs.len()" . to_string ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 external_inputs . len ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ) ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         if   self . i   >   C1 ::ScalarField ::from_le_bytes_mod_order ( & usize ::MAX . to_le_bytes ( ) )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             return   Err ( Error ::MaxStep ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   i_bytes : [ u8 ;   8 ]   =   [ 0 ;   8 ] ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         i_bytes . copy_from_slice ( & self . i . into_bigint ( ) . to_bytes_le ( ) [ . . 8 ] ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   i_usize : usize  =   usize ::from_le_bytes ( i_bytes ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   z_i1   =   self 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             . F 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             . step_native ( i_usize ,   self . z_i . clone ( ) ,   external_inputs . clone ( ) ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // u_{i+1}.x[1] = H(cf_U_{i+1})
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   cf_u_i1_x : C1 ::ScalarField ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( U_i1 ,   W_i1 ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         if   self . i   = =   C1 ::ScalarField ::zero ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             W_i1   =   Witness ::< C1 ::ScalarField > ::dummy ( & self . ccs ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             U_i1   =   LCCCS ::dummy ( self . ccs . l ,   self . ccs . t ,   self . ccs . s ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   u_i1_x   =   U_i1 . hash ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 & self . poseidon_config , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 C1 ::ScalarField ::one ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 self . z_0 . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 z_i1 . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // hash the initial (dummy) CycleFold instance, which is used as the 2nd public
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // input in the AugmentedFCircuit
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_u_i1_x   =   self . cf_U_i . hash_cyclefold ( & self . poseidon_config ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             augmented_f_circuit   =   AugmentedFCircuit ::< C1 ,   C2 ,   GC2 ,   FC >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 _c2 : PhantomData , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 _gc2 : PhantomData , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 poseidon_config : self . poseidon_config . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 ccs : self . ccs . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 i : Some ( C1 ::ScalarField ::zero ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 i_usize : Some ( 0 ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 z_0 : Some ( self . z_0 . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 z_i : Some ( self . z_i . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 external_inputs : Some ( external_inputs . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 u_i_C : Some ( self . u_i . C ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 U_i : Some ( self . U_i . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 U_i1_C : Some ( U_i1 . C ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 F : self . F . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 x : Some ( u_i1_x ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 nimfs_proof : None , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 // cyclefold values
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 cf_u_i_cmW : None , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 cf_U_i : None , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 cf_x : Some ( cf_u_i1_x ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 cf_cmT : None , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         }   else   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   mut   transcript_p : PoseidonTranscript < C1 >   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 PoseidonTranscript ::< C1 > ::new ( & self . poseidon_config ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   ( rho_bits ,   nimfs_proof ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ( nimfs_proof ,   U_i1 ,   W_i1 ,   rho_bits )   =   NIMFS ::< C1 ,   PoseidonTranscript < C1 > > ::prove ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 & mut   transcript_p , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 & self . ccs , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 & [ self . U_i . clone ( ) ] , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 & [ self . u_i . clone ( ) ] , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 & [ self . W_i . clone ( ) ] , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 & [ self . w_i . clone ( ) ] , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // sanity check: check the folded instance relation
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             #[ cfg(test) ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             U_i1 . check_relation ( & self . ccs ,   & W_i1 ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   u_i1_x   =   U_i1 . hash ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 & self . poseidon_config , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 self . i   +   C1 ::ScalarField ::one ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 self . z_0 . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 z_i1 . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   rho_Fq   =   C2 ::ScalarField ::from_bigint ( BigInteger ::from_bits_le ( & rho_bits ) ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 . ok_or ( Error ::OutOfBounds ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // CycleFold part:
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // get the vector used as public inputs 'x' in the CycleFold circuit
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // cyclefold circuit for cmW
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   cf_u_i_x   =   [ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 vec ! [ rho_Fq ] , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 get_cm_coordinates ( & self . U_i . C ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 get_cm_coordinates ( & self . u_i . C ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 get_cm_coordinates ( & U_i1 . C ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             . concat ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   cf_circuit   =   CycleFoldCircuit ::< C1 ,   GC1 >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 _gc : PhantomData , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 r_bits : Some ( rho_bits . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 p1 : Some ( self . U_i . clone ( ) . C ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 p2 : Some ( self . u_i . clone ( ) . C ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 x : Some ( cf_u_i_x . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             let   ( _cf_w_i ,   cf_u_i ,   cf_W_i1 ,   cf_U_i1 ,   cf_cmT ,   _ )   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 fold_cyclefold_circuit ::< C1 ,   GC1 ,   C2 ,   GC2 ,   FC ,   CS1 ,   CS2 > ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     & self . poseidon_config , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     self . cf_r1cs . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     self . cf_cs_params . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     self . cf_W_i . clone ( ) ,   // CycleFold running instance witness
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     self . cf_U_i . clone ( ) ,   // CycleFold running instance
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     cf_u_i_x , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     cf_circuit , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_u_i1_x   =   cf_U_i1 . hash_cyclefold ( & self . poseidon_config ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             augmented_f_circuit   =   AugmentedFCircuit ::< C1 ,   C2 ,   GC2 ,   FC >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 _c2 : PhantomData , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 _gc2 : PhantomData , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 poseidon_config : self . poseidon_config . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 ccs : self . ccs . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 i : Some ( self . i ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 i_usize : Some ( i_usize ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 z_0 : Some ( self . z_0 . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 z_i : Some ( self . z_i . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 external_inputs : Some ( external_inputs ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 u_i_C : Some ( self . u_i . C ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 U_i : Some ( self . U_i . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 U_i1_C : Some ( U_i1 . C ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 F : self . F . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 x : Some ( u_i1_x ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 nimfs_proof : Some ( nimfs_proof ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 // cyclefold values
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 cf_u_i_cmW : Some ( cf_u_i . cmW ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 cf_U_i : Some ( self . cf_U_i . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 cf_x : Some ( cf_u_i1_x ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 cf_cmT : Some ( cf_cmT ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // assign the next round instances
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             self . cf_W_i   =   cf_W_i1 ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             self . cf_U_i   =   cf_U_i1 ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( cs ,   _ )   =   augmented_f_circuit . compute_cs_ccs ( ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         #[ cfg(test) ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         assert ! ( cs . is_satisfied ( ) ? ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( r1cs_w_i1 ,   r1cs_x_i1 )   =   extract_w_x ::< C1 ::ScalarField > ( & cs ) ;   // includes 1 and public inputs
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   r1cs_z   =   [ 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             vec ! [ C1 ::ScalarField ::one ( ) ] , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             r1cs_x_i1 . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             r1cs_w_i1 . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         . concat ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // compute committed instances, w_{i+1}, u_{i+1}, which will be used as w_i, u_i, so we
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // assign them directly to w_i, u_i.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( u_i ,   w_i )   =   self 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             . ccs 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             . to_cccs ::< _ ,   C1 ,   CS1 > ( & mut   rng ,   & self . cs_params ,   & r1cs_z ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         self . u_i   =   u_i . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         self . w_i   =   w_i . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // set values for next iteration
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         self . i   + =   C1 ::ScalarField ::one ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // assign z_{i+1} into z_i
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         self . z_i   =   z_i1 . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         self . U_i   =   U_i1 . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         self . W_i   =   W_i1 . clone ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         #[ cfg(test) ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // check the new LCCCS instance relation
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             self . U_i . check_relation ( & self . ccs ,   & self . W_i ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             // check the new CCCS instance relation
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             self . u_i . check_relation ( & self . ccs ,   & self . w_i ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         Ok ( ( ) ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     fn  state ( & self )   -> Vec < C1 ::ScalarField >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         self . z_i . clone ( ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     fn  instances ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         & self , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     )   -> ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         Self ::RunningInstance , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         Self ::IncomingInstance , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         Self ::CFInstance , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ( self . U_i . clone ( ) ,   self . W_i . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ( self . u_i . clone ( ) ,   self . w_i . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             ( self . cf_U_i . clone ( ) ,   self . cf_W_i . clone ( ) ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// Implements IVC.V of HyperNova+CycleFold. Notice that this method does not include the
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     /// commitments verification, which is done in the Decider.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     fn  verify ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         vp : Self ::VerifierParam , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         z_0 : Vec < C1 ::ScalarField > ,   // initial state
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         z_i : Vec < C1 ::ScalarField > ,   // last state
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         num_steps : C1 ::ScalarField , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         running_instance : Self ::RunningInstance , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         incoming_instance : Self ::IncomingInstance , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         cyclefold_instance : Self ::CFInstance , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     )   -> Result < ( ) ,   Error >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         if   num_steps   = =   C1 ::ScalarField ::zero ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             if   z_0   ! =   z_i   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 return   Err ( Error ::IVCVerificationFail ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             return   Ok ( ( ) ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( U_i ,   W_i )   =   running_instance ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( u_i ,   w_i )   =   incoming_instance ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( cf_U_i ,   cf_W_i )   =   cyclefold_instance ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         if   u_i . x . len ( )   ! =   2   | |   U_i . x . len ( )   ! =   2   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             return   Err ( Error ::IVCVerificationFail ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // check that u_i's output points to the running instance
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // u_i.X[0] == H(i, z_0, z_i, U_i)
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   expected_u_i_x   =   U_i . hash ( & vp . poseidon_config ,   num_steps ,   z_0 ,   z_i . clone ( ) ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         if   expected_u_i_x   ! =   u_i . x [ 0 ]   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             return   Err ( Error ::IVCVerificationFail ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // u_i.X[1] == H(cf_U_i)
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   expected_cf_u_i_x   =   cf_U_i . hash_cyclefold ( & vp . poseidon_config ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         if   expected_cf_u_i_x   ! =   u_i . x [ 1 ]   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             return   Err ( Error ::IVCVerificationFail ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // check LCCCS satisfiability
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         U_i . check_relation ( & vp . ccs ,   & W_i ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // check CCCS satisfiability
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         u_i . check_relation ( & vp . ccs ,   & w_i ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // check CycleFold's RelaxedR1CS satisfiability
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         vp . cf_r1cs 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             . check_relaxed_instance_relation ( & cf_W_i ,   & cf_U_i ) ? ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         Ok ( ( ) ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					#[ cfg(test) ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					mod  tests   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   crate ::commitment ::kzg ::KZG ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   ark_bn254 ::{ constraints ::GVar ,   Bn254 ,   Fr ,   G1Projective   as   Projective } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   ark_grumpkin ::{ constraints ::GVar   as   GVar2 ,   Projective   as   Projective2 } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   super ::* ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   crate ::commitment ::pedersen ::Pedersen ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   crate ::frontend ::tests ::CubicFCircuit ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     use   crate ::transcript ::poseidon ::poseidon_canonical_config ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     #[ test ] 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     pub   fn  test_ivc ( )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   poseidon_config   =   poseidon_canonical_config ::< Fr > ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   F_circuit   =   CubicFCircuit ::< Fr > ::new ( ( ) ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // run the test using Pedersen commitments on both sides of the curve cycle
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         test_ivc_opt ::< Pedersen < Projective > ,   Pedersen < Projective2 > > ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             poseidon_config . clone ( ) , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             F_circuit , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // run the test using KZG for the commitments on the main curve, and Pedersen for the
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         // commitments on the secondary curve
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         test_ivc_opt ::< KZG < Bn254 > ,   Pedersen < Projective2 > > ( poseidon_config ,   F_circuit ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     // test_ivc allowing to choose the CommitmentSchemes
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     fn  test_ivc_opt < CS1 : CommitmentScheme < Projective > ,   CS2 : CommitmentScheme < Projective2 > > ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         poseidon_config : PoseidonConfig < Fr > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         F_circuit : CubicFCircuit < Fr > , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     )   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   rng   =   ark_std ::test_rng ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         type  HN < CS1 ,   CS2 >   = 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             HyperNova < Projective ,   GVar ,   Projective2 ,   GVar2 ,   CubicFCircuit < Fr > ,   CS1 ,   CS2 > ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   prep_param   =   PreprocessorParam ::< Projective ,   Projective2 ,   CubicFCircuit < Fr > ,   CS1 ,   CS2 >   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             poseidon_config , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             F : F_circuit , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cs_params : None , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cf_cs_params : None , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( prover_params ,   verifier_params )   =   HN ::preprocess ( & mut   rng ,   & prep_param ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   z_0   =   vec ! [ Fr ::from ( 3_ u32 ) ] ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   mut   hypernova   =   HN ::init ( & prover_params ,   F_circuit ,   z_0 . clone ( ) ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   num_steps : usize  =   3 ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         for   _   in   0 . . num_steps   { 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             hypernova . prove_step ( & mut   rng ,   vec ! [ ] ) . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         assert_eq ! ( Fr ::from ( num_steps   as   u32 ) ,   hypernova . i ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let   ( running_instance ,   incoming_instance ,   cyclefold_instance )   =   hypernova . instances ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         HN ::verify ( 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             verifier_params , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             z_0 , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             hypernova . z_i , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             hypernova . i , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             running_instance , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             incoming_instance , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             cyclefold_instance , 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         ) 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         . unwrap ( ) ; 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     } 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}