From d8fcb423de85715101212d279fa81f53265d7e82 Mon Sep 17 00:00:00 2001 From: Tao Zhu Date: Thu, 7 Dec 2023 23:19:12 +0000 Subject: [PATCH 1/3] add requested limits to static meta --- .../src/runtime_transaction.rs | 33 ++++++++++++++++++- runtime-transaction/src/transaction_meta.rs | 32 ++++++++++++++++-- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/runtime-transaction/src/runtime_transaction.rs b/runtime-transaction/src/runtime_transaction.rs index df6acbccdd2905..84b69c6da4be6b 100644 --- a/runtime-transaction/src/runtime_transaction.rs +++ b/runtime-transaction/src/runtime_transaction.rs @@ -10,12 +10,14 @@ //! ALT, RuntimeTransaction transits into Dynamically Loaded state, //! with its dynamic metadata loaded. use { - crate::transaction_meta::{DynamicMeta, StaticMeta, TransactionMeta}, + crate::transaction_meta::{DynamicMeta, RequestedLimits, StaticMeta, TransactionMeta}, + solana_program_runtime::compute_budget_processor::ComputeBudgetLimits, solana_sdk::{ hash::Hash, message::{AddressLoader, SanitizedMessage, SanitizedVersionedMessage}, signature::Signature, simple_vote_transaction_checker::is_simple_vote_transaction, + slot_history::Slot, transaction::{Result, SanitizedVersionedTransaction}, }, }; @@ -41,6 +43,17 @@ impl StaticMetaAccess for SanitizedVersionedMessage {} impl StaticMetaAccess for SanitizedMessage {} impl DynamicMetaAccess for SanitizedMessage {} +impl RequestedLimits for RuntimeTransaction { + fn requested_limits(&self, current_slot: Option) -> Option<&ComputeBudgetLimits> { + if let Some(current_slot) = current_slot { + (current_slot <= self.meta.requested_limits.expiry) + .then_some(&self.meta.requested_limits.compute_budget_limits) + } else { + Some(&self.meta.requested_limits.compute_budget_limits) + } + } +} + impl StaticMeta for RuntimeTransaction { fn message_hash(&self) -> &Hash { &self.meta.message_hash @@ -48,6 +61,18 @@ impl StaticMeta for RuntimeTransaction { fn is_simple_vote_tx(&self) -> bool { self.meta.is_simple_vote_tx } + fn compute_unit_limit(&self, current_slot: Option) -> Option { + self.requested_limits(current_slot) + .map(|requested_limits| requested_limits.compute_unit_limit) + } + fn compute_unit_price(&self, current_slot: Option) -> Option { + self.requested_limits(current_slot) + .map(|requested_limits| requested_limits.compute_unit_price) + } + fn loaded_accounts_bytes(&self, current_slot: Option) -> Option { + self.requested_limits(current_slot) + .map(|requested_limits| requested_limits.loaded_accounts_bytes) + } } impl DynamicMeta for RuntimeTransaction {} @@ -103,6 +128,7 @@ impl RuntimeTransaction { mod tests { use { super::*, + crate::transaction_meta::RequestedLimitsWithExpiry, solana_program::{ system_instruction, vote::{self, state::Vote}, @@ -162,11 +188,13 @@ mod tests { fn test_new_runtime_transaction_static() { let hash = Hash::new_unique(); let compute_unit_price = 1_000; + let requested_limits = RequestedLimitsWithExpiry::default(); assert_eq!( TransactionMeta { message_hash: hash, is_simple_vote_tx: false, + requested_limits: requested_limits.clone(), }, get_transaction_meta( non_vote_sanitized_versioned_transaction(compute_unit_price), @@ -179,6 +207,7 @@ mod tests { TransactionMeta { message_hash: hash, is_simple_vote_tx: true, + requested_limits: requested_limits.clone(), }, get_transaction_meta( non_vote_sanitized_versioned_transaction(compute_unit_price), @@ -191,6 +220,7 @@ mod tests { TransactionMeta { message_hash: hash, is_simple_vote_tx: true, + requested_limits: requested_limits.clone(), }, get_transaction_meta(vote_sanitized_versioned_transaction(), Some(hash), None) ); @@ -199,6 +229,7 @@ mod tests { TransactionMeta { message_hash: hash, is_simple_vote_tx: false, + requested_limits, }, get_transaction_meta( vote_sanitized_versioned_transaction(), diff --git a/runtime-transaction/src/transaction_meta.rs b/runtime-transaction/src/transaction_meta.rs index 2eec699f291e36..c01ba3817142bf 100644 --- a/runtime-transaction/src/transaction_meta.rs +++ b/runtime-transaction/src/transaction_meta.rs @@ -11,13 +11,29 @@ //! The StaticMeta and DynamicMeta traits are accessor traits on the //! RuntimeTransaction types, not the TransactionMeta itself. //! -use solana_sdk::hash::Hash; +use { + solana_program_runtime::compute_budget_processor::ComputeBudgetLimits, + solana_sdk::{hash::Hash, slot_history::Slot}, +}; + +/// private trait to avoid exposing `ComputeBudgetLimits` to callsite of RuntimeTransaction. +pub(crate) trait RequestedLimits { + fn requested_limits(&self, current_slot: Option) -> Option<&ComputeBudgetLimits>; +} /// metadata can be extracted statically from sanitized transaction, -/// for example: message hash, simple-vote-tx flag, compute budget limits, -pub trait StaticMeta { +/// for example: message hash, simple-vote-tx flag, limits set by instructions +#[allow(private_bounds)] +pub trait StaticMeta: RequestedLimits { fn message_hash(&self) -> &Hash; fn is_simple_vote_tx(&self) -> bool; + + // get fields' value from RequestedLimitsWithExpiry, + // `current_slot`, sets to None to skip expiry check, otherwise if current_slot is + // before expiry, Some(value) is returned, otherwise return None. + fn compute_unit_limit(&self, current_slot: Option) -> Option; + fn compute_unit_price(&self, current_slot: Option) -> Option; + fn loaded_accounts_bytes(&self, current_slot: Option) -> Option; } /// Statically loaded meta is a supertrait of Dynamically loaded meta, when @@ -31,6 +47,16 @@ pub trait DynamicMeta: StaticMeta {} pub struct TransactionMeta { pub(crate) message_hash: Hash, pub(crate) is_simple_vote_tx: bool, + pub(crate) requested_limits: RequestedLimitsWithExpiry, +} + +/// Processing compute_budget_instructions with feature_set resolves RequestedLimits, +/// and the resolved values expire at the end of the current epoch, as feature_set +/// may change between epochs. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub(crate) struct RequestedLimitsWithExpiry { + pub(crate) expiry: Slot, + pub(crate) compute_budget_limits: ComputeBudgetLimits, } impl TransactionMeta { From 4661f4015b1b3781dd132b08d2cde84e9ad0d595 Mon Sep 17 00:00:00 2001 From: Tao Zhu Date: Mon, 11 Dec 2023 23:27:20 +0000 Subject: [PATCH 2/3] extract requested_limits when creating static RuntimeTransaction; add renew trait --- .../src/runtime_transaction.rs | 271 +++++++++++++----- runtime-transaction/src/transaction_meta.rs | 11 + 2 files changed, 207 insertions(+), 75 deletions(-) diff --git a/runtime-transaction/src/runtime_transaction.rs b/runtime-transaction/src/runtime_transaction.rs index 84b69c6da4be6b..e98d3b78d6c3cb 100644 --- a/runtime-transaction/src/runtime_transaction.rs +++ b/runtime-transaction/src/runtime_transaction.rs @@ -11,8 +11,11 @@ //! with its dynamic metadata loaded. use { crate::transaction_meta::{DynamicMeta, RequestedLimits, StaticMeta, TransactionMeta}, - solana_program_runtime::compute_budget_processor::ComputeBudgetLimits, + solana_program_runtime::compute_budget_processor::{ + process_compute_budget_instructions, ComputeBudgetLimits, + }, solana_sdk::{ + feature_set::FeatureSet, hash::Hash, message::{AddressLoader, SanitizedMessage, SanitizedVersionedMessage}, signature::Signature, @@ -82,6 +85,8 @@ impl RuntimeTransaction { sanitized_versioned_tx: SanitizedVersionedTransaction, message_hash: Option, is_simple_vote_tx: Option, + feature_set: &FeatureSet, + expiry: Slot, ) -> Result { let mut meta = TransactionMeta::default(); meta.set_is_simple_vote_tx( @@ -90,15 +95,37 @@ impl RuntimeTransaction { ); let (signatures, message) = sanitized_versioned_tx.destruct(); - meta.set_message_hash(message_hash.unwrap_or_else(|| message.message.hash())); + let compute_budget_limits: ComputeBudgetLimits = + process_compute_budget_instructions(message.program_instructions_iter(), feature_set)?; + meta.set_compute_budget_limits(compute_budget_limits, expiry); + Ok(Self { signatures, message, meta, }) } + + // RuntimeTransaction instance can be renewed into a new instance if its cached TransactionMeta + // was expired. + pub fn renew_from(self, feature_set: &FeatureSet, expiry: Slot) -> Result { + let compute_budget_limits: ComputeBudgetLimits = process_compute_budget_instructions( + self.message.program_instructions_iter(), + feature_set, + )?; + + let mut meta = TransactionMeta::default(); + let _ = std::mem::replace(&mut meta, self.meta); + meta.set_compute_budget_limits(compute_budget_limits, expiry); + + Ok(Self { + signatures: self.signatures, + message: self.message, + meta, + }) + } } impl RuntimeTransaction { @@ -128,13 +155,13 @@ impl RuntimeTransaction { mod tests { use { super::*, - crate::transaction_meta::RequestedLimitsWithExpiry, solana_program::{ system_instruction, vote::{self, state::Vote}, }, solana_sdk::{ compute_budget::ComputeBudgetInstruction, + instruction::Instruction, message::Message, signer::{keypair::Keypair, Signer}, transaction::{SimpleAddressLoader, Transaction, VersionedTransaction}, @@ -157,98 +184,109 @@ 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, + } + + 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, - is_simple_vote: Option, - ) -> TransactionMeta { - RuntimeTransaction::::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; - let requested_limits = RequestedLimitsWithExpiry::default(); - - assert_eq!( - TransactionMeta { - message_hash: hash, - is_simple_vote_tx: false, - requested_limits: requested_limits.clone(), - }, - get_transaction_meta( - non_vote_sanitized_versioned_transaction(compute_unit_price), - Some(hash), - None + fn test_runtime_transaction_is_vote_meta() { + fn get_is_simple_vote( + svt: SanitizedVersionedTransaction, + is_simple_vote: Option, + ) -> bool { + RuntimeTransaction::::try_from( + svt, + None, + is_simple_vote, + &FeatureSet::default(), + 0, ) - ); + .unwrap() + .meta + .is_simple_vote_tx + } - assert_eq!( - TransactionMeta { - message_hash: hash, - is_simple_vote_tx: true, - requested_limits: requested_limits.clone(), - }, - 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(), + None + )); - assert_eq!( - TransactionMeta { - message_hash: hash, - is_simple_vote_tx: true, - requested_limits: requested_limits.clone(), - }, - get_transaction_meta(vote_sanitized_versioned_transaction(), Some(hash), None) - ); + assert!(get_is_simple_vote( + non_vote_sanitized_versioned_transaction(), + Some(true), // override + )); - assert_eq!( - TransactionMeta { - message_hash: hash, - is_simple_vote_tx: false, - requested_limits, - }, - get_transaction_meta( - vote_sanitized_versioned_transaction(), - Some(hash), - Some(false), // override - ) - ); + assert!(get_is_simple_vote( + vote_sanitized_versioned_transaction(), + None + )); + + 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 expiry: Slot = 1; let statically_loaded_transaction = RuntimeTransaction::::try_from( - non_vote_sanitized_versioned_transaction(compute_unit_price), + non_vote_sanitized_versioned_transaction(), Some(hash), None, + &FeatureSet::default(), + expiry, ) .unwrap(); @@ -265,4 +303,87 @@ 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 feature_set = FeatureSet::all_enabled(); + let expiry = 100; + let mut test_transaction = TestTransaction::new(); + + let runtime_transaction_static = RuntimeTransaction::::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, + &feature_set, + expiry, + ) + .unwrap(); + + // asserts before metadata expiration + 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(Some(expiry)) + .unwrap() + ); + assert_eq!( + compute_unit_price, + runtime_transaction_static + .compute_unit_price(Some(expiry)) + .unwrap() + ); + assert_eq!( + loaded_accounts_bytes, + runtime_transaction_static + .loaded_accounts_bytes(Some(expiry)) + .unwrap() + ); + + // asserts after metadata expiration + let current_slot = expiry + 1; + assert!(runtime_transaction_static + .compute_unit_limit(Some(current_slot)) + .is_none()); + assert!(runtime_transaction_static + .compute_unit_price(Some(current_slot)) + .is_none()); + assert!(runtime_transaction_static + .loaded_accounts_bytes(Some(current_slot)) + .is_none()); + + // asserts after renewal + let renewed_runtime_transaction_static = runtime_transaction_static + .renew_from(&feature_set, current_slot) + .unwrap(); + assert_eq!(&hash, renewed_runtime_transaction_static.message_hash()); + assert!(!renewed_runtime_transaction_static.is_simple_vote_tx()); + assert_eq!( + compute_unit_limit, + renewed_runtime_transaction_static + .compute_unit_limit(Some(current_slot)) + .unwrap() + ); + assert_eq!( + compute_unit_price, + renewed_runtime_transaction_static + .compute_unit_price(Some(current_slot)) + .unwrap() + ); + assert_eq!( + loaded_accounts_bytes, + renewed_runtime_transaction_static + .loaded_accounts_bytes(Some(current_slot)) + .unwrap() + ); + } } diff --git a/runtime-transaction/src/transaction_meta.rs b/runtime-transaction/src/transaction_meta.rs index c01ba3817142bf..0731ce1c5be77e 100644 --- a/runtime-transaction/src/transaction_meta.rs +++ b/runtime-transaction/src/transaction_meta.rs @@ -67,4 +67,15 @@ 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_budget_limits( + &mut self, + compute_budget_limits: ComputeBudgetLimits, + expiry: Slot, + ) { + self.requested_limits = RequestedLimitsWithExpiry { + expiry, + compute_budget_limits, + }; + } } From 61cdcd3ce491311bd534b8b690d37c56154ada4a Mon Sep 17 00:00:00 2001 From: Tao Zhu Date: Fri, 15 Dec 2023 22:33:58 +0000 Subject: [PATCH 3/3] rebase to catch up on compue_budget_processor no longer needs feature_set; update requested limits as flat fields of static meta without expiry --- .../src/runtime_transaction.rs | 134 +++--------------- runtime-transaction/src/transaction_meta.rs | 55 +++---- 2 files changed, 41 insertions(+), 148 deletions(-) diff --git a/runtime-transaction/src/runtime_transaction.rs b/runtime-transaction/src/runtime_transaction.rs index e98d3b78d6c3cb..3ca7d4fb7920cd 100644 --- a/runtime-transaction/src/runtime_transaction.rs +++ b/runtime-transaction/src/runtime_transaction.rs @@ -10,17 +10,15 @@ //! ALT, RuntimeTransaction transits into Dynamically Loaded state, //! with its dynamic metadata loaded. use { - crate::transaction_meta::{DynamicMeta, RequestedLimits, StaticMeta, TransactionMeta}, + crate::transaction_meta::{DynamicMeta, StaticMeta, TransactionMeta}, solana_program_runtime::compute_budget_processor::{ process_compute_budget_instructions, ComputeBudgetLimits, }, solana_sdk::{ - feature_set::FeatureSet, hash::Hash, message::{AddressLoader, SanitizedMessage, SanitizedVersionedMessage}, signature::Signature, simple_vote_transaction_checker::is_simple_vote_transaction, - slot_history::Slot, transaction::{Result, SanitizedVersionedTransaction}, }, }; @@ -46,17 +44,6 @@ impl StaticMetaAccess for SanitizedVersionedMessage {} impl StaticMetaAccess for SanitizedMessage {} impl DynamicMetaAccess for SanitizedMessage {} -impl RequestedLimits for RuntimeTransaction { - fn requested_limits(&self, current_slot: Option) -> Option<&ComputeBudgetLimits> { - if let Some(current_slot) = current_slot { - (current_slot <= self.meta.requested_limits.expiry) - .then_some(&self.meta.requested_limits.compute_budget_limits) - } else { - Some(&self.meta.requested_limits.compute_budget_limits) - } - } -} - impl StaticMeta for RuntimeTransaction { fn message_hash(&self) -> &Hash { &self.meta.message_hash @@ -64,17 +51,14 @@ impl StaticMeta for RuntimeTransaction { fn is_simple_vote_tx(&self) -> bool { self.meta.is_simple_vote_tx } - fn compute_unit_limit(&self, current_slot: Option) -> Option { - self.requested_limits(current_slot) - .map(|requested_limits| requested_limits.compute_unit_limit) + fn compute_unit_limit(&self) -> u32 { + self.meta.compute_unit_limit } - fn compute_unit_price(&self, current_slot: Option) -> Option { - self.requested_limits(current_slot) - .map(|requested_limits| requested_limits.compute_unit_price) + fn compute_unit_price(&self) -> u64 { + self.meta.compute_unit_price } - fn loaded_accounts_bytes(&self, current_slot: Option) -> Option { - self.requested_limits(current_slot) - .map(|requested_limits| requested_limits.loaded_accounts_bytes) + fn loaded_accounts_bytes(&self) -> u32 { + self.meta.loaded_accounts_bytes } } @@ -85,8 +69,6 @@ impl RuntimeTransaction { sanitized_versioned_tx: SanitizedVersionedTransaction, message_hash: Option, is_simple_vote_tx: Option, - feature_set: &FeatureSet, - expiry: Slot, ) -> Result { let mut meta = TransactionMeta::default(); meta.set_is_simple_vote_tx( @@ -97,9 +79,15 @@ impl RuntimeTransaction { let (signatures, message) = sanitized_versioned_tx.destruct(); meta.set_message_hash(message_hash.unwrap_or_else(|| message.message.hash())); - let compute_budget_limits: ComputeBudgetLimits = - process_compute_budget_instructions(message.program_instructions_iter(), feature_set)?; - meta.set_compute_budget_limits(compute_budget_limits, expiry); + 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, @@ -107,25 +95,6 @@ impl RuntimeTransaction { meta, }) } - - // RuntimeTransaction instance can be renewed into a new instance if its cached TransactionMeta - // was expired. - pub fn renew_from(self, feature_set: &FeatureSet, expiry: Slot) -> Result { - let compute_budget_limits: ComputeBudgetLimits = process_compute_budget_instructions( - self.message.program_instructions_iter(), - feature_set, - )?; - - let mut meta = TransactionMeta::default(); - let _ = std::mem::replace(&mut meta, self.meta); - meta.set_compute_budget_limits(compute_budget_limits, expiry); - - Ok(Self { - signatures: self.signatures, - message: self.message, - meta, - }) - } } impl RuntimeTransaction { @@ -242,16 +211,10 @@ mod tests { svt: SanitizedVersionedTransaction, is_simple_vote: Option, ) -> bool { - RuntimeTransaction::::try_from( - svt, - None, - is_simple_vote, - &FeatureSet::default(), - 0, - ) - .unwrap() - .meta - .is_simple_vote_tx + RuntimeTransaction::::try_from(svt, None, is_simple_vote) + .unwrap() + .meta + .is_simple_vote_tx } assert!(!get_is_simple_vote( @@ -278,15 +241,12 @@ mod tests { #[test] fn test_advancing_transaction_type() { let hash = Hash::new_unique(); - let expiry: Slot = 1; let statically_loaded_transaction = RuntimeTransaction::::try_from( non_vote_sanitized_versioned_transaction(), Some(hash), None, - &FeatureSet::default(), - expiry, ) .unwrap(); @@ -310,8 +270,6 @@ mod tests { let compute_unit_limit = 250_000; let compute_unit_price = 1_000; let loaded_accounts_bytes = 1_024; - let feature_set = FeatureSet::all_enabled(); - let expiry = 100; let mut test_transaction = TestTransaction::new(); let runtime_transaction_static = RuntimeTransaction::::try_from( @@ -322,68 +280,22 @@ mod tests { .to_sanitized_versioned_transaction(), Some(hash), None, - &feature_set, - expiry, ) .unwrap(); - // asserts before metadata expiration 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(Some(expiry)) - .unwrap() - ); - assert_eq!( - compute_unit_price, - runtime_transaction_static - .compute_unit_price(Some(expiry)) - .unwrap() - ); - assert_eq!( - loaded_accounts_bytes, - runtime_transaction_static - .loaded_accounts_bytes(Some(expiry)) - .unwrap() - ); - - // asserts after metadata expiration - let current_slot = expiry + 1; - assert!(runtime_transaction_static - .compute_unit_limit(Some(current_slot)) - .is_none()); - assert!(runtime_transaction_static - .compute_unit_price(Some(current_slot)) - .is_none()); - assert!(runtime_transaction_static - .loaded_accounts_bytes(Some(current_slot)) - .is_none()); - - // asserts after renewal - let renewed_runtime_transaction_static = runtime_transaction_static - .renew_from(&feature_set, current_slot) - .unwrap(); - assert_eq!(&hash, renewed_runtime_transaction_static.message_hash()); - assert!(!renewed_runtime_transaction_static.is_simple_vote_tx()); - assert_eq!( - compute_unit_limit, - renewed_runtime_transaction_static - .compute_unit_limit(Some(current_slot)) - .unwrap() + runtime_transaction_static.compute_unit_limit() ); assert_eq!( compute_unit_price, - renewed_runtime_transaction_static - .compute_unit_price(Some(current_slot)) - .unwrap() + runtime_transaction_static.compute_unit_price() ); assert_eq!( loaded_accounts_bytes, - renewed_runtime_transaction_static - .loaded_accounts_bytes(Some(current_slot)) - .unwrap() + runtime_transaction_static.loaded_accounts_bytes() ); } } diff --git a/runtime-transaction/src/transaction_meta.rs b/runtime-transaction/src/transaction_meta.rs index 0731ce1c5be77e..f46fa39c3ab71b 100644 --- a/runtime-transaction/src/transaction_meta.rs +++ b/runtime-transaction/src/transaction_meta.rs @@ -11,29 +11,16 @@ //! The StaticMeta and DynamicMeta traits are accessor traits on the //! RuntimeTransaction types, not the TransactionMeta itself. //! -use { - solana_program_runtime::compute_budget_processor::ComputeBudgetLimits, - solana_sdk::{hash::Hash, slot_history::Slot}, -}; - -/// private trait to avoid exposing `ComputeBudgetLimits` to callsite of RuntimeTransaction. -pub(crate) trait RequestedLimits { - fn requested_limits(&self, current_slot: Option) -> Option<&ComputeBudgetLimits>; -} +use solana_sdk::hash::Hash; /// metadata can be extracted statically from sanitized transaction, /// for example: message hash, simple-vote-tx flag, limits set by instructions -#[allow(private_bounds)] -pub trait StaticMeta: RequestedLimits { +pub trait StaticMeta { fn message_hash(&self) -> &Hash; fn is_simple_vote_tx(&self) -> bool; - - // get fields' value from RequestedLimitsWithExpiry, - // `current_slot`, sets to None to skip expiry check, otherwise if current_slot is - // before expiry, Some(value) is returned, otherwise return None. - fn compute_unit_limit(&self, current_slot: Option) -> Option; - fn compute_unit_price(&self, current_slot: Option) -> Option; - fn loaded_accounts_bytes(&self, current_slot: Option) -> Option; + 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 @@ -47,16 +34,9 @@ pub trait DynamicMeta: StaticMeta {} pub struct TransactionMeta { pub(crate) message_hash: Hash, pub(crate) is_simple_vote_tx: bool, - pub(crate) requested_limits: RequestedLimitsWithExpiry, -} - -/// Processing compute_budget_instructions with feature_set resolves RequestedLimits, -/// and the resolved values expire at the end of the current epoch, as feature_set -/// may change between epochs. -#[derive(Clone, Debug, Default, PartialEq, Eq)] -pub(crate) struct RequestedLimitsWithExpiry { - pub(crate) expiry: Slot, - pub(crate) compute_budget_limits: ComputeBudgetLimits, + pub(crate) compute_unit_limit: u32, + pub(crate) compute_unit_price: u64, + pub(crate) loaded_accounts_bytes: u32, } impl TransactionMeta { @@ -68,14 +48,15 @@ impl TransactionMeta { self.is_simple_vote_tx = is_simple_vote_tx; } - pub(crate) fn set_compute_budget_limits( - &mut self, - compute_budget_limits: ComputeBudgetLimits, - expiry: Slot, - ) { - self.requested_limits = RequestedLimitsWithExpiry { - expiry, - compute_budget_limits, - }; + 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; } }