Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Use last_valid_block_height in services and client apps #19163

Merged
merged 6 commits into from
Aug 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions banks-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl BanksClient {
&mut self,
ctx: Context,
commitment: CommitmentLevel,
) -> impl Future<Output = io::Result<(FeeCalculator, Hash, Slot)>> + '_ {
) -> impl Future<Output = io::Result<(FeeCalculator, Hash, u64)>> + '_ {
self.inner
.get_fees_with_commitment_and_context(ctx, commitment)
}
Expand All @@ -84,6 +84,14 @@ impl BanksClient {
self.inner.get_slot_with_context(ctx, commitment)
}

pub fn get_block_height_with_context(
&mut self,
ctx: Context,
commitment: CommitmentLevel,
) -> impl Future<Output = io::Result<Slot>> + '_ {
self.inner.get_block_height_with_context(ctx, commitment)
}

pub fn process_transaction_with_commitment_and_context(
&mut self,
ctx: Context,
Expand Down Expand Up @@ -119,7 +127,7 @@ impl BanksClient {
/// use them to calculate the transaction fee.
pub fn get_fees(
&mut self,
) -> impl Future<Output = io::Result<(FeeCalculator, Hash, Slot)>> + '_ {
) -> impl Future<Output = io::Result<(FeeCalculator, Hash, u64)>> + '_ {
self.get_fees_with_commitment_and_context(context::current(), CommitmentLevel::default())
}

Expand Down Expand Up @@ -195,12 +203,18 @@ impl BanksClient {
self.process_transactions_with_commitment(transactions, CommitmentLevel::default())
}

/// 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.
/// 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 = io::Result<Slot>> + '_ {
self.get_slot_with_context(context::current(), CommitmentLevel::default())
}

/// Return the most recent rooted block height. All transactions at or below this height
/// are said to be finalized. The cluster will not fork to a higher block height.
pub fn get_root_block_height(&mut self) -> impl Future<Output = io::Result<Slot>> + '_ {
self.get_block_height_with_context(context::current(), CommitmentLevel::default())
}

