mirror of
https://github.com/arnaucube/sonobe.git
synced 2026-01-22 13:51:35 +01:00
Protogalaxy verifier circuit (#95)
* Add in-circuit couterparts of util functions * Support folding `CommittedInstance`s with `u` and `x` * Initial implementation of protogalaxy verifier circuit * Fix the edge case in `all_powers_var` * Absorb `u` and `x` as well * Fix imports * Rename some test functions for clarity * Format * Avoid the use of magic numbers
This commit is contained in:
179
folding-schemes/src/folding/protogalaxy/circuits.rs
Normal file
179
folding-schemes/src/folding/protogalaxy/circuits.rs
Normal file
@@ -0,0 +1,179 @@
|
||||
use ark_crypto_primitives::sponge::CryptographicSponge;
|
||||
use ark_ec::CurveGroup;
|
||||
use ark_poly::{univariate::DensePolynomial, EvaluationDomain, GeneralEvaluationDomain};
|
||||
use ark_r1cs_std::{
|
||||
alloc::AllocVar,
|
||||
fields::{fp::FpVar, FieldVar},
|
||||
poly::polynomial::univariate::dense::DensePolynomialVar,
|
||||
};
|
||||
use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
|
||||
|
||||
use super::{
|
||||
folding::lagrange_polys,
|
||||
utils::{all_powers_var, betas_star_var, exponential_powers_var},
|
||||
CommittedInstanceVar,
|
||||
};
|
||||
use crate::{
|
||||
folding::circuits::nonnative::affine::NonNativeAffineVar, transcript::TranscriptVar,
|
||||
utils::gadgets::VectorGadget,
|
||||
};
|
||||
|
||||
pub struct FoldingGadget {}
|
||||
|
||||
impl FoldingGadget {
|
||||
pub fn fold_committed_instance<C: CurveGroup, S: CryptographicSponge>(
|
||||
transcript: &mut impl TranscriptVar<C::ScalarField, S>,
|
||||
// running instance
|
||||
instance: &CommittedInstanceVar<C>,
|
||||
// incoming instances
|
||||
vec_instances: &[CommittedInstanceVar<C>],
|
||||
// polys from P
|
||||
F_coeffs: Vec<FpVar<C::ScalarField>>,
|
||||
K_coeffs: Vec<FpVar<C::ScalarField>>,
|
||||
) -> Result<CommittedInstanceVar<C>, SynthesisError> {
|
||||
let t = instance.betas.len();
|
||||
let n = F_coeffs.len();
|
||||
|
||||
// absorb the committed instances
|
||||
transcript.absorb(instance)?;
|
||||
transcript.absorb(&vec_instances)?;
|
||||
|
||||
let delta = transcript.get_challenge()?;
|
||||
let deltas = exponential_powers_var(delta, t);
|
||||
|
||||
transcript.absorb(&F_coeffs)?;
|
||||
|
||||
let alpha = transcript.get_challenge()?;
|
||||
let alphas = all_powers_var(alpha.clone(), n);
|
||||
|
||||
// F(alpha) = e + \sum_t F_i * alpha^i
|
||||
let mut F_alpha = instance.e.clone();
|
||||
for (i, F_i) in F_coeffs.iter().skip(1).enumerate() {
|
||||
F_alpha += F_i * &alphas[i + 1];
|
||||
}
|
||||
|
||||
let betas_star = betas_star_var(&instance.betas, &deltas, &alpha);
|
||||
|
||||
let k = vec_instances.len();
|
||||
let H = GeneralEvaluationDomain::new(k + 1).unwrap();
|
||||
let L_X = lagrange_polys(H)
|
||||
.into_iter()
|
||||
.map(|poly| {
|
||||
DensePolynomialVar::from_coefficients_vec(
|
||||
poly.coeffs
|
||||
.into_iter()
|
||||
.map(FpVar::constant)
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let Z_X = DensePolynomialVar::from_coefficients_vec(
|
||||
DensePolynomial::from(H.vanishing_polynomial())
|
||||
.coeffs
|
||||
.into_iter()
|
||||
.map(FpVar::constant)
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
let K_X = DensePolynomialVar { coeffs: K_coeffs };
|
||||
|
||||
transcript.absorb(&K_X.coeffs)?;
|
||||
|
||||
let gamma = transcript.get_challenge()?;
|
||||
|
||||
let L_X_evals = L_X
|
||||
.iter()
|
||||
.take(k + 1)
|
||||
.map(|L| L.evaluate(&gamma))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let e_star = F_alpha * &L_X_evals[0] + Z_X.evaluate(&gamma)? * K_X.evaluate(&gamma)?;
|
||||
|
||||
let mut u_star = &instance.u * &L_X_evals[0];
|
||||
let mut x_star = instance.x.mul_scalar(&L_X_evals[0])?;
|
||||
for i in 0..k {
|
||||
u_star += &vec_instances[i].u * &L_X_evals[i + 1];
|
||||
x_star = x_star.add(&vec_instances[i].x.mul_scalar(&L_X_evals[i + 1])?)?;
|
||||
}
|
||||
|
||||
// return the folded instance
|
||||
Ok(CommittedInstanceVar {
|
||||
betas: betas_star,
|
||||
// phi will be computed in CycleFold
|
||||
phi: NonNativeAffineVar::new_constant(ConstraintSystemRef::None, C::zero())?,
|
||||
e: e_star,
|
||||
u: u_star,
|
||||
x: x_star,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ark_crypto_primitives::sponge::{
|
||||
constraints::CryptographicSpongeVar,
|
||||
poseidon::{constraints::PoseidonSpongeVar, PoseidonSponge},
|
||||
};
|
||||
use ark_pallas::{Fr, Projective};
|
||||
use ark_r1cs_std::R1CSVar;
|
||||
use ark_relations::r1cs::ConstraintSystem;
|
||||
use std::error::Error;
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
arith::r1cs::tests::get_test_r1cs,
|
||||
folding::protogalaxy::folding::{tests::prepare_inputs, Folding},
|
||||
transcript::poseidon::poseidon_canonical_config,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_fold_gadget() -> Result<(), Box<dyn Error>> {
|
||||
let k = 7;
|
||||
let (witness, instance, witnesses, instances) = prepare_inputs(k);
|
||||
let r1cs = get_test_r1cs::<Fr>();
|
||||
|
||||
// init Prover & Verifier's transcript
|
||||
let poseidon_config = poseidon_canonical_config::<Fr>();
|
||||
let mut transcript_p = PoseidonSponge::new(&poseidon_config);
|
||||
let mut transcript_v = PoseidonSponge::new(&poseidon_config);
|
||||
|
||||
let (_, _, F_coeffs, K_coeffs) = Folding::<Projective>::prove(
|
||||
&mut transcript_p,
|
||||
&r1cs,
|
||||
&instance,
|
||||
&witness,
|
||||
&instances,
|
||||
&witnesses,
|
||||
)?;
|
||||
|
||||
let folded_instance = Folding::<Projective>::verify(
|
||||
&mut transcript_v,
|
||||
&r1cs,
|
||||
&instance,
|
||||
&instances,
|
||||
F_coeffs.clone(),
|
||||
K_coeffs.clone(),
|
||||
)?;
|
||||
|
||||
let cs = ConstraintSystem::new_ref();
|
||||
let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), &poseidon_config);
|
||||
let instance_var = CommittedInstanceVar::new_witness(cs.clone(), || Ok(instance))?;
|
||||
let instances_var = Vec::new_witness(cs.clone(), || Ok(instances))?;
|
||||
let F_coeffs_var = Vec::new_witness(cs.clone(), || Ok(F_coeffs))?;
|
||||
let K_coeffs_var = Vec::new_witness(cs.clone(), || Ok(K_coeffs))?;
|
||||
|
||||
let folded_instance_var = FoldingGadget::fold_committed_instance(
|
||||
&mut transcript_var,
|
||||
&instance_var,
|
||||
&instances_var,
|
||||
F_coeffs_var,
|
||||
K_coeffs_var,
|
||||
)?;
|
||||
assert_eq!(folded_instance.betas, folded_instance_var.betas.value()?);
|
||||
assert_eq!(folded_instance.e, folded_instance_var.e.value()?);
|
||||
assert_eq!(folded_instance.u, folded_instance_var.u.value()?);
|
||||
assert_eq!(folded_instance.x, folded_instance_var.x.value()?);
|
||||
assert!(cs.is_satisfied()?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user