Browse Source

rm unused pedersen.rs methods, some more polishing

main
arnaucube 9 months ago
parent
commit
c6d42a8356
6 changed files with 59 additions and 161 deletions
  1. +0
    -1
      Cargo.toml
  2. +6
    -4
      README.md
  3. +0
    -2
      src/lib.rs
  4. +1
    -105
      src/pedersen.rs
  5. +40
    -41
      src/protogalaxy.rs
  6. +12
    -8
      src/utils.rs

+ 0
- 1
Cargo.toml

@ -12,7 +12,6 @@ ark-ec = { version = "0.4.0", default-features = false }
ark-poly = "0.4.0"
ark-serialize = { version = "0.4.0", default-features = false, features = [ "derive" ] }
rand = { version = "0.8", features = [ "std", "std_rng" ] }
merlin = { version = "3.0.0" }
ark-crypto-primitives = { version = "^0.4.0", default-features = false, features = [ "r1cs", "snark", "sponge", "crh" ] }
[dev-dependencies]

+ 6
- 4
README.md

@ -2,7 +2,7 @@
Proof of concept implementation of ProtoGalaxy (https://eprint.iacr.org/2023/1106.pdf) using [arkworks](https://github.com/arkworks-rs).
> Do not use in production.
> Experimental code, do not use in production.
Thanks to [Liam Eagen](https://twitter.com/LiamEagen) and [Ariel Gabizon](https://twitter.com/rel_zeta_tech) for their kind explanations.
@ -56,8 +56,10 @@ let betas = powers_of_beta(beta, t);
let (F_coeffs, K_coeffs, folded_instance, folded_witness) = Folding::<G1Projective>::prover(
&mut transcript_p,
&r1cs,
// running instance
instance.clone(),
witness,
// incomming instances
instances.clone(),
witnesses,
);
@ -66,8 +68,8 @@ let (F_coeffs, K_coeffs, folded_instance, folded_witness) = Folding::
let folded_instance_v = Folding::<G1Projective>::verifier(
&mut transcript_v,
&r1cs,
instance,
instances,
instance, // running instance
instances, // incomming instances
F_coeffs,
K_coeffs,
);
@ -75,6 +77,6 @@ let folded_instance_v = Folding::::verifier(
// check that the folded instance satisfies the relation
assert!(check_instance(&r2cs, folded_instance, folded_witness));
// now, the folded instance & witness can be folded again with n other instances.
// now, the folded instance & witness can be folded again with k other instances.
```
(see the actual code for more details)

+ 0
- 2
src/lib.rs

@ -1,7 +1,5 @@
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
// #![allow(unused)] // TMP
// #![allow(dead_code)] // TMP
pub mod pedersen;
pub mod protogalaxy;

+ 1
- 105
src/pedersen.rs

@ -1,9 +1,6 @@
/// pedersen.rs file adapted from https://github.com/arnaucube/nova-study
use ark_ec::{CurveGroup, Group};
use ark_std::{
rand::{Rng, RngCore},
UniformRand,
};
use ark_std::{rand::Rng, UniformRand};
use std::marker::PhantomData;
use crate::utils::{vec_add, vec_scalar_mul};
@ -11,11 +8,6 @@ use crate::utils::{vec_add, vec_scalar_mul};
use crate::transcript::Transcript;
use ark_crypto_primitives::sponge::Absorb;
pub struct ProofElem<C: CurveGroup> {
R: C,
t1: C::ScalarField,
t2: C::ScalarField,
}
pub struct Proof<C: CurveGroup> {
R: C,
u_: Vec<C::ScalarField>,
@ -23,7 +15,6 @@ pub struct Proof {
}
pub struct Params<C: CurveGroup> {
g: C,
h: C,
pub generators: Vec<C::Affine>,
}
@ -46,22 +37,12 @@ where
let g: C = C::generator();
let generators: Vec<C::Affine> = vec![C::Affine::rand(rng); max];
let params: Params<C> = Params::<C> {
g,
h: g.mul(h_scalar),
generators,
};
params
}
pub fn commit_elem<R: RngCore>(
rng: &mut R,
params: &Params<C>,
v: &C::ScalarField,
) -> CommitmentElem<C> {
let r = C::ScalarField::rand(rng);
let cm: C = params.g.mul(v) + params.h.mul(r);
CommitmentElem::<C> { cm, r }
}
pub fn commit(
params: &Params<C>,
v: &Vec<C::ScalarField>,
@ -71,27 +52,6 @@ where
Commitment::<C>(cm)
}
pub fn prove_elem(
params: &Params<C>,
transcript: &mut Transcript<C::ScalarField, C>,
cm: C,
v: C::ScalarField,
r: C::ScalarField,
) -> ProofElem<C> {
let r1 = transcript.get_challenge();
let r2 = transcript.get_challenge();
let R: C = params.g.mul(r1) + params.h.mul(r2);
transcript.add_point(&cm);
transcript.add_point(&R);
let e = transcript.get_challenge();
let t1 = r1 + v * e;
let t2 = r2 + r * e;
ProofElem::<C> { R, t1, t2 }
}
pub fn prove(
params: &Params<C>,
transcript: &mut Transcript<C::ScalarField, C>,
@ -133,81 +93,17 @@ where
}
true
}
pub fn verify_elem(
params: &Params<C>,
transcript: &mut Transcript<C::ScalarField, C>,
cm: C,
proof: ProofElem<C>,
) -> bool {
// s1, s2 just to match Prover's transcript
transcript.get_challenge(); // r_1
transcript.get_challenge(); // r_2
transcript.add_point(&cm);
transcript.add_point(&proof.R);
let e = transcript.get_challenge();
let lhs = proof.R + cm.mul(e);
let rhs = params.g.mul(proof.t1) + params.h.mul(proof.t2);
if lhs != rhs {
return false;
}
true
}
}
#[derive(Clone, Debug)]
pub struct Commitment<C: CurveGroup>(pub C);
pub struct CommitmentElem<C: CurveGroup> {
pub cm: C,
pub r: C::ScalarField,
}
impl<C: CurveGroup> CommitmentElem<C>
where
<C as Group>::ScalarField: Absorb,
<C as CurveGroup>::BaseField: Absorb,
{
pub fn prove(
&self,
params: &Params<C>,
transcript: &mut Transcript<C::ScalarField, C>,
v: C::ScalarField,
) -> ProofElem<C> {
Pedersen::<C>::prove_elem(params, transcript, self.cm, v, self.r)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::transcript::poseidon_test_config;
use ark_bls12_381::{Fr, G1Projective};
#[test]
fn test_pedersen_single_element() {
let mut rng = ark_std::test_rng();
// setup params
let params = Pedersen::<G1Projective>::new_params(
&mut rng, 0, /* 0, as here we don't use commit_vec */
);
let poseidon_config = poseidon_test_config::<Fr>();
// init Prover's transcript
let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
// init Verifier's transcript
let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
let v = Fr::rand(&mut rng);
let cm = Pedersen::commit_elem(&mut rng, &params, &v);
let proof = cm.prove(&params, &mut transcript_p, v);
// also can use:
// let proof = Pedersen::prove_elem(&params, &mut transcript_p, cm.cm, v, cm.r);
let v = Pedersen::verify_elem(&params, &mut transcript_v, cm.cm, proof);
assert!(v);
}
#[test]
fn test_pedersen_vector() {
let mut rng = ark_std::test_rng();

+ 40
- 41
src/protogalaxy.rs

@ -37,21 +37,21 @@ where
<C as Group>::ScalarField: Absorb,
<C as CurveGroup>::BaseField: Absorb,
{
// WIP naming of functions
pub fn prover(
#![allow(clippy::type_complexity)]
pub fn prove(
transcript: &mut Transcript<C::ScalarField, C>,
r1cs: &R1CS<C::ScalarField>,
// running instance
instance: CommittedInstance<C>,
w: Witness<C>,
instance: &CommittedInstance<C>,
w: &Witness<C>,
// incomming instances
vec_instances: Vec<CommittedInstance<C>>,
vec_w: Vec<Witness<C>>,
vec_instances: &[CommittedInstance<C>],
vec_w: &[Witness<C>],
) -> (
Vec<C::ScalarField>,
Vec<C::ScalarField>,
CommittedInstance<C>,
Witness<C>,
Vec<C::ScalarField>,
Vec<C::ScalarField>,
) {
let t = instance.betas.len();
let n = r1cs.A[0].len();
@ -66,9 +66,9 @@ where
// F(X)
let mut F_X: SparsePolynomial<C::ScalarField> = SparsePolynomial::zero();
for i in 0..n {
for (i, f_w_i) in f_w.iter().enumerate() {
let lhs = pow_i_over_x::<C::ScalarField>(i, &instance.betas, &deltas);
let curr = &lhs * f_w[i];
let curr = &lhs * *f_w_i;
F_X = F_X.add(curr);
}
@ -102,7 +102,7 @@ where
betas: betas_star.clone(),
e: F_alpha,
},
&w,
w,
));
let mut ws: Vec<Vec<C::ScalarField>> = Vec::new();
@ -146,12 +146,11 @@ where
let f_ev = eval_f(r1cs, &inner);
let mut Gsum = C::ScalarField::zero();
for i in 0..n {
for (i, f_ev_i) in f_ev.iter().enumerate() {
let pow_i_betas = pow_i(i, &betas_star);
let curr = pow_i_betas * f_ev[i];
let curr = pow_i_betas * f_ev_i;
Gsum += curr;
}
// G_evals[hi] = Gsum / Z_X.evaluate(&h); // WIP
G_evals[hi] = Gsum;
}
let G_X: DensePolynomial<C::ScalarField> =
@ -162,7 +161,7 @@ where
let G_L0e = &G_X - &L0_e;
// TODO move division by Z_X to the prev loop
let (K_X, remainder) = G_L0e.divide_by_vanishing_poly(H).unwrap();
assert!(remainder.is_zero());
assert!(remainder.is_zero()); // sanity check
transcript.add_vec(&K_X.coeffs);
@ -188,8 +187,6 @@ where
}
(
F_X_dense.coeffs,
K_X.coeffs,
CommittedInstance {
betas: betas_star,
phi: Commitment(phi_star),
@ -197,18 +194,20 @@ where
},
Witness {
w: w_star,
r_w: w.r_w, // wip, fold also r_w (blinding used for the w commitment)
r_w: r_w_star,
},
F_X_dense.coeffs,
K_X.coeffs,
)
}
pub fn verifier(
pub fn verify(
transcript: &mut Transcript<C::ScalarField, C>,
r1cs: &R1CS<C::ScalarField>,
// running instance
instance: CommittedInstance<C>,
instance: &CommittedInstance<C>,
// incomming instances
vec_instances: Vec<CommittedInstance<C>>,
vec_instances: &[CommittedInstance<C>],
// polys from P
F_coeffs: Vec<C::ScalarField>,
K_coeffs: Vec<C::ScalarField>,
@ -337,13 +336,13 @@ fn check_instance(
instance: &CommittedInstance<C>,
w: &Witness<C>,
) -> bool {
let n = 2_u64.pow(instance.betas.len() as u32) as usize;
assert_eq!(instance.betas.len(), log2(w.w.len()) as usize);
let f_w = eval_f(r1cs, &w.w); // f(w)
let mut r = C::ScalarField::zero();
for i in 0..n {
r += pow_i(i, &instance.betas) * f_w[i];
for (i, f_w_i) in f_w.iter().enumerate() {
r += pow_i(i, &instance.betas) * f_w_i;
}
if instance.e == r {
return true;
@ -550,21 +549,21 @@ mod tests {
let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
let (F_coeffs, K_coeffs, folded_instance, folded_witness) = Folding::<G1Projective>::prover(
let (folded_instance, folded_witness, F_coeffs, K_coeffs) = Folding::<G1Projective>::prove(
&mut transcript_p,
&r1cs,
instance.clone(),
witness,
instances.clone(),
witnesses,
&instance,
&witness,
&instances,
&witnesses,
);
// veriier
let folded_instance_v = Folding::<G1Projective>::verifier(
let folded_instance_v = Folding::<G1Projective>::verify(
&mut transcript_v,
&r1cs,
instance,
instances,
&instance,
&instances,
F_coeffs,
K_coeffs,
);
@ -597,22 +596,22 @@ mod tests {
// generate the instances to be fold
let (_, _, witnesses, instances) = prepare_inputs(k);
let (F_coeffs, K_coeffs, folded_instance, folded_witness) =
Folding::<G1Projective>::prover(
let (folded_instance, folded_witness, F_coeffs, K_coeffs) =
Folding::<G1Projective>::prove(
&mut transcript_p,
&r1cs,
running_instance.clone(),
running_witness.clone(),
instances.clone(),
witnesses,
&running_instance,
&running_witness,
&instances,
&witnesses,
);
// veriier
let folded_instance_v = Folding::<G1Projective>::verifier(
let folded_instance_v = Folding::<G1Projective>::verify(
&mut transcript_v,
&r1cs,
running_instance.clone(),
instances,
&running_instance,
&instances,
F_coeffs,
K_coeffs,
);

+ 12
- 8
src/utils.rs

@ -2,6 +2,7 @@ use ark_ff::fields::PrimeField;
use ark_std::cfg_iter;
pub fn vec_add<F: PrimeField>(a: &[F], b: &[F]) -> Vec<F> {
assert_eq!(a.len(), b.len());
let mut r: Vec<F> = vec![F::zero(); a.len()];
for i in 0..a.len() {
r[i] = a[i] + b[i];
@ -10,6 +11,7 @@ pub fn vec_add(a: &[F], b: &[F]) -> Vec {
}
pub fn vec_sub<F: PrimeField>(a: &[F], b: &[F]) -> Vec<F> {
assert_eq!(a.len(), b.len());
let mut r: Vec<F> = vec![F::zero(); a.len()];
for i in 0..a.len() {
r[i] = a[i] - b[i];
@ -33,23 +35,25 @@ pub fn is_zero_vec(vec: &[F]) -> bool {
true
}
#[allow(clippy::needless_range_loop)]
pub fn mat_vec_mul<F: PrimeField>(M: &Vec<Vec<F>>, z: &[F]) -> Vec<F> {
// TODO assert len
assert!(!M.is_empty());
assert_eq!(M[0].len(), z.len());
let mut r: Vec<F> = vec![F::zero(); M.len()];
for i in 0..M.len() {
for j in 0..M[i].len() {
r[i] += M[i][j] * z[j];
for (i, M_i) in M.iter().enumerate() {
for (j, M_ij) in M_i.iter().enumerate() {
r[i] += *M_ij * z[j];
}
}
r
}
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()
}
// returns (b, b^2, b^4, ..., b^{2^{t-1}}) TODO find better name
// returns (b, b^2, b^4, ..., b^{2^{t-1}})
pub fn powers_of_beta<F: PrimeField>(b: F, t: usize) -> Vec<F> {
let mut r = vec![F::zero(); t];
r[0] = b;
@ -61,8 +65,8 @@ pub fn powers_of_beta(b: F, t: usize) -> Vec {
pub fn all_powers<F: PrimeField>(a: F, n: usize) -> Vec<F> {
let mut r = vec![F::zero(); n];
// TODO more efficiently
for i in 0..n {
r[i] = a.pow([i as u64]);
for (i, r_i) in r.iter_mut().enumerate() {
*r_i = a.pow([i as u64]);
}
r
}

Loading…
Cancel
Save