Skip to main content

reth_node_core/args/
dev.rs

1//! clap [Args](clap::Args) for Dev testnet configuration
2
3use std::time::Duration;
4
5use clap::Args;
6use humantime::parse_duration;
7
8const DEFAULT_MNEMONIC: &str = "test test test test test test test test test test test junk";
9
10/// Parameters for Dev testnet configuration
11#[derive(Debug, Args, PartialEq, Eq, Clone)]
12#[command(next_help_heading = "Dev testnet")]
13pub struct DevArgs {
14    /// Start the node in dev mode
15    ///
16    /// This mode uses a local proof-of-authority consensus engine with either fixed block times
17    /// or automatically mined blocks.
18    /// Disables network discovery and enables local http server.
19    /// Prefunds 20 accounts derived by mnemonic "test test test test test test test test test test
20    /// test junk" with 10 000 ETH each.
21    #[arg(long = "dev", alias = "auto-mine", help_heading = "Dev testnet", verbatim_doc_comment)]
22    pub dev: bool,
23
24    /// How many transactions to mine per block.
25    #[arg(
26        long = "dev.block-max-transactions",
27        help_heading = "Dev testnet",
28        conflicts_with = "block_time"
29    )]
30    pub block_max_transactions: Option<usize>,
31
32    /// Interval between blocks.
33    ///
34    /// Parses strings using [`humantime::parse_duration`]
35    /// --dev.block-time 12s
36    #[arg(
37        long = "dev.block-time",
38        help_heading = "Dev testnet",
39        conflicts_with = "block_max_transactions",
40        value_parser = parse_duration,
41        verbatim_doc_comment
42    )]
43    pub block_time: Option<Duration>,
44
45    /// Time to wait after initiating payload building before resolving.
46    ///
47    /// Introduces a sleep between `fork_choice_updated` and `resolve_kind` in the
48    /// local miner, giving the payload job time for multiple rebuild attempts with
49    /// new transactions from the pool.
50    ///
51    /// Parses strings using [`humantime::parse_duration`]
52    /// --dev.payload-wait-time 450ms
53    #[arg(
54        long = "dev.payload-wait-time",
55        help_heading = "Dev testnet",
56        value_parser = parse_duration,
57        verbatim_doc_comment
58    )]
59    pub payload_wait_time: Option<Duration>,
60
61    /// Derive dev accounts from a fixed mnemonic instead of random ones.
62    #[arg(
63        long = "dev.mnemonic",
64        help_heading = "Dev testnet",
65        value_name = "MNEMONIC",
66        requires = "dev",
67        verbatim_doc_comment,
68        default_value = DEFAULT_MNEMONIC
69    )]
70    pub dev_mnemonic: String,
71}
72
73impl Default for DevArgs {
74    fn default() -> Self {
75        Self {
76            dev: false,
77            block_max_transactions: None,
78            block_time: None,
79            payload_wait_time: None,
80            dev_mnemonic: DEFAULT_MNEMONIC.to_string(),
81        }
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88    use clap::Parser;
89
90    /// A helper type to parse Args more easily
91    #[derive(Parser)]
92    struct CommandParser<T: Args> {
93        #[command(flatten)]
94        args: T,
95    }
96
97    #[test]
98    fn test_parse_dev_args() {
99        let args = CommandParser::<DevArgs>::parse_from(["reth"]).args;
100        assert_eq!(
101            args,
102            DevArgs {
103                dev: false,
104                block_max_transactions: None,
105                block_time: None,
106                payload_wait_time: None,
107                dev_mnemonic: DEFAULT_MNEMONIC.to_string(),
108            }
109        );
110
111        let args = CommandParser::<DevArgs>::parse_from(["reth", "--dev"]).args;
112        assert_eq!(
113            args,
114            DevArgs {
115                dev: true,
116                block_max_transactions: None,
117                block_time: None,
118                payload_wait_time: None,
119                dev_mnemonic: DEFAULT_MNEMONIC.to_string(),
120            }
121        );
122
123        let args = CommandParser::<DevArgs>::parse_from(["reth", "--auto-mine"]).args;
124        assert_eq!(
125            args,
126            DevArgs {
127                dev: true,
128                block_max_transactions: None,
129                block_time: None,
130                payload_wait_time: None,
131                dev_mnemonic: DEFAULT_MNEMONIC.to_string(),
132            }
133        );
134
135        let args = CommandParser::<DevArgs>::parse_from([
136            "reth",
137            "--dev",
138            "--dev.block-max-transactions",
139            "2",
140        ])
141        .args;
142        assert_eq!(
143            args,
144            DevArgs {
145                dev: true,
146                block_max_transactions: Some(2),
147                block_time: None,
148                payload_wait_time: None,
149                dev_mnemonic: DEFAULT_MNEMONIC.to_string(),
150            }
151        );
152
153        let args =
154            CommandParser::<DevArgs>::parse_from(["reth", "--dev", "--dev.block-time", "1s"]).args;
155        assert_eq!(
156            args,
157            DevArgs {
158                dev: true,
159                block_max_transactions: None,
160                block_time: Some(std::time::Duration::from_secs(1)),
161                payload_wait_time: None,
162                dev_mnemonic: DEFAULT_MNEMONIC.to_string(),
163            }
164        );
165    }
166
167    #[test]
168    fn test_parse_dev_args_conflicts() {
169        let args = CommandParser::<DevArgs>::try_parse_from([
170            "reth",
171            "--dev",
172            "--dev.block-max-transactions",
173            "2",
174            "--dev.block-time",
175            "1s",
176        ]);
177        assert!(args.is_err());
178    }
179
180    #[test]
181    fn dev_args_default_sanity_check() {
182        let default_args = DevArgs::default();
183        let args = CommandParser::<DevArgs>::parse_from(["reth"]).args;
184        assert_eq!(args, default_args);
185    }
186}