agave_validator/commands/run/args/
rpc_bootstrap_config.rs1use {
2 crate::{
3 bootstrap::RpcBootstrapConfig,
4 commands::{FromClapArgMatches, Result},
5 },
6 clap::{value_t, Arg, ArgMatches},
7 solana_genesis_utils::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
8 std::sync::LazyLock,
9};
10
11static DEFAULT_MAX_GENESIS_ARCHIVE_UNPACKED_SIZE: LazyLock<String> =
12 LazyLock::new(|| MAX_GENESIS_ARCHIVE_UNPACKED_SIZE.to_string());
13
14#[cfg(test)]
15impl Default for RpcBootstrapConfig {
16 fn default() -> Self {
17 Self {
18 no_genesis_fetch: false,
19 no_snapshot_fetch: false,
20 check_vote_account: None,
21 only_known_rpc: false,
22 max_genesis_archive_unpacked_size: 10485760,
23 incremental_snapshot_fetch: true,
24 }
25 }
26}
27
28impl FromClapArgMatches for RpcBootstrapConfig {
29 fn from_clap_arg_match(matches: &ArgMatches) -> Result<Self> {
30 let no_genesis_fetch = matches.is_present("no_genesis_fetch");
31
32 let no_snapshot_fetch = matches.is_present("no_snapshot_fetch");
33
34 let check_vote_account = matches
35 .value_of("check_vote_account")
36 .map(|url| url.to_string());
37
38 let only_known_rpc = matches.is_present("only_known_rpc");
39
40 let max_genesis_archive_unpacked_size =
41 value_t!(matches, "max_genesis_archive_unpacked_size", u64).map_err(|err| {
42 Box::<dyn std::error::Error>::from(format!(
43 "failed to parse max_genesis_archive_unpacked_size: {err}"
44 ))
45 })?;
46
47 let no_incremental_snapshots = matches.is_present("no_incremental_snapshots");
48
49 Ok(Self {
50 no_genesis_fetch,
51 no_snapshot_fetch,
52 check_vote_account,
53 only_known_rpc,
54 max_genesis_archive_unpacked_size,
55 incremental_snapshot_fetch: !no_incremental_snapshots,
56 })
57 }
58}
59
60pub(crate) fn args<'a, 'b>() -> Vec<Arg<'a, 'b>> {
61 vec![
62 Arg::with_name("no_genesis_fetch")
63 .long("no-genesis-fetch")
64 .takes_value(false)
65 .help("Do not fetch genesis from the cluster"),
66 Arg::with_name("no_snapshot_fetch")
67 .long("no-snapshot-fetch")
68 .takes_value(false)
69 .help(
70 "Do not attempt to fetch a snapshot from the cluster, start from a local snapshot \
71 if present",
72 ),
73 Arg::with_name("check_vote_account")
74 .long("check-vote-account")
75 .takes_value(true)
76 .value_name("RPC_URL")
77 .requires("entrypoint")
78 .conflicts_with_all(&["no_voting"])
79 .help(
80 "Sanity check vote account state at startup. The JSON RPC endpoint at RPC_URL \
81 must expose `--full-rpc-api`",
82 ),
83 Arg::with_name("only_known_rpc")
84 .alias("no-untrusted-rpc")
85 .long("only-known-rpc")
86 .takes_value(false)
87 .requires("known_validators")
88 .help("Use the RPC service of known validators only"),
89 Arg::with_name("max_genesis_archive_unpacked_size")
90 .long("max-genesis-archive-unpacked-size")
91 .value_name("NUMBER")
92 .takes_value(true)
93 .default_value(&DEFAULT_MAX_GENESIS_ARCHIVE_UNPACKED_SIZE)
94 .help("maximum total uncompressed file size of downloaded genesis archive"),
95 Arg::with_name("no_incremental_snapshots")
96 .long("no-incremental-snapshots")
97 .takes_value(false)
98 .help("Disable incremental snapshots"),
99 ]
100}
101
102#[cfg(test)]
103mod tests {
104 use {
105 super::*,
106 crate::commands::run::args::{
107 tests::verify_args_struct_by_command_run_with_identity_setup, RunArgs,
108 },
109 solana_pubkey::Pubkey,
110 std::{
111 collections::HashSet,
112 net::{IpAddr, Ipv4Addr, SocketAddr},
113 },
114 };
115
116 #[test]
117 fn verify_args_struct_by_command_run_with_no_genesis_fetch() {
118 {
120 let default_run_args = RunArgs::default();
121 let expected_args = RunArgs {
122 rpc_bootstrap_config: RpcBootstrapConfig {
123 no_genesis_fetch: true,
124 ..RpcBootstrapConfig::default()
125 },
126 ..default_run_args.clone()
127 };
128 verify_args_struct_by_command_run_with_identity_setup(
129 default_run_args.clone(),
130 vec!["--no-genesis-fetch"],
131 expected_args,
132 );
133 }
134 }
135
136 #[test]
137 fn verify_args_struct_by_command_run_with_no_snapshot_fetch() {
138 {
140 let default_run_args = RunArgs::default();
141 let expected_args = RunArgs {
142 rpc_bootstrap_config: RpcBootstrapConfig {
143 no_snapshot_fetch: true,
144 ..RpcBootstrapConfig::default()
145 },
146 ..default_run_args.clone()
147 };
148 verify_args_struct_by_command_run_with_identity_setup(
149 default_run_args.clone(),
150 vec!["--no-snapshot-fetch"],
151 expected_args,
152 );
153 }
154 }
155
156 #[test]
157 fn verify_args_struct_by_command_run_with_check_vote_account() {
158 {
160 let default_run_args = RunArgs::default();
161 let expected_args = RunArgs {
162 entrypoints: vec![SocketAddr::new(
163 IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
164 8000,
165 )],
166 rpc_bootstrap_config: RpcBootstrapConfig {
167 check_vote_account: Some("https://api.mainnet-beta.solana.com".to_string()),
168 ..RpcBootstrapConfig::default()
169 },
170 ..default_run_args.clone()
171 };
172 verify_args_struct_by_command_run_with_identity_setup(
173 default_run_args,
174 vec![
175 "--entrypoint",
177 "127.0.0.1:8000",
178 "--check-vote-account",
179 "https://api.mainnet-beta.solana.com",
180 ],
181 expected_args,
182 );
183 }
184 }
185
186 #[test]
187 fn verify_args_struct_by_command_run_with_only_known_rpc() {
188 {
190 let default_run_args = RunArgs::default();
191 let known_validators_pubkey = Pubkey::new_unique();
192 let known_validators = Some(HashSet::from([known_validators_pubkey]));
193 let expected_args = RunArgs {
194 known_validators,
195 rpc_bootstrap_config: RpcBootstrapConfig {
196 only_known_rpc: true,
197 ..RpcBootstrapConfig::default()
198 },
199 ..default_run_args.clone()
200 };
201 verify_args_struct_by_command_run_with_identity_setup(
202 default_run_args,
203 vec![
204 "--known-validator",
206 &known_validators_pubkey.to_string(),
207 "--only-known-rpc",
208 ],
209 expected_args,
210 );
211 }
212
213 {
215 let default_run_args = RunArgs::default();
216 let known_validators_pubkey = Pubkey::new_unique();
217 let known_validators = Some(HashSet::from([known_validators_pubkey]));
218 let expected_args = RunArgs {
219 known_validators,
220 rpc_bootstrap_config: RpcBootstrapConfig {
221 only_known_rpc: true,
222 ..RpcBootstrapConfig::default()
223 },
224 ..default_run_args.clone()
225 };
226 verify_args_struct_by_command_run_with_identity_setup(
227 default_run_args,
228 vec![
229 "--known-validator",
231 &known_validators_pubkey.to_string(),
232 "--no-untrusted-rpc",
233 ],
234 expected_args,
235 );
236 }
237 }
238
239 #[test]
240 fn verify_args_struct_by_command_run_with_incremental_snapshot_fetch() {
241 {
243 let default_run_args = RunArgs::default();
244 let expected_args = RunArgs {
245 rpc_bootstrap_config: RpcBootstrapConfig {
246 incremental_snapshot_fetch: false,
247 ..RpcBootstrapConfig::default()
248 },
249 ..default_run_args.clone()
250 };
251 verify_args_struct_by_command_run_with_identity_setup(
252 default_run_args,
253 vec!["--no-incremental-snapshots"],
254 expected_args,
255 );
256 }
257 }
258
259 #[test]
260 fn test_default_max_genesis_archive_unpacked_size_unchanged() {
261 assert_eq!(
262 *DEFAULT_MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
263 (10 * 1024 * 1024).to_string()
264 );
265 }
266}