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_sdk::{
commitment_config::CommitmentConfig,
instruction::{AccountMeta, Instruction},
message::Message,
pubkey::Pubkey,
rpc_port::DEFAULT_RPC_PORT,
@ -33,10 +34,6 @@ use std::{
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(
client: &RpcClient,
faucet_addr: &SocketAddr,
@ -55,7 +52,7 @@ pub fn airdrop_lamports(
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) {
Ok(transaction) => {
let mut tries = 0;
@ -375,10 +372,10 @@ fn run_accounts_bench(
info!("Targeting {}", entrypoint_addr);
let mut last_blockhash = Instant::now();
let mut latest_blockhash = Instant::now();
let mut last_log = Instant::now();
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 total_accounts_created = 0;
let mut total_accounts_closed = 0;
@ -406,16 +403,32 @@ fn run_accounts_bench(
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 {
if last_blockhash.elapsed().as_millis() > 10_000 {
recent_blockhash = client.get_recent_blockhash().expect("blockhash");
last_blockhash = Instant::now();
if latest_blockhash.elapsed().as_millis() > 10_000 {
blockhash = client.get_latest_blockhash().expect("blockhash");
latest_blockhash = Instant::now();
}
let fee = recent_blockhash
.1
.lamports_per_signature
.saturating_mul(NUM_SIGNATURES);
let fee = client
.get_fee_for_message(&blockhash, &message)
.expect("get_fee_for_message");
let lamports = min_balance + fee;
for (i, balance) in balances.iter_mut().enumerate() {
@ -464,7 +477,7 @@ fn run_accounts_bench(
mint,
);
let signers: Vec<&Keypair> = vec![keypair, &base_keypair];
Transaction::new(&signers, message, recent_blockhash.0)
Transaction::new(&signers, message, blockhash)
})
.collect();
balances[i] = balances[i].saturating_sub(lamports * txs.len() as u64);
@ -496,7 +509,7 @@ fn run_accounts_bench(
mint.is_some(),
);
let signers: Vec<&Keypair> = vec![payer_keypairs[0], &base_keypair];
Transaction::new(&signers, message, recent_blockhash.0)
Transaction::new(&signers, message, blockhash)
})
.collect();
balances[0] = balances[0].saturating_sub(fee * txs.len() as u64);

View File

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

View File

@ -10,8 +10,8 @@ use solana_sdk::{
client::Client,
clock::{DEFAULT_S_PER_SLOT, MAX_PROCESSING_AGE},
commitment_config::CommitmentConfig,
fee_calculator::FeeCalculator,
hash::Hash,
instruction::{AccountMeta, Instruction},
message::Message,
pubkey::Pubkey,
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)>>>>;
fn get_recent_blockhash<T: Client>(client: &T) -> (Hash, FeeCalculator) {
fn get_latest_blockhash<T: Client>(client: &T) -> Hash {
loop {
match client.get_recent_blockhash_with_commitment(CommitmentConfig::processed()) {
Ok((blockhash, fee_calculator, _last_valid_slot)) => {
return (blockhash, fee_calculator)
}
match client.get_latest_blockhash_with_commitment(CommitmentConfig::processed()) {
Ok((blockhash, _)) => return blockhash,
Err(err) => {
info!("Couldn't get recent blockhash: {:?}", err);
info!("Couldn't get last blockhash: {:?}", err);
sleep(Duration::from_secs(1));
}
};
@ -239,19 +237,19 @@ where
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 total_tx_sent_count = Arc::new(AtomicUsize::new(0));
let blockhash_thread = {
let exit_signal = exit_signal.clone();
let recent_blockhash = recent_blockhash.clone();
let blockhash = blockhash.clone();
let client = client.clone();
let id = id.pubkey();
Builder::new()
.name("solana-blockhash-poller".to_string())
.spawn(move || {
poll_blockhash(&exit_signal, &recent_blockhash, &client, &id);
poll_blockhash(&exit_signal, &blockhash, &client, &id);
})
.unwrap()
};
@ -271,7 +269,7 @@ where
let start = Instant::now();
generate_chunked_transfers(
recent_blockhash,
blockhash,
&shared_txs,
shared_tx_active_thread_count,
source_keypair_chunks,
@ -402,7 +400,7 @@ fn poll_blockhash<T: Client>(
loop {
let blockhash_updated = {
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_last_updated = Instant::now();
true
@ -540,7 +538,7 @@ impl<'a> FundingTransactions<'a> for Vec<(&'a Keypair, Transaction)> {
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
self.sign(blockhash);
@ -732,7 +730,7 @@ pub fn airdrop_lamports<T: Client>(
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) {
Ok(transaction) => {
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.
let enough_lamports = 8 * lamports_per_account / 10;
if first_keypair_balance < enough_lamports || last_keypair_balance < enough_lamports {
let fee_rate_governor = client.get_fee_rate_governor().unwrap();
let max_fee = fee_rate_governor.max_lamports_per_signature;
let single_sig_message = Message::new(
&[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 total_keypairs = keypairs.len() as u64 + 1; // Add one for funding keypair
let total = lamports_per_account * total_keypairs + extra_fees;

View File

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

View File

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

View File

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

View File

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

View File

@ -23,7 +23,6 @@ use solana_client::{
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
rpc_response::Fees,
tpu_client::{TpuClient, TpuClientConfig},
};
use solana_rbpf::{
@ -1067,7 +1066,7 @@ fn process_set_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 {
Transaction::new_unsigned(Message::new(
@ -1343,7 +1342,7 @@ fn close(
recipient_pubkey: &Pubkey,
authority_signer: &dyn Signer,
) -> 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(
&[bpf_loader_upgradeable::close(
@ -1891,14 +1890,14 @@ fn check_payer(
balance_needed: u64,
messages: &[&Message],
) -> 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?
check_account_for_spend_multiple_fees_with_commitment(
rpc_client,
&config.signers[0].pubkey(),
balance_needed,
&fee_calculator,
&blockhash,
messages,
config.commitment,
)?;
@ -1920,7 +1919,7 @@ fn send_deploy_messages(
if let Some(message) = initial_message {
if let Some(initial_signer) = initial_signer {
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());
// 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_signer) = write_signer {
trace!("Writing program data");
let Fees {
blockhash,
last_valid_block_height,
..
} = rpc_client
.get_fees_with_commitment(config.commitment)?
.value;
let (blockhash, last_valid_block_height) =
rpc_client.get_latest_blockhash_with_commitment(config.commitment)?;
let mut write_transactions = vec![];
for message in write_messages.iter() {
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(final_signers) = final_signers {
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 signers = final_signers.to_vec();
@ -2141,11 +2135,8 @@ fn send_and_confirm_transactions_with_spinner<T: Signers>(
send_retries -= 1;
// Re-sign any failed transactions with a new blockhash and retry
let Fees {
blockhash,
last_valid_block_height: new_last_valid_block_height,
..
} = rpc_client.get_fees_with_commitment(commitment)?.value;
let (blockhash, new_last_valid_block_height) =
rpc_client.get_latest_blockhash_with_commitment(commitment)?;
last_valid_block_height = new_last_valid_block_height;
transactions = vec![];
for (_, mut transaction) in pending_transactions.into_iter() {

View File

@ -1,12 +1,12 @@
use crate::{
checks::{calculate_fee, check_account_for_balance_with_commitment},
checks::{check_account_for_balance_with_commitment, get_fee_for_message},
cli::CliError,
};
use clap::ArgMatches;
use solana_clap_utils::{input_parsers::lamports_of_sol, offline::SIGN_ONLY_ARG};
use solana_client::rpc_client::RpcClient;
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,
};
@ -47,7 +47,7 @@ pub fn resolve_spend_tx_and_check_account_balance<F>(
rpc_client: &RpcClient,
sign_only: bool,
amount: SpendAmount,
fee_calculator: &FeeCalculator,
blockhash: &Hash,
from_pubkey: &Pubkey,
build_message: F,
commitment: CommitmentConfig,
@ -59,7 +59,7 @@ where
rpc_client,
sign_only,
amount,
fee_calculator,
blockhash,
from_pubkey,
from_pubkey,
build_message,
@ -71,7 +71,7 @@ pub fn resolve_spend_tx_and_check_account_balances<F>(
rpc_client: &RpcClient,
sign_only: bool,
amount: SpendAmount,
fee_calculator: &FeeCalculator,
blockhash: &Hash,
from_pubkey: &Pubkey,
fee_pubkey: &Pubkey,
build_message: F,
@ -82,26 +82,28 @@ where
{
if sign_only {
let (message, SpendAndFee { spend, fee: _ }) = resolve_spend_message(
rpc_client,
amount,
fee_calculator,
None,
0,
from_pubkey,
fee_pubkey,
build_message,
);
)?;
Ok((message, spend))
} else {
let from_balance = rpc_client
.get_balance_with_commitment(from_pubkey, commitment)?
.value;
let (message, SpendAndFee { spend, fee }) = resolve_spend_message(
rpc_client,
amount,
fee_calculator,
Some(blockhash),
from_balance,
from_pubkey,
fee_pubkey,
build_message,
);
)?;
if from_pubkey == fee_pubkey {
if from_balance == 0 || from_balance < spend + fee {
return Err(CliError::InsufficientFundsForSpendAndFee(
@ -130,43 +132,46 @@ where
}
fn resolve_spend_message<F>(
rpc_client: &RpcClient,
amount: SpendAmount,
fee_calculator: &FeeCalculator,
blockhash: Option<&Hash>,
from_balance: u64,
from_pubkey: &Pubkey,
fee_pubkey: &Pubkey,
build_message: F,
) -> (Message, SpendAndFee)
) -> Result<(Message, SpendAndFee), CliError>
where
F: Fn(u64) -> Message,
{
match amount {
SpendAmount::Some(lamports) => {
let message = build_message(lamports);
let fee = calculate_fee(fee_calculator, &[&message]);
(
message,
SpendAndFee {
spend: lamports,
fee,
},
)
}
SpendAmount::All => {
let fee = match blockhash {
Some(blockhash) => {
let dummy_message = build_message(0);
let fee = calculate_fee(fee_calculator, &[&dummy_message]);
get_fee_for_message(rpc_client, blockhash, &[&dummy_message])?
}
None => 0, // Offline, cannot calulate fee
};
match amount {
SpendAmount::Some(lamports) => Ok((
build_message(lamports),
SpendAndFee {
spend: lamports,
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) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
let (message, lamports) = resolve_spend_tx_and_check_account_balances(
rpc_client,
sign_only,
amount,
&fee_calculator,
&recent_blockhash,
&from.pubkey(),
&fee_payer.pubkey(),
build_message,
@ -1387,8 +1386,7 @@ pub fn process_stake_authorize(
}
ixs = ixs.with_memo(memo);
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
let nonce_authority = config.signers[nonce_authority];
let fee_payer = config.signers[fee_payer];
@ -1427,7 +1425,7 @@ pub fn process_stake_authorize(
check_account_for_fee_with_commitment(
rpc_client,
&tx.message.account_keys[0],
&fee_calculator,
&recent_blockhash,
&tx.message,
config.commitment,
)?;
@ -1455,8 +1453,7 @@ pub fn process_deactivate_stake_account(
seed: Option<&String>,
fee_payer: SignerIndex,
) -> ProcessResult {
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
let stake_authority = config.signers[stake_authority];
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(
rpc_client,
&tx.message.account_keys[0],
&fee_calculator,
&recent_blockhash,
&tx.message,
config.commitment,
)?;
@ -1543,8 +1540,7 @@ pub fn process_withdraw_stake(
*stake_account_pubkey
};
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
let fee_payer = config.signers[fee_payer];
let nonce_authority = config.signers[nonce_authority];
@ -1575,7 +1571,7 @@ pub fn process_withdraw_stake(
rpc_client,
sign_only,
amount,
&fee_calculator,
&recent_blockhash,
&stake_account_address,
&fee_payer.pubkey(),
build_message,
@ -1606,7 +1602,7 @@ pub fn process_withdraw_stake(
check_account_for_fee_with_commitment(
rpc_client,
&tx.message.account_keys[0],
&fee_calculator,
&recent_blockhash,
&tx.message,
config.commitment,
)?;
@ -1692,8 +1688,7 @@ pub fn process_split_stake(
}
}
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
let ixs = if let Some(seed) = split_stake_account_seed {
stake_instruction::split_with_seed(
@ -1751,7 +1746,7 @@ pub fn process_split_stake(
check_account_for_fee_with_commitment(
rpc_client,
&tx.message.account_keys[0],
&fee_calculator,
&recent_blockhash,
&tx.message,
config.commitment,
)?;
@ -1812,8 +1807,7 @@ pub fn process_merge_stake(
}
}
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
let ixs = stake_instruction::merge(
stake_account_pubkey,
@ -1858,7 +1852,7 @@ pub fn process_merge_stake(
check_account_for_fee_with_commitment(
rpc_client,
&tx.message.account_keys[0],
&fee_calculator,
&recent_blockhash,
&tx.message,
config.commitment,
)?;
@ -1887,8 +1881,7 @@ pub fn process_stake_set_lockup(
memo: Option<&String>,
fee_payer: SignerIndex,
) -> ProcessResult {
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
let custodian = config.signers[custodian];
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(
rpc_client,
&tx.message.account_keys[0],
&fee_calculator,
&recent_blockhash,
&tx.message,
config.commitment,
)?;
@ -2291,8 +2284,7 @@ pub fn process_delegate_stake(
}
}
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
let ixs = vec![stake_instruction::delegate_stake(
stake_account_pubkey,
@ -2337,7 +2329,7 @@ pub fn process_delegate_stake(
check_account_for_fee_with_commitment(
rpc_client,
&tx.message.account_keys[0],
&fee_calculator,
&recent_blockhash,
&tx.message,
config.commitment,
)?;

View File

@ -345,18 +345,18 @@ pub fn process_set_validator_info(
};
// 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(
rpc_client,
false,
SpendAmount::Some(lamports),
&fee_calculator,
&latest_blockhash,
&config.signers[0].pubkey(),
build_message,
config.commitment,
)?;
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)?;
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(
rpc_client,
false,
amount,
&fee_calculator,
&latest_blockhash,
&config.signers[0].pubkey(),
build_message,
config.commitment,
)?;
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);
log_instruction_custom_error::<SystemError>(result, config)
}
@ -639,7 +639,7 @@ pub fn process_vote_authorize(
(&authorized.pubkey(), "authorized_account".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() {
vote_instruction::authorize_checked(
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 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(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&latest_blockhash,
&tx.message,
config.commitment,
)?;
@ -686,7 +686,7 @@ pub fn process_vote_update_validator(
(vote_account_pubkey, "vote_account_pubkey".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(
vote_account_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 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(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&latest_blockhash,
&tx.message,
config.commitment,
)?;
@ -717,7 +717,7 @@ pub fn process_vote_update_commission(
memo: Option<&String>,
) -> ProcessResult {
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(
vote_account_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 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(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&latest_blockhash,
&tx.message,
config.commitment,
)?;
@ -836,7 +836,7 @@ pub fn process_withdraw_from_vote_account(
destination_account_pubkey: &Pubkey,
memo: Option<&String>,
) -> 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 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 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(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&latest_blockhash,
&transaction.message,
config.commitment,
)?;

View File

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

View File

@ -356,7 +356,7 @@ fn test_offline_stake_delegation_and_deactivation() {
process_command(&config_validator).unwrap();
// Delegate stake offline
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
let blockhash = rpc_client.get_latest_blockhash().unwrap();
config_offline.command = CliCommand::DelegateStake {
stake_account_pubkey: stake_keypair.pubkey(),
vote_account_pubkey: test_validator.vote_account_address(),
@ -394,7 +394,7 @@ fn test_offline_stake_delegation_and_deactivation() {
process_command(&config_payer).unwrap();
// Deactivate stake offline
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
let blockhash = rpc_client.get_latest_blockhash().unwrap();
config_offline.command = CliCommand::DeactivateStake {
stake_account_pubkey: stake_keypair.pubkey(),
stake_authority: 0,
@ -714,7 +714,7 @@ fn test_stake_authorize() {
// Offline assignment of new nonced stake authority
let nonced_authority = Keypair::new();
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 {
stake_account_pubkey,
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);
// 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 {
stake_account_pubkey,
new_authorizations: vec![StakeAuthorizationIndexed {

View File

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

View File

@ -19,6 +19,7 @@ pub enum Source {
}
impl Source {
#[deprecated(since = "1.8.0", note = "Please use `get_blockhash` instead")]
pub fn get_blockhash_and_fee_calculator(
&self,
rpc_client: &RpcClient,
@ -26,6 +27,7 @@ impl Source {
) -> Result<(Hash, FeeCalculator), Box<dyn std::error::Error>> {
match self {
Self::Cluster => {
#[allow(deprecated)]
let res = rpc_client
.get_recent_blockhash_with_commitment(commitment)?
.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(
&self,
rpc_client: &RpcClient,
@ -47,6 +53,7 @@ impl Source {
) -> Result<Option<FeeCalculator>, Box<dyn std::error::Error>> {
match self {
Self::Cluster => {
#[allow(deprecated)]
let res = rpc_client
.get_fee_calculator_for_blockhash_with_commitment(blockhash, commitment)?
.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)]
@ -90,6 +131,7 @@ impl BlockhashQuery {
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(
&self,
rpc_client: &RpcClient,
@ -98,16 +140,36 @@ impl BlockhashQuery {
match self {
BlockhashQuery::None(hash) => Ok((*hash, FeeCalculator::default())),
BlockhashQuery::FeeCalculator(source, hash) => {
#[allow(deprecated)]
let fee_calculator = source
.get_fee_calculator(rpc_client, hash, commitment)?
.ok_or(format!("Hash has expired {:?}", hash))?;
Ok((*hash, fee_calculator))
}
BlockhashQuery::All(source) => {
BlockhashQuery::All(source) =>
{
#[allow(deprecated)]
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 {
@ -282,6 +344,7 @@ mod tests {
}
#[test]
#[allow(deprecated)]
fn test_blockhash_query_get_blockhash_fee_calc() {
let test_blockhash = hash(&[0u8]);
let rpc_blockhash = hash(&[1u8]);

View File

@ -6,9 +6,9 @@ use {
rpc_config::RpcBlockProductionConfig,
rpc_request::RpcRequest,
rpc_response::{
Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange, RpcFees,
RpcResponseContext, RpcSimulateTransactionResult, RpcStakeActivation, RpcSupply,
RpcVersionInfo, RpcVoteAccountStatus, StakeActivationState,
Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange, RpcBlockhash,
RpcFees, RpcResponseContext, RpcSimulateTransactionResult, RpcStakeActivation,
RpcSupply, RpcVersionInfo, RpcVoteAccountStatus, StakeActivationState,
},
rpc_sender::RpcSender,
},
@ -271,6 +271,17 @@ impl RpcSender for MockSender {
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,
};
Ok(val)

View File

@ -38,6 +38,7 @@ use {
epoch_schedule::EpochSchedule,
fee_calculator::{FeeCalculator, FeeRateGovernor},
hash::Hash,
message::Message,
pubkey::Pubkey,
signature::Signature,
transaction::{self, uses_durable_nonce, Transaction},
@ -722,7 +723,7 @@ impl RpcClient {
preflight_commitment: Some(preflight_commitment.commitment),
..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(
RpcRequest::SendTransaction,
json!([serialized_encoded, config]),
@ -859,7 +860,7 @@ impl RpcClient {
commitment: Some(commitment),
..config
};
let serialized_encoded = serialize_encode_transaction(transaction, encoding)?;
let serialized_encoded = serialize_and_encode::<Transaction>(transaction, encoding)?;
self.send(
RpcRequest::SimulateTransaction,
json!([serialized_encoded, config]),
@ -1981,9 +1982,8 @@ impl RpcClient {
let signature = self.send_transaction(transaction)?;
let recent_blockhash = if uses_durable_nonce(transaction).is_some() {
let (recent_blockhash, ..) = self
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())?
.value;
let (recent_blockhash, ..) =
self.get_latest_blockhash_with_commitment(CommitmentConfig::processed())?;
recent_blockhash
} else {
transaction.message.recent_blockhash
@ -1994,13 +1994,9 @@ impl RpcClient {
Some(Ok(_)) => return Ok(signature),
Some(Err(e)) => return Err(e.into()),
None => {
let fee_calculator = self
.get_fee_calculator_for_blockhash_with_commitment(
&recent_blockhash,
CommitmentConfig::processed(),
)?
.value;
if fee_calculator.is_none() {
if !self
.is_blockhash_valid(&recent_blockhash, CommitmentConfig::processed())?
{
// Block hash is not found by some reason
break 'sending;
} 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> {
#[allow(deprecated)]
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> {
let Response {
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)> {
#[allow(deprecated)]
let (blockhash, fee_calculator, _last_valid_slot) = self
.get_recent_blockhash_with_commitment(self.commitment())?
.value;
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(
&self,
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(
&self,
blockhash: &Hash,
) -> ClientResult<Option<FeeCalculator>> {
#[allow(deprecated)]
Ok(self
.get_fee_calculator_for_blockhash_with_commitment(blockhash, self.commitment())?
.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(
&self,
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> {
let Response {
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)> {
let mut num_retries = 0;
let start = Instant::now();
while start.elapsed().as_secs() < 5 {
#[allow(deprecated)]
if let Ok((new_blockhash, fee_calculator)) = self.get_recent_blockhash() {
if new_blockhash != *blockhash {
return Ok((new_blockhash, fee_calculator));
@ -2831,8 +2865,7 @@ impl RpcClient {
config: RpcSendTransactionConfig,
) -> ClientResult<Signature> {
let recent_blockhash = if uses_durable_nonce(transaction).is_some() {
self.get_recent_blockhash_with_commitment(CommitmentConfig::processed())?
.value
self.get_latest_blockhash_with_commitment(CommitmentConfig::processed())?
.0
} else {
transaction.message.recent_blockhash
@ -2872,13 +2905,8 @@ impl RpcClient {
let status = self
.get_signature_status_with_commitment(signature, CommitmentConfig::processed())?;
if status.is_none() {
let blockhash_not_found = self
.get_fee_calculator_for_blockhash_with_commitment(
recent_blockhash,
CommitmentConfig::processed(),
)?
.value
.is_none();
let blockhash_not_found =
!self.is_blockhash_valid(recent_blockhash, CommitmentConfig::processed())?;
if blockhash_not_found && now.elapsed() >= confirm_transaction_initial_timeout {
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>
where
T: serde::de::DeserializeOwned,
@ -2951,18 +3057,18 @@ impl RpcClient {
}
}
fn serialize_encode_transaction(
transaction: &Transaction,
encoding: UiTransactionEncoding,
) -> ClientResult<String> {
let serialized = serialize(transaction)
.map_err(|e| ClientErrorKind::Custom(format!("transaction serialization failed: {}", e)))?;
pub fn serialize_and_encode<T>(input: &T, encoding: UiTransactionEncoding) -> ClientResult<String>
where
T: serde::ser::Serialize,
{
let serialized = serialize(input)
.map_err(|e| ClientErrorKind::Custom(format!("Serialization failed: {}", e)))?;
let encoded = match encoding {
UiTransactionEncoding::Base58 => bs58::encode(serialized).into_string(),
UiTransactionEncoding::Base64 => base64::encode(serialized),
_ => {
return Err(ClientErrorKind::Custom(format!(
"unsupported transaction encoding: {}. Supported encodings: base58, base64",
"unsupported encoding: {}. Supported encodings: base58, base64",
encoding
))
.into())
@ -3094,12 +3200,14 @@ mod tests {
.unwrap();
assert_eq!(balance, 50);
#[allow(deprecated)]
let blockhash: String = rpc_client
.send(RpcRequest::GetRecentBlockhash, Value::Null)
.unwrap();
assert_eq!(blockhash, "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
// Send erroneous parameter
#[allow(deprecated)]
let blockhash: ClientResult<String> =
rpc_client.send(RpcRequest::GetRecentBlockhash, json!(["parameter"]));
assert!(blockhash.is_err());
@ -3134,12 +3242,14 @@ mod tests {
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);
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]
@ -3229,4 +3339,20 @@ mod tests {
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)]
pub enum RpcRequest {
Custom {
method: &'static str,
},
DeregisterNode,
GetAccountInfo,
GetBalance,
@ -18,7 +21,6 @@ pub enum RpcRequest {
GetBlocksWithLimit,
GetBlockTime,
GetClusterNodes,
#[deprecated(since = "1.7.0", note = "Please use RpcRequest::GetBlock instead")]
GetConfirmedBlock,
#[deprecated(since = "1.7.0", note = "Please use RpcRequest::GetBlocks instead")]
@ -38,11 +40,23 @@ pub enum RpcRequest {
note = "Please use RpcRequest::GetTransaction instead"
)]
GetConfirmedTransaction,
GetEpochInfo,
GetEpochSchedule,
#[deprecated(
since = "1.8.0",
note = "Please use RpcRequest::GetFeeForMessage instead"
)]
GetFeeCalculatorForBlockhash,
GetFeeForMessage,
#[deprecated(
since = "1.8.0",
note = "Please do not use, will no longer be available in the future"
)]
GetFeeRateGovernor,
#[deprecated(
since = "1.8.0",
note = "Please use RpcRequest::GetFeeForMessage instead"
)]
GetFees,
GetFirstAvailableBlock,
GetGenesisHash,
@ -52,12 +66,17 @@ pub enum RpcRequest {
GetInflationRate,
GetInflationReward,
GetLargestAccounts,
GetLatestBlockhash,
GetLeaderSchedule,
GetMaxRetransmitSlot,
GetMaxShredInsertSlot,
GetMinimumBalanceForRentExemption,
GetMultipleAccounts,
GetProgramAccounts,
#[deprecated(
since = "1.8.0",
note = "Please use RpcRequest::GetLatestBlockhash instead"
)]
GetRecentBlockhash,
GetRecentPerformanceSamples,
GetSnapshotSlot,
@ -80,21 +99,20 @@ pub enum RpcRequest {
GetTransactionCount,
GetVersion,
GetVoteAccounts,
IsBlockhashValid,
MinimumLedgerSlot,
RegisterNode,
RequestAirdrop,
SendTransaction,
SimulateTransaction,
SignVote,
Custom {
method: &'static str,
},
}
#[allow(deprecated)]
impl fmt::Display for RpcRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let method = match self {
RpcRequest::Custom { method } => method,
RpcRequest::DeregisterNode => "deregisterNode",
RpcRequest::GetAccountInfo => "getAccountInfo",
RpcRequest::GetBalance => "getBalance",
@ -113,6 +131,7 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetEpochInfo => "getEpochInfo",
RpcRequest::GetEpochSchedule => "getEpochSchedule",
RpcRequest::GetFeeCalculatorForBlockhash => "getFeeCalculatorForBlockhash",
RpcRequest::GetFeeForMessage => "getFeeForMessage",
RpcRequest::GetFeeRateGovernor => "getFeeRateGovernor",
RpcRequest::GetFees => "getFees",
RpcRequest::GetFirstAvailableBlock => "getFirstAvailableBlock",
@ -123,6 +142,7 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetInflationRate => "getInflationRate",
RpcRequest::GetInflationReward => "getInflationReward",
RpcRequest::GetLargestAccounts => "getLargestAccounts",
RpcRequest::GetLatestBlockhash => "getLatestBlockhash",
RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
RpcRequest::GetMaxRetransmitSlot => "getMaxRetransmitSlot",
RpcRequest::GetMaxShredInsertSlot => "getMaxShredInsertSlot",
@ -151,13 +171,13 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetTransactionCount => "getTransactionCount",
RpcRequest::GetVersion => "getVersion",
RpcRequest::GetVoteAccounts => "getVoteAccounts",
RpcRequest::IsBlockhashValid => "isBlockhashValid",
RpcRequest::MinimumLedgerSlot => "minimumLedgerSlot",
RpcRequest::RegisterNode => "registerNode",
RpcRequest::RequestAirdrop => "requestAirdrop",
RpcRequest::SendTransaction => "sendTransaction",
RpcRequest::SimulateTransaction => "simulateTransaction",
RpcRequest::SignVote => "signVote",
RpcRequest::Custom { method } => method,
};
write!(f, "{}", method)
@ -261,14 +281,17 @@ mod tests {
let request = test_request.build_request_json(1, Value::Null);
assert_eq!(request["method"], "getEpochInfo");
#[allow(deprecated)]
let test_request = RpcRequest::GetRecentBlockhash;
let request = test_request.build_request_json(1, Value::Null);
assert_eq!(request["method"], "getRecentBlockhash");
#[allow(deprecated)]
let test_request = RpcRequest::GetFeeCalculatorForBlockhash;
let request = test_request.build_request_json(1, json!([addr]));
assert_eq!(request["method"], "getFeeCalculatorForBlockhash");
#[allow(deprecated)]
let test_request = RpcRequest::GetFeeRateGovernor;
let request = test_request.build_request_json(1, Value::Null);
assert_eq!(request["method"], "getFeeRateGovernor");
@ -298,6 +321,7 @@ mod tests {
let addr = json!("deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
// Test request with CommitmentConfig and no params
#[allow(deprecated)]
let test_request = RpcRequest::GetRecentBlockhash;
let request = test_request.build_request_json(1, json!([commitment_config]));
assert_eq!(request["params"], json!([commitment_config.clone()]));

View File

@ -41,6 +41,13 @@ pub struct RpcBlockhashFeeCalculator {
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)]
#[serde(rename_all = "camelCase")]
pub struct RpcFees {

View File

@ -246,7 +246,7 @@ impl ThinClient {
}
}
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);
}
Err(io::Error::new(
@ -333,7 +333,7 @@ impl SyncClient for ThinClient {
keypairs: &T,
message: Message,
) -> 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 signature = self.send_and_confirm_transaction(keypairs, &mut transaction, 5, 0)?;
Ok(signature)
@ -404,6 +404,7 @@ impl SyncClient for ThinClient {
}
fn get_recent_blockhash(&self) -> TransportResult<(Hash, FeeCalculator)> {
#[allow(deprecated)]
let (blockhash, fee_calculator, _last_valid_slot) =
self.get_recent_blockhash_with_commitment(CommitmentConfig::default())?;
Ok((blockhash, fee_calculator))
@ -415,6 +416,7 @@ impl SyncClient for ThinClient {
) -> TransportResult<(Hash, FeeCalculator, Slot)> {
let index = self.optimizer.experiment();
let now = Instant::now();
#[allow(deprecated)]
let recent_blockhash =
self.rpc_clients[index].get_recent_blockhash_with_commitment(commitment_config);
match recent_blockhash {
@ -433,12 +435,14 @@ impl SyncClient for ThinClient {
&self,
blockhash: &Hash,
) -> TransportResult<Option<FeeCalculator>> {
#[allow(deprecated)]
self.rpc_client()
.get_fee_calculator_for_blockhash(blockhash)
.map_err(|e| e.into())
}
fn get_fee_rate_governor(&self) -> TransportResult<FeeRateGovernor> {
#[allow(deprecated)]
self.rpc_client()
.get_fee_rate_governor()
.map_err(|e| e.into())
@ -556,10 +560,57 @@ impl SyncClient for ThinClient {
}
fn get_new_blockhash(&self, blockhash: &Hash) -> TransportResult<(Hash, FeeCalculator)> {
#[allow(deprecated)]
self.rpc_client()
.get_new_blockhash(blockhash)
.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 {

View File

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

View File

@ -82,12 +82,12 @@ impl VoteSimulator {
for (pubkey, vote) in cluster_votes.iter() {
if vote.contains(&parent) {
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(
// Must vote > root to be processed
vec![parent],
parent_bank.hash(),
last_blockhash,
latest_blockhash,
&keypairs.node_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 (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 signature = client.send_transaction(&tx).unwrap();

View File

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

View File

@ -122,7 +122,7 @@ https://github.com/solana-labs/solana/blob/b6bfed64cb159ee67bb6bdbaefc7f833bbed3
// Number of signatures processed in this block
&signature_count_buf,
// 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())
.is_err()
{
let (recent_blockhash, _fee_calculator) = rpc_client.get_recent_blockhash()?;
let recent_blockhash = rpc_client.get_latest_blockhash()?;
let lamports = rpc_client
.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: &SignedUpdateManifest,
) -> 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 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");
assert!(bal > 0);
let (blockhash, _fee_calculator, _last_valid_slot) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::confirmed())
let (blockhash, _) = client
.get_latest_blockhash_with_commitment(CommitmentConfig::confirmed())
.unwrap();
let mut transaction =
system_transaction::transfer(funding_keypair, &random_keypair.pubkey(), 1, blockhash);
@ -115,8 +115,8 @@ pub fn send_many_transactions(
)
.expect("balance in source");
assert!(bal > 0);
let (blockhash, _fee_calculator, _last_valid_slot) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
let (blockhash, _) = client
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap();
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 (blockhash, _fee_calculator, _last_valid_slot) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
let (blockhash, _) = client
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap();
let mut transaction = system_transaction::transfer(
funding_keypair,

View File

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

View File

@ -191,8 +191,8 @@ fn test_local_cluster_signature_subscribe() {
non_bootstrap_info.client_facing_addr(),
VALIDATOR_PORT_RANGE,
);
let (blockhash, _fee_calculator, _last_valid_slot) = tx_client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
let (blockhash, _) = tx_client
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap();
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;
while !solana_runtime::accounts_db::FROZEN_ACCOUNT_PANIC.load(Ordering::Relaxed) {
// Transfer from frozen account
let (blockhash, _fee_calculator, _last_valid_slot) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
let (blockhash, _) = client
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap();
client
.async_transfer(
@ -3246,8 +3246,8 @@ fn setup_transfer_scan_threads(
if exit_.load(Ordering::Relaxed) {
return;
}
let (blockhash, _fee_calculator, _last_valid_slot) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
let (blockhash, _) = client
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
.unwrap();
for i in 0..starting_keypairs_.len() {
client

View File

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

View File

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

View File

@ -60,6 +60,7 @@ use {
epoch_schedule::EpochSchedule,
exit::Exit,
hash::Hash,
message::Message,
pubkey::Pubkey,
sanitize::Sanitize,
signature::{Keypair, Signature, Signer},
@ -80,6 +81,7 @@ use {
state::{Account as TokenAccount, Mint},
},
std::{
any::type_name,
cmp::{max, min},
collections::{HashMap, HashSet},
net::SocketAddr,
@ -531,7 +533,8 @@ impl JsonRpcRequestProcessor {
commitment: Option<CommitmentConfig>,
) -> RpcResponse<RpcBlockhashFeeCalculator> {
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(
&bank,
RpcBlockhashFeeCalculator {
@ -543,7 +546,8 @@ impl JsonRpcRequestProcessor {
fn get_fees(&self, commitment: Option<CommitmentConfig>) -> RpcResponse<RpcFees> {
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)]
let last_valid_slot = bank
.get_blockhash_last_valid_slot(&blockhash)
@ -568,6 +572,7 @@ impl JsonRpcRequestProcessor {
commitment: Option<CommitmentConfig>,
) -> RpcResponse<Option<RpcFeeCalculator>> {
let bank = self.bank(commitment);
#[allow(deprecated)]
let fee_calculator = bank.get_fee_calculator(blockhash);
new_response(
&bank,
@ -577,6 +582,7 @@ impl JsonRpcRequestProcessor {
fn get_fee_rate_governor(&self) -> RpcResponse<RpcFeeRateGovernor> {
let bank = self.bank(None);
#[allow(deprecated)]
let fee_rate_governor = bank.get_fee_rate_governor();
new_response(
&bank,
@ -1896,6 +1902,45 @@ impl JsonRpcRequestProcessor {
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(
@ -2410,34 +2455,6 @@ pub mod rpc_bank {
#[rpc(meta, name = "getEpochSchedule")]
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")]
fn get_slot_leader(
&self,
@ -2500,44 +2517,6 @@ pub mod rpc_bank {
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(
&self,
meta: Self::Metadata,
@ -3084,6 +3063,31 @@ pub mod rpc_full {
#[rpc(meta, name = "getFirstAvailableBlock")]
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;
@ -3232,7 +3236,7 @@ pub mod rpc_full {
let blockhash = if let Some(blockhash) = config.recent_blockhash {
verify_hash(&blockhash)?
} else {
bank.confirmed_last_blockhash().0
bank.confirmed_last_blockhash()
};
let last_valid_block_height = bank
.get_blockhash_last_valid_block_height(&blockhash)
@ -3269,7 +3273,8 @@ pub mod rpc_full {
debug!("send_transaction rpc request received");
let config = config.unwrap_or_default();
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
.preflight_commitment
@ -3369,7 +3374,7 @@ pub mod rpc_full {
debug!("simulate_transaction rpc request received");
let config = config.unwrap_or_default();
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);
if config.sig_verify {
@ -3578,10 +3583,126 @@ pub mod rpc_full {
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 {
#![allow(deprecated)]
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 WORST_CASE_BASE64_TX: usize = 1644; // Golden, bump if PACKET_DATA_SIZE changes
fn deserialize_transaction(
encoded_transaction: String,
const MAX_BASE58_SIZE: usize = 1683; // Golden, bump if PACKET_DATA_SIZE changes
const MAX_BASE64_SIZE: usize = 1644; // Golden, bump if PACKET_DATA_SIZE changes
fn decode_and_deserialize<T>(
encoded: String,
encoding: UiTransactionEncoding,
) -> Result<(Vec<u8>, Transaction)> {
let wire_transaction = match encoding {
) -> Result<(Vec<u8>, T)>
where
T: serde::de::DeserializeOwned + Sanitize,
{
let wire_output = match encoding {
UiTransactionEncoding::Base58 => {
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!(
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})",
encoded_transaction.len(),
WORST_CASE_BASE58_TX,
"encoded {} too large: {} bytes (max: encoded/raw {}/{})",
type_name::<T>(),
encoded.len(),
MAX_BASE58_SIZE,
PACKET_DATA_SIZE,
)));
}
bs58::decode(encoded_transaction)
bs58::decode(encoded)
.into_vec()
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?
}
UiTransactionEncoding::Base64 => {
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!(
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})",
encoded_transaction.len(),
WORST_CASE_BASE64_TX,
"encoded {} too large: {} bytes (max: encoded/raw {}/{})",
type_name::<T>(),
encoded.len(),
MAX_BASE64_SIZE,
PACKET_DATA_SIZE,
)));
}
base64::decode(encoded_transaction)
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?
base64::decode(encoded).map_err(|e| Error::invalid_params(format!("{:?}", e)))?
}
_ => {
return Err(Error::invalid_params(format!(
"unsupported transaction encoding: {}. Supported encodings: base58, base64",
"unsupported encoding: {}. Supported encodings: base58, base64",
encoding
)))
}
};
if wire_transaction.len() > PACKET_DATA_SIZE {
if wire_output.len() > PACKET_DATA_SIZE {
let err = format!(
"transaction too large: {} bytes (max: {} bytes)",
wire_transaction.len(),
"encoded {} too large: {} bytes (max: {} bytes)",
type_name::<T>(),
wire_output.len(),
PACKET_DATA_SIZE
);
info!("{}", err);
@ -3928,22 +4054,23 @@ fn deserialize_transaction(
.with_limit(PACKET_DATA_SIZE as u64)
.with_fixint_encoding()
.allow_trailing_bytes()
.deserialize_from(&wire_transaction[..])
.deserialize_from(&wire_output[..])
.map_err(|err| {
info!("transaction deserialize error: {:?}", err);
info!("deserialize error: {}", err);
Error::invalid_params(&err.to_string())
})
.and_then(|transaction: Transaction| {
if let Err(err) = transaction.sanitize() {
.and_then(|output: T| {
if let Err(err) = output.sanitize() {
Err(Error::invalid_params(format!(
"invalid transaction: {}",
"invalid {}: {}",
type_name::<T>(),
err
)))
} 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>> {
@ -3966,7 +4093,7 @@ pub fn create_test_transactions_and_populate_blockstore(
let keypair2 = keypairs[2];
let keypair3 = keypairs[3];
let slot = bank.slot();
let blockhash = bank.confirmed_last_blockhash().0;
let blockhash = bank.confirmed_last_blockhash();
// Generate transactions for processing
// Successful transaction
@ -4032,7 +4159,9 @@ pub fn create_test_transactions_and_populate_blockstore(
#[cfg(test)]
pub mod tests {
use {
super::{rpc_accounts::*, rpc_bank::*, rpc_full::*, rpc_minimal::*, *},
super::{
rpc_accounts::*, rpc_bank::*, rpc_deprecated_v1_8::*, rpc_full::*, rpc_minimal::*, *,
},
crate::{
optimistically_confirmed_bank_tracker::{
BankNotification, OptimisticallyConfirmedBankTracker,
@ -4196,7 +4325,7 @@ pub mod tests {
let exit = Arc::new(AtomicBool::new(false));
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);
bank.process_transaction(&tx).expect("process transaction");
let tx =
@ -4267,6 +4396,7 @@ pub mod tests {
io.extend_with(rpc_bank::BankDataImpl.to_delegate());
io.extend_with(rpc_accounts::AccountsDataImpl.to_delegate());
io.extend_with(rpc_full::FullImpl.to_delegate());
io.extend_with(rpc_deprecated_v1_8::DeprecatedV1_8Impl.to_delegate());
RpcHandler {
io,
meta,
@ -5675,6 +5805,7 @@ pub mod tests {
let bob_pubkey = solana_sdk::pubkey::new_rand();
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 fee_calculator = RpcFeeCalculator { fee_calculator };
@ -5855,7 +5986,7 @@ pub mod tests {
assert_eq!(
res,
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(
@ -5919,7 +6050,7 @@ pub mod tests {
assert_eq!(
res,
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() {
let ff_tx = vec![0xffu8; PACKET_DATA_SIZE];
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);
assert_eq!(tx64.len(), WORST_CASE_BASE64_TX);
assert_eq!(tx64.len(), MAX_BASE64_SIZE);
}
#[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
let too_big = PACKET_DATA_SIZE + 2;
let tx_ser = vec![0xffu8; too_big];
let tx58 = bs58::encode(&tx_ser).into_string();
let tx58_len = tx58.len();
let expect58 = Error::invalid_params(format!(
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})",
tx58_len, WORST_CASE_BASE58_TX, PACKET_DATA_SIZE,
"encoded solana_sdk::transaction::Transaction too large: {} bytes (max: encoded/raw {}/{})",
tx58_len, MAX_BASE58_SIZE, PACKET_DATA_SIZE,
));
assert_eq!(
deserialize_transaction(tx58, UiTransactionEncoding::Base58).unwrap_err(),
decode_and_deserialize::<Transaction>(tx58, UiTransactionEncoding::Base58).unwrap_err(),
expect58
);
let tx64 = base64::encode(&tx_ser);
let tx64_len = tx64.len();
let expect64 = Error::invalid_params(format!(
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})",
tx64_len, WORST_CASE_BASE64_TX, PACKET_DATA_SIZE,
"encoded solana_sdk::transaction::Transaction too large: {} bytes (max: encoded/raw {}/{})",
tx64_len, MAX_BASE64_SIZE, PACKET_DATA_SIZE,
));
assert_eq!(
deserialize_transaction(tx64, UiTransactionEncoding::Base64).unwrap_err(),
decode_and_deserialize::<Transaction>(tx64, UiTransactionEncoding::Base64).unwrap_err(),
expect64
);
let too_big = PACKET_DATA_SIZE + 1;
let tx_ser = vec![0x00u8; too_big];
let tx58 = bs58::encode(&tx_ser).into_string();
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
));
assert_eq!(
deserialize_transaction(tx58, UiTransactionEncoding::Base58).unwrap_err(),
decode_and_deserialize::<Transaction>(tx58, UiTransactionEncoding::Base58).unwrap_err(),
expect
);
let tx64 = base64::encode(&tx_ser);
assert_eq!(
deserialize_transaction(tx64, UiTransactionEncoding::Base64).unwrap_err(),
decode_and_deserialize::<Transaction>(tx64, UiTransactionEncoding::Base64).unwrap_err(),
expect
);
}
#[test]
fn test_deserialize_transaction_unsanitary() {
fn test_decode_and_deserialize_unsanitary() {
let unsanitary_tx58 = "ju9xZWuDBX4pRxX2oZkTjxU5jB4SSTgEGhX8bQ8PURNzyzqKMPPpNvWihx8zUe\
FfrbVNoAaEsNKZvGzAnTDy5bhNT9kt6KFCTBixpvrLCzg4M5UdFUQYrn1gdgjX\
pLHxcaShD81xBNaFDgnA2nkkdHnKtZt4hVSfKAmw3VRZbjrZ7L2fKZBx21CwsG\
hD6onjM2M3qZW5C8J6d1pj41MxKmZgPBSha3MyKkNLkAGFASK"
.to_string();
let expect58 =
Error::invalid_params("invalid transaction: index out of bounds".to_string());
let expect58 = Error::invalid_params(
"invalid solana_sdk::transaction::Transaction: index out of bounds".to_string(),
);
assert_eq!(
deserialize_transaction(unsanitary_tx58, UiTransactionEncoding::Base58).unwrap_err(),
decode_and_deserialize::<Transaction>(unsanitary_tx58, UiTransactionEncoding::Base58)
.unwrap_err(),
expect58
);
}

View File

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

View File

@ -106,9 +106,11 @@ impl TransactionStatusService {
let fee_calculator = nonce_rollback
.map(|nonce_rollback| nonce_rollback.fee_calculator())
.unwrap_or_else(|| {
#[allow(deprecated)]
bank.get_fee_calculator(&transaction.message().recent_blockhash)
})
.expect("FeeCalculator must exist");
#[allow(deprecated)]
let fee = fee_calculator.calculate_fee(transaction.message());
let (writable_keys, readonly_keys) =
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!()));
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()));
Transaction::new(&[&rando0], message, blockhash)
})
@ -76,7 +76,7 @@ pub fn create_native_loader_transactions(
.unwrap_or_else(|_| panic!("{}:{}", line!(), file!()));
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()));
Transaction::new(&[&rando0], message, blockhash)
})

View File

@ -450,11 +450,13 @@ impl Accounts {
.as_ref()
.map(|nonce_rollback| nonce_rollback.fee_calculator())
.unwrap_or_else(|| {
#[allow(deprecated)]
hash_queue
.get_fee_calculator(&tx.message().recent_blockhash)
.cloned()
});
let fee = if let Some(fee_calculator) = fee_calculator {
#[allow(deprecated)]
fee_calculator.calculate_fee(tx.message())
} else {
return (Err(TransactionError::BlockhashNotFound), None);
@ -1292,7 +1294,9 @@ mod tests {
);
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 =
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()
}
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 {
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) {
let blockhash_queue = self.blockhash_queue.read().unwrap();
let last_hash = blockhash_queue.last_hash();
(
last_hash,
#[allow(deprecated)]
blockhash_queue
.get_fee_calculator(&last_hash)
.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> {
let blockhash_queue = self.blockhash_queue.read().unwrap();
#[allow(deprecated)]
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 {
&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(
since = "1.6.11",
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)
}
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;
let parents = self.parents();
if parents.is_empty() {
#[allow(deprecated)]
self.last_blockhash_with_fee_calculator()
} else {
let index = NUM_BLOCKHASH_CONFIRMATIONS.min(parents.len() - 1);
#[allow(deprecated)]
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.
pub fn clear_signatures(&self) {
self.src.status_cache.write().unwrap().clear();
@ -3400,6 +3439,7 @@ impl Bank {
let blockhash = blockhash_queue.last_hash();
(
blockhash,
#[allow(deprecated)]
blockhash_queue
.get_fee_calculator(&blockhash)
.cloned()
@ -3582,6 +3622,7 @@ impl Bank {
.map(|maybe_fee_calculator| (maybe_fee_calculator, true))
.unwrap_or_else(|| {
(
#[allow(deprecated)]
hash_queue
.get_fee_calculator(&tx.message().recent_blockhash)
.cloned(),
@ -3590,6 +3631,7 @@ impl Bank {
});
let fee_calculator = fee_calculator.ok_or(TransactionError::BlockhashNotFound)?;
#[allow(deprecated)]
let fee = fee_calculator.calculate_fee(tx.message());
let message = tx.message();
@ -3658,6 +3700,7 @@ impl Bank {
}
let mut write_time = Measure::start("write_time");
#[allow(deprecated)]
self.rc.accounts.store_cached(
self.slot(),
sanitized_txs.as_transactions_iter(),
@ -8304,11 +8347,13 @@ pub(crate) mod tests {
let mut bank = Bank::new_for_tests(&genesis_config);
goto_end_of_slot(&mut bank);
#[allow(deprecated)]
let (cheap_blockhash, cheap_fee_calculator) = bank.last_blockhash_with_fee_calculator();
assert_eq!(cheap_fee_calculator.lamports_per_signature, 0);
let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
goto_end_of_slot(&mut bank);
#[allow(deprecated)]
let (expensive_blockhash, expensive_fee_calculator) =
bank.last_blockhash_with_fee_calculator();
assert!(

View File

@ -148,6 +148,7 @@ impl SyncClient for BankClient {
}
fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)> {
#[allow(deprecated)]
Ok(self.bank.last_blockhash_with_fee_calculator())
}
@ -155,6 +156,7 @@ impl SyncClient for BankClient {
&self,
_commitment_config: CommitmentConfig,
) -> Result<(Hash, FeeCalculator, u64)> {
#[allow(deprecated)]
let (blockhash, fee_calculator) = self.bank.last_blockhash_with_fee_calculator();
#[allow(deprecated)]
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>> {
#[allow(deprecated)]
Ok(self.bank.get_fee_calculator(blockhash))
}
fn get_fee_rate_governor(&self) -> Result<FeeRateGovernor> {
#[allow(deprecated)]
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)> {
let (last_blockhash, fee_calculator) = self.get_recent_blockhash()?;
if last_blockhash != *blockhash {
Ok((last_blockhash, fee_calculator))
#[allow(deprecated)]
let (recent_blockhash, fee_calculator) = self.get_recent_blockhash()?;
if recent_blockhash != *blockhash {
Ok((recent_blockhash, fee_calculator))
} else {
Err(TransportError::IoError(io::Error::new(
io::ErrorKind::Other,
@ -272,6 +277,53 @@ impl SyncClient for BankClient {
fn get_epoch_info(&self) -> Result<EpochInfo> {
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 {

View File

@ -46,6 +46,10 @@ impl BlockhashQueue {
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> {
self.ages.get(hash).map(|hash_age| &hash_age.fee_calculator)
}
@ -66,9 +70,8 @@ impl BlockhashQueue {
}
/// check if hash is valid
#[cfg(test)]
pub fn check_hash(&self, hash: Hash) -> bool {
self.ages.get(&hash).is_some()
pub fn check_hash(&self, hash: &Hash) -> bool {
self.ages.get(hash).is_some()
}
pub fn genesis_hash(&mut self, hash: &Hash, fee_calculator: &FeeCalculator) {
@ -148,9 +151,9 @@ mod tests {
fn test_register_hash() {
let last_hash = Hash::default();
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());
assert!(hash_queue.check_hash(last_hash));
assert!(hash_queue.check_hash(&last_hash));
assert_eq!(hash_queue.hash_height(), 1);
}
@ -163,12 +166,12 @@ mod tests {
hash_queue.register_hash(&last_hash, &FeeCalculator::default());
}
// 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 we are not able to use the oldest remaining hash.
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));
}

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 {
let mut num_secp256k1_signatures: u64 = 0;
for instruction in &message.instructions {
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() {
let id = message.account_keys[program_index];
if secp256k1_program::check_id(&id) && !instruction.data.is_empty() {
@ -193,6 +197,7 @@ mod tests {
}
#[test]
#[allow(deprecated)]
fn test_fee_calculator_calculate_fee() {
// Default: no fee.
let message = Message::default();
@ -216,6 +221,7 @@ mod tests {
}
#[test]
#[allow(deprecated)]
fn test_fee_calculator_calculate_fee_secp256k1() {
use crate::instruction::Instruction;
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>;
/// Get recent blockhash
#[deprecated(since = "1.8.0", note = "Please use `get_latest_blockhash` instead")]
fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)>;
/// 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(
&self,
commitment_config: CommitmentConfig,
@ -91,9 +96,17 @@ pub trait SyncClient {
/// Get `Some(FeeCalculator)` associated with `blockhash` if it is still in
/// 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>>;
/// 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>;
/// Get signature status.
@ -136,7 +149,29 @@ pub trait SyncClient {
/// Poll to confirm a transaction.
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)>;
/// 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 {

View File

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

View File

@ -19,7 +19,6 @@ use solana_client::{
rpc_client::RpcClient,
rpc_config::RpcSendTransactionConfig,
rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
rpc_response::Fees,
};
use solana_sdk::{
clock::Slot,
@ -164,7 +163,7 @@ fn transfer<S: Signer>(
let create_instruction =
system_instruction::transfer(&sender_keypair.pubkey(), to_pubkey, lamports);
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(
&[sender_keypair],
message,
@ -387,13 +386,8 @@ fn send_messages(
if args.dry_run {
Ok((Transaction::new_unsigned(message), std::u64::MAX))
} else {
let Fees {
blockhash,
last_valid_block_height,
..
} = client
.get_fees_with_commitment(CommitmentConfig::default())?
.value;
let (blockhash, last_valid_block_height) =
client.get_latest_blockhash_with_commitment(CommitmentConfig::default())?;
let transaction = Transaction::new(&signers, message, blockhash);
let config = RpcSendTransactionConfig {
skip_preflight: true,
@ -448,14 +442,10 @@ fn distribute_allocations(
&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() {
check_spl_token_balances(num_signatures, allocations, client, args, created_accounts)?;
check_spl_token_balances(&messages, allocations, client, args, created_accounts)?;
} 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)?;
@ -733,18 +723,21 @@ fn log_transaction_confirmations(
}
fn check_payer_balances(
num_signatures: usize,
messages: &[Message],
allocations: &[Allocation],
client: &RpcClient,
args: &DistributeTokensArgs,
) -> Result<(), Error> {
let mut undistributed_tokens: u64 = allocations.iter().map(|x| x.amount).sum();
let (_blockhash, fee_calculator) = client.get_recent_blockhash()?;
let fees = fee_calculator
.lamports_per_signature
.checked_mul(num_signatures as u64)
.unwrap();
let blockhash = client.get_latest_blockhash()?;
let fees = messages
.iter()
.map(|message| client.get_fee_for_message(&blockhash, message))
.collect::<Result<Vec<_>, _>>()
.unwrap()
.iter()
.sum();
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;
@ -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 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);
client
.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 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);
client
.send_and_confirm_transaction_with_spinner(&transaction)
@ -1210,12 +1203,24 @@ mod tests {
use super::*;
use solana_core::test_validator::TestValidator;
use solana_sdk::{
instruction::AccountMeta,
signature::{read_keypair_file, write_keypair_file, Signer},
stake::instruction::StakeInstruction,
};
use solana_streamer::socket::SocketAddrSpace;
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]
fn test_process_token_allocations() {
let alice = Keypair::new();
@ -1594,7 +1599,7 @@ mod tests {
&sender_keypair_file,
None,
);
check_payer_balances(1, &allocations, &client, &args).unwrap();
check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap();
// Unfunded payer
let unfunded_payer = Keypair::new();
@ -1607,7 +1612,9 @@ mod tests {
.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 {
assert_eq!(
sources,
@ -1644,7 +1651,9 @@ mod tests {
args.fee_payer = read_keypair_file(&partially_funded_payer_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 {
assert_eq!(
sources,
@ -1697,7 +1706,7 @@ mod tests {
&sender_keypair_file,
None,
);
check_payer_balances(1, &allocations, &client, &args).unwrap();
check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap();
// Unfunded sender
let unfunded_payer = Keypair::new();
@ -1708,7 +1717,9 @@ mod tests {
.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 {
assert_eq!(sources, vec![FundingSource::SystemAccount].into());
assert_eq!(amount, allocation_amount.to_string());
@ -1722,7 +1733,9 @@ mod tests {
.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 {
assert_eq!(sources, vec![FundingSource::FeePayer].into());
assert_eq!(amount, fees_in_sol.to_string());
@ -1756,7 +1769,7 @@ mod tests {
);
let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
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);
client
.send_and_confirm_transaction_with_spinner(&transaction)
@ -1809,7 +1822,7 @@ mod tests {
&sender_keypair_file,
Some(stake_args),
);
check_payer_balances(1, &allocations, &client, &args).unwrap();
check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap();
// Underfunded stake-account
let expensive_allocation_amount = 5000.0;
@ -1818,8 +1831,13 @@ mod tests {
amount: sol_to_lamports(expensive_allocation_amount),
lockup_date: "".to_string(),
}];
let err_result =
check_payer_balances(1, &expensive_allocations, &client, &args).unwrap_err();
let err_result = check_payer_balances(
&[one_signer_message()],
&expensive_allocations,
&client,
&args,
)
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::StakeAccount].into());
assert_eq!(
@ -1841,7 +1859,9 @@ mod tests {
.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 {
assert_eq!(
sources,
@ -1878,7 +1898,9 @@ mod tests {
args.fee_payer = read_keypair_file(&partially_funded_payer_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 {
assert_eq!(
sources,
@ -1938,7 +1960,7 @@ mod tests {
&sender_keypair_file,
Some(stake_args),
);
check_payer_balances(1, &allocations, &client, &args).unwrap();
check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap();
// Unfunded sender
let unfunded_payer = Keypair::new();
@ -1949,7 +1971,9 @@ mod tests {
.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 {
assert_eq!(sources, vec![FundingSource::SystemAccount].into());
assert_eq!(amount, unlocked_sol.to_string());
@ -1963,7 +1987,9 @@ mod tests {
.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 {
assert_eq!(sources, vec![FundingSource::FeePayer].into());
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,
};
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 spl_associated_token_account_v1_0::{
create_associated_token_account, get_associated_token_address,
@ -85,7 +85,7 @@ pub fn build_spl_token_instructions(
}
pub fn check_spl_token_balances(
num_signatures: usize,
messages: &[Message],
allocations: &[Allocation],
client: &RpcClient,
args: &DistributeTokensArgs,
@ -97,11 +97,14 @@ pub fn check_spl_token_balances(
.expect("spl_token_args must be some");
let allocation_amount: u64 = allocations.iter().map(|x| x.amount).sum();
let fee_calculator = client.get_recent_blockhash()?.1;
let fees = fee_calculator
.lamports_per_signature
.checked_mul(num_signatures as u64)
.unwrap();
let blockhash = client.get_latest_blockhash()?;
let fees: u64 = messages
.iter()
.map(|message| client.get_fee_for_message(&blockhash, message))
.collect::<Result<Vec<_>, _>>()
.unwrap()
.iter()
.sum();
let token_account_rent_exempt_balance =
client.get_minimum_balance_for_rent_exemption(SplTokenAccount::LEN)?;

View File

@ -183,7 +183,7 @@ fn get_cluster_info(
rpc_client: &RpcClient,
) -> client_error::Result<(u64, Hash, RpcVoteAccountStatus, HashMap<Pubkey, u64>)> {
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 mut validator_balances = HashMap::new();