solana_program/
program.rs1use crate::{
14 account_info::AccountInfo, entrypoint::ProgramResult, instruction::Instruction, pubkey::Pubkey,
15 stable_layout::stable_instruction::StableInstruction,
16};
17pub use solana_cpi::MAX_RETURN_DATA;
18
19pub fn invoke(instruction: &Instruction, account_infos: &[AccountInfo]) -> ProgramResult {
24 invoke_signed(instruction, account_infos, &[])
25}
26
27pub fn invoke_unchecked(instruction: &Instruction, account_infos: &[AccountInfo]) -> ProgramResult {
41 invoke_signed_unchecked(instruction, account_infos, &[])
42}
43
44pub fn invoke_signed(
49 instruction: &Instruction,
50 account_infos: &[AccountInfo],
51 signers_seeds: &[&[&[u8]]],
52) -> ProgramResult {
53 for account_meta in instruction.accounts.iter() {
55 for account_info in account_infos.iter() {
56 if account_meta.pubkey == *account_info.key {
57 if account_meta.is_writable {
58 let _ = account_info.try_borrow_mut_lamports()?;
59 let _ = account_info.try_borrow_mut_data()?;
60 } else {
61 let _ = account_info.try_borrow_lamports()?;
62 let _ = account_info.try_borrow_data()?;
63 }
64 break;
65 }
66 }
67 }
68
69 invoke_signed_unchecked(instruction, account_infos, signers_seeds)
70}
71
72pub fn invoke_signed_unchecked(
86 instruction: &Instruction,
87 account_infos: &[AccountInfo],
88 signers_seeds: &[&[&[u8]]],
89) -> ProgramResult {
90 #[cfg(target_os = "solana")]
91 {
92 solana_cpi::invoke_signed_unchecked(instruction, account_infos, signers_seeds)
93 }
94
95 #[cfg(not(target_os = "solana"))]
96 crate::program_stubs::sol_invoke_signed(instruction, account_infos, signers_seeds)
97}
98
99pub fn set_return_data(data: &[u8]) {
104 #[cfg(target_os = "solana")]
105 {
106 solana_cpi::set_return_data(data);
107 }
108
109 #[cfg(not(target_os = "solana"))]
110 crate::program_stubs::sol_set_return_data(data)
111}
112
113pub fn get_return_data() -> Option<(Pubkey, Vec<u8>)> {
118 #[cfg(target_os = "solana")]
119 {
120 solana_cpi::get_return_data()
121 }
122
123 #[cfg(not(target_os = "solana"))]
124 crate::program_stubs::sol_get_return_data()
125}
126
127#[doc(hidden)]
129#[allow(clippy::arithmetic_side_effects)]
130pub fn check_type_assumptions() {
131 use {
132 crate::instruction::AccountMeta,
133 core::mem::offset_of,
134 std::{
135 mem::{align_of, size_of},
136 str::FromStr,
137 },
138 };
139
140 assert_eq!(size_of::<u64>(), size_of::<usize>());
142 assert_eq!(1, align_of::<u8>());
144
145 {
147 assert_eq!(size_of::<AccountMeta>(), 32 + 1 + 1);
148
149 let pubkey1 = Pubkey::from_str("J9PYCcoKusHyKRMXnBL17VTXC3MVETyqBG2KyLXVv6Ai").unwrap();
150 let pubkey2 = Pubkey::from_str("Hvy4GHgPToZNoENTKjC4mJqpzWWjgTwXrFufKfxYiKkV").unwrap();
151 let pubkey3 = Pubkey::from_str("JDMyRL8rCkae7maCSv47upNuBMFd3Mgos1fz2AvYzVzY").unwrap();
152 let account_meta1 = AccountMeta {
153 pubkey: pubkey2,
154 is_signer: true,
155 is_writable: false,
156 };
157 let account_meta2 = AccountMeta {
158 pubkey: pubkey3,
159 is_signer: false,
160 is_writable: true,
161 };
162 let data = vec![1, 2, 3, 4, 5];
163 let instruction = Instruction {
164 program_id: pubkey1,
165 accounts: vec![account_meta1.clone(), account_meta2.clone()],
166 data: data.clone(),
167 };
168 let instruction = StableInstruction::from(instruction);
169 let instruction_addr = &instruction as *const _ as u64;
170
171 assert_eq!(offset_of!(StableInstruction, program_id), 48);
173 let pubkey_ptr = (instruction_addr + 48) as *const Pubkey;
174 unsafe {
175 assert_eq!(*pubkey_ptr, pubkey1);
176 }
177
178 assert_eq!(offset_of!(StableInstruction, accounts), 0);
180 let accounts_ptr = (instruction_addr) as *const *const AccountMeta;
181 let accounts_cap = (instruction_addr + 8) as *const usize;
182 let accounts_len = (instruction_addr + 16) as *const usize;
183 unsafe {
184 assert_eq!(*accounts_cap, 2);
185 assert_eq!(*accounts_len, 2);
186 let account_meta_ptr = *accounts_ptr;
187 assert_eq!(*account_meta_ptr, account_meta1);
188 assert_eq!(*(account_meta_ptr.offset(1)), account_meta2);
189 }
190
191 assert_eq!(offset_of!(StableInstruction, data), 24);
193 let data_ptr = (instruction_addr + 24) as *const *const [u8; 5];
194 let data_cap = (instruction_addr + 24 + 8) as *const usize;
195 let data_len = (instruction_addr + 24 + 16) as *const usize;
196 unsafe {
197 assert_eq!(*data_cap, 5);
198
199 assert_eq!(*data_len, 5);
200 let u8_ptr = *data_ptr;
201 assert_eq!(*u8_ptr, data[..]);
202 }
203 }
204
205 solana_account_info::check_type_assumptions();
206}
207
208#[cfg(test)]
209mod tests {
210 #[test]
211 fn test_check_type_assumptions() {
212 super::check_type_assumptions()
213 }
214}