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.

189 lines
5.5 KiB

  1. use ark_ec::AffineRepr;
  2. use ark_std::ops::Add;
  3. use std::marker::PhantomData;
  4. use crate::pedersen::{Commitment, CommitmentVec};
  5. use crate::r1cs::*;
  6. use crate::transcript::Transcript;
  7. use crate::utils::*;
  8. // Phi: φ in the paper (later 𝖴), a folded instance
  9. pub struct Phi<C: AffineRepr> {
  10. cmE: Commitment<C>, // TODO not Commitment but directly C (without rE)
  11. u: C::ScalarField,
  12. cmW: Commitment<C>, // TODO not Commitment but directly C (without rW)
  13. x: Vec<C::ScalarField>,
  14. }
  15. // FWit: Folded Witness
  16. pub struct FWit<C: AffineRepr> {
  17. E: Vec<C::ScalarField>,
  18. rE: C::ScalarField,
  19. W: Vec<C::ScalarField>,
  20. rW: C::ScalarField,
  21. }
  22. impl<C: AffineRepr> FWit<C> {
  23. pub fn commit(&self) -> Phi<C> {
  24. unimplemented!();
  25. }
  26. }
  27. pub struct NIFS<C: AffineRepr> {
  28. _phantom: PhantomData<C>,
  29. }
  30. impl<C: AffineRepr> NIFS<C> {
  31. pub fn comp_T(
  32. cs1: RelaxedR1CS<C::ScalarField>,
  33. cs2: RelaxedR1CS<C::ScalarField>,
  34. z1: &Vec<C::ScalarField>,
  35. z2: &Vec<C::ScalarField>,
  36. ) -> Vec<C::ScalarField> {
  37. // assuming cs1.R1CS == cs2.R1CS
  38. let (A, B, C) = (cs1.ABC.A, cs1.ABC.B, cs1.ABC.C);
  39. // this is parallelizable (for the future)
  40. let Az1 = matrix_vector_product(&A, &z1);
  41. let Bz1 = matrix_vector_product(&B, &z1);
  42. let Az1_Bz1 = hadamard_product(Az1, Bz1);
  43. let Az2 = matrix_vector_product(&A, &z2);
  44. let Bz2 = matrix_vector_product(&B, &z2);
  45. let Az2_Bz2 = hadamard_product(Az2, Bz2);
  46. let Cz2 = matrix_vector_product(&C, &z2);
  47. let Cz1 = matrix_vector_product(&C, &z1);
  48. let u1Cz2 = vector_elem_product(&Cz2, &cs1.u);
  49. let u2Cz1 = vector_elem_product(&Cz1, &cs2.u);
  50. // this will get simplifyied with future operators from Add trait
  51. let T = vec_sub(vec_sub(vec_add(Az1_Bz1, Az2_Bz2), u1Cz2), u2Cz1);
  52. T
  53. }
  54. pub fn fold_witness(
  55. r: C::ScalarField,
  56. fw1: &FWit<C>,
  57. fw2: &FWit<C>,
  58. T: Vec<C::ScalarField>,
  59. ) -> FWit<C> {
  60. let r2 = r * r;
  61. let E: Vec<C::ScalarField> = vec_add(
  62. // TODO this syntax will be simplified with future operators impl
  63. vec_add(fw1.E.clone(), vector_elem_product(&T, &r)),
  64. vector_elem_product(&fw2.E, &r2),
  65. );
  66. let rE = fw1.rE + r * fw2.rE;
  67. let W = vec_add(fw1.W.clone(), vector_elem_product(&fw2.W, &r));
  68. let rW = fw1.rW + r * fw2.rW;
  69. FWit::<C> {
  70. E: E.into(),
  71. rE,
  72. W: W.into(),
  73. rW,
  74. }
  75. }
  76. pub fn fold_instance(
  77. r: C::ScalarField,
  78. phi1: Phi<C>,
  79. phi2: Phi<C>,
  80. cmT: CommitmentVec<C>,
  81. ) -> Phi<C> {
  82. let r2 = r * r;
  83. let cmE = phi1.cmE.cm + cmT.cm.mul(r) + phi2.cmE.cm.mul(r2);
  84. let u = phi1.u + r * phi2.u;
  85. let cmW = phi1.cmW.cm + phi2.cmW.cm.mul(r);
  86. let x = vec_add(phi1.x, vector_elem_product(&phi2.x, &r));
  87. Phi::<C> {
  88. cmE: Commitment::<C> {
  89. cm: cmE.into(),
  90. r: phi1.cmE.r,
  91. },
  92. u,
  93. cmW: Commitment::<C> {
  94. cm: cmW.into(),
  95. r: phi1.cmW.r,
  96. },
  97. x,
  98. }
  99. }
  100. }
  101. #[cfg(test)]
  102. mod tests {
  103. use super::*;
  104. use crate::pedersen::Pedersen;
  105. use ark_bn254::{g1::G1Affine, Fr};
  106. use ark_ec::CurveGroup;
  107. use ark_std::{
  108. rand::{Rng, RngCore},
  109. UniformRand,
  110. };
  111. use ark_std::{One, Zero};
  112. use std::ops::Mul;
  113. #[test]
  114. fn test_simple_folding() {
  115. let mut rng = ark_std::test_rng();
  116. // R1CS for: x^3 + x + 5 = y
  117. let A = to_F_matrix::<Fr>(vec![
  118. vec![0, 1, 0, 0, 0, 0],
  119. vec![0, 0, 0, 1, 0, 0],
  120. vec![0, 1, 0, 0, 1, 0],
  121. vec![5, 0, 0, 0, 0, 1],
  122. ]);
  123. let B = to_F_matrix::<Fr>(vec![
  124. vec![0, 1, 0, 0, 0, 0],
  125. vec![0, 1, 0, 0, 0, 0],
  126. vec![1, 0, 0, 0, 0, 0],
  127. vec![1, 0, 0, 0, 0, 0],
  128. ]);
  129. let C = to_F_matrix::<Fr>(vec![
  130. vec![0, 0, 0, 1, 0, 0],
  131. vec![0, 0, 0, 0, 1, 0],
  132. vec![0, 0, 0, 0, 0, 1],
  133. vec![0, 0, 1, 0, 0, 0],
  134. ]);
  135. let z1 = to_F_vec::<Fr>(vec![1, 3, 35, 9, 27, 30]);
  136. let z2 = to_F_vec::<Fr>(vec![1, 4, 73, 16, 64, 68]);
  137. let relaxed_r1cs_1 = R1CS::<Fr> {
  138. A: A.clone(),
  139. B: B.clone(),
  140. C: C.clone(),
  141. }
  142. .relax();
  143. let relaxed_r1cs_2 = R1CS::<Fr> { A, B, C }.relax();
  144. let T = NIFS::<G1Affine>::comp_T(relaxed_r1cs_1, relaxed_r1cs_2, &z1, &z2);
  145. let params = Pedersen::<G1Affine>::new_params(&mut rng);
  146. let cmT = Pedersen::commit_vec(&mut rng, &params, &T);
  147. let r = Fr::rand(&mut rng); // this would come from the transcript
  148. // WIP TMP
  149. let fw1 = FWit::<G1Affine> {
  150. E: vec![Fr::zero(); T.len()],
  151. rE: Fr::zero(),
  152. W: z1,
  153. rW: Fr::zero(),
  154. };
  155. let fw2 = FWit::<G1Affine> {
  156. E: vec![Fr::zero(); T.len()],
  157. rE: Fr::zero(),
  158. W: z2,
  159. rW: Fr::zero(),
  160. };
  161. // fold witness
  162. let folded_witness = NIFS::<G1Affine>::fold_witness(r, &fw1, &fw2, T);
  163. let phi1 = fw1.commit(); // <- unimplemented
  164. let phi2 = fw2.commit();
  165. // fold instance
  166. let folded_instance = NIFS::<G1Affine>::fold_instance(r, phi1, phi2, cmT);
  167. // naive check r1cs of the folded witness
  168. // assert_eq!(hadamard_product(Az, Bz), vec_add(vector_elem_product(Cz, u), E));
  169. }
  170. }