use algebra::{ curves::bls12::{Bls12Parameters, G1Prepared, TwistType}, fields::Field, BitIterator, One, ProjectiveCurve, }; use r1cs_core::{ConstraintSystem, SynthesisError}; use crate::{ fields::{fp::FpGadget, fp2::Fp2Gadget, FieldGadget}, groups::curves::short_weierstrass::AffineGadget, prelude::*, Vec, }; use core::fmt::Debug; pub type G1Gadget

= AffineGadget<

::G1Parameters,

::Fp, FpGadget<

::Fp>, >; pub type G2Gadget

= AffineGadget<

::G2Parameters,

::Fp, Fp2G

>; #[derive(Derivative)] #[derivative( Clone(bound = "G1Gadget

: Clone"), Debug(bound = "G1Gadget

: Debug") )] pub struct G1PreparedGadget(pub G1Gadget

); impl G1PreparedGadget

{ pub fn get_value(&self) -> Option> { Some(G1Prepared::from(self.0.get_value().unwrap().into_affine())) } pub fn from_affine>( _cs: CS, q: &G1Gadget

, ) -> Result { Ok(G1PreparedGadget(q.clone())) } } impl ToBytesGadget for G1PreparedGadget

{ #[inline] fn to_bytes>( &self, mut cs: CS, ) -> Result, SynthesisError> { self.0.to_bytes(&mut cs.ns(|| "g_alpha to bytes")) } fn to_bytes_strict>( &self, cs: CS, ) -> Result, SynthesisError> { self.to_bytes(cs) } } type Fp2G

= Fp2Gadget<

::Fp2Params,

::Fp>; type LCoeff

= (Fp2G

, Fp2G

); #[derive(Derivative)] #[derivative( Clone(bound = "Fp2Gadget: Clone"), Debug(bound = "Fp2Gadget: Debug") )] pub struct G2PreparedGadget { pub ell_coeffs: Vec>, } impl ToBytesGadget for G2PreparedGadget

{ #[inline] fn to_bytes>( &self, mut cs: CS, ) -> Result, SynthesisError> { let mut bytes = Vec::new(); for (i, coeffs) in self.ell_coeffs.iter().enumerate() { let mut cs = cs.ns(|| format!("Iteration {}", i)); bytes.extend_from_slice(&coeffs.0.to_bytes(&mut cs.ns(|| "c0"))?); bytes.extend_from_slice(&coeffs.1.to_bytes(&mut cs.ns(|| "c1"))?); } Ok(bytes) } fn to_bytes_strict>( &self, cs: CS, ) -> Result, SynthesisError> { self.to_bytes(cs) } } impl G2PreparedGadget

{ pub fn from_affine>( mut cs: CS, q: &G2Gadget

, ) -> Result { let two_inv = P::Fp::one().double().inverse().unwrap(); let zero = G2Gadget::

::zero(cs.ns(|| "zero"))?; q.enforce_not_equal(cs.ns(|| "enforce not zero"), &zero)?; let mut ell_coeffs = vec![]; let mut r = q.clone(); for (j, i) in BitIterator::new(P::X).skip(1).enumerate() { let mut cs = cs.ns(|| format!("Iteration {}", j)); ell_coeffs.push(Self::double(cs.ns(|| "double"), &mut r, &two_inv)?); if i { ell_coeffs.push(Self::add(cs.ns(|| "add"), &mut r, &q)?); } } Ok(Self { ell_coeffs }) } fn double>( mut cs: CS, r: &mut G2Gadget

, two_inv: &P::Fp, ) -> Result, SynthesisError> { let a = r.y.inverse(cs.ns(|| "Inverse"))?; let mut b = r.x.square(cs.ns(|| "square x"))?; let b_tmp = b.clone(); b.mul_by_fp_constant_in_place(cs.ns(|| "mul by two_inv"), two_inv)?; b.add_in_place(cs.ns(|| "compute b"), &b_tmp)?; let c = a.mul(cs.ns(|| "compute c"), &b)?; let d = r.x.double(cs.ns(|| "compute d"))?; let x3 = c.square(cs.ns(|| "c^2"))?.sub(cs.ns(|| "sub d"), &d)?; let e = c .mul(cs.ns(|| "c*r.x"), &r.x)? .sub(cs.ns(|| "sub r.y"), &r.y)?; let c_x3 = c.mul(cs.ns(|| "c*x_3"), &x3)?; let y3 = e.sub(cs.ns(|| "e = c * x3"), &c_x3)?; let mut f = c; f.negate_in_place(cs.ns(|| "c = -c"))?; r.x = x3; r.y = y3; match P::TWIST_TYPE { TwistType::M => Ok((e, f)), TwistType::D => Ok((f, e)), } } fn add>( mut cs: CS, r: &mut G2Gadget

, q: &G2Gadget

, ) -> Result, SynthesisError> { let a = q.x.sub(cs.ns(|| "q.x - r.x"), &r.x)? .inverse(cs.ns(|| "calc a"))?; let b = q.y.sub(cs.ns(|| "q.y - r.y"), &r.y)?; let c = a.mul(cs.ns(|| "compute c"), &b)?; let d = r.x.add(cs.ns(|| "r.x + q.x"), &q.x)?; let x3 = c.square(cs.ns(|| "c^2"))?.sub(cs.ns(|| "sub d"), &d)?; let e = r.x.sub(cs.ns(|| "r.x - x3"), &x3)? .mul(cs.ns(|| "c * (r.x - x3)"), &c)?; let y3 = e.sub(cs.ns(|| "calc y3"), &r.y)?; let g = c .mul(cs.ns(|| "c*r.x"), &r.x)? .sub(cs.ns(|| "calc g"), &r.y)?; let mut f = c; f.negate_in_place(cs.ns(|| "c = -c"))?; r.x = x3; r.y = y3; match P::TWIST_TYPE { TwistType::M => Ok((g, f)), TwistType::D => Ok((f, g)), } } }