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 generators: 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 generators: Vec<C> = vec![C::rand(rng); max];
37 let params: Params<C> = Params::<C> {
38 g,
39 h: g.mul(h_scalar).into(),
40 generators,
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, ¶ms.generators);
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, ¶ms.generators)).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_, ¶ms.generators);
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, ¶ms, &v);
189 let proof = cm.prove(¶ms, &mut transcript_p, v);
190 // also can use:
191 // let proof = Pedersen::prove_elem(¶ms, &mut transcript_p, cm.cm, v, cm.r);
192 let v = Pedersen::verify_elem(¶ms, &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(¶ms, &v, &r);
211 let proof = Pedersen::prove(¶ms, &mut transcript_p, &cm, &v, &r);
212 let v = Pedersen::verify(¶ms, &mut transcript_v, cm, proof);
213 assert!(v);
214 }
215}