From 4f3a2b3f78d70a8c3d9b37e90ee8d0b80c1dc9f6 Mon Sep 17 00:00:00 2001 From: Filip Laurentiu Date: Wed, 29 Jan 2025 12:02:32 +0200 Subject: [PATCH 1/4] Affine coordinate are not correctly exposed from the underlying type. ProjectivePoints have 3 coordinates (x,y,z) and the AffinePoint incorrectly expose just the (x, y) coordinate without converting the representation from projective to affine. --- crates/starknet-types-core/src/curve/affine_point.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/starknet-types-core/src/curve/affine_point.rs b/crates/starknet-types-core/src/curve/affine_point.rs index 76a73b92..04f515a6 100644 --- a/crates/starknet-types-core/src/curve/affine_point.rs +++ b/crates/starknet-types-core/src/curve/affine_point.rs @@ -44,12 +44,12 @@ impl AffinePoint { /// Returns the `x` coordinate of the point. pub fn x(&self) -> Felt { - Felt(*self.0.x()) + Felt(*self.0.to_affine().x()) } /// Returns the `y` coordinate of the point. pub fn y(&self) -> Felt { - Felt(*self.0.y()) + Felt(*self.0.to_affine().y()) } // Returns the generator point of the StarkCurve @@ -70,7 +70,7 @@ impl core::ops::Add for AffinePoint { type Output = AffinePoint; fn add(self, rhs: Self) -> Self::Output { - AffinePoint(self.0.operate_with_affine(&rhs.0)) + AffinePoint(self.0.operate_with_affine(&rhs.0.to_affine())) } } From 9c0676eaa8151f36a56b00aa4238768c8f1a589c Mon Sep 17 00:00:00 2001 From: Filip Laurentiu Date: Wed, 29 Jan 2025 19:38:56 +0200 Subject: [PATCH 2/4] Fix the `Add` implementation --- crates/starknet-types-core/src/curve/affine_point.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/starknet-types-core/src/curve/affine_point.rs b/crates/starknet-types-core/src/curve/affine_point.rs index 04f515a6..5ee09db2 100644 --- a/crates/starknet-types-core/src/curve/affine_point.rs +++ b/crates/starknet-types-core/src/curve/affine_point.rs @@ -70,7 +70,7 @@ impl core::ops::Add for AffinePoint { type Output = AffinePoint; fn add(self, rhs: Self) -> Self::Output { - AffinePoint(self.0.operate_with_affine(&rhs.0.to_affine())) + AffinePoint(self.0.operate_with(&rhs.0)) } } From d71fda0cc7cca61615b46fa32d24011a74965c88 Mon Sep 17 00:00:00 2001 From: Filip Laurentiu Date: Wed, 29 Jan 2025 12:15:28 +0200 Subject: [PATCH 3/4] Implement new_from_x for the AffinePoint to recover point just from the x coordinate --- .../src/curve/affine_point.rs | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/crates/starknet-types-core/src/curve/affine_point.rs b/crates/starknet-types-core/src/curve/affine_point.rs index 5ee09db2..3a5a31cc 100644 --- a/crates/starknet-types-core/src/curve/affine_point.rs +++ b/crates/starknet-types-core/src/curve/affine_point.rs @@ -4,6 +4,7 @@ use lambdaworks_math::{ elliptic_curve::{ short_weierstrass::{ curves::stark_curve::StarkCurve, point::ShortWeierstrassProjectivePoint, + traits::IsShortWeierstrass, }, traits::{FromAffine, IsEllipticCurve}, }, @@ -33,6 +34,28 @@ impl AffinePoint { ])) } + /// Construct new affine point from the `x` coordinate and the parity bit. + /// If the parity bit is false, choose the y-coordinate with even parity. + /// If the parity bit is true, choose the y-coordinate with odd parity. + pub fn new_from_x(x: &Felt, y_parity: bool) -> Option { + // right hand side of the stark curve equation `y^2 = x^3 + α*x + β (mod p)`. + let rhs = x * x * x + Felt(StarkCurve::a()) * x + Felt(StarkCurve::b()); + + let (root_1, root_2) = rhs.0.sqrt()?; + + let root_1_le_bits = root_1.to_bits_le(); + let first_bit = root_1_le_bits.first()?; + + let y = if *first_bit == y_parity { + root_1 + } else { + root_2 + }; + + // the curve equation is already satisfied above and is safe to create a new unchecked point + Some(Self::new_unchecked(*x, Felt(y))) + } + /// The point at infinity. pub fn identity() -> AffinePoint { Self(ShortWeierstrassProjectivePoint::neutral_element()) @@ -86,6 +109,7 @@ impl core::ops::Mul for &AffinePoint { #[cfg(test)] mod test { use super::*; + use std::ops::Neg; #[test] fn affine_point_new_unchecked() { @@ -191,4 +215,30 @@ mod test { .unwrap() ); } + + #[test] + fn affine_new_from_x_odd() { + let p = AffinePoint::new( + Felt::from_hex_unchecked("0x2d39148a92f479fb077389d"), + Felt::from_hex_unchecked( + "0x6e5d97edf7283fe7a7fe9deef2619224f42cb1bd531dd23380ad066c61ee20b", + ), + ) + .unwrap(); + + assert_eq!(p, AffinePoint::new_from_x(&p.x(), true).unwrap()); + } + + #[test] + fn affine_new_from_x_even() { + let p = AffinePoint::new( + Felt::from_hex_unchecked("0x2d39148a92f479fb077389d"), + Felt::from_hex_unchecked( + "0x6e5d97edf7283fe7a7fe9deef2619224f42cb1bd531dd23380ad066c61ee20b", + ), + ) + .unwrap(); + + assert_eq!(p.neg(), AffinePoint::new_from_x(&p.x(), false).unwrap()); + } } From a5df5c19966d3c924e2406cbb848f119dd85d2ea Mon Sep 17 00:00:00 2001 From: Filip Laurentiu Date: Fri, 11 Jul 2025 12:53:11 +0300 Subject: [PATCH 4/4] Update crates/starknet-types-core/src/curve/affine_point.rs Update comments to improve clarity Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> --- crates/starknet-types-core/src/curve/affine_point.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/starknet-types-core/src/curve/affine_point.rs b/crates/starknet-types-core/src/curve/affine_point.rs index 3a5a31cc..6ed616a9 100644 --- a/crates/starknet-types-core/src/curve/affine_point.rs +++ b/crates/starknet-types-core/src/curve/affine_point.rs @@ -34,9 +34,9 @@ impl AffinePoint { ])) } - /// Construct new affine point from the `x` coordinate and the parity bit. - /// If the parity bit is false, choose the y-coordinate with even parity. - /// If the parity bit is true, choose the y-coordinate with odd parity. + /// Construct new affine point from the `x` coordinate and the parity bit `y_parity`. + /// If `y_parity` is false, choose the y-coordinate with even parity. + /// If `y_parity` is true, choose the y-coordinate with odd parity. pub fn new_from_x(x: &Felt, y_parity: bool) -> Option { // right hand side of the stark curve equation `y^2 = x^3 + α*x + β (mod p)`. let rhs = x * x * x + Felt(StarkCurve::a()) * x + Felt(StarkCurve::b());