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_MULTIPROOF_TASK_CHUNK_SIZE_V2: usize = DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE * 4;
41
42pub const DEFAULT_RESERVED_CPU_CORES: usize = 1;
46
47pub const DEFAULT_PREWARM_MAX_CONCURRENCY: usize = 16;
49
50const DEFAULT_BLOCK_BUFFER_LIMIT: u32 = EPOCH_SLOTS as u32 * 2;
51const DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH: u32 = 256;
52const DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE: usize = 4;
53const DEFAULT_CROSS_BLOCK_CACHE_SIZE: usize = default_cross_block_cache_size();
54
55const fn default_cross_block_cache_size() -> usize {
56 if cfg!(test) {
57 1024 * 1024 } else if cfg!(target_pointer_width = "32") {
59 usize::MAX } else {
61 4 * 1024 * 1024 * 1024 }
63}
64
65pub fn has_enough_parallelism() -> bool {
74 #[cfg(feature = "std")]
75 {
76 std::thread::available_parallelism().is_ok_and(|num| num.get() >= 5)
77 }
78 #[cfg(not(feature = "std"))]
79 false
80}
81
82#[derive(Debug, Clone)]
84pub struct TreeConfig {
85 persistence_threshold: u64,
88 memory_block_buffer_target: u64,
93 block_buffer_limit: u32,
96 max_invalid_header_cache_length: u32,
98 max_execute_block_batch_size: usize,
103 legacy_state_root: bool,
106 always_compare_trie_updates: bool,
109 disable_state_cache: bool,
111 disable_prewarming: bool,
113 disable_parallel_sparse_trie: bool,
115 state_provider_metrics: bool,
117 cross_block_cache_size: usize,
119 has_enough_parallelism: bool,
121 multiproof_chunking_enabled: bool,
123 multiproof_chunk_size: usize,
125 reserved_cpu_cores: usize,
127 precompile_cache_disabled: bool,
129 state_root_fallback: bool,
131 always_process_payload_attributes_on_canonical_head: bool,
145 prewarm_max_concurrency: usize,
147 allow_unwind_canonical_header: bool,
149 storage_worker_count: usize,
151 account_worker_count: usize,
153 enable_proof_v2: bool,
155 disable_cache_metrics: bool,
157}
158
159impl Default for TreeConfig {
160 fn default() -> Self {
161 Self {
162 persistence_threshold: DEFAULT_PERSISTENCE_THRESHOLD,
163 memory_block_buffer_target: DEFAULT_MEMORY_BLOCK_BUFFER_TARGET,
164 block_buffer_limit: DEFAULT_BLOCK_BUFFER_LIMIT,
165 max_invalid_header_cache_length: DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH,
166 max_execute_block_batch_size: DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE,
167 legacy_state_root: false,
168 always_compare_trie_updates: false,
169 disable_state_cache: false,
170 disable_prewarming: false,
171 disable_parallel_sparse_trie: false,
172 state_provider_metrics: false,
173 cross_block_cache_size: DEFAULT_CROSS_BLOCK_CACHE_SIZE,
174 has_enough_parallelism: has_enough_parallelism(),
175 multiproof_chunking_enabled: true,
176 multiproof_chunk_size: DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE,
177 reserved_cpu_cores: DEFAULT_RESERVED_CPU_CORES,
178 precompile_cache_disabled: false,
179 state_root_fallback: false,
180 always_process_payload_attributes_on_canonical_head: false,
181 prewarm_max_concurrency: DEFAULT_PREWARM_MAX_CONCURRENCY,
182 allow_unwind_canonical_header: false,
183 storage_worker_count: default_storage_worker_count(),
184 account_worker_count: default_account_worker_count(),
185 enable_proof_v2: false,
186 disable_cache_metrics: false,
187 }
188 }
189}
190
191impl TreeConfig {
192 #[expect(clippy::too_many_arguments)]
194 pub const fn new(
195 persistence_threshold: u64,
196 memory_block_buffer_target: u64,
197 block_buffer_limit: u32,
198 max_invalid_header_cache_length: u32,
199 max_execute_block_batch_size: usize,
200 legacy_state_root: bool,
201 always_compare_trie_updates: bool,
202 disable_state_cache: bool,
203 disable_prewarming: bool,
204 disable_parallel_sparse_trie: bool,
205 state_provider_metrics: bool,
206 cross_block_cache_size: usize,
207 has_enough_parallelism: bool,
208 multiproof_chunking_enabled: bool,
209 multiproof_chunk_size: usize,
210 reserved_cpu_cores: usize,
211 precompile_cache_disabled: bool,
212 state_root_fallback: bool,
213 always_process_payload_attributes_on_canonical_head: bool,
214 prewarm_max_concurrency: usize,
215 allow_unwind_canonical_header: bool,
216 storage_worker_count: usize,
217 account_worker_count: usize,
218 enable_proof_v2: bool,
219 disable_cache_metrics: bool,
220 ) -> Self {
221 Self {
222 persistence_threshold,
223 memory_block_buffer_target,
224 block_buffer_limit,
225 max_invalid_header_cache_length,
226 max_execute_block_batch_size,
227 legacy_state_root,
228 always_compare_trie_updates,
229 disable_state_cache,
230 disable_prewarming,
231 disable_parallel_sparse_trie,
232 state_provider_metrics,
233 cross_block_cache_size,
234 has_enough_parallelism,
235 multiproof_chunking_enabled,
236 multiproof_chunk_size,
237 reserved_cpu_cores,
238 precompile_cache_disabled,
239 state_root_fallback,
240 always_process_payload_attributes_on_canonical_head,
241 prewarm_max_concurrency,
242 allow_unwind_canonical_header,
243 storage_worker_count,
244 account_worker_count,
245 enable_proof_v2,
246 disable_cache_metrics,
247 }
248 }
249
250 pub const fn persistence_threshold(&self) -> u64 {
252 self.persistence_threshold
253 }
254
255 pub const fn memory_block_buffer_target(&self) -> u64 {
257 self.memory_block_buffer_target
258 }
259
260 pub const fn block_buffer_limit(&self) -> u32 {
262 self.block_buffer_limit
263 }
264
265 pub const fn max_invalid_header_cache_length(&self) -> u32 {
267 self.max_invalid_header_cache_length
268 }
269
270 pub const fn max_execute_block_batch_size(&self) -> usize {
272 self.max_execute_block_batch_size
273 }
274
275 pub const fn multiproof_chunking_enabled(&self) -> bool {
277 self.multiproof_chunking_enabled
278 }
279
280 pub const fn multiproof_chunk_size(&self) -> usize {
282 self.multiproof_chunk_size
283 }
284
285 pub const fn effective_multiproof_chunk_size(&self) -> usize {
288 if self.enable_proof_v2 && self.multiproof_chunk_size == DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE
289 {
290 DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE_V2
291 } else {
292 self.multiproof_chunk_size
293 }
294 }
295
296 pub const fn reserved_cpu_cores(&self) -> usize {
298 self.reserved_cpu_cores
299 }
300
301 pub const fn legacy_state_root(&self) -> bool {
304 self.legacy_state_root
305 }
306
307 pub const fn state_provider_metrics(&self) -> bool {
309 self.state_provider_metrics
310 }
311
312 pub const fn disable_parallel_sparse_trie(&self) -> bool {
314 self.disable_parallel_sparse_trie
315 }
316
317 pub const fn disable_state_cache(&self) -> bool {
319 self.disable_state_cache
320 }
321
322 pub const fn disable_prewarming(&self) -> bool {
324 self.disable_prewarming
325 }
326
327 pub const fn always_compare_trie_updates(&self) -> bool {
330 self.always_compare_trie_updates
331 }
332
333 pub const fn cross_block_cache_size(&self) -> usize {
335 self.cross_block_cache_size
336 }
337
338 pub const fn precompile_cache_disabled(&self) -> bool {
340 self.precompile_cache_disabled
341 }
342
343 pub const fn state_root_fallback(&self) -> bool {
345 self.state_root_fallback
346 }
347
348 pub const fn with_always_process_payload_attributes_on_canonical_head(
350 mut self,
351 always_process_payload_attributes_on_canonical_head: bool,
352 ) -> Self {
353 self.always_process_payload_attributes_on_canonical_head =
354 always_process_payload_attributes_on_canonical_head;
355 self
356 }
357
358 pub const fn always_process_payload_attributes_on_canonical_head(&self) -> bool {
361 self.always_process_payload_attributes_on_canonical_head
362 }
363
364 pub const fn unwind_canonical_header(&self) -> bool {
366 self.allow_unwind_canonical_header
367 }
368
369 pub const fn with_persistence_threshold(mut self, persistence_threshold: u64) -> Self {
371 self.persistence_threshold = persistence_threshold;
372 self
373 }
374
375 pub const fn with_memory_block_buffer_target(
377 mut self,
378 memory_block_buffer_target: u64,
379 ) -> Self {
380 self.memory_block_buffer_target = memory_block_buffer_target;
381 self
382 }
383
384 pub const fn with_block_buffer_limit(mut self, block_buffer_limit: u32) -> Self {
386 self.block_buffer_limit = block_buffer_limit;
387 self
388 }
389
390 pub const fn with_max_invalid_header_cache_length(
392 mut self,
393 max_invalid_header_cache_length: u32,
394 ) -> Self {
395 self.max_invalid_header_cache_length = max_invalid_header_cache_length;
396 self
397 }
398
399 pub const fn with_max_execute_block_batch_size(
401 mut self,
402 max_execute_block_batch_size: usize,
403 ) -> Self {
404 self.max_execute_block_batch_size = max_execute_block_batch_size;
405 self
406 }
407
408 pub const fn with_legacy_state_root(mut self, legacy_state_root: bool) -> Self {
410 self.legacy_state_root = legacy_state_root;
411 self
412 }
413
414 pub const fn without_state_cache(mut self, disable_state_cache: bool) -> Self {
416 self.disable_state_cache = disable_state_cache;
417 self
418 }
419
420 pub const fn without_prewarming(mut self, disable_prewarming: bool) -> Self {
422 self.disable_prewarming = disable_prewarming;
423 self
424 }
425
426 pub const fn with_always_compare_trie_updates(
429 mut self,
430 always_compare_trie_updates: bool,
431 ) -> Self {
432 self.always_compare_trie_updates = always_compare_trie_updates;
433 self
434 }
435
436 pub const fn with_cross_block_cache_size(mut self, cross_block_cache_size: usize) -> Self {
438 self.cross_block_cache_size = cross_block_cache_size;
439 self
440 }
441
442 pub const fn with_has_enough_parallelism(mut self, has_enough_parallelism: bool) -> Self {
444 self.has_enough_parallelism = has_enough_parallelism;
445 self
446 }
447
448 pub const fn with_state_provider_metrics(mut self, state_provider_metrics: bool) -> Self {
450 self.state_provider_metrics = state_provider_metrics;
451 self
452 }
453
454 pub const fn with_disable_parallel_sparse_trie(
456 mut self,
457 disable_parallel_sparse_trie: bool,
458 ) -> Self {
459 self.disable_parallel_sparse_trie = disable_parallel_sparse_trie;
460 self
461 }
462
463 pub const fn with_multiproof_chunking_enabled(
465 mut self,
466 multiproof_chunking_enabled: bool,
467 ) -> Self {
468 self.multiproof_chunking_enabled = multiproof_chunking_enabled;
469 self
470 }
471
472 pub const fn with_multiproof_chunk_size(mut self, multiproof_chunk_size: usize) -> Self {
474 self.multiproof_chunk_size = multiproof_chunk_size;
475 self
476 }
477
478 pub const fn with_reserved_cpu_cores(mut self, reserved_cpu_cores: usize) -> Self {
480 self.reserved_cpu_cores = reserved_cpu_cores;
481 self
482 }
483
484 pub const fn without_precompile_cache(mut self, precompile_cache_disabled: bool) -> Self {
486 self.precompile_cache_disabled = precompile_cache_disabled;
487 self
488 }
489
490 pub const fn with_state_root_fallback(mut self, state_root_fallback: bool) -> Self {
492 self.state_root_fallback = state_root_fallback;
493 self
494 }
495
496 pub const fn with_unwind_canonical_header(mut self, unwind_canonical_header: bool) -> Self {
498 self.allow_unwind_canonical_header = unwind_canonical_header;
499 self
500 }
501
502 pub const fn use_state_root_task(&self) -> bool {
504 self.has_enough_parallelism && !self.legacy_state_root
505 }
506
507 pub const fn with_prewarm_max_concurrency(mut self, prewarm_max_concurrency: usize) -> Self {
509 self.prewarm_max_concurrency = prewarm_max_concurrency;
510 self
511 }
512
513 pub const fn prewarm_max_concurrency(&self) -> usize {
515 self.prewarm_max_concurrency
516 }
517
518 pub const fn storage_worker_count(&self) -> usize {
520 self.storage_worker_count
521 }
522
523 pub fn with_storage_worker_count(mut self, storage_worker_count: usize) -> Self {
525 self.storage_worker_count = storage_worker_count.max(MIN_WORKER_COUNT);
526 self
527 }
528
529 pub const fn account_worker_count(&self) -> usize {
531 self.account_worker_count
532 }
533
534 pub fn with_account_worker_count(mut self, account_worker_count: usize) -> Self {
536 self.account_worker_count = account_worker_count.max(MIN_WORKER_COUNT);
537 self
538 }
539
540 pub const fn enable_proof_v2(&self) -> bool {
542 self.enable_proof_v2
543 }
544
545 pub const fn with_enable_proof_v2(mut self, enable_proof_v2: bool) -> Self {
547 self.enable_proof_v2 = enable_proof_v2;
548 self
549 }
550
551 pub const fn disable_cache_metrics(&self) -> bool {
553 self.disable_cache_metrics
554 }
555
556 pub const fn without_cache_metrics(mut self, disable_cache_metrics: bool) -> Self {
558 self.disable_cache_metrics = disable_cache_metrics;
559 self
560 }
561}