瀏覽代碼

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
Tao Zhu 1 年之前
父節點
當前提交
310c7a4f9d
共有 2 個文件被更改,包括 151 次插入69 次删除
  1. 132 68
      runtime-transaction/src/runtime_transaction.rs
  2. 19 1
      runtime-transaction/src/transaction_meta.rs

+ 132 - 68
runtime-transaction/src/runtime_transaction.rs

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

+ 19 - 1
runtime-transaction/src/transaction_meta.rs

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