@ -2,17 +2,16 @@ use ark_crypto_primitives::sponge::Absorb;
use ark_ec ::{ CurveGroup , Group } ;
use ark_ec ::{ CurveGroup , Group } ;
use ark_ff ::fields ::PrimeField ;
use ark_ff ::fields ::PrimeField ;
use ark_std ::log2 ;
use ark_std ::log2 ;
use ark_std ::{ cfg_into_iter , One , Zero } ;
use ark_std ::{ cfg_into_iter , Zero } ;
use std ::marker ::PhantomData ;
use std ::marker ::PhantomData ;
use std ::ops ::{ Add , Mul } ;
use std ::ops ::Add ;
use ark_ff ::{ batch_inversion , FftField } ;
use ark_poly ::{
use ark_poly ::{
univariate ::{ DensePolynomial , SparsePolynomial } ,
univariate ::{ DensePolynomial , SparsePolynomial } ,
DenseUVPolynomial , EvaluationDomain , Evaluations , GeneralEvaluationDomain , Polynomial ,
DenseUVPolynomial , EvaluationDomain , Evaluations , GeneralEvaluationDomain , Polynomial ,
} ;
} ;
use crate ::pedersen ::{ Commitment , Params as PedersenParams , Pedersen , Proof as PedersenProof } ;
use crate ::pedersen ::Commitment ;
use crate ::transcript ::Transcript ;
use crate ::transcript ::Transcript ;
use crate ::utils ::* ;
use crate ::utils ::* ;
@ -40,8 +39,7 @@ where
{
{
// WIP naming of functions
// WIP naming of functions
pub fn prover (
pub fn prover (
tr : & mut Transcript < C ::ScalarField , C > ,
pedersen_params : & PedersenParams < C > ,
transcript : & mut Transcript < C ::ScalarField , C > ,
r1cs : & R1CS < C ::ScalarField > ,
r1cs : & R1CS < C ::ScalarField > ,
// running instance
// running instance
instance : CommittedInstance < C > ,
instance : CommittedInstance < C > ,
@ -57,13 +55,14 @@ where
) {
) {
let t = instance . betas . len ( ) ;
let t = instance . betas . len ( ) ;
let n = r1cs . A [ 0 ] . len ( ) ;
let n = r1cs . A [ 0 ] . len ( ) ;
assert_eq ! ( w . w . len ( ) , n ) ;
assert_eq ! ( log2 ( n ) as usize , t ) ;
// TODO initialize transcript
// TODO initialize transcript
let delta = tr . get_challenge ( ) ;
let delta = transcript . get_challenge ( ) ;
let deltas = powers_of_beta ( delta , t ) ;
let deltas = powers_of_beta ( delta , t ) ;
let f_w = eval_f ( & r1cs , & w . w ) ;
// println!("is f(w) {:?}", f_w);
let f_w = eval_f ( r1cs , & w . w ) ;
// F(X)
// F(X)
let mut F_X : SparsePolynomial < C ::ScalarField > = SparsePolynomial ::zero ( ) ;
let mut F_X : SparsePolynomial < C ::ScalarField > = SparsePolynomial ::zero ( ) ;
@ -74,9 +73,9 @@ where
}
}
let F_X_dense = DensePolynomial ::from ( F_X . clone ( ) ) ;
let F_X_dense = DensePolynomial ::from ( F_X . clone ( ) ) ;
tr . add_vec ( & F_X_dense . coeffs ) ;
transcript . add_vec ( & F_X_dense . coeffs ) ;
let alpha = tr . get_challenge ( ) ;
let alpha = transcript . get_challenge ( ) ;
// eval F(alpha)
// eval F(alpha)
let F_alpha = F_X . evaluate ( & alpha ) ;
let F_alpha = F_X . evaluate ( & alpha ) ;
@ -106,31 +105,78 @@ where
w . clone ( ) ,
w . clone ( ) ,
) ) ;
) ) ;
let gamma = tr . get_challenge ( ) ;
let gamma = transcript . get_challenge ( ) ;
// TODO WIP compute G(X) & K(X)
let G_evals : Vec < C ::ScalarField > = vec ! [ C ::ScalarField ::zero ( ) ; n ] ;
let G_X : DensePolynomial < C ::ScalarField > =
Evaluations ::< C ::ScalarField > ::from_vec_and_domain ( G_evals . clone ( ) , H ) . interpolate ( ) ;
// dbg!(&G_X);
let ( K_X , remainder ) = G_X . divide_by_vanishing_poly ( H ) . unwrap ( ) ;
// dbg!(&K_X);
assert ! ( remainder . is_zero ( ) ) ;
let mut ws : Vec < Vec < C ::ScalarField > > = Vec ::new ( ) ;
ws . push ( w . w . clone ( ) ) ;
for wj in vec_w . iter ( ) {
assert_eq ! ( wj . w . len ( ) , n ) ;
ws . push ( wj . w . clone ( ) ) ;
}
let k = vec_instances . len ( ) ;
let H = GeneralEvaluationDomain ::< C ::ScalarField > ::new ( k + 1 ) . unwrap ( ) ;
let EH = GeneralEvaluationDomain ::< C ::ScalarField > ::new ( t * k + 1 ) . unwrap ( ) ;
let L_X : Vec < DensePolynomial < C ::ScalarField > > = lagrange_polys ( H ) ;
// K(X) computation in a naive way, next iterations will compute K(X) as described in Claim
// 4.5 of the paper.
let mut G_evals : Vec < C ::ScalarField > = vec ! [ C ::ScalarField ::zero ( ) ; EH . size ( ) ] ;
for ( hi , h ) in EH . elements ( ) . enumerate ( ) {
// each iteration evaluates G(h)
// inner = L_0(x) * w + \sum_k L_i(x) * w_j
let mut inner : Vec < C ::ScalarField > = vec ! [ C ::ScalarField ::zero ( ) ; ws [ 0 ] . len ( ) ] ;
for ( i , w ) in ws . iter ( ) . enumerate ( ) {
// Li_w = Li(X) * wj
let mut Li_w : Vec < DensePolynomial < C ::ScalarField > > =
vec ! [ DensePolynomial ::< C ::ScalarField > ::zero ( ) ; w . len ( ) ] ;
for ( j , wj ) in w . iter ( ) . enumerate ( ) {
let Li_wj = & L_X [ i ] * * wj ;
Li_w [ j ] = Li_wj ;
}
// Li_w_h = Li_w(h) = Li(h) * wj
let mut Liw_h : Vec < C ::ScalarField > = vec ! [ C ::ScalarField ::zero ( ) ; w . len ( ) ] ;
for ( j , _ ) in Li_w . iter ( ) . enumerate ( ) {
Liw_h [ j ] = Li_w [ j ] . evaluate ( & h ) ;
}
for j in 0 . . inner . len ( ) {
inner [ j ] + = Liw_h [ j ] ;
}
}
let f_ev = eval_f ( r1cs , & inner ) ;
let mut Gsum = C ::ScalarField ::zero ( ) ;
for i in 0 . . n {
let pow_i_betas = pow_i ( i , & betas_star ) ;
let curr = pow_i_betas * f_ev [ i ] ;
Gsum + = curr ;
}
// G_evals[hi] = Gsum / Z_X.evaluate(&h); // WIP
G_evals [ hi ] = Gsum ;
}
let G_X : DensePolynomial < C ::ScalarField > =
Evaluations ::< C ::ScalarField > ::from_vec_and_domain ( G_evals . clone ( ) , EH ) . interpolate ( ) ;
let Z_X : DensePolynomial < C ::ScalarField > = H . vanishing_polynomial ( ) . into ( ) ;
let Z_X : DensePolynomial < C ::ScalarField > = H . vanishing_polynomial ( ) . into ( ) ;
// K(X) = (G(X)- F(alpha)*L_0(X)) / Z(X)
let L0_e = & L_X [ 0 ] * F_alpha ; // L0(X)*F(a) will be 0 in the native case
let G_L0e = & G_X - & L0_e ;
// TODO move division by Z_X to the prev loop
let ( K_X , remainder ) = G_L0e . divide_by_vanishing_poly ( H ) . unwrap ( ) ;
assert ! ( remainder . is_zero ( ) ) ;
let e_star =
let e_star =
F_alpha * L_X [ 0 ] . evaluate ( & gamma ) + Z_X . evaluate ( & gamma ) * K_X . evaluate ( & gamma ) ;
F_alpha * L_X [ 0 ] . evaluate ( & gamma ) + Z_X . evaluate ( & gamma ) * K_X . evaluate ( & gamma ) ;
let mut phi_star : C = instance . phi . 0 * L_X [ 0 ] . evaluate ( & gamma ) ;
let mut phi_star : C = instance . phi . 0 * L_X [ 0 ] . evaluate ( & gamma ) ;
for i in 0 . . k {
for i in 0 . . k {
phi_star + = vec_instances [ i ] . phi . 0 * L_X [ i ] . evaluate ( & gamma ) ;
phi_star + = vec_instances [ i ] . phi . 0 * L_X [ i + 1 ] . evaluate ( & gamma ) ;
}
}
let mut w_star : Vec < C ::ScalarField > = vec_scalar_mul ( & w . w , & L_X [ 0 ] . evaluate ( & gamma ) ) ;
let mut w_star : Vec < C ::ScalarField > = vec_scalar_mul ( & w . w , & L_X [ 0 ] . evaluate ( & gamma ) ) ;
for i in 0 . . k {
for i in 0 . . k {
w_star = vec_add (
w_star = vec_add (
& w_star ,
& w_star ,
& vec_scalar_mul ( & vec_w [ i ] . w , & L_X [ i ] . evaluate ( & gamma ) ) ,
& vec_scalar_mul ( & vec_w [ i ] . w , & L_X [ i + 1 ] . evaluate ( & gamma ) ) ,
) ;
) ;
}
}
@ -144,15 +190,14 @@ where
} ,
} ,
Witness {
Witness {
w : w_star ,
w : w_star ,
r_w : w . r_w ,
r_w : w . r_w , // wip, fold also r_w (blinding used for the w commitment)
} ,
} ,
)
)
}
}
pub fn verifier (
pub fn verifier (
tr : & mut Transcript < C ::ScalarField , C > ,
pedersen_params : & PedersenParams < C > ,
r1cs : R1CS < C ::ScalarField > ,
transcript : & mut Transcript < C ::ScalarField , C > ,
r1cs : & R1CS < C ::ScalarField > ,
// running instance
// running instance
instance : CommittedInstance < C > ,
instance : CommittedInstance < C > ,
// incomming instances
// incomming instances
@ -164,17 +209,14 @@ where
let t = instance . betas . len ( ) ;
let t = instance . betas . len ( ) ;
let n = r1cs . A [ 0 ] . len ( ) ;
let n = r1cs . A [ 0 ] . len ( ) ;
let delta = tr . get_challenge ( ) ;
let delta = transcript . get_challenge ( ) ;
let deltas = powers_of_beta ( delta , t ) ;
let deltas = powers_of_beta ( delta , t ) ;
tr . add_vec ( & F_coeffs ) ;
transcript . add_vec ( & F_coeffs ) ;
let alpha = tr . get_challenge ( ) ;
let alpha = transcript . get_challenge ( ) ;
let alphas = all_powers ( alpha , n ) ;
let alphas = all_powers ( alpha , n ) ;
// dbg!(instance.e);
// dbg!(F_coeffs[0]);
// F(alpha) = e + \sum_t F_i * alpha^i
// F(alpha) = e + \sum_t F_i * alpha^i
let mut F_alpha = instance . e ;
let mut F_alpha = instance . e ;
for ( i , F_i ) in F_coeffs . iter ( ) . enumerate ( ) {
for ( i , F_i ) in F_coeffs . iter ( ) . enumerate ( ) {
@ -193,20 +235,21 @@ where
. map ( | ( beta_i , delta_i_alpha ) | * beta_i + delta_i_alpha )
. map ( | ( beta_i , delta_i_alpha ) | * beta_i + delta_i_alpha )
. collect ( ) ;
. collect ( ) ;
let gamma = tr . get_challenge ( ) ;
let gamma = transcript . get_challenge ( ) ;
let k = vec_instances . len ( ) ;
let k = vec_instances . len ( ) ;
let domain_k = GeneralEvaluationDomain ::< C ::ScalarField > ::new ( k ) . unwrap ( ) ;
let L_X : Vec < DensePolynomial < C ::ScalarField > > = lagrange_polys ( domain_k ) ;
let Z_X : DensePolynomial < C ::ScalarField > = domain_k . vanishing_polynomial ( ) . into ( ) ;
let H = GeneralEvaluationDomain ::< C ::ScalarField > ::new ( k + 1 ) . unwrap ( ) ;
let L_X : Vec < DensePolynomial < C ::ScalarField > > = lagrange_polys ( H ) ;
let Z_X : DensePolynomial < C ::ScalarField > = H . vanishing_polynomial ( ) . into ( ) ;
let K_X : DensePolynomial < C ::ScalarField > =
let K_X : DensePolynomial < C ::ScalarField > =
DensePolynomial ::< C ::ScalarField > ::from_coefficients_vec ( K_coeffs ) ;
DensePolynomial ::< C ::ScalarField > ::from_coefficients_vec ( K_coeffs ) ;
let e_star =
let e_star =
F_alpha * L_X [ 0 ] . evaluate ( & gamma ) + Z_X . evaluate ( & gamma ) * K_X . evaluate ( & gamma ) ;
F_alpha * L_X [ 0 ] . evaluate ( & gamma ) + Z_X . evaluate ( & gamma ) * K_X . evaluate ( & gamma ) ;
let mut phi_star : C = instance . phi . 0 * L_X [ 0 ] . evaluate ( & gamma ) ;
let mut phi_star : C = instance . phi . 0 * L_X [ 0 ] . evaluate ( & gamma ) ;
for i in 0 . . k {
for i in 0 . . k {
phi_star + = vec_instances [ i ] . phi . 0 * L_X [ i ] . evaluate ( & gamma ) ;
phi_star + = vec_instances [ i ] . phi . 0 * L_X [ i + 1 ] . evaluate ( & gamma ) ;
}
}
// return the folded instance
// return the folded instance
@ -226,12 +269,12 @@ fn pow_i(i: usize, betas: &Vec) -> F {
let b = bit_decompose ( i as u64 , n as usize ) ;
let b = bit_decompose ( i as u64 , n as usize ) ;
let mut r : F = F ::one ( ) ;
let mut r : F = F ::one ( ) ;
for ( j , beta_i ) in betas . iter ( ) . enumerate ( ) {
for ( j , beta_j ) in betas . iter ( ) . enumerate ( ) {
let mut b_j = F ::zero ( ) ;
let mut b_j = F ::zero ( ) ;
if b [ j ] {
if b [ j ] {
b_j = F ::one ( ) ;
b_j = F ::one ( ) ;
}
}
r * = ( F ::one ( ) - b_j ) + b_j * betas [ j ] ;
r * = ( F ::one ( ) - b_j ) + b_j * beta_j ;
}
}
r
r
}
}
@ -244,20 +287,19 @@ fn pow_i_over_x(i: usize, betas: &Vec, deltas: &Vec) -> Spa
let mut r : SparsePolynomial < F > =
let mut r : SparsePolynomial < F > =
SparsePolynomial ::< F > ::from_coefficients_vec ( vec ! [ ( 0 , F ::one ( ) ) ] ) ; // start with r(x) = 1
SparsePolynomial ::< F > ::from_coefficients_vec ( vec ! [ ( 0 , F ::one ( ) ) ] ) ; // start with r(x) = 1
for ( j , beta_i ) in betas . iter ( ) . enumerate ( ) {
for ( j , beta_j ) in betas . iter ( ) . enumerate ( ) {
if b [ j ] {
if b [ j ] {
let curr : SparsePolynomial < F > =
let curr : SparsePolynomial < F > =
SparsePolynomial ::< F > ::from_coefficients_vec ( vec ! [ ( 0 , betas [ j ] ) , ( 1 , deltas [ j ] ) ] ) ;
SparsePolynomial ::< F > ::from_coefficients_vec ( vec ! [ ( 0 , * beta_j ) , ( 1 , deltas [ j ] ) ] ) ;
r = r . mul ( & curr ) ;
r = r . mul ( & curr ) ;
}
}
}
}
r
r
}
}
// method from caulk: https://github.com/caulk-crypto/caulk/tree/8210b51fb8a9eef4335505d1695c44ddc7bf8170/src/multi/setup.rs#L300
// lagrange_polys method from caulk: https://github.com/caulk-crypto/caulk/tree/8210b51fb8a9eef4335505d1695c44ddc7bf8170/src/multi/setup.rs#L300
fn lagrange_polys < F : PrimeField > ( domain_n : GeneralEvaluationDomain < F > ) -> Vec < DensePolynomial < F > > {
fn lagrange_polys < F : PrimeField > ( domain_n : GeneralEvaluationDomain < F > ) -> Vec < DensePolynomial < F > > {
let mut lagrange_polynomials : Vec < DensePolynomial < F > > = Vec ::new ( ) ;
let mut lagrange_polynomials : Vec < DensePolynomial < F > > = Vec ::new ( ) ;
for i in 0 . . domain_n . size ( ) {
for i in 0 . . domain_n . size ( ) {
let evals : Vec < F > = cfg_into_iter ! ( 0 . . domain_n . size ( ) )
let evals : Vec < F > = cfg_into_iter ! ( 0 . . domain_n . size ( ) )
. map ( | k | if k = = i { F ::one ( ) } else { F ::zero ( ) } )
. map ( | k | if k = = i { F ::one ( ) } else { F ::zero ( ) } )
@ -275,11 +317,10 @@ pub struct R1CS {
}
}
// f(w) in R1CS context
// f(w) in R1CS context
fn eval_f < F : PrimeField > ( r1cs : & R1CS < F > , w : & Vec < F > ) -> Vec < F > {
let AzBz = hadamard ( & mat_vec_mul ( & r1cs . A , & w ) , & mat_vec_mul ( & r1cs . B , & w ) ) ;
let Cz = mat_vec_mul ( & r1cs . C , & w ) ;
let f_w = vec_sub ( & AzBz , & Cz ) ;
f_w
fn eval_f < F : PrimeField > ( r1cs : & R1CS < F > , w : & [ F ] ) -> Vec < F > {
let AzBz = hadamard ( & mat_vec_mul ( & r1cs . A , w ) , & mat_vec_mul ( & r1cs . B , w ) ) ;
let Cz = mat_vec_mul ( & r1cs . C , w ) ;
vec_sub ( & AzBz , & Cz )
}
}
fn check_instance < C : CurveGroup > (
fn check_instance < C : CurveGroup > (
@ -288,11 +329,8 @@ fn check_instance(
w : Witness < C > ,
w : Witness < C > ,
) -> bool {
) -> bool {
let n = 2_ u64 . pow ( instance . betas . len ( ) as u32 ) as usize ;
let n = 2_ u64 . pow ( instance . betas . len ( ) as u32 ) as usize ;
dbg ! ( n ) ;
dbg ! ( w . w . len ( ) ) ;
let f_w = eval_f ( & r1cs , & w . w ) ; // f(w)
dbg ! ( f_w . len ( ) ) ;
let f_w = eval_f ( r1cs , & w . w ) ; // f(w)
let mut r = C ::ScalarField ::zero ( ) ;
let mut r = C ::ScalarField ::zero ( ) ;
for i in 0 . . n {
for i in 0 . . n {
@ -310,7 +348,6 @@ mod tests {
use crate ::pedersen ::Pedersen ;
use crate ::pedersen ::Pedersen ;
use crate ::transcript ::poseidon_test_config ;
use crate ::transcript ::poseidon_test_config ;
use ark_bls12_381 ::{ Fr , G1Projective } ;
use ark_bls12_381 ::{ Fr , G1Projective } ;
use ark_std ::One ;
use ark_std ::UniformRand ;
use ark_std ::UniformRand ;
pub fn to_F_matrix < F : PrimeField > ( M : Vec < Vec < usize > > ) -> Vec < Vec < F > > {
pub fn to_F_matrix < F : PrimeField > ( M : Vec < Vec < usize > > ) -> Vec < Vec < F > > {
@ -405,16 +442,22 @@ mod tests {
let mut rng = ark_std ::test_rng ( ) ;
let mut rng = ark_std ::test_rng ( ) ;
let t = 3 ;
let t = 3 ;
let n = 8 ;
let n = 8 ;
// let beta = Fr::rand(&mut rng);
// let delta = Fr::rand(&mut rng);
let beta = Fr ::from ( 3 ) ;
let delta = Fr ::from ( 5 ) ;
let beta = Fr ::rand ( & mut rng ) ;
let delta = Fr ::rand ( & mut rng ) ;
let betas = powers_of_beta ( beta , t ) ;
let betas = powers_of_beta ( beta , t ) ;
let deltas = powers_of_beta ( delta , t ) ;
let deltas = powers_of_beta ( delta , t ) ;
// for i in 0..n {
// dbg!(pow_i_over_x(i, &betas, &deltas));
// }
// compute b + X*d, with X=rand
let x = Fr ::rand ( & mut rng ) ;
let bxd = vec_add ( & betas , & vec_scalar_mul ( & deltas , & x ) ) ;
// assert that computing pow_over_x of betas,deltas, is equivalent to first computing the
// vector [betas+X*deltas] and then computing pow_i over it
for i in 0 . . n {
let pow_i1 = pow_i_over_x ( i , & betas , & deltas ) ;
let pow_i2 = pow_i ( i , & bxd ) ;
assert_eq ! ( pow_i1 . evaluate ( & x ) , pow_i2 ) ;
}
}
}
#[ test ]
#[ test ]
@ -431,15 +474,15 @@ mod tests {
}
}
#[ test ]
#[ test ]
fn test_fold ( ) {
fn test_fold_native_case ( ) {
let mut rng = ark_std ::test_rng ( ) ;
let mut rng = ark_std ::test_rng ( ) ;
let pedersen_params = Pedersen ::< G1Projective > ::new_params ( & mut rng , 100 ) ; // 100 is wip, will get it from actual vec
let pedersen_params = Pedersen ::< G1Projective > ::new_params ( & mut rng , 100 ) ; // 100 is wip, will get it from actual vec
let poseidon_config = poseidon_test_config ::< Fr > ( ) ;
let poseidon_config = poseidon_test_config ::< Fr > ( ) ;
let k = 5 ;
let k = 6 ;
let r1cs = get_test_r1cs ::< Fr > ( ) ;
let r1cs = get_test_r1cs ::< Fr > ( ) ;
let mut z = get_test_z ::< Fr > ( 3 ) ;
let z = get_test_z ::< Fr > ( 3 ) ;
let mut zs : Vec < Vec < Fr > > = Vec ::new ( ) ;
let mut zs : Vec < Vec < Fr > > = Vec ::new ( ) ;
for i in 0 . . k {
for i in 0 . . k {
let z_i = get_test_z ::< Fr > ( i + 4 ) ;
let z_i = get_test_z ::< Fr > ( i + 4 ) ;
@ -452,8 +495,6 @@ mod tests {
let n = z . len ( ) ;
let n = z . len ( ) ;
let t = log2 ( n ) as usize ;
let t = log2 ( n ) as usize ;
dbg ! ( n ) ;
dbg ! ( t ) ;
let beta = Fr ::rand ( & mut rng ) ;
let beta = Fr ::rand ( & mut rng ) ;
let betas = powers_of_beta ( beta , t ) ;
let betas = powers_of_beta ( beta , t ) ;
@ -489,30 +530,30 @@ mod tests {
let ( F_coeffs , K_coeffs , folded_instance , folded_witness ) = Folding ::< G1Projective > ::prover (
let ( F_coeffs , K_coeffs , folded_instance , folded_witness ) = Folding ::< G1Projective > ::prover (
& mut transcript_p ,
& mut transcript_p ,
& pedersen_params ,
& r1cs ,
& r1cs ,
instance . clone ( ) ,
instance . clone ( ) ,
witness ,
witness ,
instances . clone ( ) ,
instances . clone ( ) ,
witnesses ,
witnesses ,
) ;
) ;
dbg ! ( & F_coeffs ) ;
// veriier
// veriier
let folded_instance_v = Folding ::< G1Projective > ::verifier (
let folded_instance_v = Folding ::< G1Projective > ::verifier (
& mut transcript_v ,
& mut transcript_v ,
& pedersen_params ,
r1cs . clone ( ) , // TODO rm clone do borrow
& r1cs ,
instance ,
instance ,
instances ,
instances ,
F_coeffs ,
F_coeffs ,
K_coeffs ,
K_coeffs ,
) ;
) ;
// check that prover & verifier folded instances are the same values
assert_eq ! ( folded_instance . phi . 0 , folded_instance_v . phi . 0 ) ;
assert_eq ! ( folded_instance . phi . 0 , folded_instance_v . phi . 0 ) ;
assert_eq ! ( folded_instance . betas , folded_instance_v . betas ) ;
assert_eq ! ( folded_instance . betas , folded_instance_v . betas ) ;
assert_eq ! ( folded_instance . e , folded_instance_v . e ) ;
assert_eq ! ( folded_instance . e , folded_instance_v . e ) ;
assert ! ( ! folded_instance . e . is_zero ( ) ) ;
// assert!(check_instance(&r1cs, folded_instance, folded_witness));
// check that the folded instance satisfies the relation
assert ! ( check_instance ( & r1cs , folded_instance , folded_witness ) ) ;
}
}
}
}