Share function to get priority details from various transaction types (#26643)
This commit is contained in:
parent
be8813e588
commit
22d465cd57
|
@ -187,7 +187,10 @@ impl ForwardPacketBatchesByAccounts {
|
||||||
mod tests {
|
mod tests {
|
||||||
use {
|
use {
|
||||||
super::*,
|
super::*,
|
||||||
crate::unprocessed_packet_batches::{DeserializedPacket, TransactionPriorityDetails},
|
crate::{
|
||||||
|
transaction_priority_details::TransactionPriorityDetails,
|
||||||
|
unprocessed_packet_batches::DeserializedPacket,
|
||||||
|
},
|
||||||
solana_runtime::{
|
solana_runtime::{
|
||||||
bank::Bank,
|
bank::Bank,
|
||||||
bank_forks::BankForks,
|
bank_forks::BankForks,
|
||||||
|
|
|
@ -68,6 +68,7 @@ mod tower1_7_14;
|
||||||
pub mod tower_storage;
|
pub mod tower_storage;
|
||||||
pub mod tpu;
|
pub mod tpu;
|
||||||
pub mod tracer_packet_stats;
|
pub mod tracer_packet_stats;
|
||||||
|
pub mod transaction_priority_details;
|
||||||
pub mod tree_diff;
|
pub mod tree_diff;
|
||||||
pub mod tvu;
|
pub mod tvu;
|
||||||
pub mod unfrozen_gossip_verified_vote_hashes;
|
pub mod unfrozen_gossip_verified_vote_hashes;
|
||||||
|
|
|
@ -0,0 +1,177 @@
|
||||||
|
use {
|
||||||
|
solana_program_runtime::compute_budget::ComputeBudget,
|
||||||
|
solana_sdk::{
|
||||||
|
instruction::CompiledInstruction,
|
||||||
|
pubkey::Pubkey,
|
||||||
|
transaction::{SanitizedTransaction, SanitizedVersionedTransaction},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct TransactionPriorityDetails {
|
||||||
|
pub priority: u64,
|
||||||
|
pub compute_unit_limit: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait GetTransactionPriorityDetails {
|
||||||
|
fn get_transaction_priority_details(&self) -> Option<TransactionPriorityDetails>;
|
||||||
|
|
||||||
|
fn process_compute_budget_instruction<'a>(
|
||||||
|
instructions: impl Iterator<Item = (&'a Pubkey, &'a CompiledInstruction)>,
|
||||||
|
) -> Option<TransactionPriorityDetails> {
|
||||||
|
let mut compute_budget = ComputeBudget::default();
|
||||||
|
let prioritization_fee_details = compute_budget
|
||||||
|
.process_instructions(
|
||||||
|
instructions,
|
||||||
|
true, // use default units per instruction
|
||||||
|
true, // don't reject txs that use set compute unit price ix
|
||||||
|
)
|
||||||
|
.ok()?;
|
||||||
|
Some(TransactionPriorityDetails {
|
||||||
|
priority: prioritization_fee_details.get_priority(),
|
||||||
|
compute_unit_limit: compute_budget.compute_unit_limit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetTransactionPriorityDetails for SanitizedVersionedTransaction {
|
||||||
|
fn get_transaction_priority_details(&self) -> Option<TransactionPriorityDetails> {
|
||||||
|
Self::process_compute_budget_instruction(self.get_message().program_instructions_iter())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetTransactionPriorityDetails for SanitizedTransaction {
|
||||||
|
fn get_transaction_priority_details(&self) -> Option<TransactionPriorityDetails> {
|
||||||
|
Self::process_compute_budget_instruction(self.message().program_instructions_iter())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use {
|
||||||
|
super::*,
|
||||||
|
solana_sdk::{
|
||||||
|
compute_budget::ComputeBudgetInstruction,
|
||||||
|
message::Message,
|
||||||
|
pubkey::Pubkey,
|
||||||
|
signature::{Keypair, Signer},
|
||||||
|
system_instruction,
|
||||||
|
transaction::{Transaction, VersionedTransaction},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_priority_with_valid_request_heap_frame_tx() {
|
||||||
|
let keypair = Keypair::new();
|
||||||
|
let transaction = Transaction::new_unsigned(Message::new(
|
||||||
|
&[
|
||||||
|
system_instruction::transfer(&keypair.pubkey(), &Pubkey::new_unique(), 1),
|
||||||
|
ComputeBudgetInstruction::request_heap_frame(32 * 1024),
|
||||||
|
],
|
||||||
|
Some(&keypair.pubkey()),
|
||||||
|
));
|
||||||
|
|
||||||
|
// assert for SanitizedVersionedTransaction
|
||||||
|
let versioned_transaction = VersionedTransaction::from(transaction.clone());
|
||||||
|
let sanitized_versioned_transaction =
|
||||||
|
SanitizedVersionedTransaction::try_new(versioned_transaction).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
sanitized_versioned_transaction.get_transaction_priority_details(),
|
||||||
|
Some(TransactionPriorityDetails {
|
||||||
|
priority: 0,
|
||||||
|
compute_unit_limit:
|
||||||
|
solana_program_runtime::compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT
|
||||||
|
as u64
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert for SanitizedTransaction
|
||||||
|
let sanitized_transaction =
|
||||||
|
SanitizedTransaction::try_from_legacy_transaction(transaction).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
sanitized_transaction.get_transaction_priority_details(),
|
||||||
|
Some(TransactionPriorityDetails {
|
||||||
|
priority: 0,
|
||||||
|
compute_unit_limit:
|
||||||
|
solana_program_runtime::compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT
|
||||||
|
as u64
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_priority_with_valid_set_compute_units_limit() {
|
||||||
|
let requested_cu = 101u32;
|
||||||
|
let keypair = Keypair::new();
|
||||||
|
let transaction = Transaction::new_unsigned(Message::new(
|
||||||
|
&[
|
||||||
|
system_instruction::transfer(&keypair.pubkey(), &Pubkey::new_unique(), 1),
|
||||||
|
ComputeBudgetInstruction::set_compute_unit_limit(requested_cu),
|
||||||
|
],
|
||||||
|
Some(&keypair.pubkey()),
|
||||||
|
));
|
||||||
|
|
||||||
|
// assert for SanitizedVersionedTransaction
|
||||||
|
let versioned_transaction = VersionedTransaction::from(transaction.clone());
|
||||||
|
let sanitized_versioned_transaction =
|
||||||
|
SanitizedVersionedTransaction::try_new(versioned_transaction).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
sanitized_versioned_transaction.get_transaction_priority_details(),
|
||||||
|
Some(TransactionPriorityDetails {
|
||||||
|
priority: 0,
|
||||||
|
compute_unit_limit: requested_cu as u64,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert for SanitizedTransaction
|
||||||
|
let sanitized_transaction =
|
||||||
|
SanitizedTransaction::try_from_legacy_transaction(transaction).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
sanitized_transaction.get_transaction_priority_details(),
|
||||||
|
Some(TransactionPriorityDetails {
|
||||||
|
priority: 0,
|
||||||
|
compute_unit_limit: requested_cu as u64,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_priority_with_valid_set_compute_unit_price() {
|
||||||
|
let requested_price = 1_000;
|
||||||
|
let keypair = Keypair::new();
|
||||||
|
let transaction = Transaction::new_unsigned(Message::new(
|
||||||
|
&[
|
||||||
|
system_instruction::transfer(&keypair.pubkey(), &Pubkey::new_unique(), 1),
|
||||||
|
ComputeBudgetInstruction::set_compute_unit_price(requested_price),
|
||||||
|
],
|
||||||
|
Some(&keypair.pubkey()),
|
||||||
|
));
|
||||||
|
|
||||||
|
// assert for SanitizedVersionedTransaction
|
||||||
|
let versioned_transaction = VersionedTransaction::from(transaction.clone());
|
||||||
|
let sanitized_versioned_transaction =
|
||||||
|
SanitizedVersionedTransaction::try_new(versioned_transaction).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
sanitized_versioned_transaction.get_transaction_priority_details(),
|
||||||
|
Some(TransactionPriorityDetails {
|
||||||
|
priority: requested_price,
|
||||||
|
compute_unit_limit:
|
||||||
|
solana_program_runtime::compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT
|
||||||
|
as u64
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert for SanitizedTransaction
|
||||||
|
let sanitized_transaction =
|
||||||
|
SanitizedTransaction::try_from_legacy_transaction(transaction).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
sanitized_transaction.get_transaction_priority_details(),
|
||||||
|
Some(TransactionPriorityDetails {
|
||||||
|
priority: requested_price,
|
||||||
|
compute_unit_limit:
|
||||||
|
solana_program_runtime::compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT
|
||||||
|
as u64
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,13 @@
|
||||||
use {
|
use {
|
||||||
|
crate::transaction_priority_details::{
|
||||||
|
GetTransactionPriorityDetails, TransactionPriorityDetails,
|
||||||
|
},
|
||||||
min_max_heap::MinMaxHeap,
|
min_max_heap::MinMaxHeap,
|
||||||
solana_perf::packet::{Packet, PacketBatch},
|
solana_perf::packet::{Packet, PacketBatch},
|
||||||
solana_program_runtime::compute_budget::ComputeBudget,
|
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
feature_set,
|
feature_set,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
message::{Message, SanitizedVersionedMessage},
|
message::Message,
|
||||||
sanitize::SanitizeError,
|
sanitize::SanitizeError,
|
||||||
short_vec::decode_shortu16_len,
|
short_vec::decode_shortu16_len,
|
||||||
signature::Signature,
|
signature::Signature,
|
||||||
|
@ -39,12 +41,6 @@ pub enum DeserializedPacketError {
|
||||||
PrioritizationFailure,
|
PrioritizationFailure,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
|
||||||
pub struct TransactionPriorityDetails {
|
|
||||||
pub priority: u64,
|
|
||||||
pub compute_unit_limit: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct ImmutableDeserializedPacket {
|
pub struct ImmutableDeserializedPacket {
|
||||||
original_packet: Packet,
|
original_packet: Packet,
|
||||||
|
@ -113,7 +109,7 @@ impl DeserializedPacket {
|
||||||
|
|
||||||
// drop transaction if prioritization fails.
|
// drop transaction if prioritization fails.
|
||||||
let priority_details = priority_details
|
let priority_details = priority_details
|
||||||
.or_else(|| get_priority_details(sanitized_transaction.get_message()))
|
.or_else(|| sanitized_transaction.get_transaction_priority_details())
|
||||||
.ok_or(DeserializedPacketError::PrioritizationFailure)?;
|
.ok_or(DeserializedPacketError::PrioritizationFailure)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -406,21 +402,6 @@ pub fn packet_message(packet: &Packet) -> Result<&[u8], DeserializedPacketError>
|
||||||
.ok_or(DeserializedPacketError::SignatureOverflowed(sig_size))
|
.ok_or(DeserializedPacketError::SignatureOverflowed(sig_size))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_priority_details(message: &SanitizedVersionedMessage) -> Option<TransactionPriorityDetails> {
|
|
||||||
let mut compute_budget = ComputeBudget::default();
|
|
||||||
let prioritization_fee_details = compute_budget
|
|
||||||
.process_instructions(
|
|
||||||
message.program_instructions_iter(),
|
|
||||||
true, // use default units per instruction
|
|
||||||
true, // don't reject txs that use set compute unit price ix
|
|
||||||
)
|
|
||||||
.ok()?;
|
|
||||||
Some(TransactionPriorityDetails {
|
|
||||||
priority: prioritization_fee_details.get_priority(),
|
|
||||||
compute_unit_limit: compute_budget.compute_unit_limit,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn transactions_to_deserialized_packets(
|
pub fn transactions_to_deserialized_packets(
|
||||||
transactions: &[Transaction],
|
transactions: &[Transaction],
|
||||||
) -> Result<Vec<DeserializedPacket>, DeserializedPacketError> {
|
) -> Result<Vec<DeserializedPacket>, DeserializedPacketError> {
|
||||||
|
@ -464,11 +445,8 @@ mod tests {
|
||||||
super::*,
|
super::*,
|
||||||
solana_perf::packet::PacketFlags,
|
solana_perf::packet::PacketFlags,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
compute_budget::ComputeBudgetInstruction,
|
|
||||||
message::VersionedMessage,
|
|
||||||
pubkey::Pubkey,
|
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
system_instruction, system_transaction,
|
system_transaction,
|
||||||
transaction::{SimpleAddressLoader, Transaction},
|
transaction::{SimpleAddressLoader, Transaction},
|
||||||
},
|
},
|
||||||
solana_vote_program::vote_transaction,
|
solana_vote_program::vote_transaction,
|
||||||
|
@ -600,72 +578,6 @@ mod tests {
|
||||||
assert!(unprocessed_packet_batches.pop_max_n(0).is_none());
|
assert!(unprocessed_packet_batches.pop_max_n(0).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_get_priority_with_valid_request_heap_frame_tx() {
|
|
||||||
let payer = Pubkey::new_unique();
|
|
||||||
let message = SanitizedVersionedMessage::try_from(VersionedMessage::Legacy(Message::new(
|
|
||||||
&[
|
|
||||||
system_instruction::transfer(&Pubkey::new_unique(), &Pubkey::new_unique(), 1),
|
|
||||||
ComputeBudgetInstruction::request_heap_frame(32 * 1024),
|
|
||||||
],
|
|
||||||
Some(&payer),
|
|
||||||
)))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
get_priority_details(&message),
|
|
||||||
Some(TransactionPriorityDetails {
|
|
||||||
priority: 0,
|
|
||||||
compute_unit_limit:
|
|
||||||
solana_program_runtime::compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT
|
|
||||||
as u64
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_get_priority_with_valid_set_compute_units_limit() {
|
|
||||||
let requested_cu = 101u32;
|
|
||||||
let payer = Pubkey::new_unique();
|
|
||||||
let message = SanitizedVersionedMessage::try_from(VersionedMessage::Legacy(Message::new(
|
|
||||||
&[
|
|
||||||
system_instruction::transfer(&Pubkey::new_unique(), &Pubkey::new_unique(), 1),
|
|
||||||
ComputeBudgetInstruction::set_compute_unit_limit(requested_cu),
|
|
||||||
],
|
|
||||||
Some(&payer),
|
|
||||||
)))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
get_priority_details(&message),
|
|
||||||
Some(TransactionPriorityDetails {
|
|
||||||
priority: 0,
|
|
||||||
compute_unit_limit: requested_cu as u64,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_get_priority_with_valid_set_compute_unit_price() {
|
|
||||||
let requested_price = 1_000;
|
|
||||||
let payer = Pubkey::new_unique();
|
|
||||||
let message = SanitizedVersionedMessage::try_from(VersionedMessage::Legacy(Message::new(
|
|
||||||
&[
|
|
||||||
system_instruction::transfer(&Pubkey::new_unique(), &Pubkey::new_unique(), 1),
|
|
||||||
ComputeBudgetInstruction::set_compute_unit_price(requested_price),
|
|
||||||
],
|
|
||||||
Some(&payer),
|
|
||||||
)))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
get_priority_details(&message),
|
|
||||||
Some(TransactionPriorityDetails {
|
|
||||||
priority: requested_price,
|
|
||||||
compute_unit_limit:
|
|
||||||
solana_program_runtime::compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT
|
|
||||||
as u64
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn make_test_packets(
|
fn make_test_packets(
|
||||||
transactions: Vec<Transaction>,
|
transactions: Vec<Transaction>,
|
||||||
|
|
Loading…
Reference in New Issue