use algebra::{
curves::mnt6::{
g2::{AteAdditionCoefficients, AteDoubleCoefficients},
G1Prepared, G2Prepared, MNT6Parameters,
},
Field,
};
use core::borrow::Borrow;
use r1cs_core::{ConstraintSystem, SynthesisError};
use crate::{
fields::{fp::FpGadget, fp3::Fp3Gadget, FieldGadget},
groups::curves::short_weierstrass::AffineGadget,
pairing::mnt6::PairingGadget,
prelude::*,
Vec,
};
pub type G1Gadget
= AffineGadget<
::G1Parameters,
::Fp,
FpGadget<
::Fp>,
>;
pub type G2Gadget
=
AffineGadget<
::G2Parameters,
::Fp, Fp3G
>;
#[derive(Derivative)]
#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
pub struct G1PreparedGadget {
pub x: FpGadget,
pub y: FpGadget,
pub x_twist: Fp3Gadget,
pub y_twist: Fp3Gadget,
}
impl AllocGadget, P::Fp> for G1PreparedGadget {
fn alloc_constant>(
mut cs: CS,
t: T,
) -> Result
where
T: Borrow>,
{
let obj = t.borrow();
let x_gadget = FpGadget::::alloc_constant(&mut cs.ns(|| "x"), &obj.x)?;
let y_gadget = FpGadget::::alloc_constant(&mut cs.ns(|| "y"), &obj.y)?;
let x_twist_gadget = Fp3Gadget::::alloc_constant(
&mut cs.ns(|| "x_twist"),
&obj.x_twist,
)?;
let y_twist_gadget = Fp3Gadget::::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>(_cs: CS, _f: F) -> Result
where
F: FnOnce() -> Result,
T: Borrow>,
{
todo!()
}
fn alloc_input>(
_cs: CS,
_f: F,
) -> Result
where
F: FnOnce() -> Result,
T: Borrow>,
{
todo!()
}
}
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 = Fp3Gadget::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)?,
q.x.mul_by_constant(cs.ns(|| "g1.x * twist.c2"), &P::TWIST.c2)?,
);
let y_twist = Fp3Gadget::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)?,
q.y.mul_by_constant(cs.ns(|| "g1.y * twist.c2"), &P::TWIST.c2)?,
);
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 Fp3G = Fp3Gadget<
::Fp3Params,
::Fp>;
#[derive(Derivative)]
#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
pub struct G2PreparedGadget {
pub x: Fp3Gadget,
pub y: Fp3Gadget,
pub x_over_twist: Fp3Gadget,
pub y_over_twist: Fp3Gadget,
pub double_coefficients: Vec>,
pub addition_coefficients: Vec>,
}
impl AllocGadget, P::Fp> for G2PreparedGadget {
fn alloc_constant>(
mut cs: CS,
t: T,
) -> Result
where
T: Borrow>,
{
let obj = t.borrow();
let x_gadget =
Fp3Gadget::::alloc_constant(&mut cs.ns(|| "x"), &obj.x)?;
let y_gadget =
Fp3Gadget::::alloc_constant(&mut cs.ns(|| "y"), &obj.y)?;
let x_over_twist_gadget = Fp3Gadget::::alloc_constant(
&mut cs.ns(|| "x_over_twist"),
&obj.x_over_twist,
)?;
let y_over_twist_gadget = Fp3Gadget::::alloc_constant(
&mut cs.ns(|| "y_over_twist"),
&obj.y_over_twist,
)?;
let mut double_coefficients_gadget = Vec::>::new();
for (i, double_coefficient) in obj.double_coefficients.iter().enumerate() {
double_coefficients_gadget.push(AteDoubleCoefficientsGadget::::alloc_constant(
&mut cs.ns(|| format!("double_coefficient#{}", i)),
double_coefficient,
)?);
}
let mut addition_coefficients_gadget = Vec::>::new();
for (i, addition_coefficient) in obj.addition_coefficients.iter().enumerate() {
addition_coefficients_gadget.push(AteAdditionCoefficientsGadget::::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>(_cs: CS, _f: F) -> Result
where
F: FnOnce() -> Result,
T: Borrow>,
{
todo!()
}
fn alloc_input>(
_cs: CS,
_f: F,
) -> Result
where
F: FnOnce() -> Result,
T: Borrow>,
{
todo!()
}
}
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::