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 extern crate memoffset;
132 use {
133 crate::instruction::AccountMeta,
134 memoffset::offset_of,
135 std::{
136 mem::{align_of, size_of},
137 str::FromStr,
138 },
139 };
140
141 assert_eq!(size_of::<u64>(), size_of::<usize>());
143 assert_eq!(1, align_of::<u8>());
145
146 {
148 assert_eq!(size_of::<AccountMeta>(), 32 + 1 + 1);
149
150 let pubkey1 = Pubkey::from_str("J9PYCcoKusHyKRMXnBL17VTXC3MVETyqBG2KyLXVv6Ai").unwrap();
151 let pubkey2 = Pubkey::from_str("Hvy4GHgPToZNoENTKjC4mJqpzWWjgTwXrFufKfxYiKkV").unwrap();
152 let pubkey3 = Pubkey::from_str("JDMyRL8rCkae7maCSv47upNuBMFd3Mgos1fz2AvYzVzY").unwrap();
153 let account_meta1 = AccountMeta {
154 pubkey: pubkey2,
155 is_signer: true,
156 is_writable: false,
157 };
158 let account_meta2 = AccountMeta {
159 pubkey: pubkey3,
160 is_signer: false,
161 is_writable: true,
162 };
163 let data = vec![1, 2, 3, 4, 5];
164 let instruction = Instruction {
165 program_id: pubkey1,
166 accounts: vec![account_meta1.clone(), account_meta2.clone()],
167 data: data.clone(),
168 };
169 let instruction = StableInstruction::from(instruction);
170 let instruction_addr = &instruction as *const _ as u64;
171
172 assert_eq!(offset_of!(StableInstruction, program_id), 48);
174 let pubkey_ptr = (instruction_addr + 48) as *const Pubkey;
175 unsafe {
176 assert_eq!(*pubkey_ptr, pubkey1);
177 }
178
179 assert_eq!(offset_of!(StableInstruction, accounts), 0);
181 let accounts_ptr = (instruction_addr) as *const *const AccountMeta;
182 let accounts_cap = (instruction_addr + 8) as *const usize;
183 let accounts_len = (instruction_addr + 16) as *const usize;
184 unsafe {
185 assert_eq!(*accounts_cap, 2);
186 assert_eq!(*accounts_len, 2);
187 let account_meta_ptr = *accounts_ptr;
188 assert_eq!(*account_meta_ptr, account_meta1);
189 assert_eq!(*(account_meta_ptr.offset(1)), account_meta2);
190 }
191
192 assert_eq!(offset_of!(StableInstruction, data), 24);
194 let data_ptr = (instruction_addr + 24) as *const *const [u8; 5];
195 let data_cap = (instruction_addr + 24 + 8) as *const usize;
196 let data_len = (instruction_addr + 24 + 16) as *const usize;
197 unsafe {
198 assert_eq!(*data_cap, 5);
199
200 assert_eq!(*data_len, 5);
201 let u8_ptr = *data_ptr;
202 assert_eq!(*u8_ptr, data[..]);
203 }
204 }
205
206 solana_account_info::check_type_assumptions();
207}
208
209#[cfg(test)]
210mod tests {
211 #[test]
212 fn test_check_type_assumptions() {
213 super::check_type_assumptions()
214 }
215}