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