Skip to main content

solana_runtime_transaction/
runtime_transaction.rs

1//! RuntimeTransaction is `runtime` facing representation of transaction, while
2//! solana_transaction::sanitized::SanitizedTransaction is client facing representation.
3//!
4//! It has two states:
5//! 1. Statically Loaded: after receiving `packet` from sigverify and deserializing
6//!    it into `solana_transaction::versioned::VersionedTransaction`, then sanitizing into
7//!    `solana_transaction::versioned::sanitized::SanitizedVersionedTransaction`, which can be wrapped into
8//!    `RuntimeTransaction` with static transaction metadata extracted.
9//! 2. Dynamically Loaded: after successfully loaded account addresses from onchain
10//!    ALT, RuntimeTransaction<SanitizedMessage> transits into Dynamically Loaded state,
11//!    with its dynamic metadata loaded.
12use {
13    crate::transaction_meta::{CachedTransactionMeta, TransactionConfiguration, TransactionMeta},
14    agave_feature_set::FeatureSet,
15    core::ops::Deref,
16    solana_compute_budget_instruction::compute_budget_instruction_details::*,
17    solana_hash::Hash,
18    solana_message::{AccountKeys, TransactionSignatureDetails},
19    solana_pubkey::Pubkey,
20    solana_signature::Signature,
21    solana_svm_transaction::{
22        instruction::SVMInstruction,
23        message_address_table_lookup::SVMMessageAddressTableLookup,
24        svm_message::{SVMMessage, SVMStaticMessage},
25        svm_transaction::SVMStaticTransaction,
26    },
27    solana_transaction::{TransactionError, versioned::TransactionVersion},
28};
29
30mod sdk_transactions;
31mod transaction_view;
32
33#[cfg_attr(feature = "dev-context-only-utils", derive(Clone))]
34#[derive(Debug)]
35pub struct RuntimeTransaction<T> {
36    transaction: T,
37    // transaction meta is a collection of fields, it is updated
38    // during message state transition
39    meta: CachedTransactionMeta,
40}
41
42impl<T> RuntimeTransaction<T> {
43    pub fn into_inner_transaction(self) -> T {
44        self.transaction
45    }
46}
47
48impl<T> TransactionMeta for RuntimeTransaction<T> {
49    fn message_hash(&self) -> &Hash {
50        &self.meta.message_hash
51    }
52    fn is_simple_vote_transaction(&self) -> bool {
53        self.meta.is_simple_vote_transaction
54    }
55    fn signature_details(&self) -> &TransactionSignatureDetails {
56        &self.meta.signature_details
57    }
58    fn transaction_configuration(
59        &self,
60        feature_set: &FeatureSet,
61    ) -> Result<TransactionConfiguration, TransactionError> {
62        self.meta
63            .versioned_transaction_config
64            .try_into_config(feature_set)
65    }
66    fn instruction_data_len(&self) -> u16 {
67        self.meta.instruction_data_len
68    }
69}
70
71impl<T> Deref for RuntimeTransaction<T> {
72    type Target = T;
73
74    fn deref(&self) -> &Self::Target {
75        &self.transaction
76    }
77}
78impl<T: SVMStaticMessage> SVMStaticMessage for RuntimeTransaction<T> {
79    fn version(&self) -> TransactionVersion {
80        self.transaction.version()
81    }
82
83    fn num_transaction_signatures(&self) -> u64 {
84        self.transaction.num_transaction_signatures()
85    }
86    // override to access from the cached meta instead of re-calculating
87    fn num_ed25519_signatures(&self) -> u64 {
88        self.meta
89            .signature_details
90            .num_ed25519_instruction_signatures()
91    }
92    // override to access from the cached meta instead of re-calculating
93    fn num_secp256k1_signatures(&self) -> u64 {
94        self.meta
95            .signature_details
96            .num_secp256k1_instruction_signatures()
97    }
98    // override to access form the cached meta instead of re-calculating
99    fn num_secp256r1_signatures(&self) -> u64 {
100        self.meta
101            .signature_details
102            .num_secp256r1_instruction_signatures()
103    }
104
105    fn num_write_locks(&self) -> u64 {
106        self.transaction.num_write_locks()
107    }
108
109    fn num_readonly_signed_static_accounts(&self) -> u8 {
110        self.transaction.num_readonly_signed_static_accounts()
111    }
112
113    fn num_readonly_unsigned_static_accounts(&self) -> u8 {
114        self.transaction.num_readonly_unsigned_static_accounts()
115    }
116
117    fn recent_blockhash(&self) -> &Hash {
118        self.transaction.recent_blockhash()
119    }
120
121    fn num_instructions(&self) -> usize {
122        self.transaction.num_instructions()
123    }
124
125    fn instructions_iter(&self) -> impl Iterator<Item = SVMInstruction<'_>> {
126        self.transaction.instructions_iter()
127    }
128
129    fn program_instructions_iter(
130        &self,
131    ) -> impl Iterator<Item = (&Pubkey, SVMInstruction<'_>)> + Clone {
132        self.transaction.program_instructions_iter()
133    }
134
135    fn static_account_keys(&self) -> &[Pubkey] {
136        self.transaction.static_account_keys()
137    }
138
139    fn fee_payer(&self) -> &Pubkey {
140        self.transaction.fee_payer()
141    }
142
143    fn num_lookup_tables(&self) -> usize {
144        self.transaction.num_lookup_tables()
145    }
146
147    fn message_address_table_lookups(
148        &self,
149    ) -> impl Iterator<Item = SVMMessageAddressTableLookup<'_>> {
150        self.transaction.message_address_table_lookups()
151    }
152
153    fn is_signer(&self, index: usize) -> bool {
154        self.transaction.is_signer(index)
155    }
156
157    fn is_invoked(&self, key_index: usize) -> bool {
158        self.transaction.is_invoked(key_index)
159    }
160}
161
162impl<T: SVMMessage> SVMMessage for RuntimeTransaction<T> {
163    fn account_keys(&self) -> AccountKeys<'_> {
164        self.transaction.account_keys()
165    }
166
167    fn is_writable(&self, index: usize) -> bool {
168        self.transaction.is_writable(index)
169    }
170}
171
172impl<T: SVMStaticTransaction> SVMStaticTransaction for RuntimeTransaction<T> {
173    fn signature(&self) -> &Signature {
174        self.transaction.signature()
175    }
176
177    fn signatures(&self) -> &[Signature] {
178        self.transaction.signatures()
179    }
180}