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