arnaucube
arnaucube/sonobePublic Self-hosted repository
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(
 41        params: &Params<C>,
 42        v: &Vec<C::ScalarField>,
 43        r: &C::ScalarField,
 44    ) -> Result<C, Error> {
 45        if params.generators.len() < v.len() {
 46            return Err(Error::PedersenParamsLen);
 47        }
 48        // h⋅r + <g, v>
 49        // use msm_unchecked because we already ensured at the if that lengths match
 50        Ok(params.h.mul(r) + C::msm_unchecked(&params.generators[..v.len()], v))
 51    }
 52
 53    pub fn prove(
 54        params: &Params<C>,
 55        transcript: &mut impl Transcript<C>,
 56        cm: &C,
 57        v: &Vec<C::ScalarField>,
 58        r: &C::ScalarField,
 59    ) -> Result<Proof<C>, Error> {
 60        if params.generators.len() < v.len() {
 61            return Err(Error::PedersenParamsLen);
 62        }
 63
 64        transcript.absorb_point(cm);
 65        let r1 = transcript.get_challenge();
 66        let d = transcript.get_challenges(v.len());
 67
 68        // R = h⋅r_1 + <g, d>
 69        // use msm_unchecked because we already ensured at the if that lengths match
 70        let R: C = params.h.mul(r1) + C::msm_unchecked(&params.generators[..d.len()], &d);
 71
 72        transcript.absorb_point(&R);
 73        let e = transcript.get_challenge();
 74
 75        // u = d + v⋅e
 76        let u = vec_add(&vec_scalar_mul(v, &e), &d)?;
 77        // r_u = e⋅r + r_1
 78        let r_u = e * r + r1;
 79
 80        Ok(Proof::<C> { R, u, r_u })
 81    }
 82
 83    pub fn verify(
 84        params: &Params<C>,
 85        transcript: &mut impl Transcript<C>,
 86        cm: C,
 87        proof: Proof<C>,
 88    ) -> Result<(), Error> {
 89        if params.generators.len() < proof.u.len() {
 90            return Err(Error::PedersenParamsLen);
 91        }
 92
 93        transcript.absorb_point(&cm);
 94        transcript.get_challenge(); // r_1
 95        transcript.get_challenges(proof.u.len()); // d
 96        transcript.absorb_point(&proof.R);
 97        let e = transcript.get_challenge();
 98
 99        // check that: R + cm == h⋅r_u + <g, u>
100        let lhs = proof.R + cm.mul(e);
101        // use msm_unchecked because we already ensured at the if that lengths match
102        let rhs = params.h.mul(proof.r_u)
103            + C::msm_unchecked(&params.generators[..proof.u.len()], &proof.u);
104        if lhs != rhs {
105            return Err(Error::PedersenVerificationFail);
106        }
107        Ok(())
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114    use crate::transcript::poseidon::{tests::poseidon_test_config, PoseidonTranscript};
115
116    use ark_pallas::{Fr, Projective};
117
118    #[test]
119    fn test_pedersen_vector() {
120        let mut rng = ark_std::test_rng();
121
122        const n: usize = 10;
123        // setup params
124        let params = Pedersen::<Projective>::new_params(&mut rng, n);
125        let poseidon_config = poseidon_test_config::<Fr>();
126
127        // init Prover's transcript
128        let mut transcript_p = PoseidonTranscript::<Projective>::new(&poseidon_config);
129        // init Verifier's transcript
130        let mut transcript_v = PoseidonTranscript::<Projective>::new(&poseidon_config);
131
132        let v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
133        let r: Fr = Fr::rand(&mut rng);
134        let cm = Pedersen::<Projective>::commit(&params, &v, &r).unwrap();
135        let proof = Pedersen::<Projective>::prove(&params, &mut transcript_p, &cm, &v, &r).unwrap();
136        Pedersen::<Projective>::verify(&params, &mut transcript_v, cm, proof).unwrap();
137    }
138}