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(params: &Params<C>, v: &Vec<C::ScalarField>, r: &C::ScalarField) -> C {
 41        // h⋅r + <g, v>
 42        params.h.mul(r) + C::msm(&params.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(&params.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(&params.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(&params, &v, &r);
117        let proof = Pedersen::<Projective>::prove(&params, &mut transcript_p, &cm, &v, &r).unwrap();
118        let v = Pedersen::<Projective>::verify(&params, &mut transcript_v, cm, proof);
119        assert!(v);
120    }
121}