diff --git a/banks-server/src/banks_server.rs b/banks-server/src/banks_server.rs index 1fcdce1ad436c5..d104562b1ba42f 100644 --- a/banks-server/src/banks_server.rs +++ b/banks-server/src/banks_server.rs @@ -420,6 +420,7 @@ impl Banks for BanksServer { let bank = self.bank(commitment); let sanitized_message = SanitizedMessage::try_from(message).ok()?; bank.get_fee_for_message(&sanitized_message) + .map(|fee_details| fee_details.sum()) } } diff --git a/core/src/banking_stage/consumer.rs b/core/src/banking_stage/consumer.rs index 64b68889747633..5ea84af76b194b 100644 --- a/core/src/banking_stage/consumer.rs +++ b/core/src/banking_stage/consumer.rs @@ -719,7 +719,7 @@ impl Consumer { bank.feature_set.is_active( &feature_set::include_loaded_accounts_data_size_in_fee_calculation::id(), ), - ); + ).sum(); let (mut fee_payer_account, _slot) = bank .rc .accounts diff --git a/programs/sbf/tests/programs.rs b/programs/sbf/tests/programs.rs index 8f8f9d2ffec92d..8fc4a18ecf561a 100644 --- a/programs/sbf/tests/programs.rs +++ b/programs/sbf/tests/programs.rs @@ -206,10 +206,12 @@ fn execute_transactions( ), } .expect("lamports_per_signature must be available"); - let fee = bank.get_fee_for_message_with_lamports_per_signature( - &SanitizedMessage::try_from(tx.message().clone()).unwrap(), - lamports_per_signature, - ); + let fee = bank + .get_fee_for_message_with_lamports_per_signature( + &SanitizedMessage::try_from(tx.message().clone()).unwrap(), + lamports_per_signature, + ) + .sum(); let inner_instructions = inner_instructions.map(|inner_instructions| { map_inner_instructions(inner_instructions).collect() @@ -3983,14 +3985,16 @@ fn test_program_fees() { ); let sanitized_message = SanitizedMessage::try_from(message.clone()).unwrap(); - let expected_normal_fee = fee_structure.calculate_fee( - &sanitized_message, - congestion_multiplier, - &process_compute_budget_instructions(sanitized_message.program_instructions_iter()) - .unwrap_or_default() - .into(), - false, - ); + let expected_normal_fee = fee_structure + .calculate_fee( + &sanitized_message, + congestion_multiplier, + &process_compute_budget_instructions(sanitized_message.program_instructions_iter()) + .unwrap_or_default() + .into(), + false, + ) + .sum(); bank_client .send_and_confirm_message(&[&mint_keypair], message) .unwrap(); @@ -4006,14 +4010,16 @@ fn test_program_fees() { Some(&mint_keypair.pubkey()), ); let sanitized_message = SanitizedMessage::try_from(message.clone()).unwrap(); - let expected_prioritized_fee = fee_structure.calculate_fee( - &sanitized_message, - congestion_multiplier, - &process_compute_budget_instructions(sanitized_message.program_instructions_iter()) - .unwrap_or_default() - .into(), - false, - ); + let expected_prioritized_fee = fee_structure + .calculate_fee( + &sanitized_message, + congestion_multiplier, + &process_compute_budget_instructions(sanitized_message.program_instructions_iter()) + .unwrap_or_default() + .into(), + false, + ) + .sum(); assert!(expected_normal_fee < expected_prioritized_fee); bank_client diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index 5cc5b82344e0d1..b5546e7b86bb8c 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -4017,7 +4017,9 @@ pub mod rpc_full { .map_err(|err| { Error::invalid_params(format!("invalid transaction message: {err}")) })?; - let fee = bank.get_fee_for_message(&sanitized_message); + let fee = bank + .get_fee_for_message(&sanitized_message) + .map(|fee_details| fee_details.sum()); Ok(new_response(bank, fee)) } diff --git a/rpc/src/transaction_status_service.rs b/rpc/src/transaction_status_service.rs index eca53c66658766..19bfb55dbc622e 100644 --- a/rpc/src/transaction_status_service.rs +++ b/rpc/src/transaction_status_service.rs @@ -114,10 +114,12 @@ impl TransactionStatusService { ), } .expect("lamports_per_signature must be available"); - let fee = bank.get_fee_for_message_with_lamports_per_signature( - transaction.message(), - lamports_per_signature, - ); + let fee = bank + .get_fee_for_message_with_lamports_per_signature( + transaction.message(), + lamports_per_signature, + ) + .sum(); let tx_account_locks = transaction.get_account_locks_unchecked(); let inner_instructions = inner_instructions.map(|inner_instructions| { diff --git a/runtime/src/accounts/mod.rs b/runtime/src/accounts/mod.rs index 9c99143416a345..cd17a24870e76b 100644 --- a/runtime/src/accounts/mod.rs +++ b/runtime/src/accounts/mod.rs @@ -72,17 +72,20 @@ pub(super) fn load_accounts( hash_queue.get_lamports_per_signature(tx.message().recent_blockhash()) }); let fee = if let Some(lamports_per_signature) = lamports_per_signature { - fee_structure.calculate_fee( - tx.message(), - lamports_per_signature, - &process_compute_budget_instructions( - tx.message().program_instructions_iter(), + fee_structure + .calculate_fee( + tx.message(), + lamports_per_signature, + &process_compute_budget_instructions( + tx.message().program_instructions_iter(), + ) + .unwrap_or_default() + .into(), + feature_set.is_active( + &include_loaded_accounts_data_size_in_fee_calculation::id(), + ), ) - .unwrap_or_default() - .into(), - feature_set - .is_active(&include_loaded_accounts_data_size_in_fee_calculation::id()), - ) + .sum() } else { return (Err(TransactionError::BlockhashNotFound), None); }; @@ -688,14 +691,16 @@ mod tests { ); let message = SanitizedMessage::try_from(tx.message().clone()).unwrap(); - let fee = FeeStructure::default().calculate_fee( - &message, - lamports_per_signature, - &process_compute_budget_instructions(message.program_instructions_iter()) - .unwrap_or_default() - .into(), - false, - ); + let fee = FeeStructure::default() + .calculate_fee( + &message, + lamports_per_signature, + &process_compute_budget_instructions(message.program_instructions_iter()) + .unwrap_or_default() + .into(), + false, + ) + .sum(); assert_eq!(fee, lamports_per_signature); let loaded_accounts = load_accounts_with_fee( @@ -1222,14 +1227,16 @@ mod tests { ); let message = SanitizedMessage::try_from(tx.message().clone()).unwrap(); - let fee = FeeStructure::default().calculate_fee( - &message, - lamports_per_signature, - &process_compute_budget_instructions(message.program_instructions_iter()) - .unwrap_or_default() - .into(), - false, - ); + let fee = FeeStructure::default() + .calculate_fee( + &message, + lamports_per_signature, + &process_compute_budget_instructions(message.program_instructions_iter()) + .unwrap_or_default() + .into(), + false, + ) + .sum(); assert_eq!(fee, lamports_per_signature + prioritization_fee); // assert fail to load account with 2B lamport balance for transaction asking for 2B diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index b1b34289290746..b87dc06ed002c5 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -146,7 +146,7 @@ use { epoch_schedule::EpochSchedule, feature, feature_set::{self, include_loaded_accounts_data_size_in_fee_calculation, FeatureSet}, - fee::FeeStructure, + fee::{FeeDetails, FeeStructure}, fee_calculator::{FeeCalculator, FeeRateGovernor}, genesis_config::{ClusterType, GenesisConfig}, hard_forks::HardForks, @@ -3998,7 +3998,7 @@ impl Bank { &self.fee_rate_governor } - pub fn get_fee_for_message(&self, message: &SanitizedMessage) -> Option { + pub fn get_fee_for_message(&self, message: &SanitizedMessage) -> Option { let lamports_per_signature = { let blockhash_queue = self.blockhash_queue.read().unwrap(); blockhash_queue.get_lamports_per_signature(message.recent_blockhash()) @@ -4047,7 +4047,7 @@ impl Bank { &self, message: &SanitizedMessage, lamports_per_signature: u64, - ) -> u64 { + ) -> FeeDetails { self.fee_structure.calculate_fee( message, lamports_per_signature, @@ -5500,10 +5500,12 @@ impl Bank { let lamports_per_signature = lamports_per_signature.ok_or(TransactionError::BlockhashNotFound)?; - let fee = self.get_fee_for_message_with_lamports_per_signature( - tx.message(), - lamports_per_signature, - ); + let fee = self + .get_fee_for_message_with_lamports_per_signature( + tx.message(), + lamports_per_signature, + ) + .sum(); // In case of instruction error, even though no accounts // were stored we still need to charge the payer the diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index efe8b1970dfeff..8372d4ac2bbaf0 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -5278,7 +5278,8 @@ fn test_nonce_transaction() { let mut expected_balance = 4_650_000 - bank .get_fee_for_message(&recent_message.try_into().unwrap()) - .unwrap(); + .unwrap() + .sum(); assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance); assert_eq!(bank.get_balance(&nonce_pubkey), 250_000); assert_eq!(bank.get_balance(&alice_pubkey), 100_000); @@ -5337,7 +5338,8 @@ fn test_nonce_transaction() { recent_message.recent_blockhash = bank.last_blockhash(); expected_balance -= bank .get_fee_for_message(&SanitizedMessage::try_from(recent_message).unwrap()) - .unwrap(); + .unwrap() + .sum(); assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance); assert_ne!( nonce_hash, @@ -5405,7 +5407,8 @@ fn test_nonce_transaction_with_tx_wide_caps() { let mut expected_balance = 4_650_000 - bank .get_fee_for_message(&recent_message.try_into().unwrap()) - .unwrap(); + .unwrap() + .sum(); assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance); assert_eq!(bank.get_balance(&nonce_pubkey), 250_000); assert_eq!(bank.get_balance(&alice_pubkey), 100_000); @@ -5464,7 +5467,8 @@ fn test_nonce_transaction_with_tx_wide_caps() { recent_message.recent_blockhash = bank.last_blockhash(); expected_balance -= bank .get_fee_for_message(&SanitizedMessage::try_from(recent_message).unwrap()) - .unwrap(); + .unwrap() + .sum(); assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance); assert_ne!( nonce_hash, @@ -5597,6 +5601,7 @@ fn test_nonce_payer() { - bank .get_fee_for_message(&recent_message.try_into().unwrap()) .unwrap() + .sum() ); assert_ne!( nonce_hash, @@ -5664,6 +5669,7 @@ fn test_nonce_payer_tx_wide_cap() { - bank .get_fee_for_message(&recent_message.try_into().unwrap()) .unwrap() + .sum() ); assert_ne!( nonce_hash, @@ -10028,7 +10034,9 @@ fn calculate_test_fee( .unwrap_or_default() .into(); - fee_structure.calculate_fee(message, lamports_per_signature, &budget_limits, false) + fee_structure + .calculate_fee(message, lamports_per_signature, &budget_limits, false) + .sum() } #[test] @@ -10755,7 +10763,7 @@ fn test_invalid_rent_state_changes_fee_payer() { &recent_blockhash, )) .unwrap(); - let fee = bank.get_fee_for_message(&dummy_message).unwrap(); + let fee = bank.get_fee_for_message(&dummy_message).unwrap().sum(); // RentPaying fee-payer can remain RentPaying let tx = Transaction::new( @@ -12126,7 +12134,9 @@ fn test_bank_verify_accounts_hash_with_base() { let transaction = SanitizedTransaction::from_transaction_for_tests( system_transaction::transfer(&key2, &key3.pubkey(), amount, blockhash), ); - bank.get_fee_for_message(transaction.message()).unwrap() + bank.get_fee_for_message(transaction.message()) + .unwrap() + .sum() }; bank.transfer(amount + fee, &mint, &key1.pubkey()).unwrap(); bank.transfer(amount + fee, &mint, &key2.pubkey()).unwrap(); diff --git a/runtime/src/bank_client.rs b/runtime/src/bank_client.rs index 7fe6418d4110b2..d07a39a68a40ff 100644 --- a/runtime/src/bank_client.rs +++ b/runtime/src/bank_client.rs @@ -289,6 +289,7 @@ impl SyncClient for BankClient { SanitizedMessage::try_from(message.clone()) .ok() .and_then(|sanitized_message| self.bank.get_fee_for_message(&sanitized_message)) + .map(|fee_details| fee_details.sum()) .ok_or_else(|| { TransportError::IoError(io::Error::new( io::ErrorKind::Other, diff --git a/runtime/src/snapshot_bank_utils.rs b/runtime/src/snapshot_bank_utils.rs index 5494eb1beb716c..dcf2e160da2083 100644 --- a/runtime/src/snapshot_bank_utils.rs +++ b/runtime/src/snapshot_bank_utils.rs @@ -1816,7 +1816,7 @@ mod tests { lamports_to_transfer, blockhash, )); - let fee = bank2.get_fee_for_message(tx.message()).unwrap(); + let fee = bank2.get_fee_for_message(tx.message()).unwrap().sum(); let tx = system_transaction::transfer( &key1, &key2.pubkey(), @@ -2184,7 +2184,9 @@ mod tests { let transaction = SanitizedTransaction::from_transaction_for_tests( system_transaction::transfer(&key2, &key3.pubkey(), amount, blockhash), ); - bank.get_fee_for_message(transaction.message()).unwrap() + bank.get_fee_for_message(transaction.message()) + .unwrap() + .sum() }; bank.transfer(amount + fee, mint, &key1.pubkey()).unwrap(); bank.transfer(amount + fee, mint, &key2.pubkey()).unwrap(); diff --git a/sdk/src/fee.rs b/sdk/src/fee.rs index 2fb045aba5d73e..2e85cca1eccd40 100644 --- a/sdk/src/fee.rs +++ b/sdk/src/fee.rs @@ -31,6 +31,19 @@ pub struct FeeStructure { pub compute_fee_bins: Vec, } +/// Return type of calculate_fee(...) +#[derive(Debug, Default, Clone, Eq, PartialEq)] +pub struct FeeDetails { + pub transaction_fee: u64, + pub prioritization_fee: u64, +} + +impl FeeDetails { + pub fn sum(&self) -> u64 { + self.transaction_fee.saturating_add(self.prioritization_fee) + } +} + pub const ACCOUNT_DATA_COST_PAGE_SIZE: u64 = 32_u64.saturating_mul(1024); impl FeeStructure { @@ -83,7 +96,7 @@ impl FeeStructure { _lamports_per_signature: u64, budget_limits: &FeeBudgetLimits, include_loaded_account_data_size_in_fee: bool, - ) -> u64 { + ) -> FeeDetails { let signature_fee = message .num_signatures() .saturating_mul(self.lamports_per_signature); @@ -115,12 +128,13 @@ impl FeeStructure { .unwrap_or_default() }); - (budget_limits - .prioritization_fee - .saturating_add(signature_fee) - .saturating_add(write_lock_fee) - .saturating_add(compute_fee) as f64) - .round() as u64 + FeeDetails { + transaction_fee: (signature_fee + .saturating_add(write_lock_fee) + .saturating_add(compute_fee) as f64) + .round() as u64, + prioritization_fee: budget_limits.prioritization_fee, + } } }