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(
 55        params: &Params<C>,
 56        v: &Vec<C::ScalarField>,
 57        r: &C::ScalarField, // random value is provided, in order to be choosen by other parts of the protocol
 58    ) -> Commitment<C> {
 59        let cm = params.h.mul(r) + naive_msm(v, &params.r_vec);
 60        Commitment::<C>(cm.into())
 61    }
 62
 63    pub fn prove_elem(
 64        params: &Params<C>,
 65        transcript: &mut Transcript<C::ScalarField>,
 66        cm: C,
 67        v: C::ScalarField,
 68        r: C::ScalarField,
 69    ) -> Proof_elem<C> {
 70        let r1 = transcript.get_challenge(b"r_1");
 71        let r2 = transcript.get_challenge(b"r_2");
 72
 73        let R: C = (params.g.mul(r1) + params.h.mul(r2)).into();
 74
 75        transcript.add(b"cm", &cm);
 76        transcript.add(b"R", &R);
 77        let e = transcript.get_challenge(b"e");
 78
 79        let t1 = r1 + v * e;
 80        let t2 = r2 + r * e;
 81
 82        Proof_elem::<C> { R, t1, t2 }
 83    }
 84    pub fn prove(
 85        params: &Params<C>,
 86        transcript: &mut Transcript<C::ScalarField>,
 87        cm: &Commitment<C>, // TODO maybe it makes sense to not have a type wrapper and use directly C
 88        v: &Vec<C::ScalarField>,
 89        r: &C::ScalarField,
 90    ) -> Proof<C> {
 91        let r1 = transcript.get_challenge(b"r_1");
 92        let d = transcript.get_challenge_vec(b"d", v.len());
 93
 94        let R: C = (params.h.mul(r1) + naive_msm(&d, &params.r_vec)).into();
 95
 96        transcript.add(b"cm", &cm.0);
 97        transcript.add(b"R", &R);
 98        let e = transcript.get_challenge(b"e");
 99
100        let u_ = vec_add(&vector_elem_product(&v, &e), &d);
101        let ru_ = e * r + r1;
102
103        Proof::<C> { R, u_, ru_ }
104    }
105    pub fn verify(
106        params: &Params<C>,
107        transcript: &mut Transcript<C::ScalarField>,
108        cm: Commitment<C>,
109        proof: Proof<C>,
110    ) -> bool {
111        // r1, d just to match Prover's transcript
112        transcript.get_challenge(b"r_1");
113        transcript.get_challenge_vec(b"d", proof.u_.len());
114
115        transcript.add(b"cm", &cm.0);
116        transcript.add(b"R", &proof.R);
117        let e = transcript.get_challenge(b"e");
118        let lhs = proof.R + cm.0.mul(e);
119        let rhs = params.h.mul(proof.ru_) + naive_msm(&proof.u_, &params.r_vec);
120        if lhs != rhs {
121            return false;
122        }
123        true
124    }
125
126    pub fn verify_elem(
127        params: &Params<C>,
128        transcript: &mut Transcript<C::ScalarField>,
129        cm: C,
130        proof: Proof_elem<C>,
131    ) -> bool {
132        // s1, s2 just to match Prover's transcript
133        transcript.get_challenge(b"r_1");
134        transcript.get_challenge(b"r_2");
135
136        transcript.add(b"cm", &cm);
137        transcript.add(b"R", &proof.R);
138        let e = transcript.get_challenge(b"e");
139        let lhs = proof.R + cm.mul(e);
140        let rhs = params.g.mul(proof.t1) + params.h.mul(proof.t2);
141        if lhs != rhs {
142            return false;
143        }
144        true
145    }
146}
147
148pub struct Commitment<C: AffineRepr>(pub C);
149
150pub struct CommitmentElem<C: AffineRepr> {
151    pub cm: C,
152    pub r: C::ScalarField,
153}
154impl<C: AffineRepr> CommitmentElem<C> {
155    pub fn prove(
156        &self,
157        params: &Params<C>,
158        transcript: &mut Transcript<C::ScalarField>,
159        v: C::ScalarField,
160    ) -> Proof_elem<C> {
161        Pedersen::<C>::prove_elem(params, transcript, self.cm, v, self.r)
162    }
163}
164
165#[cfg(test)]
166mod tests {
167    use super::*;
168    use ark_bn254::{g1::G1Affine, Fr};
169    use ark_ec::CurveGroup;
170    use std::ops::Mul;
171
172    #[test]
173    fn test_pedersen_single_element() {
174        let mut rng = ark_std::test_rng();
175
176        // setup params
177        let params = Pedersen::<G1Affine>::new_params(
178            &mut rng, 0, /* 0, as here we don't use commit_vec */
179        );
180
181        // init Prover's transcript
182        let mut transcript_p: Transcript<Fr> = Transcript::<Fr>::new();
183        // init Verifier's transcript
184        let mut transcript_v: Transcript<Fr> = Transcript::<Fr>::new();
185
186        let v = Fr::rand(&mut rng);
187
188        let cm = Pedersen::commit_elem(&mut rng, &params, &v);
189        let proof = cm.prove(&params, &mut transcript_p, v);
190        // also can use:
191        // let proof = Pedersen::prove_elem(&params, &mut transcript_p, cm.cm, v, cm.r);
192        let v = Pedersen::verify_elem(&params, &mut transcript_v, cm.cm, proof);
193        assert!(v);
194    }
195    #[test]
196    fn test_pedersen_vector() {
197        let mut rng = ark_std::test_rng();
198
199        const n: usize = 10;
200        // setup params
201        let params = Pedersen::<G1Affine>::new_params(&mut rng, n);
202
203        // init Prover's transcript
204        let mut transcript_p: Transcript<Fr> = Transcript::<Fr>::new();
205        // init Verifier's transcript
206        let mut transcript_v: Transcript<Fr> = Transcript::<Fr>::new();
207
208        let v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
209        let r: Fr = Fr::rand(&mut rng);
210        let cm = Pedersen::commit(&params, &v, &r);
211        let proof = Pedersen::prove(&params, &mut transcript_p, &cm, &v, &r);
212        let v = Pedersen::verify(&params, &mut transcript_v, cm, proof);
213        assert!(v);
214    }
215}