Deprecate FeeCalculator returning APIs (#19120)

This commit is contained in:
Jack May 2021-08-13 09:08:20 -07:00 committed by GitHub
parent 26e963f436
commit 0b50bb2b20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 1119 additions and 463 deletions

View File

@ -12,6 +12,7 @@ use solana_measure::measure::Measure;
use solana_runtime::inline_spl_token_v2_0; use solana_runtime::inline_spl_token_v2_0;
use solana_sdk::{ use solana_sdk::{
commitment_config::CommitmentConfig, commitment_config::CommitmentConfig,
instruction::{AccountMeta, Instruction},
message::Message, message::Message,
pubkey::Pubkey, pubkey::Pubkey,
rpc_port::DEFAULT_RPC_PORT, rpc_port::DEFAULT_RPC_PORT,
@ -33,10 +34,6 @@ use std::{
time::{Duration, Instant}, time::{Duration, Instant},
}; };
// Create and close messages both require 2 signatures; if transaction construction changes, update
// this magic number
const NUM_SIGNATURES: u64 = 2;
pub fn airdrop_lamports( pub fn airdrop_lamports(
client: &RpcClient, client: &RpcClient,
faucet_addr: &SocketAddr, faucet_addr: &SocketAddr,
@ -55,7 +52,7 @@ pub fn airdrop_lamports(
id.pubkey(), id.pubkey(),
); );
let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap(); let blockhash = client.get_latest_blockhash().unwrap();
match request_airdrop_transaction(faucet_addr, &id.pubkey(), airdrop_amount, blockhash) { match request_airdrop_transaction(faucet_addr, &id.pubkey(), airdrop_amount, blockhash) {
Ok(transaction) => { Ok(transaction) => {
let mut tries = 0; let mut tries = 0;
@ -375,10 +372,10 @@ fn run_accounts_bench(
info!("Targeting {}", entrypoint_addr); info!("Targeting {}", entrypoint_addr);
let mut last_blockhash = Instant::now(); let mut latest_blockhash = Instant::now();
let mut last_log = Instant::now(); let mut last_log = Instant::now();
let mut count = 0; let mut count = 0;
let mut recent_blockhash = client.get_recent_blockhash().expect("blockhash"); let mut blockhash = client.get_latest_blockhash().expect("blockhash");
let mut tx_sent_count = 0; let mut tx_sent_count = 0;
let mut total_accounts_created = 0; let mut total_accounts_created = 0;
let mut total_accounts_closed = 0; let mut total_accounts_closed = 0;
@ -406,16 +403,32 @@ fn run_accounts_bench(
let executor = TransactionExecutor::new(entrypoint_addr); let executor = TransactionExecutor::new(entrypoint_addr);
// Create and close messages both require 2 signatures, fake a 2 signature message to calculate fees
let message = Message::new(
&[
Instruction::new_with_bytes(
Pubkey::new_unique(),
&[],
vec![AccountMeta::new(Pubkey::new_unique(), true)],
),
Instruction::new_with_bytes(
Pubkey::new_unique(),
&[],
vec![AccountMeta::new(Pubkey::new_unique(), true)],
),
],
None,
);
loop { loop {
if last_blockhash.elapsed().as_millis() > 10_000 { if latest_blockhash.elapsed().as_millis() > 10_000 {
recent_blockhash = client.get_recent_blockhash().expect("blockhash"); blockhash = client.get_latest_blockhash().expect("blockhash");
last_blockhash = Instant::now(); latest_blockhash = Instant::now();
} }
let fee = recent_blockhash let fee = client
.1 .get_fee_for_message(&blockhash, &message)
.lamports_per_signature .expect("get_fee_for_message");
.saturating_mul(NUM_SIGNATURES);
let lamports = min_balance + fee; let lamports = min_balance + fee;
for (i, balance) in balances.iter_mut().enumerate() { for (i, balance) in balances.iter_mut().enumerate() {
@ -464,7 +477,7 @@ fn run_accounts_bench(
mint, mint,
); );
let signers: Vec<&Keypair> = vec![keypair, &base_keypair]; let signers: Vec<&Keypair> = vec![keypair, &base_keypair];
Transaction::new(&signers, message, recent_blockhash.0) Transaction::new(&signers, message, blockhash)
}) })
.collect(); .collect();
balances[i] = balances[i].saturating_sub(lamports * txs.len() as u64); balances[i] = balances[i].saturating_sub(lamports * txs.len() as u64);
@ -496,7 +509,7 @@ fn run_accounts_bench(
mint.is_some(), mint.is_some(),
); );
let signers: Vec<&Keypair> = vec![payer_keypairs[0], &base_keypair]; let signers: Vec<&Keypair> = vec![payer_keypairs[0], &base_keypair];
Transaction::new(&signers, message, recent_blockhash.0) Transaction::new(&signers, message, blockhash)
}) })
.collect(); .collect();
balances[0] = balances[0].saturating_sub(fee * txs.len() as u64); balances[0] = balances[0].saturating_sub(fee * txs.len() as u64);

View File

@ -167,6 +167,7 @@ impl Banks for BanksServer {
commitment: CommitmentLevel, commitment: CommitmentLevel,
) -> (FeeCalculator, Hash, u64) { ) -> (FeeCalculator, Hash, u64) {
let bank = self.bank(commitment); let bank = self.bank(commitment);
#[allow(deprecated)]
let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator(); let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator();
let last_valid_block_height = bank let last_valid_block_height = bank
.get_blockhash_last_valid_block_height(&blockhash) .get_blockhash_last_valid_block_height(&blockhash)

View File

@ -10,8 +10,8 @@ use solana_sdk::{
client::Client, client::Client,
clock::{DEFAULT_S_PER_SLOT, MAX_PROCESSING_AGE}, clock::{DEFAULT_S_PER_SLOT, MAX_PROCESSING_AGE},
commitment_config::CommitmentConfig, commitment_config::CommitmentConfig,
fee_calculator::FeeCalculator,
hash::Hash, hash::Hash,
instruction::{AccountMeta, Instruction},
message::Message, message::Message,
pubkey::Pubkey, pubkey::Pubkey,
signature::{Keypair, Signer}, signature::{Keypair, Signer},
@ -45,14 +45,12 @@ pub type Result<T> = std::result::Result<T, BenchTpsError>;
pub type SharedTransactions = Arc<RwLock<VecDeque<Vec<(Transaction, u64)>>>>; pub type SharedTransactions = Arc<RwLock<VecDeque<Vec<(Transaction, u64)>>>>;
fn get_recent_blockhash<T: Client>(client: &T) -> (Hash, FeeCalculator) { fn get_latest_blockhash<T: Client>(client: &T) -> Hash {
loop { loop {
match client.get_recent_blockhash_with_commitment(CommitmentConfig::processed()) { match client.get_latest_blockhash_with_commitment(CommitmentConfig::processed()) {
Ok((blockhash, fee_calculator, _last_valid_slot)) => { Ok((blockhash, _)) => return blockhash,
return (blockhash, fee_calculator)
}
Err(err) => { Err(err) => {
info!("Couldn't get recent blockhash: {:?}", err); info!("Couldn't get last blockhash: {:?}", err);
sleep(Duration::from_secs(1)); sleep(Duration::from_secs(1));
} }
}; };
@ -239,19 +237,19 @@ where
let shared_txs: SharedTransactions = Arc::new(RwLock::new(VecDeque::new())); let shared_txs: SharedTransactions = Arc::new(RwLock::new(VecDeque::new()));
let recent_blockhash = Arc::new(RwLock::new(get_recent_blockhash(client.as_ref()).0)); let blockhash = Arc::new(RwLock::new(get_latest_blockhash(client.as_ref())));
let shared_tx_active_thread_count = Arc::new(AtomicIsize::new(0)); let shared_tx_active_thread_count = Arc::new(AtomicIsize::new(0));
let total_tx_sent_count = Arc::new(AtomicUsize::new(0)); let total_tx_sent_count = Arc::new(AtomicUsize::new(0));
let blockhash_thread = { let blockhash_thread = {
let exit_signal = exit_signal.clone(); let exit_signal = exit_signal.clone();
let recent_blockhash = recent_blockhash.clone(); let blockhash = blockhash.clone();
let client = client.clone(); let client = client.clone();
let id = id.pubkey(); let id = id.pubkey();
Builder::new() Builder::new()
.name("solana-blockhash-poller".to_string()) .name("solana-blockhash-poller".to_string())
.spawn(move || { .spawn(move || {
poll_blockhash(&exit_signal, &recent_blockhash, &client, &id); poll_blockhash(&exit_signal, &blockhash, &client, &id);
}) })
.unwrap() .unwrap()
}; };
@ -271,7 +269,7 @@ where
let start = Instant::now(); let start = Instant::now();
generate_chunked_transfers( generate_chunked_transfers(
recent_blockhash, blockhash,
&shared_txs, &shared_txs,
shared_tx_active_thread_count, shared_tx_active_thread_count,
source_keypair_chunks, source_keypair_chunks,
@ -402,7 +400,7 @@ fn poll_blockhash<T: Client>(
loop { loop {
let blockhash_updated = { let blockhash_updated = {
let old_blockhash = *blockhash.read().unwrap(); let old_blockhash = *blockhash.read().unwrap();
if let Ok((new_blockhash, _fee)) = client.get_new_blockhash(&old_blockhash) { if let Ok(new_blockhash) = client.get_new_latest_blockhash(&old_blockhash) {
*blockhash.write().unwrap() = new_blockhash; *blockhash.write().unwrap() = new_blockhash;
blockhash_last_updated = Instant::now(); blockhash_last_updated = Instant::now();
true true
@ -540,7 +538,7 @@ impl<'a> FundingTransactions<'a> for Vec<(&'a Keypair, Transaction)> {
self.len(), self.len(),
); );
let (blockhash, _fee_calculator) = get_recent_blockhash(client.as_ref()); let blockhash = get_latest_blockhash(client.as_ref());
// re-sign retained to_fund_txes with updated blockhash // re-sign retained to_fund_txes with updated blockhash
self.sign(blockhash); self.sign(blockhash);
@ -732,7 +730,7 @@ pub fn airdrop_lamports<T: Client>(
id.pubkey(), id.pubkey(),
); );
let (blockhash, _fee_calculator) = get_recent_blockhash(client); let blockhash = get_latest_blockhash(client);
match request_airdrop_transaction(faucet_addr, &id.pubkey(), airdrop_amount, blockhash) { match request_airdrop_transaction(faucet_addr, &id.pubkey(), airdrop_amount, blockhash) {
Ok(transaction) => { Ok(transaction) => {
let mut tries = 0; let mut tries = 0;
@ -890,8 +888,18 @@ pub fn generate_and_fund_keypairs<T: 'static + Client + Send + Sync>(
// pay for the transaction fees in a new run. // pay for the transaction fees in a new run.
let enough_lamports = 8 * lamports_per_account / 10; let enough_lamports = 8 * lamports_per_account / 10;
if first_keypair_balance < enough_lamports || last_keypair_balance < enough_lamports { if first_keypair_balance < enough_lamports || last_keypair_balance < enough_lamports {
let fee_rate_governor = client.get_fee_rate_governor().unwrap(); let single_sig_message = Message::new(
let max_fee = fee_rate_governor.max_lamports_per_signature; &[Instruction::new_with_bytes(
Pubkey::new_unique(),
&[],
vec![AccountMeta::new(Pubkey::new_unique(), true)],
)],
None,
);
let blockhash = client.get_latest_blockhash().unwrap();
let max_fee = client
.get_fee_for_message(&blockhash, &single_sig_message)
.unwrap();
let extra_fees = extra * max_fee; let extra_fees = extra * max_fee;
let total_keypairs = keypairs.len() as u64 + 1; // Add one for funding keypair let total_keypairs = keypairs.len() as u64 + 1; // Add one for funding keypair
let total = lamports_per_account * total_keypairs + extra_fees; let total = lamports_per_account * total_keypairs + extra_fees;

View File

@ -4,30 +4,30 @@ use solana_client::{
rpc_client::RpcClient, rpc_client::RpcClient,
}; };
use solana_sdk::{ use solana_sdk::{
commitment_config::CommitmentConfig, fee_calculator::FeeCalculator, message::Message, commitment_config::CommitmentConfig, hash::Hash, message::Message,
native_token::lamports_to_sol, pubkey::Pubkey, native_token::lamports_to_sol, pubkey::Pubkey,
}; };
pub fn check_account_for_fee( pub fn check_account_for_fee(
rpc_client: &RpcClient, rpc_client: &RpcClient,
account_pubkey: &Pubkey, account_pubkey: &Pubkey,
fee_calculator: &FeeCalculator, blockhash: &Hash,
message: &Message, message: &Message,
) -> Result<(), CliError> { ) -> Result<(), CliError> {
check_account_for_multiple_fees(rpc_client, account_pubkey, fee_calculator, &[message]) check_account_for_multiple_fees(rpc_client, account_pubkey, blockhash, &[message])
} }
pub fn check_account_for_fee_with_commitment( pub fn check_account_for_fee_with_commitment(
rpc_client: &RpcClient, rpc_client: &RpcClient,
account_pubkey: &Pubkey, account_pubkey: &Pubkey,
fee_calculator: &FeeCalculator, blockhash: &Hash,
message: &Message, message: &Message,
commitment: CommitmentConfig, commitment: CommitmentConfig,
) -> Result<(), CliError> { ) -> Result<(), CliError> {
check_account_for_multiple_fees_with_commitment( check_account_for_multiple_fees_with_commitment(
rpc_client, rpc_client,
account_pubkey, account_pubkey,
fee_calculator, blockhash,
&[message], &[message],
commitment, commitment,
) )
@ -36,13 +36,13 @@ pub fn check_account_for_fee_with_commitment(
pub fn check_account_for_multiple_fees( pub fn check_account_for_multiple_fees(
rpc_client: &RpcClient, rpc_client: &RpcClient,
account_pubkey: &Pubkey, account_pubkey: &Pubkey,
fee_calculator: &FeeCalculator, blockhash: &Hash,
messages: &[&Message], messages: &[&Message],
) -> Result<(), CliError> { ) -> Result<(), CliError> {
check_account_for_multiple_fees_with_commitment( check_account_for_multiple_fees_with_commitment(
rpc_client, rpc_client,
account_pubkey, account_pubkey,
fee_calculator, blockhash,
messages, messages,
CommitmentConfig::default(), CommitmentConfig::default(),
) )
@ -51,7 +51,7 @@ pub fn check_account_for_multiple_fees(
pub fn check_account_for_multiple_fees_with_commitment( pub fn check_account_for_multiple_fees_with_commitment(
rpc_client: &RpcClient, rpc_client: &RpcClient,
account_pubkey: &Pubkey, account_pubkey: &Pubkey,
fee_calculator: &FeeCalculator, blockhash: &Hash,
messages: &[&Message], messages: &[&Message],
commitment: CommitmentConfig, commitment: CommitmentConfig,
) -> Result<(), CliError> { ) -> Result<(), CliError> {
@ -59,7 +59,7 @@ pub fn check_account_for_multiple_fees_with_commitment(
rpc_client, rpc_client,
account_pubkey, account_pubkey,
0, 0,
fee_calculator, blockhash,
messages, messages,
commitment, commitment,
) )
@ -69,11 +69,11 @@ pub fn check_account_for_spend_multiple_fees_with_commitment(
rpc_client: &RpcClient, rpc_client: &RpcClient,
account_pubkey: &Pubkey, account_pubkey: &Pubkey,
balance: u64, balance: u64,
fee_calculator: &FeeCalculator, blockhash: &Hash,
messages: &[&Message], messages: &[&Message],
commitment: CommitmentConfig, commitment: CommitmentConfig,
) -> Result<(), CliError> { ) -> Result<(), CliError> {
let fee = calculate_fee(fee_calculator, messages); let fee = get_fee_for_message(rpc_client, blockhash, messages)?;
if !check_account_for_balance_with_commitment( if !check_account_for_balance_with_commitment(
rpc_client, rpc_client,
account_pubkey, account_pubkey,
@ -98,11 +98,17 @@ pub fn check_account_for_spend_multiple_fees_with_commitment(
Ok(()) Ok(())
} }
pub fn calculate_fee(fee_calculator: &FeeCalculator, messages: &[&Message]) -> u64 { pub fn get_fee_for_message(
messages rpc_client: &RpcClient,
blockhash: &Hash,
messages: &[&Message],
) -> Result<u64, CliError> {
Ok(messages
.iter() .iter()
.map(|message| fee_calculator.calculate_fee(message)) .map(|message| rpc_client.get_fee_for_message(blockhash, message))
.sum() .collect::<Result<Vec<_>, _>>()?
.iter()
.sum())
} }
pub fn check_account_for_balance( pub fn check_account_for_balance(
@ -166,7 +172,6 @@ mod tests {
value: json!(account_balance), value: json!(account_balance),
}); });
let pubkey = solana_sdk::pubkey::new_rand(); let pubkey = solana_sdk::pubkey::new_rand();
let fee_calculator = FeeCalculator::new(1);
let pubkey0 = Pubkey::new(&[0; 32]); let pubkey0 = Pubkey::new(&[0; 32]);
let pubkey1 = Pubkey::new(&[1; 32]); let pubkey1 = Pubkey::new(&[1; 32]);
@ -180,21 +185,32 @@ mod tests {
let mut mocks = HashMap::new(); let mut mocks = HashMap::new();
mocks.insert(RpcRequest::GetBalance, account_balance_response.clone()); mocks.insert(RpcRequest::GetBalance, account_balance_response.clone());
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks); let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
check_account_for_fee(&rpc_client, &pubkey, &fee_calculator, &message0) let blockhash = rpc_client.get_latest_blockhash().unwrap();
check_account_for_fee(&rpc_client, &pubkey, &blockhash, &message0)
.expect("unexpected result"); .expect("unexpected result");
let check_fee_response = json!(Response {
context: RpcResponseContext { slot: 1 },
value: json!(2),
});
let mut mocks = HashMap::new(); let mut mocks = HashMap::new();
mocks.insert(RpcRequest::GetFeeForMessage, check_fee_response);
mocks.insert(RpcRequest::GetBalance, account_balance_response.clone()); mocks.insert(RpcRequest::GetBalance, account_balance_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!(check_account_for_fee(&rpc_client, &pubkey, &fee_calculator, &message1).is_err()); assert!(check_account_for_fee(&rpc_client, &pubkey, &blockhash, &message1).is_err());
let check_fee_response = json!(Response {
context: RpcResponseContext { slot: 1 },
value: json!(2),
});
let mut mocks = HashMap::new(); let mut mocks = HashMap::new();
mocks.insert(RpcRequest::GetFeeForMessage, check_fee_response);
mocks.insert(RpcRequest::GetBalance, account_balance_response); mocks.insert(RpcRequest::GetBalance, account_balance_response);
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks); let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert!(check_account_for_multiple_fees( assert!(check_account_for_multiple_fees(
&rpc_client, &rpc_client,
&pubkey, &pubkey,
&fee_calculator, &blockhash,
&[&message0, &message0] &[&message0, &message0]
) )
.is_err()); .is_err());
@ -204,17 +220,17 @@ mod tests {
context: RpcResponseContext { slot: 1 }, context: RpcResponseContext { slot: 1 },
value: json!(account_balance), value: json!(account_balance),
}); });
let check_fee_response = json!(Response {
context: RpcResponseContext { slot: 1 },
value: json!(1),
});
let mut mocks = HashMap::new(); let mut mocks = HashMap::new();
mocks.insert(RpcRequest::GetFeeForMessage, check_fee_response);
mocks.insert(RpcRequest::GetBalance, account_balance_response); mocks.insert(RpcRequest::GetBalance, account_balance_response);
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks); let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
check_account_for_multiple_fees( check_account_for_multiple_fees(&rpc_client, &pubkey, &blockhash, &[&message0, &message0])
&rpc_client,
&pubkey,
&fee_calculator,
&[&message0, &message0],
)
.expect("unexpected result"); .expect("unexpected result");
} }
@ -237,27 +253,45 @@ mod tests {
} }
#[test] #[test]
fn test_calculate_fee() { fn test_get_fee_for_message() {
let fee_calculator = FeeCalculator::new(1); let check_fee_response = json!(Response {
// No messages, no fee. context: RpcResponseContext { slot: 1 },
assert_eq!(calculate_fee(&fee_calculator, &[]), 0); value: json!(1),
});
let mut mocks = HashMap::new();
mocks.insert(RpcRequest::GetFeeForMessage, check_fee_response);
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
let blockhash = rpc_client.get_latest_blockhash().unwrap();
// No signatures, no fee. // No messages, no fee.
let message = Message::default(); assert_eq!(
assert_eq!(calculate_fee(&fee_calculator, &[&message, &message]), 0); get_fee_for_message(&rpc_client, &blockhash, &[]).unwrap(),
0
);
// One message w/ one signature, a fee. // One message w/ one signature, a fee.
let pubkey0 = Pubkey::new(&[0; 32]); let pubkey0 = Pubkey::new(&[0; 32]);
let pubkey1 = Pubkey::new(&[1; 32]); let pubkey1 = Pubkey::new(&[1; 32]);
let ix0 = system_instruction::transfer(&pubkey0, &pubkey1, 1); let ix0 = system_instruction::transfer(&pubkey0, &pubkey1, 1);
let message0 = Message::new(&[ix0], Some(&pubkey0)); let message0 = Message::new(&[ix0], Some(&pubkey0));
assert_eq!(calculate_fee(&fee_calculator, &[&message0]), 1); assert_eq!(
get_fee_for_message(&rpc_client, &blockhash, &[&message0]).unwrap(),
1
);
// Two messages, additive fees. // No signatures, no fee.
let ix0 = system_instruction::transfer(&pubkey0, &pubkey1, 1); let check_fee_response = json!(Response {
let ix1 = system_instruction::transfer(&pubkey1, &pubkey0, 1); context: RpcResponseContext { slot: 1 },
let message1 = Message::new(&[ix0, ix1], Some(&pubkey0)); value: json!(0),
assert_eq!(calculate_fee(&fee_calculator, &[&message0, &message1]), 3); });
let mut mocks = HashMap::new();
mocks.insert(RpcRequest::GetFeeForMessage, check_fee_response);
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
let message = Message::default();
assert_eq!(
get_fee_for_message(&rpc_client, &blockhash, &[&message, &message]).unwrap(),
0
);
} }
#[test] #[test]

View File

@ -1523,7 +1523,7 @@ pub fn request_and_confirm_airdrop(
to_pubkey: &Pubkey, to_pubkey: &Pubkey,
lamports: u64, lamports: u64,
) -> ClientResult<Signature> { ) -> ClientResult<Signature> {
let (recent_blockhash, _fee_calculator) = rpc_client.get_recent_blockhash()?; let recent_blockhash = rpc_client.get_latest_blockhash()?;
let signature = let signature =
rpc_client.request_airdrop_with_blockhash(to_pubkey, lamports, &recent_blockhash)?; rpc_client.request_airdrop_with_blockhash(to_pubkey, lamports, &recent_blockhash)?;
rpc_client.confirm_transaction_with_spinner( rpc_client.confirm_transaction_with_spinner(

View File

@ -142,9 +142,10 @@ impl ClusterQuerySubCommands for App<'_, '_> {
SubCommand::with_name("cluster-version") SubCommand::with_name("cluster-version")
.about("Get the version of the cluster entrypoint"), .about("Get the version of the cluster entrypoint"),
) )
// Deprecated in v1.8.0
.subcommand( .subcommand(
SubCommand::with_name("fees") SubCommand::with_name("fees")
.about("Display current cluster fees") .about("Display current cluster fees (Deprecated in v1.8.0)")
.arg( .arg(
Arg::with_name("blockhash") Arg::with_name("blockhash")
.long("blockhash") .long("blockhash")
@ -950,6 +951,7 @@ pub fn process_fees(
blockhash: Option<&Hash>, blockhash: Option<&Hash>,
) -> ProcessResult { ) -> ProcessResult {
let fees = if let Some(recent_blockhash) = blockhash { let fees = if let Some(recent_blockhash) = blockhash {
#[allow(deprecated)]
let result = rpc_client.get_fee_calculator_for_blockhash_with_commitment( let result = rpc_client.get_fee_calculator_for_blockhash_with_commitment(
recent_blockhash, recent_blockhash,
config.commitment, config.commitment,
@ -966,6 +968,7 @@ pub fn process_fees(
CliFees::none() CliFees::none()
} }
} else { } else {
#[allow(deprecated)]
let result = rpc_client.get_fees_with_commitment(config.commitment)?; let result = rpc_client.get_fees_with_commitment(config.commitment)?;
CliFees::some( CliFees::some(
result.context.slot, result.context.slot,
@ -1374,7 +1377,7 @@ pub fn process_ping(
let mut confirmed_count = 0; let mut confirmed_count = 0;
let mut confirmation_time: VecDeque<u64> = VecDeque::with_capacity(1024); let mut confirmation_time: VecDeque<u64> = VecDeque::with_capacity(1024);
let (mut blockhash, mut fee_calculator) = rpc_client.get_recent_blockhash()?; let mut blockhash = rpc_client.get_latest_blockhash()?;
let mut blockhash_transaction_count = 0; let mut blockhash_transaction_count = 0;
let mut blockhash_acquired = Instant::now(); let mut blockhash_acquired = Instant::now();
if let Some(fixed_blockhash) = fixed_blockhash { if let Some(fixed_blockhash) = fixed_blockhash {
@ -1393,9 +1396,8 @@ pub fn process_ping(
let now = Instant::now(); let now = Instant::now();
if fixed_blockhash.is_none() && now.duration_since(blockhash_acquired).as_secs() > 60 { if fixed_blockhash.is_none() && now.duration_since(blockhash_acquired).as_secs() > 60 {
// Fetch a new blockhash every minute // Fetch a new blockhash every minute
let (new_blockhash, new_fee_calculator) = rpc_client.get_new_blockhash(&blockhash)?; let new_blockhash = rpc_client.get_new_latest_blockhash(&blockhash)?;
blockhash = new_blockhash; blockhash = new_blockhash;
fee_calculator = new_fee_calculator;
blockhash_transaction_count = 0; blockhash_transaction_count = 0;
blockhash_acquired = Instant::now(); blockhash_acquired = Instant::now();
} }
@ -1414,7 +1416,7 @@ pub fn process_ping(
rpc_client, rpc_client,
false, false,
SpendAmount::Some(lamports), SpendAmount::Some(lamports),
&fee_calculator, &blockhash,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
build_message, build_message,
config.commitment, config.commitment,

View File

@ -409,12 +409,12 @@ fn process_activate(
let rent = rpc_client.get_minimum_balance_for_rent_exemption(Feature::size_of())?; let rent = rpc_client.get_minimum_balance_for_rent_exemption(Feature::size_of())?;
let (blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?; let blockhash = rpc_client.get_latest_blockhash()?;
let (message, _) = resolve_spend_tx_and_check_account_balance( let (message, _) = resolve_spend_tx_and_check_account_balance(
rpc_client, rpc_client,
false, false,
SpendAmount::Some(rent), SpendAmount::Some(rent),
&fee_calculator, &blockhash,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
|lamports| { |lamports| {
Message::new( Message::new(

View File

@ -351,7 +351,7 @@ pub fn process_authorize_nonce_account(
memo: Option<&String>, memo: Option<&String>,
new_authority: &Pubkey, new_authority: &Pubkey,
) -> ProcessResult { ) -> ProcessResult {
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?; let latest_blockhash = rpc_client.get_latest_blockhash()?;
let nonce_authority = config.signers[nonce_authority]; let nonce_authority = config.signers[nonce_authority];
let ixs = vec![authorize_nonce_account( let ixs = vec![authorize_nonce_account(
@ -362,12 +362,12 @@ pub fn process_authorize_nonce_account(
.with_memo(memo); .with_memo(memo);
let message = Message::new(&ixs, Some(&config.signers[0].pubkey())); let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message); let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?; tx.try_sign(&config.signers, latest_blockhash)?;
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
&fee_calculator, &latest_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;
@ -434,13 +434,13 @@ pub fn process_create_nonce_account(
Message::new(&ixs, Some(&config.signers[0].pubkey())) Message::new(&ixs, Some(&config.signers[0].pubkey()))
}; };
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?; let latest_blockhash = rpc_client.get_latest_blockhash()?;
let (message, lamports) = resolve_spend_tx_and_check_account_balance( let (message, lamports) = resolve_spend_tx_and_check_account_balance(
rpc_client, rpc_client,
false, false,
amount, amount,
&fee_calculator, &latest_blockhash,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
build_message, build_message,
config.commitment, config.commitment,
@ -468,7 +468,7 @@ pub fn process_create_nonce_account(
} }
let mut tx = Transaction::new_unsigned(message); let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?; tx.try_sign(&config.signers, latest_blockhash)?;
let merge_errors = let merge_errors =
get_feature_is_active(rpc_client, &merge_nonce_error_into_system_error::id())?; get_feature_is_active(rpc_client, &merge_nonce_error_into_system_error::id())?;
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx); let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
@ -544,14 +544,14 @@ pub fn process_new_nonce(
&nonce_authority.pubkey(), &nonce_authority.pubkey(),
)] )]
.with_memo(memo); .with_memo(memo);
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?; let latest_blockhash = rpc_client.get_latest_blockhash()?;
let message = Message::new(&ixs, Some(&config.signers[0].pubkey())); let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message); let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?; tx.try_sign(&config.signers, latest_blockhash)?;
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
&fee_calculator, &latest_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;
@ -611,7 +611,7 @@ pub fn process_withdraw_from_nonce_account(
destination_account_pubkey: &Pubkey, destination_account_pubkey: &Pubkey,
lamports: u64, lamports: u64,
) -> ProcessResult { ) -> ProcessResult {
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?; let latest_blockhash = rpc_client.get_latest_blockhash()?;
let nonce_authority = config.signers[nonce_authority]; let nonce_authority = config.signers[nonce_authority];
let ixs = vec![withdraw_nonce_account( let ixs = vec![withdraw_nonce_account(
@ -623,11 +623,11 @@ pub fn process_withdraw_from_nonce_account(
.with_memo(memo); .with_memo(memo);
let message = Message::new(&ixs, Some(&config.signers[0].pubkey())); let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message); let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?; tx.try_sign(&config.signers, latest_blockhash)?;
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
&fee_calculator, &latest_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;

View File

@ -23,7 +23,6 @@ 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::{
@ -1067,7 +1066,7 @@ fn process_set_authority(
}; };
trace!("Set a new authority"); trace!("Set a new authority");
let (blockhash, _) = rpc_client.get_recent_blockhash()?; let blockhash = rpc_client.get_latest_blockhash()?;
let mut tx = if let Some(ref pubkey) = program_pubkey { let mut tx = if let Some(ref pubkey) = program_pubkey {
Transaction::new_unsigned(Message::new( Transaction::new_unsigned(Message::new(
@ -1343,7 +1342,7 @@ fn close(
recipient_pubkey: &Pubkey, recipient_pubkey: &Pubkey,
authority_signer: &dyn Signer, authority_signer: &dyn Signer,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
let (blockhash, _) = rpc_client.get_recent_blockhash()?; let blockhash = rpc_client.get_latest_blockhash()?;
let mut tx = Transaction::new_unsigned(Message::new( let mut tx = Transaction::new_unsigned(Message::new(
&[bpf_loader_upgradeable::close( &[bpf_loader_upgradeable::close(
@ -1891,14 +1890,14 @@ fn check_payer(
balance_needed: u64, balance_needed: u64,
messages: &[&Message], messages: &[&Message],
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
let (_, fee_calculator) = rpc_client.get_recent_blockhash()?; let blockhash = rpc_client.get_latest_blockhash()?;
// Does the payer have enough? // Does the payer have enough?
check_account_for_spend_multiple_fees_with_commitment( check_account_for_spend_multiple_fees_with_commitment(
rpc_client, rpc_client,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
balance_needed, balance_needed,
&fee_calculator, &blockhash,
messages, messages,
config.commitment, config.commitment,
)?; )?;
@ -1920,7 +1919,7 @@ fn send_deploy_messages(
if let Some(message) = initial_message { if let Some(message) = initial_message {
if let Some(initial_signer) = initial_signer { if let Some(initial_signer) = initial_signer {
trace!("Preparing the required accounts"); trace!("Preparing the required accounts");
let (blockhash, _) = rpc_client.get_recent_blockhash()?; let blockhash = rpc_client.get_latest_blockhash()?;
let mut initial_transaction = Transaction::new_unsigned(message.clone()); let mut initial_transaction = Transaction::new_unsigned(message.clone());
// Most of the initial_transaction combinations require both the fee-payer and new program // Most of the initial_transaction combinations require both the fee-payer and new program
@ -1943,13 +1942,8 @@ 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 Fees { let (blockhash, last_valid_block_height) =
blockhash, rpc_client.get_latest_blockhash_with_commitment(config.commitment)?;
last_valid_block_height,
..
} = rpc_client
.get_fees_with_commitment(config.commitment)?
.value;
let mut write_transactions = vec![]; let mut write_transactions = vec![];
for message in write_messages.iter() { for message in write_messages.iter() {
let mut tx = Transaction::new_unsigned(message.clone()); let mut tx = Transaction::new_unsigned(message.clone());
@ -1972,7 +1966,7 @@ fn send_deploy_messages(
if let Some(message) = final_message { if let Some(message) = final_message {
if let Some(final_signers) = final_signers { if let Some(final_signers) = final_signers {
trace!("Deploying program"); trace!("Deploying program");
let (blockhash, _) = rpc_client.get_recent_blockhash()?; let blockhash = rpc_client.get_latest_blockhash()?;
let mut final_tx = Transaction::new_unsigned(message.clone()); let mut final_tx = Transaction::new_unsigned(message.clone());
let mut signers = final_signers.to_vec(); let mut signers = final_signers.to_vec();
@ -2141,11 +2135,8 @@ 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 Fees { let (blockhash, new_last_valid_block_height) =
blockhash, rpc_client.get_latest_blockhash_with_commitment(commitment)?;
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; 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() {

View File

@ -1,12 +1,12 @@
use crate::{ use crate::{
checks::{calculate_fee, check_account_for_balance_with_commitment}, checks::{check_account_for_balance_with_commitment, get_fee_for_message},
cli::CliError, cli::CliError,
}; };
use clap::ArgMatches; use clap::ArgMatches;
use solana_clap_utils::{input_parsers::lamports_of_sol, offline::SIGN_ONLY_ARG}; use solana_clap_utils::{input_parsers::lamports_of_sol, offline::SIGN_ONLY_ARG};
use solana_client::rpc_client::RpcClient; use solana_client::rpc_client::RpcClient;
use solana_sdk::{ use solana_sdk::{
commitment_config::CommitmentConfig, fee_calculator::FeeCalculator, message::Message, commitment_config::CommitmentConfig, hash::Hash, message::Message,
native_token::lamports_to_sol, pubkey::Pubkey, native_token::lamports_to_sol, pubkey::Pubkey,
}; };
@ -47,7 +47,7 @@ pub fn resolve_spend_tx_and_check_account_balance<F>(
rpc_client: &RpcClient, rpc_client: &RpcClient,
sign_only: bool, sign_only: bool,
amount: SpendAmount, amount: SpendAmount,
fee_calculator: &FeeCalculator, blockhash: &Hash,
from_pubkey: &Pubkey, from_pubkey: &Pubkey,
build_message: F, build_message: F,
commitment: CommitmentConfig, commitment: CommitmentConfig,
@ -59,7 +59,7 @@ where
rpc_client, rpc_client,
sign_only, sign_only,
amount, amount,
fee_calculator, blockhash,
from_pubkey, from_pubkey,
from_pubkey, from_pubkey,
build_message, build_message,
@ -71,7 +71,7 @@ pub fn resolve_spend_tx_and_check_account_balances<F>(
rpc_client: &RpcClient, rpc_client: &RpcClient,
sign_only: bool, sign_only: bool,
amount: SpendAmount, amount: SpendAmount,
fee_calculator: &FeeCalculator, blockhash: &Hash,
from_pubkey: &Pubkey, from_pubkey: &Pubkey,
fee_pubkey: &Pubkey, fee_pubkey: &Pubkey,
build_message: F, build_message: F,
@ -82,26 +82,28 @@ where
{ {
if sign_only { if sign_only {
let (message, SpendAndFee { spend, fee: _ }) = resolve_spend_message( let (message, SpendAndFee { spend, fee: _ }) = resolve_spend_message(
rpc_client,
amount, amount,
fee_calculator, None,
0, 0,
from_pubkey, from_pubkey,
fee_pubkey, fee_pubkey,
build_message, build_message,
); )?;
Ok((message, spend)) Ok((message, spend))
} else { } else {
let from_balance = rpc_client let from_balance = rpc_client
.get_balance_with_commitment(from_pubkey, commitment)? .get_balance_with_commitment(from_pubkey, commitment)?
.value; .value;
let (message, SpendAndFee { spend, fee }) = resolve_spend_message( let (message, SpendAndFee { spend, fee }) = resolve_spend_message(
rpc_client,
amount, amount,
fee_calculator, Some(blockhash),
from_balance, from_balance,
from_pubkey, from_pubkey,
fee_pubkey, fee_pubkey,
build_message, build_message,
); )?;
if from_pubkey == fee_pubkey { if from_pubkey == fee_pubkey {
if from_balance == 0 || from_balance < spend + fee { if from_balance == 0 || from_balance < spend + fee {
return Err(CliError::InsufficientFundsForSpendAndFee( return Err(CliError::InsufficientFundsForSpendAndFee(
@ -130,43 +132,46 @@ where
} }
fn resolve_spend_message<F>( fn resolve_spend_message<F>(
rpc_client: &RpcClient,
amount: SpendAmount, amount: SpendAmount,
fee_calculator: &FeeCalculator, blockhash: Option<&Hash>,
from_balance: u64, from_balance: u64,
from_pubkey: &Pubkey, from_pubkey: &Pubkey,
fee_pubkey: &Pubkey, fee_pubkey: &Pubkey,
build_message: F, build_message: F,
) -> (Message, SpendAndFee) ) -> Result<(Message, SpendAndFee), CliError>
where where
F: Fn(u64) -> Message, F: Fn(u64) -> Message,
{ {
match amount { let fee = match blockhash {
SpendAmount::Some(lamports) => { Some(blockhash) => {
let message = build_message(lamports);
let fee = calculate_fee(fee_calculator, &[&message]);
(
message,
SpendAndFee {
spend: lamports,
fee,
},
)
}
SpendAmount::All => {
let dummy_message = build_message(0); let dummy_message = build_message(0);
let fee = calculate_fee(fee_calculator, &[&dummy_message]); get_fee_for_message(rpc_client, blockhash, &[&dummy_message])?
let lamports = if from_pubkey == fee_pubkey { }
from_balance.saturating_sub(fee) None => 0, // Offline, cannot calulate fee
} else {
from_balance
}; };
(
match amount {
SpendAmount::Some(lamports) => Ok((
build_message(lamports), build_message(lamports),
SpendAndFee { SpendAndFee {
spend: lamports, spend: lamports,
fee, fee,
}, },
) )),
SpendAmount::All => {
let lamports = if from_pubkey == fee_pubkey {
from_balance.saturating_sub(fee)
} else {
from_balance
};
Ok((
build_message(lamports),
SpendAndFee {
spend: lamports,
fee,
},
))
} }
} }
} }

View File

@ -1272,14 +1272,13 @@ pub fn process_create_stake_account(
} }
}; };
let (recent_blockhash, fee_calculator) = let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let (message, lamports) = resolve_spend_tx_and_check_account_balances( let (message, lamports) = resolve_spend_tx_and_check_account_balances(
rpc_client, rpc_client,
sign_only, sign_only,
amount, amount,
&fee_calculator, &recent_blockhash,
&from.pubkey(), &from.pubkey(),
&fee_payer.pubkey(), &fee_payer.pubkey(),
build_message, build_message,
@ -1387,8 +1386,7 @@ pub fn process_stake_authorize(
} }
ixs = ixs.with_memo(memo); ixs = ixs.with_memo(memo);
let (recent_blockhash, fee_calculator) = let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let nonce_authority = config.signers[nonce_authority]; let nonce_authority = config.signers[nonce_authority];
let fee_payer = config.signers[fee_payer]; let fee_payer = config.signers[fee_payer];
@ -1427,7 +1425,7 @@ pub fn process_stake_authorize(
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&tx.message.account_keys[0], &tx.message.account_keys[0],
&fee_calculator, &recent_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;
@ -1455,8 +1453,7 @@ pub fn process_deactivate_stake_account(
seed: Option<&String>, seed: Option<&String>,
fee_payer: SignerIndex, fee_payer: SignerIndex,
) -> ProcessResult { ) -> ProcessResult {
let (recent_blockhash, fee_calculator) = let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let stake_authority = config.signers[stake_authority]; let stake_authority = config.signers[stake_authority];
let stake_account_address = if let Some(seed) = seed { let stake_account_address = if let Some(seed) = seed {
@ -1507,7 +1504,7 @@ pub fn process_deactivate_stake_account(
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&tx.message.account_keys[0], &tx.message.account_keys[0],
&fee_calculator, &recent_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;
@ -1543,8 +1540,7 @@ pub fn process_withdraw_stake(
*stake_account_pubkey *stake_account_pubkey
}; };
let (recent_blockhash, fee_calculator) = let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let fee_payer = config.signers[fee_payer]; let fee_payer = config.signers[fee_payer];
let nonce_authority = config.signers[nonce_authority]; let nonce_authority = config.signers[nonce_authority];
@ -1575,7 +1571,7 @@ pub fn process_withdraw_stake(
rpc_client, rpc_client,
sign_only, sign_only,
amount, amount,
&fee_calculator, &recent_blockhash,
&stake_account_address, &stake_account_address,
&fee_payer.pubkey(), &fee_payer.pubkey(),
build_message, build_message,
@ -1606,7 +1602,7 @@ pub fn process_withdraw_stake(
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&tx.message.account_keys[0], &tx.message.account_keys[0],
&fee_calculator, &recent_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;
@ -1692,8 +1688,7 @@ pub fn process_split_stake(
} }
} }
let (recent_blockhash, fee_calculator) = let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let ixs = if let Some(seed) = split_stake_account_seed { let ixs = if let Some(seed) = split_stake_account_seed {
stake_instruction::split_with_seed( stake_instruction::split_with_seed(
@ -1751,7 +1746,7 @@ pub fn process_split_stake(
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&tx.message.account_keys[0], &tx.message.account_keys[0],
&fee_calculator, &recent_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;
@ -1812,8 +1807,7 @@ pub fn process_merge_stake(
} }
} }
let (recent_blockhash, fee_calculator) = let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let ixs = stake_instruction::merge( let ixs = stake_instruction::merge(
stake_account_pubkey, stake_account_pubkey,
@ -1858,7 +1852,7 @@ pub fn process_merge_stake(
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&tx.message.account_keys[0], &tx.message.account_keys[0],
&fee_calculator, &recent_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;
@ -1887,8 +1881,7 @@ pub fn process_stake_set_lockup(
memo: Option<&String>, memo: Option<&String>,
fee_payer: SignerIndex, fee_payer: SignerIndex,
) -> ProcessResult { ) -> ProcessResult {
let (recent_blockhash, fee_calculator) = let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let custodian = config.signers[custodian]; let custodian = config.signers[custodian];
let ixs = vec![if new_custodian_signer.is_some() { let ixs = vec![if new_custodian_signer.is_some() {
@ -1934,7 +1927,7 @@ pub fn process_stake_set_lockup(
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&tx.message.account_keys[0], &tx.message.account_keys[0],
&fee_calculator, &recent_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;
@ -2291,8 +2284,7 @@ pub fn process_delegate_stake(
} }
} }
let (recent_blockhash, fee_calculator) = let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let ixs = vec![stake_instruction::delegate_stake( let ixs = vec![stake_instruction::delegate_stake(
stake_account_pubkey, stake_account_pubkey,
@ -2337,7 +2329,7 @@ pub fn process_delegate_stake(
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&tx.message.account_keys[0], &tx.message.account_keys[0],
&fee_calculator, &recent_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;

View File

@ -345,18 +345,18 @@ pub fn process_set_validator_info(
}; };
// Submit transaction // Submit transaction
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?; let latest_blockhash = rpc_client.get_latest_blockhash()?;
let (message, _) = resolve_spend_tx_and_check_account_balance( let (message, _) = resolve_spend_tx_and_check_account_balance(
rpc_client, rpc_client,
false, false,
SpendAmount::Some(lamports), SpendAmount::Some(lamports),
&fee_calculator, &latest_blockhash,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
build_message, build_message,
config.commitment, config.commitment,
)?; )?;
let mut tx = Transaction::new_unsigned(message); let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&signers, recent_blockhash)?; tx.try_sign(&signers, latest_blockhash)?;
let signature_str = rpc_client.send_and_confirm_transaction_with_spinner(&tx)?; let signature_str = rpc_client.send_and_confirm_transaction_with_spinner(&tx)?;
println!("Success! Validator info published at: {:?}", info_pubkey); println!("Success! Validator info published at: {:?}", info_pubkey);

View File

@ -605,19 +605,19 @@ pub fn process_create_vote_account(
} }
} }
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?; let latest_blockhash = rpc_client.get_latest_blockhash()?;
let (message, _) = resolve_spend_tx_and_check_account_balance( let (message, _) = resolve_spend_tx_and_check_account_balance(
rpc_client, rpc_client,
false, false,
amount, amount,
&fee_calculator, &latest_blockhash,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
build_message, build_message,
config.commitment, config.commitment,
)?; )?;
let mut tx = Transaction::new_unsigned(message); let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?; tx.try_sign(&config.signers, latest_blockhash)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx); let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
log_instruction_custom_error::<SystemError>(result, config) log_instruction_custom_error::<SystemError>(result, config)
} }
@ -639,7 +639,7 @@ pub fn process_vote_authorize(
(&authorized.pubkey(), "authorized_account".to_string()), (&authorized.pubkey(), "authorized_account".to_string()),
(new_authorized_pubkey, "new_authorized_pubkey".to_string()), (new_authorized_pubkey, "new_authorized_pubkey".to_string()),
)?; )?;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?; let latest_blockhash = rpc_client.get_latest_blockhash()?;
let vote_ix = if new_authorized_signer.is_some() { let vote_ix = if new_authorized_signer.is_some() {
vote_instruction::authorize_checked( vote_instruction::authorize_checked(
vote_account_pubkey, // vote account to update vote_account_pubkey, // vote account to update
@ -659,11 +659,11 @@ pub fn process_vote_authorize(
let message = Message::new(&ixs, Some(&config.signers[0].pubkey())); let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message); let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?; tx.try_sign(&config.signers, latest_blockhash)?;
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
&fee_calculator, &latest_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;
@ -686,7 +686,7 @@ pub fn process_vote_update_validator(
(vote_account_pubkey, "vote_account_pubkey".to_string()), (vote_account_pubkey, "vote_account_pubkey".to_string()),
(&new_identity_pubkey, "new_identity_account".to_string()), (&new_identity_pubkey, "new_identity_account".to_string()),
)?; )?;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?; let latest_blockhash = rpc_client.get_latest_blockhash()?;
let ixs = vec![vote_instruction::update_validator_identity( let ixs = vec![vote_instruction::update_validator_identity(
vote_account_pubkey, vote_account_pubkey,
&authorized_withdrawer.pubkey(), &authorized_withdrawer.pubkey(),
@ -696,11 +696,11 @@ pub fn process_vote_update_validator(
let message = Message::new(&ixs, Some(&config.signers[0].pubkey())); let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message); let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?; tx.try_sign(&config.signers, latest_blockhash)?;
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
&fee_calculator, &latest_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;
@ -717,7 +717,7 @@ pub fn process_vote_update_commission(
memo: Option<&String>, memo: Option<&String>,
) -> ProcessResult { ) -> ProcessResult {
let authorized_withdrawer = config.signers[withdraw_authority]; let authorized_withdrawer = config.signers[withdraw_authority];
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?; let latest_blockhash = rpc_client.get_latest_blockhash()?;
let ixs = vec![vote_instruction::update_commission( let ixs = vec![vote_instruction::update_commission(
vote_account_pubkey, vote_account_pubkey,
&authorized_withdrawer.pubkey(), &authorized_withdrawer.pubkey(),
@ -727,11 +727,11 @@ pub fn process_vote_update_commission(
let message = Message::new(&ixs, Some(&config.signers[0].pubkey())); let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message); let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?; tx.try_sign(&config.signers, latest_blockhash)?;
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
&fee_calculator, &latest_blockhash,
&tx.message, &tx.message,
config.commitment, config.commitment,
)?; )?;
@ -836,7 +836,7 @@ pub fn process_withdraw_from_vote_account(
destination_account_pubkey: &Pubkey, destination_account_pubkey: &Pubkey,
memo: Option<&String>, memo: Option<&String>,
) -> ProcessResult { ) -> ProcessResult {
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?; let latest_blockhash = rpc_client.get_latest_blockhash()?;
let withdraw_authority = config.signers[withdraw_authority]; let withdraw_authority = config.signers[withdraw_authority];
let current_balance = rpc_client.get_balance(vote_account_pubkey)?; let current_balance = rpc_client.get_balance(vote_account_pubkey)?;
@ -865,11 +865,11 @@ pub fn process_withdraw_from_vote_account(
let message = Message::new(&ixs, Some(&config.signers[0].pubkey())); let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
let mut transaction = Transaction::new_unsigned(message); let mut transaction = Transaction::new_unsigned(message);
transaction.try_sign(&config.signers, recent_blockhash)?; transaction.try_sign(&config.signers, latest_blockhash)?;
check_account_for_fee_with_commitment( check_account_for_fee_with_commitment(
rpc_client, rpc_client,
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
&fee_calculator, &latest_blockhash,
&transaction.message, &transaction.message,
config.commitment, config.commitment,
)?; )?;

View File

@ -645,8 +645,7 @@ pub fn process_transfer(
let from = config.signers[from]; let from = config.signers[from];
let mut from_pubkey = from.pubkey(); let mut from_pubkey = from.pubkey();
let (recent_blockhash, fee_calculator) = let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
if !sign_only && !allow_unfunded_recipient { if !sign_only && !allow_unfunded_recipient {
let recipient_balance = rpc_client let recipient_balance = rpc_client
@ -706,7 +705,7 @@ pub fn process_transfer(
rpc_client, rpc_client,
sign_only, sign_only,
amount, amount,
&fee_calculator, &recent_blockhash,
&from_pubkey, &from_pubkey,
&fee_payer.pubkey(), &fee_payer.pubkey(),
build_message, build_message,

View File

@ -356,7 +356,7 @@ fn test_offline_stake_delegation_and_deactivation() {
process_command(&config_validator).unwrap(); process_command(&config_validator).unwrap();
// Delegate stake offline // Delegate stake offline
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap(); let blockhash = rpc_client.get_latest_blockhash().unwrap();
config_offline.command = CliCommand::DelegateStake { config_offline.command = CliCommand::DelegateStake {
stake_account_pubkey: stake_keypair.pubkey(), stake_account_pubkey: stake_keypair.pubkey(),
vote_account_pubkey: test_validator.vote_account_address(), vote_account_pubkey: test_validator.vote_account_address(),
@ -394,7 +394,7 @@ fn test_offline_stake_delegation_and_deactivation() {
process_command(&config_payer).unwrap(); process_command(&config_payer).unwrap();
// Deactivate stake offline // Deactivate stake offline
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap(); let blockhash = rpc_client.get_latest_blockhash().unwrap();
config_offline.command = CliCommand::DeactivateStake { config_offline.command = CliCommand::DeactivateStake {
stake_account_pubkey: stake_keypair.pubkey(), stake_account_pubkey: stake_keypair.pubkey(),
stake_authority: 0, stake_authority: 0,
@ -714,7 +714,7 @@ fn test_stake_authorize() {
// Offline assignment of new nonced stake authority // Offline assignment of new nonced stake authority
let nonced_authority = Keypair::new(); let nonced_authority = Keypair::new();
let nonced_authority_pubkey = nonced_authority.pubkey(); let nonced_authority_pubkey = nonced_authority.pubkey();
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap(); let blockhash = rpc_client.get_latest_blockhash().unwrap();
config_offline.command = CliCommand::StakeAuthorize { config_offline.command = CliCommand::StakeAuthorize {
stake_account_pubkey, stake_account_pubkey,
new_authorizations: vec![StakeAuthorizationIndexed { new_authorizations: vec![StakeAuthorizationIndexed {
@ -964,7 +964,7 @@ fn test_stake_authorize_with_fee_payer() {
check_recent_balance(100_000 - SIG_FEE - SIG_FEE, &rpc_client, &payer_pubkey); check_recent_balance(100_000 - SIG_FEE - SIG_FEE, &rpc_client, &payer_pubkey);
// Assign authority with offline fee payer // Assign authority with offline fee payer
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap(); let blockhash = rpc_client.get_latest_blockhash().unwrap();
config_offline.command = CliCommand::StakeAuthorize { config_offline.command = CliCommand::StakeAuthorize {
stake_account_pubkey, stake_account_pubkey,
new_authorizations: vec![StakeAuthorizationIndexed { new_authorizations: vec![StakeAuthorizationIndexed {

View File

@ -106,7 +106,7 @@ fn test_transfer() {
check_recent_balance(50, &rpc_client, &offline_pubkey); check_recent_balance(50, &rpc_client, &offline_pubkey);
// Offline transfer // Offline transfer
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap(); let blockhash = rpc_client.get_latest_blockhash().unwrap();
offline.command = CliCommand::Transfer { offline.command = CliCommand::Transfer {
amount: SpendAmount::Some(10), amount: SpendAmount::Some(10),
to: recipient_pubkey, to: recipient_pubkey,
@ -318,7 +318,7 @@ fn test_transfer_multisession_signing() {
check_ready(&rpc_client); check_ready(&rpc_client);
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap(); let blockhash = rpc_client.get_latest_blockhash().unwrap();
// Offline fee-payer signs first // Offline fee-payer signs first
let mut fee_payer_config = CliConfig::recent_for_tests(); let mut fee_payer_config = CliConfig::recent_for_tests();

View File

@ -19,6 +19,7 @@ pub enum Source {
} }
impl Source { impl Source {
#[deprecated(since = "1.8.0", note = "Please use `get_blockhash` instead")]
pub fn get_blockhash_and_fee_calculator( pub fn get_blockhash_and_fee_calculator(
&self, &self,
rpc_client: &RpcClient, rpc_client: &RpcClient,
@ -26,6 +27,7 @@ impl Source {
) -> Result<(Hash, FeeCalculator), Box<dyn std::error::Error>> { ) -> Result<(Hash, FeeCalculator), Box<dyn std::error::Error>> {
match self { match self {
Self::Cluster => { Self::Cluster => {
#[allow(deprecated)]
let res = rpc_client let res = rpc_client
.get_recent_blockhash_with_commitment(commitment)? .get_recent_blockhash_with_commitment(commitment)?
.value; .value;
@ -39,6 +41,10 @@ impl Source {
} }
} }
#[deprecated(
since = "1.8.0",
note = "Please do not use, will no longer be available in the future"
)]
pub fn get_fee_calculator( pub fn get_fee_calculator(
&self, &self,
rpc_client: &RpcClient, rpc_client: &RpcClient,
@ -47,6 +53,7 @@ impl Source {
) -> Result<Option<FeeCalculator>, Box<dyn std::error::Error>> { ) -> Result<Option<FeeCalculator>, Box<dyn std::error::Error>> {
match self { match self {
Self::Cluster => { Self::Cluster => {
#[allow(deprecated)]
let res = rpc_client let res = rpc_client
.get_fee_calculator_for_blockhash_with_commitment(blockhash, commitment)? .get_fee_calculator_for_blockhash_with_commitment(blockhash, commitment)?
.value; .value;
@ -61,6 +68,40 @@ impl Source {
} }
} }
} }
pub fn get_blockhash(
&self,
rpc_client: &RpcClient,
commitment: CommitmentConfig,
) -> Result<Hash, Box<dyn std::error::Error>> {
match self {
Self::Cluster => {
let (blockhash, _) = rpc_client.get_latest_blockhash_with_commitment(commitment)?;
Ok(blockhash)
}
Self::NonceAccount(ref pubkey) => {
let data = nonce_utils::get_account_with_commitment(rpc_client, pubkey, commitment)
.and_then(|ref a| nonce_utils::data_from_account(a))?;
Ok(data.blockhash)
}
}
}
pub fn is_blockhash_valid(
&self,
rpc_client: &RpcClient,
blockhash: &Hash,
commitment: CommitmentConfig,
) -> Result<bool, Box<dyn std::error::Error>> {
Ok(match self {
Self::Cluster => rpc_client.is_blockhash_valid(blockhash, commitment)?,
Self::NonceAccount(ref pubkey) => {
let _ = nonce_utils::get_account_with_commitment(rpc_client, pubkey, commitment)
.and_then(|ref a| nonce_utils::data_from_account(a))?;
true
}
})
}
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -90,6 +131,7 @@ impl BlockhashQuery {
BlockhashQuery::new(blockhash, sign_only, nonce_account) BlockhashQuery::new(blockhash, sign_only, nonce_account)
} }
#[deprecated(since = "1.8.0", note = "Please use `get_blockhash` instead")]
pub fn get_blockhash_and_fee_calculator( pub fn get_blockhash_and_fee_calculator(
&self, &self,
rpc_client: &RpcClient, rpc_client: &RpcClient,
@ -98,16 +140,36 @@ impl BlockhashQuery {
match self { match self {
BlockhashQuery::None(hash) => Ok((*hash, FeeCalculator::default())), BlockhashQuery::None(hash) => Ok((*hash, FeeCalculator::default())),
BlockhashQuery::FeeCalculator(source, hash) => { BlockhashQuery::FeeCalculator(source, hash) => {
#[allow(deprecated)]
let fee_calculator = source let fee_calculator = source
.get_fee_calculator(rpc_client, hash, commitment)? .get_fee_calculator(rpc_client, hash, commitment)?
.ok_or(format!("Hash has expired {:?}", hash))?; .ok_or(format!("Hash has expired {:?}", hash))?;
Ok((*hash, fee_calculator)) Ok((*hash, fee_calculator))
} }
BlockhashQuery::All(source) => { BlockhashQuery::All(source) =>
{
#[allow(deprecated)]
source.get_blockhash_and_fee_calculator(rpc_client, commitment) source.get_blockhash_and_fee_calculator(rpc_client, commitment)
} }
} }
} }
pub fn get_blockhash(
&self,
rpc_client: &RpcClient,
commitment: CommitmentConfig,
) -> Result<Hash, Box<dyn std::error::Error>> {
match self {
BlockhashQuery::None(hash) => Ok(*hash),
BlockhashQuery::FeeCalculator(source, hash) => {
if !source.is_blockhash_valid(rpc_client, hash, commitment)? {
return Err(format!("Hash has expired {:?}", hash).into());
}
Ok(*hash)
}
BlockhashQuery::All(source) => source.get_blockhash(rpc_client, commitment),
}
}
} }
impl Default for BlockhashQuery { impl Default for BlockhashQuery {
@ -282,6 +344,7 @@ mod tests {
} }
#[test] #[test]
#[allow(deprecated)]
fn test_blockhash_query_get_blockhash_fee_calc() { fn test_blockhash_query_get_blockhash_fee_calc() {
let test_blockhash = hash(&[0u8]); let test_blockhash = hash(&[0u8]);
let rpc_blockhash = hash(&[1u8]); let rpc_blockhash = hash(&[1u8]);

View File

@ -6,9 +6,9 @@ use {
rpc_config::RpcBlockProductionConfig, rpc_config::RpcBlockProductionConfig,
rpc_request::RpcRequest, rpc_request::RpcRequest,
rpc_response::{ rpc_response::{
Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange, RpcFees, Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange, RpcBlockhash,
RpcResponseContext, RpcSimulateTransactionResult, RpcStakeActivation, RpcSupply, RpcFees, RpcResponseContext, RpcSimulateTransactionResult, RpcStakeActivation,
RpcVersionInfo, RpcVoteAccountStatus, StakeActivationState, RpcSupply, RpcVersionInfo, RpcVoteAccountStatus, StakeActivationState,
}, },
rpc_sender::RpcSender, rpc_sender::RpcSender,
}, },
@ -271,6 +271,17 @@ impl RpcSender for MockSender {
feature_set: Some(version.feature_set), feature_set: Some(version.feature_set),
}) })
} }
"getLatestBlockhash" => serde_json::to_value(Response {
context: RpcResponseContext { slot: 1 },
value: RpcBlockhash {
blockhash: PUBKEY.to_string(),
last_valid_block_height: 0,
},
})?,
"getFeeForMessage" => serde_json::to_value(Response {
context: RpcResponseContext { slot: 1 },
value: json!(Some(0)),
})?,
_ => Value::Null, _ => Value::Null,
}; };
Ok(val) Ok(val)

View File

@ -38,6 +38,7 @@ use {
epoch_schedule::EpochSchedule, epoch_schedule::EpochSchedule,
fee_calculator::{FeeCalculator, FeeRateGovernor}, fee_calculator::{FeeCalculator, FeeRateGovernor},
hash::Hash, hash::Hash,
message::Message,
pubkey::Pubkey, pubkey::Pubkey,
signature::Signature, signature::Signature,
transaction::{self, uses_durable_nonce, Transaction}, transaction::{self, uses_durable_nonce, Transaction},
@ -722,7 +723,7 @@ impl RpcClient {
preflight_commitment: Some(preflight_commitment.commitment), preflight_commitment: Some(preflight_commitment.commitment),
..config ..config
}; };
let serialized_encoded = serialize_encode_transaction(transaction, encoding)?; let serialized_encoded = serialize_and_encode::<Transaction>(transaction, encoding)?;
let signature_base58_str: String = match self.send( let signature_base58_str: String = match self.send(
RpcRequest::SendTransaction, RpcRequest::SendTransaction,
json!([serialized_encoded, config]), json!([serialized_encoded, config]),
@ -859,7 +860,7 @@ impl RpcClient {
commitment: Some(commitment), commitment: Some(commitment),
..config ..config
}; };
let serialized_encoded = serialize_encode_transaction(transaction, encoding)?; let serialized_encoded = serialize_and_encode::<Transaction>(transaction, encoding)?;
self.send( self.send(
RpcRequest::SimulateTransaction, RpcRequest::SimulateTransaction,
json!([serialized_encoded, config]), json!([serialized_encoded, config]),
@ -1981,9 +1982,8 @@ impl RpcClient {
let signature = self.send_transaction(transaction)?; let signature = self.send_transaction(transaction)?;
let recent_blockhash = if uses_durable_nonce(transaction).is_some() { let recent_blockhash = if uses_durable_nonce(transaction).is_some() {
let (recent_blockhash, ..) = self let (recent_blockhash, ..) =
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())? self.get_latest_blockhash_with_commitment(CommitmentConfig::processed())?;
.value;
recent_blockhash recent_blockhash
} else { } else {
transaction.message.recent_blockhash transaction.message.recent_blockhash
@ -1994,13 +1994,9 @@ impl RpcClient {
Some(Ok(_)) => return Ok(signature), Some(Ok(_)) => return Ok(signature),
Some(Err(e)) => return Err(e.into()), Some(Err(e)) => return Err(e.into()),
None => { None => {
let fee_calculator = self if !self
.get_fee_calculator_for_blockhash_with_commitment( .is_blockhash_valid(&recent_blockhash, CommitmentConfig::processed())?
&recent_blockhash, {
CommitmentConfig::processed(),
)?
.value;
if fee_calculator.is_none() {
// Block hash is not found by some reason // Block hash is not found by some reason
break 'sending; break 'sending;
} else if cfg!(not(test)) } else if cfg!(not(test))
@ -2209,10 +2205,21 @@ impl RpcClient {
) )
} }
#[deprecated(
since = "1.8.0",
note = "Please use `get_latest_blockhash` and `get_fee_for_message` instead"
)]
#[allow(deprecated)]
pub fn get_fees(&self) -> ClientResult<Fees> { pub fn get_fees(&self) -> ClientResult<Fees> {
#[allow(deprecated)]
Ok(self.get_fees_with_commitment(self.commitment())?.value) Ok(self.get_fees_with_commitment(self.commitment())?.value)
} }
#[deprecated(
since = "1.8.0",
note = "Please use `get_latest_blockhash_with_commitment` and `get_fee_for_message` instead"
)]
#[allow(deprecated)]
pub fn get_fees_with_commitment(&self, commitment_config: CommitmentConfig) -> RpcResult<Fees> { pub fn get_fees_with_commitment(&self, commitment_config: CommitmentConfig) -> RpcResult<Fees> {
let Response { let Response {
context, context,
@ -2237,13 +2244,21 @@ impl RpcClient {
}) })
} }
#[deprecated(since = "1.8.0", note = "Please use `get_latest_blockhash` instead")]
#[allow(deprecated)]
pub fn get_recent_blockhash(&self) -> ClientResult<(Hash, FeeCalculator)> { pub fn get_recent_blockhash(&self) -> ClientResult<(Hash, FeeCalculator)> {
#[allow(deprecated)]
let (blockhash, fee_calculator, _last_valid_slot) = self let (blockhash, fee_calculator, _last_valid_slot) = self
.get_recent_blockhash_with_commitment(self.commitment())? .get_recent_blockhash_with_commitment(self.commitment())?
.value; .value;
Ok((blockhash, fee_calculator)) Ok((blockhash, fee_calculator))
} }
#[deprecated(
since = "1.8.0",
note = "Please use `get_latest_blockhash_with_commitment` instead"
)]
#[allow(deprecated)]
pub fn get_recent_blockhash_with_commitment( pub fn get_recent_blockhash_with_commitment(
&self, &self,
commitment_config: CommitmentConfig, commitment_config: CommitmentConfig,
@ -2307,15 +2322,23 @@ impl RpcClient {
}) })
} }
#[deprecated(since = "1.8.0", note = "Please `get_fee_for_message` instead")]
#[allow(deprecated)]
pub fn get_fee_calculator_for_blockhash( pub fn get_fee_calculator_for_blockhash(
&self, &self,
blockhash: &Hash, blockhash: &Hash,
) -> ClientResult<Option<FeeCalculator>> { ) -> ClientResult<Option<FeeCalculator>> {
#[allow(deprecated)]
Ok(self Ok(self
.get_fee_calculator_for_blockhash_with_commitment(blockhash, self.commitment())? .get_fee_calculator_for_blockhash_with_commitment(blockhash, self.commitment())?
.value) .value)
} }
#[deprecated(
since = "1.8.0",
note = "Please `get_latest_blockhash_with_commitment` and `get_fee_for_message` instead"
)]
#[allow(deprecated)]
pub fn get_fee_calculator_for_blockhash_with_commitment( pub fn get_fee_calculator_for_blockhash_with_commitment(
&self, &self,
blockhash: &Hash, blockhash: &Hash,
@ -2335,6 +2358,11 @@ impl RpcClient {
}) })
} }
#[deprecated(
since = "1.8.0",
note = "Please do not use, will no longer be available in the future"
)]
#[allow(deprecated)]
pub fn get_fee_rate_governor(&self) -> RpcResult<FeeRateGovernor> { pub fn get_fee_rate_governor(&self) -> RpcResult<FeeRateGovernor> {
let Response { let Response {
context, context,
@ -2348,10 +2376,16 @@ impl RpcClient {
}) })
} }
#[deprecated(
since = "1.8.0",
note = "Please use `get_new_latest_blockhash` instead"
)]
#[allow(deprecated)]
pub fn get_new_blockhash(&self, blockhash: &Hash) -> ClientResult<(Hash, FeeCalculator)> { pub fn get_new_blockhash(&self, blockhash: &Hash) -> ClientResult<(Hash, FeeCalculator)> {
let mut num_retries = 0; let mut num_retries = 0;
let start = Instant::now(); let start = Instant::now();
while start.elapsed().as_secs() < 5 { while start.elapsed().as_secs() < 5 {
#[allow(deprecated)]
if let Ok((new_blockhash, fee_calculator)) = self.get_recent_blockhash() { if let Ok((new_blockhash, fee_calculator)) = self.get_recent_blockhash() {
if new_blockhash != *blockhash { if new_blockhash != *blockhash {
return Ok((new_blockhash, fee_calculator)); return Ok((new_blockhash, fee_calculator));
@ -2831,8 +2865,7 @@ impl RpcClient {
config: RpcSendTransactionConfig, config: RpcSendTransactionConfig,
) -> ClientResult<Signature> { ) -> ClientResult<Signature> {
let recent_blockhash = if uses_durable_nonce(transaction).is_some() { let recent_blockhash = if uses_durable_nonce(transaction).is_some() {
self.get_recent_blockhash_with_commitment(CommitmentConfig::processed())? self.get_latest_blockhash_with_commitment(CommitmentConfig::processed())?
.value
.0 .0
} else { } else {
transaction.message.recent_blockhash transaction.message.recent_blockhash
@ -2872,13 +2905,8 @@ impl RpcClient {
let status = self let status = self
.get_signature_status_with_commitment(signature, CommitmentConfig::processed())?; .get_signature_status_with_commitment(signature, CommitmentConfig::processed())?;
if status.is_none() { if status.is_none() {
let blockhash_not_found = self let blockhash_not_found =
.get_fee_calculator_for_blockhash_with_commitment( !self.is_blockhash_valid(recent_blockhash, CommitmentConfig::processed())?;
recent_blockhash,
CommitmentConfig::processed(),
)?
.value
.is_none();
if blockhash_not_found && now.elapsed() >= confirm_transaction_initial_timeout { if blockhash_not_found && now.elapsed() >= confirm_transaction_initial_timeout {
break (signature, status); break (signature, status);
} }
@ -2936,6 +2964,84 @@ impl RpcClient {
} }
} }
pub fn get_latest_blockhash(&self) -> ClientResult<Hash> {
let (blockhash, _) = self.get_latest_blockhash_with_commitment(self.commitment())?;
Ok(blockhash)
}
pub fn get_latest_blockhash_with_commitment(
&self,
commitment: CommitmentConfig,
) -> ClientResult<(Hash, u64)> {
let latest_blockhash = self
.send::<Response<RpcBlockhash>>(
RpcRequest::GetLatestBlockhash,
json!([self.maybe_map_commitment(commitment)?]),
)?
.value;
let blockhash = latest_blockhash.blockhash.parse().map_err(|_| {
ClientError::new_with_request(
RpcError::ParseError("Hash".to_string()).into(),
RpcRequest::GetLatestBlockhash,
)
})?;
Ok((blockhash, latest_blockhash.last_valid_block_height))
}
pub fn is_blockhash_valid(
&self,
blockhash: &Hash,
commitment: CommitmentConfig,
) -> ClientResult<bool> {
let result = self.send::<Response<bool>>(
RpcRequest::IsBlockhashValid,
json!([blockhash.to_string(), commitment,]),
)?;
Ok(result.value)
}
pub fn get_fee_for_message(&self, blockhash: &Hash, message: &Message) -> ClientResult<u64> {
let serialized_encoded =
serialize_and_encode::<Message>(message, UiTransactionEncoding::Base64)?;
let result = self.send::<Response<Option<u64>>>(
RpcRequest::GetFeeForMessage,
json!([
blockhash.to_string(),
serialized_encoded,
UiTransactionEncoding::Base64,
self.commitment(),
]),
)?;
result
.value
.ok_or_else(|| ClientErrorKind::Custom("Invalid blockhash".to_string()).into())
}
pub fn get_new_latest_blockhash(&self, blockhash: &Hash) -> ClientResult<Hash> {
let mut num_retries = 0;
let start = Instant::now();
while start.elapsed().as_secs() < 5 {
if let Ok(new_blockhash) = self.get_latest_blockhash() {
if new_blockhash != *blockhash {
return Ok(new_blockhash);
}
}
debug!("Got same blockhash ({:?}), will retry...", blockhash);
// Retry ~twice during a slot
sleep(Duration::from_millis(DEFAULT_MS_PER_SLOT / 2));
num_retries += 1;
}
Err(RpcError::ForUser(format!(
"Unable to get new blockhash after {}ms (retried {} times), stuck at {}",
start.elapsed().as_millis(),
num_retries,
blockhash
))
.into())
}
pub fn send<T>(&self, request: RpcRequest, params: Value) -> ClientResult<T> pub fn send<T>(&self, request: RpcRequest, params: Value) -> ClientResult<T>
where where
T: serde::de::DeserializeOwned, T: serde::de::DeserializeOwned,
@ -2951,18 +3057,18 @@ impl RpcClient {
} }
} }
fn serialize_encode_transaction( pub fn serialize_and_encode<T>(input: &T, encoding: UiTransactionEncoding) -> ClientResult<String>
transaction: &Transaction, where
encoding: UiTransactionEncoding, T: serde::ser::Serialize,
) -> ClientResult<String> { {
let serialized = serialize(transaction) let serialized = serialize(input)
.map_err(|e| ClientErrorKind::Custom(format!("transaction serialization failed: {}", e)))?; .map_err(|e| ClientErrorKind::Custom(format!("Serialization failed: {}", e)))?;
let encoded = match encoding { let encoded = match encoding {
UiTransactionEncoding::Base58 => bs58::encode(serialized).into_string(), UiTransactionEncoding::Base58 => bs58::encode(serialized).into_string(),
UiTransactionEncoding::Base64 => base64::encode(serialized), UiTransactionEncoding::Base64 => base64::encode(serialized),
_ => { _ => {
return Err(ClientErrorKind::Custom(format!( return Err(ClientErrorKind::Custom(format!(
"unsupported transaction encoding: {}. Supported encodings: base58, base64", "unsupported encoding: {}. Supported encodings: base58, base64",
encoding encoding
)) ))
.into()) .into())
@ -3094,12 +3200,14 @@ mod tests {
.unwrap(); .unwrap();
assert_eq!(balance, 50); assert_eq!(balance, 50);
#[allow(deprecated)]
let blockhash: String = rpc_client let blockhash: String = rpc_client
.send(RpcRequest::GetRecentBlockhash, Value::Null) .send(RpcRequest::GetRecentBlockhash, Value::Null)
.unwrap(); .unwrap();
assert_eq!(blockhash, "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"); assert_eq!(blockhash, "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
// Send erroneous parameter // Send erroneous parameter
#[allow(deprecated)]
let blockhash: ClientResult<String> = let blockhash: ClientResult<String> =
rpc_client.send(RpcRequest::GetRecentBlockhash, json!(["parameter"])); rpc_client.send(RpcRequest::GetRecentBlockhash, json!(["parameter"]));
assert!(blockhash.is_err()); assert!(blockhash.is_err());
@ -3134,12 +3242,14 @@ mod tests {
let expected_blockhash: Hash = PUBKEY.parse().unwrap(); let expected_blockhash: Hash = PUBKEY.parse().unwrap();
let (blockhash, _fee_calculator) = rpc_client.get_recent_blockhash().expect("blockhash ok"); let blockhash = rpc_client.get_latest_blockhash().expect("blockhash ok");
assert_eq!(blockhash, expected_blockhash); assert_eq!(blockhash, expected_blockhash);
let rpc_client = RpcClient::new_mock("fails".to_string()); let rpc_client = RpcClient::new_mock("fails".to_string());
assert!(rpc_client.get_recent_blockhash().is_err()); #[allow(deprecated)]
let result = rpc_client.get_recent_blockhash();
assert!(result.is_err());
} }
#[test] #[test]
@ -3229,4 +3339,20 @@ mod tests {
Ok(()) Ok(())
} }
#[test]
fn test_get_latest_blockhash() {
let rpc_client = RpcClient::new_mock("succeeds".to_string());
let expected_blockhash: Hash = PUBKEY.parse().unwrap();
let blockhash = rpc_client.get_latest_blockhash().expect("blockhash ok");
assert_eq!(blockhash, expected_blockhash);
let rpc_client = RpcClient::new_mock("fails".to_string());
#[allow(deprecated)]
let is_err = rpc_client.get_latest_blockhash().is_err();
assert!(is_err);
}
} }

View File

@ -8,6 +8,9 @@ use {
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum RpcRequest { pub enum RpcRequest {
Custom {
method: &'static str,
},
DeregisterNode, DeregisterNode,
GetAccountInfo, GetAccountInfo,
GetBalance, GetBalance,
@ -18,7 +21,6 @@ pub enum RpcRequest {
GetBlocksWithLimit, GetBlocksWithLimit,
GetBlockTime, GetBlockTime,
GetClusterNodes, GetClusterNodes,
#[deprecated(since = "1.7.0", note = "Please use RpcRequest::GetBlock instead")] #[deprecated(since = "1.7.0", note = "Please use RpcRequest::GetBlock instead")]
GetConfirmedBlock, GetConfirmedBlock,
#[deprecated(since = "1.7.0", note = "Please use RpcRequest::GetBlocks instead")] #[deprecated(since = "1.7.0", note = "Please use RpcRequest::GetBlocks instead")]
@ -38,11 +40,23 @@ pub enum RpcRequest {
note = "Please use RpcRequest::GetTransaction instead" note = "Please use RpcRequest::GetTransaction instead"
)] )]
GetConfirmedTransaction, GetConfirmedTransaction,
GetEpochInfo, GetEpochInfo,
GetEpochSchedule, GetEpochSchedule,
#[deprecated(
since = "1.8.0",
note = "Please use RpcRequest::GetFeeForMessage instead"
)]
GetFeeCalculatorForBlockhash, GetFeeCalculatorForBlockhash,
GetFeeForMessage,
#[deprecated(
since = "1.8.0",
note = "Please do not use, will no longer be available in the future"
)]
GetFeeRateGovernor, GetFeeRateGovernor,
#[deprecated(
since = "1.8.0",
note = "Please use RpcRequest::GetFeeForMessage instead"
)]
GetFees, GetFees,
GetFirstAvailableBlock, GetFirstAvailableBlock,
GetGenesisHash, GetGenesisHash,
@ -52,12 +66,17 @@ pub enum RpcRequest {
GetInflationRate, GetInflationRate,
GetInflationReward, GetInflationReward,
GetLargestAccounts, GetLargestAccounts,
GetLatestBlockhash,
GetLeaderSchedule, GetLeaderSchedule,
GetMaxRetransmitSlot, GetMaxRetransmitSlot,
GetMaxShredInsertSlot, GetMaxShredInsertSlot,
GetMinimumBalanceForRentExemption, GetMinimumBalanceForRentExemption,
GetMultipleAccounts, GetMultipleAccounts,
GetProgramAccounts, GetProgramAccounts,
#[deprecated(
since = "1.8.0",
note = "Please use RpcRequest::GetLatestBlockhash instead"
)]
GetRecentBlockhash, GetRecentBlockhash,
GetRecentPerformanceSamples, GetRecentPerformanceSamples,
GetSnapshotSlot, GetSnapshotSlot,
@ -80,21 +99,20 @@ pub enum RpcRequest {
GetTransactionCount, GetTransactionCount,
GetVersion, GetVersion,
GetVoteAccounts, GetVoteAccounts,
IsBlockhashValid,
MinimumLedgerSlot, MinimumLedgerSlot,
RegisterNode, RegisterNode,
RequestAirdrop, RequestAirdrop,
SendTransaction, SendTransaction,
SimulateTransaction, SimulateTransaction,
SignVote, SignVote,
Custom {
method: &'static str,
},
} }
#[allow(deprecated)] #[allow(deprecated)]
impl fmt::Display for RpcRequest { impl fmt::Display for RpcRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let method = match self { let method = match self {
RpcRequest::Custom { method } => method,
RpcRequest::DeregisterNode => "deregisterNode", RpcRequest::DeregisterNode => "deregisterNode",
RpcRequest::GetAccountInfo => "getAccountInfo", RpcRequest::GetAccountInfo => "getAccountInfo",
RpcRequest::GetBalance => "getBalance", RpcRequest::GetBalance => "getBalance",
@ -113,6 +131,7 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetEpochInfo => "getEpochInfo", RpcRequest::GetEpochInfo => "getEpochInfo",
RpcRequest::GetEpochSchedule => "getEpochSchedule", RpcRequest::GetEpochSchedule => "getEpochSchedule",
RpcRequest::GetFeeCalculatorForBlockhash => "getFeeCalculatorForBlockhash", RpcRequest::GetFeeCalculatorForBlockhash => "getFeeCalculatorForBlockhash",
RpcRequest::GetFeeForMessage => "getFeeForMessage",
RpcRequest::GetFeeRateGovernor => "getFeeRateGovernor", RpcRequest::GetFeeRateGovernor => "getFeeRateGovernor",
RpcRequest::GetFees => "getFees", RpcRequest::GetFees => "getFees",
RpcRequest::GetFirstAvailableBlock => "getFirstAvailableBlock", RpcRequest::GetFirstAvailableBlock => "getFirstAvailableBlock",
@ -123,6 +142,7 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetInflationRate => "getInflationRate", RpcRequest::GetInflationRate => "getInflationRate",
RpcRequest::GetInflationReward => "getInflationReward", RpcRequest::GetInflationReward => "getInflationReward",
RpcRequest::GetLargestAccounts => "getLargestAccounts", RpcRequest::GetLargestAccounts => "getLargestAccounts",
RpcRequest::GetLatestBlockhash => "getLatestBlockhash",
RpcRequest::GetLeaderSchedule => "getLeaderSchedule", RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
RpcRequest::GetMaxRetransmitSlot => "getMaxRetransmitSlot", RpcRequest::GetMaxRetransmitSlot => "getMaxRetransmitSlot",
RpcRequest::GetMaxShredInsertSlot => "getMaxShredInsertSlot", RpcRequest::GetMaxShredInsertSlot => "getMaxShredInsertSlot",
@ -151,13 +171,13 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetTransactionCount => "getTransactionCount", RpcRequest::GetTransactionCount => "getTransactionCount",
RpcRequest::GetVersion => "getVersion", RpcRequest::GetVersion => "getVersion",
RpcRequest::GetVoteAccounts => "getVoteAccounts", RpcRequest::GetVoteAccounts => "getVoteAccounts",
RpcRequest::IsBlockhashValid => "isBlockhashValid",
RpcRequest::MinimumLedgerSlot => "minimumLedgerSlot", RpcRequest::MinimumLedgerSlot => "minimumLedgerSlot",
RpcRequest::RegisterNode => "registerNode", RpcRequest::RegisterNode => "registerNode",
RpcRequest::RequestAirdrop => "requestAirdrop", RpcRequest::RequestAirdrop => "requestAirdrop",
RpcRequest::SendTransaction => "sendTransaction", RpcRequest::SendTransaction => "sendTransaction",
RpcRequest::SimulateTransaction => "simulateTransaction", RpcRequest::SimulateTransaction => "simulateTransaction",
RpcRequest::SignVote => "signVote", RpcRequest::SignVote => "signVote",
RpcRequest::Custom { method } => method,
}; };
write!(f, "{}", method) write!(f, "{}", method)
@ -261,14 +281,17 @@ mod tests {
let request = test_request.build_request_json(1, Value::Null); let request = test_request.build_request_json(1, Value::Null);
assert_eq!(request["method"], "getEpochInfo"); assert_eq!(request["method"], "getEpochInfo");
#[allow(deprecated)]
let test_request = RpcRequest::GetRecentBlockhash; let test_request = RpcRequest::GetRecentBlockhash;
let request = test_request.build_request_json(1, Value::Null); let request = test_request.build_request_json(1, Value::Null);
assert_eq!(request["method"], "getRecentBlockhash"); assert_eq!(request["method"], "getRecentBlockhash");
#[allow(deprecated)]
let test_request = RpcRequest::GetFeeCalculatorForBlockhash; let test_request = RpcRequest::GetFeeCalculatorForBlockhash;
let request = test_request.build_request_json(1, json!([addr])); let request = test_request.build_request_json(1, json!([addr]));
assert_eq!(request["method"], "getFeeCalculatorForBlockhash"); assert_eq!(request["method"], "getFeeCalculatorForBlockhash");
#[allow(deprecated)]
let test_request = RpcRequest::GetFeeRateGovernor; let test_request = RpcRequest::GetFeeRateGovernor;
let request = test_request.build_request_json(1, Value::Null); let request = test_request.build_request_json(1, Value::Null);
assert_eq!(request["method"], "getFeeRateGovernor"); assert_eq!(request["method"], "getFeeRateGovernor");
@ -298,6 +321,7 @@ mod tests {
let addr = json!("deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"); let addr = json!("deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
// Test request with CommitmentConfig and no params // Test request with CommitmentConfig and no params
#[allow(deprecated)]
let test_request = RpcRequest::GetRecentBlockhash; let test_request = RpcRequest::GetRecentBlockhash;
let request = test_request.build_request_json(1, json!([commitment_config])); let request = test_request.build_request_json(1, json!([commitment_config]));
assert_eq!(request["params"], json!([commitment_config.clone()])); assert_eq!(request["params"], json!([commitment_config.clone()]));

View File

@ -41,6 +41,13 @@ pub struct RpcBlockhashFeeCalculator {
pub fee_calculator: FeeCalculator, pub fee_calculator: FeeCalculator,
} }
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcBlockhash {
pub blockhash: String,
pub last_valid_block_height: u64,
}
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RpcFees { pub struct RpcFees {

View File

@ -246,7 +246,7 @@ impl ThinClient {
} }
} }
info!("{} tries failed transfer to {}", x, self.tpu_addr()); info!("{} tries failed transfer to {}", x, self.tpu_addr());
let (blockhash, _fee_calculator) = self.get_recent_blockhash()?; let blockhash = self.get_latest_blockhash()?;
transaction.sign(keypairs, blockhash); transaction.sign(keypairs, blockhash);
} }
Err(io::Error::new( Err(io::Error::new(
@ -333,7 +333,7 @@ impl SyncClient for ThinClient {
keypairs: &T, keypairs: &T,
message: Message, message: Message,
) -> TransportResult<Signature> { ) -> TransportResult<Signature> {
let (blockhash, _fee_calculator) = self.get_recent_blockhash()?; let blockhash = self.get_latest_blockhash()?;
let mut transaction = Transaction::new(keypairs, message, blockhash); let mut transaction = Transaction::new(keypairs, message, blockhash);
let signature = self.send_and_confirm_transaction(keypairs, &mut transaction, 5, 0)?; let signature = self.send_and_confirm_transaction(keypairs, &mut transaction, 5, 0)?;
Ok(signature) Ok(signature)
@ -404,6 +404,7 @@ impl SyncClient for ThinClient {
} }
fn get_recent_blockhash(&self) -> TransportResult<(Hash, FeeCalculator)> { fn get_recent_blockhash(&self) -> TransportResult<(Hash, FeeCalculator)> {
#[allow(deprecated)]
let (blockhash, fee_calculator, _last_valid_slot) = let (blockhash, fee_calculator, _last_valid_slot) =
self.get_recent_blockhash_with_commitment(CommitmentConfig::default())?; self.get_recent_blockhash_with_commitment(CommitmentConfig::default())?;
Ok((blockhash, fee_calculator)) Ok((blockhash, fee_calculator))
@ -415,6 +416,7 @@ impl SyncClient for ThinClient {
) -> TransportResult<(Hash, FeeCalculator, Slot)> { ) -> TransportResult<(Hash, FeeCalculator, Slot)> {
let index = self.optimizer.experiment(); let index = self.optimizer.experiment();
let now = Instant::now(); let now = Instant::now();
#[allow(deprecated)]
let recent_blockhash = let recent_blockhash =
self.rpc_clients[index].get_recent_blockhash_with_commitment(commitment_config); self.rpc_clients[index].get_recent_blockhash_with_commitment(commitment_config);
match recent_blockhash { match recent_blockhash {
@ -433,12 +435,14 @@ impl SyncClient for ThinClient {
&self, &self,
blockhash: &Hash, blockhash: &Hash,
) -> TransportResult<Option<FeeCalculator>> { ) -> TransportResult<Option<FeeCalculator>> {
#[allow(deprecated)]
self.rpc_client() self.rpc_client()
.get_fee_calculator_for_blockhash(blockhash) .get_fee_calculator_for_blockhash(blockhash)
.map_err(|e| e.into()) .map_err(|e| e.into())
} }
fn get_fee_rate_governor(&self) -> TransportResult<FeeRateGovernor> { fn get_fee_rate_governor(&self) -> TransportResult<FeeRateGovernor> {
#[allow(deprecated)]
self.rpc_client() self.rpc_client()
.get_fee_rate_governor() .get_fee_rate_governor()
.map_err(|e| e.into()) .map_err(|e| e.into())
@ -556,10 +560,57 @@ impl SyncClient for ThinClient {
} }
fn get_new_blockhash(&self, blockhash: &Hash) -> TransportResult<(Hash, FeeCalculator)> { fn get_new_blockhash(&self, blockhash: &Hash) -> TransportResult<(Hash, FeeCalculator)> {
#[allow(deprecated)]
self.rpc_client() self.rpc_client()
.get_new_blockhash(blockhash) .get_new_blockhash(blockhash)
.map_err(|e| e.into()) .map_err(|e| e.into())
} }
fn get_latest_blockhash(&self) -> TransportResult<Hash> {
let (blockhash, _) =
self.get_latest_blockhash_with_commitment(CommitmentConfig::default())?;
Ok(blockhash)
}
fn get_latest_blockhash_with_commitment(
&self,
commitment_config: CommitmentConfig,
) -> TransportResult<(Hash, u64)> {
let index = self.optimizer.experiment();
let now = Instant::now();
match self.rpc_clients[index].get_latest_blockhash_with_commitment(commitment_config) {
Ok((blockhash, last_valid_block_height)) => {
self.optimizer.report(index, duration_as_ms(&now.elapsed()));
Ok((blockhash, last_valid_block_height))
}
Err(e) => {
self.optimizer.report(index, std::u64::MAX);
Err(e.into())
}
}
}
fn is_blockhash_valid(
&self,
blockhash: &Hash,
commitment_config: CommitmentConfig,
) -> TransportResult<bool> {
self.rpc_client()
.is_blockhash_valid(blockhash, commitment_config)
.map_err(|e| e.into())
}
fn get_fee_for_message(&self, blockhash: &Hash, message: &Message) -> TransportResult<u64> {
self.rpc_client()
.get_fee_for_message(blockhash, message)
.map_err(|e| e.into())
}
fn get_new_latest_blockhash(&self, blockhash: &Hash) -> TransportResult<Hash> {
self.rpc_client()
.get_new_latest_blockhash(blockhash)
.map_err(|e| e.into())
}
} }
impl AsyncClient for ThinClient { impl AsyncClient for ThinClient {

View File

@ -28,6 +28,8 @@ use {
exit::Exit, exit::Exit,
fee_calculator::{FeeCalculator, FeeRateGovernor}, fee_calculator::{FeeCalculator, FeeRateGovernor},
hash::Hash, hash::Hash,
instruction::{AccountMeta, Instruction},
message::Message,
native_token::sol_to_lamports, native_token::sol_to_lamports,
pubkey::Pubkey, pubkey::Pubkey,
rent::Rent, rent::Rent,
@ -551,27 +553,42 @@ impl TestValidator {
{ {
let rpc_client = let rpc_client =
RpcClient::new_with_commitment(rpc_url.clone(), CommitmentConfig::processed()); RpcClient::new_with_commitment(rpc_url.clone(), CommitmentConfig::processed());
let message = Message::new(
if let Ok(result) = rpc_client.get_fee_rate_governor() { &[Instruction::new_with_bytes(
let fee_rate_governor = result.value; Pubkey::new_unique(),
if fee_rate_governor.target_lamports_per_signature > 0 { &[],
vec![AccountMeta::new(Pubkey::new_unique(), true)],
)],
None,
);
const MAX_TRIES: u64 = 10;
let mut num_tries = 0;
loop { loop {
match rpc_client.get_recent_blockhash() { num_tries += 1;
Ok((_blockhash, fee_calculator)) => { if num_tries > MAX_TRIES {
if fee_calculator.lamports_per_signature != 0 { break;
}
println!("Waiting for fees to stabilize {:?}...", num_tries);
match rpc_client.get_latest_blockhash() {
Ok(blockhash) => match rpc_client.get_fee_for_message(&blockhash, &message) {
Ok(fee) => {
if fee != 0 {
break; break;
} }
} }
Err(err) => { Err(err) => {
warn!("get_recent_blockhash() failed: {:?}", err); warn!("get_fee_for_message() failed: {:?}", err);
break;
}
},
Err(err) => {
warn!("get_latest_blockhash() failed: {:?}", err);
break; break;
} }
} }
sleep(Duration::from_millis(DEFAULT_MS_PER_SLOT)); sleep(Duration::from_millis(DEFAULT_MS_PER_SLOT));
} }
} }
}
}
Ok(TestValidator { Ok(TestValidator {
ledger_path, ledger_path,
@ -615,6 +632,7 @@ impl TestValidator {
pub fn rpc_client(&self) -> (RpcClient, Hash, FeeCalculator) { pub fn rpc_client(&self) -> (RpcClient, Hash, FeeCalculator) {
let rpc_client = let rpc_client =
RpcClient::new_with_commitment(self.rpc_url.clone(), CommitmentConfig::processed()); RpcClient::new_with_commitment(self.rpc_url.clone(), CommitmentConfig::processed());
#[allow(deprecated)]
let (recent_blockhash, fee_calculator) = rpc_client let (recent_blockhash, fee_calculator) = rpc_client
.get_recent_blockhash() .get_recent_blockhash()
.expect("get_recent_blockhash"); .expect("get_recent_blockhash");

View File

@ -82,12 +82,12 @@ impl VoteSimulator {
for (pubkey, vote) in cluster_votes.iter() { for (pubkey, vote) in cluster_votes.iter() {
if vote.contains(&parent) { if vote.contains(&parent) {
let keypairs = self.validator_keypairs.get(pubkey).unwrap(); let keypairs = self.validator_keypairs.get(pubkey).unwrap();
let last_blockhash = parent_bank.last_blockhash(); let latest_blockhash = parent_bank.last_blockhash();
let vote_tx = vote_transaction::new_vote_transaction( let vote_tx = vote_transaction::new_vote_transaction(
// Must vote > root to be processed // Must vote > root to be processed
vec![parent], vec![parent],
parent_bank.hash(), parent_bank.hash(),
last_blockhash, latest_blockhash,
&keypairs.node_keypair, &keypairs.node_keypair,
&keypairs.vote_keypair, &keypairs.vote_keypair,
&keypairs.vote_keypair, &keypairs.vote_keypair,

View File

@ -53,7 +53,7 @@ fn test_rpc_client() {
let original_alice_balance = client.get_balance(&alice.pubkey()).unwrap(); let original_alice_balance = client.get_balance(&alice.pubkey()).unwrap();
let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap(); let blockhash = client.get_latest_blockhash().unwrap();
let tx = system_transaction::transfer(&alice, &bob_pubkey, sol_to_lamports(20.0), blockhash); let tx = system_transaction::transfer(&alice, &bob_pubkey, sol_to_lamports(20.0), blockhash);
let signature = client.send_transaction(&tx).unwrap(); let signature = client.send_transaction(&tx).unwrap();

View File

@ -231,7 +231,7 @@ fn test_rpc_subscriptions() {
transactions_socket.connect(test_validator.tpu()).unwrap(); transactions_socket.connect(test_validator.tpu()).unwrap();
let rpc_client = RpcClient::new(test_validator.rpc_url()); let rpc_client = RpcClient::new(test_validator.rpc_url());
let recent_blockhash = rpc_client.get_recent_blockhash().unwrap().0; let recent_blockhash = rpc_client.get_latest_blockhash().unwrap();
// Create transaction signatures to subscribe to // Create transaction signatures to subscribe to
let transactions: Vec<Transaction> = (0..1000) let transactions: Vec<Transaction> = (0..1000)
@ -406,7 +406,7 @@ fn test_tpu_send_transaction() {
) )
.unwrap(); .unwrap();
let recent_blockhash = rpc_client.get_recent_blockhash().unwrap().0; let recent_blockhash = rpc_client.get_latest_blockhash().unwrap();
let tx = let tx =
system_transaction::transfer(&mint_keypair, &Pubkey::new_unique(), 42, recent_blockhash); system_transaction::transfer(&mint_keypair, &Pubkey::new_unique(), 42, recent_blockhash);
assert!(tpu_client.send_transaction(&tx)); assert!(tpu_client.send_transaction(&tx));
@ -433,8 +433,8 @@ fn deserialize_rpc_error() -> ClientResult<()> {
let bob = Keypair::new(); let bob = Keypair::new();
let lamports = 50; let lamports = 50;
let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?; let blockhash = rpc_client.get_latest_blockhash()?;
let mut tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, recent_blockhash); let mut tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, blockhash);
// This will cause an error // This will cause an error
tx.signatures.clear(); tx.signatures.clear();

View File

@ -122,7 +122,7 @@ https://github.com/solana-labs/solana/blob/b6bfed64cb159ee67bb6bdbaefc7f833bbed3
// Number of signatures processed in this block // Number of signatures processed in this block
&signature_count_buf, &signature_count_buf,
// Last PoH hash in this block // Last PoH hash in this block
self.last_blockhash().as_ref(), self.latest_blockhash().as_ref(),
]); ]);
``` ```

View File

@ -218,7 +218,7 @@ fn new_update_manifest(
.get_account_data(&update_manifest_keypair.pubkey()) .get_account_data(&update_manifest_keypair.pubkey())
.is_err() .is_err()
{ {
let (recent_blockhash, _fee_calculator) = rpc_client.get_recent_blockhash()?; let recent_blockhash = rpc_client.get_latest_blockhash()?;
let lamports = rpc_client let lamports = rpc_client
.get_minimum_balance_for_rent_exemption(SignedUpdateManifest::max_space() as usize)?; .get_minimum_balance_for_rent_exemption(SignedUpdateManifest::max_space() as usize)?;
@ -244,7 +244,7 @@ fn store_update_manifest(
update_manifest_keypair: &Keypair, update_manifest_keypair: &Keypair,
update_manifest: &SignedUpdateManifest, update_manifest: &SignedUpdateManifest,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
let (recent_blockhash, _fee_calculator) = rpc_client.get_recent_blockhash()?; let recent_blockhash = rpc_client.get_latest_blockhash()?;
let signers = [from_keypair, update_manifest_keypair]; let signers = [from_keypair, update_manifest_keypair];
let instruction = config_instruction::store::<SignedUpdateManifest>( let instruction = config_instruction::store::<SignedUpdateManifest>(

View File

@ -66,8 +66,8 @@ pub fn spend_and_verify_all_nodes<S: ::std::hash::BuildHasher + Sync + Send>(
) )
.expect("balance in source"); .expect("balance in source");
assert!(bal > 0); assert!(bal > 0);
let (blockhash, _fee_calculator, _last_valid_slot) = client let (blockhash, _) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::confirmed()) .get_latest_blockhash_with_commitment(CommitmentConfig::confirmed())
.unwrap(); .unwrap();
let mut transaction = let mut transaction =
system_transaction::transfer(funding_keypair, &random_keypair.pubkey(), 1, blockhash); system_transaction::transfer(funding_keypair, &random_keypair.pubkey(), 1, blockhash);
@ -115,8 +115,8 @@ pub fn send_many_transactions(
) )
.expect("balance in source"); .expect("balance in source");
assert!(bal > 0); assert!(bal > 0);
let (blockhash, _fee_calculator, _last_valid_slot) = client let (blockhash, _) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed()) .get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap(); .unwrap();
let transfer_amount = thread_rng().gen_range(1, max_tokens_per_transfer); let transfer_amount = thread_rng().gen_range(1, max_tokens_per_transfer);
@ -241,8 +241,8 @@ pub fn kill_entry_and_spend_and_verify_rest(
} }
let random_keypair = Keypair::new(); let random_keypair = Keypair::new();
let (blockhash, _fee_calculator, _last_valid_slot) = client let (blockhash, _) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed()) .get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap(); .unwrap();
let mut transaction = system_transaction::transfer( let mut transaction = system_transaction::transfer(
funding_keypair, funding_keypair,

View File

@ -481,8 +481,8 @@ impl LocalCluster {
lamports: u64, lamports: u64,
) -> u64 { ) -> u64 {
trace!("getting leader blockhash"); trace!("getting leader blockhash");
let (blockhash, _fee_calculator, _last_valid_slot) = client let (blockhash, _) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed()) .get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap(); .unwrap();
let mut tx = system_transaction::transfer(source_keypair, dest_pubkey, lamports, blockhash); let mut tx = system_transaction::transfer(source_keypair, dest_pubkey, lamports, blockhash);
info!( info!(
@ -542,7 +542,7 @@ impl LocalCluster {
&[from_account.as_ref(), vote_account], &[from_account.as_ref(), vote_account],
message, message,
client client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed()) .get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap() .unwrap()
.0, .0,
); );
@ -570,7 +570,7 @@ impl LocalCluster {
&[from_account.as_ref(), &stake_account_keypair], &[from_account.as_ref(), &stake_account_keypair],
message, message,
client client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed()) .get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap() .unwrap()
.0, .0,
); );

View File

@ -191,8 +191,8 @@ fn test_local_cluster_signature_subscribe() {
non_bootstrap_info.client_facing_addr(), non_bootstrap_info.client_facing_addr(),
VALIDATOR_PORT_RANGE, VALIDATOR_PORT_RANGE,
); );
let (blockhash, _fee_calculator, _last_valid_slot) = tx_client let (blockhash, _) = tx_client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed()) .get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap(); .unwrap();
let mut transaction = system_transaction::transfer( let mut transaction = system_transaction::transfer(
@ -1475,8 +1475,8 @@ fn generate_frozen_account_panic(mut cluster: LocalCluster, frozen_account: Arc<
let mut i = 0; let mut i = 0;
while !solana_runtime::accounts_db::FROZEN_ACCOUNT_PANIC.load(Ordering::Relaxed) { while !solana_runtime::accounts_db::FROZEN_ACCOUNT_PANIC.load(Ordering::Relaxed) {
// Transfer from frozen account // Transfer from frozen account
let (blockhash, _fee_calculator, _last_valid_slot) = client let (blockhash, _) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed()) .get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap(); .unwrap();
client client
.async_transfer( .async_transfer(
@ -3246,8 +3246,8 @@ fn setup_transfer_scan_threads(
if exit_.load(Ordering::Relaxed) { if exit_.load(Ordering::Relaxed) {
return; return;
} }
let (blockhash, _fee_calculator, _last_valid_slot) = client let (blockhash, _) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed()) .get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap(); .unwrap();
for i in 0..starting_keypairs_.len() { for i in 0..starting_keypairs_.len() {
client client

View File

@ -451,12 +451,12 @@ fn setup_fee_calculator(bank: Bank) -> Bank {
} }
let last_blockhash = bank.last_blockhash(); let last_blockhash = bank.last_blockhash();
// Make sure the new last_blockhash now requires a fee // Make sure the new last_blockhash now requires a fee
assert_ne!( #[allow(deprecated)]
bank.get_fee_calculator(&last_blockhash) let lamports_per_signature = bank
.get_fee_calculator(&last_blockhash)
.expect("fee_calculator") .expect("fee_calculator")
.lamports_per_signature, .lamports_per_signature;
0 assert_ne!(lamports_per_signature, 0);
);
bank bank
} }

View File

@ -362,10 +362,12 @@ fn execute_transactions(bank: &Bank, txs: &[Transaction]) -> Vec<ConfirmedTransa
post_token_balances, post_token_balances,
log_messages, log_messages,
)| { )| {
#[allow(deprecated)]
let fee_calculator = nonce_rollback let fee_calculator = nonce_rollback
.map(|nonce_rollback| nonce_rollback.fee_calculator()) .map(|nonce_rollback| nonce_rollback.fee_calculator())
.unwrap_or_else(|| bank.get_fee_calculator(&tx.message().recent_blockhash)) .unwrap_or_else(|| bank.get_fee_calculator(&tx.message().recent_blockhash))
.expect("FeeCalculator must exist"); .expect("FeeCalculator must exist");
#[allow(deprecated)]
let fee = fee_calculator.calculate_fee(tx.message()); let fee = fee_calculator.calculate_fee(tx.message());
let inner_instructions = inner_instructions.map(|inner_instructions| { let inner_instructions = inner_instructions.map(|inner_instructions| {

View File

@ -60,6 +60,7 @@ use {
epoch_schedule::EpochSchedule, epoch_schedule::EpochSchedule,
exit::Exit, exit::Exit,
hash::Hash, hash::Hash,
message::Message,
pubkey::Pubkey, pubkey::Pubkey,
sanitize::Sanitize, sanitize::Sanitize,
signature::{Keypair, Signature, Signer}, signature::{Keypair, Signature, Signer},
@ -80,6 +81,7 @@ use {
state::{Account as TokenAccount, Mint}, state::{Account as TokenAccount, Mint},
}, },
std::{ std::{
any::type_name,
cmp::{max, min}, cmp::{max, min},
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
net::SocketAddr, net::SocketAddr,
@ -531,7 +533,8 @@ impl JsonRpcRequestProcessor {
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> RpcResponse<RpcBlockhashFeeCalculator> { ) -> RpcResponse<RpcBlockhashFeeCalculator> {
let bank = self.bank(commitment); let bank = self.bank(commitment);
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash(); #[allow(deprecated)]
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash_with_fee_calculator();
new_response( new_response(
&bank, &bank,
RpcBlockhashFeeCalculator { RpcBlockhashFeeCalculator {
@ -543,7 +546,8 @@ 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(); #[allow(deprecated)]
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash_with_fee_calculator();
#[allow(deprecated)] #[allow(deprecated)]
let last_valid_slot = bank let last_valid_slot = bank
.get_blockhash_last_valid_slot(&blockhash) .get_blockhash_last_valid_slot(&blockhash)
@ -568,6 +572,7 @@ impl JsonRpcRequestProcessor {
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> RpcResponse<Option<RpcFeeCalculator>> { ) -> RpcResponse<Option<RpcFeeCalculator>> {
let bank = self.bank(commitment); let bank = self.bank(commitment);
#[allow(deprecated)]
let fee_calculator = bank.get_fee_calculator(blockhash); let fee_calculator = bank.get_fee_calculator(blockhash);
new_response( new_response(
&bank, &bank,
@ -577,6 +582,7 @@ impl JsonRpcRequestProcessor {
fn get_fee_rate_governor(&self) -> RpcResponse<RpcFeeRateGovernor> { fn get_fee_rate_governor(&self) -> RpcResponse<RpcFeeRateGovernor> {
let bank = self.bank(None); let bank = self.bank(None);
#[allow(deprecated)]
let fee_rate_governor = bank.get_fee_rate_governor(); let fee_rate_governor = bank.get_fee_rate_governor();
new_response( new_response(
&bank, &bank,
@ -1896,6 +1902,45 @@ impl JsonRpcRequestProcessor {
self.get_filtered_program_accounts(bank, &spl_token_id_v2_0(), filters) self.get_filtered_program_accounts(bank, &spl_token_id_v2_0(), filters)
} }
} }
fn get_latest_blockhash(
&self,
commitment: Option<CommitmentConfig>,
) -> RpcResponse<RpcBlockhash> {
let bank = self.bank(commitment);
let blockhash = bank.last_blockhash();
let last_valid_block_height = bank
.get_blockhash_last_valid_block_height(&blockhash)
.expect("bank blockhash queue should contain blockhash");
new_response(
&bank,
RpcBlockhash {
blockhash: blockhash.to_string(),
last_valid_block_height,
},
)
}
fn is_blockhash_valid(
&self,
blockhash: &Hash,
commitment: Option<CommitmentConfig>,
) -> RpcResponse<bool> {
let bank = self.bank(commitment);
let is_valid = bank.is_blockhash_valid(blockhash);
new_response(&bank, is_valid)
}
fn get_fee_for_message(
&self,
blockhash: &Hash,
message: &Message,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<Option<u64>>> {
let bank = self.bank(commitment);
let fee = bank.get_fee_for_message(blockhash, message);
Ok(new_response(&bank, fee))
}
} }
fn verify_transaction( fn verify_transaction(
@ -2410,34 +2455,6 @@ pub mod rpc_bank {
#[rpc(meta, name = "getEpochSchedule")] #[rpc(meta, name = "getEpochSchedule")]
fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result<EpochSchedule>; fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result<EpochSchedule>;
#[rpc(meta, name = "getRecentBlockhash")]
fn get_recent_blockhash(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<RpcBlockhashFeeCalculator>>;
#[rpc(meta, name = "getFees")]
fn get_fees(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<RpcFees>>;
#[rpc(meta, name = "getFeeCalculatorForBlockhash")]
fn get_fee_calculator_for_blockhash(
&self,
meta: Self::Metadata,
blockhash: String,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<Option<RpcFeeCalculator>>>;
#[rpc(meta, name = "getFeeRateGovernor")]
fn get_fee_rate_governor(
&self,
meta: Self::Metadata,
) -> Result<RpcResponse<RpcFeeRateGovernor>>;
#[rpc(meta, name = "getSlotLeader")] #[rpc(meta, name = "getSlotLeader")]
fn get_slot_leader( fn get_slot_leader(
&self, &self,
@ -2500,44 +2517,6 @@ pub mod rpc_bank {
Ok(meta.get_epoch_schedule()) Ok(meta.get_epoch_schedule())
} }
fn get_recent_blockhash(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<RpcBlockhashFeeCalculator>> {
debug!("get_recent_blockhash rpc request received");
Ok(meta.get_recent_blockhash(commitment))
}
fn get_fees(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<RpcFees>> {
debug!("get_fees rpc request received");
Ok(meta.get_fees(commitment))
}
fn get_fee_calculator_for_blockhash(
&self,
meta: Self::Metadata,
blockhash: String,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<Option<RpcFeeCalculator>>> {
debug!("get_fee_calculator_for_blockhash rpc request received");
let blockhash = Hash::from_str(&blockhash)
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?;
Ok(meta.get_fee_calculator_for_blockhash(&blockhash, commitment))
}
fn get_fee_rate_governor(
&self,
meta: Self::Metadata,
) -> Result<RpcResponse<RpcFeeRateGovernor>> {
debug!("get_fee_rate_governor rpc request received");
Ok(meta.get_fee_rate_governor())
}
fn get_slot_leader( fn get_slot_leader(
&self, &self,
meta: Self::Metadata, meta: Self::Metadata,
@ -3084,6 +3063,31 @@ pub mod rpc_full {
#[rpc(meta, name = "getFirstAvailableBlock")] #[rpc(meta, name = "getFirstAvailableBlock")]
fn get_first_available_block(&self, meta: Self::Metadata) -> BoxFuture<Result<Slot>>; fn get_first_available_block(&self, meta: Self::Metadata) -> BoxFuture<Result<Slot>>;
#[rpc(meta, name = "getLatestBlockhash")]
fn get_latest_blockhash(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<RpcBlockhash>>;
#[rpc(meta, name = "isBlockhashValid")]
fn is_blockhash_valid(
&self,
meta: Self::Metadata,
blockhash: String,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<bool>>;
#[rpc(meta, name = "getFeeForMessage")]
fn get_fee_for_message(
&self,
meta: Self::Metadata,
blockhash: String,
data: String,
encoding: UiTransactionEncoding,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<Option<u64>>>;
} }
pub struct FullImpl; pub struct FullImpl;
@ -3232,7 +3236,7 @@ pub mod rpc_full {
let blockhash = if let Some(blockhash) = config.recent_blockhash { let blockhash = if let Some(blockhash) = config.recent_blockhash {
verify_hash(&blockhash)? verify_hash(&blockhash)?
} else { } else {
bank.confirmed_last_blockhash().0 bank.confirmed_last_blockhash()
}; };
let last_valid_block_height = bank let last_valid_block_height = bank
.get_blockhash_last_valid_block_height(&blockhash) .get_blockhash_last_valid_block_height(&blockhash)
@ -3269,7 +3273,8 @@ pub mod rpc_full {
debug!("send_transaction rpc request received"); debug!("send_transaction rpc request received");
let config = config.unwrap_or_default(); let config = config.unwrap_or_default();
let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58); let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58);
let (wire_transaction, transaction) = deserialize_transaction(data, encoding)?; let (wire_transaction, transaction) =
decode_and_deserialize::<Transaction>(data, encoding)?;
let preflight_commitment = config let preflight_commitment = config
.preflight_commitment .preflight_commitment
@ -3369,7 +3374,7 @@ pub mod rpc_full {
debug!("simulate_transaction rpc request received"); debug!("simulate_transaction rpc request received");
let config = config.unwrap_or_default(); let config = config.unwrap_or_default();
let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58); let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58);
let (_, mut transaction) = deserialize_transaction(data, encoding)?; let (_, mut transaction) = decode_and_deserialize::<Transaction>(data, encoding)?;
let bank = &*meta.bank(config.commitment); let bank = &*meta.bank(config.commitment);
if config.sig_verify { if config.sig_verify {
@ -3578,10 +3583,126 @@ pub mod rpc_full {
Box::pin(async move { meta.get_inflation_reward(addresses, config).await }) Box::pin(async move { meta.get_inflation_reward(addresses, config).await })
} }
fn get_latest_blockhash(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<RpcBlockhash>> {
debug!("get_latest_blockhash rpc request received");
Ok(meta.get_latest_blockhash(commitment))
}
fn is_blockhash_valid(
&self,
meta: Self::Metadata,
blockhash: String,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<bool>> {
let blockhash = Hash::from_str(&blockhash)
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?;
Ok(meta.is_blockhash_valid(&blockhash, commitment))
}
fn get_fee_for_message(
&self,
meta: Self::Metadata,
blockhash: String,
data: String,
encoding: UiTransactionEncoding,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<Option<u64>>> {
debug!("get_fee_for_message rpc request received");
let blockhash = Hash::from_str(&blockhash)
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?;
let (_, message) = decode_and_deserialize::<Message>(data, encoding)?;
meta.get_fee_for_message(&blockhash, &message, commitment)
}
} }
} }
// Deprecated RPC methods, collected for easy deactivation and removal in v1.8 // RPC methods deprecated in v1.8
pub mod rpc_deprecated_v1_8 {
#![allow(deprecated)]
use super::*;
#[rpc]
pub trait DeprecatedV1_8 {
type Metadata;
#[rpc(meta, name = "getRecentBlockhash")]
fn get_recent_blockhash(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<RpcBlockhashFeeCalculator>>;
#[rpc(meta, name = "getFees")]
fn get_fees(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<RpcFees>>;
#[rpc(meta, name = "getFeeCalculatorForBlockhash")]
fn get_fee_calculator_for_blockhash(
&self,
meta: Self::Metadata,
blockhash: String,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<Option<RpcFeeCalculator>>>;
#[rpc(meta, name = "getFeeRateGovernor")]
fn get_fee_rate_governor(
&self,
meta: Self::Metadata,
) -> Result<RpcResponse<RpcFeeRateGovernor>>;
}
pub struct DeprecatedV1_8Impl;
impl DeprecatedV1_8 for DeprecatedV1_8Impl {
type Metadata = JsonRpcRequestProcessor;
fn get_recent_blockhash(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<RpcBlockhashFeeCalculator>> {
debug!("get_recent_blockhash rpc request received");
Ok(meta.get_recent_blockhash(commitment))
}
fn get_fees(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<RpcFees>> {
debug!("get_fees rpc request received");
Ok(meta.get_fees(commitment))
}
fn get_fee_calculator_for_blockhash(
&self,
meta: Self::Metadata,
blockhash: String,
commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<Option<RpcFeeCalculator>>> {
debug!("get_fee_calculator_for_blockhash rpc request received");
let blockhash = Hash::from_str(&blockhash)
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?;
Ok(meta.get_fee_calculator_for_blockhash(&blockhash, commitment))
}
fn get_fee_rate_governor(
&self,
meta: Self::Metadata,
) -> Result<RpcResponse<RpcFeeRateGovernor>> {
debug!("get_fee_rate_governor rpc request received");
Ok(meta.get_fee_rate_governor())
}
}
}
// RPC methods deprecated in v1.7
pub mod rpc_deprecated_v1_7 { pub mod rpc_deprecated_v1_7 {
#![allow(deprecated)] #![allow(deprecated)]
use super::*; use super::*;
@ -3874,51 +3995,56 @@ pub mod rpc_obsolete_v1_7 {
} }
} }
const WORST_CASE_BASE58_TX: usize = 1683; // Golden, bump if PACKET_DATA_SIZE changes const MAX_BASE58_SIZE: usize = 1683; // Golden, bump if PACKET_DATA_SIZE changes
const WORST_CASE_BASE64_TX: usize = 1644; // Golden, bump if PACKET_DATA_SIZE changes const MAX_BASE64_SIZE: usize = 1644; // Golden, bump if PACKET_DATA_SIZE changes
fn deserialize_transaction( fn decode_and_deserialize<T>(
encoded_transaction: String, encoded: String,
encoding: UiTransactionEncoding, encoding: UiTransactionEncoding,
) -> Result<(Vec<u8>, Transaction)> { ) -> Result<(Vec<u8>, T)>
let wire_transaction = match encoding { where
T: serde::de::DeserializeOwned + Sanitize,
{
let wire_output = match encoding {
UiTransactionEncoding::Base58 => { UiTransactionEncoding::Base58 => {
inc_new_counter_info!("rpc-base58_encoded_tx", 1); inc_new_counter_info!("rpc-base58_encoded_tx", 1);
if encoded_transaction.len() > WORST_CASE_BASE58_TX { if encoded.len() > MAX_BASE58_SIZE {
return Err(Error::invalid_params(format!( return Err(Error::invalid_params(format!(
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})", "encoded {} too large: {} bytes (max: encoded/raw {}/{})",
encoded_transaction.len(), type_name::<T>(),
WORST_CASE_BASE58_TX, encoded.len(),
MAX_BASE58_SIZE,
PACKET_DATA_SIZE, PACKET_DATA_SIZE,
))); )));
} }
bs58::decode(encoded_transaction) bs58::decode(encoded)
.into_vec() .into_vec()
.map_err(|e| Error::invalid_params(format!("{:?}", e)))? .map_err(|e| Error::invalid_params(format!("{:?}", e)))?
} }
UiTransactionEncoding::Base64 => { UiTransactionEncoding::Base64 => {
inc_new_counter_info!("rpc-base64_encoded_tx", 1); inc_new_counter_info!("rpc-base64_encoded_tx", 1);
if encoded_transaction.len() > WORST_CASE_BASE64_TX { if encoded.len() > MAX_BASE64_SIZE {
return Err(Error::invalid_params(format!( return Err(Error::invalid_params(format!(
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})", "encoded {} too large: {} bytes (max: encoded/raw {}/{})",
encoded_transaction.len(), type_name::<T>(),
WORST_CASE_BASE64_TX, encoded.len(),
MAX_BASE64_SIZE,
PACKET_DATA_SIZE, PACKET_DATA_SIZE,
))); )));
} }
base64::decode(encoded_transaction) base64::decode(encoded).map_err(|e| Error::invalid_params(format!("{:?}", e)))?
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?
} }
_ => { _ => {
return Err(Error::invalid_params(format!( return Err(Error::invalid_params(format!(
"unsupported transaction encoding: {}. Supported encodings: base58, base64", "unsupported encoding: {}. Supported encodings: base58, base64",
encoding encoding
))) )))
} }
}; };
if wire_transaction.len() > PACKET_DATA_SIZE { if wire_output.len() > PACKET_DATA_SIZE {
let err = format!( let err = format!(
"transaction too large: {} bytes (max: {} bytes)", "encoded {} too large: {} bytes (max: {} bytes)",
wire_transaction.len(), type_name::<T>(),
wire_output.len(),
PACKET_DATA_SIZE PACKET_DATA_SIZE
); );
info!("{}", err); info!("{}", err);
@ -3928,22 +4054,23 @@ fn deserialize_transaction(
.with_limit(PACKET_DATA_SIZE as u64) .with_limit(PACKET_DATA_SIZE as u64)
.with_fixint_encoding() .with_fixint_encoding()
.allow_trailing_bytes() .allow_trailing_bytes()
.deserialize_from(&wire_transaction[..]) .deserialize_from(&wire_output[..])
.map_err(|err| { .map_err(|err| {
info!("transaction deserialize error: {:?}", err); info!("deserialize error: {}", err);
Error::invalid_params(&err.to_string()) Error::invalid_params(&err.to_string())
}) })
.and_then(|transaction: Transaction| { .and_then(|output: T| {
if let Err(err) = transaction.sanitize() { if let Err(err) = output.sanitize() {
Err(Error::invalid_params(format!( Err(Error::invalid_params(format!(
"invalid transaction: {}", "invalid {}: {}",
type_name::<T>(),
err err
))) )))
} else { } else {
Ok(transaction) Ok(output)
} }
}) })
.map(|transaction| (wire_transaction, transaction)) .map(|output| (wire_output, output))
} }
pub(crate) fn create_validator_exit(exit: &Arc<AtomicBool>) -> Arc<RwLock<Exit>> { pub(crate) fn create_validator_exit(exit: &Arc<AtomicBool>) -> Arc<RwLock<Exit>> {
@ -3966,7 +4093,7 @@ pub fn create_test_transactions_and_populate_blockstore(
let keypair2 = keypairs[2]; let keypair2 = keypairs[2];
let keypair3 = keypairs[3]; let keypair3 = keypairs[3];
let slot = bank.slot(); let slot = bank.slot();
let blockhash = bank.confirmed_last_blockhash().0; let blockhash = bank.confirmed_last_blockhash();
// Generate transactions for processing // Generate transactions for processing
// Successful transaction // Successful transaction
@ -4032,7 +4159,9 @@ pub fn create_test_transactions_and_populate_blockstore(
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use { use {
super::{rpc_accounts::*, rpc_bank::*, rpc_full::*, rpc_minimal::*, *}, super::{
rpc_accounts::*, rpc_bank::*, rpc_deprecated_v1_8::*, rpc_full::*, rpc_minimal::*, *,
},
crate::{ crate::{
optimistically_confirmed_bank_tracker::{ optimistically_confirmed_bank_tracker::{
BankNotification, OptimisticallyConfirmedBankTracker, BankNotification, OptimisticallyConfirmedBankTracker,
@ -4196,7 +4325,7 @@ pub mod tests {
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
let validator_exit = create_validator_exit(&exit); let validator_exit = create_validator_exit(&exit);
let blockhash = bank.confirmed_last_blockhash().0; let blockhash = bank.confirmed_last_blockhash();
let tx = system_transaction::transfer(&alice, pubkey, 20, blockhash); let tx = system_transaction::transfer(&alice, pubkey, 20, blockhash);
bank.process_transaction(&tx).expect("process transaction"); bank.process_transaction(&tx).expect("process transaction");
let tx = let tx =
@ -4267,6 +4396,7 @@ pub mod tests {
io.extend_with(rpc_bank::BankDataImpl.to_delegate()); io.extend_with(rpc_bank::BankDataImpl.to_delegate());
io.extend_with(rpc_accounts::AccountsDataImpl.to_delegate()); io.extend_with(rpc_accounts::AccountsDataImpl.to_delegate());
io.extend_with(rpc_full::FullImpl.to_delegate()); io.extend_with(rpc_full::FullImpl.to_delegate());
io.extend_with(rpc_deprecated_v1_8::DeprecatedV1_8Impl.to_delegate());
RpcHandler { RpcHandler {
io, io,
meta, meta,
@ -5675,6 +5805,7 @@ pub mod tests {
let bob_pubkey = solana_sdk::pubkey::new_rand(); let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey); let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
#[allow(deprecated)]
let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator(); let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator();
let fee_calculator = RpcFeeCalculator { fee_calculator }; let fee_calculator = RpcFeeCalculator { fee_calculator };
@ -5855,7 +5986,7 @@ pub mod tests {
assert_eq!( assert_eq!(
res, res,
Some( Some(
r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid transaction: index out of bounds"},"id":1}"#.to_string(), r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid solana_sdk::transaction::Transaction: index out of bounds"},"id":1}"#.to_string(),
) )
); );
let mut bad_transaction = system_transaction::transfer( let mut bad_transaction = system_transaction::transfer(
@ -5919,7 +6050,7 @@ pub mod tests {
assert_eq!( assert_eq!(
res, res,
Some( Some(
r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid transaction: index out of bounds"},"id":1}"#.to_string(), r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid solana_sdk::transaction::Transaction: index out of bounds"},"id":1}"#.to_string(),
) )
); );
} }
@ -7615,66 +7746,68 @@ pub mod tests {
fn test_worst_case_encoded_tx_goldens() { fn test_worst_case_encoded_tx_goldens() {
let ff_tx = vec![0xffu8; PACKET_DATA_SIZE]; let ff_tx = vec![0xffu8; PACKET_DATA_SIZE];
let tx58 = bs58::encode(&ff_tx).into_string(); let tx58 = bs58::encode(&ff_tx).into_string();
assert_eq!(tx58.len(), WORST_CASE_BASE58_TX); assert_eq!(tx58.len(), MAX_BASE58_SIZE);
let tx64 = base64::encode(&ff_tx); let tx64 = base64::encode(&ff_tx);
assert_eq!(tx64.len(), WORST_CASE_BASE64_TX); assert_eq!(tx64.len(), MAX_BASE64_SIZE);
} }
#[test] #[test]
fn test_deserialize_transaction_too_large_payloads_fail() { fn test_decode_and_deserialize_too_large_payloads_fail() {
// +2 because +1 still fits in base64 encoded worst-case // +2 because +1 still fits in base64 encoded worst-case
let too_big = PACKET_DATA_SIZE + 2; let too_big = PACKET_DATA_SIZE + 2;
let tx_ser = vec![0xffu8; too_big]; let tx_ser = vec![0xffu8; too_big];
let tx58 = bs58::encode(&tx_ser).into_string(); let tx58 = bs58::encode(&tx_ser).into_string();
let tx58_len = tx58.len(); let tx58_len = tx58.len();
let expect58 = Error::invalid_params(format!( let expect58 = Error::invalid_params(format!(
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})", "encoded solana_sdk::transaction::Transaction too large: {} bytes (max: encoded/raw {}/{})",
tx58_len, WORST_CASE_BASE58_TX, PACKET_DATA_SIZE, tx58_len, MAX_BASE58_SIZE, PACKET_DATA_SIZE,
)); ));
assert_eq!( assert_eq!(
deserialize_transaction(tx58, UiTransactionEncoding::Base58).unwrap_err(), decode_and_deserialize::<Transaction>(tx58, UiTransactionEncoding::Base58).unwrap_err(),
expect58 expect58
); );
let tx64 = base64::encode(&tx_ser); let tx64 = base64::encode(&tx_ser);
let tx64_len = tx64.len(); let tx64_len = tx64.len();
let expect64 = Error::invalid_params(format!( let expect64 = Error::invalid_params(format!(
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})", "encoded solana_sdk::transaction::Transaction too large: {} bytes (max: encoded/raw {}/{})",
tx64_len, WORST_CASE_BASE64_TX, PACKET_DATA_SIZE, tx64_len, MAX_BASE64_SIZE, PACKET_DATA_SIZE,
)); ));
assert_eq!( assert_eq!(
deserialize_transaction(tx64, UiTransactionEncoding::Base64).unwrap_err(), decode_and_deserialize::<Transaction>(tx64, UiTransactionEncoding::Base64).unwrap_err(),
expect64 expect64
); );
let too_big = PACKET_DATA_SIZE + 1; let too_big = PACKET_DATA_SIZE + 1;
let tx_ser = vec![0x00u8; too_big]; let tx_ser = vec![0x00u8; too_big];
let tx58 = bs58::encode(&tx_ser).into_string(); let tx58 = bs58::encode(&tx_ser).into_string();
let expect = Error::invalid_params(format!( let expect = Error::invalid_params(format!(
"transaction too large: {} bytes (max: {} bytes)", "encoded solana_sdk::transaction::Transaction too large: {} bytes (max: {} bytes)",
too_big, PACKET_DATA_SIZE too_big, PACKET_DATA_SIZE
)); ));
assert_eq!( assert_eq!(
deserialize_transaction(tx58, UiTransactionEncoding::Base58).unwrap_err(), decode_and_deserialize::<Transaction>(tx58, UiTransactionEncoding::Base58).unwrap_err(),
expect expect
); );
let tx64 = base64::encode(&tx_ser); let tx64 = base64::encode(&tx_ser);
assert_eq!( assert_eq!(
deserialize_transaction(tx64, UiTransactionEncoding::Base64).unwrap_err(), decode_and_deserialize::<Transaction>(tx64, UiTransactionEncoding::Base64).unwrap_err(),
expect expect
); );
} }
#[test] #[test]
fn test_deserialize_transaction_unsanitary() { fn test_decode_and_deserialize_unsanitary() {
let unsanitary_tx58 = "ju9xZWuDBX4pRxX2oZkTjxU5jB4SSTgEGhX8bQ8PURNzyzqKMPPpNvWihx8zUe\ let unsanitary_tx58 = "ju9xZWuDBX4pRxX2oZkTjxU5jB4SSTgEGhX8bQ8PURNzyzqKMPPpNvWihx8zUe\
FfrbVNoAaEsNKZvGzAnTDy5bhNT9kt6KFCTBixpvrLCzg4M5UdFUQYrn1gdgjX\ FfrbVNoAaEsNKZvGzAnTDy5bhNT9kt6KFCTBixpvrLCzg4M5UdFUQYrn1gdgjX\
pLHxcaShD81xBNaFDgnA2nkkdHnKtZt4hVSfKAmw3VRZbjrZ7L2fKZBx21CwsG\ pLHxcaShD81xBNaFDgnA2nkkdHnKtZt4hVSfKAmw3VRZbjrZ7L2fKZBx21CwsG\
hD6onjM2M3qZW5C8J6d1pj41MxKmZgPBSha3MyKkNLkAGFASK" hD6onjM2M3qZW5C8J6d1pj41MxKmZgPBSha3MyKkNLkAGFASK"
.to_string(); .to_string();
let expect58 = let expect58 = Error::invalid_params(
Error::invalid_params("invalid transaction: index out of bounds".to_string()); "invalid solana_sdk::transaction::Transaction: index out of bounds".to_string(),
);
assert_eq!( assert_eq!(
deserialize_transaction(unsanitary_tx58, UiTransactionEncoding::Base58).unwrap_err(), decode_and_deserialize::<Transaction>(unsanitary_tx58, UiTransactionEncoding::Base58)
.unwrap_err(),
expect58 expect58
); );
} }

View File

@ -5,8 +5,8 @@ use {
max_slots::MaxSlots, max_slots::MaxSlots,
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank, optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
rpc::{ rpc::{
rpc_accounts::*, rpc_bank::*, rpc_deprecated_v1_7::*, rpc_full::*, rpc_minimal::*, rpc_accounts::*, rpc_bank::*, rpc_deprecated_v1_7::*, rpc_deprecated_v1_8::*,
rpc_obsolete_v1_7::*, *, rpc_full::*, rpc_minimal::*, rpc_obsolete_v1_7::*, *,
}, },
rpc_health::*, rpc_health::*,
send_transaction_service::{LeaderInfo, SendTransactionService}, send_transaction_service::{LeaderInfo, SendTransactionService},
@ -408,6 +408,7 @@ impl JsonRpcService {
io.extend_with(rpc_accounts::AccountsDataImpl.to_delegate()); io.extend_with(rpc_accounts::AccountsDataImpl.to_delegate());
io.extend_with(rpc_full::FullImpl.to_delegate()); io.extend_with(rpc_full::FullImpl.to_delegate());
io.extend_with(rpc_deprecated_v1_7::DeprecatedV1_7Impl.to_delegate()); io.extend_with(rpc_deprecated_v1_7::DeprecatedV1_7Impl.to_delegate());
io.extend_with(rpc_deprecated_v1_8::DeprecatedV1_8Impl.to_delegate());
} }
if obsolete_v1_7_api { if obsolete_v1_7_api {
io.extend_with(rpc_obsolete_v1_7::ObsoleteV1_7Impl.to_delegate()); io.extend_with(rpc_obsolete_v1_7::ObsoleteV1_7Impl.to_delegate());

View File

@ -106,9 +106,11 @@ impl TransactionStatusService {
let fee_calculator = nonce_rollback let fee_calculator = nonce_rollback
.map(|nonce_rollback| nonce_rollback.fee_calculator()) .map(|nonce_rollback| nonce_rollback.fee_calculator())
.unwrap_or_else(|| { .unwrap_or_else(|| {
#[allow(deprecated)]
bank.get_fee_calculator(&transaction.message().recent_blockhash) bank.get_fee_calculator(&transaction.message().recent_blockhash)
}) })
.expect("FeeCalculator must exist"); .expect("FeeCalculator must exist");
#[allow(deprecated)]
let fee = fee_calculator.calculate_fee(transaction.message()); let fee = fee_calculator.calculate_fee(transaction.message());
let (writable_keys, readonly_keys) = let (writable_keys, readonly_keys) =
transaction.message.get_account_keys_by_lock_type(); transaction.message.get_account_keys_by_lock_type();

View File

@ -54,7 +54,7 @@ pub fn create_builtin_transactions(
.unwrap_or_else(|_| panic!("{}:{}", line!(), file!())); .unwrap_or_else(|_| panic!("{}:{}", line!(), file!()));
let instruction = create_invoke_instruction(rando0.pubkey(), program_id, &1u8); let instruction = create_invoke_instruction(rando0.pubkey(), program_id, &1u8);
let (blockhash, _fee_calculator) = bank_client.get_recent_blockhash().unwrap(); let blockhash = bank_client.get_latest_blockhash().unwrap();
let message = Message::new(&[instruction], Some(&mint_keypair.pubkey())); let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
Transaction::new(&[&rando0], message, blockhash) Transaction::new(&[&rando0], message, blockhash)
}) })
@ -76,7 +76,7 @@ pub fn create_native_loader_transactions(
.unwrap_or_else(|_| panic!("{}:{}", line!(), file!())); .unwrap_or_else(|_| panic!("{}:{}", line!(), file!()));
let instruction = create_invoke_instruction(rando0.pubkey(), program_id, &1u8); let instruction = create_invoke_instruction(rando0.pubkey(), program_id, &1u8);
let (blockhash, _fee_calculator) = bank_client.get_recent_blockhash().unwrap(); let blockhash = bank_client.get_latest_blockhash().unwrap();
let message = Message::new(&[instruction], Some(&mint_keypair.pubkey())); let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
Transaction::new(&[&rando0], message, blockhash) Transaction::new(&[&rando0], message, blockhash)
}) })

View File

@ -450,11 +450,13 @@ impl Accounts {
.as_ref() .as_ref()
.map(|nonce_rollback| nonce_rollback.fee_calculator()) .map(|nonce_rollback| nonce_rollback.fee_calculator())
.unwrap_or_else(|| { .unwrap_or_else(|| {
#[allow(deprecated)]
hash_queue hash_queue
.get_fee_calculator(&tx.message().recent_blockhash) .get_fee_calculator(&tx.message().recent_blockhash)
.cloned() .cloned()
}); });
let fee = if let Some(fee_calculator) = fee_calculator { let fee = if let Some(fee_calculator) = fee_calculator {
#[allow(deprecated)]
fee_calculator.calculate_fee(tx.message()) fee_calculator.calculate_fee(tx.message())
} else { } else {
return (Err(TransactionError::BlockhashNotFound), None); return (Err(TransactionError::BlockhashNotFound), None);
@ -1292,7 +1294,9 @@ mod tests {
); );
let fee_calculator = FeeCalculator::new(10); let fee_calculator = FeeCalculator::new(10);
assert_eq!(fee_calculator.calculate_fee(tx.message()), 10); #[allow(deprecated)]
let fee = fee_calculator.calculate_fee(tx.message());
assert_eq!(fee, 10);
let loaded_accounts = let loaded_accounts =
load_accounts_with_fee(tx, &accounts, &fee_calculator, &mut error_counters); load_accounts_with_fee(tx, &accounts, &fee_calculator, &mut error_counters);

View File

@ -2667,15 +2667,25 @@ impl Bank {
self.blockhash_queue.read().unwrap().last_hash() self.blockhash_queue.read().unwrap().last_hash()
} }
pub fn is_blockhash_valid(&self, hash: &Hash) -> bool {
let blockhash_queue = self.blockhash_queue.read().unwrap();
blockhash_queue.check_hash(hash)
}
pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> u64 { pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> u64 {
self.rent_collector.rent.minimum_balance(data_len) self.rent_collector.rent.minimum_balance(data_len)
} }
#[deprecated(
since = "1.8.0",
note = "Please use `last_blockhash` and `get_fee_for_message` instead"
)]
pub fn last_blockhash_with_fee_calculator(&self) -> (Hash, FeeCalculator) { pub fn last_blockhash_with_fee_calculator(&self) -> (Hash, FeeCalculator) {
let blockhash_queue = self.blockhash_queue.read().unwrap(); let blockhash_queue = self.blockhash_queue.read().unwrap();
let last_hash = blockhash_queue.last_hash(); let last_hash = blockhash_queue.last_hash();
( (
last_hash, last_hash,
#[allow(deprecated)]
blockhash_queue blockhash_queue
.get_fee_calculator(&last_hash) .get_fee_calculator(&last_hash)
.unwrap() .unwrap()
@ -2683,15 +2693,26 @@ impl Bank {
) )
} }
#[deprecated(since = "1.8.0", note = "Please use `get_fee_for_message` instead")]
pub fn get_fee_calculator(&self, hash: &Hash) -> Option<FeeCalculator> { pub fn get_fee_calculator(&self, hash: &Hash) -> Option<FeeCalculator> {
let blockhash_queue = self.blockhash_queue.read().unwrap(); let blockhash_queue = self.blockhash_queue.read().unwrap();
#[allow(deprecated)]
blockhash_queue.get_fee_calculator(hash).cloned() blockhash_queue.get_fee_calculator(hash).cloned()
} }
#[deprecated(since = "1.8.0", note = "Please use `get_fee_for_message` instead")]
pub fn get_fee_rate_governor(&self) -> &FeeRateGovernor { pub fn get_fee_rate_governor(&self) -> &FeeRateGovernor {
&self.fee_rate_governor &self.fee_rate_governor
} }
pub fn get_fee_for_message(&self, hash: &Hash, message: &Message) -> Option<u64> {
let blockhash_queue = self.blockhash_queue.read().unwrap();
#[allow(deprecated)]
let fee_calculator = blockhash_queue.get_fee_calculator(hash)?;
#[allow(deprecated)]
Some(fee_calculator.calculate_fee(message))
}
#[deprecated( #[deprecated(
since = "1.6.11", since = "1.6.11",
note = "Please use `get_blockhash_last_valid_block_height`" note = "Please use `get_blockhash_last_valid_block_height`"
@ -2714,18 +2735,36 @@ impl Bank {
.map(|age| self.block_height + blockhash_queue.len() as u64 - age) .map(|age| self.block_height + blockhash_queue.len() as u64 - age)
} }
pub fn confirmed_last_blockhash(&self) -> (Hash, FeeCalculator) { #[deprecated(
since = "1.8.0",
note = "Please use `confirmed_last_blockhash` and `get_fee_for_message` instead"
)]
pub fn confirmed_last_blockhash_with_fee_calculator(&self) -> (Hash, FeeCalculator) {
const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3; const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
let parents = self.parents(); let parents = self.parents();
if parents.is_empty() { if parents.is_empty() {
#[allow(deprecated)]
self.last_blockhash_with_fee_calculator() self.last_blockhash_with_fee_calculator()
} else { } else {
let index = NUM_BLOCKHASH_CONFIRMATIONS.min(parents.len() - 1); let index = NUM_BLOCKHASH_CONFIRMATIONS.min(parents.len() - 1);
#[allow(deprecated)]
parents[index].last_blockhash_with_fee_calculator() parents[index].last_blockhash_with_fee_calculator()
} }
} }
pub fn confirmed_last_blockhash(&self) -> Hash {
const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
let parents = self.parents();
if parents.is_empty() {
self.last_blockhash()
} else {
let index = NUM_BLOCKHASH_CONFIRMATIONS.min(parents.len() - 1);
parents[index].last_blockhash()
}
}
/// Forget all signatures. Useful for benchmarking. /// Forget all signatures. Useful for benchmarking.
pub fn clear_signatures(&self) { pub fn clear_signatures(&self) {
self.src.status_cache.write().unwrap().clear(); self.src.status_cache.write().unwrap().clear();
@ -3400,6 +3439,7 @@ impl Bank {
let blockhash = blockhash_queue.last_hash(); let blockhash = blockhash_queue.last_hash();
( (
blockhash, blockhash,
#[allow(deprecated)]
blockhash_queue blockhash_queue
.get_fee_calculator(&blockhash) .get_fee_calculator(&blockhash)
.cloned() .cloned()
@ -3582,6 +3622,7 @@ impl Bank {
.map(|maybe_fee_calculator| (maybe_fee_calculator, true)) .map(|maybe_fee_calculator| (maybe_fee_calculator, true))
.unwrap_or_else(|| { .unwrap_or_else(|| {
( (
#[allow(deprecated)]
hash_queue hash_queue
.get_fee_calculator(&tx.message().recent_blockhash) .get_fee_calculator(&tx.message().recent_blockhash)
.cloned(), .cloned(),
@ -3590,6 +3631,7 @@ impl Bank {
}); });
let fee_calculator = fee_calculator.ok_or(TransactionError::BlockhashNotFound)?; let fee_calculator = fee_calculator.ok_or(TransactionError::BlockhashNotFound)?;
#[allow(deprecated)]
let fee = fee_calculator.calculate_fee(tx.message()); let fee = fee_calculator.calculate_fee(tx.message());
let message = tx.message(); let message = tx.message();
@ -3658,6 +3700,7 @@ impl Bank {
} }
let mut write_time = Measure::start("write_time"); let mut write_time = Measure::start("write_time");
#[allow(deprecated)]
self.rc.accounts.store_cached( self.rc.accounts.store_cached(
self.slot(), self.slot(),
sanitized_txs.as_transactions_iter(), sanitized_txs.as_transactions_iter(),
@ -8304,11 +8347,13 @@ pub(crate) mod tests {
let mut bank = Bank::new_for_tests(&genesis_config); let mut bank = Bank::new_for_tests(&genesis_config);
goto_end_of_slot(&mut bank); goto_end_of_slot(&mut bank);
#[allow(deprecated)]
let (cheap_blockhash, cheap_fee_calculator) = bank.last_blockhash_with_fee_calculator(); let (cheap_blockhash, cheap_fee_calculator) = bank.last_blockhash_with_fee_calculator();
assert_eq!(cheap_fee_calculator.lamports_per_signature, 0); assert_eq!(cheap_fee_calculator.lamports_per_signature, 0);
let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1); let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
goto_end_of_slot(&mut bank); goto_end_of_slot(&mut bank);
#[allow(deprecated)]
let (expensive_blockhash, expensive_fee_calculator) = let (expensive_blockhash, expensive_fee_calculator) =
bank.last_blockhash_with_fee_calculator(); bank.last_blockhash_with_fee_calculator();
assert!( assert!(

View File

@ -148,6 +148,7 @@ impl SyncClient for BankClient {
} }
fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)> { fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)> {
#[allow(deprecated)]
Ok(self.bank.last_blockhash_with_fee_calculator()) Ok(self.bank.last_blockhash_with_fee_calculator())
} }
@ -155,6 +156,7 @@ impl SyncClient for BankClient {
&self, &self,
_commitment_config: CommitmentConfig, _commitment_config: CommitmentConfig,
) -> Result<(Hash, FeeCalculator, u64)> { ) -> Result<(Hash, FeeCalculator, u64)> {
#[allow(deprecated)]
let (blockhash, fee_calculator) = self.bank.last_blockhash_with_fee_calculator(); let (blockhash, fee_calculator) = self.bank.last_blockhash_with_fee_calculator();
#[allow(deprecated)] #[allow(deprecated)]
let last_valid_slot = self let last_valid_slot = self
@ -165,10 +167,12 @@ impl SyncClient for BankClient {
} }
fn get_fee_calculator_for_blockhash(&self, blockhash: &Hash) -> Result<Option<FeeCalculator>> { fn get_fee_calculator_for_blockhash(&self, blockhash: &Hash) -> Result<Option<FeeCalculator>> {
#[allow(deprecated)]
Ok(self.bank.get_fee_calculator(blockhash)) Ok(self.bank.get_fee_calculator(blockhash))
} }
fn get_fee_rate_governor(&self) -> Result<FeeRateGovernor> { fn get_fee_rate_governor(&self) -> Result<FeeRateGovernor> {
#[allow(deprecated)]
Ok(self.bank.get_fee_rate_governor().clone()) Ok(self.bank.get_fee_rate_governor().clone())
} }
@ -258,9 +262,10 @@ impl SyncClient for BankClient {
} }
fn get_new_blockhash(&self, blockhash: &Hash) -> Result<(Hash, FeeCalculator)> { fn get_new_blockhash(&self, blockhash: &Hash) -> Result<(Hash, FeeCalculator)> {
let (last_blockhash, fee_calculator) = self.get_recent_blockhash()?; #[allow(deprecated)]
if last_blockhash != *blockhash { let (recent_blockhash, fee_calculator) = self.get_recent_blockhash()?;
Ok((last_blockhash, fee_calculator)) if recent_blockhash != *blockhash {
Ok((recent_blockhash, fee_calculator))
} else { } else {
Err(TransportError::IoError(io::Error::new( Err(TransportError::IoError(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
@ -272,6 +277,53 @@ impl SyncClient for BankClient {
fn get_epoch_info(&self) -> Result<EpochInfo> { fn get_epoch_info(&self) -> Result<EpochInfo> {
Ok(self.bank.get_epoch_info()) Ok(self.bank.get_epoch_info())
} }
fn get_latest_blockhash(&self) -> Result<Hash> {
Ok(self.bank.last_blockhash())
}
fn get_latest_blockhash_with_commitment(
&self,
_commitment_config: CommitmentConfig,
) -> Result<(Hash, u64)> {
let blockhash = self.bank.last_blockhash();
let last_valid_block_height = self
.bank
.get_blockhash_last_valid_block_height(&blockhash)
.expect("bank blockhash queue should contain blockhash");
Ok((blockhash, last_valid_block_height))
}
fn is_blockhash_valid(
&self,
blockhash: &Hash,
_commitment_config: CommitmentConfig,
) -> Result<bool> {
Ok(self.bank.is_blockhash_valid(blockhash))
}
fn get_fee_for_message(&self, blockhash: &Hash, message: &Message) -> Result<u64> {
self.bank
.get_fee_for_message(blockhash, message)
.ok_or_else(|| {
TransportError::IoError(io::Error::new(
io::ErrorKind::Other,
"Unable calculate fee",
))
})
}
fn get_new_latest_blockhash(&self, blockhash: &Hash) -> Result<Hash> {
let latest_blockhash = self.get_latest_blockhash()?;
if latest_blockhash != *blockhash {
Ok(latest_blockhash)
} else {
Err(TransportError::IoError(io::Error::new(
io::ErrorKind::Other,
"Unable to get new blockhash",
)))
}
}
} }
impl BankClient { impl BankClient {

View File

@ -46,6 +46,10 @@ impl BlockhashQueue {
self.last_hash.expect("no hash has been set") self.last_hash.expect("no hash has been set")
} }
#[deprecated(
since = "1.8.0",
note = "Please do not use, will no longer be available in the future"
)]
pub fn get_fee_calculator(&self, hash: &Hash) -> Option<&FeeCalculator> { pub fn get_fee_calculator(&self, hash: &Hash) -> Option<&FeeCalculator> {
self.ages.get(hash).map(|hash_age| &hash_age.fee_calculator) self.ages.get(hash).map(|hash_age| &hash_age.fee_calculator)
} }
@ -66,9 +70,8 @@ impl BlockhashQueue {
} }
/// check if hash is valid /// check if hash is valid
#[cfg(test)] pub fn check_hash(&self, hash: &Hash) -> bool {
pub fn check_hash(&self, hash: Hash) -> bool { self.ages.get(hash).is_some()
self.ages.get(&hash).is_some()
} }
pub fn genesis_hash(&mut self, hash: &Hash, fee_calculator: &FeeCalculator) { pub fn genesis_hash(&mut self, hash: &Hash, fee_calculator: &FeeCalculator) {
@ -148,9 +151,9 @@ mod tests {
fn test_register_hash() { fn test_register_hash() {
let last_hash = Hash::default(); let last_hash = Hash::default();
let mut hash_queue = BlockhashQueue::new(100); let mut hash_queue = BlockhashQueue::new(100);
assert!(!hash_queue.check_hash(last_hash)); assert!(!hash_queue.check_hash(&last_hash));
hash_queue.register_hash(&last_hash, &FeeCalculator::default()); hash_queue.register_hash(&last_hash, &FeeCalculator::default());
assert!(hash_queue.check_hash(last_hash)); assert!(hash_queue.check_hash(&last_hash));
assert_eq!(hash_queue.hash_height(), 1); assert_eq!(hash_queue.hash_height(), 1);
} }
@ -163,12 +166,12 @@ mod tests {
hash_queue.register_hash(&last_hash, &FeeCalculator::default()); hash_queue.register_hash(&last_hash, &FeeCalculator::default());
} }
// Assert we're no longer able to use the oldest hash. // Assert we're no longer able to use the oldest hash.
assert!(!hash_queue.check_hash(last_hash)); assert!(!hash_queue.check_hash(&last_hash));
assert_eq!(None, hash_queue.check_hash_age(&last_hash, 0)); assert_eq!(None, hash_queue.check_hash_age(&last_hash, 0));
// Assert we are not able to use the oldest remaining hash. // Assert we are not able to use the oldest remaining hash.
let last_valid_hash = hash(&serialize(&1).unwrap()); let last_valid_hash = hash(&serialize(&1).unwrap());
assert!(hash_queue.check_hash(last_valid_hash)); assert!(hash_queue.check_hash(&last_valid_hash));
assert_eq!(Some(false), hash_queue.check_hash_age(&last_valid_hash, 0)); assert_eq!(Some(false), hash_queue.check_hash_age(&last_valid_hash, 0));
} }

View File

@ -27,11 +27,15 @@ impl FeeCalculator {
} }
} }
#[deprecated(
since = "1.8.0",
note = "Please do not use, will no longer be available in the future"
)]
pub fn calculate_fee(&self, message: &Message) -> u64 { pub fn calculate_fee(&self, message: &Message) -> u64 {
let mut num_secp256k1_signatures: u64 = 0; let mut num_secp256k1_signatures: u64 = 0;
for instruction in &message.instructions { for instruction in &message.instructions {
let program_index = instruction.program_id_index as usize; let program_index = instruction.program_id_index as usize;
// Transaction may not be sanitized here // Message may not be sanitized here
if program_index < message.account_keys.len() { if program_index < message.account_keys.len() {
let id = message.account_keys[program_index]; let id = message.account_keys[program_index];
if secp256k1_program::check_id(&id) && !instruction.data.is_empty() { if secp256k1_program::check_id(&id) && !instruction.data.is_empty() {
@ -193,6 +197,7 @@ mod tests {
} }
#[test] #[test]
#[allow(deprecated)]
fn test_fee_calculator_calculate_fee() { fn test_fee_calculator_calculate_fee() {
// Default: no fee. // Default: no fee.
let message = Message::default(); let message = Message::default();
@ -216,6 +221,7 @@ mod tests {
} }
#[test] #[test]
#[allow(deprecated)]
fn test_fee_calculator_calculate_fee_secp256k1() { fn test_fee_calculator_calculate_fee_secp256k1() {
use crate::instruction::Instruction; use crate::instruction::Instruction;
let pubkey0 = Pubkey::new(&[0; 32]); let pubkey0 = Pubkey::new(&[0; 32]);

View File

@ -81,9 +81,14 @@ pub trait SyncClient {
fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> Result<u64>; fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> Result<u64>;
/// Get recent blockhash /// Get recent blockhash
#[deprecated(since = "1.8.0", note = "Please use `get_latest_blockhash` instead")]
fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)>; fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)>;
/// Get recent blockhash. Uses explicit commitment configuration. /// Get recent blockhash. Uses explicit commitment configuration.
#[deprecated(
since = "1.8.0",
note = "Please use `get_latest_blockhash_with_commitment` and `get_fee_for_message` instead"
)]
fn get_recent_blockhash_with_commitment( fn get_recent_blockhash_with_commitment(
&self, &self,
commitment_config: CommitmentConfig, commitment_config: CommitmentConfig,
@ -91,9 +96,17 @@ pub trait SyncClient {
/// Get `Some(FeeCalculator)` associated with `blockhash` if it is still in /// Get `Some(FeeCalculator)` associated with `blockhash` if it is still in
/// the BlockhashQueue`, otherwise `None` /// the BlockhashQueue`, otherwise `None`
#[deprecated(
since = "1.8.0",
note = "Please use `get_fee_for_message` or `is_blockhash_valid` instead"
)]
fn get_fee_calculator_for_blockhash(&self, blockhash: &Hash) -> Result<Option<FeeCalculator>>; fn get_fee_calculator_for_blockhash(&self, blockhash: &Hash) -> Result<Option<FeeCalculator>>;
/// Get recent fee rate governor /// Get recent fee rate governor
#[deprecated(
since = "1.8.0",
note = "Please do not use, will no longer be available in the future"
)]
fn get_fee_rate_governor(&self) -> Result<FeeRateGovernor>; fn get_fee_rate_governor(&self) -> Result<FeeRateGovernor>;
/// Get signature status. /// Get signature status.
@ -136,7 +149,29 @@ pub trait SyncClient {
/// Poll to confirm a transaction. /// Poll to confirm a transaction.
fn poll_for_signature(&self, signature: &Signature) -> Result<()>; fn poll_for_signature(&self, signature: &Signature) -> Result<()>;
#[deprecated(
since = "1.8.0",
note = "Please use `get_new_latest_blockhash` instead"
)]
fn get_new_blockhash(&self, blockhash: &Hash) -> Result<(Hash, FeeCalculator)>; fn get_new_blockhash(&self, blockhash: &Hash) -> Result<(Hash, FeeCalculator)>;
/// Get last known blockhash
fn get_latest_blockhash(&self) -> Result<Hash>;
/// Get recent blockhash. Uses explicit commitment configuration.
fn get_latest_blockhash_with_commitment(
&self,
commitment_config: CommitmentConfig,
) -> Result<(Hash, u64)>;
/// Check if the blockhash is valid
fn is_blockhash_valid(&self, blockhash: &Hash, commitment: CommitmentConfig) -> Result<bool>;
/// Calculate the fee for a `Message`
fn get_fee_for_message(&self, blockhash: &Hash, message: &Message) -> Result<u64>;
/// Get a new blockhash after the one specified
fn get_new_latest_blockhash(&self, blockhash: &Hash) -> Result<Hash>;
} }
pub trait AsyncClient { pub trait AsyncClient {

View File

@ -205,8 +205,7 @@ fn send_and_confirm_message<S: Signers>(
) -> Result<Signature, ClientError> { ) -> Result<Signature, ClientError> {
let mut transaction = Transaction::new_unsigned(message); let mut transaction = Transaction::new_unsigned(message);
let (blockhash, _fee_calculator) = let blockhash = client.get_new_latest_blockhash(&transaction.message().recent_blockhash)?;
client.get_new_blockhash(&transaction.message().recent_blockhash)?;
transaction.try_sign(signers, blockhash)?; transaction.try_sign(signers, blockhash)?;
if no_wait { if no_wait {

View File

@ -19,7 +19,6 @@ 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,
@ -164,7 +163,7 @@ fn transfer<S: Signer>(
let create_instruction = let create_instruction =
system_instruction::transfer(&sender_keypair.pubkey(), to_pubkey, lamports); system_instruction::transfer(&sender_keypair.pubkey(), to_pubkey, lamports);
let message = Message::new(&[create_instruction], Some(&sender_keypair.pubkey())); let message = Message::new(&[create_instruction], Some(&sender_keypair.pubkey()));
let (recent_blockhash, _fees) = client.get_recent_blockhash()?; let recent_blockhash = client.get_latest_blockhash()?;
Ok(Transaction::new( Ok(Transaction::new(
&[sender_keypair], &[sender_keypair],
message, message,
@ -387,13 +386,8 @@ 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 Fees { let (blockhash, last_valid_block_height) =
blockhash, client.get_latest_blockhash_with_commitment(CommitmentConfig::default())?;
last_valid_block_height,
..
} = client
.get_fees_with_commitment(CommitmentConfig::default())?
.value;
let transaction = Transaction::new(&signers, message, blockhash); let transaction = Transaction::new(&signers, message, blockhash);
let config = RpcSendTransactionConfig { let config = RpcSendTransactionConfig {
skip_preflight: true, skip_preflight: true,
@ -448,14 +442,10 @@ fn distribute_allocations(
&mut created_accounts, &mut created_accounts,
)?; )?;
let num_signatures = messages
.iter()
.map(|message| message.header.num_required_signatures as usize)
.sum();
if args.spl_token_args.is_some() { if args.spl_token_args.is_some() {
check_spl_token_balances(num_signatures, allocations, client, args, created_accounts)?; check_spl_token_balances(&messages, allocations, client, args, created_accounts)?;
} else { } else {
check_payer_balances(num_signatures, allocations, client, args)?; check_payer_balances(&messages, allocations, client, args)?;
} }
send_messages(client, db, allocations, args, exit, messages, stake_extras)?; send_messages(client, db, allocations, args, exit, messages, stake_extras)?;
@ -733,18 +723,21 @@ fn log_transaction_confirmations(
} }
fn check_payer_balances( fn check_payer_balances(
num_signatures: usize, messages: &[Message],
allocations: &[Allocation], allocations: &[Allocation],
client: &RpcClient, client: &RpcClient,
args: &DistributeTokensArgs, args: &DistributeTokensArgs,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut undistributed_tokens: u64 = allocations.iter().map(|x| x.amount).sum(); let mut undistributed_tokens: u64 = allocations.iter().map(|x| x.amount).sum();
let (_blockhash, fee_calculator) = client.get_recent_blockhash()?; let blockhash = client.get_latest_blockhash()?;
let fees = fee_calculator let fees = messages
.lamports_per_signature .iter()
.checked_mul(num_signatures as u64) .map(|message| client.get_fee_for_message(&blockhash, message))
.unwrap(); .collect::<Result<Vec<_>, _>>()
.unwrap()
.iter()
.sum();
let (distribution_source, unlocked_sol_source) = if let Some(stake_args) = &args.stake_args { let (distribution_source, unlocked_sol_source) = if let Some(stake_args) = &args.stake_args {
let total_unlocked_sol = allocations.len() as u64 * stake_args.unlocked_sol; let total_unlocked_sol = allocations.len() as u64 * stake_args.unlocked_sol;
@ -988,7 +981,7 @@ pub fn test_process_create_stake_with_client(client: &RpcClient, sender_keypair:
); );
let message = Message::new(&instructions, Some(&sender_keypair.pubkey())); let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
let signers = [&sender_keypair, &stake_account_keypair]; let signers = [&sender_keypair, &stake_account_keypair];
let (blockhash, _fees) = client.get_recent_blockhash().unwrap(); let blockhash = client.get_latest_blockhash().unwrap();
let transaction = Transaction::new(&signers, message, blockhash); let transaction = Transaction::new(&signers, message, blockhash);
client client
.send_and_confirm_transaction_with_spinner(&transaction) .send_and_confirm_transaction_with_spinner(&transaction)
@ -1110,7 +1103,7 @@ pub fn test_process_distribute_stake_with_client(client: &RpcClient, sender_keyp
); );
let message = Message::new(&instructions, Some(&sender_keypair.pubkey())); let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
let signers = [&sender_keypair, &stake_account_keypair]; let signers = [&sender_keypair, &stake_account_keypair];
let (blockhash, _fees) = client.get_recent_blockhash().unwrap(); let blockhash = client.get_latest_blockhash().unwrap();
let transaction = Transaction::new(&signers, message, blockhash); let transaction = Transaction::new(&signers, message, blockhash);
client client
.send_and_confirm_transaction_with_spinner(&transaction) .send_and_confirm_transaction_with_spinner(&transaction)
@ -1210,12 +1203,24 @@ mod tests {
use super::*; use super::*;
use solana_core::test_validator::TestValidator; use solana_core::test_validator::TestValidator;
use solana_sdk::{ use solana_sdk::{
instruction::AccountMeta,
signature::{read_keypair_file, write_keypair_file, Signer}, signature::{read_keypair_file, write_keypair_file, Signer},
stake::instruction::StakeInstruction, stake::instruction::StakeInstruction,
}; };
use solana_streamer::socket::SocketAddrSpace; use solana_streamer::socket::SocketAddrSpace;
use solana_transaction_status::TransactionConfirmationStatus; use solana_transaction_status::TransactionConfirmationStatus;
fn one_signer_message() -> Message {
Message::new(
&[Instruction::new_with_bytes(
Pubkey::new_unique(),
&[],
vec![AccountMeta::new(Pubkey::default(), true)],
)],
None,
)
}
#[test] #[test]
fn test_process_token_allocations() { fn test_process_token_allocations() {
let alice = Keypair::new(); let alice = Keypair::new();
@ -1594,7 +1599,7 @@ mod tests {
&sender_keypair_file, &sender_keypair_file,
None, None,
); );
check_payer_balances(1, &allocations, &client, &args).unwrap(); check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap();
// Unfunded payer // Unfunded payer
let unfunded_payer = Keypair::new(); let unfunded_payer = Keypair::new();
@ -1607,7 +1612,9 @@ mod tests {
.unwrap() .unwrap()
.into(); .into();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err(); let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!( assert_eq!(
sources, sources,
@ -1644,7 +1651,9 @@ mod tests {
args.fee_payer = read_keypair_file(&partially_funded_payer_keypair_file) args.fee_payer = read_keypair_file(&partially_funded_payer_keypair_file)
.unwrap() .unwrap()
.into(); .into();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err(); let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!( assert_eq!(
sources, sources,
@ -1697,7 +1706,7 @@ mod tests {
&sender_keypair_file, &sender_keypair_file,
None, None,
); );
check_payer_balances(1, &allocations, &client, &args).unwrap(); check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap();
// Unfunded sender // Unfunded sender
let unfunded_payer = Keypair::new(); let unfunded_payer = Keypair::new();
@ -1708,7 +1717,9 @@ mod tests {
.into(); .into();
args.fee_payer = read_keypair_file(&sender_keypair_file).unwrap().into(); args.fee_payer = read_keypair_file(&sender_keypair_file).unwrap().into();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err(); let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::SystemAccount].into()); assert_eq!(sources, vec![FundingSource::SystemAccount].into());
assert_eq!(amount, allocation_amount.to_string()); assert_eq!(amount, allocation_amount.to_string());
@ -1722,7 +1733,9 @@ mod tests {
.unwrap() .unwrap()
.into(); .into();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err(); let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::FeePayer].into()); assert_eq!(sources, vec![FundingSource::FeePayer].into());
assert_eq!(amount, fees_in_sol.to_string()); assert_eq!(amount, fees_in_sol.to_string());
@ -1756,7 +1769,7 @@ mod tests {
); );
let message = Message::new(&instructions, Some(&sender_keypair.pubkey())); let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
let signers = [sender_keypair, &stake_account_keypair]; let signers = [sender_keypair, &stake_account_keypair];
let (blockhash, _fees) = client.get_recent_blockhash().unwrap(); let blockhash = client.get_latest_blockhash().unwrap();
let transaction = Transaction::new(&signers, message, blockhash); let transaction = Transaction::new(&signers, message, blockhash);
client client
.send_and_confirm_transaction_with_spinner(&transaction) .send_and_confirm_transaction_with_spinner(&transaction)
@ -1809,7 +1822,7 @@ mod tests {
&sender_keypair_file, &sender_keypair_file,
Some(stake_args), Some(stake_args),
); );
check_payer_balances(1, &allocations, &client, &args).unwrap(); check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap();
// Underfunded stake-account // Underfunded stake-account
let expensive_allocation_amount = 5000.0; let expensive_allocation_amount = 5000.0;
@ -1818,8 +1831,13 @@ mod tests {
amount: sol_to_lamports(expensive_allocation_amount), amount: sol_to_lamports(expensive_allocation_amount),
lockup_date: "".to_string(), lockup_date: "".to_string(),
}]; }];
let err_result = let err_result = check_payer_balances(
check_payer_balances(1, &expensive_allocations, &client, &args).unwrap_err(); &[one_signer_message()],
&expensive_allocations,
&client,
&args,
)
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::StakeAccount].into()); assert_eq!(sources, vec![FundingSource::StakeAccount].into());
assert_eq!( assert_eq!(
@ -1841,7 +1859,9 @@ mod tests {
.unwrap() .unwrap()
.into(); .into();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err(); let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!( assert_eq!(
sources, sources,
@ -1878,7 +1898,9 @@ mod tests {
args.fee_payer = read_keypair_file(&partially_funded_payer_keypair_file) args.fee_payer = read_keypair_file(&partially_funded_payer_keypair_file)
.unwrap() .unwrap()
.into(); .into();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err(); let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!( assert_eq!(
sources, sources,
@ -1938,7 +1960,7 @@ mod tests {
&sender_keypair_file, &sender_keypair_file,
Some(stake_args), Some(stake_args),
); );
check_payer_balances(1, &allocations, &client, &args).unwrap(); check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap();
// Unfunded sender // Unfunded sender
let unfunded_payer = Keypair::new(); let unfunded_payer = Keypair::new();
@ -1949,7 +1971,9 @@ mod tests {
.into(); .into();
args.fee_payer = read_keypair_file(&sender_keypair_file).unwrap().into(); args.fee_payer = read_keypair_file(&sender_keypair_file).unwrap().into();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err(); let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::SystemAccount].into()); assert_eq!(sources, vec![FundingSource::SystemAccount].into());
assert_eq!(amount, unlocked_sol.to_string()); assert_eq!(amount, unlocked_sol.to_string());
@ -1963,7 +1987,9 @@ mod tests {
.unwrap() .unwrap()
.into(); .into();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err(); let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::FeePayer].into()); assert_eq!(sources, vec![FundingSource::FeePayer].into());
assert_eq!(amount, fees_in_sol.to_string()); assert_eq!(amount, fees_in_sol.to_string());

View File

@ -8,7 +8,7 @@ use solana_account_decoder::parse_token::{
spl_token_v2_0_pubkey, spl_token_v2_0_pubkey,
}; };
use solana_client::rpc_client::RpcClient; use solana_client::rpc_client::RpcClient;
use solana_sdk::{instruction::Instruction, native_token::lamports_to_sol}; use solana_sdk::{instruction::Instruction, message::Message, native_token::lamports_to_sol};
use solana_transaction_status::parse_token::spl_token_v2_0_instruction; use solana_transaction_status::parse_token::spl_token_v2_0_instruction;
use spl_associated_token_account_v1_0::{ use spl_associated_token_account_v1_0::{
create_associated_token_account, get_associated_token_address, create_associated_token_account, get_associated_token_address,
@ -85,7 +85,7 @@ pub fn build_spl_token_instructions(
} }
pub fn check_spl_token_balances( pub fn check_spl_token_balances(
num_signatures: usize, messages: &[Message],
allocations: &[Allocation], allocations: &[Allocation],
client: &RpcClient, client: &RpcClient,
args: &DistributeTokensArgs, args: &DistributeTokensArgs,
@ -97,11 +97,14 @@ pub fn check_spl_token_balances(
.expect("spl_token_args must be some"); .expect("spl_token_args must be some");
let allocation_amount: u64 = allocations.iter().map(|x| x.amount).sum(); let allocation_amount: u64 = allocations.iter().map(|x| x.amount).sum();
let fee_calculator = client.get_recent_blockhash()?.1; let blockhash = client.get_latest_blockhash()?;
let fees = fee_calculator let fees: u64 = messages
.lamports_per_signature .iter()
.checked_mul(num_signatures as u64) .map(|message| client.get_fee_for_message(&blockhash, message))
.unwrap(); .collect::<Result<Vec<_>, _>>()
.unwrap()
.iter()
.sum();
let token_account_rent_exempt_balance = let token_account_rent_exempt_balance =
client.get_minimum_balance_for_rent_exemption(SplTokenAccount::LEN)?; client.get_minimum_balance_for_rent_exemption(SplTokenAccount::LEN)?;

View File

@ -183,7 +183,7 @@ fn get_cluster_info(
rpc_client: &RpcClient, rpc_client: &RpcClient,
) -> client_error::Result<(u64, Hash, RpcVoteAccountStatus, HashMap<Pubkey, u64>)> { ) -> client_error::Result<(u64, Hash, RpcVoteAccountStatus, HashMap<Pubkey, u64>)> {
let transaction_count = rpc_client.get_transaction_count()?; let transaction_count = rpc_client.get_transaction_count()?;
let recent_blockhash = rpc_client.get_recent_blockhash()?.0; let recent_blockhash = rpc_client.get_latest_blockhash()?;
let vote_accounts = rpc_client.get_vote_accounts()?; let vote_accounts = rpc_client.get_vote_accounts()?;
let mut validator_balances = HashMap::new(); let mut validator_balances = HashMap::new();