Update fee api to use blockhash (#21054)

This commit is contained in:
Jack May
2021-10-29 13:52:59 -07:00
committed by GitHub
parent aea3c66fa8
commit bced07a099
16 changed files with 142 additions and 93 deletions

View File

@@ -248,7 +248,7 @@ 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 // Create and close messages both require 2 signatures, fake a 2 signature message to calculate fees
let message = Message::new( let mut message = Message::new(
&[ &[
Instruction::new_with_bytes( Instruction::new_with_bytes(
Pubkey::new_unique(), Pubkey::new_unique(),
@@ -270,6 +270,7 @@ fn run_accounts_bench(
latest_blockhash = Instant::now(); latest_blockhash = Instant::now();
} }
message.recent_blockhash = blockhash;
let fee = client let fee = client
.get_fee_for_message(&message) .get_fee_for_message(&message)
.expect("get_fee_for_message"); .expect("get_fee_for_message");

View File

@@ -289,7 +289,7 @@ impl Banks for BanksServer {
) -> Option<u64> { ) -> Option<u64> {
let bank = self.bank(commitment); let bank = self.bank(commitment);
let sanitized_message = SanitizedMessage::try_from(message).ok()?; let sanitized_message = SanitizedMessage::try_from(message).ok()?;
Some(bank.get_fee_for_message(&sanitized_message)) bank.get_fee_for_message(&sanitized_message)
} }
} }

View File

@@ -8,7 +8,7 @@ use solana_measure::measure::Measure;
use solana_metrics::{self, datapoint_info}; use solana_metrics::{self, datapoint_info};
use solana_sdk::{ use solana_sdk::{
client::Client, client::Client,
clock::{DEFAULT_S_PER_SLOT, MAX_PROCESSING_AGE}, clock::{DEFAULT_MS_PER_SLOT, DEFAULT_S_PER_SLOT, MAX_PROCESSING_AGE},
commitment_config::CommitmentConfig, commitment_config::CommitmentConfig,
hash::Hash, hash::Hash,
instruction::{AccountMeta, Instruction}, instruction::{AccountMeta, Instruction},
@@ -389,6 +389,22 @@ fn generate_txs(
} }
} }
fn get_new_latest_blockhash<T: Client>(client: &Arc<T>, blockhash: &Hash) -> Option<Hash> {
let start = Instant::now();
while start.elapsed().as_secs() < 5 {
if let Ok(new_blockhash) = client.get_latest_blockhash() {
if new_blockhash != *blockhash {
return Some(new_blockhash);
}
}
debug!("Got same blockhash ({:?}), will retry...", blockhash);
// Retry ~twice during a slot
sleep(Duration::from_millis(DEFAULT_MS_PER_SLOT / 2));
}
None
}
fn poll_blockhash<T: Client>( fn poll_blockhash<T: Client>(
exit_signal: &Arc<AtomicBool>, exit_signal: &Arc<AtomicBool>,
blockhash: &Arc<RwLock<Hash>>, blockhash: &Arc<RwLock<Hash>>,
@@ -400,7 +416,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) = client.get_new_latest_blockhash(&old_blockhash) { if let Some(new_blockhash) = get_new_latest_blockhash(client, &old_blockhash) {
*blockhash.write().unwrap() = new_blockhash; *blockhash.write().unwrap() = new_blockhash;
blockhash_last_updated = Instant::now(); blockhash_last_updated = Instant::now();
true true
@@ -888,13 +904,14 @@ 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 single_sig_message = Message::new( let single_sig_message = Message::new_with_blockhash(
&[Instruction::new_with_bytes( &[Instruction::new_with_bytes(
Pubkey::new_unique(), Pubkey::new_unique(),
&[], &[],
vec![AccountMeta::new(Pubkey::new_unique(), true)], vec![AccountMeta::new(Pubkey::new_unique(), true)],
)], )],
None, None,
&client.get_latest_blockhash().unwrap(),
); );
let max_fee = client.get_fee_for_message(&single_sig_message).unwrap(); let max_fee = client.get_fee_for_message(&single_sig_message).unwrap();
let extra_fees = extra * max_fee; let extra_fees = extra * max_fee;

View File

@@ -65,7 +65,7 @@ pub fn check_account_for_spend_multiple_fees_with_commitment(
messages: &[&Message], messages: &[&Message],
commitment: CommitmentConfig, commitment: CommitmentConfig,
) -> Result<(), CliError> { ) -> Result<(), CliError> {
let fee = get_fee_for_message(rpc_client, messages)?; let fee = get_fee_for_messages(rpc_client, messages)?;
if !check_account_for_balance_with_commitment( if !check_account_for_balance_with_commitment(
rpc_client, rpc_client,
account_pubkey, account_pubkey,
@@ -90,10 +90,16 @@ pub fn check_account_for_spend_multiple_fees_with_commitment(
Ok(()) Ok(())
} }
pub fn get_fee_for_message(rpc_client: &RpcClient, messages: &[&Message]) -> Result<u64, CliError> { pub fn get_fee_for_messages(
rpc_client: &RpcClient,
messages: &[&Message],
) -> Result<u64, CliError> {
Ok(messages Ok(messages
.iter() .iter()
.map(|message| rpc_client.get_fee_for_message(message)) .map(|message| {
println!("msg {:?}", message.recent_blockhash);
rpc_client.get_fee_for_message(message)
})
.collect::<Result<Vec<_>, _>>()? .collect::<Result<Vec<_>, _>>()?
.iter() .iter()
.sum()) .sum())
@@ -235,7 +241,7 @@ mod tests {
} }
#[test] #[test]
fn test_get_fee_for_message() { fn test_get_fee_for_messages() {
let check_fee_response = json!(Response { let check_fee_response = json!(Response {
context: RpcResponseContext { slot: 1 }, context: RpcResponseContext { slot: 1 },
value: json!(1), value: json!(1),
@@ -245,14 +251,14 @@ mod tests {
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks); let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
// No messages, no fee. // No messages, no fee.
assert_eq!(get_fee_for_message(&rpc_client, &[]).unwrap(), 0); assert_eq!(get_fee_for_messages(&rpc_client, &[]).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!(get_fee_for_message(&rpc_client, &[&message0]).unwrap(), 1); assert_eq!(get_fee_for_messages(&rpc_client, &[&message0]).unwrap(), 1);
// No signatures, no fee. // No signatures, no fee.
let check_fee_response = json!(Response { let check_fee_response = json!(Response {
@@ -264,7 +270,7 @@ mod tests {
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks); let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
let message = Message::default(); let message = Message::default();
assert_eq!( assert_eq!(
get_fee_for_message(&rpc_client, &[&message, &message]).unwrap(), get_fee_for_messages(&rpc_client, &[&message, &message]).unwrap(),
0 0
); );
} }

View File

@@ -1710,6 +1710,7 @@ fn do_process_program_write_and_deploy(
) -> ProcessResult { ) -> ProcessResult {
// Build messages to calculate fees // Build messages to calculate fees
let mut messages: Vec<&Message> = Vec::new(); let mut messages: Vec<&Message> = Vec::new();
let blockhash = rpc_client.get_latest_blockhash()?;
// Initialize buffer account or complete if already partially initialized // Initialize buffer account or complete if already partially initialized
let (initial_message, write_messages, balance_needed) = let (initial_message, write_messages, balance_needed) =
@@ -1755,9 +1756,10 @@ fn do_process_program_write_and_deploy(
) )
}; };
let initial_message = if !initial_instructions.is_empty() { let initial_message = if !initial_instructions.is_empty() {
Some(Message::new( Some(Message::new_with_blockhash(
&initial_instructions, &initial_instructions,
Some(&config.signers[0].pubkey()), Some(&config.signers[0].pubkey()),
&blockhash,
)) ))
} else { } else {
None None
@@ -1777,7 +1779,7 @@ fn do_process_program_write_and_deploy(
} else { } else {
loader_instruction::write(buffer_pubkey, loader_id, offset, bytes) loader_instruction::write(buffer_pubkey, loader_id, offset, bytes)
}; };
Message::new(&[instruction], Some(&payer_pubkey)) Message::new_with_blockhash(&[instruction], Some(&payer_pubkey), &blockhash)
}; };
let mut write_messages = vec![]; let mut write_messages = vec![];
@@ -1806,7 +1808,7 @@ fn do_process_program_write_and_deploy(
let final_message = if let Some(program_signers) = program_signers { let final_message = if let Some(program_signers) = program_signers {
let message = if loader_id == &bpf_loader_upgradeable::id() { let message = if loader_id == &bpf_loader_upgradeable::id() {
Message::new( Message::new_with_blockhash(
&bpf_loader_upgradeable::deploy_with_max_program_len( &bpf_loader_upgradeable::deploy_with_max_program_len(
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
&program_signers[0].pubkey(), &program_signers[0].pubkey(),
@@ -1818,11 +1820,13 @@ fn do_process_program_write_and_deploy(
programdata_len, programdata_len,
)?, )?,
Some(&config.signers[0].pubkey()), Some(&config.signers[0].pubkey()),
&blockhash,
) )
} else { } else {
Message::new( Message::new_with_blockhash(
&[loader_instruction::finalize(buffer_pubkey, loader_id)], &[loader_instruction::finalize(buffer_pubkey, loader_id)],
Some(&config.signers[0].pubkey()), Some(&config.signers[0].pubkey()),
&blockhash,
) )
}; };
Some(message) Some(message)
@@ -1876,6 +1880,7 @@ fn do_process_program_upgrade(
// Build messages to calculate fees // Build messages to calculate fees
let mut messages: Vec<&Message> = Vec::new(); let mut messages: Vec<&Message> = Vec::new();
let blockhash = rpc_client.get_latest_blockhash()?;
let (initial_message, write_messages, balance_needed) = let (initial_message, write_messages, balance_needed) =
if let Some(buffer_signer) = buffer_signer { if let Some(buffer_signer) = buffer_signer {
@@ -1907,9 +1912,10 @@ fn do_process_program_upgrade(
}; };
let initial_message = if !initial_instructions.is_empty() { let initial_message = if !initial_instructions.is_empty() {
Some(Message::new( Some(Message::new_with_blockhash(
&initial_instructions, &initial_instructions,
Some(&config.signers[0].pubkey()), Some(&config.signers[0].pubkey()),
&blockhash,
)) ))
} else { } else {
None None
@@ -1925,7 +1931,7 @@ fn do_process_program_upgrade(
offset, offset,
bytes, bytes,
); );
Message::new(&[instruction], Some(&payer_pubkey)) Message::new_with_blockhash(&[instruction], Some(&payer_pubkey), &blockhash)
}; };
// Create and add write messages // Create and add write messages
@@ -1952,7 +1958,7 @@ fn do_process_program_upgrade(
} }
// Create and add final message // Create and add final message
let final_message = Message::new( let final_message = Message::new_with_blockhash(
&[bpf_loader_upgradeable::upgrade( &[bpf_loader_upgradeable::upgrade(
program_id, program_id,
buffer_pubkey, buffer_pubkey,
@@ -1960,6 +1966,7 @@ fn do_process_program_upgrade(
&config.signers[0].pubkey(), &config.signers[0].pubkey(),
)], )],
Some(&config.signers[0].pubkey()), Some(&config.signers[0].pubkey()),
&blockhash,
); );
messages.push(&final_message); messages.push(&final_message);

View File

@@ -1,5 +1,5 @@
use crate::{ use crate::{
checks::{check_account_for_balance_with_commitment, get_fee_for_message}, checks::{check_account_for_balance_with_commitment, get_fee_for_messages},
cli::CliError, cli::CliError,
}; };
use clap::ArgMatches; use clap::ArgMatches;
@@ -144,9 +144,10 @@ where
F: Fn(u64) -> Message, F: Fn(u64) -> Message,
{ {
let fee = match blockhash { let fee = match blockhash {
Some(_) => { Some(blockhash) => {
let dummy_message = build_message(0); let mut dummy_message = build_message(0);
get_fee_for_message(rpc_client, &[&dummy_message])? dummy_message.recent_blockhash = *blockhash;
get_fee_for_messages(rpc_client, &[&dummy_message])?
} }
None => 0, // Offline, cannot calulate fee None => 0, // Offline, cannot calulate fee
}; };

View File

@@ -4285,7 +4285,7 @@ impl RpcClient {
#[deprecated( #[deprecated(
since = "1.9.0", since = "1.9.0",
note = "Please use `get_new_latest_blockhash` instead" note = "Please do not use, will no longer be available in the future"
)] )]
#[allow(deprecated)] #[allow(deprecated)]
pub fn get_new_blockhash(&self, blockhash: &Hash) -> ClientResult<(Hash, FeeCalculator)> { pub fn get_new_blockhash(&self, blockhash: &Hash) -> ClientResult<(Hash, FeeCalculator)> {
@@ -4802,7 +4802,9 @@ impl RpcClient {
#[allow(deprecated)] #[allow(deprecated)]
pub fn get_fee_for_message(&self, message: &Message) -> ClientResult<u64> { pub fn get_fee_for_message(&self, message: &Message) -> ClientResult<u64> {
if self.get_node_version()? < semver::Version::new(1, 9, 0) { if self.get_node_version()? < semver::Version::new(1, 9, 0) {
let Fees { fee_calculator, .. } = self.get_fees()?; let fee_calculator = self
.get_fee_calculator_for_blockhash(&message.recent_blockhash)?
.ok_or_else(|| ClientErrorKind::Custom("Invalid blockhash".to_string()))?;
Ok(fee_calculator Ok(fee_calculator
.lamports_per_signature .lamports_per_signature
.saturating_mul(message.header.num_required_signatures as u64)) .saturating_mul(message.header.num_required_signatures as u64))

View File

@@ -605,12 +605,6 @@ impl SyncClient for ThinClient {
.get_fee_for_message(message) .get_fee_for_message(message)
.map_err(|e| e.into()) .map_err(|e| e.into())
} }
fn get_new_latest_blockhash(&self, blockhash: &Hash) -> TransportResult<Hash> {
self.rpc_client()
.get_new_latest_blockhash(blockhash)
.map_err(|e| e.into())
}
} }
impl AsyncClient for ThinClient { impl AsyncClient for ThinClient {

View File

@@ -1978,10 +1978,10 @@ impl JsonRpcRequestProcessor {
&self, &self,
message: &SanitizedMessage, message: &SanitizedMessage,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<Option<u64>>> { ) -> RpcResponse<Option<u64>> {
let bank = self.bank(commitment); let bank = self.bank(commitment);
let fee = bank.get_fee_for_message(message); let fee = bank.get_fee_for_message(message);
Ok(new_response(&bank, Some(fee))) new_response(&bank, fee)
} }
} }
@@ -3706,11 +3706,10 @@ pub mod rpc_full {
debug!("get_fee_for_message rpc request received"); debug!("get_fee_for_message rpc request received");
let (_, message) = let (_, message) =
decode_and_deserialize::<Message>(data, UiTransactionEncoding::Base64)?; decode_and_deserialize::<Message>(data, UiTransactionEncoding::Base64)?;
SanitizedMessage::try_from(message) let sanitized_message = SanitizedMessage::try_from(message).map_err(|err| {
.map_err(|err| { Error::invalid_params(format!("invalid transaction message: {}", err))
Error::invalid_params(format!("invalid transaction message: {}", err)) })?;
}) Ok(meta.get_fee_for_message(&sanitized_message, commitment))
.and_then(|message| meta.get_fee_for_message(&message, commitment))
} }
} }
} }

View File

@@ -3118,8 +3118,11 @@ impl Bank {
&self.fee_rate_governor &self.fee_rate_governor
} }
pub fn get_fee_for_message(&self, message: &SanitizedMessage) -> u64 { pub fn get_fee_for_message(&self, message: &SanitizedMessage) -> Option<u64> {
Self::calculate_fee(message, self.fee_rate_governor.lamports_per_signature) let blockhash_queue = self.blockhash_queue.read().unwrap();
let lamports_per_signature =
blockhash_queue.get_lamports_per_signature(message.recent_blockhash())?;
Some(Self::calculate_fee(message, lamports_per_signature))
} }
pub fn get_fee_for_message_with_lamports_per_signature( pub fn get_fee_for_message_with_lamports_per_signature(
@@ -11022,8 +11025,12 @@ pub(crate) mod tests {
assert_eq!(bank.process_transaction(&durable_tx), Ok(())); assert_eq!(bank.process_transaction(&durable_tx), Ok(()));
/* Check balances */ /* Check balances */
let mut expected_balance = let mut recent_message = durable_tx.message;
4_650_000 - bank.get_fee_for_message(&durable_tx.message.try_into().unwrap()); recent_message.recent_blockhash = bank.last_blockhash();
let mut expected_balance = 4_650_000
- bank
.get_fee_for_message(&recent_message.try_into().unwrap())
.unwrap();
assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance); assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
assert_eq!(bank.get_balance(&nonce_pubkey), 250_000); assert_eq!(bank.get_balance(&nonce_pubkey), 250_000);
assert_eq!(bank.get_balance(&alice_pubkey), 100_000); assert_eq!(bank.get_balance(&alice_pubkey), 100_000);
@@ -11075,8 +11082,11 @@ pub(crate) mod tests {
)) ))
); );
/* Check fee charged and nonce has advanced */ /* Check fee charged and nonce has advanced */
let mut recent_message = durable_tx.message.clone();
recent_message.recent_blockhash = bank.last_blockhash();
expected_balance -= bank expected_balance -= bank
.get_fee_for_message(&SanitizedMessage::try_from(durable_tx.message.clone()).unwrap()); .get_fee_for_message(&SanitizedMessage::try_from(recent_message).unwrap())
.unwrap();
assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance); assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
assert_ne!(nonce_hash, get_nonce_account(&bank, &nonce_pubkey).unwrap()); assert_ne!(nonce_hash, get_nonce_account(&bank, &nonce_pubkey).unwrap());
/* Confirm replaying a TX that failed with InstructionError::* now /* Confirm replaying a TX that failed with InstructionError::* now
@@ -11135,10 +11145,14 @@ pub(crate) mod tests {
)) ))
); );
/* Check fee charged and nonce has *not* advanced */ /* Check fee charged and nonce has *not* advanced */
let mut recent_message = durable_tx.message;
recent_message.recent_blockhash = bank.last_blockhash();
assert_eq!( assert_eq!(
bank.get_balance(&custodian_pubkey), bank.get_balance(&custodian_pubkey),
initial_custodian_balance initial_custodian_balance
- bank.get_fee_for_message(&durable_tx.message.try_into().unwrap()) - bank
.get_fee_for_message(&recent_message.try_into().unwrap())
.unwrap()
); );
assert_eq!(nonce_hash, get_nonce_account(&bank, &nonce_pubkey).unwrap()); assert_eq!(nonce_hash, get_nonce_account(&bank, &nonce_pubkey).unwrap());
} }
@@ -11185,10 +11199,14 @@ pub(crate) mod tests {
)) ))
); );
/* Check fee charged and nonce has advanced */ /* Check fee charged and nonce has advanced */
let mut recent_message = durable_tx.message;
recent_message.recent_blockhash = bank.last_blockhash();
assert_eq!( assert_eq!(
bank.get_balance(&nonce_pubkey), bank.get_balance(&nonce_pubkey),
nonce_starting_balance nonce_starting_balance
- bank.get_fee_for_message(&durable_tx.message.try_into().unwrap()) - bank
.get_fee_for_message(&recent_message.try_into().unwrap())
.unwrap()
); );
assert_ne!(nonce_hash, get_nonce_account(&bank, &nonce_pubkey).unwrap()); assert_ne!(nonce_hash, get_nonce_account(&bank, &nonce_pubkey).unwrap());
} }

View File

@@ -314,26 +314,16 @@ impl SyncClient for BankClient {
fn get_fee_for_message(&self, message: &Message) -> Result<u64> { fn get_fee_for_message(&self, message: &Message) -> Result<u64> {
SanitizedMessage::try_from(message.clone()) SanitizedMessage::try_from(message.clone())
.map(|message| self.bank.get_fee_for_message(&message)) .ok()
.map_err(|_| { .map(|sanitized_message| self.bank.get_fee_for_message(&sanitized_message))
.flatten()
.ok_or_else(|| {
TransportError::IoError(io::Error::new( TransportError::IoError(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
"Unable calculate fee", "Unable calculate fee",
)) ))
}) })
} }
fn get_new_latest_blockhash(&self, blockhash: &Hash) -> Result<Hash> {
let latest_blockhash = self.get_latest_blockhash()?;
if latest_blockhash != *blockhash {
Ok(latest_blockhash)
} else {
Err(TransportError::IoError(io::Error::new(
io::ErrorKind::Other,
"Unable to get new blockhash",
)))
}
}
} }
impl BankClient { impl BankClient {

View File

@@ -3042,18 +3042,19 @@ mod tests {
let slot = slot + 1; let slot = slot + 1;
let bank2 = Arc::new(Bank::new_from_parent(&bank1, &collector, slot)); let bank2 = Arc::new(Bank::new_from_parent(&bank1, &collector, slot));
let blockhash = bank2.last_blockhash();
let tx = SanitizedTransaction::from_transaction_for_tests(system_transaction::transfer( let tx = SanitizedTransaction::from_transaction_for_tests(system_transaction::transfer(
&key1, &key1,
&key2.pubkey(), &key2.pubkey(),
lamports_to_transfer, lamports_to_transfer,
bank2.last_blockhash(), blockhash,
)); ));
let fee = bank2.get_fee_for_message(tx.message()); let fee = bank2.get_fee_for_message(tx.message()).unwrap();
let tx = system_transaction::transfer( let tx = system_transaction::transfer(
&key1, &key1,
&key2.pubkey(), &key2.pubkey(),
lamports_to_transfer - fee, lamports_to_transfer - fee,
bank2.last_blockhash(), blockhash,
); );
bank2.process_transaction(&tx).unwrap(); bank2.process_transaction(&tx).unwrap();
assert_eq!( assert_eq!(

View File

@@ -245,6 +245,14 @@ impl Message {
} }
pub fn new(instructions: &[Instruction], payer: Option<&Pubkey>) -> Self { pub fn new(instructions: &[Instruction], payer: Option<&Pubkey>) -> Self {
Self::new_with_blockhash(instructions, payer, &Hash::default())
}
pub fn new_with_blockhash(
instructions: &[Instruction],
payer: Option<&Pubkey>,
blockhash: &Hash,
) -> Self {
let InstructionKeys { let InstructionKeys {
mut signed_keys, mut signed_keys,
unsigned_keys, unsigned_keys,
@@ -259,7 +267,7 @@ impl Message {
num_readonly_signed_accounts, num_readonly_signed_accounts,
num_readonly_unsigned_accounts, num_readonly_unsigned_accounts,
signed_keys, signed_keys,
Hash::default(), *blockhash,
instructions, instructions,
) )
} }

View File

@@ -87,7 +87,7 @@ pub trait SyncClient {
/// Get recent blockhash. Uses explicit commitment configuration. /// Get recent blockhash. Uses explicit commitment configuration.
#[deprecated( #[deprecated(
since = "1.9.0", since = "1.9.0",
note = "Please use `get_latest_blockhash_with_commitment` and `get_fee_for_message` instead" note = "Please use `get_latest_blockhash_with_commitment` and `get_latest_blockhash_with_commitment` instead"
)] )]
fn get_recent_blockhash_with_commitment( fn get_recent_blockhash_with_commitment(
&self, &self,
@@ -151,7 +151,7 @@ pub trait SyncClient {
#[deprecated( #[deprecated(
since = "1.9.0", since = "1.9.0",
note = "Please use `get_new_latest_blockhash` instead" note = "Please do not use, will no longer be available in the future"
)] )]
fn get_new_blockhash(&self, blockhash: &Hash) -> Result<(Hash, FeeCalculator)>; fn get_new_blockhash(&self, blockhash: &Hash) -> Result<(Hash, FeeCalculator)>;
@@ -169,9 +169,6 @@ pub trait SyncClient {
/// Calculate the fee for a `Message` /// Calculate the fee for a `Message`
fn get_fee_for_message(&self, message: &Message) -> Result<u64>; fn get_fee_for_message(&self, message: &Message) -> Result<u64>;
/// Get a new blockhash after the one specified
fn get_new_latest_blockhash(&self, blockhash: &Hash) -> Result<Hash>;
} }
pub trait AsyncClient { pub trait AsyncClient {

View File

@@ -562,7 +562,7 @@ 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( let mut message = Message::new(
&[Instruction::new_with_bytes( &[Instruction::new_with_bytes(
Pubkey::new_unique(), Pubkey::new_unique(),
&[], &[],
@@ -579,17 +579,20 @@ impl TestValidator {
} }
println!("Waiting for fees to stabilize {:?}...", num_tries); println!("Waiting for fees to stabilize {:?}...", num_tries);
match rpc_client.get_latest_blockhash() { match rpc_client.get_latest_blockhash() {
Ok(_) => match rpc_client.get_fee_for_message(&message) { Ok(blockhash) => {
Ok(fee) => { message.recent_blockhash = blockhash;
if fee != 0 { match rpc_client.get_fee_for_message(&message) {
Ok(fee) => {
if fee != 0 {
break;
}
}
Err(err) => {
warn!("get_fee_for_message() failed: {:?}", err);
break; break;
} }
} }
Err(err) => { }
warn!("get_fee_for_message() failed: {:?}", err);
break;
}
},
Err(err) => { Err(err) => {
warn!("get_latest_blockhash() failed: {:?}", err); warn!("get_latest_blockhash() failed: {:?}", err);
break; break;

View File

@@ -340,7 +340,11 @@ fn build_messages(
do_create_associated_token_account, do_create_associated_token_account,
); );
let fee_payer_pubkey = args.fee_payer.pubkey(); let fee_payer_pubkey = args.fee_payer.pubkey();
let message = Message::new(&instructions, Some(&fee_payer_pubkey)); let message = Message::new_with_blockhash(
&instructions,
Some(&fee_payer_pubkey),
&client.get_latest_blockhash()?,
);
messages.push(message); messages.push(message);
stake_extras.push((new_stake_account_keypair, lockup_date)); stake_extras.push((new_stake_account_keypair, lockup_date));
} }
@@ -1209,14 +1213,15 @@ mod tests {
use solana_test_validator::TestValidator; use solana_test_validator::TestValidator;
use solana_transaction_status::TransactionConfirmationStatus; use solana_transaction_status::TransactionConfirmationStatus;
fn one_signer_message() -> Message { fn one_signer_message(client: &RpcClient) -> Message {
Message::new( Message::new_with_blockhash(
&[Instruction::new_with_bytes( &[Instruction::new_with_bytes(
Pubkey::new_unique(), Pubkey::new_unique(),
&[], &[],
vec![AccountMeta::new(Pubkey::default(), true)], vec![AccountMeta::new(Pubkey::default(), true)],
)], )],
None, None,
&client.get_latest_blockhash().unwrap(),
) )
} }
@@ -1598,7 +1603,7 @@ mod tests {
&sender_keypair_file, &sender_keypair_file,
None, None,
); );
check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap(); check_payer_balances(&[one_signer_message(&client)], &allocations, &client, &args).unwrap();
// Unfunded payer // Unfunded payer
let unfunded_payer = Keypair::new(); let unfunded_payer = Keypair::new();
@@ -1612,7 +1617,7 @@ mod tests {
.into(); .into();
let err_result = let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args) check_payer_balances(&[one_signer_message(&client)], &allocations, &client, &args)
.unwrap_err(); .unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!( assert_eq!(
@@ -1651,7 +1656,7 @@ mod tests {
.unwrap() .unwrap()
.into(); .into();
let err_result = let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args) check_payer_balances(&[one_signer_message(&client)], &allocations, &client, &args)
.unwrap_err(); .unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!( assert_eq!(
@@ -1705,7 +1710,7 @@ mod tests {
&sender_keypair_file, &sender_keypair_file,
None, None,
); );
check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap(); check_payer_balances(&[one_signer_message(&client)], &allocations, &client, &args).unwrap();
// Unfunded sender // Unfunded sender
let unfunded_payer = Keypair::new(); let unfunded_payer = Keypair::new();
@@ -1717,7 +1722,7 @@ mod tests {
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 = let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args) check_payer_balances(&[one_signer_message(&client)], &allocations, &client, &args)
.unwrap_err(); .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());
@@ -1733,7 +1738,7 @@ mod tests {
.into(); .into();
let err_result = let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args) check_payer_balances(&[one_signer_message(&client)], &allocations, &client, &args)
.unwrap_err(); .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());
@@ -1821,7 +1826,7 @@ mod tests {
&sender_keypair_file, &sender_keypair_file,
Some(stake_args), Some(stake_args),
); );
check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap(); check_payer_balances(&[one_signer_message(&client)], &allocations, &client, &args).unwrap();
// Underfunded stake-account // Underfunded stake-account
let expensive_allocation_amount = 5000.0; let expensive_allocation_amount = 5000.0;
@@ -1831,7 +1836,7 @@ mod tests {
lockup_date: "".to_string(), lockup_date: "".to_string(),
}]; }];
let err_result = check_payer_balances( let err_result = check_payer_balances(
&[one_signer_message()], &[one_signer_message(&client)],
&expensive_allocations, &expensive_allocations,
&client, &client,
&args, &args,
@@ -1859,7 +1864,7 @@ mod tests {
.into(); .into();
let err_result = let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args) check_payer_balances(&[one_signer_message(&client)], &allocations, &client, &args)
.unwrap_err(); .unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!( assert_eq!(
@@ -1898,7 +1903,7 @@ mod tests {
.unwrap() .unwrap()
.into(); .into();
let err_result = let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args) check_payer_balances(&[one_signer_message(&client)], &allocations, &client, &args)
.unwrap_err(); .unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!( assert_eq!(
@@ -1959,7 +1964,7 @@ mod tests {
&sender_keypair_file, &sender_keypair_file,
Some(stake_args), Some(stake_args),
); );
check_payer_balances(&[one_signer_message()], &allocations, &client, &args).unwrap(); check_payer_balances(&[one_signer_message(&client)], &allocations, &client, &args).unwrap();
// Unfunded sender // Unfunded sender
let unfunded_payer = Keypair::new(); let unfunded_payer = Keypair::new();
@@ -1971,7 +1976,7 @@ mod tests {
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 = let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args) check_payer_balances(&[one_signer_message(&client)], &allocations, &client, &args)
.unwrap_err(); .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());
@@ -1987,7 +1992,7 @@ mod tests {
.into(); .into();
let err_result = let err_result =
check_payer_balances(&[one_signer_message()], &allocations, &client, &args) check_payer_balances(&[one_signer_message(&client)], &allocations, &client, &args)
.unwrap_err(); .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());