diff --git a/client/src/thin_client.rs b/client/src/thin_client.rs index e5b70b3d8e..2eb0aded17 100644 --- a/client/src/thin_client.rs +++ b/client/src/thin_client.rs @@ -16,7 +16,7 @@ use solana_sdk::packet::PACKET_DATA_SIZE; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil, Signature}; use solana_sdk::system_instruction; -use solana_sdk::timing::duration_as_ms; +use solana_sdk::timing::{duration_as_ms, MAX_PROCESSING_AGE}; use solana_sdk::transaction::{self, Transaction}; use solana_sdk::transport::Result as TransportResult; use std::io; @@ -206,17 +206,24 @@ impl ThinClient { min_confirmed_blocks: usize, ) -> io::Result { for x in 0..tries { + let now = Instant::now(); let mut buf = vec![0; serialized_size(&transaction).unwrap() as usize]; let mut wr = std::io::Cursor::new(&mut buf[..]); serialize_into(&mut wr, &transaction) .expect("serialize Transaction in pub fn transfer_signed"); - self.transactions_socket - .send_to(&buf[..], &self.transactions_addr())?; - if self - .poll_for_signature_confirmation(&transaction.signatures[0], min_confirmed_blocks) - .is_ok() - { - return Ok(transaction.signatures[0]); + // resend the same transaction until the transaction has no chance of succeeding + while now.elapsed().as_secs() < MAX_PROCESSING_AGE as u64 { + self.transactions_socket + .send_to(&buf[..], &self.transactions_addr())?; + if self + .poll_for_signature_confirmation( + &transaction.signatures[0], + min_confirmed_blocks, + ) + .is_ok() + { + return Ok(transaction.signatures[0]); + } } info!( "{} tries failed transfer to {}", diff --git a/core/src/banking_stage.rs b/core/src/banking_stage.rs index 0c08fcc6ed..d59455a5bf 100644 --- a/core/src/banking_stage.rs +++ b/core/src/banking_stage.rs @@ -22,8 +22,8 @@ use solana_runtime::locked_accounts_results::LockedAccountsResults; use solana_sdk::poh_config::PohConfig; use solana_sdk::pubkey::Pubkey; use solana_sdk::timing::{ - self, duration_as_us, DEFAULT_NUM_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT, - MAX_RECENT_BLOCKHASHES, MAX_TRANSACTION_FORWARDING_DELAY, + self, duration_as_us, DEFAULT_NUM_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT, MAX_PROCESSING_AGE, + MAX_TRANSACTION_FORWARDING_DELAY, }; use solana_sdk::transaction::{self, Transaction, TransactionError}; use std::net::UdpSocket; @@ -423,7 +423,7 @@ impl BankingStage { // TODO: Banking stage threads should be prioritized to complete faster then this queue // expires. let (loaded_accounts, results) = - bank.load_and_execute_transactions(txs, lock_results, MAX_RECENT_BLOCKHASHES / 2); + bank.load_and_execute_transactions(txs, lock_results, MAX_PROCESSING_AGE); let load_execute_time = now.elapsed(); let freeze_lock = bank.freeze_lock(); @@ -620,7 +620,7 @@ impl BankingStage { let result = bank.check_transactions( transactions, &filter, - (MAX_RECENT_BLOCKHASHES / 2) + (MAX_PROCESSING_AGE) .saturating_sub(MAX_TRANSACTION_FORWARDING_DELAY) .saturating_sub( (FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET * bank.ticks_per_slot() diff --git a/core/src/replicator.rs b/core/src/replicator.rs index 70fb65bf12..d2c05fe3a6 100644 --- a/core/src/replicator.rs +++ b/core/src/replicator.rs @@ -500,7 +500,11 @@ impl Replicator { > 0 ); // ...or no lamports for fees - assert!(client.poll_get_balance(&self.keypair.pubkey()).unwrap() > 0); + let balance = client.poll_get_balance(&self.keypair.pubkey()).unwrap(); + if balance == 0 { + error!("Unable to submit mining proof, insufficient Replicator Account balance"); + return; + } let (blockhash, _) = client.get_recent_blockhash().expect("No recent blockhash"); let instruction = storage_instruction::mining_proof( diff --git a/sdk/src/timing.rs b/sdk/src/timing.rs index 19dfd2f344..71bea4bc2c 100644 --- a/sdk/src/timing.rs +++ b/sdk/src/timing.rs @@ -26,6 +26,9 @@ pub const MAX_HASH_AGE_IN_SECONDS: usize = 120; // This must be <= MAX_HASH_AGE_IN_SECONDS, otherwise there's risk for DuplicateSignature errors pub const MAX_RECENT_BLOCKHASHES: usize = MAX_HASH_AGE_IN_SECONDS; +// The maximum age of a blockhash that will be accepted by the leader +pub const MAX_PROCESSING_AGE: usize = MAX_RECENT_BLOCKHASHES / 2; + /// This is maximum time consumed in forwarding a transaction from one node to next, before /// it can be processed in the target node #[cfg(feature = "cuda")]