From ee5743bfc1a91638150029b615fa21fdb6a3292e Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Thu, 18 Sep 2025 16:37:07 -0300 Subject: [PATCH 1/5] Downgrade Lambdaworks dependency to 0.11.0 --- crates/starknet-types-core/Cargo.toml | 4 +- .../src/curve/projective_point.rs | 2 +- crates/starknet-types-core/src/felt/mod.rs | 2 +- crates/starknet-types-core/src/qm31/mod.rs | 66 +++++++++++++------ 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/crates/starknet-types-core/Cargo.toml b/crates/starknet-types-core/Cargo.toml index 2ac1e5a..b33c8fc 100644 --- a/crates/starknet-types-core/Cargo.toml +++ b/crates/starknet-types-core/Cargo.toml @@ -11,7 +11,7 @@ description = "Core types representation for Starknet" readme = "README.md" [dependencies] -lambdaworks-math = { version = "0.12.0", default-features = false } +lambdaworks-math = { version = "0.11.0", default-features = false } num-traits = { version = "0.2", default-features = false } num-bigint = { version = "0.4", default-features = false } num-integer = { version = "0.1", default-features = false } @@ -23,7 +23,7 @@ digest = { version = "0.10.7", optional = true } serde = { version = "1", optional = true, default-features = false, features = [ "alloc", "derive" ] } -lambdaworks-crypto = { version = "0.12.0", default-features = false, optional = true } +lambdaworks-crypto = { version = "0.11.0", default-features = false, optional = true } parity-scale-codec = { version = "3.6", default-features = false, optional = true } lazy_static = { version = "1.5", default-features = false, optional = true } zeroize = { version = "1.8.1", default-features = false, optional = true } diff --git a/crates/starknet-types-core/src/curve/projective_point.rs b/crates/starknet-types-core/src/curve/projective_point.rs index 6541479..0578269 100644 --- a/crates/starknet-types-core/src/curve/projective_point.rs +++ b/crates/starknet-types-core/src/curve/projective_point.rs @@ -17,7 +17,7 @@ pub struct ProjectivePoint(pub(crate) ShortWeierstrassProjectivePoint Result { - Ok(Self(ShortWeierstrassProjectivePoint::new([x.0, y.0, z.0])?)) + Ok(Self(ShortWeierstrassProjectivePoint::new([x.0, y.0, z.0]))) } /// Creates a new short Weierstrass projective point, assuming the coordinates are valid. diff --git a/crates/starknet-types-core/src/felt/mod.rs b/crates/starknet-types-core/src/felt/mod.rs index 60b86f7..6b3d138 100644 --- a/crates/starknet-types-core/src/felt/mod.rs +++ b/crates/starknet-types-core/src/felt/mod.rs @@ -234,7 +234,7 @@ impl Felt { /// Finite field division. pub fn field_div(&self, rhs: &NonZeroFelt) -> Self { - Self((self.0 / rhs.0).expect("dividing by a non zero felt will never fail")) + Self(self.0 / rhs.0) } /// Truncated quotient between `self` and `rhs`. diff --git a/crates/starknet-types-core/src/qm31/mod.rs b/crates/starknet-types-core/src/qm31/mod.rs index d9a5bf3..6c63bc2 100644 --- a/crates/starknet-types-core/src/qm31/mod.rs +++ b/crates/starknet-types-core/src/qm31/mod.rs @@ -8,7 +8,7 @@ use lambdaworks_math::field::{ element::FieldElement, errors::FieldError, fields::mersenne31::{ - extensions::Degree4ExtensionField, + extensions::{Degree2ExtensionField, Degree4ExtensionField}, field::{Mersenne31Field, MERSENNE_31_PRIME_FIELD_ORDER}, }, traits::IsField, @@ -19,6 +19,10 @@ mod num_traits_impl; use crate::felt::Felt; +type FpE = FieldElement; +type Fp2E = FieldElement; +type Fp4E = FieldElement; + /// A value in the Degree-4 (quadruple) extension of the Mersenne 31 (M31) field. /// /// Each QM31 value is represented by two values in the Degree-2 (complex) @@ -27,7 +31,7 @@ use crate::felt::Felt; /// /// An M31 coordinate fits in 31 bits, as it has a maximum value of: `(1 << 31) - 1`. #[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct QM31(pub FieldElement); +pub struct QM31(pub Fp4E); #[derive(Debug, Clone, Copy)] pub struct InvalidQM31Packing(pub Felt); @@ -45,12 +49,10 @@ impl std::fmt::Display for InvalidQM31Packing { impl QM31 { /// Creates a QM31 from four M31 elements. pub fn from_coefficients(a: u32, b: u32, c: u32, d: u32) -> Self { - Self(Degree4ExtensionField::const_from_coefficients( - Mersenne31Field::from_base_type(a), - Mersenne31Field::from_base_type(b), - Mersenne31Field::from_base_type(c), - Mersenne31Field::from_base_type(d), - )) + Self(Fp4E::const_from_raw([ + Fp2E::const_from_raw([FpE::const_from_raw(a), FpE::const_from_raw(b)]), + Fp2E::const_from_raw([FpE::const_from_raw(c), FpE::const_from_raw(d)]), + ])) } /// Extracts M31 elements from a QM31. @@ -91,7 +93,7 @@ impl QM31 { /// /// See the method [QM31::pack_into_felt] for a detailed explanation on the /// packing format. - pub fn unpack_from_felt(felt: &Felt) -> Result { + pub fn unpack_from_felt(felt: &Felt) -> Result { const MASK_36: u64 = (1 << 36) - 1; const MASK_8: u64 = (1 << 8) - 1; @@ -117,9 +119,16 @@ impl QM31 { } } - Ok(QM31(Degree4ExtensionField::const_from_coefficients( - c1 as u32, c2 as u32, c3 as u32, c4 as u32, - ))) + Ok(Self(Fp4E::const_from_raw([ + Fp2E::const_from_raw([ + FpE::const_from_raw(c1 as u32), + FpE::const_from_raw(c2 as u32), + ]), + Fp2E::const_from_raw([ + FpE::const_from_raw(c3 as u32), + FpE::const_from_raw(c4 as u32), + ]), + ]))) } /// Multiplicative inverse inside field. @@ -153,7 +162,7 @@ impl Div for QM31 { type Output = Result; fn div(self, rhs: Self) -> Self::Output { - Ok(Self(self.0.div(rhs.0)?)) + Ok(Self(self.0.div(rhs.0))) } } impl AddAssign for QM31 { @@ -181,7 +190,10 @@ mod test { }; use num_bigint::BigInt; - use crate::{felt::Felt, qm31::QM31}; + use crate::{ + felt::Felt, + qm31::{Fp2E, Fp4E, FpE, QM31}, + }; #[test] fn qm31_packing_and_unpacking() { @@ -196,9 +208,16 @@ mod test { ]; for [c1, c2, c3, c4] in cases { - let qm31 = QM31(Degree4ExtensionField::const_from_coefficients( - c1, c2, c3, c4, - )); + let qm31 = QM31(Fp4E::const_from_raw([ + Fp2E::const_from_raw([ + FpE::const_from_raw(c1 as u32), + FpE::const_from_raw(c2 as u32), + ]), + Fp2E::const_from_raw([ + FpE::const_from_raw(c3 as u32), + FpE::const_from_raw(c4 as u32), + ]), + ])); let packed_qm31 = qm31.pack_into_felt(); let unpacked_qm31 = QM31::unpack_from_felt(&packed_qm31).unwrap(); @@ -219,9 +238,16 @@ mod test { ]; for [c1, c2, c3, c4] in cases { - let qm31 = QM31(Degree4ExtensionField::const_from_coefficients( - c1, c2, c3, c4, - )); + let qm31 = QM31(Fp4E::const_from_raw([ + Fp2E::const_from_raw([ + FpE::const_from_raw(c1 as u32), + FpE::const_from_raw(c2 as u32), + ]), + Fp2E::const_from_raw([ + FpE::const_from_raw(c3 as u32), + FpE::const_from_raw(c4 as u32), + ]), + ])); let packed_qm31 = qm31.pack_into_felt(); let expected_packing = BigInt::from(c1) From aec53e31e6ff91187e272f65c4be373a49e55a97 Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Thu, 18 Sep 2025 17:04:58 -0300 Subject: [PATCH 2/5] Remove unused dependencies --- crates/starknet-types-core/src/qm31/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/starknet-types-core/src/qm31/mod.rs b/crates/starknet-types-core/src/qm31/mod.rs index 6c63bc2..1b10d9e 100644 --- a/crates/starknet-types-core/src/qm31/mod.rs +++ b/crates/starknet-types-core/src/qm31/mod.rs @@ -11,7 +11,6 @@ use lambdaworks_math::field::{ extensions::{Degree2ExtensionField, Degree4ExtensionField}, field::{Mersenne31Field, MERSENNE_31_PRIME_FIELD_ORDER}, }, - traits::IsField, }; #[cfg(feature = "num-traits")] @@ -185,9 +184,7 @@ impl Neg for QM31 { #[cfg(test)] mod test { - use lambdaworks_math::field::fields::mersenne31::{ - extensions::Degree4ExtensionField, field::MERSENNE_31_PRIME_FIELD_ORDER, - }; + use lambdaworks_math::field::fields::mersenne31::field::MERSENNE_31_PRIME_FIELD_ORDER; use num_bigint::BigInt; use crate::{ From 7a5b5228a19862154c9db51f4c7d673ca4862840 Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Thu, 18 Sep 2025 17:16:08 -0300 Subject: [PATCH 3/5] Add comments about preserving API --- crates/starknet-types-core/src/curve/projective_point.rs | 4 ++++ crates/starknet-types-core/src/qm31/mod.rs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/crates/starknet-types-core/src/curve/projective_point.rs b/crates/starknet-types-core/src/curve/projective_point.rs index 0578269..9da5673 100644 --- a/crates/starknet-types-core/src/curve/projective_point.rs +++ b/crates/starknet-types-core/src/curve/projective_point.rs @@ -17,6 +17,10 @@ pub struct ProjectivePoint(pub(crate) ShortWeierstrassProjectivePoint Result { + // While this function returns a `Result` it will always return the `Ok` variant. + // v0.3.0 bumped lambdaworks from 0.10.0 to 0.12.0 but v0.3.1 downgraded it to 0.11.0 + // so the idea is to preserve the API. + // This function should be simplified before releasing a major version (i.e. 0.4.0) Ok(Self(ShortWeierstrassProjectivePoint::new([x.0, y.0, z.0]))) } diff --git a/crates/starknet-types-core/src/qm31/mod.rs b/crates/starknet-types-core/src/qm31/mod.rs index 1b10d9e..bbdc186 100644 --- a/crates/starknet-types-core/src/qm31/mod.rs +++ b/crates/starknet-types-core/src/qm31/mod.rs @@ -161,6 +161,10 @@ impl Div for QM31 { type Output = Result; fn div(self, rhs: Self) -> Self::Output { + // While this function returns a `Result` it will always return the `Ok` variant. + // v0.3.0 bumped lambdaworks from 0.10.0 to 0.12.0 but v0.3.1 downgraded it to 0.11.0 + // so the idea is to preserve the API. + // This function should be simplified before releasing a major version (i.e. 0.4.0) Ok(Self(self.0.div(rhs.0))) } } From 603f4816910838581da94fbde9e618499a2c06bb Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Thu, 18 Sep 2025 17:16:52 -0300 Subject: [PATCH 4/5] Refactor Fp4E creation from coefficients --- crates/starknet-types-core/src/qm31/mod.rs | 53 ++++++++-------------- 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/crates/starknet-types-core/src/qm31/mod.rs b/crates/starknet-types-core/src/qm31/mod.rs index bbdc186..ebcb67e 100644 --- a/crates/starknet-types-core/src/qm31/mod.rs +++ b/crates/starknet-types-core/src/qm31/mod.rs @@ -48,10 +48,7 @@ impl std::fmt::Display for InvalidQM31Packing { impl QM31 { /// Creates a QM31 from four M31 elements. pub fn from_coefficients(a: u32, b: u32, c: u32, d: u32) -> Self { - Self(Fp4E::const_from_raw([ - Fp2E::const_from_raw([FpE::const_from_raw(a), FpE::const_from_raw(b)]), - Fp2E::const_from_raw([FpE::const_from_raw(c), FpE::const_from_raw(d)]), - ])) + Self(const_from_coefficients(a, b, c, d)) } /// Extracts M31 elements from a QM31. @@ -118,16 +115,9 @@ impl QM31 { } } - Ok(Self(Fp4E::const_from_raw([ - Fp2E::const_from_raw([ - FpE::const_from_raw(c1 as u32), - FpE::const_from_raw(c2 as u32), - ]), - Fp2E::const_from_raw([ - FpE::const_from_raw(c3 as u32), - FpE::const_from_raw(c4 as u32), - ]), - ]))) + Ok(Self(const_from_coefficients( + c1 as u32, c2 as u32, c3 as u32, c4 as u32, + ))) } /// Multiplicative inverse inside field. @@ -186,6 +176,13 @@ impl Neg for QM31 { } } +const fn const_from_coefficients(a: u32, b: u32, c: u32, d: u32) -> Fp4E { + Fp4E::const_from_raw([ + Fp2E::const_from_raw([FpE::const_from_raw(a), FpE::const_from_raw(b)]), + Fp2E::const_from_raw([FpE::const_from_raw(c), FpE::const_from_raw(d)]), + ]) +} + #[cfg(test)] mod test { use lambdaworks_math::field::fields::mersenne31::field::MERSENNE_31_PRIME_FIELD_ORDER; @@ -193,7 +190,7 @@ mod test { use crate::{ felt::Felt, - qm31::{Fp2E, Fp4E, FpE, QM31}, + qm31::{const_from_coefficients, QM31}, }; #[test] @@ -209,16 +206,9 @@ mod test { ]; for [c1, c2, c3, c4] in cases { - let qm31 = QM31(Fp4E::const_from_raw([ - Fp2E::const_from_raw([ - FpE::const_from_raw(c1 as u32), - FpE::const_from_raw(c2 as u32), - ]), - Fp2E::const_from_raw([ - FpE::const_from_raw(c3 as u32), - FpE::const_from_raw(c4 as u32), - ]), - ])); + let qm31 = QM31(const_from_coefficients( + c1 as u32, c2 as u32, c3 as u32, c4 as u32, + )); let packed_qm31 = qm31.pack_into_felt(); let unpacked_qm31 = QM31::unpack_from_felt(&packed_qm31).unwrap(); @@ -239,16 +229,9 @@ mod test { ]; for [c1, c2, c3, c4] in cases { - let qm31 = QM31(Fp4E::const_from_raw([ - Fp2E::const_from_raw([ - FpE::const_from_raw(c1 as u32), - FpE::const_from_raw(c2 as u32), - ]), - Fp2E::const_from_raw([ - FpE::const_from_raw(c3 as u32), - FpE::const_from_raw(c4 as u32), - ]), - ])); + let qm31 = QM31(const_from_coefficients( + c1 as u32, c2 as u32, c3 as u32, c4 as u32, + )); let packed_qm31 = qm31.pack_into_felt(); let expected_packing = BigInt::from(c1) From 6d9cca01dbf58cdbcfaf40daa6773e28a7d72776 Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Thu, 18 Sep 2025 17:20:07 -0300 Subject: [PATCH 5/5] Rename from_coefficients private fn --- crates/starknet-types-core/src/qm31/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/starknet-types-core/src/qm31/mod.rs b/crates/starknet-types-core/src/qm31/mod.rs index ebcb67e..2f5c72f 100644 --- a/crates/starknet-types-core/src/qm31/mod.rs +++ b/crates/starknet-types-core/src/qm31/mod.rs @@ -48,7 +48,7 @@ impl std::fmt::Display for InvalidQM31Packing { impl QM31 { /// Creates a QM31 from four M31 elements. pub fn from_coefficients(a: u32, b: u32, c: u32, d: u32) -> Self { - Self(const_from_coefficients(a, b, c, d)) + Self(const_fp4e_from_coefficients(a, b, c, d)) } /// Extracts M31 elements from a QM31. @@ -115,7 +115,7 @@ impl QM31 { } } - Ok(Self(const_from_coefficients( + Ok(Self(const_fp4e_from_coefficients( c1 as u32, c2 as u32, c3 as u32, c4 as u32, ))) } @@ -176,7 +176,7 @@ impl Neg for QM31 { } } -const fn const_from_coefficients(a: u32, b: u32, c: u32, d: u32) -> Fp4E { +const fn const_fp4e_from_coefficients(a: u32, b: u32, c: u32, d: u32) -> Fp4E { Fp4E::const_from_raw([ Fp2E::const_from_raw([FpE::const_from_raw(a), FpE::const_from_raw(b)]), Fp2E::const_from_raw([FpE::const_from_raw(c), FpE::const_from_raw(d)]), @@ -190,7 +190,7 @@ mod test { use crate::{ felt::Felt, - qm31::{const_from_coefficients, QM31}, + qm31::{const_fp4e_from_coefficients, QM31}, }; #[test] @@ -206,7 +206,7 @@ mod test { ]; for [c1, c2, c3, c4] in cases { - let qm31 = QM31(const_from_coefficients( + let qm31 = QM31(const_fp4e_from_coefficients( c1 as u32, c2 as u32, c3 as u32, c4 as u32, )); let packed_qm31 = qm31.pack_into_felt(); @@ -229,7 +229,7 @@ mod test { ]; for [c1, c2, c3, c4] in cases { - let qm31 = QM31(const_from_coefficients( + let qm31 = QM31(const_fp4e_from_coefficients( c1 as u32, c2 as u32, c3 as u32, c4 as u32, )); let packed_qm31 = qm31.pack_into_felt();