1pub const DEFAULT_PERSISTENCE_THRESHOLD: u64 = 2;
5
6pub const DEFAULT_MEMORY_BLOCK_BUFFER_TARGET: u64 = 0;
8
9pub const DEFAULT_MAX_PROOF_TASK_CONCURRENCY: u64 = 256;
11
12fn default_storage_worker_count() -> usize {
14 #[cfg(feature = "std")]
15 {
16 std::thread::available_parallelism().map(|n| (n.get() * 2).clamp(2, 64)).unwrap_or(8)
17 }
18 #[cfg(not(feature = "std"))]
19 {
20 8
21 }
22}
23
24pub const DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE: usize = 10;
26
27pub const DEFAULT_RESERVED_CPU_CORES: usize = 1;
31
32pub const DEFAULT_PREWARM_MAX_CONCURRENCY: usize = 16;
34
35const DEFAULT_BLOCK_BUFFER_LIMIT: u32 = 256;
36const DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH: u32 = 256;
37const DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE: usize = 4;
38const DEFAULT_CROSS_BLOCK_CACHE_SIZE: u64 = 4 * 1024 * 1024 * 1024;
39
40pub fn has_enough_parallelism() -> bool {
49 #[cfg(feature = "std")]
50 {
51 std::thread::available_parallelism().is_ok_and(|num| num.get() >= 5)
52 }
53 #[cfg(not(feature = "std"))]
54 false
55}
56
57#[derive(Debug, Clone)]
59pub struct TreeConfig {
60 persistence_threshold: u64,
63 memory_block_buffer_target: u64,
68 block_buffer_limit: u32,
71 max_invalid_header_cache_length: u32,
73 max_execute_block_batch_size: usize,
78 legacy_state_root: bool,
81 always_compare_trie_updates: bool,
84 disable_caching_and_prewarming: bool,
86 disable_parallel_sparse_trie: bool,
88 state_provider_metrics: bool,
90 cross_block_cache_size: u64,
92 has_enough_parallelism: bool,
94 max_proof_task_concurrency: u64,
96 multiproof_chunking_enabled: bool,
98 multiproof_chunk_size: usize,
100 reserved_cpu_cores: usize,
102 precompile_cache_disabled: bool,
104 state_root_fallback: bool,
106 always_process_payload_attributes_on_canonical_head: bool,
120 prewarm_max_concurrency: usize,
122 allow_unwind_canonical_header: bool,
124 storage_worker_count: usize,
126}
127
128impl Default for TreeConfig {
129 fn default() -> Self {
130 Self {
131 persistence_threshold: DEFAULT_PERSISTENCE_THRESHOLD,
132 memory_block_buffer_target: DEFAULT_MEMORY_BLOCK_BUFFER_TARGET,
133 block_buffer_limit: DEFAULT_BLOCK_BUFFER_LIMIT,
134 max_invalid_header_cache_length: DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH,
135 max_execute_block_batch_size: DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE,
136 legacy_state_root: false,
137 always_compare_trie_updates: false,
138 disable_caching_and_prewarming: false,
139 disable_parallel_sparse_trie: false,
140 state_provider_metrics: false,
141 cross_block_cache_size: DEFAULT_CROSS_BLOCK_CACHE_SIZE,
142 has_enough_parallelism: has_enough_parallelism(),
143 max_proof_task_concurrency: DEFAULT_MAX_PROOF_TASK_CONCURRENCY,
144 multiproof_chunking_enabled: true,
145 multiproof_chunk_size: DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE,
146 reserved_cpu_cores: DEFAULT_RESERVED_CPU_CORES,
147 precompile_cache_disabled: false,
148 state_root_fallback: false,
149 always_process_payload_attributes_on_canonical_head: false,
150 prewarm_max_concurrency: DEFAULT_PREWARM_MAX_CONCURRENCY,
151 allow_unwind_canonical_header: false,
152 storage_worker_count: default_storage_worker_count(),
153 }
154 }
155}
156
157impl TreeConfig {
158 #[expect(clippy::too_many_arguments)]
160 pub const fn new(
161 persistence_threshold: u64,
162 memory_block_buffer_target: u64,
163 block_buffer_limit: u32,
164 max_invalid_header_cache_length: u32,
165 max_execute_block_batch_size: usize,
166 legacy_state_root: bool,
167 always_compare_trie_updates: bool,
168 disable_caching_and_prewarming: bool,
169 disable_parallel_sparse_trie: bool,
170 state_provider_metrics: bool,
171 cross_block_cache_size: u64,
172 has_enough_parallelism: bool,
173 max_proof_task_concurrency: u64,
174 multiproof_chunking_enabled: bool,
175 multiproof_chunk_size: usize,
176 reserved_cpu_cores: usize,
177 precompile_cache_disabled: bool,
178 state_root_fallback: bool,
179 always_process_payload_attributes_on_canonical_head: bool,
180 prewarm_max_concurrency: usize,
181 allow_unwind_canonical_header: bool,
182 storage_worker_count: usize,
183 ) -> Self {
184 assert!(max_proof_task_concurrency > 0, "max_proof_task_concurrency must be at least 1");
185 Self {
186 persistence_threshold,
187 memory_block_buffer_target,
188 block_buffer_limit,
189 max_invalid_header_cache_length,
190 max_execute_block_batch_size,
191 legacy_state_root,
192 always_compare_trie_updates,
193 disable_caching_and_prewarming,
194 disable_parallel_sparse_trie,
195 state_provider_metrics,
196 cross_block_cache_size,
197 has_enough_parallelism,
198 max_proof_task_concurrency,
199 multiproof_chunking_enabled,
200 multiproof_chunk_size,
201 reserved_cpu_cores,
202 precompile_cache_disabled,
203 state_root_fallback,
204 always_process_payload_attributes_on_canonical_head,
205 prewarm_max_concurrency,
206 allow_unwind_canonical_header,
207 storage_worker_count,
208 }
209 }
210
211 pub const fn persistence_threshold(&self) -> u64 {
213 self.persistence_threshold
214 }
215
216 pub const fn memory_block_buffer_target(&self) -> u64 {
218 self.memory_block_buffer_target
219 }
220
221 pub const fn block_buffer_limit(&self) -> u32 {
223 self.block_buffer_limit
224 }
225
226 pub const fn max_invalid_header_cache_length(&self) -> u32 {
228 self.max_invalid_header_cache_length
229 }
230
231 pub const fn max_execute_block_batch_size(&self) -> usize {
233 self.max_execute_block_batch_size
234 }
235
236 pub const fn max_proof_task_concurrency(&self) -> u64 {
238 self.max_proof_task_concurrency
239 }
240
241 pub const fn multiproof_chunking_enabled(&self) -> bool {
243 self.multiproof_chunking_enabled
244 }
245
246 pub const fn multiproof_chunk_size(&self) -> usize {
248 self.multiproof_chunk_size
249 }
250
251 pub const fn reserved_cpu_cores(&self) -> usize {
253 self.reserved_cpu_cores
254 }
255
256 pub const fn legacy_state_root(&self) -> bool {
259 self.legacy_state_root
260 }
261
262 pub const fn state_provider_metrics(&self) -> bool {
264 self.state_provider_metrics
265 }
266
267 pub const fn disable_parallel_sparse_trie(&self) -> bool {
269 self.disable_parallel_sparse_trie
270 }
271
272 pub const fn disable_caching_and_prewarming(&self) -> bool {
274 self.disable_caching_and_prewarming
275 }
276
277 pub const fn always_compare_trie_updates(&self) -> bool {
280 self.always_compare_trie_updates
281 }
282
283 pub const fn cross_block_cache_size(&self) -> u64 {
285 self.cross_block_cache_size
286 }
287
288 pub const fn precompile_cache_disabled(&self) -> bool {
290 self.precompile_cache_disabled
291 }
292
293 pub const fn state_root_fallback(&self) -> bool {
295 self.state_root_fallback
296 }
297
298 pub const fn with_always_process_payload_attributes_on_canonical_head(
300 mut self,
301 always_process_payload_attributes_on_canonical_head: bool,
302 ) -> Self {
303 self.always_process_payload_attributes_on_canonical_head =
304 always_process_payload_attributes_on_canonical_head;
305 self
306 }
307
308 pub const fn always_process_payload_attributes_on_canonical_head(&self) -> bool {
311 self.always_process_payload_attributes_on_canonical_head
312 }
313
314 pub const fn unwind_canonical_header(&self) -> bool {
316 self.allow_unwind_canonical_header
317 }
318
319 pub const fn with_persistence_threshold(mut self, persistence_threshold: u64) -> Self {
321 self.persistence_threshold = persistence_threshold;
322 self
323 }
324
325 pub const fn with_memory_block_buffer_target(
327 mut self,
328 memory_block_buffer_target: u64,
329 ) -> Self {
330 self.memory_block_buffer_target = memory_block_buffer_target;
331 self
332 }
333
334 pub const fn with_block_buffer_limit(mut self, block_buffer_limit: u32) -> Self {
336 self.block_buffer_limit = block_buffer_limit;
337 self
338 }
339
340 pub const fn with_max_invalid_header_cache_length(
342 mut self,
343 max_invalid_header_cache_length: u32,
344 ) -> Self {
345 self.max_invalid_header_cache_length = max_invalid_header_cache_length;
346 self
347 }
348
349 pub const fn with_max_execute_block_batch_size(
351 mut self,
352 max_execute_block_batch_size: usize,
353 ) -> Self {
354 self.max_execute_block_batch_size = max_execute_block_batch_size;
355 self
356 }
357
358 pub const fn with_legacy_state_root(mut self, legacy_state_root: bool) -> Self {
360 self.legacy_state_root = legacy_state_root;
361 self
362 }
363
364 pub const fn without_caching_and_prewarming(
366 mut self,
367 disable_caching_and_prewarming: bool,
368 ) -> Self {
369 self.disable_caching_and_prewarming = disable_caching_and_prewarming;
370 self
371 }
372
373 pub const fn with_always_compare_trie_updates(
376 mut self,
377 always_compare_trie_updates: bool,
378 ) -> Self {
379 self.always_compare_trie_updates = always_compare_trie_updates;
380 self
381 }
382
383 pub const fn with_cross_block_cache_size(mut self, cross_block_cache_size: u64) -> Self {
385 self.cross_block_cache_size = cross_block_cache_size;
386 self
387 }
388
389 pub const fn with_has_enough_parallelism(mut self, has_enough_parallelism: bool) -> Self {
391 self.has_enough_parallelism = has_enough_parallelism;
392 self
393 }
394
395 pub const fn with_state_provider_metrics(mut self, state_provider_metrics: bool) -> Self {
397 self.state_provider_metrics = state_provider_metrics;
398 self
399 }
400
401 pub const fn with_disable_parallel_sparse_trie(
403 mut self,
404 disable_parallel_sparse_trie: bool,
405 ) -> Self {
406 self.disable_parallel_sparse_trie = disable_parallel_sparse_trie;
407 self
408 }
409
410 pub const fn with_max_proof_task_concurrency(
412 mut self,
413 max_proof_task_concurrency: u64,
414 ) -> Self {
415 assert!(max_proof_task_concurrency > 0, "max_proof_task_concurrency must be at least 1");
416 self.max_proof_task_concurrency = max_proof_task_concurrency;
417 self
418 }
419
420 pub const fn with_multiproof_chunking_enabled(
422 mut self,
423 multiproof_chunking_enabled: bool,
424 ) -> Self {
425 self.multiproof_chunking_enabled = multiproof_chunking_enabled;
426 self
427 }
428
429 pub const fn with_multiproof_chunk_size(mut self, multiproof_chunk_size: usize) -> Self {
431 self.multiproof_chunk_size = multiproof_chunk_size;
432 self
433 }
434
435 pub const fn with_reserved_cpu_cores(mut self, reserved_cpu_cores: usize) -> Self {
437 self.reserved_cpu_cores = reserved_cpu_cores;
438 self
439 }
440
441 pub const fn without_precompile_cache(mut self, precompile_cache_disabled: bool) -> Self {
443 self.precompile_cache_disabled = precompile_cache_disabled;
444 self
445 }
446
447 pub const fn with_state_root_fallback(mut self, state_root_fallback: bool) -> Self {
449 self.state_root_fallback = state_root_fallback;
450 self
451 }
452
453 pub const fn with_unwind_canonical_header(mut self, unwind_canonical_header: bool) -> Self {
455 self.allow_unwind_canonical_header = unwind_canonical_header;
456 self
457 }
458
459 pub const fn use_state_root_task(&self) -> bool {
461 self.has_enough_parallelism && !self.legacy_state_root
462 }
463
464 pub const fn with_prewarm_max_concurrency(mut self, prewarm_max_concurrency: usize) -> Self {
466 self.prewarm_max_concurrency = prewarm_max_concurrency;
467 self
468 }
469
470 pub const fn prewarm_max_concurrency(&self) -> usize {
472 self.prewarm_max_concurrency
473 }
474
475 pub const fn storage_worker_count(&self) -> usize {
477 self.storage_worker_count
478 }
479
480 pub const fn with_storage_worker_count(mut self, storage_worker_count: usize) -> Self {
482 self.storage_worker_count = storage_worker_count;
483 self
484 }
485}