use algebra::{
curves::mnt4::{
g2::{AteAdditionCoefficients, AteDoubleCoefficients},
G1Prepared, G2Prepared, MNT4Parameters,
},
Field,
};
use r1cs_core::{ConstraintSystem, SynthesisError};
use crate::{
fields::{fp::FpGadget, fp2::Fp2Gadget, FieldGadget},
groups::curves::short_weierstrass::AffineGadget,
pairing::mnt4::PairingGadget,
prelude::*,
Vec,
};
pub type G1Gadget
= AffineGadget<
::G1Parameters,
::Fp,
FpGadget<
::Fp>,
>;
pub type G2Gadget
=
AffineGadget<
::G2Parameters,
::Fp, Fp2G
>;
#[derive(Derivative)]
#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))]
pub struct G1PreparedGadget {
pub x: FpGadget,
pub y: FpGadget,
pub x_twist: Fp2Gadget,
pub y_twist: Fp2Gadget,
}
impl G1PreparedGadget {
pub fn get_value(&self) -> Option> {
match (
self.x.get_value(),
self.y.get_value(),
self.x_twist.get_value(),
self.y_twist.get_value(),
) {
(Some(x), Some(y), Some(x_twist), Some(y_twist)) => Some(G1Prepared {
x,
y,
x_twist,
y_twist,
}),
_ => None,
}
}
pub fn from_affine>(
mut cs: CS,
q: &G1Gadget,
) -> Result {
let x_twist = Fp2Gadget::new(
q.x.mul_by_constant(cs.ns(|| "g1.x * twist.c0"), &P::TWIST.c0)?,
q.x.mul_by_constant(cs.ns(|| "g1.x * twist.c1"), &P::TWIST.c1)?,
);
let y_twist = Fp2Gadget::new(
q.y.mul_by_constant(cs.ns(|| "g1.y * twist.c0"), &P::TWIST.c0)?,
q.y.mul_by_constant(cs.ns(|| "g1.y * twist.c1"), &P::TWIST.c1)?,
);
Ok(G1PreparedGadget {
x: q.x.clone(),
y: q.y.clone(),
x_twist,
y_twist,
})
}
}
impl ToBytesGadget for G1PreparedGadget {
#[inline]
fn to_bytes>(
&self,
mut cs: CS,
) -> Result, SynthesisError> {
let mut x = self.x.to_bytes(&mut cs.ns(|| "x to bytes"))?;
let mut y = self.y.to_bytes(&mut cs.ns(|| "y to bytes"))?;
let mut x_twist = self.x_twist.to_bytes(&mut cs.ns(|| "x_twist to bytes"))?;
let mut y_twist = self.y_twist.to_bytes(&mut cs.ns(|| "y_twist to bytes"))?;
x.append(&mut y);
x.append(&mut x_twist);
x.append(&mut y_twist);
Ok(x)
}
fn to_non_unique_bytes>(
&self,
mut cs: CS,
) -> Result, SynthesisError> {
let mut x = self.x.to_non_unique_bytes(&mut cs.ns(|| "x to bytes"))?;
let mut y = self.y.to_non_unique_bytes(&mut cs.ns(|| "y to bytes"))?;
let mut x_twist = self
.x_twist
.to_non_unique_bytes(&mut cs.ns(|| "x_twist to bytes"))?;
let mut y_twist = self
.y_twist
.to_non_unique_bytes(&mut cs.ns(|| "y_twist to bytes"))?;
x.append(&mut y);
x.append(&mut x_twist);
x.append(&mut y_twist);
Ok(x)
}
}
type Fp2G = Fp2Gadget<
::Fp2Params,
::Fp>;
#[derive(Derivative)]
#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))]
pub struct G2PreparedGadget {
pub x: Fp2Gadget,
pub y: Fp2Gadget,
pub x_over_twist: Fp2Gadget,
pub y_over_twist: Fp2Gadget,
pub double_coefficients: Vec>,
pub addition_coefficients: Vec>,
}
impl ToBytesGadget for G2PreparedGadget {
#[inline]
fn to_bytes>(
&self,
mut cs: CS,
) -> Result, SynthesisError> {
let mut x = self.x.to_bytes(&mut cs.ns(|| "x to bytes"))?;
let mut y = self.y.to_bytes(&mut cs.ns(|| "y to bytes"))?;
let mut x_over_twist = self
.x_over_twist
.to_bytes(&mut cs.ns(|| "x_over_twist to bytes"))?;
let mut y_over_twist = self
.y_over_twist
.to_bytes(&mut cs.ns(|| "y_over_twist to bytes"))?;
x.append(&mut y);
x.append(&mut x_over_twist);
x.append(&mut y_over_twist);
for (i, coeff) in self.double_coefficients.iter().enumerate() {
x.extend_from_slice(&coeff.to_bytes(cs.ns(|| format!("double_coefficients {}", i)))?);
}
for (i, coeff) in self.addition_coefficients.iter().enumerate() {
x.extend_from_slice(&coeff.to_bytes(cs.ns(|| format!("addition_coefficients {}", i)))?);
}
Ok(x)
}
fn to_non_unique_bytes>(
&self,
mut cs: CS,
) -> Result, SynthesisError> {
let mut x = self.x.to_non_unique_bytes(&mut cs.ns(|| "x to bytes"))?;
let mut y = self.y.to_non_unique_bytes(&mut cs.ns(|| "y to bytes"))?;
let mut x_over_twist = self
.x_over_twist
.to_non_unique_bytes(&mut cs.ns(|| "x_over_twist to bytes"))?;
let mut y_over_twist = self
.y_over_twist
.to_non_unique_bytes(&mut cs.ns(|| "y_over_twist to bytes"))?;
x.append(&mut y);
x.append(&mut x_over_twist);
x.append(&mut y_over_twist);
for (i, coeff) in self.double_coefficients.iter().enumerate() {
x.extend_from_slice(
&coeff.to_non_unique_bytes(cs.ns(|| format!("double_coefficients {}", i)))?,
);
}
for (i, coeff) in self.addition_coefficients.iter().enumerate() {
x.extend_from_slice(
&coeff.to_non_unique_bytes(cs.ns(|| format!("addition_coefficients {}", i)))?,
);
}
Ok(x)
}
}
impl G2PreparedGadget {
pub fn get_value(&self) -> Option> {
match (
self.x.get_value(),
self.y.get_value(),
self.x_over_twist.get_value(),
self.y_over_twist.get_value(),
self.double_coefficients
.iter()
.map(|coeff| coeff.get_value())
.collect::