add hash of public params for Nova & HyperNova (#118)

- implement hash of public params for Nova & HyperNova
- abstract pp_hash computation for folding schemes
- add pp_hash to solidity contract generator to verify the decider proof
This commit is contained in:
2024-07-05 11:47:18 +02:00
committed by GitHub
parent b5667968f4
commit c17fcf56c6
33 changed files with 665 additions and 406 deletions

View File

@@ -7,7 +7,7 @@ use std::sync::Arc;
use ark_std::rand::Rng;
use super::Witness;
use crate::ccs::CCS;
use crate::arith::{ccs::CCS, Arith};
use crate::commitment::CommitmentScheme;
use crate::utils::mle::dense_vec_to_dense_mle;
use crate::utils::vec::mat_vec_mul;
@@ -125,7 +125,7 @@ pub mod tests {
use ark_std::UniformRand;
use super::*;
use crate::ccs::tests::{get_test_ccs, get_test_z};
use crate::arith::ccs::tests::{get_test_ccs, get_test_z};
use crate::utils::hypercube::BooleanHypercube;
/// Do some sanity checks on q(x). It's a multivariable polynomial and it should evaluate to zero inside the

View File

@@ -44,7 +44,7 @@ use crate::frontend::FCircuit;
use crate::utils::virtual_polynomial::VPAuxInfo;
use crate::Error;
use crate::{
ccs::{r1cs::extract_r1cs, CCS},
arith::{ccs::CCS, r1cs::extract_r1cs},
transcript::{
poseidon::{PoseidonTranscript, PoseidonTranscriptVar},
Transcript, TranscriptVar,
@@ -143,6 +143,7 @@ where
pub fn hash(
self,
crh_params: &CRHParametersVar<CF1<C>>,
pp_hash: FpVar<CF1<C>>,
i: FpVar<CF1<C>>,
z_0: Vec<FpVar<CF1<C>>>,
z_i: Vec<FpVar<CF1<C>>>,
@@ -155,7 +156,7 @@ where
self.v,
]
.concat();
let input = [vec![i], z_0, z_i, U_vec.clone()].concat();
let input = [vec![pp_hash, i], z_0, z_i, U_vec.clone()].concat();
Ok((
CRHGadget::<C::ScalarField>::evaluate(crh_params, &input)?,
U_vec,
@@ -455,6 +456,7 @@ pub struct AugmentedFCircuit<
pub _gc2: PhantomData<GC2>,
pub poseidon_config: PoseidonConfig<CF1<C1>>,
pub ccs: CCS<C1::ScalarField>, // CCS of the AugmentedFCircuit
pub pp_hash: Option<CF1<C1>>,
pub i: Option<CF1<C1>>,
pub i_usize: Option<usize>,
pub z_0: Option<Vec<C1::ScalarField>>,
@@ -497,6 +499,7 @@ where
_gc2: PhantomData,
poseidon_config: poseidon_config.clone(),
ccs,
pp_hash: None,
i: None,
i_usize: None,
z_0: None,
@@ -559,6 +562,7 @@ where
let mut transcript_p: PoseidonTranscript<C1> =
PoseidonTranscript::<C1>::new(&self.poseidon_config.clone());
// since this is only for the number of constraints, no need to absorb the pp_hash here
let (nimfs_proof, U_i1, _, _) = NIMFS::<C1, PoseidonTranscript<C1>>::prove(
&mut transcript_p,
&ccs,
@@ -573,6 +577,7 @@ where
_gc2: PhantomData,
poseidon_config: self.poseidon_config.clone(),
ccs: ccs.clone(),
pp_hash: Some(C1::ScalarField::zero()),
i: Some(C1::ScalarField::zero()),
i_usize: Some(0),
z_0: Some(z_0.clone()),
@@ -624,6 +629,9 @@ where
for<'a> &'a GC2: GroupOpsBounds<'a, C2, GC2>,
{
fn generate_constraints(self, cs: ConstraintSystemRef<CF1<C1>>) -> Result<(), SynthesisError> {
let pp_hash = FpVar::<CF1<C1>>::new_witness(cs.clone(), || {
Ok(self.pp_hash.unwrap_or_else(CF1::<C1>::zero))
})?;
let i = FpVar::<CF1<C1>>::new_witness(cs.clone(), || {
Ok(self.i.unwrap_or_else(CF1::<C1>::zero))
})?;
@@ -680,11 +688,15 @@ where
// Primary Part
// P.1. Compute u_i.x
// u_i.x[0] = H(i, z_0, z_i, U_i)
let (u_i_x, _) = U_i
.clone()
.hash(&crh_params, i.clone(), z_0.clone(), z_i.clone())?;
let (u_i_x, _) = U_i.clone().hash(
&crh_params,
pp_hash.clone(),
i.clone(),
z_0.clone(),
z_i.clone(),
)?;
// u_i.x[1] = H(cf_U_i)
let (cf_u_i_x, cf_U_i_vec) = cf_U_i.clone().hash(&crh_params)?;
let (cf_u_i_x, cf_U_i_vec) = cf_U_i.clone().hash(&crh_params, pp_hash.clone())?;
// P.2. Construct u_i
let u_i = CCCSVar::<C1> {
@@ -700,8 +712,9 @@ where
// Notice that NIMFSGadget::fold_committed_instance does not fold C. We set `U_i1.C` to
// unconstrained witnesses `U_i1_C` respectively. Its correctness will be checked on the
// other curve.
let transcript =
let mut transcript =
PoseidonTranscriptVar::<C1::ScalarField>::new(cs.clone(), &self.poseidon_config);
transcript.absorb(pp_hash.clone())?;
let (mut U_i1, rho_bits) = NIMFSGadget::<C1>::verify(
cs.clone(),
&self.ccs.clone(),
@@ -716,12 +729,14 @@ where
// P.4.a compute and check the first output of F'
let (u_i1_x, _) = U_i1.clone().hash(
&crh_params,
pp_hash.clone(),
i + FpVar::<CF1<C1>>::one(),
z_0.clone(),
z_i1.clone(),
)?;
let (u_i1_x_base, _) = LCCCSVar::new_constant(cs.clone(), U_dummy)?.hash(
&crh_params,
pp_hash.clone(),
FpVar::<CF1<C1>>::one(),
z_0.clone(),
z_i1.clone(),
@@ -763,6 +778,7 @@ where
let cf_r_bits = CycleFoldChallengeGadget::<C2, GC2>::get_challenge_gadget(
cs.clone(),
&self.poseidon_config,
pp_hash.clone(),
cf_U_i_vec,
cf_u_i.clone(),
cf_cmT.clone(),
@@ -786,10 +802,10 @@ where
// P.4.b compute and check the second output of F'
// Base case: u_{i+1}.x[1] == H(cf_U_{\bot})
// Non-base case: u_{i+1}.x[1] == H(cf_U_{i+1})
let (cf_u_i1_x, _) = cf_U_i1.clone().hash(&crh_params)?;
let (cf_u_i1_x, _) = cf_U_i1.clone().hash(&crh_params, pp_hash.clone())?;
let (cf_u_i1_x_base, _) =
CycleFoldCommittedInstanceVar::new_constant(cs.clone(), cf_u_dummy)?
.hash(&crh_params)?;
.hash(&crh_params, pp_hash)?;
let cf_x = FpVar::new_input(cs.clone(), || {
Ok(self.cf_x.unwrap_or(cf_u_i1_x_base.value()?))
})?;
@@ -810,10 +826,12 @@ mod tests {
use super::*;
use crate::{
ccs::{
arith::{
ccs::{
tests::{get_test_ccs, get_test_z},
CCS,
},
r1cs::extract_w_x,
tests::{get_test_ccs, get_test_z},
CCS,
},
commitment::{pedersen::Pedersen, CommitmentScheme},
folding::{
@@ -1049,6 +1067,7 @@ mod tests {
let (pedersen_params, _) =
Pedersen::<Projective>::setup(&mut rng, ccs.n - ccs.l - 1).unwrap();
let pp_hash = Fr::from(42u32); // only for test
let i = Fr::from(3_u32);
let z_0 = vec![Fr::from(3_u32)];
@@ -1058,19 +1077,26 @@ mod tests {
.unwrap();
let h = lcccs
.clone()
.hash(&poseidon_config, i, z_0.clone(), z_i.clone())
.hash(&poseidon_config, pp_hash, i, z_0.clone(), z_i.clone())
.unwrap();
let cs = ConstraintSystem::<Fr>::new_ref();
let crh_params = CRHParametersVar::<Fr>::new_constant(cs.clone(), poseidon_config).unwrap();
let pp_hashVar = FpVar::<Fr>::new_witness(cs.clone(), || Ok(pp_hash)).unwrap();
let iVar = FpVar::<Fr>::new_witness(cs.clone(), || Ok(i)).unwrap();
let z_0Var = Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(z_0.clone())).unwrap();
let z_iVar = Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(z_i.clone())).unwrap();
let lcccsVar = LCCCSVar::<Projective>::new_witness(cs.clone(), || Ok(lcccs)).unwrap();
let (hVar, _) = lcccsVar
.clone()
.hash(&crh_params, iVar.clone(), z_0Var.clone(), z_iVar.clone())
.hash(
&crh_params,
pp_hashVar,
iVar.clone(),
z_0Var.clone(),
z_iVar.clone(),
)
.unwrap();
assert!(cs.is_satisfied().unwrap());
@@ -1112,6 +1138,9 @@ mod tests {
let (cf_pedersen_params, _) =
Pedersen::<Projective2>::setup(&mut rng, cf_r1cs.A.n_cols - cf_r1cs.l - 1).unwrap();
// public params hash
let pp_hash = Fr::from(42u32); // only for test
// first step
let z_0 = vec![Fr::from(3_u32)];
let mut z_i = z_0.clone();
@@ -1132,9 +1161,15 @@ mod tests {
let mut cf_W_i = cf_W_dummy.clone();
let mut cf_U_i = cf_U_dummy.clone();
u_i.x = vec![
U_i.hash(&poseidon_config, Fr::zero(), z_0.clone(), z_i.clone())
.unwrap(),
cf_U_i.hash_cyclefold(&poseidon_config).unwrap(),
U_i.hash(
&poseidon_config,
pp_hash,
Fr::zero(),
z_0.clone(),
z_i.clone(),
)
.unwrap(),
cf_U_i.hash_cyclefold(&poseidon_config, pp_hash).unwrap(),
];
let n_steps: usize = 4;
@@ -1151,12 +1186,18 @@ mod tests {
U_i1 = LCCCS::dummy(ccs.l, ccs.t, ccs.s);
let u_i1_x = U_i1
.hash(&poseidon_config, Fr::one(), z_0.clone(), z_i1.clone())
.hash(
&poseidon_config,
pp_hash,
Fr::one(),
z_0.clone(),
z_i1.clone(),
)
.unwrap();
// hash the initial (dummy) CycleFold instance, which is used as the 2nd public
// input in the AugmentedFCircuit
let cf_u_i1_x = cf_U_i.hash_cyclefold(&poseidon_config).unwrap();
let cf_u_i1_x = cf_U_i.hash_cyclefold(&poseidon_config, pp_hash).unwrap();
augmented_f_circuit =
AugmentedFCircuit::<Projective, Projective2, GVar2, CubicFCircuit<Fr>> {
@@ -1164,6 +1205,7 @@ mod tests {
_gc2: PhantomData,
poseidon_config: poseidon_config.clone(),
ccs: ccs.clone(),
pp_hash: Some(pp_hash),
i: Some(Fr::zero()),
i_usize: Some(0),
z_0: Some(z_0.clone()),
@@ -1185,6 +1227,7 @@ mod tests {
} else {
let mut transcript_p: PoseidonTranscript<Projective> =
PoseidonTranscript::<Projective>::new(&poseidon_config.clone());
transcript_p.absorb(&pp_hash);
let (rho_bits, nimfs_proof);
(nimfs_proof, U_i1, W_i1, rho_bits) =
NIMFS::<Projective, PoseidonTranscript<Projective>>::prove(
@@ -1201,7 +1244,13 @@ mod tests {
U_i1.check_relation(&ccs, &W_i1).unwrap();
let u_i1_x = U_i1
.hash(&poseidon_config, iFr + Fr::one(), z_0.clone(), z_i1.clone())
.hash(
&poseidon_config,
pp_hash,
iFr + Fr::one(),
z_0.clone(),
z_i1.clone(),
)
.unwrap();
let rho_Fq = Fq::from_bigint(BigInteger::from_bits_le(&rho_bits)).unwrap();
@@ -1236,6 +1285,7 @@ mod tests {
&poseidon_config,
cf_r1cs.clone(),
cf_pedersen_params.clone(),
pp_hash,
cf_W_i.clone(), // CycleFold running instance witness
cf_U_i.clone(), // CycleFold running instance
cf_u_i_x, // CycleFold incoming instance
@@ -1245,7 +1295,7 @@ mod tests {
// hash the CycleFold folded instance, which is used as the 2nd public input in the
// AugmentedFCircuit
let cf_u_i1_x = cf_U_i1.hash_cyclefold(&poseidon_config).unwrap();
let cf_u_i1_x = cf_U_i1.hash_cyclefold(&poseidon_config, pp_hash).unwrap();
augmented_f_circuit =
AugmentedFCircuit::<Projective, Projective2, GVar2, CubicFCircuit<Fr>> {
@@ -1253,6 +1303,7 @@ mod tests {
_gc2: PhantomData,
poseidon_config: poseidon_config.clone(),
ccs: ccs.clone(),
pp_hash: Some(pp_hash),
i: Some(iFr),
i_usize: Some(i),
z_0: Some(z_0.clone()),
@@ -1296,9 +1347,15 @@ mod tests {
assert_eq!(u_i.x[0], augmented_f_circuit.x.unwrap());
assert_eq!(u_i.x[1], augmented_f_circuit.cf_x.unwrap());
let expected_u_i1_x = U_i1
.hash(&poseidon_config, iFr + Fr::one(), z_0.clone(), z_i1.clone())
.hash(
&poseidon_config,
pp_hash,
iFr + Fr::one(),
z_0.clone(),
z_i1.clone(),
)
.unwrap();
let expected_cf_U_i1_x = cf_U_i.hash_cyclefold(&poseidon_config).unwrap();
let expected_cf_U_i1_x = cf_U_i.hash_cyclefold(&poseidon_config, pp_hash).unwrap();
// u_i is already u_i1 at this point, check that has the expected value at x[0]
assert_eq!(u_i.x[0], expected_u_i1_x);
assert_eq!(u_i.x[1], expected_cf_U_i1_x);

View File

@@ -10,7 +10,7 @@ use ark_std::rand::Rng;
use ark_std::Zero;
use super::Witness;
use crate::ccs::CCS;
use crate::arith::ccs::CCS;
use crate::commitment::CommitmentScheme;
use crate::folding::circuits::nonnative::affine::nonnative_affine_to_field_elements;
use crate::utils::mle::dense_vec_to_dense_mle;
@@ -129,6 +129,7 @@ where
pub fn hash(
&self,
poseidon_config: &PoseidonConfig<C::ScalarField>,
pp_hash: C::ScalarField,
i: C::ScalarField,
z_0: Vec<C::ScalarField>,
z_i: Vec<C::ScalarField>,
@@ -138,7 +139,7 @@ where
CRH::<C::ScalarField>::evaluate(
poseidon_config,
vec![
vec![i],
vec![pp_hash, i],
z_0,
z_i,
C_x,
@@ -164,9 +165,10 @@ pub mod tests {
use std::sync::Arc;
use super::*;
use crate::ccs::{
use crate::arith::{
ccs::tests::{get_test_ccs, get_test_z},
r1cs::R1CS,
tests::{get_test_ccs, get_test_z},
Arith,
};
use crate::commitment::pedersen::Pedersen;
use crate::utils::hypercube::BooleanHypercube;

View File

@@ -24,16 +24,17 @@ use crate::folding::circuits::{
CF2,
};
use crate::folding::nova::{
get_r1cs_from_cs, traits::NovaR1CS, CommittedInstance, Witness as NovaWitness,
get_r1cs_from_cs, traits::NovaR1CS, CommittedInstance, PreprocessorParam,
Witness as NovaWitness,
};
use crate::frontend::FCircuit;
use crate::utils::get_cm_coordinates;
use crate::utils::{get_cm_coordinates, pp_hash};
use crate::Error;
use crate::FoldingScheme;
use crate::{
ccs::{
arith::{
ccs::CCS,
r1cs::{extract_w_x, R1CS},
CCS,
},
transcript::{poseidon::PoseidonTranscript, Transcript},
};
@@ -56,22 +57,6 @@ impl<F: PrimeField> Witness<F> {
}
}
#[derive(Debug, Clone)]
pub struct PreprocessorParam<C1, C2, FC, CS1, CS2>
where
C1: CurveGroup,
C2: CurveGroup,
FC: FCircuit<C1::ScalarField>,
CS1: CommitmentScheme<C1>,
CS2: CommitmentScheme<C2>,
{
pub poseidon_config: PoseidonConfig<C1::ScalarField>,
pub F: FC,
// cs_params & cf_cs_params: if not provided, will be generated at the preprocess method
pub cs_params: Option<CS1::ProverParams>,
pub cf_cs_params: Option<CS2::ProverParams>,
}
#[derive(Debug, Clone)]
pub struct ProverParams<C1, C2, CS1, CS2>
where
@@ -97,8 +82,27 @@ pub struct VerifierParams<
pub poseidon_config: PoseidonConfig<C1::ScalarField>,
pub ccs: CCS<C1::ScalarField>,
pub cf_r1cs: R1CS<C2::ScalarField>,
pub cs_params: CS1::ProverParams,
pub cf_cs_params: CS2::ProverParams,
pub cs_vp: CS1::VerifierParams,
pub cf_cs_vp: CS2::VerifierParams,
}
impl<C1, C2, CS1, CS2> VerifierParams<C1, C2, CS1, CS2>
where
C1: CurveGroup,
C2: CurveGroup,
CS1: CommitmentScheme<C1>,
CS2: CommitmentScheme<C2>,
{
/// returns the hash of the public parameters of HyperNova
pub fn pp_hash(&self) -> Result<C1::ScalarField, Error> {
pp_hash::<C1, C2, CS1, CS2>(
&self.ccs,
&self.cf_r1cs,
&self.cs_vp,
&self.cf_cs_vp,
&self.poseidon_config,
)
}
}
/// Implements HyperNova+CycleFold's IVC, described in
@@ -130,6 +134,8 @@ where
pub cf_cs_params: CS2::ProverParams,
/// F circuit, the circuit that is being folded
pub F: FC,
/// public params hash
pub pp_hash: C1::ScalarField,
pub i: C1::ScalarField,
/// initial state
pub z_0: Vec<C1::ScalarField>,
@@ -185,35 +191,49 @@ where
let cf_circuit = CycleFoldCircuit::<C1, GC1>::empty();
let cf_r1cs = get_r1cs_from_cs::<C2::ScalarField>(cf_circuit)?;
// if cs_params & cf_cs_params exist, use them, if not, generate new ones
let cs_params: CS1::ProverParams;
let cf_cs_params: CS2::ProverParams;
if prep_param.cs_params.is_some() && prep_param.cf_cs_params.is_some() {
cs_params = prep_param.clone().cs_params.unwrap();
cf_cs_params = prep_param.clone().cf_cs_params.unwrap();
// if cs params exist, use them, if not, generate new ones
let cs_pp: CS1::ProverParams;
let cs_vp: CS1::VerifierParams;
let cf_cs_pp: CS2::ProverParams;
let cf_cs_vp: CS2::VerifierParams;
if prep_param.cs_pp.is_some()
&& prep_param.cf_cs_pp.is_some()
&& prep_param.cs_vp.is_some()
&& prep_param.cf_cs_vp.is_some()
{
cs_pp = prep_param.clone().cs_pp.unwrap();
cs_vp = prep_param.clone().cs_vp.unwrap();
cf_cs_pp = prep_param.clone().cf_cs_pp.unwrap();
cf_cs_vp = prep_param.clone().cf_cs_vp.unwrap();
} else {
(cs_params, _) = CS1::setup(&mut rng, ccs.n - ccs.l - 1).unwrap();
(cf_cs_params, _) = CS2::setup(&mut rng, cf_r1cs.A.n_cols - cf_r1cs.l - 1).unwrap();
(cs_pp, cs_vp) = CS1::setup(&mut rng, ccs.n - ccs.l - 1)?;
(cf_cs_pp, cf_cs_vp) = CS2::setup(&mut rng, cf_r1cs.A.n_cols - cf_r1cs.l - 1)?;
}
let pp = ProverParams::<C1, C2, CS1, CS2> {
poseidon_config: prep_param.poseidon_config.clone(),
cs_params: cs_params.clone(),
cf_cs_params: cf_cs_params.clone(),
cs_params: cs_pp.clone(),
cf_cs_params: cf_cs_pp.clone(),
ccs: Some(ccs.clone()),
};
let vp = VerifierParams::<C1, C2, CS1, CS2> {
poseidon_config: prep_param.poseidon_config.clone(),
ccs,
cf_r1cs,
cs_params: cs_params.clone(),
cf_cs_params: cf_cs_params.clone(),
cs_vp: cs_vp.clone(),
cf_cs_vp: cf_cs_vp.clone(),
};
Ok((pp, vp))
}
/// Initializes the HyperNova+CycleFold's IVC for the given parameters and initial state `z_0`.
fn init(pp: &Self::ProverParam, F: FC, z_0: Vec<C1::ScalarField>) -> Result<Self, Error> {
fn init(
params: (Self::ProverParam, Self::VerifierParam),
F: FC,
z_0: Vec<C1::ScalarField>,
) -> Result<Self, Error> {
let (pp, vp) = params;
// prepare the HyperNova's AugmentedFCircuit and CycleFold's circuits and obtain its CCS
// and R1CS respectively
let augmented_f_circuit = AugmentedFCircuit::<C1, C2, GC2, FC>::empty(
@@ -226,6 +246,9 @@ where
let cf_circuit = CycleFoldCircuit::<C1, GC1>::empty();
let cf_r1cs = get_r1cs_from_cs::<C2::ScalarField>(cf_circuit)?;
// compute the public params hash
let pp_hash = vp.pp_hash()?;
// setup the dummy instances
let W_dummy = Witness::<C1::ScalarField>::dummy(&ccs);
let U_dummy = LCCCS::<C1>::dummy(ccs.l, ccs.t, ccs.s);
@@ -236,11 +259,12 @@ where
u_dummy.x = vec![
U_dummy.hash(
&pp.poseidon_config,
pp_hash,
C1::ScalarField::zero(),
z_0.clone(),
z_0.clone(),
)?,
cf_U_dummy.hash_cyclefold(&pp.poseidon_config)?,
cf_U_dummy.hash_cyclefold(&pp.poseidon_config, pp_hash)?,
];
// W_dummy=W_0 is a 'dummy witness', all zeroes, but with the size corresponding to the
@@ -255,6 +279,7 @@ where
cs_params: pp.cs_params.clone(),
cf_cs_params: pp.cf_cs_params.clone(),
F,
pp_hash,
i: C1::ScalarField::zero(),
z_0: z_0.clone(),
z_i: z_0,
@@ -315,6 +340,7 @@ where
let u_i1_x = U_i1.hash(
&self.poseidon_config,
self.pp_hash,
C1::ScalarField::one(),
self.z_0.clone(),
z_i1.clone(),
@@ -322,13 +348,16 @@ where
// hash the initial (dummy) CycleFold instance, which is used as the 2nd public
// input in the AugmentedFCircuit
cf_u_i1_x = self.cf_U_i.hash_cyclefold(&self.poseidon_config)?;
cf_u_i1_x = self
.cf_U_i
.hash_cyclefold(&self.poseidon_config, self.pp_hash)?;
augmented_f_circuit = AugmentedFCircuit::<C1, C2, GC2, FC> {
_c2: PhantomData,
_gc2: PhantomData,
poseidon_config: self.poseidon_config.clone(),
ccs: self.ccs.clone(),
pp_hash: Some(self.pp_hash),
i: Some(C1::ScalarField::zero()),
i_usize: Some(0),
z_0: Some(self.z_0.clone()),
@@ -350,6 +379,7 @@ where
} else {
let mut transcript_p: PoseidonTranscript<C1> =
PoseidonTranscript::<C1>::new(&self.poseidon_config);
transcript_p.absorb(&self.pp_hash);
let (rho_bits, nimfs_proof);
(nimfs_proof, U_i1, W_i1, rho_bits) = NIMFS::<C1, PoseidonTranscript<C1>>::prove(
&mut transcript_p,
@@ -366,6 +396,7 @@ where
let u_i1_x = U_i1.hash(
&self.poseidon_config,
self.pp_hash,
self.i + C1::ScalarField::one(),
self.z_0.clone(),
z_i1.clone(),
@@ -397,19 +428,21 @@ where
&self.poseidon_config,
self.cf_r1cs.clone(),
self.cf_cs_params.clone(),
self.pp_hash,
self.cf_W_i.clone(), // CycleFold running instance witness
self.cf_U_i.clone(), // CycleFold running instance
cf_u_i_x,
cf_circuit,
)?;
cf_u_i1_x = cf_U_i1.hash_cyclefold(&self.poseidon_config)?;
cf_u_i1_x = cf_U_i1.hash_cyclefold(&self.poseidon_config, self.pp_hash)?;
augmented_f_circuit = AugmentedFCircuit::<C1, C2, GC2, FC> {
_c2: PhantomData,
_gc2: PhantomData,
poseidon_config: self.poseidon_config.clone(),
ccs: self.ccs.clone(),
pp_hash: Some(self.pp_hash),
i: Some(self.i),
i_usize: Some(i_usize),
z_0: Some(self.z_0.clone()),
@@ -516,14 +549,16 @@ where
return Err(Error::IVCVerificationFail);
}
let pp_hash = vp.pp_hash()?;
// check that u_i's output points to the running instance
// u_i.X[0] == H(i, z_0, z_i, U_i)
let expected_u_i_x = U_i.hash(&vp.poseidon_config, num_steps, z_0, z_i.clone())?;
let expected_u_i_x = U_i.hash(&vp.poseidon_config, pp_hash, num_steps, z_0, z_i.clone())?;
if expected_u_i_x != u_i.x[0] {
return Err(Error::IVCVerificationFail);
}
// u_i.X[1] == H(cf_U_i)
let expected_cf_u_i_x = cf_U_i.hash_cyclefold(&vp.poseidon_config)?;
let expected_cf_u_i_x = cf_U_i.hash_cyclefold(&vp.poseidon_config, pp_hash)?;
if expected_cf_u_i_x != u_i.x[1] {
return Err(Error::IVCVerificationFail);
}
@@ -578,16 +613,20 @@ mod tests {
type HN<CS1, CS2> =
HyperNova<Projective, GVar, Projective2, GVar2, CubicFCircuit<Fr>, CS1, CS2>;
let prep_param = PreprocessorParam::<Projective, Projective2, CubicFCircuit<Fr>, CS1, CS2> {
poseidon_config,
F: F_circuit,
cs_params: None,
cf_cs_params: None,
};
let prep_param =
PreprocessorParam::<Projective, Projective2, CubicFCircuit<Fr>, CS1, CS2>::new(
poseidon_config.clone(),
F_circuit,
);
let (prover_params, verifier_params) = HN::preprocess(&mut rng, &prep_param).unwrap();
let z_0 = vec![Fr::from(3_u32)];
let mut hypernova = HN::init(&prover_params, F_circuit, z_0.clone()).unwrap();
let mut hypernova = HN::init(
(prover_params, verifier_params.clone()),
F_circuit,
z_0.clone(),
)
.unwrap();
let num_steps: usize = 3;
for _ in 0..num_steps {

View File

@@ -11,7 +11,7 @@ use super::{
utils::{compute_c, compute_g, compute_sigmas_thetas},
Witness,
};
use crate::ccs::CCS;
use crate::arith::ccs::CCS;
use crate::constants::N_BITS_RO;
use crate::folding::circuits::nonnative::affine::nonnative_affine_to_field_elements;
use crate::transcript::Transcript;
@@ -408,7 +408,10 @@ where
#[cfg(test)]
pub mod tests {
use super::*;
use crate::ccs::tests::{get_test_ccs, get_test_z};
use crate::arith::{
ccs::tests::{get_test_ccs, get_test_z},
Arith,
};
use crate::transcript::poseidon::poseidon_canonical_config;
use crate::transcript::poseidon::PoseidonTranscript;
use ark_std::test_rng;

View File

@@ -7,7 +7,7 @@ use std::sync::Arc;
use super::lcccs::LCCCS;
use super::nimfs::SigmasThetas;
use crate::ccs::CCS;
use crate::arith::ccs::CCS;
use crate::utils::mle::dense_vec_to_dense_mle;
use crate::utils::vec::mat_vec_mul;
use crate::utils::virtual_polynomial::{build_eq_x_r_vec, eq_eval, VirtualPolynomial};
@@ -167,7 +167,10 @@ pub mod tests {
use ark_std::Zero;
use super::*;
use crate::ccs::tests::{get_test_ccs, get_test_z};
use crate::arith::{
ccs::tests::{get_test_ccs, get_test_z},
Arith,
};
use crate::commitment::{pedersen::Pedersen, CommitmentScheme};
use crate::folding::hypernova::lcccs::tests::compute_Ls;
use crate::utils::hypercube::BooleanHypercube;