1pub const DEFAULT_PERSISTENCE_THRESHOLD: u64 = 2;
5
6pub const DEFAULT_MEMORY_BLOCK_BUFFER_TARGET: u64 = 0;
8
9pub const MIN_WORKER_COUNT: usize = 32;
11
12fn default_storage_worker_count() -> usize {
14 #[cfg(feature = "std")]
15 {
16 std::thread::available_parallelism().map_or(8, |n| n.get() * 2).min(MIN_WORKER_COUNT)
17 }
18 #[cfg(not(feature = "std"))]
19 {
20 8
21 }
22}
23
24fn default_account_worker_count() -> usize {
29 default_storage_worker_count()
30}
31
32pub const DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE: usize = 10;
34
35pub const DEFAULT_RESERVED_CPU_CORES: usize = 1;
39
40pub const DEFAULT_PREWARM_MAX_CONCURRENCY: usize = 16;
42
43const DEFAULT_BLOCK_BUFFER_LIMIT: u32 = 256;
44const DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH: u32 = 256;
45const DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE: usize = 4;
46const DEFAULT_CROSS_BLOCK_CACHE_SIZE: u64 = 4 * 1024 * 1024 * 1024;
47
48pub fn has_enough_parallelism() -> bool {
57 #[cfg(feature = "std")]
58 {
59 std::thread::available_parallelism().is_ok_and(|num| num.get() >= 5)
60 }
61 #[cfg(not(feature = "std"))]
62 false
63}
64
65#[derive(Debug, Clone)]
67pub struct TreeConfig {
68 persistence_threshold: u64,
71 memory_block_buffer_target: u64,
76 block_buffer_limit: u32,
79 max_invalid_header_cache_length: u32,
81 max_execute_block_batch_size: usize,
86 legacy_state_root: bool,
89 always_compare_trie_updates: bool,
92 disable_prewarming: bool,
94 disable_parallel_sparse_trie: bool,
96 state_provider_metrics: bool,
98 cross_block_cache_size: u64,
100 has_enough_parallelism: bool,
102 multiproof_chunking_enabled: bool,
104 multiproof_chunk_size: usize,
106 reserved_cpu_cores: usize,
108 precompile_cache_disabled: bool,
110 state_root_fallback: bool,
112 always_process_payload_attributes_on_canonical_head: bool,
126 prewarm_max_concurrency: usize,
128 allow_unwind_canonical_header: bool,
130 storage_worker_count: usize,
132 account_worker_count: usize,
134}
135
136impl Default for TreeConfig {
137 fn default() -> Self {
138 Self {
139 persistence_threshold: DEFAULT_PERSISTENCE_THRESHOLD,
140 memory_block_buffer_target: DEFAULT_MEMORY_BLOCK_BUFFER_TARGET,
141 block_buffer_limit: DEFAULT_BLOCK_BUFFER_LIMIT,
142 max_invalid_header_cache_length: DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH,
143 max_execute_block_batch_size: DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE,
144 legacy_state_root: false,
145 always_compare_trie_updates: false,
146 disable_prewarming: false,
147 disable_parallel_sparse_trie: false,
148 state_provider_metrics: false,
149 cross_block_cache_size: DEFAULT_CROSS_BLOCK_CACHE_SIZE,
150 has_enough_parallelism: has_enough_parallelism(),
151 multiproof_chunking_enabled: true,
152 multiproof_chunk_size: DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE,
153 reserved_cpu_cores: DEFAULT_RESERVED_CPU_CORES,
154 precompile_cache_disabled: false,
155 state_root_fallback: false,
156 always_process_payload_attributes_on_canonical_head: false,
157 prewarm_max_concurrency: DEFAULT_PREWARM_MAX_CONCURRENCY,
158 allow_unwind_canonical_header: false,
159 storage_worker_count: default_storage_worker_count(),
160 account_worker_count: default_account_worker_count(),
161 }
162 }
163}
164
165impl TreeConfig {
166 #[expect(clippy::too_many_arguments)]
168 pub const fn new(
169 persistence_threshold: u64,
170 memory_block_buffer_target: u64,
171 block_buffer_limit: u32,
172 max_invalid_header_cache_length: u32,
173 max_execute_block_batch_size: usize,
174 legacy_state_root: bool,
175 always_compare_trie_updates: bool,
176 disable_prewarming: bool,
177 disable_parallel_sparse_trie: bool,
178 state_provider_metrics: bool,
179 cross_block_cache_size: u64,
180 has_enough_parallelism: bool,
181 multiproof_chunking_enabled: bool,
182 multiproof_chunk_size: usize,
183 reserved_cpu_cores: usize,
184 precompile_cache_disabled: bool,
185 state_root_fallback: bool,
186 always_process_payload_attributes_on_canonical_head: bool,
187 prewarm_max_concurrency: usize,
188 allow_unwind_canonical_header: bool,
189 storage_worker_count: usize,
190 account_worker_count: usize,
191 ) -> Self {
192 Self {
193 persistence_threshold,
194 memory_block_buffer_target,
195 block_buffer_limit,
196 max_invalid_header_cache_length,
197 max_execute_block_batch_size,
198 legacy_state_root,
199 always_compare_trie_updates,
200 disable_prewarming,
201 disable_parallel_sparse_trie,
202 state_provider_metrics,
203 cross_block_cache_size,
204 has_enough_parallelism,
205 multiproof_chunking_enabled,
206 multiproof_chunk_size,
207 reserved_cpu_cores,
208 precompile_cache_disabled,
209 state_root_fallback,
210 always_process_payload_attributes_on_canonical_head,
211 prewarm_max_concurrency,
212 allow_unwind_canonical_header,
213 storage_worker_count,
214 account_worker_count,
215 }
216 }
217
218 pub const fn persistence_threshold(&self) -> u64 {
220 self.persistence_threshold
221 }
222
223 pub const fn memory_block_buffer_target(&self) -> u64 {
225 self.memory_block_buffer_target
226 }
227
228 pub const fn block_buffer_limit(&self) -> u32 {
230 self.block_buffer_limit
231 }
232
233 pub const fn max_invalid_header_cache_length(&self) -> u32 {
235 self.max_invalid_header_cache_length
236 }
237
238 pub const fn max_execute_block_batch_size(&self) -> usize {
240 self.max_execute_block_batch_size
241 }
242
243 pub const fn multiproof_chunking_enabled(&self) -> bool {
245 self.multiproof_chunking_enabled
246 }
247
248 pub const fn multiproof_chunk_size(&self) -> usize {
250 self.multiproof_chunk_size
251 }
252
253 pub const fn reserved_cpu_cores(&self) -> usize {
255 self.reserved_cpu_cores
256 }
257
258 pub const fn legacy_state_root(&self) -> bool {
261 self.legacy_state_root
262 }
263
264 pub const fn state_provider_metrics(&self) -> bool {
266 self.state_provider_metrics
267 }
268
269 pub const fn disable_parallel_sparse_trie(&self) -> bool {
271 self.disable_parallel_sparse_trie
272 }
273
274 pub const fn disable_prewarming(&self) -> bool {
276 self.disable_prewarming
277 }
278
279 pub const fn always_compare_trie_updates(&self) -> bool {
282 self.always_compare_trie_updates
283 }
284
285 pub const fn cross_block_cache_size(&self) -> u64 {
287 self.cross_block_cache_size
288 }
289
290 pub const fn precompile_cache_disabled(&self) -> bool {
292 self.precompile_cache_disabled
293 }
294
295 pub const fn state_root_fallback(&self) -> bool {
297 self.state_root_fallback
298 }
299
300 pub const fn with_always_process_payload_attributes_on_canonical_head(
302 mut self,
303 always_process_payload_attributes_on_canonical_head: bool,
304 ) -> Self {
305 self.always_process_payload_attributes_on_canonical_head =
306 always_process_payload_attributes_on_canonical_head;
307 self
308 }
309
310 pub const fn always_process_payload_attributes_on_canonical_head(&self) -> bool {
313 self.always_process_payload_attributes_on_canonical_head
314 }
315
316 pub const fn unwind_canonical_header(&self) -> bool {
318 self.allow_unwind_canonical_header
319 }
320
321 pub const fn with_persistence_threshold(mut self, persistence_threshold: u64) -> Self {
323 self.persistence_threshold = persistence_threshold;
324 self
325 }
326
327 pub const fn with_memory_block_buffer_target(
329 mut self,
330 memory_block_buffer_target: u64,
331 ) -> Self {
332 self.memory_block_buffer_target = memory_block_buffer_target;
333 self
334 }
335
336 pub const fn with_block_buffer_limit(mut self, block_buffer_limit: u32) -> Self {
338 self.block_buffer_limit = block_buffer_limit;
339 self
340 }
341
342 pub const fn with_max_invalid_header_cache_length(
344 mut self,
345 max_invalid_header_cache_length: u32,
346 ) -> Self {
347 self.max_invalid_header_cache_length = max_invalid_header_cache_length;
348 self
349 }
350
351 pub const fn with_max_execute_block_batch_size(
353 mut self,
354 max_execute_block_batch_size: usize,
355 ) -> Self {
356 self.max_execute_block_batch_size = max_execute_block_batch_size;
357 self
358 }
359
360 pub const fn with_legacy_state_root(mut self, legacy_state_root: bool) -> Self {
362 self.legacy_state_root = legacy_state_root;
363 self
364 }
365
366 pub const fn without_prewarming(mut self, disable_prewarming: bool) -> Self {
368 self.disable_prewarming = disable_prewarming;
369 self
370 }
371
372 pub const fn with_always_compare_trie_updates(
375 mut self,
376 always_compare_trie_updates: bool,
377 ) -> Self {
378 self.always_compare_trie_updates = always_compare_trie_updates;
379 self
380 }
381
382 pub const fn with_cross_block_cache_size(mut self, cross_block_cache_size: u64) -> Self {
384 self.cross_block_cache_size = cross_block_cache_size;
385 self
386 }
387
388 pub const fn with_has_enough_parallelism(mut self, has_enough_parallelism: bool) -> Self {
390 self.has_enough_parallelism = has_enough_parallelism;
391 self
392 }
393
394 pub const fn with_state_provider_metrics(mut self, state_provider_metrics: bool) -> Self {
396 self.state_provider_metrics = state_provider_metrics;
397 self
398 }
399
400 pub const fn with_disable_parallel_sparse_trie(
402 mut self,
403 disable_parallel_sparse_trie: bool,
404 ) -> Self {
405 self.disable_parallel_sparse_trie = disable_parallel_sparse_trie;
406 self
407 }
408
409 pub const fn with_multiproof_chunking_enabled(
411 mut self,
412 multiproof_chunking_enabled: bool,
413 ) -> Self {
414 self.multiproof_chunking_enabled = multiproof_chunking_enabled;
415 self
416 }
417
418 pub const fn with_multiproof_chunk_size(mut self, multiproof_chunk_size: usize) -> Self {
420 self.multiproof_chunk_size = multiproof_chunk_size;
421 self
422 }
423
424 pub const fn with_reserved_cpu_cores(mut self, reserved_cpu_cores: usize) -> Self {
426 self.reserved_cpu_cores = reserved_cpu_cores;
427 self
428 }
429
430 pub const fn without_precompile_cache(mut self, precompile_cache_disabled: bool) -> Self {
432 self.precompile_cache_disabled = precompile_cache_disabled;
433 self
434 }
435
436 pub const fn with_state_root_fallback(mut self, state_root_fallback: bool) -> Self {
438 self.state_root_fallback = state_root_fallback;
439 self
440 }
441
442 pub const fn with_unwind_canonical_header(mut self, unwind_canonical_header: bool) -> Self {
444 self.allow_unwind_canonical_header = unwind_canonical_header;
445 self
446 }
447
448 pub const fn use_state_root_task(&self) -> bool {
450 self.has_enough_parallelism && !self.legacy_state_root
451 }
452
453 pub const fn with_prewarm_max_concurrency(mut self, prewarm_max_concurrency: usize) -> Self {
455 self.prewarm_max_concurrency = prewarm_max_concurrency;
456 self
457 }
458
459 pub const fn prewarm_max_concurrency(&self) -> usize {
461 self.prewarm_max_concurrency
462 }
463
464 pub const fn storage_worker_count(&self) -> usize {
466 self.storage_worker_count
467 }
468
469 pub fn with_storage_worker_count(mut self, storage_worker_count: usize) -> Self {
471 self.storage_worker_count = storage_worker_count.max(MIN_WORKER_COUNT);
472 self
473 }
474
475 pub const fn account_worker_count(&self) -> usize {
477 self.account_worker_count
478 }
479
480 pub fn with_account_worker_count(mut self, account_worker_count: usize) -> Self {
482 self.account_worker_count = account_worker_count.max(MIN_WORKER_COUNT);
483 self
484 }
485}