diff --git a/faucet/src/faucet.rs b/faucet/src/faucet.rs index e23f1142c..c38dc8d43 100644 --- a/faucet/src/faucet.rs +++ b/faucet/src/faucet.rs @@ -330,16 +330,18 @@ pub fn request_airdrop_transaction( pub fn run_local_faucet_with_port( faucet_keypair: Keypair, sender: Sender>, + time_input: Option, per_time_cap: Option, + per_request_cap: Option, port: u16, // 0 => auto assign ) { thread::spawn(move || { let faucet_addr = socketaddr!(0, port); let faucet = Arc::new(Mutex::new(Faucet::new( faucet_keypair, - None, + time_input, per_time_cap, - None, + per_request_cap, ))); let runtime = Runtime::new().unwrap(); runtime.block_on(run_faucet(faucet, faucet_addr, Some(sender))); @@ -349,7 +351,7 @@ pub fn run_local_faucet_with_port( // For integration tests. Listens on random open port and reports port to Sender. pub fn run_local_faucet(faucet_keypair: Keypair, per_time_cap: Option) -> SocketAddr { let (sender, receiver) = unbounded(); - run_local_faucet_with_port(faucet_keypair, sender, per_time_cap, 0); + run_local_faucet_with_port(faucet_keypair, sender, None, per_time_cap, None, 0); receiver .recv() .expect("run_local_faucet") diff --git a/validator/src/bin/solana-test-validator.rs b/validator/src/bin/solana-test-validator.rs index 148bd047d..7f1610b1e 100644 --- a/validator/src/bin/solana-test-validator.rs +++ b/validator/src/bin/solana-test-validator.rs @@ -177,10 +177,7 @@ fn main() { }); let compute_unit_limit = value_t!(matches, "compute_unit_limit", u64).ok(); - let faucet_addr = Some(SocketAddr::new( - IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), - faucet_port, - )); + let faucet_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), faucet_port); let mut programs_to_load = vec![]; if let Some(values) = matches.values_of("bpf_program") { @@ -296,14 +293,27 @@ fn main() { }); let faucet_pubkey = faucet_keypair.pubkey(); - if let Some(faucet_addr) = &faucet_addr { - let (sender, receiver) = unbounded(); - run_local_faucet_with_port(faucet_keypair, sender, None, faucet_addr.port()); - let _ = receiver.recv().expect("run faucet").unwrap_or_else(|err| { - println!("Error: failed to start faucet: {err}"); - exit(1); - }); - } + let faucet_time_slice_secs = value_t_or_exit!(matches, "faucet_time_slice_secs", u64); + let faucet_per_time_cap = value_t!(matches, "faucet_per_time_sol_cap", f64) + .ok() + .map(sol_to_lamports); + let faucet_per_request_cap = value_t!(matches, "faucet_per_request_sol_cap", f64) + .ok() + .map(sol_to_lamports); + + let (sender, receiver) = unbounded(); + run_local_faucet_with_port( + faucet_keypair, + sender, + Some(faucet_time_slice_secs), + faucet_per_time_cap, + faucet_per_request_cap, + faucet_addr.port(), + ); + let _ = receiver.recv().expect("run faucet").unwrap_or_else(|err| { + println!("Error: failed to start faucet: {err}"); + exit(1); + }); let features_to_deactivate = pubkeys_of(&matches, "deactivate_feature").unwrap_or_default(); @@ -413,7 +423,7 @@ fn main() { enable_rpc_transaction_history: true, enable_extended_tx_metadata_storage: true, rpc_bigtable_config, - faucet_addr, + faucet_addr: Some(faucet_addr), account_indexes, ..JsonRpcConfig::default_for_test() }); diff --git a/validator/src/cli.rs b/validator/src/cli.rs index 07b7303d3..103809937 100644 --- a/validator/src/cli.rs +++ b/validator/src/cli.rs @@ -10,7 +10,7 @@ use { }, keypair::SKIP_SEED_PHRASE_VALIDATION_ARG, }, - solana_faucet::faucet::FAUCET_PORT, + solana_faucet::faucet::{self, FAUCET_PORT}, solana_net_utils::{MINIMUM_VALIDATOR_PORT_RANGE_WIDTH, VALIDATOR_PORT_RANGE}, solana_rpc::{rpc::MAX_REQUEST_BODY_SIZE, rpc_pubsub_service::PubSubConfig}, solana_rpc_client_api::request::MAX_MULTIPLE_ACCOUNTS, @@ -2164,6 +2164,38 @@ pub fn test_app<'a>(version: &'a str, default_args: &'a DefaultTestArgs) -> App< If the ledger already exists then this parameter is silently ignored", ), ) + .arg( + Arg::with_name("faucet_time_slice_secs") + .long("faucet-time-slice-secs") + .takes_value(true) + .value_name("SECS") + .default_value(default_args.faucet_time_slice_secs.as_str()) + .help( + "Time slice (in secs) over which to limit faucet requests", + ), + ) + .arg( + Arg::with_name("faucet_per_time_sol_cap") + .long("faucet-per-time-sol-cap") + .takes_value(true) + .value_name("SOL") + .min_values(0) + .max_values(1) + .help( + "Per-time slice limit for faucet requests, in SOL", + ), + ) + .arg( + Arg::with_name("faucet_per_request_sol_cap") + .long("faucet-per-request-sol-cap") + .takes_value(true) + .value_name("SOL") + .min_values(0) + .max_values(1) + .help( + "Per-request limit for faucet requests, in SOL", + ), + ) .arg( Arg::with_name("geyser_plugin_config") .long("geyser-plugin-config") @@ -2214,6 +2246,7 @@ pub struct DefaultTestArgs { pub faucet_port: String, pub limit_ledger_size: String, pub faucet_sol: String, + pub faucet_time_slice_secs: String, } impl DefaultTestArgs { @@ -2227,6 +2260,7 @@ impl DefaultTestArgs { */ limit_ledger_size: 10_000.to_string(), faucet_sol: (1_000_000.).to_string(), + faucet_time_slice_secs: (faucet::TIME_SLICE).to_string(), } } }