Share function to get priority details from various transaction types (#26643)

This commit is contained in:
Tao Zhu 2022-07-15 18:17:22 -05:00 committed by GitHub
parent be8813e588
commit 22d465cd57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 188 additions and 95 deletions

View File

@ -187,7 +187,10 @@ impl ForwardPacketBatchesByAccounts {
mod tests {
use {
super::*,
crate::unprocessed_packet_batches::{DeserializedPacket, TransactionPriorityDetails},
crate::{
transaction_priority_details::TransactionPriorityDetails,
unprocessed_packet_batches::DeserializedPacket,
},
solana_runtime::{
bank::Bank,
bank_forks::BankForks,

View File

@ -68,6 +68,7 @@ mod tower1_7_14;
pub mod tower_storage;
pub mod tpu;
pub mod tracer_packet_stats;
pub mod transaction_priority_details;
pub mod tree_diff;
pub mod tvu;
pub mod unfrozen_gossip_verified_vote_hashes;

View File

@ -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
})
);
}
}

View File

@ -1,11 +1,13 @@
use {
crate::transaction_priority_details::{
GetTransactionPriorityDetails, TransactionPriorityDetails,
},
min_max_heap::MinMaxHeap,
solana_perf::packet::{Packet, PacketBatch},
solana_program_runtime::compute_budget::ComputeBudget,
solana_sdk::{
feature_set,
hash::Hash,
message::{Message, SanitizedVersionedMessage},
message::Message,
sanitize::SanitizeError,
short_vec::decode_shortu16_len,
signature::Signature,
@ -39,12 +41,6 @@ pub enum DeserializedPacketError {
PrioritizationFailure,
}
#[derive(Debug, PartialEq, Eq)]
pub struct TransactionPriorityDetails {
pub priority: u64,
pub compute_unit_limit: u64,
}
#[derive(Debug, PartialEq, Eq)]
pub struct ImmutableDeserializedPacket {
original_packet: Packet,
@ -113,7 +109,7 @@ impl DeserializedPacket {
// drop transaction if prioritization fails.
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(Self {
@ -406,21 +402,6 @@ pub fn packet_message(packet: &Packet) -> Result<&[u8], DeserializedPacketError>
.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(
transactions: &[Transaction],
) -> Result<Vec<DeserializedPacket>, DeserializedPacketError> {
@ -464,11 +445,8 @@ mod tests {
super::*,
solana_perf::packet::PacketFlags,
solana_sdk::{
compute_budget::ComputeBudgetInstruction,
message::VersionedMessage,
pubkey::Pubkey,
signature::{Keypair, Signer},
system_instruction, system_transaction,
system_transaction,
transaction::{SimpleAddressLoader, Transaction},
},
solana_vote_program::vote_transaction,
@ -600,72 +578,6 @@ mod tests {
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)]
fn make_test_packets(
transactions: Vec<Transaction>,