Skip to main content

reth_rpc_eth_types/cache/
config.rs

1//! Configuration for RPC cache.
2
3use serde::{Deserialize, Serialize};
4use std::time::Duration;
5
6use reth_rpc_server_types::constants::cache::{
7    DEFAULT_BAL_CACHE_MAX_BYTES, DEFAULT_BAL_CACHE_MAX_LEN, DEFAULT_BLOCK_CACHE_MAX_BYTES,
8    DEFAULT_BLOCK_CACHE_MAX_LEN, DEFAULT_CACHE_IDLE_TIMEOUT, DEFAULT_CONCURRENT_DB_REQUESTS,
9    DEFAULT_MAX_CACHED_TX_HASHES, DEFAULT_RECEIPT_CACHE_MAX_BYTES, DEFAULT_RECEIPT_CACHE_MAX_LEN,
10};
11
12/// Settings for the [`EthStateCache`](super::EthStateCache).
13///
14/// Byte budgets cover estimated payload sizes, excluding map and request queue overhead. Shared
15/// payloads can remain allocated after eviction while other components still hold references.
16#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
17#[serde(default, rename_all = "camelCase")]
18pub struct EthStateCacheConfig {
19    /// Max number of blocks in cache.
20    ///
21    /// Default is 1000.
22    pub max_blocks: u32,
23    /// Max number of blocks' receipts in cache.
24    ///
25    /// Default is 500.
26    pub max_receipts: u32,
27    /// Max number of EVM BALs in cache.
28    ///
29    /// Default is 1000.
30    pub max_bals: u32,
31    /// Maximum estimated memory retained by the block cache, in bytes.
32    ///
33    /// Defaults to 2 GiB. Zero disables caching. The entry count limit also applies.
34    pub max_blocks_bytes: usize,
35    /// Maximum estimated memory retained by the receipts cache, in bytes.
36    ///
37    /// Defaults to 1 GiB. Zero disables caching. The entry count limit also applies.
38    pub max_receipts_bytes: usize,
39    /// Maximum estimated memory retained by the BAL cache, in bytes.
40    ///
41    /// Defaults to 500 MiB. Zero disables caching. The entry count limit also applies.
42    pub max_bals_bytes: usize,
43    /// Duration after which an unused block, receipts collection, or BAL is evicted.
44    ///
45    /// Defaults to one hour. Successful lookups refresh the timeout. Zero disables expiration.
46    /// Periodic cleanup starts at least once per minute and removes expired entries in bounded
47    /// batches.
48    pub idle_timeout: Duration,
49    /// Cache BALs computed by RPC requests for transaction tracing. Disabled by default.
50    #[serde(default)]
51    pub cache_computed_bals: bool,
52    /// Prewarm BALs until native BAL support, optionally replaying this many recent blocks on
53    /// startup. `Some(0)` prewarms only new canonical blocks; `None` disables prewarming.
54    ///
55    /// Implies caching of BALs computed by RPC requests.
56    #[serde(default)]
57    pub prewarm_bals: Option<usize>,
58    /// Max number of concurrent database requests.
59    ///
60    /// Default is 512.
61    pub max_concurrent_db_requests: usize,
62    /// Maximum number of transaction hashes to cache for transaction lookups.
63    pub max_cached_tx_hashes: u32,
64}
65
66impl Default for EthStateCacheConfig {
67    fn default() -> Self {
68        Self {
69            max_blocks: DEFAULT_BLOCK_CACHE_MAX_LEN,
70            max_receipts: DEFAULT_RECEIPT_CACHE_MAX_LEN,
71            max_bals: DEFAULT_BAL_CACHE_MAX_LEN,
72            max_blocks_bytes: DEFAULT_BLOCK_CACHE_MAX_BYTES,
73            max_receipts_bytes: DEFAULT_RECEIPT_CACHE_MAX_BYTES,
74            max_bals_bytes: DEFAULT_BAL_CACHE_MAX_BYTES,
75            idle_timeout: DEFAULT_CACHE_IDLE_TIMEOUT,
76            cache_computed_bals: false,
77            prewarm_bals: None,
78            max_concurrent_db_requests: DEFAULT_CONCURRENT_DB_REQUESTS,
79            max_cached_tx_hashes: DEFAULT_MAX_CACHED_TX_HASHES,
80        }
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    #[test]
89    fn legacy_cache_config_uses_default_limits() {
90        let config: EthStateCacheConfig = serde_json::from_value(serde_json::json!({
91            "maxBlocks": 1000,
92            "maxReceipts": 500,
93            "maxBals": 1000,
94            "maxConcurrentDbRequests": 512,
95            "maxCachedTxHashes": 100000
96        }))
97        .unwrap();
98
99        assert_eq!(config, EthStateCacheConfig::default());
100        assert_eq!(config.max_blocks_bytes, DEFAULT_BLOCK_CACHE_MAX_BYTES);
101        assert_eq!(config.max_receipts_bytes, DEFAULT_RECEIPT_CACHE_MAX_BYTES);
102        assert_eq!(config.max_bals_bytes, DEFAULT_BAL_CACHE_MAX_BYTES);
103        assert_eq!(config.idle_timeout, DEFAULT_CACHE_IDLE_TIMEOUT);
104    }
105
106    #[test]
107    fn cache_memory_limits_and_idle_timeout_round_trip() {
108        for config in [
109            EthStateCacheConfig::default(),
110            EthStateCacheConfig {
111                max_blocks_bytes: 1024,
112                max_receipts_bytes: 2048,
113                max_bals_bytes: 4096,
114                idle_timeout: Duration::from_millis(1500),
115                ..Default::default()
116            },
117            EthStateCacheConfig {
118                max_blocks_bytes: 0,
119                max_receipts_bytes: 0,
120                max_bals_bytes: 0,
121                idle_timeout: Duration::ZERO,
122                ..Default::default()
123            },
124        ] {
125            let serialized = serde_json::to_value(config).unwrap();
126            assert_eq!(serialized["maxBlocksBytes"], serde_json::json!(config.max_blocks_bytes));
127            assert_eq!(
128                serialized["maxReceiptsBytes"],
129                serde_json::json!(config.max_receipts_bytes)
130            );
131            assert_eq!(serialized["maxBalsBytes"], serde_json::json!(config.max_bals_bytes));
132            assert_eq!(serde_json::from_value::<EthStateCacheConfig>(serialized).unwrap(), config);
133        }
134    }
135}