Skip to content

Commit

Permalink
Handle scientific notation in fn felt_from_number (lambdaclass#1188)
Browse files Browse the repository at this point in the history
* Handle scientific notation cases in fn felt_from_number

* Update CHANGELOG.md

* Add aux function

* Add endline
  • Loading branch information
pefontana authored and kariy committed Jun 23, 2023
1 parent be0db09 commit 60b88e7
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Cairo-VM Changelog

#### Upcoming Changes
* fix: Handle the deserialization of serde_json::Number with scientific notation (e.g.: Number(1e27)) in felt_from_number function [#1188](https://github.com/lambdaclass/cairo-rs/pull/1188)

* bugfix: Use cairo constants in `ASSERT_250_BIT` hint [#1187](https://github.com/lambdaclass/cairo-rs/pull/1187)

Expand Down
40 changes: 38 additions & 2 deletions src/serde/deserialize_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
},
};
use felt::{Felt252, PRIME_STR};
use num_traits::Num;
use num_traits::{Num, Pow};
use serde::Serializer;
use serde::{de, de::MapAccess, de::SeqAccess, Deserialize, Deserializer, Serialize};
use serde_json::Number;
Expand Down Expand Up @@ -171,10 +171,32 @@ where
let n = Number::deserialize(deserializer)?;
match Felt252::parse_bytes(n.to_string().as_bytes(), 10) {
Some(x) => Ok(Some(x)),
None => Err(String::from("felt_from_number parse error")).map_err(de::Error::custom),
None => {
// Handle de Number with scientific notation cases
// e.g.: n = Number(1e27)
let felt = deserialize_scientific_notation(n);
if felt.is_some() {
return Ok(felt);
}

Err(de::Error::custom(String::from(
"felt_from_number parse error",
)))
}
}
}

fn deserialize_scientific_notation(n: Number) -> Option<Felt252> {
let str = n.to_string();
let list: [&str; 2] = str.split('e').collect::<Vec<&str>>().try_into().ok()?;

let base = Felt252::parse_bytes(list[0].to_string().as_bytes(), 10)?;
let exponent = list[1].parse::<u32>().ok()?;

let result = base * Felt252::from(10).pow(exponent);
Some(result)
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct ReferenceManager {
pub references: Vec<Reference>,
Expand Down Expand Up @@ -459,6 +481,7 @@ mod tests {
use super::*;
use assert_matches::assert_matches;
use felt::felt_str;
use num_traits::One;
use num_traits::Zero;

#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -1401,4 +1424,17 @@ mod tests {
let iden: Result<Identifier, serde_json::Error> = serde_json::from_str(valid_json);
assert!(iden.err().is_some());
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn test_felt_from_number_with_scientific_notation() {
let n = Number::deserialize(serde_json::Value::from(1000000000000000000000000000_u128))
.unwrap();
assert_eq!(n.to_string(), "1e27".to_owned());

assert_matches!(
felt_from_number(n),
Ok(x) if x == Some(Felt252::one() * Felt252::from(10).pow(27))
);
}
}

0 comments on commit 60b88e7

Please sign in to comment.