/// 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 fn get_account_with_commitment(
Expand Down Expand Up @@ -386,16 +400,16 @@ mod tests {
Runtime::new()?.block_on(async {
let client_transport = start_local_server(bank_forks, block_commitment_cache).await;
let mut banks_client = start_client(client_transport).await?;
let (_, recent_blockhash, last_valid_slot) = banks_client.get_fees().await?;
let (_, recent_blockhash, last_valid_block_height) = banks_client.get_fees().await?;
let transaction = Transaction::new(&[&genesis.mint_keypair], message, recent_blockhash);
let signature = transaction.signatures[0];
banks_client.send_transaction(transaction).await?;

let mut status = banks_client.get_transaction_status(signature).await?;

while status.is_none() {
let root_slot = banks_client.get_root_slot().await?;
if root_slot > last_valid_slot {
let root_block_height = banks_client.get_root_block_height().await?;
if root_block_height > last_valid_block_height {
break;
}
sleep(Duration::from_millis(100)).await;
Expand Down
1 change: 1 addition & 0 deletions banks-interface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub trait Banks {
async fn get_transaction_status_with_context(signature: Signature)
-> Option<TransactionStatus>;
async fn get_slot_with_context(commitment: CommitmentLevel) -> Slot;
async fn get_block_height_with_context(commitment: CommitmentLevel) -> u64;
async fn process_transaction_with_commitment_and_context(
transaction: Transaction,
commitment: CommitmentLevel,
Expand Down
40 changes: 26 additions & 14 deletions banks-server/src/banks_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl BanksServer {
self,
signature: &Signature,
blockhash: &Hash,
last_valid_slot: Slot,
last_valid_block_height: u64,
commitment: CommitmentLevel,
) -> Option<transaction::Result<()>> {
let mut status = self
Expand All @@ -119,7 +119,7 @@ impl BanksServer {
while status.is_none() {
sleep(Duration::from_millis(200)).await;
let bank = self.bank(commitment);
if bank.slot() > last_valid_slot {
if bank.block_height() > last_valid_block_height {
break;
}
status = bank.get_signature_status_with_blockhash(signature, blockhash);
Expand All @@ -145,28 +145,33 @@ fn verify_transaction(
impl Banks for BanksServer {
async fn send_transaction_with_context(self, _: Context, transaction: Transaction) {
let blockhash = &transaction.message.recent_blockhash;
let last_valid_slot = self
let last_valid_block_height = self
.bank_forks
.read()
.unwrap()
.root_bank()
.get_blockhash_last_valid_slot(blockhash)
.get_blockhash_last_valid_block_height(blockhash)
.unwrap();
let signature = transaction.signatures.get(0).cloned().unwrap_or_default();
let info =
TransactionInfo::new(signature, serialize(&transaction).unwrap(), last_valid_slot);
let info = TransactionInfo::new(
signature,
serialize(&transaction).unwrap(),
last_valid_block_height,
);
self.transaction_sender.send(info).unwrap();
}

async fn get_fees_with_commitment_and_context(
self,
_: Context,
commitment: CommitmentLevel,
) -> (FeeCalculator, Hash, Slot) {
) -> (FeeCalculator, Hash, u64) {
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)
let last_valid_block_height = bank
.get_blockhash_last_valid_block_height(&blockhash)
.unwrap();
(fee_calculator, blockhash, last_valid_block_height)
}

async fn get_transaction_status_with_context(
Expand Down Expand Up @@ -209,6 +214,10 @@ impl Banks for BanksServer {
self.slot(commitment)
}

async fn get_block_height_with_context(self, _: Context, commitment: CommitmentLevel) -> u64 {
self.bank(commitment).block_height()
}

async fn process_transaction_with_commitment_and_context(
self,
_: Context,
Expand All @@ -223,18 +232,21 @@ impl Banks for BanksServer {
}

let blockhash = &transaction.message.recent_blockhash;
let last_valid_slot = self
let last_valid_block_height = self
.bank_forks
.read()
.unwrap()
.root_bank()
.get_blockhash_last_valid_slot(blockhash)
.get_blockhash_last_valid_block_height(blockhash)
.unwrap();
let signature = transaction.signatures.get(0).cloned().unwrap_or_default();
let info =
TransactionInfo::new(signature, serialize(&transaction).unwrap(), last_valid_slot);
let info = TransactionInfo::new(
signature,
serialize(&transaction).unwrap(),
last_valid_block_height,
);
self.transaction_sender.send(info).unwrap();
self.poll_signature_status(&signature, blockhash, last_valid_slot, commitment)
self.poll_signature_status(&signature, blockhash, last_valid_block_height, commitment)
.await
}

Expand Down
14 changes: 9 additions & 5 deletions banks-server/src/send_transaction_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use log::*;
use solana_metrics::{datapoint_warn, inc_new_counter_info};
use solana_runtime::{bank::Bank, bank_forks::BankForks};
use solana_sdk::{clock::Slot, signature::Signature};
use solana_sdk::signature::Signature;
use std::{
collections::HashMap,
net::{SocketAddr, UdpSocket},
Expand All @@ -24,15 +24,19 @@ pub struct SendTransactionService {
pub struct TransactionInfo {
pub signature: Signature,
pub wire_transaction: Vec<u8>,
pub last_valid_slot: Slot,
pub last_valid_block_height: u64,
}

impl TransactionInfo {
pub fn new(signature: Signature, wire_transaction: Vec<u8>, last_valid_slot: Slot) -> Self {
pub fn new(
signature: Signature,
wire_transaction: Vec<u8>,
last_valid_block_height: u64,
) -> Self {
Self {
signature,
wire_transaction,
last_valid_slot,
last_valid_block_height,
}
}
}
Expand Down Expand Up @@ -124,7 +128,7 @@ impl SendTransactionService {
result.rooted += 1;
inc_new_counter_info!("send_transaction_service-rooted", 1);
false
} else if transaction_info.last_valid_slot < root_bank.slot() {
} else if transaction_info.last_valid_block_height < root_bank.block_height() {
info!("Dropping expired transaction: {}", signature);
result.expired += 1;
inc_new_counter_info!("send_transaction_service-expired", 1);
Expand Down
34 changes: 20 additions & 14 deletions cli/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use solana_client::{
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
rpc_response::Fees,
tpu_client::{TpuClient, TpuClientConfig},
};
use solana_rbpf::{
Expand All @@ -35,7 +36,6 @@ use solana_sdk::{
account_utils::StateMut,
bpf_loader, bpf_loader_deprecated,
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
clock::Slot,
commitment_config::CommitmentConfig,
instruction::Instruction,
instruction::InstructionError,
Expand Down Expand Up @@ -1943,8 +1943,12 @@ fn send_deploy_messages(
if let Some(write_messages) = write_messages {
if let Some(write_signer) = write_signer {
trace!("Writing program data");
let (blockhash, _, last_valid_slot) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
let Fees {
blockhash,
last_valid_block_height,
..
} = rpc_client
.get_fees_with_commitment(config.commitment)?
.value;
let mut write_transactions = vec![];
for message in write_messages.iter() {
Expand All @@ -1959,7 +1963,7 @@ fn send_deploy_messages(
write_transactions,
&[payer_signer, write_signer],
config.commitment,
last_valid_slot,
last_valid_block_height,
)
.map_err(|err| format!("Data writes to account failed: {}", err))?;
}
Expand Down Expand Up @@ -2029,7 +2033,7 @@ fn send_and_confirm_transactions_with_spinner<T: Signers>(
mut transactions: Vec<Transaction>,
signer_keys: &T,
commitment: CommitmentConfig,
mut last_valid_slot: Slot,
mut last_valid_block_height: u64,
) -> Result<(), Box<dyn error::Error>> {
let progress_bar = new_spinner_progress_bar();
let mut send_retries = 5;
Expand Down Expand Up @@ -2069,7 +2073,7 @@ fn send_and_confirm_transactions_with_spinner<T: Signers>(

// Collect statuses for all the transactions, drop those that are confirmed
loop {
let mut slot = 0;
let mut block_height = 0;
let pending_signatures = pending_transactions.keys().cloned().collect::<Vec<_>>();
for pending_signatures_chunk in
pending_signatures.chunks(MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS)
Expand All @@ -2094,20 +2098,20 @@ fn send_and_confirm_transactions_with_spinner<T: Signers>(
}
}

slot = rpc_client.get_slot()?;
block_height = rpc_client.get_block_height()?;
progress_bar.set_message(format!(
"[{}/{}] Transactions confirmed. Retrying in {} slots",
"[{}/{}] Transactions confirmed. Retrying in {} blocks",
num_transactions - pending_transactions.len(),
num_transactions,
last_valid_slot.saturating_sub(slot)
last_valid_block_height.saturating_sub(block_height)
));
}

if pending_transactions.is_empty() {
return Ok(());
}

if slot > last_valid_slot {
if block_height > last_valid_block_height {
break;
}

Expand Down Expand Up @@ -2137,10 +2141,12 @@ fn send_and_confirm_transactions_with_spinner<T: Signers>(
send_retries -= 1;

// Re-sign any failed transactions with a new blockhash and retry
let (blockhash, _fee_calculator, new_last_valid_slot) = rpc_client
.get_recent_blockhash_with_commitment(commitment)?
.value;
last_valid_slot = new_last_valid_slot;
let Fees {
blockhash,
last_valid_block_height: new_last_valid_block_height,
..
} = rpc_client.get_fees_with_commitment(commitment)?.value;
last_valid_block_height = new_last_valid_block_height;
transactions = vec![];
for (_, mut transaction) in pending_transactions.into_iter() {
transaction.try_sign(signer_keys, blockhash)?;
Expand Down
29 changes: 11 additions & 18 deletions client/src/blockhash_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ mod tests {
use crate::{
blockhash_query,
rpc_request::RpcRequest,
rpc_response::{Response, RpcFeeCalculator, RpcResponseContext},
rpc_response::{Response, RpcFeeCalculator, RpcFees, RpcResponseContext},
};
use clap::App;
use serde_json::{self, json, Value};
use serde_json::{self, json};
use solana_account_decoder::{UiAccount, UiAccountEncoding};
use solana_sdk::{account::Account, hash::hash, nonce, system_program};
use std::collections::HashMap;
Expand Down Expand Up @@ -288,10 +288,12 @@ mod tests {
let rpc_fee_calc = FeeCalculator::new(42);
let get_recent_blockhash_response = json!(Response {
context: RpcResponseContext { slot: 1 },
value: json!((
Value::String(rpc_blockhash.to_string()),
serde_json::to_value(rpc_fee_calc.clone()).unwrap()
)),
value: json!(RpcFees {
blockhash: rpc_blockhash.to_string(),
fee_calculator: rpc_fee_calc.clone(),
last_valid_slot: 42,
last_valid_block_height: 42,
}),
});
let get_fee_calculator_for_blockhash_response = json!(Response {
context: RpcResponseContext { slot: 1 },
Expand All @@ -300,10 +302,7 @@ mod tests {
}),
});
let mut mocks = HashMap::new();
mocks.insert(
RpcRequest::GetRecentBlockhash,
get_recent_blockhash_response.clone(),
);
mocks.insert(RpcRequest::GetFees, get_recent_blockhash_response.clone());
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!(
BlockhashQuery::default()
Expand All @@ -312,10 +311,7 @@ mod tests {
(rpc_blockhash, rpc_fee_calc.clone()),
);
let mut mocks = HashMap::new();
mocks.insert(
RpcRequest::GetRecentBlockhash,
get_recent_blockhash_response.clone(),
);
mocks.insert(RpcRequest::GetFees, get_recent_blockhash_response.clone());
mocks.insert(
RpcRequest::GetFeeCalculatorForBlockhash,
get_fee_calculator_for_blockhash_response,
Expand All @@ -328,10 +324,7 @@ mod tests {
(test_blockhash, rpc_fee_calc),
);
let mut mocks = HashMap::new();
mocks.insert(
RpcRequest::GetRecentBlockhash,
get_recent_blockhash_response,
);
mocks.insert(RpcRequest::GetFees, get_recent_blockhash_response);
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!(
BlockhashQuery::None(test_blockhash)
Expand Down
9 changes: 0 additions & 9 deletions client/src/fees.rs

This file was deleted.

Loading