diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c067f3..e58ad59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ - Add `UInt::{from_bytes_le, from_bytes_be, to_bytes_be}`. - [\#143](https://github.com/arkworks-rs/r1cs-std/pull/143) Add `AllocVar::new_variable_with_inferred_mode`. - [\#144](https://github.com/arkworks-rs/r1cs-std/pull/144) Add `ToConstraintFieldGadget` bounds to `CurveVar` and `FieldVar` +- [\#190](https://github.com/arkworks-rs/r1cs-std/pull/190) Add `affine_xy, affine_x, affine_y` functions to `CurveVar` ### Improvements diff --git a/src/groups/curves/short_weierstrass/mod.rs b/src/groups/curves/short_weierstrass/mod.rs index fbfa8e3..5fea123 100644 --- a/src/groups/curves/short_weierstrass/mod.rs +++ b/src/groups/curves/short_weierstrass/mod.rs @@ -377,6 +377,8 @@ where F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { + type BaseFieldVar = F; + fn constant(g: SWProjective

) -> Self { let cs = ConstraintSystemRef::None; Self::new_variable_omit_on_curve_check(cs, || Ok(g), AllocationMode::Constant).unwrap() @@ -573,6 +575,11 @@ where *self += Self::constant(base).scalar_mul_le(bits.iter())?; Ok(()) } + + fn affine_xy(&self) -> Result<(F, F), SynthesisError> { + let self_affine = self.to_affine()?; + Ok((self_affine.x, self_affine.y)) + } } impl ToConstraintFieldGadget> for ProjectiveVar diff --git a/src/groups/curves/twisted_edwards/mod.rs b/src/groups/curves/twisted_edwards/mod.rs index 83c50a0..7d8a957 100644 --- a/src/groups/curves/twisted_edwards/mod.rs +++ b/src/groups/curves/twisted_edwards/mod.rs @@ -402,6 +402,8 @@ where + TwoBitLookupGadget, TableConstant = P::BaseField>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { + type BaseFieldVar = F; + fn constant(g: TEProjective

) -> Self { let cs = ConstraintSystemRef::None; Self::new_variable_omit_on_curve_check(cs, || Ok(g), AllocationMode::Constant).unwrap() @@ -547,6 +549,10 @@ where Ok(()) } + + fn affine_xy(&self) -> Result<(F, F), SynthesisError> { + Ok((self.x.clone(), self.y.clone())) + } } impl AllocVar, BasePrimeField

> for AffineVar diff --git a/src/groups/mod.rs b/src/groups/mod.rs index 85cdeea..19193ae 100644 --- a/src/groups/mod.rs +++ b/src/groups/mod.rs @@ -53,6 +53,8 @@ pub trait CurveVar: + for<'a> Mul<&'a EmulatedFpVar, Output = Self> + MulAssign> { + type BaseFieldVar: FieldVar; + /// Returns the constant `F::zero()`. This is the identity /// of the group. fn zero() -> Self; @@ -68,6 +70,19 @@ pub trait CurveVar: /// This *should not* allocate any variables. fn constant(other: C) -> Self; + /// Returns the x and y coordinates in Affine representation. + fn affine_xy(&self) -> Result<(Self::BaseFieldVar, Self::BaseFieldVar), SynthesisError>; + + /// Returns the x coordinate in Affine representation. + fn affine_x(&self) -> Result { + self.affine_xy().map(|(x, _)| x) + } + + /// Returns the y coordinate in Affine representation. + fn affine_y(&self) -> Result { + self.affine_xy().map(|(_, y)| y) + } + /// Allocates a variable in the subgroup without checking if it's in the /// prime-order subgroup. fn new_variable_omit_prime_order_check(