1use alloy_eips::merge::EPOCH_SLOTS;
4
5pub const DEFAULT_PERSISTENCE_THRESHOLD: u64 = 2;
7
8pub const DEFAULT_MEMORY_BLOCK_BUFFER_TARGET: u64 = 0;
10
11pub const MIN_WORKER_COUNT: usize = 32;
13
14fn default_storage_worker_count() -> usize {
16 #[cfg(feature = "std")]
17 {
18 std::thread::available_parallelism().map_or(8, |n| n.get() * 2).min(MIN_WORKER_COUNT)
19 }
20 #[cfg(not(feature = "std"))]
21 {
22 8
23 }
24}
25
26fn default_account_worker_count() -> usize {
31 default_storage_worker_count()
32}
33
34pub const DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE: usize = 60;
36
37pub const DEFAULT_RESERVED_CPU_CORES: usize = 1;
41
42pub const DEFAULT_PREWARM_MAX_CONCURRENCY: usize = 16;
44
45const DEFAULT_BLOCK_BUFFER_LIMIT: u32 = EPOCH_SLOTS as u32 * 2;
46const DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH: u32 = 256;
47const DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE: usize = 4;
48const DEFAULT_CROSS_BLOCK_CACHE_SIZE: u64 = 4 * 1024 * 1024 * 1024;
49
50pub fn has_enough_parallelism() -> bool {
59 #[cfg(feature = "std")]
60 {
61 std::thread::available_parallelism().is_ok_and(|num| num.get() >= 5)
62 }
63 #[cfg(not(feature = "std"))]
64 false
65}
66
67#[derive(Debug, Clone)]
69pub struct TreeConfig {
70 persistence_threshold: u64,
73 memory_block_buffer_target: u64,
78 block_buffer_limit: u32,
81 max_invalid_header_cache_length: u32,
83 max_execute_block_batch_size: usize,
88 legacy_state_root: bool,
91 always_compare_trie_updates: bool,
94 disable_state_cache: bool,
96 disable_prewarming: bool,
98 disable_parallel_sparse_trie: bool,
100 state_provider_metrics: bool,
102 cross_block_cache_size: u64,
104 has_enough_parallelism: bool,
106 multiproof_chunking_enabled: bool,
108 multiproof_chunk_size: usize,
110 reserved_cpu_cores: usize,
112 precompile_cache_disabled: bool,
114 state_root_fallback: bool,
116 always_process_payload_attributes_on_canonical_head: bool,
130 prewarm_max_concurrency: usize,
132 allow_unwind_canonical_header: bool,
134 storage_worker_count: usize,
136 account_worker_count: usize,
138}
139
140impl Default for TreeConfig {
141 fn default() -> Self {
142 Self {
143 persistence_threshold: DEFAULT_PERSISTENCE_THRESHOLD,
144 memory_block_buffer_target: DEFAULT_MEMORY_BLOCK_BUFFER_TARGET,
145 block_buffer_limit: DEFAULT_BLOCK_BUFFER_LIMIT,
146 max_invalid_header_cache_length: DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH,
147 max_execute_block_batch_size: DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE,
148 legacy_state_root: false,
149 always_compare_trie_updates: false,
150 disable_state_cache: false,
151 disable_prewarming: false,
152 disable_parallel_sparse_trie: false,
153 state_provider_metrics: false,
154 cross_block_cache_size: DEFAULT_CROSS_BLOCK_CACHE_SIZE,
155 has_enough_parallelism: has_enough_parallelism(),
156 multiproof_chunking_enabled: true,
157 multiproof_chunk_size: DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE,
158 reserved_cpu_cores: DEFAULT_RESERVED_CPU_CORES,
159 precompile_cache_disabled: false,
160 state_root_fallback: false,
161 always_process_payload_attributes_on_canonical_head: false,
162 prewarm_max_concurrency: DEFAULT_PREWARM_MAX_CONCURRENCY,
163 allow_unwind_canonical_header: false,
164 storage_worker_count: default_storage_worker_count(),
165 account_worker_count: default_account_worker_count(),
166 }
167 }
168}
169
170impl TreeConfig {
171 #[expect(clippy::too_many_arguments)]
173 pub const fn new(
174 persistence_threshold: u64,
175 memory_block_buffer_target: u64,
176 block_buffer_limit: u32,
177 max_invalid_header_cache_length: u32,
178 max_execute_block_batch_size: usize,
179 legacy_state_root: bool,
180 always_compare_trie_updates: bool,
181 disable_state_cache: bool,
182 disable_prewarming: bool,
183 disable_parallel_sparse_trie: bool,
184 state_provider_metrics: bool,
185 cross_block_cache_size: u64,
186 has_enough_parallelism: bool,
187 multiproof_chunking_enabled: bool,
188 multiproof_chunk_size: usize,
189 reserved_cpu_cores: usize,
190 precompile_cache_disabled: bool,
191 state_root_fallback: bool,
192 always_process_payload_attributes_on_canonical_head: bool,
193 prewarm_max_concurrency: usize,
194 allow_unwind_canonical_header: bool,
195 storage_worker_count: usize,
196 account_worker_count: usize,
197 ) -> Self {
198 Self {
199 persistence_threshold,
200 memory_block_buffer_target,
201 block_buffer_limit,
202 max_invalid_header_cache_length,
203 max_execute_block_batch_size,
204 legacy_state_root,
205 always_compare_trie_updates,
206 disable_state_cache,
207 disable_prewarming,
208 disable_parallel_sparse_trie,
209 state_provider_metrics,
210 cross_block_cache_size,
211 has_enough_parallelism,
212 multiproof_chunking_enabled,
213 multiproof_chunk_size,
214 reserved_cpu_cores,
215 precompile_cache_disabled,
216 state_root_fallback,
217 always_process_payload_attributes_on_canonical_head,
218 prewarm_max_concurrency,
219 allow_unwind_canonical_header,
220 storage_worker_count,
221 account_worker_count,
222 }
223 }
224
225 pub const fn persistence_threshold(&self) -> u64 {
227 self.persistence_threshold
228 }
229
230 pub const fn memory_block_buffer_target(&self) -> u64 {
232 self.memory_block_buffer_target
233 }
234
235 pub const fn block_buffer_limit(&self) -> u32 {
237 self.block_buffer_limit
238 }
239
240 pub const fn max_invalid_header_cache_length(&self) -> u32 {
242 self.max_invalid_header_cache_length
243 }
244
245 pub const fn max_execute_block_batch_size(&self) -> usize {
247 self.max_execute_block_batch_size
248 }
249
250 pub const fn multiproof_chunking_enabled(&self) -> bool {
252 self.multiproof_chunking_enabled
253 }
254
255 pub const fn multiproof_chunk_size(&self) -> usize {
257 self.multiproof_chunk_size
258 }
259
260 pub const fn reserved_cpu_cores(&self) -> usize {
262 self.reserved_cpu_cores
263 }
264
265 pub const fn legacy_state_root(&self) -> bool {
268 self.legacy_state_root
269 }
270
271 pub const fn state_provider_metrics(&self) -> bool {
273 self.state_provider_metrics
274 }
275
276 pub const fn disable_parallel_sparse_trie(&self) -> bool {
278 self.disable_parallel_sparse_trie
279 }
280
281 pub const fn disable_state_cache(&self) -> bool {
283 self.disable_state_cache
284 }
285
286 pub const fn disable_prewarming(&self) -> bool {
288 self.disable_prewarming
289 }
290
291 pub const fn always_compare_trie_updates(&self) -> bool {
294 self.always_compare_trie_updates
295 }
296
297 pub const fn cross_block_cache_size(&self) -> u64 {
299 self.cross_block_cache_size
300 }
301
302 pub const fn precompile_cache_disabled(&self) -> bool {
304 self.precompile_cache_disabled
305 }
306
307 pub const fn state_root_fallback(&self) -> bool {
309 self.state_root_fallback
310 }
311
312 pub const fn with_always_process_payload_attributes_on_canonical_head(
314 mut self,
315 always_process_payload_attributes_on_canonical_head: bool,
316 ) -> Self {
317 self.always_process_payload_attributes_on_canonical_head =
318 always_process_payload_attributes_on_canonical_head;
319 self
320 }
321
322 pub const fn always_process_payload_attributes_on_canonical_head(&self) -> bool {
325 self.always_process_payload_attributes_on_canonical_head
326 }
327
328 pub const fn unwind_canonical_header(&self) -> bool {
330 self.allow_unwind_canonical_header
331 }
332
333 pub const fn with_persistence_threshold(mut self, persistence_threshold: u64) -> Self {
335 self.persistence_threshold = persistence_threshold;
336 self
337 }
338
339 pub const fn with_memory_block_buffer_target(
341 mut self,
342 memory_block_buffer_target: u64,
343 ) -> Self {
344 self.memory_block_buffer_target = memory_block_buffer_target;
345 self
346 }
347
348 pub const fn with_block_buffer_limit(mut self, block_buffer_limit: u32) -> Self {
350 self.block_buffer_limit = block_buffer_limit;
351 self
352 }
353
354 pub const fn with_max_invalid_header_cache_length(
356 mut self,
357 max_invalid_header_cache_length: u32,
358 ) -> Self {
359 self.max_invalid_header_cache_length = max_invalid_header_cache_length;
360 self
361 }
362
363 pub const fn with_max_execute_block_batch_size(
365 mut self,
366 max_execute_block_batch_size: usize,
367 ) -> Self {
368 self.max_execute_block_batch_size = max_execute_block_batch_size;
369 self
370 }
371
372 pub const fn with_legacy_state_root(mut self, legacy_state_root: bool) -> Self {
374 self.legacy_state_root = legacy_state_root;
375 self
376 }
377
378 pub const fn without_state_cache(mut self, disable_state_cache: bool) -> Self {
380 self.disable_state_cache = disable_state_cache;
381 self
382 }
383
384 pub const fn without_prewarming(mut self, disable_prewarming: bool) -> Self {
386 self.disable_prewarming = disable_prewarming;
387 self
388 }
389
390 pub const fn with_always_compare_trie_updates(
393 mut self,
394 always_compare_trie_updates: bool,
395 ) -> Self {
396 self.always_compare_trie_updates = always_compare_trie_updates;
397 self
398 }
399
400 pub const fn with_cross_block_cache_size(mut self, cross_block_cache_size: u64) -> Self {
402 self.cross_block_cache_size = cross_block_cache_size;
403 self
404 }
405
406 pub const fn with_has_enough_parallelism(mut self, has_enough_parallelism: bool) -> Self {
408 self.has_enough_parallelism = has_enough_parallelism;
409 self
410 }
411
412 pub const fn has_enough_parallelism(&self) -> bool {
414 self.has_enough_parallelism
415 }
416
417 pub const fn with_state_provider_metrics(mut self, state_provider_metrics: bool) -> Self {
419 self.state_provider_metrics = state_provider_metrics;
420 self
421 }
422
423 pub const fn with_disable_parallel_sparse_trie(
425 mut self,
426 disable_parallel_sparse_trie: bool,
427 ) -> Self {
428 self.disable_parallel_sparse_trie = disable_parallel_sparse_trie;
429 self
430 }
431
432 pub const fn with_multiproof_chunking_enabled(
434 mut self,
435 multiproof_chunking_enabled: bool,
436 ) -> Self {
437 self.multiproof_chunking_enabled = multiproof_chunking_enabled;
438 self
439 }
440
441 pub const fn with_multiproof_chunk_size(mut self, multiproof_chunk_size: usize) -> Self {
443 self.multiproof_chunk_size = multiproof_chunk_size;
444 self
445 }
446
447 pub const fn with_reserved_cpu_cores(mut self, reserved_cpu_cores: usize) -> Self {
449 self.reserved_cpu_cores = reserved_cpu_cores;
450 self
451 }
452
453 pub const fn without_precompile_cache(mut self, precompile_cache_disabled: bool) -> Self {
455 self.precompile_cache_disabled = precompile_cache_disabled;
456 self
457 }
458
459 pub const fn with_state_root_fallback(mut self, state_root_fallback: bool) -> Self {
461 self.state_root_fallback = state_root_fallback;
462 self
463 }
464
465 pub const fn with_unwind_canonical_header(mut self, unwind_canonical_header: bool) -> Self {
467 self.allow_unwind_canonical_header = unwind_canonical_header;
468 self
469 }
470
471 pub const fn use_state_root_task(&self) -> bool {
473 self.has_enough_parallelism && !self.legacy_state_root
474 }
475
476 pub const fn with_prewarm_max_concurrency(mut self, prewarm_max_concurrency: usize) -> Self {
478 self.prewarm_max_concurrency = prewarm_max_concurrency;
479 self
480 }
481
482 pub const fn prewarm_max_concurrency(&self) -> usize {
484 self.prewarm_max_concurrency
485 }
486
487 pub const fn storage_worker_count(&self) -> usize {
489 self.storage_worker_count
490 }
491
492 pub fn with_storage_worker_count(mut self, storage_worker_count: usize) -> Self {
494 self.storage_worker_count = storage_worker_count.max(MIN_WORKER_COUNT);
495 self
496 }
497
498 pub const fn account_worker_count(&self) -> usize {
500 self.account_worker_count
501 }
502
503 pub fn with_account_worker_count(mut self, account_worker_count: usize) -> Self {
505 self.account_worker_count = account_worker_count.max(MIN_WORKER_COUNT);
506 self
507 }
508}