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::{DynamicMeta, StaticMeta, TransactionMeta},
14    core::ops::Deref,
15    solana_compute_budget_instruction::compute_budget_instruction_details::*,
16    solana_hash::Hash,
17    solana_message::{AccountKeys, TransactionSignatureDetails},
18    solana_pubkey::Pubkey,
19    solana_signature::Signature,
20    solana_svm_transaction::{
21        instruction::SVMInstruction, message_address_table_lookup::SVMMessageAddressTableLookup,
22        svm_message::SVMMessage, svm_transaction::SVMTransaction,
23    },
24};
25
26mod sdk_transactions;
27mod transaction_view;
28
29#[cfg_attr(feature = "dev-context-only-utils", derive(Clone))]
30#[derive(Debug)]
31pub struct RuntimeTransaction<T> {
32    transaction: T,
33    // transaction meta is a collection of fields, it is updated
34    // during message state transition
35    meta: TransactionMeta,
36}
37
38impl<T> RuntimeTransaction<T> {
39    pub fn into_inner_transaction(self) -> T {
40        self.transaction
41    }
42}
43
44impl<T> StaticMeta for RuntimeTransaction<T> {
45    fn message_hash(&self) -> &Hash {
46        &self.meta.message_hash
47    }
48    fn is_simple_vote_transaction(&self) -> bool {
49        self.meta.is_simple_vote_transaction
50    }
51    fn signature_details(&self) -> &TransactionSignatureDetails {
52        &self.meta.signature_details
53    }
54    fn compute_budget_instruction_details(&self) -> &ComputeBudgetInstructionDetails {
55        &self.meta.compute_budget_instruction_details
56    }
57    fn instruction_data_len(&self) -> u16 {
58        self.meta.instruction_data_len
59    }
60}
61
62impl<T: SVMMessage> DynamicMeta for RuntimeTransaction<T> {}
63
64impl<T> Deref for RuntimeTransaction<T> {
65    type Target = T;
66
67    fn deref(&self) -> &Self::Target {
68        &self.transaction
69    }
70}
71
72impl<T: SVMMessage> SVMMessage for RuntimeTransaction<T> {
73    fn num_transaction_signatures(&self) -> u64 {
74        self.transaction.num_transaction_signatures()
75    }
76    // override to access from the cached meta instead of re-calculating
77    fn num_ed25519_signatures(&self) -> u64 {
78        self.meta
79            .signature_details
80            .num_ed25519_instruction_signatures()
81    }
82    // override to access from the cached meta instead of re-calculating
83    fn num_secp256k1_signatures(&self) -> u64 {
84        self.meta
85            .signature_details
86            .num_secp256k1_instruction_signatures()
87    }
88    // override to access form the cached meta instead of re-calculating
89    fn num_secp256r1_signatures(&self) -> u64 {
90        self.meta
91            .signature_details
92            .num_secp256r1_instruction_signatures()
93    }
94
95    fn num_write_locks(&self) -> u64 {
96        self.transaction.num_write_locks()
97    }
98
99    fn recent_blockhash(&self) -> &Hash {
100        self.transaction.recent_blockhash()
101    }
102
103    fn num_instructions(&self) -> usize {
104        self.transaction.num_instructions()
105    }
106
107    fn instructions_iter(&self) -> impl Iterator<Item = SVMInstruction> {
108        self.transaction.instructions_iter()
109    }
110
111    fn program_instructions_iter(&self) -> impl Iterator<Item = (&Pubkey, SVMInstruction)> + Clone {
112        self.transaction.program_instructions_iter()
113    }
114
115    fn static_account_keys(&self) -> &[Pubkey] {
116        self.transaction.static_account_keys()
117    }
118
119    fn account_keys(&self) -> AccountKeys {
120        self.transaction.account_keys()
121    }
122
123    fn fee_payer(&self) -> &Pubkey {
124        self.transaction.fee_payer()
125    }
126
127    fn is_writable(&self, index: usize) -> bool {
128        self.transaction.is_writable(index)
129    }
130
131    fn is_signer(&self, index: usize) -> bool {
132        self.transaction.is_signer(index)
133    }
134
135    fn is_invoked(&self, key_index: usize) -> bool {
136        self.transaction.is_invoked(key_index)
137    }
138
139    fn num_lookup_tables(&self) -> usize {
140        self.transaction.num_lookup_tables()
141    }
142
143    fn message_address_table_lookups(&self) -> impl Iterator<Item = SVMMessageAddressTableLookup> {
144        self.transaction.message_address_table_lookups()
145    }
146}
147
148impl<T: SVMTransaction> SVMTransaction for RuntimeTransaction<T> {
149    fn signature(&self) -> &Signature {
150        self.transaction.signature()
151    }
152
153    fn signatures(&self) -> &[Signature] {
154        self.transaction.signatures()
155    }
156}