From 4ee4eaad25b416c7a5a15675f28ad92f0930d9a3 Mon Sep 17 00:00:00 2001 From: Hein Dauven Date: Tue, 29 Oct 2024 11:36:01 +0100 Subject: [PATCH 1/2] rusk: upgrade toml to workspace version - Updated `toml` version in Rusk to workspace version - Fixed u64 (de)serialization due to `toml` limitations - Ingest `feeder_gas_call` as String, update example.toml accordingly --- rusk/Cargo.toml | 11 ++++++-- rusk/default.config.toml | 4 +-- rusk/src/bin/config/http.rs | 56 +++++++++++++++++++++++++++++++++---- 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/rusk/Cargo.toml b/rusk/Cargo.toml index 0c2b1eb4ce..3e1adbe421 100644 --- a/rusk/Cargo.toml +++ b/rusk/Cargo.toml @@ -26,7 +26,7 @@ semver = { workspace = true } anyhow = { workspace = true } rustc_tools_util = { workspace = true } rand = { workspace = true } -toml = "=0.5.11" +toml = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } serde_with = { workspace = true, features = ["hex"] } @@ -92,7 +92,14 @@ criterion = { workspace = true } rustc_tools_util = { workspace = true } [features] -default = ["ephemeral", "recovery-state", "recovery-keys", "prover", "chain", "http-wasm"] +default = [ + "ephemeral", + "recovery-state", + "recovery-keys", + "prover", + "chain", + "http-wasm", +] ephemeral = ["dep:rusk-recovery", "dep:tempfile", "recovery-state", "chain"] recovery-state = ["rusk-recovery/state", "dep:tempfile"] recovery-keys = ["rusk-recovery/keys"] diff --git a/rusk/default.config.toml b/rusk/default.config.toml index a41f396f88..8509b77699 100644 --- a/rusk/default.config.toml +++ b/rusk/default.config.toml @@ -9,8 +9,8 @@ #key = # The default max cost for feeder calls is the maximum representable. Put in a -# normal number to change -#feeder_call_gas = u64::MAX +# a string wrapped number up to u64 +#feeder_call_gas = "18446744073709551615" #ws_sub_channel_cap = 16, #ws_event_channel_cap = 1024, diff --git a/rusk/src/bin/config/http.rs b/rusk/src/bin/config/http.rs index 3d102255ce..31914020e3 100644 --- a/rusk/src/bin/config/http.rs +++ b/rusk/src/bin/config/http.rs @@ -7,7 +7,8 @@ use std::path::PathBuf; use hyper::HeaderMap; -use serde::{Deserialize, Serialize}; +use serde::de::{self, Unexpected}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::args::Args; @@ -17,7 +18,11 @@ pub struct HttpConfig { pub key: Option, #[serde(default = "default_listen")] pub listen: bool, - #[serde(default = "default_feeder_call_gas")] + #[serde( + default = "default_feeder_call_gas", + deserialize_with = "deserialize_feeder_call_gas", + serialize_with = "serialize_feeder_call_gas" + )] pub feeder_call_gas: u64, listen_address: Option, #[serde(default = "default_ws_sub_channel_cap")] @@ -28,6 +33,36 @@ pub struct HttpConfig { pub headers: HeaderMap, } +// Custom deserialization function for `feeder_call_gas`. +// TOML values are limited to `i64::MAX` in `toml-rs`, so we parse `u64` as a +// string. +fn deserialize_feeder_call_gas<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + String::deserialize(deserializer)? + .parse::() + .map_err(|_| { + de::Error::invalid_value( + Unexpected::Str("a valid u64 as a string"), + &"a u64 integer", + ) + }) +} + +// Custom serialization function for `feeder_call_gas`. +// Serializes `u64` as a string to bypass `i64::MAX` limitations in TOML +// parsing. +fn serialize_feeder_call_gas( + value: &u64, + serializer: S, +) -> Result +where + S: Serializer, +{ + serializer.serialize_str(&value.to_string()) +} + impl Default for HttpConfig { fn default() -> Self { Self { @@ -119,7 +154,7 @@ mod vec_header_map { struct TupleVecVisitor; impl<'de> Visitor<'de> for TupleVecVisitor { - type Value = Vec<(&'de str, &'de str)>; + type Value = Vec<(String, String)>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a tuple header name and value") @@ -146,7 +181,7 @@ mod vec_header_map { for (k, v) in tuple_vec { let name = HeaderName::from_bytes(k.as_bytes()) .map_err(D::Error::custom)?; - let value = HeaderValue::from_str(v).map_err(D::Error::custom)?; + let value = HeaderValue::from_str(&v).map_err(D::Error::custom)?; headers.insert(name, value); } @@ -179,7 +214,7 @@ mod tests { #[test] fn deserialize_config() { let config_str = r#"listen = true - feeder_call_gas = 18446744 + feeder_call_gas = "18446744" ws_sub_channel_cap = 16 ws_event_channel_cap = 1024 headers = [["name1", "value1"], ["name2", "value2"]]"#; @@ -187,4 +222,15 @@ mod tests { toml::from_str::(config_str) .expect("deserializing config should succeed"); } + + #[test] + fn deserialize_invalid_feeder_call_gas() { + let config_str = r#"feeder_call_gas = "invalid_number""#; + let result = toml::from_str::(config_str); + assert!(result.is_err()); + + let config_str = r#"feeder_call_gas = 18446744"#; + let result = toml::from_str::(config_str); + assert!(result.is_err()); + } } From 0b5ccfbc525f98ca5c8c76bd98b1747f51dbc972 Mon Sep 17 00:00:00 2001 From: Hein Dauven Date: Tue, 29 Oct 2024 12:44:35 +0100 Subject: [PATCH 2/2] rusk: Add test cases for large feeder_call_gas deser --- rusk/default.config.toml | 2 +- rusk/src/bin/config/http.rs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/rusk/default.config.toml b/rusk/default.config.toml index 8509b77699..71d023a9b0 100644 --- a/rusk/default.config.toml +++ b/rusk/default.config.toml @@ -9,7 +9,7 @@ #key = # The default max cost for feeder calls is the maximum representable. Put in a -# a string wrapped number up to u64 +# a string wrapped number up to u64::MAX #feeder_call_gas = "18446744073709551615" #ws_sub_channel_cap = 16, diff --git a/rusk/src/bin/config/http.rs b/rusk/src/bin/config/http.rs index 31914020e3..244b42e809 100644 --- a/rusk/src/bin/config/http.rs +++ b/rusk/src/bin/config/http.rs @@ -233,4 +233,18 @@ mod tests { let result = toml::from_str::(config_str); assert!(result.is_err()); } + + #[test] + fn deserialize_large_feeder_call_gas() { + // A feeder_call_gas value beyond i64::MAX, but within u64 limits + let config_str = r#"feeder_call_gas = "9999999999999999999""#; + let config: HttpConfig = toml::from_str(config_str) + .expect("parsing large u64 value should succeed"); + assert_eq!(config.feeder_call_gas, 9999999999999999999); + + let config_str = r#"feeder_call_gas = "18446744073709551615""#; // u64::MAX + let config: HttpConfig = toml::from_str(config_str) + .expect("parsing u64::MAX should succeed"); + assert_eq!(config.feeder_call_gas, u64::MAX); + } }