|
|
@@ -0,0 +1,324 @@
|
|
|
+use {
|
|
|
+ crate::commands::{Error, FromClapArgMatches, Result},
|
|
|
+ clap::{value_t, ArgMatches},
|
|
|
+ solana_send_transaction_service::send_transaction_service::{
|
|
|
+ Config as SendTransactionServiceConfig, MAX_TRANSACTION_SENDS_PER_SECOND,
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+impl FromClapArgMatches for SendTransactionServiceConfig {
|
|
|
+ fn from_clap_arg_match(matches: &ArgMatches) -> Result<Self> {
|
|
|
+ let batch_send_rate_ms = value_t!(matches, "rpc_send_transaction_batch_ms", u64)?;
|
|
|
+ let retry_rate_ms = value_t!(matches, "rpc_send_transaction_retry_ms", u64)?;
|
|
|
+ if batch_send_rate_ms > retry_rate_ms {
|
|
|
+ return Err(Error::Dynamic(Box::<dyn std::error::Error>::from(format!(
|
|
|
+ "the specified rpc-send-batch-ms ({batch_send_rate_ms}) is invalid, it must be <= \
|
|
|
+ rpc-send-retry-ms ({retry_rate_ms})"
|
|
|
+ ))));
|
|
|
+ }
|
|
|
+
|
|
|
+ let batch_size = value_t!(matches, "rpc_send_transaction_batch_size", usize)?;
|
|
|
+ let millis_per_second = 1000;
|
|
|
+ let tps = batch_size as u64 * millis_per_second / batch_send_rate_ms;
|
|
|
+ if tps > MAX_TRANSACTION_SENDS_PER_SECOND {
|
|
|
+ return Err(Error::Dynamic(Box::<dyn std::error::Error>::from(format!(
|
|
|
+ "either the specified rpc-send-batch-size ({batch_size}) or rpc-send-batch-ms \
|
|
|
+ ({batch_send_rate_ms}) is invalid, 'rpc-send-batch-size * 1000 / \
|
|
|
+ rpc-send-batch-ms' must be smaller than ({MAX_TRANSACTION_SENDS_PER_SECOND}) .",
|
|
|
+ ))));
|
|
|
+ }
|
|
|
+
|
|
|
+ let tpu_peers = matches
|
|
|
+ .values_of("rpc_send_transaction_tpu_peer")
|
|
|
+ .map(|values| values.map(solana_net_utils::parse_host_port).collect())
|
|
|
+ .transpose()
|
|
|
+ .map_err(|e| {
|
|
|
+ Error::Dynamic(Box::<dyn std::error::Error>::from(format!(
|
|
|
+ "Invalid tpu peer address: {e}",
|
|
|
+ )))
|
|
|
+ })?;
|
|
|
+
|
|
|
+ let default_max_retries =
|
|
|
+ value_t!(matches, "rpc_send_transaction_default_max_retries", usize).ok();
|
|
|
+
|
|
|
+ let service_max_retries =
|
|
|
+ value_t!(matches, "rpc_send_transaction_service_max_retries", usize)?;
|
|
|
+
|
|
|
+ let retry_pool_max_size =
|
|
|
+ value_t!(matches, "rpc_send_transaction_retry_pool_max_size", usize)?;
|
|
|
+
|
|
|
+ let rpc_send_transaction_also_leader =
|
|
|
+ matches.is_present("rpc_send_transaction_also_leader");
|
|
|
+ let leader_forward_count = if tpu_peers.is_some() && !rpc_send_transaction_also_leader {
|
|
|
+ // rpc-sts is configured to send only to specific tpu peers. disable leader forwards
|
|
|
+ 0
|
|
|
+ } else {
|
|
|
+ value_t!(matches, "rpc_send_transaction_leader_forward_count", u64)?
|
|
|
+ };
|
|
|
+
|
|
|
+ Ok(SendTransactionServiceConfig {
|
|
|
+ retry_rate_ms,
|
|
|
+ batch_size,
|
|
|
+ batch_send_rate_ms,
|
|
|
+ default_max_retries,
|
|
|
+ service_max_retries,
|
|
|
+ retry_pool_max_size,
|
|
|
+ tpu_peers,
|
|
|
+ leader_forward_count,
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[cfg(test)]
|
|
|
+mod tests {
|
|
|
+ use {
|
|
|
+ super::*,
|
|
|
+ crate::commands::run::args::{
|
|
|
+ tests::verify_args_struct_by_command_run_with_identity_setup, RunArgs,
|
|
|
+ },
|
|
|
+ std::net::{Ipv4Addr, SocketAddr},
|
|
|
+ };
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn verify_args_struct_by_command_run_with_retry_rate_ms() {
|
|
|
+ let default_run_args = RunArgs::default();
|
|
|
+ let expected_args = RunArgs {
|
|
|
+ send_transaction_service_config: SendTransactionServiceConfig {
|
|
|
+ retry_rate_ms: 99999,
|
|
|
+ ..default_run_args.send_transaction_service_config.clone()
|
|
|
+ },
|
|
|
+ ..default_run_args.clone()
|
|
|
+ };
|
|
|
+ verify_args_struct_by_command_run_with_identity_setup(
|
|
|
+ default_run_args,
|
|
|
+ vec!["--rpc-send-retry-ms", "99999"],
|
|
|
+ expected_args,
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn verify_args_struct_by_command_run_with_batch_size() {
|
|
|
+ {
|
|
|
+ let default_run_args = RunArgs::default();
|
|
|
+ let expected_args = RunArgs {
|
|
|
+ send_transaction_service_config: SendTransactionServiceConfig {
|
|
|
+ batch_size: 1,
|
|
|
+ ..default_run_args.send_transaction_service_config.clone()
|
|
|
+ },
|
|
|
+ ..default_run_args.clone()
|
|
|
+ };
|
|
|
+ verify_args_struct_by_command_run_with_identity_setup(
|
|
|
+ default_run_args,
|
|
|
+ vec!["--rpc-send-batch-size", "1"],
|
|
|
+ expected_args,
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ let default_run_args = RunArgs::default();
|
|
|
+ let expected_args = RunArgs {
|
|
|
+ send_transaction_service_config: SendTransactionServiceConfig {
|
|
|
+ batch_size: 999,
|
|
|
+ batch_send_rate_ms: 1000,
|
|
|
+ ..default_run_args.send_transaction_service_config.clone()
|
|
|
+ },
|
|
|
+ ..default_run_args.clone()
|
|
|
+ };
|
|
|
+ verify_args_struct_by_command_run_with_identity_setup(
|
|
|
+ default_run_args,
|
|
|
+ vec![
|
|
|
+ "--rpc-send-batch-size",
|
|
|
+ "999",
|
|
|
+ "--rpc-send-batch-ms",
|
|
|
+ "1000",
|
|
|
+ ],
|
|
|
+ expected_args,
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn verify_args_struct_by_command_run_with_batch_send_rate_ms() {
|
|
|
+ let default_run_args = RunArgs::default();
|
|
|
+ let expected_args = RunArgs {
|
|
|
+ send_transaction_service_config: SendTransactionServiceConfig {
|
|
|
+ batch_send_rate_ms: 1999,
|
|
|
+ ..default_run_args.send_transaction_service_config.clone()
|
|
|
+ },
|
|
|
+ ..default_run_args.clone()
|
|
|
+ };
|
|
|
+ verify_args_struct_by_command_run_with_identity_setup(
|
|
|
+ default_run_args,
|
|
|
+ vec!["--rpc-send-batch-ms", "1999"],
|
|
|
+ expected_args,
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn verify_args_struct_by_command_run_with_default_max_retries() {
|
|
|
+ let default_run_args = RunArgs::default();
|
|
|
+ let expected_args = RunArgs {
|
|
|
+ send_transaction_service_config: SendTransactionServiceConfig {
|
|
|
+ default_max_retries: Some(9999),
|
|
|
+ ..default_run_args.send_transaction_service_config.clone()
|
|
|
+ },
|
|
|
+ ..default_run_args.clone()
|
|
|
+ };
|
|
|
+ verify_args_struct_by_command_run_with_identity_setup(
|
|
|
+ default_run_args,
|
|
|
+ vec!["--rpc-send-default-max-retries", "9999"],
|
|
|
+ expected_args,
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn verify_args_struct_by_command_run_with_service_max_retries() {
|
|
|
+ let default_run_args = RunArgs::default();
|
|
|
+ let expected_args = RunArgs {
|
|
|
+ send_transaction_service_config: SendTransactionServiceConfig {
|
|
|
+ service_max_retries: 9999,
|
|
|
+ ..default_run_args.send_transaction_service_config.clone()
|
|
|
+ },
|
|
|
+ ..default_run_args.clone()
|
|
|
+ };
|
|
|
+ verify_args_struct_by_command_run_with_identity_setup(
|
|
|
+ default_run_args,
|
|
|
+ vec!["--rpc-send-service-max-retries", "9999"],
|
|
|
+ expected_args,
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn verify_args_struct_by_command_run_with_retry_pool_max_size() {
|
|
|
+ let default_run_args = RunArgs::default();
|
|
|
+ let expected_args = RunArgs {
|
|
|
+ send_transaction_service_config: SendTransactionServiceConfig {
|
|
|
+ retry_pool_max_size: 9999,
|
|
|
+ ..default_run_args.send_transaction_service_config.clone()
|
|
|
+ },
|
|
|
+ ..default_run_args.clone()
|
|
|
+ };
|
|
|
+ verify_args_struct_by_command_run_with_identity_setup(
|
|
|
+ default_run_args,
|
|
|
+ vec!["--rpc-send-transaction-retry-pool-max-size", "9999"],
|
|
|
+ expected_args,
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn verify_args_struct_by_command_run_with_tpu_peers() {
|
|
|
+ // single tpu peer
|
|
|
+ {
|
|
|
+ let default_run_args = RunArgs::default();
|
|
|
+ let expected_args = RunArgs {
|
|
|
+ send_transaction_service_config: SendTransactionServiceConfig {
|
|
|
+ tpu_peers: Some(vec![SocketAddr::from((Ipv4Addr::LOCALHOST, 8000))]),
|
|
|
+ leader_forward_count: 0, // see SendTransactionServiceConfig::from_clap_arg_match for more details
|
|
|
+ ..default_run_args.send_transaction_service_config.clone()
|
|
|
+ },
|
|
|
+ ..default_run_args.clone()
|
|
|
+ };
|
|
|
+ verify_args_struct_by_command_run_with_identity_setup(
|
|
|
+ default_run_args,
|
|
|
+ vec!["--rpc-send-transaction-tpu-peer", "127.0.0.1:8000"],
|
|
|
+ expected_args,
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // multiple tpu peers
|
|
|
+ {
|
|
|
+ let default_run_args = RunArgs::default();
|
|
|
+ let expected_args = RunArgs {
|
|
|
+ send_transaction_service_config: SendTransactionServiceConfig {
|
|
|
+ tpu_peers: Some(vec![
|
|
|
+ SocketAddr::from((Ipv4Addr::LOCALHOST, 8000)),
|
|
|
+ SocketAddr::from((Ipv4Addr::LOCALHOST, 8001)),
|
|
|
+ SocketAddr::from((Ipv4Addr::LOCALHOST, 8002)),
|
|
|
+ ]),
|
|
|
+ leader_forward_count: 0, // see SendTransactionServiceConfig::from_clap_arg_match for more details
|
|
|
+ ..default_run_args.send_transaction_service_config.clone()
|
|
|
+ },
|
|
|
+ ..default_run_args.clone()
|
|
|
+ };
|
|
|
+ verify_args_struct_by_command_run_with_identity_setup(
|
|
|
+ default_run_args,
|
|
|
+ vec![
|
|
|
+ "--rpc-send-transaction-tpu-peer",
|
|
|
+ "127.0.0.1:8000",
|
|
|
+ "--rpc-send-transaction-tpu-peer",
|
|
|
+ "127.0.0.1:8001",
|
|
|
+ "--rpc-send-transaction-tpu-peer",
|
|
|
+ "127.0.0.1:8002",
|
|
|
+ ],
|
|
|
+ expected_args,
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn verify_args_struct_by_command_run_with_rpc_send_transaction_leader_forward_count() {
|
|
|
+ // rpc-send-transaction-leader-forward-count
|
|
|
+ {
|
|
|
+ let default_run_args = RunArgs::default();
|
|
|
+ let expected_args = RunArgs {
|
|
|
+ send_transaction_service_config: SendTransactionServiceConfig {
|
|
|
+ leader_forward_count: 100,
|
|
|
+ ..default_run_args.send_transaction_service_config.clone()
|
|
|
+ },
|
|
|
+ ..default_run_args.clone()
|
|
|
+ };
|
|
|
+ verify_args_struct_by_command_run_with_identity_setup(
|
|
|
+ default_run_args,
|
|
|
+ vec!["--rpc-send-leader-count", "100"],
|
|
|
+ expected_args,
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // rpc-send-transaction-leader-forward-count + rpc-send-transaction-tpu-peer
|
|
|
+ {
|
|
|
+ let default_run_args = RunArgs::default();
|
|
|
+ let expected_args = RunArgs {
|
|
|
+ send_transaction_service_config: SendTransactionServiceConfig {
|
|
|
+ leader_forward_count: 0,
|
|
|
+ tpu_peers: Some(vec![SocketAddr::from((Ipv4Addr::LOCALHOST, 8000))]),
|
|
|
+ ..default_run_args.send_transaction_service_config.clone()
|
|
|
+ },
|
|
|
+ ..default_run_args.clone()
|
|
|
+ };
|
|
|
+ verify_args_struct_by_command_run_with_identity_setup(
|
|
|
+ default_run_args,
|
|
|
+ vec![
|
|
|
+ "--rpc-send-transaction-tpu-peer",
|
|
|
+ "127.0.0.1:8000",
|
|
|
+ "--rpc-send-leader-count",
|
|
|
+ "100",
|
|
|
+ ],
|
|
|
+ expected_args,
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // rpc-send-transaction-leader-forward-count + rpc-send-transaction-also-leader + rpc-send-transaction-tpu-peer
|
|
|
+ {
|
|
|
+ let default_run_args = RunArgs::default();
|
|
|
+ let expected_args = RunArgs {
|
|
|
+ send_transaction_service_config: SendTransactionServiceConfig {
|
|
|
+ tpu_peers: Some(vec![SocketAddr::from((Ipv4Addr::LOCALHOST, 8000))]),
|
|
|
+ leader_forward_count: 100,
|
|
|
+ ..default_run_args.send_transaction_service_config.clone()
|
|
|
+ },
|
|
|
+ ..default_run_args.clone()
|
|
|
+ };
|
|
|
+ verify_args_struct_by_command_run_with_identity_setup(
|
|
|
+ default_run_args,
|
|
|
+ vec![
|
|
|
+ "--rpc-send-transaction-tpu-peer",
|
|
|
+ "127.0.0.1:8000",
|
|
|
+ "--rpc-send-transaction-also-leader",
|
|
|
+ "--rpc-send-leader-count",
|
|
|
+ "100",
|
|
|
+ ],
|
|
|
+ expected_args,
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|