Skip to content

Commit

Permalink
Inputize trait
Browse files Browse the repository at this point in the history
  • Loading branch information
winderica committed Oct 4, 2024
1 parent 2aca8ed commit 60e9e58
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 99 deletions.
42 changes: 37 additions & 5 deletions folding-schemes/src/folding/circuits/cyclefold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,59 @@ use ark_relations::r1cs::{
};
use ark_std::fmt::Debug;
use ark_std::rand::RngCore;
use ark_std::Zero;
use ark_std::{One, Zero};
use core::{borrow::Borrow, marker::PhantomData};

use super::{nonnative::uint::NonNativeUintVar, CF1, CF2};
use crate::arith::{
r1cs::{circuits::R1CSMatricesVar, extract_w_x, R1CS},
ArithGadget,
};
use crate::commitment::CommitmentScheme;
use crate::constants::NOVA_N_BITS_RO;
use crate::folding::nova::{nifs::NIFS, traits::NIFSTrait};
use crate::transcript::{AbsorbNonNative, AbsorbNonNativeGadget, Transcript, TranscriptVar};
use crate::utils::gadgets::{EquivalenceGadget, VectorGadget};
use crate::Error;
use crate::{
arith::{
r1cs::{circuits::R1CSMatricesVar, extract_w_x, R1CS},
ArithGadget,
},
folding::traits::Inputize,
};

/// Re-export the Nova committed instance as `CycleFoldCommittedInstance` and
/// witness as `CycleFoldWitness`, for clarity and consistency
pub use crate::folding::nova::{
CommittedInstance as CycleFoldCommittedInstance, Witness as CycleFoldWitness,
};

impl<C: CurveGroup, GC: CurveVar<C, CF2<C>>> Inputize<CF2<C>, CycleFoldCommittedInstanceVar<C, GC>>
for CycleFoldCommittedInstance<C>
{
fn inputize(&self) -> Vec<CF2<C>> {
let zero = (&C::BaseField::zero(), &C::BaseField::zero());
let cmE = self.cmE.into_affine();
let cmW = self.cmW.into_affine();
let (cmE_x, cmE_y) = cmE.xy().unwrap_or(zero);
let (cmW_x, cmW_y) = cmW.xy().unwrap_or(zero);
self.u
.inputize()
.into_iter()
.chain(self.x.iter().flat_map(|x| x.inputize()))
.chain(
[
*cmE_x,
*cmE_y,
C::BaseField::one(),
*cmW_x,
*cmW_y,
C::BaseField::one(),
]
.into_iter()
.flat_map(|x| x.to_base_prime_field_elements()),
)
.collect()
}
}

/// CycleFoldCommittedInstanceVar is the CycleFold CommittedInstance represented
/// in folding verifier circuit
#[derive(Debug, Clone)]
Expand Down
31 changes: 17 additions & 14 deletions folding-schemes/src/folding/circuits/nonnative/affine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ use ark_serialize::{CanonicalSerialize, CanonicalSerializeWithFlags};
use ark_std::Zero;
use core::borrow::Borrow;

use crate::transcript::{AbsorbNonNative, AbsorbNonNativeGadget};
use crate::{
folding::traits::Inputize,
transcript::{AbsorbNonNative, AbsorbNonNativeGadget},
};

use super::uint::{nonnative_field_to_field_elements, NonNativeUintVar};

Expand Down Expand Up @@ -104,21 +107,19 @@ pub(crate) fn nonnative_affine_to_field_elements<C: CurveGroup>(
(x, y)
}

