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;
10
11pub struct Proof<C: AffineRepr> {
12 R: C,
13 t1: C::ScalarField,
14 t2: C::ScalarField,
15}
16
17pub struct Params<C: AffineRepr> {
18 g: C,
19 h: C,
20 pub r_vec: Vec<C>,
21}
22
23pub struct Pedersen<C: AffineRepr> {
24 _phantom: PhantomData<C>,
25}
26
27impl<C: AffineRepr> Pedersen<C> {
28 pub fn new_params<R: Rng>(rng: &mut R, max: usize) -> Params<C> {
29 let h_scalar = C::ScalarField::rand(rng);
30 let g: C = C::generator();
31 let r_vec: Vec<C> = vec![C::rand(rng); max];
32 let params: Params<C> = Params::<C> {
33 g,
34 h: g.mul(h_scalar).into(),
35 r_vec, // will need 2 r: rE, rW
36 };
37 params
38 }
39
40 pub fn commit_elem<R: RngCore>(
41 rng: &mut R,
42 params: &Params<C>,
43 v: &C::ScalarField,
44 ) -> CommitmentElem<C> {
45 let r = C::ScalarField::rand(rng);
46 let cm: C = (params.g.mul(v) + params.h.mul(r)).into();
47 CommitmentElem::<C> { cm, r }
48 }
49 pub fn commit(rs: &Vec<C>, v: &Vec<C::ScalarField>) -> Commitment<C> {
50 let cm = naive_msm(v, &rs);
51 Commitment::<C>(cm)
52 }
53
54 pub fn prove_elem(
55 params: &Params<C>,
56 transcript: &mut Transcript<C::ScalarField>,
57 cm: C,
58 v: C::ScalarField,
59 r: C::ScalarField,
60 ) -> Proof<C> {
61 let s1 = transcript.get_challenge(b"s_1");
62 let s2 = transcript.get_challenge(b"s_2");
63
64 let R: C = (params.g.mul(s1) + params.h.mul(s2)).into();
65
66 transcript.add(b"cm", &cm);
67 transcript.add(b"R", &R);
68 let c = transcript.get_challenge(b"c");
69
70 let t1 = s1 + v * c;
71 let t2 = s2 + r * c;
72
73 Proof::<C> { R, t1, t2 }
74 }
75
76 pub fn verify_elem(
77 params: &Params<C>,
78 transcript: &mut Transcript<C::ScalarField>,
79 cm: C,
80 proof: Proof<C>,
81 ) -> bool {
82 // s1, s2 just to match Prover's transcript
83 transcript.get_challenge(b"s_1");
84 transcript.get_challenge(b"s_2");
85
86 transcript.add(b"cm", &cm);
87 transcript.add(b"R", &proof.R);
88 let c = transcript.get_challenge(b"c");
89 let lhs = proof.R + cm.mul(c);
90 let rhs = params.g.mul(proof.t1) + params.h.mul(proof.t2);
91 if lhs != rhs {
92 return false;
93 }
94 true
95 }
96}
97
98pub struct Commitment<C: AffineRepr>(pub C);
99
100pub struct CommitmentElem<C: AffineRepr> {
101 pub cm: C,
102 pub r: C::ScalarField,
103}
104impl<C: AffineRepr> CommitmentElem<C> {
105 pub fn prove(
106 &self,
107 params: &Params<C>,
108 transcript: &mut Transcript<C::ScalarField>,
109 v: C::ScalarField,
110 ) -> Proof<C> {
111 Pedersen::<C>::prove_elem(params, transcript, self.cm, v, self.r)
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118 use ark_bn254::{g1::G1Affine, Fr};
119 use ark_ec::CurveGroup;
120 use std::ops::Mul;
121
122 #[test]
123 fn test_pedersen() {
124 let mut rng = ark_std::test_rng();
125
126 // setup params
127 let params = Pedersen::<G1Affine>::new_params(
128 &mut rng, 0, /* 0, as here we don't use commit_vec */
129 );
130
131 // init Prover's transcript
132 let mut transcript_p: Transcript<Fr> = Transcript::<Fr>::new();
133 // init Verifier's transcript
134 let mut transcript_v: Transcript<Fr> = Transcript::<Fr>::new();
135
136 let v = Fr::rand(&mut rng);
137
138 let cm = Pedersen::commit_elem(&mut rng, ¶ms, &v);
139 let proof = cm.prove(¶ms, &mut transcript_p, v);
140 // also can use:
141 // let proof = Pedersen::prove_elem(¶ms, &mut transcript_p, cm.cm, v, cm.r);
142 let v = Pedersen::verify_elem(¶ms, &mut transcript_v, cm.cm, proof);
143 assert!(v);
144 }
145}