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