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