arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/r1cs-std/src/groups/curves/short_weierstrass/mnt6/mod.rs
r1cs-std/src/groups/curves/short_weierstrass/mnt6/mod.rsRaw
  1use algebra::{
  2    curves::mnt6::{
  3        g2::{AteAdditionCoefficients, AteDoubleCoefficients},
  4        G1Prepared, G2Prepared, MNT6Parameters,
  5    },
  6    Field,
  7};
  8use core::borrow::Borrow;
  9use r1cs_core::{ConstraintSystem, SynthesisError};
 10
 11use crate::{
 12    fields::{fp::FpGadget, fp3::Fp3Gadget, FieldGadget},
 13    groups::curves::short_weierstrass::AffineGadget,
 14    pairing::mnt6::PairingGadget,
 15    prelude::*,
 16    Vec,
 17};
 18
 19pub type G1Gadget<P> = AffineGadget<
 20    <P as MNT6Parameters>::G1Parameters,
 21    <P as MNT6Parameters>::Fp,
 22    FpGadget<<P as MNT6Parameters>::Fp>,
 23>;
 24
 25pub type G2Gadget<P> =
 26    AffineGadget<<P as MNT6Parameters>::G2Parameters, <P as MNT6Parameters>::Fp, Fp3G<P>>;
 27
 28#[derive(Derivative)]
 29#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
 30pub struct G1PreparedGadget<P: MNT6Parameters> {
 31    pub x: FpGadget<P::Fp>,
 32    pub y: FpGadget<P::Fp>,
 33    pub x_twist: Fp3Gadget<P::Fp3Params, P::Fp>,
 34    pub y_twist: Fp3Gadget<P::Fp3Params, P::Fp>,
 35}
 36
 37impl<P: MNT6Parameters> AllocGadget<G1Prepared<P>, P::Fp> for G1PreparedGadget<P> {
 38    fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
 39        mut cs: CS,
 40        t: T,
 41    ) -> Result<Self, SynthesisError>
 42    where
 43        T: Borrow<G1Prepared<P>>,
 44    {
 45        let obj = t.borrow();
 46
 47        let x_gadget = FpGadget::<P::Fp>::alloc_constant(&mut cs.ns(|| "x"), &obj.x)?;
 48        let y_gadget = FpGadget::<P::Fp>::alloc_constant(&mut cs.ns(|| "y"), &obj.y)?;
 49        let x_twist_gadget = Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(
 50            &mut cs.ns(|| "x_twist"),
 51            &obj.x_twist,
 52        )?;
 53        let y_twist_gadget = Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(
 54            &mut cs.ns(|| "y_twist"),
 55            &obj.y_twist,
 56        )?;
 57
 58        Ok(Self {
 59            x: x_gadget,
 60            y: y_gadget,
 61            x_twist: x_twist_gadget,
 62            y_twist: y_twist_gadget,
 63        })
 64    }
 65
 66    fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
 67    where
 68        F: FnOnce() -> Result<T, SynthesisError>,
 69        T: Borrow<G1Prepared<P>>,
 70    {
 71        todo!()
 72    }
 73
 74    fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
 75        _cs: CS,
 76        _f: F,
 77    ) -> Result<Self, SynthesisError>
 78    where
 79        F: FnOnce() -> Result<T, SynthesisError>,
 80        T: Borrow<G1Prepared<P>>,
 81    {
 82        todo!()
 83    }
 84}
 85
 86impl<P: MNT6Parameters> G1PreparedGadget<P> {
 87    pub fn get_value(&self) -> Option<G1Prepared<P>> {
 88        match (
 89            self.x.get_value(),
 90            self.y.get_value(),
 91            self.x_twist.get_value(),
 92            self.y_twist.get_value(),
 93        ) {
 94            (Some(x), Some(y), Some(x_twist), Some(y_twist)) => Some(G1Prepared {
 95                x,
 96                y,
 97                x_twist,
 98                y_twist,
 99            }),
100            _ => None,
101        }
102    }
103
104    pub fn from_affine<CS: ConstraintSystem<P::Fp>>(
105        mut cs: CS,
106        q: &G1Gadget<P>,
107    ) -> Result<Self, SynthesisError> {
108        let x_twist = Fp3Gadget::new(
109            q.x.mul_by_constant(cs.ns(|| "g1.x * twist.c0"), &P::TWIST.c0)?,
110            q.x.mul_by_constant(cs.ns(|| "g1.x * twist.c1"), &P::TWIST.c1)?,
111            q.x.mul_by_constant(cs.ns(|| "g1.x * twist.c2"), &P::TWIST.c2)?,
112        );
113        let y_twist = Fp3Gadget::new(
114            q.y.mul_by_constant(cs.ns(|| "g1.y * twist.c0"), &P::TWIST.c0)?,
115            q.y.mul_by_constant(cs.ns(|| "g1.y * twist.c1"), &P::TWIST.c1)?,
116            q.y.mul_by_constant(cs.ns(|| "g1.y * twist.c2"), &P::TWIST.c2)?,
117        );
118        Ok(G1PreparedGadget {
119            x: q.x.clone(),
120            y: q.y.clone(),
121            x_twist,
122            y_twist,
123        })
124    }
125}
126
127impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for G1PreparedGadget<P> {
128    #[inline]
129    fn to_bytes<CS: ConstraintSystem<P::Fp>>(
130        &self,
131        mut cs: CS,
132    ) -> Result<Vec<UInt8>, SynthesisError> {
133        let mut x = self.x.to_bytes(&mut cs.ns(|| "x to bytes"))?;
134        let mut y = self.y.to_bytes(&mut cs.ns(|| "y to bytes"))?;
135        let mut x_twist = self.x_twist.to_bytes(&mut cs.ns(|| "x_twist to bytes"))?;
136        let mut y_twist = self.y_twist.to_bytes(&mut cs.ns(|| "y_twist to bytes"))?;
137
138        x.append(&mut y);
139        x.append(&mut x_twist);
140        x.append(&mut y_twist);
141        Ok(x)
142    }
143
144    fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
145        &self,
146        mut cs: CS,
147    ) -> Result<Vec<UInt8>, SynthesisError> {
148        let mut x = self.x.to_non_unique_bytes(&mut cs.ns(|| "x to bytes"))?;
149        let mut y = self.y.to_non_unique_bytes(&mut cs.ns(|| "y to bytes"))?;
150        let mut x_twist = self
151            .x_twist
152            .to_non_unique_bytes(&mut cs.ns(|| "x_twist to bytes"))?;
153        let mut y_twist = self
154            .y_twist
155            .to_non_unique_bytes(&mut cs.ns(|| "y_twist to bytes"))?;
156
157        x.append(&mut y);
158        x.append(&mut x_twist);
159        x.append(&mut y_twist);
160        Ok(x)
161    }
162}
163
164type Fp3G<P> = Fp3Gadget<<P as MNT6Parameters>::Fp3Params, <P as MNT6Parameters>::Fp>;
165#[derive(Derivative)]
166#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
167pub struct G2PreparedGadget<P: MNT6Parameters> {
168    pub x: Fp3Gadget<P::Fp3Params, P::Fp>,
169    pub y: Fp3Gadget<P::Fp3Params, P::Fp>,
170    pub x_over_twist: Fp3Gadget<P::Fp3Params, P::Fp>,
171    pub y_over_twist: Fp3Gadget<P::Fp3Params, P::Fp>,
172    pub double_coefficients: Vec<AteDoubleCoefficientsGadget<P>>,
173    pub addition_coefficients: Vec<AteAdditionCoefficientsGadget<P>>,
174}
175
176impl<P: MNT6Parameters> AllocGadget<G2Prepared<P>, P::Fp> for G2PreparedGadget<P> {
177    fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
178        mut cs: CS,
179        t: T,
180    ) -> Result<Self, SynthesisError>
181    where
182        T: Borrow<G2Prepared<P>>,
183    {
184        let obj = t.borrow();
185
186        let x_gadget =
187            Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "x"), &obj.x)?;
188        let y_gadget =
189            Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "y"), &obj.y)?;
190
191        let x_over_twist_gadget = Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(
192            &mut cs.ns(|| "x_over_twist"),
193            &obj.x_over_twist,
194        )?;
195        let y_over_twist_gadget = Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(
196            &mut cs.ns(|| "y_over_twist"),
197            &obj.y_over_twist,
198        )?;
199
200        let mut double_coefficients_gadget = Vec::<AteDoubleCoefficientsGadget<P>>::new();
201        for (i, double_coefficient) in obj.double_coefficients.iter().enumerate() {
202            double_coefficients_gadget.push(AteDoubleCoefficientsGadget::<P>::alloc_constant(
203                &mut cs.ns(|| format!("double_coefficient#{}", i)),
204                double_coefficient,
205            )?);
206        }
207
208        let mut addition_coefficients_gadget = Vec::<AteAdditionCoefficientsGadget<P>>::new();
209        for (i, addition_coefficient) in obj.addition_coefficients.iter().enumerate() {
210            addition_coefficients_gadget.push(AteAdditionCoefficientsGadget::<P>::alloc_constant(
211                &mut cs.ns(|| format!("addition_coefficient#{}", i)),
212                addition_coefficient,
213            )?);
214        }
215
216        Ok(Self {
217            x: x_gadget,
218            y: y_gadget,
219            x_over_twist: x_over_twist_gadget,
220            y_over_twist: y_over_twist_gadget,
221            double_coefficients: double_coefficients_gadget,
222            addition_coefficients: addition_coefficients_gadget,
223        })
224    }
225
226    fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
227    where
228        F: FnOnce() -> Result<T, SynthesisError>,
229        T: Borrow<G2Prepared<P>>,
230    {
231        todo!()
232    }
233
234    fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
235        _cs: CS,
236        _f: F,
237    ) -> Result<Self, SynthesisError>
238    where
239        F: FnOnce() -> Result<T, SynthesisError>,
240        T: Borrow<G2Prepared<P>>,
241    {
242        todo!()
243    }
244}
245
246impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for G2PreparedGadget<P> {
247    #[inline]
248    fn to_bytes<CS: ConstraintSystem<P::Fp>>(
249        &self,
250        mut cs: CS,
251    ) -> Result<Vec<UInt8>, SynthesisError> {
252        let mut x = self.x.to_bytes(&mut cs.ns(|| "x to bytes"))?;
253        let mut y = self.y.to_bytes(&mut cs.ns(|| "y to bytes"))?;
254        let mut x_over_twist = self
255            .x_over_twist
256            .to_bytes(&mut cs.ns(|| "x_over_twist to bytes"))?;
257        let mut y_over_twist = self
258            .y_over_twist
259            .to_bytes(&mut cs.ns(|| "y_over_twist to bytes"))?;
260
261        x.append(&mut y);
262        x.append(&mut x_over_twist);
263        x.append(&mut y_over_twist);
264
265        for (i, coeff) in self.double_coefficients.iter().enumerate() {
266            x.extend_from_slice(&coeff.to_bytes(cs.ns(|| format!("double_coefficients {}", i)))?);
267        }
268        for (i, coeff) in self.addition_coefficients.iter().enumerate() {
269            x.extend_from_slice(&coeff.to_bytes(cs.ns(|| format!("addition_coefficients {}", i)))?);
270        }
271        Ok(x)
272    }
273
274    fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
275        &self,
276        mut cs: CS,
277    ) -> Result<Vec<UInt8>, SynthesisError> {
278        let mut x = self.x.to_non_unique_bytes(&mut cs.ns(|| "x to bytes"))?;
279        let mut y = self.y.to_non_unique_bytes(&mut cs.ns(|| "y to bytes"))?;
280        let mut x_over_twist = self
281            .x_over_twist
282            .to_non_unique_bytes(&mut cs.ns(|| "x_over_twist to bytes"))?;
283        let mut y_over_twist = self
284            .y_over_twist
285            .to_non_unique_bytes(&mut cs.ns(|| "y_over_twist to bytes"))?;
286
287        x.append(&mut y);
288        x.append(&mut x_over_twist);
289        x.append(&mut y_over_twist);
290
291        for (i, coeff) in self.double_coefficients.iter().enumerate() {
292            x.extend_from_slice(
293                &coeff.to_non_unique_bytes(cs.ns(|| format!("double_coefficients {}", i)))?,
294            );
295        }
296        for (i, coeff) in self.addition_coefficients.iter().enumerate() {
297            x.extend_from_slice(
298                &coeff.to_non_unique_bytes(cs.ns(|| format!("addition_coefficients {}", i)))?,
299            );
300        }
301        Ok(x)
302    }
303}
304
305impl<P: MNT6Parameters> G2PreparedGadget<P> {
306    pub fn get_value(&self) -> Option<G2Prepared<P>> {
307        match (
308            self.x.get_value(),
309            self.y.get_value(),
310            self.x_over_twist.get_value(),
311            self.y_over_twist.get_value(),
312            self.double_coefficients
313                .iter()
314                .map(|coeff| coeff.get_value())
315                .collect::<Option<Vec<AteDoubleCoefficients<P>>>>(),
316            self.addition_coefficients
317                .iter()
318                .map(|coeff| coeff.get_value())
319                .collect::<Option<Vec<AteAdditionCoefficients<P>>>>(),
320        ) {
321            (
322                Some(x),
323                Some(y),
324                Some(x_over_twist),
325                Some(y_over_twist),
326                Some(double_coefficients),
327                Some(addition_coefficients),
328            ) => Some(G2Prepared {
329                x,
330                y,
331                x_over_twist,
332                y_over_twist,
333                double_coefficients,
334                addition_coefficients,
335            }),
336            _ => None,
337        }
338    }
339
340    pub fn from_affine<CS: ConstraintSystem<P::Fp>>(
341        mut cs: CS,
342        q: &G2Gadget<P>,
343    ) -> Result<Self, SynthesisError> {
344        let twist_inv = P::TWIST.inverse().unwrap();
345
346        let mut g2p = G2PreparedGadget {
347            x: q.x.clone(),
348            y: q.y.clone(),
349            x_over_twist: q.x.mul_by_constant(cs.ns(|| "x over twist"), &twist_inv)?,
350            y_over_twist: q.y.mul_by_constant(cs.ns(|| "y over twist"), &twist_inv)?,
351            double_coefficients: vec![],
352            addition_coefficients: vec![],
353        };
354
355        let fp2_one = Fp3G::<P>::one(cs.ns(|| "one"))?;
356        let mut r = G2ProjectiveExtendedGadget {
357            x: q.x.clone(),
358            y: q.y.clone(),
359            z: fp2_one.clone(),
360            t: fp2_one,
361        };
362
363        for (idx, value) in P::ATE_LOOP_COUNT.iter().rev().enumerate() {
364            let mut tmp = *value;
365            let skip_extraneous_bits = 64 - value.leading_zeros();
366            let mut v = Vec::with_capacity(16);
367            for i in 0..64 {
368                if idx == 0 && (i == 0 || i >= skip_extraneous_bits) {
369                    continue;
370                }
371                v.push(tmp & 1 == 1);
372                tmp >>= 1;
373            }
374
375            let mut cs = cs.ns(|| format!("ate loop iteration {}", idx));
376
377            for (j, bit) in v.iter().rev().enumerate() {
378                let (r2, coeff) = PairingGadget::<P>::doubling_step_for_flipped_miller_loop(
379                    cs.ns(|| format!("doubling step {}", j)),
380                    &r,
381                )?;
382                g2p.double_coefficients.push(coeff);
383                r = r2;
384
385                if *bit {
386                    let (r2, coeff) =
387                        PairingGadget::<P>::mixed_addition_step_for_flipped_miller_loop(
388                            cs.ns(|| format!("mixed addition step {}", j)),
389                            &q.x,
390                            &q.y,
391                            &r,
392                        )?;
393                    g2p.addition_coefficients.push(coeff);
394                    r = r2;
395                }
396
397                tmp >>= 1;
398            }
399        }
400
401        if P::ATE_IS_LOOP_COUNT_NEG {
402            let rz_inv = r.z.inverse(cs.ns(|| "inverse r.z"))?;
403            let rz2_inv = rz_inv.square(cs.ns(|| "rz_inv^2"))?;
404            let rz3_inv = rz_inv.mul(cs.ns(|| "rz_inv * rz_inv^2"), &rz2_inv)?;
405
406            let minus_r_affine_x = r.x.mul(cs.ns(|| "r.x * rz2_inv"), &rz2_inv)?;
407            let minus_r_affine_y =
408                r.y.negate(cs.ns(|| "-r.y"))?
409                    .mul(cs.ns(|| "-r.y * rz3_inv"), &rz3_inv)?;
410
411            let add_result = PairingGadget::<P>::mixed_addition_step_for_flipped_miller_loop(
412                cs.ns(|| "mixed_addition step"),
413                &minus_r_affine_x,
414                &minus_r_affine_y,
415                &r,
416            )?;
417            g2p.addition_coefficients.push(add_result.1);
418        }
419
420        Ok(g2p)
421    }
422}
423
424#[derive(Derivative)]
425#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
426pub struct AteDoubleCoefficientsGadget<P: MNT6Parameters> {
427    pub c_h: Fp3Gadget<P::Fp3Params, P::Fp>,
428    pub c_4c: Fp3Gadget<P::Fp3Params, P::Fp>,
429    pub c_j: Fp3Gadget<P::Fp3Params, P::Fp>,
430    pub c_l: Fp3Gadget<P::Fp3Params, P::Fp>,
431}
432
433impl<P: MNT6Parameters> AllocGadget<AteDoubleCoefficients<P>, P::Fp>
434    for AteDoubleCoefficientsGadget<P>
435{
436    fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
437        mut cs: CS,
438        t: T,
439    ) -> Result<Self, SynthesisError>
440    where
441        T: Borrow<AteDoubleCoefficients<P>>,
442    {
443        let obj = t.borrow();
444
445        let c_h_gadget =
446            Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "c_h"), &obj.c_h)?;
447        let c_4c_gadget =
448            Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "c_4c"), &obj.c_4c)?;
449        let c_j_gadget =
450            Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "c_j"), &obj.c_j)?;
451        let c_l_gadget =
452            Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "c_l"), &obj.c_l)?;
453
454        Ok(Self {
455            c_h: c_h_gadget,
456            c_4c: c_4c_gadget,
457            c_j: c_j_gadget,
458            c_l: c_l_gadget,
459        })
460    }
461
462    fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
463    where
464        F: FnOnce() -> Result<T, SynthesisError>,
465        T: Borrow<AteDoubleCoefficients<P>>,
466    {
467        todo!()
468    }
469
470    fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
471        _cs: CS,
472        _f: F,
473    ) -> Result<Self, SynthesisError>
474    where
475        F: FnOnce() -> Result<T, SynthesisError>,
476        T: Borrow<AteDoubleCoefficients<P>>,
477    {
478        todo!()
479    }
480}
481
482impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for AteDoubleCoefficientsGadget<P> {
483    #[inline]
484    fn to_bytes<CS: ConstraintSystem<P::Fp>>(
485        &self,
486        mut cs: CS,
487    ) -> Result<Vec<UInt8>, SynthesisError> {
488        let mut c_h = self.c_h.to_bytes(&mut cs.ns(|| "c_h to bytes"))?;
489        let mut c_4c = self.c_4c.to_bytes(&mut cs.ns(|| "c_4c to bytes"))?;
490        let mut c_j = self.c_j.to_bytes(&mut cs.ns(|| "c_j to bytes"))?;
491        let mut c_l = self.c_l.to_bytes(&mut cs.ns(|| "c_l to bytes"))?;
492
493        c_h.append(&mut c_4c);
494        c_h.append(&mut c_j);
495        c_h.append(&mut c_l);
496        Ok(c_h)
497    }
498
499    fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
500        &self,
501        mut cs: CS,
502    ) -> Result<Vec<UInt8>, SynthesisError> {
503        let mut c_h = self
504            .c_h
505            .to_non_unique_bytes(&mut cs.ns(|| "c_h to bytes"))?;
506        let mut c_4c = self
507            .c_4c
508            .to_non_unique_bytes(&mut cs.ns(|| "c_4c to bytes"))?;
509        let mut c_j = self
510            .c_j
511            .to_non_unique_bytes(&mut cs.ns(|| "c_j to bytes"))?;
512        let mut c_l = self
513            .c_l
514            .to_non_unique_bytes(&mut cs.ns(|| "c_l to bytes"))?;
515
516        c_h.append(&mut c_4c);
517        c_h.append(&mut c_j);
518        c_h.append(&mut c_l);
519        Ok(c_h)
520    }
521}
522
523impl<P: MNT6Parameters> AteDoubleCoefficientsGadget<P> {
524    pub fn get_value(&self) -> Option<AteDoubleCoefficients<P>> {
525        match (
526            self.c_h.get_value(),
527            self.c_4c.get_value(),
528            self.c_j.get_value(),
529            self.c_l.get_value(),
530        ) {
531            (Some(c_h), Some(c_4c), Some(c_j), Some(c_l)) => Some(AteDoubleCoefficients {
532                c_h,
533                c_4c,
534                c_j,
535                c_l,
536            }),
537            _ => None,
538        }
539    }
540}
541
542#[derive(Derivative)]
543#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
544pub struct AteAdditionCoefficientsGadget<P: MNT6Parameters> {
545    pub c_l1: Fp3Gadget<P::Fp3Params, P::Fp>,
546    pub c_rz: Fp3Gadget<P::Fp3Params, P::Fp>,
547}
548
549impl<P: MNT6Parameters> AllocGadget<AteAdditionCoefficients<P>, P::Fp>
550    for AteAdditionCoefficientsGadget<P>
551{
552    fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
553        mut cs: CS,
554        t: T,
555    ) -> Result<Self, SynthesisError>
556    where
557        T: Borrow<AteAdditionCoefficients<P>>,
558    {
559        let t = t.borrow();
560
561        let c_l1 = Fp3Gadget::alloc_constant(&mut cs.ns(|| "c_l1"), &t.c_l1)?;
562        let c_rz = Fp3Gadget::alloc_constant(&mut cs.ns(|| "c_rz"), &t.c_rz)?;
563
564        Ok(Self { c_l1, c_rz })
565    }
566
567    fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
568    where
569        F: FnOnce() -> Result<T, SynthesisError>,
570        T: Borrow<AteAdditionCoefficients<P>>,
571    {
572        todo!()
573    }
574
575    fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
576        _cs: CS,
577        _f: F,
578    ) -> Result<Self, SynthesisError>
579    where
580        F: FnOnce() -> Result<T, SynthesisError>,
581        T: Borrow<AteAdditionCoefficients<P>>,
582    {
583        todo!()
584    }
585}
586
587impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for AteAdditionCoefficientsGadget<P> {
588    #[inline]
589    fn to_bytes<CS: ConstraintSystem<P::Fp>>(
590        &self,
591        mut cs: CS,
592    ) -> Result<Vec<UInt8>, SynthesisError> {
593        let mut c_l1 = self.c_l1.to_bytes(&mut cs.ns(|| "c_l1 to bytes"))?;
594        let mut c_rz = self.c_rz.to_bytes(&mut cs.ns(|| "c_rz to bytes"))?;
595
596        c_l1.append(&mut c_rz);
597        Ok(c_l1)
598    }
599
600    fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
601        &self,
602        mut cs: CS,
603    ) -> Result<Vec<UInt8>, SynthesisError> {
604        let mut c_l1 = self
605            .c_l1
606            .to_non_unique_bytes(&mut cs.ns(|| "c_l1 to bytes"))?;
607        let mut c_rz = self
608            .c_rz
609            .to_non_unique_bytes(&mut cs.ns(|| "c_rz to bytes"))?;
610
611        c_l1.append(&mut c_rz);
612        Ok(c_l1)
613    }
614}
615
616impl<P: MNT6Parameters> AteAdditionCoefficientsGadget<P> {
617    pub fn get_value(&self) -> Option<AteAdditionCoefficients<P>> {
618        match (self.c_l1.get_value(), self.c_rz.get_value()) {
619            (Some(c_l1), Some(c_rz)) => Some(AteAdditionCoefficients { c_l1, c_rz }),
620            _ => None,
621        }
622    }
623}
624
625pub struct G2ProjectiveExtendedGadget<P: MNT6Parameters> {
626    pub x: Fp3Gadget<P::Fp3Params, P::Fp>,
627    pub y: Fp3Gadget<P::Fp3Params, P::Fp>,
628    pub z: Fp3Gadget<P::Fp3Params, P::Fp>,
629    pub t: Fp3Gadget<P::Fp3Params, P::Fp>,
630}