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