solana_bpf_loader_program/syscalls/
sysvar.rs1use {
2 super::*, crate::translate_mut,
3 solana_program_runtime::execution_budget::SVMTransactionExecutionCost,
4};
5
6fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId + Clone>(
7 sysvar: Result<Arc<T>, InstructionError>,
8 var_addr: u64,
9 check_aligned: bool,
10 memory_mapping: &mut MemoryMapping,
11 invoke_context: &mut InvokeContext,
12) -> Result<u64, Error> {
13 consume_compute_meter(
14 invoke_context,
15 invoke_context
16 .get_execution_cost()
17 .sysvar_base_cost
18 .saturating_add(size_of::<T>() as u64),
19 )?;
20 translate_mut!(
21 memory_mapping,
22 check_aligned,
23 let var: &mut T = map(var_addr)?;
24 );
25
26 let sysvar: Arc<T> = sysvar?;
31 *var = T::clone(sysvar.as_ref());
32
33 Ok(SUCCESS)
34}
35
36declare_builtin_function!(
37 SyscallGetClockSysvar,
39 fn rust(
40 invoke_context: &mut InvokeContext,
41 var_addr: u64,
42 _arg2: u64,
43 _arg3: u64,
44 _arg4: u64,
45 _arg5: u64,
46 memory_mapping: &mut MemoryMapping,
47 ) -> Result<u64, Error> {
48 get_sysvar(
49 invoke_context.get_sysvar_cache().get_clock(),
50 var_addr,
51 invoke_context.get_check_aligned(),
52 memory_mapping,
53 invoke_context,
54 )
55 }
56);
57
58declare_builtin_function!(
59 SyscallGetEpochScheduleSysvar,
61 fn rust(
62 invoke_context: &mut InvokeContext,
63 var_addr: u64,
64 _arg2: u64,
65 _arg3: u64,
66 _arg4: u64,
67 _arg5: u64,
68 memory_mapping: &mut MemoryMapping,
69 ) -> Result<u64, Error> {
70 get_sysvar(
71 invoke_context.get_sysvar_cache().get_epoch_schedule(),
72 var_addr,
73 invoke_context.get_check_aligned(),
74 memory_mapping,
75 invoke_context,
76 )
77 }
78);
79
80declare_builtin_function!(
81 SyscallGetEpochRewardsSysvar,
83 fn rust(
84 invoke_context: &mut InvokeContext,
85 var_addr: u64,
86 _arg2: u64,
87 _arg3: u64,
88 _arg4: u64,
89 _arg5: u64,
90 memory_mapping: &mut MemoryMapping,
91 ) -> Result<u64, Error> {
92 get_sysvar(
93 invoke_context.get_sysvar_cache().get_epoch_rewards(),
94 var_addr,
95 invoke_context.get_check_aligned(),
96 memory_mapping,
97 invoke_context,
98 )
99 }
100);
101
102declare_builtin_function!(
103 SyscallGetFeesSysvar,
105 fn rust(
106 invoke_context: &mut InvokeContext,
107 var_addr: u64,
108 _arg2: u64,
109 _arg3: u64,
110 _arg4: u64,
111 _arg5: u64,
112 memory_mapping: &mut MemoryMapping,
113 ) -> Result<u64, Error> {
114 #[allow(deprecated)]
115 {
116 get_sysvar(
117 invoke_context.get_sysvar_cache().get_fees(),
118 var_addr,
119 invoke_context.get_check_aligned(),
120 memory_mapping,
121 invoke_context,
122 )
123 }
124 }
125);
126
127declare_builtin_function!(
128 SyscallGetRentSysvar,
130 fn rust(
131 invoke_context: &mut InvokeContext,
132 var_addr: u64,
133 _arg2: u64,
134 _arg3: u64,
135 _arg4: u64,
136 _arg5: u64,
137 memory_mapping: &mut MemoryMapping,
138 ) -> Result<u64, Error> {
139 get_sysvar(
140 invoke_context.get_sysvar_cache().get_rent(),
141 var_addr,
142 invoke_context.get_check_aligned(),
143 memory_mapping,
144 invoke_context,
145 )
146 }
147);
148
149declare_builtin_function!(
150 SyscallGetLastRestartSlotSysvar,
152 fn rust(
153 invoke_context: &mut InvokeContext,
154 var_addr: u64,
155 _arg2: u64,
156 _arg3: u64,
157 _arg4: u64,
158 _arg5: u64,
159 memory_mapping: &mut MemoryMapping,
160 ) -> Result<u64, Error> {
161 get_sysvar(
162 invoke_context.get_sysvar_cache().get_last_restart_slot(),
163 var_addr,
164 invoke_context.get_check_aligned(),
165 memory_mapping,
166 invoke_context,
167 )
168 }
169);
170
171const SYSVAR_NOT_FOUND: u64 = 2;
172const OFFSET_LENGTH_EXCEEDS_SYSVAR: u64 = 1;
173
174declare_builtin_function!(
177 SyscallGetSysvar,
179 fn rust(
180 invoke_context: &mut InvokeContext,
181 sysvar_id_addr: u64,
182 var_addr: u64,
183 offset: u64,
184 length: u64,
185 _arg5: u64,
186 memory_mapping: &mut MemoryMapping,
187 ) -> Result<u64, Error> {
188 let check_aligned = invoke_context.get_check_aligned();
189 let SVMTransactionExecutionCost {
190 sysvar_base_cost,
191 cpi_bytes_per_unit,
192 mem_op_base_cost,
193 ..
194 } = *invoke_context.get_execution_cost();
195
196 let sysvar_id_cost = 32_u64.checked_div(cpi_bytes_per_unit).unwrap_or(0);
198 let sysvar_buf_cost = length.checked_div(cpi_bytes_per_unit).unwrap_or(0);
199 consume_compute_meter(
200 invoke_context,
201 sysvar_base_cost
202 .saturating_add(sysvar_id_cost)
203 .saturating_add(std::cmp::max(sysvar_buf_cost, mem_op_base_cost)),
204 )?;
205
206 translate_mut!(
208 memory_mapping,
209 check_aligned,
210 let var: &mut [u8] = map(var_addr, length)?;
211 );
212
213 let sysvar_id = translate_type::<Pubkey>(memory_mapping, sysvar_id_addr, check_aligned)?;
215
216 let offset_length = offset
218 .checked_add(length)
219 .ok_or(InstructionError::ArithmeticOverflow)?;
220
221 let _ = var_addr
223 .checked_add(length)
224 .ok_or(InstructionError::ArithmeticOverflow)?;
225
226 let cache = invoke_context.get_sysvar_cache();
227
228 let sysvar_buf = match cache.sysvar_id_to_buffer(sysvar_id) {
230 None => return Ok(SYSVAR_NOT_FOUND),
231 Some(ref sysvar_buf) => sysvar_buf,
232 };
233
234 if let Some(sysvar_slice) = sysvar_buf.get(offset as usize..offset_length as usize) {
236 var.copy_from_slice(sysvar_slice);
237 } else {
238 return Ok(OFFSET_LENGTH_EXCEEDS_SYSVAR);
239 }
240
241 Ok(SUCCESS)
242 }
243);