Add user requested CU (eg. compute_budget.compute_unit_limit) to immutable_deserialized_packet, to be used in cost model and prioritized forwarding (#25695)
This commit is contained in:
parent
149a54b786
commit
51ac599915
|
@ -2120,7 +2120,6 @@ impl BankingStage {
|
||||||
.increment_newly_buffered_packets_count(packet_indexes.len() as u64);
|
.increment_newly_buffered_packets_count(packet_indexes.len() as u64);
|
||||||
|
|
||||||
let number_of_dropped_packets = unprocessed_packet_batches.insert_batch(
|
let number_of_dropped_packets = unprocessed_packet_batches.insert_batch(
|
||||||
// Passing `None` for bank for now will make all packet weights 0
|
|
||||||
unprocessed_packet_batches::deserialize_packets(packet_batch, packet_indexes),
|
unprocessed_packet_batches::deserialize_packets(packet_batch, packet_indexes),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -34,13 +34,19 @@ pub enum DeserializedPacketError {
|
||||||
PrioritizationFailure,
|
PrioritizationFailure,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct TransactionPriorityDetails {
|
||||||
|
priority: u64,
|
||||||
|
compute_unit_limit: u64,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct ImmutableDeserializedPacket {
|
pub struct ImmutableDeserializedPacket {
|
||||||
original_packet: Packet,
|
original_packet: Packet,
|
||||||
transaction: SanitizedVersionedTransaction,
|
transaction: SanitizedVersionedTransaction,
|
||||||
message_hash: Hash,
|
message_hash: Hash,
|
||||||
is_simple_vote: bool,
|
is_simple_vote: bool,
|
||||||
priority: u64,
|
priority_details: TransactionPriorityDetails,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImmutableDeserializedPacket {
|
impl ImmutableDeserializedPacket {
|
||||||
|
@ -65,7 +71,11 @@ impl ImmutableDeserializedPacket {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn priority(&self) -> u64 {
|
pub fn priority(&self) -> u64 {
|
||||||
self.priority
|
self.priority_details.priority
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compute_unit_limit(&self) -> u64 {
|
||||||
|
self.priority_details.compute_unit_limit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,13 +93,16 @@ impl DeserializedPacket {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn new_with_priority(packet: Packet, priority: u64) -> Result<Self, DeserializedPacketError> {
|
fn new_with_priority_details(
|
||||||
Self::new_internal(packet, Some(priority))
|
packet: Packet,
|
||||||
|
priority_details: TransactionPriorityDetails,
|
||||||
|
) -> Result<Self, DeserializedPacketError> {
|
||||||
|
Self::new_internal(packet, Some(priority_details))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_internal(
|
pub fn new_internal(
|
||||||
packet: Packet,
|
packet: Packet,
|
||||||
priority: Option<u64>,
|
priority_details: Option<TransactionPriorityDetails>,
|
||||||
) -> Result<Self, DeserializedPacketError> {
|
) -> Result<Self, DeserializedPacketError> {
|
||||||
let versioned_transaction: VersionedTransaction = packet.deserialize_slice(..)?;
|
let versioned_transaction: VersionedTransaction = packet.deserialize_slice(..)?;
|
||||||
let sanitized_transaction = SanitizedVersionedTransaction::try_from(versioned_transaction)?;
|
let sanitized_transaction = SanitizedVersionedTransaction::try_from(versioned_transaction)?;
|
||||||
|
@ -98,8 +111,8 @@ impl DeserializedPacket {
|
||||||
let is_simple_vote = packet.meta.is_simple_vote_tx();
|
let is_simple_vote = packet.meta.is_simple_vote_tx();
|
||||||
|
|
||||||
// drop transaction if prioritization fails.
|
// drop transaction if prioritization fails.
|
||||||
let priority = priority
|
let priority_details = priority_details
|
||||||
.or_else(|| get_priority(sanitized_transaction.get_message()))
|
.or_else(|| get_priority_details(sanitized_transaction.get_message()))
|
||||||
.ok_or(DeserializedPacketError::PrioritizationFailure)?;
|
.ok_or(DeserializedPacketError::PrioritizationFailure)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -108,7 +121,7 @@ impl DeserializedPacket {
|
||||||
transaction: sanitized_transaction,
|
transaction: sanitized_transaction,
|
||||||
message_hash,
|
message_hash,
|
||||||
is_simple_vote,
|
is_simple_vote,
|
||||||
priority,
|
priority_details,
|
||||||
}),
|
}),
|
||||||
forwarded: false,
|
forwarded: false,
|
||||||
})
|
})
|
||||||
|
@ -364,7 +377,7 @@ pub fn packet_message(packet: &Packet) -> Result<&[u8], DeserializedPacketError>
|
||||||
.ok_or(DeserializedPacketError::SignatureOverflowed(sig_size))
|
.ok_or(DeserializedPacketError::SignatureOverflowed(sig_size))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_priority(message: &SanitizedVersionedMessage) -> Option<u64> {
|
fn get_priority_details(message: &SanitizedVersionedMessage) -> Option<TransactionPriorityDetails> {
|
||||||
let mut compute_budget = ComputeBudget::default();
|
let mut compute_budget = ComputeBudget::default();
|
||||||
let prioritization_fee_details = compute_budget
|
let prioritization_fee_details = compute_budget
|
||||||
.process_instructions(
|
.process_instructions(
|
||||||
|
@ -374,7 +387,10 @@ fn get_priority(message: &SanitizedVersionedMessage) -> Option<u64> {
|
||||||
true, // don't reject txs that use set compute unit price ix
|
true, // don't reject txs that use set compute unit price ix
|
||||||
)
|
)
|
||||||
.ok()?;
|
.ok()?;
|
||||||
Some(prioritization_fee_details.get_priority())
|
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(
|
||||||
|
@ -395,7 +411,7 @@ mod tests {
|
||||||
super::*,
|
super::*,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
compute_budget::ComputeBudgetInstruction, message::VersionedMessage, pubkey::Pubkey,
|
compute_budget::ComputeBudgetInstruction, message::VersionedMessage, pubkey::Pubkey,
|
||||||
signature::Keypair, system_transaction,
|
signature::Keypair, system_instruction, system_transaction,
|
||||||
},
|
},
|
||||||
std::net::IpAddr,
|
std::net::IpAddr,
|
||||||
};
|
};
|
||||||
|
@ -415,7 +431,7 @@ mod tests {
|
||||||
DeserializedPacket::new(packet).unwrap()
|
DeserializedPacket::new(packet).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn packet_with_priority(priority: u64) -> DeserializedPacket {
|
fn packet_with_priority_details(priority: u64, compute_unit_limit: u64) -> DeserializedPacket {
|
||||||
let tx = system_transaction::transfer(
|
let tx = system_transaction::transfer(
|
||||||
&Keypair::new(),
|
&Keypair::new(),
|
||||||
&solana_sdk::pubkey::new_rand(),
|
&solana_sdk::pubkey::new_rand(),
|
||||||
|
@ -423,7 +439,14 @@ mod tests {
|
||||||
Hash::new_unique(),
|
Hash::new_unique(),
|
||||||
);
|
);
|
||||||
let packet = Packet::from_data(None, &tx).unwrap();
|
let packet = Packet::from_data(None, &tx).unwrap();
|
||||||
DeserializedPacket::new_with_priority(packet, priority).unwrap()
|
DeserializedPacket::new_with_priority_details(
|
||||||
|
packet,
|
||||||
|
TransactionPriorityDetails {
|
||||||
|
priority,
|
||||||
|
compute_unit_limit,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -444,10 +467,10 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unprocessed_packet_batches_insert_minimum_packet_over_capacity() {
|
fn test_unprocessed_packet_batches_insert_minimum_packet_over_capacity() {
|
||||||
let heavier_packet_weight = 2;
|
let heavier_packet_weight = 2;
|
||||||
let heavier_packet = packet_with_priority(heavier_packet_weight);
|
let heavier_packet = packet_with_priority_details(heavier_packet_weight, 200_000);
|
||||||
|
|
||||||
let lesser_packet_weight = heavier_packet_weight - 1;
|
let lesser_packet_weight = heavier_packet_weight - 1;
|
||||||
let lesser_packet = packet_with_priority(lesser_packet_weight);
|
let lesser_packet = packet_with_priority_details(lesser_packet_weight, 200_000);
|
||||||
|
|
||||||
// Test that the heavier packet is actually heavier
|
// Test that the heavier packet is actually heavier
|
||||||
let mut unprocessed_packet_batches = UnprocessedPacketBatches::with_capacity(2);
|
let mut unprocessed_packet_batches = UnprocessedPacketBatches::with_capacity(2);
|
||||||
|
@ -528,10 +551,65 @@ mod tests {
|
||||||
fn test_get_priority_with_valid_request_heap_frame_tx() {
|
fn test_get_priority_with_valid_request_heap_frame_tx() {
|
||||||
let payer = Pubkey::new_unique();
|
let payer = Pubkey::new_unique();
|
||||||
let message = SanitizedVersionedMessage::try_from(VersionedMessage::Legacy(Message::new(
|
let message = SanitizedVersionedMessage::try_from(VersionedMessage::Legacy(Message::new(
|
||||||
&[ComputeBudgetInstruction::request_heap_frame(32 * 1024)],
|
&[
|
||||||
|
system_instruction::transfer(&Pubkey::new_unique(), &Pubkey::new_unique(), 1),
|
||||||
|
ComputeBudgetInstruction::request_heap_frame(32 * 1024),
|
||||||
|
],
|
||||||
Some(&payer),
|
Some(&payer),
|
||||||
)))
|
)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(get_priority(&message), Some(0));
|
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
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue