protogalaxy-poc/src/pedersen.rs
src/pedersen.rsRaw
1/// pedersen.rs file adapted from https://github.com/arnaucube/nova-study
2use ark_ec::{CurveGroup, Group};
3use ark_std::{rand::Rng, UniformRand};
4use std::marker::PhantomData;
5
6use crate::utils::{vec_add, vec_scalar_mul};
7
8use crate::transcript::Transcript;
9use ark_crypto_primitives::sponge::Absorb;
10
11pub struct Proof<C: CurveGroup> {
12 R: C,
13 u_: Vec<C::ScalarField>,
14 ru_: C::ScalarField,
15}
16
17pub struct Params<C: CurveGroup> {
18 h: C,
19 pub generators: Vec<C::Affine>,
20}
21
22pub struct Pedersen<C: CurveGroup>
23where
24 <C as Group>::ScalarField: Absorb,
25 <C as CurveGroup>::BaseField: Absorb,
26{
27 _c: PhantomData<C>,
28}
29
30impl<C: CurveGroup> Pedersen<C>
31where
32 <C as Group>::ScalarField: Absorb,
33 <C as CurveGroup>::BaseField: Absorb,
34{
35 pub fn new_params<R: Rng>(rng: &mut R, max: usize) -> Params<C> {
36 let h_scalar = C::ScalarField::rand(rng);
37 let g: C = C::generator();
38 let generators: Vec<C::Affine> = vec![C::Affine::rand(rng); max];
39 let params: Params<C> = Params::<C> {
40 h: g.mul(h_scalar),
41 generators,
42 };
43 params
44 }
45
46 pub fn commit(
47 params: &Params<C>,
48 v: &Vec<C::ScalarField>,
49 r: &C::ScalarField, // random value is provided, in order to be choosen by other parts of the protocol
50 ) -> Commitment<C> {
51 let cm = params.h.mul(r) + C::msm(¶ms.generators[..v.len()], v).unwrap();
52 Commitment::<C>(cm)
53 }
54
55 pub fn prove(
56 params: &Params<C>,
57 transcript: &mut Transcript<C::ScalarField, C>,
58 cm: &Commitment<C>, // TODO maybe it makes sense to not have a type wrapper and use directly C
59 v: &Vec<C::ScalarField>,
60 r: &C::ScalarField,
61 ) -> Proof<C> {
62 let r1 = transcript.get_challenge();
63 let d = transcript.get_challenge_vec(v.len());
64
65 let R: C = params.h.mul(r1) + C::msm(¶ms.generators, &d).unwrap();
66
67 transcript.add_point(&cm.0);
68 transcript.add_point(&R);
69 let e = transcript.get_challenge();
70
71 let u_ = vec_add(&vec_scalar_mul(v, &e), &d);
72 let ru_ = e * r + r1;
73
74 Proof::<C> { R, u_, ru_ }
75 }
76 pub fn verify(
77 params: &Params<C>,
78 transcript: &mut Transcript<C::ScalarField, C>,
79 cm: Commitment<C>,
80 proof: Proof<C>,
81 ) -> bool {
82 // r1, d just to match Prover's transcript
83 transcript.get_challenge(); // r_1
84 transcript.get_challenge_vec(proof.u_.len()); // d
85
86 transcript.add_point(&cm.0);
87 transcript.add_point(&proof.R);
88 let e = transcript.get_challenge();
89 let lhs = proof.R + cm.0.mul(e);
90 let rhs = params.h.mul(proof.ru_) + C::msm(¶ms.generators, &proof.u_).unwrap();
91 if lhs != rhs {
92 return false;
93 }
94 true
95 }
96}
97
98#[derive(Clone, Debug)]
99pub struct Commitment<C: CurveGroup>(pub C);
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use crate::transcript::poseidon_test_config;
105 use ark_bls12_381::{Fr, G1Projective};
106
107 #[test]
108 fn test_pedersen_vector() {
109 let mut rng = ark_std::test_rng();
110
111 const n: usize = 10;
112 // setup params
113 let params = Pedersen::<G1Projective>::new_params(&mut rng, n);
114 let poseidon_config = poseidon_test_config::<Fr>();
115
116 // init Prover's transcript
117 let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
118 // init Verifier's transcript
119 let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
120
121 let v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
122 let r: Fr = Fr::rand(&mut rng);
123 let cm = Pedersen::commit(¶ms, &v, &r);
124 let proof = Pedersen::prove(¶ms, &mut transcript_p, &cm, &v, &r);
125 let v = Pedersen::verify(¶ms, &mut transcript_v, cm, proof);
126 assert!(v);
127 }
128}