arnaucube
arnaucube/protogalaxy-pocPublic Self-hosted repository
protogalaxy-poc/src/pedersen.rs
src/pedersen.rsRaw
  1/// pedersen.rs file adapted from https://github.com/arnaucube/nova-study
  2use ark_ec::{CurveGroup, Group};
  3use ark_std::{
  4    rand::{Rng, RngCore},
  5    UniformRand,
  6};
  7use std::marker::PhantomData;
  8
  9use crate::utils::{vec_add, vec_scalar_mul};
 10
 11use crate::transcript::Transcript;
 12use ark_crypto_primitives::sponge::Absorb;
 13
 14pub struct ProofElem<C: CurveGroup> {
 15    R: C,
 16    t1: C::ScalarField,
 17    t2: C::ScalarField,
 18}
 19pub struct Proof<C: CurveGroup> {
 20    R: C,
 21    u_: Vec<C::ScalarField>,
 22    ru_: C::ScalarField,
 23}
 24
 25pub struct Params<C: CurveGroup> {
 26    g: C,
 27    h: C,
 28    pub generators: Vec<C::Affine>,
 29}
 30
 31pub struct Pedersen<C: CurveGroup>
 32where
 33    <C as Group>::ScalarField: Absorb,
 34    <C as CurveGroup>::BaseField: Absorb,
 35{
 36    _c: PhantomData<C>,
 37}
 38
 39impl<C: CurveGroup> Pedersen<C>
 40where
 41    <C as Group>::ScalarField: Absorb,
 42    <C as CurveGroup>::BaseField: Absorb,
 43{
 44    pub fn new_params<R: Rng>(rng: &mut R, max: usize) -> Params<C> {
 45        let h_scalar = C::ScalarField::rand(rng);
 46        let g: C = C::generator();
 47        let generators: Vec<C::Affine> = vec![C::Affine::rand(rng); max];
 48        let params: Params<C> = Params::<C> {
 49            g,
 50            h: g.mul(h_scalar),
 51            generators,
 52        };
 53        params
 54    }
 55
 56    pub fn commit_elem<R: RngCore>(
 57        rng: &mut R,
 58        params: &Params<C>,
 59        v: &C::ScalarField,
 60    ) -> CommitmentElem<C> {
 61        let r = C::ScalarField::rand(rng);
 62        let cm: C = params.g.mul(v) + params.h.mul(r);
 63        CommitmentElem::<C> { cm, r }
 64    }
 65    pub fn commit(
 66        params: &Params<C>,
 67        v: &Vec<C::ScalarField>,
 68        r: &C::ScalarField, // random value is provided, in order to be choosen by other parts of the protocol
 69    ) -> Commitment<C> {
 70        let cm = params.h.mul(r) + C::msm(&params.generators[..v.len()], v).unwrap();
 71        Commitment::<C>(cm)
 72    }
 73
 74    pub fn prove_elem(
 75        params: &Params<C>,
 76        transcript: &mut Transcript<C::ScalarField, C>,
 77        cm: C,
 78        v: C::ScalarField,
 79        r: C::ScalarField,
 80    ) -> ProofElem<C> {
 81        let r1 = transcript.get_challenge();
 82        let r2 = transcript.get_challenge();
 83
 84        let R: C = params.g.mul(r1) + params.h.mul(r2);
 85
 86        transcript.add_point(&cm);
 87        transcript.add_point(&R);
 88        let e = transcript.get_challenge();
 89
 90        let t1 = r1 + v * e;
 91        let t2 = r2 + r * e;
 92
 93        ProofElem::<C> { R, t1, t2 }
 94    }
 95    pub fn prove(
 96        params: &Params<C>,
 97        transcript: &mut Transcript<C::ScalarField, C>,
 98        cm: &Commitment<C>, // TODO maybe it makes sense to not have a type wrapper and use directly C
 99        v: &Vec<C::ScalarField>,
100        r: &C::ScalarField,
101    ) -> Proof<C> {
102        let r1 = transcript.get_challenge();
103        let d = transcript.get_challenge_vec(v.len());
104
105        let R: C = params.h.mul(r1) + C::msm(&params.generators, &d).unwrap();
106
107        transcript.add_point(&cm.0);
108        transcript.add_point(&R);
109        let e = transcript.get_challenge();
110
111        let u_ = vec_add(&vec_scalar_mul(v, &e), &d);
112        let ru_ = e * r + r1;
113
114        Proof::<C> { R, u_, ru_ }
115    }
116    pub fn verify(
117        params: &Params<C>,
118        transcript: &mut Transcript<C::ScalarField, C>,
119        cm: Commitment<C>,
120        proof: Proof<C>,
121    ) -> bool {
122        // r1, d just to match Prover's transcript
123        transcript.get_challenge(); // r_1
124        transcript.get_challenge_vec(proof.u_.len()); // d
125
126        transcript.add_point(&cm.0);
127        transcript.add_point(&proof.R);
128        let e = transcript.get_challenge();
129        let lhs = proof.R + cm.0.mul(e);
130        let rhs = params.h.mul(proof.ru_) + C::msm(&params.generators, &proof.u_).unwrap();
131        if lhs != rhs {
132            return false;
133        }
134        true
135    }
136
137    pub fn verify_elem(
138        params: &Params<C>,
139        transcript: &mut Transcript<C::ScalarField, C>,
140        cm: C,
141        proof: ProofElem<C>,
142    ) -> bool {
143        // s1, s2 just to match Prover's transcript
144        transcript.get_challenge(); // r_1
145        transcript.get_challenge(); // r_2
146
147        transcript.add_point(&cm);
148        transcript.add_point(&proof.R);
149        let e = transcript.get_challenge();
150        let lhs = proof.R + cm.mul(e);
151        let rhs = params.g.mul(proof.t1) + params.h.mul(proof.t2);
152        if lhs != rhs {
153            return false;
154        }
155        true
156    }
157}
158
159#[derive(Clone, Debug)]
160pub struct Commitment<C: CurveGroup>(pub C);
161
162pub struct CommitmentElem<C: CurveGroup> {
163    pub cm: C,
164    pub r: C::ScalarField,
165}
166impl<C: CurveGroup> CommitmentElem<C>
167where
168    <C as Group>::ScalarField: Absorb,
169    <C as CurveGroup>::BaseField: Absorb,
170{
171    pub fn prove(
172        &self,
173        params: &Params<C>,
174        transcript: &mut Transcript<C::ScalarField, C>,
175        v: C::ScalarField,
176    ) -> ProofElem<C> {
177        Pedersen::<C>::prove_elem(params, transcript, self.cm, v, self.r)
178    }
179}
180
181#[cfg(test)]
182mod tests {
183    use super::*;
184    use crate::transcript::poseidon_test_config;
185    use ark_bls12_381::{Fr, G1Projective};
186
187    #[test]
188    fn test_pedersen_single_element() {
189        let mut rng = ark_std::test_rng();
190
191        // setup params
192        let params = Pedersen::<G1Projective>::new_params(
193            &mut rng, 0, /* 0, as here we don't use commit_vec */
194        );
195        let poseidon_config = poseidon_test_config::<Fr>();
196
197        // init Prover's transcript
198        let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
199        // init Verifier's transcript
200        let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
201
202        let v = Fr::rand(&mut rng);
203
204        let cm = Pedersen::commit_elem(&mut rng, &params, &v);
205        let proof = cm.prove(&params, &mut transcript_p, v);
206        // also can use:
207        // let proof = Pedersen::prove_elem(&params, &mut transcript_p, cm.cm, v, cm.r);
208        let v = Pedersen::verify_elem(&params, &mut transcript_v, cm.cm, proof);
209        assert!(v);
210    }
211    #[test]
212    fn test_pedersen_vector() {
213        let mut rng = ark_std::test_rng();
214
215        const n: usize = 10;
216        // setup params
217        let params = Pedersen::<G1Projective>::new_params(&mut rng, n);
218        let poseidon_config = poseidon_test_config::<Fr>();
219
220        // init Prover's transcript
221        let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
222        // init Verifier's transcript
223        let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
224
225        let v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
226        let r: Fr = Fr::rand(&mut rng);
227        let cm = Pedersen::commit(&params, &v, &r);
228        let proof = Pedersen::prove(&params, &mut transcript_p, &cm, &v, &r);
229        let v = Pedersen::verify(&params, &mut transcript_v, cm, proof);
230        assert!(v);
231    }
232}