diff --git a/core/src/unprocessed_packet_batches.rs b/core/src/unprocessed_packet_batches.rs index 5f2fb3e889abca..821bbde6a7208b 100644 --- a/core/src/unprocessed_packet_batches.rs +++ b/core/src/unprocessed_packet_batches.rs @@ -2,10 +2,10 @@ use { retain_mut::RetainMut, solana_gossip::weighted_shuffle::WeightedShuffle, solana_perf::packet::{limited_deserialize, Packet, PacketBatch}, - solana_program_runtime::compute_budget::ComputeBudget, solana_runtime::bank::Bank, solana_sdk::{ clock::Slot, + feature_set::tx_wide_compute_cap, hash::Hash, message::{ v0::{self}, @@ -33,7 +33,7 @@ struct FeePerCu { impl FeePerCu { fn too_old(&self, slot: &Slot) -> bool { const MAX_SLOT_AGE: Slot = 1; - slot - &self.slot >= MAX_SLOT_AGE + slot - self.slot >= MAX_SLOT_AGE } } @@ -245,11 +245,11 @@ impl UnprocessedPacketBatches { let bank = bank.as_ref().unwrap(); let deserialized_packet = self.locate_packet_mut(locator)?; if let Some(cached_fee_per_cu) = - Self::get_cached_fee_per_cu(&deserialized_packet, &bank.slot()) + Self::get_cached_fee_per_cu(deserialized_packet, &bank.slot()) { Some(cached_fee_per_cu) } else { - let computed_fee_per_cu = Self::compute_fee_per_cu(&deserialized_packet, bank); + let computed_fee_per_cu = Self::compute_fee_per_cu(deserialized_packet, bank); if let Some(computed_fee_per_cu) = computed_fee_per_cu { deserialized_packet.fee_per_cu = Some(FeePerCu { fee_per_cu: computed_fee_per_cu, @@ -279,16 +279,13 @@ impl UnprocessedPacketBatches { fn compute_fee_per_cu(deserialized_packet: &DeserializedPacket, bank: &Bank) -> Option { let sanitized_message = Self::sanitize_message(&deserialized_packet.versioned_transaction.message, bank)?; - let total_fee = bank.get_fee_for_message(&sanitized_message)?; - - // TODO refactor `bank.get_fee_for_message()` to return both fee and CUs to avoid - // calling ComputeBudget twice. - let mut compute_budget = ComputeBudget::default(); - let _ = compute_budget - .process_message(&sanitized_message, false) - .ok()?; - - Some(total_fee / compute_budget.max_units) + let (total_fee, max_units) = Bank::calculate_fee( + &sanitized_message, + bank.get_lamports_per_signature(), + &bank.fee_structure, + bank.feature_set.is_active(&tx_wide_compute_cap::id()), + ); + Some(total_fee / max_units) } fn get_cached_fee_per_cu(deserialized_packet: &DeserializedPacket, slot: &Slot) -> Option { diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index 80d2e57785abb8..ec4c4abff0aef4 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -507,16 +507,17 @@ impl Accounts { .unwrap_or_else(|| { hash_queue.get_lamports_per_signature(tx.message().recent_blockhash()) }); - let fee = if let Some(lamports_per_signature) = lamports_per_signature { - Bank::calculate_fee( - tx.message(), - lamports_per_signature, - fee_structure, - feature_set.is_active(&tx_wide_compute_cap::id()), - ) - } else { - return (Err(TransactionError::BlockhashNotFound), None); - }; + let (fee, _max_units) = + if let Some(lamports_per_signature) = lamports_per_signature { + Bank::calculate_fee( + tx.message(), + lamports_per_signature, + fee_structure, + feature_set.is_active(&tx_wide_compute_cap::id()), + ) + } else { + return (Err(TransactionError::BlockhashNotFound), None); + }; let loaded_transaction = match self.load_transaction( ancestors, @@ -1589,7 +1590,7 @@ mod tests { instructions, ); - let fee = Bank::calculate_fee( + let (fee, _max_units) = Bank::calculate_fee( &SanitizedMessage::try_from(tx.message().clone()).unwrap(), 10, &FeeStructure::default(), diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 88da129f95796b..b72845044fb608 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -3308,12 +3308,15 @@ impl Bank { NoncePartial::new(address, account).lamports_per_signature() }) })?; - Some(Self::calculate_fee( - message, - lamports_per_signature, - &self.fee_structure, - self.feature_set.is_active(&tx_wide_compute_cap::id()), - )) + Some( + Self::calculate_fee( + message, + lamports_per_signature, + &self.fee_structure, + self.feature_set.is_active(&tx_wide_compute_cap::id()), + ) + .0, + ) } pub fn get_fee_for_message_with_lamports_per_signature( @@ -3327,6 +3330,7 @@ impl Bank { &self.fee_structure, self.feature_set.is_active(&tx_wide_compute_cap::id()), ) + .0 } #[deprecated( @@ -4304,12 +4308,13 @@ impl Bank { } /// Calculate fee for `SanitizedMessage` + /// returns (total_fee, max_units) pub fn calculate_fee( message: &SanitizedMessage, lamports_per_signature: u64, fee_structure: &FeeStructure, tx_wide_compute_cap: bool, - ) -> u64 { + ) -> (u64, u64) { if tx_wide_compute_cap { // Fee based on compute units and signatures const BASE_CONGESTION: f64 = 5_000.0; @@ -4341,15 +4346,21 @@ impl Bank { .unwrap_or_default() }); - ((additional_fee - .saturating_add(signature_fee) - .saturating_add(write_lock_fee) - .saturating_add(compute_fee) as f64) - * congestion_multiplier) - .round() as u64 + ( + ((additional_fee + .saturating_add(signature_fee) + .saturating_add(write_lock_fee) + .saturating_add(compute_fee) as f64) + * congestion_multiplier) + .round() as u64, + compute_budget.max_units, + ) } else { // Fee based only on signatures - lamports_per_signature.saturating_mul(Self::get_num_signatures_in_message(message)) + ( + lamports_per_signature.saturating_mul(Self::get_num_signatures_in_message(message)), + compute_budget::MAX_UNITS as u64, + ) } } @@ -4384,7 +4395,7 @@ impl Bank { let lamports_per_signature = lamports_per_signature.ok_or(TransactionError::BlockhashNotFound)?; - let fee = Self::calculate_fee( + let (fee, _units) = Self::calculate_fee( tx.message(), lamports_per_signature, &self.fee_structure, @@ -9540,7 +9551,7 @@ pub(crate) mod tests { } = create_genesis_config_with_leader(mint, &leader, 3); genesis_config.fee_rate_governor = FeeRateGovernor::new(4, 0); // something divisible by 2 - let expected_fee_paid = Bank::calculate_fee( + let (expected_fee_paid, _max_units) = Bank::calculate_fee( &SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap(), genesis_config .fee_rate_governor @@ -9725,7 +9736,7 @@ pub(crate) mod tests { let tx = system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, cheap_blockhash); assert_eq!(bank.process_transaction(&tx), Ok(())); assert_eq!(bank.get_balance(&key.pubkey()), 1); - let cheap_fee = Bank::calculate_fee( + let (cheap_fee, _max_units) = Bank::calculate_fee( &SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap(), cheap_lamports_per_signature, &FeeStructure::default(), @@ -9742,7 +9753,7 @@ pub(crate) mod tests { let tx = system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, expensive_blockhash); assert_eq!(bank.process_transaction(&tx), Ok(())); assert_eq!(bank.get_balance(&key.pubkey()), 1); - let expensive_fee = Bank::calculate_fee( + let (expensive_fee, _max_units) = Bank::calculate_fee( &SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap(), expensive_lamports_per_signature, &FeeStructure::default(), @@ -9863,7 +9874,8 @@ pub(crate) mod tests { .lamports_per_signature, &FeeStructure::default(), true, - ) * 2 + ) + .0 * 2 ) .0 ); @@ -16155,13 +16167,13 @@ pub(crate) mod tests { SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap(); assert_eq!( Bank::calculate_fee(&message, 0, &FeeStructure::default(), false), - 0 + (0, compute_budget::MAX_UNITS as u64) ); // One signature, a fee. assert_eq!( Bank::calculate_fee(&message, 1, &FeeStructure::default(), false), - 1 + (1, compute_budget::MAX_UNITS as u64) ); // Two signatures, double the fee. @@ -16172,7 +16184,7 @@ pub(crate) mod tests { let message = SanitizedMessage::try_from(Message::new(&[ix0, ix1], Some(&key0))).unwrap(); assert_eq!( Bank::calculate_fee(&message, 2, &FeeStructure::default(), false), - 4 + (4, compute_budget::MAX_UNITS as u64) ); } @@ -16188,7 +16200,10 @@ pub(crate) mod tests { SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap(); assert_eq!( Bank::calculate_fee(&message, 1, &fee_structure, true), - max_fee + lamports_per_signature + ( + max_fee + lamports_per_signature, + compute_budget::MAX_UNITS as u64 + ) ); // Three signatures, two instructions, no unit request @@ -16200,7 +16215,10 @@ pub(crate) mod tests { .unwrap(); assert_eq!( Bank::calculate_fee(&message, 1, &fee_structure, true), - max_fee + 3 * lamports_per_signature + ( + max_fee + 3 * lamports_per_signature, + compute_budget::MAX_UNITS as u64 + ) ); // Explicit fee schedule @@ -16226,7 +16244,7 @@ pub(crate) mod tests { let message = SanitizedMessage::try_from(Message::new(&[ix0, ix1], Some(&Pubkey::new_unique()))) .unwrap(); - let fee = Bank::calculate_fee(&message, 1, &fee_structure, true); + let (fee, _units) = Bank::calculate_fee(&message, 1, &fee_structure, true); assert_eq!( fee, sol_to_lamports(pair.1) + lamports_per_signature + ADDITIONAL_FEE @@ -16262,7 +16280,7 @@ pub(crate) mod tests { .unwrap(); assert_eq!( Bank::calculate_fee(&message, 1, &FeeStructure::default(), false), - 2 + (2, compute_budget::MAX_UNITS as u64) ); secp_instruction1.data = vec![0]; @@ -16274,7 +16292,7 @@ pub(crate) mod tests { .unwrap(); assert_eq!( Bank::calculate_fee(&message, 1, &FeeStructure::default(), false), - 11 + (11, compute_budget::MAX_UNITS as u64) ); }