1#![allow(unexpected_cfgs)]
2
3#[macro_export]
5#[cfg(not(target_os = "solana"))]
6macro_rules! declare_sol_app_stubs {
7 () => {
8 $crate::common_stub_types!();
9
10 #[repr(C)]
11 pub struct SolAppSyscallStubs {
12 pub stubs_api: SyscallStubsApi,
13 }
14
15 impl SyscallStubs for SolAppSyscallStubs {
16 fn sol_get_clock_sysvar(&self, var_addr: *mut u8) -> u64 {
17 (self.stubs_api.sol_get_clock_sysvar)(var_addr)
18 }
19 fn sol_get_epoch_rewards_sysvar(&self, var_addr: *mut u8) -> u64 {
20 (self.stubs_api.sol_get_epoch_rewards_sysvar)(var_addr)
21 }
22 fn sol_get_epoch_schedule_sysvar(&self, var_addr: *mut u8) -> u64 {
23 (self.stubs_api.sol_get_epoch_schedule_sysvar)(var_addr)
24 }
25 fn sol_get_epoch_stake(&self, vote_address: *const u8) -> u64 {
26 (self.stubs_api.sol_get_epoch_stake)(vote_address)
27 }
28 fn sol_get_fees_sysvar(&self, var_addr: *mut u8) -> u64 {
29 (self.stubs_api.sol_get_fees_sysvar)(var_addr)
30 }
31 fn sol_get_last_restart_slot(&self, var_addr: *mut u8) -> u64 {
32 (self.stubs_api.sol_get_last_restart_slot)(var_addr)
33 }
34 fn sol_get_rent_sysvar(&self, var_addr: *mut u8) -> u64 {
35 (self.stubs_api.sol_get_rent_sysvar)(var_addr)
36 }
37 fn sol_get_stack_height(&self) -> u64 {
38 (self.stubs_api.sol_get_stack_height)()
39 }
40 fn sol_remaining_compute_units(&self) -> u64 {
41 (self.stubs_api.sol_remaining_compute_units)()
42 }
43 unsafe fn sol_memcmp(&self, s1: *const u8, s2: *const u8, n: usize, result: *mut i32) {
44 (self.stubs_api.sol_memcmp_)(s1, s2, n as u64, result);
45 }
46 unsafe fn sol_memcpy(&self, dst: *mut u8, src: *const u8, n: usize) {
47 (self.stubs_api.sol_memcpy_)(dst, src, n as u64)
48 }
49 unsafe fn sol_memmove(&self, dst: *mut u8, src: *const u8, n: usize) {
50 (self.stubs_api.sol_memmove_)(dst, src, n as u64)
51 }
52 unsafe fn sol_memset(&self, s: *mut u8, c: u8, n: usize) {
53 (self.stubs_api.sol_memset_)(s, c, n as u64)
54 }
55 fn sol_get_sysvar(
56 &self,
57 sysvar_id_addr: *const u8,
58 var_addr: *mut u8,
59 offset: u64,
60 length: u64,
61 ) -> u64 {
62 (self.stubs_api.sol_get_sysvar)(sysvar_id_addr, var_addr, offset, length)
63 }
64 fn sol_log_compute_units(&self) {
65 (self.stubs_api.sol_log_compute_units_)()
66 }
67 fn sol_log(&self, message: &str) {
68 (self.stubs_api.sol_log_)(message.as_ptr(), message.len() as u64)
69 }
70 fn sol_log_data(&self, fields: &[&[u8]]) {
71 (self.stubs_api.sol_log_data)(fields.as_ptr() as *const u8, fields.len() as u64);
72 }
73 fn sol_set_return_data(&self, data: &[u8]) {
74 (self.stubs_api.sol_set_return_data)(data.as_ptr(), data.len() as u64);
75 }
76 fn sol_get_return_data(&self) -> Option<(Pubkey, Vec<u8>)> {
77 let mut program_id = CPubkey::from([0u8; 32]);
78 let data_bytes_to_alloc =
79 (self.stubs_api.sol_get_return_data)(&mut u8::default(), 0, &mut program_id);
80 if data_bytes_to_alloc == 0 {
81 return None;
82 }
83 let mut vdata = vec![0u8; data_bytes_to_alloc as usize];
84 let same_bytes_num_expected = (self.stubs_api.sol_get_return_data)(
85 vdata.as_mut_ptr(),
86 vdata.len() as _,
87 &mut program_id,
88 );
89 if same_bytes_num_expected == data_bytes_to_alloc {
90 Some((Pubkey::new_from_array(*program_id.as_array()), vdata))
91 } else {
92 None
93 }
94 }
95 fn sol_get_processed_sibling_instruction(&self, index: usize) -> Option<Instruction> {
96 let mut meta = CProcessedSiblingInstruction {
97 accounts_len: 0,
98 data_len: 0,
99 };
100 let mut program_id = CPubkey::from([0u8; 32]);
101 if 1 == (self.stubs_api.sol_get_processed_sibling_instruction)(
102 index as _,
103 &mut meta,
104 &mut program_id,
105 &mut u8::default(),
106 &mut CAccountMeta::default(),
107 ) {
108 let accounts_to_alloc = meta.accounts_len;
109 let data_bytes_to_alloc = meta.data_len;
110 let mut caccount_metas = vec![CAccountMeta::default(); accounts_to_alloc as _];
111 let mut vdata = vec![0u8; data_bytes_to_alloc as _];
112 let res = (self.stubs_api.sol_get_processed_sibling_instruction)(
113 index as _,
114 &mut meta,
115 &mut program_id,
116 vdata.as_mut_ptr(),
117 caccount_metas.as_mut_ptr(),
118 );
119 if res != 0 && res != 1 {
120 let mut account_metas = vec![];
121 for cai in &caccount_metas {
122 let pubkey = unsafe { *(*cai.pubkey).as_array() };
124 let account_meta = AccountMeta {
125 is_signer: cai.is_signer,
126 is_writable: cai.is_writable,
127 pubkey: Pubkey::new_from_array(pubkey),
128 };
129 account_metas.push(account_meta);
130 }
131 return Some(Instruction {
132 accounts: account_metas,
133 data: vdata,
134 program_id: Pubkey::new_from_array(*program_id.as_array()),
135 });
136 }
137 }
138 None
139 }
140 fn sol_invoke_signed(
141 &self,
142 instruction: &Instruction,
143 account_infos: &[AccountInfo],
144 signers_seeds: &[&[&[u8]]],
145 ) -> ProgramResult {
146 let mut caccounts = vec![];
147 for account_meta in &instruction.accounts {
148 let caccount = CAccountMeta {
149 is_signer: account_meta.is_signer,
150 is_writable: account_meta.is_writable,
151 pubkey: &account_meta.pubkey as *const _ as *const CPubkey,
152 };
153 caccounts.push(caccount);
154 }
155 let cinstr = CInstruction {
156 program_id: &instruction.program_id as *const _ as *const CPubkey,
157 accounts_len: instruction.accounts.len() as _,
158 data_len: instruction.data.len() as _,
159 accounts: caccounts.as_ptr(),
160 data: instruction.data.as_ptr(),
161 };
162 let mut caccount_infos = vec![];
163 for account_info in account_infos {
164 let lamports_ref = &mut *account_info.lamports.borrow_mut();
165 let data_ref = &mut *account_info.data.borrow_mut();
166 let caccount_info = CAccountInfo {
167 is_signer: account_info.is_signer,
168 is_writable: account_info.is_writable,
169 executable: account_info.executable,
170 rent_epoch: account_info.rent_epoch,
171 data_len: data_ref.len() as _,
172 data: data_ref.as_mut_ptr(),
173 lamports: *lamports_ref as *mut u64,
174 key: account_info.key as *const _ as *const CPubkey,
175 owner: account_info.owner as *const _ as *const CPubkey,
176 };
177 let cai = &caccount_info;
178 let key: &Pubkey = unsafe { &*((*cai).key as *const Pubkey) };
179 let owner: &Pubkey = unsafe { &*((*cai).owner as *const Pubkey) };
180 caccount_infos.push(caccount_info);
181 }
182
183 let res = (self.stubs_api.sol_invoke_signed_c)(
184 &cinstr as *const _ as *const u8,
185 caccount_infos.as_ptr() as *const u8,
186 caccount_infos.len() as _,
187 signers_seeds.as_ptr() as *const u8,
188 signers_seeds.len() as _,
189 );
190 if res == 0 {
191 for (i, ai) in account_infos.iter().enumerate() {
192 let new_data_slice = unsafe {
193 std::slice::from_raw_parts_mut(
194 (*ai.data.borrow_mut()).as_mut_ptr(),
195 caccount_infos[i].data_len as _,
196 )
197 };
198 *ai.data.borrow_mut() = new_data_slice;
199 assert!(ai.lamports() == unsafe { *caccount_infos[i].lamports });
200 }
201 Ok(())
202 } else {
203 Err(ProgramError::Custom(res as _))
204 }
205 }
206 }
207
208 #[no_mangle]
209 pub extern "C" fn set_stubs(stubs_api: SyscallStubsApi) {
210 let stubs = Box::new(SolAppSyscallStubs { stubs_api });
211 let _ = set_syscall_stubs(stubs);
212 }
213 };
214}