Use last_valid_block_height in services and client apps (#19163)

* Add deprecated tag to Bank::get_blockhash_last_valid_slot

* Update SendTransactionService to use last_valid_block_height

* Update solana-tokens to use last_valid_block_height

* Remove dangling file

* Update solana program to use last_valid_block_height

* Update Banks crates to use last_valid_block_height
This commit is contained in:
Tyera Eulberg 2021-08-11 01:04:00 -06:00 committed by GitHub
parent c4f2e5f88c
commit 5970083b4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 190 additions and 128 deletions

View File

@ -62,7 +62,7 @@ impl BanksClient {
&mut self, &mut self,
ctx: Context, ctx: Context,
commitment: CommitmentLevel, commitment: CommitmentLevel,
) -> impl Future<Output = io::Result<(FeeCalculator, Hash, Slot)>> + '_ { ) -> impl Future<Output = io::Result<(FeeCalculator, Hash, u64)>> + '_ {
self.inner self.inner
.get_fees_with_commitment_and_context(ctx, commitment) .get_fees_with_commitment_and_context(ctx, commitment)
} }
@ -84,6 +84,14 @@ impl BanksClient {
self.inner.get_slot_with_context(ctx, commitment) 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( pub fn process_transaction_with_commitment_and_context(
&mut self, &mut self,
ctx: Context, ctx: Context,
@ -119,7 +127,7 @@ impl BanksClient {
/// use them to calculate the transaction fee. /// use them to calculate the transaction fee.
pub fn get_fees( pub fn get_fees(
&mut self, &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()) self.get_fees_with_commitment_and_context(context::current(), CommitmentLevel::default())
} }
@ -195,12 +203,18 @@ impl BanksClient {
self.process_transactions_with_commitment(transactions, CommitmentLevel::default()) self.process_transactions_with_commitment(transactions, CommitmentLevel::default())
} }
/// Return the most recent rooted slot height. All transactions at or below this 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 height. /// 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>> + '_ { pub fn get_root_slot(&mut self) -> impl Future<Output = io::Result<Slot>> + '_ {
self.get_slot_with_context(context::current(), CommitmentLevel::default()) 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 /// 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. /// commitment level. If the account is not found, None is returned.
pub fn get_account_with_commitment( pub fn get_account_with_commitment(
@ -386,7 +400,7 @@ mod tests {
Runtime::new()?.block_on(async { Runtime::new()?.block_on(async {
let client_transport = start_local_server(bank_forks, block_commitment_cache).await; let client_transport = start_local_server(bank_forks, block_commitment_cache).await;
let mut banks_client = start_client(client_transport).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 transaction = Transaction::new(&[&genesis.mint_keypair], message, recent_blockhash);
let signature = transaction.signatures[0]; let signature = transaction.signatures[0];
banks_client.send_transaction(transaction).await?; banks_client.send_transaction(transaction).await?;
@ -394,8 +408,8 @@ mod tests {
let mut status = banks_client.get_transaction_status(signature).await?; let mut status = banks_client.get_transaction_status(signature).await?;
while status.is_none() { while status.is_none() {
let root_slot = banks_client.get_root_slot().await?; let root_block_height = banks_client.get_root_block_height().await?;
if root_slot > last_valid_slot { if root_block_height > last_valid_block_height {
break; break;
} }
sleep(Duration::from_millis(100)).await; sleep(Duration::from_millis(100)).await;

View File

@ -34,6 +34,7 @@ pub trait Banks {
async fn get_transaction_status_with_context(signature: Signature) async fn get_transaction_status_with_context(signature: Signature)
-> Option<TransactionStatus>; -> Option<TransactionStatus>;
async fn get_slot_with_context(commitment: CommitmentLevel) -> Slot; 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( async fn process_transaction_with_commitment_and_context(
transaction: Transaction, transaction: Transaction,
commitment: CommitmentLevel, commitment: CommitmentLevel,

View File

@ -110,7 +110,7 @@ impl BanksServer {
self, self,
signature: &Signature, signature: &Signature,
blockhash: &Hash, blockhash: &Hash,
last_valid_slot: Slot, last_valid_block_height: u64,
commitment: CommitmentLevel, commitment: CommitmentLevel,
) -> Option<transaction::Result<()>> { ) -> Option<transaction::Result<()>> {
let mut status = self let mut status = self
@ -119,7 +119,7 @@ impl BanksServer {
while status.is_none() { while status.is_none() {
sleep(Duration::from_millis(200)).await; sleep(Duration::from_millis(200)).await;
let bank = self.bank(commitment); let bank = self.bank(commitment);
if bank.slot() > last_valid_slot { if bank.block_height() > last_valid_block_height {
break; break;
} }
status = bank.get_signature_status_with_blockhash(signature, blockhash); status = bank.get_signature_status_with_blockhash(signature, blockhash);
@ -145,16 +145,19 @@ fn verify_transaction(
impl Banks for BanksServer { impl Banks for BanksServer {
async fn send_transaction_with_context(self, _: Context, transaction: Transaction) { async fn send_transaction_with_context(self, _: Context, transaction: Transaction) {
let blockhash = &transaction.message.recent_blockhash; let blockhash = &transaction.message.recent_blockhash;
let last_valid_slot = self let last_valid_block_height = self
.bank_forks .bank_forks
.read() .read()
.unwrap() .unwrap()
.root_bank() .root_bank()
.get_blockhash_last_valid_slot(blockhash) .get_blockhash_last_valid_block_height(blockhash)
.unwrap(); .unwrap();
let signature = transaction.signatures.get(0).cloned().unwrap_or_default(); let signature = transaction.signatures.get(0).cloned().unwrap_or_default();
let info = let info = TransactionInfo::new(
TransactionInfo::new(signature, serialize(&transaction).unwrap(), last_valid_slot); signature,
serialize(&transaction).unwrap(),
last_valid_block_height,
);
self.transaction_sender.send(info).unwrap(); self.transaction_sender.send(info).unwrap();
} }
@ -162,11 +165,13 @@ impl Banks for BanksServer {
self, self,
_: Context, _: Context,
commitment: CommitmentLevel, commitment: CommitmentLevel,
) -> (FeeCalculator, Hash, Slot) { ) -> (FeeCalculator, Hash, u64) {
let bank = self.bank(commitment); let bank = self.bank(commitment);
let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator(); let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator();
let last_valid_slot = bank.get_blockhash_last_valid_slot(&blockhash).unwrap(); let last_valid_block_height = bank
(fee_calculator, blockhash, last_valid_slot) .get_blockhash_last_valid_block_height(&blockhash)
.unwrap();
(fee_calculator, blockhash, last_valid_block_height)
} }
async fn get_transaction_status_with_context( async fn get_transaction_status_with_context(
@ -209,6 +214,10 @@ impl Banks for BanksServer {
self.slot(commitment) 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( async fn process_transaction_with_commitment_and_context(
self, self,
_: Context, _: Context,
@ -223,18 +232,21 @@ impl Banks for BanksServer {
} }
let blockhash = &transaction.message.recent_blockhash; let blockhash = &transaction.message.recent_blockhash;
let last_valid_slot = self let last_valid_block_height = self
.bank_forks .bank_forks
.read() .read()
.unwrap() .unwrap()
.root_bank() .root_bank()
.get_blockhash_last_valid_slot(blockhash) .get_blockhash_last_valid_block_height(blockhash)
.unwrap(); .unwrap();
let signature = transaction.signatures.get(0).cloned().unwrap_or_default(); let signature = transaction.signatures.get(0).cloned().unwrap_or_default();
let info = let info = TransactionInfo::new(
TransactionInfo::new(signature, serialize(&transaction).unwrap(), last_valid_slot); signature,
serialize(&transaction).unwrap(),
last_valid_block_height,
);
self.transaction_sender.send(info).unwrap(); 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 .await
} }

View File

@ -2,7 +2,7 @@
use log::*; use log::*;
use solana_metrics::{datapoint_warn, inc_new_counter_info}; use solana_metrics::{datapoint_warn, inc_new_counter_info};
use solana_runtime::{bank::Bank, bank_forks::BankForks}; use solana_runtime::{bank::Bank, bank_forks::BankForks};
use solana_sdk::{clock::Slot, signature::Signature}; use solana_sdk::signature::Signature;
use std::{ use std::{
collections::HashMap, collections::HashMap,
net::{SocketAddr, UdpSocket}, net::{SocketAddr, UdpSocket},
@ -24,15 +24,19 @@ pub struct SendTransactionService {
pub struct TransactionInfo { pub struct TransactionInfo {
pub signature: Signature, pub signature: Signature,
pub wire_transaction: Vec<u8>, pub wire_transaction: Vec<u8>,
pub last_valid_slot: Slot, pub last_valid_block_height: u64,
} }
impl TransactionInfo { 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 { Self {
signature, signature,
wire_transaction, wire_transaction,
last_valid_slot, last_valid_block_height,
} }
} }
} }
@ -124,7 +128,7 @@ impl SendTransactionService {
result.rooted += 1; result.rooted += 1;
inc_new_counter_info!("send_transaction_service-rooted", 1); inc_new_counter_info!("send_transaction_service-rooted", 1);
false 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); info!("Dropping expired transaction: {}", signature);
result.expired += 1; result.expired += 1;
inc_new_counter_info!("send_transaction_service-expired", 1); inc_new_counter_info!("send_transaction_service-expired", 1);

View File

@ -23,6 +23,7 @@ use solana_client::{
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig}, rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType}, rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS, rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
rpc_response::Fees,
tpu_client::{TpuClient, TpuClientConfig}, tpu_client::{TpuClient, TpuClientConfig},
}; };
use solana_rbpf::{ use solana_rbpf::{
@ -35,7 +36,6 @@ use solana_sdk::{
account_utils::StateMut, account_utils::StateMut,
bpf_loader, bpf_loader_deprecated, bpf_loader, bpf_loader_deprecated,
bpf_loader_upgradeable::{self, UpgradeableLoaderState}, bpf_loader_upgradeable::{self, UpgradeableLoaderState},
clock::Slot,
commitment_config::CommitmentConfig, commitment_config::CommitmentConfig,
instruction::Instruction, instruction::Instruction,
instruction::InstructionError, instruction::InstructionError,
@ -1943,8 +1943,12 @@ fn send_deploy_messages(
if let Some(write_messages) = write_messages { if let Some(write_messages) = write_messages {
if let Some(write_signer) = write_signer { if let Some(write_signer) = write_signer {
trace!("Writing program data"); trace!("Writing program data");
let (blockhash, _, last_valid_slot) = rpc_client let Fees {
.get_recent_blockhash_with_commitment(config.commitment)? blockhash,
last_valid_block_height,
..
} = rpc_client
.get_fees_with_commitment(config.commitment)?
.value; .value;
let mut write_transactions = vec![]; let mut write_transactions = vec![];
for message in write_messages.iter() { for message in write_messages.iter() {
@ -1959,7 +1963,7 @@ fn send_deploy_messages(
write_transactions, write_transactions,
&[payer_signer, write_signer], &[payer_signer, write_signer],
config.commitment, config.commitment,
last_valid_slot, last_valid_block_height,
) )
.map_err(|err| format!("Data writes to account failed: {}", err))?; .map_err(|err| format!("Data writes to account failed: {}", err))?;
} }
@ -2029,7 +2033,7 @@ fn send_and_confirm_transactions_with_spinner<T: Signers>(
mut transactions: Vec<Transaction>, mut transactions: Vec<Transaction>,
signer_keys: &T, signer_keys: &T,
commitment: CommitmentConfig, commitment: CommitmentConfig,
mut last_valid_slot: Slot, mut last_valid_block_height: u64,
) -> Result<(), Box<dyn error::Error>> { ) -> Result<(), Box<dyn error::Error>> {
let progress_bar = new_spinner_progress_bar(); let progress_bar = new_spinner_progress_bar();
let mut send_retries = 5; let mut send_retries = 5;
@ -2069,7 +2073,7 @@ fn send_and_confirm_transactions_with_spinner<T: Signers>(
// Collect statuses for all the transactions, drop those that are confirmed // Collect statuses for all the transactions, drop those that are confirmed
loop { loop {
let mut slot = 0; let mut block_height = 0;
let pending_signatures = pending_transactions.keys().cloned().collect::<Vec<_>>(); let pending_signatures = pending_transactions.keys().cloned().collect::<Vec<_>>();
for pending_signatures_chunk in for pending_signatures_chunk in
pending_signatures.chunks(MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS) pending_signatures.chunks(MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS)
@ -2094,12 +2098,12 @@ 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!( progress_bar.set_message(format!(
"[{}/{}] Transactions confirmed. Retrying in {} slots", "[{}/{}] Transactions confirmed. Retrying in {} blocks",
num_transactions - pending_transactions.len(), num_transactions - pending_transactions.len(),
num_transactions, num_transactions,
last_valid_slot.saturating_sub(slot) last_valid_block_height.saturating_sub(block_height)
)); ));
} }
@ -2107,7 +2111,7 @@ fn send_and_confirm_transactions_with_spinner<T: Signers>(
return Ok(()); return Ok(());
} }
if slot > last_valid_slot { if block_height > last_valid_block_height {
break; break;
} }
@ -2137,10 +2141,12 @@ fn send_and_confirm_transactions_with_spinner<T: Signers>(
send_retries -= 1; send_retries -= 1;
// Re-sign any failed transactions with a new blockhash and retry // Re-sign any failed transactions with a new blockhash and retry
let (blockhash, _fee_calculator, new_last_valid_slot) = rpc_client let Fees {
.get_recent_blockhash_with_commitment(commitment)? blockhash,
.value; last_valid_block_height: new_last_valid_block_height,
last_valid_slot = new_last_valid_slot; ..
} = rpc_client.get_fees_with_commitment(commitment)?.value;
last_valid_block_height = new_last_valid_block_height;
transactions = vec![]; transactions = vec![];
for (_, mut transaction) in pending_transactions.into_iter() { for (_, mut transaction) in pending_transactions.into_iter() {
transaction.try_sign(signer_keys, blockhash)?; transaction.try_sign(signer_keys, blockhash)?;

View File

@ -122,10 +122,10 @@ mod tests {
use crate::{ use crate::{
blockhash_query, blockhash_query,
rpc_request::RpcRequest, rpc_request::RpcRequest,
rpc_response::{Response, RpcFeeCalculator, RpcResponseContext}, rpc_response::{Response, RpcFeeCalculator, RpcFees, RpcResponseContext},
}; };
use clap::App; use clap::App;
use serde_json::{self, json, Value}; use serde_json::{self, json};
use solana_account_decoder::{UiAccount, UiAccountEncoding}; use solana_account_decoder::{UiAccount, UiAccountEncoding};
use solana_sdk::{account::Account, hash::hash, nonce, system_program}; use solana_sdk::{account::Account, hash::hash, nonce, system_program};
use std::collections::HashMap; use std::collections::HashMap;
@ -288,10 +288,12 @@ mod tests {
let rpc_fee_calc = FeeCalculator::new(42); let rpc_fee_calc = FeeCalculator::new(42);
let get_recent_blockhash_response = json!(Response { let get_recent_blockhash_response = json!(Response {
context: RpcResponseContext { slot: 1 }, context: RpcResponseContext { slot: 1 },
value: json!(( value: json!(RpcFees {
Value::String(rpc_blockhash.to_string()), blockhash: rpc_blockhash.to_string(),
serde_json::to_value(rpc_fee_calc.clone()).unwrap() fee_calculator: rpc_fee_calc.clone(),
)), last_valid_slot: 42,
last_valid_block_height: 42,
}),
}); });
let get_fee_calculator_for_blockhash_response = json!(Response { let get_fee_calculator_for_blockhash_response = json!(Response {
context: RpcResponseContext { slot: 1 }, context: RpcResponseContext { slot: 1 },
@ -300,10 +302,7 @@ mod tests {
}), }),
}); });
let mut mocks = HashMap::new(); let mut mocks = HashMap::new();
mocks.insert( mocks.insert(RpcRequest::GetFees, get_recent_blockhash_response.clone());
RpcRequest::GetRecentBlockhash,
get_recent_blockhash_response.clone(),
);
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks); let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!( assert_eq!(
BlockhashQuery::default() BlockhashQuery::default()
@ -312,10 +311,7 @@ mod tests {
(rpc_blockhash, rpc_fee_calc.clone()), (rpc_blockhash, rpc_fee_calc.clone()),
); );
let mut mocks = HashMap::new(); let mut mocks = HashMap::new();
mocks.insert( mocks.insert(RpcRequest::GetFees, get_recent_blockhash_response.clone());
RpcRequest::GetRecentBlockhash,
get_recent_blockhash_response.clone(),
);
mocks.insert( mocks.insert(
RpcRequest::GetFeeCalculatorForBlockhash, RpcRequest::GetFeeCalculatorForBlockhash,
get_fee_calculator_for_blockhash_response, get_fee_calculator_for_blockhash_response,
@ -328,10 +324,7 @@ mod tests {
(test_blockhash, rpc_fee_calc), (test_blockhash, rpc_fee_calc),
); );
let mut mocks = HashMap::new(); let mut mocks = HashMap::new();
mocks.insert( mocks.insert(RpcRequest::GetFees, get_recent_blockhash_response);
RpcRequest::GetRecentBlockhash,
get_recent_blockhash_response,
);
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks); let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!( assert_eq!(
BlockhashQuery::None(test_blockhash) BlockhashQuery::None(test_blockhash)

View File

@ -1,9 +0,0 @@
use crate::{fee_calculator::FeeCalculator, hash::Hash};
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Fees {
pub blockhash: Hash,
pub fee_calculator: FeeCalculator,
pub last_valid_block_height: u64,
}

View File

@ -6,7 +6,7 @@ use {
rpc_config::RpcBlockProductionConfig, rpc_config::RpcBlockProductionConfig,
rpc_request::RpcRequest, rpc_request::RpcRequest,
rpc_response::{ rpc_response::{
Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange, Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange, RpcFees,
RpcResponseContext, RpcSimulateTransactionResult, RpcStakeActivation, RpcSupply, RpcResponseContext, RpcSimulateTransactionResult, RpcStakeActivation, RpcSupply,
RpcVersionInfo, RpcVoteAccountStatus, StakeActivationState, RpcVersionInfo, RpcVoteAccountStatus, StakeActivationState,
}, },
@ -123,6 +123,16 @@ impl RpcSender for MockSender {
context: RpcResponseContext { slot: 1 }, context: RpcResponseContext { slot: 1 },
value: serde_json::to_value(FeeRateGovernor::default()).unwrap(), value: serde_json::to_value(FeeRateGovernor::default()).unwrap(),
})?, })?,
"getFees" => serde_json::to_value(Response {
context: RpcResponseContext { slot: 1 },
value: serde_json::to_value(RpcFees {
blockhash: PUBKEY.to_string(),
fee_calculator: FeeCalculator::default(),
last_valid_slot: 42,
last_valid_block_height: 42,
})
.unwrap(),
})?,
"getSignatureStatuses" => { "getSignatureStatuses" => {
let status: transaction::Result<()> = if self.url == "account_in_use" { let status: transaction::Result<()> = if self.url == "account_in_use" {
Err(TransactionError::AccountInUse) Err(TransactionError::AccountInUse)

View File

@ -544,6 +544,7 @@ impl JsonRpcRequestProcessor {
fn get_fees(&self, commitment: Option<CommitmentConfig>) -> RpcResponse<RpcFees> { fn get_fees(&self, commitment: Option<CommitmentConfig>) -> RpcResponse<RpcFees> {
let bank = self.bank(commitment); let bank = self.bank(commitment);
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash(); let (blockhash, fee_calculator) = bank.confirmed_last_blockhash();
#[allow(deprecated)]
let last_valid_slot = bank let last_valid_slot = bank
.get_blockhash_last_valid_slot(&blockhash) .get_blockhash_last_valid_slot(&blockhash)
.expect("bank blockhash queue should contain blockhash"); .expect("bank blockhash queue should contain blockhash");
@ -2140,7 +2141,7 @@ fn _send_transaction(
meta: JsonRpcRequestProcessor, meta: JsonRpcRequestProcessor,
transaction: Transaction, transaction: Transaction,
wire_transaction: Vec<u8>, wire_transaction: Vec<u8>,
last_valid_slot: Slot, last_valid_block_height: u64,
durable_nonce_info: Option<(Pubkey, Hash)>, durable_nonce_info: Option<(Pubkey, Hash)>,
) -> Result<String> { ) -> Result<String> {
if transaction.signatures.is_empty() { if transaction.signatures.is_empty() {
@ -2150,7 +2151,7 @@ fn _send_transaction(
let transaction_info = TransactionInfo::new( let transaction_info = TransactionInfo::new(
signature, signature,
wire_transaction, wire_transaction,
last_valid_slot, last_valid_block_height,
durable_nonce_info, durable_nonce_info,
); );
meta.transaction_sender meta.transaction_sender
@ -3233,7 +3234,9 @@ pub mod rpc_full {
} else { } else {
bank.confirmed_last_blockhash().0 bank.confirmed_last_blockhash().0
}; };
let last_valid_slot = bank.get_blockhash_last_valid_slot(&blockhash).unwrap_or(0); let last_valid_block_height = bank
.get_blockhash_last_valid_block_height(&blockhash)
.unwrap_or(0);
let transaction = let transaction =
request_airdrop_transaction(&faucet_addr, &pubkey, lamports, blockhash).map_err( request_airdrop_transaction(&faucet_addr, &pubkey, lamports, blockhash).map_err(
@ -3248,7 +3251,13 @@ pub mod rpc_full {
Error::internal_error() Error::internal_error()
})?; })?;
_send_transaction(meta, transaction, wire_transaction, last_valid_slot, None) _send_transaction(
meta,
transaction,
wire_transaction,
last_valid_block_height,
None,
)
} }
fn send_transaction( fn send_transaction(
@ -3267,8 +3276,8 @@ pub mod rpc_full {
.map(|commitment| CommitmentConfig { commitment }); .map(|commitment| CommitmentConfig { commitment });
let preflight_bank = &*meta.bank(preflight_commitment); let preflight_bank = &*meta.bank(preflight_commitment);
let mut last_valid_slot = preflight_bank let mut last_valid_block_height = preflight_bank
.get_blockhash_last_valid_slot(&transaction.message.recent_blockhash) .get_blockhash_last_valid_block_height(&transaction.message.recent_blockhash)
.unwrap_or(0); .unwrap_or(0);
let durable_nonce_info = solana_sdk::transaction::uses_durable_nonce(&transaction) let durable_nonce_info = solana_sdk::transaction::uses_durable_nonce(&transaction)
@ -3280,11 +3289,12 @@ pub mod rpc_full {
}) })
.map(|&pubkey| (pubkey, transaction.message.recent_blockhash)); .map(|&pubkey| (pubkey, transaction.message.recent_blockhash));
if durable_nonce_info.is_some() { if durable_nonce_info.is_some() {
// While it uses a defined constant, this last_valid_slot value is chosen arbitrarily. // While it uses a defined constant, this last_valid_block_height value is chosen arbitrarily.
// It provides a fallback timeout for durable-nonce transaction retries in case of // It provides a fallback timeout for durable-nonce transaction retries in case of
// malicious packing of the retry queue. Durable-nonce transactions are otherwise // malicious packing of the retry queue. Durable-nonce transactions are otherwise
// retried until the nonce is advanced. // retried until the nonce is advanced.
last_valid_slot = preflight_bank.slot() + MAX_RECENT_BLOCKHASHES as u64; last_valid_block_height =
preflight_bank.block_height() + MAX_RECENT_BLOCKHASHES as u64;
} }
if !config.skip_preflight { if !config.skip_preflight {
@ -3345,7 +3355,7 @@ pub mod rpc_full {
meta, meta,
transaction, transaction,
wire_transaction, wire_transaction,
last_valid_slot, last_valid_block_height,
durable_nonce_info, durable_nonce_info,
) )
} }

View File

@ -6,10 +6,7 @@ use {
solana_poh::poh_recorder::PohRecorder, solana_poh::poh_recorder::PohRecorder,
solana_runtime::{bank::Bank, bank_forks::BankForks}, solana_runtime::{bank::Bank, bank_forks::BankForks},
solana_sdk::{ solana_sdk::{
clock::{Slot, NUM_CONSECUTIVE_LEADER_SLOTS}, clock::NUM_CONSECUTIVE_LEADER_SLOTS, hash::Hash, nonce_account, pubkey::Pubkey,
hash::Hash,
nonce_account,
pubkey::Pubkey,
signature::Signature, signature::Signature,
}, },
std::{ std::{
@ -34,7 +31,7 @@ pub struct SendTransactionService {
pub struct TransactionInfo { pub struct TransactionInfo {
pub signature: Signature, pub signature: Signature,
pub wire_transaction: Vec<u8>, pub wire_transaction: Vec<u8>,
pub last_valid_slot: Slot, pub last_valid_block_height: u64,
pub durable_nonce_info: Option<(Pubkey, Hash)>, pub durable_nonce_info: Option<(Pubkey, Hash)>,
} }
@ -42,13 +39,13 @@ impl TransactionInfo {
pub fn new( pub fn new(
signature: Signature, signature: Signature,
wire_transaction: Vec<u8>, wire_transaction: Vec<u8>,
last_valid_slot: Slot, last_valid_block_height: u64,
durable_nonce_info: Option<(Pubkey, Hash)>, durable_nonce_info: Option<(Pubkey, Hash)>,
) -> Self { ) -> Self {
Self { Self {
signature, signature,
wire_transaction, wire_transaction,
last_valid_slot, last_valid_block_height,
durable_nonce_info, durable_nonce_info,
} }
} }
@ -244,7 +241,7 @@ impl SendTransactionService {
return false; return false;
} }
} }
if transaction_info.last_valid_slot < root_bank.slot() { if transaction_info.last_valid_block_height < root_bank.block_height() {
info!("Dropping expired transaction: {}", signature); info!("Dropping expired transaction: {}", signature);
result.expired += 1; result.expired += 1;
inc_new_counter_info!("send_transaction_service-expired", 1); inc_new_counter_info!("send_transaction_service-expired", 1);
@ -391,7 +388,12 @@ mod test {
info!("Expired transactions are dropped..."); info!("Expired transactions are dropped...");
transactions.insert( transactions.insert(
Signature::default(), Signature::default(),
TransactionInfo::new(Signature::default(), vec![], root_bank.slot() - 1, None), TransactionInfo::new(
Signature::default(),
vec![],
root_bank.block_height() - 1,
None,
),
); );
let result = SendTransactionService::process_transactions( let result = SendTransactionService::process_transactions(
&working_bank, &working_bank,
@ -414,7 +416,7 @@ mod test {
info!("Rooted transactions are dropped..."); info!("Rooted transactions are dropped...");
transactions.insert( transactions.insert(
rooted_signature, rooted_signature,
TransactionInfo::new(rooted_signature, vec![], working_bank.slot(), None), TransactionInfo::new(rooted_signature, vec![], working_bank.block_height(), None),
); );
let result = SendTransactionService::process_transactions( let result = SendTransactionService::process_transactions(
&working_bank, &working_bank,
@ -437,7 +439,7 @@ mod test {
info!("Failed transactions are dropped..."); info!("Failed transactions are dropped...");
transactions.insert( transactions.insert(
failed_signature, failed_signature,
TransactionInfo::new(failed_signature, vec![], working_bank.slot(), None), TransactionInfo::new(failed_signature, vec![], working_bank.block_height(), None),
); );
let result = SendTransactionService::process_transactions( let result = SendTransactionService::process_transactions(
&working_bank, &working_bank,
@ -460,7 +462,12 @@ mod test {
info!("Non-rooted transactions are kept..."); info!("Non-rooted transactions are kept...");
transactions.insert( transactions.insert(
non_rooted_signature, non_rooted_signature,
TransactionInfo::new(non_rooted_signature, vec![], working_bank.slot(), None), TransactionInfo::new(
non_rooted_signature,
vec![],
working_bank.block_height(),
None,
),
); );
let result = SendTransactionService::process_transactions( let result = SendTransactionService::process_transactions(
&working_bank, &working_bank,
@ -484,7 +491,12 @@ mod test {
info!("Unknown transactions are retried..."); info!("Unknown transactions are retried...");
transactions.insert( transactions.insert(
Signature::default(), Signature::default(),
TransactionInfo::new(Signature::default(), vec![], working_bank.slot(), None), TransactionInfo::new(
Signature::default(),
vec![],
working_bank.block_height(),
None,
),
); );
let result = SendTransactionService::process_transactions( let result = SendTransactionService::process_transactions(
&working_bank, &working_bank,
@ -542,7 +554,7 @@ mod test {
.transfer(2, &mint_keypair, &mint_keypair.pubkey()) .transfer(2, &mint_keypair, &mint_keypair.pubkey())
.unwrap(); .unwrap();
let last_valid_slot = working_bank.slot() + 300; let last_valid_block_height = working_bank.block_height() + 300;
let failed_signature = { let failed_signature = {
let blockhash = working_bank.last_blockhash(); let blockhash = working_bank.last_blockhash();
@ -561,7 +573,7 @@ mod test {
TransactionInfo::new( TransactionInfo::new(
rooted_signature, rooted_signature,
vec![], vec![],
last_valid_slot, last_valid_block_height,
Some((nonce_address, durable_nonce)), Some((nonce_address, durable_nonce)),
), ),
); );
@ -588,7 +600,7 @@ mod test {
TransactionInfo::new( TransactionInfo::new(
rooted_signature, rooted_signature,
vec![], vec![],
last_valid_slot, last_valid_block_height,
Some((nonce_address, Hash::new_unique())), Some((nonce_address, Hash::new_unique())),
), ),
); );
@ -617,7 +629,7 @@ mod test {
TransactionInfo::new( TransactionInfo::new(
Signature::default(), Signature::default(),
vec![], vec![],
last_valid_slot, last_valid_block_height,
Some((nonce_address, Hash::new_unique())), Some((nonce_address, Hash::new_unique())),
), ),
); );
@ -638,13 +650,13 @@ mod test {
..ProcessTransactionsResult::default() ..ProcessTransactionsResult::default()
} }
); );
// ... or last_valid_slot timeout has passed // ... or last_valid_block_height timeout has passed
transactions.insert( transactions.insert(
Signature::default(), Signature::default(),
TransactionInfo::new( TransactionInfo::new(
Signature::default(), Signature::default(),
vec![], vec![],
root_bank.slot() - 1, root_bank.block_height() - 1,
Some((nonce_address, durable_nonce)), Some((nonce_address, durable_nonce)),
), ),
); );
@ -672,7 +684,7 @@ mod test {
TransactionInfo::new( TransactionInfo::new(
failed_signature, failed_signature,
vec![], vec![],
last_valid_slot, last_valid_block_height,
Some((nonce_address, Hash::new_unique())), // runtime should advance nonce on failed transactions Some((nonce_address, Hash::new_unique())), // runtime should advance nonce on failed transactions
), ),
); );
@ -700,7 +712,7 @@ mod test {
TransactionInfo::new( TransactionInfo::new(
non_rooted_signature, non_rooted_signature,
vec![], vec![],
last_valid_slot, last_valid_block_height,
Some((nonce_address, Hash::new_unique())), // runtime advances nonce when transaction lands Some((nonce_address, Hash::new_unique())), // runtime advances nonce when transaction lands
), ),
); );
@ -729,7 +741,7 @@ mod test {
TransactionInfo::new( TransactionInfo::new(
Signature::default(), Signature::default(),
vec![], vec![],
last_valid_slot, last_valid_block_height,
Some((nonce_address, durable_nonce)), Some((nonce_address, durable_nonce)),
), ),
); );

View File

@ -2692,7 +2692,10 @@ impl Bank {
&self.fee_rate_governor &self.fee_rate_governor
} }
// DEPRECATED #[deprecated(
since = "1.6.11",
note = "Please use `get_blockhash_last_valid_block_height`"
)]
pub fn get_blockhash_last_valid_slot(&self, blockhash: &Hash) -> Option<Slot> { pub fn get_blockhash_last_valid_slot(&self, blockhash: &Hash) -> Option<Slot> {
let blockhash_queue = self.blockhash_queue.read().unwrap(); let blockhash_queue = self.blockhash_queue.read().unwrap();
// This calculation will need to be updated to consider epoch boundaries if BlockhashQueue // This calculation will need to be updated to consider epoch boundaries if BlockhashQueue

View File

@ -156,6 +156,7 @@ impl SyncClient for BankClient {
_commitment_config: CommitmentConfig, _commitment_config: CommitmentConfig,
) -> Result<(Hash, FeeCalculator, u64)> { ) -> Result<(Hash, FeeCalculator, u64)> {
let (blockhash, fee_calculator) = self.bank.last_blockhash_with_fee_calculator(); let (blockhash, fee_calculator) = self.bank.last_blockhash_with_fee_calculator();
#[allow(deprecated)]
let last_valid_slot = self let last_valid_slot = self
.bank .bank
.get_blockhash_last_valid_slot(&blockhash) .get_blockhash_last_valid_slot(&blockhash)

View File

@ -19,6 +19,7 @@ use solana_client::{
rpc_client::RpcClient, rpc_client::RpcClient,
rpc_config::RpcSendTransactionConfig, rpc_config::RpcSendTransactionConfig,
rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS, rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
rpc_response::Fees,
}; };
use solana_sdk::{ use solana_sdk::{
clock::Slot, clock::Slot,
@ -386,8 +387,12 @@ fn send_messages(
if args.dry_run { if args.dry_run {
Ok((Transaction::new_unsigned(message), std::u64::MAX)) Ok((Transaction::new_unsigned(message), std::u64::MAX))
} else { } else {
let (blockhash, _fee_calculator, last_valid_slot) = client let Fees {
.get_recent_blockhash_with_commitment(CommitmentConfig::default())? blockhash,
last_valid_block_height,
..
} = client
.get_fees_with_commitment(CommitmentConfig::default())?
.value; .value;
let transaction = Transaction::new(&signers, message, blockhash); let transaction = Transaction::new(&signers, message, blockhash);
let config = RpcSendTransactionConfig { let config = RpcSendTransactionConfig {
@ -395,11 +400,11 @@ fn send_messages(
..RpcSendTransactionConfig::default() ..RpcSendTransactionConfig::default()
}; };
client.send_transaction_with_config(&transaction, config)?; client.send_transaction_with_config(&transaction, config)?;
Ok((transaction, last_valid_slot)) Ok((transaction, last_valid_block_height))
} }
}; };
match result { match result {
Ok((transaction, last_valid_slot)) => { Ok((transaction, last_valid_block_height)) => {
let new_stake_account_address_option = let new_stake_account_address_option =
args.stake_args.as_ref().map(|_| &new_stake_account_address); args.stake_args.as_ref().map(|_| &new_stake_account_address);
db::set_transaction_info( db::set_transaction_info(
@ -409,7 +414,7 @@ fn send_messages(
&transaction, &transaction,
new_stake_account_address_option, new_stake_account_address_option,
false, false,
last_valid_slot, last_valid_block_height,
lockup_date, lockup_date,
)?; )?;
} }
@ -658,7 +663,7 @@ fn update_finalized_transactions(
if info.finalized_date.is_some() { if info.finalized_date.is_some() {
None None
} else { } else {
Some((&info.transaction, info.last_valid_slot)) Some((&info.transaction, info.last_valid_block_height))
} }
}) })
.collect(); .collect();
@ -700,8 +705,8 @@ fn log_transaction_confirmations(
statuses: Vec<Option<TransactionStatus>>, statuses: Vec<Option<TransactionStatus>>,
confirmations: &mut Option<usize>, confirmations: &mut Option<usize>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let root_slot = client.get_slot()?; let finalized_block_height = client.get_block_height()?;
for ((transaction, last_valid_slot), opt_transaction_status) in unconfirmed_transactions for ((transaction, last_valid_block_height), opt_transaction_status) in unconfirmed_transactions
.into_iter() .into_iter()
.zip(statuses.into_iter()) .zip(statuses.into_iter())
{ {
@ -709,8 +714,8 @@ fn log_transaction_confirmations(
db, db,
&transaction.signatures[0], &transaction.signatures[0],
opt_transaction_status, opt_transaction_status,
last_valid_slot, last_valid_block_height,
root_slot, finalized_block_height,
) { ) {
Ok(Some(confs)) => { Ok(Some(confs)) => {
*confirmations = Some(cmp::min(confs, confirmations.unwrap_or(usize::MAX))); *confirmations = Some(cmp::min(confs, confirmations.unwrap_or(usize::MAX)));
@ -1982,7 +1987,7 @@ mod tests {
let sender = Keypair::new(); let sender = Keypair::new();
let recipient = Pubkey::new_unique(); let recipient = Pubkey::new_unique();
let amount = sol_to_lamports(1.0); let amount = sol_to_lamports(1.0);
let last_valid_slot = 222; let last_valid_block_height = 222;
let transaction = transfer(&client, amount, &sender, &recipient).unwrap(); let transaction = transfer(&client, amount, &sender, &recipient).unwrap();
// Queue db data // Queue db data
@ -1993,7 +1998,7 @@ mod tests {
&transaction, &transaction,
None, None,
false, false,
last_valid_slot, last_valid_block_height,
None, None,
) )
.unwrap(); .unwrap();
@ -2082,7 +2087,7 @@ mod tests {
new_stake_account_address: None, new_stake_account_address: None,
finalized_date: None, finalized_date: None,
transaction, transaction,
last_valid_slot, last_valid_block_height,
lockup_date: None, lockup_date: None,
} }
); );
@ -2104,7 +2109,7 @@ mod tests {
let sender = Keypair::new(); let sender = Keypair::new();
let recipient = Pubkey::new_unique(); let recipient = Pubkey::new_unique();
let amount = sol_to_lamports(1.0); let amount = sol_to_lamports(1.0);
let last_valid_slot = 222; let last_valid_block_height = 222;
let transaction = transfer(&client, amount, &sender, &recipient).unwrap(); let transaction = transfer(&client, amount, &sender, &recipient).unwrap();
// Queue db data // Queue db data
@ -2115,7 +2120,7 @@ mod tests {
&transaction, &transaction,
None, None,
false, false,
last_valid_slot, last_valid_block_height,
None, None,
) )
.unwrap(); .unwrap();
@ -2186,7 +2191,7 @@ mod tests {
new_stake_account_address: None, new_stake_account_address: None,
finalized_date: None, finalized_date: None,
transaction, transaction,
last_valid_slot, last_valid_block_height,
lockup_date: None, lockup_date: None,
})); }));
assert!(transaction_info.contains(&TransactionInfo { assert!(transaction_info.contains(&TransactionInfo {
@ -2195,7 +2200,7 @@ mod tests {
new_stake_account_address: None, new_stake_account_address: None,
finalized_date: None, finalized_date: None,
transaction: Transaction::new_unsigned(message), transaction: Transaction::new_unsigned(message),
last_valid_slot: std::u64::MAX, last_valid_block_height: std::u64::MAX,
lockup_date: None, lockup_date: None,
})); }));
@ -2281,7 +2286,7 @@ mod tests {
let sender = Keypair::new(); let sender = Keypair::new();
let recipient = Pubkey::new_unique(); let recipient = Pubkey::new_unique();
let amount = sol_to_lamports(1.0); let amount = sol_to_lamports(1.0);
let last_valid_slot = 222; let last_valid_block_height = 222;
let transaction = transfer(&client, amount, &sender, &recipient).unwrap(); let transaction = transfer(&client, amount, &sender, &recipient).unwrap();
// Queue unconfirmed transaction into db // Queue unconfirmed transaction into db
@ -2292,7 +2297,7 @@ mod tests {
&transaction, &transaction,
None, None,
false, false,
last_valid_slot, last_valid_block_height,
None, None,
) )
.unwrap(); .unwrap();
@ -2374,7 +2379,7 @@ mod tests {
let sender = Keypair::new(); let sender = Keypair::new();
let recipient = Pubkey::new_unique(); let recipient = Pubkey::new_unique();
let amount = sol_to_lamports(1.0); let amount = sol_to_lamports(1.0);
let last_valid_slot = 222; let last_valid_block_height = 222;
let transaction = transfer(&client, amount, &sender, &recipient).unwrap(); let transaction = transfer(&client, amount, &sender, &recipient).unwrap();
// Queue unconfirmed transaction into db // Queue unconfirmed transaction into db
@ -2385,7 +2390,7 @@ mod tests {
&transaction, &transaction,
None, None,
false, false,
last_valid_slot, last_valid_block_height,
None, None,
) )
.unwrap(); .unwrap();

View File

@ -12,7 +12,7 @@ pub struct TransactionInfo {
pub new_stake_account_address: Option<Pubkey>, pub new_stake_account_address: Option<Pubkey>,
pub finalized_date: Option<DateTime<Utc>>, pub finalized_date: Option<DateTime<Utc>>,
pub transaction: Transaction, pub transaction: Transaction,
pub last_valid_slot: Slot, pub last_valid_block_height: Slot,
pub lockup_date: Option<DateTime<Utc>>, pub lockup_date: Option<DateTime<Utc>>,
} }
@ -38,7 +38,7 @@ impl Default for TransactionInfo {
new_stake_account_address: None, new_stake_account_address: None,
finalized_date: None, finalized_date: None,
transaction, transaction,
last_valid_slot: 0, last_valid_block_height: 0,
lockup_date: None, lockup_date: None,
} }
} }
@ -108,7 +108,7 @@ pub fn set_transaction_info(
transaction: &Transaction, transaction: &Transaction,
new_stake_account_address: Option<&Pubkey>, new_stake_account_address: Option<&Pubkey>,
finalized: bool, finalized: bool,
last_valid_slot: Slot, last_valid_block_height: u64,
lockup_date: Option<DateTime<Utc>>, lockup_date: Option<DateTime<Utc>>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let finalized_date = if finalized { Some(Utc::now()) } else { None }; let finalized_date = if finalized { Some(Utc::now()) } else { None };
@ -118,7 +118,7 @@ pub fn set_transaction_info(
new_stake_account_address: new_stake_account_address.cloned(), new_stake_account_address: new_stake_account_address.cloned(),
finalized_date, finalized_date,
transaction: transaction.clone(), transaction: transaction.clone(),
last_valid_slot, last_valid_block_height,
lockup_date, lockup_date,
}; };
let signature = transaction.signatures[0]; let signature = transaction.signatures[0];
@ -134,11 +134,11 @@ pub fn update_finalized_transaction(
db: &mut PickleDb, db: &mut PickleDb,
signature: &Signature, signature: &Signature,
opt_transaction_status: Option<TransactionStatus>, opt_transaction_status: Option<TransactionStatus>,
last_valid_slot: Slot, last_valid_block_height: u64,
root_slot: Slot, finalized_block_height: u64,
) -> Result<Option<usize>, Error> { ) -> Result<Option<usize>, Error> {
if opt_transaction_status.is_none() { if opt_transaction_status.is_none() {
if root_slot > last_valid_slot { if finalized_block_height > last_valid_block_height {
eprintln!( eprintln!(
"Signature not found {} and blockhash expired. Transaction either dropped or the validator purged the transaction status.", "Signature not found {} and blockhash expired. Transaction either dropped or the validator purged the transaction status.",
signature signature