Deprecate FeeCalculator returning APIs (#19120)
This commit is contained in:
parent
26e963f436
commit
0b50bb2b20
|
@ -12,6 +12,7 @@ use solana_measure::measure::Measure;
|
||||||
use solana_runtime::inline_spl_token_v2_0;
|
use solana_runtime::inline_spl_token_v2_0;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
commitment_config::CommitmentConfig,
|
commitment_config::CommitmentConfig,
|
||||||
|
instruction::{AccountMeta, Instruction},
|
||||||
message::Message,
|
message::Message,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rpc_port::DEFAULT_RPC_PORT,
|
rpc_port::DEFAULT_RPC_PORT,
|
||||||
|
@ -33,10 +34,6 @@ use std::{
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create and close messages both require 2 signatures; if transaction construction changes, update
|
|
||||||
// this magic number
|
|
||||||
const NUM_SIGNATURES: u64 = 2;
|
|
||||||
|
|
||||||
pub fn airdrop_lamports(
|
pub fn airdrop_lamports(
|
||||||
client: &RpcClient,
|
client: &RpcClient,
|
||||||
faucet_addr: &SocketAddr,
|
faucet_addr: &SocketAddr,
|
||||||
|
@ -55,7 +52,7 @@ pub fn airdrop_lamports(
|
||||||
id.pubkey(),
|
id.pubkey(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap();
|
let blockhash = client.get_latest_blockhash().unwrap();
|
||||||
match request_airdrop_transaction(faucet_addr, &id.pubkey(), airdrop_amount, blockhash) {
|
match request_airdrop_transaction(faucet_addr, &id.pubkey(), airdrop_amount, blockhash) {
|
||||||
Ok(transaction) => {
|
Ok(transaction) => {
|
||||||
let mut tries = 0;
|
let mut tries = 0;
|
||||||
|
@ -375,10 +372,10 @@ fn run_accounts_bench(
|
||||||
|
|
||||||
info!("Targeting {}", entrypoint_addr);
|
info!("Targeting {}", entrypoint_addr);
|
||||||
|
|
||||||
let mut last_blockhash = Instant::now();
|
let mut latest_blockhash = Instant::now();
|
||||||
let mut last_log = Instant::now();
|
let mut last_log = Instant::now();
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let mut recent_blockhash = client.get_recent_blockhash().expect("blockhash");
|
let mut blockhash = client.get_latest_blockhash().expect("blockhash");
|
||||||
let mut tx_sent_count = 0;
|
let mut tx_sent_count = 0;
|
||||||
let mut total_accounts_created = 0;
|
let mut total_accounts_created = 0;
|
||||||
let mut total_accounts_closed = 0;
|
let mut total_accounts_closed = 0;
|
||||||
|
@ -406,16 +403,32 @@ fn run_accounts_bench(
|
||||||
|
|
||||||
let executor = TransactionExecutor::new(entrypoint_addr);
|
let executor = TransactionExecutor::new(entrypoint_addr);
|
||||||
|
|
||||||
|
// Create and close messages both require 2 signatures, fake a 2 signature message to calculate fees
|
||||||
|
let message = Message::new(
|
||||||
|
&[
|
||||||
|
Instruction::new_with_bytes(
|
||||||
|
Pubkey::new_unique(),
|
||||||
|
&[],
|
||||||
|
vec![AccountMeta::new(Pubkey::new_unique(), true)],
|
||||||
|
),
|
||||||
|
Instruction::new_with_bytes(
|
||||||
|
Pubkey::new_unique(),
|
||||||
|
&[],
|
||||||
|
vec![AccountMeta::new(Pubkey::new_unique(), true)],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if last_blockhash.elapsed().as_millis() > 10_000 {
|
if latest_blockhash.elapsed().as_millis() > 10_000 {
|
||||||
recent_blockhash = client.get_recent_blockhash().expect("blockhash");
|
blockhash = client.get_latest_blockhash().expect("blockhash");
|
||||||
last_blockhash = Instant::now();
|
latest_blockhash = Instant::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
let fee = recent_blockhash
|
let fee = client
|
||||||
.1
|
.get_fee_for_message(&blockhash, &message)
|
||||||
.lamports_per_signature
|
.expect("get_fee_for_message");
|
||||||
.saturating_mul(NUM_SIGNATURES);
|
|
||||||
let lamports = min_balance + fee;
|
let lamports = min_balance + fee;
|
||||||
|
|
||||||
for (i, balance) in balances.iter_mut().enumerate() {
|
for (i, balance) in balances.iter_mut().enumerate() {
|
||||||
|
@ -464,7 +477,7 @@ fn run_accounts_bench(
|
||||||
mint,
|
mint,
|
||||||
);
|
);
|
||||||
let signers: Vec<&Keypair> = vec![keypair, &base_keypair];
|
let signers: Vec<&Keypair> = vec![keypair, &base_keypair];
|
||||||
Transaction::new(&signers, message, recent_blockhash.0)
|
Transaction::new(&signers, message, blockhash)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
balances[i] = balances[i].saturating_sub(lamports * txs.len() as u64);
|
balances[i] = balances[i].saturating_sub(lamports * txs.len() as u64);
|
||||||
|
@ -496,7 +509,7 @@ fn run_accounts_bench(
|
||||||
mint.is_some(),
|
mint.is_some(),
|
||||||
);
|
);
|
||||||
let signers: Vec<&Keypair> = vec![payer_keypairs[0], &base_keypair];
|
let signers: Vec<&Keypair> = vec![payer_keypairs[0], &base_keypair];
|
||||||
Transaction::new(&signers, message, recent_blockhash.0)
|
Transaction::new(&signers, message, blockhash)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
balances[0] = balances[0].saturating_sub(fee * txs.len() as u64);
|
balances[0] = balances[0].saturating_sub(fee * txs.len() as u64);
|
||||||
|
|
|
@ -167,6 +167,7 @@ impl Banks for BanksServer {
|
||||||
commitment: CommitmentLevel,
|
commitment: CommitmentLevel,
|
||||||
) -> (FeeCalculator, Hash, u64) {
|
) -> (FeeCalculator, Hash, u64) {
|
||||||
let bank = self.bank(commitment);
|
let bank = self.bank(commitment);
|
||||||
|
#[allow(deprecated)]
|
||||||
let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator();
|
let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator();
|
||||||
let last_valid_block_height = bank
|
let last_valid_block_height = bank
|
||||||
.get_blockhash_last_valid_block_height(&blockhash)
|
.get_blockhash_last_valid_block_height(&blockhash)
|
||||||
|
|
|
@ -10,8 +10,8 @@ use solana_sdk::{
|
||||||
client::Client,
|
client::Client,
|
||||||
clock::{DEFAULT_S_PER_SLOT, MAX_PROCESSING_AGE},
|
clock::{DEFAULT_S_PER_SLOT, MAX_PROCESSING_AGE},
|
||||||
commitment_config::CommitmentConfig,
|
commitment_config::CommitmentConfig,
|
||||||
fee_calculator::FeeCalculator,
|
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
|
instruction::{AccountMeta, Instruction},
|
||||||
message::Message,
|
message::Message,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
|
@ -45,14 +45,12 @@ pub type Result<T> = std::result::Result<T, BenchTpsError>;
|
||||||
|
|
||||||
pub type SharedTransactions = Arc<RwLock<VecDeque<Vec<(Transaction, u64)>>>>;
|
pub type SharedTransactions = Arc<RwLock<VecDeque<Vec<(Transaction, u64)>>>>;
|
||||||
|
|
||||||
fn get_recent_blockhash<T: Client>(client: &T) -> (Hash, FeeCalculator) {
|
fn get_latest_blockhash<T: Client>(client: &T) -> Hash {
|
||||||
loop {
|
loop {
|
||||||
match client.get_recent_blockhash_with_commitment(CommitmentConfig::processed()) {
|
match client.get_latest_blockhash_with_commitment(CommitmentConfig::processed()) {
|
||||||
Ok((blockhash, fee_calculator, _last_valid_slot)) => {
|
Ok((blockhash, _)) => return blockhash,
|
||||||
return (blockhash, fee_calculator)
|
|
||||||
}
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
info!("Couldn't get recent blockhash: {:?}", err);
|
info!("Couldn't get last blockhash: {:?}", err);
|
||||||
sleep(Duration::from_secs(1));
|
sleep(Duration::from_secs(1));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -239,19 +237,19 @@ where
|
||||||
|
|
||||||
let shared_txs: SharedTransactions = Arc::new(RwLock::new(VecDeque::new()));
|
let shared_txs: SharedTransactions = Arc::new(RwLock::new(VecDeque::new()));
|
||||||
|
|
||||||
let recent_blockhash = Arc::new(RwLock::new(get_recent_blockhash(client.as_ref()).0));
|
let blockhash = Arc::new(RwLock::new(get_latest_blockhash(client.as_ref())));
|
||||||
let shared_tx_active_thread_count = Arc::new(AtomicIsize::new(0));
|
let shared_tx_active_thread_count = Arc::new(AtomicIsize::new(0));
|
||||||
let total_tx_sent_count = Arc::new(AtomicUsize::new(0));
|
let total_tx_sent_count = Arc::new(AtomicUsize::new(0));
|
||||||
|
|
||||||
let blockhash_thread = {
|
let blockhash_thread = {
|
||||||
let exit_signal = exit_signal.clone();
|
let exit_signal = exit_signal.clone();
|
||||||
let recent_blockhash = recent_blockhash.clone();
|
let blockhash = blockhash.clone();
|
||||||
let client = client.clone();
|
let client = client.clone();
|
||||||
let id = id.pubkey();
|
let id = id.pubkey();
|
||||||
Builder::new()
|
Builder::new()
|
||||||
.name("solana-blockhash-poller".to_string())
|
.name("solana-blockhash-poller".to_string())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
poll_blockhash(&exit_signal, &recent_blockhash, &client, &id);
|
poll_blockhash(&exit_signal, &blockhash, &client, &id);
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
@ -271,7 +269,7 @@ where
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
||||||
generate_chunked_transfers(
|
generate_chunked_transfers(
|
||||||
recent_blockhash,
|
blockhash,
|
||||||
&shared_txs,
|
&shared_txs,
|
||||||
shared_tx_active_thread_count,
|
shared_tx_active_thread_count,
|
||||||
source_keypair_chunks,
|
source_keypair_chunks,
|
||||||
|
@ -402,7 +400,7 @@ fn poll_blockhash<T: Client>(
|
||||||
loop {
|
loop {
|
||||||
let blockhash_updated = {
|
let blockhash_updated = {
|
||||||
let old_blockhash = *blockhash.read().unwrap();
|
let old_blockhash = *blockhash.read().unwrap();
|
||||||
if let Ok((new_blockhash, _fee)) = client.get_new_blockhash(&old_blockhash) {
|
if let Ok(new_blockhash) = client.get_new_latest_blockhash(&old_blockhash) {
|
||||||
*blockhash.write().unwrap() = new_blockhash;
|
*blockhash.write().unwrap() = new_blockhash;
|
||||||
blockhash_last_updated = Instant::now();
|
blockhash_last_updated = Instant::now();
|
||||||
true
|
true
|
||||||
|
@ -540,7 +538,7 @@ impl<'a> FundingTransactions<'a> for Vec<(&'a Keypair, Transaction)> {
|
||||||
self.len(),
|
self.len(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let (blockhash, _fee_calculator) = get_recent_blockhash(client.as_ref());
|
let blockhash = get_latest_blockhash(client.as_ref());
|
||||||
|
|
||||||
// re-sign retained to_fund_txes with updated blockhash
|
// re-sign retained to_fund_txes with updated blockhash
|
||||||
self.sign(blockhash);
|
self.sign(blockhash);
|
||||||
|
@ -732,7 +730,7 @@ pub fn airdrop_lamports<T: Client>(
|
||||||
id.pubkey(),
|
id.pubkey(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let (blockhash, _fee_calculator) = get_recent_blockhash(client);
|
let blockhash = get_latest_blockhash(client);
|
||||||
match request_airdrop_transaction(faucet_addr, &id.pubkey(), airdrop_amount, blockhash) {
|
match request_airdrop_transaction(faucet_addr, &id.pubkey(), airdrop_amount, blockhash) {
|
||||||
Ok(transaction) => {
|
Ok(transaction) => {
|
||||||
let mut tries = 0;
|
let mut tries = 0;
|
||||||
|
@ -890,8 +888,18 @@ pub fn generate_and_fund_keypairs<T: 'static + Client + Send + Sync>(
|
||||||
// pay for the transaction fees in a new run.
|
// pay for the transaction fees in a new run.
|
||||||
let enough_lamports = 8 * lamports_per_account / 10;
|
let enough_lamports = 8 * lamports_per_account / 10;
|
||||||
if first_keypair_balance < enough_lamports || last_keypair_balance < enough_lamports {
|
if first_keypair_balance < enough_lamports || last_keypair_balance < enough_lamports {
|
||||||
let fee_rate_governor = client.get_fee_rate_governor().unwrap();
|
let single_sig_message = Message::new(
|
||||||
let max_fee = fee_rate_governor.max_lamports_per_signature;
|
&[Instruction::new_with_bytes(
|
||||||
|
Pubkey::new_unique(),
|
||||||
|
&[],
|
||||||
|
vec![AccountMeta::new(Pubkey::new_unique(), true)],
|
||||||
|
)],
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
let blockhash = client.get_latest_blockhash().unwrap();
|
||||||
|
let max_fee = client
|
||||||
|
.get_fee_for_message(&blockhash, &single_sig_message)
|
||||||
|
.unwrap();
|
||||||
let extra_fees = extra * max_fee;
|
let extra_fees = extra * max_fee;
|
||||||
let total_keypairs = keypairs.len() as u64 + 1; // Add one for funding keypair
|
let total_keypairs = keypairs.len() as u64 + 1; // Add one for funding keypair
|
||||||
let total = lamports_per_account * total_keypairs + extra_fees;
|
let total = lamports_per_account * total_keypairs + extra_fees;
|
||||||
|
|
|
@ -4,30 +4,30 @@ use solana_client::{
|
||||||
rpc_client::RpcClient,
|
rpc_client::RpcClient,
|
||||||
};
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
commitment_config::CommitmentConfig, fee_calculator::FeeCalculator, message::Message,
|
commitment_config::CommitmentConfig, hash::Hash, message::Message,
|
||||||
native_token::lamports_to_sol, pubkey::Pubkey,
|
native_token::lamports_to_sol, pubkey::Pubkey,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn check_account_for_fee(
|
pub fn check_account_for_fee(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
account_pubkey: &Pubkey,
|
account_pubkey: &Pubkey,
|
||||||
fee_calculator: &FeeCalculator,
|
blockhash: &Hash,
|
||||||
message: &Message,
|
message: &Message,
|
||||||
) -> Result<(), CliError> {
|
) -> Result<(), CliError> {
|
||||||
check_account_for_multiple_fees(rpc_client, account_pubkey, fee_calculator, &[message])
|
check_account_for_multiple_fees(rpc_client, account_pubkey, blockhash, &[message])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_account_for_fee_with_commitment(
|
pub fn check_account_for_fee_with_commitment(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
account_pubkey: &Pubkey,
|
account_pubkey: &Pubkey,
|
||||||
fee_calculator: &FeeCalculator,
|
blockhash: &Hash,
|
||||||
message: &Message,
|
message: &Message,
|
||||||
commitment: CommitmentConfig,
|
commitment: CommitmentConfig,
|
||||||
) -> Result<(), CliError> {
|
) -> Result<(), CliError> {
|
||||||
check_account_for_multiple_fees_with_commitment(
|
check_account_for_multiple_fees_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
account_pubkey,
|
account_pubkey,
|
||||||
fee_calculator,
|
blockhash,
|
||||||
&[message],
|
&[message],
|
||||||
commitment,
|
commitment,
|
||||||
)
|
)
|
||||||
|
@ -36,13 +36,13 @@ pub fn check_account_for_fee_with_commitment(
|
||||||
pub fn check_account_for_multiple_fees(
|
pub fn check_account_for_multiple_fees(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
account_pubkey: &Pubkey,
|
account_pubkey: &Pubkey,
|
||||||
fee_calculator: &FeeCalculator,
|
blockhash: &Hash,
|
||||||
messages: &[&Message],
|
messages: &[&Message],
|
||||||
) -> Result<(), CliError> {
|
) -> Result<(), CliError> {
|
||||||
check_account_for_multiple_fees_with_commitment(
|
check_account_for_multiple_fees_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
account_pubkey,
|
account_pubkey,
|
||||||
fee_calculator,
|
blockhash,
|
||||||
messages,
|
messages,
|
||||||
CommitmentConfig::default(),
|
CommitmentConfig::default(),
|
||||||
)
|
)
|
||||||
|
@ -51,7 +51,7 @@ pub fn check_account_for_multiple_fees(
|
||||||
pub fn check_account_for_multiple_fees_with_commitment(
|
pub fn check_account_for_multiple_fees_with_commitment(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
account_pubkey: &Pubkey,
|
account_pubkey: &Pubkey,
|
||||||
fee_calculator: &FeeCalculator,
|
blockhash: &Hash,
|
||||||
messages: &[&Message],
|
messages: &[&Message],
|
||||||
commitment: CommitmentConfig,
|
commitment: CommitmentConfig,
|
||||||
) -> Result<(), CliError> {
|
) -> Result<(), CliError> {
|
||||||
|
@ -59,7 +59,7 @@ pub fn check_account_for_multiple_fees_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
account_pubkey,
|
account_pubkey,
|
||||||
0,
|
0,
|
||||||
fee_calculator,
|
blockhash,
|
||||||
messages,
|
messages,
|
||||||
commitment,
|
commitment,
|
||||||
)
|
)
|
||||||
|
@ -69,11 +69,11 @@ pub fn check_account_for_spend_multiple_fees_with_commitment(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
account_pubkey: &Pubkey,
|
account_pubkey: &Pubkey,
|
||||||
balance: u64,
|
balance: u64,
|
||||||
fee_calculator: &FeeCalculator,
|
blockhash: &Hash,
|
||||||
messages: &[&Message],
|
messages: &[&Message],
|
||||||
commitment: CommitmentConfig,
|
commitment: CommitmentConfig,
|
||||||
) -> Result<(), CliError> {
|
) -> Result<(), CliError> {
|
||||||
let fee = calculate_fee(fee_calculator, messages);
|
let fee = get_fee_for_message(rpc_client, blockhash, messages)?;
|
||||||
if !check_account_for_balance_with_commitment(
|
if !check_account_for_balance_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
account_pubkey,
|
account_pubkey,
|
||||||
|
@ -98,11 +98,17 @@ pub fn check_account_for_spend_multiple_fees_with_commitment(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_fee(fee_calculator: &FeeCalculator, messages: &[&Message]) -> u64 {
|
pub fn get_fee_for_message(
|
||||||
messages
|
rpc_client: &RpcClient,
|
||||||
|
blockhash: &Hash,
|
||||||
|
messages: &[&Message],
|
||||||
|
) -> Result<u64, CliError> {
|
||||||
|
Ok(messages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|message| fee_calculator.calculate_fee(message))
|
.map(|message| rpc_client.get_fee_for_message(blockhash, message))
|
||||||
.sum()
|
.collect::<Result<Vec<_>, _>>()?
|
||||||
|
.iter()
|
||||||
|
.sum())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_account_for_balance(
|
pub fn check_account_for_balance(
|
||||||
|
@ -166,7 +172,6 @@ mod tests {
|
||||||
value: json!(account_balance),
|
value: json!(account_balance),
|
||||||
});
|
});
|
||||||
let pubkey = solana_sdk::pubkey::new_rand();
|
let pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let fee_calculator = FeeCalculator::new(1);
|
|
||||||
|
|
||||||
let pubkey0 = Pubkey::new(&[0; 32]);
|
let pubkey0 = Pubkey::new(&[0; 32]);
|
||||||
let pubkey1 = Pubkey::new(&[1; 32]);
|
let pubkey1 = Pubkey::new(&[1; 32]);
|
||||||
|
@ -180,21 +185,32 @@ mod tests {
|
||||||
let mut mocks = HashMap::new();
|
let mut mocks = HashMap::new();
|
||||||
mocks.insert(RpcRequest::GetBalance, account_balance_response.clone());
|
mocks.insert(RpcRequest::GetBalance, account_balance_response.clone());
|
||||||
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
||||||
check_account_for_fee(&rpc_client, &pubkey, &fee_calculator, &message0)
|
let blockhash = rpc_client.get_latest_blockhash().unwrap();
|
||||||
|
check_account_for_fee(&rpc_client, &pubkey, &blockhash, &message0)
|
||||||
.expect("unexpected result");
|
.expect("unexpected result");
|
||||||
|
|
||||||
|
let check_fee_response = json!(Response {
|
||||||
|
context: RpcResponseContext { slot: 1 },
|
||||||
|
value: json!(2),
|
||||||
|
});
|
||||||
let mut mocks = HashMap::new();
|
let mut mocks = HashMap::new();
|
||||||
|
mocks.insert(RpcRequest::GetFeeForMessage, check_fee_response);
|
||||||
mocks.insert(RpcRequest::GetBalance, account_balance_response.clone());
|
mocks.insert(RpcRequest::GetBalance, account_balance_response.clone());
|
||||||
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
||||||
assert!(check_account_for_fee(&rpc_client, &pubkey, &fee_calculator, &message1).is_err());
|
assert!(check_account_for_fee(&rpc_client, &pubkey, &blockhash, &message1).is_err());
|
||||||
|
|
||||||
|
let check_fee_response = json!(Response {
|
||||||
|
context: RpcResponseContext { slot: 1 },
|
||||||
|
value: json!(2),
|
||||||
|
});
|
||||||
let mut mocks = HashMap::new();
|
let mut mocks = HashMap::new();
|
||||||
|
mocks.insert(RpcRequest::GetFeeForMessage, check_fee_response);
|
||||||
mocks.insert(RpcRequest::GetBalance, account_balance_response);
|
mocks.insert(RpcRequest::GetBalance, account_balance_response);
|
||||||
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
||||||
assert!(check_account_for_multiple_fees(
|
assert!(check_account_for_multiple_fees(
|
||||||
&rpc_client,
|
&rpc_client,
|
||||||
&pubkey,
|
&pubkey,
|
||||||
&fee_calculator,
|
&blockhash,
|
||||||
&[&message0, &message0]
|
&[&message0, &message0]
|
||||||
)
|
)
|
||||||
.is_err());
|
.is_err());
|
||||||
|
@ -204,18 +220,18 @@ mod tests {
|
||||||
context: RpcResponseContext { slot: 1 },
|
context: RpcResponseContext { slot: 1 },
|
||||||
value: json!(account_balance),
|
value: json!(account_balance),
|
||||||
});
|
});
|
||||||
|
let check_fee_response = json!(Response {
|
||||||
|
context: RpcResponseContext { slot: 1 },
|
||||||
|
value: json!(1),
|
||||||
|
});
|
||||||
|
|
||||||
let mut mocks = HashMap::new();
|
let mut mocks = HashMap::new();
|
||||||
|
mocks.insert(RpcRequest::GetFeeForMessage, check_fee_response);
|
||||||
mocks.insert(RpcRequest::GetBalance, account_balance_response);
|
mocks.insert(RpcRequest::GetBalance, account_balance_response);
|
||||||
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
||||||
|
|
||||||
check_account_for_multiple_fees(
|
check_account_for_multiple_fees(&rpc_client, &pubkey, &blockhash, &[&message0, &message0])
|
||||||
&rpc_client,
|
.expect("unexpected result");
|
||||||
&pubkey,
|
|
||||||
&fee_calculator,
|
|
||||||
&[&message0, &message0],
|
|
||||||
)
|
|
||||||
.expect("unexpected result");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -237,27 +253,45 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_calculate_fee() {
|
fn test_get_fee_for_message() {
|
||||||
let fee_calculator = FeeCalculator::new(1);
|
let check_fee_response = json!(Response {
|
||||||
// No messages, no fee.
|
context: RpcResponseContext { slot: 1 },
|
||||||
assert_eq!(calculate_fee(&fee_calculator, &[]), 0);
|
value: json!(1),
|
||||||
|
});
|
||||||
|
let mut mocks = HashMap::new();
|
||||||
|
mocks.insert(RpcRequest::GetFeeForMessage, check_fee_response);
|
||||||
|
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
||||||
|
let blockhash = rpc_client.get_latest_blockhash().unwrap();
|
||||||
|
|
||||||
// No signatures, no fee.
|
// No messages, no fee.
|
||||||
let message = Message::default();
|
assert_eq!(
|
||||||
assert_eq!(calculate_fee(&fee_calculator, &[&message, &message]), 0);
|
get_fee_for_message(&rpc_client, &blockhash, &[]).unwrap(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
// One message w/ one signature, a fee.
|
// One message w/ one signature, a fee.
|
||||||
let pubkey0 = Pubkey::new(&[0; 32]);
|
let pubkey0 = Pubkey::new(&[0; 32]);
|
||||||
let pubkey1 = Pubkey::new(&[1; 32]);
|
let pubkey1 = Pubkey::new(&[1; 32]);
|
||||||
let ix0 = system_instruction::transfer(&pubkey0, &pubkey1, 1);
|
let ix0 = system_instruction::transfer(&pubkey0, &pubkey1, 1);
|
||||||
let message0 = Message::new(&[ix0], Some(&pubkey0));
|
let message0 = Message::new(&[ix0], Some(&pubkey0));
|
||||||
assert_eq!(calculate_fee(&fee_calculator, &[&message0]), 1);
|
assert_eq!(
|
||||||
|
get_fee_for_message(&rpc_client, &blockhash, &[&message0]).unwrap(),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
// Two messages, additive fees.
|
// No signatures, no fee.
|
||||||
let ix0 = system_instruction::transfer(&pubkey0, &pubkey1, 1);
|
let check_fee_response = json!(Response {
|
||||||
let ix1 = system_instruction::transfer(&pubkey1, &pubkey0, 1);
|
context: RpcResponseContext { slot: 1 },
|
||||||
let message1 = Message::new(&[ix0, ix1], Some(&pubkey0));
|
value: json!(0),
|
||||||
assert_eq!(calculate_fee(&fee_calculator, &[&message0, &message1]), 3);
|
});
|
||||||
|
let mut mocks = HashMap::new();
|
||||||
|
mocks.insert(RpcRequest::GetFeeForMessage, check_fee_response);
|
||||||
|
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
||||||
|
let message = Message::default();
|
||||||
|
assert_eq!(
|
||||||
|
get_fee_for_message(&rpc_client, &blockhash, &[&message, &message]).unwrap(),
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1523,7 +1523,7 @@ pub fn request_and_confirm_airdrop(
|
||||||
to_pubkey: &Pubkey,
|
to_pubkey: &Pubkey,
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
) -> ClientResult<Signature> {
|
) -> ClientResult<Signature> {
|
||||||
let (recent_blockhash, _fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let recent_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
let signature =
|
let signature =
|
||||||
rpc_client.request_airdrop_with_blockhash(to_pubkey, lamports, &recent_blockhash)?;
|
rpc_client.request_airdrop_with_blockhash(to_pubkey, lamports, &recent_blockhash)?;
|
||||||
rpc_client.confirm_transaction_with_spinner(
|
rpc_client.confirm_transaction_with_spinner(
|
||||||
|
|
|
@ -142,9 +142,10 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
||||||
SubCommand::with_name("cluster-version")
|
SubCommand::with_name("cluster-version")
|
||||||
.about("Get the version of the cluster entrypoint"),
|
.about("Get the version of the cluster entrypoint"),
|
||||||
)
|
)
|
||||||
|
// Deprecated in v1.8.0
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("fees")
|
SubCommand::with_name("fees")
|
||||||
.about("Display current cluster fees")
|
.about("Display current cluster fees (Deprecated in v1.8.0)")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("blockhash")
|
Arg::with_name("blockhash")
|
||||||
.long("blockhash")
|
.long("blockhash")
|
||||||
|
@ -950,6 +951,7 @@ pub fn process_fees(
|
||||||
blockhash: Option<&Hash>,
|
blockhash: Option<&Hash>,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
let fees = if let Some(recent_blockhash) = blockhash {
|
let fees = if let Some(recent_blockhash) = blockhash {
|
||||||
|
#[allow(deprecated)]
|
||||||
let result = rpc_client.get_fee_calculator_for_blockhash_with_commitment(
|
let result = rpc_client.get_fee_calculator_for_blockhash_with_commitment(
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
|
@ -966,6 +968,7 @@ pub fn process_fees(
|
||||||
CliFees::none()
|
CliFees::none()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#[allow(deprecated)]
|
||||||
let result = rpc_client.get_fees_with_commitment(config.commitment)?;
|
let result = rpc_client.get_fees_with_commitment(config.commitment)?;
|
||||||
CliFees::some(
|
CliFees::some(
|
||||||
result.context.slot,
|
result.context.slot,
|
||||||
|
@ -1374,7 +1377,7 @@ pub fn process_ping(
|
||||||
let mut confirmed_count = 0;
|
let mut confirmed_count = 0;
|
||||||
let mut confirmation_time: VecDeque<u64> = VecDeque::with_capacity(1024);
|
let mut confirmation_time: VecDeque<u64> = VecDeque::with_capacity(1024);
|
||||||
|
|
||||||
let (mut blockhash, mut fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let mut blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
let mut blockhash_transaction_count = 0;
|
let mut blockhash_transaction_count = 0;
|
||||||
let mut blockhash_acquired = Instant::now();
|
let mut blockhash_acquired = Instant::now();
|
||||||
if let Some(fixed_blockhash) = fixed_blockhash {
|
if let Some(fixed_blockhash) = fixed_blockhash {
|
||||||
|
@ -1393,9 +1396,8 @@ pub fn process_ping(
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
if fixed_blockhash.is_none() && now.duration_since(blockhash_acquired).as_secs() > 60 {
|
if fixed_blockhash.is_none() && now.duration_since(blockhash_acquired).as_secs() > 60 {
|
||||||
// Fetch a new blockhash every minute
|
// Fetch a new blockhash every minute
|
||||||
let (new_blockhash, new_fee_calculator) = rpc_client.get_new_blockhash(&blockhash)?;
|
let new_blockhash = rpc_client.get_new_latest_blockhash(&blockhash)?;
|
||||||
blockhash = new_blockhash;
|
blockhash = new_blockhash;
|
||||||
fee_calculator = new_fee_calculator;
|
|
||||||
blockhash_transaction_count = 0;
|
blockhash_transaction_count = 0;
|
||||||
blockhash_acquired = Instant::now();
|
blockhash_acquired = Instant::now();
|
||||||
}
|
}
|
||||||
|
@ -1414,7 +1416,7 @@ pub fn process_ping(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
false,
|
false,
|
||||||
SpendAmount::Some(lamports),
|
SpendAmount::Some(lamports),
|
||||||
&fee_calculator,
|
&blockhash,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
build_message,
|
build_message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
|
|
|
@ -409,12 +409,12 @@ fn process_activate(
|
||||||
|
|
||||||
let rent = rpc_client.get_minimum_balance_for_rent_exemption(Feature::size_of())?;
|
let rent = rpc_client.get_minimum_balance_for_rent_exemption(Feature::size_of())?;
|
||||||
|
|
||||||
let (blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
let (message, _) = resolve_spend_tx_and_check_account_balance(
|
let (message, _) = resolve_spend_tx_and_check_account_balance(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
false,
|
false,
|
||||||
SpendAmount::Some(rent),
|
SpendAmount::Some(rent),
|
||||||
&fee_calculator,
|
&blockhash,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
|lamports| {
|
|lamports| {
|
||||||
Message::new(
|
Message::new(
|
||||||
|
|
|
@ -351,7 +351,7 @@ pub fn process_authorize_nonce_account(
|
||||||
memo: Option<&String>,
|
memo: Option<&String>,
|
||||||
new_authority: &Pubkey,
|
new_authority: &Pubkey,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let latest_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
|
|
||||||
let nonce_authority = config.signers[nonce_authority];
|
let nonce_authority = config.signers[nonce_authority];
|
||||||
let ixs = vec![authorize_nonce_account(
|
let ixs = vec![authorize_nonce_account(
|
||||||
|
@ -362,12 +362,12 @@ pub fn process_authorize_nonce_account(
|
||||||
.with_memo(memo);
|
.with_memo(memo);
|
||||||
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
||||||
let mut tx = Transaction::new_unsigned(message);
|
let mut tx = Transaction::new_unsigned(message);
|
||||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
tx.try_sign(&config.signers, latest_blockhash)?;
|
||||||
|
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
&fee_calculator,
|
&latest_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
@ -434,13 +434,13 @@ pub fn process_create_nonce_account(
|
||||||
Message::new(&ixs, Some(&config.signers[0].pubkey()))
|
Message::new(&ixs, Some(&config.signers[0].pubkey()))
|
||||||
};
|
};
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let latest_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
|
|
||||||
let (message, lamports) = resolve_spend_tx_and_check_account_balance(
|
let (message, lamports) = resolve_spend_tx_and_check_account_balance(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
false,
|
false,
|
||||||
amount,
|
amount,
|
||||||
&fee_calculator,
|
&latest_blockhash,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
build_message,
|
build_message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
|
@ -468,7 +468,7 @@ pub fn process_create_nonce_account(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut tx = Transaction::new_unsigned(message);
|
let mut tx = Transaction::new_unsigned(message);
|
||||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
tx.try_sign(&config.signers, latest_blockhash)?;
|
||||||
let merge_errors =
|
let merge_errors =
|
||||||
get_feature_is_active(rpc_client, &merge_nonce_error_into_system_error::id())?;
|
get_feature_is_active(rpc_client, &merge_nonce_error_into_system_error::id())?;
|
||||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
|
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
|
||||||
|
@ -544,14 +544,14 @@ pub fn process_new_nonce(
|
||||||
&nonce_authority.pubkey(),
|
&nonce_authority.pubkey(),
|
||||||
)]
|
)]
|
||||||
.with_memo(memo);
|
.with_memo(memo);
|
||||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let latest_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
||||||
let mut tx = Transaction::new_unsigned(message);
|
let mut tx = Transaction::new_unsigned(message);
|
||||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
tx.try_sign(&config.signers, latest_blockhash)?;
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
&fee_calculator,
|
&latest_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
@ -611,7 +611,7 @@ pub fn process_withdraw_from_nonce_account(
|
||||||
destination_account_pubkey: &Pubkey,
|
destination_account_pubkey: &Pubkey,
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let latest_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
|
|
||||||
let nonce_authority = config.signers[nonce_authority];
|
let nonce_authority = config.signers[nonce_authority];
|
||||||
let ixs = vec![withdraw_nonce_account(
|
let ixs = vec![withdraw_nonce_account(
|
||||||
|
@ -623,11 +623,11 @@ pub fn process_withdraw_from_nonce_account(
|
||||||
.with_memo(memo);
|
.with_memo(memo);
|
||||||
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
||||||
let mut tx = Transaction::new_unsigned(message);
|
let mut tx = Transaction::new_unsigned(message);
|
||||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
tx.try_sign(&config.signers, latest_blockhash)?;
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
&fee_calculator,
|
&latest_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -23,7 +23,6 @@ use solana_client::{
|
||||||
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
|
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
|
||||||
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
|
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
|
||||||
rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
|
rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
|
||||||
rpc_response::Fees,
|
|
||||||
tpu_client::{TpuClient, TpuClientConfig},
|
tpu_client::{TpuClient, TpuClientConfig},
|
||||||
};
|
};
|
||||||
use solana_rbpf::{
|
use solana_rbpf::{
|
||||||
|
@ -1067,7 +1066,7 @@ fn process_set_authority(
|
||||||
};
|
};
|
||||||
|
|
||||||
trace!("Set a new authority");
|
trace!("Set a new authority");
|
||||||
let (blockhash, _) = rpc_client.get_recent_blockhash()?;
|
let blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
|
|
||||||
let mut tx = if let Some(ref pubkey) = program_pubkey {
|
let mut tx = if let Some(ref pubkey) = program_pubkey {
|
||||||
Transaction::new_unsigned(Message::new(
|
Transaction::new_unsigned(Message::new(
|
||||||
|
@ -1343,7 +1342,7 @@ fn close(
|
||||||
recipient_pubkey: &Pubkey,
|
recipient_pubkey: &Pubkey,
|
||||||
authority_signer: &dyn Signer,
|
authority_signer: &dyn Signer,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (blockhash, _) = rpc_client.get_recent_blockhash()?;
|
let blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
|
|
||||||
let mut tx = Transaction::new_unsigned(Message::new(
|
let mut tx = Transaction::new_unsigned(Message::new(
|
||||||
&[bpf_loader_upgradeable::close(
|
&[bpf_loader_upgradeable::close(
|
||||||
|
@ -1891,14 +1890,14 @@ fn check_payer(
|
||||||
balance_needed: u64,
|
balance_needed: u64,
|
||||||
messages: &[&Message],
|
messages: &[&Message],
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (_, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
|
|
||||||
// Does the payer have enough?
|
// Does the payer have enough?
|
||||||
check_account_for_spend_multiple_fees_with_commitment(
|
check_account_for_spend_multiple_fees_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
balance_needed,
|
balance_needed,
|
||||||
&fee_calculator,
|
&blockhash,
|
||||||
messages,
|
messages,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
@ -1920,7 +1919,7 @@ fn send_deploy_messages(
|
||||||
if let Some(message) = initial_message {
|
if let Some(message) = initial_message {
|
||||||
if let Some(initial_signer) = initial_signer {
|
if let Some(initial_signer) = initial_signer {
|
||||||
trace!("Preparing the required accounts");
|
trace!("Preparing the required accounts");
|
||||||
let (blockhash, _) = rpc_client.get_recent_blockhash()?;
|
let blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
|
|
||||||
let mut initial_transaction = Transaction::new_unsigned(message.clone());
|
let mut initial_transaction = Transaction::new_unsigned(message.clone());
|
||||||
// Most of the initial_transaction combinations require both the fee-payer and new program
|
// Most of the initial_transaction combinations require both the fee-payer and new program
|
||||||
|
@ -1943,13 +1942,8 @@ fn send_deploy_messages(
|
||||||
if let Some(write_messages) = write_messages {
|
if let Some(write_messages) = write_messages {
|
||||||
if let Some(write_signer) = write_signer {
|
if let Some(write_signer) = write_signer {
|
||||||
trace!("Writing program data");
|
trace!("Writing program data");
|
||||||
let Fees {
|
let (blockhash, last_valid_block_height) =
|
||||||
blockhash,
|
rpc_client.get_latest_blockhash_with_commitment(config.commitment)?;
|
||||||
last_valid_block_height,
|
|
||||||
..
|
|
||||||
} = rpc_client
|
|
||||||
.get_fees_with_commitment(config.commitment)?
|
|
||||||
.value;
|
|
||||||
let mut write_transactions = vec![];
|
let mut write_transactions = vec![];
|
||||||
for message in write_messages.iter() {
|
for message in write_messages.iter() {
|
||||||
let mut tx = Transaction::new_unsigned(message.clone());
|
let mut tx = Transaction::new_unsigned(message.clone());
|
||||||
|
@ -1972,7 +1966,7 @@ fn send_deploy_messages(
|
||||||
if let Some(message) = final_message {
|
if let Some(message) = final_message {
|
||||||
if let Some(final_signers) = final_signers {
|
if let Some(final_signers) = final_signers {
|
||||||
trace!("Deploying program");
|
trace!("Deploying program");
|
||||||
let (blockhash, _) = rpc_client.get_recent_blockhash()?;
|
let blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
|
|
||||||
let mut final_tx = Transaction::new_unsigned(message.clone());
|
let mut final_tx = Transaction::new_unsigned(message.clone());
|
||||||
let mut signers = final_signers.to_vec();
|
let mut signers = final_signers.to_vec();
|
||||||
|
@ -2141,11 +2135,8 @@ fn send_and_confirm_transactions_with_spinner<T: Signers>(
|
||||||
send_retries -= 1;
|
send_retries -= 1;
|
||||||
|
|
||||||
// Re-sign any failed transactions with a new blockhash and retry
|
// Re-sign any failed transactions with a new blockhash and retry
|
||||||
let Fees {
|
let (blockhash, new_last_valid_block_height) =
|
||||||
blockhash,
|
rpc_client.get_latest_blockhash_with_commitment(commitment)?;
|
||||||
last_valid_block_height: new_last_valid_block_height,
|
|
||||||
..
|
|
||||||
} = rpc_client.get_fees_with_commitment(commitment)?.value;
|
|
||||||
last_valid_block_height = new_last_valid_block_height;
|
last_valid_block_height = new_last_valid_block_height;
|
||||||
transactions = vec![];
|
transactions = vec![];
|
||||||
for (_, mut transaction) in pending_transactions.into_iter() {
|
for (_, mut transaction) in pending_transactions.into_iter() {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
checks::{calculate_fee, check_account_for_balance_with_commitment},
|
checks::{check_account_for_balance_with_commitment, get_fee_for_message},
|
||||||
cli::CliError,
|
cli::CliError,
|
||||||
};
|
};
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use solana_clap_utils::{input_parsers::lamports_of_sol, offline::SIGN_ONLY_ARG};
|
use solana_clap_utils::{input_parsers::lamports_of_sol, offline::SIGN_ONLY_ARG};
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
commitment_config::CommitmentConfig, fee_calculator::FeeCalculator, message::Message,
|
commitment_config::CommitmentConfig, hash::Hash, message::Message,
|
||||||
native_token::lamports_to_sol, pubkey::Pubkey,
|
native_token::lamports_to_sol, pubkey::Pubkey,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ pub fn resolve_spend_tx_and_check_account_balance<F>(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
sign_only: bool,
|
sign_only: bool,
|
||||||
amount: SpendAmount,
|
amount: SpendAmount,
|
||||||
fee_calculator: &FeeCalculator,
|
blockhash: &Hash,
|
||||||
from_pubkey: &Pubkey,
|
from_pubkey: &Pubkey,
|
||||||
build_message: F,
|
build_message: F,
|
||||||
commitment: CommitmentConfig,
|
commitment: CommitmentConfig,
|
||||||
|
@ -59,7 +59,7 @@ where
|
||||||
rpc_client,
|
rpc_client,
|
||||||
sign_only,
|
sign_only,
|
||||||
amount,
|
amount,
|
||||||
fee_calculator,
|
blockhash,
|
||||||
from_pubkey,
|
from_pubkey,
|
||||||
from_pubkey,
|
from_pubkey,
|
||||||
build_message,
|
build_message,
|
||||||
|
@ -71,7 +71,7 @@ pub fn resolve_spend_tx_and_check_account_balances<F>(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
sign_only: bool,
|
sign_only: bool,
|
||||||
amount: SpendAmount,
|
amount: SpendAmount,
|
||||||
fee_calculator: &FeeCalculator,
|
blockhash: &Hash,
|
||||||
from_pubkey: &Pubkey,
|
from_pubkey: &Pubkey,
|
||||||
fee_pubkey: &Pubkey,
|
fee_pubkey: &Pubkey,
|
||||||
build_message: F,
|
build_message: F,
|
||||||
|
@ -82,26 +82,28 @@ where
|
||||||
{
|
{
|
||||||
if sign_only {
|
if sign_only {
|
||||||
let (message, SpendAndFee { spend, fee: _ }) = resolve_spend_message(
|
let (message, SpendAndFee { spend, fee: _ }) = resolve_spend_message(
|
||||||
|
rpc_client,
|
||||||
amount,
|
amount,
|
||||||
fee_calculator,
|
None,
|
||||||
0,
|
0,
|
||||||
from_pubkey,
|
from_pubkey,
|
||||||
fee_pubkey,
|
fee_pubkey,
|
||||||
build_message,
|
build_message,
|
||||||
);
|
)?;
|
||||||
Ok((message, spend))
|
Ok((message, spend))
|
||||||
} else {
|
} else {
|
||||||
let from_balance = rpc_client
|
let from_balance = rpc_client
|
||||||
.get_balance_with_commitment(from_pubkey, commitment)?
|
.get_balance_with_commitment(from_pubkey, commitment)?
|
||||||
.value;
|
.value;
|
||||||
let (message, SpendAndFee { spend, fee }) = resolve_spend_message(
|
let (message, SpendAndFee { spend, fee }) = resolve_spend_message(
|
||||||
|
rpc_client,
|
||||||
amount,
|
amount,
|
||||||
fee_calculator,
|
Some(blockhash),
|
||||||
from_balance,
|
from_balance,
|
||||||
from_pubkey,
|
from_pubkey,
|
||||||
fee_pubkey,
|
fee_pubkey,
|
||||||
build_message,
|
build_message,
|
||||||
);
|
)?;
|
||||||
if from_pubkey == fee_pubkey {
|
if from_pubkey == fee_pubkey {
|
||||||
if from_balance == 0 || from_balance < spend + fee {
|
if from_balance == 0 || from_balance < spend + fee {
|
||||||
return Err(CliError::InsufficientFundsForSpendAndFee(
|
return Err(CliError::InsufficientFundsForSpendAndFee(
|
||||||
|
@ -130,43 +132,46 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_spend_message<F>(
|
fn resolve_spend_message<F>(
|
||||||
|
rpc_client: &RpcClient,
|
||||||
amount: SpendAmount,
|
amount: SpendAmount,
|
||||||
fee_calculator: &FeeCalculator,
|
blockhash: Option<&Hash>,
|
||||||
from_balance: u64,
|
from_balance: u64,
|
||||||
from_pubkey: &Pubkey,
|
from_pubkey: &Pubkey,
|
||||||
fee_pubkey: &Pubkey,
|
fee_pubkey: &Pubkey,
|
||||||
build_message: F,
|
build_message: F,
|
||||||
) -> (Message, SpendAndFee)
|
) -> Result<(Message, SpendAndFee), CliError>
|
||||||
where
|
where
|
||||||
F: Fn(u64) -> Message,
|
F: Fn(u64) -> Message,
|
||||||
{
|
{
|
||||||
match amount {
|
let fee = match blockhash {
|
||||||
SpendAmount::Some(lamports) => {
|
Some(blockhash) => {
|
||||||
let message = build_message(lamports);
|
|
||||||
let fee = calculate_fee(fee_calculator, &[&message]);
|
|
||||||
(
|
|
||||||
message,
|
|
||||||
SpendAndFee {
|
|
||||||
spend: lamports,
|
|
||||||
fee,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
SpendAmount::All => {
|
|
||||||
let dummy_message = build_message(0);
|
let dummy_message = build_message(0);
|
||||||
let fee = calculate_fee(fee_calculator, &[&dummy_message]);
|
get_fee_for_message(rpc_client, blockhash, &[&dummy_message])?
|
||||||
|
}
|
||||||
|
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 {
|
let lamports = if from_pubkey == fee_pubkey {
|
||||||
from_balance.saturating_sub(fee)
|
from_balance.saturating_sub(fee)
|
||||||
} else {
|
} else {
|
||||||
from_balance
|
from_balance
|
||||||
};
|
};
|
||||||
(
|
Ok((
|
||||||
build_message(lamports),
|
build_message(lamports),
|
||||||
SpendAndFee {
|
SpendAndFee {
|
||||||
spend: lamports,
|
spend: lamports,
|
||||||
fee,
|
fee,
|
||||||
},
|
},
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1272,14 +1272,13 @@ pub fn process_create_stake_account(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) =
|
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
|
||||||
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
|
|
||||||
|
|
||||||
let (message, lamports) = resolve_spend_tx_and_check_account_balances(
|
let (message, lamports) = resolve_spend_tx_and_check_account_balances(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
sign_only,
|
sign_only,
|
||||||
amount,
|
amount,
|
||||||
&fee_calculator,
|
&recent_blockhash,
|
||||||
&from.pubkey(),
|
&from.pubkey(),
|
||||||
&fee_payer.pubkey(),
|
&fee_payer.pubkey(),
|
||||||
build_message,
|
build_message,
|
||||||
|
@ -1387,8 +1386,7 @@ pub fn process_stake_authorize(
|
||||||
}
|
}
|
||||||
ixs = ixs.with_memo(memo);
|
ixs = ixs.with_memo(memo);
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) =
|
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
|
||||||
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
|
|
||||||
|
|
||||||
let nonce_authority = config.signers[nonce_authority];
|
let nonce_authority = config.signers[nonce_authority];
|
||||||
let fee_payer = config.signers[fee_payer];
|
let fee_payer = config.signers[fee_payer];
|
||||||
|
@ -1427,7 +1425,7 @@ pub fn process_stake_authorize(
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&tx.message.account_keys[0],
|
&tx.message.account_keys[0],
|
||||||
&fee_calculator,
|
&recent_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
@ -1455,8 +1453,7 @@ pub fn process_deactivate_stake_account(
|
||||||
seed: Option<&String>,
|
seed: Option<&String>,
|
||||||
fee_payer: SignerIndex,
|
fee_payer: SignerIndex,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
let (recent_blockhash, fee_calculator) =
|
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
|
||||||
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
|
|
||||||
let stake_authority = config.signers[stake_authority];
|
let stake_authority = config.signers[stake_authority];
|
||||||
|
|
||||||
let stake_account_address = if let Some(seed) = seed {
|
let stake_account_address = if let Some(seed) = seed {
|
||||||
|
@ -1507,7 +1504,7 @@ pub fn process_deactivate_stake_account(
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&tx.message.account_keys[0],
|
&tx.message.account_keys[0],
|
||||||
&fee_calculator,
|
&recent_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
@ -1543,8 +1540,7 @@ pub fn process_withdraw_stake(
|
||||||
*stake_account_pubkey
|
*stake_account_pubkey
|
||||||
};
|
};
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) =
|
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
|
||||||
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
|
|
||||||
|
|
||||||
let fee_payer = config.signers[fee_payer];
|
let fee_payer = config.signers[fee_payer];
|
||||||
let nonce_authority = config.signers[nonce_authority];
|
let nonce_authority = config.signers[nonce_authority];
|
||||||
|
@ -1575,7 +1571,7 @@ pub fn process_withdraw_stake(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
sign_only,
|
sign_only,
|
||||||
amount,
|
amount,
|
||||||
&fee_calculator,
|
&recent_blockhash,
|
||||||
&stake_account_address,
|
&stake_account_address,
|
||||||
&fee_payer.pubkey(),
|
&fee_payer.pubkey(),
|
||||||
build_message,
|
build_message,
|
||||||
|
@ -1606,7 +1602,7 @@ pub fn process_withdraw_stake(
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&tx.message.account_keys[0],
|
&tx.message.account_keys[0],
|
||||||
&fee_calculator,
|
&recent_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
@ -1692,8 +1688,7 @@ pub fn process_split_stake(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) =
|
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
|
||||||
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
|
|
||||||
|
|
||||||
let ixs = if let Some(seed) = split_stake_account_seed {
|
let ixs = if let Some(seed) = split_stake_account_seed {
|
||||||
stake_instruction::split_with_seed(
|
stake_instruction::split_with_seed(
|
||||||
|
@ -1751,7 +1746,7 @@ pub fn process_split_stake(
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&tx.message.account_keys[0],
|
&tx.message.account_keys[0],
|
||||||
&fee_calculator,
|
&recent_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
@ -1812,8 +1807,7 @@ pub fn process_merge_stake(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) =
|
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
|
||||||
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
|
|
||||||
|
|
||||||
let ixs = stake_instruction::merge(
|
let ixs = stake_instruction::merge(
|
||||||
stake_account_pubkey,
|
stake_account_pubkey,
|
||||||
|
@ -1858,7 +1852,7 @@ pub fn process_merge_stake(
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&tx.message.account_keys[0],
|
&tx.message.account_keys[0],
|
||||||
&fee_calculator,
|
&recent_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
@ -1887,8 +1881,7 @@ pub fn process_stake_set_lockup(
|
||||||
memo: Option<&String>,
|
memo: Option<&String>,
|
||||||
fee_payer: SignerIndex,
|
fee_payer: SignerIndex,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
let (recent_blockhash, fee_calculator) =
|
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
|
||||||
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
|
|
||||||
let custodian = config.signers[custodian];
|
let custodian = config.signers[custodian];
|
||||||
|
|
||||||
let ixs = vec![if new_custodian_signer.is_some() {
|
let ixs = vec![if new_custodian_signer.is_some() {
|
||||||
|
@ -1934,7 +1927,7 @@ pub fn process_stake_set_lockup(
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&tx.message.account_keys[0],
|
&tx.message.account_keys[0],
|
||||||
&fee_calculator,
|
&recent_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
@ -2291,8 +2284,7 @@ pub fn process_delegate_stake(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) =
|
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
|
||||||
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
|
|
||||||
|
|
||||||
let ixs = vec![stake_instruction::delegate_stake(
|
let ixs = vec![stake_instruction::delegate_stake(
|
||||||
stake_account_pubkey,
|
stake_account_pubkey,
|
||||||
|
@ -2337,7 +2329,7 @@ pub fn process_delegate_stake(
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&tx.message.account_keys[0],
|
&tx.message.account_keys[0],
|
||||||
&fee_calculator,
|
&recent_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -345,18 +345,18 @@ pub fn process_set_validator_info(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Submit transaction
|
// Submit transaction
|
||||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let latest_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
let (message, _) = resolve_spend_tx_and_check_account_balance(
|
let (message, _) = resolve_spend_tx_and_check_account_balance(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
false,
|
false,
|
||||||
SpendAmount::Some(lamports),
|
SpendAmount::Some(lamports),
|
||||||
&fee_calculator,
|
&latest_blockhash,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
build_message,
|
build_message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
let mut tx = Transaction::new_unsigned(message);
|
let mut tx = Transaction::new_unsigned(message);
|
||||||
tx.try_sign(&signers, recent_blockhash)?;
|
tx.try_sign(&signers, latest_blockhash)?;
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction_with_spinner(&tx)?;
|
let signature_str = rpc_client.send_and_confirm_transaction_with_spinner(&tx)?;
|
||||||
|
|
||||||
println!("Success! Validator info published at: {:?}", info_pubkey);
|
println!("Success! Validator info published at: {:?}", info_pubkey);
|
||||||
|
|
|
@ -605,19 +605,19 @@ pub fn process_create_vote_account(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let latest_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
|
|
||||||
let (message, _) = resolve_spend_tx_and_check_account_balance(
|
let (message, _) = resolve_spend_tx_and_check_account_balance(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
false,
|
false,
|
||||||
amount,
|
amount,
|
||||||
&fee_calculator,
|
&latest_blockhash,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
build_message,
|
build_message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
let mut tx = Transaction::new_unsigned(message);
|
let mut tx = Transaction::new_unsigned(message);
|
||||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
tx.try_sign(&config.signers, latest_blockhash)?;
|
||||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
|
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
|
||||||
log_instruction_custom_error::<SystemError>(result, config)
|
log_instruction_custom_error::<SystemError>(result, config)
|
||||||
}
|
}
|
||||||
|
@ -639,7 +639,7 @@ pub fn process_vote_authorize(
|
||||||
(&authorized.pubkey(), "authorized_account".to_string()),
|
(&authorized.pubkey(), "authorized_account".to_string()),
|
||||||
(new_authorized_pubkey, "new_authorized_pubkey".to_string()),
|
(new_authorized_pubkey, "new_authorized_pubkey".to_string()),
|
||||||
)?;
|
)?;
|
||||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let latest_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
let vote_ix = if new_authorized_signer.is_some() {
|
let vote_ix = if new_authorized_signer.is_some() {
|
||||||
vote_instruction::authorize_checked(
|
vote_instruction::authorize_checked(
|
||||||
vote_account_pubkey, // vote account to update
|
vote_account_pubkey, // vote account to update
|
||||||
|
@ -659,11 +659,11 @@ pub fn process_vote_authorize(
|
||||||
|
|
||||||
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
||||||
let mut tx = Transaction::new_unsigned(message);
|
let mut tx = Transaction::new_unsigned(message);
|
||||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
tx.try_sign(&config.signers, latest_blockhash)?;
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
&fee_calculator,
|
&latest_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
@ -686,7 +686,7 @@ pub fn process_vote_update_validator(
|
||||||
(vote_account_pubkey, "vote_account_pubkey".to_string()),
|
(vote_account_pubkey, "vote_account_pubkey".to_string()),
|
||||||
(&new_identity_pubkey, "new_identity_account".to_string()),
|
(&new_identity_pubkey, "new_identity_account".to_string()),
|
||||||
)?;
|
)?;
|
||||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let latest_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
let ixs = vec![vote_instruction::update_validator_identity(
|
let ixs = vec![vote_instruction::update_validator_identity(
|
||||||
vote_account_pubkey,
|
vote_account_pubkey,
|
||||||
&authorized_withdrawer.pubkey(),
|
&authorized_withdrawer.pubkey(),
|
||||||
|
@ -696,11 +696,11 @@ pub fn process_vote_update_validator(
|
||||||
|
|
||||||
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
||||||
let mut tx = Transaction::new_unsigned(message);
|
let mut tx = Transaction::new_unsigned(message);
|
||||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
tx.try_sign(&config.signers, latest_blockhash)?;
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
&fee_calculator,
|
&latest_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
@ -717,7 +717,7 @@ pub fn process_vote_update_commission(
|
||||||
memo: Option<&String>,
|
memo: Option<&String>,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
let authorized_withdrawer = config.signers[withdraw_authority];
|
let authorized_withdrawer = config.signers[withdraw_authority];
|
||||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let latest_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
let ixs = vec![vote_instruction::update_commission(
|
let ixs = vec![vote_instruction::update_commission(
|
||||||
vote_account_pubkey,
|
vote_account_pubkey,
|
||||||
&authorized_withdrawer.pubkey(),
|
&authorized_withdrawer.pubkey(),
|
||||||
|
@ -727,11 +727,11 @@ pub fn process_vote_update_commission(
|
||||||
|
|
||||||
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
||||||
let mut tx = Transaction::new_unsigned(message);
|
let mut tx = Transaction::new_unsigned(message);
|
||||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
tx.try_sign(&config.signers, latest_blockhash)?;
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
&fee_calculator,
|
&latest_blockhash,
|
||||||
&tx.message,
|
&tx.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
@ -836,7 +836,7 @@ pub fn process_withdraw_from_vote_account(
|
||||||
destination_account_pubkey: &Pubkey,
|
destination_account_pubkey: &Pubkey,
|
||||||
memo: Option<&String>,
|
memo: Option<&String>,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let latest_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
let withdraw_authority = config.signers[withdraw_authority];
|
let withdraw_authority = config.signers[withdraw_authority];
|
||||||
|
|
||||||
let current_balance = rpc_client.get_balance(vote_account_pubkey)?;
|
let current_balance = rpc_client.get_balance(vote_account_pubkey)?;
|
||||||
|
@ -865,11 +865,11 @@ pub fn process_withdraw_from_vote_account(
|
||||||
|
|
||||||
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
|
||||||
let mut transaction = Transaction::new_unsigned(message);
|
let mut transaction = Transaction::new_unsigned(message);
|
||||||
transaction.try_sign(&config.signers, recent_blockhash)?;
|
transaction.try_sign(&config.signers, latest_blockhash)?;
|
||||||
check_account_for_fee_with_commitment(
|
check_account_for_fee_with_commitment(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
&config.signers[0].pubkey(),
|
&config.signers[0].pubkey(),
|
||||||
&fee_calculator,
|
&latest_blockhash,
|
||||||
&transaction.message,
|
&transaction.message,
|
||||||
config.commitment,
|
config.commitment,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -645,8 +645,7 @@ pub fn process_transfer(
|
||||||
let from = config.signers[from];
|
let from = config.signers[from];
|
||||||
let mut from_pubkey = from.pubkey();
|
let mut from_pubkey = from.pubkey();
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) =
|
let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?;
|
||||||
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
|
|
||||||
|
|
||||||
if !sign_only && !allow_unfunded_recipient {
|
if !sign_only && !allow_unfunded_recipient {
|
||||||
let recipient_balance = rpc_client
|
let recipient_balance = rpc_client
|
||||||
|
@ -706,7 +705,7 @@ pub fn process_transfer(
|
||||||
rpc_client,
|
rpc_client,
|
||||||
sign_only,
|
sign_only,
|
||||||
amount,
|
amount,
|
||||||
&fee_calculator,
|
&recent_blockhash,
|
||||||
&from_pubkey,
|
&from_pubkey,
|
||||||
&fee_payer.pubkey(),
|
&fee_payer.pubkey(),
|
||||||
build_message,
|
build_message,
|
||||||
|
|
|
@ -356,7 +356,7 @@ fn test_offline_stake_delegation_and_deactivation() {
|
||||||
process_command(&config_validator).unwrap();
|
process_command(&config_validator).unwrap();
|
||||||
|
|
||||||
// Delegate stake offline
|
// Delegate stake offline
|
||||||
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
|
let blockhash = rpc_client.get_latest_blockhash().unwrap();
|
||||||
config_offline.command = CliCommand::DelegateStake {
|
config_offline.command = CliCommand::DelegateStake {
|
||||||
stake_account_pubkey: stake_keypair.pubkey(),
|
stake_account_pubkey: stake_keypair.pubkey(),
|
||||||
vote_account_pubkey: test_validator.vote_account_address(),
|
vote_account_pubkey: test_validator.vote_account_address(),
|
||||||
|
@ -394,7 +394,7 @@ fn test_offline_stake_delegation_and_deactivation() {
|
||||||
process_command(&config_payer).unwrap();
|
process_command(&config_payer).unwrap();
|
||||||
|
|
||||||
// Deactivate stake offline
|
// Deactivate stake offline
|
||||||
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
|
let blockhash = rpc_client.get_latest_blockhash().unwrap();
|
||||||
config_offline.command = CliCommand::DeactivateStake {
|
config_offline.command = CliCommand::DeactivateStake {
|
||||||
stake_account_pubkey: stake_keypair.pubkey(),
|
stake_account_pubkey: stake_keypair.pubkey(),
|
||||||
stake_authority: 0,
|
stake_authority: 0,
|
||||||
|
@ -714,7 +714,7 @@ fn test_stake_authorize() {
|
||||||
// Offline assignment of new nonced stake authority
|
// Offline assignment of new nonced stake authority
|
||||||
let nonced_authority = Keypair::new();
|
let nonced_authority = Keypair::new();
|
||||||
let nonced_authority_pubkey = nonced_authority.pubkey();
|
let nonced_authority_pubkey = nonced_authority.pubkey();
|
||||||
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
|
let blockhash = rpc_client.get_latest_blockhash().unwrap();
|
||||||
config_offline.command = CliCommand::StakeAuthorize {
|
config_offline.command = CliCommand::StakeAuthorize {
|
||||||
stake_account_pubkey,
|
stake_account_pubkey,
|
||||||
new_authorizations: vec![StakeAuthorizationIndexed {
|
new_authorizations: vec![StakeAuthorizationIndexed {
|
||||||
|
@ -964,7 +964,7 @@ fn test_stake_authorize_with_fee_payer() {
|
||||||
check_recent_balance(100_000 - SIG_FEE - SIG_FEE, &rpc_client, &payer_pubkey);
|
check_recent_balance(100_000 - SIG_FEE - SIG_FEE, &rpc_client, &payer_pubkey);
|
||||||
|
|
||||||
// Assign authority with offline fee payer
|
// Assign authority with offline fee payer
|
||||||
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
|
let blockhash = rpc_client.get_latest_blockhash().unwrap();
|
||||||
config_offline.command = CliCommand::StakeAuthorize {
|
config_offline.command = CliCommand::StakeAuthorize {
|
||||||
stake_account_pubkey,
|
stake_account_pubkey,
|
||||||
new_authorizations: vec![StakeAuthorizationIndexed {
|
new_authorizations: vec![StakeAuthorizationIndexed {
|
||||||
|
|
|
@ -106,7 +106,7 @@ fn test_transfer() {
|
||||||
check_recent_balance(50, &rpc_client, &offline_pubkey);
|
check_recent_balance(50, &rpc_client, &offline_pubkey);
|
||||||
|
|
||||||
// Offline transfer
|
// Offline transfer
|
||||||
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
|
let blockhash = rpc_client.get_latest_blockhash().unwrap();
|
||||||
offline.command = CliCommand::Transfer {
|
offline.command = CliCommand::Transfer {
|
||||||
amount: SpendAmount::Some(10),
|
amount: SpendAmount::Some(10),
|
||||||
to: recipient_pubkey,
|
to: recipient_pubkey,
|
||||||
|
@ -318,7 +318,7 @@ fn test_transfer_multisession_signing() {
|
||||||
|
|
||||||
check_ready(&rpc_client);
|
check_ready(&rpc_client);
|
||||||
|
|
||||||
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
|
let blockhash = rpc_client.get_latest_blockhash().unwrap();
|
||||||
|
|
||||||
// Offline fee-payer signs first
|
// Offline fee-payer signs first
|
||||||
let mut fee_payer_config = CliConfig::recent_for_tests();
|
let mut fee_payer_config = CliConfig::recent_for_tests();
|
||||||
|
|
|
@ -19,6 +19,7 @@ pub enum Source {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Source {
|
impl Source {
|
||||||
|
#[deprecated(since = "1.8.0", note = "Please use `get_blockhash` instead")]
|
||||||
pub fn get_blockhash_and_fee_calculator(
|
pub fn get_blockhash_and_fee_calculator(
|
||||||
&self,
|
&self,
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
|
@ -26,6 +27,7 @@ impl Source {
|
||||||
) -> Result<(Hash, FeeCalculator), Box<dyn std::error::Error>> {
|
) -> Result<(Hash, FeeCalculator), Box<dyn std::error::Error>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Cluster => {
|
Self::Cluster => {
|
||||||
|
#[allow(deprecated)]
|
||||||
let res = rpc_client
|
let res = rpc_client
|
||||||
.get_recent_blockhash_with_commitment(commitment)?
|
.get_recent_blockhash_with_commitment(commitment)?
|
||||||
.value;
|
.value;
|
||||||
|
@ -39,6 +41,10 @@ impl Source {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please do not use, will no longer be available in the future"
|
||||||
|
)]
|
||||||
pub fn get_fee_calculator(
|
pub fn get_fee_calculator(
|
||||||
&self,
|
&self,
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
|
@ -47,6 +53,7 @@ impl Source {
|
||||||
) -> Result<Option<FeeCalculator>, Box<dyn std::error::Error>> {
|
) -> Result<Option<FeeCalculator>, Box<dyn std::error::Error>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Cluster => {
|
Self::Cluster => {
|
||||||
|
#[allow(deprecated)]
|
||||||
let res = rpc_client
|
let res = rpc_client
|
||||||
.get_fee_calculator_for_blockhash_with_commitment(blockhash, commitment)?
|
.get_fee_calculator_for_blockhash_with_commitment(blockhash, commitment)?
|
||||||
.value;
|
.value;
|
||||||
|
@ -61,6 +68,40 @@ impl Source {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_blockhash(
|
||||||
|
&self,
|
||||||
|
rpc_client: &RpcClient,
|
||||||
|
commitment: CommitmentConfig,
|
||||||
|
) -> Result<Hash, Box<dyn std::error::Error>> {
|
||||||
|
match self {
|
||||||
|
Self::Cluster => {
|
||||||
|
let (blockhash, _) = rpc_client.get_latest_blockhash_with_commitment(commitment)?;
|
||||||
|
Ok(blockhash)
|
||||||
|
}
|
||||||
|
Self::NonceAccount(ref pubkey) => {
|
||||||
|
let data = nonce_utils::get_account_with_commitment(rpc_client, pubkey, commitment)
|
||||||
|
.and_then(|ref a| nonce_utils::data_from_account(a))?;
|
||||||
|
Ok(data.blockhash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_blockhash_valid(
|
||||||
|
&self,
|
||||||
|
rpc_client: &RpcClient,
|
||||||
|
blockhash: &Hash,
|
||||||
|
commitment: CommitmentConfig,
|
||||||
|
) -> Result<bool, Box<dyn std::error::Error>> {
|
||||||
|
Ok(match self {
|
||||||
|
Self::Cluster => rpc_client.is_blockhash_valid(blockhash, commitment)?,
|
||||||
|
Self::NonceAccount(ref pubkey) => {
|
||||||
|
let _ = nonce_utils::get_account_with_commitment(rpc_client, pubkey, commitment)
|
||||||
|
.and_then(|ref a| nonce_utils::data_from_account(a))?;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
|
@ -90,6 +131,7 @@ impl BlockhashQuery {
|
||||||
BlockhashQuery::new(blockhash, sign_only, nonce_account)
|
BlockhashQuery::new(blockhash, sign_only, nonce_account)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.8.0", note = "Please use `get_blockhash` instead")]
|
||||||
pub fn get_blockhash_and_fee_calculator(
|
pub fn get_blockhash_and_fee_calculator(
|
||||||
&self,
|
&self,
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
|
@ -98,16 +140,36 @@ impl BlockhashQuery {
|
||||||
match self {
|
match self {
|
||||||
BlockhashQuery::None(hash) => Ok((*hash, FeeCalculator::default())),
|
BlockhashQuery::None(hash) => Ok((*hash, FeeCalculator::default())),
|
||||||
BlockhashQuery::FeeCalculator(source, hash) => {
|
BlockhashQuery::FeeCalculator(source, hash) => {
|
||||||
|
#[allow(deprecated)]
|
||||||
let fee_calculator = source
|
let fee_calculator = source
|
||||||
.get_fee_calculator(rpc_client, hash, commitment)?
|
.get_fee_calculator(rpc_client, hash, commitment)?
|
||||||
.ok_or(format!("Hash has expired {:?}", hash))?;
|
.ok_or(format!("Hash has expired {:?}", hash))?;
|
||||||
Ok((*hash, fee_calculator))
|
Ok((*hash, fee_calculator))
|
||||||
}
|
}
|
||||||
BlockhashQuery::All(source) => {
|
BlockhashQuery::All(source) =>
|
||||||
|
{
|
||||||
|
#[allow(deprecated)]
|
||||||
source.get_blockhash_and_fee_calculator(rpc_client, commitment)
|
source.get_blockhash_and_fee_calculator(rpc_client, commitment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_blockhash(
|
||||||
|
&self,
|
||||||
|
rpc_client: &RpcClient,
|
||||||
|
commitment: CommitmentConfig,
|
||||||
|
) -> Result<Hash, Box<dyn std::error::Error>> {
|
||||||
|
match self {
|
||||||
|
BlockhashQuery::None(hash) => Ok(*hash),
|
||||||
|
BlockhashQuery::FeeCalculator(source, hash) => {
|
||||||
|
if !source.is_blockhash_valid(rpc_client, hash, commitment)? {
|
||||||
|
return Err(format!("Hash has expired {:?}", hash).into());
|
||||||
|
}
|
||||||
|
Ok(*hash)
|
||||||
|
}
|
||||||
|
BlockhashQuery::All(source) => source.get_blockhash(rpc_client, commitment),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BlockhashQuery {
|
impl Default for BlockhashQuery {
|
||||||
|
@ -282,6 +344,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(deprecated)]
|
||||||
fn test_blockhash_query_get_blockhash_fee_calc() {
|
fn test_blockhash_query_get_blockhash_fee_calc() {
|
||||||
let test_blockhash = hash(&[0u8]);
|
let test_blockhash = hash(&[0u8]);
|
||||||
let rpc_blockhash = hash(&[1u8]);
|
let rpc_blockhash = hash(&[1u8]);
|
||||||
|
|
|
@ -6,9 +6,9 @@ use {
|
||||||
rpc_config::RpcBlockProductionConfig,
|
rpc_config::RpcBlockProductionConfig,
|
||||||
rpc_request::RpcRequest,
|
rpc_request::RpcRequest,
|
||||||
rpc_response::{
|
rpc_response::{
|
||||||
Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange, RpcFees,
|
Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange, RpcBlockhash,
|
||||||
RpcResponseContext, RpcSimulateTransactionResult, RpcStakeActivation, RpcSupply,
|
RpcFees, RpcResponseContext, RpcSimulateTransactionResult, RpcStakeActivation,
|
||||||
RpcVersionInfo, RpcVoteAccountStatus, StakeActivationState,
|
RpcSupply, RpcVersionInfo, RpcVoteAccountStatus, StakeActivationState,
|
||||||
},
|
},
|
||||||
rpc_sender::RpcSender,
|
rpc_sender::RpcSender,
|
||||||
},
|
},
|
||||||
|
@ -271,6 +271,17 @@ impl RpcSender for MockSender {
|
||||||
feature_set: Some(version.feature_set),
|
feature_set: Some(version.feature_set),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
"getLatestBlockhash" => serde_json::to_value(Response {
|
||||||
|
context: RpcResponseContext { slot: 1 },
|
||||||
|
value: RpcBlockhash {
|
||||||
|
blockhash: PUBKEY.to_string(),
|
||||||
|
last_valid_block_height: 0,
|
||||||
|
},
|
||||||
|
})?,
|
||||||
|
"getFeeForMessage" => serde_json::to_value(Response {
|
||||||
|
context: RpcResponseContext { slot: 1 },
|
||||||
|
value: json!(Some(0)),
|
||||||
|
})?,
|
||||||
_ => Value::Null,
|
_ => Value::Null,
|
||||||
};
|
};
|
||||||
Ok(val)
|
Ok(val)
|
||||||
|
|
|
@ -38,6 +38,7 @@ use {
|
||||||
epoch_schedule::EpochSchedule,
|
epoch_schedule::EpochSchedule,
|
||||||
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
|
message::Message,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::Signature,
|
signature::Signature,
|
||||||
transaction::{self, uses_durable_nonce, Transaction},
|
transaction::{self, uses_durable_nonce, Transaction},
|
||||||
|
@ -722,7 +723,7 @@ impl RpcClient {
|
||||||
preflight_commitment: Some(preflight_commitment.commitment),
|
preflight_commitment: Some(preflight_commitment.commitment),
|
||||||
..config
|
..config
|
||||||
};
|
};
|
||||||
let serialized_encoded = serialize_encode_transaction(transaction, encoding)?;
|
let serialized_encoded = serialize_and_encode::<Transaction>(transaction, encoding)?;
|
||||||
let signature_base58_str: String = match self.send(
|
let signature_base58_str: String = match self.send(
|
||||||
RpcRequest::SendTransaction,
|
RpcRequest::SendTransaction,
|
||||||
json!([serialized_encoded, config]),
|
json!([serialized_encoded, config]),
|
||||||
|
@ -859,7 +860,7 @@ impl RpcClient {
|
||||||
commitment: Some(commitment),
|
commitment: Some(commitment),
|
||||||
..config
|
..config
|
||||||
};
|
};
|
||||||
let serialized_encoded = serialize_encode_transaction(transaction, encoding)?;
|
let serialized_encoded = serialize_and_encode::<Transaction>(transaction, encoding)?;
|
||||||
self.send(
|
self.send(
|
||||||
RpcRequest::SimulateTransaction,
|
RpcRequest::SimulateTransaction,
|
||||||
json!([serialized_encoded, config]),
|
json!([serialized_encoded, config]),
|
||||||
|
@ -1981,9 +1982,8 @@ impl RpcClient {
|
||||||
let signature = self.send_transaction(transaction)?;
|
let signature = self.send_transaction(transaction)?;
|
||||||
|
|
||||||
let recent_blockhash = if uses_durable_nonce(transaction).is_some() {
|
let recent_blockhash = if uses_durable_nonce(transaction).is_some() {
|
||||||
let (recent_blockhash, ..) = self
|
let (recent_blockhash, ..) =
|
||||||
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())?
|
self.get_latest_blockhash_with_commitment(CommitmentConfig::processed())?;
|
||||||
.value;
|
|
||||||
recent_blockhash
|
recent_blockhash
|
||||||
} else {
|
} else {
|
||||||
transaction.message.recent_blockhash
|
transaction.message.recent_blockhash
|
||||||
|
@ -1994,13 +1994,9 @@ impl RpcClient {
|
||||||
Some(Ok(_)) => return Ok(signature),
|
Some(Ok(_)) => return Ok(signature),
|
||||||
Some(Err(e)) => return Err(e.into()),
|
Some(Err(e)) => return Err(e.into()),
|
||||||
None => {
|
None => {
|
||||||
let fee_calculator = self
|
if !self
|
||||||
.get_fee_calculator_for_blockhash_with_commitment(
|
.is_blockhash_valid(&recent_blockhash, CommitmentConfig::processed())?
|
||||||
&recent_blockhash,
|
{
|
||||||
CommitmentConfig::processed(),
|
|
||||||
)?
|
|
||||||
.value;
|
|
||||||
if fee_calculator.is_none() {
|
|
||||||
// Block hash is not found by some reason
|
// Block hash is not found by some reason
|
||||||
break 'sending;
|
break 'sending;
|
||||||
} else if cfg!(not(test))
|
} else if cfg!(not(test))
|
||||||
|
@ -2209,10 +2205,21 @@ impl RpcClient {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please use `get_latest_blockhash` and `get_fee_for_message` instead"
|
||||||
|
)]
|
||||||
|
#[allow(deprecated)]
|
||||||
pub fn get_fees(&self) -> ClientResult<Fees> {
|
pub fn get_fees(&self) -> ClientResult<Fees> {
|
||||||
|
#[allow(deprecated)]
|
||||||
Ok(self.get_fees_with_commitment(self.commitment())?.value)
|
Ok(self.get_fees_with_commitment(self.commitment())?.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please use `get_latest_blockhash_with_commitment` and `get_fee_for_message` instead"
|
||||||
|
)]
|
||||||
|
#[allow(deprecated)]
|
||||||
pub fn get_fees_with_commitment(&self, commitment_config: CommitmentConfig) -> RpcResult<Fees> {
|
pub fn get_fees_with_commitment(&self, commitment_config: CommitmentConfig) -> RpcResult<Fees> {
|
||||||
let Response {
|
let Response {
|
||||||
context,
|
context,
|
||||||
|
@ -2237,13 +2244,21 @@ impl RpcClient {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.8.0", note = "Please use `get_latest_blockhash` instead")]
|
||||||
|
#[allow(deprecated)]
|
||||||
pub fn get_recent_blockhash(&self) -> ClientResult<(Hash, FeeCalculator)> {
|
pub fn get_recent_blockhash(&self) -> ClientResult<(Hash, FeeCalculator)> {
|
||||||
|
#[allow(deprecated)]
|
||||||
let (blockhash, fee_calculator, _last_valid_slot) = self
|
let (blockhash, fee_calculator, _last_valid_slot) = self
|
||||||
.get_recent_blockhash_with_commitment(self.commitment())?
|
.get_recent_blockhash_with_commitment(self.commitment())?
|
||||||
.value;
|
.value;
|
||||||
Ok((blockhash, fee_calculator))
|
Ok((blockhash, fee_calculator))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please use `get_latest_blockhash_with_commitment` instead"
|
||||||
|
)]
|
||||||
|
#[allow(deprecated)]
|
||||||
pub fn get_recent_blockhash_with_commitment(
|
pub fn get_recent_blockhash_with_commitment(
|
||||||
&self,
|
&self,
|
||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
|
@ -2307,15 +2322,23 @@ impl RpcClient {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.8.0", note = "Please `get_fee_for_message` instead")]
|
||||||
|
#[allow(deprecated)]
|
||||||
pub fn get_fee_calculator_for_blockhash(
|
pub fn get_fee_calculator_for_blockhash(
|
||||||
&self,
|
&self,
|
||||||
blockhash: &Hash,
|
blockhash: &Hash,
|
||||||
) -> ClientResult<Option<FeeCalculator>> {
|
) -> ClientResult<Option<FeeCalculator>> {
|
||||||
|
#[allow(deprecated)]
|
||||||
Ok(self
|
Ok(self
|
||||||
.get_fee_calculator_for_blockhash_with_commitment(blockhash, self.commitment())?
|
.get_fee_calculator_for_blockhash_with_commitment(blockhash, self.commitment())?
|
||||||
.value)
|
.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please `get_latest_blockhash_with_commitment` and `get_fee_for_message` instead"
|
||||||
|
)]
|
||||||
|
#[allow(deprecated)]
|
||||||
pub fn get_fee_calculator_for_blockhash_with_commitment(
|
pub fn get_fee_calculator_for_blockhash_with_commitment(
|
||||||
&self,
|
&self,
|
||||||
blockhash: &Hash,
|
blockhash: &Hash,
|
||||||
|
@ -2335,6 +2358,11 @@ impl RpcClient {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please do not use, will no longer be available in the future"
|
||||||
|
)]
|
||||||
|
#[allow(deprecated)]
|
||||||
pub fn get_fee_rate_governor(&self) -> RpcResult<FeeRateGovernor> {
|
pub fn get_fee_rate_governor(&self) -> RpcResult<FeeRateGovernor> {
|
||||||
let Response {
|
let Response {
|
||||||
context,
|
context,
|
||||||
|
@ -2348,10 +2376,16 @@ impl RpcClient {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please use `get_new_latest_blockhash` instead"
|
||||||
|
)]
|
||||||
|
#[allow(deprecated)]
|
||||||
pub fn get_new_blockhash(&self, blockhash: &Hash) -> ClientResult<(Hash, FeeCalculator)> {
|
pub fn get_new_blockhash(&self, blockhash: &Hash) -> ClientResult<(Hash, FeeCalculator)> {
|
||||||
let mut num_retries = 0;
|
let mut num_retries = 0;
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
while start.elapsed().as_secs() < 5 {
|
while start.elapsed().as_secs() < 5 {
|
||||||
|
#[allow(deprecated)]
|
||||||
if let Ok((new_blockhash, fee_calculator)) = self.get_recent_blockhash() {
|
if let Ok((new_blockhash, fee_calculator)) = self.get_recent_blockhash() {
|
||||||
if new_blockhash != *blockhash {
|
if new_blockhash != *blockhash {
|
||||||
return Ok((new_blockhash, fee_calculator));
|
return Ok((new_blockhash, fee_calculator));
|
||||||
|
@ -2831,8 +2865,7 @@ impl RpcClient {
|
||||||
config: RpcSendTransactionConfig,
|
config: RpcSendTransactionConfig,
|
||||||
) -> ClientResult<Signature> {
|
) -> ClientResult<Signature> {
|
||||||
let recent_blockhash = if uses_durable_nonce(transaction).is_some() {
|
let recent_blockhash = if uses_durable_nonce(transaction).is_some() {
|
||||||
self.get_recent_blockhash_with_commitment(CommitmentConfig::processed())?
|
self.get_latest_blockhash_with_commitment(CommitmentConfig::processed())?
|
||||||
.value
|
|
||||||
.0
|
.0
|
||||||
} else {
|
} else {
|
||||||
transaction.message.recent_blockhash
|
transaction.message.recent_blockhash
|
||||||
|
@ -2872,13 +2905,8 @@ impl RpcClient {
|
||||||
let status = self
|
let status = self
|
||||||
.get_signature_status_with_commitment(signature, CommitmentConfig::processed())?;
|
.get_signature_status_with_commitment(signature, CommitmentConfig::processed())?;
|
||||||
if status.is_none() {
|
if status.is_none() {
|
||||||
let blockhash_not_found = self
|
let blockhash_not_found =
|
||||||
.get_fee_calculator_for_blockhash_with_commitment(
|
!self.is_blockhash_valid(recent_blockhash, CommitmentConfig::processed())?;
|
||||||
recent_blockhash,
|
|
||||||
CommitmentConfig::processed(),
|
|
||||||
)?
|
|
||||||
.value
|
|
||||||
.is_none();
|
|
||||||
if blockhash_not_found && now.elapsed() >= confirm_transaction_initial_timeout {
|
if blockhash_not_found && now.elapsed() >= confirm_transaction_initial_timeout {
|
||||||
break (signature, status);
|
break (signature, status);
|
||||||
}
|
}
|
||||||
|
@ -2936,6 +2964,84 @@ impl RpcClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_latest_blockhash(&self) -> ClientResult<Hash> {
|
||||||
|
let (blockhash, _) = self.get_latest_blockhash_with_commitment(self.commitment())?;
|
||||||
|
Ok(blockhash)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_latest_blockhash_with_commitment(
|
||||||
|
&self,
|
||||||
|
commitment: CommitmentConfig,
|
||||||
|
) -> ClientResult<(Hash, u64)> {
|
||||||
|
let latest_blockhash = self
|
||||||
|
.send::<Response<RpcBlockhash>>(
|
||||||
|
RpcRequest::GetLatestBlockhash,
|
||||||
|
json!([self.maybe_map_commitment(commitment)?]),
|
||||||
|
)?
|
||||||
|
.value;
|
||||||
|
|
||||||
|
let blockhash = latest_blockhash.blockhash.parse().map_err(|_| {
|
||||||
|
ClientError::new_with_request(
|
||||||
|
RpcError::ParseError("Hash".to_string()).into(),
|
||||||
|
RpcRequest::GetLatestBlockhash,
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
Ok((blockhash, latest_blockhash.last_valid_block_height))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_blockhash_valid(
|
||||||
|
&self,
|
||||||
|
blockhash: &Hash,
|
||||||
|
commitment: CommitmentConfig,
|
||||||
|
) -> ClientResult<bool> {
|
||||||
|
let result = self.send::<Response<bool>>(
|
||||||
|
RpcRequest::IsBlockhashValid,
|
||||||
|
json!([blockhash.to_string(), commitment,]),
|
||||||
|
)?;
|
||||||
|
Ok(result.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_fee_for_message(&self, blockhash: &Hash, message: &Message) -> ClientResult<u64> {
|
||||||
|
let serialized_encoded =
|
||||||
|
serialize_and_encode::<Message>(message, UiTransactionEncoding::Base64)?;
|
||||||
|
let result = self.send::<Response<Option<u64>>>(
|
||||||
|
RpcRequest::GetFeeForMessage,
|
||||||
|
json!([
|
||||||
|
blockhash.to_string(),
|
||||||
|
serialized_encoded,
|
||||||
|
UiTransactionEncoding::Base64,
|
||||||
|
self.commitment(),
|
||||||
|
]),
|
||||||
|
)?;
|
||||||
|
result
|
||||||
|
.value
|
||||||
|
.ok_or_else(|| ClientErrorKind::Custom("Invalid blockhash".to_string()).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_new_latest_blockhash(&self, blockhash: &Hash) -> ClientResult<Hash> {
|
||||||
|
let mut num_retries = 0;
|
||||||
|
let start = Instant::now();
|
||||||
|
while start.elapsed().as_secs() < 5 {
|
||||||
|
if let Ok(new_blockhash) = self.get_latest_blockhash() {
|
||||||
|
if new_blockhash != *blockhash {
|
||||||
|
return Ok(new_blockhash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug!("Got same blockhash ({:?}), will retry...", blockhash);
|
||||||
|
|
||||||
|
// Retry ~twice during a slot
|
||||||
|
sleep(Duration::from_millis(DEFAULT_MS_PER_SLOT / 2));
|
||||||
|
num_retries += 1;
|
||||||
|
}
|
||||||
|
Err(RpcError::ForUser(format!(
|
||||||
|
"Unable to get new blockhash after {}ms (retried {} times), stuck at {}",
|
||||||
|
start.elapsed().as_millis(),
|
||||||
|
num_retries,
|
||||||
|
blockhash
|
||||||
|
))
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn send<T>(&self, request: RpcRequest, params: Value) -> ClientResult<T>
|
pub fn send<T>(&self, request: RpcRequest, params: Value) -> ClientResult<T>
|
||||||
where
|
where
|
||||||
T: serde::de::DeserializeOwned,
|
T: serde::de::DeserializeOwned,
|
||||||
|
@ -2951,18 +3057,18 @@ impl RpcClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_encode_transaction(
|
pub fn serialize_and_encode<T>(input: &T, encoding: UiTransactionEncoding) -> ClientResult<String>
|
||||||
transaction: &Transaction,
|
where
|
||||||
encoding: UiTransactionEncoding,
|
T: serde::ser::Serialize,
|
||||||
) -> ClientResult<String> {
|
{
|
||||||
let serialized = serialize(transaction)
|
let serialized = serialize(input)
|
||||||
.map_err(|e| ClientErrorKind::Custom(format!("transaction serialization failed: {}", e)))?;
|
.map_err(|e| ClientErrorKind::Custom(format!("Serialization failed: {}", e)))?;
|
||||||
let encoded = match encoding {
|
let encoded = match encoding {
|
||||||
UiTransactionEncoding::Base58 => bs58::encode(serialized).into_string(),
|
UiTransactionEncoding::Base58 => bs58::encode(serialized).into_string(),
|
||||||
UiTransactionEncoding::Base64 => base64::encode(serialized),
|
UiTransactionEncoding::Base64 => base64::encode(serialized),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ClientErrorKind::Custom(format!(
|
return Err(ClientErrorKind::Custom(format!(
|
||||||
"unsupported transaction encoding: {}. Supported encodings: base58, base64",
|
"unsupported encoding: {}. Supported encodings: base58, base64",
|
||||||
encoding
|
encoding
|
||||||
))
|
))
|
||||||
.into())
|
.into())
|
||||||
|
@ -3094,12 +3200,14 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(balance, 50);
|
assert_eq!(balance, 50);
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
let blockhash: String = rpc_client
|
let blockhash: String = rpc_client
|
||||||
.send(RpcRequest::GetRecentBlockhash, Value::Null)
|
.send(RpcRequest::GetRecentBlockhash, Value::Null)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(blockhash, "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
|
assert_eq!(blockhash, "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
|
||||||
|
|
||||||
// Send erroneous parameter
|
// Send erroneous parameter
|
||||||
|
#[allow(deprecated)]
|
||||||
let blockhash: ClientResult<String> =
|
let blockhash: ClientResult<String> =
|
||||||
rpc_client.send(RpcRequest::GetRecentBlockhash, json!(["parameter"]));
|
rpc_client.send(RpcRequest::GetRecentBlockhash, json!(["parameter"]));
|
||||||
assert!(blockhash.is_err());
|
assert!(blockhash.is_err());
|
||||||
|
@ -3134,12 +3242,14 @@ mod tests {
|
||||||
|
|
||||||
let expected_blockhash: Hash = PUBKEY.parse().unwrap();
|
let expected_blockhash: Hash = PUBKEY.parse().unwrap();
|
||||||
|
|
||||||
let (blockhash, _fee_calculator) = rpc_client.get_recent_blockhash().expect("blockhash ok");
|
let blockhash = rpc_client.get_latest_blockhash().expect("blockhash ok");
|
||||||
assert_eq!(blockhash, expected_blockhash);
|
assert_eq!(blockhash, expected_blockhash);
|
||||||
|
|
||||||
let rpc_client = RpcClient::new_mock("fails".to_string());
|
let rpc_client = RpcClient::new_mock("fails".to_string());
|
||||||
|
|
||||||
assert!(rpc_client.get_recent_blockhash().is_err());
|
#[allow(deprecated)]
|
||||||
|
let result = rpc_client.get_recent_blockhash();
|
||||||
|
assert!(result.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -3229,4 +3339,20 @@ mod tests {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_latest_blockhash() {
|
||||||
|
let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
|
||||||
|
let expected_blockhash: Hash = PUBKEY.parse().unwrap();
|
||||||
|
|
||||||
|
let blockhash = rpc_client.get_latest_blockhash().expect("blockhash ok");
|
||||||
|
assert_eq!(blockhash, expected_blockhash);
|
||||||
|
|
||||||
|
let rpc_client = RpcClient::new_mock("fails".to_string());
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
let is_err = rpc_client.get_latest_blockhash().is_err();
|
||||||
|
assert!(is_err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,9 @@ use {
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
pub enum RpcRequest {
|
pub enum RpcRequest {
|
||||||
|
Custom {
|
||||||
|
method: &'static str,
|
||||||
|
},
|
||||||
DeregisterNode,
|
DeregisterNode,
|
||||||
GetAccountInfo,
|
GetAccountInfo,
|
||||||
GetBalance,
|
GetBalance,
|
||||||
|
@ -18,7 +21,6 @@ pub enum RpcRequest {
|
||||||
GetBlocksWithLimit,
|
GetBlocksWithLimit,
|
||||||
GetBlockTime,
|
GetBlockTime,
|
||||||
GetClusterNodes,
|
GetClusterNodes,
|
||||||
|
|
||||||
#[deprecated(since = "1.7.0", note = "Please use RpcRequest::GetBlock instead")]
|
#[deprecated(since = "1.7.0", note = "Please use RpcRequest::GetBlock instead")]
|
||||||
GetConfirmedBlock,
|
GetConfirmedBlock,
|
||||||
#[deprecated(since = "1.7.0", note = "Please use RpcRequest::GetBlocks instead")]
|
#[deprecated(since = "1.7.0", note = "Please use RpcRequest::GetBlocks instead")]
|
||||||
|
@ -38,11 +40,23 @@ pub enum RpcRequest {
|
||||||
note = "Please use RpcRequest::GetTransaction instead"
|
note = "Please use RpcRequest::GetTransaction instead"
|
||||||
)]
|
)]
|
||||||
GetConfirmedTransaction,
|
GetConfirmedTransaction,
|
||||||
|
|
||||||
GetEpochInfo,
|
GetEpochInfo,
|
||||||
GetEpochSchedule,
|
GetEpochSchedule,
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please use RpcRequest::GetFeeForMessage instead"
|
||||||
|
)]
|
||||||
GetFeeCalculatorForBlockhash,
|
GetFeeCalculatorForBlockhash,
|
||||||
|
GetFeeForMessage,
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please do not use, will no longer be available in the future"
|
||||||
|
)]
|
||||||
GetFeeRateGovernor,
|
GetFeeRateGovernor,
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please use RpcRequest::GetFeeForMessage instead"
|
||||||
|
)]
|
||||||
GetFees,
|
GetFees,
|
||||||
GetFirstAvailableBlock,
|
GetFirstAvailableBlock,
|
||||||
GetGenesisHash,
|
GetGenesisHash,
|
||||||
|
@ -52,12 +66,17 @@ pub enum RpcRequest {
|
||||||
GetInflationRate,
|
GetInflationRate,
|
||||||
GetInflationReward,
|
GetInflationReward,
|
||||||
GetLargestAccounts,
|
GetLargestAccounts,
|
||||||
|
GetLatestBlockhash,
|
||||||
GetLeaderSchedule,
|
GetLeaderSchedule,
|
||||||
GetMaxRetransmitSlot,
|
GetMaxRetransmitSlot,
|
||||||
GetMaxShredInsertSlot,
|
GetMaxShredInsertSlot,
|
||||||
GetMinimumBalanceForRentExemption,
|
GetMinimumBalanceForRentExemption,
|
||||||
GetMultipleAccounts,
|
GetMultipleAccounts,
|
||||||
GetProgramAccounts,
|
GetProgramAccounts,
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please use RpcRequest::GetLatestBlockhash instead"
|
||||||
|
)]
|
||||||
GetRecentBlockhash,
|
GetRecentBlockhash,
|
||||||
GetRecentPerformanceSamples,
|
GetRecentPerformanceSamples,
|
||||||
GetSnapshotSlot,
|
GetSnapshotSlot,
|
||||||
|
@ -80,21 +99,20 @@ pub enum RpcRequest {
|
||||||
GetTransactionCount,
|
GetTransactionCount,
|
||||||
GetVersion,
|
GetVersion,
|
||||||
GetVoteAccounts,
|
GetVoteAccounts,
|
||||||
|
IsBlockhashValid,
|
||||||
MinimumLedgerSlot,
|
MinimumLedgerSlot,
|
||||||
RegisterNode,
|
RegisterNode,
|
||||||
RequestAirdrop,
|
RequestAirdrop,
|
||||||
SendTransaction,
|
SendTransaction,
|
||||||
SimulateTransaction,
|
SimulateTransaction,
|
||||||
SignVote,
|
SignVote,
|
||||||
Custom {
|
|
||||||
method: &'static str,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl fmt::Display for RpcRequest {
|
impl fmt::Display for RpcRequest {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let method = match self {
|
let method = match self {
|
||||||
|
RpcRequest::Custom { method } => method,
|
||||||
RpcRequest::DeregisterNode => "deregisterNode",
|
RpcRequest::DeregisterNode => "deregisterNode",
|
||||||
RpcRequest::GetAccountInfo => "getAccountInfo",
|
RpcRequest::GetAccountInfo => "getAccountInfo",
|
||||||
RpcRequest::GetBalance => "getBalance",
|
RpcRequest::GetBalance => "getBalance",
|
||||||
|
@ -113,6 +131,7 @@ impl fmt::Display for RpcRequest {
|
||||||
RpcRequest::GetEpochInfo => "getEpochInfo",
|
RpcRequest::GetEpochInfo => "getEpochInfo",
|
||||||
RpcRequest::GetEpochSchedule => "getEpochSchedule",
|
RpcRequest::GetEpochSchedule => "getEpochSchedule",
|
||||||
RpcRequest::GetFeeCalculatorForBlockhash => "getFeeCalculatorForBlockhash",
|
RpcRequest::GetFeeCalculatorForBlockhash => "getFeeCalculatorForBlockhash",
|
||||||
|
RpcRequest::GetFeeForMessage => "getFeeForMessage",
|
||||||
RpcRequest::GetFeeRateGovernor => "getFeeRateGovernor",
|
RpcRequest::GetFeeRateGovernor => "getFeeRateGovernor",
|
||||||
RpcRequest::GetFees => "getFees",
|
RpcRequest::GetFees => "getFees",
|
||||||
RpcRequest::GetFirstAvailableBlock => "getFirstAvailableBlock",
|
RpcRequest::GetFirstAvailableBlock => "getFirstAvailableBlock",
|
||||||
|
@ -123,6 +142,7 @@ impl fmt::Display for RpcRequest {
|
||||||
RpcRequest::GetInflationRate => "getInflationRate",
|
RpcRequest::GetInflationRate => "getInflationRate",
|
||||||
RpcRequest::GetInflationReward => "getInflationReward",
|
RpcRequest::GetInflationReward => "getInflationReward",
|
||||||
RpcRequest::GetLargestAccounts => "getLargestAccounts",
|
RpcRequest::GetLargestAccounts => "getLargestAccounts",
|
||||||
|
RpcRequest::GetLatestBlockhash => "getLatestBlockhash",
|
||||||
RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
|
RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
|
||||||
RpcRequest::GetMaxRetransmitSlot => "getMaxRetransmitSlot",
|
RpcRequest::GetMaxRetransmitSlot => "getMaxRetransmitSlot",
|
||||||
RpcRequest::GetMaxShredInsertSlot => "getMaxShredInsertSlot",
|
RpcRequest::GetMaxShredInsertSlot => "getMaxShredInsertSlot",
|
||||||
|
@ -151,13 +171,13 @@ impl fmt::Display for RpcRequest {
|
||||||
RpcRequest::GetTransactionCount => "getTransactionCount",
|
RpcRequest::GetTransactionCount => "getTransactionCount",
|
||||||
RpcRequest::GetVersion => "getVersion",
|
RpcRequest::GetVersion => "getVersion",
|
||||||
RpcRequest::GetVoteAccounts => "getVoteAccounts",
|
RpcRequest::GetVoteAccounts => "getVoteAccounts",
|
||||||
|
RpcRequest::IsBlockhashValid => "isBlockhashValid",
|
||||||
RpcRequest::MinimumLedgerSlot => "minimumLedgerSlot",
|
RpcRequest::MinimumLedgerSlot => "minimumLedgerSlot",
|
||||||
RpcRequest::RegisterNode => "registerNode",
|
RpcRequest::RegisterNode => "registerNode",
|
||||||
RpcRequest::RequestAirdrop => "requestAirdrop",
|
RpcRequest::RequestAirdrop => "requestAirdrop",
|
||||||
RpcRequest::SendTransaction => "sendTransaction",
|
RpcRequest::SendTransaction => "sendTransaction",
|
||||||
RpcRequest::SimulateTransaction => "simulateTransaction",
|
RpcRequest::SimulateTransaction => "simulateTransaction",
|
||||||
RpcRequest::SignVote => "signVote",
|
RpcRequest::SignVote => "signVote",
|
||||||
RpcRequest::Custom { method } => method,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(f, "{}", method)
|
write!(f, "{}", method)
|
||||||
|
@ -261,14 +281,17 @@ mod tests {
|
||||||
let request = test_request.build_request_json(1, Value::Null);
|
let request = test_request.build_request_json(1, Value::Null);
|
||||||
assert_eq!(request["method"], "getEpochInfo");
|
assert_eq!(request["method"], "getEpochInfo");
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
let test_request = RpcRequest::GetRecentBlockhash;
|
let test_request = RpcRequest::GetRecentBlockhash;
|
||||||
let request = test_request.build_request_json(1, Value::Null);
|
let request = test_request.build_request_json(1, Value::Null);
|
||||||
assert_eq!(request["method"], "getRecentBlockhash");
|
assert_eq!(request["method"], "getRecentBlockhash");
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
let test_request = RpcRequest::GetFeeCalculatorForBlockhash;
|
let test_request = RpcRequest::GetFeeCalculatorForBlockhash;
|
||||||
let request = test_request.build_request_json(1, json!([addr]));
|
let request = test_request.build_request_json(1, json!([addr]));
|
||||||
assert_eq!(request["method"], "getFeeCalculatorForBlockhash");
|
assert_eq!(request["method"], "getFeeCalculatorForBlockhash");
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
let test_request = RpcRequest::GetFeeRateGovernor;
|
let test_request = RpcRequest::GetFeeRateGovernor;
|
||||||
let request = test_request.build_request_json(1, Value::Null);
|
let request = test_request.build_request_json(1, Value::Null);
|
||||||
assert_eq!(request["method"], "getFeeRateGovernor");
|
assert_eq!(request["method"], "getFeeRateGovernor");
|
||||||
|
@ -298,6 +321,7 @@ mod tests {
|
||||||
let addr = json!("deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
|
let addr = json!("deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
|
||||||
|
|
||||||
// Test request with CommitmentConfig and no params
|
// Test request with CommitmentConfig and no params
|
||||||
|
#[allow(deprecated)]
|
||||||
let test_request = RpcRequest::GetRecentBlockhash;
|
let test_request = RpcRequest::GetRecentBlockhash;
|
||||||
let request = test_request.build_request_json(1, json!([commitment_config]));
|
let request = test_request.build_request_json(1, json!([commitment_config]));
|
||||||
assert_eq!(request["params"], json!([commitment_config.clone()]));
|
assert_eq!(request["params"], json!([commitment_config.clone()]));
|
||||||
|
|
|
@ -41,6 +41,13 @@ pub struct RpcBlockhashFeeCalculator {
|
||||||
pub fee_calculator: FeeCalculator,
|
pub fee_calculator: FeeCalculator,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct RpcBlockhash {
|
||||||
|
pub blockhash: String,
|
||||||
|
pub last_valid_block_height: u64,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct RpcFees {
|
pub struct RpcFees {
|
||||||
|
|
|
@ -246,7 +246,7 @@ impl ThinClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info!("{} tries failed transfer to {}", x, self.tpu_addr());
|
info!("{} tries failed transfer to {}", x, self.tpu_addr());
|
||||||
let (blockhash, _fee_calculator) = self.get_recent_blockhash()?;
|
let blockhash = self.get_latest_blockhash()?;
|
||||||
transaction.sign(keypairs, blockhash);
|
transaction.sign(keypairs, blockhash);
|
||||||
}
|
}
|
||||||
Err(io::Error::new(
|
Err(io::Error::new(
|
||||||
|
@ -333,7 +333,7 @@ impl SyncClient for ThinClient {
|
||||||
keypairs: &T,
|
keypairs: &T,
|
||||||
message: Message,
|
message: Message,
|
||||||
) -> TransportResult<Signature> {
|
) -> TransportResult<Signature> {
|
||||||
let (blockhash, _fee_calculator) = self.get_recent_blockhash()?;
|
let blockhash = self.get_latest_blockhash()?;
|
||||||
let mut transaction = Transaction::new(keypairs, message, blockhash);
|
let mut transaction = Transaction::new(keypairs, message, blockhash);
|
||||||
let signature = self.send_and_confirm_transaction(keypairs, &mut transaction, 5, 0)?;
|
let signature = self.send_and_confirm_transaction(keypairs, &mut transaction, 5, 0)?;
|
||||||
Ok(signature)
|
Ok(signature)
|
||||||
|
@ -404,6 +404,7 @@ impl SyncClient for ThinClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_recent_blockhash(&self) -> TransportResult<(Hash, FeeCalculator)> {
|
fn get_recent_blockhash(&self) -> TransportResult<(Hash, FeeCalculator)> {
|
||||||
|
#[allow(deprecated)]
|
||||||
let (blockhash, fee_calculator, _last_valid_slot) =
|
let (blockhash, fee_calculator, _last_valid_slot) =
|
||||||
self.get_recent_blockhash_with_commitment(CommitmentConfig::default())?;
|
self.get_recent_blockhash_with_commitment(CommitmentConfig::default())?;
|
||||||
Ok((blockhash, fee_calculator))
|
Ok((blockhash, fee_calculator))
|
||||||
|
@ -415,6 +416,7 @@ impl SyncClient for ThinClient {
|
||||||
) -> TransportResult<(Hash, FeeCalculator, Slot)> {
|
) -> TransportResult<(Hash, FeeCalculator, Slot)> {
|
||||||
let index = self.optimizer.experiment();
|
let index = self.optimizer.experiment();
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
|
#[allow(deprecated)]
|
||||||
let recent_blockhash =
|
let recent_blockhash =
|
||||||
self.rpc_clients[index].get_recent_blockhash_with_commitment(commitment_config);
|
self.rpc_clients[index].get_recent_blockhash_with_commitment(commitment_config);
|
||||||
match recent_blockhash {
|
match recent_blockhash {
|
||||||
|
@ -433,12 +435,14 @@ impl SyncClient for ThinClient {
|
||||||
&self,
|
&self,
|
||||||
blockhash: &Hash,
|
blockhash: &Hash,
|
||||||
) -> TransportResult<Option<FeeCalculator>> {
|
) -> TransportResult<Option<FeeCalculator>> {
|
||||||
|
#[allow(deprecated)]
|
||||||
self.rpc_client()
|
self.rpc_client()
|
||||||
.get_fee_calculator_for_blockhash(blockhash)
|
.get_fee_calculator_for_blockhash(blockhash)
|
||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_fee_rate_governor(&self) -> TransportResult<FeeRateGovernor> {
|
fn get_fee_rate_governor(&self) -> TransportResult<FeeRateGovernor> {
|
||||||
|
#[allow(deprecated)]
|
||||||
self.rpc_client()
|
self.rpc_client()
|
||||||
.get_fee_rate_governor()
|
.get_fee_rate_governor()
|
||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
|
@ -556,10 +560,57 @@ impl SyncClient for ThinClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_new_blockhash(&self, blockhash: &Hash) -> TransportResult<(Hash, FeeCalculator)> {
|
fn get_new_blockhash(&self, blockhash: &Hash) -> TransportResult<(Hash, FeeCalculator)> {
|
||||||
|
#[allow(deprecated)]
|
||||||
self.rpc_client()
|
self.rpc_client()
|
||||||
.get_new_blockhash(blockhash)
|
.get_new_blockhash(blockhash)
|
||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_latest_blockhash(&self) -> TransportResult<Hash> {
|
||||||
|
let (blockhash, _) =
|
||||||
|
self.get_latest_blockhash_with_commitment(CommitmentConfig::default())?;
|
||||||
|
Ok(blockhash)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_latest_blockhash_with_commitment(
|
||||||
|
&self,
|
||||||
|
commitment_config: CommitmentConfig,
|
||||||
|
) -> TransportResult<(Hash, u64)> {
|
||||||
|
let index = self.optimizer.experiment();
|
||||||
|
let now = Instant::now();
|
||||||
|
match self.rpc_clients[index].get_latest_blockhash_with_commitment(commitment_config) {
|
||||||
|
Ok((blockhash, last_valid_block_height)) => {
|
||||||
|
self.optimizer.report(index, duration_as_ms(&now.elapsed()));
|
||||||
|
Ok((blockhash, last_valid_block_height))
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
self.optimizer.report(index, std::u64::MAX);
|
||||||
|
Err(e.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_blockhash_valid(
|
||||||
|
&self,
|
||||||
|
blockhash: &Hash,
|
||||||
|
commitment_config: CommitmentConfig,
|
||||||
|
) -> TransportResult<bool> {
|
||||||
|
self.rpc_client()
|
||||||
|
.is_blockhash_valid(blockhash, commitment_config)
|
||||||
|
.map_err(|e| e.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_fee_for_message(&self, blockhash: &Hash, message: &Message) -> TransportResult<u64> {
|
||||||
|
self.rpc_client()
|
||||||
|
.get_fee_for_message(blockhash, message)
|
||||||
|
.map_err(|e| e.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_new_latest_blockhash(&self, blockhash: &Hash) -> TransportResult<Hash> {
|
||||||
|
self.rpc_client()
|
||||||
|
.get_new_latest_blockhash(blockhash)
|
||||||
|
.map_err(|e| e.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsyncClient for ThinClient {
|
impl AsyncClient for ThinClient {
|
||||||
|
|
|
@ -28,6 +28,8 @@ use {
|
||||||
exit::Exit,
|
exit::Exit,
|
||||||
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
|
instruction::{AccountMeta, Instruction},
|
||||||
|
message::Message,
|
||||||
native_token::sol_to_lamports,
|
native_token::sol_to_lamports,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
|
@ -551,25 +553,40 @@ impl TestValidator {
|
||||||
{
|
{
|
||||||
let rpc_client =
|
let rpc_client =
|
||||||
RpcClient::new_with_commitment(rpc_url.clone(), CommitmentConfig::processed());
|
RpcClient::new_with_commitment(rpc_url.clone(), CommitmentConfig::processed());
|
||||||
|
let message = Message::new(
|
||||||
if let Ok(result) = rpc_client.get_fee_rate_governor() {
|
&[Instruction::new_with_bytes(
|
||||||
let fee_rate_governor = result.value;
|
Pubkey::new_unique(),
|
||||||
if fee_rate_governor.target_lamports_per_signature > 0 {
|
&[],
|
||||||
loop {
|
vec![AccountMeta::new(Pubkey::new_unique(), true)],
|
||||||
match rpc_client.get_recent_blockhash() {
|
)],
|
||||||
Ok((_blockhash, fee_calculator)) => {
|
None,
|
||||||
if fee_calculator.lamports_per_signature != 0 {
|
);
|
||||||
break;
|
const MAX_TRIES: u64 = 10;
|
||||||
}
|
let mut num_tries = 0;
|
||||||
}
|
loop {
|
||||||
Err(err) => {
|
num_tries += 1;
|
||||||
warn!("get_recent_blockhash() failed: {:?}", err);
|
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;
|
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) {
|
pub fn rpc_client(&self) -> (RpcClient, Hash, FeeCalculator) {
|
||||||
let rpc_client =
|
let rpc_client =
|
||||||
RpcClient::new_with_commitment(self.rpc_url.clone(), CommitmentConfig::processed());
|
RpcClient::new_with_commitment(self.rpc_url.clone(), CommitmentConfig::processed());
|
||||||
|
#[allow(deprecated)]
|
||||||
let (recent_blockhash, fee_calculator) = rpc_client
|
let (recent_blockhash, fee_calculator) = rpc_client
|
||||||
.get_recent_blockhash()
|
.get_recent_blockhash()
|
||||||
.expect("get_recent_blockhash");
|
.expect("get_recent_blockhash");
|
||||||
|
|
|
@ -82,12 +82,12 @@ impl VoteSimulator {
|
||||||
for (pubkey, vote) in cluster_votes.iter() {
|
for (pubkey, vote) in cluster_votes.iter() {
|
||||||
if vote.contains(&parent) {
|
if vote.contains(&parent) {
|
||||||
let keypairs = self.validator_keypairs.get(pubkey).unwrap();
|
let keypairs = self.validator_keypairs.get(pubkey).unwrap();
|
||||||
let last_blockhash = parent_bank.last_blockhash();
|
let latest_blockhash = parent_bank.last_blockhash();
|
||||||
let vote_tx = vote_transaction::new_vote_transaction(
|
let vote_tx = vote_transaction::new_vote_transaction(
|
||||||
// Must vote > root to be processed
|
// Must vote > root to be processed
|
||||||
vec![parent],
|
vec![parent],
|
||||||
parent_bank.hash(),
|
parent_bank.hash(),
|
||||||
last_blockhash,
|
latest_blockhash,
|
||||||
&keypairs.node_keypair,
|
&keypairs.node_keypair,
|
||||||
&keypairs.vote_keypair,
|
&keypairs.vote_keypair,
|
||||||
&keypairs.vote_keypair,
|
&keypairs.vote_keypair,
|
||||||
|
|
|
@ -53,7 +53,7 @@ fn test_rpc_client() {
|
||||||
|
|
||||||
let original_alice_balance = client.get_balance(&alice.pubkey()).unwrap();
|
let original_alice_balance = client.get_balance(&alice.pubkey()).unwrap();
|
||||||
|
|
||||||
let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap();
|
let blockhash = client.get_latest_blockhash().unwrap();
|
||||||
|
|
||||||
let tx = system_transaction::transfer(&alice, &bob_pubkey, sol_to_lamports(20.0), blockhash);
|
let tx = system_transaction::transfer(&alice, &bob_pubkey, sol_to_lamports(20.0), blockhash);
|
||||||
let signature = client.send_transaction(&tx).unwrap();
|
let signature = client.send_transaction(&tx).unwrap();
|
||||||
|
|
|
@ -231,7 +231,7 @@ fn test_rpc_subscriptions() {
|
||||||
transactions_socket.connect(test_validator.tpu()).unwrap();
|
transactions_socket.connect(test_validator.tpu()).unwrap();
|
||||||
|
|
||||||
let rpc_client = RpcClient::new(test_validator.rpc_url());
|
let rpc_client = RpcClient::new(test_validator.rpc_url());
|
||||||
let recent_blockhash = rpc_client.get_recent_blockhash().unwrap().0;
|
let recent_blockhash = rpc_client.get_latest_blockhash().unwrap();
|
||||||
|
|
||||||
// Create transaction signatures to subscribe to
|
// Create transaction signatures to subscribe to
|
||||||
let transactions: Vec<Transaction> = (0..1000)
|
let transactions: Vec<Transaction> = (0..1000)
|
||||||
|
@ -406,7 +406,7 @@ fn test_tpu_send_transaction() {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let recent_blockhash = rpc_client.get_recent_blockhash().unwrap().0;
|
let recent_blockhash = rpc_client.get_latest_blockhash().unwrap();
|
||||||
let tx =
|
let tx =
|
||||||
system_transaction::transfer(&mint_keypair, &Pubkey::new_unique(), 42, recent_blockhash);
|
system_transaction::transfer(&mint_keypair, &Pubkey::new_unique(), 42, recent_blockhash);
|
||||||
assert!(tpu_client.send_transaction(&tx));
|
assert!(tpu_client.send_transaction(&tx));
|
||||||
|
@ -433,8 +433,8 @@ fn deserialize_rpc_error() -> ClientResult<()> {
|
||||||
|
|
||||||
let bob = Keypair::new();
|
let bob = Keypair::new();
|
||||||
let lamports = 50;
|
let lamports = 50;
|
||||||
let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?;
|
let blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
let mut tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, recent_blockhash);
|
let mut tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, blockhash);
|
||||||
|
|
||||||
// This will cause an error
|
// This will cause an error
|
||||||
tx.signatures.clear();
|
tx.signatures.clear();
|
||||||
|
|
|
@ -122,7 +122,7 @@ https://github.com/solana-labs/solana/blob/b6bfed64cb159ee67bb6bdbaefc7f833bbed3
|
||||||
// Number of signatures processed in this block
|
// Number of signatures processed in this block
|
||||||
&signature_count_buf,
|
&signature_count_buf,
|
||||||
// Last PoH hash in this block
|
// Last PoH hash in this block
|
||||||
self.last_blockhash().as_ref(),
|
self.latest_blockhash().as_ref(),
|
||||||
]);
|
]);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -218,7 +218,7 @@ fn new_update_manifest(
|
||||||
.get_account_data(&update_manifest_keypair.pubkey())
|
.get_account_data(&update_manifest_keypair.pubkey())
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
let (recent_blockhash, _fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let recent_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
|
|
||||||
let lamports = rpc_client
|
let lamports = rpc_client
|
||||||
.get_minimum_balance_for_rent_exemption(SignedUpdateManifest::max_space() as usize)?;
|
.get_minimum_balance_for_rent_exemption(SignedUpdateManifest::max_space() as usize)?;
|
||||||
|
@ -244,7 +244,7 @@ fn store_update_manifest(
|
||||||
update_manifest_keypair: &Keypair,
|
update_manifest_keypair: &Keypair,
|
||||||
update_manifest: &SignedUpdateManifest,
|
update_manifest: &SignedUpdateManifest,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (recent_blockhash, _fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let recent_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
|
|
||||||
let signers = [from_keypair, update_manifest_keypair];
|
let signers = [from_keypair, update_manifest_keypair];
|
||||||
let instruction = config_instruction::store::<SignedUpdateManifest>(
|
let instruction = config_instruction::store::<SignedUpdateManifest>(
|
||||||
|
|
|
@ -66,8 +66,8 @@ pub fn spend_and_verify_all_nodes<S: ::std::hash::BuildHasher + Sync + Send>(
|
||||||
)
|
)
|
||||||
.expect("balance in source");
|
.expect("balance in source");
|
||||||
assert!(bal > 0);
|
assert!(bal > 0);
|
||||||
let (blockhash, _fee_calculator, _last_valid_slot) = client
|
let (blockhash, _) = client
|
||||||
.get_recent_blockhash_with_commitment(CommitmentConfig::confirmed())
|
.get_latest_blockhash_with_commitment(CommitmentConfig::confirmed())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut transaction =
|
let mut transaction =
|
||||||
system_transaction::transfer(funding_keypair, &random_keypair.pubkey(), 1, blockhash);
|
system_transaction::transfer(funding_keypair, &random_keypair.pubkey(), 1, blockhash);
|
||||||
|
@ -115,8 +115,8 @@ pub fn send_many_transactions(
|
||||||
)
|
)
|
||||||
.expect("balance in source");
|
.expect("balance in source");
|
||||||
assert!(bal > 0);
|
assert!(bal > 0);
|
||||||
let (blockhash, _fee_calculator, _last_valid_slot) = client
|
let (blockhash, _) = client
|
||||||
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
|
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let transfer_amount = thread_rng().gen_range(1, max_tokens_per_transfer);
|
let transfer_amount = thread_rng().gen_range(1, max_tokens_per_transfer);
|
||||||
|
|
||||||
|
@ -241,8 +241,8 @@ pub fn kill_entry_and_spend_and_verify_rest(
|
||||||
}
|
}
|
||||||
|
|
||||||
let random_keypair = Keypair::new();
|
let random_keypair = Keypair::new();
|
||||||
let (blockhash, _fee_calculator, _last_valid_slot) = client
|
let (blockhash, _) = client
|
||||||
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
|
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut transaction = system_transaction::transfer(
|
let mut transaction = system_transaction::transfer(
|
||||||
funding_keypair,
|
funding_keypair,
|
||||||
|
|
|
@ -481,8 +481,8 @@ impl LocalCluster {
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
trace!("getting leader blockhash");
|
trace!("getting leader blockhash");
|
||||||
let (blockhash, _fee_calculator, _last_valid_slot) = client
|
let (blockhash, _) = client
|
||||||
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
|
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut tx = system_transaction::transfer(source_keypair, dest_pubkey, lamports, blockhash);
|
let mut tx = system_transaction::transfer(source_keypair, dest_pubkey, lamports, blockhash);
|
||||||
info!(
|
info!(
|
||||||
|
@ -542,7 +542,7 @@ impl LocalCluster {
|
||||||
&[from_account.as_ref(), vote_account],
|
&[from_account.as_ref(), vote_account],
|
||||||
message,
|
message,
|
||||||
client
|
client
|
||||||
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
|
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0,
|
.0,
|
||||||
);
|
);
|
||||||
|
@ -570,7 +570,7 @@ impl LocalCluster {
|
||||||
&[from_account.as_ref(), &stake_account_keypair],
|
&[from_account.as_ref(), &stake_account_keypair],
|
||||||
message,
|
message,
|
||||||
client
|
client
|
||||||
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
|
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0,
|
.0,
|
||||||
);
|
);
|
||||||
|
|
|
@ -191,8 +191,8 @@ fn test_local_cluster_signature_subscribe() {
|
||||||
non_bootstrap_info.client_facing_addr(),
|
non_bootstrap_info.client_facing_addr(),
|
||||||
VALIDATOR_PORT_RANGE,
|
VALIDATOR_PORT_RANGE,
|
||||||
);
|
);
|
||||||
let (blockhash, _fee_calculator, _last_valid_slot) = tx_client
|
let (blockhash, _) = tx_client
|
||||||
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
|
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut transaction = system_transaction::transfer(
|
let mut transaction = system_transaction::transfer(
|
||||||
|
@ -1475,8 +1475,8 @@ fn generate_frozen_account_panic(mut cluster: LocalCluster, frozen_account: Arc<
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while !solana_runtime::accounts_db::FROZEN_ACCOUNT_PANIC.load(Ordering::Relaxed) {
|
while !solana_runtime::accounts_db::FROZEN_ACCOUNT_PANIC.load(Ordering::Relaxed) {
|
||||||
// Transfer from frozen account
|
// Transfer from frozen account
|
||||||
let (blockhash, _fee_calculator, _last_valid_slot) = client
|
let (blockhash, _) = client
|
||||||
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
|
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
client
|
client
|
||||||
.async_transfer(
|
.async_transfer(
|
||||||
|
@ -3246,8 +3246,8 @@ fn setup_transfer_scan_threads(
|
||||||
if exit_.load(Ordering::Relaxed) {
|
if exit_.load(Ordering::Relaxed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let (blockhash, _fee_calculator, _last_valid_slot) = client
|
let (blockhash, _) = client
|
||||||
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
|
.get_latest_blockhash_with_commitment(CommitmentConfig::processed())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for i in 0..starting_keypairs_.len() {
|
for i in 0..starting_keypairs_.len() {
|
||||||
client
|
client
|
||||||
|
|
|
@ -451,12 +451,12 @@ fn setup_fee_calculator(bank: Bank) -> Bank {
|
||||||
}
|
}
|
||||||
let last_blockhash = bank.last_blockhash();
|
let last_blockhash = bank.last_blockhash();
|
||||||
// Make sure the new last_blockhash now requires a fee
|
// Make sure the new last_blockhash now requires a fee
|
||||||
assert_ne!(
|
#[allow(deprecated)]
|
||||||
bank.get_fee_calculator(&last_blockhash)
|
let lamports_per_signature = bank
|
||||||
.expect("fee_calculator")
|
.get_fee_calculator(&last_blockhash)
|
||||||
.lamports_per_signature,
|
.expect("fee_calculator")
|
||||||
0
|
.lamports_per_signature;
|
||||||
);
|
assert_ne!(lamports_per_signature, 0);
|
||||||
|
|
||||||
bank
|
bank
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,10 +362,12 @@ fn execute_transactions(bank: &Bank, txs: &[Transaction]) -> Vec<ConfirmedTransa
|
||||||
post_token_balances,
|
post_token_balances,
|
||||||
log_messages,
|
log_messages,
|
||||||
)| {
|
)| {
|
||||||
|
#[allow(deprecated)]
|
||||||
let fee_calculator = nonce_rollback
|
let fee_calculator = nonce_rollback
|
||||||
.map(|nonce_rollback| nonce_rollback.fee_calculator())
|
.map(|nonce_rollback| nonce_rollback.fee_calculator())
|
||||||
.unwrap_or_else(|| bank.get_fee_calculator(&tx.message().recent_blockhash))
|
.unwrap_or_else(|| bank.get_fee_calculator(&tx.message().recent_blockhash))
|
||||||
.expect("FeeCalculator must exist");
|
.expect("FeeCalculator must exist");
|
||||||
|
#[allow(deprecated)]
|
||||||
let fee = fee_calculator.calculate_fee(tx.message());
|
let fee = fee_calculator.calculate_fee(tx.message());
|
||||||
|
|
||||||
let inner_instructions = inner_instructions.map(|inner_instructions| {
|
let inner_instructions = inner_instructions.map(|inner_instructions| {
|
||||||
|
|
375
rpc/src/rpc.rs
375
rpc/src/rpc.rs
|
@ -60,6 +60,7 @@ use {
|
||||||
epoch_schedule::EpochSchedule,
|
epoch_schedule::EpochSchedule,
|
||||||
exit::Exit,
|
exit::Exit,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
|
message::Message,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
sanitize::Sanitize,
|
sanitize::Sanitize,
|
||||||
signature::{Keypair, Signature, Signer},
|
signature::{Keypair, Signature, Signer},
|
||||||
|
@ -80,6 +81,7 @@ use {
|
||||||
state::{Account as TokenAccount, Mint},
|
state::{Account as TokenAccount, Mint},
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
|
any::type_name,
|
||||||
cmp::{max, min},
|
cmp::{max, min},
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
|
@ -531,7 +533,8 @@ impl JsonRpcRequestProcessor {
|
||||||
commitment: Option<CommitmentConfig>,
|
commitment: Option<CommitmentConfig>,
|
||||||
) -> RpcResponse<RpcBlockhashFeeCalculator> {
|
) -> RpcResponse<RpcBlockhashFeeCalculator> {
|
||||||
let bank = self.bank(commitment);
|
let bank = self.bank(commitment);
|
||||||
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash();
|
#[allow(deprecated)]
|
||||||
|
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash_with_fee_calculator();
|
||||||
new_response(
|
new_response(
|
||||||
&bank,
|
&bank,
|
||||||
RpcBlockhashFeeCalculator {
|
RpcBlockhashFeeCalculator {
|
||||||
|
@ -543,7 +546,8 @@ impl JsonRpcRequestProcessor {
|
||||||
|
|
||||||
fn get_fees(&self, commitment: Option<CommitmentConfig>) -> RpcResponse<RpcFees> {
|
fn get_fees(&self, commitment: Option<CommitmentConfig>) -> RpcResponse<RpcFees> {
|
||||||
let bank = self.bank(commitment);
|
let bank = self.bank(commitment);
|
||||||
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash();
|
#[allow(deprecated)]
|
||||||
|
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash_with_fee_calculator();
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
let last_valid_slot = bank
|
let last_valid_slot = bank
|
||||||
.get_blockhash_last_valid_slot(&blockhash)
|
.get_blockhash_last_valid_slot(&blockhash)
|
||||||
|
@ -568,6 +572,7 @@ impl JsonRpcRequestProcessor {
|
||||||
commitment: Option<CommitmentConfig>,
|
commitment: Option<CommitmentConfig>,
|
||||||
) -> RpcResponse<Option<RpcFeeCalculator>> {
|
) -> RpcResponse<Option<RpcFeeCalculator>> {
|
||||||
let bank = self.bank(commitment);
|
let bank = self.bank(commitment);
|
||||||
|
#[allow(deprecated)]
|
||||||
let fee_calculator = bank.get_fee_calculator(blockhash);
|
let fee_calculator = bank.get_fee_calculator(blockhash);
|
||||||
new_response(
|
new_response(
|
||||||
&bank,
|
&bank,
|
||||||
|
@ -577,6 +582,7 @@ impl JsonRpcRequestProcessor {
|
||||||
|
|
||||||
fn get_fee_rate_governor(&self) -> RpcResponse<RpcFeeRateGovernor> {
|
fn get_fee_rate_governor(&self) -> RpcResponse<RpcFeeRateGovernor> {
|
||||||
let bank = self.bank(None);
|
let bank = self.bank(None);
|
||||||
|
#[allow(deprecated)]
|
||||||
let fee_rate_governor = bank.get_fee_rate_governor();
|
let fee_rate_governor = bank.get_fee_rate_governor();
|
||||||
new_response(
|
new_response(
|
||||||
&bank,
|
&bank,
|
||||||
|
@ -1896,6 +1902,45 @@ impl JsonRpcRequestProcessor {
|
||||||
self.get_filtered_program_accounts(bank, &spl_token_id_v2_0(), filters)
|
self.get_filtered_program_accounts(bank, &spl_token_id_v2_0(), filters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_latest_blockhash(
|
||||||
|
&self,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> RpcResponse<RpcBlockhash> {
|
||||||
|
let bank = self.bank(commitment);
|
||||||
|
let blockhash = bank.last_blockhash();
|
||||||
|
let last_valid_block_height = bank
|
||||||
|
.get_blockhash_last_valid_block_height(&blockhash)
|
||||||
|
.expect("bank blockhash queue should contain blockhash");
|
||||||
|
new_response(
|
||||||
|
&bank,
|
||||||
|
RpcBlockhash {
|
||||||
|
blockhash: blockhash.to_string(),
|
||||||
|
last_valid_block_height,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_blockhash_valid(
|
||||||
|
&self,
|
||||||
|
blockhash: &Hash,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> RpcResponse<bool> {
|
||||||
|
let bank = self.bank(commitment);
|
||||||
|
let is_valid = bank.is_blockhash_valid(blockhash);
|
||||||
|
new_response(&bank, is_valid)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_fee_for_message(
|
||||||
|
&self,
|
||||||
|
blockhash: &Hash,
|
||||||
|
message: &Message,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<Option<u64>>> {
|
||||||
|
let bank = self.bank(commitment);
|
||||||
|
let fee = bank.get_fee_for_message(blockhash, message);
|
||||||
|
Ok(new_response(&bank, fee))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_transaction(
|
fn verify_transaction(
|
||||||
|
@ -2410,34 +2455,6 @@ pub mod rpc_bank {
|
||||||
#[rpc(meta, name = "getEpochSchedule")]
|
#[rpc(meta, name = "getEpochSchedule")]
|
||||||
fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result<EpochSchedule>;
|
fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result<EpochSchedule>;
|
||||||
|
|
||||||
#[rpc(meta, name = "getRecentBlockhash")]
|
|
||||||
fn get_recent_blockhash(
|
|
||||||
&self,
|
|
||||||
meta: Self::Metadata,
|
|
||||||
commitment: Option<CommitmentConfig>,
|
|
||||||
) -> Result<RpcResponse<RpcBlockhashFeeCalculator>>;
|
|
||||||
|
|
||||||
#[rpc(meta, name = "getFees")]
|
|
||||||
fn get_fees(
|
|
||||||
&self,
|
|
||||||
meta: Self::Metadata,
|
|
||||||
commitment: Option<CommitmentConfig>,
|
|
||||||
) -> Result<RpcResponse<RpcFees>>;
|
|
||||||
|
|
||||||
#[rpc(meta, name = "getFeeCalculatorForBlockhash")]
|
|
||||||
fn get_fee_calculator_for_blockhash(
|
|
||||||
&self,
|
|
||||||
meta: Self::Metadata,
|
|
||||||
blockhash: String,
|
|
||||||
commitment: Option<CommitmentConfig>,
|
|
||||||
) -> Result<RpcResponse<Option<RpcFeeCalculator>>>;
|
|
||||||
|
|
||||||
#[rpc(meta, name = "getFeeRateGovernor")]
|
|
||||||
fn get_fee_rate_governor(
|
|
||||||
&self,
|
|
||||||
meta: Self::Metadata,
|
|
||||||
) -> Result<RpcResponse<RpcFeeRateGovernor>>;
|
|
||||||
|
|
||||||
#[rpc(meta, name = "getSlotLeader")]
|
#[rpc(meta, name = "getSlotLeader")]
|
||||||
fn get_slot_leader(
|
fn get_slot_leader(
|
||||||
&self,
|
&self,
|
||||||
|
@ -2500,44 +2517,6 @@ pub mod rpc_bank {
|
||||||
Ok(meta.get_epoch_schedule())
|
Ok(meta.get_epoch_schedule())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_recent_blockhash(
|
|
||||||
&self,
|
|
||||||
meta: Self::Metadata,
|
|
||||||
commitment: Option<CommitmentConfig>,
|
|
||||||
) -> Result<RpcResponse<RpcBlockhashFeeCalculator>> {
|
|
||||||
debug!("get_recent_blockhash rpc request received");
|
|
||||||
Ok(meta.get_recent_blockhash(commitment))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_fees(
|
|
||||||
&self,
|
|
||||||
meta: Self::Metadata,
|
|
||||||
commitment: Option<CommitmentConfig>,
|
|
||||||
) -> Result<RpcResponse<RpcFees>> {
|
|
||||||
debug!("get_fees rpc request received");
|
|
||||||
Ok(meta.get_fees(commitment))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_fee_calculator_for_blockhash(
|
|
||||||
&self,
|
|
||||||
meta: Self::Metadata,
|
|
||||||
blockhash: String,
|
|
||||||
commitment: Option<CommitmentConfig>,
|
|
||||||
) -> Result<RpcResponse<Option<RpcFeeCalculator>>> {
|
|
||||||
debug!("get_fee_calculator_for_blockhash rpc request received");
|
|
||||||
let blockhash = Hash::from_str(&blockhash)
|
|
||||||
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?;
|
|
||||||
Ok(meta.get_fee_calculator_for_blockhash(&blockhash, commitment))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_fee_rate_governor(
|
|
||||||
&self,
|
|
||||||
meta: Self::Metadata,
|
|
||||||
) -> Result<RpcResponse<RpcFeeRateGovernor>> {
|
|
||||||
debug!("get_fee_rate_governor rpc request received");
|
|
||||||
Ok(meta.get_fee_rate_governor())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_slot_leader(
|
fn get_slot_leader(
|
||||||
&self,
|
&self,
|
||||||
meta: Self::Metadata,
|
meta: Self::Metadata,
|
||||||
|
@ -3084,6 +3063,31 @@ pub mod rpc_full {
|
||||||
|
|
||||||
#[rpc(meta, name = "getFirstAvailableBlock")]
|
#[rpc(meta, name = "getFirstAvailableBlock")]
|
||||||
fn get_first_available_block(&self, meta: Self::Metadata) -> BoxFuture<Result<Slot>>;
|
fn get_first_available_block(&self, meta: Self::Metadata) -> BoxFuture<Result<Slot>>;
|
||||||
|
|
||||||
|
#[rpc(meta, name = "getLatestBlockhash")]
|
||||||
|
fn get_latest_blockhash(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<RpcBlockhash>>;
|
||||||
|
|
||||||
|
#[rpc(meta, name = "isBlockhashValid")]
|
||||||
|
fn is_blockhash_valid(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
blockhash: String,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<bool>>;
|
||||||
|
|
||||||
|
#[rpc(meta, name = "getFeeForMessage")]
|
||||||
|
fn get_fee_for_message(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
blockhash: String,
|
||||||
|
data: String,
|
||||||
|
encoding: UiTransactionEncoding,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<Option<u64>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FullImpl;
|
pub struct FullImpl;
|
||||||
|
@ -3232,7 +3236,7 @@ pub mod rpc_full {
|
||||||
let blockhash = if let Some(blockhash) = config.recent_blockhash {
|
let blockhash = if let Some(blockhash) = config.recent_blockhash {
|
||||||
verify_hash(&blockhash)?
|
verify_hash(&blockhash)?
|
||||||
} else {
|
} else {
|
||||||
bank.confirmed_last_blockhash().0
|
bank.confirmed_last_blockhash()
|
||||||
};
|
};
|
||||||
let last_valid_block_height = bank
|
let last_valid_block_height = bank
|
||||||
.get_blockhash_last_valid_block_height(&blockhash)
|
.get_blockhash_last_valid_block_height(&blockhash)
|
||||||
|
@ -3269,7 +3273,8 @@ pub mod rpc_full {
|
||||||
debug!("send_transaction rpc request received");
|
debug!("send_transaction rpc request received");
|
||||||
let config = config.unwrap_or_default();
|
let config = config.unwrap_or_default();
|
||||||
let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58);
|
let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58);
|
||||||
let (wire_transaction, transaction) = deserialize_transaction(data, encoding)?;
|
let (wire_transaction, transaction) =
|
||||||
|
decode_and_deserialize::<Transaction>(data, encoding)?;
|
||||||
|
|
||||||
let preflight_commitment = config
|
let preflight_commitment = config
|
||||||
.preflight_commitment
|
.preflight_commitment
|
||||||
|
@ -3369,7 +3374,7 @@ pub mod rpc_full {
|
||||||
debug!("simulate_transaction rpc request received");
|
debug!("simulate_transaction rpc request received");
|
||||||
let config = config.unwrap_or_default();
|
let config = config.unwrap_or_default();
|
||||||
let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58);
|
let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58);
|
||||||
let (_, mut transaction) = deserialize_transaction(data, encoding)?;
|
let (_, mut transaction) = decode_and_deserialize::<Transaction>(data, encoding)?;
|
||||||
|
|
||||||
let bank = &*meta.bank(config.commitment);
|
let bank = &*meta.bank(config.commitment);
|
||||||
if config.sig_verify {
|
if config.sig_verify {
|
||||||
|
@ -3578,10 +3583,126 @@ pub mod rpc_full {
|
||||||
|
|
||||||
Box::pin(async move { meta.get_inflation_reward(addresses, config).await })
|
Box::pin(async move { meta.get_inflation_reward(addresses, config).await })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_latest_blockhash(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<RpcBlockhash>> {
|
||||||
|
debug!("get_latest_blockhash rpc request received");
|
||||||
|
Ok(meta.get_latest_blockhash(commitment))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_blockhash_valid(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
blockhash: String,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<bool>> {
|
||||||
|
let blockhash = Hash::from_str(&blockhash)
|
||||||
|
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?;
|
||||||
|
Ok(meta.is_blockhash_valid(&blockhash, commitment))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_fee_for_message(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
blockhash: String,
|
||||||
|
data: String,
|
||||||
|
encoding: UiTransactionEncoding,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<Option<u64>>> {
|
||||||
|
debug!("get_fee_for_message rpc request received");
|
||||||
|
let blockhash = Hash::from_str(&blockhash)
|
||||||
|
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?;
|
||||||
|
let (_, message) = decode_and_deserialize::<Message>(data, encoding)?;
|
||||||
|
meta.get_fee_for_message(&blockhash, &message, commitment)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated RPC methods, collected for easy deactivation and removal in v1.8
|
// RPC methods deprecated in v1.8
|
||||||
|
pub mod rpc_deprecated_v1_8 {
|
||||||
|
#![allow(deprecated)]
|
||||||
|
use super::*;
|
||||||
|
#[rpc]
|
||||||
|
pub trait DeprecatedV1_8 {
|
||||||
|
type Metadata;
|
||||||
|
|
||||||
|
#[rpc(meta, name = "getRecentBlockhash")]
|
||||||
|
fn get_recent_blockhash(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<RpcBlockhashFeeCalculator>>;
|
||||||
|
|
||||||
|
#[rpc(meta, name = "getFees")]
|
||||||
|
fn get_fees(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<RpcFees>>;
|
||||||
|
|
||||||
|
#[rpc(meta, name = "getFeeCalculatorForBlockhash")]
|
||||||
|
fn get_fee_calculator_for_blockhash(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
blockhash: String,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<Option<RpcFeeCalculator>>>;
|
||||||
|
|
||||||
|
#[rpc(meta, name = "getFeeRateGovernor")]
|
||||||
|
fn get_fee_rate_governor(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
) -> Result<RpcResponse<RpcFeeRateGovernor>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DeprecatedV1_8Impl;
|
||||||
|
impl DeprecatedV1_8 for DeprecatedV1_8Impl {
|
||||||
|
type Metadata = JsonRpcRequestProcessor;
|
||||||
|
|
||||||
|
fn get_recent_blockhash(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<RpcBlockhashFeeCalculator>> {
|
||||||
|
debug!("get_recent_blockhash rpc request received");
|
||||||
|
Ok(meta.get_recent_blockhash(commitment))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_fees(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<RpcFees>> {
|
||||||
|
debug!("get_fees rpc request received");
|
||||||
|
Ok(meta.get_fees(commitment))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_fee_calculator_for_blockhash(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
blockhash: String,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<RpcResponse<Option<RpcFeeCalculator>>> {
|
||||||
|
debug!("get_fee_calculator_for_blockhash rpc request received");
|
||||||
|
let blockhash = Hash::from_str(&blockhash)
|
||||||
|
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?;
|
||||||
|
Ok(meta.get_fee_calculator_for_blockhash(&blockhash, commitment))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_fee_rate_governor(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
) -> Result<RpcResponse<RpcFeeRateGovernor>> {
|
||||||
|
debug!("get_fee_rate_governor rpc request received");
|
||||||
|
Ok(meta.get_fee_rate_governor())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPC methods deprecated in v1.7
|
||||||
pub mod rpc_deprecated_v1_7 {
|
pub mod rpc_deprecated_v1_7 {
|
||||||
#![allow(deprecated)]
|
#![allow(deprecated)]
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -3874,51 +3995,56 @@ pub mod rpc_obsolete_v1_7 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const WORST_CASE_BASE58_TX: usize = 1683; // Golden, bump if PACKET_DATA_SIZE changes
|
const MAX_BASE58_SIZE: usize = 1683; // Golden, bump if PACKET_DATA_SIZE changes
|
||||||
const WORST_CASE_BASE64_TX: usize = 1644; // Golden, bump if PACKET_DATA_SIZE changes
|
const MAX_BASE64_SIZE: usize = 1644; // Golden, bump if PACKET_DATA_SIZE changes
|
||||||
fn deserialize_transaction(
|
fn decode_and_deserialize<T>(
|
||||||
encoded_transaction: String,
|
encoded: String,
|
||||||
encoding: UiTransactionEncoding,
|
encoding: UiTransactionEncoding,
|
||||||
) -> Result<(Vec<u8>, Transaction)> {
|
) -> Result<(Vec<u8>, T)>
|
||||||
let wire_transaction = match encoding {
|
where
|
||||||
|
T: serde::de::DeserializeOwned + Sanitize,
|
||||||
|
{
|
||||||
|
let wire_output = match encoding {
|
||||||
UiTransactionEncoding::Base58 => {
|
UiTransactionEncoding::Base58 => {
|
||||||
inc_new_counter_info!("rpc-base58_encoded_tx", 1);
|
inc_new_counter_info!("rpc-base58_encoded_tx", 1);
|
||||||
if encoded_transaction.len() > WORST_CASE_BASE58_TX {
|
if encoded.len() > MAX_BASE58_SIZE {
|
||||||
return Err(Error::invalid_params(format!(
|
return Err(Error::invalid_params(format!(
|
||||||
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})",
|
"encoded {} too large: {} bytes (max: encoded/raw {}/{})",
|
||||||
encoded_transaction.len(),
|
type_name::<T>(),
|
||||||
WORST_CASE_BASE58_TX,
|
encoded.len(),
|
||||||
|
MAX_BASE58_SIZE,
|
||||||
PACKET_DATA_SIZE,
|
PACKET_DATA_SIZE,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
bs58::decode(encoded_transaction)
|
bs58::decode(encoded)
|
||||||
.into_vec()
|
.into_vec()
|
||||||
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?
|
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?
|
||||||
}
|
}
|
||||||
UiTransactionEncoding::Base64 => {
|
UiTransactionEncoding::Base64 => {
|
||||||
inc_new_counter_info!("rpc-base64_encoded_tx", 1);
|
inc_new_counter_info!("rpc-base64_encoded_tx", 1);
|
||||||
if encoded_transaction.len() > WORST_CASE_BASE64_TX {
|
if encoded.len() > MAX_BASE64_SIZE {
|
||||||
return Err(Error::invalid_params(format!(
|
return Err(Error::invalid_params(format!(
|
||||||
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})",
|
"encoded {} too large: {} bytes (max: encoded/raw {}/{})",
|
||||||
encoded_transaction.len(),
|
type_name::<T>(),
|
||||||
WORST_CASE_BASE64_TX,
|
encoded.len(),
|
||||||
|
MAX_BASE64_SIZE,
|
||||||
PACKET_DATA_SIZE,
|
PACKET_DATA_SIZE,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
base64::decode(encoded_transaction)
|
base64::decode(encoded).map_err(|e| Error::invalid_params(format!("{:?}", e)))?
|
||||||
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::invalid_params(format!(
|
return Err(Error::invalid_params(format!(
|
||||||
"unsupported transaction encoding: {}. Supported encodings: base58, base64",
|
"unsupported encoding: {}. Supported encodings: base58, base64",
|
||||||
encoding
|
encoding
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if wire_transaction.len() > PACKET_DATA_SIZE {
|
if wire_output.len() > PACKET_DATA_SIZE {
|
||||||
let err = format!(
|
let err = format!(
|
||||||
"transaction too large: {} bytes (max: {} bytes)",
|
"encoded {} too large: {} bytes (max: {} bytes)",
|
||||||
wire_transaction.len(),
|
type_name::<T>(),
|
||||||
|
wire_output.len(),
|
||||||
PACKET_DATA_SIZE
|
PACKET_DATA_SIZE
|
||||||
);
|
);
|
||||||
info!("{}", err);
|
info!("{}", err);
|
||||||
|
@ -3928,22 +4054,23 @@ fn deserialize_transaction(
|
||||||
.with_limit(PACKET_DATA_SIZE as u64)
|
.with_limit(PACKET_DATA_SIZE as u64)
|
||||||
.with_fixint_encoding()
|
.with_fixint_encoding()
|
||||||
.allow_trailing_bytes()
|
.allow_trailing_bytes()
|
||||||
.deserialize_from(&wire_transaction[..])
|
.deserialize_from(&wire_output[..])
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
info!("transaction deserialize error: {:?}", err);
|
info!("deserialize error: {}", err);
|
||||||
Error::invalid_params(&err.to_string())
|
Error::invalid_params(&err.to_string())
|
||||||
})
|
})
|
||||||
.and_then(|transaction: Transaction| {
|
.and_then(|output: T| {
|
||||||
if let Err(err) = transaction.sanitize() {
|
if let Err(err) = output.sanitize() {
|
||||||
Err(Error::invalid_params(format!(
|
Err(Error::invalid_params(format!(
|
||||||
"invalid transaction: {}",
|
"invalid {}: {}",
|
||||||
|
type_name::<T>(),
|
||||||
err
|
err
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
Ok(transaction)
|
Ok(output)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map(|transaction| (wire_transaction, transaction))
|
.map(|output| (wire_output, output))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn create_validator_exit(exit: &Arc<AtomicBool>) -> Arc<RwLock<Exit>> {
|
pub(crate) fn create_validator_exit(exit: &Arc<AtomicBool>) -> Arc<RwLock<Exit>> {
|
||||||
|
@ -3966,7 +4093,7 @@ pub fn create_test_transactions_and_populate_blockstore(
|
||||||
let keypair2 = keypairs[2];
|
let keypair2 = keypairs[2];
|
||||||
let keypair3 = keypairs[3];
|
let keypair3 = keypairs[3];
|
||||||
let slot = bank.slot();
|
let slot = bank.slot();
|
||||||
let blockhash = bank.confirmed_last_blockhash().0;
|
let blockhash = bank.confirmed_last_blockhash();
|
||||||
|
|
||||||
// Generate transactions for processing
|
// Generate transactions for processing
|
||||||
// Successful transaction
|
// Successful transaction
|
||||||
|
@ -4032,7 +4159,9 @@ pub fn create_test_transactions_and_populate_blockstore(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use {
|
use {
|
||||||
super::{rpc_accounts::*, rpc_bank::*, rpc_full::*, rpc_minimal::*, *},
|
super::{
|
||||||
|
rpc_accounts::*, rpc_bank::*, rpc_deprecated_v1_8::*, rpc_full::*, rpc_minimal::*, *,
|
||||||
|
},
|
||||||
crate::{
|
crate::{
|
||||||
optimistically_confirmed_bank_tracker::{
|
optimistically_confirmed_bank_tracker::{
|
||||||
BankNotification, OptimisticallyConfirmedBankTracker,
|
BankNotification, OptimisticallyConfirmedBankTracker,
|
||||||
|
@ -4196,7 +4325,7 @@ pub mod tests {
|
||||||
let exit = Arc::new(AtomicBool::new(false));
|
let exit = Arc::new(AtomicBool::new(false));
|
||||||
let validator_exit = create_validator_exit(&exit);
|
let validator_exit = create_validator_exit(&exit);
|
||||||
|
|
||||||
let blockhash = bank.confirmed_last_blockhash().0;
|
let blockhash = bank.confirmed_last_blockhash();
|
||||||
let tx = system_transaction::transfer(&alice, pubkey, 20, blockhash);
|
let tx = system_transaction::transfer(&alice, pubkey, 20, blockhash);
|
||||||
bank.process_transaction(&tx).expect("process transaction");
|
bank.process_transaction(&tx).expect("process transaction");
|
||||||
let tx =
|
let tx =
|
||||||
|
@ -4267,6 +4396,7 @@ pub mod tests {
|
||||||
io.extend_with(rpc_bank::BankDataImpl.to_delegate());
|
io.extend_with(rpc_bank::BankDataImpl.to_delegate());
|
||||||
io.extend_with(rpc_accounts::AccountsDataImpl.to_delegate());
|
io.extend_with(rpc_accounts::AccountsDataImpl.to_delegate());
|
||||||
io.extend_with(rpc_full::FullImpl.to_delegate());
|
io.extend_with(rpc_full::FullImpl.to_delegate());
|
||||||
|
io.extend_with(rpc_deprecated_v1_8::DeprecatedV1_8Impl.to_delegate());
|
||||||
RpcHandler {
|
RpcHandler {
|
||||||
io,
|
io,
|
||||||
meta,
|
meta,
|
||||||
|
@ -5675,6 +5805,7 @@ pub mod tests {
|
||||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator();
|
let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator();
|
||||||
let fee_calculator = RpcFeeCalculator { fee_calculator };
|
let fee_calculator = RpcFeeCalculator { fee_calculator };
|
||||||
|
|
||||||
|
@ -5855,7 +5986,7 @@ pub mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res,
|
res,
|
||||||
Some(
|
Some(
|
||||||
r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid transaction: index out of bounds"},"id":1}"#.to_string(),
|
r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid solana_sdk::transaction::Transaction: index out of bounds"},"id":1}"#.to_string(),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
let mut bad_transaction = system_transaction::transfer(
|
let mut bad_transaction = system_transaction::transfer(
|
||||||
|
@ -5919,7 +6050,7 @@ pub mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res,
|
res,
|
||||||
Some(
|
Some(
|
||||||
r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid transaction: index out of bounds"},"id":1}"#.to_string(),
|
r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid solana_sdk::transaction::Transaction: index out of bounds"},"id":1}"#.to_string(),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7615,66 +7746,68 @@ pub mod tests {
|
||||||
fn test_worst_case_encoded_tx_goldens() {
|
fn test_worst_case_encoded_tx_goldens() {
|
||||||
let ff_tx = vec![0xffu8; PACKET_DATA_SIZE];
|
let ff_tx = vec![0xffu8; PACKET_DATA_SIZE];
|
||||||
let tx58 = bs58::encode(&ff_tx).into_string();
|
let tx58 = bs58::encode(&ff_tx).into_string();
|
||||||
assert_eq!(tx58.len(), WORST_CASE_BASE58_TX);
|
assert_eq!(tx58.len(), MAX_BASE58_SIZE);
|
||||||
let tx64 = base64::encode(&ff_tx);
|
let tx64 = base64::encode(&ff_tx);
|
||||||
assert_eq!(tx64.len(), WORST_CASE_BASE64_TX);
|
assert_eq!(tx64.len(), MAX_BASE64_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deserialize_transaction_too_large_payloads_fail() {
|
fn test_decode_and_deserialize_too_large_payloads_fail() {
|
||||||
// +2 because +1 still fits in base64 encoded worst-case
|
// +2 because +1 still fits in base64 encoded worst-case
|
||||||
let too_big = PACKET_DATA_SIZE + 2;
|
let too_big = PACKET_DATA_SIZE + 2;
|
||||||
let tx_ser = vec![0xffu8; too_big];
|
let tx_ser = vec![0xffu8; too_big];
|
||||||
let tx58 = bs58::encode(&tx_ser).into_string();
|
let tx58 = bs58::encode(&tx_ser).into_string();
|
||||||
let tx58_len = tx58.len();
|
let tx58_len = tx58.len();
|
||||||
let expect58 = Error::invalid_params(format!(
|
let expect58 = Error::invalid_params(format!(
|
||||||
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})",
|
"encoded solana_sdk::transaction::Transaction too large: {} bytes (max: encoded/raw {}/{})",
|
||||||
tx58_len, WORST_CASE_BASE58_TX, PACKET_DATA_SIZE,
|
tx58_len, MAX_BASE58_SIZE, PACKET_DATA_SIZE,
|
||||||
));
|
));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
deserialize_transaction(tx58, UiTransactionEncoding::Base58).unwrap_err(),
|
decode_and_deserialize::<Transaction>(tx58, UiTransactionEncoding::Base58).unwrap_err(),
|
||||||
expect58
|
expect58
|
||||||
);
|
);
|
||||||
let tx64 = base64::encode(&tx_ser);
|
let tx64 = base64::encode(&tx_ser);
|
||||||
let tx64_len = tx64.len();
|
let tx64_len = tx64.len();
|
||||||
let expect64 = Error::invalid_params(format!(
|
let expect64 = Error::invalid_params(format!(
|
||||||
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})",
|
"encoded solana_sdk::transaction::Transaction too large: {} bytes (max: encoded/raw {}/{})",
|
||||||
tx64_len, WORST_CASE_BASE64_TX, PACKET_DATA_SIZE,
|
tx64_len, MAX_BASE64_SIZE, PACKET_DATA_SIZE,
|
||||||
));
|
));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
deserialize_transaction(tx64, UiTransactionEncoding::Base64).unwrap_err(),
|
decode_and_deserialize::<Transaction>(tx64, UiTransactionEncoding::Base64).unwrap_err(),
|
||||||
expect64
|
expect64
|
||||||
);
|
);
|
||||||
let too_big = PACKET_DATA_SIZE + 1;
|
let too_big = PACKET_DATA_SIZE + 1;
|
||||||
let tx_ser = vec![0x00u8; too_big];
|
let tx_ser = vec![0x00u8; too_big];
|
||||||
let tx58 = bs58::encode(&tx_ser).into_string();
|
let tx58 = bs58::encode(&tx_ser).into_string();
|
||||||
let expect = Error::invalid_params(format!(
|
let expect = Error::invalid_params(format!(
|
||||||
"transaction too large: {} bytes (max: {} bytes)",
|
"encoded solana_sdk::transaction::Transaction too large: {} bytes (max: {} bytes)",
|
||||||
too_big, PACKET_DATA_SIZE
|
too_big, PACKET_DATA_SIZE
|
||||||
));
|
));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
deserialize_transaction(tx58, UiTransactionEncoding::Base58).unwrap_err(),
|
decode_and_deserialize::<Transaction>(tx58, UiTransactionEncoding::Base58).unwrap_err(),
|
||||||
expect
|
expect
|
||||||
);
|
);
|
||||||
let tx64 = base64::encode(&tx_ser);
|
let tx64 = base64::encode(&tx_ser);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
deserialize_transaction(tx64, UiTransactionEncoding::Base64).unwrap_err(),
|
decode_and_deserialize::<Transaction>(tx64, UiTransactionEncoding::Base64).unwrap_err(),
|
||||||
expect
|
expect
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deserialize_transaction_unsanitary() {
|
fn test_decode_and_deserialize_unsanitary() {
|
||||||
let unsanitary_tx58 = "ju9xZWuDBX4pRxX2oZkTjxU5jB4SSTgEGhX8bQ8PURNzyzqKMPPpNvWihx8zUe\
|
let unsanitary_tx58 = "ju9xZWuDBX4pRxX2oZkTjxU5jB4SSTgEGhX8bQ8PURNzyzqKMPPpNvWihx8zUe\
|
||||||
FfrbVNoAaEsNKZvGzAnTDy5bhNT9kt6KFCTBixpvrLCzg4M5UdFUQYrn1gdgjX\
|
FfrbVNoAaEsNKZvGzAnTDy5bhNT9kt6KFCTBixpvrLCzg4M5UdFUQYrn1gdgjX\
|
||||||
pLHxcaShD81xBNaFDgnA2nkkdHnKtZt4hVSfKAmw3VRZbjrZ7L2fKZBx21CwsG\
|
pLHxcaShD81xBNaFDgnA2nkkdHnKtZt4hVSfKAmw3VRZbjrZ7L2fKZBx21CwsG\
|
||||||
hD6onjM2M3qZW5C8J6d1pj41MxKmZgPBSha3MyKkNLkAGFASK"
|
hD6onjM2M3qZW5C8J6d1pj41MxKmZgPBSha3MyKkNLkAGFASK"
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
let expect58 =
|
let expect58 = Error::invalid_params(
|
||||||
Error::invalid_params("invalid transaction: index out of bounds".to_string());
|
"invalid solana_sdk::transaction::Transaction: index out of bounds".to_string(),
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
deserialize_transaction(unsanitary_tx58, UiTransactionEncoding::Base58).unwrap_err(),
|
decode_and_deserialize::<Transaction>(unsanitary_tx58, UiTransactionEncoding::Base58)
|
||||||
|
.unwrap_err(),
|
||||||
expect58
|
expect58
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ use {
|
||||||
max_slots::MaxSlots,
|
max_slots::MaxSlots,
|
||||||
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
||||||
rpc::{
|
rpc::{
|
||||||
rpc_accounts::*, rpc_bank::*, rpc_deprecated_v1_7::*, rpc_full::*, rpc_minimal::*,
|
rpc_accounts::*, rpc_bank::*, rpc_deprecated_v1_7::*, rpc_deprecated_v1_8::*,
|
||||||
rpc_obsolete_v1_7::*, *,
|
rpc_full::*, rpc_minimal::*, rpc_obsolete_v1_7::*, *,
|
||||||
},
|
},
|
||||||
rpc_health::*,
|
rpc_health::*,
|
||||||
send_transaction_service::{LeaderInfo, SendTransactionService},
|
send_transaction_service::{LeaderInfo, SendTransactionService},
|
||||||
|
@ -408,6 +408,7 @@ impl JsonRpcService {
|
||||||
io.extend_with(rpc_accounts::AccountsDataImpl.to_delegate());
|
io.extend_with(rpc_accounts::AccountsDataImpl.to_delegate());
|
||||||
io.extend_with(rpc_full::FullImpl.to_delegate());
|
io.extend_with(rpc_full::FullImpl.to_delegate());
|
||||||
io.extend_with(rpc_deprecated_v1_7::DeprecatedV1_7Impl.to_delegate());
|
io.extend_with(rpc_deprecated_v1_7::DeprecatedV1_7Impl.to_delegate());
|
||||||
|
io.extend_with(rpc_deprecated_v1_8::DeprecatedV1_8Impl.to_delegate());
|
||||||
}
|
}
|
||||||
if obsolete_v1_7_api {
|
if obsolete_v1_7_api {
|
||||||
io.extend_with(rpc_obsolete_v1_7::ObsoleteV1_7Impl.to_delegate());
|
io.extend_with(rpc_obsolete_v1_7::ObsoleteV1_7Impl.to_delegate());
|
||||||
|
|
|
@ -106,9 +106,11 @@ impl TransactionStatusService {
|
||||||
let fee_calculator = nonce_rollback
|
let fee_calculator = nonce_rollback
|
||||||
.map(|nonce_rollback| nonce_rollback.fee_calculator())
|
.map(|nonce_rollback| nonce_rollback.fee_calculator())
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
|
#[allow(deprecated)]
|
||||||
bank.get_fee_calculator(&transaction.message().recent_blockhash)
|
bank.get_fee_calculator(&transaction.message().recent_blockhash)
|
||||||
})
|
})
|
||||||
.expect("FeeCalculator must exist");
|
.expect("FeeCalculator must exist");
|
||||||
|
#[allow(deprecated)]
|
||||||
let fee = fee_calculator.calculate_fee(transaction.message());
|
let fee = fee_calculator.calculate_fee(transaction.message());
|
||||||
let (writable_keys, readonly_keys) =
|
let (writable_keys, readonly_keys) =
|
||||||
transaction.message.get_account_keys_by_lock_type();
|
transaction.message.get_account_keys_by_lock_type();
|
||||||
|
|
|
@ -54,7 +54,7 @@ pub fn create_builtin_transactions(
|
||||||
.unwrap_or_else(|_| panic!("{}:{}", line!(), file!()));
|
.unwrap_or_else(|_| panic!("{}:{}", line!(), file!()));
|
||||||
|
|
||||||
let instruction = create_invoke_instruction(rando0.pubkey(), program_id, &1u8);
|
let instruction = create_invoke_instruction(rando0.pubkey(), program_id, &1u8);
|
||||||
let (blockhash, _fee_calculator) = bank_client.get_recent_blockhash().unwrap();
|
let blockhash = bank_client.get_latest_blockhash().unwrap();
|
||||||
let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
|
let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
|
||||||
Transaction::new(&[&rando0], message, blockhash)
|
Transaction::new(&[&rando0], message, blockhash)
|
||||||
})
|
})
|
||||||
|
@ -76,7 +76,7 @@ pub fn create_native_loader_transactions(
|
||||||
.unwrap_or_else(|_| panic!("{}:{}", line!(), file!()));
|
.unwrap_or_else(|_| panic!("{}:{}", line!(), file!()));
|
||||||
|
|
||||||
let instruction = create_invoke_instruction(rando0.pubkey(), program_id, &1u8);
|
let instruction = create_invoke_instruction(rando0.pubkey(), program_id, &1u8);
|
||||||
let (blockhash, _fee_calculator) = bank_client.get_recent_blockhash().unwrap();
|
let blockhash = bank_client.get_latest_blockhash().unwrap();
|
||||||
let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
|
let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
|
||||||
Transaction::new(&[&rando0], message, blockhash)
|
Transaction::new(&[&rando0], message, blockhash)
|
||||||
})
|
})
|
||||||
|
|
|
@ -450,11 +450,13 @@ impl Accounts {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|nonce_rollback| nonce_rollback.fee_calculator())
|
.map(|nonce_rollback| nonce_rollback.fee_calculator())
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
|
#[allow(deprecated)]
|
||||||
hash_queue
|
hash_queue
|
||||||
.get_fee_calculator(&tx.message().recent_blockhash)
|
.get_fee_calculator(&tx.message().recent_blockhash)
|
||||||
.cloned()
|
.cloned()
|
||||||
});
|
});
|
||||||
let fee = if let Some(fee_calculator) = fee_calculator {
|
let fee = if let Some(fee_calculator) = fee_calculator {
|
||||||
|
#[allow(deprecated)]
|
||||||
fee_calculator.calculate_fee(tx.message())
|
fee_calculator.calculate_fee(tx.message())
|
||||||
} else {
|
} else {
|
||||||
return (Err(TransactionError::BlockhashNotFound), None);
|
return (Err(TransactionError::BlockhashNotFound), None);
|
||||||
|
@ -1292,7 +1294,9 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let fee_calculator = FeeCalculator::new(10);
|
let fee_calculator = FeeCalculator::new(10);
|
||||||
assert_eq!(fee_calculator.calculate_fee(tx.message()), 10);
|
#[allow(deprecated)]
|
||||||
|
let fee = fee_calculator.calculate_fee(tx.message());
|
||||||
|
assert_eq!(fee, 10);
|
||||||
|
|
||||||
let loaded_accounts =
|
let loaded_accounts =
|
||||||
load_accounts_with_fee(tx, &accounts, &fee_calculator, &mut error_counters);
|
load_accounts_with_fee(tx, &accounts, &fee_calculator, &mut error_counters);
|
||||||
|
|
|
@ -2667,15 +2667,25 @@ impl Bank {
|
||||||
self.blockhash_queue.read().unwrap().last_hash()
|
self.blockhash_queue.read().unwrap().last_hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_blockhash_valid(&self, hash: &Hash) -> bool {
|
||||||
|
let blockhash_queue = self.blockhash_queue.read().unwrap();
|
||||||
|
blockhash_queue.check_hash(hash)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> u64 {
|
pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> u64 {
|
||||||
self.rent_collector.rent.minimum_balance(data_len)
|
self.rent_collector.rent.minimum_balance(data_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please use `last_blockhash` and `get_fee_for_message` instead"
|
||||||
|
)]
|
||||||
pub fn last_blockhash_with_fee_calculator(&self) -> (Hash, FeeCalculator) {
|
pub fn last_blockhash_with_fee_calculator(&self) -> (Hash, FeeCalculator) {
|
||||||
let blockhash_queue = self.blockhash_queue.read().unwrap();
|
let blockhash_queue = self.blockhash_queue.read().unwrap();
|
||||||
let last_hash = blockhash_queue.last_hash();
|
let last_hash = blockhash_queue.last_hash();
|
||||||
(
|
(
|
||||||
last_hash,
|
last_hash,
|
||||||
|
#[allow(deprecated)]
|
||||||
blockhash_queue
|
blockhash_queue
|
||||||
.get_fee_calculator(&last_hash)
|
.get_fee_calculator(&last_hash)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -2683,15 +2693,26 @@ impl Bank {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.8.0", note = "Please use `get_fee_for_message` instead")]
|
||||||
pub fn get_fee_calculator(&self, hash: &Hash) -> Option<FeeCalculator> {
|
pub fn get_fee_calculator(&self, hash: &Hash) -> Option<FeeCalculator> {
|
||||||
let blockhash_queue = self.blockhash_queue.read().unwrap();
|
let blockhash_queue = self.blockhash_queue.read().unwrap();
|
||||||
|
#[allow(deprecated)]
|
||||||
blockhash_queue.get_fee_calculator(hash).cloned()
|
blockhash_queue.get_fee_calculator(hash).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.8.0", note = "Please use `get_fee_for_message` instead")]
|
||||||
pub fn get_fee_rate_governor(&self) -> &FeeRateGovernor {
|
pub fn get_fee_rate_governor(&self) -> &FeeRateGovernor {
|
||||||
&self.fee_rate_governor
|
&self.fee_rate_governor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_fee_for_message(&self, hash: &Hash, message: &Message) -> Option<u64> {
|
||||||
|
let blockhash_queue = self.blockhash_queue.read().unwrap();
|
||||||
|
#[allow(deprecated)]
|
||||||
|
let fee_calculator = blockhash_queue.get_fee_calculator(hash)?;
|
||||||
|
#[allow(deprecated)]
|
||||||
|
Some(fee_calculator.calculate_fee(message))
|
||||||
|
}
|
||||||
|
|
||||||
#[deprecated(
|
#[deprecated(
|
||||||
since = "1.6.11",
|
since = "1.6.11",
|
||||||
note = "Please use `get_blockhash_last_valid_block_height`"
|
note = "Please use `get_blockhash_last_valid_block_height`"
|
||||||
|
@ -2714,18 +2735,36 @@ impl Bank {
|
||||||
.map(|age| self.block_height + blockhash_queue.len() as u64 - age)
|
.map(|age| self.block_height + blockhash_queue.len() as u64 - age)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn confirmed_last_blockhash(&self) -> (Hash, FeeCalculator) {
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please use `confirmed_last_blockhash` and `get_fee_for_message` instead"
|
||||||
|
)]
|
||||||
|
pub fn confirmed_last_blockhash_with_fee_calculator(&self) -> (Hash, FeeCalculator) {
|
||||||
const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
|
const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
|
||||||
|
|
||||||
let parents = self.parents();
|
let parents = self.parents();
|
||||||
if parents.is_empty() {
|
if parents.is_empty() {
|
||||||
|
#[allow(deprecated)]
|
||||||
self.last_blockhash_with_fee_calculator()
|
self.last_blockhash_with_fee_calculator()
|
||||||
} else {
|
} else {
|
||||||
let index = NUM_BLOCKHASH_CONFIRMATIONS.min(parents.len() - 1);
|
let index = NUM_BLOCKHASH_CONFIRMATIONS.min(parents.len() - 1);
|
||||||
|
#[allow(deprecated)]
|
||||||
parents[index].last_blockhash_with_fee_calculator()
|
parents[index].last_blockhash_with_fee_calculator()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn confirmed_last_blockhash(&self) -> Hash {
|
||||||
|
const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
|
||||||
|
|
||||||
|
let parents = self.parents();
|
||||||
|
if parents.is_empty() {
|
||||||
|
self.last_blockhash()
|
||||||
|
} else {
|
||||||
|
let index = NUM_BLOCKHASH_CONFIRMATIONS.min(parents.len() - 1);
|
||||||
|
parents[index].last_blockhash()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Forget all signatures. Useful for benchmarking.
|
/// Forget all signatures. Useful for benchmarking.
|
||||||
pub fn clear_signatures(&self) {
|
pub fn clear_signatures(&self) {
|
||||||
self.src.status_cache.write().unwrap().clear();
|
self.src.status_cache.write().unwrap().clear();
|
||||||
|
@ -3400,6 +3439,7 @@ impl Bank {
|
||||||
let blockhash = blockhash_queue.last_hash();
|
let blockhash = blockhash_queue.last_hash();
|
||||||
(
|
(
|
||||||
blockhash,
|
blockhash,
|
||||||
|
#[allow(deprecated)]
|
||||||
blockhash_queue
|
blockhash_queue
|
||||||
.get_fee_calculator(&blockhash)
|
.get_fee_calculator(&blockhash)
|
||||||
.cloned()
|
.cloned()
|
||||||
|
@ -3582,6 +3622,7 @@ impl Bank {
|
||||||
.map(|maybe_fee_calculator| (maybe_fee_calculator, true))
|
.map(|maybe_fee_calculator| (maybe_fee_calculator, true))
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
(
|
(
|
||||||
|
#[allow(deprecated)]
|
||||||
hash_queue
|
hash_queue
|
||||||
.get_fee_calculator(&tx.message().recent_blockhash)
|
.get_fee_calculator(&tx.message().recent_blockhash)
|
||||||
.cloned(),
|
.cloned(),
|
||||||
|
@ -3590,6 +3631,7 @@ impl Bank {
|
||||||
});
|
});
|
||||||
let fee_calculator = fee_calculator.ok_or(TransactionError::BlockhashNotFound)?;
|
let fee_calculator = fee_calculator.ok_or(TransactionError::BlockhashNotFound)?;
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
let fee = fee_calculator.calculate_fee(tx.message());
|
let fee = fee_calculator.calculate_fee(tx.message());
|
||||||
|
|
||||||
let message = tx.message();
|
let message = tx.message();
|
||||||
|
@ -3658,6 +3700,7 @@ impl Bank {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut write_time = Measure::start("write_time");
|
let mut write_time = Measure::start("write_time");
|
||||||
|
#[allow(deprecated)]
|
||||||
self.rc.accounts.store_cached(
|
self.rc.accounts.store_cached(
|
||||||
self.slot(),
|
self.slot(),
|
||||||
sanitized_txs.as_transactions_iter(),
|
sanitized_txs.as_transactions_iter(),
|
||||||
|
@ -8304,11 +8347,13 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
let mut bank = Bank::new_for_tests(&genesis_config);
|
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||||
goto_end_of_slot(&mut bank);
|
goto_end_of_slot(&mut bank);
|
||||||
|
#[allow(deprecated)]
|
||||||
let (cheap_blockhash, cheap_fee_calculator) = bank.last_blockhash_with_fee_calculator();
|
let (cheap_blockhash, cheap_fee_calculator) = bank.last_blockhash_with_fee_calculator();
|
||||||
assert_eq!(cheap_fee_calculator.lamports_per_signature, 0);
|
assert_eq!(cheap_fee_calculator.lamports_per_signature, 0);
|
||||||
|
|
||||||
let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
|
let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
|
||||||
goto_end_of_slot(&mut bank);
|
goto_end_of_slot(&mut bank);
|
||||||
|
#[allow(deprecated)]
|
||||||
let (expensive_blockhash, expensive_fee_calculator) =
|
let (expensive_blockhash, expensive_fee_calculator) =
|
||||||
bank.last_blockhash_with_fee_calculator();
|
bank.last_blockhash_with_fee_calculator();
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
@ -148,6 +148,7 @@ impl SyncClient for BankClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)> {
|
fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)> {
|
||||||
|
#[allow(deprecated)]
|
||||||
Ok(self.bank.last_blockhash_with_fee_calculator())
|
Ok(self.bank.last_blockhash_with_fee_calculator())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +156,7 @@ impl SyncClient for BankClient {
|
||||||
&self,
|
&self,
|
||||||
_commitment_config: CommitmentConfig,
|
_commitment_config: CommitmentConfig,
|
||||||
) -> Result<(Hash, FeeCalculator, u64)> {
|
) -> Result<(Hash, FeeCalculator, u64)> {
|
||||||
|
#[allow(deprecated)]
|
||||||
let (blockhash, fee_calculator) = self.bank.last_blockhash_with_fee_calculator();
|
let (blockhash, fee_calculator) = self.bank.last_blockhash_with_fee_calculator();
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
let last_valid_slot = self
|
let last_valid_slot = self
|
||||||
|
@ -165,10 +167,12 @@ impl SyncClient for BankClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_fee_calculator_for_blockhash(&self, blockhash: &Hash) -> Result<Option<FeeCalculator>> {
|
fn get_fee_calculator_for_blockhash(&self, blockhash: &Hash) -> Result<Option<FeeCalculator>> {
|
||||||
|
#[allow(deprecated)]
|
||||||
Ok(self.bank.get_fee_calculator(blockhash))
|
Ok(self.bank.get_fee_calculator(blockhash))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_fee_rate_governor(&self) -> Result<FeeRateGovernor> {
|
fn get_fee_rate_governor(&self) -> Result<FeeRateGovernor> {
|
||||||
|
#[allow(deprecated)]
|
||||||
Ok(self.bank.get_fee_rate_governor().clone())
|
Ok(self.bank.get_fee_rate_governor().clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,9 +262,10 @@ impl SyncClient for BankClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_new_blockhash(&self, blockhash: &Hash) -> Result<(Hash, FeeCalculator)> {
|
fn get_new_blockhash(&self, blockhash: &Hash) -> Result<(Hash, FeeCalculator)> {
|
||||||
let (last_blockhash, fee_calculator) = self.get_recent_blockhash()?;
|
#[allow(deprecated)]
|
||||||
if last_blockhash != *blockhash {
|
let (recent_blockhash, fee_calculator) = self.get_recent_blockhash()?;
|
||||||
Ok((last_blockhash, fee_calculator))
|
if recent_blockhash != *blockhash {
|
||||||
|
Ok((recent_blockhash, fee_calculator))
|
||||||
} else {
|
} else {
|
||||||
Err(TransportError::IoError(io::Error::new(
|
Err(TransportError::IoError(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
|
@ -272,6 +277,53 @@ impl SyncClient for BankClient {
|
||||||
fn get_epoch_info(&self) -> Result<EpochInfo> {
|
fn get_epoch_info(&self) -> Result<EpochInfo> {
|
||||||
Ok(self.bank.get_epoch_info())
|
Ok(self.bank.get_epoch_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_latest_blockhash(&self) -> Result<Hash> {
|
||||||
|
Ok(self.bank.last_blockhash())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_latest_blockhash_with_commitment(
|
||||||
|
&self,
|
||||||
|
_commitment_config: CommitmentConfig,
|
||||||
|
) -> Result<(Hash, u64)> {
|
||||||
|
let blockhash = self.bank.last_blockhash();
|
||||||
|
let last_valid_block_height = self
|
||||||
|
.bank
|
||||||
|
.get_blockhash_last_valid_block_height(&blockhash)
|
||||||
|
.expect("bank blockhash queue should contain blockhash");
|
||||||
|
Ok((blockhash, last_valid_block_height))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_blockhash_valid(
|
||||||
|
&self,
|
||||||
|
blockhash: &Hash,
|
||||||
|
_commitment_config: CommitmentConfig,
|
||||||
|
) -> Result<bool> {
|
||||||
|
Ok(self.bank.is_blockhash_valid(blockhash))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_fee_for_message(&self, blockhash: &Hash, message: &Message) -> Result<u64> {
|
||||||
|
self.bank
|
||||||
|
.get_fee_for_message(blockhash, message)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
TransportError::IoError(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
"Unable calculate fee",
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_new_latest_blockhash(&self, blockhash: &Hash) -> Result<Hash> {
|
||||||
|
let latest_blockhash = self.get_latest_blockhash()?;
|
||||||
|
if latest_blockhash != *blockhash {
|
||||||
|
Ok(latest_blockhash)
|
||||||
|
} else {
|
||||||
|
Err(TransportError::IoError(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
"Unable to get new blockhash",
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BankClient {
|
impl BankClient {
|
||||||
|
|
|
@ -46,6 +46,10 @@ impl BlockhashQueue {
|
||||||
self.last_hash.expect("no hash has been set")
|
self.last_hash.expect("no hash has been set")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please do not use, will no longer be available in the future"
|
||||||
|
)]
|
||||||
pub fn get_fee_calculator(&self, hash: &Hash) -> Option<&FeeCalculator> {
|
pub fn get_fee_calculator(&self, hash: &Hash) -> Option<&FeeCalculator> {
|
||||||
self.ages.get(hash).map(|hash_age| &hash_age.fee_calculator)
|
self.ages.get(hash).map(|hash_age| &hash_age.fee_calculator)
|
||||||
}
|
}
|
||||||
|
@ -66,9 +70,8 @@ impl BlockhashQueue {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// check if hash is valid
|
/// check if hash is valid
|
||||||
#[cfg(test)]
|
pub fn check_hash(&self, hash: &Hash) -> bool {
|
||||||
pub fn check_hash(&self, hash: Hash) -> bool {
|
self.ages.get(hash).is_some()
|
||||||
self.ages.get(&hash).is_some()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn genesis_hash(&mut self, hash: &Hash, fee_calculator: &FeeCalculator) {
|
pub fn genesis_hash(&mut self, hash: &Hash, fee_calculator: &FeeCalculator) {
|
||||||
|
@ -148,9 +151,9 @@ mod tests {
|
||||||
fn test_register_hash() {
|
fn test_register_hash() {
|
||||||
let last_hash = Hash::default();
|
let last_hash = Hash::default();
|
||||||
let mut hash_queue = BlockhashQueue::new(100);
|
let mut hash_queue = BlockhashQueue::new(100);
|
||||||
assert!(!hash_queue.check_hash(last_hash));
|
assert!(!hash_queue.check_hash(&last_hash));
|
||||||
hash_queue.register_hash(&last_hash, &FeeCalculator::default());
|
hash_queue.register_hash(&last_hash, &FeeCalculator::default());
|
||||||
assert!(hash_queue.check_hash(last_hash));
|
assert!(hash_queue.check_hash(&last_hash));
|
||||||
assert_eq!(hash_queue.hash_height(), 1);
|
assert_eq!(hash_queue.hash_height(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,12 +166,12 @@ mod tests {
|
||||||
hash_queue.register_hash(&last_hash, &FeeCalculator::default());
|
hash_queue.register_hash(&last_hash, &FeeCalculator::default());
|
||||||
}
|
}
|
||||||
// Assert we're no longer able to use the oldest hash.
|
// Assert we're no longer able to use the oldest hash.
|
||||||
assert!(!hash_queue.check_hash(last_hash));
|
assert!(!hash_queue.check_hash(&last_hash));
|
||||||
assert_eq!(None, hash_queue.check_hash_age(&last_hash, 0));
|
assert_eq!(None, hash_queue.check_hash_age(&last_hash, 0));
|
||||||
|
|
||||||
// Assert we are not able to use the oldest remaining hash.
|
// Assert we are not able to use the oldest remaining hash.
|
||||||
let last_valid_hash = hash(&serialize(&1).unwrap());
|
let last_valid_hash = hash(&serialize(&1).unwrap());
|
||||||
assert!(hash_queue.check_hash(last_valid_hash));
|
assert!(hash_queue.check_hash(&last_valid_hash));
|
||||||
assert_eq!(Some(false), hash_queue.check_hash_age(&last_valid_hash, 0));
|
assert_eq!(Some(false), hash_queue.check_hash_age(&last_valid_hash, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,15 @@ impl FeeCalculator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please do not use, will no longer be available in the future"
|
||||||
|
)]
|
||||||
pub fn calculate_fee(&self, message: &Message) -> u64 {
|
pub fn calculate_fee(&self, message: &Message) -> u64 {
|
||||||
let mut num_secp256k1_signatures: u64 = 0;
|
let mut num_secp256k1_signatures: u64 = 0;
|
||||||
for instruction in &message.instructions {
|
for instruction in &message.instructions {
|
||||||
let program_index = instruction.program_id_index as usize;
|
let program_index = instruction.program_id_index as usize;
|
||||||
// Transaction may not be sanitized here
|
// Message may not be sanitized here
|
||||||
if program_index < message.account_keys.len() {
|
if program_index < message.account_keys.len() {
|
||||||
let id = message.account_keys[program_index];
|
let id = message.account_keys[program_index];
|
||||||
if secp256k1_program::check_id(&id) && !instruction.data.is_empty() {
|
if secp256k1_program::check_id(&id) && !instruction.data.is_empty() {
|
||||||
|
@ -193,6 +197,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(deprecated)]
|
||||||
fn test_fee_calculator_calculate_fee() {
|
fn test_fee_calculator_calculate_fee() {
|
||||||
// Default: no fee.
|
// Default: no fee.
|
||||||
let message = Message::default();
|
let message = Message::default();
|
||||||
|
@ -216,6 +221,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(deprecated)]
|
||||||
fn test_fee_calculator_calculate_fee_secp256k1() {
|
fn test_fee_calculator_calculate_fee_secp256k1() {
|
||||||
use crate::instruction::Instruction;
|
use crate::instruction::Instruction;
|
||||||
let pubkey0 = Pubkey::new(&[0; 32]);
|
let pubkey0 = Pubkey::new(&[0; 32]);
|
||||||
|
|
|
@ -81,9 +81,14 @@ pub trait SyncClient {
|
||||||
fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> Result<u64>;
|
fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> Result<u64>;
|
||||||
|
|
||||||
/// Get recent blockhash
|
/// Get recent blockhash
|
||||||
|
#[deprecated(since = "1.8.0", note = "Please use `get_latest_blockhash` instead")]
|
||||||
fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)>;
|
fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)>;
|
||||||
|
|
||||||
/// Get recent blockhash. Uses explicit commitment configuration.
|
/// Get recent blockhash. Uses explicit commitment configuration.
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please use `get_latest_blockhash_with_commitment` and `get_fee_for_message` instead"
|
||||||
|
)]
|
||||||
fn get_recent_blockhash_with_commitment(
|
fn get_recent_blockhash_with_commitment(
|
||||||
&self,
|
&self,
|
||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
|
@ -91,9 +96,17 @@ pub trait SyncClient {
|
||||||
|
|
||||||
/// Get `Some(FeeCalculator)` associated with `blockhash` if it is still in
|
/// Get `Some(FeeCalculator)` associated with `blockhash` if it is still in
|
||||||
/// the BlockhashQueue`, otherwise `None`
|
/// the BlockhashQueue`, otherwise `None`
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please use `get_fee_for_message` or `is_blockhash_valid` instead"
|
||||||
|
)]
|
||||||
fn get_fee_calculator_for_blockhash(&self, blockhash: &Hash) -> Result<Option<FeeCalculator>>;
|
fn get_fee_calculator_for_blockhash(&self, blockhash: &Hash) -> Result<Option<FeeCalculator>>;
|
||||||
|
|
||||||
/// Get recent fee rate governor
|
/// Get recent fee rate governor
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please do not use, will no longer be available in the future"
|
||||||
|
)]
|
||||||
fn get_fee_rate_governor(&self) -> Result<FeeRateGovernor>;
|
fn get_fee_rate_governor(&self) -> Result<FeeRateGovernor>;
|
||||||
|
|
||||||
/// Get signature status.
|
/// Get signature status.
|
||||||
|
@ -136,7 +149,29 @@ pub trait SyncClient {
|
||||||
/// Poll to confirm a transaction.
|
/// Poll to confirm a transaction.
|
||||||
fn poll_for_signature(&self, signature: &Signature) -> Result<()>;
|
fn poll_for_signature(&self, signature: &Signature) -> Result<()>;
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.8.0",
|
||||||
|
note = "Please use `get_new_latest_blockhash` instead"
|
||||||
|
)]
|
||||||
fn get_new_blockhash(&self, blockhash: &Hash) -> Result<(Hash, FeeCalculator)>;
|
fn get_new_blockhash(&self, blockhash: &Hash) -> Result<(Hash, FeeCalculator)>;
|
||||||
|
|
||||||
|
/// Get last known blockhash
|
||||||
|
fn get_latest_blockhash(&self) -> Result<Hash>;
|
||||||
|
|
||||||
|
/// Get recent blockhash. Uses explicit commitment configuration.
|
||||||
|
fn get_latest_blockhash_with_commitment(
|
||||||
|
&self,
|
||||||
|
commitment_config: CommitmentConfig,
|
||||||
|
) -> Result<(Hash, u64)>;
|
||||||
|
|
||||||
|
/// Check if the blockhash is valid
|
||||||
|
fn is_blockhash_valid(&self, blockhash: &Hash, commitment: CommitmentConfig) -> Result<bool>;
|
||||||
|
|
||||||
|
/// Calculate the fee for a `Message`
|
||||||
|
fn get_fee_for_message(&self, blockhash: &Hash, message: &Message) -> Result<u64>;
|
||||||
|
|
||||||
|
/// Get a new blockhash after the one specified
|
||||||
|
fn get_new_latest_blockhash(&self, blockhash: &Hash) -> Result<Hash>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AsyncClient {
|
pub trait AsyncClient {
|
||||||
|
|
|
@ -205,8 +205,7 @@ fn send_and_confirm_message<S: Signers>(
|
||||||
) -> Result<Signature, ClientError> {
|
) -> Result<Signature, ClientError> {
|
||||||
let mut transaction = Transaction::new_unsigned(message);
|
let mut transaction = Transaction::new_unsigned(message);
|
||||||
|
|
||||||
let (blockhash, _fee_calculator) =
|
let blockhash = client.get_new_latest_blockhash(&transaction.message().recent_blockhash)?;
|
||||||
client.get_new_blockhash(&transaction.message().recent_blockhash)?;
|
|
||||||
transaction.try_sign(signers, blockhash)?;
|
transaction.try_sign(signers, blockhash)?;
|
||||||
|
|
||||||
if no_wait {
|
if no_wait {
|
||||||
|
|
|
@ -19,7 +19,6 @@ use solana_client::{
|
||||||
rpc_client::RpcClient,
|
rpc_client::RpcClient,
|
||||||
rpc_config::RpcSendTransactionConfig,
|
rpc_config::RpcSendTransactionConfig,
|
||||||
rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
|
rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
|
||||||
rpc_response::Fees,
|
|
||||||
};
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
clock::Slot,
|
clock::Slot,
|
||||||
|
@ -164,7 +163,7 @@ fn transfer<S: Signer>(
|
||||||
let create_instruction =
|
let create_instruction =
|
||||||
system_instruction::transfer(&sender_keypair.pubkey(), to_pubkey, lamports);
|
system_instruction::transfer(&sender_keypair.pubkey(), to_pubkey, lamports);
|
||||||
let message = Message::new(&[create_instruction], Some(&sender_keypair.pubkey()));
|
let message = Message::new(&[create_instruction], Some(&sender_keypair.pubkey()));
|
||||||
let (recent_blockhash, _fees) = client.get_recent_blockhash()?;
|
let recent_blockhash = client.get_latest_blockhash()?;
|
||||||
Ok(Transaction::new(
|
Ok(Transaction::new(
|
||||||
&[sender_keypair],
|
&[sender_keypair],
|
||||||
message,
|
message,
|
||||||
|
@ -387,13 +386,8 @@ fn send_messages(
|
||||||
if args.dry_run {
|
if args.dry_run {
|
||||||
Ok((Transaction::new_unsigned(message), std::u64::MAX))
|
Ok((Transaction::new_unsigned(message), std::u64::MAX))
|
||||||
} else {
|
} else {
|
||||||
let Fees {
|
let (blockhash, last_valid_block_height) =
|
||||||
blockhash,
|
client.get_latest_blockhash_with_commitment(CommitmentConfig::default())?;
|
||||||
last_valid_block_height,
|
|
||||||
..
|
|
||||||
} = client
|
|
||||||
.get_fees_with_commitment(CommitmentConfig::default())?
|
|
||||||
.value;
|
|
||||||
let transaction = Transaction::new(&signers, message, blockhash);
|
let transaction = Transaction::new(&signers, message, blockhash);
|
||||||
let config = RpcSendTransactionConfig {
|
let config = RpcSendTransactionConfig {
|
||||||
skip_preflight: true,
|
skip_preflight: true,
|
||||||
|
@ -448,14 +442,10 @@ fn distribute_allocations(
|
||||||
&mut created_accounts,
|
&mut created_accounts,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let num_signatures = messages
|
|
||||||
.iter()
|
|
||||||
.map(|message| message.header.num_required_signatures as usize)
|
|
||||||
.sum();
|
|
||||||
if args.spl_token_args.is_some() {
|
if args.spl_token_args.is_some() {
|
||||||
check_spl_token_balances(num_signatures, allocations, client, args, created_accounts)?;
|
check_spl_token_balances(&messages, allocations, client, args, created_accounts)?;
|
||||||
} else {
|
} else {
|
||||||
check_payer_balances(num_signatures, allocations, client, args)?;
|
check_payer_balances(&messages, allocations, client, args)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_messages(client, db, allocations, args, exit, messages, stake_extras)?;
|
send_messages(client, db, allocations, args, exit, messages, stake_extras)?;
|
||||||
|
@ -733,18 +723,21 @@ fn log_transaction_confirmations(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_payer_balances(
|
fn check_payer_balances(
|
||||||
num_signatures: usize,
|
messages: &[Message],
|
||||||
allocations: &[Allocation],
|
allocations: &[Allocation],
|
||||||
client: &RpcClient,
|
client: &RpcClient,
|
||||||
args: &DistributeTokensArgs,
|
args: &DistributeTokensArgs,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut undistributed_tokens: u64 = allocations.iter().map(|x| x.amount).sum();
|
let mut undistributed_tokens: u64 = allocations.iter().map(|x| x.amount).sum();
|
||||||
|
|
||||||
let (_blockhash, fee_calculator) = client.get_recent_blockhash()?;
|
let blockhash = client.get_latest_blockhash()?;
|
||||||
let fees = fee_calculator
|
let fees = messages
|
||||||
.lamports_per_signature
|
.iter()
|
||||||
.checked_mul(num_signatures as u64)
|
.map(|message| client.get_fee_for_message(&blockhash, message))
|
||||||
.unwrap();
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.sum();
|
||||||
|
|
||||||
let (distribution_source, unlocked_sol_source) = if let Some(stake_args) = &args.stake_args {
|
let (distribution_source, unlocked_sol_source) = if let Some(stake_args) = &args.stake_args {
|
||||||
let total_unlocked_sol = allocations.len() as u64 * stake_args.unlocked_sol;
|
let total_unlocked_sol = allocations.len() as u64 * stake_args.unlocked_sol;
|
||||||
|
@ -988,7 +981,7 @@ pub fn test_process_create_stake_with_client(client: &RpcClient, sender_keypair:
|
||||||
);
|
);
|
||||||
let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
|
let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
|
||||||
let signers = [&sender_keypair, &stake_account_keypair];
|
let signers = [&sender_keypair, &stake_account_keypair];
|
||||||
let (blockhash, _fees) = client.get_recent_blockhash().unwrap();
|
let blockhash = client.get_latest_blockhash().unwrap();
|
||||||
let transaction = Transaction::new(&signers, message, blockhash);
|
let transaction = Transaction::new(&signers, message, blockhash);
|
||||||
client
|
client
|
||||||
.send_and_confirm_transaction_with_spinner(&transaction)
|
.send_and_confirm_transaction_with_spinner(&transaction)
|
||||||
|
@ -1110,7 +1103,7 @@ pub fn test_process_distribute_stake_with_client(client: &RpcClient, sender_keyp
|
||||||
);
|
);
|
||||||
let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
|
let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
|
||||||
let signers = [&sender_keypair, &stake_account_keypair];
|
let signers = [&sender_keypair, &stake_account_keypair];
|
||||||
let (blockhash, _fees) = client.get_recent_blockhash().unwrap();
|
let blockhash = client.get_latest_blockhash().unwrap();
|
||||||
let transaction = Transaction::new(&signers, message, blockhash);
|
let transaction = Transaction::new(&signers, message, blockhash);
|
||||||
client
|
client
|
||||||
.send_and_confirm_transaction_with_spinner(&transaction)
|
.send_and_confirm_transaction_with_spinner(&transaction)
|
||||||
|
@ -1210,12 +1203,24 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use solana_core::test_validator::TestValidator;
|
use solana_core::test_validator::TestValidator;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
|
instruction::AccountMeta,
|
||||||
signature::{read_keypair_file, write_keypair_file, Signer},
|
signature::{read_keypair_file, write_keypair_file, Signer},
|
||||||
stake::instruction::StakeInstruction,
|
stake::instruction::StakeInstruction,
|
||||||
};
|
};
|
||||||
use solana_streamer::socket::SocketAddrSpace;
|
use solana_streamer::socket::SocketAddrSpace;
|
||||||
use solana_transaction_status::TransactionConfirmationStatus;
|
use solana_transaction_status::TransactionConfirmationStatus;
|
||||||
|
|
||||||
|
fn one_signer_message() -> Message {
|
||||||
|
Message::new(
|
||||||
|
&[Instruction::new_with_bytes(
|
||||||
|
Pubkey::new_unique(),
|
||||||
|
&[],
|
||||||
|
vec![AccountMeta::new(Pubkey::default(), true)],
|
||||||
|
)],
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_process_token_allocations() {
|
fn test_process_token_allocations() {
|
||||||
let alice = Keypair::new();
|
let alice = Keypair::new();
|
||||||
|
@ -1594,7 +1599,7 @@ mod tests {
|
||||||
&sender_keypair_file,
|
&sender_keypair_file,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
check_payer_balances(1, &allocations, &client, &args).unwrap();
|
check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap();
|
||||||
|
|
||||||
// Unfunded payer
|
// Unfunded payer
|
||||||
let unfunded_payer = Keypair::new();
|
let unfunded_payer = Keypair::new();
|
||||||
|
@ -1607,7 +1612,9 @@ mod tests {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
let err_result =
|
||||||
|
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
|
||||||
|
.unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sources,
|
sources,
|
||||||
|
@ -1644,7 +1651,9 @@ mod tests {
|
||||||
args.fee_payer = read_keypair_file(&partially_funded_payer_keypair_file)
|
args.fee_payer = read_keypair_file(&partially_funded_payer_keypair_file)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into();
|
.into();
|
||||||
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
let err_result =
|
||||||
|
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
|
||||||
|
.unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sources,
|
sources,
|
||||||
|
@ -1697,7 +1706,7 @@ mod tests {
|
||||||
&sender_keypair_file,
|
&sender_keypair_file,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
check_payer_balances(1, &allocations, &client, &args).unwrap();
|
check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap();
|
||||||
|
|
||||||
// Unfunded sender
|
// Unfunded sender
|
||||||
let unfunded_payer = Keypair::new();
|
let unfunded_payer = Keypair::new();
|
||||||
|
@ -1708,7 +1717,9 @@ mod tests {
|
||||||
.into();
|
.into();
|
||||||
args.fee_payer = read_keypair_file(&sender_keypair_file).unwrap().into();
|
args.fee_payer = read_keypair_file(&sender_keypair_file).unwrap().into();
|
||||||
|
|
||||||
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
let err_result =
|
||||||
|
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
|
||||||
|
.unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(sources, vec![FundingSource::SystemAccount].into());
|
assert_eq!(sources, vec![FundingSource::SystemAccount].into());
|
||||||
assert_eq!(amount, allocation_amount.to_string());
|
assert_eq!(amount, allocation_amount.to_string());
|
||||||
|
@ -1722,7 +1733,9 @@ mod tests {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
let err_result =
|
||||||
|
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
|
||||||
|
.unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(sources, vec![FundingSource::FeePayer].into());
|
assert_eq!(sources, vec![FundingSource::FeePayer].into());
|
||||||
assert_eq!(amount, fees_in_sol.to_string());
|
assert_eq!(amount, fees_in_sol.to_string());
|
||||||
|
@ -1756,7 +1769,7 @@ mod tests {
|
||||||
);
|
);
|
||||||
let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
|
let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
|
||||||
let signers = [sender_keypair, &stake_account_keypair];
|
let signers = [sender_keypair, &stake_account_keypair];
|
||||||
let (blockhash, _fees) = client.get_recent_blockhash().unwrap();
|
let blockhash = client.get_latest_blockhash().unwrap();
|
||||||
let transaction = Transaction::new(&signers, message, blockhash);
|
let transaction = Transaction::new(&signers, message, blockhash);
|
||||||
client
|
client
|
||||||
.send_and_confirm_transaction_with_spinner(&transaction)
|
.send_and_confirm_transaction_with_spinner(&transaction)
|
||||||
|
@ -1809,7 +1822,7 @@ mod tests {
|
||||||
&sender_keypair_file,
|
&sender_keypair_file,
|
||||||
Some(stake_args),
|
Some(stake_args),
|
||||||
);
|
);
|
||||||
check_payer_balances(1, &allocations, &client, &args).unwrap();
|
check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap();
|
||||||
|
|
||||||
// Underfunded stake-account
|
// Underfunded stake-account
|
||||||
let expensive_allocation_amount = 5000.0;
|
let expensive_allocation_amount = 5000.0;
|
||||||
|
@ -1818,8 +1831,13 @@ mod tests {
|
||||||
amount: sol_to_lamports(expensive_allocation_amount),
|
amount: sol_to_lamports(expensive_allocation_amount),
|
||||||
lockup_date: "".to_string(),
|
lockup_date: "".to_string(),
|
||||||
}];
|
}];
|
||||||
let err_result =
|
let err_result = check_payer_balances(
|
||||||
check_payer_balances(1, &expensive_allocations, &client, &args).unwrap_err();
|
&[one_signer_message()],
|
||||||
|
&expensive_allocations,
|
||||||
|
&client,
|
||||||
|
&args,
|
||||||
|
)
|
||||||
|
.unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(sources, vec![FundingSource::StakeAccount].into());
|
assert_eq!(sources, vec![FundingSource::StakeAccount].into());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -1841,7 +1859,9 @@ mod tests {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
let err_result =
|
||||||
|
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
|
||||||
|
.unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sources,
|
sources,
|
||||||
|
@ -1878,7 +1898,9 @@ mod tests {
|
||||||
args.fee_payer = read_keypair_file(&partially_funded_payer_keypair_file)
|
args.fee_payer = read_keypair_file(&partially_funded_payer_keypair_file)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into();
|
.into();
|
||||||
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
let err_result =
|
||||||
|
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
|
||||||
|
.unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sources,
|
sources,
|
||||||
|
@ -1938,7 +1960,7 @@ mod tests {
|
||||||
&sender_keypair_file,
|
&sender_keypair_file,
|
||||||
Some(stake_args),
|
Some(stake_args),
|
||||||
);
|
);
|
||||||
check_payer_balances(1, &allocations, &client, &args).unwrap();
|
check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap();
|
||||||
|
|
||||||
// Unfunded sender
|
// Unfunded sender
|
||||||
let unfunded_payer = Keypair::new();
|
let unfunded_payer = Keypair::new();
|
||||||
|
@ -1949,7 +1971,9 @@ mod tests {
|
||||||
.into();
|
.into();
|
||||||
args.fee_payer = read_keypair_file(&sender_keypair_file).unwrap().into();
|
args.fee_payer = read_keypair_file(&sender_keypair_file).unwrap().into();
|
||||||
|
|
||||||
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
let err_result =
|
||||||
|
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
|
||||||
|
.unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(sources, vec![FundingSource::SystemAccount].into());
|
assert_eq!(sources, vec![FundingSource::SystemAccount].into());
|
||||||
assert_eq!(amount, unlocked_sol.to_string());
|
assert_eq!(amount, unlocked_sol.to_string());
|
||||||
|
@ -1963,7 +1987,9 @@ mod tests {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
let err_result =
|
||||||
|
check_payer_balances(&[one_signer_message()], &allocations, &client, &args)
|
||||||
|
.unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(sources, vec![FundingSource::FeePayer].into());
|
assert_eq!(sources, vec![FundingSource::FeePayer].into());
|
||||||
assert_eq!(amount, fees_in_sol.to_string());
|
assert_eq!(amount, fees_in_sol.to_string());
|
||||||
|
|
|
@ -8,7 +8,7 @@ use solana_account_decoder::parse_token::{
|
||||||
spl_token_v2_0_pubkey,
|
spl_token_v2_0_pubkey,
|
||||||
};
|
};
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_sdk::{instruction::Instruction, native_token::lamports_to_sol};
|
use solana_sdk::{instruction::Instruction, message::Message, native_token::lamports_to_sol};
|
||||||
use solana_transaction_status::parse_token::spl_token_v2_0_instruction;
|
use solana_transaction_status::parse_token::spl_token_v2_0_instruction;
|
||||||
use spl_associated_token_account_v1_0::{
|
use spl_associated_token_account_v1_0::{
|
||||||
create_associated_token_account, get_associated_token_address,
|
create_associated_token_account, get_associated_token_address,
|
||||||
|
@ -85,7 +85,7 @@ pub fn build_spl_token_instructions(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_spl_token_balances(
|
pub fn check_spl_token_balances(
|
||||||
num_signatures: usize,
|
messages: &[Message],
|
||||||
allocations: &[Allocation],
|
allocations: &[Allocation],
|
||||||
client: &RpcClient,
|
client: &RpcClient,
|
||||||
args: &DistributeTokensArgs,
|
args: &DistributeTokensArgs,
|
||||||
|
@ -97,11 +97,14 @@ pub fn check_spl_token_balances(
|
||||||
.expect("spl_token_args must be some");
|
.expect("spl_token_args must be some");
|
||||||
let allocation_amount: u64 = allocations.iter().map(|x| x.amount).sum();
|
let allocation_amount: u64 = allocations.iter().map(|x| x.amount).sum();
|
||||||
|
|
||||||
let fee_calculator = client.get_recent_blockhash()?.1;
|
let blockhash = client.get_latest_blockhash()?;
|
||||||
let fees = fee_calculator
|
let fees: u64 = messages
|
||||||
.lamports_per_signature
|
.iter()
|
||||||
.checked_mul(num_signatures as u64)
|
.map(|message| client.get_fee_for_message(&blockhash, message))
|
||||||
.unwrap();
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.sum();
|
||||||
|
|
||||||
let token_account_rent_exempt_balance =
|
let token_account_rent_exempt_balance =
|
||||||
client.get_minimum_balance_for_rent_exemption(SplTokenAccount::LEN)?;
|
client.get_minimum_balance_for_rent_exemption(SplTokenAccount::LEN)?;
|
||||||
|
|
|
@ -183,7 +183,7 @@ fn get_cluster_info(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
) -> client_error::Result<(u64, Hash, RpcVoteAccountStatus, HashMap<Pubkey, u64>)> {
|
) -> client_error::Result<(u64, Hash, RpcVoteAccountStatus, HashMap<Pubkey, u64>)> {
|
||||||
let transaction_count = rpc_client.get_transaction_count()?;
|
let transaction_count = rpc_client.get_transaction_count()?;
|
||||||
let recent_blockhash = rpc_client.get_recent_blockhash()?.0;
|
let recent_blockhash = rpc_client.get_latest_blockhash()?;
|
||||||
let vote_accounts = rpc_client.get_vote_accounts()?;
|
let vote_accounts = rpc_client.get_vote_accounts()?;
|
||||||
|
|
||||||
let mut validator_balances = HashMap::new();
|
let mut validator_balances = HashMap::new();
|
||||||
|
|
Loading…
Reference in New Issue