arnaucube
arnaucube/sonobePublic Self-hosted repository
add error handling to several pending methods (#30)

arnaucube root@arnaucube.com
Wed, 04 Oct 2023 15:43:24 +0200
commit

13e471aeaf408355e3764091a35335152055574c

parent

8256c27609a2effbf9a255f0709eb0b1c3055b36

M rust-toolchain → rust-toolchain

@@ -1,1 +1,1 @@

-1.71.0+1.71.1
M src/ccs/mod.rs → src/ccs/mod.rs

@@ -51,14 +51,14 @@

// 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
M src/ccs/r1cs.rs → src/ccs/r1cs.rs

@@ -22,8 +22,10 @@ pub fn check_relation(&self, z: &[F]) -> Result<(), Error> {

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(()) }

@@ -60,7 +62,9 @@ let Cz = mat_vec_mul_sparse(&self.C, z);

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(()) }
M src/decider/circuit.rs → src/decider/circuit.rs

@@ -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;

@@ -19,13 +20,13 @@ _f: PhantomData<F>,

} 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())?; }

@@ -42,13 +43,18 @@ }

} 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()];

@@ -57,13 +63,18 @@ result[i] = a.clone() * c;

} 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)]
M src/folding/hypernova/cccs.rs → src/folding/hypernova/cccs.rs

@@ -109,7 +109,9 @@ w: &Witness<C::ScalarField>,

) -> 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> =
M src/folding/hypernova/lcccs.rs → src/folding/hypernova/lcccs.rs

@@ -94,12 +94,16 @@ w: &Witness<C::ScalarField>,

) -> 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(()) } }
M src/folding/hypernova/nimfs.rs → src/folding/hypernova/nimfs.rs

@@ -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;

@@ -139,8 +140,9 @@ }

/// 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>,

@@ -148,11 +150,15 @@ 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

@@ -205,7 +211,9 @@

// 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();

@@ -215,8 +223,12 @@ let gamma_j = gamma.pow([(i * ccs.t + j) as u64]);

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

@@ -240,14 +252,14 @@

// 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

@@ -259,11 +271,15 @@ ccs: &CCS<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();

@@ -312,7 +328,9 @@ .collect(),

&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.

@@ -321,23 +339,24 @@ &proof.sc_proof.proofs.last().unwrap().evaluations,

*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, - ) + )) } }

@@ -417,7 +436,8 @@ &[running_instance.clone()],

&[new_instance.clone()], &[w1], &[w2], - ); + ) + .unwrap(); // Verifier's transcript let mut transcript_v = IOPTranscript::<Fr>::new(b"multifolding");

@@ -430,7 +450,8 @@ &ccs,

&[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

@@ -475,7 +496,8 @@ &[running_instance.clone()],

&[new_instance.clone()], &[w1], &[w2], - ); + ) + .unwrap(); // run the verifier side of the multifolding let folded_lcccs_v = NIMFS::<Projective>::verify(

@@ -484,7 +506,8 @@ &ccs,

&[running_instance.clone()], &[new_instance.clone()], proof, - ); + ) + .unwrap(); assert_eq!(folded_lcccs, folded_lcccs_v);

@@ -552,7 +575,8 @@ &lcccs_instances,

&cccs_instances, &w_lcccs, &w_cccs, - ); + ) + .unwrap(); // Verifier's transcript let mut transcript_v = IOPTranscript::<Fr>::new(b"multifolding");

@@ -565,7 +589,8 @@ &ccs,

&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

@@ -636,7 +661,8 @@ &lcccs_instances,

&cccs_instances, &w_lcccs, &w_cccs, - ); + ) + .unwrap(); // Run the verifier side of the multifolding let folded_lcccs_v = NIMFS::<Projective>::verify(

@@ -645,7 +671,8 @@ &ccs,

&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
M src/folding/nova/circuits.rs → src/folding/nova/circuits.rs

@@ -222,7 +222,7 @@ let r_bits = tr.get_challenge_nbits(128);

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();
M src/folding/nova/nifs.rs → src/folding/nova/nifs.rs

@@ -8,6 +8,7 @@ use crate::folding::nova::{CommittedInstance, Witness};

use crate::pedersen::{Params as PedersenParams, Pedersen, Proof as PedersenProof}; use crate::transcript::Transcript; use crate::utils::vec::*; +use crate::Error; /// Implements the Non-Interactive Folding Scheme described in section 4 of /// https://eprint.iacr.org/2021/370.pdf

@@ -26,7 +27,7 @@ u1: C::ScalarField,

