mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-11 08:21:30 +01:00
Update curve variables in r1cs-std.
This commit is contained in:
@@ -1,234 +1,195 @@
|
|||||||
use algebra::{
|
use algebra::{
|
||||||
curves::bls12::{Bls12Parameters, G1Prepared, G2Prepared, TwistType},
|
curves::{
|
||||||
|
bls12::{Bls12Parameters, G1Prepared, G2Prepared, TwistType},
|
||||||
|
short_weierstrass_jacobian::GroupAffine,
|
||||||
|
},
|
||||||
fields::Field,
|
fields::Field,
|
||||||
BitIterator, One, ProjectiveCurve,
|
BitIterator, One,
|
||||||
};
|
};
|
||||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
use r1cs_core::SynthesisError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fields::{fp::FpGadget, fp2::Fp2Gadget, FieldGadget},
|
fields::{fp::FpVar, fp2::Fp2Var, FieldVar},
|
||||||
groups::curves::short_weierstrass::AffineGadget,
|
groups::curves::short_weierstrass::*,
|
||||||
prelude::*,
|
|
||||||
Vec,
|
Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
use core::{borrow::Borrow, fmt::Debug, ops::Mul};
|
use core::fmt::Debug;
|
||||||
|
|
||||||
pub type G1Gadget<P> = AffineGadget<
|
pub type G1Var<P> =
|
||||||
<P as Bls12Parameters>::G1Parameters,
|
ProjectiveVar<<P as Bls12Parameters>::G1Parameters, FpVar<<P as Bls12Parameters>::Fp>>;
|
||||||
<P as Bls12Parameters>::Fp,
|
pub type G1AffineVar<P> =
|
||||||
FpGadget<<P as Bls12Parameters>::Fp>,
|
AffineVar<<P as Bls12Parameters>::G1Parameters, FpVar<<P as Bls12Parameters>::Fp>>;
|
||||||
>;
|
|
||||||
|
|
||||||
pub type G2Gadget<P> =
|
pub type G2Var<P> = ProjectiveVar<<P as Bls12Parameters>::G2Parameters, Fp2G<P>>;
|
||||||
AffineGadget<<P as Bls12Parameters>::G2Parameters, <P as Bls12Parameters>::Fp, Fp2G<P>>;
|
pub type G2AffineVar<P> = AffineVar<<P as Bls12Parameters>::G2Parameters, Fp2G<P>>;
|
||||||
|
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(
|
#[derivative(Clone(bound = "G1Var<P>: Clone"), Debug(bound = "G1Var<P>: Debug"))]
|
||||||
Clone(bound = "G1Gadget<P>: Clone"),
|
pub struct G1PreparedVar<P: Bls12Parameters>(pub AffineVar<P::G1Parameters, FpVar<P::Fp>>);
|
||||||
Debug(bound = "G1Gadget<P>: Debug")
|
|
||||||
)]
|
|
||||||
pub struct G1PreparedGadget<P: Bls12Parameters>(pub G1Gadget<P>);
|
|
||||||
|
|
||||||
impl<P: Bls12Parameters> AllocGadget<G1Prepared<P>, P::Fp> for G1PreparedGadget<P> {
|
impl<P: Bls12Parameters> G1PreparedVar<P> {
|
||||||
fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
|
pub fn value(&self) -> Result<G1Prepared<P>, SynthesisError> {
|
||||||
mut cs: CS,
|
let x = self.0.x.value()?;
|
||||||
t: T,
|
let y = self.0.y.value()?;
|
||||||
) -> Result<Self, SynthesisError>
|
let infinity = self.0.infinity.value()?;
|
||||||
where
|
let g = GroupAffine::new(x, y, infinity);
|
||||||
T: Borrow<G1Prepared<P>>,
|
Ok(g.into())
|
||||||
{
|
|
||||||
let obj = t.borrow();
|
|
||||||
|
|
||||||
Ok(Self(G1Gadget::<P>::alloc_constant(
|
|
||||||
&mut cs.ns(|| "g1"),
|
|
||||||
&obj.0.into(),
|
|
||||||
)?))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
|
pub fn from_group_var(q: &G1Var<P>) -> Result<Self, SynthesisError> {
|
||||||
where
|
let g = q.to_affine()?;
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
Ok(Self(g))
|
||||||
T: Borrow<G1Prepared<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
|
|
||||||
_cs: CS,
|
|
||||||
_f: F,
|
|
||||||
) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<G1Prepared<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: Bls12Parameters> G1PreparedGadget<P> {
|
impl<P: Bls12Parameters> AllocVar<G1Prepared<P>, P::Fp> for G1PreparedVar<P> {
|
||||||
pub fn get_value(&self) -> Option<G1Prepared<P>> {
|
fn new_variable<T: Borrow<G1Prepared<P>>>(
|
||||||
Some(G1Prepared::from(self.0.get_value().unwrap().into_affine()))
|
cs: impl Into<Namespace<P::Fp>>,
|
||||||
}
|
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||||
|
mode: AllocationMode,
|
||||||
pub fn from_affine<CS: ConstraintSystem<P::Fp>>(
|
|
||||||
_cs: CS,
|
|
||||||
q: &G1Gadget<P>,
|
|
||||||
) -> Result<Self, SynthesisError> {
|
) -> Result<Self, SynthesisError> {
|
||||||
Ok(G1PreparedGadget(q.clone()))
|
let ns = cs.into();
|
||||||
|
let cs = ns.cs();
|
||||||
|
let g1_prep = f().map(|b| b.borrow().0);
|
||||||
|
|
||||||
|
let x = FpVar::new_variable(cs.ns("x"), || g1_prep.map(|g| g.x), mode)?;
|
||||||
|
let y = FpVar::new_variable(cs.ns("y"), || g1_prep.map(|g| g.y), mode)?;
|
||||||
|
let infinity = Boolean::new_variable(cs.ns("inf"), || g1_prep.map(|g| g.infinity), mode)?;
|
||||||
|
let g = AffineVar::new(x, y, infinity);
|
||||||
|
Ok(Self(g))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G1PreparedGadget<P> {
|
impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G1PreparedVar<P> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(
|
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
&self,
|
let mut bytes = self.0.x.to_bytes()?;
|
||||||
mut cs: CS,
|
let y_bytes = self.0.y.to_bytes()?;
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
let inf_bytes = self.0.infinity.to_bytes()?;
|
||||||
self.0.to_bytes(&mut cs.ns(|| "g_alpha to bytes"))
|
bytes.extend_from_slice(&y_bytes);
|
||||||
|
bytes.extend_from_slice(&inf_bytes);
|
||||||
|
Ok(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
|
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
&self,
|
let mut bytes = self.0.x.to_bytes()?;
|
||||||
mut cs: CS,
|
let y_bytes = self.0.y.to_bytes()?;
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
let inf_bytes = self.0.infinity.to_bytes()?;
|
||||||
self.0
|
bytes.extend_from_slice(&y_bytes);
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "g_alpha to bytes"))
|
bytes.extend_from_slice(&inf_bytes);
|
||||||
|
Ok(bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Fp2G<P> = Fp2Gadget<<P as Bls12Parameters>::Fp2Params, <P as Bls12Parameters>::Fp>;
|
type Fp2G<P> = Fp2Var<<P as Bls12Parameters>::Fp2Params>;
|
||||||
type LCoeff<P> = (Fp2G<P>, Fp2G<P>);
|
type LCoeff<P> = (Fp2G<P>, Fp2G<P>);
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(
|
#[derivative(
|
||||||
Clone(bound = "Fp2Gadget<P::Fp2Params, P::Fp>: Clone"),
|
Clone(bound = "Fp2Var<P::Fp2Params>: Clone"),
|
||||||
Debug(bound = "Fp2Gadget<P::Fp2Params, P::Fp>: Debug")
|
Debug(bound = "Fp2Var<P::Fp2Params>: Debug")
|
||||||
)]
|
)]
|
||||||
pub struct G2PreparedGadget<P: Bls12Parameters> {
|
pub struct G2PreparedVar<P: Bls12Parameters> {
|
||||||
pub ell_coeffs: Vec<LCoeff<P>>,
|
pub ell_coeffs: Vec<LCoeff<P>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: Bls12Parameters> AllocGadget<G2Prepared<P>, P::Fp> for G2PreparedGadget<P> {
|
impl<P: Bls12Parameters> AllocVar<G2Prepared<P>, P::Fp> for G2PreparedVar<P> {
|
||||||
fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
|
fn new_variable<T: Borrow<G2Prepared<P>>>(
|
||||||
mut cs: CS,
|
cs: impl Into<Namespace<P::Fp>>,
|
||||||
t: T,
|
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||||
) -> Result<Self, SynthesisError>
|
mode: AllocationMode,
|
||||||
where
|
|
||||||
T: Borrow<G2Prepared<P>>,
|
|
||||||
{
|
|
||||||
let obj = t.borrow();
|
|
||||||
let mut res = Vec::<LCoeff<P>>::new();
|
|
||||||
|
|
||||||
for (i, (x, y, z)) in obj.ell_coeffs.iter().enumerate() {
|
|
||||||
let z_inverse = z.inverse().unwrap();
|
|
||||||
|
|
||||||
let x_normalized = x.mul(&z_inverse);
|
|
||||||
let y_normalized = y.mul(&z_inverse);
|
|
||||||
|
|
||||||
let x_gadget =
|
|
||||||
Fp2Gadget::alloc_constant(&mut cs.ns(|| format!("alloc_x#{}", i)), x_normalized)?;
|
|
||||||
let y_gadget =
|
|
||||||
Fp2Gadget::alloc_constant(&mut cs.ns(|| format!("alloc_y#{}", i)), y_normalized)?;
|
|
||||||
|
|
||||||
res.push((x_gadget, y_gadget));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self { ell_coeffs: res })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<G2Prepared<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
|
|
||||||
_cs: CS,
|
|
||||||
_f: F,
|
|
||||||
) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<G2Prepared<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G2PreparedGadget<P> {
|
|
||||||
#[inline]
|
|
||||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(
|
|
||||||
&self,
|
|
||||||
mut cs: CS,
|
|
||||||
) -> Result<Vec<UInt8>, 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_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
|
|
||||||
&self,
|
|
||||||
mut cs: CS,
|
|
||||||
) -> Result<Vec<UInt8>, 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_non_unique_bytes(&mut cs.ns(|| "c0"))?);
|
|
||||||
bytes.extend_from_slice(&coeffs.1.to_non_unique_bytes(&mut cs.ns(|| "c1"))?);
|
|
||||||
}
|
|
||||||
Ok(bytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Bls12Parameters> G2PreparedGadget<P> {
|
|
||||||
pub fn from_affine<CS: ConstraintSystem<P::Fp>>(
|
|
||||||
mut cs: CS,
|
|
||||||
q: &G2Gadget<P>,
|
|
||||||
) -> Result<Self, SynthesisError> {
|
) -> Result<Self, SynthesisError> {
|
||||||
|
let ns = cs.into();
|
||||||
|
let cs = ns.cs();
|
||||||
|
let g2_prep = f().map(|b| {
|
||||||
|
let projective_coeffs = &b.borrow().ell_coeffs;
|
||||||
|
let mut z_s = projective_coeffs
|
||||||
|
.iter()
|
||||||
|
.map(|(_, _, z)| *z)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
algebra::fields::batch_inversion(&mut z_s);
|
||||||
|
projective_coeffs
|
||||||
|
.iter()
|
||||||
|
.zip(z_s)
|
||||||
|
.map(|((x, y, _), z_inv)| (*x * &z_inv, *y * &z_inv))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
|
||||||
|
let l = Vec::new_variable(
|
||||||
|
cs.ns("l"),
|
||||||
|
|| {
|
||||||
|
g2_prep
|
||||||
|
.clone()
|
||||||
|
.map(|c| c.iter().map(|(l, _)| *l).collect::<Vec<_>>())
|
||||||
|
},
|
||||||
|
mode,
|
||||||
|
)?;
|
||||||
|
let r = Vec::new_variable(
|
||||||
|
cs.ns("r"),
|
||||||
|
|| g2_prep.map(|c| c.iter().map(|(_, r)| *r).collect::<Vec<_>>()),
|
||||||
|
mode,
|
||||||
|
)?;
|
||||||
|
let ell_coeffs = l.into_iter().zip(r).collect();
|
||||||
|
Ok(Self { ell_coeffs })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G2PreparedVar<P> {
|
||||||
|
#[inline]
|
||||||
|
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
|
let mut bytes = Vec::new();
|
||||||
|
for coeffs in &self.ell_coeffs {
|
||||||
|
bytes.extend_from_slice(&coeffs.0.to_bytes()?);
|
||||||
|
bytes.extend_from_slice(&coeffs.1.to_bytes()?);
|
||||||
|
}
|
||||||
|
Ok(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
|
let mut bytes = Vec::new();
|
||||||
|
for coeffs in &self.ell_coeffs {
|
||||||
|
bytes.extend_from_slice(&coeffs.0.to_non_unique_bytes()?);
|
||||||
|
bytes.extend_from_slice(&coeffs.1.to_non_unique_bytes()?);
|
||||||
|
}
|
||||||
|
Ok(bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Bls12Parameters> G2PreparedVar<P> {
|
||||||
|
pub fn from_group_var(q: &G2Var<P>) -> Result<Self, SynthesisError> {
|
||||||
|
let q = q.to_affine()?;
|
||||||
let two_inv = P::Fp::one().double().inverse().unwrap();
|
let two_inv = P::Fp::one().double().inverse().unwrap();
|
||||||
let zero = G2Gadget::<P>::zero(cs.ns(|| "zero"))?;
|
// Enforce that `q` is not the point at infinity.
|
||||||
q.enforce_not_equal(cs.ns(|| "enforce not zero"), &zero)?;
|
q.infinity.enforce_not_equal(&Boolean::Constant(true))?;
|
||||||
let mut ell_coeffs = vec![];
|
let mut ell_coeffs = vec![];
|
||||||
let mut r = q.clone();
|
let mut r = q.clone();
|
||||||
|
|
||||||
for (j, i) in BitIterator::new(P::X).skip(1).enumerate() {
|
for i in BitIterator::new(P::X).skip(1) {
|
||||||
let mut cs = cs.ns(|| format!("Iteration {}", j));
|
ell_coeffs.push(Self::double(&mut r, &two_inv)?);
|
||||||
ell_coeffs.push(Self::double(cs.ns(|| "double"), &mut r, &two_inv)?);
|
|
||||||
|
|
||||||
if i {
|
if i {
|
||||||
ell_coeffs.push(Self::add(cs.ns(|| "add"), &mut r, &q)?);
|
ell_coeffs.push(Self::add(&mut r, &q)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self { ell_coeffs })
|
Ok(Self { ell_coeffs })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn double<CS: ConstraintSystem<P::Fp>>(
|
fn double(r: &mut G2AffineVar<P>, two_inv: &P::Fp) -> Result<LCoeff<P>, SynthesisError> {
|
||||||
mut cs: CS,
|
let a = r.y.inverse()?;
|
||||||
r: &mut G2Gadget<P>,
|
let mut b = r.x.square()?;
|
||||||
two_inv: &P::Fp,
|
|
||||||
) -> Result<LCoeff<P>, SynthesisError> {
|
|
||||||
let a = r.y.inverse(cs.ns(|| "Inverse"))?;
|
|
||||||
let mut b = r.x.square(cs.ns(|| "square x"))?;
|
|
||||||
let b_tmp = b.clone();
|
let b_tmp = b.clone();
|
||||||
b.mul_by_fp_constant_in_place(cs.ns(|| "mul by two_inv"), two_inv)?;
|
b.mul_assign_by_base_field_constant(*two_inv);
|
||||||
b.add_in_place(cs.ns(|| "compute b"), &b_tmp)?;
|
b += &b_tmp;
|
||||||
|
|
||||||
let c = a.mul(cs.ns(|| "compute c"), &b)?;
|
let c = &a * &b;
|
||||||
let d = r.x.double(cs.ns(|| "compute d"))?;
|
let d = r.x.double()?;
|
||||||
let x3 = c.square(cs.ns(|| "c^2"))?.sub(cs.ns(|| "sub d"), &d)?;
|
let x3 = c.square()? - &d;
|
||||||
let e = c
|
let e = &c * &r.x - &r.y;
|
||||||
.mul(cs.ns(|| "c*r.x"), &r.x)?
|
let c_x3 = &c * &x3;
|
||||||
.sub(cs.ns(|| "sub r.y"), &r.y)?;
|
let y3 = &e - &c_x3;
|
||||||
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;
|
let mut f = c;
|
||||||
f.negate_in_place(cs.ns(|| "c = -c"))?;
|
f.negate_in_place()?;
|
||||||
r.x = x3;
|
r.x = x3;
|
||||||
r.y = y3;
|
r.y = y3;
|
||||||
match P::TWIST_TYPE {
|
match P::TWIST_TYPE {
|
||||||
@@ -237,28 +198,18 @@ impl<P: Bls12Parameters> G2PreparedGadget<P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add<CS: ConstraintSystem<P::Fp>>(
|
fn add(r: &mut G2AffineVar<P>, q: &G2AffineVar<P>) -> Result<LCoeff<P>, SynthesisError> {
|
||||||
mut cs: CS,
|
let a = (&q.x - &r.x).inverse()?;
|
||||||
r: &mut G2Gadget<P>,
|
let b = &q.y - &r.y;
|
||||||
q: &G2Gadget<P>,
|
let c = &a * &b;
|
||||||
) -> Result<LCoeff<P>, SynthesisError> {
|
let d = &r.x + &q.x;
|
||||||
let a =
|
let x3 = c.square()? - &d;
|
||||||
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 =
|
let e = (&r.x - &x3) * &c;
|
||||||
r.x.sub(cs.ns(|| "r.x - x3"), &x3)?
|
let y3 = e - &r.y;
|
||||||
.mul(cs.ns(|| "c * (r.x - x3)"), &c)?;
|
let g = &c * &r.x - &r.y;
|
||||||
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;
|
let mut f = c;
|
||||||
f.negate_in_place(cs.ns(|| "c = -c"))?;
|
f.negate_in_place()?;
|
||||||
r.x = x3;
|
r.x = x3;
|
||||||
r.y = y3;
|
r.y = y3;
|
||||||
match P::TWIST_TYPE {
|
match P::TWIST_TYPE {
|
||||||
|
|||||||
@@ -5,66 +5,76 @@ use algebra::{
|
|||||||
},
|
},
|
||||||
Field,
|
Field,
|
||||||
};
|
};
|
||||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
use r1cs_core::{Namespace, SynthesisError};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fields::{fp::FpGadget, fp2::Fp2Gadget, FieldGadget},
|
fields::{fp::FpVar, fp2::Fp2Var, FieldVar},
|
||||||
groups::curves::short_weierstrass::AffineGadget,
|
groups::curves::short_weierstrass::ProjectiveVar,
|
||||||
pairing::mnt4::PairingGadget,
|
pairing::mnt4::PairingVar,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Vec,
|
Vec,
|
||||||
};
|
};
|
||||||
use core::borrow::Borrow;
|
use core::borrow::Borrow;
|
||||||
|
|
||||||
pub type G1Gadget<P> = AffineGadget<
|
pub type G1Var<P> =
|
||||||
<P as MNT4Parameters>::G1Parameters,
|
ProjectiveVar<<P as MNT4Parameters>::G1Parameters, FpVar<<P as MNT4Parameters>::Fp>>;
|
||||||
<P as MNT4Parameters>::Fp,
|
|
||||||
FpGadget<<P as MNT4Parameters>::Fp>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
pub type G2Gadget<P> =
|
pub type G2Var<P> = ProjectiveVar<<P as MNT4Parameters>::G2Parameters, Fp2G<P>>;
|
||||||
AffineGadget<<P as MNT4Parameters>::G2Parameters, <P as MNT4Parameters>::Fp, Fp2G<P>>;
|
|
||||||
|
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))]
|
#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))]
|
||||||
pub struct G1PreparedGadget<P: MNT4Parameters> {
|
pub struct G1PreparedVar<P: MNT4Parameters> {
|
||||||
pub x: FpGadget<P::Fp>,
|
pub x: FpVar<P::Fp>,
|
||||||
pub y: FpGadget<P::Fp>,
|
pub y: FpVar<P::Fp>,
|
||||||
pub x_twist: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub x_twist: Fp2Var<P::Fp2Params>,
|
||||||
pub y_twist: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub y_twist: Fp2Var<P::Fp2Params>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT4Parameters> G1PreparedGadget<P> {
|
impl<P: MNT4Parameters> AllocVar<G1Prepared<P>, P::Fp> for G1PreparedVar<P> {
|
||||||
pub fn get_value(&self) -> Option<G1Prepared<P>> {
|
fn new_variable<T: Borrow<G1Prepared<P>>>(
|
||||||
match (
|
cs: impl Into<Namespace<P::Fp>>,
|
||||||
self.x.get_value(),
|
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||||
self.y.get_value(),
|
mode: AllocationMode,
|
||||||
self.x_twist.get_value(),
|
) -> Result<Self, SynthesisError> {
|
||||||
self.y_twist.get_value(),
|
let ns = cs.into();
|
||||||
) {
|
let cs = ns.cs();
|
||||||
(Some(x), Some(y), Some(x_twist), Some(y_twist)) => Some(G1Prepared {
|
|
||||||
|
let g1_prep = f().map(|b| *b.borrow());
|
||||||
|
|
||||||
|
let x = FpVar::new_variable(cs.ns("x"), || g1_prep.map(|g| g.x), mode)?;
|
||||||
|
let y = FpVar::new_variable(cs.ns("y"), || g1_prep.map(|g| g.y), mode)?;
|
||||||
|
let x_twist = Fp2Var::new_variable(cs.ns("x_twist"), || g1_prep.map(|g| g.x_twist), mode)?;
|
||||||
|
let y_twist = Fp2Var::new_variable(cs.ns("y_twist"), || g1_prep.map(|g| g.y_twist), mode)?;
|
||||||
|
Ok(Self {
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
x_twist,
|
x_twist,
|
||||||
y_twist,
|
y_twist,
|
||||||
}),
|
})
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_affine<CS: ConstraintSystem<P::Fp>>(
|
impl<P: MNT4Parameters> G1PreparedVar<P> {
|
||||||
mut cs: CS,
|
pub fn value(&self) -> Result<G1Prepared<P>, SynthesisError> {
|
||||||
q: &G1Gadget<P>,
|
let (x, y, x_twist, y_twist) = (
|
||||||
) -> Result<Self, SynthesisError> {
|
self.x.value()?,
|
||||||
let x_twist = Fp2Gadget::new(
|
self.y.value()?,
|
||||||
q.x.mul_by_constant(cs.ns(|| "g1.x * twist.c0"), &P::TWIST.c0)?,
|
self.x_twist.value()?,
|
||||||
q.x.mul_by_constant(cs.ns(|| "g1.x * twist.c1"), &P::TWIST.c1)?,
|
self.y_twist.value()?,
|
||||||
);
|
);
|
||||||
let y_twist = Fp2Gadget::new(
|
Ok(G1Prepared {
|
||||||
q.y.mul_by_constant(cs.ns(|| "g1.y * twist.c0"), &P::TWIST.c0)?,
|
x,
|
||||||
q.y.mul_by_constant(cs.ns(|| "g1.y * twist.c1"), &P::TWIST.c1)?,
|
y,
|
||||||
);
|
x_twist,
|
||||||
Ok(G1PreparedGadget {
|
y_twist,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_group_var(q: &G1Var<P>) -> Result<Self, SynthesisError> {
|
||||||
|
let q = q.to_affine()?;
|
||||||
|
let x_twist = Fp2Var::new(&q.x * P::TWIST.c0, &q.x * P::TWIST.c1);
|
||||||
|
let y_twist = Fp2Var::new(&q.y * P::TWIST.c0, &q.y * P::TWIST.c1);
|
||||||
|
Ok(G1PreparedVar {
|
||||||
x: q.x.clone(),
|
x: q.x.clone(),
|
||||||
y: q.y.clone(),
|
y: q.y.clone(),
|
||||||
x_twist,
|
x_twist,
|
||||||
@@ -73,63 +83,13 @@ impl<P: MNT4Parameters> G1PreparedGadget<P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT4Parameters> AllocGadget<G1Prepared<P>, P::Fp> for G1PreparedGadget<P> {
|
impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for G1PreparedVar<P> {
|
||||||
fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
|
|
||||||
mut cs: CS,
|
|
||||||
t: T,
|
|
||||||
) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
T: Borrow<G1Prepared<P>>,
|
|
||||||
{
|
|
||||||
let obj = t.borrow();
|
|
||||||
let x = FpGadget::<P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_x"), &obj.x)?;
|
|
||||||
let y = FpGadget::<P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_y"), &obj.y)?;
|
|
||||||
let x_twist = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(
|
|
||||||
&mut cs.ns(|| "alloc_x_twist"),
|
|
||||||
&obj.x_twist,
|
|
||||||
)?;
|
|
||||||
let y_twist = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(
|
|
||||||
&mut cs.ns(|| "alloc_y_twist"),
|
|
||||||
&obj.y_twist,
|
|
||||||
)?;
|
|
||||||
Ok(G1PreparedGadget {
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
x_twist,
|
|
||||||
y_twist,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<G1Prepared<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
|
|
||||||
_cs: CS,
|
|
||||||
_f: F,
|
|
||||||
) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<G1Prepared<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for G1PreparedGadget<P> {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(
|
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
&self,
|
let mut x = self.x.to_bytes()?;
|
||||||
mut cs: CS,
|
let mut y = self.y.to_bytes()?;
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
let mut x_twist = self.x_twist.to_bytes()?;
|
||||||
let mut x = self.x.to_bytes(&mut cs.ns(|| "x to bytes"))?;
|
let mut y_twist = self.y_twist.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 y);
|
||||||
x.append(&mut x_twist);
|
x.append(&mut x_twist);
|
||||||
@@ -137,18 +97,11 @@ impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for G1PreparedGadget<P> {
|
|||||||
Ok(x)
|
Ok(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
|
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
&self,
|
let mut x = self.x.to_non_unique_bytes()?;
|
||||||
mut cs: CS,
|
let mut y = self.y.to_non_unique_bytes()?;
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
let mut x_twist = self.x_twist.to_non_unique_bytes()?;
|
||||||
let mut x = self.x.to_non_unique_bytes(&mut cs.ns(|| "x to bytes"))?;
|
let mut y_twist = self.y_twist.to_non_unique_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 y);
|
||||||
x.append(&mut x_twist);
|
x.append(&mut x_twist);
|
||||||
@@ -157,53 +110,116 @@ impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for G1PreparedGadget<P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Fp2G<P> = Fp2Gadget<<P as MNT4Parameters>::Fp2Params, <P as MNT4Parameters>::Fp>;
|
type Fp2G<P> = Fp2Var<<P as MNT4Parameters>::Fp2Params>;
|
||||||
|
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))]
|
#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))]
|
||||||
pub struct G2PreparedGadget<P: MNT4Parameters> {
|
pub struct G2PreparedVar<P: MNT4Parameters> {
|
||||||
pub x: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub x: Fp2Var<P::Fp2Params>,
|
||||||
pub y: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub y: Fp2Var<P::Fp2Params>,
|
||||||
pub x_over_twist: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub x_over_twist: Fp2Var<P::Fp2Params>,
|
||||||
pub y_over_twist: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub y_over_twist: Fp2Var<P::Fp2Params>,
|
||||||
pub double_coefficients: Vec<AteDoubleCoefficientsGadget<P>>,
|
pub double_coefficients: Vec<AteDoubleCoefficientsVar<P>>,
|
||||||
pub addition_coefficients: Vec<AteAdditionCoefficientsGadget<P>>,
|
pub addition_coefficients: Vec<AteAdditionCoefficientsVar<P>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT4Parameters> AllocGadget<G2Prepared<P>, P::Fp> for G2PreparedGadget<P> {
|
impl<P: MNT4Parameters> AllocVar<G2Prepared<P>, P::Fp> for G2PreparedVar<P> {
|
||||||
fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
|
fn new_variable<T: Borrow<G2Prepared<P>>>(
|
||||||
mut cs: CS,
|
cs: impl Into<Namespace<P::Fp>>,
|
||||||
t: T,
|
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||||
) -> Result<Self, SynthesisError>
|
mode: AllocationMode,
|
||||||
where
|
) -> Result<Self, SynthesisError> {
|
||||||
T: Borrow<G2Prepared<P>>,
|
let ns = cs.into();
|
||||||
{
|
let cs = ns.cs();
|
||||||
let obj = t.borrow();
|
|
||||||
let x = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_x"), &obj.x)?;
|
let g2_prep = f().map(|b| b.borrow().clone());
|
||||||
let y = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_y"), &obj.y)?;
|
let g2 = g2_prep.as_ref().map_err(|e| *e);
|
||||||
let x_over_twist = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(
|
|
||||||
&mut cs.ns(|| "alloc_x_over_twist"),
|
let x = Fp2Var::new_variable(cs.ns("x"), || g2.map(|g| g.x), mode)?;
|
||||||
&obj.x_over_twist,
|
let y = Fp2Var::new_variable(cs.ns("y"), || g2.map(|g| g.y), mode)?;
|
||||||
|
let x_over_twist =
|
||||||
|
Fp2Var::new_variable(cs.ns("x_over_twist"), || g2.map(|g| g.x_over_twist), mode)?;
|
||||||
|
let y_over_twist =
|
||||||
|
Fp2Var::new_variable(cs.ns("y_over_twist"), || g2.map(|g| g.y_over_twist), mode)?;
|
||||||
|
let double_coefficients = Vec::new_variable(
|
||||||
|
cs.ns("double coeffs"),
|
||||||
|
|| g2.map(|g| g.double_coefficients.clone()),
|
||||||
|
mode,
|
||||||
)?;
|
)?;
|
||||||
let y_over_twist = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(
|
let addition_coefficients = Vec::new_variable(
|
||||||
&mut cs.ns(|| "alloc_y_over_twist"),
|
cs.ns("add coeffs"),
|
||||||
&obj.y_over_twist,
|
|| g2.map(|g| g.addition_coefficients.clone()),
|
||||||
|
mode,
|
||||||
)?;
|
)?;
|
||||||
let mut double_coefficients = Vec::<AteDoubleCoefficientsGadget<P>>::new();
|
Ok(Self {
|
||||||
for (i, item) in obj.double_coefficients.iter().enumerate() {
|
x,
|
||||||
double_coefficients.push(AteDoubleCoefficientsGadget::<P>::alloc_constant(
|
y,
|
||||||
&mut cs.ns(|| format!("alloc_double_coefficients_{}", i)),
|
x_over_twist,
|
||||||
item,
|
y_over_twist,
|
||||||
)?);
|
double_coefficients,
|
||||||
|
addition_coefficients,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
let mut addition_coefficients = Vec::<AteAdditionCoefficientsGadget<P>>::new();
|
|
||||||
for (i, item) in obj.addition_coefficients.iter().enumerate() {
|
|
||||||
addition_coefficients.push(AteAdditionCoefficientsGadget::<P>::alloc_constant(
|
|
||||||
&mut cs.ns(|| format!("alloc_addition_coefficients_{}", i)),
|
|
||||||
item,
|
|
||||||
)?);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(G2PreparedGadget {
|
impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for G2PreparedVar<P> {
|
||||||
|
#[inline]
|
||||||
|
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
|
let mut x = self.x.to_bytes()?;
|
||||||
|
let mut y = self.y.to_bytes()?;
|
||||||
|
let mut x_over_twist = self.x_over_twist.to_bytes()?;
|
||||||
|
let mut y_over_twist = self.y_over_twist.to_bytes()?;
|
||||||
|
|
||||||
|
x.append(&mut y);
|
||||||
|
x.append(&mut x_over_twist);
|
||||||
|
x.append(&mut y_over_twist);
|
||||||
|
|
||||||
|
for coeff in &self.double_coefficients {
|
||||||
|
x.extend_from_slice(&coeff.to_bytes()?);
|
||||||
|
}
|
||||||
|
for coeff in &self.addition_coefficients {
|
||||||
|
x.extend_from_slice(&coeff.to_bytes()?);
|
||||||
|
}
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
|
let mut x = self.x.to_non_unique_bytes()?;
|
||||||
|
let mut y = self.y.to_non_unique_bytes()?;
|
||||||
|
let mut x_over_twist = self.x_over_twist.to_non_unique_bytes()?;
|
||||||
|
let mut y_over_twist = self.y_over_twist.to_non_unique_bytes()?;
|
||||||
|
|
||||||
|
x.append(&mut y);
|
||||||
|
x.append(&mut x_over_twist);
|
||||||
|
x.append(&mut y_over_twist);
|
||||||
|
|
||||||
|
for coeff in &self.double_coefficients {
|
||||||
|
x.extend_from_slice(&coeff.to_non_unique_bytes()?);
|
||||||
|
}
|
||||||
|
for coeff in &self.addition_coefficients {
|
||||||
|
x.extend_from_slice(&coeff.to_non_unique_bytes()?);
|
||||||
|
}
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: MNT4Parameters> G2PreparedVar<P> {
|
||||||
|
pub fn value(&self) -> Result<G2Prepared<P>, SynthesisError> {
|
||||||
|
let x = self.x.value()?;
|
||||||
|
let y = self.y.value()?;
|
||||||
|
let x_over_twist = self.x_over_twist.value()?;
|
||||||
|
let y_over_twist = self.y_over_twist.value()?;
|
||||||
|
let double_coefficients = self
|
||||||
|
.double_coefficients
|
||||||
|
.iter()
|
||||||
|
.map(|coeff| coeff.value())
|
||||||
|
.collect::<Result<Vec<AteDoubleCoefficients<P>>, _>>()?;
|
||||||
|
let addition_coefficients = self
|
||||||
|
.addition_coefficients
|
||||||
|
.iter()
|
||||||
|
.map(|coeff| coeff.value())
|
||||||
|
.collect::<Result<Vec<AteAdditionCoefficients<P>>, _>>()?;
|
||||||
|
Ok(G2Prepared {
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
x_over_twist,
|
x_over_twist,
|
||||||
@@ -213,141 +229,24 @@ impl<P: MNT4Parameters> AllocGadget<G2Prepared<P>, P::Fp> for G2PreparedGadget<P
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
|
pub fn from_group_var(q: &G2Var<P>) -> Result<Self, SynthesisError> {
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<G2Prepared<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
|
|
||||||
_cs: CS,
|
|
||||||
_f: F,
|
|
||||||
) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<G2Prepared<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for G2PreparedGadget<P> {
|
|
||||||
#[inline]
|
|
||||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(
|
|
||||||
&self,
|
|
||||||
mut cs: CS,
|
|
||||||
) -> Result<Vec<UInt8>, 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<CS: ConstraintSystem<P::Fp>>(
|
|
||||||
&self,
|
|
||||||
mut cs: CS,
|
|
||||||
) -> Result<Vec<UInt8>, 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<P: MNT4Parameters> G2PreparedGadget<P> {
|
|
||||||
pub fn get_value(&self) -> Option<G2Prepared<P>> {
|
|
||||||
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::<Option<Vec<AteDoubleCoefficients<P>>>>(),
|
|
||||||
self.addition_coefficients
|
|
||||||
.iter()
|
|
||||||
.map(|coeff| coeff.get_value())
|
|
||||||
.collect::<Option<Vec<AteAdditionCoefficients<P>>>>(),
|
|
||||||
) {
|
|
||||||
(
|
|
||||||
Some(x),
|
|
||||||
Some(y),
|
|
||||||
Some(x_over_twist),
|
|
||||||
Some(y_over_twist),
|
|
||||||
Some(double_coefficients),
|
|
||||||
Some(addition_coefficients),
|
|
||||||
) => Some(G2Prepared {
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
x_over_twist,
|
|
||||||
y_over_twist,
|
|
||||||
double_coefficients,
|
|
||||||
addition_coefficients,
|
|
||||||
}),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_affine<CS: ConstraintSystem<P::Fp>>(
|
|
||||||
mut cs: CS,
|
|
||||||
q: &G2Gadget<P>,
|
|
||||||
) -> Result<Self, SynthesisError> {
|
|
||||||
let twist_inv = P::TWIST.inverse().unwrap();
|
let twist_inv = P::TWIST.inverse().unwrap();
|
||||||
|
let q = q.to_affine()?;
|
||||||
|
|
||||||
let mut g2p = G2PreparedGadget {
|
let mut g2p = G2PreparedVar {
|
||||||
x: q.x.clone(),
|
x: q.x.clone(),
|
||||||
y: q.y.clone(),
|
y: q.y.clone(),
|
||||||
x_over_twist: q.x.mul_by_constant(cs.ns(|| "x over twist"), &twist_inv)?,
|
x_over_twist: &q.x * twist_inv,
|
||||||
y_over_twist: q.y.mul_by_constant(cs.ns(|| "y over twist"), &twist_inv)?,
|
y_over_twist: &q.y * twist_inv,
|
||||||
double_coefficients: vec![],
|
double_coefficients: vec![],
|
||||||
addition_coefficients: vec![],
|
addition_coefficients: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let fp2_one = Fp2G::<P>::one(cs.ns(|| "one"))?;
|
let mut r = G2ProjectiveExtendedVar {
|
||||||
let mut r = G2ProjectiveExtendedGadget {
|
|
||||||
x: q.x.clone(),
|
x: q.x.clone(),
|
||||||
y: q.y.clone(),
|
y: q.y.clone(),
|
||||||
z: fp2_one.clone(),
|
z: Fp2G::<P>::one(),
|
||||||
t: fp2_one,
|
t: Fp2G::<P>::one(),
|
||||||
};
|
};
|
||||||
|
|
||||||
for (idx, value) in P::ATE_LOOP_COUNT.iter().rev().enumerate() {
|
for (idx, value) in P::ATE_LOOP_COUNT.iter().rev().enumerate() {
|
||||||
@@ -362,23 +261,14 @@ impl<P: MNT4Parameters> G2PreparedGadget<P> {
|
|||||||
tmp >>= 1;
|
tmp >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cs = cs.ns(|| format!("ate loop iteration {}", idx));
|
for bit in v.iter().rev() {
|
||||||
|
let (r2, coeff) = PairingVar::<P>::doubling_step_for_flipped_miller_loop(&r)?;
|
||||||
for (j, bit) in v.iter().rev().enumerate() {
|
|
||||||
let (r2, coeff) = PairingGadget::<P>::doubling_step_for_flipped_miller_loop(
|
|
||||||
cs.ns(|| format!("doubling step {}", j)),
|
|
||||||
&r,
|
|
||||||
)?;
|
|
||||||
g2p.double_coefficients.push(coeff);
|
g2p.double_coefficients.push(coeff);
|
||||||
r = r2;
|
r = r2;
|
||||||
|
|
||||||
if *bit {
|
if *bit {
|
||||||
let (r2, coeff) =
|
let (r2, coeff) = PairingVar::<P>::mixed_addition_step_for_flipped_miller_loop(
|
||||||
PairingGadget::<P>::mixed_addition_step_for_flipped_miller_loop(
|
&q.x, &q.y, &r,
|
||||||
cs.ns(|| format!("mixed addition step {}", j)),
|
|
||||||
&q.x,
|
|
||||||
&q.y,
|
|
||||||
&r,
|
|
||||||
)?;
|
)?;
|
||||||
g2p.addition_coefficients.push(coeff);
|
g2p.addition_coefficients.push(coeff);
|
||||||
r = r2;
|
r = r2;
|
||||||
@@ -389,17 +279,14 @@ impl<P: MNT4Parameters> G2PreparedGadget<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if P::ATE_IS_LOOP_COUNT_NEG {
|
if P::ATE_IS_LOOP_COUNT_NEG {
|
||||||
let rz_inv = r.z.inverse(cs.ns(|| "inverse r.z"))?;
|
let rz_inv = r.z.inverse()?;
|
||||||
let rz2_inv = rz_inv.square(cs.ns(|| "rz_inv^2"))?;
|
let rz2_inv = rz_inv.square()?;
|
||||||
let rz3_inv = rz_inv.mul(cs.ns(|| "rz_inv * rz_inv^2"), &rz2_inv)?;
|
let rz3_inv = &rz_inv * &rz2_inv;
|
||||||
|
|
||||||
let minus_r_affine_x = r.x.mul(cs.ns(|| "r.x * rz2_inv"), &rz2_inv)?;
|
let minus_r_affine_x = &r.x * &rz2_inv;
|
||||||
let minus_r_affine_y =
|
let minus_r_affine_y = r.y.negate()? * &rz3_inv;
|
||||||
r.y.negate(cs.ns(|| "-r.y"))?
|
|
||||||
.mul(cs.ns(|| "-r.y * rz3_inv"), &rz3_inv)?;
|
|
||||||
|
|
||||||
let add_result = PairingGadget::<P>::mixed_addition_step_for_flipped_miller_loop(
|
let add_result = PairingVar::<P>::mixed_addition_step_for_flipped_miller_loop(
|
||||||
cs.ns(|| "mixed_addition step"),
|
|
||||||
&minus_r_affine_x,
|
&minus_r_affine_x,
|
||||||
&minus_r_affine_y,
|
&minus_r_affine_y,
|
||||||
&r,
|
&r,
|
||||||
@@ -413,73 +300,45 @@ impl<P: MNT4Parameters> G2PreparedGadget<P> {
|
|||||||
|
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))]
|
#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))]
|
||||||
pub struct AteDoubleCoefficientsGadget<P: MNT4Parameters> {
|
pub struct AteDoubleCoefficientsVar<P: MNT4Parameters> {
|
||||||
pub c_h: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub c_h: Fp2Var<P::Fp2Params>,
|
||||||
pub c_4c: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub c_4c: Fp2Var<P::Fp2Params>,
|
||||||
pub c_j: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub c_j: Fp2Var<P::Fp2Params>,
|
||||||
pub c_l: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub c_l: Fp2Var<P::Fp2Params>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT4Parameters> AllocGadget<AteDoubleCoefficients<P>, P::Fp>
|
impl<P: MNT4Parameters> AllocVar<AteDoubleCoefficients<P>, P::Fp> for AteDoubleCoefficientsVar<P> {
|
||||||
for AteDoubleCoefficientsGadget<P>
|
fn new_variable<T: Borrow<AteDoubleCoefficients<P>>>(
|
||||||
{
|
cs: impl Into<Namespace<P::Fp>>,
|
||||||
fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
|
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||||
mut cs: CS,
|
mode: AllocationMode,
|
||||||
t: T,
|
) -> Result<Self, SynthesisError> {
|
||||||
) -> Result<Self, SynthesisError>
|
let ns = cs.into();
|
||||||
where
|
let cs = ns.cs();
|
||||||
T: Borrow<AteDoubleCoefficients<P>>,
|
|
||||||
{
|
|
||||||
let obj = t.borrow();
|
|
||||||
let c_h =
|
|
||||||
Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_c_h"), &obj.c_h)?;
|
|
||||||
let c_4c = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(
|
|
||||||
&mut cs.ns(|| "alloc_c_4c"),
|
|
||||||
&obj.c_4c,
|
|
||||||
)?;
|
|
||||||
let c_j =
|
|
||||||
Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_c_j"), &obj.c_j)?;
|
|
||||||
let c_l =
|
|
||||||
Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(&mut cs.ns(|| "alloc_c_l"), &obj.c_l)?;
|
|
||||||
|
|
||||||
Ok(AteDoubleCoefficientsGadget {
|
let c_prep = f().map(|c| c.borrow().clone());
|
||||||
|
let c = c_prep.as_ref().map_err(|e| *e);
|
||||||
|
|
||||||
|
let c_h = Fp2Var::new_variable(cs.ns("c_h"), || c.map(|c| c.c_h), mode)?;
|
||||||
|
let c_4c = Fp2Var::new_variable(cs.ns("c_4c"), || c.map(|c| c.c_4c), mode)?;
|
||||||
|
let c_j = Fp2Var::new_variable(cs.ns("c_j"), || c.map(|c| c.c_j), mode)?;
|
||||||
|
let c_l = Fp2Var::new_variable(cs.ns("c_l"), || c.map(|c| c.c_l), mode)?;
|
||||||
|
Ok(Self {
|
||||||
c_h,
|
c_h,
|
||||||
c_4c,
|
c_4c,
|
||||||
c_j,
|
c_j,
|
||||||
c_l,
|
c_l,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<AteDoubleCoefficients<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
|
impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for AteDoubleCoefficientsVar<P> {
|
||||||
_cs: CS,
|
|
||||||
_f: F,
|
|
||||||
) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<AteDoubleCoefficients<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for AteDoubleCoefficientsGadget<P> {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(
|
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
&self,
|
let mut c_h = self.c_h.to_bytes()?;
|
||||||
mut cs: CS,
|
let mut c_4c = self.c_4c.to_bytes()?;
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
let mut c_j = self.c_j.to_bytes()?;
|
||||||
let mut c_h = self.c_h.to_bytes(&mut cs.ns(|| "c_h to bytes"))?;
|
let mut c_l = self.c_l.to_bytes()?;
|
||||||
let mut c_4c = self.c_4c.to_bytes(&mut cs.ns(|| "c_4c to bytes"))?;
|
|
||||||
let mut c_j = self.c_j.to_bytes(&mut cs.ns(|| "c_j to bytes"))?;
|
|
||||||
let mut c_l = self.c_l.to_bytes(&mut cs.ns(|| "c_l to bytes"))?;
|
|
||||||
|
|
||||||
c_h.append(&mut c_4c);
|
c_h.append(&mut c_4c);
|
||||||
c_h.append(&mut c_j);
|
c_h.append(&mut c_j);
|
||||||
@@ -487,22 +346,11 @@ impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for AteDoubleCoefficientsGadget<P>
|
|||||||
Ok(c_h)
|
Ok(c_h)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
|
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
&self,
|
let mut c_h = self.c_h.to_non_unique_bytes()?;
|
||||||
mut cs: CS,
|
let mut c_4c = self.c_4c.to_non_unique_bytes()?;
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
let mut c_j = self.c_j.to_non_unique_bytes()?;
|
||||||
let mut c_h = self
|
let mut c_l = self.c_l.to_non_unique_bytes()?;
|
||||||
.c_h
|
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "c_h to bytes"))?;
|
|
||||||
let mut c_4c = self
|
|
||||||
.c_4c
|
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "c_4c to bytes"))?;
|
|
||||||
let mut c_j = self
|
|
||||||
.c_j
|
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "c_j to bytes"))?;
|
|
||||||
let mut c_l = self
|
|
||||||
.c_l
|
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "c_l to bytes"))?;
|
|
||||||
|
|
||||||
c_h.append(&mut c_4c);
|
c_h.append(&mut c_4c);
|
||||||
c_h.append(&mut c_j);
|
c_h.append(&mut c_j);
|
||||||
@@ -511,115 +359,79 @@ impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for AteDoubleCoefficientsGadget<P>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT4Parameters> AteDoubleCoefficientsGadget<P> {
|
impl<P: MNT4Parameters> AteDoubleCoefficientsVar<P> {
|
||||||
pub fn get_value(&self) -> Option<AteDoubleCoefficients<P>> {
|
pub fn value(&self) -> Result<AteDoubleCoefficients<P>, SynthesisError> {
|
||||||
match (
|
let (c_h, c_4c, c_j, c_l) = (
|
||||||
self.c_h.get_value(),
|
self.c_l.value()?,
|
||||||
self.c_4c.get_value(),
|
self.c_4c.value()?,
|
||||||
self.c_j.get_value(),
|
self.c_j.value()?,
|
||||||
self.c_l.get_value(),
|
self.c_l.value()?,
|
||||||
) {
|
);
|
||||||
(Some(c_h), Some(c_4c), Some(c_j), Some(c_l)) => Some(AteDoubleCoefficients {
|
Ok(AteDoubleCoefficients {
|
||||||
c_h,
|
c_h,
|
||||||
c_4c,
|
c_4c,
|
||||||
c_j,
|
c_j,
|
||||||
c_l,
|
c_l,
|
||||||
}),
|
})
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))]
|
#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))]
|
||||||
pub struct AteAdditionCoefficientsGadget<P: MNT4Parameters> {
|
pub struct AteAdditionCoefficientsVar<P: MNT4Parameters> {
|
||||||
pub c_l1: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub c_l1: Fp2Var<P::Fp2Params>,
|
||||||
pub c_rz: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub c_rz: Fp2Var<P::Fp2Params>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT4Parameters> AllocGadget<AteAdditionCoefficients<P>, P::Fp>
|
impl<P: MNT4Parameters> AllocVar<AteAdditionCoefficients<P>, P::Fp>
|
||||||
for AteAdditionCoefficientsGadget<P>
|
for AteAdditionCoefficientsVar<P>
|
||||||
{
|
{
|
||||||
fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
|
fn new_variable<T: Borrow<AteAdditionCoefficients<P>>>(
|
||||||
mut cs: CS,
|
cs: impl Into<Namespace<P::Fp>>,
|
||||||
t: T,
|
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||||
) -> Result<Self, SynthesisError>
|
mode: AllocationMode,
|
||||||
where
|
) -> Result<Self, SynthesisError> {
|
||||||
T: Borrow<AteAdditionCoefficients<P>>,
|
let ns = cs.into();
|
||||||
{
|
let cs = ns.cs();
|
||||||
let obj = t.borrow();
|
|
||||||
let c_l1 = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(
|
|
||||||
&mut cs.ns(|| "alloc_c_l1"),
|
|
||||||
&obj.c_l1,
|
|
||||||
)?;
|
|
||||||
let c_rz = Fp2Gadget::<P::Fp2Params, P::Fp>::alloc_constant(
|
|
||||||
&mut cs.ns(|| "alloc_c_rz"),
|
|
||||||
&obj.c_rz,
|
|
||||||
)?;
|
|
||||||
Ok(AteAdditionCoefficientsGadget { c_l1, c_rz })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
|
let c_prep = f().map(|c| c.borrow().clone());
|
||||||
where
|
let c = c_prep.as_ref().map_err(|e| *e);
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<AteAdditionCoefficients<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
|
let c_l1 = Fp2Var::new_variable(cs.ns("c_l1"), || c.map(|c| c.c_l1), mode)?;
|
||||||
_cs: CS,
|
let c_rz = Fp2Var::new_variable(cs.ns("c_rz"), || c.map(|c| c.c_rz), mode)?;
|
||||||
_f: F,
|
Ok(Self { c_l1, c_rz })
|
||||||
) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<AteAdditionCoefficients<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for AteAdditionCoefficientsGadget<P> {
|
impl<P: MNT4Parameters> ToBytesGadget<P::Fp> for AteAdditionCoefficientsVar<P> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(
|
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
&self,
|
let mut c_l1 = self.c_l1.to_bytes()?;
|
||||||
mut cs: CS,
|
let mut c_rz = self.c_rz.to_bytes()?;
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
|
||||||
let mut c_l1 = self.c_l1.to_bytes(&mut cs.ns(|| "c_l1 to bytes"))?;
|
|
||||||
let mut c_rz = self.c_rz.to_bytes(&mut cs.ns(|| "c_rz to bytes"))?;
|
|
||||||
|
|
||||||
c_l1.append(&mut c_rz);
|
c_l1.append(&mut c_rz);
|
||||||
Ok(c_l1)
|
Ok(c_l1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
|
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
&self,
|
let mut c_l1 = self.c_l1.to_non_unique_bytes()?;
|
||||||
mut cs: CS,
|
let mut c_rz = self.c_rz.to_non_unique_bytes()?;
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
|
||||||
let mut c_l1 = self
|
|
||||||
.c_l1
|
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "c_l1 to bytes"))?;
|
|
||||||
let mut c_rz = self
|
|
||||||
.c_rz
|
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "c_rz to bytes"))?;
|
|
||||||
|
|
||||||
c_l1.append(&mut c_rz);
|
c_l1.append(&mut c_rz);
|
||||||
Ok(c_l1)
|
Ok(c_l1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT4Parameters> AteAdditionCoefficientsGadget<P> {
|
impl<P: MNT4Parameters> AteAdditionCoefficientsVar<P> {
|
||||||
pub fn get_value(&self) -> Option<AteAdditionCoefficients<P>> {
|
pub fn value(&self) -> Result<AteAdditionCoefficients<P>, SynthesisError> {
|
||||||
match (self.c_l1.get_value(), self.c_rz.get_value()) {
|
let (c_l1, c_rz) = (self.c_l1.value()?, self.c_rz.value()?);
|
||||||
(Some(c_l1), Some(c_rz)) => Some(AteAdditionCoefficients { c_l1, c_rz }),
|
Ok(AteAdditionCoefficients { c_l1, c_rz })
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct G2ProjectiveExtendedGadget<P: MNT4Parameters> {
|
pub struct G2ProjectiveExtendedVar<P: MNT4Parameters> {
|
||||||
pub x: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub x: Fp2Var<P::Fp2Params>,
|
||||||
pub y: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub y: Fp2Var<P::Fp2Params>,
|
||||||
pub z: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub z: Fp2Var<P::Fp2Params>,
|
||||||
pub t: Fp2Gadget<P::Fp2Params, P::Fp>,
|
pub t: Fp2Var<P::Fp2Params>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,135 +5,91 @@ use algebra::{
|
|||||||
},
|
},
|
||||||
Field,
|
Field,
|
||||||
};
|
};
|
||||||
use core::borrow::Borrow;
|
use r1cs_core::{Namespace, SynthesisError};
|
||||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fields::{fp::FpGadget, fp3::Fp3Gadget, FieldGadget},
|
fields::{fp::FpVar, fp3::Fp3Var, FieldVar},
|
||||||
groups::curves::short_weierstrass::AffineGadget,
|
groups::curves::short_weierstrass::ProjectiveVar,
|
||||||
pairing::mnt6::PairingGadget,
|
pairing::mnt6::PairingVar,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Vec,
|
Vec,
|
||||||
};
|
};
|
||||||
|
use core::borrow::Borrow;
|
||||||
|
|
||||||
pub type G1Gadget<P> = AffineGadget<
|
pub type G1Var<P> =
|
||||||
<P as MNT6Parameters>::G1Parameters,
|
ProjectiveVar<<P as MNT6Parameters>::G1Parameters, FpVar<<P as MNT6Parameters>::Fp>>;
|
||||||
<P as MNT6Parameters>::Fp,
|
|
||||||
FpGadget<<P as MNT6Parameters>::Fp>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
pub type G2Gadget<P> =
|
pub type G2Var<P> = ProjectiveVar<<P as MNT6Parameters>::G2Parameters, Fp3G<P>>;
|
||||||
AffineGadget<<P as MNT6Parameters>::G2Parameters, <P as MNT6Parameters>::Fp, Fp3G<P>>;
|
|
||||||
|
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
|
#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
|
||||||
pub struct G1PreparedGadget<P: MNT6Parameters> {
|
pub struct G1PreparedVar<P: MNT6Parameters> {
|
||||||
pub x: FpGadget<P::Fp>,
|
pub x: FpVar<P::Fp>,
|
||||||
pub y: FpGadget<P::Fp>,
|
pub y: FpVar<P::Fp>,
|
||||||
pub x_twist: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub x_twist: Fp3Var<P::Fp3Params>,
|
||||||
pub y_twist: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub y_twist: Fp3Var<P::Fp3Params>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT6Parameters> AllocGadget<G1Prepared<P>, P::Fp> for G1PreparedGadget<P> {
|
impl<P: MNT6Parameters> G1PreparedVar<P> {
|
||||||
fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
|
pub fn value(&self) -> Result<G1Prepared<P>, SynthesisError> {
|
||||||
mut cs: CS,
|
let x = self.x.value()?;
|
||||||
t: T,
|
let y = self.y.value()?;
|
||||||
) -> Result<Self, SynthesisError>
|
let x_twist = self.x_twist.value()?;
|
||||||
where
|
let y_twist = self.y_twist.value()?;
|
||||||
T: Borrow<G1Prepared<P>>,
|
Ok(G1Prepared {
|
||||||
{
|
|
||||||
let obj = t.borrow();
|
|
||||||
|
|
||||||
let x_gadget = FpGadget::<P::Fp>::alloc_constant(&mut cs.ns(|| "x"), &obj.x)?;
|
|
||||||
let y_gadget = FpGadget::<P::Fp>::alloc_constant(&mut cs.ns(|| "y"), &obj.y)?;
|
|
||||||
let x_twist_gadget = Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(
|
|
||||||
&mut cs.ns(|| "x_twist"),
|
|
||||||
&obj.x_twist,
|
|
||||||
)?;
|
|
||||||
let y_twist_gadget = Fp3Gadget::<P::Fp3Params, P::Fp>::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<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<G1Prepared<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
|
|
||||||
_cs: CS,
|
|
||||||
_f: F,
|
|
||||||
) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<G1Prepared<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: MNT6Parameters> G1PreparedGadget<P> {
|
|
||||||
pub fn get_value(&self) -> Option<G1Prepared<P>> {
|
|
||||||
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,
|
x,
|
||||||
y,
|
y,
|
||||||
x_twist,
|
x_twist,
|
||||||
y_twist,
|
y_twist,
|
||||||
}),
|
})
|
||||||
_ => None,
|
}
|
||||||
|
|
||||||
|
pub fn from_group_var(q: &G1Var<P>) -> Result<Self, SynthesisError> {
|
||||||
|
let q = q.to_affine()?;
|
||||||
|
let zero = FpVar::<P::Fp>::zero();
|
||||||
|
let x_twist = Fp3Var::new(q.x.clone(), zero.clone(), zero.clone()) * P::TWIST;
|
||||||
|
let y_twist = Fp3Var::new(q.y.clone(), zero.clone(), zero.clone()) * P::TWIST;
|
||||||
|
let result = G1PreparedVar {
|
||||||
|
x: q.x.clone(),
|
||||||
|
y: q.y.clone(),
|
||||||
|
x_twist,
|
||||||
|
y_twist,
|
||||||
|
};
|
||||||
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_affine<CS: ConstraintSystem<P::Fp>>(
|
impl<P: MNT6Parameters> AllocVar<G1Prepared<P>, P::Fp> for G1PreparedVar<P> {
|
||||||
mut cs: CS,
|
fn new_variable<T: Borrow<G1Prepared<P>>>(
|
||||||
q: &G1Gadget<P>,
|
cs: impl Into<Namespace<P::Fp>>,
|
||||||
|
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||||
|
mode: AllocationMode,
|
||||||
) -> Result<Self, SynthesisError> {
|
) -> Result<Self, SynthesisError> {
|
||||||
let x_twist = Fp3Gadget::new(
|
let ns = cs.into();
|
||||||
q.x.mul_by_constant(cs.ns(|| "g1.x * twist.c0"), &P::TWIST.c0)?,
|
let cs = ns.cs();
|
||||||
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 g1_prep = f().map(|b| *b.borrow());
|
||||||
);
|
|
||||||
let y_twist = Fp3Gadget::new(
|
let x = FpVar::new_variable(cs.ns("x"), || g1_prep.map(|g| g.x), mode)?;
|
||||||
q.y.mul_by_constant(cs.ns(|| "g1.y * twist.c0"), &P::TWIST.c0)?,
|
let y = FpVar::new_variable(cs.ns("y"), || g1_prep.map(|g| g.y), mode)?;
|
||||||
q.y.mul_by_constant(cs.ns(|| "g1.y * twist.c1"), &P::TWIST.c1)?,
|
let x_twist = Fp3Var::new_variable(cs.ns("x_twist"), || g1_prep.map(|g| g.x_twist), mode)?;
|
||||||
q.y.mul_by_constant(cs.ns(|| "g1.y * twist.c2"), &P::TWIST.c2)?,
|
let y_twist = Fp3Var::new_variable(cs.ns("y_twist"), || g1_prep.map(|g| g.y_twist), mode)?;
|
||||||
);
|
Ok(Self {
|
||||||
Ok(G1PreparedGadget {
|
x,
|
||||||
x: q.x.clone(),
|
y,
|
||||||
y: q.y.clone(),
|
|
||||||
x_twist,
|
x_twist,
|
||||||
y_twist,
|
y_twist,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for G1PreparedGadget<P> {
|
impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for G1PreparedVar<P> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(
|
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
&self,
|
let mut x = self.x.to_bytes()?;
|
||||||
mut cs: CS,
|
let mut y = self.y.to_bytes()?;
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
let mut x_twist = self.x_twist.to_bytes()?;
|
||||||
let mut x = self.x.to_bytes(&mut cs.ns(|| "x to bytes"))?;
|
let mut y_twist = self.y_twist.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 y);
|
||||||
x.append(&mut x_twist);
|
x.append(&mut x_twist);
|
||||||
@@ -141,18 +97,11 @@ impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for G1PreparedGadget<P> {
|
|||||||
Ok(x)
|
Ok(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
|
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
&self,
|
let mut x = self.x.to_non_unique_bytes()?;
|
||||||
mut cs: CS,
|
let mut y = self.y.to_non_unique_bytes()?;
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
let mut x_twist = self.x_twist.to_non_unique_bytes()?;
|
||||||
let mut x = self.x.to_non_unique_bytes(&mut cs.ns(|| "x to bytes"))?;
|
let mut y_twist = self.y_twist.to_non_unique_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 y);
|
||||||
x.append(&mut x_twist);
|
x.append(&mut x_twist);
|
||||||
@@ -161,203 +110,142 @@ impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for G1PreparedGadget<P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Fp3G<P> = Fp3Gadget<<P as MNT6Parameters>::Fp3Params, <P as MNT6Parameters>::Fp>;
|
type Fp3G<P> = Fp3Var<<P as MNT6Parameters>::Fp3Params>;
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
|
#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
|
||||||
pub struct G2PreparedGadget<P: MNT6Parameters> {
|
pub struct G2PreparedVar<P: MNT6Parameters> {
|
||||||
pub x: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub x: Fp3Var<P::Fp3Params>,
|
||||||
pub y: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub y: Fp3Var<P::Fp3Params>,
|
||||||
pub x_over_twist: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub x_over_twist: Fp3Var<P::Fp3Params>,
|
||||||
pub y_over_twist: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub y_over_twist: Fp3Var<P::Fp3Params>,
|
||||||
pub double_coefficients: Vec<AteDoubleCoefficientsGadget<P>>,
|
pub double_coefficients: Vec<AteDoubleCoefficientsVar<P>>,
|
||||||
pub addition_coefficients: Vec<AteAdditionCoefficientsGadget<P>>,
|
pub addition_coefficients: Vec<AteAdditionCoefficientsVar<P>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT6Parameters> AllocGadget<G2Prepared<P>, P::Fp> for G2PreparedGadget<P> {
|
impl<P: MNT6Parameters> AllocVar<G2Prepared<P>, P::Fp> for G2PreparedVar<P> {
|
||||||
fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
|
fn new_variable<T: Borrow<G2Prepared<P>>>(
|
||||||
mut cs: CS,
|
cs: impl Into<Namespace<P::Fp>>,
|
||||||
t: T,
|
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||||
) -> Result<Self, SynthesisError>
|
mode: AllocationMode,
|
||||||
where
|
) -> Result<Self, SynthesisError> {
|
||||||
T: Borrow<G2Prepared<P>>,
|
let ns = cs.into();
|
||||||
{
|
let cs = ns.cs();
|
||||||
let obj = t.borrow();
|
|
||||||
|
|
||||||
let x_gadget =
|
let g2_prep = f().map(|b| b.borrow().clone());
|
||||||
Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "x"), &obj.x)?;
|
let g2 = g2_prep.as_ref().map_err(|e| *e);
|
||||||
let y_gadget =
|
|
||||||
Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "y"), &obj.y)?;
|
|
||||||
|
|
||||||
let x_over_twist_gadget = Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(
|
let x = Fp3Var::new_variable(cs.ns("x"), || g2.map(|g| g.x), mode)?;
|
||||||
&mut cs.ns(|| "x_over_twist"),
|
let y = Fp3Var::new_variable(cs.ns("y"), || g2.map(|g| g.y), mode)?;
|
||||||
&obj.x_over_twist,
|
let x_over_twist =
|
||||||
|
Fp3Var::new_variable(cs.ns("x_over_twist"), || g2.map(|g| g.x_over_twist), mode)?;
|
||||||
|
let y_over_twist =
|
||||||
|
Fp3Var::new_variable(cs.ns("y_over_twist"), || g2.map(|g| g.y_over_twist), mode)?;
|
||||||
|
let double_coefficients = Vec::new_variable(
|
||||||
|
cs.ns("double coeffs"),
|
||||||
|
|| g2.map(|g| g.double_coefficients.clone()),
|
||||||
|
mode,
|
||||||
)?;
|
)?;
|
||||||
let y_over_twist_gadget = Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(
|
let addition_coefficients = Vec::new_variable(
|
||||||
&mut cs.ns(|| "y_over_twist"),
|
cs.ns("add coeffs"),
|
||||||
&obj.y_over_twist,
|
|| g2.map(|g| g.addition_coefficients.clone()),
|
||||||
|
mode,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut double_coefficients_gadget = Vec::<AteDoubleCoefficientsGadget<P>>::new();
|
|
||||||
for (i, double_coefficient) in obj.double_coefficients.iter().enumerate() {
|
|
||||||
double_coefficients_gadget.push(AteDoubleCoefficientsGadget::<P>::alloc_constant(
|
|
||||||
&mut cs.ns(|| format!("double_coefficient#{}", i)),
|
|
||||||
double_coefficient,
|
|
||||||
)?);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut addition_coefficients_gadget = Vec::<AteAdditionCoefficientsGadget<P>>::new();
|
|
||||||
for (i, addition_coefficient) in obj.addition_coefficients.iter().enumerate() {
|
|
||||||
addition_coefficients_gadget.push(AteAdditionCoefficientsGadget::<P>::alloc_constant(
|
|
||||||
&mut cs.ns(|| format!("addition_coefficient#{}", i)),
|
|
||||||
addition_coefficient,
|
|
||||||
)?);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self {
|
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<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<G2Prepared<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
|
|
||||||
_cs: CS,
|
|
||||||
_f: F,
|
|
||||||
) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<G2Prepared<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for G2PreparedGadget<P> {
|
|
||||||
#[inline]
|
|
||||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(
|
|
||||||
&self,
|
|
||||||
mut cs: CS,
|
|
||||||
) -> Result<Vec<UInt8>, 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<CS: ConstraintSystem<P::Fp>>(
|
|
||||||
&self,
|
|
||||||
mut cs: CS,
|
|
||||||
) -> Result<Vec<UInt8>, 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<P: MNT6Parameters> G2PreparedGadget<P> {
|
|
||||||
pub fn get_value(&self) -> Option<G2Prepared<P>> {
|
|
||||||
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::<Option<Vec<AteDoubleCoefficients<P>>>>(),
|
|
||||||
self.addition_coefficients
|
|
||||||
.iter()
|
|
||||||
.map(|coeff| coeff.get_value())
|
|
||||||
.collect::<Option<Vec<AteAdditionCoefficients<P>>>>(),
|
|
||||||
) {
|
|
||||||
(
|
|
||||||
Some(x),
|
|
||||||
Some(y),
|
|
||||||
Some(x_over_twist),
|
|
||||||
Some(y_over_twist),
|
|
||||||
Some(double_coefficients),
|
|
||||||
Some(addition_coefficients),
|
|
||||||
) => Some(G2Prepared {
|
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
x_over_twist,
|
x_over_twist,
|
||||||
y_over_twist,
|
y_over_twist,
|
||||||
double_coefficients,
|
double_coefficients,
|
||||||
addition_coefficients,
|
addition_coefficients,
|
||||||
}),
|
})
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_affine<CS: ConstraintSystem<P::Fp>>(
|
impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for G2PreparedVar<P> {
|
||||||
mut cs: CS,
|
#[inline]
|
||||||
q: &G2Gadget<P>,
|
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
) -> Result<Self, SynthesisError> {
|
let mut x = self.x.to_bytes()?;
|
||||||
|
let mut y = self.y.to_bytes()?;
|
||||||
|
let mut x_over_twist = self.x_over_twist.to_bytes()?;
|
||||||
|
let mut y_over_twist = self.y_over_twist.to_bytes()?;
|
||||||
|
|
||||||
|
x.append(&mut y);
|
||||||
|
x.append(&mut x_over_twist);
|
||||||
|
x.append(&mut y_over_twist);
|
||||||
|
|
||||||
|
for coeff in self.double_coefficients.iter() {
|
||||||
|
x.extend_from_slice(&coeff.to_bytes()?);
|
||||||
|
}
|
||||||
|
for coeff in self.addition_coefficients.iter() {
|
||||||
|
x.extend_from_slice(&coeff.to_bytes()?);
|
||||||
|
}
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
|
let mut x = self.x.to_non_unique_bytes()?;
|
||||||
|
let mut y = self.y.to_non_unique_bytes()?;
|
||||||
|
let mut x_over_twist = self.x_over_twist.to_non_unique_bytes()?;
|
||||||
|
let mut y_over_twist = self.y_over_twist.to_non_unique_bytes()?;
|
||||||
|
|
||||||
|
x.append(&mut y);
|
||||||
|
x.append(&mut x_over_twist);
|
||||||
|
x.append(&mut y_over_twist);
|
||||||
|
|
||||||
|
for coeff in self.double_coefficients.iter() {
|
||||||
|
x.extend_from_slice(&coeff.to_non_unique_bytes()?);
|
||||||
|
}
|
||||||
|
for coeff in self.addition_coefficients.iter() {
|
||||||
|
x.extend_from_slice(&coeff.to_non_unique_bytes()?);
|
||||||
|
}
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: MNT6Parameters> G2PreparedVar<P> {
|
||||||
|
pub fn value(&self) -> Result<G2Prepared<P>, SynthesisError> {
|
||||||
|
let x = self.x.value()?;
|
||||||
|
let y = self.y.value()?;
|
||||||
|
let x_over_twist = self.x_over_twist.value()?;
|
||||||
|
let y_over_twist = self.y_over_twist.value()?;
|
||||||
|
let double_coefficients = self
|
||||||
|
.double_coefficients
|
||||||
|
.iter()
|
||||||
|
.map(|coeff| coeff.value())
|
||||||
|
.collect::<Result<Vec<_>, SynthesisError>>()?;
|
||||||
|
let addition_coefficients = self
|
||||||
|
.addition_coefficients
|
||||||
|
.iter()
|
||||||
|
.map(|coeff| coeff.value())
|
||||||
|
.collect::<Result<Vec<_>, SynthesisError>>()?;
|
||||||
|
Ok(G2Prepared {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
x_over_twist,
|
||||||
|
y_over_twist,
|
||||||
|
double_coefficients,
|
||||||
|
addition_coefficients,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_group_var(q: &G2Var<P>) -> Result<Self, SynthesisError> {
|
||||||
|
let q = q.to_affine()?;
|
||||||
let twist_inv = P::TWIST.inverse().unwrap();
|
let twist_inv = P::TWIST.inverse().unwrap();
|
||||||
|
|
||||||
let mut g2p = G2PreparedGadget {
|
let mut g2p = G2PreparedVar {
|
||||||
x: q.x.clone(),
|
x: q.x.clone(),
|
||||||
y: q.y.clone(),
|
y: q.y.clone(),
|
||||||
x_over_twist: q.x.mul_by_constant(cs.ns(|| "x over twist"), &twist_inv)?,
|
x_over_twist: &q.x * twist_inv,
|
||||||
y_over_twist: q.y.mul_by_constant(cs.ns(|| "y over twist"), &twist_inv)?,
|
y_over_twist: &q.y * twist_inv,
|
||||||
double_coefficients: vec![],
|
double_coefficients: vec![],
|
||||||
addition_coefficients: vec![],
|
addition_coefficients: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let fp2_one = Fp3G::<P>::one(cs.ns(|| "one"))?;
|
let mut r = G2ProjectiveExtendedVar {
|
||||||
let mut r = G2ProjectiveExtendedGadget {
|
|
||||||
x: q.x.clone(),
|
x: q.x.clone(),
|
||||||
y: q.y.clone(),
|
y: q.y.clone(),
|
||||||
z: fp2_one.clone(),
|
z: Fp3G::<P>::one(),
|
||||||
t: fp2_one,
|
t: Fp3G::<P>::one(),
|
||||||
};
|
};
|
||||||
|
|
||||||
for (idx, value) in P::ATE_LOOP_COUNT.iter().rev().enumerate() {
|
for (idx, value) in P::ATE_LOOP_COUNT.iter().rev().enumerate() {
|
||||||
@@ -372,23 +260,14 @@ impl<P: MNT6Parameters> G2PreparedGadget<P> {
|
|||||||
tmp >>= 1;
|
tmp >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cs = cs.ns(|| format!("ate loop iteration {}", idx));
|
for bit in v.iter().rev() {
|
||||||
|
let (r2, coeff) = PairingVar::<P>::doubling_step_for_flipped_miller_loop(&r)?;
|
||||||
for (j, bit) in v.iter().rev().enumerate() {
|
|
||||||
let (r2, coeff) = PairingGadget::<P>::doubling_step_for_flipped_miller_loop(
|
|
||||||
cs.ns(|| format!("doubling step {}", j)),
|
|
||||||
&r,
|
|
||||||
)?;
|
|
||||||
g2p.double_coefficients.push(coeff);
|
g2p.double_coefficients.push(coeff);
|
||||||
r = r2;
|
r = r2;
|
||||||
|
|
||||||
if *bit {
|
if *bit {
|
||||||
let (r2, coeff) =
|
let (r2, coeff) = PairingVar::<P>::mixed_addition_step_for_flipped_miller_loop(
|
||||||
PairingGadget::<P>::mixed_addition_step_for_flipped_miller_loop(
|
&q.x, &q.y, &r,
|
||||||
cs.ns(|| format!("mixed addition step {}", j)),
|
|
||||||
&q.x,
|
|
||||||
&q.y,
|
|
||||||
&r,
|
|
||||||
)?;
|
)?;
|
||||||
g2p.addition_coefficients.push(coeff);
|
g2p.addition_coefficients.push(coeff);
|
||||||
r = r2;
|
r = r2;
|
||||||
@@ -399,17 +278,14 @@ impl<P: MNT6Parameters> G2PreparedGadget<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if P::ATE_IS_LOOP_COUNT_NEG {
|
if P::ATE_IS_LOOP_COUNT_NEG {
|
||||||
let rz_inv = r.z.inverse(cs.ns(|| "inverse r.z"))?;
|
let rz_inv = r.z.inverse()?;
|
||||||
let rz2_inv = rz_inv.square(cs.ns(|| "rz_inv^2"))?;
|
let rz2_inv = rz_inv.square()?;
|
||||||
let rz3_inv = rz_inv.mul(cs.ns(|| "rz_inv * rz_inv^2"), &rz2_inv)?;
|
let rz3_inv = &rz_inv * &rz2_inv;
|
||||||
|
|
||||||
let minus_r_affine_x = r.x.mul(cs.ns(|| "r.x * rz2_inv"), &rz2_inv)?;
|
let minus_r_affine_x = &r.x * &rz2_inv;
|
||||||
let minus_r_affine_y =
|
let minus_r_affine_y = r.y.negate()? * &rz3_inv;
|
||||||
r.y.negate(cs.ns(|| "-r.y"))?
|
|
||||||
.mul(cs.ns(|| "-r.y * rz3_inv"), &rz3_inv)?;
|
|
||||||
|
|
||||||
let add_result = PairingGadget::<P>::mixed_addition_step_for_flipped_miller_loop(
|
let add_result = PairingVar::<P>::mixed_addition_step_for_flipped_miller_loop(
|
||||||
cs.ns(|| "mixed_addition step"),
|
|
||||||
&minus_r_affine_x,
|
&minus_r_affine_x,
|
||||||
&minus_r_affine_y,
|
&minus_r_affine_y,
|
||||||
&r,
|
&r,
|
||||||
@@ -423,208 +299,137 @@ impl<P: MNT6Parameters> G2PreparedGadget<P> {
|
|||||||
|
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
|
#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
|
||||||
pub struct AteDoubleCoefficientsGadget<P: MNT6Parameters> {
|
pub struct AteDoubleCoefficientsVar<P: MNT6Parameters> {
|
||||||
pub c_h: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub c_h: Fp3Var<P::Fp3Params>,
|
||||||
pub c_4c: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub c_4c: Fp3Var<P::Fp3Params>,
|
||||||
pub c_j: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub c_j: Fp3Var<P::Fp3Params>,
|
||||||
pub c_l: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub c_l: Fp3Var<P::Fp3Params>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT6Parameters> AllocGadget<AteDoubleCoefficients<P>, P::Fp>
|
impl<P: MNT6Parameters> AllocVar<AteDoubleCoefficients<P>, P::Fp> for AteDoubleCoefficientsVar<P> {
|
||||||
for AteDoubleCoefficientsGadget<P>
|
fn new_variable<T: Borrow<AteDoubleCoefficients<P>>>(
|
||||||
{
|
cs: impl Into<Namespace<P::Fp>>,
|
||||||
fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
|
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||||
mut cs: CS,
|
mode: AllocationMode,
|
||||||
t: T,
|
) -> Result<Self, SynthesisError> {
|
||||||
) -> Result<Self, SynthesisError>
|
let ns = cs.into();
|
||||||
where
|
let cs = ns.cs();
|
||||||
T: Borrow<AteDoubleCoefficients<P>>,
|
|
||||||
{
|
|
||||||
let obj = t.borrow();
|
|
||||||
|
|
||||||
let c_h_gadget =
|
let c_prep = f().map(|c| c.borrow().clone());
|
||||||
Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "c_h"), &obj.c_h)?;
|
let c = c_prep.as_ref().map_err(|e| *e);
|
||||||
let c_4c_gadget =
|
|
||||||
Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "c_4c"), &obj.c_4c)?;
|
|
||||||
let c_j_gadget =
|
|
||||||
Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "c_j"), &obj.c_j)?;
|
|
||||||
let c_l_gadget =
|
|
||||||
Fp3Gadget::<P::Fp3Params, P::Fp>::alloc_constant(&mut cs.ns(|| "c_l"), &obj.c_l)?;
|
|
||||||
|
|
||||||
|
let c_h = Fp3Var::new_variable(cs.ns("c_h"), || c.map(|c| c.c_h), mode)?;
|
||||||
|
let c_4c = Fp3Var::new_variable(cs.ns("c_4c"), || c.map(|c| c.c_4c), mode)?;
|
||||||
|
let c_j = Fp3Var::new_variable(cs.ns("c_j"), || c.map(|c| c.c_j), mode)?;
|
||||||
|
let c_l = Fp3Var::new_variable(cs.ns("c_l"), || c.map(|c| c.c_l), mode)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
c_h: c_h_gadget,
|
|
||||||
c_4c: c_4c_gadget,
|
|
||||||
c_j: c_j_gadget,
|
|
||||||
c_l: c_l_gadget,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<AteDoubleCoefficients<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
|
|
||||||
_cs: CS,
|
|
||||||
_f: F,
|
|
||||||
) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<AteDoubleCoefficients<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for AteDoubleCoefficientsGadget<P> {
|
|
||||||
#[inline]
|
|
||||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(
|
|
||||||
&self,
|
|
||||||
mut cs: CS,
|
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
|
||||||
let mut c_h = self.c_h.to_bytes(&mut cs.ns(|| "c_h to bytes"))?;
|
|
||||||
let mut c_4c = self.c_4c.to_bytes(&mut cs.ns(|| "c_4c to bytes"))?;
|
|
||||||
let mut c_j = self.c_j.to_bytes(&mut cs.ns(|| "c_j to bytes"))?;
|
|
||||||
let mut c_l = self.c_l.to_bytes(&mut cs.ns(|| "c_l to bytes"))?;
|
|
||||||
|
|
||||||
c_h.append(&mut c_4c);
|
|
||||||
c_h.append(&mut c_j);
|
|
||||||
c_h.append(&mut c_l);
|
|
||||||
Ok(c_h)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
|
|
||||||
&self,
|
|
||||||
mut cs: CS,
|
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
|
||||||
let mut c_h = self
|
|
||||||
.c_h
|
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "c_h to bytes"))?;
|
|
||||||
let mut c_4c = self
|
|
||||||
.c_4c
|
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "c_4c to bytes"))?;
|
|
||||||
let mut c_j = self
|
|
||||||
.c_j
|
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "c_j to bytes"))?;
|
|
||||||
let mut c_l = self
|
|
||||||
.c_l
|
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "c_l to bytes"))?;
|
|
||||||
|
|
||||||
c_h.append(&mut c_4c);
|
|
||||||
c_h.append(&mut c_j);
|
|
||||||
c_h.append(&mut c_l);
|
|
||||||
Ok(c_h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: MNT6Parameters> AteDoubleCoefficientsGadget<P> {
|
|
||||||
pub fn get_value(&self) -> Option<AteDoubleCoefficients<P>> {
|
|
||||||
match (
|
|
||||||
self.c_h.get_value(),
|
|
||||||
self.c_4c.get_value(),
|
|
||||||
self.c_j.get_value(),
|
|
||||||
self.c_l.get_value(),
|
|
||||||
) {
|
|
||||||
(Some(c_h), Some(c_4c), Some(c_j), Some(c_l)) => Some(AteDoubleCoefficients {
|
|
||||||
c_h,
|
c_h,
|
||||||
c_4c,
|
c_4c,
|
||||||
c_j,
|
c_j,
|
||||||
c_l,
|
c_l,
|
||||||
}),
|
})
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for AteDoubleCoefficientsVar<P> {
|
||||||
|
#[inline]
|
||||||
|
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
|
let mut c_h = self.c_h.to_bytes()?;
|
||||||
|
let mut c_4c = self.c_4c.to_bytes()?;
|
||||||
|
let mut c_j = self.c_j.to_bytes()?;
|
||||||
|
let mut c_l = self.c_l.to_bytes()?;
|
||||||
|
|
||||||
|
c_h.append(&mut c_4c);
|
||||||
|
c_h.append(&mut c_j);
|
||||||
|
c_h.append(&mut c_l);
|
||||||
|
Ok(c_h)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
|
let mut c_h = self.c_h.to_non_unique_bytes()?;
|
||||||
|
let mut c_4c = self.c_4c.to_non_unique_bytes()?;
|
||||||
|
let mut c_j = self.c_j.to_non_unique_bytes()?;
|
||||||
|
let mut c_l = self.c_l.to_non_unique_bytes()?;
|
||||||
|
|
||||||
|
c_h.append(&mut c_4c);
|
||||||
|
c_h.append(&mut c_j);
|
||||||
|
c_h.append(&mut c_l);
|
||||||
|
Ok(c_h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: MNT6Parameters> AteDoubleCoefficientsVar<P> {
|
||||||
|
pub fn value(&self) -> Result<AteDoubleCoefficients<P>, SynthesisError> {
|
||||||
|
let c_h = self.c_h.value()?;
|
||||||
|
let c_4c = self.c_4c.value()?;
|
||||||
|
let c_j = self.c_j.value()?;
|
||||||
|
let c_l = self.c_l.value()?;
|
||||||
|
Ok(AteDoubleCoefficients {
|
||||||
|
c_h,
|
||||||
|
c_4c,
|
||||||
|
c_j,
|
||||||
|
c_l,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
|
#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))]
|
||||||
pub struct AteAdditionCoefficientsGadget<P: MNT6Parameters> {
|
pub struct AteAdditionCoefficientsVar<P: MNT6Parameters> {
|
||||||
pub c_l1: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub c_l1: Fp3Var<P::Fp3Params>,
|
||||||
pub c_rz: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub c_rz: Fp3Var<P::Fp3Params>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT6Parameters> AllocGadget<AteAdditionCoefficients<P>, P::Fp>
|
impl<P: MNT6Parameters> AllocVar<AteAdditionCoefficients<P>, P::Fp>
|
||||||
for AteAdditionCoefficientsGadget<P>
|
for AteAdditionCoefficientsVar<P>
|
||||||
{
|
{
|
||||||
fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
|
fn new_variable<T: Borrow<AteAdditionCoefficients<P>>>(
|
||||||
mut cs: CS,
|
cs: impl Into<Namespace<P::Fp>>,
|
||||||
t: T,
|
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||||
) -> Result<Self, SynthesisError>
|
mode: AllocationMode,
|
||||||
where
|
) -> Result<Self, SynthesisError> {
|
||||||
T: Borrow<AteAdditionCoefficients<P>>,
|
let ns = cs.into();
|
||||||
{
|
let cs = ns.cs();
|
||||||
let t = t.borrow();
|
|
||||||
|
|
||||||
let c_l1 = Fp3Gadget::alloc_constant(&mut cs.ns(|| "c_l1"), &t.c_l1)?;
|
let c_prep = f().map(|c| c.borrow().clone());
|
||||||
let c_rz = Fp3Gadget::alloc_constant(&mut cs.ns(|| "c_rz"), &t.c_rz)?;
|
let c = c_prep.as_ref().map_err(|e| *e);
|
||||||
|
|
||||||
|
let c_l1 = Fp3Var::new_variable(cs.ns("c_l1"), || c.map(|c| c.c_l1), mode)?;
|
||||||
|
let c_rz = Fp3Var::new_variable(cs.ns("c_rz"), || c.map(|c| c.c_rz), mode)?;
|
||||||
Ok(Self { c_l1, c_rz })
|
Ok(Self { c_l1, c_rz })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<AteAdditionCoefficients<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
|
impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for AteAdditionCoefficientsVar<P> {
|
||||||
_cs: CS,
|
|
||||||
_f: F,
|
|
||||||
) -> Result<Self, SynthesisError>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<AteAdditionCoefficients<P>>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: MNT6Parameters> ToBytesGadget<P::Fp> for AteAdditionCoefficientsGadget<P> {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(
|
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
&self,
|
let mut c_l1 = self.c_l1.to_bytes()?;
|
||||||
mut cs: CS,
|
let mut c_rz = self.c_rz.to_bytes()?;
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
|
||||||
let mut c_l1 = self.c_l1.to_bytes(&mut cs.ns(|| "c_l1 to bytes"))?;
|
|
||||||
let mut c_rz = self.c_rz.to_bytes(&mut cs.ns(|| "c_rz to bytes"))?;
|
|
||||||
|
|
||||||
c_l1.append(&mut c_rz);
|
c_l1.append(&mut c_rz);
|
||||||
Ok(c_l1)
|
Ok(c_l1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
|
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||||
&self,
|
let mut c_l1 = self.c_l1.to_non_unique_bytes()?;
|
||||||
mut cs: CS,
|
let mut c_rz = self.c_rz.to_non_unique_bytes()?;
|
||||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
|
||||||
let mut c_l1 = self
|
|
||||||
.c_l1
|
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "c_l1 to bytes"))?;
|
|
||||||
let mut c_rz = self
|
|
||||||
.c_rz
|
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "c_rz to bytes"))?;
|
|
||||||
|
|
||||||
c_l1.append(&mut c_rz);
|
c_l1.append(&mut c_rz);
|
||||||
Ok(c_l1)
|
Ok(c_l1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: MNT6Parameters> AteAdditionCoefficientsGadget<P> {
|
impl<P: MNT6Parameters> AteAdditionCoefficientsVar<P> {
|
||||||
pub fn get_value(&self) -> Option<AteAdditionCoefficients<P>> {
|
pub fn value(&self) -> Result<AteAdditionCoefficients<P>, SynthesisError> {
|
||||||
match (self.c_l1.get_value(), self.c_rz.get_value()) {
|
let c_l1 = self.c_l1.value()?;
|
||||||
(Some(c_l1), Some(c_rz)) => Some(AteAdditionCoefficients { c_l1, c_rz }),
|
let c_rz = self.c_rz.value()?;
|
||||||
_ => None,
|
Ok(AteAdditionCoefficients { c_l1, c_rz })
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct G2ProjectiveExtendedGadget<P: MNT6Parameters> {
|
pub struct G2ProjectiveExtendedVar<P: MNT6Parameters> {
|
||||||
pub x: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub x: Fp3Var<P::Fp3Params>,
|
||||||
pub y: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub y: Fp3Var<P::Fp3Params>,
|
||||||
pub z: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub z: Fp3Var<P::Fp3Params>,
|
||||||
pub t: Fp3Gadget<P::Fp3Params, P::Fp>,
|
pub t: Fp3Var<P::Fp3Params>,
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,222 +1,214 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use algebra::{Field, Group};
|
use algebra::{Field, ProjectiveCurve};
|
||||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
use core::ops::{Add, AddAssign, Sub, SubAssign};
|
||||||
|
use r1cs_core::{Namespace, SynthesisError};
|
||||||
|
|
||||||
use core::{borrow::Borrow, fmt::Debug};
|
use core::{borrow::Borrow, fmt::Debug};
|
||||||
|
|
||||||
pub mod curves;
|
pub mod curves;
|
||||||
|
|
||||||
pub use self::curves::short_weierstrass::{bls12, mnt4, mnt6};
|
pub use self::curves::short_weierstrass::bls12;
|
||||||
|
pub use self::curves::short_weierstrass::mnt4;
|
||||||
|
pub use self::curves::short_weierstrass::mnt6;
|
||||||
|
|
||||||
pub trait GroupGadget<G: Group, ConstraintF: Field>:
|
/// A hack used to work around the lack of implied bounds.
|
||||||
|
pub trait GroupOpsBounds<'a, F, T: 'a>:
|
||||||
Sized
|
Sized
|
||||||
+ ToBytesGadget<ConstraintF>
|
+ Add<&'a T, Output = T>
|
||||||
+ NEqGadget<ConstraintF>
|
+ Sub<&'a T, Output = T>
|
||||||
+ EqGadget<ConstraintF>
|
+ Add<T, Output = T>
|
||||||
+ ToBitsGadget<ConstraintF>
|
+ Sub<T, Output = T>
|
||||||
+ CondSelectGadget<ConstraintF>
|
+ Add<F, Output = T>
|
||||||
+ AllocGadget<G, ConstraintF>
|
+ Sub<F, Output = T>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait CurveVar<C: ProjectiveCurve, ConstraintF: Field>:
|
||||||
|
'static
|
||||||
|
+ Sized
|
||||||
+ Clone
|
+ Clone
|
||||||
+ Debug
|
+ Debug
|
||||||
|
+ R1CSVar<ConstraintF, Value = C>
|
||||||
|
+ ToBitsGadget<ConstraintF>
|
||||||
|
+ ToBytesGadget<ConstraintF>
|
||||||
|
+ EqGadget<ConstraintF>
|
||||||
|
+ CondSelectGadget<ConstraintF>
|
||||||
|
+ AllocVar<C, ConstraintF>
|
||||||
|
+ AllocVar<C::Affine, ConstraintF>
|
||||||
|
+ for<'a> GroupOpsBounds<'a, C, Self>
|
||||||
|
+ for<'a> AddAssign<&'a Self>
|
||||||
|
+ for<'a> SubAssign<&'a Self>
|
||||||
|
+ AddAssign<C>
|
||||||
|
+ SubAssign<C>
|
||||||
|
+ AddAssign<Self>
|
||||||
|
+ SubAssign<Self>
|
||||||
{
|
{
|
||||||
type Value: Debug;
|
fn constant(other: C) -> Self;
|
||||||
type Variable;
|
|
||||||
|
|
||||||
fn get_value(&self) -> Option<Self::Value>;
|
fn zero() -> Self;
|
||||||
|
|
||||||
fn get_variable(&self) -> Self::Variable;
|
fn is_zero(&self) -> Result<Boolean<ConstraintF>, SynthesisError> {
|
||||||
|
self.is_eq(&Self::zero())
|
||||||
fn zero<CS: ConstraintSystem<ConstraintF>>(cs: CS) -> Result<Self, SynthesisError>;
|
|
||||||
|
|
||||||
fn add<CS: ConstraintSystem<ConstraintF>>(
|
|
||||||
&self,
|
|
||||||
cs: CS,
|
|
||||||
other: &Self,
|
|
||||||
) -> Result<Self, SynthesisError>;
|
|
||||||
|
|
||||||
fn sub<CS: ConstraintSystem<ConstraintF>>(
|
|
||||||
&self,
|
|
||||||
mut cs: CS,
|
|
||||||
other: &Self,
|
|
||||||
) -> Result<Self, SynthesisError> {
|
|
||||||
let neg_other = other.negate(cs.ns(|| "Negate other"))?;
|
|
||||||
self.add(cs.ns(|| "Self - other"), &neg_other)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_constant<CS: ConstraintSystem<ConstraintF>>(
|
/// Allocate a variable in the subgroup without checking if it's in the
|
||||||
&self,
|
/// prime-order subgroup
|
||||||
cs: CS,
|
fn new_variable_omit_prime_order_check(
|
||||||
other: &G,
|
cs: impl Into<Namespace<ConstraintF>>,
|
||||||
|
f: impl FnOnce() -> Result<C, SynthesisError>,
|
||||||
|
mode: AllocationMode,
|
||||||
) -> Result<Self, SynthesisError>;
|
) -> Result<Self, SynthesisError>;
|
||||||
|
|
||||||
fn sub_constant<CS: ConstraintSystem<ConstraintF>>(
|
/// Enforce that `self` is in the prime-order subgroup.
|
||||||
&self,
|
fn enforce_prime_order(&self) -> Result<(), SynthesisError>;
|
||||||
mut cs: CS,
|
|
||||||
other: &G,
|
fn double(&self) -> Result<Self, SynthesisError> {
|
||||||
) -> Result<Self, SynthesisError> {
|
let mut result = self.clone();
|
||||||
let neg_other = -(*other);
|
result.double_in_place()?;
|
||||||
self.add_constant(cs.ns(|| "Self - other"), &neg_other)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn double_in_place<CS: ConstraintSystem<ConstraintF>>(
|
fn double_in_place(&mut self) -> Result<(), SynthesisError>;
|
||||||
&mut self,
|
|
||||||
cs: CS,
|
|
||||||
) -> Result<(), SynthesisError>;
|
|
||||||
|
|
||||||
fn negate<CS: ConstraintSystem<ConstraintF>>(&self, cs: CS) -> Result<Self, SynthesisError>;
|
fn negate(&self) -> Result<Self, SynthesisError>;
|
||||||
|
|
||||||
/// Inputs must be specified in *little-endian* form.
|
/// Inputs must be specified in *little-endian* form.
|
||||||
/// If the addition law is incomplete for the identity element,
|
/// If the addition law is incomplete for the identity element,
|
||||||
/// `result` must not be the identity element.
|
/// `result` must not be the identity element.
|
||||||
fn mul_bits<'a, CS: ConstraintSystem<ConstraintF>>(
|
fn mul_bits<'a>(
|
||||||
&self,
|
&self,
|
||||||
mut cs: CS,
|
bits: impl Iterator<Item = &'a Boolean<ConstraintF>>,
|
||||||
result: &Self,
|
|
||||||
bits: impl Iterator<Item = &'a Boolean>,
|
|
||||||
) -> Result<Self, SynthesisError> {
|
) -> Result<Self, SynthesisError> {
|
||||||
let mut power = self.clone();
|
let mut power = self.clone();
|
||||||
let mut result = result.clone();
|
let mut result = Self::zero();
|
||||||
for (i, bit) in bits.enumerate() {
|
for bit in bits {
|
||||||
let new_encoded = result.add(&mut cs.ns(|| format!("Add {}-th power", i)), &power)?;
|
let new_encoded = result.clone() + &power;
|
||||||
result = Self::conditionally_select(
|
result = bit.borrow().select(&new_encoded, &result)?;
|
||||||
&mut cs.ns(|| format!("Select {}", i)),
|
power.double_in_place()?;
|
||||||
bit.borrow(),
|
|
||||||
&new_encoded,
|
|
||||||
&result,
|
|
||||||
)?;
|
|
||||||
power.double_in_place(&mut cs.ns(|| format!("{}-th Doubling", i)))?;
|
|
||||||
}
|
}
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn precomputed_base_scalar_mul<'a, CS, I, B>(
|
fn precomputed_base_scalar_mul<'a, I, B>(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut cs: CS,
|
|
||||||
scalar_bits_with_base_powers: I,
|
scalar_bits_with_base_powers: I,
|
||||||
) -> Result<(), SynthesisError>
|
) -> Result<(), SynthesisError>
|
||||||
where
|
where
|
||||||
CS: ConstraintSystem<ConstraintF>,
|
I: Iterator<Item = (B, &'a C)>,
|
||||||
I: Iterator<Item = (B, &'a G)>,
|
B: Borrow<Boolean<ConstraintF>>,
|
||||||
B: Borrow<Boolean>,
|
C: 'a,
|
||||||
G: 'a,
|
|
||||||
{
|
{
|
||||||
for (i, (bit, base_power)) in scalar_bits_with_base_powers.enumerate() {
|
for (bit, base_power) in scalar_bits_with_base_powers {
|
||||||
let new_encoded = self.add_constant(
|
let new_encoded = self.clone() + *base_power;
|
||||||
&mut cs.ns(|| format!("Add {}-th base power", i)),
|
*self = bit.borrow().select(&new_encoded, self)?;
|
||||||
&base_power,
|
|
||||||
)?;
|
|
||||||
*self = Self::conditionally_select(
|
|
||||||
&mut cs.ns(|| format!("Conditional Select {}", i)),
|
|
||||||
bit.borrow(),
|
|
||||||
&new_encoded,
|
|
||||||
&self,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn precomputed_base_3_bit_signed_digit_scalar_mul<'a, CS, I, J, B>(
|
fn precomputed_base_3_bit_signed_digit_scalar_mul<'a, I, J, B>(
|
||||||
_: CS,
|
|
||||||
_: &[B],
|
_: &[B],
|
||||||
_: &[J],
|
_: &[J],
|
||||||
) -> Result<Self, SynthesisError>
|
) -> Result<Self, SynthesisError>
|
||||||
where
|
where
|
||||||
CS: ConstraintSystem<ConstraintF>,
|
I: Borrow<[Boolean<ConstraintF>]>,
|
||||||
I: Borrow<[Boolean]>,
|
|
||||||
J: Borrow<[I]>,
|
J: Borrow<[I]>,
|
||||||
B: Borrow<[G]>,
|
B: Borrow<[C]>,
|
||||||
{
|
{
|
||||||
Err(SynthesisError::AssignmentMissing)
|
Err(SynthesisError::AssignmentMissing)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn precomputed_base_multiscalar_mul<'a, CS, T, I, B>(
|
fn precomputed_base_multiscalar_mul<'a, T, I, B>(
|
||||||
mut cs: CS,
|
|
||||||
bases: &[B],
|
bases: &[B],
|
||||||
scalars: I,
|
scalars: I,
|
||||||
) -> Result<Self, SynthesisError>
|
) -> Result<Self, SynthesisError>
|
||||||
where
|
where
|
||||||
CS: ConstraintSystem<ConstraintF>,
|
|
||||||
T: 'a + ToBitsGadget<ConstraintF> + ?Sized,
|
T: 'a + ToBitsGadget<ConstraintF> + ?Sized,
|
||||||
I: Iterator<Item = &'a T>,
|
I: Iterator<Item = &'a T>,
|
||||||
B: Borrow<[G]>,
|
B: Borrow<[C]>,
|
||||||
{
|
{
|
||||||
let mut result = Self::zero(&mut cs.ns(|| "Declare Result"))?;
|
let mut result = Self::zero();
|
||||||
// Compute ∏(h_i^{m_i}) for all i.
|
// Compute ∏(h_i^{m_i}) for all i.
|
||||||
for (i, (bits, base_powers)) in scalars.zip(bases).enumerate() {
|
for (bits, base_powers) in scalars.zip(bases) {
|
||||||
let base_powers = base_powers.borrow();
|
let base_powers = base_powers.borrow();
|
||||||
let bits = bits.to_bits(&mut cs.ns(|| format!("Convert Scalar {} to bits", i)))?;
|
let bits = bits.to_bits()?;
|
||||||
result.precomputed_base_scalar_mul(
|
result.precomputed_base_scalar_mul(bits.iter().zip(base_powers))?;
|
||||||
cs.ns(|| format!("Chunk {}", i)),
|
|
||||||
bits.iter().zip(base_powers),
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cost_of_add() -> usize;
|
|
||||||
|
|
||||||
fn cost_of_double() -> usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use algebra::{test_rng, Field};
|
use algebra::{test_rng, Field, ProjectiveCurve};
|
||||||
use r1cs_core::ConstraintSystem;
|
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||||
|
|
||||||
use crate::{prelude::*, test_constraint_system::TestConstraintSystem};
|
use crate::prelude::*;
|
||||||
use algebra::groups::Group;
|
|
||||||
|
|
||||||
pub(crate) fn group_test<ConstraintF: Field, G: Group, GG: GroupGadget<G, ConstraintF>>() {
|
pub(crate) fn group_test<C: ProjectiveCurve, ConstraintF: Field, GG: CurveVar<C, ConstraintF>>(
|
||||||
let mut cs = TestConstraintSystem::<ConstraintF>::new();
|
) -> Result<(), SynthesisError>
|
||||||
|
where
|
||||||
|
for<'a> &'a GG: GroupOpsBounds<'a, C, GG>,
|
||||||
|
{
|
||||||
|
let cs = ConstraintSystem::<ConstraintF>::new_ref();
|
||||||
|
|
||||||
let mut rng = test_rng();
|
let mut rng = test_rng();
|
||||||
let a_native = G::rand(&mut rng);
|
let a_native = C::rand(&mut rng);
|
||||||
let b_native = G::rand(&mut rng);
|
let b_native = C::rand(&mut rng);
|
||||||
let a = GG::alloc(&mut cs.ns(|| "generate_a"), || Ok(a_native)).unwrap();
|
let a = GG::new_witness(cs.ns("generate_a"), || Ok(a_native)).unwrap();
|
||||||
let b = GG::alloc(&mut cs.ns(|| "generate_b"), || Ok(b_native)).unwrap();
|
let b = GG::new_witness(cs.ns("generate_b"), || Ok(b_native)).unwrap();
|
||||||
|
|
||||||
let zero = GG::zero(cs.ns(|| "Zero")).unwrap();
|
let zero = GG::zero();
|
||||||
assert_eq!(zero, zero);
|
assert_eq!(zero.value()?, zero.value()?);
|
||||||
|
|
||||||
// a == a
|
// a == a
|
||||||
assert_eq!(a, a);
|
assert_eq!(a.value()?, a.value()?);
|
||||||
// a + 0 = a
|
// a + 0 = a
|
||||||
assert_eq!(a.add(cs.ns(|| "a_plus_zero"), &zero).unwrap(), a);
|
assert_eq!((&a + &zero).value()?, a.value()?);
|
||||||
// a - 0 = a
|
// a - 0 = a
|
||||||
assert_eq!(a.sub(cs.ns(|| "a_minus_zero"), &zero).unwrap(), a);
|
assert_eq!((&a - &zero).value()?, a.value()?);
|
||||||
// a - a = 0
|
// a - a = 0
|
||||||
assert_eq!(a.sub(cs.ns(|| "a_minus_a"), &a).unwrap(), zero);
|
assert_eq!((&a - &a).value()?, zero.value()?);
|
||||||
// a + b = b + a
|
// a + b = b + a
|
||||||
let a_b = a.add(cs.ns(|| "a_plus_b"), &b).unwrap();
|
let a_b = &a + &b;
|
||||||
let b_a = b.add(cs.ns(|| "b_plus_a"), &a).unwrap();
|
let b_a = &b + &a;
|
||||||
assert_eq!(a_b, b_a);
|
assert_eq!(a_b.value()?, b_a.value()?);
|
||||||
|
a_b.enforce_equal(&b_a)?;
|
||||||
|
assert!(cs.is_satisfied().unwrap());
|
||||||
|
|
||||||
// (a + b) + a = a + (b + a)
|
// (a + b) + a = a + (b + a)
|
||||||
let ab_a = a_b.add(&mut cs.ns(|| "a_b_plus_a"), &a).unwrap();
|
let ab_a = &a_b + &a;
|
||||||
let a_ba = a.add(&mut cs.ns(|| "a_plus_b_a"), &b_a).unwrap();
|
let a_ba = &a + &b_a;
|
||||||
assert_eq!(ab_a, a_ba);
|
assert_eq!(ab_a.value()?, a_ba.value()?);
|
||||||
|
ab_a.enforce_equal(&a_ba)?;
|
||||||
|
assert!(cs.is_satisfied().unwrap());
|
||||||
|
|
||||||
// a.double() = a + a
|
// a.double() = a + a
|
||||||
let a_a = a.add(cs.ns(|| "a + a"), &a).unwrap();
|
let a_a = &a + &a;
|
||||||
let mut a2 = a.clone();
|
let mut a2 = a.clone();
|
||||||
a2.double_in_place(cs.ns(|| "2a")).unwrap();
|
a2.double_in_place()?;
|
||||||
assert_eq!(a2, a_a);
|
a2.enforce_equal(&a_a)?;
|
||||||
|
assert_eq!(a2.value()?, a_native.double());
|
||||||
|
assert_eq!(a_a.value()?, a_native.double());
|
||||||
|
assert_eq!(a2.value()?, a_a.value()?);
|
||||||
|
assert!(cs.is_satisfied().unwrap());
|
||||||
|
|
||||||
// b.double() = b + b
|
// b.double() = b + b
|
||||||
let mut b2 = b.clone();
|
let mut b2 = b.clone();
|
||||||
b2.double_in_place(cs.ns(|| "2b")).unwrap();
|
b2.double_in_place()?;
|
||||||
let b_b = b.add(cs.ns(|| "b + b"), &b).unwrap();
|
let b_b = &b + &b;
|
||||||
assert_eq!(b2, b_b);
|
b2.enforce_equal(&b_b)?;
|
||||||
|
assert!(cs.is_satisfied().unwrap());
|
||||||
|
assert_eq!(b2.value()?, b_b.value()?);
|
||||||
|
|
||||||
let _ = a.to_bytes(&mut cs.ns(|| "ToBytes")).unwrap();
|
let _ = a.to_bytes()?;
|
||||||
let _ = a
|
let _ = a.to_non_unique_bytes()?;
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "ToBytes Strict"))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let _ = b.to_bytes(&mut cs.ns(|| "b ToBytes")).unwrap();
|
let _ = b.to_bytes()?;
|
||||||
let _ = b
|
let _ = b.to_non_unique_bytes()?;
|
||||||
.to_non_unique_bytes(&mut cs.ns(|| "b ToBytes Strict"))
|
if !cs.is_satisfied().unwrap() {
|
||||||
.unwrap();
|
|
||||||
if !cs.is_satisfied() {
|
|
||||||
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
||||||
}
|
}
|
||||||
assert!(cs.is_satisfied());
|
assert!(cs.is_satisfied().unwrap());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user