Skip to content

Commit

Permalink
add error handling to several pending methods
Browse files Browse the repository at this point in the history
  • Loading branch information
arnaucube committed Oct 3, 2023
1 parent 8256c27 commit 9c8cef9
Show file tree
Hide file tree
Showing 12 changed files with 203 additions and 120 deletions.
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.71.0
1.71.1
4 changes: 2 additions & 2 deletions src/ccs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ impl<C: CurveGroup> CCS<C> {
// complete the hadamard chain
let mut hadamard_result = vec![C::ScalarField::one(); self.m];
for M_j in vec_M_j.into_iter() {
hadamard_result = hadamard(&hadamard_result, &mat_vec_mul_sparse(M_j, z));
hadamard_result = hadamard(&hadamard_result, &mat_vec_mul_sparse(M_j, z))?;
}

// multiply by the coefficient of this step
let c_M_j_z = vec_scalar_mul(&hadamard_result, &self.c[i]);

// add it to the final vector
result = vec_add(&result, &c_M_j_z);
result = vec_add(&result, &c_M_j_z)?;
}

// make sure the final vector is all zeroes
Expand Down
10 changes: 7 additions & 3 deletions src/ccs/r1cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ impl<F: PrimeField> R1CS<F> {
let Az = mat_vec_mul_sparse(&self.A, z);
let Bz = mat_vec_mul_sparse(&self.B, z);
let Cz = mat_vec_mul_sparse(&self.C, z);
let AzBz = hadamard(&Az, &Bz);
assert_eq!(AzBz, Cz);
let AzBz = hadamard(&Az, &Bz)?;
if AzBz != Cz {
return Err(Error::NotSatisfied);
}

Ok(())
}
Expand Down Expand Up @@ -60,7 +62,9 @@ impl<F: PrimeField> RelaxedR1CS<F> {
let uCz = vec_scalar_mul(&Cz, &self.u);
let uCzE = vec_add(&uCz, &self.E);
let AzBz = hadamard(&Az, &Bz);
assert_eq!(AzBz, uCzE);
if AzBz != uCzE {
return Err(Error::NotSatisfied);
}

Ok(())
}
Expand Down
29 changes: 20 additions & 9 deletions src/decider/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use core::{borrow::Borrow, marker::PhantomData};

use crate::ccs::r1cs::RelaxedR1CS;
use crate::utils::vec::SparseMatrix;
use crate::Error;

pub type ConstraintF<C> = <<C as CurveGroup>::BaseField as Field>::BasePrimeField;

