Skip to content

Commit 5b9c8b4

Browse files
committed
feat: Add support for both ip and hostname for peers
It is convinent to be able to specify both IPs and hostnames as peers. Especially, when you are building ephemeral testnets and want to specify peers as ``` ./snarkos start --peers "validator0:4130,client0:4130" ``` Where you can populate the `/etc/hosts` file with subnet hostnames.
1 parent 2cb5444 commit 5b9c8b4

File tree

1 file changed

+69
-6
lines changed

1 file changed

+69
-6
lines changed

cli/src/commands/start.rs

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use rand::{Rng, SeedableRng};
4242
use rand_chacha::ChaChaRng;
4343
use serde::{Deserialize, Serialize};
4444
use std::{
45-
net::SocketAddr,
45+
net::{SocketAddr, ToSocketAddrs},
4646
path::PathBuf,
4747
sync::{Arc, atomic::AtomicBool},
4848
};
@@ -228,11 +228,18 @@ impl Start {
228228
false => Ok(self
229229
.peers
230230
.split(',')
231-
.flat_map(|ip| match ip.parse::<SocketAddr>() {
232-
Ok(ip) => Some(ip),
233-
Err(e) => {
234-
eprintln!("The IP supplied to --peers ('{ip}') is malformed: {e}");
235-
None
231+
.flat_map(|ip_or_hostname| {
232+
let trimmed = ip_or_hostname.trim();
233+
match trimmed.to_socket_addrs() {
234+
Ok(mut ip_iter) => {
235+
// A hostname might resolve to multiple IP addresses. We will use only the first one,
236+
// assuming this aligns with the user's expectations.
237+
ip_iter.next()
238+
},
239+
Err(e) => {
240+
eprintln!("The hostname or IP supplied to --peers ('{trimmed}') is malformed: {e}");
241+
None
242+
}
236243
}
237244
})
238245
.collect()),
@@ -1039,4 +1046,60 @@ mod tests {
10391046
panic!("Unexpected result of clap parsing!");
10401047
}
10411048
}
1049+
1050+
#[test]
1051+
fn parse_peers_when_ips() {
1052+
let arg_vec = vec!["snarkos", "start", "--peers", "127.0.0.1:3030,127.0.0.2:3030"];
1053+
let cli = CLI::parse_from(arg_vec);
1054+
1055+
if let Command::Start(start) = cli.command {
1056+
let peers = start.parse_trusted_peers();
1057+
assert!(peers.is_ok());
1058+
assert_eq!(peers.unwrap().len(), 2, "Expected two peers");
1059+
} else {
1060+
panic!("Unexpected result of clap parsing!");
1061+
}
1062+
}
1063+
1064+
#[test]
1065+
fn parse_peers_when_hostnames() {
1066+
let arg_vec = vec!["snarkos", "start", "--peers", "www.example.com:4130,www.google.com:4130"];
1067+
let cli = CLI::parse_from(arg_vec);
1068+
1069+
if let Command::Start(start) = cli.command {
1070+
let peers = start.parse_trusted_peers();
1071+
assert!(peers.is_ok());
1072+
assert_eq!(peers.unwrap().len(), 2, "Expected two peers");
1073+
} else {
1074+
panic!("Unexpected result of clap parsing!");
1075+
}
1076+
}
1077+
1078+
#[test]
1079+
fn parse_peers_when_mixed_and_with_whitespaces() {
1080+
let arg_vec = vec!["snarkos", "start", "--peers", " 127.0.0.1:3030, www.google.com:4130 "];
1081+
let cli = CLI::parse_from(arg_vec);
1082+
1083+
if let Command::Start(start) = cli.command {
1084+
let peers = start.parse_trusted_peers();
1085+
assert!(peers.is_ok());
1086+
assert_eq!(peers.unwrap().len(), 2, "Expected two peers");
1087+
} else {
1088+
panic!("Unexpected result of clap parsing!");
1089+
}
1090+
}
1091+
1092+
#[test]
1093+
fn parse_peers_when_unknown_hostname_gracefully() {
1094+
let arg_vec = vec!["snarkos", "start", "--peers", "banana.cake.eafafdaeefasdfasd.com"];
1095+
let cli = CLI::parse_from(arg_vec);
1096+
1097+
if let Command::Start(start) = cli.command {
1098+
let peers = start.parse_trusted_peers();
1099+
assert!(peers.is_ok());
1100+
assert!(peers.unwrap().is_empty(), "Expected no peers to be found");
1101+
} else {
1102+
panic!("Unexpected result of clap parsing!");
1103+
}
1104+
}
10421105
}

0 commit comments

Comments
 (0)