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.

314 lines
12 KiB

  1. use ark_ec::CurveGroup;
  2. use ark_ff::{Field, PrimeField};
  3. use ark_r1cs_std::{
  4. alloc::{AllocVar, AllocationMode},
  5. boolean::Boolean,
  6. eq::EqGadget,
  7. fields::{fp::FpVar, nonnative::NonNativeFieldVar, FieldVar},
  8. groups::GroupOpsBounds,
  9. prelude::CurveVar,
  10. ToBitsGadget,
  11. ToConstraintFieldGadget,
  12. // groups::curves::short_weierstrass::ProjectiveVar,
  13. };
  14. // use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar;
  15. use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError};
  16. // use ark_crypto_primitives::crh::poseidon::{
  17. // constraints::{CRHGadget, CRHParametersVar},
  18. // CRH,
  19. // };
  20. // use ark_crypto_primitives::crh::{CRHScheme, CRHSchemeGadget};
  21. // use ark_crypto_primitives::snark::{FromFieldElementsGadget, SNARKGadget, SNARK};
  22. use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar;
  23. use ark_crypto_primitives::sponge::poseidon::{
  24. constraints::PoseidonSpongeVar, PoseidonConfig, PoseidonSponge,
  25. };
  26. use core::{borrow::Borrow, marker::PhantomData};
  27. use derivative::Derivative;
  28. use crate::nifs::Phi;
  29. pub type ConstraintF<C> = <<C as CurveGroup>::BaseField as Field>::BasePrimeField;
  30. #[derive(Debug, Derivative)]
  31. #[derivative(Clone(bound = "C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>"))]
  32. pub struct PhiVar<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>>
  33. where
  34. for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
  35. {
  36. _c: PhantomData<C>,
  37. cmE: GC,
  38. u: NonNativeFieldVar<C::ScalarField, ConstraintF<C>>,
  39. cmW: GC,
  40. x: NonNativeFieldVar<C::ScalarField, ConstraintF<C>>,
  41. }
  42. impl<C, GC> AllocVar<Phi<C>, ConstraintF<C>> for PhiVar<C, GC>
  43. where
  44. C: CurveGroup,
  45. GC: CurveVar<C, ConstraintF<C>>,
  46. for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
  47. {
  48. fn new_variable<T: Borrow<Phi<C>>>(
  49. cs: impl Into<Namespace<ConstraintF<C>>>,
  50. f: impl FnOnce() -> Result<T, SynthesisError>,
  51. mode: AllocationMode,
  52. ) -> Result<Self, SynthesisError> {
  53. f().and_then(|val| {
  54. let cs = cs.into();
  55. let u = NonNativeFieldVar::<C::ScalarField, ConstraintF<C>>::new_variable(
  56. cs.clone(),
  57. || Ok(val.borrow().u),
  58. mode,
  59. )?;
  60. let cmE = GC::new_variable(cs.clone(), || Ok(val.borrow().cmE.0), mode)?;
  61. let cmW = GC::new_variable(cs.clone(), || Ok(val.borrow().cmW.0), mode)?;
  62. let x = NonNativeFieldVar::<C::ScalarField, ConstraintF<C>>::new_variable(
  63. cs,
  64. || Ok(val.borrow().x),
  65. mode,
  66. )?;
  67. Ok(Self {
  68. _c: PhantomData,
  69. cmE,
  70. u,
  71. cmW,
  72. x,
  73. })
  74. })
  75. }
  76. }
  77. pub struct NIFSGadget<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>> {
  78. _c: PhantomData<C>,
  79. _gc: PhantomData<GC>,
  80. }
  81. impl<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>> NIFSGadget<C, GC>
  82. where
  83. C: CurveGroup,
  84. GC: CurveVar<C, ConstraintF<C>>,
  85. for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
  86. {
  87. // implements the constraints for NIFS.V
  88. pub fn verify(
  89. r: NonNativeFieldVar<C::ScalarField, ConstraintF<C>>,
  90. cmT: GC,
  91. phi1: PhiVar<C, GC>,
  92. phi2: PhiVar<C, GC>,
  93. phi3: PhiVar<C, GC>,
  94. ) -> Result<(), SynthesisError> {
  95. let r2 = r.square()?;
  96. phi3.cmE.enforce_equal(
  97. &(phi1.cmE
  98. + cmT.scalar_mul_le(r.to_bits_le()?.iter())?
  99. + phi2.cmE.scalar_mul_le(r2.to_bits_le()?.iter())?),
  100. )?;
  101. phi3.u.enforce_equal(&(phi1.u + r.clone() * phi2.u))?;
  102. phi3.cmW
  103. .enforce_equal(&(phi1.cmW + phi2.cmW.scalar_mul_le(r.to_bits_le()?.iter())?))?;
  104. // wip x's check
  105. phi3.x.enforce_equal(&(phi1.x + r * phi2.x))?;
  106. Ok(())
  107. }
  108. }
  109. use ark_crypto_primitives::sponge::Absorb;
  110. pub struct AugmentedFCircuit<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>>
  111. where
  112. <<C as CurveGroup>::BaseField as Field>::BasePrimeField: Absorb,
  113. {
  114. pub _c: PhantomData<C>,
  115. pub _gc: PhantomData<GC>,
  116. // pub poseidon_native: PoseidonSponge<ConstraintF<C>>,
  117. pub poseidon_config: PoseidonConfig<ConstraintF<C>>,
  118. pub i: Option<C::BaseField>,
  119. pub z_0: Option<C::BaseField>,
  120. pub z_i: Option<C::BaseField>,
  121. pub z_i1: Option<C::BaseField>, // z_{i+1}
  122. pub phi: Option<Phi<C>>, // phi_i in the paper sometimes appears as phi (φ) and others as 𝗎
  123. pub phiBig: Option<Phi<C>>, // ϕ_i
  124. pub phiOut: Option<Phi<C>>, // ϕ_{i+1}
  125. pub cmT: Option<C>,
  126. pub r: Option<C::ScalarField>, // This will not be an input and derived from a hash internally in the circuit (poseidon transcript)
  127. }
  128. impl<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>> ConstraintSynthesizer<ConstraintF<C>>
  129. for AugmentedFCircuit<C, GC>
  130. where
  131. C: CurveGroup,
  132. GC: CurveVar<C, ConstraintF<C>>,
  133. for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
  134. <C as CurveGroup>::BaseField: PrimeField,
  135. <<C as CurveGroup>::BaseField as Field>::BasePrimeField: Absorb,
  136. {
  137. fn generate_constraints(
  138. self,
  139. cs: ConstraintSystemRef<ConstraintF<C>>,
  140. ) -> Result<(), SynthesisError> {
  141. let i = FpVar::<ConstraintF<C>>::new_witness(cs.clone(), || Ok(self.i.unwrap()))?;
  142. let z_0 = FpVar::<ConstraintF<C>>::new_witness(cs.clone(), || Ok(self.z_0.unwrap()))?;
  143. let z_i = FpVar::<ConstraintF<C>>::new_witness(cs.clone(), || Ok(self.z_i.unwrap()))?;
  144. let z_i1 = FpVar::<ConstraintF<C>>::new_witness(cs.clone(), || Ok(self.z_i1.unwrap()))?;
  145. let phi = PhiVar::<C, GC>::new_witness(cs.clone(), || Ok(self.phi.unwrap()))?;
  146. let phiBig = PhiVar::<C, GC>::new_witness(cs.clone(), || Ok(self.phiBig.unwrap()))?;
  147. let phiOut = PhiVar::<C, GC>::new_witness(cs.clone(), || Ok(self.phiOut.unwrap()))?;
  148. let cmT = GC::new_witness(cs.clone(), || Ok(self.cmT.unwrap()))?;
  149. let r =
  150. NonNativeFieldVar::<C::ScalarField, ConstraintF<C>>::new_witness(cs.clone(), || {
  151. Ok(self.r.unwrap())
  152. })?; // r will come from transcript
  153. // 1. phi.x == H(vk_nifs, i, z_0, z_i, phiBig)
  154. let mut sponge =
  155. PoseidonSpongeVar::<ConstraintF<C>>::new(cs.clone(), &self.poseidon_config);
  156. let input = vec![i.clone(), z_0.clone(), z_i.clone()];
  157. sponge.absorb(&input)?;
  158. let input = vec![
  159. phiBig.u.to_constraint_field()?,
  160. phiBig.x.to_constraint_field()?,
  161. ];
  162. sponge.absorb(&input)?;
  163. let input = vec![phiBig.cmE.to_bytes()?, phiBig.cmW.to_bytes()?];
  164. sponge.absorb(&input)?;
  165. let h = sponge.squeeze_field_elements(1).unwrap();
  166. let x_CF = phi.x.to_constraint_field()?; // phi.x on the ConstraintF<C>
  167. x_CF[0].enforce_equal(&h[0])?; // review
  168. // 2. phi.cmE==0, phi.u==1
  169. (phi.cmE.is_zero()?).enforce_equal(&Boolean::TRUE)?;
  170. (phi.u.is_one()?).enforce_equal(&Boolean::TRUE)?;
  171. // 3. nifs.verify, checks that folding phi & phiBig obtains phiOut
  172. NIFSGadget::<C, GC>::verify(r, cmT, phi, phiBig, phiOut.clone())?;
  173. // 4. zksnark.V(vk_snark, phi_new, proof_phi)
  174. // 5. phiOut.x == H(i+1, z_0, z_i+1, phiOut)
  175. // WIP
  176. let mut sponge = PoseidonSpongeVar::<ConstraintF<C>>::new(cs, &self.poseidon_config);
  177. let input = vec![i + FpVar::<ConstraintF<C>>::one(), z_0, z_i1];
  178. sponge.absorb(&input)?;
  179. let input = vec![phiOut.cmE.to_bytes()?, phiOut.cmW.to_bytes()?];
  180. sponge.absorb(&input)?;
  181. let h = sponge.squeeze_field_elements(1).unwrap();
  182. let x_CF = phiOut.x.to_constraint_field()?; // phi.x on the ConstraintF<C>
  183. x_CF[0].enforce_equal(&h[0])?; // review
  184. Ok(())
  185. }
  186. }
  187. //////////
  188. // pub struct Nova<MainField: PrimeField, SecondField: PrimeField, C1: CurveGroup, C2: CurveGroup> {}
  189. // pub trait SNARKs<MainField: PrimeField, SecondField: PrimeField> {
  190. // type AugmentedFunctionSNARK: SNARK<MainField>;
  191. // // type FunctionSNARK: ConstraintSynthesizer<Fr>; // F
  192. // type DummyStepSNARK: SNARK<SecondField>;
  193. //
  194. // type AugmentedFunctionCircuit: SNARKGadget<MainField, SecondField, Self::AugmentedFunctionSNARK>; // F'
  195. // type FunctionCircuit: ConstraintSynthesizer<MainField>; // F
  196. // type DummyStepCircuit: SNARKGadget<SecondField, MainField, Self::DummyStepSNARK>;
  197. // }
  198. // pub struct TS<
  199. // MainField: PrimeField,
  200. // SecondField: PrimeField,
  201. // Config: SNARKs<MainField, SecondField>,
  202. // > {
  203. // augmentedF_pk: <Config::AugmentedFunctionSNARK as SNARK<MainField>>::ProvingKey,
  204. // augmentedF_vk: <Config::AugmentedFunctionSNARK as SNARK<MainField>>::VerifyingKey,
  205. //
  206. // dummy_pk: <Config::DummyStepSNARK as SNARK<SecondField>>::ProvingKey,
  207. // dummy_vk: <Config::DummyStepSNARK as SNARK<SecondField>>::VerifyingKey,
  208. // }
  209. #[cfg(test)]
  210. mod test {
  211. use super::*;
  212. use crate::transcript::Transcript;
  213. use ark_relations::r1cs::ConstraintSystem;
  214. use ark_std::UniformRand;
  215. use crate::nifs;
  216. use crate::pedersen;
  217. use crate::transcript::poseidon_test_config;
  218. use ark_ec::Group;
  219. // use ark_ed_on_mnt4_298::{constraints::EdwardsVar, EdwardsProjective};
  220. use crate::pedersen::Commitment;
  221. // use ark_mnt4_298::{constraints::G1Var as MNT4G1Var, G1Projective as MNT4G1Projective}
  222. use ark_mnt4_298::{Fq, Fr};
  223. use ark_mnt6_298::{constraints::G1Var as MNT6G1Var, G1Projective as MNT6G1Projective};
  224. use ark_std::One;
  225. // mnt4's Fr is the Constraint Field,
  226. // while mnt4's Fq is the Field where we work, which is the C::ScalarField for C==MNT6G1
  227. #[test]
  228. fn test_phi_var() {
  229. let phi = Phi::<MNT6G1Projective> {
  230. cmE: Commitment(MNT6G1Projective::generator()),
  231. u: Fq::one(),
  232. cmW: Commitment(MNT6G1Projective::generator()),
  233. x: Fq::one(),
  234. };
  235. let cs = ConstraintSystem::<Fr>::new_ref();
  236. let _phiVar =
  237. PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi)).unwrap();
  238. // println!("num_constraints={:?}", cs.num_constraints());
  239. }
  240. #[test]
  241. fn test_nifs_gadget() {
  242. let mut rng = ark_std::test_rng();
  243. let pedersen_params = pedersen::Pedersen::<MNT6G1Projective>::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec
  244. let poseidon_config = poseidon_test_config::<Fq>();
  245. let cs = ConstraintSystem::<Fr>::new_ref();
  246. let (r1cs, ws, _) = nifs::gen_test_values::<Fq>(2);
  247. let (A, _, _) = (r1cs.A.clone(), r1cs.B.clone(), r1cs.C.clone());
  248. let r = Fq::rand(&mut rng); // this would come from the transcript
  249. let fw1 = nifs::FWit::<MNT6G1Projective>::new(ws[0].clone(), A.len());
  250. let fw2 = nifs::FWit::<MNT6G1Projective>::new(ws[1].clone(), A.len());
  251. let mut transcript_p = Transcript::<Fq, MNT6G1Projective>::new(&poseidon_config);
  252. let (_fw3, phi1, phi2, _T, cmT) = nifs::NIFS::<MNT6G1Projective>::P(
  253. &mut transcript_p,
  254. &pedersen_params,
  255. r,
  256. &r1cs,
  257. fw1,
  258. fw2,
  259. );
  260. let phi3 = nifs::NIFS::<MNT6G1Projective>::V(r, &phi1, &phi2, &cmT);
  261. let phi1Var =
  262. PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi1)).unwrap();
  263. let phi2Var =
  264. PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi2)).unwrap();
  265. let phi3Var =
  266. PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi3)).unwrap();
  267. let cmTVar = MNT6G1Var::new_witness(cs.clone(), || Ok(cmT.0)).unwrap();
  268. let rVar = NonNativeFieldVar::<Fq, Fr>::new_witness(cs.clone(), || Ok(r)).unwrap();
  269. NIFSGadget::<MNT6G1Projective, MNT6G1Var>::verify(rVar, cmTVar, phi1Var, phi2Var, phi3Var)
  270. .unwrap();
  271. // println!("num_constraints={:?}", cs.num_constraints());
  272. }
  273. }