u2: C::ScalarField, z1: &[C::ScalarField], z2: &[C::ScalarField], - ) -> Vec<C::ScalarField> { + ) -> Result<Vec<C::ScalarField>, Error> { let (A, B, C) = (r1cs.A.clone(), r1cs.B.clone(), r1cs.C.clone()); // this is parallelizable (for the future)

@@ -37,12 +38,12 @@ let Az2 = mat_vec_mul_sparse(&A, z2);

let Bz2 = mat_vec_mul_sparse(&B, z2); let Cz2 = mat_vec_mul_sparse(&C, z2); - let Az1_Bz2 = hadamard(&Az1, &Bz2); - let Az2_Bz1 = hadamard(&Az2, &Bz1); + let Az1_Bz2 = hadamard(&Az1, &Bz2)?; + let Az2_Bz1 = hadamard(&Az2, &Bz1)?; let u1Cz2 = vec_scalar_mul(&Cz2, &u1); let u2Cz1 = vec_scalar_mul(&Cz1, &u2); - vec_sub(&vec_sub(&vec_add(&Az1_Bz2, &Az2_Bz1), &u1Cz2), &u2Cz1) + vec_sub(&vec_sub(&vec_add(&Az1_Bz2, &Az2_Bz1)?, &u1Cz2)?, &u2Cz1) } pub fn fold_witness(

@@ -51,17 +52,17 @@ w1: &Witness<C>,

w2: &Witness<C>, T: &[C::ScalarField], rT: C::ScalarField, - ) -> Witness<C> { + ) -> Result<Witness<C>, Error> { let r2 = r * r; let E: Vec<C::ScalarField> = vec_add( - &vec_add(&w1.E, &vec_scalar_mul(T, &r)), + &vec_add(&w1.E, &vec_scalar_mul(T, &r))?, &vec_scalar_mul(&w2.E, &r2), - ); + )?; let rE = w1.rE + r * rT + r2 * w2.rE; let W: Vec<C::ScalarField> = w1.W.iter().zip(&w2.W).map(|(a, b)| *a + (r * b)).collect(); let rW = w1.rW + r * w2.rW; - Witness::<C> { E, rE, W, rW } + Ok(Witness::<C> { E, rE, W, rW }) } pub fn fold_committed_instance(

@@ -95,22 +96,22 @@ w1: &Witness<C>,

ci1: &CommittedInstance<C>, w2: &Witness<C>, ci2: &CommittedInstance<C>, - ) -> (Witness<C>, CommittedInstance<C>, Vec<C::ScalarField>, C) { + ) -> Result<(Witness<C>, CommittedInstance<C>, Vec<C::ScalarField>, C), Error> { let z1: Vec<C::ScalarField> = [vec![ci1.u], ci1.x.to_vec(), w1.W.to_vec()].concat(); let z2: Vec<C::ScalarField> = [vec![ci2.u], ci2.x.to_vec(), w2.W.to_vec()].concat(); // compute cross terms - let T = Self::compute_T(r1cs, ci1.u, ci2.u, &z1, &z2); + let T = Self::compute_T(r1cs, ci1.u, ci2.u, &z1, &z2)?; let rT = C::ScalarField::one(); // use 1 as rT since we don't need hiding property for cm(T) let cmT = Pedersen::commit(pedersen_params, &T, &rT); // fold witness - let w3 = NIFS::<C>::fold_witness(r, w1, w2, &T, rT); + let w3 = NIFS::<C>::fold_witness(r, w1, w2, &T, rT)?; // fold committed instancs let ci3 = NIFS::<C>::fold_committed_instance(r, ci1, ci2, &cmT); - (w3, ci3, T, cmT) + Ok((w3, ci3, T, cmT)) } // NIFS.V

@@ -124,28 +125,30 @@ ) -> CommittedInstance<C> {

NIFS::<C>::fold_committed_instance(r, ci1, ci2, cmT) } - // verify commited folded instance (ci) relations + /// Verify commited folded instance (ci) relations. Notice that this method does not open the + /// commitments, but just checks that the given committed instances (ci1, ci2) when folded + /// result in the folded committed instance (ci3) values. pub fn verify_folded_instance( r: C::ScalarField, ci1: &CommittedInstance<C>, ci2: &CommittedInstance<C>, ci3: &CommittedInstance<C>, cmT: &C, - ) -> bool { + ) -> Result<(), Error> { let r2 = r * r; if ci3.cmE != (ci1.cmE + cmT.mul(r) + ci2.cmE.mul(r2)) { - return false; + return Err(Error::NotSatisfied); } if ci3.u != ci1.u + r * ci2.u { - return false; + return Err(Error::NotSatisfied); } if ci3.cmW != (ci1.cmW + ci2.cmW.mul(r)) { - return false; + return Err(Error::NotSatisfied); } - if ci3.x != vec_add(&ci1.x, &vec_scalar_mul(&ci2.x, &r)) { - return false; + if ci3.x != vec_add(&ci1.x, &vec_scalar_mul(&ci2.x, &r))? { + return Err(Error::NotSatisfied); } - true + Ok(()) } pub fn open_commitments(

