Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make short_weierstrass::Affine's infinity flag conditional #639

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ec/src/hashing/curve_maps/swu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ mod test {

/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const GENERATOR: Affine<Self> = Affine::new_unchecked(MontFp!("62"), MontFp!("70"));

/// We use `bool` because the point (0, 0) could be on the curve.
type ZeroIndicator = bool;
}

impl SWUConfig for TestSWUMapToCurveConfig {
Expand Down
8 changes: 7 additions & 1 deletion ec/src/hashing/curve_maps/wb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ mod test {

/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const GENERATOR: Affine<Self> = Affine::new_unchecked(MontFp!("62"), MontFp!("70"));

/// We use `()` because the point (0, 0) is not on the curve.
type ZeroIndicator = ();
}

/// Testing WB19 hashing on a small curve
Expand Down Expand Up @@ -193,11 +196,14 @@ mod test {
const COEFF_A: F127 = MontFp!("109");

/// COEFF_B = 124
#[rustfmt::skip]
#[rustfmt::skip]
const COEFF_B: F127 = MontFp!("124");

/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const GENERATOR: Affine<Self> = Affine::new_unchecked(MontFp!("84"), MontFp!("2"));

/// We use `bool because the point (0, 0) could be on the curve.
type ZeroIndicator = bool;
}

/// SWU parameters for E_isogenous
Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/bn/g1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl<'a, P: BnConfig> From<&'a G1Projective<P>> for G1Prepared<P> {

impl<P: BnConfig> G1Prepared<P> {
pub fn is_zero(&self) -> bool {
self.0.infinity
self.0.is_zero()
}
}

Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/bn/g2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ impl<P: BnConfig> Default for G2Prepared<P> {

impl<P: BnConfig> From<G2Affine<P>> for G2Prepared<P> {
fn from(q: G2Affine<P>) -> Self {
if q.infinity {
if q.is_zero() {
G2Prepared {
ell_coeffs: vec![],
infinity: true,
Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/bw6/g1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl<'a, P: BW6Config> From<&'a G1Projective<P>> for G1Prepared<P> {

impl<P: BW6Config> G1Prepared<P> {
pub fn is_zero(&self) -> bool {
self.0.infinity
self.0.is_zero()
}
}

Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/bw6/g2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl<P: BW6Config> Default for G2Prepared<P> {

impl<P: BW6Config> From<G2Affine<P>> for G2Prepared<P> {
fn from(q: G2Affine<P>) -> Self {
if q.infinity {
if q.is_zero() {
return Self {
ell_coeffs_1: vec![],
ell_coeffs_2: vec![],
Expand Down
30 changes: 15 additions & 15 deletions ec/src/models/short_weierstrass/affine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use ark_ff::{fields::Field, PrimeField, ToConstraintField, UniformRand};

use zeroize::Zeroize;

use super::{Projective, SWCurveConfig, SWFlags};
use super::{Projective, SWCurveConfig, SWFlags, ZeroInd};
use crate::AffineRepr;

/// Affine coordinates for a point on an elliptic curve in short Weierstrass
Expand All @@ -38,7 +38,7 @@ pub struct Affine<P: SWCurveConfig> {
#[doc(hidden)]
pub y: P::BaseField,
#[doc(hidden)]
pub infinity: bool,
pub infinity: P::ZeroIndicator,
}

impl<P: SWCurveConfig> PartialEq<Projective<P>> for Affine<P> {
Expand All @@ -49,7 +49,7 @@ impl<P: SWCurveConfig> PartialEq<Projective<P>> for Affine<P> {

impl<P: SWCurveConfig> Display for Affine<P> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self.infinity {
match self.is_zero() {
true => write!(f, "infinity"),
false => write!(f, "({}, {})", self.x, self.y),
}
Expand All @@ -58,7 +58,7 @@ impl<P: SWCurveConfig> Display for Affine<P> {

impl<P: SWCurveConfig> Debug for Affine<P> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self.infinity {
match self.is_zero() {
true => write!(f, "infinity"),
false => write!(f, "({}, {})", self.x, self.y),
}
Expand All @@ -72,7 +72,7 @@ impl<P: SWCurveConfig> Affine<P> {
let point = Self {
x,
y,
infinity: false,
infinity: P::ZeroIndicator::IS_NOT_ZERO,
};
assert!(point.is_on_curve());
assert!(point.is_in_correct_subgroup_assuming_on_curve());
Expand All @@ -89,15 +89,18 @@ impl<P: SWCurveConfig> Affine<P> {
Self {
x,
y,
infinity: false,
infinity: P::ZeroIndicator::IS_NOT_ZERO,
}
}

pub const fn identity() -> Self {
// Setting these to zero is *load-bearing* and important.
// These are the values that represent the identity element
// when `P::ZeroIndicator` is `()`.
Self {
x: P::BaseField::ZERO,
y: P::BaseField::ZERO,
infinity: true,
infinity: P::ZeroIndicator::IS_ZERO,
}
}

Expand Down Expand Up @@ -142,7 +145,7 @@ impl<P: SWCurveConfig> Affine<P> {

/// Checks if `self` is a valid point on the curve.
pub fn is_on_curve(&self) -> bool {
if !self.infinity {
if !self.is_zero() {
// Rust does not optimise away addition with zero
let mut x3b = P::add_b(self.x.square() * self.x);
if !P::COEFF_A.is_zero() {
Expand All @@ -155,7 +158,7 @@ impl<P: SWCurveConfig> Affine<P> {
}

pub fn to_flags(&self) -> SWFlags {
if self.infinity {
if self.is_zero() {
SWFlags::PointAtInfinity
} else if self.y <= -self.y {
SWFlags::YIsPositive
Expand Down Expand Up @@ -206,7 +209,7 @@ impl<P: SWCurveConfig> AffineRepr for Affine<P> {
type Group = Projective<P>;

fn xy(&self) -> Option<(&Self::BaseField, &Self::BaseField)> {
(!self.infinity).then(|| (&self.x, &self.y))
(!self.is_zero()).then(|| (&self.x, &self.y))
}

#[inline]
Expand All @@ -215,11 +218,7 @@ impl<P: SWCurveConfig> AffineRepr for Affine<P> {
}

fn zero() -> Self {
Self {
x: P::BaseField::ZERO,
y: P::BaseField::ZERO,
infinity: true,
}
Self::identity()
}

fn from_random_bytes(bytes: &[u8]) -> Option<Self> {
Expand Down Expand Up @@ -382,6 +381,7 @@ impl<P: SWCurveConfig> CanonicalDeserialize for Affine<P> {
impl<M: SWCurveConfig, ConstraintF: Field> ToConstraintField<ConstraintF> for Affine<M>
where
M::BaseField: ToConstraintField<ConstraintF>,
M::ZeroIndicator: ToConstraintField<ConstraintF>,
{
#[inline]
fn to_field_elements(&self) -> Option<Vec<ConstraintF>> {
Expand Down
1 change: 1 addition & 0 deletions ec/src/models/short_weierstrass/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,7 @@ impl<P: SWCurveConfig> CanonicalDeserialize for Projective<P> {
impl<M: SWCurveConfig, ConstraintF: Field> ToConstraintField<ConstraintF> for Projective<M>
where
M::BaseField: ToConstraintField<ConstraintF>,
M::ZeroIndicator: ToConstraintField<ConstraintF>,
{
#[inline]
fn to_field_elements(&self) -> Option<Vec<ConstraintF>> {
Expand Down
37 changes: 35 additions & 2 deletions ec/src/models/short_weierstrass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use ark_serialize::{
CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize,
CanonicalSerializeWithFlags, Compress, SerializationError, Valid, Validate,
};
use ark_std::io::{Read, Write};
use ark_std::{
hash::Hash,
io::{Read, Write},
};

use ark_ff::fields::Field;

Expand Down Expand Up @@ -30,6 +33,9 @@ pub trait SWCurveConfig: super::CurveConfig {
/// Generator of the prime-order subgroup.
const GENERATOR: Affine<Self>;

/// A type that is stored in `Affine<Self>` to indicate whether the point is at infinity.
type ZeroIndicator: ZeroInd<Self>;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really happy with this name; happy to take suggestions for better name.


/// Helper method for computing `elem * Self::COEFF_A`.
///
/// The default implementation should be overridden only if
Expand Down Expand Up @@ -124,7 +130,7 @@ pub trait SWCurveConfig: super::CurveConfig {
mut writer: W,
compress: ark_serialize::Compress,
) -> Result<(), SerializationError> {
let (x, y, flags) = match item.infinity {
let (x, y, flags) = match item.is_zero() {
true => (
Self::BaseField::zero(),
Self::BaseField::zero(),
Expand Down Expand Up @@ -198,3 +204,30 @@ pub trait SWCurveConfig: super::CurveConfig {
}
}
}

pub trait ZeroInd<C: SWCurveConfig>:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for this.

Hash + Ord + Eq + Copy + Sync + Send + Sized + 'static
{
const IS_ZERO: Self;
const IS_NOT_ZERO: Self;
fn is_zero(point: &Affine<C>) -> bool;
fn zeroize(&mut self) {
*self = Self::IS_NOT_ZERO;
}
}

impl<C: SWCurveConfig<ZeroIndicator = bool>> ZeroInd<C> for bool {
const IS_ZERO: Self = true;
const IS_NOT_ZERO: Self = false;
fn is_zero(point: &Affine<C>) -> bool {
point.infinity
}
}

impl<C: SWCurveConfig> ZeroInd<C> for () {
const IS_ZERO: Self = ();
const IS_NOT_ZERO: Self = ();
fn is_zero(point: &Affine<C>) -> bool {
point.x.is_zero() & point.y.is_zero()
}
}
2 changes: 2 additions & 0 deletions test-curves/src/bls12_381/g1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ impl short_weierstrass::SWCurveConfig for Config {
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);

type ZeroIndicator = ();

#[inline(always)]
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
Expand Down
1 change: 1 addition & 0 deletions test-curves/src/bls12_381/g1_swu_iso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl SWCurveConfig for SwuIsoConfig {
const COEFF_B: Fq = MontFp!("2906670324641927570491258158026293881577086121416628140204402091718288198173574630967936031029026176254968826637280");

const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
type ZeroIndicator = ();
}

/// Lexicographically smallest, valid x-coordinate of a point P on the curve (with its corresponding y) multiplied by the cofactor.
Expand Down
2 changes: 2 additions & 0 deletions test-curves/src/bls12_381/g2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ impl short_weierstrass::SWCurveConfig for Config {
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);

type ZeroIndicator = bool;

#[inline(always)]
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
Expand Down
2 changes: 2 additions & 0 deletions test-curves/src/bls12_381/g2_swu_iso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ impl SWCurveConfig for SwuIsoConfig {
const COEFF_B: Fq2 = Fq2::new(MontFp!("1012"), MontFp!("1012"));

const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);

type ZeroIndicator = bool;
}

/// Lexicographically smallest, valid x-coordinate of a point P on the curve (with its corresponding y) multiplied by the cofactor.
Expand Down
3 changes: 3 additions & 0 deletions test-curves/src/bn384_small_two_adicity/g1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ impl short_weierstrass::SWCurveConfig for Config {
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);

/// We can use `()`, because the point `(0, 0)` is not on the curve.
type ZeroIndicator = ();

#[inline(always)]
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
Expand Down
3 changes: 3 additions & 0 deletions test-curves/src/mnt4_753/g1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ impl short_weierstrass::SWCurveConfig for Config {

/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);

/// We use `bool because `(0, 0)` could be on the curve.
type ZeroIndicator = bool;
}

// Generator of G1
Expand Down
3 changes: 3 additions & 0 deletions test-curves/src/secp256k1/g1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ impl SWCurveConfig for Config {
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}

/// We use `()` because `(0, 0)` cannot be on the curve.
type ZeroIndicator = ();
}

/// G_GENERATOR_X = 55066263022277343669578718895168534326250603453777594175500187360389116729240
Expand Down