Expand All @@ -19,13 +20,13 @@ pub struct RelaxedR1CSGadget<F: PrimeField> {
}
impl<F: PrimeField> RelaxedR1CSGadget<F> {
/// performs the RelaxedR1CS check (Az∘Bz==uCz+E)
pub fn check(rel_r1cs: RelaxedR1CSVar<F>, z: Vec<FpVar<F>>) -> Result<(), SynthesisError> {
pub fn check(rel_r1cs: RelaxedR1CSVar<F>, z: Vec<FpVar<F>>) -> Result<(), Error> {
let Az = mat_vec_mul_sparse(rel_r1cs.A, z.clone());
let Bz = mat_vec_mul_sparse(rel_r1cs.B, z.clone());
let Cz = mat_vec_mul_sparse(rel_r1cs.C, z.clone());
let uCz = vec_scalar_mul(&Cz, &rel_r1cs.u);
let uCzE = vec_add(&uCz, &rel_r1cs.E);
let AzBz = hadamard(&Az, &Bz);
let uCzE = vec_add(&uCz, &rel_r1cs.E)?;
let AzBz = hadamard(&Az, &Bz)?;
for i in 0..AzBz.len() {
AzBz[i].enforce_equal(&uCzE[i].clone())?;
}
Expand All @@ -42,13 +43,18 @@ fn mat_vec_mul_sparse<F: PrimeField>(m: SparseMatrixVar<F>, v: Vec<FpVar<F>>) ->
}
res
}
pub fn vec_add<F: PrimeField>(a: &Vec<FpVar<F>>, b: &Vec<FpVar<F>>) -> Vec<FpVar<F>> {
assert_eq!(a.len(), b.len());
pub fn vec_add<F: PrimeField>(
a: &Vec<FpVar<F>>,
b: &Vec<FpVar<F>>,
) -> Result<Vec<FpVar<F>>, Error> {
if a.len() != b.len() {
return Err(Error::NotSameLength);
}
let mut r: Vec<FpVar<F>> = vec![FpVar::<F>::zero(); a.len()];
for i in 0..a.len() {
r[i] = a[i].clone() + b[i].clone();
}
r
Ok(r)
}
pub fn vec_scalar_mul<F: PrimeField>(vec: &Vec<FpVar<F>>, c: &FpVar<F>) -> Vec<FpVar<F>> {
let mut result = vec![FpVar::<F>::zero(); vec.len()];
Expand All @@ -57,13 +63,18 @@ pub fn vec_scalar_mul<F: PrimeField>(vec: &Vec<FpVar<F>>, c: &FpVar<F>) -> Vec<F
}
result
}
pub fn hadamard<F: PrimeField>(a: &Vec<FpVar<F>>, b: &Vec<FpVar<F>>) -> Vec<FpVar<F>> {
assert_eq!(a.len(), b.len());
pub fn hadamard<F: PrimeField>(
a: &Vec<FpVar<F>>,
b: &Vec<FpVar<F>>,
) -> Result<Vec<FpVar<F>>, Error> {
if a.len() != b.len() {
return Err(Error::NotSameLength);
}
let mut r: Vec<FpVar<F>> = vec![FpVar::<F>::zero(); a.len()];
for i in 0..a.len() {
r[i] = a[i].clone() * b[i].clone();
}
r
Ok(r)
}

#[derive(Debug, Clone)]
Expand Down
4 changes: 3 additions & 1 deletion src/folding/hypernova/cccs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ impl<C: CurveGroup> CCCS<C> {
) -> Result<(), Error> {
// check that C is the commitment of w. Notice that this is not verifying a Pedersen
// opening, but checking that the Commmitment comes from committing to the witness.
assert_eq!(self.C, Pedersen::commit(pedersen_params, &w.w, &w.r_w));
if self.C != Pedersen::commit(pedersen_params, &w.w, &w.r_w) {
return Err(Error::NotSatisfied);
}

// check CCCS relation
let z: Vec<C::ScalarField> =
Expand Down
8 changes: 6 additions & 2 deletions src/folding/hypernova/lcccs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,16 @@ impl<C: CurveGroup> LCCCS<C> {
) -> Result<(), Error> {
// check that C is the commitment of w. Notice that this is not verifying a Pedersen
// opening, but checking that the Commmitment comes from committing to the witness.
assert_eq!(self.C, Pedersen::commit(pedersen_params, &w.w, &w.r_w));
if self.C != Pedersen::commit(pedersen_params, &w.w, &w.r_w) {
return Err(Error::NotSatisfied);
}

// check CCS relation
let z: Vec<C::ScalarField> = [vec![self.u], self.x.clone(), w.w.to_vec()].concat();
let computed_v = compute_all_sum_Mz_evals(&ccs.M, &z, &self.r_x, ccs.s_prime);
assert_eq!(computed_v, self.v);
if computed_v != self.v {
return Err(Error::NotSatisfied);
}
Ok(())
}
}
Expand Down
85 changes: 56 additions & 29 deletions src/folding/hypernova/nimfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::utils::hypercube::BooleanHypercube;
use crate::utils::sum_check::structs::IOPProof as SumCheckProof;
use crate::utils::sum_check::{verifier::interpolate_uni_poly, SumCheck};
use crate::utils::virtual_polynomial::VPAuxInfo;
use crate::Error;

use std::marker::PhantomData;

Expand Down Expand Up @@ -139,20 +140,25 @@ impl<C: CurveGroup> NIMFS<C> {

/// Performs the multifolding prover. Given μ LCCCS instances and ν CCS instances, fold them
/// into a single LCCCS instance. Since this is the prover, also fold their witness.
/// Returns the final folded LCCCS, the folded witness, the sumcheck proof, and the helper
/// sumcheck claim sigmas and thetas.
/// Returns the final folded LCCCS, the folded witness, and the multifolding proof, which
/// contains the sumcheck proof and the helper sumcheck claim sigmas and thetas.
#[allow(clippy::type_complexity)]
pub fn prove(
transcript: &mut IOPTranscript<C::ScalarField>,
ccs: &CCS<C>,
running_instances: &[LCCCS<C>],
new_instances: &[CCCS<C>],
w_lcccs: &[Witness<C::ScalarField>],
w_cccs: &[Witness<C::ScalarField>],
) -> (Proof<C>, LCCCS<C>, Witness<C::ScalarField>) {
) -> Result<(Proof<C>, LCCCS<C>, Witness<C::ScalarField>), Error> {
// TODO appends to transcript

assert!(!running_instances.is_empty());
assert!(!new_instances.is_empty());
if running_instances.is_empty() {
return Err(Error::Empty);
}
if new_instances.is_empty() {
return Err(Error::Empty);
}

// construct the LCCCS z vector from the relaxation factor, public IO and witness
// XXX this deserves its own function in LCCCS
Expand Down Expand Up @@ -205,7 +211,9 @@ impl<C: CurveGroup> NIMFS<C> {
// note: this is the sum of g(x) over the whole boolean hypercube
let extracted_sum =
<PolyIOP<C::ScalarField> as SumCheck<C::ScalarField>>::extract_sum(&sumcheck_proof);
assert_eq!(extracted_sum, g_over_bhc);
if extracted_sum != g_over_bhc {
return Err(Error::NotEqual);
}
// Sanity check 2: expect \sum v_j * gamma^j to be equal to the sum of g(x) over the
// boolean hypercube (and also equal to the extracted_sum from the SumCheck).
let mut sum_v_j_gamma = C::ScalarField::zero();
Expand All @@ -215,8 +223,12 @@ impl<C: CurveGroup> NIMFS<C> {
sum_v_j_gamma += running_instance.v[j] * gamma_j;
}
}
assert_eq!(g_over_bhc, sum_v_j_gamma);
assert_eq!(extracted_sum, sum_v_j_gamma);
if g_over_bhc != sum_v_j_gamma {
return Err(Error::NotEqual);
}
if extracted_sum != sum_v_j_gamma {
return Err(Error::NotEqual);
}
//////////////////////////////////////////////////////////////////////

// Step 2: dig into the sumcheck and extract r_x_prime
Expand All @@ -240,14 +252,14 @@ impl<C: CurveGroup> NIMFS<C> {
// Step 8: Fold the witnesses
let folded_witness = Self::fold_witness(w_lcccs, w_cccs, rho);

(
Ok((
Proof::<C> {
sc_proof: sumcheck_proof,
sigmas_thetas,
},
folded_lcccs,
folded_witness,
)
))
}

/// Performs the multifolding verifier. Given μ LCCCS instances and ν CCS instances, fold them
Expand All @@ -259,11 +271,15 @@ impl<C: CurveGroup> NIMFS<C> {
running_instances: &[LCCCS<C>],
new_instances: &[CCCS<C>],
proof: Proof<C>,
) -> LCCCS<C> {
) -> Result<LCCCS<C>, Error> {
// TODO appends to transcript

assert!(!running_instances.is_empty());
assert!(!new_instances.is_empty());
if running_instances.is_empty() {
return Err(Error::Empty);
}
if new_instances.is_empty() {
return Err(Error::Empty);
}

// Step 1: Get some challenges
let gamma: C::ScalarField = transcript.get_and_append_challenge(b"gamma").unwrap();
Expand Down Expand Up @@ -312,7 +328,9 @@ impl<C: CurveGroup> NIMFS<C> {
&r_x_prime,
);
// check that the g(r_x') from the sumcheck proof is equal to the computed c from sigmas&thetas
assert_eq!(c, sumcheck_subclaim.expected_evaluation);
if c != sumcheck_subclaim.expected_evaluation {
return Err(Error::NotEqual);
}

// Sanity check: we can also compute g(r_x') from the proof last evaluation value, and
// should be equal to the previously obtained values.
Expand All @@ -321,23 +339,24 @@ impl<C: CurveGroup> NIMFS<C> {
*r_x_prime.last().unwrap(),
)
.unwrap();
assert_eq!(g_on_rxprime_from_sumcheck_last_eval, c);
assert_eq!(
g_on_rxprime_from_sumcheck_last_eval,
sumcheck_subclaim.expected_evaluation
);
if g_on_rxprime_from_sumcheck_last_eval != c {
return Err(Error::NotEqual);
}
if g_on_rxprime_from_sumcheck_last_eval != sumcheck_subclaim.expected_evaluation {
return Err(Error::NotEqual);
}

// Step 6: Get the folding challenge
let rho: C::ScalarField = transcript.get_and_append_challenge(b"rho").unwrap();

// Step 7: Compute the folded instance
Self::fold(
Ok(Self::fold(
running_instances,
new_instances,
&proof.sigmas_thetas,
r_x_prime,
rho,
)
))
}
}

Expand Down Expand Up @@ -417,7 +436,8 @@ pub mod tests {
&[new_instance.clone()],
&[w1],
&[w2],
);
)
.unwrap();

// Verifier's transcript
let mut transcript_v = IOPTranscript::<Fr>::new(b"multifolding");
Expand All @@ -430,7 +450,8 @@ pub mod tests {
&[running_instance.clone()],
&[new_instance.clone()],
proof,
);
)
.unwrap();
assert_eq!(folded_lcccs, folded_lcccs_v);

// Check that the folded LCCCS instance is a valid instance with respect to the folded witness
Expand Down Expand Up @@ -475,7 +496,8 @@ pub mod tests {
&[new_instance.clone()],
&[w1],
&[w2],
);
)
.unwrap();

