From 7ba3d790a2412e1c2c89bc9ebc7bb5cca62f765f Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Mon, 6 Jul 2020 22:31:12 -0600 Subject: [PATCH] Add CommitmentLevel variants --- runtime/src/banks_service.rs | 62 +++++++++++++++----- sdk/src/banks_client.rs | 110 ++++++++++++++++++++++++++++++++--- 2 files changed, 148 insertions(+), 24 deletions(-) diff --git a/runtime/src/banks_service.rs b/runtime/src/banks_service.rs index f63baa191338cb..06508bc099bd7d 100644 --- a/runtime/src/banks_service.rs +++ b/runtime/src/banks_service.rs @@ -7,6 +7,7 @@ use solana_sdk::{ account::Account, banks_client::{start_tcp_client, Banks, BanksClient}, clock::Slot, + commitment_config::CommitmentLevel, fee_calculator::FeeCalculator, hash::Hash, pubkey::Pubkey, @@ -73,29 +74,51 @@ impl BanksService { .unwrap(); Self::new_with_sender(bank_forks, transaction_sender) } + + fn slot(&self, commitment: CommitmentLevel) -> Slot { + match commitment { + CommitmentLevel::Recent => self.bank_forks.highest_slot(), + CommitmentLevel::Root => self.bank_forks.root(), + CommitmentLevel::Single | CommitmentLevel::SingleGossip => { + //TODO: self.block_commitment_cache.highest_confirmed_slot() + todo!(); + } + CommitmentLevel::Max => { + //TODO: self.block_commitment_cache.largest_confirmed_root() + self.bank_forks.root() + } + } + } + + fn bank(&self, commitment: CommitmentLevel) -> &Arc { + &self.bank_forks[self.slot(commitment)] + } } async fn poll_transaction_status( - root_bank: Arc, + bank: Arc, signature: Signature, last_valid_slot: Slot, ) -> Option> { - let mut status = root_bank.get_signature_status(&signature); + let mut status = bank.get_signature_status(&signature); while status.is_none() { - let root_slot = root_bank.slot(); - if root_slot > last_valid_slot { + if bank.slot() > last_valid_slot { break; } delay_for(Duration::from_millis(100)).await; - status = root_bank.get_signature_status(&signature); + status = bank.get_signature_status(&signature); } status } #[tarpc::server] impl Banks for BanksService { - async fn get_fees(self, _: Context) -> (FeeCalculator, Hash, Slot) { - let bank = self.bank_forks.root_bank(); + async fn get_fees_with_commitment( + self, + _: Context, + commitment: CommitmentLevel, + ) -> (FeeCalculator, Hash, Slot) { + let bank = self.bank(commitment); let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator(); let last_valid_slot = bank.get_blockhash_last_valid_slot(&blockhash).unwrap(); (fee_calculator, blockhash, last_valid_slot) @@ -105,45 +128,54 @@ impl Banks for BanksService { self.transaction_sender.send(transaction).unwrap(); } - async fn get_signature_status( + async fn get_signature_status_with_commitment( self, _: Context, signature: Signature, + commitment: CommitmentLevel, ) -> Option> { - let bank = self.bank_forks.root_bank(); + let bank = self.bank(commitment); bank.get_signature_status(&signature) } - async fn get_signature_statuses( + async fn get_signature_statuses_with_commitment( self, _: Context, signatures: Vec, + commitment: CommitmentLevel, ) -> Vec>> { - let bank = self.bank_forks.root_bank(); + let bank = self.bank(commitment); signatures .iter() .map(|x| bank.get_signature_status(x)) .collect() } - async fn get_root_slot(self, _: Context) -> Slot { - self.bank_forks.root() + async fn get_slot(self, _: Context, commitment: CommitmentLevel) -> Slot { + self.slot(commitment) } async fn send_and_confirm_transaction( self, _: Context, transaction: Transaction, + commitment: CommitmentLevel, ) -> Option> { let blockhash = &transaction.message.recent_blockhash; let root_bank = self.bank_forks.root_bank(); let last_valid_slot = root_bank.get_blockhash_last_valid_slot(&blockhash).unwrap(); let signature = transaction.signatures.get(0).cloned().unwrap_or_default(); self.transaction_sender.send(transaction).unwrap(); - poll_transaction_status(root_bank.clone(), signature, last_valid_slot).await + let bank = self.bank(commitment).clone(); + poll_transaction_status(bank, signature, last_valid_slot).await } - async fn get_account(self, _: Context, pubkey: Pubkey) -> Option { + async fn get_account_with_commitment( + self, + _: Context, + pubkey: Pubkey, + _commitment: CommitmentLevel, + ) -> Option { let bank = self.bank_forks.root_bank(); bank.get_account(&pubkey) } diff --git a/sdk/src/banks_client.rs b/sdk/src/banks_client.rs index ae9230706c94ba..1d134ba4e34d26 100644 --- a/sdk/src/banks_client.rs +++ b/sdk/src/banks_client.rs @@ -1,6 +1,7 @@ use crate::{ account::Account, clock::Slot, + commitment_config::CommitmentLevel, fee_calculator::FeeCalculator, hash::Hash, pubkey::Pubkey, @@ -16,43 +17,82 @@ use tokio_serde::formats::Bincode; #[tarpc::service] pub trait Banks { - async fn get_fees() -> (FeeCalculator, Hash, Slot); + async fn get_fees_with_commitment(commitement: CommitmentLevel) -> (FeeCalculator, Hash, Slot); async fn send_transaction(transaction: Transaction); - async fn get_signature_status(signature: Signature) -> Option>; - async fn get_signature_statuses( + async fn get_signature_status_with_commitment( + signature: Signature, + commitement: CommitmentLevel, + ) -> Option>; + async fn get_signature_statuses_with_commitment( signatures: Vec, + commitment: CommitmentLevel, ) -> Vec>>; - async fn get_root_slot() -> Slot; + async fn get_slot(commitment: CommitmentLevel) -> Slot; async fn send_and_confirm_transaction( transaction: Transaction, + commitment: CommitmentLevel, ) -> Option>; - async fn get_account(pubkey: Pubkey) -> Option; + async fn get_account_with_commitment( + pubkey: Pubkey, + commitment: CommitmentLevel, + ) -> Option; } #[async_trait] pub trait BanksClientExt { async fn get_recent_blockhash(&mut self, _: Context) -> io::Result; + async fn process_transaction_with_commitment( + &mut self, + _: Context, + transaction: Transaction, + commitment: CommitmentLevel, + ) -> transport::Result<()>; async fn process_transaction( &mut self, _: Context, transaction: Transaction, ) -> transport::Result<()>; + async fn get_fees(&mut self, _: Context) -> io::Result<(FeeCalculator, Hash, Slot)>; + async fn get_signature_status( + &mut self, + _: Context, + signature: Signature, + ) -> io::Result>>; + async fn get_signature_statuses( + &mut self, + _: Context, + signatures: Vec, + ) -> io::Result>>>; + async fn get_root_slot(&mut self, _: Context) -> io::Result; + async fn get_account(&mut self, _: Context, pubkey: Pubkey) -> io::Result>; + async fn get_balance_with_commitment( + &mut self, + _: Context, + pubkey: Pubkey, + commitment: CommitmentLevel, + ) -> io::Result; async fn get_balance(&mut self, _: Context, pubkey: Pubkey) -> io::Result; } #[async_trait] impl BanksClientExt for BanksClient { + async fn get_fees(&mut self, context: Context) -> io::Result<(FeeCalculator, Hash, Slot)> { + self.get_fees_with_commitment(context, CommitmentLevel::Root) + .await + } + async fn get_recent_blockhash(&mut self, context: Context) -> io::Result { Ok(self.get_fees(context).await?.1) } - async fn process_transaction( + async fn process_transaction_with_commitment( &mut self, context: Context, transaction: Transaction, + commitment: CommitmentLevel, ) -> transport::Result<()> { let result = self - .send_and_confirm_transaction(context, transaction) + .send_and_confirm_transaction(context, transaction, commitment) .await?; match result { None => Err(Error::new(ErrorKind::TimedOut, "invalid blockhash or fee-payer").into()), @@ -60,10 +100,62 @@ impl BanksClientExt for BanksClient { } } - async fn get_balance(&mut self, context: Context, pubkey: Pubkey) -> io::Result { - let account = self.get_account(context, pubkey).await?; + async fn process_transaction( + &mut self, + context: Context, + transaction: Transaction, + ) -> transport::Result<()> { + self.process_transaction_with_commitment(context, transaction, CommitmentLevel::default()) + .await + } + + async fn get_root_slot(&mut self, context: Context) -> io::Result { + self.get_slot(context, CommitmentLevel::Root).await + } + + async fn get_account( + &mut self, + context: Context, + pubkey: Pubkey, + ) -> io::Result> { + self.get_account_with_commitment(context, pubkey, CommitmentLevel::default()) + .await + } + + async fn get_balance_with_commitment( + &mut self, + context: Context, + pubkey: Pubkey, + commitment: CommitmentLevel, + ) -> io::Result { + let account = self + .get_account_with_commitment(context, pubkey, commitment) + .await?; Ok(account.map(|x| x.lamports).unwrap_or(0)) } + + async fn get_balance(&mut self, context: Context, pubkey: Pubkey) -> io::Result { + self.get_balance_with_commitment(context, pubkey, CommitmentLevel::default()) + .await + } + + async fn get_signature_status( + &mut self, + context: Context, + signature: Signature, + ) -> io::Result>> { + self.get_signature_status_with_commitment(context, signature, CommitmentLevel::default()) + .await + } + + async fn get_signature_statuses( + &mut self, + context: Context, + signatures: Vec, + ) -> io::Result>>> { + self.get_signature_statuses_with_commitment(context, signatures, CommitmentLevel::default()) + .await + } } pub async fn start_tcp_client(addr: T) -> io::Result {