-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #53 from privacy-scaling-explorations/dev/hypernov…
…a-nimfs-verifier-circuit/mul-gammapow-eq-sigma-gadget A gadget to compute the first term of the sum in section 5, step 5
- Loading branch information
Showing
2 changed files
with
120 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,105 @@ | ||
// hypernova nimfs verifier circuit | ||
// see section 5 in https://eprint.iacr.org/2023/573.pdf | ||
|
||
use ark_ff::PrimeField; | ||
use ark_r1cs_std::{ | ||
fields::{fp::FpVar, FieldVar}, | ||
ToBitsGadget, | ||
}; | ||
use ark_relations::r1cs::SynthesisError; | ||
use std::marker::PhantomData; | ||
|
||
/// Gadget to compute the sum of all $\gamma^{j} \cdot eq(r_{x_j}, r_x^{\prime}) \cdot \sigma_j$. | ||
pub struct SumMulsGammaPowsEqSigmaGadget<F: PrimeField> { | ||
_f: PhantomData<F>, | ||
} | ||
|
||
impl<F: PrimeField> SumMulsGammaPowsEqSigmaGadget<F> { | ||
/// Computes the sum $\Sigma_{j}^{j + n} \gamma^{j} \cdot eq_eval \cdot \sigma_{j}$, where $n$ is the length of the `sigmas` vector | ||
/// It corresponds to the first term of the sum that $\mathcal{V}$ has to compute at section 5, step 5 of "A multi-folding scheme for CCS". | ||
/// | ||
/// # Arguments | ||
/// - `sigmas`: vector of $\sigma_j$ values | ||
/// - `eq_eval`: the value of $\tilde{eq}(x_j, x^{\prime})$ | ||
/// - `gamma`: value $\gamma$ | ||
/// - `j`: the power at which we start to compute $\gamma^{j}$. This is needed in the contexxt of multifolding. | ||
/// | ||
/// # Notes | ||
/// In the context of multifolding, `j` corresponds to `ccs.t` in `compute_c_from_sigmas_and_thetas` | ||
pub fn sum_muls_gamma_pows_eq_sigma( | ||
sigmas: Vec<FpVar<F>>, | ||
eq_eval: FpVar<F>, | ||
gamma: FpVar<F>, | ||
j: FpVar<F>, | ||
) -> Result<FpVar<F>, SynthesisError> { | ||
let mut result = FpVar::<F>::zero(); | ||
let mut gamma_pow = gamma.pow_le(&j.to_bits_le()?)?; | ||
for sigma in sigmas { | ||
result += gamma_pow.clone() * eq_eval.clone() * sigma; | ||
gamma_pow *= gamma.clone(); | ||
} | ||
Ok(result) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::SumMulsGammaPowsEqSigmaGadget; | ||
use crate::{ | ||
ccs::{ | ||
tests::{get_test_ccs, get_test_z}, | ||
CCS, | ||
}, | ||
folding::hypernova::utils::{compute_sigmas_and_thetas, sum_muls_gamma_pows_eq_sigma}, | ||
pedersen::Pedersen, | ||
utils::virtual_polynomial::eq_eval, | ||
}; | ||
use ark_pallas::{Fr, Projective}; | ||
use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, R1CSVar}; | ||
use ark_relations::r1cs::ConstraintSystem; | ||
use ark_std::{test_rng, UniformRand}; | ||
|
||
#[test] | ||
pub fn test_sum_muls_gamma_pow_eq_sigma_gadget() { | ||
let mut rng = test_rng(); | ||
let ccs: CCS<Projective> = get_test_ccs(); | ||
let z1 = get_test_z(3); | ||
let z2 = get_test_z(4); | ||
|
||
let gamma: Fr = Fr::rand(&mut rng); | ||
let r_x_prime: Vec<Fr> = (0..ccs.s).map(|_| Fr::rand(&mut rng)).collect(); | ||
|
||
// Initialize a multifolding object | ||
let pedersen_params = Pedersen::new_params(&mut rng, ccs.n - ccs.l - 1); | ||
let (lcccs_instance, _) = ccs.to_lcccs(&mut rng, &pedersen_params, &z1).unwrap(); | ||
let sigmas_thetas = | ||
compute_sigmas_and_thetas(&ccs, &[z1.clone()], &[z2.clone()], &r_x_prime); | ||
|
||
let mut e_lcccs = Vec::new(); | ||
for r_x in &vec![lcccs_instance.r_x] { | ||
e_lcccs.push(eq_eval(r_x, &r_x_prime).unwrap()); | ||
} | ||
|
||
// Initialize cs and gamma | ||
let cs = ConstraintSystem::<Fr>::new_ref(); | ||
let gamma_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(gamma)).unwrap(); | ||
|
||
for (i, sigmas) in sigmas_thetas.0.iter().enumerate() { | ||
let expected = | ||
sum_muls_gamma_pows_eq_sigma(gamma, e_lcccs[i], sigmas, (i * ccs.t) as u64); | ||
let sigmas_var = | ||
Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(sigmas.clone())).unwrap(); | ||
let eq_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(e_lcccs[i])).unwrap(); | ||
let pow = | ||
FpVar::<Fr>::new_witness(cs.clone(), || Ok(Fr::from((i * ccs.t) as u64))).unwrap(); | ||
let computed = SumMulsGammaPowsEqSigmaGadget::sum_muls_gamma_pows_eq_sigma( | ||
sigmas_var, | ||
eq_var, | ||
gamma_var.clone(), | ||
pow, | ||
) | ||
.unwrap(); | ||
assert_eq!(expected, computed.value().unwrap()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters