Skip to content

Commit

Permalink
Merge pull request #51 from privacy-scaling-explorations/dev/hypernov…
Browse files Browse the repository at this point in the history
…a-nimfs-verifier-circuit/eq-gadget

feat: `EqEvalGadget` for computing `eq(x, y)`
  • Loading branch information
dmpierre authored Jan 5, 2024
2 parents 0954ea3 + 5c0e56c commit 72ac59c
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/folding/circuits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use ark_ff::Field;

pub mod nonnative;
pub mod sum_check;
pub mod utils;

// CF represents the constraints field
pub type CF<C> = <<C as CurveGroup>::BaseField as Field>::BasePrimeField;
75 changes: 75 additions & 0 deletions src/folding/circuits/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use ark_ff::PrimeField;
use ark_r1cs_std::fields::{fp::FpVar, FieldVar};
use ark_relations::r1cs::SynthesisError;
use std::marker::PhantomData;

/// EqEval is a gadget for computing $\tilde{eq}(a, b) = \Pi_{i=1}^{l}(a_i \cdot b_i + (1 - a_i)(1 - b_i))$
/// :warning: This is not the ark_r1cs_std::eq::EqGadget
pub struct EqEvalGadget<F: PrimeField> {
_f: PhantomData<F>,
}

impl<F: PrimeField> EqEvalGadget<F> {
/// Gadget to evaluate eq polynomial.
/// Follows the implementation of `eq_eval` found in this crate.
pub fn eq_eval(x: Vec<FpVar<F>>, y: Vec<FpVar<F>>) -> Result<FpVar<F>, SynthesisError> {
if x.len() != y.len() {
return Err(SynthesisError::Unsatisfiable);
}
if x.is_empty() || y.is_empty() {
return Err(SynthesisError::AssignmentMissing);
}
let mut e = FpVar::<F>::one();
for (xi, yi) in x.iter().zip(y.iter()) {
let xi_yi = xi * yi;
e *= xi_yi.clone() + xi_yi - xi - yi + F::one();
}
Ok(e)
}
}

#[cfg(test)]
mod tests {

use crate::utils::virtual_polynomial::eq_eval;

use super::EqEvalGadget;
use ark_ff::Field;
use ark_pallas::Fr;
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_eq_eval_gadget() {
let mut rng = test_rng();
let cs = ConstraintSystem::<Fr>::new_ref();

for i in 1..20 {
let x_vec: Vec<Fr> = (0..i).map(|_| Fr::rand(&mut rng)).collect();
let y_vec: Vec<Fr> = (0..i).map(|_| Fr::rand(&mut rng)).collect();
let x: Vec<FpVar<Fr>> = x_vec
.iter()
.map(|x| FpVar::<Fr>::new_witness(cs.clone(), || Ok(x)).unwrap())
.collect();
let y: Vec<FpVar<Fr>> = y_vec
.iter()
.map(|y| FpVar::<Fr>::new_witness(cs.clone(), || Ok(y)).unwrap())
.collect();
let expected_eq_eval = eq_eval::<Fr>(&x_vec, &y_vec).unwrap();
let gadget_eq_eval: FpVar<Fr> = EqEvalGadget::<Fr>::eq_eval(x, y).unwrap();
assert_eq!(expected_eq_eval, gadget_eq_eval.value().unwrap());
}

let x: Vec<FpVar<Fr>> = vec![];
let y: Vec<FpVar<Fr>> = vec![];
let gadget_eq_eval = EqEvalGadget::<Fr>::eq_eval(x, y);
assert!(gadget_eq_eval.is_err());

let x: Vec<FpVar<Fr>> = vec![];
let y: Vec<FpVar<Fr>> =
vec![FpVar::<Fr>::new_witness(cs.clone(), || Ok(&Fr::ONE)).unwrap()];
let gadget_eq_eval = EqEvalGadget::<Fr>::eq_eval(x, y);
assert!(gadget_eq_eval.is_err());
}
}

0 comments on commit 72ac59c

Please sign in to comment.