1use clap::{builder::Resettable, Args};
4use eyre::ensure;
5use reth_cli_util::{parse_duration_from_secs_or_ms, parsers::format_duration_as_secs_or_ms};
6use reth_engine_primitives::{
7 TreeConfig, DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE, DEFAULT_PERSISTENCE_BACKPRESSURE_THRESHOLD,
8 DEFAULT_SPARSE_TRIE_MAX_HOT_ACCOUNTS, DEFAULT_SPARSE_TRIE_MAX_HOT_SLOTS,
9};
10use std::{sync::OnceLock, time::Duration};
11
12use crate::node_config::{
13 DEFAULT_CROSS_BLOCK_CACHE_SIZE_MB, DEFAULT_MEMORY_BLOCK_BUFFER_TARGET,
14 DEFAULT_PERSISTENCE_THRESHOLD, DEFAULT_RESERVED_CPU_CORES,
15};
16
17static ENGINE_DEFAULTS: OnceLock<DefaultEngineValues> = OnceLock::new();
19
20#[derive(Debug, Clone)]
24pub struct DefaultEngineValues {
25 persistence_threshold: u64,
26 persistence_backpressure_threshold: u64,
27 memory_block_buffer_target: u64,
28 legacy_state_root_task_enabled: bool,
29 state_cache_disabled: bool,
30 prewarming_disabled: bool,
31 state_provider_metrics: bool,
32 cross_block_cache_size: usize,
33 state_root_task_compare_updates: bool,
34 accept_execution_requests_hash: bool,
35 multiproof_chunk_size: usize,
36 reserved_cpu_cores: usize,
37 precompile_cache_disabled: bool,
38 state_root_fallback: bool,
39 always_process_payload_attributes_on_canonical_head: bool,
40 allow_unwind_canonical_header: bool,
41 storage_worker_count: Option<usize>,
42 account_worker_count: Option<usize>,
43 prewarming_threads: Option<usize>,
44 cache_metrics_disabled: bool,
45 sparse_trie_max_hot_slots: usize,
46 sparse_trie_max_hot_accounts: usize,
47 slow_block_threshold: Option<Duration>,
48 disable_sparse_trie_cache_pruning: bool,
49 state_root_task_timeout: Option<String>,
50 share_execution_cache_with_payload_builder: bool,
51 share_sparse_trie_with_payload_builder: bool,
52}
53
54impl DefaultEngineValues {
55 pub fn try_init(self) -> Result<(), Self> {
57 ENGINE_DEFAULTS.set(self)
58 }
59
60 pub fn get_global() -> &'static Self {
62 ENGINE_DEFAULTS.get_or_init(Self::default)
63 }
64
65 pub const fn with_persistence_threshold(mut self, v: u64) -> Self {
67 self.persistence_threshold = v;
68 self
69 }
70
71 pub const fn with_persistence_backpressure_threshold(mut self, v: u64) -> Self {
73 self.persistence_backpressure_threshold = v;
74 self
75 }
76
77 pub const fn with_memory_block_buffer_target(mut self, v: u64) -> Self {
79 self.memory_block_buffer_target = v;
80 self
81 }
82
83 pub const fn with_legacy_state_root_task_enabled(mut self, v: bool) -> Self {
85 self.legacy_state_root_task_enabled = v;
86 self
87 }
88
89 pub const fn with_state_cache_disabled(mut self, v: bool) -> Self {
91 self.state_cache_disabled = v;
92 self
93 }
94
95 pub const fn with_prewarming_disabled(mut self, v: bool) -> Self {
97 self.prewarming_disabled = v;
98 self
99 }
100
101 pub const fn with_state_provider_metrics(mut self, v: bool) -> Self {
103 self.state_provider_metrics = v;
104 self
105 }
106
107 pub const fn with_cross_block_cache_size(mut self, v: usize) -> Self {
109 self.cross_block_cache_size = v;
110 self
111 }
112
113 pub const fn with_state_root_task_compare_updates(mut self, v: bool) -> Self {
115 self.state_root_task_compare_updates = v;
116 self
117 }
118
119 pub const fn with_accept_execution_requests_hash(mut self, v: bool) -> Self {
121 self.accept_execution_requests_hash = v;
122 self
123 }
124
125 pub const fn with_multiproof_chunk_size(mut self, v: usize) -> Self {
127 self.multiproof_chunk_size = v;
128 self
129 }
130
131 pub const fn with_reserved_cpu_cores(mut self, v: usize) -> Self {
133 self.reserved_cpu_cores = v;
134 self
135 }
136
137 pub const fn with_precompile_cache_disabled(mut self, v: bool) -> Self {
139 self.precompile_cache_disabled = v;
140 self
141 }
142
143 pub const fn with_state_root_fallback(mut self, v: bool) -> Self {
145 self.state_root_fallback = v;
146 self
147 }
148
149 pub const fn with_always_process_payload_attributes_on_canonical_head(
151 mut self,
152 v: bool,
153 ) -> Self {
154 self.always_process_payload_attributes_on_canonical_head = v;
155 self
156 }
157
158 pub const fn with_allow_unwind_canonical_header(mut self, v: bool) -> Self {
160 self.allow_unwind_canonical_header = v;
161 self
162 }
163
164 pub const fn with_storage_worker_count(mut self, v: Option<usize>) -> Self {
166 self.storage_worker_count = v;
167 self
168 }
169
170 pub const fn with_account_worker_count(mut self, v: Option<usize>) -> Self {
172 self.account_worker_count = v;
173 self
174 }
175
176 pub const fn with_prewarming_threads(mut self, v: Option<usize>) -> Self {
178 self.prewarming_threads = v;
179 self
180 }
181
182 pub const fn with_cache_metrics_disabled(mut self, v: bool) -> Self {
184 self.cache_metrics_disabled = v;
185 self
186 }
187
188 pub const fn with_sparse_trie_max_hot_slots(mut self, v: usize) -> Self {
190 self.sparse_trie_max_hot_slots = v;
191 self
192 }
193
194 pub const fn with_sparse_trie_max_hot_accounts(mut self, v: usize) -> Self {
196 self.sparse_trie_max_hot_accounts = v;
197 self
198 }
199
200 pub const fn with_slow_block_threshold(mut self, v: Option<Duration>) -> Self {
202 self.slow_block_threshold = v;
203 self
204 }
205
206 pub const fn with_disable_sparse_trie_cache_pruning(mut self, v: bool) -> Self {
208 self.disable_sparse_trie_cache_pruning = v;
209 self
210 }
211
212 pub fn with_state_root_task_timeout(mut self, v: Option<String>) -> Self {
214 self.state_root_task_timeout = v;
215 self
216 }
217
218 pub const fn with_share_execution_cache_with_payload_builder(mut self, v: bool) -> Self {
220 self.share_execution_cache_with_payload_builder = v;
221 self
222 }
223
224 pub const fn with_share_sparse_trie_with_payload_builder(mut self, v: bool) -> Self {
226 self.share_sparse_trie_with_payload_builder = v;
227 self
228 }
229}
230
231impl Default for DefaultEngineValues {
232 fn default() -> Self {
233 Self {
234 persistence_threshold: DEFAULT_PERSISTENCE_THRESHOLD,
235 persistence_backpressure_threshold: DEFAULT_PERSISTENCE_BACKPRESSURE_THRESHOLD,
236 memory_block_buffer_target: DEFAULT_MEMORY_BLOCK_BUFFER_TARGET,
237 legacy_state_root_task_enabled: false,
238 state_cache_disabled: false,
239 prewarming_disabled: false,
240 state_provider_metrics: false,
241 cross_block_cache_size: DEFAULT_CROSS_BLOCK_CACHE_SIZE_MB,
242 state_root_task_compare_updates: false,
243 accept_execution_requests_hash: false,
244 multiproof_chunk_size: DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE,
245 reserved_cpu_cores: DEFAULT_RESERVED_CPU_CORES,
246 precompile_cache_disabled: false,
247 state_root_fallback: false,
248 always_process_payload_attributes_on_canonical_head: false,
249 allow_unwind_canonical_header: false,
250 storage_worker_count: None,
251 account_worker_count: None,
252 prewarming_threads: None,
253 cache_metrics_disabled: false,
254 sparse_trie_max_hot_slots: DEFAULT_SPARSE_TRIE_MAX_HOT_SLOTS,
255 sparse_trie_max_hot_accounts: DEFAULT_SPARSE_TRIE_MAX_HOT_ACCOUNTS,
256 slow_block_threshold: None,
257 disable_sparse_trie_cache_pruning: false,
258 state_root_task_timeout: Some("1s".to_string()),
259 share_execution_cache_with_payload_builder: false,
260 share_sparse_trie_with_payload_builder: false,
261 }
262 }
263}
264
265#[derive(Debug, Clone, Args, PartialEq, Eq)]
267#[command(next_help_heading = "Engine")]
268pub struct EngineArgs {
269 #[arg(long = "engine.persistence-threshold", default_value_t = DefaultEngineValues::get_global().persistence_threshold)]
276 pub persistence_threshold: u64,
277
278 #[arg(long = "engine.persistence-backpressure-threshold", default_value_t = DefaultEngineValues::get_global().persistence_backpressure_threshold)]
282 pub persistence_backpressure_threshold: u64,
283
284 #[arg(long = "engine.memory-block-buffer-target", default_value_t = DefaultEngineValues::get_global().memory_block_buffer_target)]
286 pub memory_block_buffer_target: u64,
287
288 #[arg(long = "engine.legacy-state-root", default_value_t = DefaultEngineValues::get_global().legacy_state_root_task_enabled)]
290 pub legacy_state_root_task_enabled: bool,
291
292 #[arg(long = "engine.caching-and-prewarming", default_value = "true", hide = true)]
295 #[deprecated]
296 pub caching_and_prewarming_enabled: bool,
297
298 #[arg(long = "engine.disable-state-cache", default_value_t = DefaultEngineValues::get_global().state_cache_disabled)]
300 pub state_cache_disabled: bool,
301
302 #[arg(long = "engine.disable-prewarming", alias = "engine.disable-caching-and-prewarming", default_value_t = DefaultEngineValues::get_global().prewarming_disabled)]
304 pub prewarming_disabled: bool,
305
306 #[deprecated]
308 #[arg(long = "engine.parallel-sparse-trie", default_value = "true", hide = true)]
309 pub parallel_sparse_trie_enabled: bool,
310
311 #[deprecated]
313 #[arg(long = "engine.disable-parallel-sparse-trie", default_value = "false", hide = true)]
314 pub parallel_sparse_trie_disabled: bool,
315
316 #[arg(long = "engine.state-provider-metrics", default_value_t = DefaultEngineValues::get_global().state_provider_metrics)]
320 pub state_provider_metrics: bool,
321
322 #[arg(long = "engine.cross-block-cache-size", default_value_t = DefaultEngineValues::get_global().cross_block_cache_size)]
324 pub cross_block_cache_size: usize,
325
326 #[arg(long = "engine.state-root-task-compare-updates", default_value_t = DefaultEngineValues::get_global().state_root_task_compare_updates)]
329 pub state_root_task_compare_updates: bool,
330
331 #[arg(long = "engine.accept-execution-requests-hash", default_value_t = DefaultEngineValues::get_global().accept_execution_requests_hash)]
333 pub accept_execution_requests_hash: bool,
334
335 #[arg(long = "engine.multiproof-chunk-size", default_value_t = DefaultEngineValues::get_global().multiproof_chunk_size)]
337 pub multiproof_chunk_size: usize,
338
339 #[arg(long = "engine.reserved-cpu-cores", default_value_t = DefaultEngineValues::get_global().reserved_cpu_cores)]
341 pub reserved_cpu_cores: usize,
342
343 #[arg(long = "engine.precompile-cache", default_value = "true", hide = true)]
346 #[deprecated]
347 pub precompile_cache_enabled: bool,
348
349 #[arg(long = "engine.disable-precompile-cache", default_value_t = DefaultEngineValues::get_global().precompile_cache_disabled)]
351 pub precompile_cache_disabled: bool,
352
353 #[arg(long = "engine.state-root-fallback", default_value_t = DefaultEngineValues::get_global().state_root_fallback)]
355 pub state_root_fallback: bool,
356
357 #[arg(
363 long = "engine.always-process-payload-attributes-on-canonical-head",
364 default_value_t = DefaultEngineValues::get_global().always_process_payload_attributes_on_canonical_head
365 )]
366 pub always_process_payload_attributes_on_canonical_head: bool,
367
368 #[arg(long = "engine.allow-unwind-canonical-header", default_value_t = DefaultEngineValues::get_global().allow_unwind_canonical_header)]
371 pub allow_unwind_canonical_header: bool,
372
373 #[arg(long = "engine.storage-worker-count", default_value = Resettable::from(DefaultEngineValues::get_global().storage_worker_count.map(|v| v.to_string().into())))]
376 pub storage_worker_count: Option<usize>,
377
378 #[arg(long = "engine.account-worker-count", default_value = Resettable::from(DefaultEngineValues::get_global().account_worker_count.map(|v| v.to_string().into())))]
381 pub account_worker_count: Option<usize>,
382
383 #[arg(long = "engine.prewarming-threads", default_value = Resettable::from(DefaultEngineValues::get_global().prewarming_threads.map(|v| v.to_string().into())))]
386 pub prewarming_threads: Option<usize>,
387
388 #[arg(long = "engine.disable-cache-metrics", default_value_t = DefaultEngineValues::get_global().cache_metrics_disabled)]
390 pub cache_metrics_disabled: bool,
391
392 #[arg(long = "engine.sparse-trie-max-hot-slots", alias = "engine.sparse-trie-max-storage-tries", default_value_t = DefaultEngineValues::get_global().sparse_trie_max_hot_slots)]
394 pub sparse_trie_max_hot_slots: usize,
395
396 #[arg(long = "engine.sparse-trie-max-hot-accounts", default_value_t = DefaultEngineValues::get_global().sparse_trie_max_hot_accounts)]
398 pub sparse_trie_max_hot_accounts: usize,
399
400 #[arg(long = "engine.slow-block-threshold", value_parser = parse_duration_from_secs_or_ms, value_name = "DURATION", default_value = Resettable::from(DefaultEngineValues::get_global().slow_block_threshold.map(|threshold| format_duration_as_secs_or_ms(threshold).into())))]
409 pub slow_block_threshold: Option<Duration>,
410
411 #[arg(long = "engine.disable-sparse-trie-cache-pruning", default_value_t = DefaultEngineValues::get_global().disable_sparse_trie_cache_pruning)]
415 pub disable_sparse_trie_cache_pruning: bool,
416
417 #[arg(
426 long = "engine.state-root-task-timeout",
427 value_parser = humantime::parse_duration,
428 default_value = DefaultEngineValues::get_global().state_root_task_timeout.as_deref().unwrap_or("1s"),
429 )]
430 pub state_root_task_timeout: Option<Duration>,
431
432 #[arg(
440 long = "engine.share-execution-cache-with-payload-builder",
441 default_value_t = DefaultEngineValues::get_global().share_execution_cache_with_payload_builder,
442 )]
443 pub share_execution_cache_with_payload_builder: bool,
444
445 #[arg(
457 long = "engine.share-sparse-trie-with-payload-builder",
458 default_value_t = DefaultEngineValues::get_global().share_sparse_trie_with_payload_builder,
459 )]
460 pub share_sparse_trie_with_payload_builder: bool,
461
462 #[cfg(feature = "trie-debug")]
469 #[arg(
470 long = "engine.proof-jitter",
471 value_parser = humantime::parse_duration,
472 )]
473 pub proof_jitter: Option<Duration>,
474}
475
476#[allow(deprecated)]
477impl Default for EngineArgs {
478 fn default() -> Self {
479 let DefaultEngineValues {
480 persistence_threshold,
481 persistence_backpressure_threshold,
482 memory_block_buffer_target,
483 legacy_state_root_task_enabled,
484 state_cache_disabled,
485 prewarming_disabled,
486 state_provider_metrics,
487 cross_block_cache_size,
488 state_root_task_compare_updates,
489 accept_execution_requests_hash,
490 multiproof_chunk_size,
491 reserved_cpu_cores,
492 precompile_cache_disabled,
493 state_root_fallback,
494 always_process_payload_attributes_on_canonical_head,
495 allow_unwind_canonical_header,
496 storage_worker_count,
497 account_worker_count,
498 prewarming_threads,
499 cache_metrics_disabled,
500 sparse_trie_max_hot_slots,
501 sparse_trie_max_hot_accounts,
502 slow_block_threshold,
503 disable_sparse_trie_cache_pruning,
504 state_root_task_timeout,
505 share_execution_cache_with_payload_builder,
506 share_sparse_trie_with_payload_builder,
507 } = DefaultEngineValues::get_global().clone();
508 Self {
509 persistence_threshold,
510 persistence_backpressure_threshold,
511 memory_block_buffer_target,
512 legacy_state_root_task_enabled,
513 state_root_task_compare_updates,
514 caching_and_prewarming_enabled: true,
515 state_cache_disabled,
516 prewarming_disabled,
517 parallel_sparse_trie_enabled: true,
518 parallel_sparse_trie_disabled: false,
519 state_provider_metrics,
520 cross_block_cache_size,
521 accept_execution_requests_hash,
522 multiproof_chunk_size,
523 reserved_cpu_cores,
524 precompile_cache_enabled: true,
525 precompile_cache_disabled,
526 state_root_fallback,
527 always_process_payload_attributes_on_canonical_head,
528 allow_unwind_canonical_header,
529 storage_worker_count,
530 account_worker_count,
531 prewarming_threads,
532 cache_metrics_disabled,
533 sparse_trie_max_hot_slots,
534 sparse_trie_max_hot_accounts,
535 slow_block_threshold,
536 disable_sparse_trie_cache_pruning,
537 state_root_task_timeout: state_root_task_timeout
538 .as_deref()
539 .map(|s| humantime::parse_duration(s).expect("valid default duration")),
540 share_execution_cache_with_payload_builder,
541 share_sparse_trie_with_payload_builder,
542 #[cfg(feature = "trie-debug")]
543 proof_jitter: None,
544 }
545 }
546}
547
548impl EngineArgs {
549 pub fn validate(&self) -> eyre::Result<()> {
551 ensure!(
552 self.persistence_backpressure_threshold > self.persistence_threshold,
553 "--engine.persistence-backpressure-threshold ({}) must be greater than --engine.persistence-threshold ({})",
554 self.persistence_backpressure_threshold,
555 self.persistence_threshold
556 );
557 Ok(())
558 }
559
560 pub fn tree_config(&self) -> TreeConfig {
562 let config = TreeConfig::default()
563 .with_persistence_threshold(self.persistence_threshold)
564 .with_persistence_backpressure_threshold(self.persistence_backpressure_threshold)
565 .with_memory_block_buffer_target(self.memory_block_buffer_target)
566 .with_legacy_state_root(self.legacy_state_root_task_enabled)
567 .without_state_cache(self.state_cache_disabled)
568 .without_prewarming(self.prewarming_disabled)
569 .with_state_provider_metrics(self.state_provider_metrics)
570 .with_always_compare_trie_updates(self.state_root_task_compare_updates)
571 .with_cross_block_cache_size(self.cross_block_cache_size * 1024 * 1024)
572 .with_multiproof_chunk_size(self.multiproof_chunk_size)
573 .with_reserved_cpu_cores(self.reserved_cpu_cores)
574 .without_precompile_cache(self.precompile_cache_disabled)
575 .with_state_root_fallback(self.state_root_fallback)
576 .with_always_process_payload_attributes_on_canonical_head(
577 self.always_process_payload_attributes_on_canonical_head,
578 )
579 .with_unwind_canonical_header(self.allow_unwind_canonical_header)
580 .without_cache_metrics(self.cache_metrics_disabled)
581 .with_sparse_trie_max_hot_slots(self.sparse_trie_max_hot_slots)
582 .with_sparse_trie_max_hot_accounts(self.sparse_trie_max_hot_accounts)
583 .with_slow_block_threshold(self.slow_block_threshold)
584 .with_disable_sparse_trie_cache_pruning(self.disable_sparse_trie_cache_pruning)
585 .with_state_root_task_timeout(self.state_root_task_timeout.filter(|d| !d.is_zero()))
586 .with_share_execution_cache_with_payload_builder(
587 self.share_execution_cache_with_payload_builder,
588 )
589 .with_share_sparse_trie_with_payload_builder(
590 self.share_sparse_trie_with_payload_builder,
591 );
592 #[cfg(feature = "trie-debug")]
593 let config = config.with_proof_jitter(self.proof_jitter);
594 config
595 }
596}
597
598#[cfg(test)]
599mod tests {
600 use super::*;
601 use clap::Parser;
602
603 #[derive(Parser)]
605 struct CommandParser<T: Args> {
606 #[command(flatten)]
607 args: T,
608 }
609
610 #[test]
611 fn test_parse_engine_args() {
612 let default_args = EngineArgs::default();
613 let args = CommandParser::<EngineArgs>::parse_from(["reth"]).args;
614 assert_eq!(args, default_args);
615 }
616
617 #[test]
618 #[allow(deprecated)]
619 fn engine_args() {
620 let args = EngineArgs {
621 persistence_threshold: 100,
622 persistence_backpressure_threshold: 101,
623 memory_block_buffer_target: 50,
624 legacy_state_root_task_enabled: true,
625 caching_and_prewarming_enabled: true,
626 state_cache_disabled: true,
627 prewarming_disabled: true,
628 parallel_sparse_trie_enabled: true,
629 parallel_sparse_trie_disabled: false,
630 state_provider_metrics: true,
631 cross_block_cache_size: 256,
632 state_root_task_compare_updates: true,
633 accept_execution_requests_hash: true,
634 multiproof_chunk_size: 512,
635 reserved_cpu_cores: 4,
636 precompile_cache_enabled: true,
637 precompile_cache_disabled: true,
638 state_root_fallback: true,
639 always_process_payload_attributes_on_canonical_head: true,
640 allow_unwind_canonical_header: true,
641 storage_worker_count: Some(16),
642 account_worker_count: Some(8),
643 prewarming_threads: Some(4),
644 cache_metrics_disabled: true,
645 sparse_trie_max_hot_slots: 100,
646 sparse_trie_max_hot_accounts: 500,
647 slow_block_threshold: None,
648 disable_sparse_trie_cache_pruning: true,
649 state_root_task_timeout: Some(Duration::from_secs(2)),
650 share_execution_cache_with_payload_builder: false,
651 share_sparse_trie_with_payload_builder: false,
652 #[cfg(feature = "trie-debug")]
653 proof_jitter: None,
654 };
655
656 let parsed_args = CommandParser::<EngineArgs>::parse_from([
657 "reth",
658 "--engine.persistence-threshold",
659 "100",
660 "--engine.persistence-backpressure-threshold",
661 "101",
662 "--engine.memory-block-buffer-target",
663 "50",
664 "--engine.legacy-state-root",
665 "--engine.disable-state-cache",
666 "--engine.disable-prewarming",
667 "--engine.state-provider-metrics",
668 "--engine.cross-block-cache-size",
669 "256",
670 "--engine.state-root-task-compare-updates",
671 "--engine.accept-execution-requests-hash",
672 "--engine.multiproof-chunk-size",
673 "512",
674 "--engine.reserved-cpu-cores",
675 "4",
676 "--engine.disable-precompile-cache",
677 "--engine.state-root-fallback",
678 "--engine.always-process-payload-attributes-on-canonical-head",
679 "--engine.allow-unwind-canonical-header",
680 "--engine.storage-worker-count",
681 "16",
682 "--engine.account-worker-count",
683 "8",
684 "--engine.prewarming-threads",
685 "4",
686 "--engine.disable-cache-metrics",
687 "--engine.sparse-trie-max-hot-slots",
688 "100",
689 "--engine.sparse-trie-max-hot-accounts",
690 "500",
691 "--engine.disable-sparse-trie-cache-pruning",
692 "--engine.state-root-task-timeout",
693 "2s",
694 ])
695 .args;
696
697 assert_eq!(parsed_args, args);
698 }
699
700 #[test]
701 fn validate_rejects_invalid_backpressure_threshold() {
702 let args = EngineArgs {
703 persistence_threshold: 4,
704 persistence_backpressure_threshold: 4,
705 ..EngineArgs::default()
706 };
707
708 let err = args.validate().unwrap_err().to_string();
709 assert!(err.contains("engine.persistence-backpressure-threshold"));
710 assert!(err.contains("engine.persistence-threshold"));
711 }
712
713 #[test]
714 fn test_parse_slow_block_threshold() {
715 let args = CommandParser::<EngineArgs>::parse_from(["reth"]).args;
717 assert_eq!(args.slow_block_threshold, None);
718
719 let args =
721 CommandParser::<EngineArgs>::parse_from(["reth", "--engine.slow-block-threshold", "0"])
722 .args;
723 assert_eq!(args.slow_block_threshold, Some(Duration::ZERO));
724
725 let args = CommandParser::<EngineArgs>::parse_from([
727 "reth",
728 "--engine.slow-block-threshold",
729 "500",
730 ])
731 .args;
732 assert_eq!(args.slow_block_threshold, Some(Duration::from_secs(500)));
733
734 let args = CommandParser::<EngineArgs>::parse_from([
735 "reth",
736 "--engine.slow-block-threshold",
737 "500ms",
738 ])
739 .args;
740 assert_eq!(args.slow_block_threshold, Some(Duration::from_millis(500)));
741 }
742
743 #[test]
744 fn test_parse_share_sparse_trie_flag() {
745 let args = CommandParser::<EngineArgs>::parse_from(["reth"]).args;
746 assert!(!args.share_sparse_trie_with_payload_builder);
747 assert!(!args.tree_config().share_sparse_trie_with_payload_builder());
748
749 let args = CommandParser::<EngineArgs>::parse_from([
750 "reth",
751 "--engine.share-sparse-trie-with-payload-builder",
752 ])
753 .args;
754 assert!(args.share_sparse_trie_with_payload_builder);
755 assert!(args.tree_config().share_sparse_trie_with_payload_builder());
756 }
757}