From 380e6bda6c2707a56098a511b889af08b90f87d9 Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Tue, 4 Jul 2023 18:43:22 +0100 Subject: [PATCH 1/3] feat(config, primitives): validate Receipts prune part --- crates/config/src/config.rs | 7 ++- crates/primitives/src/serde_helper/mod.rs | 2 + crates/primitives/src/serde_helper/prune.rs | 48 +++++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 crates/primitives/src/serde_helper/prune.rs diff --git a/crates/config/src/config.rs b/crates/config/src/config.rs index f0dfb4ac2bbb..7de5b81759cc 100644 --- a/crates/config/src/config.rs +++ b/crates/config/src/config.rs @@ -5,7 +5,7 @@ use reth_downloaders::{ headers::reverse_headers::ReverseHeadersDownloaderBuilder, }; use reth_network::{NetworkConfigBuilder, PeersConfig, SessionsConfig}; -use reth_primitives::PruneMode; +use reth_primitives::{serde_helper::deserialize_opt_prune_mode_with_min_distance, PruneMode}; use secp256k1::SecretKey; use serde::{Deserialize, Serialize}; use std::path::PathBuf; @@ -305,7 +305,10 @@ pub struct PruneParts { #[serde(skip_serializing_if = "Option::is_none")] pub transaction_lookup: Option, /// Receipts pruning configuration. - #[serde(skip_serializing_if = "Option::is_none")] + #[serde( + skip_serializing_if = "Option::is_none", + deserialize_with = "deserialize_opt_prune_mode_with_min_distance::<65, _>" + )] pub receipts: Option, /// Account History pruning configuration. #[serde(skip_serializing_if = "Option::is_none")] diff --git a/crates/primitives/src/serde_helper/mod.rs b/crates/primitives/src/serde_helper/mod.rs index c63e7f62756f..7cd85f892f98 100644 --- a/crates/primitives/src/serde_helper/mod.rs +++ b/crates/primitives/src/serde_helper/mod.rs @@ -10,6 +10,8 @@ use crate::H256; pub use jsonu256::*; pub mod num; +mod prune; +pub use prune::deserialize_opt_prune_mode_with_min_distance; /// serde functions for handling primitive `u64` as [U64](crate::U64) pub mod u64_hex { diff --git a/crates/primitives/src/serde_helper/prune.rs b/crates/primitives/src/serde_helper/prune.rs new file mode 100644 index 000000000000..565a97eb3f28 --- /dev/null +++ b/crates/primitives/src/serde_helper/prune.rs @@ -0,0 +1,48 @@ +use crate::PruneMode; +use serde::{Deserialize, Deserializer}; + +/// Deserializes [`Option`] and validates that the value contained in +/// [PruneMode::Distance] (if any) is not less than the const generic parameter `MIN_DISTANCE`. +pub fn deserialize_opt_prune_mode_with_min_distance< + 'de, + const MIN_DISTANCE: u64, + D: Deserializer<'de>, +>( + deserializer: D, +) -> Result, D::Error> { + let prune_mode = Option::::deserialize(deserializer)?; + + match prune_mode { + Some(PruneMode::Distance(distance)) if distance < MIN_DISTANCE => { + Err(serde::de::Error::invalid_value( + serde::de::Unexpected::Unsigned(distance), + &"prune mode distance is below minimum allowed value", + )) + } + _ => Ok(prune_mode), + } +} + +#[cfg(test)] +mod test { + use crate::PruneMode; + use assert_matches::assert_matches; + use serde::Deserialize; + + #[test] + fn deserialize_opt_prune_mode_with_min_distance() { + #[derive(Debug, Deserialize, PartialEq, Eq)] + struct V( + #[serde( + deserialize_with = "super::deserialize_opt_prune_mode_with_min_distance::<10, _>" + )] + Option, + ); + + assert!(serde_json::from_str::(r#"{"distance": 10}"#).is_ok()); + assert_matches!( + serde_json::from_str::(r#"{"distance": 9}"#), + Err(err) if err.to_string() == "invalid value: integer `9`, expected prune mode distance is below minimum allowed value" + ); + } +} From 115ebad3aa81213706d6d33f29c4eb2cbbd80a8e Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Tue, 4 Jul 2023 19:27:04 +0100 Subject: [PATCH 2/3] improve error message --- crates/primitives/src/serde_helper/prune.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/primitives/src/serde_helper/prune.rs b/crates/primitives/src/serde_helper/prune.rs index 565a97eb3f28..7dffafdf8f7f 100644 --- a/crates/primitives/src/serde_helper/prune.rs +++ b/crates/primitives/src/serde_helper/prune.rs @@ -16,7 +16,8 @@ pub fn deserialize_opt_prune_mode_with_min_distance< Some(PruneMode::Distance(distance)) if distance < MIN_DISTANCE => { Err(serde::de::Error::invalid_value( serde::de::Unexpected::Unsigned(distance), - &"prune mode distance is below minimum allowed value", + // This message should have "expected" wording, so we say "not less than" + &format!("prune mode distance not less than {MIN_DISTANCE} blocks").as_str(), )) } _ => Ok(prune_mode), @@ -42,7 +43,7 @@ mod test { assert!(serde_json::from_str::(r#"{"distance": 10}"#).is_ok()); assert_matches!( serde_json::from_str::(r#"{"distance": 9}"#), - Err(err) if err.to_string() == "invalid value: integer `9`, expected prune mode distance is below minimum allowed value" + Err(err) if err.to_string() == "invalid value: integer `9`, expected prune mode distance not less than 10 blocks" ); } } From d8dc2b7bb89d54bd36f2719fd9e485e898223950 Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Thu, 6 Jul 2023 13:03:23 +0100 Subject: [PATCH 3/3] 65 -> 64 --- crates/config/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/config/src/config.rs b/crates/config/src/config.rs index 7de5b81759cc..40836b8c02c5 100644 --- a/crates/config/src/config.rs +++ b/crates/config/src/config.rs @@ -307,7 +307,7 @@ pub struct PruneParts { /// Receipts pruning configuration. #[serde( skip_serializing_if = "Option::is_none", - deserialize_with = "deserialize_opt_prune_mode_with_min_distance::<65, _>" + deserialize_with = "deserialize_opt_prune_mode_with_min_distance::<64, _>" )] pub receipts: Option, /// Account History pruning configuration.