rm unused pedersen.rs methods, some more polishing
@@ -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]
@@ -2,7 +2,7 @@ # protogalaxy-poc [](https://github.com/arnaucube/protogalaxy-poc/actions?query=workflow%3ATest)
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 @@ // Prover folds the instances and witnesses
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 @@ // verifier folds the instances
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 @@
// 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;
@@ -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::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 @@ ru_: C::ScalarField,
} pub struct Params<C: CurveGroup> { - g: C, h: C, pub generators: Vec<C::Affine>, }@@ -46,22 +37,12 @@ let h_scalar = C::ScalarField::rand(rng);
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 @@ let cm = params.h.mul(r) + C::msm(¶ms.generators[..v.len()], v).unwrap();
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 @@ return false;
} 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 @@ let f_w = eval_f(r1cs, &w.w);
// 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 @@ phi: instance.phi.clone(),
betas: betas_star.clone(), e: F_alpha, }, - &w, + w, )); let mut ws: Vec<Vec<C::ScalarField>> = Vec::new();@@ -146,12 +146,11 @@ }
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 @@ let L0_e = &L_X[0] * F_alpha; // L0(X)*F(a) will be 0 in the native case
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 @@ r_w_star += vec_w[i].r_w * L_X[i + 1].evaluate(&gamma);
} ( - F_X_dense.coeffs, - K_X.coeffs, CommittedInstance { betas: betas_star, phi: Commitment(phi_star),@@ -197,18 +194,20 @@ e: e_star,
}, 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 @@ r1cs: &R1CS<C::ScalarField>,
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 @@ let poseidon_config = poseidon_test_config::<Fr>();
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 @@ for _ in 0..num_iters {
// 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, );
@@ -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 @@ r
} 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 @@ }
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 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 }