From 7db3aecc3a82e20b0bfb75c8c5932f655624eabc Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Tue, 29 Jun 2021 15:14:18 -0600 Subject: [PATCH 1/5] Tidying: relocate function --- client/src/rpc_client.rs | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index e4fb5ffc6f472e..ac77de10ca7ca8 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -55,26 +55,6 @@ pub struct RpcClient { node_version: RwLock>, } -fn serialize_encode_transaction( - transaction: &Transaction, - encoding: UiTransactionEncoding, -) -> ClientResult { - let serialized = serialize(transaction) - .map_err(|e| ClientErrorKind::Custom(format!("transaction serialization failed: {}", e)))?; - let encoded = match encoding { - UiTransactionEncoding::Base58 => bs58::encode(serialized).into_string(), - UiTransactionEncoding::Base64 => base64::encode(serialized), - _ => { - return Err(ClientErrorKind::Custom(format!( - "unsupported transaction encoding: {}. Supported encodings: base58, base64", - encoding - )) - .into()) - } - }; - Ok(encoded) -} - impl RpcClient { fn new_sender( sender: T, @@ -1933,6 +1913,26 @@ impl RpcClient { } } +fn serialize_encode_transaction( + transaction: &Transaction, + encoding: UiTransactionEncoding, +) -> ClientResult { + let serialized = serialize(transaction) + .map_err(|e| ClientErrorKind::Custom(format!("transaction serialization failed: {}", e)))?; + let encoded = match encoding { + UiTransactionEncoding::Base58 => bs58::encode(serialized).into_string(), + UiTransactionEncoding::Base64 => base64::encode(serialized), + _ => { + return Err(ClientErrorKind::Custom(format!( + "unsupported transaction encoding: {}. Supported encodings: base58, base64", + encoding + )) + .into()) + } + }; + Ok(encoded) +} + #[derive(Debug, Default)] pub struct GetConfirmedSignaturesForAddress2Config { pub before: Option, From 861ec3f1587cf090ec36a409d72426d56bbf4e96 Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Tue, 29 Jun 2021 15:22:33 -0600 Subject: [PATCH 2/5] Use proper helper method for RpcClient commitment --- client/src/rpc_client.rs | 55 ++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index ac77de10ca7ca8..2f0f4ec70521cf 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -181,7 +181,7 @@ impl RpcClient { pub fn confirm_transaction(&self, signature: &Signature) -> ClientResult { Ok(self - .confirm_transaction_with_commitment(signature, self.commitment_config)? + .confirm_transaction_with_commitment(signature, self.commitment())? .value) } @@ -207,8 +207,7 @@ impl RpcClient { transaction, RpcSendTransactionConfig { preflight_commitment: Some( - self.maybe_map_commitment(self.commitment_config)? - .commitment, + self.maybe_map_commitment(self.commitment())?.commitment, ), ..RpcSendTransactionConfig::default() }, @@ -297,7 +296,7 @@ impl RpcClient { self.simulate_transaction_with_config( transaction, RpcSimulateTransactionConfig { - commitment: Some(self.commitment_config), + commitment: Some(self.commitment()), ..RpcSimulateTransactionConfig::default() }, ) @@ -335,7 +334,7 @@ impl RpcClient { &self, signature: &Signature, ) -> ClientResult>> { - self.get_signature_status_with_commitment(signature, self.commitment_config) + self.get_signature_status_with_commitment(signature, self.commitment()) } pub fn get_signature_statuses( @@ -393,7 +392,7 @@ impl RpcClient { } pub fn get_slot(&self) -> ClientResult { - self.get_slot_with_commitment(self.commitment_config) + self.get_slot_with_commitment(self.commitment()) } pub fn get_slot_with_commitment( @@ -407,7 +406,7 @@ impl RpcClient { } pub fn get_block_height(&self) -> ClientResult { - self.get_block_height_with_commitment(self.commitment_config) + self.get_block_height_with_commitment(self.commitment()) } pub fn get_block_height_with_commitment( @@ -461,14 +460,14 @@ impl RpcClient { stake_account.to_string(), RpcEpochConfig { epoch, - commitment: Some(self.commitment_config), + commitment: Some(self.commitment()), } ]), ) } pub fn supply(&self) -> RpcResult { - self.supply_with_commitment(self.commitment_config) + self.supply_with_commitment(self.commitment()) } pub fn supply_with_commitment( @@ -495,7 +494,7 @@ impl RpcClient { } pub fn get_vote_accounts(&self) -> ClientResult { - self.get_vote_accounts_with_commitment(self.commitment_config) + self.get_vote_accounts_with_commitment(self.commitment()) } pub fn get_vote_accounts_with_commitment( @@ -872,7 +871,7 @@ impl RpcClient { } pub fn get_epoch_info(&self) -> ClientResult { - self.get_epoch_info_with_commitment(self.commitment_config) + self.get_epoch_info_with_commitment(self.commitment()) } pub fn get_epoch_info_with_commitment( @@ -889,7 +888,7 @@ impl RpcClient { &self, slot: Option, ) -> ClientResult> { - self.get_leader_schedule_with_commitment(slot, self.commitment_config) + self.get_leader_schedule_with_commitment(slot, self.commitment()) } pub fn get_leader_schedule_with_commitment( @@ -959,7 +958,7 @@ impl RpcClient { addresses, RpcEpochConfig { epoch, - commitment: Some(self.commitment_config), + commitment: Some(self.commitment()), } ]), ) @@ -1025,7 +1024,7 @@ impl RpcClient { /// Note that `get_account` returns `Err(..)` if the account does not exist whereas /// `get_account_with_commitment` returns `Ok(None)` if the account does not exist. pub fn get_account(&self, pubkey: &Pubkey) -> ClientResult { - self.get_account_with_commitment(pubkey, self.commitment_config)? + self.get_account_with_commitment(pubkey, self.commitment())? .value .ok_or_else(|| RpcError::ForUser(format!("AccountNotFound: pubkey={}", pubkey)).into()) } @@ -1081,7 +1080,7 @@ impl RpcClient { pub fn get_multiple_accounts(&self, pubkeys: &[Pubkey]) -> ClientResult>> { Ok(self - .get_multiple_accounts_with_commitment(pubkeys, self.commitment_config)? + .get_multiple_accounts_with_commitment(pubkeys, self.commitment())? .value) } @@ -1135,7 +1134,7 @@ impl RpcClient { /// Request the balance of the account `pubkey`. pub fn get_balance(&self, pubkey: &Pubkey) -> ClientResult { Ok(self - .get_balance_with_commitment(pubkey, self.commitment_config)? + .get_balance_with_commitment(pubkey, self.commitment())? .value) } @@ -1193,7 +1192,7 @@ impl RpcClient { /// Request the transaction count. pub fn get_transaction_count(&self) -> ClientResult { - self.get_transaction_count_with_commitment(self.commitment_config) + self.get_transaction_count_with_commitment(self.commitment()) } pub fn get_transaction_count_with_commitment( @@ -1208,7 +1207,7 @@ impl RpcClient { pub fn get_recent_blockhash(&self) -> ClientResult<(Hash, FeeCalculator)> { let (blockhash, fee_calculator, _last_valid_slot) = self - .get_recent_blockhash_with_commitment(self.commitment_config)? + .get_recent_blockhash_with_commitment(self.commitment())? .value; Ok((blockhash, fee_calculator)) } @@ -1281,7 +1280,7 @@ impl RpcClient { blockhash: &Hash, ) -> ClientResult> { Ok(self - .get_fee_calculator_for_blockhash_with_commitment(blockhash, self.commitment_config)? + .get_fee_calculator_for_blockhash_with_commitment(blockhash, self.commitment())? .value) } @@ -1363,7 +1362,7 @@ impl RpcClient { pub fn get_token_account(&self, pubkey: &Pubkey) -> ClientResult> { Ok(self - .get_token_account_with_commitment(pubkey, self.commitment_config)? + .get_token_account_with_commitment(pubkey, self.commitment())? .value) } @@ -1424,7 +1423,7 @@ impl RpcClient { pub fn get_token_account_balance(&self, pubkey: &Pubkey) -> ClientResult { Ok(self - .get_token_account_balance_with_commitment(pubkey, self.commitment_config)? + .get_token_account_balance_with_commitment(pubkey, self.commitment())? .value) } @@ -1451,7 +1450,7 @@ impl RpcClient { .get_token_accounts_by_delegate_with_commitment( delegate, token_account_filter, - self.commitment_config, + self.commitment(), )? .value) } @@ -1490,7 +1489,7 @@ impl RpcClient { .get_token_accounts_by_owner_with_commitment( owner, token_account_filter, - self.commitment_config, + self.commitment(), )? .value) } @@ -1522,7 +1521,7 @@ impl RpcClient { pub fn get_token_supply(&self, mint: &Pubkey) -> ClientResult { Ok(self - .get_token_supply_with_commitment(mint, self.commitment_config)? + .get_token_supply_with_commitment(mint, self.commitment())? .value) } @@ -1545,7 +1544,7 @@ impl RpcClient { pubkey, lamports, RpcRequestAirdropConfig { - commitment: Some(self.commitment_config), + commitment: Some(self.commitment()), ..RpcRequestAirdropConfig::default() }, ) @@ -1561,7 +1560,7 @@ impl RpcClient { pubkey, lamports, RpcRequestAirdropConfig { - commitment: Some(self.commitment_config), + commitment: Some(self.commitment()), recent_blockhash: Some(recent_blockhash.to_string()), }, ) @@ -1664,7 +1663,7 @@ impl RpcClient { /// Poll the server to confirm a transaction. pub fn poll_for_signature(&self, signature: &Signature) -> ClientResult<()> { - self.poll_for_signature_with_commitment(signature, self.commitment_config) + self.poll_for_signature_with_commitment(signature, self.commitment()) } /// Poll the server to confirm a transaction. @@ -1774,7 +1773,7 @@ impl RpcClient { ) -> ClientResult { self.send_and_confirm_transaction_with_spinner_and_commitment( transaction, - self.commitment_config, + self.commitment(), ) } From 14d07c7f2b7847059ea2ded17146f20398946527 Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Tue, 29 Jun 2021 15:25:39 -0600 Subject: [PATCH 3/5] Add RpcClientConfig --- client/src/rpc_client.rs | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index 2f0f4ec70521cf..24e73df6136d70 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -49,21 +49,31 @@ use { }, }; +pub struct RpcClientConfig { + commitment_config: CommitmentConfig, +} + +impl RpcClientConfig { + fn with_commitment(commitment_config: CommitmentConfig) -> Self { + RpcClientConfig { commitment_config } + } +} + pub struct RpcClient { sender: Box, - commitment_config: CommitmentConfig, + config: RpcClientConfig, node_version: RwLock>, } impl RpcClient { fn new_sender( sender: T, - commitment_config: CommitmentConfig, + config: RpcClientConfig, ) -> Self { Self { sender: Box::new(sender), node_version: RwLock::new(None), - commitment_config, + config, } } @@ -72,13 +82,16 @@ impl RpcClient { } pub fn new_with_commitment(url: String, commitment_config: CommitmentConfig) -> Self { - Self::new_sender(HttpSender::new(url), commitment_config) + Self::new_sender( + HttpSender::new(url), + RpcClientConfig::with_commitment(commitment_config), + ) } pub fn new_with_timeout(url: String, timeout: Duration) -> Self { Self::new_sender( HttpSender::new_with_timeout(url, timeout), - CommitmentConfig::default(), + RpcClientConfig::with_commitment(CommitmentConfig::default()), ) } @@ -89,18 +102,21 @@ impl RpcClient { ) -> Self { Self::new_sender( HttpSender::new_with_timeout(url, timeout), - commitment_config, + RpcClientConfig::with_commitment(commitment_config), ) } pub fn new_mock(url: String) -> Self { - Self::new_sender(MockSender::new(url), CommitmentConfig::default()) + Self::new_sender( + MockSender::new(url), + RpcClientConfig::with_commitment(CommitmentConfig::default()), + ) } pub fn new_mock_with_mocks(url: String, mocks: Mocks) -> Self { Self::new_sender( MockSender::new_with_mocks(url, mocks), - CommitmentConfig::default(), + RpcClientConfig::with_commitment(CommitmentConfig::default()), ) } @@ -139,7 +155,7 @@ impl RpcClient { } pub fn commitment(&self) -> CommitmentConfig { - self.commitment_config + self.config.commitment_config } fn use_deprecated_commitment(&self) -> Result { From f155dfd569cf6d51ceb3fd92858c99b33dcc334f Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Tue, 29 Jun 2021 15:44:20 -0600 Subject: [PATCH 4/5] Add configurable confirm_transaction_initial_timeout --- client/src/rpc_client.rs | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index 24e73df6136d70..207ccef5bcf110 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -49,13 +49,18 @@ use { }, }; +#[derive(Default)] pub struct RpcClientConfig { commitment_config: CommitmentConfig, + confirm_transaction_initial_timeout: Option, } impl RpcClientConfig { fn with_commitment(commitment_config: CommitmentConfig) -> Self { - RpcClientConfig { commitment_config } + RpcClientConfig { + commitment_config, + ..Self::default() + } } } @@ -106,6 +111,21 @@ impl RpcClient { ) } + pub fn new_with_timeouts_and_commitment( + url: String, + timeout: Duration, + commitment_config: CommitmentConfig, + confirm_transaction_initial_timeout: Duration, + ) -> Self { + Self::new_sender( + HttpSender::new_with_timeout(url, timeout), + RpcClientConfig { + commitment_config, + confirm_transaction_initial_timeout: Some(confirm_transaction_initial_timeout), + }, + ) + } + pub fn new_mock(url: String) -> Self { Self::new_sender( MockSender::new(url), @@ -1845,19 +1865,25 @@ impl RpcClient { "[{}/{}] Finalizing transaction {}", confirmations, desired_confirmations, signature, )); + + let now = Instant::now(); + let confirm_transaction_initial_timeout = self + .config + .confirm_transaction_initial_timeout + .unwrap_or_default(); let (signature, status) = loop { // Get recent commitment in order to count confirmations for successful transactions let status = self .get_signature_status_with_commitment(signature, CommitmentConfig::processed())?; if status.is_none() { - if self + let blockhash_not_found = self .get_fee_calculator_for_blockhash_with_commitment( recent_blockhash, CommitmentConfig::processed(), )? .value - .is_none() - { + .is_none(); + if blockhash_not_found && now.elapsed() >= confirm_transaction_initial_timeout { break (signature, status); } } else { From 7e747f0f80c2fc339375e8546ec743481db16727 Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Tue, 29 Jun 2021 15:45:59 -0600 Subject: [PATCH 5/5] Use default 5s timeout for initial tx confirmation --- cli/src/cli.rs | 8 +++++++- cli/src/main.rs | 18 +++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 2f6ddf0a1c861e..0eb12bc6242bce 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -63,6 +63,7 @@ use std::{ use thiserror::Error; pub const DEFAULT_RPC_TIMEOUT_SECONDS: &str = "30"; +pub const DEFAULT_CONFIRM_TX_TIMEOUT_SECONDS: &str = "5"; #[derive(Debug, PartialEq)] #[allow(clippy::large_enum_variant)] @@ -453,6 +454,7 @@ pub struct CliConfig<'a> { pub output_format: OutputFormat, pub commitment: CommitmentConfig, pub send_transaction_config: RpcSendTransactionConfig, + pub confirm_transaction_initial_timeout: Duration, pub address_labels: HashMap, } @@ -597,6 +599,9 @@ impl Default for CliConfig<'_> { output_format: OutputFormat::Display, commitment: CommitmentConfig::confirmed(), send_transaction_config: RpcSendTransactionConfig::default(), + confirm_transaction_initial_timeout: Duration::from_secs( + u64::from_str(DEFAULT_CONFIRM_TX_TIMEOUT_SECONDS).unwrap(), + ), address_labels: HashMap::new(), } } @@ -1288,10 +1293,11 @@ pub fn process_command(config: &CliConfig) -> ProcessResult { } let rpc_client = if config.rpc_client.is_none() { - Arc::new(RpcClient::new_with_timeout_and_commitment( + Arc::new(RpcClient::new_with_timeouts_and_commitment( config.json_rpc_url.to_string(), config.rpc_timeout, config.commitment, + config.confirm_transaction_initial_timeout, )) } else { // Primarily for testing diff --git a/cli/src/main.rs b/cli/src/main.rs index 732f9dbc2e0d97..a6e91adad43371 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -10,7 +10,7 @@ use solana_clap_utils::{ }; use solana_cli::cli::{ app, parse_command, process_command, CliCommandInfo, CliConfig, SettingType, - DEFAULT_RPC_TIMEOUT_SECONDS, + DEFAULT_CONFIRM_TX_TIMEOUT_SECONDS, DEFAULT_RPC_TIMEOUT_SECONDS, }; use solana_cli_config::{Config, CONFIG_FILE}; use solana_cli_output::{display::println_name_value, OutputFormat}; @@ -167,6 +167,11 @@ pub fn parse_args<'a>( let rpc_timeout = value_t_or_exit!(matches, "rpc_timeout", u64); let rpc_timeout = Duration::from_secs(rpc_timeout); + let confirm_transaction_initial_timeout = + value_t_or_exit!(matches, "confirm_transaction_initial_timeout", u64); + let confirm_transaction_initial_timeout = + Duration::from_secs(confirm_transaction_initial_timeout); + let (_, websocket_url) = CliConfig::compute_websocket_url_setting( matches.value_of("websocket_url").unwrap_or(""), &config.websocket_url, @@ -235,6 +240,7 @@ pub fn parse_args<'a>( preflight_commitment: Some(commitment.commitment), ..RpcSendTransactionConfig::default() }, + confirm_transaction_initial_timeout, address_labels, }, signers, @@ -350,6 +356,16 @@ fn main() -> Result<(), Box> { .hidden(true) .help("Timeout value for RPC requests"), ) + .arg( + Arg::with_name("confirm_transaction_initial_timeout") + .long("confirm-timeout") + .value_name("SECONDS") + .takes_value(true) + .default_value(DEFAULT_CONFIRM_TX_TIMEOUT_SECONDS) + .global(true) + .hidden(true) + .help("Timeout value for initial transaction status"), + ) .subcommand( SubCommand::with_name("config") .about("Solana command-line tool configuration settings")