mirror of
https://github.com/arnaucube/sonobe.git
synced 2026-01-19 20:31:35 +01:00
Protogalaxy based IVC (#123)
* Parallelize vector and matrix operations * Implement convenient methods for `NonNativeAffineVar` * Return `L_X_evals` and intermediate `phi_star`s from ProtoGalaxy prover. These values will be used as hints to the augmented circuit * Correctly use number of variables, number of constraints, and `t` * Fix the size of `F_coeffs` and `K_coeffs` for in-circuit consistency * Improve prover's performance * Make `prepare_inputs` generic * Remove redundant parameters in verifier * Move `eval_f` to arith * `u` is unnecessary in ProtoGalaxy * Convert `RelaxedR1CS` to a trait that can be used in both Nova and ProtoGalaxy * Implement several traits for ProtoGalaxy * Move `FCircuit` impls to `utils.rs` and add `DummyCircuit` * `AugmentedFCircuit` and ProtoGalaxy-based IVC * Add explanations about IVC prover and in-circuit operations * Avoid using unstable features * Rename `PROTOGALAXY` to `PG` to make clippy happy * Fix merge conflicts in `RelaxedR1CS::sample` * Fix merge conflicts in `CycleFoldCircuit` * Swap `m` and `n` for protogalaxy * Add `#[cfg(test)]` to test-only util circuits * Prefer unit struct over empty struct * Add documents to `AugmentedFCircuit` for ProtoGalaxy * Fix the names for CycleFold cricuits in ProtoGalaxy * Fix usize conversion when targeting wasm * Restrict the visibility of fields in `AugmentedFCircuit` to `pub(super)` * Make CycleFold circuits and configs public * Add docs for `ProverParams` and `VerifierParams` * Refactor `pow_i` * Fix imports * Remove lint reasons * Fix type inference
This commit is contained in:
@@ -1,69 +1,90 @@
|
||||
use ark_crypto_primitives::sponge::Absorb;
|
||||
use ark_ec::{CurveGroup, Group};
|
||||
use ark_std::One;
|
||||
use ark_ec::CurveGroup;
|
||||
use ark_std::{rand::RngCore, One, UniformRand};
|
||||
|
||||
use super::{CommittedInstance, Witness};
|
||||
use crate::arith::{r1cs::R1CS, Arith};
|
||||
use crate::arith::r1cs::{RelaxedR1CS, R1CS};
|
||||
use crate::Error;
|
||||
|
||||
/// NovaR1CS extends R1CS methods with Nova specific methods
|
||||
pub trait NovaR1CS<C: CurveGroup> {
|
||||
/// returns a dummy instance (Witness and CommittedInstance) for the current R1CS structure
|
||||
fn dummy_instance(&self) -> (Witness<C>, CommittedInstance<C>);
|
||||
|
||||
/// checks the R1CS relation (un-relaxed) for the given Witness and CommittedInstance.
|
||||
fn check_instance_relation(
|
||||
&self,
|
||||
W: &Witness<C>,
|
||||
U: &CommittedInstance<C>,
|
||||
) -> Result<(), Error>;
|
||||
|
||||
/// checks the Relaxed R1CS relation (corresponding to the current R1CS) for the given Witness
|
||||
/// and CommittedInstance.
|
||||
fn check_relaxed_instance_relation(
|
||||
&self,
|
||||
W: &Witness<C>,
|
||||
U: &CommittedInstance<C>,
|
||||
) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
impl<C: CurveGroup> NovaR1CS<C> for R1CS<C::ScalarField>
|
||||
where
|
||||
<C as Group>::ScalarField: Absorb,
|
||||
<C as ark_ec::CurveGroup>::BaseField: ark_ff::PrimeField,
|
||||
{
|
||||
fn dummy_instance(&self) -> (Witness<C>, CommittedInstance<C>) {
|
||||
impl<C: CurveGroup> RelaxedR1CS<C, Witness<C>, CommittedInstance<C>> for R1CS<C::ScalarField> {
|
||||
fn dummy_running_instance(&self) -> (Witness<C>, CommittedInstance<C>) {
|
||||
let w_len = self.A.n_cols - 1 - self.l;
|
||||
let w_dummy = Witness::<C>::dummy(w_len, self.A.n_rows);
|
||||
let u_dummy = CommittedInstance::<C>::dummy(self.l);
|
||||
(w_dummy, u_dummy)
|
||||
}
|
||||
|
||||
// notice that this method does not check the commitment correctness
|
||||
fn check_instance_relation(
|
||||
&self,
|
||||
W: &Witness<C>,
|
||||
U: &CommittedInstance<C>,
|
||||
) -> Result<(), Error> {
|
||||
if U.cmE != C::zero() || U.u != C::ScalarField::one() {
|
||||
return Err(Error::R1CSUnrelaxedFail);
|
||||
}
|
||||
|
||||
let Z: Vec<C::ScalarField> = [vec![U.u], U.x.to_vec(), W.W.to_vec()].concat();
|
||||
self.check_relation(&Z)
|
||||
fn dummy_incoming_instance(&self) -> (Witness<C>, CommittedInstance<C>) {
|
||||
self.dummy_running_instance()
|
||||
}
|
||||
|
||||
// notice that this method does not check the commitment correctness
|
||||
fn check_relaxed_instance_relation(
|
||||
&self,
|
||||
W: &Witness<C>,
|
||||
U: &CommittedInstance<C>,
|
||||
) -> Result<(), Error> {
|
||||
let mut rel_r1cs = self.clone().relax();
|
||||
rel_r1cs.u = U.u;
|
||||
rel_r1cs.E = W.E.clone();
|
||||
fn is_relaxed(_w: &Witness<C>, u: &CommittedInstance<C>) -> bool {
|
||||
u.cmE != C::zero() || u.u != C::ScalarField::one()
|
||||
}
|
||||
|
||||
let Z: Vec<C::ScalarField> = [vec![U.u], U.x.to_vec(), W.W.to_vec()].concat();
|
||||
rel_r1cs.check_relation(&Z)
|
||||
fn extract_z(w: &Witness<C>, u: &CommittedInstance<C>) -> Vec<C::ScalarField> {
|
||||
[&[u.u][..], &u.x, &w.W].concat()
|
||||
}
|
||||
|
||||
fn check_error_terms(
|
||||
w: &Witness<C>,
|
||||
_u: &CommittedInstance<C>,
|
||||
e: Vec<C::ScalarField>,
|
||||
) -> Result<(), Error> {
|
||||
if w.E == e {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::NotSatisfied)
|
||||
}
|
||||
}
|
||||
|
||||
fn sample<CS>(
|
||||
&self,
|
||||
params: &CS::ProverParams,
|
||||
mut rng: impl RngCore,
|
||||
) -> Result<(Witness<C>, CommittedInstance<C>), Error>
|
||||
where
|
||||
CS: crate::commitment::CommitmentScheme<C, true>,
|
||||
{
|
||||
// Implements sampling a (committed) RelaxedR1CS
|
||||
// See construction 5 in https://eprint.iacr.org/2023/573.pdf
|
||||
let u = C::ScalarField::rand(&mut rng);
|
||||
let rE = C::ScalarField::rand(&mut rng);
|
||||
let rW = C::ScalarField::rand(&mut rng);
|
||||
|
||||
let W = (0..self.A.n_cols - self.l - 1)
|
||||
.map(|_| C::ScalarField::rand(&mut rng))
|
||||
.collect();
|
||||
let x = (0..self.l)
|
||||
.map(|_| C::ScalarField::rand(&mut rng))
|
||||
.collect::<Vec<C::ScalarField>>();
|
||||
let mut z = vec![u];
|
||||
z.extend(&x);
|
||||
z.extend(&W);
|
||||
|
||||
let E = <Self as RelaxedR1CS<C, Witness<C>, CommittedInstance<C>>>::compute_E(
|
||||
&self.A, &self.B, &self.C, &z, &u,
|
||||
)?;
|
||||
|
||||
debug_assert!(
|
||||
z.len() == self.A.n_cols,
|
||||
"Length of z is {}, while A has {} columns.",
|
||||
z.len(),
|
||||
self.A.n_cols
|
||||
);
|
||||
|
||||
let witness = Witness { E, rE, W, rW };
|
||||
let mut cm_witness = witness.commit::<CS, true>(params, x)?;
|
||||
|
||||
// witness.commit() sets u to 1, we set it to the sampled u value
|
||||
cm_witness.u = u;
|
||||
|
||||
debug_assert!(
|
||||
self.check_relaxed_relation(&witness, &cm_witness).is_ok(),
|
||||
"Sampled a non satisfiable relaxed R1CS, sampled u: {}, computed E: {:?}",
|
||||
u,
|
||||
witness.E
|
||||
);
|
||||
|
||||
Ok((witness, cm_witness))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user