Remove need for BanksClientExt trait (#13519)

This commit is contained in:
Greg Fitzgerald 2020-11-10 19:30:25 -07:00 committed by GitHub
parent 2c2432fddc
commit 2660b44d91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 138 additions and 105 deletions

1
Cargo.lock generated
View File

@ -3614,7 +3614,6 @@ dependencies = [
name = "solana-banks-client"
version = "1.5.0"
dependencies = [
"async-trait",
"bincode",
"futures 0.3.5",
"solana-banks-interface",

View File

@ -9,7 +9,6 @@ homepage = "https://solana.com/"
edition = "2018"
[dependencies]
async-trait = "0.1.36"
bincode = "1.3.1"
futures = "0.3"
solana-banks-interface = { path = "../banks-interface", version = "1.5.0" }

View File

@ -5,9 +5,8 @@
//! but they are undocumented, may change over time, and are generally more
//! cumbersome to use.
use async_trait::async_trait;
use futures::future::join_all;
pub use solana_banks_interface::{BanksClient, TransactionStatus};
pub use solana_banks_interface::{BanksClient as TarpcClient, TransactionStatus};
use solana_banks_interface::{BanksRequest, BanksResponse};
use solana_sdk::{
account::{from_account, Account},
@ -19,107 +18,118 @@ use solana_sdk::{
rent::Rent,
signature::Signature,
sysvar,
transaction::Transaction,
transaction::{self, Transaction},
transport,
};
use std::io::{self, Error, ErrorKind};
use tarpc::{
client, context,
rpc::{transport::channel::UnboundedChannel, ClientMessage, Response},
client::{self, channel::RequestDispatch, NewClient},
context::{self, Context},
rpc::{ClientMessage, Response},
serde_transport::tcp,
Transport,
};
use tokio::{net::ToSocketAddrs, time::Duration};
use tokio_serde::formats::Bincode;
#[async_trait]
pub trait BanksClientExt {
// This exists only for backward compatibility
pub trait BanksClientExt {}
#[derive(Clone)]
pub struct BanksClient {
inner: TarpcClient,
}
impl BanksClient {
#[allow(clippy::new_ret_no_self)]
pub fn new<C>(
config: client::Config,
transport: C,
) -> NewClient<TarpcClient, RequestDispatch<BanksRequest, BanksResponse, C>>
where
C: Transport<ClientMessage<BanksRequest>, Response<BanksResponse>>,
{
TarpcClient::new(config, transport)
}
pub async fn send_transaction_with_context(
&mut self,
ctx: Context,
transaction: Transaction,
) -> io::Result<()> {
self.inner
.send_transaction_with_context(ctx, transaction)
.await
}
pub async fn get_fees_with_commitment_and_context(
&mut self,
ctx: Context,
commitment: CommitmentLevel,
) -> io::Result<(FeeCalculator, Hash, Slot)> {
self.inner
.get_fees_with_commitment_and_context(ctx, commitment)
.await
}
pub async fn get_transaction_status_with_context(
&mut self,
ctx: Context,
signature: Signature,
) -> io::Result<Option<TransactionStatus>> {
self.inner
.get_transaction_status_with_context(ctx, signature)
.await
}
pub async fn get_slot_with_context(
&mut self,
ctx: Context,
commitment: CommitmentLevel,
) -> io::Result<Slot> {
self.inner.get_slot_with_context(ctx, commitment).await
}
pub async fn process_transaction_with_commitment_and_context(
&mut self,
ctx: Context,
transaction: Transaction,
commitment: CommitmentLevel,
) -> io::Result<Option<transaction::Result<()>>> {
self.inner
.process_transaction_with_commitment_and_context(ctx, transaction, commitment)
.await
}
pub async fn get_account_with_commitment_and_context(
&mut self,
ctx: Context,
address: Pubkey,
commitment: CommitmentLevel,
) -> io::Result<Option<Account>> {
self.inner
.get_account_with_commitment_and_context(ctx, address, commitment)
.await
}
/// Send a transaction and return immediately. The server will resend the
/// transaction until either it is accepted by the cluster or the transaction's
/// blockhash expires.
async fn send_transaction(&mut self, transaction: Transaction) -> io::Result<()>;
/// 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.
async fn get_recent_blockhash(&mut self) -> io::Result<Hash>;
/// 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.
async fn get_fees(&mut self) -> io::Result<(FeeCalculator, Hash, Slot)>;
/// Return the cluster rent
async fn get_rent(&mut self) -> io::Result<Rent>;
/// Send a transaction and return after the transaction has been rejected or
/// reached the given level of commitment.
async fn process_transaction_with_commitment(
&mut self,
transaction: Transaction,
commitment: CommitmentLevel,
) -> transport::Result<()>;
/// Send a transaction and return after the transaction has been finalized or rejected.
async fn process_transaction(&mut self, transaction: Transaction) -> transport::Result<()>;
/// Return the status of a transaction with a signature matching the transaction's first
/// signature. Return None if the transaction is not found, which may be because the
/// blockhash was expired or the fee-paying account had insufficient funds to pay the
/// transaction fee. Note that servers rarely store the full transaction history. This
/// method may return None if the transaction status has been discarded.
async fn get_transaction_status(
&mut self,
signature: Signature,
) -> io::Result<Option<TransactionStatus>>;
/// Same as get_transaction_status, but for multiple transactions.
async fn get_transaction_statuses(
&mut self,
signatures: Vec<Signature>,
) -> io::Result<Vec<Option<TransactionStatus>>>;
/// Return the most recent rooted slot height. All transactions at or below this height
/// are said to be finalized. The cluster will not fork to a higher slot height.
async fn get_root_slot(&mut self) -> io::Result<Slot>;
/// Return the account at the given address at the slot corresponding to the given
/// commitment level. If the account is not found, None is returned.
async fn get_account_with_commitment(
&mut self,
address: Pubkey,
commitment: CommitmentLevel,
) -> io::Result<Option<Account>>;
/// Return the account at the given address at the time of the most recent root slot.
/// If the account is not found, None is returned.
async fn get_account(&mut self, address: Pubkey) -> io::Result<Option<Account>>;
/// Return the balance in lamports of an account at the given address at the slot
/// corresponding to the given commitment level.
async fn get_balance_with_commitment(
&mut self,
address: Pubkey,
commitment: CommitmentLevel,
) -> io::Result<u64>;
/// Return the balance in lamports of an account at the given address at the time
/// of the most recent root slot.
async fn get_balance(&mut self, address: Pubkey) -> io::Result<u64>;
}
#[async_trait]
impl BanksClientExt for BanksClient {
async fn send_transaction(&mut self, transaction: Transaction) -> io::Result<()> {
pub async fn send_transaction(&mut self, transaction: Transaction) -> io::Result<()> {
self.send_transaction_with_context(context::current(), transaction)
.await
}
async fn get_fees(&mut self) -> io::Result<(FeeCalculator, Hash, Slot)> {
/// 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.
pub async fn get_fees(&mut self) -> io::Result<(FeeCalculator, Hash, Slot)> {
self.get_fees_with_commitment_and_context(context::current(), CommitmentLevel::Root)
.await
}
async fn get_rent(&mut self) -> io::Result<Rent> {
/// Return the cluster rent
pub async fn get_rent(&mut self) -> io::Result<Rent> {
let rent_sysvar = self
.get_account(sysvar::rent::id())
.await?
@ -130,11 +140,16 @@ impl BanksClientExt for BanksClient {
})
}
async fn get_recent_blockhash(&mut self) -> io::Result<Hash> {
/// 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.
pub async fn get_recent_blockhash(&mut self) -> io::Result<Hash> {
Ok(self.get_fees().await?.1)
}
async fn process_transaction_with_commitment(
/// Send a transaction and return after the transaction has been rejected or
/// reached the given level of commitment.
pub async fn process_transaction_with_commitment(
&mut self,
transaction: Transaction,
commitment: CommitmentLevel,
@ -150,17 +165,22 @@ impl BanksClientExt for BanksClient {
}
}
async fn process_transaction(&mut self, transaction: Transaction) -> transport::Result<()> {
/// Send a transaction and return after the transaction has been finalized or rejected.
pub async fn process_transaction(&mut self, transaction: Transaction) -> transport::Result<()> {
self.process_transaction_with_commitment(transaction, CommitmentLevel::default())
.await
}
async fn get_root_slot(&mut self) -> io::Result<Slot> {
/// Return the most recent rooted slot height. All transactions at or below this height
/// are said to be finalized. The cluster will not fork to a higher slot height.
pub async fn get_root_slot(&mut self) -> io::Result<Slot> {
self.get_slot_with_context(context::current(), CommitmentLevel::Root)
.await
}
async fn get_account_with_commitment(
/// Return the account at the given address at the slot corresponding to the given
/// commitment level. If the account is not found, None is returned.
pub async fn get_account_with_commitment(
&mut self,
address: Pubkey,
commitment: CommitmentLevel,
@ -169,12 +189,16 @@ impl BanksClientExt for BanksClient {
.await
}
async fn get_account(&mut self, address: Pubkey) -> io::Result<Option<Account>> {
/// Return the account at the given address at the time of the most recent root slot.
/// If the account is not found, None is returned.
pub async fn get_account(&mut self, address: Pubkey) -> io::Result<Option<Account>> {
self.get_account_with_commitment(address, CommitmentLevel::default())
.await
}
async fn get_balance_with_commitment(
/// Return the balance in lamports of an account at the given address at the slot
/// corresponding to the given commitment level.
pub async fn get_balance_with_commitment(
&mut self,
address: Pubkey,
commitment: CommitmentLevel,
@ -185,12 +209,19 @@ impl BanksClientExt for BanksClient {
Ok(account.map(|x| x.lamports).unwrap_or(0))
}
async fn get_balance(&mut self, address: Pubkey) -> io::Result<u64> {
/// Return the balance in lamports of an account at the given address at the time
/// of the most recent root slot.
pub async fn get_balance(&mut self, address: Pubkey) -> io::Result<u64> {
self.get_balance_with_commitment(address, CommitmentLevel::default())
.await
}
async fn get_transaction_status(
/// Return the status of a transaction with a signature matching the transaction's first
/// signature. Return None if the transaction is not found, which may be because the
/// blockhash was expired or the fee-paying account had insufficient funds to pay the
/// transaction fee. Note that servers rarely store the full transaction history. This
/// method may return None if the transaction status has been discarded.
pub async fn get_transaction_status(
&mut self,
signature: Signature,
) -> io::Result<Option<TransactionStatus>> {
@ -198,7 +229,8 @@ impl BanksClientExt for BanksClient {
.await
}
async fn get_transaction_statuses(
/// Same as get_transaction_status, but for multiple transactions.
pub async fn get_transaction_statuses(
&mut self,
signatures: Vec<Signature>,
) -> io::Result<Vec<Option<TransactionStatus>>> {
@ -219,15 +251,20 @@ impl BanksClientExt for BanksClient {
}
}
pub async fn start_client(
transport: UnboundedChannel<Response<BanksResponse>, ClientMessage<BanksRequest>>,
) -> io::Result<BanksClient> {
BanksClient::new(client::Config::default(), transport).spawn()
pub async fn start_client<C>(transport: C) -> io::Result<BanksClient>
where
C: Transport<ClientMessage<BanksRequest>, Response<BanksResponse>> + Send + 'static,
{
Ok(BanksClient {
inner: TarpcClient::new(client::Config::default(), transport).spawn()?,
})
}
pub async fn start_tcp_client<T: ToSocketAddrs>(addr: T) -> io::Result<BanksClient> {
let transport = tcp::connect(addr, Bincode::default).await?;
BanksClient::new(client::Config::default(), transport).spawn()
Ok(BanksClient {
inner: TarpcClient::new(client::Config::default(), transport).spawn()?,
})
}
#[cfg(test)]
@ -264,8 +301,7 @@ mod tests {
Runtime::new()?.block_on(async {
let client_transport = start_local_server(&bank_forks).await;
let mut banks_client =
BanksClient::new(client::Config::default(), client_transport).spawn()?;
let mut banks_client = start_client(client_transport).await?;
let recent_blockhash = banks_client.get_recent_blockhash().await?;
let transaction = Transaction::new(&[&genesis.mint_keypair], message, recent_blockhash);
@ -293,8 +329,7 @@ mod tests {
Runtime::new()?.block_on(async {
let client_transport = start_local_server(&bank_forks).await;
let mut banks_client =
BanksClient::new(client::Config::default(), client_transport).spawn()?;
let mut banks_client = start_client(client_transport).await?;
let (_, recent_blockhash, last_valid_slot) = banks_client.get_fees().await?;
let transaction = Transaction::new(&[&genesis.mint_keypair], message, recent_blockhash);
let signature = transaction.signatures[0];

View File

@ -7,7 +7,7 @@ use indexmap::IndexMap;
use indicatif::{ProgressBar, ProgressStyle};
use pickledb::PickleDb;
use serde::{Deserialize, Serialize};
use solana_banks_client::{BanksClient, BanksClientExt};
use solana_banks_client::BanksClient;
use solana_sdk::{
commitment_config::CommitmentLevel,
instruction::Instruction,