Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nova vairants (Ova) NIFS abstraction #165

Merged
merged 4 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions folding-schemes/src/folding/circuits/cyclefold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use super::{nonnative::uint::NonNativeUintVar, CF1, CF2};
use crate::arith::r1cs::{extract_w_x, R1CS};
use crate::commitment::CommitmentScheme;
use crate::constants::NOVA_N_BITS_RO;
use crate::folding::nova::nifs::NIFS;
use crate::folding::nova::{nifs::NIFS, traits::NIFSTrait};
use crate::transcript::{AbsorbNonNative, AbsorbNonNativeGadget, Transcript, TranscriptVar};
use crate::Error;

Expand Down Expand Up @@ -570,9 +570,8 @@ where
let cf_r_Fq = C1::BaseField::from_bigint(BigInteger::from_bits_le(&cf_r_bits))
.expect("cf_r_bits out of bounds");

let (cf_W_i1, cf_U_i1) = NIFS::<C2, CS2, H>::fold_instances(
cf_r_Fq, &cf_W_i, &cf_U_i, &cf_w_i, &cf_u_i, &cf_T, cf_cmT,
)?;
let (cf_W_i1, cf_U_i1) =
NIFS::<C2, CS2, H>::prove(cf_r_Fq, &cf_W_i, &cf_U_i, &cf_w_i, &cf_u_i, &cf_T, &cf_cmT)?;
Ok((cf_w_i, cf_u_i, cf_W_i1, cf_U_i1, cf_cmT, cf_r_Fq))
}

Expand All @@ -584,10 +583,11 @@ pub mod tests {
poseidon::{constraints::PoseidonSpongeVar, PoseidonSponge},
};
use ark_r1cs_std::R1CSVar;
use ark_std::UniformRand;
use ark_std::{One, UniformRand};

use super::*;
use crate::folding::nova::nifs::tests::prepare_simple_fold_inputs;
use crate::commitment::pedersen::Pedersen;
use crate::folding::nova::CommittedInstance;
use crate::transcript::poseidon::poseidon_canonical_config;
use crate::utils::get_cm_coordinates;

