From 053ed0fd68118b72c7eb9d6abfbd35bb45caba0a Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Mon, 11 Dec 2023 15:43:07 -0300 Subject: [PATCH 1/9] Implement felt to bigint functions --- crates/starknet-types-core/Cargo.toml | 1 + crates/starknet-types-core/src/felt.rs | 41 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/crates/starknet-types-core/Cargo.toml b/crates/starknet-types-core/Cargo.toml index 1b61b80..e6b9d39 100644 --- a/crates/starknet-types-core/Cargo.toml +++ b/crates/starknet-types-core/Cargo.toml @@ -21,6 +21,7 @@ arbitrary = { version = "1.3.0", optional = true, default-features = false } num-traits = { version = "0.2.16", default-features = false } num-bigint = {version = "0.4.4", default-features = false} num-integer = {version = "0.1.45", default-features = false} +lazy_static = { version = "1.4.0", default-features = false } [features] default = ["std", "serde", "curve"] diff --git a/crates/starknet-types-core/src/felt.rs b/crates/starknet-types-core/src/felt.rs index 86a905d..b96bebf 100644 --- a/crates/starknet-types-core/src/felt.rs +++ b/crates/starknet-types-core/src/felt.rs @@ -945,6 +945,47 @@ mod errors { } } +pub mod bigints { + use lazy_static::lazy_static; + use num_bigint::{BigUint, Sign, ToBigInt}; + use num_traits::Num; + + use super::*; + lazy_static! { + pub static ref CAIRO_PRIME_BIGINT: BigInt = BigInt::from_str_radix( + "800000000000011000000000000000000000000000000000000000000000001", + 16 + ) + .unwrap(); + } + + pub fn felt_to_biguint(felt: Felt) -> BigUint { + let big_digits = felt + .to_le_digits() + .into_iter() + .flat_map(|limb| [limb as u32, (limb >> 32) as u32]) + .collect(); + BigUint::new(big_digits) + } + + pub fn felt_to_bigint(felt: Felt) -> BigInt { + felt_to_biguint(felt).to_bigint().unwrap() + } + + pub fn biguint_to_felt(biguint: &BigUint) -> Felt { + Felt::from_bytes_le_slice(&biguint.to_bytes_le()) + } + + pub fn bigint_to_felt(bigint: &BigInt) -> Felt { + let (sign, bytes) = bigint.mod_floor(&CAIRO_PRIME_BIGINT).to_bytes_le(); + let felt = Felt::from_bytes_le_slice(&bytes); + if sign == Sign::Minus { + felt.neg() + } else { + felt + } + } +} #[cfg(test)] mod test { use super::alloc::{format, string::String, vec::Vec}; From 40d99fa63abfc8560a34b94180b9776548694384 Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Mon, 11 Dec 2023 18:29:58 -0300 Subject: [PATCH 2/9] remove mod --- crates/starknet-types-core/src/felt.rs | 80 ++++++++++++-------------- 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/crates/starknet-types-core/src/felt.rs b/crates/starknet-types-core/src/felt.rs index b96bebf..108bf13 100644 --- a/crates/starknet-types-core/src/felt.rs +++ b/crates/starknet-types-core/src/felt.rs @@ -1,10 +1,20 @@ use core::ops::{Add, Mul, Neg}; use bitvec::array::BitArray; -use num_bigint::BigInt; +use lazy_static::lazy_static; +use num_bigint::{BigInt, BigUint, Sign, ToBigInt}; use num_integer::Integer; +use num_traits::Num; use num_traits::{FromPrimitive, One, ToPrimitive, Zero}; +lazy_static! { + pub static ref CAIRO_PRIME_BIGINT: BigInt = BigInt::from_str_radix( + "800000000000011000000000000000000000000000000000000000000000001", + 16 + ) + .unwrap(); +} + #[cfg(target_pointer_width = "64")] pub type BitArrayStore = [u64; 4]; @@ -796,6 +806,33 @@ mod arithmetic { } } +pub fn felt_to_biguint(felt: Felt) -> BigUint { + let big_digits = felt + .to_le_digits() + .into_iter() + .flat_map(|limb| [limb as u32, (limb >> 32) as u32]) + .collect(); + BigUint::new(big_digits) +} + +pub fn felt_to_bigint(felt: Felt) -> BigInt { + felt_to_biguint(felt).to_bigint().unwrap() +} + +pub fn biguint_to_felt(biguint: &BigUint) -> Felt { + Felt::from_bytes_le_slice(&biguint.to_bytes_le()) +} + +pub fn bigint_to_felt(bigint: &BigInt) -> Felt { + let (sign, bytes) = bigint.mod_floor(&CAIRO_PRIME_BIGINT).to_bytes_le(); + let felt = Felt::from_bytes_le_slice(&bytes); + if sign == Sign::Minus { + felt.neg() + } else { + felt + } +} + #[cfg(feature = "serde")] mod serde { use ::serde::{de, ser::SerializeSeq, Deserialize, Serialize}; @@ -945,47 +982,6 @@ mod errors { } } -pub mod bigints { - use lazy_static::lazy_static; - use num_bigint::{BigUint, Sign, ToBigInt}; - use num_traits::Num; - - use super::*; - lazy_static! { - pub static ref CAIRO_PRIME_BIGINT: BigInt = BigInt::from_str_radix( - "800000000000011000000000000000000000000000000000000000000000001", - 16 - ) - .unwrap(); - } - - pub fn felt_to_biguint(felt: Felt) -> BigUint { - let big_digits = felt - .to_le_digits() - .into_iter() - .flat_map(|limb| [limb as u32, (limb >> 32) as u32]) - .collect(); - BigUint::new(big_digits) - } - - pub fn felt_to_bigint(felt: Felt) -> BigInt { - felt_to_biguint(felt).to_bigint().unwrap() - } - - pub fn biguint_to_felt(biguint: &BigUint) -> Felt { - Felt::from_bytes_le_slice(&biguint.to_bytes_le()) - } - - pub fn bigint_to_felt(bigint: &BigInt) -> Felt { - let (sign, bytes) = bigint.mod_floor(&CAIRO_PRIME_BIGINT).to_bytes_le(); - let felt = Felt::from_bytes_le_slice(&bytes); - if sign == Sign::Minus { - felt.neg() - } else { - felt - } - } -} #[cfg(test)] mod test { use super::alloc::{format, string::String, vec::Vec}; From ebfebdeaef4721c0b2c21da9440949e1c55be1e3 Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Mon, 11 Dec 2023 18:30:05 -0300 Subject: [PATCH 3/9] Add tests --- crates/starknet-types-core/src/felt.rs | 61 ++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/crates/starknet-types-core/src/felt.rs b/crates/starknet-types-core/src/felt.rs index 108bf13..41b27d4 100644 --- a/crates/starknet-types-core/src/felt.rs +++ b/crates/starknet-types-core/src/felt.rs @@ -1637,4 +1637,65 @@ mod test { assert_eq!(x.mul_mod(&y, &p), expected_result); } + + #[test] + fn bigints_to_felt() { + let one = &*CAIRO_PRIME_BIGINT + BigInt::from(1_u32); + assert_eq!(biguint_to_felt(&one.to_biguint().unwrap()), Felt::from(1)); + assert_eq!(bigint_to_felt(&one), Felt::from(1)); + + let zero = &*CAIRO_PRIME_BIGINT * 99_u32; + assert_eq!(biguint_to_felt(&zero.to_biguint().unwrap()), Felt::from(0)); + assert_eq!(bigint_to_felt(&zero), Felt::from(0)); + + assert_eq!( + bigint_to_felt(&BigInt::from(-1)), + Felt::from_hex("0x800000000000011000000000000000000000000000000000000000000000000") + .unwrap() + ); + + let numbers_str = [ + "0x0", + "0x1", + "0x10", + "0x8000000000000110000000000", + "0xffffffffffffff", + "0xffffffffefff12380777abcd", + ]; + + for number_str in numbers_str { + assert_eq!( + bigint_to_felt(&BigInt::from_str_radix(&number_str[2..], 16).unwrap()), + Felt::from_hex(number_str).unwrap() + ); + assert_eq!( + biguint_to_felt(&BigUint::from_str_radix(&number_str[2..], 16).unwrap()), + Felt::from_hex(number_str).unwrap() + ) + } + } + + #[test] + fn felt_to_bigints() { + let numbers_str = [ + "0x0", + "0x1", + "0x10", + "0x8000000000000110000000000", + "0xffffffffffffff", + "0xffffffffefff12380777abcd", + ]; + + for number_str in numbers_str { + assert_eq!( + felt_to_bigint(Felt::from_hex(number_str).unwrap()), + BigInt::from_str_radix(&number_str[2..], 16).unwrap() + ); + + assert_eq!( + felt_to_biguint(Felt::from_hex(number_str).unwrap()), + BigUint::from_str_radix(&number_str[2..], 16).unwrap() + ); + } + } } From ea4166ad75307e53a0334e4def0b8a7db2a64e0e Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Fri, 15 Dec 2023 19:08:01 -0300 Subject: [PATCH 4/9] use lazy_static spin_no_std feature --- crates/starknet-types-core/Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/starknet-types-core/Cargo.toml b/crates/starknet-types-core/Cargo.toml index e6b9d39..a280e72 100644 --- a/crates/starknet-types-core/Cargo.toml +++ b/crates/starknet-types-core/Cargo.toml @@ -21,7 +21,9 @@ arbitrary = { version = "1.3.0", optional = true, default-features = false } num-traits = { version = "0.2.16", default-features = false } num-bigint = {version = "0.4.4", default-features = false} num-integer = {version = "0.1.45", default-features = false} -lazy_static = { version = "1.4.0", default-features = false } +lazy_static = { version = "1.4.0", default-features = false, features = [ + "spin_no_std", +] } [features] default = ["std", "serde", "curve"] From 3397b48d901a058e68ead62253fa4b59dd2ddd94 Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Mon, 18 Dec 2023 20:02:49 -0300 Subject: [PATCH 5/9] impl From<&BigInt> for Felt --- crates/starknet-types-core/src/felt.rs | 30 ++++++++++++++------------ 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/crates/starknet-types-core/src/felt.rs b/crates/starknet-types-core/src/felt.rs index 41b27d4..b349823 100644 --- a/crates/starknet-types-core/src/felt.rs +++ b/crates/starknet-types-core/src/felt.rs @@ -444,6 +444,18 @@ impl From for Felt { } } +impl From<&BigInt> for Felt { + fn from(bigint: &BigInt) -> Felt { + let (sign, bytes) = bigint.mod_floor(&CAIRO_PRIME_BIGINT).to_bytes_le(); + let felt = Felt::from_bytes_le_slice(&bytes); + if sign == Sign::Minus { + felt.neg() + } else { + felt + } + } +} + macro_rules! impl_from { ($from:ty, $with:ty) => { impl From<$from> for Felt { @@ -823,16 +835,6 @@ pub fn biguint_to_felt(biguint: &BigUint) -> Felt { Felt::from_bytes_le_slice(&biguint.to_bytes_le()) } -pub fn bigint_to_felt(bigint: &BigInt) -> Felt { - let (sign, bytes) = bigint.mod_floor(&CAIRO_PRIME_BIGINT).to_bytes_le(); - let felt = Felt::from_bytes_le_slice(&bytes); - if sign == Sign::Minus { - felt.neg() - } else { - felt - } -} - #[cfg(feature = "serde")] mod serde { use ::serde::{de, ser::SerializeSeq, Deserialize, Serialize}; @@ -1642,14 +1644,14 @@ mod test { fn bigints_to_felt() { let one = &*CAIRO_PRIME_BIGINT + BigInt::from(1_u32); assert_eq!(biguint_to_felt(&one.to_biguint().unwrap()), Felt::from(1)); - assert_eq!(bigint_to_felt(&one), Felt::from(1)); + assert_eq!(Felt::from(&one), Felt::from(1)); let zero = &*CAIRO_PRIME_BIGINT * 99_u32; assert_eq!(biguint_to_felt(&zero.to_biguint().unwrap()), Felt::from(0)); - assert_eq!(bigint_to_felt(&zero), Felt::from(0)); + assert_eq!(Felt::from(&zero), Felt::from(0)); assert_eq!( - bigint_to_felt(&BigInt::from(-1)), + Felt::from(&BigInt::from(-1)), Felt::from_hex("0x800000000000011000000000000000000000000000000000000000000000000") .unwrap() ); @@ -1665,7 +1667,7 @@ mod test { for number_str in numbers_str { assert_eq!( - bigint_to_felt(&BigInt::from_str_radix(&number_str[2..], 16).unwrap()), + Felt::from(&BigInt::from_str_radix(&number_str[2..], 16).unwrap()), Felt::from_hex(number_str).unwrap() ); assert_eq!( From 0491cdc776ae15a0d234041bb8f5785d7d0f4745 Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Mon, 18 Dec 2023 20:12:23 -0300 Subject: [PATCH 6/9] impl From<&BigUint> for Felt --- crates/starknet-types-core/src/felt.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/starknet-types-core/src/felt.rs b/crates/starknet-types-core/src/felt.rs index b349823..56efc8b 100644 --- a/crates/starknet-types-core/src/felt.rs +++ b/crates/starknet-types-core/src/felt.rs @@ -456,6 +456,12 @@ impl From<&BigInt> for Felt { } } +impl From<&BigUint> for Felt { + fn from(biguint: &BigUint) -> Felt { + Felt::from_bytes_le_slice(&biguint.to_bytes_le()) + } +} + macro_rules! impl_from { ($from:ty, $with:ty) => { impl From<$from> for Felt { @@ -831,10 +837,6 @@ pub fn felt_to_bigint(felt: Felt) -> BigInt { felt_to_biguint(felt).to_bigint().unwrap() } -pub fn biguint_to_felt(biguint: &BigUint) -> Felt { - Felt::from_bytes_le_slice(&biguint.to_bytes_le()) -} - #[cfg(feature = "serde")] mod serde { use ::serde::{de, ser::SerializeSeq, Deserialize, Serialize}; @@ -1643,11 +1645,11 @@ mod test { #[test] fn bigints_to_felt() { let one = &*CAIRO_PRIME_BIGINT + BigInt::from(1_u32); - assert_eq!(biguint_to_felt(&one.to_biguint().unwrap()), Felt::from(1)); + assert_eq!(Felt::from(&one.to_biguint().unwrap()), Felt::from(1)); assert_eq!(Felt::from(&one), Felt::from(1)); let zero = &*CAIRO_PRIME_BIGINT * 99_u32; - assert_eq!(biguint_to_felt(&zero.to_biguint().unwrap()), Felt::from(0)); + assert_eq!(Felt::from(&zero.to_biguint().unwrap()), Felt::from(0)); assert_eq!(Felt::from(&zero), Felt::from(0)); assert_eq!( @@ -1671,7 +1673,7 @@ mod test { Felt::from_hex(number_str).unwrap() ); assert_eq!( - biguint_to_felt(&BigUint::from_str_radix(&number_str[2..], 16).unwrap()), + Felt::from(&BigUint::from_str_radix(&number_str[2..], 16).unwrap()), Felt::from_hex(number_str).unwrap() ) } From 8a86316e377acb27564a34325ed745c29f9a3d50 Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Mon, 18 Dec 2023 20:25:43 -0300 Subject: [PATCH 7/9] impl Felt.to_biguint() method --- crates/starknet-types-core/src/felt.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/starknet-types-core/src/felt.rs b/crates/starknet-types-core/src/felt.rs index 56efc8b..bf8b975 100644 --- a/crates/starknet-types-core/src/felt.rs +++ b/crates/starknet-types-core/src/felt.rs @@ -356,6 +356,15 @@ impl Felt { pub fn bits(&self) -> usize { self.0.representative().bits_le() } + + pub fn to_biguint(&self) -> BigUint { + let big_digits = self + .to_le_digits() + .into_iter() + .flat_map(|limb| [limb as u32, (limb >> 32) as u32]) + .collect(); + BigUint::new(big_digits) + } } #[cfg(feature = "arbitrary")] @@ -824,17 +833,8 @@ mod arithmetic { } } -pub fn felt_to_biguint(felt: Felt) -> BigUint { - let big_digits = felt - .to_le_digits() - .into_iter() - .flat_map(|limb| [limb as u32, (limb >> 32) as u32]) - .collect(); - BigUint::new(big_digits) -} - pub fn felt_to_bigint(felt: Felt) -> BigInt { - felt_to_biguint(felt).to_bigint().unwrap() + felt.to_biguint().to_bigint().unwrap() } #[cfg(feature = "serde")] @@ -1697,7 +1697,7 @@ mod test { ); assert_eq!( - felt_to_biguint(Felt::from_hex(number_str).unwrap()), + Felt::from_hex(number_str).unwrap().to_biguint(), BigUint::from_str_radix(&number_str[2..], 16).unwrap() ); } From dd7580e0c525f06a927787fc89d9afe7be572057 Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Mon, 18 Dec 2023 20:27:16 -0300 Subject: [PATCH 8/9] impl Felt.to_bigint() method --- crates/starknet-types-core/src/felt.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/starknet-types-core/src/felt.rs b/crates/starknet-types-core/src/felt.rs index bf8b975..09e8322 100644 --- a/crates/starknet-types-core/src/felt.rs +++ b/crates/starknet-types-core/src/felt.rs @@ -365,6 +365,10 @@ impl Felt { .collect(); BigUint::new(big_digits) } + + pub fn to_bigint(&self) -> BigInt { + self.to_biguint().to_bigint().unwrap() + } } #[cfg(feature = "arbitrary")] @@ -833,10 +837,6 @@ mod arithmetic { } } -pub fn felt_to_bigint(felt: Felt) -> BigInt { - felt.to_biguint().to_bigint().unwrap() -} - #[cfg(feature = "serde")] mod serde { use ::serde::{de, ser::SerializeSeq, Deserialize, Serialize}; @@ -1692,7 +1692,7 @@ mod test { for number_str in numbers_str { assert_eq!( - felt_to_bigint(Felt::from_hex(number_str).unwrap()), + Felt::from_hex(number_str).unwrap().to_bigint(), BigInt::from_str_radix(&number_str[2..], 16).unwrap() ); From 29f0b9d6446c24696893583cd17e097595ac729d Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Tue, 19 Dec 2023 16:31:45 -0300 Subject: [PATCH 9/9] remove unwrap --- crates/starknet-types-core/src/felt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/starknet-types-core/src/felt.rs b/crates/starknet-types-core/src/felt.rs index 09e8322..a354a6f 100644 --- a/crates/starknet-types-core/src/felt.rs +++ b/crates/starknet-types-core/src/felt.rs @@ -2,7 +2,7 @@ use core::ops::{Add, Mul, Neg}; use bitvec::array::BitArray; use lazy_static::lazy_static; -use num_bigint::{BigInt, BigUint, Sign, ToBigInt}; +use num_bigint::{BigInt, BigUint, Sign}; use num_integer::Integer; use num_traits::Num; use num_traits::{FromPrimitive, One, ToPrimitive, Zero}; @@ -367,7 +367,7 @@ impl Felt { } pub fn to_bigint(&self) -> BigInt { - self.to_biguint().to_bigint().unwrap() + self.to_biguint().into() } }