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
9const DEFAULT_BLOCK_BUFFER_LIMIT: u32 = 256;
10const DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH: u32 = 256;
11const DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE: usize = 4;
12const DEFAULT_CROSS_BLOCK_CACHE_SIZE: u64 = 4 * 1024 * 1024 * 1024;
13
14/// Determines if the host has enough parallelism to run the payload processor.
15///
16/// It requires at least 5 parallel threads:
17/// - Engine in main thread that spawns the state root task.
18/// - Multiproof task in payload processor
19/// - Sparse Trie task in payload processor
20/// - Multiproof computation spawned in payload processor
21/// - Storage root computation spawned in trie parallel proof
22pub fn has_enough_parallelism() -> bool {
23    #[cfg(feature = "std")]
24    {
25        std::thread::available_parallelism().is_ok_and(|num| num.get() >= 5)
26    }
27    #[cfg(not(feature = "std"))]
28    false
29}
30
31/// The configuration of the engine tree.
32#[derive(Debug)]
33pub struct TreeConfig {
34    /// Maximum number of blocks to be kept only in memory without triggering
35    /// persistence.
36    persistence_threshold: u64,
37    /// How close to the canonical head we persist blocks. Represents the ideal
38    /// number of most recent blocks to keep in memory for quick access and reorgs.
39    ///
40    /// Note: this should be less than or equal to `persistence_threshold`.
41    memory_block_buffer_target: u64,
42    /// Number of pending blocks that cannot be executed due to missing parent and
43    /// are kept in cache.
44    block_buffer_limit: u32,
45    /// Number of invalid headers to keep in cache.
46    max_invalid_header_cache_length: u32,
47    /// Maximum number of blocks to execute sequentially in a batch.
48    ///
49    /// This is used as a cutoff to prevent long-running sequential block execution when we receive
50    /// a batch of downloaded blocks.
51    max_execute_block_batch_size: usize,
52    /// Whether to use the legacy state root calculation method instead of the
53    /// new state root task
54    legacy_state_root: bool,
55    /// Whether to always compare trie updates from the state root task to the trie updates from
56    /// the regular state root calculation.
57    always_compare_trie_updates: bool,
58    /// Whether to use cross-block caching and parallel prewarming
59    use_caching_and_prewarming: bool,
60    /// Cross-block cache size in bytes.
61    cross_block_cache_size: u64,
62    /// Whether the host has enough parallelism to run state root task.
63    has_enough_parallelism: bool,
64}
65
66impl Default for TreeConfig {
67    fn default() -> Self {
68        Self {
69            persistence_threshold: DEFAULT_PERSISTENCE_THRESHOLD,
70            memory_block_buffer_target: DEFAULT_MEMORY_BLOCK_BUFFER_TARGET,
71            block_buffer_limit: DEFAULT_BLOCK_BUFFER_LIMIT,
72            max_invalid_header_cache_length: DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH,
73            max_execute_block_batch_size: DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE,
74            legacy_state_root: false,
75            always_compare_trie_updates: false,
76            use_caching_and_prewarming: false,
77            cross_block_cache_size: DEFAULT_CROSS_BLOCK_CACHE_SIZE,
78            has_enough_parallelism: has_enough_parallelism(),
79        }
80    }
81}
82
83impl TreeConfig {
84    /// Create engine tree configuration.
85    #[expect(clippy::too_many_arguments)]
86    pub const fn new(
87        persistence_threshold: u64,
88        memory_block_buffer_target: u64,
89        block_buffer_limit: u32,
90        max_invalid_header_cache_length: u32,
91        max_execute_block_batch_size: usize,
92        legacy_state_root: bool,
93        always_compare_trie_updates: bool,
94        use_caching_and_prewarming: bool,
95        cross_block_cache_size: u64,
96        has_enough_parallelism: bool,
97    ) -> Self {
98        Self {
99            persistence_threshold,
100            memory_block_buffer_target,
101            block_buffer_limit,
102            max_invalid_header_cache_length,
103            max_execute_block_batch_size,
104            legacy_state_root,
105            always_compare_trie_updates,
106            use_caching_and_prewarming,
107            cross_block_cache_size,
108            has_enough_parallelism,
109        }
110    }
111
112    /// Return the persistence threshold.
113    pub const fn persistence_threshold(&self) -> u64 {
114        self.persistence_threshold
115    }
116
117    /// Return the memory block buffer target.
118    pub const fn memory_block_buffer_target(&self) -> u64 {
119        self.memory_block_buffer_target
120    }
121
122    /// Return the block buffer limit.
123    pub const fn block_buffer_limit(&self) -> u32 {
124        self.block_buffer_limit
125    }
126
127    /// Return the maximum invalid cache header length.
128    pub const fn max_invalid_header_cache_length(&self) -> u32 {
129        self.max_invalid_header_cache_length
130    }
131
132    /// Return the maximum execute block batch size.
133    pub const fn max_execute_block_batch_size(&self) -> usize {
134        self.max_execute_block_batch_size
135    }
136
137    /// Returns whether to use the legacy state root calculation method instead
138    /// of the new state root task
139    pub const fn legacy_state_root(&self) -> bool {
140        self.legacy_state_root
141    }
142
143    /// Returns whether or not cross-block caching and parallel prewarming should be used.
144    pub const fn use_caching_and_prewarming(&self) -> bool {
145        self.use_caching_and_prewarming
146    }
147
148    /// Returns whether to always compare trie updates from the state root task to the trie updates
149    /// from the regular state root calculation.
150    pub const fn always_compare_trie_updates(&self) -> bool {
151        self.always_compare_trie_updates
152    }
153
154    /// Return the cross-block cache size.
155    pub const fn cross_block_cache_size(&self) -> u64 {
156        self.cross_block_cache_size
157    }
158
159    /// Setter for persistence threshold.
160    pub const fn with_persistence_threshold(mut self, persistence_threshold: u64) -> Self {
161        self.persistence_threshold = persistence_threshold;
162        self
163    }
164
165    /// Setter for memory block buffer target.
166    pub const fn with_memory_block_buffer_target(
167        mut self,
168        memory_block_buffer_target: u64,
169    ) -> Self {
170        self.memory_block_buffer_target = memory_block_buffer_target;
171        self
172    }
173
174    /// Setter for block buffer limit.
175    pub const fn with_block_buffer_limit(mut self, block_buffer_limit: u32) -> Self {
176        self.block_buffer_limit = block_buffer_limit;
177        self
178    }
179
180    /// Setter for maximum invalid header cache length.
181    pub const fn with_max_invalid_header_cache_length(
182        mut self,
183        max_invalid_header_cache_length: u32,
184    ) -> Self {
185        self.max_invalid_header_cache_length = max_invalid_header_cache_length;
186        self
187    }
188
189    /// Setter for maximum execute block batch size.
190    pub const fn with_max_execute_block_batch_size(
191        mut self,
192        max_execute_block_batch_size: usize,
193    ) -> Self {
194        self.max_execute_block_batch_size = max_execute_block_batch_size;
195        self
196    }
197
198    /// Setter for whether to use the legacy state root calculation method.
199    pub const fn with_legacy_state_root(mut self, legacy_state_root: bool) -> Self {
200        self.legacy_state_root = legacy_state_root;
201        self
202    }
203
204    /// Setter for whether to use the new state root task calculation method.
205    pub const fn with_caching_and_prewarming(mut self, use_caching_and_prewarming: bool) -> Self {
206        self.use_caching_and_prewarming = use_caching_and_prewarming;
207        self
208    }
209
210    /// Setter for whether to always compare trie updates from the state root task to the trie
211    /// updates from the regular state root calculation.
212    pub const fn with_always_compare_trie_updates(
213        mut self,
214        always_compare_trie_updates: bool,
215    ) -> Self {
216        self.always_compare_trie_updates = always_compare_trie_updates;
217        self
218    }
219
220    /// Setter for cross block cache size.
221    pub const fn with_cross_block_cache_size(mut self, cross_block_cache_size: u64) -> Self {
222        self.cross_block_cache_size = cross_block_cache_size;
223        self
224    }
225
226    /// Setter for has enough parallelism.
227    pub const fn with_has_enough_parallelism(mut self, has_enough_parallelism: bool) -> Self {
228        self.has_enough_parallelism = has_enough_parallelism;
229        self
230    }
231
232    /// Whether or not to use state root task
233    pub fn use_state_root_task(&self) -> bool {
234        self.has_enough_parallelism && !self.legacy_state_root
235    }
236}