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.

575 lines
21 KiB

  1. use ark_ec::{AffineRepr, CurveGroup, Group};
  2. use ark_ff::{BigInteger, Field, PrimeField, ToConstraintField};
  3. use ark_r1cs_std::{
  4. alloc::{AllocVar, AllocationMode},
  5. bits::uint8::UInt8,
  6. boolean::Boolean,
  7. eq::EqGadget,
  8. fields::{fp::FpVar, nonnative::NonNativeFieldVar, FieldVar},
  9. groups::GroupOpsBounds,
  10. prelude::CurveVar,
  11. R1CSVar,
  12. ToBitsGadget,
  13. ToBytesGadget,
  14. ToConstraintFieldGadget,
  15. // groups::curves::short_weierstrass::ProjectiveVar,
  16. };
  17. use ark_serialize::CanonicalSerialize;
  18. use ark_std::{One, Zero};
  19. // use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar;
  20. use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError};
  21. // use ark_crypto_primitives::crh::poseidon::{
  22. // constraints::{CRHGadget, CRHParametersVar},
  23. // CRH,
  24. // };
  25. // use ark_crypto_primitives::crh::{CRHScheme, CRHSchemeGadget};
  26. // use ark_crypto_primitives::snark::{FromFieldElementsGadget, SNARKGadget, SNARK};
  27. use ark_crypto_primitives::sponge::poseidon::{
  28. constraints::PoseidonSpongeVar, PoseidonConfig, PoseidonSponge,
  29. };
  30. use ark_crypto_primitives::sponge::{
  31. constraints::CryptographicSpongeVar, Absorb, CryptographicSponge,
  32. };
  33. use core::{borrow::Borrow, marker::PhantomData};
  34. use derivative::Derivative;
  35. use crate::nifs::Phi;
  36. pub type ConstraintF<C> = <<C as CurveGroup>::BaseField as Field>::BasePrimeField;
  37. #[derive(Debug, Derivative)]
  38. #[derivative(Clone(bound = "C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>"))]
  39. pub struct PhiVar<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>>
  40. where
  41. for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
  42. {
  43. _c: PhantomData<C>,
  44. cmE: GC,
  45. u: NonNativeFieldVar<C::ScalarField, ConstraintF<C>>,
  46. cmW: GC,
  47. x: NonNativeFieldVar<C::ScalarField, ConstraintF<C>>,
  48. }
  49. impl<C, GC> AllocVar<Phi<C>, ConstraintF<C>> for PhiVar<C, GC>
  50. where
  51. C: CurveGroup,
  52. GC: CurveVar<C, ConstraintF<C>>,
  53. for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
  54. {
  55. fn new_variable<T: Borrow<Phi<C>>>(
  56. cs: impl Into<Namespace<ConstraintF<C>>>,
  57. f: impl FnOnce() -> Result<T, SynthesisError>,
  58. mode: AllocationMode,
  59. ) -> Result<Self, SynthesisError> {
  60. f().and_then(|val| {
  61. let cs = cs.into();
  62. let u = NonNativeFieldVar::<C::ScalarField, ConstraintF<C>>::new_variable(
  63. cs.clone(),
  64. || Ok(val.borrow().u),
  65. mode,
  66. )?;
  67. let cmE = GC::new_variable(cs.clone(), || Ok(val.borrow().cmE.0), mode)?;
  68. let cmW = GC::new_variable(cs.clone(), || Ok(val.borrow().cmW.0), mode)?;
  69. let x = NonNativeFieldVar::<C::ScalarField, ConstraintF<C>>::new_variable(
  70. cs,
  71. || Ok(val.borrow().x),
  72. mode,
  73. )?;
  74. Ok(Self {
  75. _c: PhantomData,
  76. cmE,
  77. u,
  78. cmW,
  79. x,
  80. })
  81. })
  82. }
  83. }
  84. pub struct NIFSGadget<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>> {
  85. _c: PhantomData<C>,
  86. _gc: PhantomData<GC>,
  87. }
  88. impl<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>> NIFSGadget<C, GC>
  89. where
  90. C: CurveGroup,
  91. GC: CurveVar<C, ConstraintF<C>>,
  92. for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
  93. {
  94. // implements the constraints for NIFS.V
  95. pub fn verify(
  96. r: NonNativeFieldVar<C::ScalarField, ConstraintF<C>>,
  97. cmT: GC,
  98. phi1: PhiVar<C, GC>,
  99. phi2: PhiVar<C, GC>,
  100. phi3: PhiVar<C, GC>,
  101. ) -> Result<(), SynthesisError> {
  102. let r2 = r.square()?;
  103. phi3.cmE.enforce_equal(
  104. &(phi1.cmE
  105. + cmT.scalar_mul_le(r.to_bits_le()?.iter())?
  106. + phi2.cmE.scalar_mul_le(r2.to_bits_le()?.iter())?),
  107. )?;
  108. phi3.u.enforce_equal(&(phi1.u + r.clone() * phi2.u))?;
  109. phi3.cmW
  110. .enforce_equal(&(phi1.cmW + phi2.cmW.scalar_mul_le(r.to_bits_le()?.iter())?))?;
  111. phi3.x.enforce_equal(&(phi1.x + r * phi2.x))?;
  112. Ok(())
  113. }
  114. }
  115. pub trait FCircuit<F: PrimeField>: ConstraintSynthesizer<F> + Copy {
  116. // method that returns z_i (input), z_i1 (output)
  117. fn public(self) -> (F, F);
  118. }
  119. pub struct AugmentedFCircuit<
  120. C: CurveGroup,
  121. GC: CurveVar<C, ConstraintF<C>>,
  122. FC: FCircuit<ConstraintF<C>>,
  123. > where
  124. <<C as CurveGroup>::BaseField as Field>::BasePrimeField: Absorb,
  125. {
  126. pub _c: PhantomData<C>,
  127. pub _gc: PhantomData<GC>,
  128. // pub poseidon_native: PoseidonSponge<ConstraintF<C>>,
  129. pub poseidon_config: PoseidonConfig<ConstraintF<C>>,
  130. pub i: Option<C::BaseField>, // TODO rm Option in all params
  131. pub z_0: Option<C::BaseField>,
  132. pub z_i: Option<C::BaseField>,
  133. pub z_i1: Option<C::BaseField>, // z_{i+1}
  134. pub phi: Option<Phi<C>>, // phi_i in the paper sometimes appears as phi (φ_i) and others as 𝗎
  135. pub phiBig: Option<Phi<C>>, // ϕ_i
  136. pub phiBigOut: Option<Phi<C>>, // ϕ_{i+1}
  137. pub cmT: Option<C>,
  138. pub r: Option<C::ScalarField>, // This will not be an input and derived from a hash internally in the circuit (poseidon transcript)
  139. pub F: FC, // F circuit
  140. pub x: ConstraintF<C>, // pub input (φ_{i+1}.x)
  141. }
  142. impl<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>, FC: FCircuit<ConstraintF<C>>>
  143. ConstraintSynthesizer<ConstraintF<C>> for AugmentedFCircuit<C, GC, FC>
  144. where
  145. C: CurveGroup,
  146. GC: CurveVar<C, ConstraintF<C>>,
  147. for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
  148. <C as CurveGroup>::BaseField: PrimeField,
  149. <<C as CurveGroup>::BaseField as Field>::BasePrimeField: Absorb,
  150. {
  151. fn generate_constraints(
  152. self,
  153. cs: ConstraintSystemRef<ConstraintF<C>>,
  154. ) -> Result<(), SynthesisError> {
  155. let i = FpVar::<ConstraintF<C>>::new_input(cs.clone(), || Ok(self.i.unwrap()))?;
  156. let z_0 = FpVar::<ConstraintF<C>>::new_input(cs.clone(), || Ok(self.z_0.unwrap()))?;
  157. let z_i = FpVar::<ConstraintF<C>>::new_input(cs.clone(), || Ok(self.z_i.unwrap()))?;
  158. let z_i1 = FpVar::<ConstraintF<C>>::new_input(cs.clone(), || Ok(self.z_i1.unwrap()))?;
  159. let phi = PhiVar::<C, GC>::new_witness(cs.clone(), || Ok(self.phi.unwrap()))?;
  160. let phiBig = PhiVar::<C, GC>::new_witness(cs.clone(), || Ok(self.phiBig.unwrap()))?;
  161. let phiBigOut = PhiVar::<C, GC>::new_witness(cs.clone(), || Ok(self.phiBigOut.unwrap()))?;
  162. let cmT = GC::new_witness(cs.clone(), || Ok(self.cmT.unwrap()))?;
  163. let r =
  164. NonNativeFieldVar::<C::ScalarField, ConstraintF<C>>::new_witness(cs.clone(), || {
  165. Ok(self.r.unwrap())
  166. })?; // r will come from transcript
  167. let x = FpVar::<ConstraintF<C>>::new_input(cs.clone(), || Ok(self.x))?;
  168. // if i=0, output (φ_{i+1}.x), phiOut.x = H(vk_nifs, 1, z_0, z_i1, phi)
  169. let phiOut_x_first_iter = AugmentedFCircuit::<C, GC, FC>::phi_x_hash_var(
  170. cs.clone(),
  171. self.poseidon_config.clone(),
  172. FpVar::<ConstraintF<C>>::one(),
  173. z_0.clone(),
  174. z_i1.clone(),
  175. phiBigOut.clone(),
  176. )?;
  177. // TODO WIP: x is the output when i=0
  178. // 1. phi.x == H(vk_nifs, i, z_0, z_i, phiBig)
  179. let h = AugmentedFCircuit::<C, GC, FC>::phi_x_hash_var(
  180. cs.clone(),
  181. self.poseidon_config.clone(),
  182. i.clone(),
  183. z_0.clone(),
  184. z_i.clone(),
  185. phiBig.clone(),
  186. )?;
  187. // check that h == phi.x.
  188. // Note: phi.x is in ScalarField, while h is in ConstraintF (BaseField), that's why bytes
  189. // are used in the comparison.
  190. (phi.x.to_bytes()?).enforce_equal(&h.to_bytes()?)?; // TODO review
  191. // 2. phi.cmE==cm(0), phi.u==1
  192. // (phi.cmE.is_zero()?).enforce_equal(&Boolean::TRUE)?; // TODO not cmE=0, but check that cmE = cm(0)
  193. (phi.u.is_one()?).enforce_equal(&Boolean::TRUE)?;
  194. // 3. nifs.verify, checks that folding phi & phiBig obtains phiBigOut
  195. NIFSGadget::<C, GC>::verify(r, cmT, phi, phiBig, phiBigOut.clone())?;
  196. // 4. zksnark.V(vk_snark, phi_new, proof_phi)
  197. // 5. (φ_{i+1}.x) phiOut.x == H(i+1, z_0, z_i+1, phiBigOut)
  198. let phiOut_x = AugmentedFCircuit::<C, GC, FC>::phi_x_hash_var(
  199. cs.clone(),
  200. self.poseidon_config.clone(),
  201. i + FpVar::<ConstraintF<C>>::one(),
  202. z_0.clone(),
  203. z_i1.clone(),
  204. phiBigOut.clone(),
  205. )?; // WIP
  206. // check that inputed 'x' is equal to phiOut_x_first_iter or phiOut_x depending if we're at
  207. // i=0 or not.
  208. // if i==0: check x==phiOut_x_first_iter
  209. phiOut_x_first_iter.enforce_equal(&x)?;
  210. // else: check x==phiOut_x
  211. // WIP assert that z_i1 == F(z_i).z_i1
  212. self.F.generate_constraints(cs.clone())?;
  213. Ok(())
  214. }
  215. }
  216. impl<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>, FC: FCircuit<ConstraintF<C>>>
  217. AugmentedFCircuit<C, GC, FC>
  218. where
  219. C: CurveGroup,
  220. GC: CurveVar<C, ConstraintF<C>>,
  221. for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
  222. <<C as CurveGroup>::BaseField as Field>::BasePrimeField: Absorb,
  223. <C as CurveGroup>::BaseField: Absorb,
  224. {
  225. fn phi_x_hash_var(
  226. cs: ConstraintSystemRef<ConstraintF<C>>,
  227. poseidon_config: PoseidonConfig<ConstraintF<C>>,
  228. i: FpVar<ConstraintF<C>>,
  229. z_0: FpVar<ConstraintF<C>>,
  230. z_i: FpVar<ConstraintF<C>>,
  231. phi: PhiVar<C, GC>,
  232. ) -> Result<FpVar<ConstraintF<C>>, SynthesisError> {
  233. // note: this method can be optimized if instead of bytes representations we hash finite
  234. // field elements (in the constraint field)
  235. let mut sponge = PoseidonSpongeVar::<ConstraintF<C>>::new(cs.clone(), &poseidon_config);
  236. let input = vec![i, z_0, z_i];
  237. sponge.absorb(&input)?;
  238. let input: Vec<Vec<UInt8<ConstraintF<C>>>> = vec![phi.u.to_bytes()?, phi.x.to_bytes()?];
  239. sponge.absorb(&input)?;
  240. let input = vec![phi.cmE.to_bytes()?, phi.cmW.to_bytes()?];
  241. sponge.absorb(&input)?;
  242. let h = sponge.squeeze_field_elements(1).unwrap();
  243. Ok(h[0].clone())
  244. }
  245. fn phi_x_hash(
  246. poseidon_config: PoseidonConfig<ConstraintF<C>>,
  247. i: ConstraintF<C>,
  248. z_0: ConstraintF<C>,
  249. z_i: ConstraintF<C>,
  250. phi: Phi<C>,
  251. ) -> ConstraintF<C> {
  252. let mut sponge = PoseidonSponge::<ConstraintF<C>>::new(&poseidon_config);
  253. let input: Vec<ConstraintF<C>> = vec![i, z_0, z_i];
  254. sponge.absorb(&input);
  255. let input: Vec<Vec<u8>> = vec![
  256. phi.u.into_bigint().to_bytes_le(),
  257. phi.x.into_bigint().to_bytes_le(),
  258. ];
  259. sponge.absorb(&input);
  260. let cmE_bytes = Self::to_bytes_cs_compat(phi.cmE.0);
  261. let cmW_bytes = Self::to_bytes_cs_compat(phi.cmW.0);
  262. let input = vec![cmE_bytes, cmW_bytes];
  263. sponge.absorb(&input);
  264. let h = sponge.squeeze_field_elements(1);
  265. h[0]
  266. }
  267. fn to_bytes_cs_compat(c: C) -> Vec<u8> {
  268. // note: this method has been implemented to be compatible with the arkworks/r1cs-std
  269. // short_weierstrass/ProjectiveVar ToBytesGadget implementation, as the
  270. // arkworks/algebra/serialize/SWCurveConfig version is not compatible.
  271. let a = c.into_affine();
  272. let x = a.x().unwrap();
  273. let y = a.y().unwrap();
  274. let mut x_bytes = Vec::new();
  275. x.serialize_uncompressed(&mut x_bytes).unwrap();
  276. let mut y_bytes = Vec::new();
  277. y.serialize_uncompressed(&mut y_bytes).unwrap();
  278. x_bytes.append(&mut vec![0, 0]);
  279. y_bytes.append(&mut vec![0, 0]);
  280. x_bytes.append(&mut y_bytes);
  281. x_bytes.push(0);
  282. x_bytes
  283. }
  284. }
  285. //////////
  286. // pub struct Nova<MainField: PrimeField, SecondField: PrimeField, C1: CurveGroup, C2: CurveGroup> {}
  287. // pub trait SNARKs<MainField: PrimeField, SecondField: PrimeField> {
  288. // type AugmentedFunctionSNARK: SNARK<MainField>;
  289. // // type FunctionSNARK: ConstraintSynthesizer<Fr>; // F
  290. // type DummyStepSNARK: SNARK<SecondField>;
  291. //
  292. // type AugmentedFunctionCircuit: SNARKGadget<MainField, SecondField, Self::AugmentedFunctionSNARK>; // F'
  293. // type FunctionCircuit: ConstraintSynthesizer<MainField>; // F
  294. // type DummyStepCircuit: SNARKGadget<SecondField, MainField, Self::DummyStepSNARK>;
  295. // }
  296. // pub struct TS<
  297. // MainField: PrimeField,
  298. // SecondField: PrimeField,
  299. // Config: SNARKs<MainField, SecondField>,
  300. // > {
  301. // augmentedF_pk: <Config::AugmentedFunctionSNARK as SNARK<MainField>>::ProvingKey,
  302. // augmentedF_vk: <Config::AugmentedFunctionSNARK as SNARK<MainField>>::VerifyingKey,
  303. //
  304. // dummy_pk: <Config::DummyStepSNARK as SNARK<SecondField>>::ProvingKey,
  305. // dummy_vk: <Config::DummyStepSNARK as SNARK<SecondField>>::VerifyingKey,
  306. // }
  307. #[derive(Clone, Copy, Debug)]
  308. pub struct TestFCircuit<F: PrimeField> {
  309. z_i: F, // z_i
  310. z_i1: F, // z_{i+1}
  311. }
  312. impl<F: PrimeField> FCircuit<F> for TestFCircuit<F> {
  313. fn public(self) -> (F, F) {
  314. (self.z_i, self.z_i1)
  315. }
  316. }
  317. impl<F: PrimeField> ConstraintSynthesizer<F> for TestFCircuit<F> {
  318. fn generate_constraints(self, cs: ConstraintSystemRef<F>) -> Result<(), SynthesisError> {
  319. let z_i = FpVar::<F>::new_input(cs.clone(), || Ok(self.z_i))?;
  320. let z_i1 = FpVar::<F>::new_input(cs.clone(), || Ok(self.z_i1))?;
  321. let five = FpVar::<F>::new_constant(cs.clone(), F::from(5u32))?;
  322. let y = &z_i * &z_i * &z_i + &z_i + &five;
  323. y.enforce_equal(&z_i1)?;
  324. Ok(())
  325. }
  326. }
  327. #[cfg(test)]
  328. mod test {
  329. use super::*;
  330. use crate::transcript::Transcript;
  331. use ark_r1cs_std::R1CSVar;
  332. use ark_relations::r1cs::ConstraintSystem;
  333. use ark_std::UniformRand;
  334. use crate::nifs;
  335. use crate::pedersen;
  336. use crate::transcript::poseidon_test_config;
  337. use ark_ec::Group;
  338. // use ark_ed_on_mnt4_298::{constraints::EdwardsVar, EdwardsProjective};
  339. use crate::pedersen::Commitment;
  340. use ark_mnt4_298::{constraints::G1Var as MNT4G1Var, Fq, Fr, G1Projective as MNT4G1Projective};
  341. use ark_mnt6_298::{constraints::G1Var as MNT6G1Var, G1Projective as MNT6G1Projective};
  342. use ark_std::One;
  343. // mnt4's Fr is the Constraint Field,
  344. // while mnt4's Fq is the Field where we work, which is the C::ScalarField for C==MNT6G1
  345. #[test]
  346. fn test_phi_var() {
  347. let phi = Phi::<MNT6G1Projective> {
  348. cmE: Commitment(MNT6G1Projective::generator()),
  349. u: Fq::one(),
  350. cmW: Commitment(MNT6G1Projective::generator()),
  351. x: Fq::one(),
  352. };
  353. let cs = ConstraintSystem::<Fr>::new_ref();
  354. let _phiVar =
  355. PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi)).unwrap();
  356. // println!("num_constraints={:?}", cs.num_constraints());
  357. }
  358. #[test]
  359. fn test_phi_x_hash() {
  360. let mut rng = ark_std::test_rng();
  361. let poseidon_config = poseidon_test_config::<Fr>();
  362. let z_0 = Fr::from(0_u32);
  363. let z_i = Fr::from(3_u32);
  364. let phi = Phi::<MNT6G1Projective> {
  365. // cmE: Commitment(MNT6G1Projective::generator()),
  366. cmE: Commitment(MNT6G1Projective::rand(&mut rng)),
  367. u: Fq::one(),
  368. cmW: Commitment(MNT6G1Projective::generator()),
  369. x: Fq::one(),
  370. };
  371. let x = AugmentedFCircuit::<MNT6G1Projective, MNT6G1Var, TestFCircuit<Fr>>::phi_x_hash(
  372. poseidon_config.clone(),
  373. Fr::one(),
  374. z_0.clone(),
  375. z_i.clone(),
  376. phi.clone(),
  377. );
  378. let cs = ConstraintSystem::<Fr>::new_ref();
  379. let z_0Var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(z_0)).unwrap();
  380. let z_iVar = FpVar::<Fr>::new_witness(cs.clone(), || Ok(z_i)).unwrap();
  381. let phiVar =
  382. PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi)).unwrap();
  383. let xVar =
  384. AugmentedFCircuit::<MNT6G1Projective, MNT6G1Var, TestFCircuit<Fr>>::phi_x_hash_var(
  385. cs.clone(),
  386. poseidon_config.clone(),
  387. FpVar::<Fr>::one(),
  388. z_0Var,
  389. z_iVar,
  390. phiVar,
  391. )
  392. .unwrap();
  393. println!("num_constraints={:?}", cs.num_constraints());
  394. assert_eq!(x, xVar.value().unwrap());
  395. }
  396. #[test]
  397. fn test_nifs_gadget() {
  398. let mut rng = ark_std::test_rng();
  399. let pedersen_params = pedersen::Pedersen::<MNT6G1Projective>::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec
  400. let poseidon_config = poseidon_test_config::<Fq>();
  401. let cs = ConstraintSystem::<Fr>::new_ref();
  402. let (r1cs, ws, _) = nifs::gen_test_values::<Fq>(2);
  403. let (A, _, _) = (r1cs.A.clone(), r1cs.B.clone(), r1cs.C.clone());
  404. let r = Fq::rand(&mut rng); // this would come from the transcript
  405. let fw1 = nifs::FWit::<MNT6G1Projective>::new(ws[0].clone(), A.len());
  406. let fw2 = nifs::FWit::<MNT6G1Projective>::new(ws[1].clone(), A.len());
  407. let mut transcript_p = Transcript::<Fq, MNT6G1Projective>::new(&poseidon_config);
  408. let (_fw3, phi1, phi2, _T, cmT) = nifs::NIFS::<MNT6G1Projective>::P(
  409. &mut transcript_p,
  410. &pedersen_params,
  411. r,
  412. &r1cs,
  413. fw1,
  414. fw2,
  415. );
  416. let phi3 = nifs::NIFS::<MNT6G1Projective>::V(r, &phi1, &phi2, &cmT);
  417. let phi1Var =
  418. PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi1)).unwrap();
  419. let phi2Var =
  420. PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi2)).unwrap();
  421. let phi3Var =
  422. PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi3)).unwrap();
  423. let cmTVar = MNT6G1Var::new_witness(cs.clone(), || Ok(cmT.0)).unwrap();
  424. let rVar = NonNativeFieldVar::<Fq, Fr>::new_witness(cs.clone(), || Ok(r)).unwrap();
  425. NIFSGadget::<MNT6G1Projective, MNT6G1Var>::verify(rVar, cmTVar, phi1Var, phi2Var, phi3Var)
  426. .unwrap();
  427. // println!("num_constraints={:?}", cs.num_constraints());
  428. assert!(cs.is_satisfied().unwrap());
  429. }
  430. #[test]
  431. fn test_augmented_f_circuit() {
  432. let mut rng = ark_std::test_rng();
  433. let pedersen_params = pedersen::Pedersen::<MNT6G1Projective>::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec
  434. let poseidon_config_Fq = poseidon_test_config::<Fq>();
  435. let poseidon_config_Fr = poseidon_test_config::<Fr>();
  436. let cs = ConstraintSystem::<Fr>::new_ref();
  437. // note: gen_test_values ws is the F (internal) circuit witness only
  438. let (r1cs, ws, _) = nifs::gen_test_values::<Fq>(2);
  439. let A = r1cs.A.clone();
  440. let r = Fq::rand(&mut rng); // this would come from the transcript
  441. let fw1 = nifs::FWit::<MNT6G1Projective>::new(ws[0].clone(), A.len());
  442. let fw2 = nifs::FWit::<MNT6G1Projective>::new(ws[1].clone(), A.len());
  443. let mut transcript_p = Transcript::<Fq, MNT6G1Projective>::new(&poseidon_config_Fq);
  444. let (_fw3, mut phi1, phi2, _T, cmT) = nifs::NIFS::<MNT6G1Projective>::P(
  445. &mut transcript_p,
  446. &pedersen_params,
  447. r,
  448. &r1cs,
  449. fw1,
  450. fw2,
  451. );
  452. // println!("phi1 {:?}", phi1.cmE);
  453. let i = Fr::from(0_u32);
  454. let z_0 = Fr::from(0_u32);
  455. let z_i = Fr::from(3_u32);
  456. let z_i1 = Fr::from(35_u32);
  457. let test_F_circuit = TestFCircuit::<Fr> { z_i, z_i1 };
  458. // TODO maybe phi.x should be set from fw1 (few lines above)
  459. let phi1_x: Fr =
  460. AugmentedFCircuit::<MNT6G1Projective, MNT6G1Var, TestFCircuit<Fr>>::phi_x_hash(
  461. poseidon_config_Fr.clone(),
  462. i,
  463. z_0.clone(),
  464. z_i.clone(),
  465. phi2.clone(), // phiBig
  466. );
  467. phi1.x = Fq::from_le_bytes_mod_order(&phi1_x.into_bigint().to_bytes_le());
  468. // fold committed instance phi3
  469. let phi3 = nifs::NIFS::<MNT6G1Projective>::V(r, &phi1, &phi2, &cmT);
  470. let x = AugmentedFCircuit::<MNT6G1Projective, MNT6G1Var, TestFCircuit<Fr>>::phi_x_hash(
  471. poseidon_config_Fr.clone(),
  472. i + Fr::one(),
  473. z_0.clone(),
  474. z_i1.clone(),
  475. phi3.clone(),
  476. );
  477. let augmentedF = AugmentedFCircuit::<MNT6G1Projective, MNT6G1Var, TestFCircuit<Fr>> {
  478. _c: PhantomData,
  479. _gc: PhantomData,
  480. poseidon_config: poseidon_config_Fr.clone(),
  481. i: Some(i),
  482. z_0: Some(z_0),
  483. z_i: Some(z_i),
  484. z_i1: Some(z_i1),
  485. phi: Some(phi1),
  486. phiBig: Some(phi2),
  487. phiBigOut: Some(phi3.clone()),
  488. cmT: Some(cmT.0),
  489. r: Some(r),
  490. F: test_F_circuit,
  491. x,
  492. };
  493. augmentedF.generate_constraints(cs.clone()).unwrap();
  494. println!("num_constraints={:?}", cs.num_constraints());
  495. assert!(cs.is_satisfied().unwrap());
  496. }
  497. }