solana_svm_transaction/
svm_message.rs1use {
2 crate::{
3 instruction::SVMInstruction, message_address_table_lookup::SVMMessageAddressTableLookup,
4 },
5 core::fmt::Debug,
6 solana_sdk::{
7 hash::Hash, message::AccountKeys, nonce::NONCED_TX_MARKER_IX_INDEX, pubkey::Pubkey,
8 system_program,
9 },
10};
11
12mod sanitized_message;
13mod sanitized_transaction;
14
15pub trait SVMMessage: Debug {
17 fn num_total_signatures(&self) -> u64;
21
22 fn num_write_locks(&self) -> u64;
25
26 fn recent_blockhash(&self) -> &Hash;
28
29 fn num_instructions(&self) -> usize;
31
32 fn instructions_iter(&self) -> impl Iterator<Item = SVMInstruction>;
34
35 fn program_instructions_iter(&self) -> impl Iterator<Item = (&Pubkey, SVMInstruction)> + Clone;
38
39 fn account_keys(&self) -> AccountKeys;
41
42 fn fee_payer(&self) -> &Pubkey;
44
45 fn is_writable(&self, index: usize) -> bool;
47
48 fn is_signer(&self, index: usize) -> bool;
50
51 fn is_invoked(&self, key_index: usize) -> bool;
54
55 fn is_instruction_account(&self, key_index: usize) -> bool {
58 if let Ok(key_index) = u8::try_from(key_index) {
59 self.instructions_iter()
60 .any(|ix| ix.accounts.contains(&key_index))
61 } else {
62 false
63 }
64 }
65
66 fn get_durable_nonce(&self) -> Option<&Pubkey> {
68 let account_keys = self.account_keys();
69 self.instructions_iter()
70 .nth(usize::from(NONCED_TX_MARKER_IX_INDEX))
71 .filter(
72 |ix| match account_keys.get(usize::from(ix.program_id_index)) {
73 Some(program_id) => system_program::check_id(program_id),
74 _ => false,
75 },
76 )
77 .filter(|ix| {
78 const SERIALIZED_ADVANCE_NONCE_ACCOUNT: [u8; 4] = 4u32.to_le_bytes();
80 const SERIALIZED_SIZE: usize = SERIALIZED_ADVANCE_NONCE_ACCOUNT.len();
81
82 ix.data
83 .get(..SERIALIZED_SIZE)
84 .map(|data| data == SERIALIZED_ADVANCE_NONCE_ACCOUNT)
85 .unwrap_or(false)
86 })
87 .and_then(|ix| {
88 ix.accounts.first().and_then(|idx| {
89 let index = usize::from(*idx);
90 if !self.is_writable(index) {
91 None
92 } else {
93 account_keys.get(index)
94 }
95 })
96 })
97 }
98
99 fn get_ix_signers(&self, index: usize) -> impl Iterator<Item = &Pubkey> {
102 self.instructions_iter()
103 .nth(index)
104 .into_iter()
105 .flat_map(|ix| {
106 ix.accounts
107 .iter()
108 .copied()
109 .map(usize::from)
110 .filter(|index| self.is_signer(*index))
111 .filter_map(|signer_index| self.account_keys().get(signer_index))
112 })
113 }
114
115 fn num_lookup_tables(&self) -> usize;
117
118 fn message_address_table_lookups(&self) -> impl Iterator<Item = SVMMessageAddressTableLookup>;
120}