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.

237 lines
7.0 KiB

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