banks-client: Add `simulate_transaction` implementation (#25830)
This commit is contained in:
parent
591986eb01
commit
3be11061ed
|
@ -138,6 +138,18 @@ impl BanksClient {
|
|||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn simulate_transaction_with_commitment_and_context(
|
||||
&mut self,
|
||||
ctx: Context,
|
||||
transaction: Transaction,
|
||||
commitment: CommitmentLevel,
|
||||
) -> impl Future<Output = Result<BanksTransactionResultWithSimulation, BanksClientError>> + '_
|
||||
{
|
||||
self.inner
|
||||
.simulate_transaction_with_commitment_and_context(ctx, transaction, commitment)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn get_account_with_commitment_and_context(
|
||||
&mut self,
|
||||
ctx: Context,
|
||||
|
@ -300,6 +312,29 @@ impl BanksClient {
|
|||
self.process_transactions_with_commitment(transactions, CommitmentLevel::default())
|
||||
}
|
||||
|
||||
/// Simulate a transaction at the given commitment level
|
||||
pub fn simulate_transaction_with_commitment(
|
||||
&mut self,
|
||||
transaction: Transaction,
|
||||
commitment: CommitmentLevel,
|
||||
) -> impl Future<Output = Result<BanksTransactionResultWithSimulation, BanksClientError>> + '_
|
||||
{
|
||||
self.simulate_transaction_with_commitment_and_context(
|
||||
context::current(),
|
||||
transaction,
|
||||
commitment,
|
||||
)
|
||||
}
|
||||
|
||||
/// Simulate a transaction at the default commitment level
|
||||
pub fn simulate_transaction(
|
||||
&mut self,
|
||||
transaction: Transaction,
|
||||
) -> impl Future<Output = Result<BanksTransactionResultWithSimulation, BanksClientError>> + '_
|
||||
{
|
||||
self.simulate_transaction_with_commitment(transaction, CommitmentLevel::default())
|
||||
}
|
||||
|
||||
/// Return the most recent rooted slot. All transactions at or below this slot
|
||||
/// are said to be finalized. The cluster will not fork to a higher slot.
|
||||
pub fn get_root_slot(&mut self) -> impl Future<Output = Result<Slot, BanksClientError>> + '_ {
|
||||
|
@ -516,6 +551,11 @@ mod tests {
|
|||
|
||||
let recent_blockhash = banks_client.get_latest_blockhash().await?;
|
||||
let transaction = Transaction::new(&[&genesis.mint_keypair], message, recent_blockhash);
|
||||
let simulation_result = banks_client
|
||||
.simulate_transaction(transaction.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(simulation_result.result.unwrap().is_ok());
|
||||
banks_client.process_transaction(transaction).await.unwrap();
|
||||
assert_eq!(banks_client.get_balance(bob_pubkey).await?, 1);
|
||||
Ok(())
|
||||
|
|
|
@ -67,6 +67,10 @@ pub trait Banks {
|
|||
transaction: Transaction,
|
||||
commitment: CommitmentLevel,
|
||||
) -> Option<transaction::Result<()>>;
|
||||
async fn simulate_transaction_with_commitment_and_context(
|
||||
transaction: Transaction,
|
||||
commitment: CommitmentLevel,
|
||||
) -> BanksTransactionResultWithSimulation;
|
||||
async fn get_account_with_commitment_and_context(
|
||||
address: Pubkey,
|
||||
commitment: CommitmentLevel,
|
||||
|
|
|
@ -161,6 +161,38 @@ fn verify_transaction(
|
|||
}
|
||||
}
|
||||
|
||||
fn simulate_transaction(
|
||||
bank: &Bank,
|
||||
transaction: Transaction,
|
||||
) -> BanksTransactionResultWithSimulation {
|
||||
let sanitized_transaction = match SanitizedTransaction::try_from_legacy_transaction(transaction)
|
||||
{
|
||||
Err(err) => {
|
||||
return BanksTransactionResultWithSimulation {
|
||||
result: Some(Err(err)),
|
||||
simulation_details: None,
|
||||
};
|
||||
}
|
||||
Ok(tx) => tx,
|
||||
};
|
||||
let TransactionSimulationResult {
|
||||
result,
|
||||
logs,
|
||||
post_simulation_accounts: _,
|
||||
units_consumed,
|
||||
return_data,
|
||||
} = bank.simulate_transaction_unchecked(sanitized_transaction);
|
||||
let simulation_details = TransactionSimulationDetails {
|
||||
logs,
|
||||
units_consumed,
|
||||
return_data,
|
||||
};
|
||||
BanksTransactionResultWithSimulation {
|
||||
result: Some(result),
|
||||
simulation_details: Some(simulation_details),
|
||||
}
|
||||
}
|
||||
|
||||
#[tarpc::server]
|
||||
impl Banks for BanksServer {
|
||||
async fn send_transaction_with_context(self, _: Context, transaction: Transaction) {
|
||||
|
@ -252,41 +284,25 @@ impl Banks for BanksServer {
|
|||
transaction: Transaction,
|
||||
commitment: CommitmentLevel,
|
||||
) -> BanksTransactionResultWithSimulation {
|
||||
let sanitized_transaction =
|
||||
match SanitizedTransaction::try_from_legacy_transaction(transaction.clone()) {
|
||||
Err(err) => {
|
||||
return BanksTransactionResultWithSimulation {
|
||||
result: Some(Err(err)),
|
||||
simulation_details: None,
|
||||
};
|
||||
}
|
||||
Ok(tx) => tx,
|
||||
};
|
||||
if let TransactionSimulationResult {
|
||||
result: Err(err),
|
||||
logs,
|
||||
post_simulation_accounts: _,
|
||||
units_consumed,
|
||||
return_data,
|
||||
} = self
|
||||
.bank(commitment)
|
||||
.simulate_transaction_unchecked(sanitized_transaction)
|
||||
{
|
||||
return BanksTransactionResultWithSimulation {
|
||||
result: Some(Err(err)),
|
||||
simulation_details: Some(TransactionSimulationDetails {
|
||||
logs,
|
||||
units_consumed,
|
||||
return_data,
|
||||
}),
|
||||
};
|
||||
}
|
||||
BanksTransactionResultWithSimulation {
|
||||
result: self
|
||||
let mut simulation_result =
|
||||
simulate_transaction(&self.bank(commitment), transaction.clone());
|
||||
// Simulation was ok, so process the real transaction and replace the
|
||||
// simulation's result with the real transaction result
|
||||
if let Some(Ok(_)) = simulation_result.result {
|
||||
simulation_result.result = self
|
||||
.process_transaction_with_commitment_and_context(ctx, transaction, commitment)
|
||||
.await,
|
||||
simulation_details: None,
|
||||
.await;
|
||||
}
|
||||
simulation_result
|
||||
}
|
||||
|
||||
async fn simulate_transaction_with_commitment_and_context(
|
||||
self,
|
||||
_: Context,
|
||||
transaction: Transaction,
|
||||
commitment: CommitmentLevel,
|
||||
) -> BanksTransactionResultWithSimulation {
|
||||
simulate_transaction(&self.bank(commitment), transaction)
|
||||
}
|
||||
|
||||
async fn process_transaction_with_commitment_and_context(
|
||||
|
|
Loading…
Reference in New Issue