You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
6.6 KiB

  1. use ark_ec::{CurveGroup, Group};
  2. use ark_std::{
  3. rand::{Rng, RngCore},
  4. UniformRand,
  5. };
  6. use std::marker::PhantomData;
  7. use crate::utils::{naive_msm, vec_add, vector_elem_product};
  8. use crate::transcript::Transcript;
  9. use ark_crypto_primitives::sponge::Absorb;
  10. pub struct Proof_elem<C: CurveGroup> {
  11. R: C,
  12. t1: C::ScalarField,
  13. t2: C::ScalarField,
  14. }
  15. pub struct Proof<C: CurveGroup> {
  16. R: C,
  17. u_: Vec<C::ScalarField>,
  18. ru_: C::ScalarField,
  19. }
  20. pub struct Params<C: CurveGroup> {
  21. g: C,
  22. h: C,
  23. pub generators: Vec<C>,
  24. }
  25. pub struct Pedersen<C: CurveGroup>
  26. where
  27. <C as Group>::ScalarField: Absorb,
  28. <C as CurveGroup>::BaseField: Absorb,
  29. {
  30. _c: PhantomData<C>,
  31. }
  32. impl<C: CurveGroup> Pedersen<C>
  33. where
  34. <C as Group>::ScalarField: Absorb,
  35. <C as CurveGroup>::BaseField: Absorb,
  36. {
  37. pub fn new_params<R: Rng>(rng: &mut R, max: usize) -> Params<C> {
  38. let h_scalar = C::ScalarField::rand(rng);
  39. let g: C = C::generator();
  40. let generators: Vec<C> = vec![C::rand(rng); max];
  41. let params: Params<C> = Params::<C> {
  42. g,
  43. h: g.mul(h_scalar),
  44. generators,
  45. };
  46. params
  47. }
  48. pub fn commit_elem<R: RngCore>(
  49. rng: &mut R,
  50. params: &Params<C>,
  51. v: &C::ScalarField,
  52. ) -> CommitmentElem<C> {
  53. let r = C::ScalarField::rand(rng);
  54. let cm: C = params.g.mul(v) + params.h.mul(r);
  55. CommitmentElem::<C> { cm, r }
  56. }
  57. pub fn commit(
  58. params: &Params<C>,
  59. v: &Vec<C::ScalarField>,
  60. r: &C::ScalarField, // random value is provided, in order to be choosen by other parts of the protocol
  61. ) -> Commitment<C> {
  62. let cm = params.h.mul(r) + naive_msm(v, &params.generators);
  63. Commitment::<C>(cm)
  64. }
  65. pub fn prove_elem(
  66. params: &Params<C>,
  67. transcript: &mut Transcript<C::ScalarField, C>,
  68. cm: C,
  69. v: C::ScalarField,
  70. r: C::ScalarField,
  71. ) -> Proof_elem<C> {
  72. let r1 = transcript.get_challenge();
  73. let r2 = transcript.get_challenge();
  74. let R: C = params.g.mul(r1) + params.h.mul(r2);
  75. transcript.add_point(&cm);
  76. transcript.add_point(&R);
  77. let e = transcript.get_challenge();
  78. let t1 = r1 + v * e;
  79. let t2 = r2 + r * e;
  80. Proof_elem::<C> { R, t1, t2 }
  81. }
  82. pub fn prove(
  83. params: &Params<C>,
  84. transcript: &mut Transcript<C::ScalarField, C>,
  85. cm: &Commitment<C>, // TODO maybe it makes sense to not have a type wrapper and use directly C
  86. v: &Vec<C::ScalarField>,
  87. r: &C::ScalarField,
  88. ) -> Proof<C> {
  89. let r1 = transcript.get_challenge();
  90. let d = transcript.get_challenge_vec(v.len());
  91. let R: C = params.h.mul(r1) + naive_msm(&d, &params.generators);
  92. transcript.add_point(&cm.0);
  93. transcript.add_point(&R);
  94. let e = transcript.get_challenge();
  95. let u_ = vec_add(&vector_elem_product(v, &e), &d);
  96. let ru_ = e * r + r1;
  97. Proof::<C> { R, u_, ru_ }
  98. }
  99. pub fn verify(
  100. params: &Params<C>,
  101. transcript: &mut Transcript<C::ScalarField, C>,
  102. cm: Commitment<C>,
  103. proof: Proof<C>,
  104. ) -> bool {
  105. // r1, d just to match Prover's transcript
  106. transcript.get_challenge(); // r_1
  107. transcript.get_challenge_vec(proof.u_.len()); // d
  108. transcript.add_point(&cm.0);
  109. transcript.add_point(&proof.R);
  110. let e = transcript.get_challenge();
  111. let lhs = proof.R + cm.0.mul(e);
  112. let rhs = params.h.mul(proof.ru_) + naive_msm(&proof.u_, &params.generators);
  113. if lhs != rhs {
  114. return false;
  115. }
  116. true
  117. }
  118. pub fn verify_elem(
  119. params: &Params<C>,
  120. transcript: &mut Transcript<C::ScalarField, C>,
  121. cm: C,
  122. proof: Proof_elem<C>,
  123. ) -> bool {
  124. // s1, s2 just to match Prover's transcript
  125. transcript.get_challenge(); // r_1
  126. transcript.get_challenge(); // r_2
  127. transcript.add_point(&cm);
  128. transcript.add_point(&proof.R);
  129. let e = transcript.get_challenge();
  130. let lhs = proof.R + cm.mul(e);
  131. let rhs = params.g.mul(proof.t1) + params.h.mul(proof.t2);
  132. if lhs != rhs {
  133. return false;
  134. }
  135. true
  136. }
  137. }
  138. #[derive(Clone, Debug)]
  139. pub struct Commitment<C: CurveGroup>(pub C);
  140. pub struct CommitmentElem<C: CurveGroup> {
  141. pub cm: C,
  142. pub r: C::ScalarField,
  143. }
  144. impl<C: CurveGroup> CommitmentElem<C>
  145. where
  146. <C as Group>::ScalarField: Absorb,
  147. <C as CurveGroup>::BaseField: Absorb,
  148. {
  149. pub fn prove(
  150. &self,
  151. params: &Params<C>,
  152. transcript: &mut Transcript<C::ScalarField, C>,
  153. v: C::ScalarField,
  154. ) -> Proof_elem<C> {
  155. Pedersen::<C>::prove_elem(params, transcript, self.cm, v, self.r)
  156. }
  157. }
  158. #[cfg(test)]
  159. mod tests {
  160. use super::*;
  161. use crate::transcript::poseidon_test_config;
  162. use ark_mnt4_298::{Fr, G1Projective};
  163. #[test]
  164. fn test_pedersen_single_element() {
  165. let mut rng = ark_std::test_rng();
  166. // setup params
  167. let params = Pedersen::<G1Projective>::new_params(
  168. &mut rng, 0, /* 0, as here we don't use commit_vec */
  169. );
  170. let poseidon_config = poseidon_test_config::<Fr>();
  171. // init Prover's transcript
  172. let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
  173. // init Verifier's transcript
  174. let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
  175. let v = Fr::rand(&mut rng);
  176. let cm = Pedersen::commit_elem(&mut rng, &params, &v);
  177. let proof = cm.prove(&params, &mut transcript_p, v);
  178. // also can use:
  179. // let proof = Pedersen::prove_elem(&params, &mut transcript_p, cm.cm, v, cm.r);
  180. let v = Pedersen::verify_elem(&params, &mut transcript_v, cm.cm, proof);
  181. assert!(v);
  182. }
  183. #[test]
  184. fn test_pedersen_vector() {
  185. let mut rng = ark_std::test_rng();
  186. const n: usize = 10;
  187. // setup params
  188. let params = Pedersen::<G1Projective>::new_params(&mut rng, n);
  189. let poseidon_config = poseidon_test_config::<Fr>();
  190. // init Prover's transcript
  191. let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
  192. // init Verifier's transcript
  193. let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
  194. let v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
  195. let r: Fr = Fr::rand(&mut rng);
  196. let cm = Pedersen::commit(&params, &v, &r);
  197. let proof = Pedersen::prove(&params, &mut transcript_p, &cm, &v, &r);
  198. let v = Pedersen::verify(&params, &mut transcript_v, cm, proof);
  199. assert!(v);
  200. }
  201. }