use std::{borrow::Borrow, marker::PhantomData, ops::Neg};
use snarkvm_curves::{
templates::short_weierstrass_jacobian::{Affine as SWAffine, Projective as SWProjective},
traits::{AffineCurve, ProjectiveCurve, ShortWeierstrassParameters},
};
use snarkvm_fields::{Field, One, PrimeField, Zero};
use snarkvm_r1cs::{errors::SynthesisError, Assignment, ConstraintSystem};
use snarkvm_utilities::bititerator::BitIteratorBE;
use crate::{
bits::{Boolean, ToBitsBEGadget, ToBytesGadget},
fields::FpGadget,
integers::uint::UInt8,
traits::{
alloc::AllocGadget,
curves::{CurveGadget, GroupGadget},
eq::{ConditionalEqGadget, EqGadget, NEqGadget},
fields::{FieldGadget, ToConstraintFieldGadget},
select::CondSelectGadget,
},
ToMinimalBitsGadget,
};
#[derive(Derivative)]
#[derivative(Debug, Clone)]
#[must_use]
pub struct AffineGadget<P: ShortWeierstrassParameters, F: Field, FG: FieldGadget<P::BaseField, F>> {
pub x: FG,
pub y: FG,
pub infinity: Boolean,
_parameters: PhantomData<P>,
_engine: PhantomData<F>,
}
impl<P: ShortWeierstrassParameters, F: Field, FG: FieldGadget<P::BaseField, F>> AffineGadget<P, F, FG> {
pub fn new(x: FG, y: FG, infinity: Boolean) -> Self {
Self {
x,
y,
infinity,
_parameters: PhantomData,
_engine: PhantomData,
}
}
pub fn alloc_without_check<Fn: FnOnce() -> Result<SWProjective<P>, SynthesisError>, CS: ConstraintSystem<F>>(
mut cs: CS,
value_gen: Fn,
) -> Result<Self, SynthesisError> {
let (x, y, infinity) = match value_gen() {
Ok(ge) => {
let ge = ge.into_affine();
(Ok(ge.x), Ok(ge.y), Ok(ge.infinity))
}
_ => (
Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing),
),
};
let x = FG::alloc(&mut cs.ns(|| "x"), || x)?;
let y = FG::alloc(&mut cs.ns(|| "y"), || y)?;
let infinity = Boolean::alloc(&mut cs.ns(|| "infinity"), || infinity)?;
Ok(Self::new(x, y, infinity))
}
}
impl<P, F, FG> PartialEq for AffineGadget<P, F, FG>
where
P: ShortWeierstrassParameters,
F: Field,
FG: FieldGadget<P::BaseField, F>,
{
fn eq(&self, other: &Self) -> bool {
self.x == other.x && self.y == other.y
}
}
impl<P, F, FG> Eq for AffineGadget<P, F, FG>
where
P: ShortWeierstrassParameters,
F: Field,
FG: FieldGadget<P::BaseField, F>,
{
}
impl<P, F, FG> GroupGadget<SWProjective<P>, F> for AffineGadget<P, F, FG>
where
P: ShortWeierstrassParameters,
F: PrimeField,
FG: FieldGadget<P::BaseField, F>,
{
type Value = SWProjective<P>;
type Variable = (FG::Variable, FG::Variable);
#[inline]
fn get_value(&self) -> Option<Self::Value> {
match (self.x.get_value(), self.y.get_value(), self.infinity.get_value()) {
(Some(x), Some(y), Some(infinity)) => Some(SWAffine::new(x, y, infinity).into_projective()),
(None, None, None) => None,
_ => unreachable!(),
}
}
#[inline]
fn get_variable(&self) -> Self::Variable {
(self.x.get_variable(), self.y.get_variable())
}
#[inline]
fn zero<CS: ConstraintSystem<F>>(mut cs: CS) -> Result<Self, SynthesisError> {
Ok(Self::new(
FG::zero(cs.ns(|| "zero"))?,
FG::one(cs.ns(|| "one"))?,
Boolean::Constant(true),
))
}
#[inline]
fn add<CS: ConstraintSystem<F>>(&self, mut cs: CS, other: &Self) -> Result<Self, SynthesisError> {
let x2_minus_x1 = other.x.sub(cs.ns(|| "x2 - x1"), &self.x)?;
let y2_minus_y1 = other.y.sub(cs.ns(|| "y2 - y1"), &self.y)?;
let inv = x2_minus_x1.inverse(cs.ns(|| "compute inv"))?;
let lambda = FG::alloc(cs.ns(|| "lambda"), || {
Ok(y2_minus_y1.get_value().get()? * inv.get_value().get()?)
})?;
let x_3 = FG::alloc(&mut cs.ns(|| "x_3"), || {
let lambda_val = lambda.get_value().get()?;
let x1 = self.x.get_value().get()?;
let x2 = other.x.get_value().get()?;
Ok((lambda_val.square() - x1) - x2)
})?;
let y_3 = FG::alloc(&mut cs.ns(|| "y_3"), || {
let lambda_val = lambda.get_value().get()?;
let x_1 = self.x.get_value().get()?;
let y_1 = self.y.get_value().get()?;
let x_3 = x_3.get_value().get()?;
Ok(lambda_val * (x_1 - x_3) - y_1)
})?;
lambda.mul_equals(cs.ns(|| "check lambda"), &x2_minus_x1, &y2_minus_y1)?;
let x3_plus_x1_plus_x2 = x_3
.add(cs.ns(|| "x3 + x1"), &self.x)?
.add(cs.ns(|| "x3 + x1 + x2"), &other.x)?;
lambda.mul_equals(cs.ns(|| "check x3"), &lambda, &x3_plus_x1_plus_x2)?;
let y3_plus_y1 = y_3.add(cs.ns(|| "y3 + y1"), &self.y)?;
let x1_minus_x3 = self.x.sub(cs.ns(|| "x1 - x3"), &x_3)?;
lambda.mul_equals(cs.ns(|| ""), &x1_minus_x3, &y3_plus_y1)?;
Ok(Self::new(x_3, y_3, Boolean::Constant(false)))
}
fn add_constant<CS: ConstraintSystem<F>>(
&self,
mut cs: CS,
other: &SWProjective<P>,
) -> Result<Self, SynthesisError> {
if other.is_zero() {
return Err(SynthesisError::AssignmentMissing);
}
let other = other.into_affine();
let other_x = other.x;
let other_y = other.y;
let x2_minus_x1 = self
.x
.sub_constant(cs.ns(|| "x2 - x1"), &other_x)?
.negate(cs.ns(|| "neg1"))?;
let y2_minus_y1 = self
.y
.sub_constant(cs.ns(|| "y2 - y1"), &other_y)?
.negate(cs.ns(|| "neg2"))?;
let inv = x2_minus_x1.inverse(cs.ns(|| "compute inv"))?;
let lambda = FG::alloc(cs.ns(|| "lambda"), || {
Ok(y2_minus_y1.get_value().get()? * inv.get_value().get()?)
})?;
let x_3 = FG::alloc(&mut cs.ns(|| "x_3"), || {
let lambda_val = lambda.get_value().get()?;
let x1 = self.x.get_value().get()?;
let x2 = other_x;
Ok((lambda_val.square() - x1) - x2)
})?;
let y_3 = FG::alloc(&mut cs.ns(|| "y_3"), || {
let lambda_val = lambda.get_value().get()?;
let x_1 = self.x.get_value().get()?;
let y_1 = self.y.get_value().get()?;
let x_3 = x_3.get_value().get()?;
Ok(lambda_val * (x_1 - x_3) - y_1)
})?;
lambda.mul_equals(cs.ns(|| "check lambda"), &x2_minus_x1, &y2_minus_y1)?;
let x3_plus_x1_plus_x2 = x_3
.add(cs.ns(|| "x3 + x1"), &self.x)?
.add_constant(cs.ns(|| "x3 + x1 + x2"), &other_x)?;
lambda.mul_equals(cs.ns(|| "check x3"), &lambda, &x3_plus_x1_plus_x2)?;
let y3_plus_y1 = y_3.add(cs.ns(|| "y3 + y1"), &self.y)?;
let x1_minus_x3 = self.x.sub(cs.ns(|| "x1 - x3"), &x_3)?;
lambda.mul_equals(cs.ns(|| ""), &x1_minus_x3, &y3_plus_y1)?;
Ok(Self::new(x_3, y_3, Boolean::Constant(false)))
}
#[inline]
fn double_in_place<CS: ConstraintSystem<F>>(&mut self, mut cs: CS) -> Result<(), SynthesisError> {
let a = P::COEFF_A;
let x_squared = self.x.square(cs.ns(|| "x^2"))?;
let one = P::BaseField::one();
let two = one.double();
let three = two + one;
let three_x_squared = x_squared.mul_by_constant(cs.ns(|| "3 * x^2"), &three)?;
let three_x_squared_plus_a = three_x_squared.add_constant(cs.ns(|| "3 * x^2 + a"), &a)?;
let two_y = self.y.double(cs.ns(|| "2y"))?;
let lambda = FG::alloc(cs.ns(|| "lambda"), || {
let y_doubled_inv = two_y.get_value().get()?.inverse().get()?;
Ok(three_x_squared_plus_a.get_value().get()? * y_doubled_inv)
})?;
lambda.mul_equals(cs.ns(|| "check lambda"), &two_y, &three_x_squared_plus_a)?;
let x = lambda
.square(cs.ns(|| "lambda^2"))?
.sub(cs.ns(|| "lambda^2 - x"), &self.x)?
.sub(cs.ns(|| "lambda^2 - 2x"), &self.x)?;
let y = self
.x
.sub(cs.ns(|| "x - self.x"), &x)?
.mul(cs.ns(|| "times lambda"), &lambda)?
.sub(cs.ns(|| "plus self.y"), &self.y)?;
*self = Self::new(x, y, Boolean::Constant(false));
Ok(())
}
fn negate<CS: ConstraintSystem<F>>(&self, mut cs: CS) -> Result<Self, SynthesisError> {
Ok(Self::new(
self.x.clone(),
self.y.negate(cs.ns(|| "negate y"))?,
self.infinity,
))
}
fn cost_of_add() -> usize {
3 * FG::cost_of_mul() + FG::cost_of_inv()
}
fn cost_of_double() -> usize {
4 * FG::cost_of_mul()
}
}
impl<P, F, FG> CondSelectGadget<F> for AffineGadget<P, F, FG>
where
P: ShortWeierstrassParameters,
F: PrimeField,
FG: FieldGadget<P::BaseField, F>,
{
#[inline]
fn conditionally_select<CS: ConstraintSystem<F>>(
mut cs: CS,
cond: &Boolean,
first: &Self,
second: &Self,
) -> Result<Self, SynthesisError> {
let x = FG::conditionally_select(&mut cs.ns(|| "x"), cond, &first.x, &second.x)?;
let y = FG::conditionally_select(&mut cs.ns(|| "y"), cond, &first.y, &second.y)?;
let infinity =
Boolean::conditionally_select(&mut cs.ns(|| "infinity"), cond, &first.infinity, &second.infinity)?;
Ok(Self::new(x, y, infinity))
}
fn cost() -> usize {
2 * <FG as CondSelectGadget<F>>::cost() + <Boolean as CondSelectGadget<F>>::cost()
}
}
impl<P, F, FG> EqGadget<F> for AffineGadget<P, F, FG>
where
P: ShortWeierstrassParameters,
F: Field,
FG: FieldGadget<P::BaseField, F>,
{
fn is_eq<CS: ConstraintSystem<F>>(&self, mut cs: CS, other: &Self) -> Result<Boolean, SynthesisError> {
let x = self.x.is_eq(cs.ns(|| "x_is_eq"), &other.x)?;
let y = self.y.is_eq(cs.ns(|| "y_is_eq"), &other.y)?;
let infinity = self.infinity.is_eq(cs.ns(|| "infinity_is_eq"), &other.infinity)?;
let x_and_y = Boolean::and(cs.ns(|| "x_and_y"), &x, &y)?;
Boolean::and(cs.ns(|| "x_and_y_and_infinity"), &x_and_y, &infinity)
}
}
impl<P, F, FG> ConditionalEqGadget<F> for AffineGadget<P, F, FG>
where
P: ShortWeierstrassParameters,
F: Field,
FG: FieldGadget<P::BaseField, F>,
{
#[inline]
fn conditional_enforce_equal<CS: ConstraintSystem<F>>(
&self,
mut cs: CS,
other: &Self,
condition: &Boolean,
) -> Result<(), SynthesisError> {
self.x
.conditional_enforce_equal(&mut cs.ns(|| "X Coordinate Conditional Equality"), &other.x, condition)?;
self.y
.conditional_enforce_equal(&mut cs.ns(|| "Y Coordinate Conditional Equality"), &other.y, condition)?;
self.infinity.conditional_enforce_equal(
&mut cs.ns(|| "Infinity Conditional Equality"),
&other.infinity,
condition,
)?;
Ok(())
}
fn cost() -> usize {
2 * <FG as ConditionalEqGadget<F>>::cost()
}
}
impl<P, F, FG> NEqGadget<F> for AffineGadget<P, F, FG>
where
P: ShortWeierstrassParameters,
F: Field,
FG: FieldGadget<P::BaseField, F>,
{
#[inline]
fn enforce_not_equal<CS: ConstraintSystem<F>>(&self, mut cs: CS, other: &Self) -> Result<(), SynthesisError> {
self.x
.enforce_not_equal(&mut cs.ns(|| "X Coordinate Inequality"), &other.x)?;
self.y
.enforce_not_equal(&mut cs.ns(|| "Y Coordinate Inequality"), &other.y)?;
Ok(())
}
fn cost() -> usize {
2 * <FG as NEqGadget<F>>::cost()
}
}
impl<P: ShortWeierstrassParameters, F: PrimeField, FG: FieldGadget<P::BaseField, F>> AllocGadget<SWProjective<P>, F>
for AffineGadget<P, F, FG>
{
#[inline]
fn alloc_constant<Fn, T, CS: ConstraintSystem<F>>(mut cs: CS, value_gen: Fn) -> Result<Self, SynthesisError>
where
Fn: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<SWProjective<P>>,
{
let (x, y, infinity) = match value_gen() {
Ok(ge) => {
let ge = ge.borrow().into_affine();
(Ok(ge.x), Ok(ge.y), Ok(ge.infinity))
}
_ => (
Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing),
),
};
let b = P::COEFF_B;
let a = P::COEFF_A;
let x = FG::alloc_constant(&mut cs.ns(|| "x"), || x)?;
let y = FG::alloc_constant(&mut cs.ns(|| "y"), || y)?;
let infinity = Boolean::alloc_constant(&mut cs.ns(|| "infinity"), || infinity)?;
let x2 = x.square(&mut cs.ns(|| "x^2"))?;
let y2 = y.square(&mut cs.ns(|| "y^2"))?;
let x2_plus_a = x2.add_constant(cs.ns(|| "x^2 + a"), &a)?;
let y2_minus_b = y2.add_constant(cs.ns(|| "y^2 - b"), &b.neg())?;
x2_plus_a.mul_equals(cs.ns(|| "on curve check"), &x, &y2_minus_b)?;
Ok(Self::new(x, y, infinity))
}
#[inline]
fn alloc<Fn, T, CS: ConstraintSystem<F>>(mut cs: CS, value_gen: Fn) -> Result<Self, SynthesisError>
where
Fn: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<SWProjective<P>>,
{
let (x, y, infinity) = match value_gen() {
Ok(ge) => {
let ge = ge.borrow().into_affine();
(Ok(ge.x), Ok(ge.y), Ok(ge.infinity))
}
_ => (
Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing),
),
};
let b = P::COEFF_B;
let a = P::COEFF_A;
let x = FG::alloc(&mut cs.ns(|| "x"), || x)?;
let y = FG::alloc(&mut cs.ns(|| "y"), || y)?;
let infinity = Boolean::alloc(&mut cs.ns(|| "infinity"), || infinity)?;
let x2 = x.square(&mut cs.ns(|| "x^2"))?;
let y2 = y.square(&mut cs.ns(|| "y^2"))?;
let x2_plus_a = x2.add_constant(cs.ns(|| "x^2 + a"), &a)?;
let y2_minus_b = y2.add_constant(cs.ns(|| "y^2 - b"), &b.neg())?;
x2_plus_a.mul_equals(cs.ns(|| "on curve check"), &x, &y2_minus_b)?;
Ok(Self::new(x, y, infinity))
}
#[inline]
fn alloc_checked<Fn, T, CS: ConstraintSystem<F>>(mut cs: CS, value_gen: Fn) -> Result<Self, SynthesisError>
where
Fn: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<SWProjective<P>>,
{
let cofactor_weight = BitIteratorBE::new(P::COFACTOR).filter(|b| *b).count();
let r_minus_1 = (-P::ScalarField::one()).to_repr();
let r_weight = BitIteratorBE::new(&r_minus_1).filter(|b| *b).count();
if cofactor_weight < r_weight {
let ge = Self::alloc(cs.ns(|| "Alloc checked"), || {
value_gen().map(|ge| ge.borrow().into_affine().mul_by_cofactor_inv().into_projective())
})?;
let mut seen_one = false;
let mut result = Self::zero(cs.ns(|| "result"))?;
for (i, b) in BitIteratorBE::new(P::COFACTOR).enumerate() {
let mut cs = cs.ns(|| format!("Iteration {}", i));
let old_seen_one = seen_one;
if seen_one {
result.double_in_place(cs.ns(|| "Double"))?;
} else {
seen_one = b;
}
if b {
result = if old_seen_one {
result.add(cs.ns(|| "Add"), &ge)?
} else {
ge.clone()
};
}
}
Ok(result)
} else {
let ge = Self::alloc(cs.ns(|| "Alloc checked"), value_gen)?;
let mut seen_one = false;
let mut result = Self::zero(cs.ns(|| "result"))?;
for (i, b) in BitIteratorBE::new(r_minus_1).enumerate() {
let mut cs = cs.ns(|| format!("Iteration {}", i));
let old_seen_one = seen_one;
if seen_one {
result.double_in_place(cs.ns(|| "Double"))?;
} else {
seen_one = b;
}
if b {
result = if old_seen_one {
result.add(cs.ns(|| "Add"), &ge)?
} else {
ge.clone()
};
}
}
let neg_ge = ge.negate(cs.ns(|| "Negate ge"))?;
neg_ge.enforce_equal(cs.ns(|| "Check equals"), &result)?;
Ok(ge)
}
}
#[inline]
fn alloc_input<Fn, T, CS: ConstraintSystem<F>>(mut cs: CS, value_gen: Fn) -> Result<Self, SynthesisError>
where
Fn: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<SWProjective<P>>,
{
let (x, y, infinity) = match value_gen() {
Ok(ge) => {
let ge = ge.borrow().into_affine();
(Ok(ge.x), Ok(ge.y), Ok(ge.infinity))
}
_ => (
Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing),
),
};
let b = P::COEFF_B;
let a = P::COEFF_A;
let x = FG::alloc_input(&mut cs.ns(|| "x"), || x)?;
let y = FG::alloc_input(&mut cs.ns(|| "y"), || y)?;
let infinity = Boolean::alloc_input(&mut cs.ns(|| "infinity"), || infinity)?;
let x2 = x.square(&mut cs.ns(|| "x^2"))?;
let y2 = y.square(&mut cs.ns(|| "y^2"))?;
let x2_plus_a = x2.add_constant(cs.ns(|| "x^2 + a"), &a)?;
let y2_minus_b = y2.add_constant(cs.ns(|| "y^2 - b"), &b.neg())?;
x2_plus_a.mul_equals(cs.ns(|| "on curve check"), &x, &y2_minus_b)?;
Ok(Self::new(x, y, infinity))
}
}
impl<P: ShortWeierstrassParameters, F: PrimeField, FG: FieldGadget<P::BaseField, F>> AllocGadget<SWAffine<P>, F>
for AffineGadget<P, F, FG>
{
fn alloc_constant<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<SWAffine<P>>, CS: ConstraintSystem<F>>(
cs: CS,
f: Fn,
) -> Result<Self, SynthesisError> {
Self::alloc_constant(cs, || Ok(f()?.borrow().into_projective()))
}
fn alloc<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<SWAffine<P>>, CS: ConstraintSystem<F>>(
cs: CS,
f: Fn,
) -> Result<Self, SynthesisError> {
Self::alloc(cs, || Ok(f()?.borrow().into_projective()))
}
fn alloc_checked<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<SWAffine<P>>, CS: ConstraintSystem<F>>(
cs: CS,
f: Fn,
) -> Result<Self, SynthesisError> {
Self::alloc_checked(cs, || Ok(f()?.borrow().into_projective()))
}
fn alloc_input<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<SWAffine<P>>, CS: ConstraintSystem<F>>(
cs: CS,
f: Fn,
) -> Result<Self, SynthesisError> {
Self::alloc_input(cs, || Ok(f()?.borrow().into_projective()))
}
}
impl<P, F, FG> ToBitsBEGadget<F> for AffineGadget<P, F, FG>
where
P: ShortWeierstrassParameters,
F: Field,
FG: FieldGadget<P::BaseField, F>,
{
fn to_bits_be<CS: ConstraintSystem<F>>(&self, mut cs: CS) -> Result<Vec<Boolean>, SynthesisError> {
let mut x_bits = self.x.to_bits_be(&mut cs.ns(|| "X Coordinate To Bits"))?;
let y_bits = self.y.to_bits_be(&mut cs.ns(|| "Y Coordinate To Bits"))?;
x_bits.extend_from_slice(&y_bits);
x_bits.push(self.infinity);
Ok(x_bits)
}
fn to_bits_be_strict<CS: ConstraintSystem<F>>(&self, mut cs: CS) -> Result<Vec<Boolean>, SynthesisError> {
let mut x_bits = self.x.to_bits_be_strict(&mut cs.ns(|| "X Coordinate To Bits"))?;
let y_bits = self.y.to_bits_be_strict(&mut cs.ns(|| "Y Coordinate To Bits"))?;
x_bits.extend_from_slice(&y_bits);
x_bits.push(self.infinity);
Ok(x_bits)
}
}
impl<P, F, FG> ToMinimalBitsGadget<F> for AffineGadget<P, F, FG>
where
P: ShortWeierstrassParameters,
F: PrimeField,
FG: FieldGadget<P::BaseField, F>,
{
fn to_minimal_bits<CS: ConstraintSystem<F>>(&self, mut cs: CS) -> Result<Vec<Boolean>, SynthesisError> {
let mut res_bits = self.x.to_bits_le(cs.ns(|| "X Coordinate To Bits"))?;
res_bits.push(*self.y.to_bits_le(cs.ns(|| "Y Coordinate To Bits"))?.first().unwrap());
res_bits.push(self.infinity);
Ok(res_bits)
}
}
impl<P, F, FG> ToBytesGadget<F> for AffineGadget<P, F, FG>
where
P: ShortWeierstrassParameters,
F: Field,
FG: FieldGadget<P::BaseField, F>,
{
fn to_bytes<CS: ConstraintSystem<F>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
let mut x_bytes = self.x.to_bytes(&mut cs.ns(|| "X Coordinate To Bytes"))?;
let y_bytes = self.y.to_bytes(&mut cs.ns(|| "Y Coordinate To Bytes"))?;
let inf_bytes = self.infinity.to_bytes(&mut cs.ns(|| "Infinity to Bytes"))?;
x_bytes.extend_from_slice(&y_bytes);
x_bytes.extend_from_slice(&inf_bytes);
Ok(x_bytes)
}
fn to_bytes_strict<CS: ConstraintSystem<F>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
let mut x_bytes = self.x.to_bytes_strict(&mut cs.ns(|| "X Coordinate To Bytes"))?;
let y_bytes = self.y.to_bytes_strict(&mut cs.ns(|| "Y Coordinate To Bytes"))?;
let inf_bytes = self.infinity.to_bytes(&mut cs.ns(|| "Infinity to Bytes"))?;
x_bytes.extend_from_slice(&y_bytes);
x_bytes.extend_from_slice(&inf_bytes);
Ok(x_bytes)
}
}
impl<P, F, FG> ToConstraintFieldGadget<F> for AffineGadget<P, F, FG>
where
P: ShortWeierstrassParameters,
F: PrimeField,
FG: FieldGadget<P::BaseField, F> + ToConstraintFieldGadget<F>,
{
fn to_constraint_field<CS: ConstraintSystem<F>>(&self, mut cs: CS) -> Result<Vec<FpGadget<F>>, SynthesisError> {
let mut res = Vec::<FpGadget<F>>::new();
res.extend_from_slice(&self.x.to_constraint_field(cs.ns(|| "x_to_constraint_field"))?);
res.extend_from_slice(&self.y.to_constraint_field(cs.ns(|| "y_to_constraint_field"))?);
res.extend_from_slice(
&self
.infinity
.to_constraint_field(cs.ns(|| "infinity_to_constraint_field"))?,
);
Ok(res)
}
}
impl<P, F, FG> CurveGadget<SWProjective<P>, F> for AffineGadget<P, F, FG>
where
P: ShortWeierstrassParameters,
F: PrimeField,
FG: FieldGadget<P::BaseField, F>,
{
}