Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions core/src/banking_stage/packet_deserializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use {
crossbeam_channel::RecvTimeoutError,
solana_perf::packet::PacketBatch,
solana_runtime::bank_forks::BankForks,
solana_sdk::feature_set,
std::{
sync::{Arc, RwLock},
time::{Duration, Instant},
Expand Down Expand Up @@ -55,8 +56,10 @@ impl PacketDeserializer {

// Note: this can be removed after feature `round_compute_unit_price` is activated in
// mainnet-beta
let _working_bank = self.bank_forks.read().unwrap().working_bank();
let round_compute_unit_price_enabled = false; // TODO get from working_bank.feature_set
let working_bank = self.bank_forks.read().unwrap().working_bank();
let round_compute_unit_price_enabled = working_bank
.feature_set
.is_active(&feature_set::round_compute_unit_price::id());

Ok(Self::deserialize_and_collect_packets(
packet_count,
Expand Down
162 changes: 160 additions & 2 deletions program-runtime/src/compute_budget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ impl ComputeBudget {
support_request_units_deprecated: bool,
enable_request_heap_frame_ix: bool,
support_set_loaded_accounts_data_size_limit_ix: bool,
round_compute_unit_price: bool,
Comment thread
tao-stones marked this conversation as resolved.
Outdated
) -> Result<PrioritizationFeeDetails, TransactionError> {
let mut num_non_compute_budget_instructions: usize = 0;
let mut updated_compute_unit_limit = None;
Expand Down Expand Up @@ -221,8 +222,13 @@ impl ComputeBudget {
if prioritization_fee.is_some() {
return Err(duplicate_instruction_error);
}
prioritization_fee =
Some(PrioritizationFeeType::ComputeUnitPrice(micro_lamports));
prioritization_fee = Some(PrioritizationFeeType::ComputeUnitPrice(
if round_compute_unit_price {
Self::round_prioritization_fee(micro_lamports)
} else {
micro_lamports
},
));
}
Ok(ComputeBudgetInstruction::SetLoadedAccountsDataSizeLimit(bytes))
if support_set_loaded_accounts_data_size_limit_ix =>
Expand Down Expand Up @@ -276,6 +282,15 @@ impl ComputeBudget {
.map(|fee_type| PrioritizationFeeDetails::new(fee_type, self.compute_unit_limit))
.unwrap_or_default())
}

// https://github.com/solana-labs/solana/issues/31453 to round compute-unit-price, in micro-lamports,
// down to its nearest 1_000 micro-lamport.
const PRIORITY_FEE_TICK_SIZE: u64 = 1_000;
fn round_prioritization_fee(micro_lamports: u64) -> u64 {
micro_lamports
.saturating_div(Self::PRIORITY_FEE_TICK_SIZE)
.saturating_mul(Self::PRIORITY_FEE_TICK_SIZE)
}
}

#[cfg(test)]
Expand Down Expand Up @@ -308,6 +323,7 @@ mod tests {
false, /*not support request_units_deprecated*/
$enable_request_heap_frame_ix,
$support_set_loaded_accounts_data_size_limit_ix,
false, // not support round_compute_unit_price, it is tested separately
);
assert_eq!($expected_result, result);
assert_eq!(compute_budget, $expected_budget);
Expand Down Expand Up @@ -674,6 +690,115 @@ mod tests {
);
}

#[test]
fn test_set_compute_unit_price_instruction() {
Comment thread
apfitzge marked this conversation as resolved.
Outdated
fn test_set_compute_unit_price(
instructions: &[Instruction],
expected_result: Result<PrioritizationFeeDetails, TransactionError>,
support_round_compute_unit_price: bool,
) {
let payer_keypair = Keypair::new();
let tx = SanitizedTransaction::from_transaction_for_tests(Transaction::new(
&[&payer_keypair],
Message::new(instructions, Some(&payer_keypair.pubkey())),
Hash::default(),
));
let mut compute_budget = ComputeBudget::default();
let result = compute_budget.process_instructions(
tx.message().program_instructions_iter(),
true, // default_units_per_instruction
true, // support_request_units_deprecated
true, // enable_request_heap_frame_ix
true, // support_set_loaded_accounts_data_size_limit_ix
support_round_compute_unit_price,
);
assert_eq!(expected_result, result);
}

for support_round_compute_unit_price in [true, false] {
test_set_compute_unit_price(
&[],
Ok(PrioritizationFeeDetails::default()),
support_round_compute_unit_price,
);
}

for support_round_compute_unit_price in [true, false] {
test_set_compute_unit_price(
&[ComputeBudgetInstruction::set_compute_unit_price(0)],
Ok(PrioritizationFeeDetails::new(
PrioritizationFeeType::ComputeUnitPrice(0),
0,
)),
support_round_compute_unit_price,
);
}

for support_round_compute_unit_price in [true, false] {
let cu_price = ComputeBudget::PRIORITY_FEE_TICK_SIZE - 1;
let expected_cu_price = if support_round_compute_unit_price {
0
} else {
cu_price
};
test_set_compute_unit_price(
&[ComputeBudgetInstruction::set_compute_unit_price(cu_price)],
Ok(PrioritizationFeeDetails::new(
PrioritizationFeeType::ComputeUnitPrice(expected_cu_price),
0,
)),
support_round_compute_unit_price,
);
}

for support_round_compute_unit_price in [true, false] {
test_set_compute_unit_price(
&[ComputeBudgetInstruction::set_compute_unit_price(
ComputeBudget::PRIORITY_FEE_TICK_SIZE,
)],
Ok(PrioritizationFeeDetails::new(
PrioritizationFeeType::ComputeUnitPrice(ComputeBudget::PRIORITY_FEE_TICK_SIZE),
0,
)),
support_round_compute_unit_price,
);
}

for support_round_compute_unit_price in [true, false] {
let cu_price = ComputeBudget::PRIORITY_FEE_TICK_SIZE + 1;
let expected_cu_price = if support_round_compute_unit_price {
ComputeBudget::PRIORITY_FEE_TICK_SIZE
} else {
cu_price
};
test_set_compute_unit_price(
&[ComputeBudgetInstruction::set_compute_unit_price(cu_price)],
Ok(PrioritizationFeeDetails::new(
PrioritizationFeeType::ComputeUnitPrice(expected_cu_price),
0,
)),
support_round_compute_unit_price,
);
}

for support_round_compute_unit_price in [true, false] {
let cu_price = 3 * ComputeBudget::PRIORITY_FEE_TICK_SIZE - 1;
let expected_cu_price = if support_round_compute_unit_price {
2 * ComputeBudget::PRIORITY_FEE_TICK_SIZE
} else {
cu_price
};
test_set_compute_unit_price(
&[ComputeBudgetInstruction::set_compute_unit_price(cu_price)],
Ok(PrioritizationFeeDetails::new(
PrioritizationFeeType::ComputeUnitPrice(expected_cu_price),
0,
)),
support_round_compute_unit_price,
);
}
}

#[test]
fn test_process_loaded_accounts_data_size_limit_instruction() {
let enable_request_heap_frame_ix: bool = true;
Expand Down Expand Up @@ -835,4 +960,37 @@ mod tests {
);
}
}

#[test]
fn test_round_prioritization_fee() {
assert_eq!(
ComputeBudget::round_prioritization_fee(1),
0,
"less than 1_000 MICRO_LAMPORTS should round down to zero"
);

assert_eq!(
ComputeBudget::round_prioritization_fee(ComputeBudget::PRIORITY_FEE_TICK_SIZE - 1),
0,
"less than 1_000 MICRO_LAMPORTS should round down to zero"
);

assert_eq!(
ComputeBudget::round_prioritization_fee(ComputeBudget::PRIORITY_FEE_TICK_SIZE),
ComputeBudget::PRIORITY_FEE_TICK_SIZE,
"1_000 MICRO_LAMPORTS should round to itself"
);

assert_eq!(
ComputeBudget::round_prioritization_fee(ComputeBudget::PRIORITY_FEE_TICK_SIZE + 1),
ComputeBudget::PRIORITY_FEE_TICK_SIZE,
"more than 1_000 MICRO_LAMPORTS should round down to the nearest"
);

assert_eq!(
ComputeBudget::round_prioritization_fee(ComputeBudget::PRIORITY_FEE_TICK_SIZE * 3 - 1),
ComputeBudget::PRIORITY_FEE_TICK_SIZE * 2,
"more than 1_000 MICRO_LAMPORTS should round down to the nearest"
);
}
}
8 changes: 5 additions & 3 deletions programs/sbf/tests/programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3833,7 +3833,8 @@ fn test_program_fees() {
true,
true,
true,
false,
true,
true,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should all be true since bank has all features enabled at ln 3805

);
bank_client
.send_and_confirm_message(&[&mint_keypair], message)
Expand All @@ -3844,7 +3845,7 @@ fn test_program_fees() {
let pre_balance = bank_client.get_balance(&mint_keypair.pubkey()).unwrap();
let message = Message::new(
&[
ComputeBudgetInstruction::set_compute_unit_price(1),
ComputeBudgetInstruction::set_compute_unit_price(1_000_000_000),
Instruction::new_with_bytes(program_id, &[], vec![]),
],
Some(&mint_keypair.pubkey()),
Expand All @@ -3859,7 +3860,8 @@ fn test_program_fees() {
true,
true,
true,
false,
true,
true,
);
assert!(expected_normal_fee < expected_prioritized_fee);

Expand Down
4 changes: 2 additions & 2 deletions rpc/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8660,7 +8660,7 @@ pub mod tests {
let account0 = Pubkey::new_unique();
let account1 = Pubkey::new_unique();
let account2 = Pubkey::new_unique();
let price0 = 42;
let price0 = 40_000;
let transactions = vec![
Transaction::new_unsigned(Message::new(
&[
Expand Down Expand Up @@ -8720,7 +8720,7 @@ pub mod tests {

rpc.advance_bank_to_confirmed_slot(1);
let slot1 = rpc.working_bank().slot();
let price1 = 11;
let price1 = 1_000;
let transactions = vec![
Transaction::new_unsigned(Message::new(
&[
Expand Down
8 changes: 6 additions & 2 deletions runtime/src/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ use {
self, add_set_tx_loaded_accounts_data_size_instruction, enable_request_heap_frame_ix,
include_loaded_accounts_data_size_in_fee_calculation,
remove_congestion_multiplier_from_fee_calculation, remove_deprecated_request_unit_ix,
simplify_writable_program_account_check, use_default_units_in_fee_calculation,
FeatureSet,
round_compute_unit_price, simplify_writable_program_account_check,
use_default_units_in_fee_calculation, FeatureSet,
},
fee::FeeStructure,
genesis_config::ClusterType,
Expand Down Expand Up @@ -256,6 +256,7 @@ impl Accounts {
!feature_set.is_active(&remove_deprecated_request_unit_ix::id()),
true, // don't reject txs that use request heap size ix
feature_set.is_active(&add_set_tx_loaded_accounts_data_size_instruction::id()),
feature_set.is_active(&round_compute_unit_price::id()),
);
// sanitize against setting size limit to zero
NonZeroUsize::new(compute_budget.loaded_accounts_data_size_limit).map_or(
Expand Down Expand Up @@ -732,6 +733,7 @@ impl Accounts {
feature_set.is_active(&enable_request_heap_frame_ix::id()) || self.accounts_db.expected_cluster_type() != ClusterType::MainnetBeta,
feature_set.is_active(&add_set_tx_loaded_accounts_data_size_instruction::id()),
feature_set.is_active(&include_loaded_accounts_data_size_in_fee_calculation::id()),
feature_set.is_active(&round_compute_unit_price::id()),
)
} else {
return (Err(TransactionError::BlockhashNotFound), None);
Expand Down Expand Up @@ -1770,6 +1772,7 @@ mod tests {
true,
true,
false,
false,
);
assert_eq!(fee, lamports_per_signature);

Expand Down Expand Up @@ -4333,6 +4336,7 @@ mod tests {
true,
true,
false,
false,
);
assert_eq!(fee, lamports_per_signature + prioritization_fee);

Expand Down
9 changes: 8 additions & 1 deletion runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ use {
enable_early_verification_of_account_modifications, enable_request_heap_frame_ix,
include_loaded_accounts_data_size_in_fee_calculation,
remove_congestion_multiplier_from_fee_calculation, remove_deprecated_request_unit_ix,
use_default_units_in_fee_calculation, FeatureSet,
round_compute_unit_price, use_default_units_in_fee_calculation, FeatureSet,
},
fee::FeeStructure,
fee_calculator::{FeeCalculator, FeeRateGovernor},
Expand Down Expand Up @@ -4561,6 +4561,7 @@ impl Bank {
.is_active(&add_set_tx_loaded_accounts_data_size_instruction::id()),
self.feature_set
.is_active(&include_loaded_accounts_data_size_in_fee_calculation::id()),
self.feature_set.is_active(&round_compute_unit_price::id()),
))
}

Expand Down Expand Up @@ -4612,6 +4613,7 @@ impl Bank {
.is_active(&add_set_tx_loaded_accounts_data_size_instruction::id()),
self.feature_set
.is_active(&include_loaded_accounts_data_size_in_fee_calculation::id()),
self.feature_set.is_active(&round_compute_unit_price::id()),
)
}

Expand Down Expand Up @@ -5602,6 +5604,7 @@ impl Bank {
true, // don't reject txs that use request heap size ix
self.feature_set
.is_active(&add_set_tx_loaded_accounts_data_size_instruction::id()),
self.feature_set.is_active(&round_compute_unit_price::id()),
);
compute_budget_process_transaction_time.stop();
saturating_add_assign!(
Expand Down Expand Up @@ -5898,6 +5901,7 @@ impl Bank {
}

/// Calculate fee for `SanitizedMessage`
#[allow(clippy::too_many_arguments)]
pub fn calculate_fee(
message: &SanitizedMessage,
lamports_per_signature: u64,
Expand All @@ -5908,6 +5912,7 @@ impl Bank {
enable_request_heap_frame_ix: bool,
support_set_accounts_data_size_limit_ix: bool,
include_loaded_account_data_size_in_fee: bool,
support_round_compute_unit_price: bool,
) -> u64 {
// Fee based on compute units and signatures
let congestion_multiplier = if lamports_per_signature == 0 {
Expand All @@ -5928,6 +5933,7 @@ impl Bank {
support_request_units_deprecated,
enable_request_heap_frame_ix,
support_set_accounts_data_size_limit_ix,
support_round_compute_unit_price,
)
.unwrap_or_default();
let prioritization_fee = prioritization_fee_details.get_fee();
Expand Down Expand Up @@ -6013,6 +6019,7 @@ impl Bank {
.is_active(&add_set_tx_loaded_accounts_data_size_instruction::id()),
self.feature_set
.is_active(&include_loaded_accounts_data_size_in_fee_calculation::id()),
self.feature_set.is_active(&round_compute_unit_price::id()),
);

// In case of instruction error, even though no accounts
Expand Down
Loading