Expand Down Expand Up @@ -669,12 +669,30 @@ pub mod tests {

#[test]
fn test_nifs_full_gadget() {
let (_, _, _, _, ci1, _, ci2, _, ci3, _, cmT, r_bits, _) = prepare_simple_fold_inputs();
let mut rng = ark_std::test_rng();

let cs = ConstraintSystem::<Fq>::new_ref();
// prepare the committed instances to test in-circuit
let ci: Vec<CommittedInstance<Projective>> = (0..2)
.into_iter()
.map(|_| CommittedInstance::<Projective> {
cmE: Projective::rand(&mut rng),
u: Fr::rand(&mut rng),
cmW: Projective::rand(&mut rng),
x: vec![Fr::rand(&mut rng); 1],
})
.collect();
let (ci1, mut ci2) = (ci[0].clone(), ci[1].clone());
// make the 2nd instance a 'fresh' instance (ie. cmE=0, u=1)
ci2.cmE = Projective::zero();
ci2.u = Fr::one();
let r_bits: Vec<bool> =
Fr::rand(&mut rng).into_bigint().to_bits_le()[..NOVA_N_BITS_RO].to_vec();
let r_Fr = Fr::from_bigint(BigInteger::from_bits_le(&r_bits)).unwrap();
let cmT = Projective::rand(&mut rng);
let ci3 = NIFS::<Projective, Pedersen<Projective>>::verify(r_Fr, &ci1, &ci2, &cmT);

let cs = ConstraintSystem::<Fq>::new_ref();
let r_bitsVar = Vec::<Boolean<Fq>>::new_witness(cs.clone(), || Ok(r_bits)).unwrap();

let ci1Var =
CycleFoldCommittedInstanceVar::<Projective, GVar>::new_witness(cs.clone(), || {
Ok(ci1.clone())
Expand Down
1 change: 0 additions & 1 deletion folding-schemes/src/folding/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pub mod circuits;
pub mod hypernova;
pub mod nova;
pub mod ova;
pub mod protogalaxy;
pub mod traits;
79 changes: 50 additions & 29 deletions folding-schemes/src/folding/nova/circuits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,11 @@ where

/// ChallengeGadget computes the RO challenge used for the Nova instances NIFS, it contains a
/// rust-native and a in-circuit compatible versions.
pub struct ChallengeGadget<C: CurveGroup> {
pub struct ChallengeGadget<C: CurveGroup, CI: Absorb> {
_c: PhantomData<C>,
_ci: PhantomData<CI>,
}
impl<C: CurveGroup> ChallengeGadget<C>
impl<C: CurveGroup, CI: Absorb> ChallengeGadget<C, CI>
where
C: CurveGroup,
<C as CurveGroup>::BaseField: PrimeField,
Expand All @@ -180,14 +181,17 @@ where
pub fn get_challenge_native<T: Transcript<C::ScalarField>>(
transcript: &mut T,
pp_hash: C::ScalarField, // public params hash
U_i: CommittedInstance<C>,
u_i: CommittedInstance<C>,
cmT: C,
U_i: &CI,
u_i: &CI,
cmT: Option<&C>,
) -> Vec<bool> {
transcript.absorb(&pp_hash);
transcript.absorb(&U_i);
transcript.absorb(&u_i);
transcript.absorb_nonnative(&cmT);
// in the Nova case we absorb the cmT, in Ova case we don't since it is not used.
if let Some(cmT_value) = cmT {
transcript.absorb_nonnative(cmT_value);
}
transcript.squeeze_bits(NOVA_N_BITS_RO)
}

Expand All @@ -197,12 +201,15 @@ where
pp_hash: FpVar<CF1<C>>, // public params hash
U_i_vec: Vec<FpVar<CF1<C>>>, // apready processed input, so we don't have to recompute these values
u_i: CommittedInstanceVar<C>,
cmT: NonNativeAffineVar<C>,
cmT: Option<NonNativeAffineVar<C>>,
) -> Result<Vec<Boolean<C::ScalarField>>, SynthesisError> {
transcript.absorb(&pp_hash)?;
transcript.absorb(&U_i_vec)?;
transcript.absorb(&u_i)?;
transcript.absorb_nonnative(&cmT)?;
// in the Nova case we absorb the cmT, in Ova case we don't since it is not used.
if let Some(cmT_value) = cmT {
transcript.absorb_nonnative(&cmT_value)?;
}
transcript.squeeze_bits(NOVA_N_BITS_RO)
}
}
Expand Down Expand Up @@ -376,12 +383,12 @@ where
// P.3. nifs.verify, obtains U_{i+1} by folding u_i & U_i .

// compute r = H(u_i, U_i, cmT)
let r_bits = ChallengeGadget::<C1>::get_challenge_gadget(
let r_bits = ChallengeGadget::<C1, CommittedInstance<C1>>::get_challenge_gadget(
&mut transcript,
pp_hash.clone(),
U_i_vec,
u_i.clone(),
cmT.clone(),
Some(cmT.clone()),
)?;
let r = Boolean::le_bits_to_fp_var(&r_bits)?;
// Also convert r_bits to a `NonNativeFieldVar`
Expand Down Expand Up @@ -522,8 +529,8 @@ pub mod tests {
use ark_std::UniformRand;

use crate::commitment::pedersen::Pedersen;
use crate::folding::nova::nifs::tests::prepare_simple_fold_inputs;
use crate::folding::nova::nifs::NIFS;
use crate::folding::nova::traits::NIFSTrait;
use crate::folding::traits::CommittedInstanceOps;
use crate::transcript::poseidon::poseidon_canonical_config;

Expand All @@ -550,10 +557,22 @@ pub mod tests {

#[test]
fn test_nifs_gadget() {
let (_, _, _, _, ci1, _, ci2, _, ci3, _, cmT, _, r_Fr) = prepare_simple_fold_inputs();
let mut rng = ark_std::test_rng();

let ci3_verifier = NIFS::<Projective, Pedersen<Projective>>::verify(r_Fr, &ci1, &ci2, &cmT);
assert_eq!(ci3_verifier, ci3);
// prepare the committed instances to test in-circuit
let ci: Vec<CommittedInstance<Projective>> = (0..2)
.into_iter()
.map(|_| CommittedInstance::<Projective> {
cmE: Projective::rand(&mut rng),
u: Fr::rand(&mut rng),
cmW: Projective::rand(&mut rng),
x: vec![Fr::rand(&mut rng); 1],
})
.collect();
let (ci1, ci2) = (ci[0].clone(), ci[1].clone());
let r_Fr = Fr::rand(&mut rng);
let cmT = Projective::rand(&mut rng);
let ci3 = NIFS::<Projective, Pedersen<Projective>>::verify(r_Fr, &ci1, &ci2, &cmT);

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

Expand Down Expand Up @@ -673,13 +692,14 @@ pub mod tests {
let pp_hash = Fr::from(42u32); // only for testing

// compute the challenge natively
let r_bits = ChallengeGadget::<Projective>::get_challenge_native(
&mut transcript,
pp_hash,
U_i.clone(),
u_i.clone(),
cmT,
);
let r_bits =
ChallengeGadget::<Projective, CommittedInstance<Projective>>::get_challenge_native(
&mut transcript,
pp_hash,
&U_i,
&u_i,
Some(&cmT),
);
let r = Fr::from_bigint(BigInteger::from_bits_le(&r_bits)).unwrap();

let cs = ConstraintSystem::<Fr>::new_ref();
Expand All @@ -701,14 +721,15 @@ pub mod tests {
U_iVar.cmW.to_constraint_field().unwrap(),
]
.concat();
let r_bitsVar = ChallengeGadget::<Projective>::get_challenge_gadget(
&mut transcriptVar,
pp_hashVar,
U_iVar_vec,
u_iVar,
cmTVar,
)
.unwrap();
let r_bitsVar =
ChallengeGadget::<Projective, CommittedInstance<Projective>>::get_challenge_gadget(
&mut transcriptVar,
pp_hashVar,
U_iVar_vec,
u_iVar,
Some(cmTVar),
)
.unwrap();
assert!(cs.is_satisfied().unwrap());

// check that the natively computed and in-circuit computed hashes match
Expand Down
2 changes: 1 addition & 1 deletion folding-schemes/src/folding/nova/decider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use ark_std::{One, Zero};
use core::marker::PhantomData;

use super::decider_circuits::{DeciderCircuit1, DeciderCircuit2};
use super::{nifs::NIFS, CommittedInstance, Nova};
use super::{nifs::NIFS, traits::NIFSTrait, CommittedInstance, Nova};
use crate::commitment::CommitmentScheme;
use crate::folding::circuits::{
cyclefold::CycleFoldCommittedInstance,
Expand Down
18 changes: 9 additions & 9 deletions folding-schemes/src/folding/nova/decider_circuits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use super::{
circuits::{ChallengeGadget, CommittedInstanceVar},
decider_eth_circuit::{KZGChallengesGadget, R1CSVar, RelaxedR1CSGadget, WitnessVar},
nifs::NIFS,
traits::NIFSTrait,
CommittedInstance, Nova, Witness,
};
use crate::arith::r1cs::R1CS;
Expand Down Expand Up @@ -122,18 +123,17 @@ where
&nova.W_i.clone(),
&nova.U_i.clone(),
)?;
let r_bits = ChallengeGadget::<C1>::get_challenge_native(
let r_bits = NIFS::<C1, CS1, H>::get_challenge(
&mut transcript,
nova.pp_hash,
nova.U_i.clone(),
nova.u_i.clone(),
cmT,
&nova.U_i,
&nova.u_i,
&cmT,
);
let r_Fr = C1::ScalarField::from_bigint(BigInteger::from_bits_le(&r_bits))
.ok_or(Error::OutOfBounds)?;
let (W_i1, U_i1) = NIFS::<C1, CS1, H>::fold_instances(
r_Fr, &nova.W_i, &nova.U_i, &nova.w_i, &nova.u_i, &T, cmT,
)?;
let (W_i1, U_i1) =
NIFS::<C1, CS1, H>::prove(r_Fr, &nova.W_i, &nova.U_i, &nova.w_i, &nova.u_i, &T, &cmT)?;

// compute the commitment scheme challenges used as inputs in the circuit
let (cs_challenge_W, cs_challenge_E) =
Expand Down Expand Up @@ -283,12 +283,12 @@ where
// do the actual checks later.
let cmT =
NonNativeAffineVar::new_input(cs.clone(), || Ok(self.cmT.unwrap_or_else(C1::zero)))?;
let r_bits = ChallengeGadget::<C1>::get_challenge_gadget(
let r_bits = ChallengeGadget::<C1, CommittedInstance<C1>>::get_challenge_gadget(
&mut transcript,
pp_hash,
U_i_vec,
u_i.clone(),
cmT.clone(),
Some(cmT.clone()),
)?;
// 5.1.
let (incircuit_c_W, incircuit_c_E) =
Expand Down
1 change: 1 addition & 0 deletions folding-schemes/src/folding/nova/decider_eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use ark_std::{One, Zero};
use core::marker::PhantomData;

pub use super::decider_eth_circuit::DeciderEthCircuit;
use super::traits::NIFSTrait;
use super::{nifs::NIFS, CommittedInstance, Nova};
use crate::commitment::{
kzg::{Proof as KZGProof, KZG},
Expand Down
20 changes: 11 additions & 9 deletions folding-schemes/src/folding/nova/decider_eth_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use core::{borrow::Borrow, marker::PhantomData};
use super::{
circuits::{ChallengeGadget, CommittedInstanceVar},
nifs::NIFS,
traits::NIFSTrait,
CommittedInstance, Nova, Witness,
};
use crate::commitment::{pedersen::Params as PedersenParams, CommitmentScheme};
Expand Down Expand Up @@ -245,25 +246,26 @@ where
let mut transcript = PoseidonSponge::<C1::ScalarField>::new(&nova.poseidon_config);

// compute the U_{i+1}, W_{i+1}
let (T, cmT) = NIFS::<C1, CS1, H>::compute_cmT(
let (aux_p, aux_v) = NIFS::<C1, CS1, H>::compute_aux(
&nova.cs_pp,
&nova.r1cs.clone(),
&nova.w_i.clone(),
&nova.u_i.clone(),
&nova.W_i.clone(),
&nova.U_i.clone(),
)?;
let r_bits = ChallengeGadget::<C1>::get_challenge_native(
let cmT = aux_v;
let r_bits = ChallengeGadget::<C1, CommittedInstance<C1>>::get_challenge_native(
&mut transcript,
nova.pp_hash,
nova.U_i.clone(),
nova.u_i.clone(),
cmT,
&nova.U_i,
&nova.u_i,
Some(&cmT),
);
let r_Fr = C1::ScalarField::from_bigint(BigInteger::from_bits_le(&r_bits))
.ok_or(Error::OutOfBounds)?;
let (W_i1, U_i1) = NIFS::<C1, CS1, H>::fold_instances(
r_Fr, &nova.W_i, &nova.U_i, &nova.w_i, &nova.u_i, &T, cmT,
let (W_i1, U_i1) = NIFS::<C1, CS1, H>::prove(
r_Fr, &nova.W_i, &nova.U_i, &nova.w_i, &nova.u_i, &aux_p, &aux_v,
)?;

// compute the KZG challenges used as inputs in the circuit
Expand Down Expand Up @@ -483,12 +485,12 @@ where
let cmT =
NonNativeAffineVar::new_input(cs.clone(), || Ok(self.cmT.unwrap_or_else(C1::zero)))?;
// 1.1.a
let r_bits = ChallengeGadget::<C1>::get_challenge_gadget(
let r_bits = ChallengeGadget::<C1, CommittedInstance<C1>>::get_challenge_gadget(
&mut transcript,
pp_hash,
U_i_vec,
u_i.clone(),
cmT.clone(),
Some(cmT),
)?;
// 5.1.
let (incircuit_c_W, incircuit_c_E) =
Expand Down
Loading
Loading