reth_engine_primitives/
config.rs

1//! Engine tree configuration.
2
3/// Triggers persistence when the number of canonical blocks in memory exceeds this threshold.
4pub const DEFAULT_PERSISTENCE_THRESHOLD: u64 = 2;
5
6/// How close to the canonical head we persist blocks.
7pub const DEFAULT_MEMORY_BLOCK_BUFFER_TARGET: u64 = 2;
8
9/// Default maximum concurrency for proof tasks
10pub const DEFAULT_MAX_PROOF_TASK_CONCURRENCY: u64 = 256;
11
12/// Default number of reserved CPU cores for non-reth processes.
13///
14/// This will be deducated from the thread count of main reth global threadpool.
15pub const DEFAULT_RESERVED_CPU_CORES: usize = 1;
16
17const DEFAULT_BLOCK_BUFFER_LIMIT: u32 = 256;
18const DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH: u32 = 256;
19const DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE: usize = 4;
20const DEFAULT_CROSS_BLOCK_CACHE_SIZE: u64 = 4 * 1024 * 1024 * 1024;
21
22/// Determines if the host has enough parallelism to run the payload processor.
23///
24/// It requires at least 5 parallel threads:
25/// - Engine in main thread that spawns the state root task.
26/// - Multiproof task in payload processor
27/// - Sparse Trie task in payload processor
28/// - Multiproof computation spawned in payload processor
29/// - Storage root computation spawned in trie parallel proof
30pub fn has_enough_parallelism() -> bool {
31    #[cfg(feature = "std")]
32    {
33        std::thread::available_parallelism().is_ok_and(|num| num.get() >= 5)
34    }
35    #[cfg(not(feature = "std"))]
36    false
37}
38
39/// The configuration of the engine tree.
40#[derive(Debug)]
41pub struct TreeConfig {
42    /// Maximum number of blocks to be kept only in memory without triggering
43    /// persistence.
44    persistence_threshold: u64,
45    /// How close to the canonical head we persist blocks. Represents the ideal
46    /// number of most recent blocks to keep in memory for quick access and reorgs.
47    ///
48    /// Note: this should be less than or equal to `persistence_threshold`.
49    memory_block_buffer_target: u64,
50    /// Number of pending blocks that cannot be executed due to missing parent and
51    /// are kept in cache.
52    block_buffer_limit: u32,
53    /// Number of invalid headers to keep in cache.
54    max_invalid_header_cache_length: u32,
55    /// Maximum number of blocks to execute sequentially in a batch.
56    ///
57    /// This is used as a cutoff to prevent long-running sequential block execution when we receive
58    /// a batch of downloaded blocks.
59    max_execute_block_batch_size: usize,
60    /// Whether to use the legacy state root calculation method instead of the
61    /// new state root task.
62    legacy_state_root: bool,
63    /// Whether to always compare trie updates from the state root task to the trie updates from
64    /// the regular state root calculation.
65    always_compare_trie_updates: bool,
66    /// Whether to disable cross-block caching and parallel prewarming.
67    disable_caching_and_prewarming: bool,
68    /// Whether to enable state provider metrics.
69    state_provider_metrics: bool,
70    /// Cross-block cache size in bytes.
71    cross_block_cache_size: u64,
72    /// Whether the host has enough parallelism to run state root task.
73    has_enough_parallelism: bool,
74    /// Maximum number of concurrent proof tasks
75    max_proof_task_concurrency: u64,
76    /// Number of reserved CPU cores for non-reth processes
77    reserved_cpu_cores: usize,
78    /// Whether to enable the precompile cache
79    precompile_cache_enabled: bool,
80}
81
82impl Default for TreeConfig {
83    fn default() -> Self {
84        Self {
85            persistence_threshold: DEFAULT_PERSISTENCE_THRESHOLD,
86            memory_block_buffer_target: DEFAULT_MEMORY_BLOCK_BUFFER_TARGET,
87            block_buffer_limit: DEFAULT_BLOCK_BUFFER_LIMIT,
88            max_invalid_header_cache_length: DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH,
89            max_execute_block_batch_size: DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE,
90            legacy_state_root: false,
91            always_compare_trie_updates: false,
92            disable_caching_and_prewarming: false,
93            state_provider_metrics: false,
94            cross_block_cache_size: DEFAULT_CROSS_BLOCK_CACHE_SIZE,
95            has_enough_parallelism: has_enough_parallelism(),
96            max_proof_task_concurrency: DEFAULT_MAX_PROOF_TASK_CONCURRENCY,
97            reserved_cpu_cores: DEFAULT_RESERVED_CPU_CORES,
98            precompile_cache_enabled: false,
99        }
100    }
101}
102
103impl TreeConfig {
104    /// Create engine tree configuration.
105    #[expect(clippy::too_many_arguments)]
106    pub const fn new(
107        persistence_threshold: u64,
108        memory_block_buffer_target: u64,
109        block_buffer_limit: u32,
110        max_invalid_header_cache_length: u32,
111        max_execute_block_batch_size: usize,
112        legacy_state_root: bool,
113        always_compare_trie_updates: bool,
114        disable_caching_and_prewarming: bool,
115        state_provider_metrics: bool,
116        cross_block_cache_size: u64,
117        has_enough_parallelism: bool,
118        max_proof_task_concurrency: u64,
119        reserved_cpu_cores: usize,
120        precompile_cache_enabled: bool,
121    ) -> Self {
122        Self {
123            persistence_threshold,
124            memory_block_buffer_target,
125            block_buffer_limit,
126            max_invalid_header_cache_length,
127            max_execute_block_batch_size,
128            legacy_state_root,
129            always_compare_trie_updates,
130            disable_caching_and_prewarming,
131            state_provider_metrics,
132            cross_block_cache_size,
133            has_enough_parallelism,
134            max_proof_task_concurrency,
135            reserved_cpu_cores,
136            precompile_cache_enabled,
137        }
138    }
139
140    /// Return the persistence threshold.
141    pub const fn persistence_threshold(&self) -> u64 {
142        self.persistence_threshold
143    }
144
145    /// Return the memory block buffer target.
146    pub const fn memory_block_buffer_target(&self) -> u64 {
147        self.memory_block_buffer_target
148    }
149
150    /// Return the block buffer limit.
151    pub const fn block_buffer_limit(&self) -> u32 {
152        self.block_buffer_limit
153    }
154
155    /// Return the maximum invalid cache header length.
156    pub const fn max_invalid_header_cache_length(&self) -> u32 {
157        self.max_invalid_header_cache_length
158    }
159
160    /// Return the maximum execute block batch size.
161    pub const fn max_execute_block_batch_size(&self) -> usize {
162        self.max_execute_block_batch_size
163    }
164
165    /// Return the maximum proof task concurrency.
166    pub const fn max_proof_task_concurrency(&self) -> u64 {
167        self.max_proof_task_concurrency
168    }
169
170    /// Return the number of reserved CPU cores for non-reth processes
171    pub const fn reserved_cpu_cores(&self) -> usize {
172        self.reserved_cpu_cores
173    }
174
175    /// Returns whether to use the legacy state root calculation method instead
176    /// of the new state root task
177    pub const fn legacy_state_root(&self) -> bool {
178        self.legacy_state_root
179    }
180
181    /// Returns whether or not state provider metrics are enabled.
182    pub const fn state_provider_metrics(&self) -> bool {
183        self.state_provider_metrics
184    }
185
186    /// Returns whether or not cross-block caching and parallel prewarming should be used.
187    pub const fn disable_caching_and_prewarming(&self) -> bool {
188        self.disable_caching_and_prewarming
189    }
190
191    /// Returns whether to always compare trie updates from the state root task to the trie updates
192    /// from the regular state root calculation.
193    pub const fn always_compare_trie_updates(&self) -> bool {
194        self.always_compare_trie_updates
195    }
196
197    /// Returns the cross-block cache size.
198    pub const fn cross_block_cache_size(&self) -> u64 {
199        self.cross_block_cache_size
200    }
201
202    /// Returns whether precompile cache is enabled.
203    pub const fn precompile_cache_enabled(&self) -> bool {
204        self.precompile_cache_enabled
205    }
206
207    /// Setter for persistence threshold.
208    pub const fn with_persistence_threshold(mut self, persistence_threshold: u64) -> Self {
209        self.persistence_threshold = persistence_threshold;
210        self
211    }
212
213    /// Setter for memory block buffer target.
214    pub const fn with_memory_block_buffer_target(
215        mut self,
216        memory_block_buffer_target: u64,
217    ) -> Self {
218        self.memory_block_buffer_target = memory_block_buffer_target;
219        self
220    }
221
222    /// Setter for block buffer limit.
223    pub const fn with_block_buffer_limit(mut self, block_buffer_limit: u32) -> Self {
224        self.block_buffer_limit = block_buffer_limit;
225        self
226    }
227
228    /// Setter for maximum invalid header cache length.
229    pub const fn with_max_invalid_header_cache_length(
230        mut self,
231        max_invalid_header_cache_length: u32,
232    ) -> Self {
233        self.max_invalid_header_cache_length = max_invalid_header_cache_length;
234        self
235    }
236
237    /// Setter for maximum execute block batch size.
238    pub const fn with_max_execute_block_batch_size(
239        mut self,
240        max_execute_block_batch_size: usize,
241    ) -> Self {
242        self.max_execute_block_batch_size = max_execute_block_batch_size;
243        self
244    }
245
246    /// Setter for whether to use the legacy state root calculation method.
247    pub const fn with_legacy_state_root(mut self, legacy_state_root: bool) -> Self {
248        self.legacy_state_root = legacy_state_root;
249        self
250    }
251
252    /// Setter for whether to disable cross-block caching and parallel prewarming.
253    pub const fn without_caching_and_prewarming(
254        mut self,
255        disable_caching_and_prewarming: bool,
256    ) -> Self {
257        self.disable_caching_and_prewarming = disable_caching_and_prewarming;
258        self
259    }
260
261    /// Setter for whether to always compare trie updates from the state root task to the trie
262    /// updates from the regular state root calculation.
263    pub const fn with_always_compare_trie_updates(
264        mut self,
265        always_compare_trie_updates: bool,
266    ) -> Self {
267        self.always_compare_trie_updates = always_compare_trie_updates;
268        self
269    }
270
271    /// Setter for cross block cache size.
272    pub const fn with_cross_block_cache_size(mut self, cross_block_cache_size: u64) -> Self {
273        self.cross_block_cache_size = cross_block_cache_size;
274        self
275    }
276
277    /// Setter for has enough parallelism.
278    pub const fn with_has_enough_parallelism(mut self, has_enough_parallelism: bool) -> Self {
279        self.has_enough_parallelism = has_enough_parallelism;
280        self
281    }
282
283    /// Setter for state provider metrics.
284    pub const fn with_state_provider_metrics(mut self, state_provider_metrics: bool) -> Self {
285        self.state_provider_metrics = state_provider_metrics;
286        self
287    }
288
289    /// Setter for maximum number of concurrent proof tasks.
290    pub const fn with_max_proof_task_concurrency(
291        mut self,
292        max_proof_task_concurrency: u64,
293    ) -> Self {
294        self.max_proof_task_concurrency = max_proof_task_concurrency;
295        self
296    }
297
298    /// Setter for the number of reserved CPU cores for any non-reth processes
299    pub const fn with_reserved_cpu_cores(mut self, reserved_cpu_cores: usize) -> Self {
300        self.reserved_cpu_cores = reserved_cpu_cores;
301        self
302    }
303
304    /// Setter for whether to use the precompile cache.
305    pub const fn with_precompile_cache_enabled(mut self, precompile_cache_enabled: bool) -> Self {
306        self.precompile_cache_enabled = precompile_cache_enabled;
307        self
308    }
309
310    /// Whether or not to use state root task
311    pub const fn use_state_root_task(&self) -> bool {
312        self.has_enough_parallelism && !self.legacy_state_root
313    }
314}