add requested limits to static meta (#34361)

* add requested limits to static meta
* rebase to catch up on compue_budget_processor no longer needs feature_set; update requested limits as flat fields of static meta without expiry
This commit is contained in:
Tao Zhu 2023-12-15 18:39:19 -06:00 committed by GitHub
parent 86c88d7ff6
commit 310c7a4f9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 151 additions and 69 deletions

View File

@ -11,6 +11,9 @@
//! with its dynamic metadata loaded.
use {
crate::transaction_meta::{DynamicMeta, StaticMeta, TransactionMeta},
solana_program_runtime::compute_budget_processor::{
process_compute_budget_instructions, ComputeBudgetLimits,
},
solana_sdk::{
hash::Hash,
message::{AddressLoader, SanitizedMessage, SanitizedVersionedMessage},
@ -48,6 +51,15 @@ impl<M: StaticMetaAccess> StaticMeta for RuntimeTransaction<M> {
fn is_simple_vote_tx(&self) -> bool {
self.meta.is_simple_vote_tx
}
fn compute_unit_limit(&self) -> u32 {
self.meta.compute_unit_limit
}
fn compute_unit_price(&self) -> u64 {
self.meta.compute_unit_price
}
fn loaded_accounts_bytes(&self) -> u32 {
self.meta.loaded_accounts_bytes
}
}
impl<M: DynamicMetaAccess> DynamicMeta for RuntimeTransaction<M> {}
@ -65,9 +77,18 @@ impl RuntimeTransaction<SanitizedVersionedMessage> {
);
let (signatures, message) = sanitized_versioned_tx.destruct();
meta.set_message_hash(message_hash.unwrap_or_else(|| message.message.hash()));
let ComputeBudgetLimits {
compute_unit_limit,
compute_unit_price,
loaded_accounts_bytes,
..
} = process_compute_budget_instructions(message.program_instructions_iter())?;
meta.set_compute_unit_limit(compute_unit_limit);
meta.set_compute_unit_price(compute_unit_price);
meta.set_loaded_accounts_bytes(loaded_accounts_bytes);
Ok(Self {
signatures,
message,
@ -109,6 +130,7 @@ mod tests {
},
solana_sdk::{
compute_budget::ComputeBudgetInstruction,
instruction::Instruction,
message::Message,
signer::{keypair::Keypair, Signer},
transaction::{SimpleAddressLoader, Transaction, VersionedTransaction},
@ -131,91 +153,98 @@ mod tests {
SanitizedVersionedTransaction::try_from(VersionedTransaction::from(vote_tx)).unwrap()
}
fn non_vote_sanitized_versioned_transaction(
compute_unit_price: u64,
) -> SanitizedVersionedTransaction {
let from_keypair = Keypair::new();
let ixs = vec![
system_instruction::transfer(
fn non_vote_sanitized_versioned_transaction() -> SanitizedVersionedTransaction {
TestTransaction::new().to_sanitized_versioned_transaction()
}
// Simple transfer transaction for testing, it does not support vote instruction
// because simple vote transaction will not request limits
struct TestTransaction {
from_keypair: Keypair,
hash: Hash,
instructions: Vec<Instruction>,
}
impl TestTransaction {
fn new() -> Self {
let from_keypair = Keypair::new();
let instructions = vec![system_instruction::transfer(
&from_keypair.pubkey(),
&solana_sdk::pubkey::new_rand(),
1,
),
ComputeBudgetInstruction::set_compute_unit_price(compute_unit_price),
];
let message = Message::new(&ixs, Some(&from_keypair.pubkey()));
let tx = Transaction::new(&[&from_keypair], message, Hash::new_unique());
SanitizedVersionedTransaction::try_from(VersionedTransaction::from(tx)).unwrap()
}
)];
TestTransaction {
from_keypair,
hash: Hash::new_unique(),
instructions,
}
}
fn get_transaction_meta(
svt: SanitizedVersionedTransaction,
hash: Option<Hash>,
is_simple_vote: Option<bool>,
) -> TransactionMeta {
RuntimeTransaction::<SanitizedVersionedMessage>::try_from(svt, hash, is_simple_vote)
.unwrap()
.meta
fn add_compute_unit_limit(&mut self, val: u32) -> &mut TestTransaction {
self.instructions
.push(ComputeBudgetInstruction::set_compute_unit_limit(val));
self
}
fn add_compute_unit_price(&mut self, val: u64) -> &mut TestTransaction {
self.instructions
.push(ComputeBudgetInstruction::set_compute_unit_price(val));
self
}
fn add_loaded_accounts_bytes(&mut self, val: u32) -> &mut TestTransaction {
self.instructions
.push(ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(val));
self
}
fn to_sanitized_versioned_transaction(&self) -> SanitizedVersionedTransaction {
let message = Message::new(&self.instructions, Some(&self.from_keypair.pubkey()));
let tx = Transaction::new(&[&self.from_keypair], message, self.hash);
SanitizedVersionedTransaction::try_from(VersionedTransaction::from(tx)).unwrap()
}
}
#[test]
fn test_new_runtime_transaction_static() {
let hash = Hash::new_unique();
let compute_unit_price = 1_000;
fn test_runtime_transaction_is_vote_meta() {
fn get_is_simple_vote(
svt: SanitizedVersionedTransaction,
is_simple_vote: Option<bool>,
) -> bool {
RuntimeTransaction::<SanitizedVersionedMessage>::try_from(svt, None, is_simple_vote)
.unwrap()
.meta
.is_simple_vote_tx
}
assert_eq!(
TransactionMeta {
message_hash: hash,
is_simple_vote_tx: false,
},
get_transaction_meta(
non_vote_sanitized_versioned_transaction(compute_unit_price),
Some(hash),
None
)
);
assert!(!get_is_simple_vote(
non_vote_sanitized_versioned_transaction(),
None
));
assert_eq!(
TransactionMeta {
message_hash: hash,
is_simple_vote_tx: true,
},
get_transaction_meta(
non_vote_sanitized_versioned_transaction(compute_unit_price),
Some(hash),
Some(true), // override
)
);
assert!(get_is_simple_vote(
non_vote_sanitized_versioned_transaction(),
Some(true), // override
));
assert_eq!(
TransactionMeta {
message_hash: hash,
is_simple_vote_tx: true,
},
get_transaction_meta(vote_sanitized_versioned_transaction(), Some(hash), None)
);
assert!(get_is_simple_vote(
vote_sanitized_versioned_transaction(),
None
));
assert_eq!(
TransactionMeta {
message_hash: hash,
is_simple_vote_tx: false,
},
get_transaction_meta(
vote_sanitized_versioned_transaction(),
Some(hash),
Some(false), // override
)
);
assert!(!get_is_simple_vote(
vote_sanitized_versioned_transaction(),
Some(false), // override
));
}
#[test]
fn test_advance_transaction_type() {
fn test_advancing_transaction_type() {
let hash = Hash::new_unique();
let compute_unit_price = 999;
let statically_loaded_transaction =
RuntimeTransaction::<SanitizedVersionedMessage>::try_from(
non_vote_sanitized_versioned_transaction(compute_unit_price),
non_vote_sanitized_versioned_transaction(),
Some(hash),
None,
)
@ -234,4 +263,39 @@ mod tests {
assert_eq!(hash, *dynamically_loaded_transaction.message_hash());
assert!(!dynamically_loaded_transaction.is_simple_vote_tx());
}
#[test]
fn test_runtime_transaction_static_meta() {
let hash = Hash::new_unique();
let compute_unit_limit = 250_000;
let compute_unit_price = 1_000;
let loaded_accounts_bytes = 1_024;
let mut test_transaction = TestTransaction::new();
let runtime_transaction_static = RuntimeTransaction::<SanitizedVersionedMessage>::try_from(
test_transaction
.add_compute_unit_limit(compute_unit_limit)
.add_compute_unit_price(compute_unit_price)
.add_loaded_accounts_bytes(loaded_accounts_bytes)
.to_sanitized_versioned_transaction(),
Some(hash),
None,
)
.unwrap();
assert_eq!(&hash, runtime_transaction_static.message_hash());
assert!(!runtime_transaction_static.is_simple_vote_tx());
assert_eq!(
compute_unit_limit,
runtime_transaction_static.compute_unit_limit()
);
assert_eq!(
compute_unit_price,
runtime_transaction_static.compute_unit_price()
);
assert_eq!(
loaded_accounts_bytes,
runtime_transaction_static.loaded_accounts_bytes()
);
}
}

View File

@ -14,10 +14,13 @@
use solana_sdk::hash::Hash;
/// metadata can be extracted statically from sanitized transaction,
/// for example: message hash, simple-vote-tx flag, compute budget limits,
/// for example: message hash, simple-vote-tx flag, limits set by instructions
pub trait StaticMeta {
fn message_hash(&self) -> &Hash;
fn is_simple_vote_tx(&self) -> bool;
fn compute_unit_limit(&self) -> u32;
fn compute_unit_price(&self) -> u64;
fn loaded_accounts_bytes(&self) -> u32;
}
/// Statically loaded meta is a supertrait of Dynamically loaded meta, when
@ -31,6 +34,9 @@ pub trait DynamicMeta: StaticMeta {}
pub struct TransactionMeta {
pub(crate) message_hash: Hash,
pub(crate) is_simple_vote_tx: bool,
pub(crate) compute_unit_limit: u32,
pub(crate) compute_unit_price: u64,
pub(crate) loaded_accounts_bytes: u32,
}
impl TransactionMeta {
@ -41,4 +47,16 @@ impl TransactionMeta {
pub(crate) fn set_is_simple_vote_tx(&mut self, is_simple_vote_tx: bool) {
self.is_simple_vote_tx = is_simple_vote_tx;
}
pub(crate) fn set_compute_unit_limit(&mut self, compute_unit_limit: u32) {
self.compute_unit_limit = compute_unit_limit;
}
pub(crate) fn set_compute_unit_price(&mut self, compute_unit_price: u64) {
self.compute_unit_price = compute_unit_price;
}
pub(crate) fn set_loaded_accounts_bytes(&mut self, loaded_accounts_bytes: u32) {
self.loaded_accounts_bytes = loaded_accounts_bytes;
}
}