diff --git a/cli/src/main.rs b/cli/src/main.rs index e06cd6f17..1f8ec360f 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -66,28 +66,6 @@ pub fn parse_args(matches: &ArgMatches<'_>) -> Result) -> Result Result<(), String> { fn main() -> Result<(), Box> { solana_logger::setup(); - - let default = WalletConfig::default(); - let default_drone_port = format!("{}", default.drone_port); - let matches = app(crate_name!(), crate_description!(), crate_version!()) .arg({ let arg = Arg::with_name("config_file") @@ -164,21 +136,6 @@ fn main() -> Result<(), Box> { .validator(is_url) .help("JSON RPC URL for the solana cluster"), ) - .arg( - Arg::with_name("drone_host") - .long("drone-host") - .value_name("HOST") - .takes_value(true) - .help("Drone host to use [default: same as the --url host]"), - ) - .arg( - Arg::with_name("drone_port") - .long("drone-port") - .value_name("PORT") - .takes_value(true) - .default_value(&default_drone_port) - .help("Drone port to use"), - ) .arg( Arg::with_name("keypair") .short("k") diff --git a/cli/src/wallet.rs b/cli/src/wallet.rs index a27c812bc..7e5cf217b 100644 --- a/cli/src/wallet.rs +++ b/cli/src/wallet.rs @@ -13,7 +13,6 @@ use solana_client::client_error::ClientError; use solana_client::rpc_client::RpcClient; #[cfg(not(test))] use solana_drone::drone::request_airdrop_transaction; -use solana_drone::drone::DRONE_PORT; #[cfg(test)] use solana_drone::drone_mock::request_airdrop_transaction; use solana_sdk::account_utils::State; @@ -51,7 +50,11 @@ static CROSS_MARK: Emoji = Emoji("❌ ", ""); pub enum WalletCommand { Address, Fees, - Airdrop(u64), + Airdrop { + drone_host: Option, + drone_port: u16, + lamports: u64, + }, Balance(Pubkey), Cancel(Pubkey), Confirm(Signature), @@ -120,8 +123,6 @@ impl error::Error for WalletError { pub struct WalletConfig { pub command: WalletCommand, - pub drone_host: Option, - pub drone_port: u16, pub json_rpc_url: String, pub keypair: Keypair, pub rpc_client: Option, @@ -131,8 +132,6 @@ impl Default for WalletConfig { fn default() -> WalletConfig { WalletConfig { command: WalletCommand::Balance(Pubkey::default()), - drone_host: None, - drone_port: DRONE_PORT, json_rpc_url: "http://127.0.0.1:8899".to_string(), keypair: Keypair::new(), rpc_client: None, @@ -140,24 +139,6 @@ impl Default for WalletConfig { } } -impl WalletConfig { - pub fn drone_addr(&self) -> SocketAddr { - SocketAddr::new( - self.drone_host.unwrap_or_else(|| { - let drone_host = url::Url::parse(&self.json_rpc_url) - .unwrap() - .host() - .unwrap() - .to_string(); - solana_netutil::parse_host(&drone_host).unwrap_or_else(|err| { - panic!("Unable to resolve {}: {}", drone_host, err); - }) - }), - self.drone_port, - ) - } -} - // Return parsed values from matches at `name` fn values_of(matches: &ArgMatches<'_>, name: &str) -> Option> where @@ -205,8 +186,33 @@ pub fn parse_command( ("address", Some(_address_matches)) => Ok(WalletCommand::Address), ("fees", Some(_fees_matches)) => Ok(WalletCommand::Fees), ("airdrop", Some(airdrop_matches)) => { + let drone_port = airdrop_matches + .value_of("drone_port") + .unwrap() + .parse() + .or_else(|err| { + Err(WalletError::BadParameter(format!( + "Invalid drone port: {:?}", + err + ))) + })?; + + let drone_host = if let Some(drone_host) = matches.value_of("drone_host") { + Some(solana_netutil::parse_host(drone_host).or_else(|err| { + Err(WalletError::BadParameter(format!( + "Invalid drone host: {:?}", + err + ))) + })?) + } else { + None + }; let lamports = airdrop_matches.value_of("lamports").unwrap().parse()?; - Ok(WalletCommand::Airdrop(lamports)) + Ok(WalletCommand::Airdrop { + drone_host, + drone_port, + lamports, + }) } ("balance", Some(balance_matches)) => { let pubkey = pubkey_of(&balance_matches, "pubkey").unwrap_or(*pubkey); @@ -483,7 +489,7 @@ fn process_fees(rpc_client: &RpcClient) -> ProcessResult { fn process_airdrop( rpc_client: &RpcClient, config: &WalletConfig, - drone_addr: SocketAddr, + drone_addr: &SocketAddr, lamports: u64, ) -> ProcessResult { println!( @@ -497,7 +503,7 @@ fn process_airdrop( ))?, }; - request_and_confirm_airdrop(&rpc_client, &drone_addr, &config.keypair.pubkey(), lamports)?; + request_and_confirm_airdrop(&rpc_client, drone_addr, &config.keypair.pubkey(), lamports)?; let current_balance = rpc_client .retry_get_balance(&config.keypair.pubkey(), 5)? @@ -1348,8 +1354,6 @@ pub fn process_command(config: &WalletConfig) -> ProcessResult { } println_name_value("Using RPC Endpoint:", &config.json_rpc_url); - let drone_addr = config.drone_addr(); - let mut _rpc_client; let rpc_client = if config.rpc_client.is_none() { _rpc_client = RpcClient::new(config.json_rpc_url.to_string()); @@ -1366,8 +1370,26 @@ pub fn process_command(config: &WalletConfig) -> ProcessResult { WalletCommand::Fees => process_fees(&rpc_client), // Request an airdrop from Solana Drone; - WalletCommand::Airdrop(lamports) => { - process_airdrop(&rpc_client, config, drone_addr, *lamports) + WalletCommand::Airdrop { + drone_host, + drone_port, + lamports, + } => { + let drone_addr = SocketAddr::new( + drone_host.unwrap_or_else(|| { + let drone_host = url::Url::parse(&config.json_rpc_url) + .unwrap() + .host() + .unwrap() + .to_string(); + solana_netutil::parse_host(&drone_host).unwrap_or_else(|err| { + panic!("Unable to resolve {}: {}", drone_host, err); + }) + }), + *drone_port, + ); + + process_airdrop(&rpc_client, config, &drone_addr, *lamports) } // Check client balance @@ -1660,7 +1682,23 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .subcommand(SubCommand::with_name("fees").about("Display current cluster fees")) .subcommand( SubCommand::with_name("airdrop") - .about("Request a batch of lamports") + .about("Request lamports") + .arg( + Arg::with_name("drone_host") + .long("drone-host") + .value_name("HOST") + .takes_value(true) + .help("Drone host to use [default: the --url host]"), + ) + .arg( + Arg::with_name("drone_port") + .long("drone-port") + .value_name("PORT") + .takes_value(true) + .default_value(solana_drone::drone::DRONE_PORT_STR) + .help("Drone port to use"), + ) + .arg( Arg::with_name("lamports") .index(1) @@ -2192,29 +2230,8 @@ mod tests { use solana_client::mock_rpc_client_request::SIGNATURE; use solana_sdk::signature::gen_keypair_file; use solana_sdk::transaction::TransactionError; - use std::net::{Ipv4Addr, SocketAddr}; use std::path::PathBuf; - #[test] - fn test_wallet_config_drone_addr() { - let mut config = WalletConfig::default(); - config.json_rpc_url = "http://127.0.0.1:8899".to_string(); - let rpc_host = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); - assert_eq!( - config.drone_addr(), - SocketAddr::new(rpc_host, config.drone_port) - ); - - config.drone_port = 1234; - assert_eq!(config.drone_addr(), SocketAddr::new(rpc_host, 1234)); - - config.drone_host = Some(rpc_host); - assert_eq!( - config.drone_addr(), - SocketAddr::new(config.drone_host.unwrap(), 1234) - ); - } - #[test] fn test_wallet_parse_command() { let test_commands = app("test", "desc", "version"); @@ -2233,7 +2250,11 @@ mod tests { .get_matches_from(vec!["test", "airdrop", "50"]); assert_eq!( parse_command(&pubkey, &test_airdrop).unwrap(), - WalletCommand::Airdrop(50) + WalletCommand::Airdrop { + drone_host: None, + drone_port: solana_drone::drone::DRONE_PORT, + lamports: 50 + } ); let test_bad_airdrop = test_commands .clone() @@ -2654,7 +2675,11 @@ mod tests { assert_eq!(signature.unwrap(), SIGNATURE.to_string()); // Need airdrop cases - config.command = WalletCommand::Airdrop(50); + config.command = WalletCommand::Airdrop { + drone_host: None, + drone_port: 1234, + lamports: 50, + }; assert!(process_command(&config).is_ok()); config.rpc_client = Some(RpcClient::new_mock("airdrop".to_string())); @@ -2688,7 +2713,11 @@ mod tests { // Failure cases config.rpc_client = Some(RpcClient::new_mock("fails".to_string())); - config.command = WalletCommand::Airdrop(50); + config.command = WalletCommand::Airdrop { + drone_host: None, + drone_port: 1234, + lamports: 50, + }; assert!(process_command(&config).is_err()); config.command = WalletCommand::Balance(config.keypair.pubkey()); diff --git a/cli/tests/deploy.rs b/cli/tests/deploy.rs index aa3e0d402..5450d1702 100644 --- a/cli/tests/deploy.rs +++ b/cli/tests/deploy.rs @@ -29,9 +29,12 @@ fn test_wallet_deploy_program() { let rpc_client = RpcClient::new_socket(leader_data.rpc); let mut config = WalletConfig::default(); - config.drone_port = drone_addr.port(); config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port()); - config.command = WalletCommand::Airdrop(50); + config.command = WalletCommand::Airdrop { + drone_host: None, + drone_port: drone_addr.port(), + lamports: 50, + }; process_command(&config).unwrap(); config.command = WalletCommand::Deploy(pathbuf.to_str().unwrap().to_string()); diff --git a/cli/tests/pay.rs b/cli/tests/pay.rs index 8961e3d21..e83a334cc 100644 --- a/cli/tests/pay.rs +++ b/cli/tests/pay.rs @@ -40,12 +40,10 @@ fn test_wallet_timestamp_tx() { let rpc_client = RpcClient::new_socket(leader_data.rpc); let mut config_payer = WalletConfig::default(); - config_payer.drone_port = drone_addr.port(); config_payer.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port()); let mut config_witness = WalletConfig::default(); - config_witness.drone_port = config_payer.drone_port; config_witness.json_rpc_url = config_payer.json_rpc_url.clone(); assert_ne!( @@ -113,12 +111,10 @@ fn test_wallet_witness_tx() { let rpc_client = RpcClient::new_socket(leader_data.rpc); let mut config_payer = WalletConfig::default(); - config_payer.drone_port = drone_addr.port(); config_payer.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port()); let mut config_witness = WalletConfig::default(); - config_witness.drone_port = config_payer.drone_port; config_witness.json_rpc_url = config_payer.json_rpc_url.clone(); assert_ne!( @@ -182,12 +178,10 @@ fn test_wallet_cancel_tx() { let rpc_client = RpcClient::new_socket(leader_data.rpc); let mut config_payer = WalletConfig::default(); - config_payer.drone_port = drone_addr.port(); config_payer.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port()); let mut config_witness = WalletConfig::default(); - config_witness.drone_port = config_payer.drone_port; config_witness.json_rpc_url = config_payer.json_rpc_url.clone(); assert_ne!( diff --git a/cli/tests/request_airdrop.rs b/cli/tests/request_airdrop.rs index deb19d3f5..da56a227a 100644 --- a/cli/tests/request_airdrop.rs +++ b/cli/tests/request_airdrop.rs @@ -14,10 +14,12 @@ fn test_wallet_request_airdrop() { let drone_addr = receiver.recv().unwrap(); let mut bob_config = WalletConfig::default(); - bob_config.drone_port = drone_addr.port(); bob_config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port()); - - bob_config.command = WalletCommand::Airdrop(50); + bob_config.command = WalletCommand::Airdrop { + drone_host: None, + drone_port: drone_addr.port(), + lamports: 50, + }; let sig_response = process_command(&bob_config); sig_response.unwrap(); diff --git a/drone/src/drone.rs b/drone/src/drone.rs index 17048d36f..8fa863ed7 100644 --- a/drone/src/drone.rs +++ b/drone/src/drone.rs @@ -43,6 +43,7 @@ macro_rules! socketaddr { pub const TIME_SLICE: u64 = 60; pub const REQUEST_CAP: u64 = 100_000_000_000_000; pub const DRONE_PORT: u16 = 9900; +pub const DRONE_PORT_STR: &str = "9900"; #[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub enum DroneRequest {