Add DNS resolution to cli tools
This commit is contained in:
parent
6859907df9
commit
0767c0c07f
|
@ -2200,6 +2200,7 @@ dependencies = [
|
|||
"solana-drone 0.13.0",
|
||||
"solana-logger 0.13.0",
|
||||
"solana-metrics 0.13.0",
|
||||
"solana-netutil 0.13.0",
|
||||
"solana-sdk 0.13.0",
|
||||
]
|
||||
|
||||
|
@ -2388,6 +2389,7 @@ dependencies = [
|
|||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"solana 0.13.0",
|
||||
"solana-netutil 0.13.0",
|
||||
"solana-sdk 0.13.0",
|
||||
]
|
||||
|
||||
|
@ -2690,6 +2692,7 @@ dependencies = [
|
|||
"solana-client 0.13.0",
|
||||
"solana-drone 0.13.0",
|
||||
"solana-logger 0.13.0",
|
||||
"solana-netutil 0.13.0",
|
||||
"solana-sdk 0.13.0",
|
||||
"solana-vote-api 0.13.0",
|
||||
"solana-vote-signer 0.13.0",
|
||||
|
|
|
@ -16,6 +16,7 @@ solana-client = { path = "../client", version = "0.13.0" }
|
|||
solana-drone = { path = "../drone", version = "0.13.0" }
|
||||
solana-logger = { path = "../logger", version = "0.13.0" }
|
||||
solana-metrics = { path = "../metrics", version = "0.13.0" }
|
||||
solana-netutil = { path = "../netutil", version = "0.13.0" }
|
||||
solana-sdk = { path = "../sdk", version = "0.13.0" }
|
||||
|
||||
[features]
|
||||
|
|
|
@ -117,14 +117,14 @@ pub fn extract_args<'a>(matches: &ArgMatches<'a>) -> Config {
|
|||
let mut args = Config::default();
|
||||
|
||||
if let Some(addr) = matches.value_of("network") {
|
||||
args.network_addr = addr.parse().unwrap_or_else(|e| {
|
||||
eprintln!("failed to parse network: {}", e);
|
||||
args.network_addr = solana_netutil::parse_host_port(addr).unwrap_or_else(|e| {
|
||||
eprintln!("failed to parse network address: {}", e);
|
||||
exit(1)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(addr) = matches.value_of("drone") {
|
||||
args.drone_addr = addr.parse().unwrap_or_else(|e| {
|
||||
args.drone_addr = solana_netutil::parse_host_port(addr).unwrap_or_else(|e| {
|
||||
eprintln!("failed to parse drone address: {}", e);
|
||||
exit(1)
|
||||
});
|
||||
|
|
|
@ -161,7 +161,7 @@ This will dump all the threads stack traces into gdb.txt
|
|||
In this example the client connects to our public testnet. To run validators on the testnet you would need to open udp ports `8000-10000`.
|
||||
|
||||
```bash
|
||||
$ ./multinode-demo/client.sh --network $(dig +short testnet.solana.com):8001 --duration 60
|
||||
$ ./multinode-demo/client.sh --network testnet.solana.com:8001 --duration 60
|
||||
```
|
||||
|
||||
You can observe the effects of your client's transactions on our [dashboard](https://metrics.solana.com:3000/d/testnet/testnet-hud?orgId=2&from=now-30m&to=now&refresh=5s&var-testnet=testnet)
|
||||
|
|
|
@ -26,14 +26,7 @@ Prebuilt binaries are available for Linux x86_64 (Ubuntu 18.04 recommended).
|
|||
MacOS or WSL users may build from source.
|
||||
|
||||
### Validator Setup
|
||||
The shell commands in this section assume the following environment variables are
|
||||
set:
|
||||
```bash
|
||||
$ export ip=$(dig +short beta.testnet.solana.com)
|
||||
```
|
||||
|
||||
#### Obtaining The Software
|
||||
|
||||
##### Bootstrap with `solana-install`
|
||||
|
||||
The `solana-install` tool can be used to easily install and upgrade the cluster
|
||||
|
@ -82,8 +75,8 @@ just restarting itself before debugging further.
|
|||
|
||||
Receive an airdrop of lamports from the testnet drone:
|
||||
```bash
|
||||
$ solana-wallet -n ${ip:?} airdrop 123
|
||||
$ solana-wallet -n ${ip:?} balance
|
||||
$ solana-wallet -n beta.testnet.solana.com airdrop 123
|
||||
$ solana-wallet -n beta.testnet.solana.com balance
|
||||
```
|
||||
|
||||
Fetch the current testnet transaction count over JSON RPC:
|
||||
|
@ -95,7 +88,7 @@ Inspect the blockexplorer at http://beta.testnet.solana.com/ for activity.
|
|||
|
||||
Run the following command to join the gossip network and view all the other nodes in the cluster:
|
||||
```bash
|
||||
$ RUST_LOG=info solana-gossip --network ${ip:?}:8001
|
||||
$ solana-gossip --network beta.testnet.solana.com:8001
|
||||
```
|
||||
|
||||
### Starting The Validator
|
||||
|
@ -103,24 +96,24 @@ The following command will start a new validator node.
|
|||
|
||||
If this is a `solana-install`-installation:
|
||||
```bash
|
||||
$ fullnode-x.sh --public-address --poll-for-new-genesis-block ${ip:?}
|
||||
$ fullnode-x.sh --public-address --poll-for-new-genesis-block beta.testnet.solana.com:8001
|
||||
```
|
||||
|
||||
Alternatively, the `solana-install run` command can be used to run the validator
|
||||
node while periodically checking for and applying software updates:
|
||||
```bash
|
||||
$ solana-install run fullnode-x.sh --public-address --poll-for-new-genesis-block ${ip:?}
|
||||
$ solana-install run fullnode-x.sh --public-address --poll-for-new-genesis-block beta.testnet.solana.com:8001
|
||||
```
|
||||
|
||||
When not using `solana-install`:
|
||||
```bash
|
||||
$ USE_INSTALL=1 ./multinode-demo/fullnode-x.sh --public-address --poll-for-new-genesis-block ${ip:?}
|
||||
$ USE_INSTALL=1 ./multinode-demo/fullnode-x.sh --public-address --poll-for-new-genesis-block beta.testnet.solana.com:8001
|
||||
```
|
||||
|
||||
Then from another console, confirm the IP address if your node is now visible in
|
||||
the gossip network by running:
|
||||
```bash
|
||||
$ RUST_LOG=info solana-gossip --network ${ip:?}:8001
|
||||
$ solana-gossip --network beta.testnet.solana.com:8001
|
||||
```
|
||||
|
||||
Congratulations, you're now participating in the testnet cluster!
|
||||
|
|
|
@ -187,9 +187,9 @@ fn main() {
|
|||
if matches.is_present("enable_rpc_exit") {
|
||||
fullnode_config.rpc_config.enable_fullnode_exit = true;
|
||||
}
|
||||
fullnode_config.rpc_config.drone_addr = matches
|
||||
.value_of("rpc_drone_address")
|
||||
.map(|address| address.parse().expect("failed to parse drone address"));
|
||||
fullnode_config.rpc_config.drone_addr = matches.value_of("rpc_drone_address").map(|address| {
|
||||
solana_netutil::parse_host_port(address).expect("failed to parse drone address")
|
||||
});
|
||||
|
||||
let dynamic_port_range = parse_port_range(matches.value_of("dynamic_port_range").unwrap())
|
||||
.expect("invalid dynamic_port_range");
|
||||
|
@ -214,7 +214,8 @@ fn main() {
|
|||
fullnode_config.account_paths = None;
|
||||
}
|
||||
let cluster_entrypoint = matches.value_of("network").map(|network| {
|
||||
let gossip_addr = network.parse().expect("failed to parse network address");
|
||||
let gossip_addr =
|
||||
solana_netutil::parse_host_port(network).expect("failed to parse network address");
|
||||
ContactInfo::new_gossip_entry_point(&gossip_addr)
|
||||
});
|
||||
let (_signer_service, _signer_addr) = if let Some(signer_addr) = matches.value_of("signer") {
|
||||
|
|
|
@ -12,6 +12,7 @@ homepage = "https://solana.com/"
|
|||
clap = "2.33.0"
|
||||
env_logger = "0.6.1"
|
||||
solana = { path = "../core", version = "0.13.0" }
|
||||
solana-netutil = { path = "../netutil", version = "0.13.0" }
|
||||
solana-sdk = { path = "../sdk", version = "0.13.0" }
|
||||
|
||||
[features]
|
||||
|
|
|
@ -67,8 +67,8 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||
.get_matches();
|
||||
|
||||
if let Some(addr) = matches.value_of("network") {
|
||||
network_addr = addr.parse().unwrap_or_else(|e| {
|
||||
eprintln!("failed to parse network: {}", e);
|
||||
network_addr = solana_netutil::parse_host_port(addr).unwrap_or_else(|e| {
|
||||
eprintln!("failed to parse network address: {}", e);
|
||||
exit(1)
|
||||
});
|
||||
}
|
||||
|
|
|
@ -78,19 +78,7 @@ find_leader() {
|
|||
leader_address=127.0.0.1:8001 # Default to local leader
|
||||
elif [[ -z $2 ]]; then
|
||||
leader=$1
|
||||
|
||||
declare leader_ip
|
||||
if [[ $leader =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]; then
|
||||
leader_ip=$leader
|
||||
else
|
||||
leader_ip=$(dig +short "${leader%:*}" | head -n1)
|
||||
|
||||
if [[ -z $leader_ip ]]; then
|
||||
usage "Error: unable to resolve IP address for $leader"
|
||||
fi
|
||||
fi
|
||||
|
||||
leader_address=$leader_ip:8001
|
||||
leader_address=$leader:8001
|
||||
shift=1
|
||||
else
|
||||
leader=$1
|
||||
|
|
|
@ -7,7 +7,7 @@ use rand::{thread_rng, Rng};
|
|||
use reqwest;
|
||||
use socket2::{Domain, SockAddr, Socket, Type};
|
||||
use std::io;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener, UdpSocket};
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener, ToSocketAddrs, UdpSocket};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
/// A data type representing a public Udp socket
|
||||
|
@ -70,6 +70,31 @@ pub fn parse_port_range(port_range: &str) -> Option<PortRange> {
|
|||
Some((start_port, end_port))
|
||||
}
|
||||
|
||||
pub fn parse_host(host: &str) -> Result<IpAddr, String> {
|
||||
let ips: Vec<_> = (host, 0)
|
||||
.to_socket_addrs()
|
||||
.map_err(|err| err.to_string())?
|
||||
.map(|socket_address| socket_address.ip())
|
||||
.collect();
|
||||
if ips.is_empty() {
|
||||
Err(format!("Unable to resolve host: {}", host))
|
||||
} else {
|
||||
Ok(ips[0])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_host_port(host_port: &str) -> Result<SocketAddr, String> {
|
||||
let addrs: Vec<_> = host_port
|
||||
.to_socket_addrs()
|
||||
.map_err(|err| err.to_string())?
|
||||
.collect();
|
||||
if addrs.is_empty() {
|
||||
Err(format!("Unable to resolve host: {}", host_port))
|
||||
} else {
|
||||
Ok(addrs[0])
|
||||
}
|
||||
}
|
||||
|
||||
fn find_eth0ish_ip_addr(
|
||||
ifaces: &mut Vec<datalink::NetworkInterface>,
|
||||
enable_ipv6: bool,
|
||||
|
@ -334,6 +359,22 @@ mod tests {
|
|||
assert_eq!(parse_port_range("2-1"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_host() {
|
||||
parse_host("localhost:1234").unwrap_err();
|
||||
parse_host("localhost").unwrap();
|
||||
parse_host("127.0.0.0:1234").unwrap_err();
|
||||
parse_host("127.0.0.0").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_host_port() {
|
||||
parse_host_port("localhost:1234").unwrap();
|
||||
parse_host_port("localhost").unwrap_err();
|
||||
parse_host_port("127.0.0.0:1234").unwrap();
|
||||
parse_host_port("127.0.0.0").unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bind() {
|
||||
assert_eq!(bind_in_range((2000, 2001)).unwrap().0, 2000);
|
||||
|
|
|
@ -78,7 +78,9 @@ fn main() {
|
|||
|
||||
let network_addr = matches
|
||||
.value_of("network")
|
||||
.map(|network| network.parse().expect("failed to parse network address"))
|
||||
.map(|network| {
|
||||
solana_netutil::parse_host_port(network).expect("failed to parse network address")
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let leader_info = ContactInfo::new_gossip_entry_point(&network_addr);
|
||||
|
@ -94,6 +96,5 @@ fn main() {
|
|||
.unwrap();
|
||||
|
||||
replicator.run();
|
||||
|
||||
replicator.close();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ solana-budget-api = { path = "../programs/budget_api", version = "0.13.0" }
|
|||
solana-client = { path = "../client", version = "0.13.0" }
|
||||
solana-drone = { path = "../drone", version = "0.13.0" }
|
||||
solana-logger = { path = "../logger", version = "0.13.0" }
|
||||
solana-netutil = { path = "../netutil", version = "0.13.0" }
|
||||
solana-sdk = { path = "../sdk", version = "0.13.0" }
|
||||
solana-vote-api = { path = "../programs/vote_api", version = "0.13.0" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "0.13.0" }
|
||||
|
|
|
@ -7,28 +7,31 @@ use solana_wallet::wallet::{parse_command, process_command, WalletConfig, Wallet
|
|||
use std::error;
|
||||
|
||||
pub fn parse_args(matches: &ArgMatches<'_>) -> Result<WalletConfig, Box<dyn error::Error>> {
|
||||
let host = matches
|
||||
.value_of("host")
|
||||
.unwrap()
|
||||
.parse()
|
||||
.or_else(|_| Err(WalletError::BadParameter("Invalid host".to_string())))?;
|
||||
let host = solana_netutil::parse_host(matches.value_of("host").unwrap()).or_else(|err| {
|
||||
Err(WalletError::BadParameter(format!(
|
||||
"Invalid host: {:?}",
|
||||
err
|
||||
)))
|
||||
})?;
|
||||
|
||||
let drone_host = if let Some(drone_host) = matches.value_of("drone_host") {
|
||||
Some(
|
||||
drone_host
|
||||
.parse()
|
||||
.or_else(|_| Err(WalletError::BadParameter("Invalid drone host".to_string())))?,
|
||||
)
|
||||
Some(solana_netutil::parse_host(drone_host).or_else(|err| {
|
||||
Err(WalletError::BadParameter(format!(
|
||||
"Invalid drone host: {:?}",
|
||||
err
|
||||
)))
|
||||
})?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let rpc_host = if let Some(rpc_host) = matches.value_of("rpc_host") {
|
||||
Some(
|
||||
rpc_host
|
||||
.parse()
|
||||
.or_else(|_| Err(WalletError::BadParameter("Invalid rpc host".to_string())))?,
|
||||
)
|
||||
Some(solana_netutil::parse_host(rpc_host).or_else(|err| {
|
||||
Err(WalletError::BadParameter(format!(
|
||||
"Invalid rpc host: {:?}",
|
||||
err
|
||||
)))
|
||||
})?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -37,13 +40,23 @@ pub fn parse_args(matches: &ArgMatches<'_>) -> Result<WalletConfig, Box<dyn erro
|
|||
.value_of("drone_port")
|
||||
.unwrap()
|
||||
.parse()
|
||||
.or_else(|_| Err(WalletError::BadParameter("Invalid drone port".to_string())))?;
|
||||
.or_else(|err| {
|
||||
Err(WalletError::BadParameter(format!(
|
||||
"Invalid drone port: {:?}",
|
||||
err
|
||||
)))
|
||||
})?;
|
||||
|
||||
let rpc_port = matches
|
||||
.value_of("rpc_port")
|
||||
.unwrap()
|
||||
.parse()
|
||||
.or_else(|_| Err(WalletError::BadParameter("Invalid rpc port".to_string())))?;
|
||||
.or_else(|err| {
|
||||
Err(WalletError::BadParameter(format!(
|
||||
"Invalid rpc port: {:?}",
|
||||
err
|
||||
)))
|
||||
})?;
|
||||
|
||||
let mut path = dirs::home_dir().expect("home directory");
|
||||
let id_path = if matches.is_present("keypair") {
|
||||
|
|
Loading…
Reference in New Issue