nova-study/src/pedersen.rs
src/pedersen.rsRaw
1use ark_ec::AffineRepr;
2use ark_ec::CurveGroup;
3use ark_std::{
4 rand::{Rng, RngCore},
5 UniformRand,
6};
7use std::marker::PhantomData;
8
9use crate::transcript::Transcript;
10use crate::utils::{naive_msm, vec_add, vector_elem_product};
11
12pub struct Proof_elem<C: CurveGroup> {
13 R: C,
14 t1: C::ScalarField,
15 t2: C::ScalarField,
16}
17pub struct Proof<C: CurveGroup> {
18 R: C,
19 u_: Vec<C::ScalarField>,
20 ru_: C::ScalarField,
21}
22
23pub struct Params<C: CurveGroup> {
24 g: C,
25 h: C,
26 pub generators: Vec<C>,
27}
28
29pub struct Pedersen<C: CurveGroup> {
30 _phantom: PhantomData<C>,
31}
32
33impl<C: CurveGroup> Pedersen<C> {
34 pub fn new_params<R: Rng>(rng: &mut R, max: usize) -> Params<C> {
35 let h_scalar = C::ScalarField::rand(rng);
36 let g: C = C::generator();
37 let generators: Vec<C> = vec![C::rand(rng); max];
38 let params: Params<C> = Params::<C> {
39 g,
40 h: g.mul(h_scalar),
41 generators,
42 };
43 params
44 }
45
46 pub fn commit_elem<R: RngCore>(
47 rng: &mut R,
48 params: &Params<C>,
49 v: &C::ScalarField,
50 ) -> CommitmentElem<C> {
51 let r = C::ScalarField::rand(rng);
52 let cm: C = (params.g.mul(v) + params.h.mul(r));
53 CommitmentElem::<C> { cm, r }
54 }
55 pub fn commit(
56 params: &Params<C>,
57 v: &Vec<C::ScalarField>,
58 r: &C::ScalarField, // random value is provided, in order to be choosen by other parts of the protocol
59 ) -> Commitment<C> {
60 let cm = params.h.mul(r) + naive_msm(v, ¶ms.generators);
61 Commitment::<C>(cm)
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));
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: &Commitment<C>, // TODO maybe it makes sense to not have a type wrapper and use directly 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, ¶ms.generators);
96
97 transcript.add(b"cm", &cm.0);
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: Commitment<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.0);
117 transcript.add(b"R", &proof.R);
118 let e = transcript.get_challenge(b"e");
119 let lhs = proof.R + cm.0.mul(e);
120 let rhs = params.h.mul(proof.ru_) + naive_msm(&proof.u_, ¶ms.generators);
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
149#[derive(Clone, Debug)]
150pub struct Commitment<C: CurveGroup>(pub C);
151
152pub struct CommitmentElem<C: CurveGroup> {
153 pub cm: C,
154 pub r: C::ScalarField,
155}
156impl<C: CurveGroup> CommitmentElem<C> {
157 pub fn prove(
158 &self,
159 params: &Params<C>,
160 transcript: &mut Transcript<C::ScalarField>,
161 v: C::ScalarField,
162 ) -> Proof_elem<C> {
163 Pedersen::<C>::prove_elem(params, transcript, self.cm, v, self.r)
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170 use ark_ec::CurveGroup;
171 use ark_mnt4_298::{Fr, G1Projective};
172 use std::ops::Mul;
173
174 #[test]
175 fn test_pedersen_single_element() {
176 let mut rng = ark_std::test_rng();
177
178 // setup params
179 let params = Pedersen::<G1Projective>::new_params(
180 &mut rng, 0, /* 0, as here we don't use commit_vec */
181 );
182
183 // init Prover's transcript
184 let mut transcript_p: Transcript<Fr> = Transcript::<Fr>::new();
185 // init Verifier's transcript
186 let mut transcript_v: Transcript<Fr> = Transcript::<Fr>::new();
187
188 let v = Fr::rand(&mut rng);
189
190 let cm = Pedersen::commit_elem(&mut rng, ¶ms, &v);
191 let proof = cm.prove(¶ms, &mut transcript_p, v);
192 // also can use:
193 // let proof = Pedersen::prove_elem(¶ms, &mut transcript_p, cm.cm, v, cm.r);
194 let v = Pedersen::verify_elem(¶ms, &mut transcript_v, cm.cm, proof);
195 assert!(v);
196 }
197 #[test]
198 fn test_pedersen_vector() {
199 let mut rng = ark_std::test_rng();
200
201 const n: usize = 10;
202 // setup params
203 let params = Pedersen::<G1Projective>::new_params(&mut rng, n);
204
205 // init Prover's transcript
206 let mut transcript_p: Transcript<Fr> = Transcript::<Fr>::new();
207 // init Verifier's transcript
208 let mut transcript_v: Transcript<Fr> = Transcript::<Fr>::new();
209
210 let v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
211 let r: Fr = Fr::rand(&mut rng);
212 let cm = Pedersen::commit(¶ms, &v, &r);
213 let proof = Pedersen::prove(¶ms, &mut transcript_p, &cm, &v, &r);
214 let v = Pedersen::verify(¶ms, &mut transcript_v, cm, proof);
215 assert!(v);
216 }
217}