From 053ed0fd68118b72c7eb9d6abfbd35bb45caba0a Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Mon, 11 Dec 2023 15:43:07 -0300 Subject: [PATCH] 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};