diff --git a/crates/rpc-types-eth/src/filter.rs b/crates/rpc-types-eth/src/filter.rs index 96e2af0f3a8..cd6739139bd 100644 --- a/crates/rpc-types-eth/src/filter.rs +++ b/crates/rpc-types-eth/src/filter.rs @@ -14,6 +14,7 @@ use std::{ hash::Hash, ops::{Range, RangeFrom, RangeTo}, }; +use thiserror::Error; /// Helper type to represent a bloom filter used for matching logs. #[derive(Debug, Default)] @@ -153,6 +154,19 @@ impl From for Topic { } } +/// Represents errors that can occur when setting block filters in `FilterBlockOption`. +#[derive(Debug, PartialEq, Eq, Error)] +pub enum FilterBlockError { + /// Error indicating that the `from_block` is greater than the `to_block`. + #[error("`from_block` ({from}) is greater than `to_block` ({to})")] + FromBlockGreaterThanToBlock { + /// The starting block number, which is greater than `to`. + from: u64, + /// The ending block number, which is less than `from`. + to: u64, + }, +} + /// Represents the target range of blocks for the filter #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum FilterBlockOption { @@ -212,6 +226,20 @@ impl FilterBlockOption { matches!(self, Self::AtBlockHash(_)) } + /// Ensure block range validity + pub fn ensure_valid_block_range(&self) -> Result<(), FilterBlockError> { + // Check if from_block is greater than to_block + if let (Some(from), Some(to)) = ( + self.get_from_block().as_ref().and_then(|from| from.as_number()), + self.get_to_block().as_ref().and_then(|to| to.as_number()), + ) { + if from > to { + return Err(FilterBlockError::FromBlockGreaterThanToBlock { from, to }); + } + } + Ok(()) + } + /// Sets the block number this range filter should start at. #[must_use] pub fn with_from_block(&self, block: BlockNumberOrTag) -> Self { @@ -1154,6 +1182,31 @@ mod tests { ); } + #[test] + fn test_with_from_block_correct_range() { + // Test scenario where from_block is less than to_block + let original = FilterBlockOption::Range { + from_block: Some(BlockNumberOrTag::Number(1)), + to_block: Some(BlockNumberOrTag::Number(10)), + }; + let updated = original.with_from_block(BlockNumberOrTag::Number(5)); + assert!(updated.ensure_valid_block_range().is_ok()); + } + + #[test] + fn test_with_from_block_failure() { + // Test scenario where from_block is greater than to_block + let original = FilterBlockOption::Range { + from_block: Some(BlockNumberOrTag::Number(10)), + to_block: Some(BlockNumberOrTag::Number(5)), + }; + + assert!(matches!( + original.ensure_valid_block_range(), + Err(FilterBlockError::FromBlockGreaterThanToBlock { .. }) + )); + } + #[test] fn test_block_hash() { let s =