// run the verifier side of the multifolding
let folded_lcccs_v = NIMFS::<Projective>::verify(
Expand All @@ -484,7 +506,8 @@ pub mod tests {
&[running_instance.clone()],
&[new_instance.clone()],
proof,
);
)
.unwrap();

assert_eq!(folded_lcccs, folded_lcccs_v);

Expand Down Expand Up @@ -552,7 +575,8 @@ pub mod tests {
&cccs_instances,
&w_lcccs,
&w_cccs,
);
)
.unwrap();

// Verifier's transcript
let mut transcript_v = IOPTranscript::<Fr>::new(b"multifolding");
Expand All @@ -565,7 +589,8 @@ pub mod tests {
&lcccs_instances,
&cccs_instances,
proof,
);
)
.unwrap();
assert_eq!(folded_lcccs, folded_lcccs_v);

// Check that the folded LCCCS instance is a valid instance with respect to the folded witness
Expand Down Expand Up @@ -636,7 +661,8 @@ pub mod tests {
&cccs_instances,
&w_lcccs,
&w_cccs,
);
)
.unwrap();

// Run the verifier side of the multifolding
let folded_lcccs_v = NIMFS::<Projective>::verify(
Expand All @@ -645,7 +671,8 @@ pub mod tests {
&lcccs_instances,
&cccs_instances,
proof,
);
)
.unwrap();
assert_eq!(folded_lcccs, folded_lcccs_v);

// Check that the folded LCCCS instance is a valid instance with respect to the folded witness
Expand Down
2 changes: 1 addition & 1 deletion src/folding/nova/circuits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ mod tests {
let r_Fr = Fr::from_bigint(BigInteger::from_bits_le(&r_bits)).unwrap();

let (_w3, ci3, _T, cmT) =
NIFS::<Projective>::prove(&pedersen_params, r_Fr, &r1cs, &w1, &ci1, &w2, &ci2);
NIFS::<Projective>::prove(&pedersen_params, r_Fr, &r1cs, &w1, &ci1, &w2, &ci2).unwrap();

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

Expand Down
Loading

0 comments on commit 9c8cef9

Please sign in to comment.