Repository: ergoplatform/sigma-rust (language: rust)

Issue:
Cannot parse block headers
Hello,

I am running my local/private blockchain and learning Ergo ecosystem.
One of my current focuses is transaction building, I followed the [test](https://github.com/ergoplatform/sigma-rust/blob/a0d8064368874e5b3ac74bc9caffe028452728dc/bindings/ergo-lib-wasm/tests/test_transaction.js#L42) as example reference.
Unfortunately, during preparation, the code fails on block headers parsing `BlockHeaders.from_json`. 
After the brief check, I found out that the node returns every block header with a number in scientific notation in `powSolutions`.


Block header example
```json
{
    "extensionId": "d89ac3f01ab58970cad8db055624019d4611ff61777eaf37fae7dcc9b59d0622",
    "difficulty": "5167",
    "votes": "000000",
    "timestamp": 1669208320317,
    "size": 219,
    "stateRoot": "92e3e8dd6a58e4166e85035e6c9e27207694fb616c7c66e0111ece09e9dca4bf0a",
    "height": 414,
    "nBits": 34877184,
    "version": 2,
    "id": "9999ed27c71f0b4845a3c41bff7355d84b51d0c0f21880f940baaa74517dc12b",
    "adProofsRoot": "9054b37bbd8db31b37dce826687f80ebf141fec95434dcd28354b3b3b4c98579",
    "transactionsRoot": "610610fbed1e382ef9895268b701ae6d888bc1346c1914dd43a78347f96b24b2",
    "extensionHash": "7fae88440bd85750a4765624ccc4185326374da5757afa852210afed7eb91b3c",
    "powSolutions": {
      "pk": "03bac4a5b1b049ead13d1068a8d2835a08a0e14ca2605ac53bbf7f610a7a86fae2",
      "w": "029e412e597896f156db320ab5331b50db2a2337876db47e3606f4b0dab26f4cfc",
      "n": "0000000000000b64",
      "d": 4.121173574974252e+72
    },
    "adProofsId": "37a8b919c289e665c3a519a01e6d02d16899a20211d816884dbd7a1548b4148b",
    "transactionsId": "229880f7570690530abeb22bee15d7649dba5f35acce64f945eb3a1ed457ca93",
    "parentId": "afee323f08fb495342db9a5bf2d1a4169a529ab7ec507f798768759ef25eb428"
  }
```

Please make parsing for such a payload as robust as possible because it's returned by Ergo 5.0.2-0-b7507c43-20221102-1755-SNAPSHOT.


Discussion / hints:

Fix patch:
diff --git a/ergo-chain-types/Cargo.toml b/ergo-chain-types/Cargo.toml
index 90e11cd10..58d9b1f49 100644
--- a/ergo-chain-types/Cargo.toml
+++ b/ergo-chain-types/Cargo.toml
@@ -30,6 +30,7 @@ byteorder = { workspace = true }
 serde_with = { workspace = true, optional = true }
 proptest = { workspace = true , optional = true }
 proptest-derive = {workspace = true, optional = true }
+num-traits = { workspace = true }
 
 [features]
 default = ["json"]
diff --git a/ergo-chain-types/src/json/autolykos_solution.rs b/ergo-chain-types/src/json/autolykos_solution.rs
index c5bb2d208..4f6ed3308 100644
--- a/ergo-chain-types/src/json/autolykos_solution.rs
+++ b/ergo-chain-types/src/json/autolykos_solution.rs
@@ -3,6 +3,7 @@
 use std::str::FromStr;
 
 use num_bigint::BigInt;
+use num_traits::FromPrimitive;
 use serde::{Deserialize, Deserializer};
 
 pub(crate) fn as_base16_string<S>(value: &[u8], serializer: S) -> Result<S::Ok, S::Error>
@@ -50,9 +51,21 @@ where
             DeserializeBigIntFrom::String(s) => BigInt::from_str(&s)
                 .map(Some)
                 .map_err(|e| Error::custom(e.to_string())),
-            DeserializeBigIntFrom::SerdeJsonNumber(n) => BigInt::from_str(&n.to_string())
-                .map(Some)
-                .map_err(|e| Error::custom(e.to_string())),
+            DeserializeBigIntFrom::SerdeJsonNumber(n) => {
+                let bigint = if n.is_f64() {
+                    let n_f64 = n
+                        .as_f64()
+                        .ok_or_else(|| Error::custom("failed to convert JSON number to f64"))?;
+
+                    BigInt::from_f64(n_f64).ok_or_else(|| {
+                        Error::custom("failed to create BigInt from f64".to_string())
+                    })
+                } else {
+                    BigInt::from_str(&n.to_string()).map_err(|e| Error::custom(e.to_string()))
+                };
+
+                bigint.map(Some)
+            }
         },
         Err(e) => Err(Error::custom(e.to_string())),
     }
@@ -64,3 +77,24 @@ enum DeserializeBigIntFrom {
     String(String),
     SerdeJsonNumber(serde_json::Number),
 }
+
+#[allow(clippy::unwrap_used)]
+#[cfg(test)]
+mod tests {
+    use serde::de::IntoDeserializer;
+    use serde_json::Value;
+
+    use super::bigint_from_serde_json_number;
+
+    #[test]
+    fn test_scientific_notion_deser() {
+        let pow_d_parameter = r#"4.69094608138843e64"#;
+        let j: Value = serde_json::from_str(pow_d_parameter).unwrap();
+        let result = bigint_from_serde_json_number(j.into_deserializer()).unwrap();
+
+        assert_eq!(
+            result.unwrap().to_string(),
+            "46909460813884301641411510982628556119846083366464832536248844288"
+        )
+    }
+}


Test patch: