diff --git a/banks-client/src/lib.rs b/banks-client/src/lib.rs index 0aa1304e4c..59ca0dbfa3 100644 --- a/banks-client/src/lib.rs +++ b/banks-client/src/lib.rs @@ -61,6 +61,10 @@ impl BanksClient { self.inner.send_transaction_with_context(ctx, transaction) } + #[deprecated( + since = "1.9.0", + note = "Please use `get_fee_for_message` or `is_blockhash_valid` instead" + )] pub fn get_fees_with_commitment_and_context( &mut self, ctx: Context, @@ -129,9 +133,14 @@ impl BanksClient { /// Return the fee parameters associated with a recent, rooted blockhash. The cluster /// will use the transaction's blockhash to look up these same fee parameters and /// use them to calculate the transaction fee. + #[deprecated( + since = "1.9.0", + note = "Please use `get_fee_for_message` or `is_blockhash_valid` instead" + )] pub fn get_fees( &mut self, ) -> impl Future> + '_ { + #[allow(deprecated)] self.get_fees_with_commitment_and_context(context::current(), CommitmentLevel::default()) } @@ -153,8 +162,9 @@ impl BanksClient { /// Return a recent, rooted blockhash from the server. The cluster will only accept /// transactions with a blockhash that has not yet expired. Use the `get_fees` /// method to get both a blockhash and the blockhash's last valid slot. + #[deprecated(since = "1.9.0", note = "Please use `get_latest_blockhash` instead")] pub fn get_recent_blockhash(&mut self) -> impl Future> + '_ { - self.get_fees().map(|result| Ok(result?.1)) + self.get_latest_blockhash() } /// Send a transaction and return after the transaction has been rejected or @@ -315,6 +325,31 @@ impl BanksClient { statuses.into_iter().collect() } + pub fn get_latest_blockhash(&mut self) -> impl Future> + '_ { + self.get_latest_blockhash_with_commitment(CommitmentLevel::default()) + .map(|result| { + result? + .map(|x| x.0) + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "account not found")) + }) + } + + pub fn get_latest_blockhash_with_commitment( + &mut self, + commitment: CommitmentLevel, + ) -> impl Future>> + '_ { + self.get_latest_blockhash_with_commitment_and_context(context::current(), commitment) + } + + pub fn get_latest_blockhash_with_commitment_and_context( + &mut self, + ctx: Context, + commitment: CommitmentLevel, + ) -> impl Future>> + '_ { + self.inner + .get_latest_blockhash_with_commitment_and_context(ctx, commitment) + } + pub fn get_fee_for_message_with_commitment_and_context( &mut self, ctx: Context, @@ -386,7 +421,7 @@ mod tests { .await; let mut banks_client = start_client(client_transport).await?; - let recent_blockhash = banks_client.get_recent_blockhash().await?; + let recent_blockhash = banks_client.get_latest_blockhash().await?; let transaction = Transaction::new(&[&genesis.mint_keypair], message, recent_blockhash); banks_client.process_transaction(transaction).await.unwrap(); assert_eq!(banks_client.get_balance(bob_pubkey).await?, 1); @@ -418,7 +453,10 @@ mod tests { start_local_server(bank_forks, block_commitment_cache, Duration::from_millis(1)) .await; let mut banks_client = start_client(client_transport).await?; - let (_, recent_blockhash, last_valid_block_height) = banks_client.get_fees().await?; + let (recent_blockhash, last_valid_block_height) = banks_client + .get_latest_blockhash_with_commitment(CommitmentLevel::default()) + .await? + .unwrap(); let transaction = Transaction::new(&[&genesis.mint_keypair], message, recent_blockhash); let signature = transaction.signatures[0]; banks_client.send_transaction(transaction).await?; diff --git a/banks-interface/src/lib.rs b/banks-interface/src/lib.rs index d8562d9f23..c4fe2549df 100644 --- a/banks-interface/src/lib.rs +++ b/banks-interface/src/lib.rs @@ -52,6 +52,10 @@ pub trait Banks { address: Pubkey, commitment: CommitmentLevel, ) -> Option; + async fn get_latest_blockhash_with_context() -> Hash; + async fn get_latest_blockhash_with_commitment_and_context( + commitment: CommitmentLevel, + ) -> Option<(Hash, u64)>; async fn get_fee_for_message_with_commitment_and_context( commitment: CommitmentLevel, message: Message, diff --git a/banks-server/src/banks_server.rs b/banks-server/src/banks_server.rs index b3ae852dc9..84f37d38c0 100644 --- a/banks-server/src/banks_server.rs +++ b/banks-server/src/banks_server.rs @@ -281,6 +281,22 @@ impl Banks for BanksServer { bank.get_account(&address).map(Account::from) } + async fn get_latest_blockhash_with_context(self, _: Context) -> Hash { + let bank = self.bank(CommitmentLevel::default()); + bank.last_blockhash() + } + + async fn get_latest_blockhash_with_commitment_and_context( + self, + _: Context, + commitment: CommitmentLevel, + ) -> Option<(Hash, u64)> { + let bank = self.bank(commitment); + let blockhash = bank.last_blockhash(); + let last_valid_block_height = bank.get_blockhash_last_valid_block_height(&blockhash)?; + Some((blockhash, last_valid_block_height)) + } + async fn get_fee_for_message_with_commitment_and_context( self, _: Context, diff --git a/program-test/src/lib.rs b/program-test/src/lib.rs index ad193f6705..f037181339 100644 --- a/program-test/src/lib.rs +++ b/program-test/src/lib.rs @@ -25,7 +25,7 @@ use { entrypoint::{ProgramResult, SUCCESS}, epoch_schedule::EpochSchedule, feature_set::demote_program_write_locks, - fee_calculator::FeeRateGovernor, + fee_calculator::{FeeCalculator, FeeRateGovernor}, genesis_config::{ClusterType, GenesisConfig}, hash::Hash, instruction::Instruction, @@ -880,24 +880,30 @@ impl ProgramTest { } } -// TODO need to return lamports_per_signature? #[async_trait] pub trait ProgramTestBanksClientExt { - async fn get_new_blockhash(&mut self, blockhash: &Hash) -> io::Result<(Hash, u64)>; + /// Get a new blockhash, similar in spirit to RpcClient::get_new_blockhash() + /// + /// This probably should eventually be moved into BanksClient proper in some form + #[deprecated( + since = "1.9.0", + note = "Please use `get_new_latest_blockhash `instead" + )] + async fn get_new_blockhash(&mut self, blockhash: &Hash) -> io::Result<(Hash, FeeCalculator)>; + /// Get a new latest blockhash, similar in spirit to RpcClient::get_latest_blockhash() + async fn get_new_latest_blockhash(&mut self, blockhash: &Hash) -> io::Result; } #[async_trait] impl ProgramTestBanksClientExt for BanksClient { - /// Get a new blockhash, similar in spirit to RpcClient::get_new_blockhash() - /// - /// This probably should eventually be moved into BanksClient proper in some form - async fn get_new_blockhash(&mut self, blockhash: &Hash) -> io::Result<(Hash, u64)> { + async fn get_new_blockhash(&mut self, blockhash: &Hash) -> io::Result<(Hash, FeeCalculator)> { let mut num_retries = 0; let start = Instant::now(); while start.elapsed().as_secs() < 5 { + #[allow(deprecated)] if let Ok((fee_calculator, new_blockhash, _slot)) = self.get_fees().await { if new_blockhash != *blockhash { - return Ok((new_blockhash, fee_calculator.lamports_per_signature)); + return Ok((new_blockhash, fee_calculator)); } } debug!("Got same blockhash ({:?}), will retry...", blockhash); @@ -916,6 +922,31 @@ impl ProgramTestBanksClientExt for BanksClient { ), )) } + + async fn get_new_latest_blockhash(&mut self, blockhash: &Hash) -> io::Result { + let mut num_retries = 0; + let start = Instant::now(); + while start.elapsed().as_secs() < 5 { + let new_blockhash = self.get_latest_blockhash().await?; + if new_blockhash != *blockhash { + return Ok(new_blockhash); + } + debug!("Got same blockhash ({:?}), will retry...", blockhash); + + tokio::time::sleep(Duration::from_millis(200)).await; + num_retries += 1; + } + + Err(io::Error::new( + io::ErrorKind::Other, + format!( + "Unable to get new blockhash after {}ms (retried {} times), stuck at {}", + start.elapsed().as_millis(), + num_retries, + blockhash + ), + )) + } } struct DroppableTask(Arc, JoinHandle); diff --git a/program-test/tests/warp.rs b/program-test/tests/warp.rs index 0279146826..78496aca06 100644 --- a/program-test/tests/warp.rs +++ b/program-test/tests/warp.rs @@ -423,10 +423,9 @@ async fn get_blockhash_post_warp() { let new_blockhash = context .banks_client - .get_new_blockhash(&context.last_blockhash) + .get_new_latest_blockhash(&context.last_blockhash) .await - .unwrap() - .0; + .unwrap(); let mut tx = Transaction::new_with_payer(&[], Some(&context.payer.pubkey())); tx.sign(&[&context.payer], new_blockhash); context.banks_client.process_transaction(tx).await.unwrap(); @@ -435,10 +434,9 @@ async fn get_blockhash_post_warp() { let new_blockhash = context .banks_client - .get_new_blockhash(&context.last_blockhash) + .get_new_latest_blockhash(&context.last_blockhash) .await - .unwrap() - .0; + .unwrap(); let mut tx = Transaction::new_with_payer(&[], Some(&context.payer.pubkey())); tx.sign(&[&context.payer], new_blockhash); diff --git a/sdk/src/client.rs b/sdk/src/client.rs index 4a9b284870..6d54ad590b 100644 --- a/sdk/src/client.rs +++ b/sdk/src/client.rs @@ -158,7 +158,7 @@ pub trait SyncClient { /// Get last known blockhash fn get_latest_blockhash(&self) -> Result; - /// Get recent blockhash. Uses explicit commitment configuration. + /// Get latest blockhash with last valid block height. Uses explicit commitment configuration. fn get_latest_blockhash_with_commitment( &self, commitment_config: CommitmentConfig,