Skip to content

Commit

Permalink
Update cmE of E=0-vec to work as zero point
Browse files Browse the repository at this point in the history
Update cmE of E=0-vec to work as zero point instead of as cm(0-vec)
  • Loading branch information
arnaucube committed Oct 27, 2023
1 parent 97a7ba6 commit 27665b1
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 24 deletions.
46 changes: 46 additions & 0 deletions src/folding/circuits/nonnative.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use ark_r1cs_std::{
fields::nonnative::NonNativeFieldVar,
};
use ark_relations::r1cs::{Namespace, SynthesisError};
use ark_std::{One, Zero};
use core::borrow::Borrow;

/// NonNativeAffineVar represents an elliptic curve point in Affine represenation in the non-native
Expand All @@ -31,6 +32,19 @@ where
let cs = cs.into();

let affine = val.borrow().into_affine();
if affine.is_zero() {
let x = NonNativeFieldVar::<C::BaseField, C::ScalarField>::new_variable(
cs.clone(),
|| Ok(C::BaseField::zero()),
mode,
)?;
let y = NonNativeFieldVar::<C::BaseField, C::ScalarField>::new_variable(
cs.clone(),
|| Ok(C::BaseField::one()),
mode,
)?;
return Ok(Self { x, y });
}
let xy = affine.xy().unwrap();
let x = NonNativeFieldVar::<C::BaseField, C::ScalarField>::new_variable(
cs.clone(),
Expand Down Expand Up @@ -58,6 +72,20 @@ where
<C as ark_ec::CurveGroup>::BaseField: ark_ff::PrimeField,
{
let affine = p.into_affine();
if affine.is_zero() {
let x =
AllocatedNonNativeFieldVar::<C::BaseField, C::ScalarField>::get_limbs_representations(
&C::BaseField::zero(),
OptimizationType::Weight,
)?;
let y =
AllocatedNonNativeFieldVar::<C::BaseField, C::ScalarField>::get_limbs_representations(
&C::BaseField::one(),
OptimizationType::Weight,
)?;
return Ok((x, y));
}

let (x, y) = affine.xy().unwrap();
let x = AllocatedNonNativeFieldVar::<C::BaseField, C::ScalarField>::get_limbs_representations(
x,
Expand All @@ -69,3 +97,21 @@ where
)?;
Ok((x, y))
}

#[cfg(test)]
mod tests {
use super::*;
use ark_pallas::{Fq, Fr, Projective};
use ark_r1cs_std::alloc::AllocVar;
use ark_relations::r1cs::ConstraintSystem;
use ark_std::Zero;

#[test]
fn test_alloc_nonnativeaffinevar_zero() {
let cs = ConstraintSystem::<Fr>::new_ref();

// dealing with the 'zero' point should not panic when doing the unwrap
let p = Projective::zero();
NonNativeAffineVar::<Fq, Fr>::new_witness(cs.clone(), || Ok(p)).unwrap();
}
}
41 changes: 22 additions & 19 deletions src/folding/nova/circuits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,23 +257,26 @@ where
let z_i = FpVar::<CF1<C>>::new_witness(cs.clone(), || Ok(z_i_native))?;
let z_i1 = FpVar::<CF1<C>>::new_witness(cs.clone(), || Ok(z_i1_native))?;

let u_dummy = CommittedInstance {
cmE: C::generator(),
let u_dummy_native = CommittedInstance {
cmE: C::zero(),
u: C::ScalarField::zero(),
cmW: C::generator(),
cmW: C::zero(),
x: vec![CF1::<C>::zero()],
};

let u_dummy =
CommittedInstanceVar::<C>::new_witness(cs.clone(), || Ok(u_dummy_native.clone()))?;
let u_i = CommittedInstanceVar::<C>::new_witness(cs.clone(), || {
Ok(self.u_i.unwrap_or_else(|| u_dummy.clone()))
Ok(self.u_i.unwrap_or_else(|| u_dummy_native.clone()))
})?;
let U_i = CommittedInstanceVar::<C>::new_witness(cs.clone(), || {
Ok(self.U_i.unwrap_or_else(|| u_dummy.clone()))
Ok(self.U_i.unwrap_or_else(|| u_dummy_native.clone()))
})?;
let U_i1 = CommittedInstanceVar::<C>::new_witness(cs.clone(), || {
Ok(self.U_i1.unwrap_or_else(|| u_dummy.clone()))
Ok(self.U_i1.unwrap_or_else(|| u_dummy_native.clone()))
})?;
// let cmT = NonNativeAffineVar::new_witness(cs.clone(), || Ok(self.cmT.unwrap()))?; // TODO TMP
let _cmT =
NonNativeAffineVar::new_witness(cs.clone(), || Ok(self.cmT.unwrap_or_else(C::zero)))?;
let r =
FpVar::<CF1<C>>::new_witness(cs.clone(), || Ok(self.r.unwrap_or_else(CF1::<C>::zero)))?; // r will come from higher level transcript
let x =
Expand All @@ -295,7 +298,10 @@ where
(u_i.x[0]).conditional_enforce_equal(&u_i_x, &is_not_basecase)?;

// 2. u_i.cmE==cm(0), u_i.u==1
// (u_i.cmE.is_zero()?).enforce_equal(&Boolean::TRUE)?; // TODO not cmE=0, but check that cmE = cm(0)
(u_i.cmE.x.is_eq(&u_dummy.cmE.x)?)
.conditional_enforce_equal(&Boolean::TRUE, &is_not_basecase)?;
(u_i.cmE.y.is_eq(&u_dummy.cmE.y)?)
.conditional_enforce_equal(&Boolean::TRUE, &is_not_basecase)?;
(u_i.u.is_one()?).conditional_enforce_equal(&Boolean::TRUE, &is_not_basecase)?;

// 3. nifs.verify, checks that folding u_i & U_i obtains U_{i+1}.
Expand Down Expand Up @@ -420,7 +426,7 @@ mod tests {
let w2 = Witness::<Projective>::new(w2.clone(), r1cs.A.n_rows);

let mut rng = ark_std::test_rng();
let pedersen_params = Pedersen::<Projective>::new_params(&mut rng, r1cs.A.n_cols);
let pedersen_params = Pedersen::<Projective>::new_params(&mut rng, r1cs.A.n_rows);

// compute committed instances
let ci1 = w1.commit(&pedersen_params, x1.clone());
Expand All @@ -435,6 +441,9 @@ mod tests {
let (_w3, ci3, _T, cmT) =
NIFS::<Projective>::prove(&pedersen_params, r_Fr, &r1cs, &w1, &ci1, &w2, &ci2).unwrap();

let ci3_verifier = NIFS::<Projective>::verify(r_Fr, &ci1, &ci2, &cmT);
assert_eq!(ci3_verifier, ci3);

let cs = ConstraintSystem::<Fr>::new_ref();

let rVar = FpVar::<Fr>::new_witness(cs.clone(), || Ok(r_Fr)).unwrap();
Expand Down Expand Up @@ -570,19 +579,18 @@ mod tests {

let mut tr = PoseidonTranscript::<Projective>::new(&poseidon_config);

let pedersen_params = Pedersen::<Projective>::new_params(&mut rng, r1cs.A.n_cols);
let pedersen_params = Pedersen::<Projective>::new_params(&mut rng, r1cs.A.n_rows);

// first step
let z_0 = Fr::from(3_u32);
let mut z_i = z_0;
let z_i = z_0;
let mut z_i1 = Fr::from(35_u32);

// set the circuit to be folded with z_i=z_0=3 and z_{i+1}=35 (initial values)
let mut test_F_circuit = TestFCircuit::<Fr> { z_i, z_i1 };

let w_dummy = Witness::<Projective>::new(vec![Fr::zero(); F_witness_len], r1cs.A.n_rows);
let mut u_dummy = w_dummy.commit(&pedersen_params, vec![Fr::zero(); x.len()]);
u_dummy.u = Fr::zero();
let u_dummy = CommittedInstance::<Projective>::dummy(x.len());

// Wi is a 'dummy witness', all zeroes, but with the size corresponding to the R1CS that
// we're working with.
Expand All @@ -606,10 +614,6 @@ mod tests {
let mut u_i1_x: Fr;
let n_steps: usize = 4;
for _ in 0..n_steps {
dbg!(&i);
dbg!(&z_i);
dbg!(&z_i1);

if i == Fr::zero() {
// base case: i=0, z_i=z_0, U_i = U_d := dummy instance
// u_1.x = H(1, z_0, z_i, U_i)
Expand Down Expand Up @@ -684,7 +688,6 @@ mod tests {
}
assert!(is_satisfied);

println!("num_constraints={:?}", cs.num_constraints());
cs.finalize();
let cs = cs.into_inner().unwrap();
// notice that here we use 'Z' (uppercase) to denote the 'z-vector' as in the paper,
Expand All @@ -705,7 +708,7 @@ mod tests {
// set values for next iteration
i += Fr::one();
test_F_circuit.step(); // advance the F circuit state
(z_i, z_i1) = test_F_circuit.public();
(_, z_i1) = test_F_circuit.public();
U_i = U_i1.clone();
W_i = W_i1.clone();
}
Expand Down
17 changes: 15 additions & 2 deletions src/folding/nova/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use ark_std::{One, Zero};
use crate::ccs::r1cs::R1CS;
use crate::folding::circuits::nonnative::point_to_nonnative_limbs;
use crate::pedersen::{Params as PedersenParams, Pedersen};
use crate::utils::vec::is_zero_vec;
use crate::Error;

pub mod circuits;
Expand All @@ -28,6 +29,15 @@ where
<C as Group>::ScalarField: Absorb,
<C as ark_ec::CurveGroup>::BaseField: ark_ff::PrimeField,
{
pub fn dummy(io_len: usize) -> Self {
Self {
cmE: C::zero(),
u: C::ScalarField::zero(),
cmW: C::zero(),
x: vec![C::ScalarField::zero(); io_len],
}
}

/// hash implements the committed instance hash compatible with the gadget implemented in
/// nova/circuits.rs::CommittedInstanceVar.hash.
/// Returns `H(i, z_0, z_i, U_i)`, where `i` can be `i` but also `i+1`, and `U` is the
Expand Down Expand Up @@ -73,7 +83,7 @@ where
pub fn new(w: Vec<C::ScalarField>, e_len: usize) -> Self {
Self {
E: vec![C::ScalarField::zero(); e_len],
rE: C::ScalarField::one(),
rE: C::ScalarField::zero(), // because we use C::zero() as cmE
W: w,
rW: C::ScalarField::one(),
}
Expand All @@ -83,7 +93,10 @@ where
params: &PedersenParams<C>,
x: Vec<C::ScalarField>,
) -> CommittedInstance<C> {
let cmE = Pedersen::commit(params, &self.E, &self.rE);
let mut cmE = C::zero();
if !is_zero_vec::<C::ScalarField>(&self.E) {
cmE = Pedersen::commit(params, &self.E, &self.rE);
}
let cmW = Pedersen::commit(params, &self.W, &self.rW);
CommittedInstance {
cmE,
Expand Down
13 changes: 10 additions & 3 deletions src/folding/nova/nifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,13 @@ where
#[cfg(test)]
pub mod tests {
use super::*;
use crate::ccs::r1cs::tests::{get_test_r1cs, get_test_z};
use crate::transcript::poseidon::{tests::poseidon_test_config, PoseidonTranscript};
use ark_ff::PrimeField;
use ark_pallas::{Fr, Projective};
use ark_std::{UniformRand, Zero};
use ark_std::{ops::Mul, UniformRand, Zero};

use crate::ccs::r1cs::tests::{get_test_r1cs, get_test_z};
use crate::transcript::poseidon::{tests::poseidon_test_config, PoseidonTranscript};
use crate::utils::vec::vec_scalar_mul;

pub fn check_relaxed_r1cs<F: PrimeField>(r1cs: &R1CS<F>, z: &[F], u: &F, E: &[F]) -> bool {
let Az = mat_vec_mul_sparse(&r1cs.A, z);
Expand Down Expand Up @@ -275,6 +277,10 @@ pub mod tests {
assert_eq!(ci3_expected.cmE, ci3.cmE);
assert_eq!(ci3_expected.cmW, ci3.cmW);

// next equalities should hold since we started from two cmE of zero-vector E's
assert_eq!(ci3.cmE, cmT.mul(r));
assert_eq!(w3.E, vec_scalar_mul(&T, &r));

// NIFS.Verify_Folded_Instance:
NIFS::<Projective>::verify_folded_instance(r, &ci1, &ci2, &ci3, &cmT).unwrap();

Expand All @@ -294,6 +300,7 @@ pub mod tests {
&cmT,
)
.unwrap();

NIFS::<Projective>::verify_commitments(
&mut transcript_v,
&pedersen_params,
Expand Down

0 comments on commit 27665b1

Please sign in to comment.