@@ -155,31 +158,33 @@ w: &Witness<C>,

ci: &CommittedInstance<C>, T: Vec<C::ScalarField>, cmT: &C, - ) -> (PedersenProof<C>, PedersenProof<C>, PedersenProof<C>) { - let cmE_proof = Pedersen::prove(pedersen_params, tr, &ci.cmE, &w.E, &w.rE); - let cmW_proof = Pedersen::prove(pedersen_params, tr, &ci.cmW, &w.W, &w.rW); - let cmT_proof = Pedersen::prove(pedersen_params, tr, cmT, &T, &C::ScalarField::one()); // cm(T) is committed with rT=1 - (cmE_proof, cmW_proof, cmT_proof) + ) -> Result<[PedersenProof<C>; 3], Error> { + let cmE_proof = Pedersen::prove(pedersen_params, tr, &ci.cmE, &w.E, &w.rE)?; + let cmW_proof = Pedersen::prove(pedersen_params, tr, &ci.cmW, &w.W, &w.rW)?; + let cmT_proof = Pedersen::prove(pedersen_params, tr, cmT, &T, &C::ScalarField::one())?; // cm(T) is committed with rT=1 + Ok([cmE_proof, cmW_proof, cmT_proof]) } pub fn verify_commitments( tr: &mut impl Transcript<C>, pedersen_params: &PedersenParams<C>, ci: CommittedInstance<C>, cmT: C, - cmE_proof: PedersenProof<C>, - cmW_proof: PedersenProof<C>, - cmT_proof: PedersenProof<C>, - ) -> bool { - if !Pedersen::verify(pedersen_params, tr, ci.cmE, cmE_proof) { - return false; + cm_proofs: [PedersenProof<C>; 3], + ) -> Result<(), Error> { + if cm_proofs.len() != 3 { + // cm_proofs should have length 3: [cmE_proof, cmW_proof, cmT_proof] + return Err(Error::NotExpectedLength); + } + if !Pedersen::verify(pedersen_params, tr, ci.cmE, cm_proofs[0].clone()) { + return Err(Error::CommitmentVerificationFail); } - if !Pedersen::verify(pedersen_params, tr, ci.cmW, cmW_proof) { - return false; + if !Pedersen::verify(pedersen_params, tr, ci.cmW, cm_proofs[1].clone()) { + return Err(Error::CommitmentVerificationFail); } - if !Pedersen::verify(pedersen_params, tr, cmT, cmT_proof) { - return false; + if !Pedersen::verify(pedersen_params, tr, cmT, cm_proofs[2].clone()) { + return Err(Error::CommitmentVerificationFail); } - true + Ok(()) } }

@@ -222,7 +227,7 @@ let ci2 = w2.commit(&pedersen_params, x2.clone());

// NIFS.P let (w3, _, T, cmT) = - NIFS::<Projective>::prove(&pedersen_params, r, &r1cs, &w1, &ci1, &w2, &ci2); + NIFS::<Projective>::prove(&pedersen_params, r, &r1cs, &w1, &ci1, &w2, &ci2).unwrap(); // NIFS.V let ci3 = NIFS::<Projective>::verify(r, &ci1, &ci2, &cmT);

@@ -230,7 +235,7 @@

// naive check that the folded witness satisfies the relaxed r1cs let z3: Vec<Fr> = [vec![ci3.u], ci3.x.to_vec(), w3.W.to_vec()].concat(); // check that z3 is as expected - let z3_aux = vec_add(&z1, &vec_scalar_mul(&z2, &r)); + let z3_aux = vec_add(&z1, &vec_scalar_mul(&z2, &r)).unwrap(); assert_eq!(z3, z3_aux); // check that relations hold for the 2 inputted instances and the folded one check_relaxed_r1cs(&r1cs, z1, ci1.u, &w1.E);

@@ -244,9 +249,7 @@ assert_eq!(ci3_expected.cmE, ci3.cmE);

assert_eq!(ci3_expected.cmW, ci3.cmW); // NIFS.Verify_Folded_Instance: - assert!(NIFS::<Projective>::verify_folded_instance( - r, &ci1, &ci2, &ci3, &cmT - )); + NIFS::<Projective>::verify_folded_instance(r, &ci1, &ci2, &ci3, &cmT).unwrap(); let poseidon_config = poseidon_test_config::<Fr>(); // init Prover's transcript

@@ -255,24 +258,23 @@ // init Verifier's transcript

let mut transcript_v = PoseidonTranscript::<Projective>::new(&poseidon_config); // check openings of ci3.cmE, ci3.cmW and cmT - let (cmE_proof, cmW_proof, cmT_proof) = NIFS::<Projective>::open_commitments( + let cm_proofs = NIFS::<Projective>::open_commitments( &mut transcript_p, &pedersen_params, &w3, &ci3, T, &cmT, - ); - let v = NIFS::<Projective>::verify_commitments( + ) + .unwrap(); + NIFS::<Projective>::verify_commitments( &mut transcript_v, &pedersen_params, ci3, cmT, - cmE_proof, - cmW_proof, - cmT_proof, - ); - assert!(v); + cm_proofs, + ) + .unwrap(); } #[test]

@@ -319,7 +321,8 @@ &running_instance_w,

&running_committed_instance, &incomming_instance_w, &incomming_committed_instance, - ); + ) + .unwrap(); // NIFS.V let folded_committed_instance = NIFS::<Projective>::verify(
M src/lib.rs → src/lib.rs

