agave_validator/commands/set_public_address/
mod.rs

1use {
2    crate::{
3        admin_rpc_service,
4        commands::{FromClapArgMatches, Result},
5    },
6    clap::{App, Arg, ArgGroup, ArgMatches, SubCommand},
7    std::{net::SocketAddr, path::Path},
8};
9
10const COMMAND: &str = "set-public-address";
11
12#[derive(Debug, PartialEq)]
13pub struct SetPublicAddressArgs {
14    pub tpu_addr: Option<SocketAddr>,
15    pub tpu_forwards_addr: Option<SocketAddr>,
16}
17
18impl FromClapArgMatches for SetPublicAddressArgs {
19    fn from_clap_arg_match(matches: &ArgMatches) -> Result<Self> {
20        let parse_arg_addr = |arg_name: &str,
21                              arg_long: &str|
22         -> std::result::Result<
23            Option<SocketAddr>,
24            Box<dyn std::error::Error>,
25        > {
26            Ok(matches.value_of(arg_name).map(|host_port| {
27                solana_net_utils::parse_host_port(host_port).map_err(|err| {
28                    format!(
29                        "failed to parse --{arg_long} address. It must be in the HOST:PORT format. {err}"
30                    )
31                })
32            })
33            .transpose()?)
34        };
35        Ok(SetPublicAddressArgs {
36            tpu_addr: parse_arg_addr("tpu_addr", "tpu")?,
37            tpu_forwards_addr: parse_arg_addr("tpu_forwards_addr", "tpu-forwards")?,
38        })
39    }
40}
41
42pub fn command<'a>() -> App<'a, 'a> {
43    SubCommand::with_name(COMMAND)
44        .about("Specify addresses to advertise in gossip")
45        .arg(
46            Arg::with_name("tpu_addr")
47                .long("tpu")
48                .value_name("HOST:PORT")
49                .takes_value(true)
50                .validator(solana_net_utils::is_host_port)
51                .help("TPU address to advertise in gossip"),
52        )
53        .arg(
54            Arg::with_name("tpu_forwards_addr")
55                .long("tpu-forwards")
56                .value_name("HOST:PORT")
57                .takes_value(true)
58                .validator(solana_net_utils::is_host_port)
59                .help("TPU Forwards address to advertise in gossip"),
60        )
61        .group(
62            ArgGroup::with_name("set_public_address_details")
63                .args(&["tpu_addr", "tpu_forwards_addr"])
64                .required(true)
65                .multiple(true),
66        )
67        .after_help("Note: At least one arg must be used. Using multiple is ok")
68}
69
70pub fn execute(matches: &ArgMatches, ledger_path: &Path) -> Result<()> {
71    let set_public_address_args = SetPublicAddressArgs::from_clap_arg_match(matches)?;
72
73    macro_rules! set_public_address {
74        ($public_addr:expr, $set_public_address:ident, $request:literal) => {
75            if let Some(public_addr) = $public_addr {
76                let admin_client = admin_rpc_service::connect(ledger_path);
77                admin_rpc_service::runtime().block_on(async move {
78                    admin_client.await?.$set_public_address(public_addr).await
79                })
80            } else {
81                Ok(())
82            }
83        };
84    }
85    set_public_address!(
86        set_public_address_args.tpu_addr,
87        set_public_tpu_address,
88        "setPublicTpuAddress"
89    )?;
90    set_public_address!(
91        set_public_address_args.tpu_forwards_addr,
92        set_public_tpu_forwards_address,
93        "set public tpu forwards address"
94    )?;
95    Ok(())
96}
97
98#[cfg(test)]
99mod tests {
100    use {
101        super::*,
102        crate::commands::tests::{
103            verify_args_struct_by_command, verify_args_struct_by_command_is_error,
104        },
105    };
106
107    #[test]
108    fn verify_args_struct_by_command_set_public_default() {
109        verify_args_struct_by_command_is_error::<SetPublicAddressArgs>(command(), vec![COMMAND]);
110    }
111
112    #[test]
113    fn verify_args_struct_by_command_set_public_address_tpu() {
114        verify_args_struct_by_command(
115            command(),
116            vec![COMMAND, "--tpu", "127.0.0.1:8080"],
117            SetPublicAddressArgs {
118                tpu_addr: Some(SocketAddr::from(([127, 0, 0, 1], 8080))),
119                tpu_forwards_addr: None,
120            },
121        );
122    }
123
124    #[test]
125    fn verify_args_struct_by_command_set_public_address_tpu_forwards() {
126        verify_args_struct_by_command(
127            command(),
128            vec![COMMAND, "--tpu-forwards", "127.0.0.1:8081"],
129            SetPublicAddressArgs {
130                tpu_addr: None,
131                tpu_forwards_addr: Some(SocketAddr::from(([127, 0, 0, 1], 8081))),
132            },
133        );
134    }
135
136    #[test]
137    fn verify_args_struct_by_command_set_public_address_tpu_and_tpu_forwards() {
138        verify_args_struct_by_command(
139            command(),
140            vec![
141                COMMAND,
142                "--tpu",
143                "127.0.0.1:8080",
144                "--tpu-forwards",
145                "127.0.0.1:8081",
146            ],
147            SetPublicAddressArgs {
148                tpu_addr: Some(SocketAddr::from(([127, 0, 0, 1], 8080))),
149                tpu_forwards_addr: Some(SocketAddr::from(([127, 0, 0, 1], 8081))),
150            },
151        );
152    }
153}