impl<C: CurveGroup> NonNativeAffineVar<C> {
// Extracts a list of field elements of type `C::ScalarField` from the public input
// `p`, in exactly the same way as how `NonNativeAffineVar` is represented as limbs of type
// `FpVar` in-circuit.
#[allow(clippy::type_complexity)]
pub fn inputize(p: C) -> Result<(Vec<C::ScalarField>, Vec<C::ScalarField>), SynthesisError> {
let affine = p.into_affine();
impl<C: CurveGroup> Inputize<C::ScalarField, NonNativeAffineVar<C>> for C {
fn inputize(&self) -> Vec<C::ScalarField> {
let affine = self.into_affine();
let zero = (&C::BaseField::zero(), &C::BaseField::zero());
let (x, y) = affine.xy().unwrap_or(zero);

let x = NonNativeUintVar::inputize(*x);
let y = NonNativeUintVar::inputize(*y);
Ok((x, y))
let x = x.inputize();
let y = y.inputize();
[x, y].concat()
}
}

impl<C: CurveGroup> NonNativeAffineVar<C> {
pub fn zero() -> Self {
Self::new_constant(ConstraintSystemRef::None, C::zero()).unwrap()
}
Expand Down Expand Up @@ -179,9 +180,11 @@ mod tests {
let mut rng = ark_std::test_rng();
let p = Projective::rand(&mut rng);
let pVar = NonNativeAffineVar::<Projective>::new_witness(cs.clone(), || Ok(p)).unwrap();
let (x, y) = NonNativeAffineVar::inputize(p).unwrap();
let xy = p.inputize();

assert_eq!(pVar.x.0.value().unwrap(), x);
assert_eq!(pVar.y.0.value().unwrap(), y);
assert_eq!(
[pVar.x.0.value().unwrap(), pVar.y.0.value().unwrap()].concat(),
xy
);
}
}
9 changes: 5 additions & 4 deletions folding-schemes/src/folding/circuits/nonnative/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use num_bigint::BigUint;
use num_integer::Integer;

use crate::{
folding::traits::Inputize,
transcript::{AbsorbNonNative, AbsorbNonNativeGadget},
utils::gadgets::{EquivalenceGadget, MatrixGadget, SparseMatrixVar, VectorGadget},
};
Expand Down Expand Up @@ -259,15 +260,15 @@ impl<F: PrimeField, G: Field> AllocVar<G, F> for NonNativeUintVar<F> {
}
}

impl<F: PrimeField> NonNativeUintVar<F> {
pub fn inputize<T: Field>(x: T) -> Vec<F> {
impl<F: PrimeField, T: Field> Inputize<F, NonNativeUintVar<F>> for T {
fn inputize(&self) -> Vec<F> {
assert_eq!(T::extension_degree(), 1);
x.to_base_prime_field_elements()
self.to_base_prime_field_elements()
.next()
.unwrap()
.into_bigint()
.to_bits_le()
.chunks(Self::bits_per_limb())
.chunks(NonNativeUintVar::<F>::bits_per_limb())
.map(|chunk| F::from_bigint(F::BigInt::from_bits_le(chunk)).unwrap())
.collect()
}
Expand Down
7 changes: 7 additions & 0 deletions folding-schemes/src/folding/hypernova/cccs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use super::Witness;
use crate::arith::{ccs::CCS, Arith};
use crate::commitment::CommitmentScheme;
use crate::folding::circuits::CF1;
use crate::folding::traits::Inputize;
use crate::folding::traits::{CommittedInstanceOps, Dummy};
use crate::transcript::AbsorbNonNative;
use crate::utils::mle::dense_vec_to_dense_mle;
Expand Down Expand Up @@ -152,6 +153,12 @@ impl<C: CurveGroup> CommittedInstanceOps<C> for CCCS<C> {
}
}

impl<C: CurveGroup> Inputize<C::ScalarField, CCCSVar<C>> for CCCS<C> {
fn inputize(&self) -> Vec<C::ScalarField> {
[&self.C.inputize()[..], &self.x].concat()
}
}

#[cfg(test)]
pub mod tests {
use ark_pallas::Fr;
Expand Down
13 changes: 3 additions & 10 deletions folding-schemes/src/folding/hypernova/decider_eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ use super::{lcccs::LCCCS, HyperNova};
use crate::commitment::{
kzg::Proof as KZGProof, pedersen::Params as PedersenParams, CommitmentScheme,
};
use crate::folding::circuits::{nonnative::affine::NonNativeAffineVar, CF2};
use crate::folding::circuits::CF2;
use crate::folding::nova::decider_eth::VerifierParam;
use crate::folding::traits::Inputize;
use crate::frontend::FCircuit;
use crate::Error;
use crate::{Decider as DeciderTrait, FoldingScheme};
Expand Down Expand Up @@ -192,19 +193,11 @@ where
// Note: the NIMFS proof is checked inside the DeciderEthCircuit, which ensures that the
// 'proof.U_i1' is correctly computed

let (cmC_x, cmC_y) = NonNativeAffineVar::inputize(proof.U_i1.C)?;

let public_input: Vec<C1::ScalarField> = [
vec![pp_hash, i],
z_0,
z_i,
// U_i+1:
cmC_x,
cmC_y,
vec![proof.U_i1.u],
proof.U_i1.x.clone(),
proof.U_i1.r_x.clone(),
proof.U_i1.v.clone(),
proof.U_i1.inputize(),
vec![proof.kzg_challenge, proof.kzg_proof.eval, proof.rho],
]
.concat();
Expand Down
14 changes: 14 additions & 0 deletions folding-schemes/src/folding/hypernova/lcccs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::arith::ccs::CCS;
use crate::arith::Arith;
use crate::commitment::CommitmentScheme;
use crate::folding::circuits::CF1;
use crate::folding::traits::Inputize;
use crate::folding::traits::{CommittedInstanceOps, Dummy};
use crate::transcript::AbsorbNonNative;
use crate::utils::mle::dense_vec_to_dense_mle;
Expand Down Expand Up @@ -154,6 +155,19 @@ impl<C: CurveGroup> CommittedInstanceOps<C> for LCCCS<C> {
}
}

impl<C: CurveGroup> Inputize<C::ScalarField, LCCCSVar<C>> for LCCCS<C> {
fn inputize(&self) -> Vec<C::ScalarField> {
[
&self.C.inputize(),
&[self.u][..],
&self.x,
&self.r_x,
&self.v,
]
.concat()
}
}

#[cfg(test)]
pub mod tests {
use ark_pallas::{Fr, Projective};
Expand Down
51 changes: 7 additions & 44 deletions folding-schemes/src/folding/nova/decider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/// More details can be found at the documentation page:
/// https://privacy-scaling-explorations.github.io/sonobe-docs/design/nova-decider-offchain.html
use ark_crypto_primitives::sponge::Absorb;
use ark_ec::{AffineRepr, CurveGroup, Group};
use ark_ec::{CurveGroup, Group};
use ark_ff::{BigInteger, PrimeField};
use ark_r1cs_std::{groups::GroupOpsBounds, prelude::CurveVar, ToConstraintFieldGadget};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
Expand All @@ -16,10 +16,10 @@ use super::decider_circuits::{DeciderCircuit1, DeciderCircuit2};
use super::{nifs::NIFS, traits::NIFSTrait, CommittedInstance, Nova};
use crate::commitment::CommitmentScheme;
use crate::folding::circuits::{
cyclefold::CycleFoldCommittedInstance,
nonnative::{affine::NonNativeAffineVar, uint::NonNativeUintVar},
cyclefold::{CycleFoldCommittedInstance, CycleFoldCommittedInstanceVar},
CF2,
};
use crate::folding::traits::Inputize;
use crate::frontend::FCircuit;
use crate::Error;
use crate::{Decider as DeciderTrait, FoldingScheme};
Expand Down Expand Up @@ -288,50 +288,21 @@ where
// compute U = U_{d+1}= NIFS.V(U_d, u_d, cmT)
let U = NIFS::<C1, CS1>::verify(proof.r, running_instance, incoming_instance, &proof.cmT);

let (cmE_x, cmE_y) = NonNativeAffineVar::inputize(U.cmE)?;
let (cmW_x, cmW_y) = NonNativeAffineVar::inputize(U.cmW)?;
let (cmT_x, cmT_y) = NonNativeAffineVar::inputize(proof.cmT)?;

let zero = (&C2::BaseField::zero(), &C2::BaseField::zero());
let cmE_affine = proof.cf_U_i.cmE.into_affine();
let cmW_affine = proof.cf_U_i.cmW.into_affine();
let (cf_cmE_x, cf_cmE_y) = cmE_affine.xy().unwrap_or(zero);
let cf_cmE_z = C1::ScalarField::one();
let (cf_cmW_x, cf_cmW_y) = cmW_affine.xy().unwrap_or(zero);
let cf_cmW_z = C1::ScalarField::one();

// snark proof 1
let c1_public_input: Vec<C1::ScalarField> = [
vec![vp.pp_hash, i],
z_0,
z_i,
// U_{i+1} values:
vec![U.u],
U.x.clone(),
cmE_x,
cmE_y,
cmW_x,
cmW_y,
U.inputize(),
// CS1 values:
proof.cs1_challenges.to_vec(), // c_W, c_E
vec![
proof.cs1_proofs[0].eval, // eval_W
proof.cs1_proofs[1].eval, // eval_E
],
// cf_U_i values
NonNativeUintVar::<CF2<C2>>::inputize(proof.cf_U_i.u),
proof
.cf_U_i
.x
.iter()
.flat_map(|&x_i| NonNativeUintVar::<CF2<C2>>::inputize(x_i))
.collect::<Vec<C1::ScalarField>>(),
vec![
*cf_cmE_x, *cf_cmE_y, cf_cmE_z, *cf_cmW_x, *cf_cmW_y, cf_cmW_z,
],
Inputize::<CF2<C2>, CycleFoldCommittedInstanceVar<C2, GC2>>::inputize(&proof.cf_U_i),
// NIFS values:
cmT_x,
cmT_y,
proof.cmT.inputize(),
vec![proof.r],
]
.concat();
Expand All @@ -342,21 +313,13 @@ where
return Err(Error::SNARKVerificationFail);
}

let (cf2_cmE_x, cf2_cmE_y) = NonNativeAffineVar::inputize(proof.cf_U_i.cmE)?;
let (cf2_cmW_x, cf2_cmW_y) = NonNativeAffineVar::inputize(proof.cf_U_i.cmW)?;

// snark proof 2
// migrate pp_hash from C1::Fr to C1::Fq
let pp_hash_Fq =
C2::ScalarField::from_le_bytes_mod_order(&vp.pp_hash.into_bigint().to_bytes_le());
let c2_public_input: Vec<C2::ScalarField> = [
vec![pp_hash_Fq],
vec![proof.cf_U_i.u],
proof.cf_U_i.x.clone(),
cf2_cmE_x,
cf2_cmE_y,
cf2_cmW_x,
cf2_cmW_y,
proof.cf_U_i.inputize(),
proof.cs2_challenges.to_vec(),
vec![
proof.cs2_proofs[0].eval, // eval_W
Expand Down
17 changes: 4 additions & 13 deletions folding-schemes/src/folding/nova/decider_eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ use crate::commitment::{
pedersen::Params as PedersenParams,
CommitmentScheme,
};
use crate::folding::circuits::{nonnative::affine::NonNativeAffineVar, CF2};
use crate::folding::circuits::CF2;
use crate::folding::traits::Inputize;
use crate::frontend::FCircuit;
use crate::Error;
use crate::{Decider as DeciderTrait, FoldingScheme};
Expand Down Expand Up @@ -212,27 +213,17 @@ where
// compute U = U_{d+1}= NIFS.V(U_d, u_d, cmT)
let U = NIFS::<C1, CS1>::verify(proof.r, running_instance, incoming_instance, &proof.cmT);

let (cmE_x, cmE_y) = NonNativeAffineVar::inputize(U.cmE)?;
let (cmW_x, cmW_y) = NonNativeAffineVar::inputize(U.cmW)?;
let (cmT_x, cmT_y) = NonNativeAffineVar::inputize(proof.cmT)?;

let public_input: Vec<C1::ScalarField> = [
vec![vp.pp_hash, i],
z_0,
z_i,
vec![U.u],
U.x.clone(),
cmE_x,
cmE_y,
cmW_x,
cmW_y,
U.inputize(),
proof.kzg_challenges.to_vec(),
vec![
proof.kzg_proofs[0].eval, // eval_W
proof.kzg_proofs[1].eval, // eval_E
],
cmT_x,
cmT_y,
proof.cmT.inputize(),
vec![proof.r],
]
.concat();
Expand Down
14 changes: 13 additions & 1 deletion folding-schemes/src/folding/nova/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub mod decider_circuits;
pub mod decider_eth;
pub mod decider_eth_circuit;

use super::traits::{CommittedInstanceOps, WitnessOps};
use super::traits::{CommittedInstanceOps, Inputize, WitnessOps};

/// Configuration for Nova's CycleFold circuit
pub struct NovaCycleFoldConfig<C: CurveGroup> {
Expand Down Expand Up @@ -134,6 +134,18 @@ impl<C: CurveGroup> CommittedInstanceOps<C> for CommittedInstance<C> {
}
}

impl<C: CurveGroup> Inputize<C::ScalarField, CommittedInstanceVar<C>> for CommittedInstance<C> {
fn inputize(&self) -> Vec<C::ScalarField> {
[
&[self.u][..],
&self.x,
&self.cmE.inputize(),
&self.cmW.inputize(),
]
.concat()
}
}

#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
pub struct Witness<C: CurveGroup> {
pub E: Vec<C::ScalarField>,
Expand Down
Loading

0 comments on commit 60e9e58

Please sign in to comment.