@@ -16,10 +16,23 @@ pub mod frontend;

pub mod pedersen; pub mod utils; -#[derive(Debug, Error)] +#[derive(Debug, Error, PartialEq)] pub enum Error { + #[error("ark_relations::r1cs::SynthesisError")] + SynthesisError(#[from] ark_relations::r1cs::SynthesisError), + #[error("Relation not satisfied")] NotSatisfied, + #[error("Not equal")] + NotEqual, + #[error("Vectors should have the same length")] + NotSameLength, + #[error("Vector's length is not the expected")] + NotExpectedLength, + #[error("Can not be empty")] + Empty, + #[error("Commitment verification failed")] + CommitmentVerificationFail, } /// FoldingScheme defines trait that is implemented by the diverse folding schemes. It is defined
M src/pedersen.rs → src/pedersen.rs

@@ -5,6 +5,7 @@

use crate::utils::vec::{vec_add, vec_scalar_mul}; use crate::transcript::Transcript; +use crate::Error; #[derive(Debug, Clone, Eq, PartialEq)] pub struct Proof<C: CurveGroup> {

@@ -47,7 +48,7 @@ transcript: &mut impl Transcript<C>,

cm: &C, v: &Vec<C::ScalarField>, r: &C::ScalarField, - ) -> Proof<C> { + ) -> Result<Proof<C>, Error> { transcript.absorb_point(cm); let r1 = transcript.get_challenge(); let d = transcript.get_challenges(v.len());

@@ -59,11 +60,11 @@ transcript.absorb_point(&R);

let e = transcript.get_challenge(); // u = d + v⋅e - let u = vec_add(&vec_scalar_mul(v, &e), &d); + let u = vec_add(&vec_scalar_mul(v, &e), &d)?; // r_u = e⋅r + r_1 let r_u = e * r + r1; - Proof::<C> { R, u, r_u } + Ok(Proof::<C> { R, u, r_u }) } pub fn verify(

@@ -113,7 +114,7 @@

let v: Vec<Fr> = vec![Fr::rand(&mut rng); n]; let r: Fr = Fr::rand(&mut rng); let cm = Pedersen::<Projective>::commit(&params, &v, &r); - let proof = Pedersen::<Projective>::prove(&params, &mut transcript_p, &cm, &v, &r); + let proof = Pedersen::<Projective>::prove(&params, &mut transcript_p, &cm, &v, &r).unwrap(); let v = Pedersen::<Projective>::verify(&params, &mut transcript_v, cm, proof); assert!(v); }
M src/utils/vec.rs → src/utils/vec.rs

@@ -3,6 +3,8 @@ pub use ark_relations::r1cs::Matrix as R1CSMatrix;

use ark_std::cfg_iter; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; +use crate::Error; + #[derive(Clone, Debug, Eq, PartialEq)] pub struct SparseMatrix<F: PrimeField> { pub n_rows: usize,

@@ -42,22 +44,26 @@ }

