mirror of
https://github.com/arnaucube/sonobe.git
synced 2026-01-10 07:51:32 +01:00
add error handling to several pending methods (#30)
This commit is contained in:
@@ -1 +1 @@
|
|||||||
1.71.0
|
1.71.1
|
||||||
|
|||||||
@@ -51,14 +51,14 @@ impl<C: CurveGroup> CCS<C> {
|
|||||||
// complete the hadamard chain
|
// complete the hadamard chain
|
||||||
let mut hadamard_result = vec![C::ScalarField::one(); self.m];
|
let mut hadamard_result = vec![C::ScalarField::one(); self.m];
|
||||||
for M_j in vec_M_j.into_iter() {
|
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
|
// multiply by the coefficient of this step
|
||||||
let c_M_j_z = vec_scalar_mul(&hadamard_result, &self.c[i]);
|
let c_M_j_z = vec_scalar_mul(&hadamard_result, &self.c[i]);
|
||||||
|
|
||||||
// add it to the final vector
|
// 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
|
// make sure the final vector is all zeroes
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ impl<F: PrimeField> R1CS<F> {
|
|||||||
let Az = mat_vec_mul_sparse(&self.A, z);
|
let Az = mat_vec_mul_sparse(&self.A, z);
|
||||||
let Bz = mat_vec_mul_sparse(&self.B, z);
|
let Bz = mat_vec_mul_sparse(&self.B, z);
|
||||||
let Cz = mat_vec_mul_sparse(&self.C, z);
|
let Cz = mat_vec_mul_sparse(&self.C, z);
|
||||||
let AzBz = hadamard(&Az, &Bz);
|
let AzBz = hadamard(&Az, &Bz)?;
|
||||||
assert_eq!(AzBz, Cz);
|
if AzBz != Cz {
|
||||||
|
return Err(Error::NotSatisfied);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -60,7 +62,9 @@ impl<F: PrimeField> RelaxedR1CS<F> {
|
|||||||
let uCz = vec_scalar_mul(&Cz, &self.u);
|
let uCz = vec_scalar_mul(&Cz, &self.u);
|
||||||
let uCzE = vec_add(&uCz, &self.E);
|
let uCzE = vec_add(&uCz, &self.E);
|
||||||
let AzBz = hadamard(&Az, &Bz);
|
let AzBz = hadamard(&Az, &Bz);
|
||||||
assert_eq!(AzBz, uCzE);
|
if AzBz != uCzE {
|
||||||
|
return Err(Error::NotSatisfied);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use core::{borrow::Borrow, marker::PhantomData};
|
|||||||
|
|
||||||
use crate::ccs::r1cs::RelaxedR1CS;
|
use crate::ccs::r1cs::RelaxedR1CS;
|
||||||
use crate::utils::vec::SparseMatrix;
|
use crate::utils::vec::SparseMatrix;
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
pub type ConstraintF<C> = <<C as CurveGroup>::BaseField as Field>::BasePrimeField;
|
pub type ConstraintF<C> = <<C as CurveGroup>::BaseField as Field>::BasePrimeField;
|
||||||
|
|
||||||
@@ -19,13 +20,13 @@ pub struct RelaxedR1CSGadget<F: PrimeField> {
|
|||||||
}
|
}
|
||||||
impl<F: PrimeField> RelaxedR1CSGadget<F> {
|
impl<F: PrimeField> RelaxedR1CSGadget<F> {
|
||||||
/// performs the RelaxedR1CS check (Az∘Bz==uCz+E)
|
/// 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 Az = mat_vec_mul_sparse(rel_r1cs.A, z.clone());
|
||||||
let Bz = mat_vec_mul_sparse(rel_r1cs.B, 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 Cz = mat_vec_mul_sparse(rel_r1cs.C, z.clone());
|
||||||
let uCz = vec_scalar_mul(&Cz, &rel_r1cs.u);
|
let uCz = vec_scalar_mul(&Cz, &rel_r1cs.u);
|
||||||
let uCzE = vec_add(&uCz, &rel_r1cs.E);
|
let uCzE = vec_add(&uCz, &rel_r1cs.E)?;
|
||||||
let AzBz = hadamard(&Az, &Bz);
|
let AzBz = hadamard(&Az, &Bz)?;
|
||||||
for i in 0..AzBz.len() {
|
for i in 0..AzBz.len() {
|
||||||
AzBz[i].enforce_equal(&uCzE[i].clone())?;
|
AzBz[i].enforce_equal(&uCzE[i].clone())?;
|
||||||
}
|
}
|
||||||
@@ -42,13 +43,18 @@ fn mat_vec_mul_sparse<F: PrimeField>(m: SparseMatrixVar<F>, v: Vec<FpVar<F>>) ->
|
|||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
pub fn vec_add<F: PrimeField>(a: &Vec<FpVar<F>>, b: &Vec<FpVar<F>>) -> Vec<FpVar<F>> {
|
pub fn vec_add<F: PrimeField>(
|
||||||
assert_eq!(a.len(), b.len());
|
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()];
|
let mut r: Vec<FpVar<F>> = vec![FpVar::<F>::zero(); a.len()];
|
||||||
for i in 0..a.len() {
|
for i in 0..a.len() {
|
||||||
r[i] = a[i].clone() + b[i].clone();
|
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>> {
|
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()];
|
let mut result = vec![FpVar::<F>::zero(); vec.len()];
|
||||||
@@ -57,13 +63,18 @@ pub fn vec_scalar_mul<F: PrimeField>(vec: &Vec<FpVar<F>>, c: &FpVar<F>) -> Vec<F
|
|||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
pub fn hadamard<F: PrimeField>(a: &Vec<FpVar<F>>, b: &Vec<FpVar<F>>) -> Vec<FpVar<F>> {
|
pub fn hadamard<F: PrimeField>(
|
||||||
assert_eq!(a.len(), b.len());
|
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()];
|
let mut r: Vec<FpVar<F>> = vec![FpVar::<F>::zero(); a.len()];
|
||||||
for i in 0..a.len() {
|
for i in 0..a.len() {
|
||||||
r[i] = a[i].clone() * b[i].clone();
|
r[i] = a[i].clone() * b[i].clone();
|
||||||
}
|
}
|
||||||
r
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@@ -109,7 +109,9 @@ impl<C: CurveGroup> CCCS<C> {
|
|||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// check that C is the commitment of w. Notice that this is not verifying a Pedersen
|
// 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.
|
// 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
|
// check CCCS relation
|
||||||
let z: Vec<C::ScalarField> =
|
let z: Vec<C::ScalarField> =
|
||||||
|
|||||||
@@ -94,12 +94,16 @@ impl<C: CurveGroup> LCCCS<C> {
|
|||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// check that C is the commitment of w. Notice that this is not verifying a Pedersen
|
// 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.
|
// 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
|
// check CCS relation
|
||||||
let z: Vec<C::ScalarField> = [vec![self.u], self.x.clone(), w.w.to_vec()].concat();
|
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);
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use crate::utils::hypercube::BooleanHypercube;
|
|||||||
use crate::utils::sum_check::structs::IOPProof as SumCheckProof;
|
use crate::utils::sum_check::structs::IOPProof as SumCheckProof;
|
||||||
use crate::utils::sum_check::{verifier::interpolate_uni_poly, SumCheck};
|
use crate::utils::sum_check::{verifier::interpolate_uni_poly, SumCheck};
|
||||||
use crate::utils::virtual_polynomial::VPAuxInfo;
|
use crate::utils::virtual_polynomial::VPAuxInfo;
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
@@ -139,8 +140,9 @@ impl<C: CurveGroup> NIMFS<C> {
|
|||||||
|
|
||||||
/// Performs the multifolding prover. Given μ LCCCS instances and ν CCS instances, fold them
|
/// 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.
|
/// 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
|
/// Returns the final folded LCCCS, the folded witness, and the multifolding proof, which
|
||||||
/// sumcheck claim sigmas and thetas.
|
/// contains the sumcheck proof and the helper sumcheck claim sigmas and thetas.
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn prove(
|
pub fn prove(
|
||||||
transcript: &mut IOPTranscript<C::ScalarField>,
|
transcript: &mut IOPTranscript<C::ScalarField>,
|
||||||
ccs: &CCS<C>,
|
ccs: &CCS<C>,
|
||||||
@@ -148,11 +150,15 @@ impl<C: CurveGroup> NIMFS<C> {
|
|||||||
new_instances: &[CCCS<C>],
|
new_instances: &[CCCS<C>],
|
||||||
w_lcccs: &[Witness<C::ScalarField>],
|
w_lcccs: &[Witness<C::ScalarField>],
|
||||||
w_cccs: &[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
|
// TODO appends to transcript
|
||||||
|
|
||||||
assert!(!running_instances.is_empty());
|
if running_instances.is_empty() {
|
||||||
assert!(!new_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
|
// construct the LCCCS z vector from the relaxation factor, public IO and witness
|
||||||
// XXX this deserves its own function in LCCCS
|
// XXX this deserves its own function in LCCCS
|
||||||
@@ -205,7 +211,9 @@ impl<C: CurveGroup> NIMFS<C> {
|
|||||||
// note: this is the sum of g(x) over the whole boolean hypercube
|
// note: this is the sum of g(x) over the whole boolean hypercube
|
||||||
let extracted_sum =
|
let extracted_sum =
|
||||||
<PolyIOP<C::ScalarField> as SumCheck<C::ScalarField>>::extract_sum(&sumcheck_proof);
|
<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
|
// 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).
|
// boolean hypercube (and also equal to the extracted_sum from the SumCheck).
|
||||||
let mut sum_v_j_gamma = C::ScalarField::zero();
|
let mut sum_v_j_gamma = C::ScalarField::zero();
|
||||||
@@ -215,8 +223,12 @@ impl<C: CurveGroup> NIMFS<C> {
|
|||||||
sum_v_j_gamma += running_instance.v[j] * gamma_j;
|
sum_v_j_gamma += running_instance.v[j] * gamma_j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert_eq!(g_over_bhc, sum_v_j_gamma);
|
if g_over_bhc != sum_v_j_gamma {
|
||||||
assert_eq!(extracted_sum, 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
|
// Step 2: dig into the sumcheck and extract r_x_prime
|
||||||
@@ -240,14 +252,14 @@ impl<C: CurveGroup> NIMFS<C> {
|
|||||||
// Step 8: Fold the witnesses
|
// Step 8: Fold the witnesses
|
||||||
let folded_witness = Self::fold_witness(w_lcccs, w_cccs, rho);
|
let folded_witness = Self::fold_witness(w_lcccs, w_cccs, rho);
|
||||||
|
|
||||||
(
|
Ok((
|
||||||
Proof::<C> {
|
Proof::<C> {
|
||||||
sc_proof: sumcheck_proof,
|
sc_proof: sumcheck_proof,
|
||||||
sigmas_thetas,
|
sigmas_thetas,
|
||||||
},
|
},
|
||||||
folded_lcccs,
|
folded_lcccs,
|
||||||
folded_witness,
|
folded_witness,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs the multifolding verifier. Given μ LCCCS instances and ν CCS instances, fold them
|
/// Performs the multifolding verifier. Given μ LCCCS instances and ν CCS instances, fold them
|
||||||
@@ -259,11 +271,15 @@ impl<C: CurveGroup> NIMFS<C> {
|
|||||||
running_instances: &[LCCCS<C>],
|
running_instances: &[LCCCS<C>],
|
||||||
new_instances: &[CCCS<C>],
|
new_instances: &[CCCS<C>],
|
||||||
proof: Proof<C>,
|
proof: Proof<C>,
|
||||||
) -> LCCCS<C> {
|
) -> Result<LCCCS<C>, Error> {
|
||||||
// TODO appends to transcript
|
// TODO appends to transcript
|
||||||
|
|
||||||
assert!(!running_instances.is_empty());
|
if running_instances.is_empty() {
|
||||||
assert!(!new_instances.is_empty());
|
return Err(Error::Empty);
|
||||||
|
}
|
||||||
|
if new_instances.is_empty() {
|
||||||
|
return Err(Error::Empty);
|
||||||
|
}
|
||||||
|
|
||||||
// Step 1: Get some challenges
|
// Step 1: Get some challenges
|
||||||
let gamma: C::ScalarField = transcript.get_and_append_challenge(b"gamma").unwrap();
|
let gamma: C::ScalarField = transcript.get_and_append_challenge(b"gamma").unwrap();
|
||||||
@@ -312,7 +328,9 @@ impl<C: CurveGroup> NIMFS<C> {
|
|||||||
&r_x_prime,
|
&r_x_prime,
|
||||||
);
|
);
|
||||||
// check that the g(r_x') from the sumcheck proof is equal to the computed c from sigmas&thetas
|
// 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
|
// Sanity check: we can also compute g(r_x') from the proof last evaluation value, and
|
||||||
// should be equal to the previously obtained values.
|
// should be equal to the previously obtained values.
|
||||||
@@ -321,23 +339,24 @@ impl<C: CurveGroup> NIMFS<C> {
|
|||||||
*r_x_prime.last().unwrap(),
|
*r_x_prime.last().unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(g_on_rxprime_from_sumcheck_last_eval, c);
|
if g_on_rxprime_from_sumcheck_last_eval != c {
|
||||||
assert_eq!(
|
return Err(Error::NotEqual);
|
||||||
g_on_rxprime_from_sumcheck_last_eval,
|
}
|
||||||
sumcheck_subclaim.expected_evaluation
|
if g_on_rxprime_from_sumcheck_last_eval != sumcheck_subclaim.expected_evaluation {
|
||||||
);
|
return Err(Error::NotEqual);
|
||||||
|
}
|
||||||
|
|
||||||
// Step 6: Get the folding challenge
|
// Step 6: Get the folding challenge
|
||||||
let rho: C::ScalarField = transcript.get_and_append_challenge(b"rho").unwrap();
|
let rho: C::ScalarField = transcript.get_and_append_challenge(b"rho").unwrap();
|
||||||
|
|
||||||
// Step 7: Compute the folded instance
|
// Step 7: Compute the folded instance
|
||||||
Self::fold(
|
Ok(Self::fold(
|
||||||
running_instances,
|
running_instances,
|
||||||
new_instances,
|
new_instances,
|
||||||
&proof.sigmas_thetas,
|
&proof.sigmas_thetas,
|
||||||
r_x_prime,
|
r_x_prime,
|
||||||
rho,
|
rho,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,7 +436,8 @@ pub mod tests {
|
|||||||
&[new_instance.clone()],
|
&[new_instance.clone()],
|
||||||
&[w1],
|
&[w1],
|
||||||
&[w2],
|
&[w2],
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Verifier's transcript
|
// Verifier's transcript
|
||||||
let mut transcript_v = IOPTranscript::<Fr>::new(b"multifolding");
|
let mut transcript_v = IOPTranscript::<Fr>::new(b"multifolding");
|
||||||
@@ -430,7 +450,8 @@ pub mod tests {
|
|||||||
&[running_instance.clone()],
|
&[running_instance.clone()],
|
||||||
&[new_instance.clone()],
|
&[new_instance.clone()],
|
||||||
proof,
|
proof,
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(folded_lcccs, folded_lcccs_v);
|
assert_eq!(folded_lcccs, folded_lcccs_v);
|
||||||
|
|
||||||
// Check that the folded LCCCS instance is a valid instance with respect to the folded witness
|
// Check that the folded LCCCS instance is a valid instance with respect to the folded witness
|
||||||
@@ -475,7 +496,8 @@ pub mod tests {
|
|||||||
&[new_instance.clone()],
|
&[new_instance.clone()],
|
||||||
&[w1],
|
&[w1],
|
||||||
&[w2],
|
&[w2],
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// run the verifier side of the multifolding
|
// run the verifier side of the multifolding
|
||||||
let folded_lcccs_v = NIMFS::<Projective>::verify(
|
let folded_lcccs_v = NIMFS::<Projective>::verify(
|
||||||
@@ -484,7 +506,8 @@ pub mod tests {
|
|||||||
&[running_instance.clone()],
|
&[running_instance.clone()],
|
||||||
&[new_instance.clone()],
|
&[new_instance.clone()],
|
||||||
proof,
|
proof,
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(folded_lcccs, folded_lcccs_v);
|
assert_eq!(folded_lcccs, folded_lcccs_v);
|
||||||
|
|
||||||
@@ -552,7 +575,8 @@ pub mod tests {
|
|||||||
&cccs_instances,
|
&cccs_instances,
|
||||||
&w_lcccs,
|
&w_lcccs,
|
||||||
&w_cccs,
|
&w_cccs,
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Verifier's transcript
|
// Verifier's transcript
|
||||||
let mut transcript_v = IOPTranscript::<Fr>::new(b"multifolding");
|
let mut transcript_v = IOPTranscript::<Fr>::new(b"multifolding");
|
||||||
@@ -565,7 +589,8 @@ pub mod tests {
|
|||||||
&lcccs_instances,
|
&lcccs_instances,
|
||||||
&cccs_instances,
|
&cccs_instances,
|
||||||
proof,
|
proof,
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(folded_lcccs, folded_lcccs_v);
|
assert_eq!(folded_lcccs, folded_lcccs_v);
|
||||||
|
|
||||||
// Check that the folded LCCCS instance is a valid instance with respect to the folded witness
|
// Check that the folded LCCCS instance is a valid instance with respect to the folded witness
|
||||||
@@ -636,7 +661,8 @@ pub mod tests {
|
|||||||
&cccs_instances,
|
&cccs_instances,
|
||||||
&w_lcccs,
|
&w_lcccs,
|
||||||
&w_cccs,
|
&w_cccs,
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Run the verifier side of the multifolding
|
// Run the verifier side of the multifolding
|
||||||
let folded_lcccs_v = NIMFS::<Projective>::verify(
|
let folded_lcccs_v = NIMFS::<Projective>::verify(
|
||||||
@@ -645,7 +671,8 @@ pub mod tests {
|
|||||||
&lcccs_instances,
|
&lcccs_instances,
|
||||||
&cccs_instances,
|
&cccs_instances,
|
||||||
proof,
|
proof,
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(folded_lcccs, folded_lcccs_v);
|
assert_eq!(folded_lcccs, folded_lcccs_v);
|
||||||
|
|
||||||
// Check that the folded LCCCS instance is a valid instance with respect to the folded witness
|
// Check that the folded LCCCS instance is a valid instance with respect to the folded witness
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ mod tests {
|
|||||||
let r_Fr = Fr::from_bigint(BigInteger::from_bits_le(&r_bits)).unwrap();
|
let r_Fr = Fr::from_bigint(BigInteger::from_bits_le(&r_bits)).unwrap();
|
||||||
|
|
||||||
let (_w3, ci3, _T, cmT) =
|
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();
|
let cs = ConstraintSystem::<Fr>::new_ref();
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use crate::folding::nova::{CommittedInstance, Witness};
|
|||||||
use crate::pedersen::{Params as PedersenParams, Pedersen, Proof as PedersenProof};
|
use crate::pedersen::{Params as PedersenParams, Pedersen, Proof as PedersenProof};
|
||||||
use crate::transcript::Transcript;
|
use crate::transcript::Transcript;
|
||||||
use crate::utils::vec::*;
|
use crate::utils::vec::*;
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
/// Implements the Non-Interactive Folding Scheme described in section 4 of
|
/// Implements the Non-Interactive Folding Scheme described in section 4 of
|
||||||
/// https://eprint.iacr.org/2021/370.pdf
|
/// https://eprint.iacr.org/2021/370.pdf
|
||||||
@@ -26,7 +27,7 @@ where
|
|||||||
u2: C::ScalarField,
|
u2: C::ScalarField,
|
||||||
z1: &[C::ScalarField],
|
z1: &[C::ScalarField],
|
||||||
z2: &[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());
|
let (A, B, C) = (r1cs.A.clone(), r1cs.B.clone(), r1cs.C.clone());
|
||||||
|
|
||||||
// this is parallelizable (for the future)
|
// this is parallelizable (for the future)
|
||||||
@@ -37,12 +38,12 @@ where
|
|||||||
let Bz2 = mat_vec_mul_sparse(&B, z2);
|
let Bz2 = mat_vec_mul_sparse(&B, z2);
|
||||||
let Cz2 = mat_vec_mul_sparse(&C, z2);
|
let Cz2 = mat_vec_mul_sparse(&C, z2);
|
||||||
|
|
||||||
let Az1_Bz2 = hadamard(&Az1, &Bz2);
|
let Az1_Bz2 = hadamard(&Az1, &Bz2)?;
|
||||||
let Az2_Bz1 = hadamard(&Az2, &Bz1);
|
let Az2_Bz1 = hadamard(&Az2, &Bz1)?;
|
||||||
let u1Cz2 = vec_scalar_mul(&Cz2, &u1);
|
let u1Cz2 = vec_scalar_mul(&Cz2, &u1);
|
||||||
let u2Cz1 = vec_scalar_mul(&Cz1, &u2);
|
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(
|
pub fn fold_witness(
|
||||||
@@ -51,17 +52,17 @@ where
|
|||||||
w2: &Witness<C>,
|
w2: &Witness<C>,
|
||||||
T: &[C::ScalarField],
|
T: &[C::ScalarField],
|
||||||
rT: C::ScalarField,
|
rT: C::ScalarField,
|
||||||
) -> Witness<C> {
|
) -> Result<Witness<C>, Error> {
|
||||||
let r2 = r * r;
|
let r2 = r * r;
|
||||||
let E: Vec<C::ScalarField> = vec_add(
|
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),
|
&vec_scalar_mul(&w2.E, &r2),
|
||||||
);
|
)?;
|
||||||
let rE = w1.rE + r * rT + r2 * w2.rE;
|
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 W: Vec<C::ScalarField> = w1.W.iter().zip(&w2.W).map(|(a, b)| *a + (r * b)).collect();
|
||||||
|
|
||||||
let rW = w1.rW + r * w2.rW;
|
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(
|
pub fn fold_committed_instance(
|
||||||
@@ -95,22 +96,22 @@ where
|
|||||||
ci1: &CommittedInstance<C>,
|
ci1: &CommittedInstance<C>,
|
||||||
w2: &Witness<C>,
|
w2: &Witness<C>,
|
||||||
ci2: &CommittedInstance<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 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();
|
let z2: Vec<C::ScalarField> = [vec![ci2.u], ci2.x.to_vec(), w2.W.to_vec()].concat();
|
||||||
|
|
||||||
// compute cross terms
|
// 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 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);
|
let cmT = Pedersen::commit(pedersen_params, &T, &rT);
|
||||||
|
|
||||||
// fold witness
|
// 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
|
// fold committed instancs
|
||||||
let ci3 = NIFS::<C>::fold_committed_instance(r, ci1, ci2, &cmT);
|
let ci3 = NIFS::<C>::fold_committed_instance(r, ci1, ci2, &cmT);
|
||||||
|
|
||||||
(w3, ci3, T, cmT)
|
Ok((w3, ci3, T, cmT))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NIFS.V
|
// NIFS.V
|
||||||
@@ -124,28 +125,30 @@ where
|
|||||||
NIFS::<C>::fold_committed_instance(r, ci1, ci2, cmT)
|
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(
|
pub fn verify_folded_instance(
|
||||||
r: C::ScalarField,
|
r: C::ScalarField,
|
||||||
ci1: &CommittedInstance<C>,
|
ci1: &CommittedInstance<C>,
|
||||||
ci2: &CommittedInstance<C>,
|
ci2: &CommittedInstance<C>,
|
||||||
ci3: &CommittedInstance<C>,
|
ci3: &CommittedInstance<C>,
|
||||||
cmT: &C,
|
cmT: &C,
|
||||||
) -> bool {
|
) -> Result<(), Error> {
|
||||||
let r2 = r * r;
|
let r2 = r * r;
|
||||||
if ci3.cmE != (ci1.cmE + cmT.mul(r) + ci2.cmE.mul(r2)) {
|
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 {
|
if ci3.u != ci1.u + r * ci2.u {
|
||||||
return false;
|
return Err(Error::NotSatisfied);
|
||||||
}
|
}
|
||||||
if ci3.cmW != (ci1.cmW + ci2.cmW.mul(r)) {
|
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)) {
|
if ci3.x != vec_add(&ci1.x, &vec_scalar_mul(&ci2.x, &r))? {
|
||||||
return false;
|
return Err(Error::NotSatisfied);
|
||||||
}
|
}
|
||||||
true
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_commitments(
|
pub fn open_commitments(
|
||||||
@@ -155,31 +158,33 @@ where
|
|||||||
ci: &CommittedInstance<C>,
|
ci: &CommittedInstance<C>,
|
||||||
T: Vec<C::ScalarField>,
|
T: Vec<C::ScalarField>,
|
||||||
cmT: &C,
|
cmT: &C,
|
||||||
) -> (PedersenProof<C>, PedersenProof<C>, PedersenProof<C>) {
|
) -> Result<[PedersenProof<C>; 3], Error> {
|
||||||
let cmE_proof = Pedersen::prove(pedersen_params, tr, &ci.cmE, &w.E, &w.rE);
|
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 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
|
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)
|
Ok([cmE_proof, cmW_proof, cmT_proof])
|
||||||
}
|
}
|
||||||
pub fn verify_commitments(
|
pub fn verify_commitments(
|
||||||
tr: &mut impl Transcript<C>,
|
tr: &mut impl Transcript<C>,
|
||||||
pedersen_params: &PedersenParams<C>,
|
pedersen_params: &PedersenParams<C>,
|
||||||
ci: CommittedInstance<C>,
|
ci: CommittedInstance<C>,
|
||||||
cmT: C,
|
cmT: C,
|
||||||
cmE_proof: PedersenProof<C>,
|
cm_proofs: [PedersenProof<C>; 3],
|
||||||
cmW_proof: PedersenProof<C>,
|
) -> Result<(), Error> {
|
||||||
cmT_proof: PedersenProof<C>,
|
if cm_proofs.len() != 3 {
|
||||||
) -> bool {
|
// cm_proofs should have length 3: [cmE_proof, cmW_proof, cmT_proof]
|
||||||
if !Pedersen::verify(pedersen_params, tr, ci.cmE, cmE_proof) {
|
return Err(Error::NotExpectedLength);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if !Pedersen::verify(pedersen_params, tr, ci.cmW, cmW_proof) {
|
if !Pedersen::verify(pedersen_params, tr, ci.cmE, cm_proofs[0].clone()) {
|
||||||
return false;
|
return Err(Error::CommitmentVerificationFail);
|
||||||
}
|
}
|
||||||
if !Pedersen::verify(pedersen_params, tr, cmT, cmT_proof) {
|
if !Pedersen::verify(pedersen_params, tr, ci.cmW, cm_proofs[1].clone()) {
|
||||||
return false;
|
return Err(Error::CommitmentVerificationFail);
|
||||||
}
|
}
|
||||||
true
|
if !Pedersen::verify(pedersen_params, tr, cmT, cm_proofs[2].clone()) {
|
||||||
|
return Err(Error::CommitmentVerificationFail);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +227,7 @@ mod tests {
|
|||||||
|
|
||||||
// NIFS.P
|
// NIFS.P
|
||||||
let (w3, _, T, cmT) =
|
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
|
// NIFS.V
|
||||||
let ci3 = NIFS::<Projective>::verify(r, &ci1, &ci2, &cmT);
|
let ci3 = NIFS::<Projective>::verify(r, &ci1, &ci2, &cmT);
|
||||||
@@ -230,7 +235,7 @@ mod tests {
|
|||||||
// naive check that the folded witness satisfies the relaxed r1cs
|
// 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();
|
let z3: Vec<Fr> = [vec![ci3.u], ci3.x.to_vec(), w3.W.to_vec()].concat();
|
||||||
// check that z3 is as expected
|
// 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);
|
assert_eq!(z3, z3_aux);
|
||||||
// check that relations hold for the 2 inputted instances and the folded one
|
// check that relations hold for the 2 inputted instances and the folded one
|
||||||
check_relaxed_r1cs(&r1cs, z1, ci1.u, &w1.E);
|
check_relaxed_r1cs(&r1cs, z1, ci1.u, &w1.E);
|
||||||
@@ -244,9 +249,7 @@ mod tests {
|
|||||||
assert_eq!(ci3_expected.cmW, ci3.cmW);
|
assert_eq!(ci3_expected.cmW, ci3.cmW);
|
||||||
|
|
||||||
// NIFS.Verify_Folded_Instance:
|
// NIFS.Verify_Folded_Instance:
|
||||||
assert!(NIFS::<Projective>::verify_folded_instance(
|
NIFS::<Projective>::verify_folded_instance(r, &ci1, &ci2, &ci3, &cmT).unwrap();
|
||||||
r, &ci1, &ci2, &ci3, &cmT
|
|
||||||
));
|
|
||||||
|
|
||||||
let poseidon_config = poseidon_test_config::<Fr>();
|
let poseidon_config = poseidon_test_config::<Fr>();
|
||||||
// init Prover's transcript
|
// init Prover's transcript
|
||||||
@@ -255,24 +258,23 @@ mod tests {
|
|||||||
let mut transcript_v = PoseidonTranscript::<Projective>::new(&poseidon_config);
|
let mut transcript_v = PoseidonTranscript::<Projective>::new(&poseidon_config);
|
||||||
|
|
||||||
// check openings of ci3.cmE, ci3.cmW and cmT
|
// 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,
|
&mut transcript_p,
|
||||||
&pedersen_params,
|
&pedersen_params,
|
||||||
&w3,
|
&w3,
|
||||||
&ci3,
|
&ci3,
|
||||||
T,
|
T,
|
||||||
&cmT,
|
&cmT,
|
||||||
);
|
)
|
||||||
let v = NIFS::<Projective>::verify_commitments(
|
.unwrap();
|
||||||
|
NIFS::<Projective>::verify_commitments(
|
||||||
&mut transcript_v,
|
&mut transcript_v,
|
||||||
&pedersen_params,
|
&pedersen_params,
|
||||||
ci3,
|
ci3,
|
||||||
cmT,
|
cmT,
|
||||||
cmE_proof,
|
cm_proofs,
|
||||||
cmW_proof,
|
)
|
||||||
cmT_proof,
|
.unwrap();
|
||||||
);
|
|
||||||
assert!(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -319,7 +321,8 @@ mod tests {
|
|||||||
&running_committed_instance,
|
&running_committed_instance,
|
||||||
&incomming_instance_w,
|
&incomming_instance_w,
|
||||||
&incomming_committed_instance,
|
&incomming_committed_instance,
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// NIFS.V
|
// NIFS.V
|
||||||
let folded_committed_instance = NIFS::<Projective>::verify(
|
let folded_committed_instance = NIFS::<Projective>::verify(
|
||||||
|
|||||||
15
src/lib.rs
15
src/lib.rs
@@ -16,10 +16,23 @@ pub mod frontend;
|
|||||||
pub mod pedersen;
|
pub mod pedersen;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
#[error("ark_relations::r1cs::SynthesisError")]
|
||||||
|
SynthesisError(#[from] ark_relations::r1cs::SynthesisError),
|
||||||
|
|
||||||
#[error("Relation not satisfied")]
|
#[error("Relation not satisfied")]
|
||||||
NotSatisfied,
|
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
|
/// FoldingScheme defines trait that is implemented by the diverse folding schemes. It is defined
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use std::marker::PhantomData;
|
|||||||
use crate::utils::vec::{vec_add, vec_scalar_mul};
|
use crate::utils::vec::{vec_add, vec_scalar_mul};
|
||||||
|
|
||||||
use crate::transcript::Transcript;
|
use crate::transcript::Transcript;
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct Proof<C: CurveGroup> {
|
pub struct Proof<C: CurveGroup> {
|
||||||
@@ -47,7 +48,7 @@ impl<C: CurveGroup> Pedersen<C> {
|
|||||||
cm: &C,
|
cm: &C,
|
||||||
v: &Vec<C::ScalarField>,
|
v: &Vec<C::ScalarField>,
|
||||||
r: &C::ScalarField,
|
r: &C::ScalarField,
|
||||||
) -> Proof<C> {
|
) -> Result<Proof<C>, Error> {
|
||||||
transcript.absorb_point(cm);
|
transcript.absorb_point(cm);
|
||||||
let r1 = transcript.get_challenge();
|
let r1 = transcript.get_challenge();
|
||||||
let d = transcript.get_challenges(v.len());
|
let d = transcript.get_challenges(v.len());
|
||||||
@@ -59,11 +60,11 @@ impl<C: CurveGroup> Pedersen<C> {
|
|||||||
let e = transcript.get_challenge();
|
let e = transcript.get_challenge();
|
||||||
|
|
||||||
// u = d + v⋅e
|
// 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
|
// r_u = e⋅r + r_1
|
||||||
let r_u = e * r + r1;
|
let r_u = e * r + r1;
|
||||||
|
|
||||||
Proof::<C> { R, u, r_u }
|
Ok(Proof::<C> { R, u, r_u })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify(
|
pub fn verify(
|
||||||
@@ -113,7 +114,7 @@ mod tests {
|
|||||||
let v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
|
let v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
|
||||||
let r: Fr = Fr::rand(&mut rng);
|
let r: Fr = Fr::rand(&mut rng);
|
||||||
let cm = Pedersen::<Projective>::commit(¶ms, &v, &r);
|
let cm = Pedersen::<Projective>::commit(¶ms, &v, &r);
|
||||||
let proof = Pedersen::<Projective>::prove(¶ms, &mut transcript_p, &cm, &v, &r);
|
let proof = Pedersen::<Projective>::prove(¶ms, &mut transcript_p, &cm, &v, &r).unwrap();
|
||||||
let v = Pedersen::<Projective>::verify(¶ms, &mut transcript_v, cm, proof);
|
let v = Pedersen::<Projective>::verify(¶ms, &mut transcript_v, cm, proof);
|
||||||
assert!(v);
|
assert!(v);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ pub use ark_relations::r1cs::Matrix as R1CSMatrix;
|
|||||||
use ark_std::cfg_iter;
|
use ark_std::cfg_iter;
|
||||||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||||
|
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct SparseMatrix<F: PrimeField> {
|
pub struct SparseMatrix<F: PrimeField> {
|
||||||
pub n_rows: usize,
|
pub n_rows: usize,
|
||||||
@@ -42,22 +44,26 @@ pub fn dense_matrix_to_sparse<F: PrimeField>(m: Vec<Vec<F>>) -> SparseMatrix<F>
|
|||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vec_add<F: PrimeField>(a: &[F], b: &[F]) -> Vec<F> {
|
pub fn vec_add<F: PrimeField>(a: &[F], b: &[F]) -> Result<Vec<F>, Error> {
|
||||||
assert_eq!(a.len(), b.len());
|
if a.len() != b.len() {
|
||||||
|
return Err(Error::NotSameLength);
|
||||||
|
}
|
||||||
let mut r: Vec<F> = vec![F::zero(); a.len()];
|
let mut r: Vec<F> = vec![F::zero(); a.len()];
|
||||||
for i in 0..a.len() {
|
for i in 0..a.len() {
|
||||||
r[i] = a[i] + b[i];
|
r[i] = a[i] + b[i];
|
||||||
}
|
}
|
||||||
r
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vec_sub<F: PrimeField>(a: &[F], b: &[F]) -> Vec<F> {
|
pub fn vec_sub<F: PrimeField>(a: &[F], b: &[F]) -> Result<Vec<F>, Error> {
|
||||||
assert_eq!(a.len(), b.len());
|
if a.len() != b.len() {
|
||||||
|
return Err(Error::NotSameLength);
|
||||||
|
}
|
||||||
let mut r: Vec<F> = vec![F::zero(); a.len()];
|
let mut r: Vec<F> = vec![F::zero(); a.len()];
|
||||||
for i in 0..a.len() {
|
for i in 0..a.len() {
|
||||||
r[i] = a[i] - b[i];
|
r[i] = a[i] - b[i];
|
||||||
}
|
}
|
||||||
r
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vec_scalar_mul<F: PrimeField>(vec: &[F], c: &F) -> Vec<F> {
|
pub fn vec_scalar_mul<F: PrimeField>(vec: &[F], c: &F) -> Vec<F> {
|
||||||
@@ -77,9 +83,13 @@ pub fn is_zero_vec<F: PrimeField>(vec: &[F]) -> bool {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mat_vec_mul<F: PrimeField>(M: &Vec<Vec<F>>, z: &[F]) -> Vec<F> {
|
pub fn mat_vec_mul<F: PrimeField>(M: &Vec<Vec<F>>, z: &[F]) -> Result<Vec<F>, Error> {
|
||||||
assert!(!M.is_empty());
|
if M.is_empty() {
|
||||||
assert_eq!(M[0].len(), z.len());
|
return Err(Error::Empty);
|
||||||
|
}
|
||||||
|
if M[0].len() != z.len() {
|
||||||
|
return Err(Error::NotSameLength);
|
||||||
|
}
|
||||||
|
|
||||||
let mut r: Vec<F> = vec![F::zero(); M.len()];
|
let mut r: Vec<F> = vec![F::zero(); M.len()];
|
||||||
for (i, M_i) in M.iter().enumerate() {
|
for (i, M_i) in M.iter().enumerate() {
|
||||||
@@ -87,7 +97,7 @@ pub fn mat_vec_mul<F: PrimeField>(M: &Vec<Vec<F>>, z: &[F]) -> Vec<F> {
|
|||||||
r[i] += *M_ij * z[j];
|
r[i] += *M_ij * z[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mat_vec_mul_sparse<F: PrimeField>(matrix: &SparseMatrix<F>, vector: &[F]) -> Vec<F> {
|
pub fn mat_vec_mul_sparse<F: PrimeField>(matrix: &SparseMatrix<F>, vector: &[F]) -> Vec<F> {
|
||||||
@@ -101,9 +111,11 @@ pub fn mat_vec_mul_sparse<F: PrimeField>(matrix: &SparseMatrix<F>, vector: &[F])
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hadamard<F: PrimeField>(a: &[F], b: &[F]) -> Vec<F> {
|
pub fn hadamard<F: PrimeField>(a: &[F], b: &[F]) -> Result<Vec<F>, Error> {
|
||||||
assert_eq!(a.len(), b.len());
|
if a.len() != b.len() {
|
||||||
cfg_iter!(a).zip(b).map(|(a, b)| *a * b).collect()
|
return Err(Error::NotSameLength);
|
||||||
|
}
|
||||||
|
Ok(cfg_iter!(a).zip(b).map(|(a, b)| *a * b).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -155,7 +167,7 @@ pub mod tests {
|
|||||||
])
|
])
|
||||||
.to_dense();
|
.to_dense();
|
||||||
let z = to_F_vec(vec![1, 3, 35, 9, 27, 30]);
|
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!(
|
assert_eq!(
|
||||||
mat_vec_mul_sparse(&dense_matrix_to_sparse(A), &z),
|
mat_vec_mul_sparse(&dense_matrix_to_sparse(A), &z),
|
||||||
to_F_vec(vec![3, 9, 30, 35])
|
to_F_vec(vec![3, 9, 30, 35])
|
||||||
@@ -165,7 +177,7 @@ pub mod tests {
|
|||||||
let v = to_F_vec(vec![19, 55, 50, 3]);
|
let v = to_F_vec(vec![19, 55, 50, 3]);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
mat_vec_mul(&A.to_dense(), &v),
|
mat_vec_mul(&A.to_dense(), &v).unwrap(),
|
||||||
to_F_vec(vec![418, 1158, 979])
|
to_F_vec(vec![418, 1158, 979])
|
||||||
);
|
);
|
||||||
assert_eq!(mat_vec_mul_sparse(&A, &v), 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 @@ pub mod tests {
|
|||||||
fn test_hadamard_product() {
|
fn test_hadamard_product() {
|
||||||
let a = to_F_vec::<Fr>(vec![1, 2, 3, 4, 5, 6]);
|
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]);
|
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]
|
#[test]
|
||||||
fn test_vec_add() {
|
fn test_vec_add() {
|
||||||
let a: Vec<Fr> = to_F_vec::<Fr>(vec![1, 2, 3, 4, 5, 6]);
|
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]);
|
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])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user