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