arnaucube
arnaucube/sonobePublic Self-hosted repository
sonobe/folding-schemes/src/folding/protogalaxy/circuits.rs
folding-schemes/src/folding/protogalaxy/circuits.rsRaw
  1use ark_crypto_primitives::sponge::CryptographicSponge;
  2use ark_ec::CurveGroup;
  3use ark_poly::{univariate::DensePolynomial, EvaluationDomain, GeneralEvaluationDomain};
  4use ark_r1cs_std::{
  5    alloc::AllocVar,
  6    fields::{fp::FpVar, FieldVar},
  7    poly::polynomial::univariate::dense::DensePolynomialVar,
  8};
  9use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
 10
 11use super::{
 12    folding::lagrange_polys,
 13    utils::{all_powers_var, betas_star_var, exponential_powers_var},
 14    CommittedInstanceVar,
 15};
 16use crate::{
 17    folding::circuits::nonnative::affine::NonNativeAffineVar, transcript::TranscriptVar,
 18    utils::gadgets::VectorGadget,
 19};
 20
 21pub struct FoldingGadget {}
 22
 23impl FoldingGadget {
 24    pub fn fold_committed_instance<C: CurveGroup, S: CryptographicSponge>(
 25        transcript: &mut impl TranscriptVar<C::ScalarField, S>,
 26        // running instance
 27        instance: &CommittedInstanceVar<C>,
 28        // incoming instances
 29        vec_instances: &[CommittedInstanceVar<C>],
 30        // polys from P
 31        F_coeffs: Vec<FpVar<C::ScalarField>>,
 32        K_coeffs: Vec<FpVar<C::ScalarField>>,
 33    ) -> Result<CommittedInstanceVar<C>, SynthesisError> {
 34        let t = instance.betas.len();
 35        let n = F_coeffs.len();
 36
 37        // absorb the committed instances
 38        transcript.absorb(instance)?;
 39        transcript.absorb(&vec_instances)?;
 40
 41        let delta = transcript.get_challenge()?;
 42        let deltas = exponential_powers_var(delta, t);
 43
 44        transcript.absorb(&F_coeffs)?;
 45
 46        let alpha = transcript.get_challenge()?;
 47        let alphas = all_powers_var(alpha.clone(), n);
 48
 49        // F(alpha) = e + \sum_t F_i * alpha^i
 50        let mut F_alpha = instance.e.clone();
 51        for (i, F_i) in F_coeffs.iter().skip(1).enumerate() {
 52            F_alpha += F_i * &alphas[i + 1];
 53        }
 54
 55        let betas_star = betas_star_var(&instance.betas, &deltas, &alpha);
 56
 57        let k = vec_instances.len();
 58        let H = GeneralEvaluationDomain::new(k + 1).unwrap();
 59        let L_X = lagrange_polys(H)
 60            .into_iter()
 61            .map(|poly| {
 62                DensePolynomialVar::from_coefficients_vec(
 63                    poly.coeffs
 64                        .into_iter()
 65                        .map(FpVar::constant)
 66                        .collect::<Vec<_>>(),
 67                )
 68            })
 69            .collect::<Vec<_>>();
 70        let Z_X = DensePolynomialVar::from_coefficients_vec(
 71            DensePolynomial::from(H.vanishing_polynomial())
 72                .coeffs
 73                .into_iter()
 74                .map(FpVar::constant)
 75                .collect::<Vec<_>>(),
 76        );
 77        let K_X = DensePolynomialVar { coeffs: K_coeffs };
 78
 79        transcript.absorb(&K_X.coeffs)?;
 80
 81        let gamma = transcript.get_challenge()?;
 82
 83        let L_X_evals = L_X
 84            .iter()
 85            .take(k + 1)
 86            .map(|L| L.evaluate(&gamma))
 87            .collect::<Result<Vec<_>, _>>()?;
 88
 89        let e_star = F_alpha * &L_X_evals[0] + Z_X.evaluate(&gamma)? * K_X.evaluate(&gamma)?;
 90
 91        let mut u_star = &instance.u * &L_X_evals[0];
 92        let mut x_star = instance.x.mul_scalar(&L_X_evals[0])?;
 93        for i in 0..k {
 94            u_star += &vec_instances[i].u * &L_X_evals[i + 1];
 95            x_star = x_star.add(&vec_instances[i].x.mul_scalar(&L_X_evals[i + 1])?)?;
 96        }
 97
 98        // return the folded instance
 99        Ok(CommittedInstanceVar {
100            betas: betas_star,
101            // phi will be computed in CycleFold
102            phi: NonNativeAffineVar::new_constant(ConstraintSystemRef::None, C::zero())?,
103            e: e_star,
104            u: u_star,
105            x: x_star,
106        })
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use ark_crypto_primitives::sponge::{
113        constraints::CryptographicSpongeVar,
114        poseidon::{constraints::PoseidonSpongeVar, PoseidonSponge},
115    };
116    use ark_pallas::{Fr, Projective};
117    use ark_r1cs_std::R1CSVar;
118    use ark_relations::r1cs::ConstraintSystem;
119    use std::error::Error;
120
121    use super::*;
122    use crate::{
123        arith::r1cs::tests::get_test_r1cs,
124        folding::protogalaxy::folding::{tests::prepare_inputs, Folding},
125        transcript::poseidon::poseidon_canonical_config,
126    };
127
128    #[test]
129    fn test_fold_gadget() -> Result<(), Box<dyn Error>> {
130        let k = 7;
131        let (witness, instance, witnesses, instances) = prepare_inputs(k);
132        let r1cs = get_test_r1cs::<Fr>();
133
134        // init Prover & Verifier's transcript
135        let poseidon_config = poseidon_canonical_config::<Fr>();
136        let mut transcript_p = PoseidonSponge::new(&poseidon_config);
137        let mut transcript_v = PoseidonSponge::new(&poseidon_config);
138
139        let (_, _, F_coeffs, K_coeffs) = Folding::<Projective>::prove(
140            &mut transcript_p,
141            &r1cs,
142            &instance,
143            &witness,
144            &instances,
145            &witnesses,
146        )?;
147
148        let folded_instance = Folding::<Projective>::verify(
149            &mut transcript_v,
150            &r1cs,
151            &instance,
152            &instances,
153            F_coeffs.clone(),
154            K_coeffs.clone(),
155        )?;
156
157        let cs = ConstraintSystem::new_ref();
158        let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), &poseidon_config);
159        let instance_var = CommittedInstanceVar::new_witness(cs.clone(), || Ok(instance))?;
160        let instances_var = Vec::new_witness(cs.clone(), || Ok(instances))?;
161        let F_coeffs_var = Vec::new_witness(cs.clone(), || Ok(F_coeffs))?;
162        let K_coeffs_var = Vec::new_witness(cs.clone(), || Ok(K_coeffs))?;
163
164        let folded_instance_var = FoldingGadget::fold_committed_instance(
165            &mut transcript_var,
166            &instance_var,
167            &instances_var,
168            F_coeffs_var,
169            K_coeffs_var,
170        )?;
171        assert_eq!(folded_instance.betas, folded_instance_var.betas.value()?);
172        assert_eq!(folded_instance.e, folded_instance_var.e.value()?);
173        assert_eq!(folded_instance.u, folded_instance_var.u.value()?);
174        assert_eq!(folded_instance.x, folded_instance_var.x.value()?);
175        assert!(cs.is_satisfied()?);
176
177        Ok(())
178    }
179}