mirror of
https://github.com/arnaucube/sonobe.git
synced 2026-01-28 14:56:40 +01:00
HyperNova: add multi-instances folding to AugmentedFCircuit & IVC (#119)
- Adds the logic to support multi-instances folding in HyperNova's AugmentedFCircuit & IVC. - Adds also methods to generate new LCCCS & CCCS instances that don't depend on the main folding chain, to be folded in in the next step - Updates CycleFold circuit & methods to work other folding schemes than Nova, adapting it to fold multiple points per circuit (instead of 2-to-1 as till now) - Handle multi-instances folding in the FoldingScheme trait interface, which expects 'None' in Nova, and 'Some' in HyperNova & other multi-folding schemes.
This commit is contained in:
@@ -20,11 +20,11 @@ use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace,
|
||||
use ark_std::{fmt::Debug, One, Zero};
|
||||
use core::{borrow::Borrow, marker::PhantomData};
|
||||
|
||||
use super::CommittedInstance;
|
||||
use super::{CommittedInstance, NOVA_CF_N_POINTS};
|
||||
use crate::constants::N_BITS_RO;
|
||||
use crate::folding::circuits::{
|
||||
cyclefold::{
|
||||
CycleFoldChallengeGadget, CycleFoldCommittedInstanceVar, NIFSFullGadget, CF_IO_LEN,
|
||||
cf_io_len, CycleFoldChallengeGadget, CycleFoldCommittedInstanceVar, NIFSFullGadget,
|
||||
},
|
||||
nonnative::{affine::NonNativeAffineVar, uint::NonNativeUintVar},
|
||||
CF1, CF2,
|
||||
@@ -337,7 +337,7 @@ where
|
||||
let cmT =
|
||||
NonNativeAffineVar::new_witness(cs.clone(), || Ok(self.cmT.unwrap_or_else(C1::zero)))?;
|
||||
|
||||
let cf_u_dummy = CommittedInstance::dummy(CF_IO_LEN);
|
||||
let cf_u_dummy = CommittedInstance::dummy(cf_io_len(NOVA_CF_N_POINTS));
|
||||
let cf_U_i = CycleFoldCommittedInstanceVar::<C2, GC2>::new_witness(cs.clone(), || {
|
||||
Ok(self.cf_U_i.unwrap_or(cf_u_dummy.clone()))
|
||||
})?;
|
||||
|
||||
@@ -361,12 +361,12 @@ pub mod tests {
|
||||
let nova_params = N::preprocess(&mut rng, &prep_param).unwrap();
|
||||
|
||||
let start = Instant::now();
|
||||
let mut nova = N::init(nova_params.clone(), F_circuit, z_0.clone()).unwrap();
|
||||
let mut nova = N::init(&nova_params, F_circuit, z_0.clone()).unwrap();
|
||||
println!("Nova initialized, {:?}", start.elapsed());
|
||||
let start = Instant::now();
|
||||
nova.prove_step(&mut rng, vec![]).unwrap();
|
||||
nova.prove_step(&mut rng, vec![], None).unwrap();
|
||||
println!("prove_step, {:?}", start.elapsed());
|
||||
nova.prove_step(&mut rng, vec![]).unwrap(); // do a 2nd step
|
||||
nova.prove_step(&mut rng, vec![], None).unwrap(); // do a 2nd step
|
||||
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
|
||||
|
||||
@@ -447,11 +447,12 @@ where
|
||||
{
|
||||
// imports here instead of at the top of the file, so we avoid having multiple
|
||||
// `#[cfg(not(test))]`
|
||||
use super::NOVA_CF_N_POINTS;
|
||||
use crate::commitment::pedersen::PedersenGadget;
|
||||
use crate::folding::circuits::cyclefold::{CycleFoldCommittedInstanceVar, CF_IO_LEN};
|
||||
use crate::folding::circuits::cyclefold::{cf_io_len, CycleFoldCommittedInstanceVar};
|
||||
use ark_r1cs_std::ToBitsGadget;
|
||||
|
||||
let cf_u_dummy_native = CommittedInstance::<C2>::dummy(CF_IO_LEN);
|
||||
let cf_u_dummy_native = CommittedInstance::<C2>::dummy(cf_io_len(NOVA_CF_N_POINTS));
|
||||
let w_dummy_native = Witness::<C2>::new(
|
||||
vec![C2::ScalarField::zero(); self.cf_r1cs.A.n_cols - 1 - self.cf_r1cs.l],
|
||||
self.cf_E_len,
|
||||
@@ -796,20 +797,15 @@ pub mod tests {
|
||||
Pedersen<Projective>,
|
||||
Pedersen<Projective2>,
|
||||
>::new(poseidon_config, F_circuit);
|
||||
let (prover_params, verifier_params) = N::preprocess(&mut rng, &prep_param).unwrap();
|
||||
let nova_params = N::preprocess(&mut rng, &prep_param).unwrap();
|
||||
|
||||
// generate a Nova instance and do a step of it
|
||||
let mut nova = N::init(
|
||||
(prover_params, verifier_params.clone()),
|
||||
F_circuit,
|
||||
z_0.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
nova.prove_step(&mut rng, vec![]).unwrap();
|
||||
let mut nova = N::init(&nova_params, F_circuit, z_0.clone()).unwrap();
|
||||
nova.prove_step(&mut rng, vec![], None).unwrap();
|
||||
let ivc_v = nova.clone();
|
||||
let (running_instance, incoming_instance, cyclefold_instance) = ivc_v.instances();
|
||||
N::verify(
|
||||
verifier_params,
|
||||
nova_params.1, // verifier_params
|
||||
z_0,
|
||||
ivc_v.z_i,
|
||||
Fr::one(),
|
||||
|
||||
@@ -37,6 +37,10 @@ use circuits::{AugmentedFCircuit, ChallengeGadget};
|
||||
use nifs::NIFS;
|
||||
use traits::NovaR1CS;
|
||||
|
||||
/// Number of points to be folded in the CycleFold circuit, in Nova's case, this is a fixed amount:
|
||||
/// 2 points to be folded.
|
||||
const NOVA_CF_N_POINTS: usize = 2_usize;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
|
||||
pub struct CommittedInstance<C: CurveGroup> {
|
||||
pub cmE: C,
|
||||
@@ -344,6 +348,7 @@ where
|
||||
type VerifierParam = VerifierParams<C1, C2, CS1, CS2>;
|
||||
type RunningInstance = (CommittedInstance<C1>, Witness<C1>);
|
||||
type IncomingInstance = (CommittedInstance<C1>, Witness<C1>);
|
||||
type MultiCommittedInstanceWithWitness = ();
|
||||
type CFInstance = (CommittedInstance<C2>, Witness<C2>);
|
||||
|
||||
fn preprocess(
|
||||
@@ -390,7 +395,7 @@ where
|
||||
|
||||
/// Initializes the Nova+CycleFold's IVC for the given parameters and initial state `z_0`.
|
||||
fn init(
|
||||
params: (Self::ProverParam, Self::VerifierParam),
|
||||
params: &(Self::ProverParam, Self::VerifierParam),
|
||||
F: FC,
|
||||
z_0: Vec<C1::ScalarField>,
|
||||
) -> Result<Self, Error> {
|
||||
@@ -402,7 +407,7 @@ where
|
||||
|
||||
let augmented_F_circuit =
|
||||
AugmentedFCircuit::<C1, C2, GC2, FC>::empty(&pp.poseidon_config, F.clone());
|
||||
let cf_circuit = CycleFoldCircuit::<C1, GC1>::empty();
|
||||
let cf_circuit = CycleFoldCircuit::<C1, GC1>::empty(NOVA_CF_N_POINTS);
|
||||
|
||||
augmented_F_circuit.generate_constraints(cs.clone())?;
|
||||
cs.finalize();
|
||||
@@ -452,6 +457,8 @@ where
|
||||
&mut self,
|
||||
_rng: impl RngCore,
|
||||
external_inputs: Vec<C1::ScalarField>,
|
||||
// Nova does not support multi-instances folding
|
||||
_other_instances: Option<Self::MultiCommittedInstanceWithWitness>,
|
||||
) -> Result<(), Error> {
|
||||
// `sponge` is for digest computation.
|
||||
let sponge = PoseidonSponge::<C1::ScalarField>::new(&self.poseidon_config);
|
||||
@@ -460,6 +467,11 @@ where
|
||||
|
||||
let augmented_F_circuit: AugmentedFCircuit<C1, C2, GC2, FC>;
|
||||
|
||||
// Nova does not support (by design) multi-instances folding
|
||||
if _other_instances.is_some() {
|
||||
return Err(Error::NoMultiInstances);
|
||||
}
|
||||
|
||||
if self.z_i.len() != self.F.state_len() {
|
||||
return Err(Error::NotSameLength(
|
||||
"z_i.len()".to_string(),
|
||||
@@ -572,16 +584,16 @@ where
|
||||
|
||||
let cfW_circuit = CycleFoldCircuit::<C1, GC1> {
|
||||
_gc: PhantomData,
|
||||
r_bits: Some(r_bits.clone()),
|
||||
p1: Some(self.U_i.clone().cmW),
|
||||
p2: Some(self.u_i.clone().cmW),
|
||||
n_points: NOVA_CF_N_POINTS,
|
||||
r_bits: Some(vec![r_bits.clone()]),
|
||||
points: Some(vec![self.U_i.clone().cmW, self.u_i.clone().cmW]),
|
||||
x: Some(cfW_u_i_x.clone()),
|
||||
};
|
||||
let cfE_circuit = CycleFoldCircuit::<C1, GC1> {
|
||||
_gc: PhantomData,
|
||||
r_bits: Some(r_bits.clone()),
|
||||
p1: Some(self.U_i.clone().cmE),
|
||||
p2: Some(cmT),
|
||||
n_points: NOVA_CF_N_POINTS,
|
||||
r_bits: Some(vec![r_bits.clone()]),
|
||||
points: Some(vec![self.U_i.clone().cmE, cmT]),
|
||||
x: Some(cfE_u_i_x.clone()),
|
||||
};
|
||||
|
||||
@@ -820,6 +832,7 @@ where
|
||||
Error,
|
||||
> {
|
||||
fold_cyclefold_circuit::<C1, GC1, C2, GC2, FC, CS1, CS2>(
|
||||
NOVA_CF_N_POINTS,
|
||||
transcript,
|
||||
self.cf_r1cs.clone(),
|
||||
self.cf_cs_pp.clone(),
|
||||
@@ -866,7 +879,7 @@ where
|
||||
{
|
||||
let augmented_F_circuit =
|
||||
AugmentedFCircuit::<C1, C2, GC2, FC>::empty(poseidon_config, F_circuit);
|
||||
let cf_circuit = CycleFoldCircuit::<C1, GC1>::empty();
|
||||
let cf_circuit = CycleFoldCircuit::<C1, GC1>::empty(NOVA_CF_N_POINTS);
|
||||
let r1cs = get_r1cs_from_cs::<C1::ScalarField>(augmented_F_circuit)?;
|
||||
let cf_r1cs = get_r1cs_from_cs::<C2::ScalarField>(cf_circuit)?;
|
||||
Ok((r1cs, cf_r1cs))
|
||||
@@ -944,11 +957,11 @@ pub mod tests {
|
||||
let nova_params = N::preprocess(&mut rng, &prep_param).unwrap();
|
||||
|
||||
let z_0 = vec![Fr::from(3_u32)];
|
||||
let mut nova = N::init(nova_params.clone(), F_circuit, z_0.clone()).unwrap();
|
||||
let mut nova = N::init(&nova_params, F_circuit, z_0.clone()).unwrap();
|
||||
|
||||
let num_steps: usize = 3;
|
||||
for _ in 0..num_steps {
|
||||
nova.prove_step(&mut rng, vec![]).unwrap();
|
||||
nova.prove_step(&mut rng, vec![], None).unwrap();
|
||||
}
|
||||
assert_eq!(Fr::from(num_steps as u32), nova.i);
|
||||
|
||||
|
||||
@@ -12,7 +12,10 @@ use std::marker::PhantomData;
|
||||
|
||||
use super::{circuits::AugmentedFCircuit, Nova, ProverParams};
|
||||
use super::{CommittedInstance, Witness};
|
||||
use crate::folding::circuits::{cyclefold::CycleFoldCircuit, CF2};
|
||||
use crate::folding::{
|
||||
circuits::{cyclefold::CycleFoldCircuit, CF2},
|
||||
nova::NOVA_CF_N_POINTS,
|
||||
};
|
||||
use crate::{
|
||||
arith::r1cs::extract_r1cs, commitment::CommitmentScheme, folding::circuits::CF1,
|
||||
frontend::FCircuit,
|
||||
@@ -134,7 +137,7 @@ where
|
||||
let cs2 = ConstraintSystem::<C1::BaseField>::new_ref();
|
||||
let augmented_F_circuit =
|
||||
AugmentedFCircuit::<C1, C2, GC2, FC>::empty(&poseidon_config, f_circuit.clone());
|
||||
let cf_circuit = CycleFoldCircuit::<C1, GC1>::empty();
|
||||
let cf_circuit = CycleFoldCircuit::<C1, GC1>::empty(NOVA_CF_N_POINTS);
|
||||
|
||||
augmented_F_circuit
|
||||
.generate_constraints(cs.clone())
|
||||
@@ -209,11 +212,11 @@ pub mod tests {
|
||||
let nova_params = N::preprocess(&mut rng, &prep_param).unwrap();
|
||||
|
||||
let z_0 = vec![Fr::from(3_u32)];
|
||||
let mut nova = N::init(nova_params.clone(), F_circuit, z_0.clone()).unwrap();
|
||||
let mut nova = N::init(&nova_params, F_circuit, z_0.clone()).unwrap();
|
||||
|
||||
let num_steps: usize = 3;
|
||||
for _ in 0..num_steps {
|
||||
nova.prove_step(&mut rng, vec![]).unwrap();
|
||||
nova.prove_step(&mut rng, vec![], None).unwrap();
|
||||
}
|
||||
|
||||
let mut writer = vec![];
|
||||
@@ -252,8 +255,10 @@ pub mod tests {
|
||||
|
||||
let num_steps: usize = 3;
|
||||
for _ in 0..num_steps {
|
||||
deserialized_nova.prove_step(&mut rng, vec![]).unwrap();
|
||||
nova.prove_step(&mut rng, vec![]).unwrap();
|
||||
deserialized_nova
|
||||
.prove_step(&mut rng, vec![], None)
|
||||
.unwrap();
|
||||
nova.prove_step(&mut rng, vec![], None).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(deserialized_nova.w_i, nova.w_i);
|
||||
|
||||
Reference in New Issue
Block a user