Prepare Zexe for recursion (#241) Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
jump to
@@ -5,9 +5,9 @@
use crate::nizk::NIZK; pub trait NIZKVerifierGadget<N: NIZK, ConstraintF: Field> { + type PreparedVerificationKeyGadget; type VerificationKeyGadget: AllocGadget<N::VerificationParameters, ConstraintF> + ToBytesGadget<ConstraintF>; - type ProofGadget: AllocGadget<N::Proof, ConstraintF>; fn check_verify<'a, CS, I, T>(@@ -24,6 +24,18 @@
fn conditional_check_verify<'a, CS, I, T>( cs: CS, verification_key: &Self::VerificationKeyGadget, + input: I, + proof: &Self::ProofGadget, + condition: &Boolean, + ) -> Result<(), SynthesisError> + where + CS: ConstraintSystem<ConstraintF>, + I: Iterator<Item = &'a T>, + T: 'a + ToBitsGadget<ConstraintF> + ?Sized; + + fn conditional_check_verify_prepared<'a, CS, I, T>( + cs: CS, + prepared_verification_key: &Self::PreparedVerificationKeyGadget, input: I, proof: &Self::ProofGadget, condition: &Boolean,
@@ -7,7 +7,7 @@ use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
use r1cs_std::prelude::*; use core::{borrow::Borrow, marker::PhantomData}; -use gm17::{Proof, VerifyingKey}; +use gm17::{PreparedVerifyingKey, Proof, VerifyingKey}; #[derive(Derivative)] #[derivative(Clone(bound = "P::G1Gadget: Clone, P::G2Gadget: Clone"))]@@ -105,6 +105,7 @@ C: ConstraintSynthesizer<PairingE::Fr>,
V: ToConstraintField<PairingE::Fr>, P: PairingGadget<PairingE, ConstraintF>, { + type PreparedVerificationKeyGadget = PreparedVerifyingKeyGadget<PairingE, ConstraintF, P>; type VerificationKeyGadget = VerifyingKeyGadget<PairingE, ConstraintF, P>; type ProofGadget = ProofGadget<PairingE, ConstraintF, P>;@@ -131,6 +132,22 @@
fn conditional_check_verify<'a, CS, I, T>( mut cs: CS, vk: &Self::VerificationKeyGadget, + public_inputs: I, + proof: &Self::ProofGadget, + condition: &Boolean, + ) -> Result<(), SynthesisError> + where + CS: ConstraintSystem<ConstraintF>, + I: Iterator<Item = &'a T>, + T: 'a + ToBitsGadget<ConstraintF> + ?Sized, + { + let pvk = vk.prepare(&mut cs.ns(|| "Prepare vk"))?; + <Self as NIZKVerifierGadget<Gm17<PairingE, C, V>, ConstraintF>>::conditional_check_verify_prepared(cs, &pvk, public_inputs, proof, condition) + } + + fn conditional_check_verify_prepared<'a, CS, I, T>( + mut cs: CS, + pvk: &Self::PreparedVerificationKeyGadget, mut public_inputs: I, proof: &Self::ProofGadget, condition: &Boolean,@@ -140,10 +157,9 @@ CS: ConstraintSystem<ConstraintF>,
I: Iterator<Item = &'a T>, T: 'a + ToBitsGadget<ConstraintF> + ?Sized, { - let pvk = vk.prepare(&mut cs.ns(|| "Prepare vk"))?; + let pvk = pvk.clone(); // e(A*G^{alpha}, B*H^{beta}) = e(G^{alpha}, H^{beta}) * e(G^{psi}, H^{gamma}) * // e(C, H) where psi = \sum_{i=0}^l input_i pvk.query[i] - let g_psi = { let mut cs = cs.ns(|| "Process input"); let mut g_psi = pvk.query[0].clone();@@ -213,6 +229,148 @@ let one = P::GTGadget::one(cs.ns(|| "GT One"))?;
test1.conditional_enforce_equal(cs.ns(|| "Test 1"), &one, condition)?; test2.conditional_enforce_equal(cs.ns(|| "Test 2"), &one, condition)?; Ok(()) + } +} + +impl<PairingE, ConstraintF, P> AllocGadget<PreparedVerifyingKey<PairingE>, ConstraintF> + for PreparedVerifyingKeyGadget<PairingE, ConstraintF, P> +where + PairingE: PairingEngine, + ConstraintF: Field, + P: PairingGadget<PairingE, ConstraintF>, + P::G1PreparedGadget: AllocGadget<PairingE::G1Prepared, ConstraintF>, + P::G2PreparedGadget: AllocGadget<PairingE::G2Prepared, ConstraintF>, +{ + #[inline] + fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>( + mut cs: CS, + val: T, + ) -> Result<Self, SynthesisError> + where + T: Borrow<PreparedVerifyingKey<PairingE>>, + { + let pvk = val.borrow().clone(); + + let g_alpha = + P::G1Gadget::alloc_constant(cs.ns(|| "g_alpha"), pvk.g_alpha.into_projective())?; + let h_beta = P::G2Gadget::alloc_constant(cs.ns(|| "h_beta"), pvk.h_beta.into_projective())?; + let g_alpha_pc = + P::G1PreparedGadget::alloc_constant(cs.ns(|| "g_alpha_pc"), pvk.g_alpha.into())?; + let h_beta_pc = + P::G2PreparedGadget::alloc_constant(cs.ns(|| "h_beta_pc"), pvk.h_beta.into())?; + let g_gamma_pc = + P::G1PreparedGadget::alloc_constant(cs.ns(|| "g_gamma_pc"), pvk.g_gamma_pc)?; + let h_gamma_pc = + P::G2PreparedGadget::alloc_constant(cs.ns(|| "h_gamma_pc"), pvk.h_gamma_pc)?; + let h_pc = P::G2PreparedGadget::alloc_constant(cs.ns(|| "h_pc"), pvk.h_pc)?; + + let mut query = Vec::<P::G1Gadget>::new(); + for (i, item) in pvk.query.iter().enumerate() { + query.push(P::G1Gadget::alloc_constant( + &mut cs.ns(|| format!("query_{}", i)), + item.borrow().into_projective(), + )?); + } + + Ok(Self { + g_alpha, + h_beta, + g_alpha_pc, + h_beta_pc, + g_gamma_pc, + h_gamma_pc, + h_pc, + query, + }) + } + + #[inline] + fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>( + mut cs: CS, + value_gen: FN, + ) -> Result<Self, SynthesisError> + where + FN: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<PreparedVerifyingKey<PairingE>>, + { + let pvk = value_gen()?.borrow().clone(); + + let g_alpha = + P::G1Gadget::alloc(cs.ns(|| "g_alpha"), || Ok(pvk.g_alpha.into_projective()))?; + let h_beta = P::G2Gadget::alloc(cs.ns(|| "h_beta"), || Ok(pvk.h_beta.into_projective()))?; + let g_alpha_pc = + P::G1PreparedGadget::alloc(cs.ns(|| "g_alpha_pc"), || Ok(pvk.g_alpha.into()))?; + let h_beta_pc = + P::G2PreparedGadget::alloc(cs.ns(|| "h_beta_pc"), || Ok(pvk.h_beta.into()))?; + let g_gamma_pc = + P::G1PreparedGadget::alloc(cs.ns(|| "g_gamma_pc"), || Ok(&pvk.g_gamma_pc))?; + let h_gamma_pc = + P::G2PreparedGadget::alloc(cs.ns(|| "h_gamma_pc"), || Ok(&pvk.h_gamma_pc))?; + let h_pc = P::G2PreparedGadget::alloc(cs.ns(|| "h_pc"), || Ok(&pvk.h_pc))?; + + let mut query = Vec::<P::G1Gadget>::new(); + for (i, item) in pvk.query.iter().enumerate() { + query.push(P::G1Gadget::alloc( + cs.ns(|| format!("query_{}", i)), + || Ok(item.borrow().into_projective()), + )?); + } + + Ok(Self { + g_alpha, + h_beta, + g_alpha_pc, + h_beta_pc, + g_gamma_pc, + h_gamma_pc, + h_pc, + query, + }) + } + + #[inline] + fn alloc_input<FN, T, CS: ConstraintSystem<ConstraintF>>( + mut cs: CS, + value_gen: FN, + ) -> Result<Self, SynthesisError> + where + FN: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<PreparedVerifyingKey<PairingE>>, + { + let pvk = value_gen()?.borrow().clone(); + + let g_alpha = + P::G1Gadget::alloc_input(cs.ns(|| "g_alpha"), || Ok(pvk.g_alpha.into_projective()))?; + let h_beta = + P::G2Gadget::alloc_input(cs.ns(|| "h_beta"), || Ok(pvk.h_beta.into_projective()))?; + let g_alpha_pc = + P::G1PreparedGadget::alloc_input(cs.ns(|| "g_alpha_pc"), || Ok(pvk.g_alpha.into()))?; + let h_beta_pc = + P::G2PreparedGadget::alloc_input(cs.ns(|| "h_beta_pc"), || Ok(pvk.h_beta.into()))?; + let g_gamma_pc = + P::G1PreparedGadget::alloc_input(cs.ns(|| "g_gamma_pc"), || Ok(&pvk.g_gamma_pc))?; + let h_gamma_pc = + P::G2PreparedGadget::alloc_input(cs.ns(|| "h_gamma_pc"), || Ok(&pvk.h_gamma_pc))?; + let h_pc = P::G2PreparedGadget::alloc_input(cs.ns(|| "h_pc"), || Ok(&pvk.h_pc))?; + + let mut query = Vec::<P::G1Gadget>::new(); + for (i, item) in pvk.query.iter().enumerate() { + query.push(P::G1Gadget::alloc_input( + &mut cs.ns(|| format!("query_{}", i)), + || Ok(item.borrow().into_projective()), + )?); + } + + Ok(Self { + g_alpha, + h_beta, + g_alpha_pc, + h_beta_pc, + g_gamma_pc, + h_gamma_pc, + h_pc, + query, + }) } }
@@ -7,7 +7,7 @@ use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
use r1cs_std::prelude::*; use core::{borrow::Borrow, marker::PhantomData}; -use groth16::{Proof, VerifyingKey}; +use groth16::{PreparedVerifyingKey, Proof, VerifyingKey}; #[derive(Derivative)] #[derivative(Clone(bound = "P::G1Gadget: Clone, P::G2Gadget: Clone"))]@@ -106,6 +106,7 @@ C: ConstraintSynthesizer<PairingE::Fr>,
V: ToConstraintField<PairingE::Fr>, P: PairingGadget<PairingE, ConstraintF>, { + type PreparedVerificationKeyGadget = PreparedVerifyingKeyGadget<PairingE, ConstraintF, P>; type VerificationKeyGadget = VerifyingKeyGadget<PairingE, ConstraintF, P>; type ProofGadget = ProofGadget<PairingE, ConstraintF, P>;@@ -132,6 +133,22 @@
fn conditional_check_verify<'a, CS, I, T>( mut cs: CS, vk: &Self::VerificationKeyGadget, + public_inputs: I, + proof: &Self::ProofGadget, + condition: &Boolean, + ) -> Result<(), SynthesisError> + where + CS: ConstraintSystem<ConstraintF>, + I: Iterator<Item = &'a T>, + T: 'a + ToBitsGadget<ConstraintF> + ?Sized, + { + let pvk = vk.prepare(&mut cs.ns(|| "Prepare vk"))?; + <Self as NIZKVerifierGadget<Groth16<PairingE, C, V>, ConstraintF>>::conditional_check_verify_prepared(cs, &pvk, public_inputs, proof, condition) + } + + fn conditional_check_verify_prepared<'a, CS, I, T>( + mut cs: CS, + pvk: &Self::PreparedVerificationKeyGadget, mut public_inputs: I, proof: &Self::ProofGadget, condition: &Boolean,@@ -141,7 +158,7 @@ CS: ConstraintSystem<ConstraintF>,
I: Iterator<Item = &'a T>, T: 'a + ToBitsGadget<ConstraintF> + ?Sized, { - let pvk = vk.prepare(&mut cs.ns(|| "Prepare vk"))?; + let pvk = pvk.clone(); let g_ic = { let mut cs = cs.ns(|| "Process input");@@ -184,6 +201,123 @@ let test = P::final_exponentiation(cs.ns(|| "Final Exp"), &test_exp).unwrap();
test.conditional_enforce_equal(cs.ns(|| "Test 1"), &pvk.alpha_g1_beta_g2, condition)?; Ok(()) + } +} + +impl<PairingE, ConstraintF, P> AllocGadget<PreparedVerifyingKey<PairingE>, ConstraintF> + for PreparedVerifyingKeyGadget<PairingE, ConstraintF, P> +where + PairingE: PairingEngine, + ConstraintF: Field, + P: PairingGadget<PairingE, ConstraintF>, + P::G2PreparedGadget: AllocGadget<PairingE::G2Prepared, ConstraintF>, +{ + fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>( + mut cs: CS, + val: T, + ) -> Result<Self, SynthesisError> + where + T: Borrow<PreparedVerifyingKey<PairingE>>, + { + let pvk = val.borrow().clone(); + + let alpha_g1_beta_g2 = + P::GTGadget::alloc_constant(cs.ns(|| "alpha_g1_beta_g2"), pvk.alpha_g1_beta_g2)?; + + let gamma_g2_neg_pc = + P::G2PreparedGadget::alloc_constant(cs.ns(|| "gamma_g2_neg_pc"), pvk.gamma_g2_neg_pc)?; + + let delta_g2_neg_pc = + P::G2PreparedGadget::alloc_constant(cs.ns(|| "delta_g2_neg_pc"), pvk.delta_g2_neg_pc)?; + + let mut gamma_abc_g1 = Vec::<P::G1Gadget>::new(); + for (i, item) in pvk.gamma_abc_g1.iter().enumerate() { + gamma_abc_g1.push(P::G1Gadget::alloc_constant( + cs.ns(|| format!("query_{}", i)), + item.borrow().into_projective(), + )?); + } + + Ok(Self { + alpha_g1_beta_g2, + gamma_g2_neg_pc, + delta_g2_neg_pc, + gamma_abc_g1, + }) + } + + fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( + mut cs: CS, + f: F, + ) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<PreparedVerifyingKey<PairingE>>, + { + let pvk = f()?.borrow().clone(); + + let alpha_g1_beta_g2 = + P::GTGadget::alloc(cs.ns(|| "alpha_g1_beta_g2"), || Ok(pvk.alpha_g1_beta_g2))?; + + let gamma_g2_neg_pc = + P::G2PreparedGadget::alloc(cs.ns(|| "gamma_g2_neg_pc"), || Ok(&pvk.gamma_g2_neg_pc))?; + + let delta_g2_neg_pc = + P::G2PreparedGadget::alloc(cs.ns(|| "delta_g2_neg_pc"), || Ok(&pvk.delta_g2_neg_pc))?; + + let mut gamma_abc_g1 = Vec::<P::G1Gadget>::new(); + for (i, item) in pvk.gamma_abc_g1.iter().enumerate() { + gamma_abc_g1.push(P::G1Gadget::alloc( + cs.ns(|| format!("query_{}", i)), + || Ok(item.borrow().into_projective()), + )?); + } + + Ok(Self { + alpha_g1_beta_g2, + gamma_g2_neg_pc, + delta_g2_neg_pc, + gamma_abc_g1, + }) + } + + fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>( + mut cs: CS, + f: F, + ) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<PreparedVerifyingKey<PairingE>>, + { + let pvk = f()?.borrow().clone(); + + let alpha_g1_beta_g2 = + P::GTGadget::alloc_input(cs.ns(|| "alpha_g1_beta_g2"), || Ok(pvk.alpha_g1_beta_g2))?; + + let gamma_g2_neg_pc = + P::G2PreparedGadget::alloc_input(cs.ns(|| "gamma_g2_neg_pc"), || { + Ok(&pvk.gamma_g2_neg_pc) + })?; + + let delta_g2_neg_pc = + P::G2PreparedGadget::alloc_input(cs.ns(|| "delta_g2_neg_pc"), || { + Ok(&pvk.delta_g2_neg_pc) + })?; + + let mut gamma_abc_g1 = Vec::<P::G1Gadget>::new(); + for (i, item) in pvk.gamma_abc_g1.iter().enumerate() { + gamma_abc_g1.push(P::G1Gadget::alloc_input( + cs.ns(|| format!("query_{}", i)), + || Ok(item.borrow().into_projective()), + )?); + } + + Ok(Self { + alpha_g1_beta_g2, + gamma_g2_neg_pc, + delta_g2_neg_pc, + gamma_abc_g1, + }) } }
@@ -852,6 +852,63 @@ Ok(vec![byte])
} } +impl<ConstraintF: PrimeField> ToConstraintFieldGadget<ConstraintF> for Boolean { + fn to_constraint_field<CS: ConstraintSystem<ConstraintF>>( + &self, + mut cs: CS, + ) -> Result<Vec<FpGadget<ConstraintF>>, SynthesisError> { + let gadget = match self { + Boolean::Constant(cond) => { + if *cond { + FpGadget::one(&mut cs.ns(|| "one"))? + } else { + FpGadget::zero(&mut cs.ns(|| "zero"))? + } + } + Boolean::Is(allocated_bit) => { + let value = match self.get_value() { + None => None, + Some(bool) => { + if bool { + Some(ConstraintF::one()) + } else { + Some(ConstraintF::zero()) + } + } + }; + + FpGadget::<ConstraintF> { + value, + variable: ConstraintVar::Var(allocated_bit.get_variable()), + } + } + Boolean::Not(allocated_bit) => { + let value = match self.get_value() { + None => None, + Some(bool) => { + if bool { + Some(ConstraintF::zero()) + } else { + Some(ConstraintF::one()) + } + } + }; + + let mut lc = LinearCombination::<ConstraintF>::zero(); + lc += (ConstraintF::one(), CS::one()); + lc += (-ConstraintF::one(), allocated_bit.get_variable()); + + FpGadget::<ConstraintF> { + value, + variable: ConstraintVar::LC(lc), + } + } + }; + + Ok(vec![gadget]) + } +} + impl<ConstraintF: PrimeField> CondSelectGadget<ConstraintF> for Boolean { fn conditionally_select<CS>( mut cs: CS,
@@ -14,7 +14,7 @@ #[derive(Clone, Debug)]
pub struct UInt32 { // Least significant bit_gadget first bits: Vec<Boolean>, - value: Option<u32>, + pub value: Option<u32>, } impl UInt32 {
@@ -40,6 +40,15 @@ }
} } +impl<F: PrimeField> ToConstraintFieldGadget<F> for FpGadget<F> { + fn to_constraint_field<CS: ConstraintSystem<F>>( + &self, + _cs: CS, + ) -> Result<Vec<FpGadget<F>>, SynthesisError> { + Ok(vec![self.clone()]) + } +} + impl<F: PrimeField> FieldGadget<F, F> for FpGadget<F> { type Variable = ConstraintVar<F>;
@@ -37,6 +37,27 @@ #[derivative(Debug = "ignore")]
_params: PhantomData<P>, } +impl<P, ConstraintF: PrimeField> ToConstraintFieldGadget<ConstraintF> for Fp12Gadget<P, ConstraintF> +where + P: Fp12Parameters, + <P::Fp6Params as Fp6Parameters>::Fp2Params: Fp2Parameters<Fp = ConstraintF>, +{ + fn to_constraint_field<CS: ConstraintSystem<ConstraintF>>( + &self, + mut cs: CS, + ) -> Result<Vec<FpGadget<ConstraintF>>, SynthesisError> { + let mut res = Vec::new(); + + let mut c0_gadget = self.c0.to_constraint_field(&mut cs.ns(|| "c0"))?; + let mut c1_gadget = self.c1.to_constraint_field(&mut cs.ns(|| "c1"))?; + + res.append(&mut c0_gadget); + res.append(&mut c1_gadget); + + Ok(res) + } +} + impl<P, ConstraintF: PrimeField> Fp12Gadget<P, ConstraintF> where P: Fp12Parameters,
@@ -17,6 +17,25 @@ #[derivative(Debug = "ignore")]
_params: PhantomData<P>, } +impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> + ToConstraintFieldGadget<ConstraintF> for Fp2Gadget<P, ConstraintF> +{ + fn to_constraint_field<CS: ConstraintSystem<ConstraintF>>( + &self, + mut cs: CS, + ) -> Result<Vec<FpGadget<ConstraintF>>, SynthesisError> { + let mut res = Vec::new(); + + let mut c0_gadget = self.c0.to_constraint_field(&mut cs.ns(|| "c0"))?; + let mut c1_gadget = self.c1.to_constraint_field(&mut cs.ns(|| "c1"))?; + + res.append(&mut c0_gadget); + res.append(&mut c1_gadget); + + Ok(res) + } +} + impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> Fp2Gadget<P, ConstraintF> { pub fn new(c0: FpGadget<ConstraintF>, c1: FpGadget<ConstraintF>) -> Self { Self {
@@ -22,6 +22,27 @@ _params: PhantomData<P>,
} impl<P: Fp3Parameters<Fp = ConstraintF>, ConstraintF: PrimeField + SquareRootField> + ToConstraintFieldGadget<ConstraintF> for Fp3Gadget<P, ConstraintF> +{ + fn to_constraint_field<CS: ConstraintSystem<ConstraintF>>( + &self, + mut cs: CS, + ) -> Result<Vec<FpGadget<ConstraintF>>, SynthesisError> { + let mut res = Vec::new(); + + let mut c0_gadget = self.c0.to_constraint_field(&mut cs.ns(|| "c0"))?; + let mut c1_gadget = self.c1.to_constraint_field(&mut cs.ns(|| "c1"))?; + let mut c2_gadget = self.c2.to_constraint_field(&mut cs.ns(|| "c2"))?; + + res.append(&mut c0_gadget); + res.append(&mut c1_gadget); + res.append(&mut c2_gadget); + + Ok(res) + } +} + +impl<P: Fp3Parameters<Fp = ConstraintF>, ConstraintF: PrimeField + SquareRootField> Fp3Gadget<P, ConstraintF> { #[inline]
@@ -28,6 +28,27 @@ #[derivative(Debug = "ignore")]
_params: PhantomData<P>, } +impl<P, ConstraintF: PrimeField> ToConstraintFieldGadget<ConstraintF> for Fp4Gadget<P, ConstraintF> +where + P: Fp4Parameters, + P::Fp2Params: Fp2Parameters<Fp = ConstraintF>, +{ + fn to_constraint_field<CS: ConstraintSystem<ConstraintF>>( + &self, + mut cs: CS, + ) -> Result<Vec<FpGadget<ConstraintF>>, SynthesisError> { + let mut res = Vec::new(); + + let mut c0_gadget = self.c0.to_constraint_field(&mut cs.ns(|| "c0"))?; + let mut c1_gadget = self.c1.to_constraint_field(&mut cs.ns(|| "c1"))?; + + res.append(&mut c0_gadget); + res.append(&mut c1_gadget); + + Ok(res) + } +} + impl<P, ConstraintF: PrimeField> Fp4Gadget<P, ConstraintF> where P: Fp4Parameters,
@@ -31,6 +31,28 @@ #[derivative(Debug = "ignore")]
_params: PhantomData<P>, } +impl<P, ConstraintF: PrimeField + SquareRootField> ToConstraintFieldGadget<ConstraintF> + for Fp6Gadget<P, ConstraintF> +where + P: Fp6Parameters, + P::Fp3Params: Fp3Parameters<Fp = ConstraintF>, +{ + fn to_constraint_field<CS: ConstraintSystem<ConstraintF>>( + &self, + mut cs: CS, + ) -> Result<Vec<FpGadget<ConstraintF>>, SynthesisError> { + let mut res = Vec::new(); + + let mut c0_gadget = self.c0.to_constraint_field(&mut cs.ns(|| "c0"))?; + let mut c1_gadget = self.c1.to_constraint_field(&mut cs.ns(|| "c1"))?; + + res.append(&mut c0_gadget); + res.append(&mut c1_gadget); + + Ok(res) + } +} + impl<P, ConstraintF: PrimeField + SquareRootField> Fp6Gadget<P, ConstraintF> where P: Fp6Parameters,
@@ -28,6 +28,29 @@ #[derivative(Debug = "ignore")]
_params: PhantomData<P>, } +impl<P, ConstraintF: PrimeField> ToConstraintFieldGadget<ConstraintF> for Fp6Gadget<P, ConstraintF> +where + P: Fp6Parameters, + P::Fp2Params: Fp2Parameters<Fp = ConstraintF>, +{ + fn to_constraint_field<CS: ConstraintSystem<ConstraintF>>( + &self, + mut cs: CS, + ) -> Result<Vec<FpGadget<ConstraintF>>, SynthesisError> { + let mut res = Vec::new(); + + let mut c0_gadget = self.c0.to_constraint_field(&mut cs.ns(|| "c0"))?; + let mut c1_gadget = self.c1.to_constraint_field(&mut cs.ns(|| "c1"))?; + let mut c2_gadget = self.c2.to_constraint_field(&mut cs.ns(|| "c2"))?; + + res.append(&mut c0_gadget); + res.append(&mut c1_gadget); + res.append(&mut c2_gadget); + + Ok(res) + } +} + impl<P, ConstraintF: PrimeField> Fp6Gadget<P, ConstraintF> where P: Fp6Parameters,
@@ -1,4 +1,4 @@
-use algebra::{fields::BitIterator, Field}; +use algebra::{fields::BitIterator, Field, PrimeField, Vec}; use core::fmt::Debug; use r1cs_core::{ConstraintSystem, SynthesisError};@@ -11,6 +11,14 @@ pub mod fp3;
pub mod fp4; pub mod fp6_2over3; pub mod fp6_3over2; + +use crate::fields::fp::FpGadget; +pub trait ToConstraintFieldGadget<ConstraintF: PrimeField> { + fn to_constraint_field<CS: ConstraintSystem<ConstraintF>>( + &self, + cs: CS, + ) -> Result<Vec<FpGadget<ConstraintF>>, SynthesisError>; +} pub trait FieldGadget<F: Field, ConstraintF: Field>: Sized
@@ -1,5 +1,5 @@
use algebra::{ - curves::bls12::{Bls12Parameters, G1Prepared, TwistType}, + curves::bls12::{Bls12Parameters, G1Prepared, G2Prepared, TwistType}, fields::Field, BitIterator, One, ProjectiveCurve, };@@ -12,7 +12,7 @@ prelude::*,
Vec, }; -use core::fmt::Debug; +use core::{borrow::Borrow, fmt::Debug, ops::Mul}; pub type G1Gadget<P> = AffineGadget< <P as Bls12Parameters>::G1Parameters,@@ -30,6 +30,42 @@ Debug(bound = "G1Gadget<P>: Debug")
)] pub struct G1PreparedGadget<P: Bls12Parameters>(pub G1Gadget<P>); +impl<P: Bls12Parameters> AllocGadget<G1Prepared<P>, P::Fp> for G1PreparedGadget<P> { + fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>( + mut cs: CS, + t: T, + ) -> Result<Self, SynthesisError> + where + T: Borrow<G1Prepared<P>>, + { + let obj = t.borrow(); + + Ok(Self(G1Gadget::<P>::alloc_constant( + &mut cs.ns(|| "g1"), + &obj.0.into(), + )?)) + } + + fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<G1Prepared<P>>, + { + todo!() + } + + fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>( + _cs: CS, + _f: F, + ) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<G1Prepared<P>>, + { + todo!() + } +} + impl<P: Bls12Parameters> G1PreparedGadget<P> { pub fn get_value(&self) -> Option<G1Prepared<P>> { Some(G1Prepared::from(self.0.get_value().unwrap().into_affine()))@@ -70,6 +106,54 @@ Debug(bound = "Fp2Gadget<P::Fp2Params, P::Fp>: Debug")
)] pub struct G2PreparedGadget<P: Bls12Parameters> { pub ell_coeffs: Vec<LCoeff<P>>, +} + +impl<P: Bls12Parameters> AllocGadget<G2Prepared<P>, P::Fp> for G2PreparedGadget<P> { + fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>( + mut cs: CS, + t: T, + ) -> Result<Self, SynthesisError> + where + T: Borrow<G2Prepared<P>>, + { + let obj = t.borrow(); + let mut res = Vec::<LCoeff<P>>::new(); + + for (i, (x, y, z)) in obj.ell_coeffs.iter().enumerate() { + let z_inverse = z.inverse().unwrap(); + + let x_normalized = x.mul(&z_inverse); + let y_normalized = y.mul(&z_inverse); + + let x_gadget = + Fp2Gadget::alloc_constant(&mut cs.ns(|| format!("alloc_x#{}", i)), x_normalized)?; + let y_gadget = + Fp2Gadget::alloc_constant(&mut cs.ns(|| format!("alloc_y#{}", i)), y_normalized)?; + + res.push((x_gadget, y_gadget)); + } + + Ok(Self { ell_coeffs: res }) + } + + fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<G2Prepared<P>>, + { + todo!() + } + + fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>( + _cs: CS, + _f: F, + ) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<G2Prepared<P>>, + { + todo!() + } } impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G2PreparedGadget<P> {
@@ -14,6 +14,7 @@ pairing::mnt4::PairingGadget,
prelude::*, Vec, }; +use core::borrow::Borrow; pub type G1Gadget<P> = AffineGadget< <P as MNT4Parameters>::G1Parameters,@@ -72,6 +73,53 @@ })
} } +impl<P: MNT4Parameters> AllocGadget<G1Prepared<P>, P::Fp> for G1PreparedGadget<P> { + fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>( + mut cs: CS, + t: T, + ) -> Result<Self, SynthesisError> + where + T: Borrow<G1Prepared<P>>, + { + let obj = t.borrow(); + let x = FpGadget::<P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_x"), &obj.x)?; + let y = FpGadget::<P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_y"), &obj.y)?; + let x_twist = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant( + &mut cs.ns(|| "alloc_x_twist"), + &obj.x_twist, + )?; + let y_twist = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant( + &mut cs.ns(|| "alloc_y_twist"), + &obj.y_twist, + )?; + Ok(G1PreparedGadget { + x, + y, + x_twist, + y_twist, + }) + } + + fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<G1Prepared<P>>, + { + todo!() + } + + fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>( + _cs: CS, + _f: F, + ) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<G1Prepared<P>>, + { + todo!() + } +} + impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for G1PreparedGadget<P> { #[inline] fn to_bytes<CS: ConstraintSystem<P::Fp>>(@@ -121,6 +169,70 @@ pub double_coefficients: Vec<AteDoubleCoefficientsGadget<P>>,
pub addition_coefficients: Vec<AteAdditionCoefficientsGadget<P>>, } +impl<P: MNT4Parameters> AllocGadget<G2Prepared<P>, P::Fp> for G2PreparedGadget<P> { + fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>( + mut cs: CS, + t: T, + ) -> Result<Self, SynthesisError> + where + T: Borrow<G2Prepared<P>>, + { + let obj = t.borrow(); + let x = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_x"), &obj.x)?; + let y = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_y"), &obj.y)?; + let x_over_twist = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant( + &mut cs.ns(|| "alloc_x_over_twist"), + &obj.x_over_twist, + )?; + let y_over_twist = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant( + &mut cs.ns(|| "alloc_y_over_twist"), + &obj.y_over_twist, + )?; + let mut double_coefficients = Vec::<AteDoubleCoefficientsGadget<P>>::new(); + for (i, item) in obj.double_coefficients.iter().enumerate() { + double_coefficients.push(AteDoubleCoefficientsGadget::<P>::alloc_constant( + &mut cs.ns(|| format!("alloc_double_coefficients_{}", i)), + item, + )?); + } + let mut addition_coefficients = Vec::<AteAdditionCoefficientsGadget<P>>::new(); + for (i, item) in obj.addition_coefficients.iter().enumerate() { + addition_coefficients.push(AteAdditionCoefficientsGadget::<P>::alloc_constant( + &mut cs.ns(|| format!("alloc_addition_coefficients_{}", i)), + item, + )?); + } + + Ok(G2PreparedGadget { + x, + y, + x_over_twist, + y_over_twist, + double_coefficients, + addition_coefficients, + }) + } + + fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<G2Prepared<P>>, + { + todo!() + } + + fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>( + _cs: CS, + _f: F, + ) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<G2Prepared<P>>, + { + todo!() + } +} + impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for G2PreparedGadget<P> { #[inline] fn to_bytes<CS: ConstraintSystem<P::Fp>>(@@ -308,6 +420,56 @@ pub c_j: Fp2Gadget<P::Fp2Params, P::Fp>,
pub c_l: Fp2Gadget<P::Fp2Params, P::Fp>, } +impl<P: MNT4Parameters> AllocGadget<AteDoubleCoefficients<P>, P::Fp> + for AteDoubleCoefficientsGadget<P> +{ + fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>( + mut cs: CS, + t: T, + ) -> Result<Self, SynthesisError> + where + T: Borrow<AteDoubleCoefficients<P>>, + { + let obj = t.borrow(); + let c_h = + Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_c_h"), &obj.c_h)?; + let c_4c = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant( + &mut cs.ns(|| "alloc_c_4c"), + &obj.c_4c, + )?; + let c_j = + Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_c_j"), &obj.c_j)?; + let c_l = + Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_c_l"), &obj.c_l)?; + + Ok(AteDoubleCoefficientsGadget { + c_h, + c_4c, + c_j, + c_l, + }) + } + + fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<AteDoubleCoefficients<P>>, + { + todo!() + } + + fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>( + _cs: CS, + _f: F, + ) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<AteDoubleCoefficients<P>>, + { + todo!() + } +} + impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for AteDoubleCoefficientsGadget<P> { #[inline] fn to_bytes<CS: ConstraintSystem<P::Fp>>(@@ -373,6 +535,48 @@ #[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))]
pub struct AteAdditionCoefficientsGadget<P: MNT4Parameters> { pub c_l1: Fp2Gadget<P::Fp2Params, P::Fp>, pub c_rz: Fp2Gadget<P::Fp2Params, P::Fp>, +} + +impl<P: MNT4Parameters> AllocGadget<AteAdditionCoefficients<P>, P::Fp> + for AteAdditionCoefficientsGadget<P> +{ + fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>( + mut cs: CS, + t: T, + ) -> Result<Self, SynthesisError> + where + T: Borrow<AteAdditionCoefficients<P>>, + { + let obj = t.borrow(); + let c_l1 = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant( + &mut cs.ns(|| "alloc_c_l1"), + &obj.c_l1, + )?; + let c_rz = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant( + &mut cs.ns(|| "alloc_c_rz"), + &obj.c_rz, + )?; + Ok(AteAdditionCoefficientsGadget { c_l1, c_rz }) + } + + fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<AteAdditionCoefficients<P>>, + { + todo!() + } + + fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>( + _cs: CS, + _f: F, + ) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<AteAdditionCoefficients<P>>, + { + todo!() + } } impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for AteAdditionCoefficientsGadget<P> {
@@ -5,6 +5,7 @@ G1Prepared, G2Prepared, MNT6Parameters,
}, Field, }; +use core::borrow::Borrow; use r1cs_core::{ConstraintSystem, SynthesisError}; use crate::{@@ -31,6 +32,55 @@ pub x: FpGadget<P::Fp>,
pub y: FpGadget<P::Fp>, pub x_twist: Fp3Gadget<P::Fp3Params, P::Fp>, pub y_twist: Fp3Gadget<P::Fp3Params, P::Fp>, +} + +impl<P: MNT6Parameters> AllocGadget<G1Prepared<P>, P::Fp> for G1PreparedGadget<P> { + fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>( + mut cs: CS, + t: T, + ) -> Result<Self, SynthesisError> + where + T: Borrow<G1Prepared<P>>, + { + let obj = t.borrow(); + + let x_gadget = FpGadget::<P::Fp>::alloc_constant(&mut cs.ns(|| "x"), &obj.x)?; + let y_gadget = FpGadget::<P::Fp>::alloc_constant(&mut cs.ns(|| "y"), &obj.y)?; + let x_twist_gadget = Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant( + &mut cs.ns(|| "x_twist"), + &obj.x_twist, + )?; + let y_twist_gadget = Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant( + &mut cs.ns(|| "y_twist"), + &obj.y_twist, + )?; + + Ok(Self { + x: x_gadget, + y: y_gadget, + x_twist: x_twist_gadget, + y_twist: y_twist_gadget, + }) + } + + fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<G1Prepared<P>>, + { + todo!() + } + + fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>( + _cs: CS, + _f: F, + ) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<G1Prepared<P>>, + { + todo!() + } } impl<P: MNT6Parameters> G1PreparedGadget<P> {@@ -123,6 +173,76 @@ pub double_coefficients: Vec<AteDoubleCoefficientsGadget<P>>,
pub addition_coefficients: Vec<AteAdditionCoefficientsGadget<P>>, } +impl<P: MNT6Parameters> AllocGadget<G2Prepared<P>, P::Fp> for G2PreparedGadget<P> { + fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>( + mut cs: CS, + t: T, + ) -> Result<Self, SynthesisError> + where + T: Borrow<G2Prepared<P>>, + { + let obj = t.borrow(); + + let x_gadget = + Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "x"), &obj.x)?; + let y_gadget = + Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "y"), &obj.y)?; + + let x_over_twist_gadget = Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant( + &mut cs.ns(|| "x_over_twist"), + &obj.x_over_twist, + )?; + let y_over_twist_gadget = Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant( + &mut cs.ns(|| "y_over_twist"), + &obj.y_over_twist, + )?; + + let mut double_coefficients_gadget = Vec::<AteDoubleCoefficientsGadget<P>>::new(); + for (i, double_coefficient) in obj.double_coefficients.iter().enumerate() { + double_coefficients_gadget.push(AteDoubleCoefficientsGadget::<P>::alloc_constant( + &mut cs.ns(|| format!("double_coefficient#{}", i)), + double_coefficient, + )?); + } + + let mut addition_coefficients_gadget = Vec::<AteAdditionCoefficientsGadget<P>>::new(); + for (i, addition_coefficient) in obj.addition_coefficients.iter().enumerate() { + addition_coefficients_gadget.push(AteAdditionCoefficientsGadget::<P>::alloc_constant( + &mut cs.ns(|| format!("addition_coefficient#{}", i)), + addition_coefficient, + )?); + } + + Ok(Self { + x: x_gadget, + y: y_gadget, + x_over_twist: x_over_twist_gadget, + y_over_twist: y_over_twist_gadget, + double_coefficients: double_coefficients_gadget, + addition_coefficients: addition_coefficients_gadget, + }) + } + + fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<G2Prepared<P>>, + { + todo!() + } + + fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>( + _cs: CS, + _f: F, + ) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<G2Prepared<P>>, + { + todo!() + } +} + impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for G2PreparedGadget<P> { #[inline] fn to_bytes<CS: ConstraintSystem<P::Fp>>(@@ -310,6 +430,55 @@ pub c_j: Fp3Gadget<P::Fp3Params, P::Fp>,
pub c_l: Fp3Gadget<P::Fp3Params, P::Fp>, } +impl<P: MNT6Parameters> AllocGadget<AteDoubleCoefficients<P>, P::Fp> + for AteDoubleCoefficientsGadget<P> +{ + fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>( + mut cs: CS, + t: T, + ) -> Result<Self, SynthesisError> + where + T: Borrow<AteDoubleCoefficients<P>>, + { + let obj = t.borrow(); + + let c_h_gadget = + Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "c_h"), &obj.c_h)?; + let c_4c_gadget = + Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "c_4c"), &obj.c_4c)?; + let c_j_gadget = + Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "c_j"), &obj.c_j)?; + let c_l_gadget = + Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "c_l"), &obj.c_l)?; + + Ok(Self { + c_h: c_h_gadget, + c_4c: c_4c_gadget, + c_j: c_j_gadget, + c_l: c_l_gadget, + }) + } + + fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<AteDoubleCoefficients<P>>, + { + todo!() + } + + fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>( + _cs: CS, + _f: F, + ) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<AteDoubleCoefficients<P>>, + { + todo!() + } +} + impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for AteDoubleCoefficientsGadget<P> { #[inline] fn to_bytes<CS: ConstraintSystem<P::Fp>>(@@ -375,6 +544,44 @@ #[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
pub struct AteAdditionCoefficientsGadget<P: MNT6Parameters> { pub c_l1: Fp3Gadget<P::Fp3Params, P::Fp>, pub c_rz: Fp3Gadget<P::Fp3Params, P::Fp>, +} + +impl<P: MNT6Parameters> AllocGadget<AteAdditionCoefficients<P>, P::Fp> + for AteAdditionCoefficientsGadget<P> +{ + fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>( + mut cs: CS, + t: T, + ) -> Result<Self, SynthesisError> + where + T: Borrow<AteAdditionCoefficients<P>>, + { + let t = t.borrow(); + + let c_l1 = Fp3Gadget::alloc_constant(&mut cs.ns(|| "c_l1"), &t.c_l1)?; + let c_rz = Fp3Gadget::alloc_constant(&mut cs.ns(|| "c_rz"), &t.c_rz)?; + + Ok(Self { c_l1, c_rz }) + } + + fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<AteAdditionCoefficients<P>>, + { + todo!() + } + + fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>( + _cs: CS, + _f: F, + ) -> Result<Self, SynthesisError> + where + F: FnOnce() -> Result<T, SynthesisError>, + T: Borrow<AteAdditionCoefficients<P>>, + { + todo!() + } } impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for AteAdditionCoefficientsGadget<P> {
@@ -29,6 +29,33 @@ _params: PhantomData<P>,
_engine: PhantomData<ConstraintF>, } +impl< + P: SWModelParameters, + ConstraintF: PrimeField, + F: FieldGadget<P::BaseField, ConstraintF> + ToConstraintFieldGadget<ConstraintF>, + > ToConstraintFieldGadget<ConstraintF> for AffineGadget<P, ConstraintF, F> +{ + fn to_constraint_field<CS: ConstraintSystem<ConstraintF>>( + &self, + mut cs: CS, + ) -> Result<Vec<FpGadget<ConstraintF>>, SynthesisError> { + let mut res = Vec::new(); + + let mut x_gadget = self.x.to_constraint_field(&mut cs.ns(|| "x"))?; + let mut y_gadget = self.y.to_constraint_field(&mut cs.ns(|| "y"))?; + + let mut infinity_gadget = self + .infinity + .to_constraint_field(&mut cs.ns(|| "infinity"))?; + + res.append(&mut x_gadget); + res.append(&mut y_gadget); + res.append(&mut infinity_gadget); + + Ok(res) + } +} + impl<P: SWModelParameters, ConstraintF: Field, F: FieldGadget<P::BaseField, ConstraintF>> AffineGadget<P, ConstraintF, F> {
@@ -3,13 +3,14 @@ curves::{
twisted_edwards_extended::GroupAffine as TEAffine, MontgomeryModelParameters, TEModelParameters, }, - BitIterator, Field, One, Zero, + BitIterator, Field, One, PrimeField, Zero, }; use r1cs_core::{ConstraintSystem, SynthesisError}; use crate::{prelude::*, Vec}; +use crate::fields::fp::FpGadget; use core::{borrow::Borrow, marker::PhantomData}; #[derive(Derivative)]@@ -232,6 +233,28 @@ let x = F::alloc(&mut cs.ns(|| "x"), || x)?;
let y = F::alloc(&mut cs.ns(|| "y"), || y)?; Ok(Self::new(x, y)) + } +} + +impl<P, ConstraintF, F> ToConstraintFieldGadget<ConstraintF> for AffineGadget<P, ConstraintF, F> +where + P: TEModelParameters, + ConstraintF: PrimeField, + F: FieldGadget<P::BaseField, ConstraintF> + ToConstraintFieldGadget<ConstraintF>, +{ + fn to_constraint_field<CS: ConstraintSystem<ConstraintF>>( + &self, + mut cs: CS, + ) -> Result<Vec<FpGadget<ConstraintF>>, SynthesisError> { + let mut res = Vec::new(); + + let mut x_gadget = self.x.to_constraint_field(&mut cs.ns(|| "x"))?; + let mut y_gadget = self.y.to_constraint_field(&mut cs.ns(|| "y"))?; + + res.append(&mut x_gadget); + res.append(&mut y_gadget); + + Ok(res) } }@@ -1449,7 +1472,7 @@ use crate::{
boolean::AllocatedBit, groups::test::group_test, prelude::*, test_constraint_system::TestConstraintSystem, }; - use algebra::{test_rng, Group, PrimeField, UniformRand}; + use algebra::{test_rng, Group, UniformRand}; use rand::Rng; group_test::<ConstraintF, TEAffine<P>, GG>();
@@ -89,7 +89,7 @@ pub use crate::{
alloc::*, bits::{boolean::Boolean, uint32::UInt32, uint8::UInt8, ToBitsGadget, ToBytesGadget}, eq::*, - fields::FieldGadget, + fields::{fp::FpGadget, FieldGadget, ToConstraintFieldGadget}, groups::GroupGadget, instantiated::*, pairing::PairingGadget,
@@ -10,8 +10,14 @@
pub trait PairingGadget<PairingE: PairingEngine, ConstraintF: Field> { type G1Gadget: GroupGadget<PairingE::G1Projective, ConstraintF>; type G2Gadget: GroupGadget<PairingE::G2Projective, ConstraintF>; - type G1PreparedGadget: ToBytesGadget<ConstraintF> + Clone + Debug; - type G2PreparedGadget: ToBytesGadget<ConstraintF> + Clone + Debug; + type G1PreparedGadget: AllocGadget<PairingE::G1Prepared, ConstraintF> + + ToBytesGadget<ConstraintF> + + Clone + + Debug; + type G2PreparedGadget: AllocGadget<PairingE::G2Prepared, ConstraintF> + + ToBytesGadget<ConstraintF> + + Clone + + Debug; type GTGadget: FieldGadget<PairingE::Fqk, ConstraintF> + Clone; fn miller_loop<CS: ConstraintSystem<ConstraintF>>(