r } -pub fn vec_add<F: PrimeField>(a: &[F], b: &[F]) -> Vec<F> { - assert_eq!(a.len(), b.len()); +pub fn vec_add<F: PrimeField>(a: &[F], b: &[F]) -> Result<Vec<F>, Error> { + if a.len() != b.len() { + return Err(Error::NotSameLength); + } let mut r: Vec<F> = vec![F::zero(); a.len()]; for i in 0..a.len() { r[i] = a[i] + b[i]; } - r + Ok(r) } -pub fn vec_sub<F: PrimeField>(a: &[F], b: &[F]) -> Vec<F> { - assert_eq!(a.len(), b.len()); +pub fn vec_sub<F: PrimeField>(a: &[F], b: &[F]) -> Result<Vec<F>, Error> { + if a.len() != b.len() { + return Err(Error::NotSameLength); + } let mut r: Vec<F> = vec![F::zero(); a.len()]; for i in 0..a.len() { r[i] = a[i] - b[i]; } - r + Ok(r) } pub fn vec_scalar_mul<F: PrimeField>(vec: &[F], c: &F) -> Vec<F> {

@@ -77,9 +83,13 @@ }

true } -pub fn mat_vec_mul<F: PrimeField>(M: &Vec<Vec<F>>, z: &[F]) -> Vec<F> { - assert!(!M.is_empty()); - assert_eq!(M[0].len(), z.len()); +pub fn mat_vec_mul<F: PrimeField>(M: &Vec<Vec<F>>, z: &[F]) -> Result<Vec<F>, Error> { + if M.is_empty() { + return Err(Error::Empty); + } + if M[0].len() != z.len() { + return Err(Error::NotSameLength); + } let mut r: Vec<F> = vec![F::zero(); M.len()]; for (i, M_i) in M.iter().enumerate() {

@@ -87,7 +97,7 @@ for (j, M_ij) in M_i.iter().enumerate() {

r[i] += *M_ij * z[j]; } } - r + Ok(r) } pub fn mat_vec_mul_sparse<F: PrimeField>(matrix: &SparseMatrix<F>, vector: &[F]) -> Vec<F> {

@@ -101,9 +111,11 @@

res } -pub fn hadamard<F: PrimeField>(a: &[F], b: &[F]) -> Vec<F> { - assert_eq!(a.len(), b.len()); - cfg_iter!(a).zip(b).map(|(a, b)| *a * b).collect() +pub fn hadamard<F: PrimeField>(a: &[F], b: &[F]) -> Result<Vec<F>, Error> { + if a.len() != b.len() { + return Err(Error::NotSameLength); + } + Ok(cfg_iter!(a).zip(b).map(|(a, b)| *a * b).collect()) } #[cfg(test)]

@@ -155,7 +167,7 @@ vec![5, 0, 0, 0, 0, 1],

]) .to_dense(); let z = to_F_vec(vec![1, 3, 35, 9, 27, 30]); - assert_eq!(mat_vec_mul(&A, &z), to_F_vec(vec![3, 9, 30, 35])); + assert_eq!(mat_vec_mul(&A, &z).unwrap(), to_F_vec(vec![3, 9, 30, 35])); assert_eq!( mat_vec_mul_sparse(&dense_matrix_to_sparse(A), &z), to_F_vec(vec![3, 9, 30, 35])

@@ -165,7 +177,7 @@ let A = to_F_matrix::<Fr>(vec![vec![2, 3, 4, 5], vec![4, 8, 12, 14], vec![9, 8, 7, 6]]);

let v = to_F_vec(vec![19, 55, 50, 3]); assert_eq!( - mat_vec_mul(&A.to_dense(), &v), + mat_vec_mul(&A.to_dense(), &v).unwrap(), to_F_vec(vec![418, 1158, 979]) ); assert_eq!(mat_vec_mul_sparse(&A, &v), to_F_vec(vec![418, 1158, 979]));

@@ -175,12 +187,18 @@ #[test]

fn test_hadamard_product() { let a = to_F_vec::<Fr>(vec![1, 2, 3, 4, 5, 6]); let b = to_F_vec(vec![7, 8, 9, 10, 11, 12]); - assert_eq!(hadamard(&a, &b), to_F_vec(vec![7, 16, 27, 40, 55, 72])); + assert_eq!( + hadamard(&a, &b).unwrap(), + to_F_vec(vec![7, 16, 27, 40, 55, 72]) + ); } #[test] fn test_vec_add() { let a: Vec<Fr> = to_F_vec::<Fr>(vec![1, 2, 3, 4, 5, 6]); let b: Vec<Fr> = to_F_vec(vec![7, 8, 9, 10, 11, 12]); - assert_eq!(vec_add(&a, &b), to_F_vec(vec![8, 10, 12, 14, 16, 18])); + assert_eq!( + vec_add(&a, &b).unwrap(), + to_F_vec(vec![8, 10, 12, 14, 16, 18]) + ); } }