sonobe/src/pedersen.rs
src/pedersen.rsRaw
1use ark_ec::CurveGroup;
2use ark_std::{rand::Rng, UniformRand};
3use std::marker::PhantomData;
4
5use crate::utils::vec::{vec_add, vec_scalar_mul};
6
7use crate::transcript::Transcript;
8use crate::Error;
9
10#[derive(Debug, Clone, Eq, PartialEq)]
11pub struct Proof<C: CurveGroup> {
12 R: C,
13 u: Vec<C::ScalarField>,
14 r_u: C::ScalarField,
15}
16
17#[derive(Debug, Clone, Eq, PartialEq)]
18pub struct Params<C: CurveGroup> {
19 h: C,
20 pub generators: Vec<C::Affine>,
21}
22
23#[derive(Debug, Clone, Eq, PartialEq)]
24pub struct Pedersen<C: CurveGroup> {
25 _c: PhantomData<C>,
26}
27
28impl<C: CurveGroup> Pedersen<C> {
29 pub fn new_params<R: Rng>(rng: &mut R, max: usize) -> Params<C> {
30 let generators: Vec<C::Affine> = std::iter::repeat_with(|| C::Affine::rand(rng))
31 .take(max.next_power_of_two())
32 .collect();
33 let params: Params<C> = Params::<C> {
34 h: C::rand(rng),
35 generators,
36 };
37 params
38 }
39
40 pub fn commit(params: &Params<C>, v: &Vec<C::ScalarField>, r: &C::ScalarField) -> C {
41 // h⋅r + <g, v>
42 params.h.mul(r) + C::msm(¶ms.generators[..v.len()], v).unwrap()
43 }
44
45 pub fn prove(
46 params: &Params<C>,
47 transcript: &mut impl Transcript<C>,
48 cm: &C,
49 v: &Vec<C::ScalarField>,
50 r: &C::ScalarField,
51 ) -> Result<Proof<C>, Error> {
52 transcript.absorb_point(cm);
53 let r1 = transcript.get_challenge();
54 let d = transcript.get_challenges(v.len());
55
56 // R = h⋅r_1 + <g, d>
57 let R: C = params.h.mul(r1) + C::msm(¶ms.generators[..d.len()], &d).unwrap();
58
59 transcript.absorb_point(&R);
60 let e = transcript.get_challenge();
61
62 // u = d + v⋅e
63 let u = vec_add(&vec_scalar_mul(v, &e), &d)?;
64 // r_u = e⋅r + r_1
65 let r_u = e * r + r1;
66
67 Ok(Proof::<C> { R, u, r_u })
68 }
69
70 pub fn verify(
71 params: &Params<C>,
72 transcript: &mut impl Transcript<C>,
73 cm: C,
74 proof: Proof<C>,
75 ) -> bool {
76 transcript.absorb_point(&cm);
77 transcript.get_challenge(); // r_1
78 transcript.get_challenges(proof.u.len()); // d
79 transcript.absorb_point(&proof.R);
80 let e = transcript.get_challenge();
81
82 // check that: R + cm == h⋅r_u + <g, u>
83 let lhs = proof.R + cm.mul(e);
84 let rhs = params.h.mul(proof.r_u)
85 + C::msm(¶ms.generators[..proof.u.len()], &proof.u).unwrap();
86 if lhs != rhs {
87 return false;
88 }
89 true
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 use crate::transcript::poseidon::{tests::poseidon_test_config, PoseidonTranscript};
97
98 use ark_pallas::{Fr, Projective};
99
100 #[test]
101 fn test_pedersen_vector() {
102 let mut rng = ark_std::test_rng();
103
104 const n: usize = 10;
105 // setup params
106 let params = Pedersen::<Projective>::new_params(&mut rng, n);
107 let poseidon_config = poseidon_test_config::<Fr>();
108
109 // init Prover's transcript
110 let mut transcript_p = PoseidonTranscript::<Projective>::new(&poseidon_config);
111 // init Verifier's transcript
112 let mut transcript_v = PoseidonTranscript::<Projective>::new(&poseidon_config);
113
114 let v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
115 let r: Fr = Fr::rand(&mut rng);
116 let cm = Pedersen::<Projective>::commit(¶ms, &v, &r);
117 let proof = Pedersen::<Projective>::prove(¶ms, &mut transcript_p, &cm, &v, &r).unwrap();
118 let v = Pedersen::<Projective>::verify(¶ms, &mut transcript_v, cm, proof);
119 assert!(v);
120 }
121}