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