mirror of
https://github.com/arnaucube/protogalaxy-poc.git
synced 2026-01-11 08:21:30 +01:00
rm unused pedersen.rs methods, some more polishing
This commit is contained in:
@@ -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]
|
||||
|
||||
10
README.md
10
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::<G1Projecti
|
||||
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::<G1Projective>::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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
106
src/pedersen.rs
106
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<C: CurveGroup> {
|
||||
}
|
||||
|
||||
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, ¶ms, &v);
|
||||
let proof = cm.prove(¶ms, &mut transcript_p, v);
|
||||
// also can use:
|
||||
// let proof = Pedersen::prove_elem(¶ms, &mut transcript_p, cm.cm, v, cm.r);
|
||||
let v = Pedersen::verify_elem(¶ms, &mut transcript_v, cm.cm, proof);
|
||||
assert!(v);
|
||||
}
|
||||
#[test]
|
||||
fn test_pedersen_vector() {
|
||||
let mut rng = ark_std::test_rng();
|
||||
|
||||
@@ -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<C: CurveGroup>(
|
||||
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,
|
||||
);
|
||||
|
||||
20
src/utils.rs
20
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<F: PrimeField>(a: &[F], b: &[F]) -> Vec<F> {
|
||||
}
|
||||
|
||||
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<F: PrimeField>(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<F: PrimeField>(b: F, t: usize) -> Vec<F> {
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user