1pub use solana_cpi::MAX_RETURN_DATA;
14use {
15 crate::{
16 account_info::AccountInfo, entrypoint::ProgramResult, instruction::Instruction,
17 pubkey::Pubkey, stable_layout::stable_instruction::StableInstruction,
18 },
19 solana_clock::Epoch,
20};
21
22pub fn invoke(instruction: &Instruction, account_infos: &[AccountInfo]) -> ProgramResult {
27 invoke_signed(instruction, account_infos, &[])
28}
29
30pub fn invoke_unchecked(instruction: &Instruction, account_infos: &[AccountInfo]) -> ProgramResult {
44 invoke_signed_unchecked(instruction, account_infos, &[])
45}
46
47pub fn invoke_signed(
52 instruction: &Instruction,
53 account_infos: &[AccountInfo],
54 signers_seeds: &[&[&[u8]]],
55) -> ProgramResult {
56 for account_meta in instruction.accounts.iter() {
58 for account_info in account_infos.iter() {
59 if account_meta.pubkey == *account_info.key {
60 if account_meta.is_writable {
61 let _ = account_info.try_borrow_mut_lamports()?;
62 let _ = account_info.try_borrow_mut_data()?;
63 } else {
64 let _ = account_info.try_borrow_lamports()?;
65 let _ = account_info.try_borrow_data()?;
66 }
67 break;
68 }
69 }
70 }
71
72 invoke_signed_unchecked(instruction, account_infos, signers_seeds)
73}
74
75pub fn invoke_signed_unchecked(
89 instruction: &Instruction,
90 account_infos: &[AccountInfo],
91 signers_seeds: &[&[&[u8]]],
92) -> ProgramResult {
93 #[cfg(target_os = "solana")]
94 {
95 solana_cpi::invoke_signed_unchecked(instruction, account_infos, signers_seeds)
96 }
97
98 #[cfg(not(target_os = "solana"))]
99 crate::program_stubs::sol_invoke_signed(instruction, account_infos, signers_seeds)
100}
101
102pub fn set_return_data(data: &[u8]) {
107 #[cfg(target_os = "solana")]
108 {
109 solana_cpi::set_return_data(data);
110 }
111
112 #[cfg(not(target_os = "solana"))]
113 crate::program_stubs::sol_set_return_data(data)
114}
115
116pub fn get_return_data() -> Option<(Pubkey, Vec<u8>)> {
121 #[cfg(target_os = "solana")]
122 {
123 solana_cpi::get_return_data()
124 }
125
126 #[cfg(not(target_os = "solana"))]
127 crate::program_stubs::sol_get_return_data()
128}
129
130#[doc(hidden)]
132#[allow(clippy::arithmetic_side_effects)]
133pub fn check_type_assumptions() {
134 extern crate memoffset;
135 use {
136 crate::instruction::AccountMeta,
137 memoffset::offset_of,
138 std::{
139 cell::RefCell,
140 mem::{align_of, size_of},
141 rc::Rc,
142 str::FromStr,
143 },
144 };
145
146 assert_eq!(size_of::<u64>(), size_of::<usize>());
148 assert_eq!(1, align_of::<u8>());
150
151 {
153 assert_eq!(size_of::<AccountMeta>(), 32 + 1 + 1);
154
155 let pubkey1 = Pubkey::from_str("J9PYCcoKusHyKRMXnBL17VTXC3MVETyqBG2KyLXVv6Ai").unwrap();
156 let pubkey2 = Pubkey::from_str("Hvy4GHgPToZNoENTKjC4mJqpzWWjgTwXrFufKfxYiKkV").unwrap();
157 let pubkey3 = Pubkey::from_str("JDMyRL8rCkae7maCSv47upNuBMFd3Mgos1fz2AvYzVzY").unwrap();
158 let account_meta1 = AccountMeta {
159 pubkey: pubkey2,
160 is_signer: true,
161 is_writable: false,
162 };
163 let account_meta2 = AccountMeta {
164 pubkey: pubkey3,
165 is_signer: false,
166 is_writable: true,
167 };
168 let data = vec![1, 2, 3, 4, 5];
169 let instruction = Instruction {
170 program_id: pubkey1,
171 accounts: vec![account_meta1.clone(), account_meta2.clone()],
172 data: data.clone(),
173 };
174 let instruction = StableInstruction::from(instruction);
175 let instruction_addr = &instruction as *const _ as u64;
176
177 assert_eq!(offset_of!(StableInstruction, program_id), 48);
179 let pubkey_ptr = (instruction_addr + 48) as *const Pubkey;
180 unsafe {
181 assert_eq!(*pubkey_ptr, pubkey1);
182 }
183
184 assert_eq!(offset_of!(StableInstruction, accounts), 0);
186 let accounts_ptr = (instruction_addr) as *const *const AccountMeta;
187 let accounts_cap = (instruction_addr + 8) as *const usize;
188 let accounts_len = (instruction_addr + 16) as *const usize;
189 unsafe {
190 assert_eq!(*accounts_cap, 2);
191 assert_eq!(*accounts_len, 2);
192 let account_meta_ptr = *accounts_ptr;
193 assert_eq!(*account_meta_ptr, account_meta1);
194 assert_eq!(*(account_meta_ptr.offset(1)), account_meta2);
195 }
196
197 assert_eq!(offset_of!(StableInstruction, data), 24);
199 let data_ptr = (instruction_addr + 24) as *const *const [u8; 5];
200 let data_cap = (instruction_addr + 24 + 8) as *const usize;
201 let data_len = (instruction_addr + 24 + 16) as *const usize;
202 unsafe {
203 assert_eq!(*data_cap, 5);
204
205 assert_eq!(*data_len, 5);
206 let u8_ptr = *data_ptr;
207 assert_eq!(*u8_ptr, data[..]);
208 }
209 }
210
211 {
213 let key = Pubkey::from_str("6o8R9NsUxNskF1MfWM1f265y4w86JYbEwqCmTacdLkHp").unwrap();
214 let mut lamports = 31;
215 let mut data = vec![1, 2, 3, 4, 5];
216 let owner = Pubkey::from_str("2tjK4XyNU54XdN9jokx46QzLybbLVGwQQvTfhcuBXAjR").unwrap();
217 let account_info = AccountInfo {
218 key: &key,
219 is_signer: true,
220 is_writable: false,
221 lamports: Rc::new(RefCell::new(&mut lamports)),
222 data: Rc::new(RefCell::new(&mut data)),
223 owner: &owner,
224 executable: true,
225 rent_epoch: 42,
226 };
227 let account_info_addr = &account_info as *const _ as u64;
228
229 assert_eq!(offset_of!(AccountInfo, key), 0);
231 let key_ptr = (account_info_addr) as *const &Pubkey;
232 unsafe {
233 assert_eq!(**key_ptr, key);
234 }
235
236 assert_eq!(offset_of!(AccountInfo, lamports), 8);
238 let lamports_ptr = (account_info_addr + 8) as *const Rc<RefCell<&mut u64>>;
239 unsafe {
240 assert_eq!(**(*lamports_ptr).as_ptr(), 31);
241 }
242
243 assert_eq!(offset_of!(AccountInfo, data), 16);
245 let data_ptr = (account_info_addr + 16) as *const Rc<RefCell<&mut [u8]>>;
246 unsafe {
247 assert_eq!((*(*data_ptr).as_ptr())[..], data[..]);
248 }
249
250 assert_eq!(offset_of!(AccountInfo, owner), 24);
252 let owner_ptr = (account_info_addr + 24) as *const &Pubkey;
253 unsafe {
254 assert_eq!(**owner_ptr, owner);
255 }
256
257 assert_eq!(offset_of!(AccountInfo, rent_epoch), 32);
259 let renbt_epoch_ptr = (account_info_addr + 32) as *const Epoch;
260 unsafe {
261 assert_eq!(*renbt_epoch_ptr, 42);
262 }
263
264 assert_eq!(offset_of!(AccountInfo, is_signer), 40);
266 let is_signer_ptr = (account_info_addr + 40) as *const bool;
267 unsafe {
268 assert!(*is_signer_ptr);
269 }
270
271 assert_eq!(offset_of!(AccountInfo, is_writable), 41);
273 let is_writable_ptr = (account_info_addr + 41) as *const bool;
274 unsafe {
275 assert!(!*is_writable_ptr);
276 }
277
278 assert_eq!(offset_of!(AccountInfo, executable), 42);
280 let executable_ptr = (account_info_addr + 42) as *const bool;
281 unsafe {
282 assert!(*executable_ptr);
283 }
284 }
285}
286
287#[cfg(test)]
288mod tests {
289 #[test]
290 fn test_check_type_assumptions() {
291 super::check_type_assumptions()
292 }
293}