mirror of
https://github.com/arnaucube/sonobe.git
synced 2026-01-13 17:31:31 +01:00
Add CommitmentProver trait, and add KZG prover to it (#62)
* Add KZG commitment scheme adapted to vector commitment Add KZG commitment scheme adapted to vector commitment Also move the `src/pedersen.rs` into `src/commitment/pedersen.rs` where it will coexist with `kzg.rs` and the trait defined in `src/commitment/mod.rs`. * Adapt Pedersen into the new CommitmentProver trait * add CommitmentProver (Pedersen&KZG) homomorphic property test * polishing * Use divide_with_q_and_r, rename skip_first_zero_coeffs Co-authored-by: han0110 <tinghan0110@gmail.com> --------- Co-authored-by: han0110 <tinghan0110@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@ ark-ff = "^0.4.0"
|
|||||||
ark-poly = "^0.4.0"
|
ark-poly = "^0.4.0"
|
||||||
ark-std = "^0.4.0"
|
ark-std = "^0.4.0"
|
||||||
ark-crypto-primitives = { version = "^0.4.0", default-features = false, features = ["r1cs", "sponge", "crh"] }
|
ark-crypto-primitives = { version = "^0.4.0", default-features = false, features = ["r1cs", "sponge", "crh"] }
|
||||||
|
ark-poly-commit = "^0.4.0"
|
||||||
ark-relations = { version = "^0.4.0", default-features = false }
|
ark-relations = { version = "^0.4.0", default-features = false }
|
||||||
ark-r1cs-std = { default-features = false } # use latest version from the patch
|
ark-r1cs-std = { default-features = false } # use latest version from the patch
|
||||||
ark-serialize = "^0.4.0"
|
ark-serialize = "^0.4.0"
|
||||||
|
|||||||
234
src/commitment/kzg.rs
Normal file
234
src/commitment/kzg.rs
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
/// Adaptation of the prover methods and structs from arkworks/poly-commit's KZG10 implementation
|
||||||
|
/// into the CommitmentProver trait.
|
||||||
|
///
|
||||||
|
/// The motivation to do so, is that we want to be able to use KZG / Pedersen for committing to
|
||||||
|
/// vectors indistinctly, and the arkworks KZG10 implementation contains all the methods under the
|
||||||
|
/// same trait, which requires the Pairing trait, where the prover does not need access to the
|
||||||
|
/// Pairing but only to G1.
|
||||||
|
/// For our case, we want the folding schemes prover to be agnostic to pairings, since in the
|
||||||
|
/// non-ethereum cases we may use non-pairing-friendly curves with Pedersen commitments, so the
|
||||||
|
/// trait & types that we use should not depend on the Pairing type for the prover. Therefore, we
|
||||||
|
/// separate the CommitmentSchemeProver from the setup and verify phases, so the prover can be
|
||||||
|
/// defined without depending on pairings.
|
||||||
|
use ark_ec::{pairing::Pairing, CurveGroup, VariableBaseMSM};
|
||||||
|
use ark_ff::PrimeField;
|
||||||
|
use ark_poly::{
|
||||||
|
univariate::{DenseOrSparsePolynomial, DensePolynomial},
|
||||||
|
DenseUVPolynomial, EvaluationDomain, Evaluations, GeneralEvaluationDomain, Polynomial,
|
||||||
|
};
|
||||||
|
use ark_poly_commit::kzg10::{VerifierKey, KZG10};
|
||||||
|
use ark_std::rand::Rng;
|
||||||
|
use ark_std::{borrow::Cow, fmt::Debug};
|
||||||
|
use ark_std::{One, Zero};
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||||
|
|
||||||
|
use super::CommitmentProver;
|
||||||
|
use crate::transcript::Transcript;
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
|
/// ProverKey defines a similar struct as in ark_poly_commit::kzg10::Powers, but instead of
|
||||||
|
/// depending on the Pairing trait it depends on the CurveGroup trait.
|
||||||
|
#[derive(Debug, Clone, Default, Eq, PartialEq)]
|
||||||
|
pub struct ProverKey<'a, C: CurveGroup> {
|
||||||
|
/// Group elements of the form `β^i G`, for different values of `i`.
|
||||||
|
pub powers_of_g: Cow<'a, [C::Affine]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct KZGSetup<P: Pairing> {
|
||||||
|
_p: PhantomData<P>,
|
||||||
|
}
|
||||||
|
impl<'a, P> KZGSetup<P>
|
||||||
|
where
|
||||||
|
P: Pairing,
|
||||||
|
{
|
||||||
|
/// setup returns the tuple (ProverKey, VerifierKey). For real world deployments the setup must
|
||||||
|
/// be computed in the most trustless way possible, usually through a MPC ceremony.
|
||||||
|
pub fn setup<R: Rng>(rng: &mut R, len: usize) -> (ProverKey<'a, P::G1>, VerifierKey<P>) {
|
||||||
|
let len = len.next_power_of_two();
|
||||||
|
let universal_params = KZG10::<P, DensePolynomial<P::ScalarField>>::setup(len, false, rng)
|
||||||
|
.expect("Setup failed");
|
||||||
|
let powers_of_g = universal_params.powers_of_g[..=len].to_vec();
|
||||||
|
let powers = ProverKey::<P::G1> {
|
||||||
|
powers_of_g: ark_std::borrow::Cow::Owned(powers_of_g),
|
||||||
|
};
|
||||||
|
let vk = VerifierKey {
|
||||||
|
g: universal_params.powers_of_g[0],
|
||||||
|
gamma_g: universal_params.powers_of_gamma_g[&0],
|
||||||
|
h: universal_params.h,
|
||||||
|
beta_h: universal_params.beta_h,
|
||||||
|
prepared_h: universal_params.prepared_h.clone(),
|
||||||
|
prepared_beta_h: universal_params.prepared_beta_h.clone(),
|
||||||
|
};
|
||||||
|
(powers, vk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// KZGProver implements the CommitmentProver trait for the KZG commitment scheme.
|
||||||
|
pub struct KZGProver<'a, C: CurveGroup> {
|
||||||
|
_a: PhantomData<&'a ()>,
|
||||||
|
_c: PhantomData<C>,
|
||||||
|
}
|
||||||
|
impl<'a, C> CommitmentProver<C> for KZGProver<'a, C>
|
||||||
|
where
|
||||||
|
C: CurveGroup,
|
||||||
|
{
|
||||||
|
type Params = ProverKey<'a, C>;
|
||||||
|
/// Proof is a tuple containing (evaluation, proof)
|
||||||
|
type Proof = (C::ScalarField, C);
|
||||||
|
|
||||||
|
/// commit implements the CommitmentProver commit interface, adapting the implementation from
|
||||||
|
/// https://github.com/arkworks-rs/poly-commit/tree/c724fa666e935bbba8db5a1421603bab542e15ab/poly-commit/src/kzg10/mod.rs#L178
|
||||||
|
/// with the main difference being the removal of the blinding factors and the no-dependancy to
|
||||||
|
/// the Pairing trait.
|
||||||
|
fn commit(
|
||||||
|
params: &Self::Params,
|
||||||
|
v: &[C::ScalarField],
|
||||||
|
_blind: &C::ScalarField,
|
||||||
|
) -> Result<C, Error> {
|
||||||
|
if !_blind.is_zero() {
|
||||||
|
return Err(Error::NotSupportedYet("blinding factors".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let polynomial = poly_from_vec(v.to_vec())?;
|
||||||
|
check_degree_is_too_large(polynomial.degree(), params.powers_of_g.len())?;
|
||||||
|
|
||||||
|
let (num_leading_zeros, plain_coeffs) =
|
||||||
|
skip_first_zero_coeffs_and_convert_to_bigints(&polynomial);
|
||||||
|
let commitment = <C as VariableBaseMSM>::msm_bigint(
|
||||||
|
¶ms.powers_of_g[num_leading_zeros..],
|
||||||
|
&plain_coeffs,
|
||||||
|
);
|
||||||
|
Ok(commitment)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// prove implements the CommitmentProver prove interface, adapting the implementation from
|
||||||
|
/// https://github.com/arkworks-rs/poly-commit/tree/c724fa666e935bbba8db5a1421603bab542e15ab/poly-commit/src/kzg10/mod.rs#L307
|
||||||
|
/// with the main difference being the removal of the blinding factors and the no-dependancy to
|
||||||
|
/// the Pairing trait.
|
||||||
|
fn prove(
|
||||||
|
params: &Self::Params,
|
||||||
|
transcript: &mut impl Transcript<C>,
|
||||||
|
cm: &C,
|
||||||
|
v: &[C::ScalarField],
|
||||||
|
_blind: &C::ScalarField,
|
||||||
|
) -> Result<Self::Proof, Error> {
|
||||||
|
if !_blind.is_zero() {
|
||||||
|
return Err(Error::NotSupportedYet("blinding factors".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let polynomial = poly_from_vec(v.to_vec())?;
|
||||||
|
check_degree_is_too_large(polynomial.degree(), params.powers_of_g.len())?;
|
||||||
|
|
||||||
|
transcript.absorb_point(cm)?;
|
||||||
|
let challenge = transcript.get_challenge();
|
||||||
|
|
||||||
|
// Compute q(x) = (p(x) - p(z)) / (x-z). Observe that this quotient does not change with z
|
||||||
|
// because p(z) is the remainder term. We can therefore omit p(z) when computing the
|
||||||
|
// quotient.
|
||||||
|
let divisor = DensePolynomial::<C::ScalarField>::from_coefficients_vec(vec![
|
||||||
|
-challenge,
|
||||||
|
C::ScalarField::one(),
|
||||||
|
]);
|
||||||
|
let (witness_poly, remainder_poly) = DenseOrSparsePolynomial::from(&polynomial)
|
||||||
|
.divide_with_q_and_r(&DenseOrSparsePolynomial::from(&divisor))
|
||||||
|
// the panic inside `divide_with_q_and_r` should never be reached, since the divisor
|
||||||
|
// polynomial is constructed right before and is set to not be zero. And the `.unwrap`
|
||||||
|
// should not give an error.
|
||||||
|
.unwrap();
|
||||||
|
let evaluation = remainder_poly[0];
|
||||||
|
|
||||||
|
check_degree_is_too_large(witness_poly.degree(), params.powers_of_g.len())?;
|
||||||
|
let (num_leading_zeros, witness_coeffs) =
|
||||||
|
skip_first_zero_coeffs_and_convert_to_bigints(&witness_poly);
|
||||||
|
let proof = <C as VariableBaseMSM>::msm_bigint(
|
||||||
|
¶ms.powers_of_g[num_leading_zeros..],
|
||||||
|
&witness_coeffs,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok((evaluation, proof))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns the interpolated polynomial of degree=v.len().next_power_of_two(), which passes through all
|
||||||
|
/// the given elements of v.
|
||||||
|
fn poly_from_vec<F: PrimeField>(v: Vec<F>) -> Result<DensePolynomial<F>, Error> {
|
||||||
|
let D = GeneralEvaluationDomain::<F>::new(v.len()).ok_or(Error::NewDomainFail)?;
|
||||||
|
Ok(Evaluations::from_vec_and_domain(v, D).interpolate())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_degree_is_too_large(
|
||||||
|
degree: usize,
|
||||||
|
num_powers: usize,
|
||||||
|
) -> Result<(), ark_poly_commit::error::Error> {
|
||||||
|
let num_coefficients = degree + 1;
|
||||||
|
if num_coefficients > num_powers {
|
||||||
|
Err(ark_poly_commit::error::Error::TooManyCoefficients {
|
||||||
|
num_coefficients,
|
||||||
|
num_powers,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn skip_first_zero_coeffs_and_convert_to_bigints<F: PrimeField, P: DenseUVPolynomial<F>>(
|
||||||
|
p: &P,
|
||||||
|
) -> (usize, Vec<F::BigInt>) {
|
||||||
|
let mut num_leading_zeros = 0;
|
||||||
|
while num_leading_zeros < p.coeffs().len() && p.coeffs()[num_leading_zeros].is_zero() {
|
||||||
|
num_leading_zeros += 1;
|
||||||
|
}
|
||||||
|
let coeffs = convert_to_bigints(&p.coeffs()[num_leading_zeros..]);
|
||||||
|
(num_leading_zeros, coeffs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_to_bigints<F: PrimeField>(p: &[F]) -> Vec<F::BigInt> {
|
||||||
|
ark_std::cfg_iter!(p)
|
||||||
|
.map(|s| s.into_bigint())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use ark_bn254::{Bn254, Fr, G1Projective as G1};
|
||||||
|
use ark_poly_commit::kzg10::{Commitment as KZG10Commitment, Proof as KZG10Proof, KZG10};
|
||||||
|
use ark_std::{test_rng, UniformRand};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::transcript::poseidon::{tests::poseidon_test_config, PoseidonTranscript};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_kzg_commitment_scheme() {
|
||||||
|
let rng = &mut test_rng();
|
||||||
|
let poseidon_config = poseidon_test_config::<Fr>();
|
||||||
|
let transcript_p = &mut PoseidonTranscript::<G1>::new(&poseidon_config);
|
||||||
|
let transcript_v = &mut PoseidonTranscript::<G1>::new(&poseidon_config);
|
||||||
|
|
||||||
|
let n = 10;
|
||||||
|
let (pk, vk): (ProverKey<G1>, VerifierKey<Bn254>) = KZGSetup::<Bn254>::setup(rng, n);
|
||||||
|
|
||||||
|
let v: Vec<Fr> = std::iter::repeat_with(|| Fr::rand(rng)).take(n).collect();
|
||||||
|
let cm = KZGProver::<G1>::commit(&pk, &v, &Fr::zero()).unwrap();
|
||||||
|
|
||||||
|
let (eval, proof) =
|
||||||
|
KZGProver::<G1>::prove(&pk, transcript_p, &cm, &v, &Fr::zero()).unwrap();
|
||||||
|
|
||||||
|
// verify the proof:
|
||||||
|
// get evaluation challenge
|
||||||
|
transcript_v.absorb_point(&cm).unwrap();
|
||||||
|
let challenge = transcript_v.get_challenge();
|
||||||
|
// verify the KZG proof using arkworks method
|
||||||
|
assert!(KZG10::<Bn254, DensePolynomial<Fr>>::check(
|
||||||
|
&vk,
|
||||||
|
&KZG10Commitment(cm.into_affine()),
|
||||||
|
challenge,
|
||||||
|
eval,
|
||||||
|
&KZG10Proof::<Bn254> {
|
||||||
|
w: proof.into_affine(),
|
||||||
|
random_v: None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
127
src/commitment/mod.rs
Normal file
127
src/commitment/mod.rs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
use ark_ec::CurveGroup;
|
||||||
|
use ark_std::fmt::Debug;
|
||||||
|
|
||||||
|
use crate::transcript::Transcript;
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
|
pub mod kzg;
|
||||||
|
pub mod pedersen;
|
||||||
|
|
||||||
|
/// CommitmentProver defines the vector commitment scheme prover trait.
|
||||||
|
pub trait CommitmentProver<C: CurveGroup> {
|
||||||
|
type Params: Debug;
|
||||||
|
type Proof: Debug;
|
||||||
|
|
||||||
|
fn commit(
|
||||||
|
params: &Self::Params,
|
||||||
|
v: &[C::ScalarField],
|
||||||
|
blind: &C::ScalarField,
|
||||||
|
) -> Result<C, Error>;
|
||||||
|
fn prove(
|
||||||
|
params: &Self::Params,
|
||||||
|
transcript: &mut impl Transcript<C>,
|
||||||
|
cm: &C,
|
||||||
|
v: &[C::ScalarField],
|
||||||
|
blind: &C::ScalarField,
|
||||||
|
) -> Result<Self::Proof, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use ark_bn254::{Bn254, Fr, G1Projective as G1};
|
||||||
|
use ark_crypto_primitives::sponge::{poseidon::PoseidonConfig, Absorb};
|
||||||
|
use ark_poly::univariate::DensePolynomial;
|
||||||
|
use ark_poly_commit::kzg10::{
|
||||||
|
Commitment as KZG10Commitment, Proof as KZG10Proof, VerifierKey, KZG10,
|
||||||
|
};
|
||||||
|
use ark_std::Zero;
|
||||||
|
use ark_std::{test_rng, UniformRand};
|
||||||
|
|
||||||
|
use super::kzg::{KZGProver, KZGSetup, ProverKey};
|
||||||
|
use super::pedersen::Pedersen;
|
||||||
|
use crate::transcript::{
|
||||||
|
poseidon::{tests::poseidon_test_config, PoseidonTranscript},
|
||||||
|
Transcript,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Computes the commitment of the two vectors using the given CommitmentProver, then computes
|
||||||
|
// their random linear combination, and returns it together with the proof of it.
|
||||||
|
fn commit_rlc_and_prove<C: CurveGroup, CP: CommitmentProver<C>>(
|
||||||
|
poseidon_config: &PoseidonConfig<C::ScalarField>,
|
||||||
|
params: &CP::Params,
|
||||||
|
r: C::ScalarField,
|
||||||
|
v_1: &[C::ScalarField],
|
||||||
|
v_2: &[C::ScalarField],
|
||||||
|
) -> Result<(C, CP::Proof), Error>
|
||||||
|
where
|
||||||
|
<C as ark_ec::Group>::ScalarField: Absorb,
|
||||||
|
{
|
||||||
|
let cm_1 = CP::commit(params, v_1, &C::ScalarField::zero())?;
|
||||||
|
let cm_2 = CP::commit(params, v_2, &C::ScalarField::zero())?;
|
||||||
|
|
||||||
|
// random linear combination of the commitment and the witness (vector v)
|
||||||
|
let cm_3 = cm_1 + cm_2.mul(r);
|
||||||
|
let v_3: Vec<C::ScalarField> = v_1.iter().zip(v_2).map(|(a, b)| *a + (r * b)).collect();
|
||||||
|
|
||||||
|
let transcript = &mut PoseidonTranscript::<C>::new(poseidon_config);
|
||||||
|
let proof = CP::prove(params, transcript, &cm_3, &v_3, &C::ScalarField::zero()).unwrap();
|
||||||
|
|
||||||
|
Ok((cm_3, proof))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_homomorphic_property_using_CommitmentProver_trait() {
|
||||||
|
let rng = &mut test_rng();
|
||||||
|
let poseidon_config = poseidon_test_config::<Fr>();
|
||||||
|
let n: usize = 100;
|
||||||
|
|
||||||
|
// set random vector for the test
|
||||||
|
let v_1: Vec<Fr> = std::iter::repeat_with(|| Fr::rand(rng)).take(n).collect();
|
||||||
|
let v_2: Vec<Fr> = std::iter::repeat_with(|| Fr::rand(rng)).take(n).collect();
|
||||||
|
// set a random challenge for the random linear combination
|
||||||
|
let r = Fr::rand(rng);
|
||||||
|
|
||||||
|
// setup params for Pedersen & KZG
|
||||||
|
let pedersen_params = Pedersen::<G1>::new_params(rng, n);
|
||||||
|
let (kzg_pk, kzg_vk): (ProverKey<G1>, VerifierKey<Bn254>) =
|
||||||
|
KZGSetup::<Bn254>::setup(rng, n);
|
||||||
|
|
||||||
|
// Pedersen commit the two vectors and return their random linear combination and proof
|
||||||
|
let (pedersen_cm, pedersen_proof) = commit_rlc_and_prove::<G1, Pedersen<G1>>(
|
||||||
|
&poseidon_config,
|
||||||
|
&pedersen_params,
|
||||||
|
r,
|
||||||
|
&v_1,
|
||||||
|
&v_2,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// KZG commit the two vectors and return their random linear combination and proof
|
||||||
|
let (kzg_cm, kzg_proof) =
|
||||||
|
commit_rlc_and_prove::<G1, KZGProver<G1>>(&poseidon_config, &kzg_pk, r, &v_1, &v_2)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// verify Pedersen
|
||||||
|
let transcript_v = &mut PoseidonTranscript::<G1>::new(&poseidon_config);
|
||||||
|
Pedersen::<G1>::verify(&pedersen_params, transcript_v, pedersen_cm, pedersen_proof)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// verify KZG
|
||||||
|
let transcript_v = &mut PoseidonTranscript::<G1>::new(&poseidon_config);
|
||||||
|
transcript_v.absorb_point(&kzg_cm).unwrap();
|
||||||
|
let challenge = transcript_v.get_challenge();
|
||||||
|
// verify the KZG proof using arkworks method
|
||||||
|
assert!(KZG10::<Bn254, DensePolynomial<Fr>>::check(
|
||||||
|
&kzg_vk,
|
||||||
|
&KZG10Commitment(kzg_cm.into_affine()),
|
||||||
|
challenge,
|
||||||
|
kzg_proof.0, // eval
|
||||||
|
&KZG10Proof::<Bn254> {
|
||||||
|
w: kzg_proof.1.into_affine(), // proof
|
||||||
|
random_v: None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,9 +5,9 @@ use ark_relations::r1cs::SynthesisError;
|
|||||||
use ark_std::{rand::Rng, UniformRand};
|
use ark_std::{rand::Rng, UniformRand};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::utils::vec::{vec_add, vec_scalar_mul};
|
use super::CommitmentProver;
|
||||||
|
|
||||||
use crate::transcript::Transcript;
|
use crate::transcript::Transcript;
|
||||||
|
use crate::utils::vec::{vec_add, vec_scalar_mul};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
@@ -39,11 +39,16 @@ impl<C: CurveGroup> Pedersen<C> {
|
|||||||
};
|
};
|
||||||
params
|
params
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn commit(
|
// implement the CommitmentProver trait for Pedersen
|
||||||
params: &Params<C>,
|
impl<C: CurveGroup> CommitmentProver<C> for Pedersen<C> {
|
||||||
v: &Vec<C::ScalarField>,
|
type Params = Params<C>;
|
||||||
r: &C::ScalarField,
|
type Proof = Proof<C>;
|
||||||
|
fn commit(
|
||||||
|
params: &Self::Params,
|
||||||
|
v: &[C::ScalarField],
|
||||||
|
r: &C::ScalarField, // blinding factor
|
||||||
) -> Result<C, Error> {
|
) -> Result<C, Error> {
|
||||||
if params.generators.len() < v.len() {
|
if params.generators.len() < v.len() {
|
||||||
return Err(Error::PedersenParamsLen(params.generators.len(), v.len()));
|
return Err(Error::PedersenParamsLen(params.generators.len(), v.len()));
|
||||||
@@ -53,13 +58,13 @@ impl<C: CurveGroup> Pedersen<C> {
|
|||||||
Ok(params.h.mul(r) + C::msm_unchecked(¶ms.generators[..v.len()], v))
|
Ok(params.h.mul(r) + C::msm_unchecked(¶ms.generators[..v.len()], v))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prove(
|
fn prove(
|
||||||
params: &Params<C>,
|
params: &Params<C>,
|
||||||
transcript: &mut impl Transcript<C>,
|
transcript: &mut impl Transcript<C>,
|
||||||
cm: &C,
|
cm: &C,
|
||||||
v: &Vec<C::ScalarField>,
|
v: &[C::ScalarField],
|
||||||
r: &C::ScalarField,
|
r: &C::ScalarField, // blinding factor
|
||||||
) -> Result<Proof<C>, Error> {
|
) -> Result<Self::Proof, Error> {
|
||||||
if params.generators.len() < v.len() {
|
if params.generators.len() < v.len() {
|
||||||
return Err(Error::PedersenParamsLen(params.generators.len(), v.len()));
|
return Err(Error::PedersenParamsLen(params.generators.len(), v.len()));
|
||||||
}
|
}
|
||||||
@@ -80,9 +85,11 @@ impl<C: CurveGroup> Pedersen<C> {
|
|||||||
// r_u = e⋅r + r_1
|
// r_u = e⋅r + r_1
|
||||||
let r_u = e * r + r1;
|
let r_u = e * r + r1;
|
||||||
|
|
||||||
Ok(Proof::<C> { R, u, r_u })
|
Ok(Self::Proof { R, u, r_u })
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C: CurveGroup> Pedersen<C> {
|
||||||
pub fn verify(
|
pub fn verify(
|
||||||
params: &Params<C>,
|
params: &Params<C>,
|
||||||
transcript: &mut impl Transcript<C>,
|
transcript: &mut impl Transcript<C>,
|
||||||
@@ -102,13 +109,13 @@ impl<C: CurveGroup> Pedersen<C> {
|
|||||||
transcript.absorb_point(&proof.R)?;
|
transcript.absorb_point(&proof.R)?;
|
||||||
let e = transcript.get_challenge();
|
let e = transcript.get_challenge();
|
||||||
|
|
||||||
// check that: R + cm == h⋅r_u + <g, u>
|
// check that: R + cm⋅e == h⋅r_u + <g, u>
|
||||||
let lhs = proof.R + cm.mul(e);
|
let lhs = proof.R + cm.mul(e);
|
||||||
// use msm_unchecked because we already ensured at the if that lengths match
|
// use msm_unchecked because we already ensured at the if that lengths match
|
||||||
let rhs = params.h.mul(proof.r_u)
|
let rhs = params.h.mul(proof.r_u)
|
||||||
+ C::msm_unchecked(¶ms.generators[..proof.u.len()], &proof.u);
|
+ C::msm_unchecked(¶ms.generators[..proof.u.len()], &proof.u);
|
||||||
if lhs != rhs {
|
if lhs != rhs {
|
||||||
return Err(Error::PedersenVerificationFail);
|
return Err(Error::CommitmentVerificationFail);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -164,7 +171,7 @@ mod tests {
|
|||||||
fn test_pedersen_vector() {
|
fn test_pedersen_vector() {
|
||||||
let mut rng = ark_std::test_rng();
|
let mut rng = ark_std::test_rng();
|
||||||
|
|
||||||
const n: usize = 10;
|
let n: usize = 10;
|
||||||
// setup params
|
// setup params
|
||||||
let params = Pedersen::<Projective>::new_params(&mut rng, n);
|
let params = Pedersen::<Projective>::new_params(&mut rng, n);
|
||||||
let poseidon_config = poseidon_test_config::<Fr>();
|
let poseidon_config = poseidon_test_config::<Fr>();
|
||||||
@@ -187,7 +194,7 @@ mod tests {
|
|||||||
fn test_pedersen_circuit() {
|
fn test_pedersen_circuit() {
|
||||||
let mut rng = ark_std::test_rng();
|
let mut rng = ark_std::test_rng();
|
||||||
|
|
||||||
const n: usize = 10;
|
let n: usize = 10;
|
||||||
// setup params
|
// setup params
|
||||||
let params = Pedersen::<Projective>::new_params(&mut rng, n);
|
let params = Pedersen::<Projective>::new_params(&mut rng, n);
|
||||||
|
|
||||||
@@ -9,7 +9,10 @@ use ark_std::{rand::Rng, UniformRand};
|
|||||||
|
|
||||||
use super::utils::compute_sum_Mz;
|
use super::utils::compute_sum_Mz;
|
||||||
use crate::ccs::CCS;
|
use crate::ccs::CCS;
|
||||||
use crate::pedersen::{Params as PedersenParams, Pedersen};
|
use crate::commitment::{
|
||||||
|
pedersen::{Params as PedersenParams, Pedersen},
|
||||||
|
CommitmentProver,
|
||||||
|
};
|
||||||
use crate::utils::hypercube::BooleanHypercube;
|
use crate::utils::hypercube::BooleanHypercube;
|
||||||
use crate::utils::mle::matrix_to_mle;
|
use crate::utils::mle::matrix_to_mle;
|
||||||
use crate::utils::mle::vec_to_mle;
|
use crate::utils::mle::vec_to_mle;
|
||||||
|
|||||||
@@ -157,11 +157,11 @@ mod tests {
|
|||||||
tests::{get_test_ccs, get_test_z},
|
tests::{get_test_ccs, get_test_z},
|
||||||
CCS,
|
CCS,
|
||||||
},
|
},
|
||||||
|
commitment::pedersen::Pedersen,
|
||||||
folding::hypernova::utils::{
|
folding::hypernova::utils::{
|
||||||
compute_c_from_sigmas_and_thetas, compute_sigmas_and_thetas, sum_ci_mul_prod_thetaj,
|
compute_c_from_sigmas_and_thetas, compute_sigmas_and_thetas, sum_ci_mul_prod_thetaj,
|
||||||
sum_muls_gamma_pows_eq_sigma,
|
sum_muls_gamma_pows_eq_sigma,
|
||||||
},
|
},
|
||||||
pedersen::Pedersen,
|
|
||||||
utils::virtual_polynomial::eq_eval,
|
utils::virtual_polynomial::eq_eval,
|
||||||
};
|
};
|
||||||
use ark_pallas::{Fr, Projective};
|
use ark_pallas::{Fr, Projective};
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ use ark_std::{rand::Rng, UniformRand};
|
|||||||
use super::cccs::Witness;
|
use super::cccs::Witness;
|
||||||
use super::utils::{compute_all_sum_Mz_evals, compute_sum_Mz};
|
use super::utils::{compute_all_sum_Mz_evals, compute_sum_Mz};
|
||||||
use crate::ccs::CCS;
|
use crate::ccs::CCS;
|
||||||
use crate::pedersen::{Params as PedersenParams, Pedersen};
|
use crate::commitment::{
|
||||||
|
pedersen::{Params as PedersenParams, Pedersen},
|
||||||
|
CommitmentProver,
|
||||||
|
};
|
||||||
use crate::utils::mle::{matrix_to_mle, vec_to_mle};
|
use crate::utils::mle::{matrix_to_mle, vec_to_mle};
|
||||||
use crate::utils::virtual_polynomial::VirtualPolynomial;
|
use crate::utils::virtual_polynomial::VirtualPolynomial;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ where
|
|||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
let mut g_over_bhc = C::ScalarField::zero();
|
let mut g_over_bhc = C::ScalarField::zero();
|
||||||
for x in BooleanHypercube::new(ccs.s) {
|
for x in BooleanHypercube::new(ccs.s) {
|
||||||
g_over_bhc += g.evaluate(&x).unwrap();
|
g_over_bhc += g.evaluate(&x)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@@ -378,7 +378,7 @@ pub mod tests {
|
|||||||
use ark_std::test_rng;
|
use ark_std::test_rng;
|
||||||
use ark_std::UniformRand;
|
use ark_std::UniformRand;
|
||||||
|
|
||||||
use crate::pedersen::Pedersen;
|
use crate::commitment::pedersen::Pedersen;
|
||||||
use ark_pallas::{Fr, Projective};
|
use ark_pallas::{Fr, Projective};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ pub mod tests {
|
|||||||
use ark_std::Zero;
|
use ark_std::Zero;
|
||||||
|
|
||||||
use crate::ccs::tests::{get_test_ccs, get_test_z};
|
use crate::ccs::tests::{get_test_ccs, get_test_z};
|
||||||
use crate::pedersen::Pedersen;
|
use crate::commitment::pedersen::Pedersen;
|
||||||
use crate::utils::multilinear_polynomial::tests::fix_last_variables;
|
use crate::utils::multilinear_polynomial::tests::fix_last_variables;
|
||||||
use crate::utils::virtual_polynomial::eq_eval;
|
use crate::utils::virtual_polynomial::eq_eval;
|
||||||
|
|
||||||
|
|||||||
@@ -470,12 +470,12 @@ pub mod tests {
|
|||||||
use tracing_subscriber::layer::SubscriberExt;
|
use tracing_subscriber::layer::SubscriberExt;
|
||||||
|
|
||||||
use crate::ccs::r1cs::{extract_r1cs, extract_w_x};
|
use crate::ccs::r1cs::{extract_r1cs, extract_w_x};
|
||||||
|
use crate::commitment::pedersen::Pedersen;
|
||||||
use crate::folding::nova::nifs::tests::prepare_simple_fold_inputs;
|
use crate::folding::nova::nifs::tests::prepare_simple_fold_inputs;
|
||||||
use crate::folding::nova::{
|
use crate::folding::nova::{
|
||||||
ivc::get_committed_instance_coordinates, nifs::NIFS, traits::NovaR1CS, Witness,
|
ivc::get_committed_instance_coordinates, nifs::NIFS, traits::NovaR1CS, Witness,
|
||||||
};
|
};
|
||||||
use crate::frontend::tests::CubicFCircuit;
|
use crate::frontend::tests::CubicFCircuit;
|
||||||
use crate::pedersen::Pedersen;
|
|
||||||
use crate::transcript::poseidon::tests::poseidon_test_config;
|
use crate::transcript::poseidon::tests::poseidon_test_config;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ use ark_std::{One, Zero};
|
|||||||
use core::{borrow::Borrow, marker::PhantomData};
|
use core::{borrow::Borrow, marker::PhantomData};
|
||||||
|
|
||||||
use crate::ccs::r1cs::R1CS;
|
use crate::ccs::r1cs::R1CS;
|
||||||
|
use crate::commitment::pedersen::Params as PedersenParams;
|
||||||
use crate::folding::nova::{
|
use crate::folding::nova::{
|
||||||
circuits::{CommittedInstanceVar, CF1, CF2},
|
circuits::{CommittedInstanceVar, CF1, CF2},
|
||||||
ivc::IVC,
|
ivc::IVC,
|
||||||
CommittedInstance, Witness,
|
CommittedInstance, Witness,
|
||||||
};
|
};
|
||||||
use crate::frontend::FCircuit;
|
use crate::frontend::FCircuit;
|
||||||
use crate::pedersen::Params as PedersenParams;
|
|
||||||
use crate::utils::gadgets::{
|
use crate::utils::gadgets::{
|
||||||
hadamard, mat_vec_mul_sparse, vec_add, vec_scalar_mul, SparseMatrixVar,
|
hadamard, mat_vec_mul_sparse, vec_add, vec_scalar_mul, SparseMatrixVar,
|
||||||
};
|
};
|
||||||
@@ -355,8 +355,8 @@ where
|
|||||||
{
|
{
|
||||||
// imports here instead of at the top of the file, so we avoid having multiple
|
// imports here instead of at the top of the file, so we avoid having multiple
|
||||||
// `#[cfg(not(test))]
|
// `#[cfg(not(test))]
|
||||||
|
use crate::commitment::pedersen::PedersenGadget;
|
||||||
use crate::folding::nova::cyclefold::{CycleFoldCommittedInstanceVar, CF_IO_LEN};
|
use crate::folding::nova::cyclefold::{CycleFoldCommittedInstanceVar, CF_IO_LEN};
|
||||||
use crate::pedersen::PedersenGadget;
|
|
||||||
use ark_r1cs_std::ToBitsGadget;
|
use ark_r1cs_std::ToBitsGadget;
|
||||||
|
|
||||||
let cf_r1cs = R1CSVar::<
|
let cf_r1cs = R1CSVar::<
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ use super::{
|
|||||||
use super::{nifs::NIFS, traits::NovaR1CS, CommittedInstance, Witness};
|
use super::{nifs::NIFS, traits::NovaR1CS, CommittedInstance, Witness};
|
||||||
use crate::ccs::r1cs::R1CS;
|
use crate::ccs::r1cs::R1CS;
|
||||||
use crate::ccs::r1cs::{extract_r1cs, extract_w_x};
|
use crate::ccs::r1cs::{extract_r1cs, extract_w_x};
|
||||||
|
use crate::commitment::pedersen::{Params as PedersenParams, Pedersen};
|
||||||
use crate::frontend::FCircuit;
|
use crate::frontend::FCircuit;
|
||||||
use crate::pedersen::{Params as PedersenParams, Pedersen};
|
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -7,8 +7,11 @@ use ark_ec::{CurveGroup, Group};
|
|||||||
use ark_std::fmt::Debug;
|
use ark_std::fmt::Debug;
|
||||||
use ark_std::{One, Zero};
|
use ark_std::{One, Zero};
|
||||||
|
|
||||||
|
use crate::commitment::{
|
||||||
|
pedersen::{Params as PedersenParams, Pedersen},
|
||||||
|
CommitmentProver,
|
||||||
|
};
|
||||||
use crate::folding::circuits::nonnative::point_to_nonnative_limbs;
|
use crate::folding::circuits::nonnative::point_to_nonnative_limbs;
|
||||||
use crate::pedersen::{Params as PedersenParams, Pedersen};
|
|
||||||
use crate::utils::vec::is_zero_vec;
|
use crate::utils::vec::is_zero_vec;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
@@ -89,11 +92,13 @@ where
|
|||||||
<C as Group>::ScalarField: Absorb,
|
<C as Group>::ScalarField: Absorb,
|
||||||
{
|
{
|
||||||
pub fn new(w: Vec<C::ScalarField>, e_len: usize) -> Self {
|
pub fn new(w: Vec<C::ScalarField>, e_len: usize) -> Self {
|
||||||
|
// note: at the current version, we don't use the blinding factors and we set them to 0
|
||||||
|
// always.
|
||||||
Self {
|
Self {
|
||||||
E: vec![C::ScalarField::zero(); e_len],
|
E: vec![C::ScalarField::zero(); e_len],
|
||||||
rE: C::ScalarField::zero(), // because we use C::zero() as cmE
|
rE: C::ScalarField::zero(),
|
||||||
W: w,
|
W: w,
|
||||||
rW: C::ScalarField::one(),
|
rW: C::ScalarField::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn commit(
|
pub fn commit(
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ use std::marker::PhantomData;
|
|||||||
|
|
||||||
use super::{CommittedInstance, Witness};
|
use super::{CommittedInstance, Witness};
|
||||||
use crate::ccs::r1cs::R1CS;
|
use crate::ccs::r1cs::R1CS;
|
||||||
use crate::pedersen::{Params as PedersenParams, Pedersen, Proof as PedersenProof};
|
use crate::commitment::{
|
||||||
|
pedersen::{Params as PedersenParams, Pedersen, Proof as PedersenProof},
|
||||||
|
CommitmentProver,
|
||||||
|
};
|
||||||
use crate::transcript::Transcript;
|
use crate::transcript::Transcript;
|
||||||
use crate::utils::vec::*;
|
use crate::utils::vec::*;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ mod tests {
|
|||||||
use ark_std::UniformRand;
|
use ark_std::UniformRand;
|
||||||
|
|
||||||
use crate::ccs::r1cs::tests::{get_test_r1cs, get_test_z};
|
use crate::ccs::r1cs::tests::{get_test_r1cs, get_test_z};
|
||||||
use crate::pedersen::Pedersen;
|
use crate::commitment::{pedersen::Pedersen, CommitmentProver};
|
||||||
use crate::transcript::poseidon::{tests::poseidon_test_config, PoseidonTranscript};
|
use crate::transcript::poseidon::{tests::poseidon_test_config, PoseidonTranscript};
|
||||||
|
|
||||||
pub(crate) fn check_instance<C: CurveGroup>(
|
pub(crate) fn check_instance<C: CurveGroup>(
|
||||||
|
|||||||
12
src/lib.rs
12
src/lib.rs
@@ -9,10 +9,10 @@ use thiserror::Error;
|
|||||||
pub mod transcript;
|
pub mod transcript;
|
||||||
use transcript::Transcript;
|
use transcript::Transcript;
|
||||||
pub mod ccs;
|
pub mod ccs;
|
||||||
|
pub mod commitment;
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
pub mod folding;
|
pub mod folding;
|
||||||
pub mod frontend;
|
pub mod frontend;
|
||||||
pub mod pedersen;
|
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
@@ -21,6 +21,10 @@ pub enum Error {
|
|||||||
SynthesisError(#[from] ark_relations::r1cs::SynthesisError),
|
SynthesisError(#[from] ark_relations::r1cs::SynthesisError),
|
||||||
#[error("ark_serialize::SerializationError")]
|
#[error("ark_serialize::SerializationError")]
|
||||||
SerializationError(#[from] ark_serialize::SerializationError),
|
SerializationError(#[from] ark_serialize::SerializationError),
|
||||||
|
#[error("ark_poly_commit::Error")]
|
||||||
|
PolyCommitError(#[from] ark_poly_commit::Error),
|
||||||
|
#[error("crate::utils::espresso::virtual_polynomial::ArithErrors")]
|
||||||
|
ArithError(#[from] utils::espresso::virtual_polynomial::ArithErrors),
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Other(String),
|
Other(String),
|
||||||
|
|
||||||
@@ -36,8 +40,8 @@ pub enum Error {
|
|||||||
Empty,
|
Empty,
|
||||||
#[error("Pedersen parameters length is not suficient (generators.len={0} < vector.len={1} unsatisfied)")]
|
#[error("Pedersen parameters length is not suficient (generators.len={0} < vector.len={1} unsatisfied)")]
|
||||||
PedersenParamsLen(usize, usize),
|
PedersenParamsLen(usize, usize),
|
||||||
#[error("Pedersen verification failed")]
|
#[error("Commitment verification failed")]
|
||||||
PedersenVerificationFail,
|
CommitmentVerificationFail,
|
||||||
#[error("IVC verification failed")]
|
#[error("IVC verification failed")]
|
||||||
IVCVerificationFail,
|
IVCVerificationFail,
|
||||||
#[error("R1CS instance is expected to not be relaxed")]
|
#[error("R1CS instance is expected to not be relaxed")]
|
||||||
@@ -52,6 +56,8 @@ pub enum Error {
|
|||||||
OutOfBounds,
|
OutOfBounds,
|
||||||
#[error("Could not construct the Evaluation Domain")]
|
#[error("Could not construct the Evaluation Domain")]
|
||||||
NewDomainFail,
|
NewDomainFail,
|
||||||
|
#[error("Feature '{0}' not supported yet")]
|
||||||
|
NotSupportedYet(String),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
ProtoGalaxy(folding::protogalaxy::ProtoGalaxyError),
|
ProtoGalaxy(folding::protogalaxy::ProtoGalaxyError),
|
||||||
|
|||||||
Reference in New Issue
Block a user