rialo_s_bpf_loader_program/syscalls/
sysvar.rs1use super::*;
6
7fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId + Clone>(
8 sysvar: Result<Arc<T>, InstructionError>,
9 var_addr: u64,
10 check_aligned: bool,
11 memory_mapping: &mut MemoryMapping<'_>,
12 invoke_context: &mut InvokeContext<'_>,
13) -> Result<u64, Error> {
14 consume_compute_meter(
15 invoke_context,
16 invoke_context
17 .get_compute_budget()
18 .sysvar_base_cost
19 .saturating_add(size_of::<T>() as u64),
20 )?;
21 let var = translate_type_mut::<T>(memory_mapping, var_addr, check_aligned)?;
22
23 let sysvar: Arc<T> = sysvar?;
28 *var = T::clone(sysvar.as_ref());
29
30 Ok(SUCCESS)
31}
32
33declare_builtin_function!(
34 SyscallGetClockSysvar,
36 fn rust(
37 invoke_context: &mut InvokeContext<'_>,
38 var_addr: u64,
39 _arg2: u64,
40 _arg3: u64,
41 _arg4: u64,
42 _arg5: u64,
43 memory_mapping: &mut MemoryMapping<'_>,
44 ) -> Result<u64, Error> {
45 get_sysvar(
46 invoke_context.get_sysvar_cache().get_clock(),
47 var_addr,
48 invoke_context.get_check_aligned(),
49 memory_mapping,
50 invoke_context,
51 )
52 }
53);
54
55declare_builtin_function!(
56 SyscallGetEpochScheduleSysvar,
58 fn rust(
59 invoke_context: &mut InvokeContext<'_>,
60 var_addr: u64,
61 _arg2: u64,
62 _arg3: u64,
63 _arg4: u64,
64 _arg5: u64,
65 memory_mapping: &mut MemoryMapping<'_>,
66 ) -> Result<u64, Error> {
67 get_sysvar(
68 invoke_context.get_sysvar_cache().get_epoch_schedule(),
69 var_addr,
70 invoke_context.get_check_aligned(),
71 memory_mapping,
72 invoke_context,
73 )
74 }
75);
76
77declare_builtin_function!(
78 SyscallGetRentSysvar,
80 fn rust(
81 invoke_context: &mut InvokeContext<'_>,
82 var_addr: u64,
83 _arg2: u64,
84 _arg3: u64,
85 _arg4: u64,
86 _arg5: u64,
87 memory_mapping: &mut MemoryMapping<'_>,
88 ) -> Result<u64, Error> {
89 get_sysvar(
90 invoke_context.get_sysvar_cache().get_rent(),
91 var_addr,
92 invoke_context.get_check_aligned(),
93 memory_mapping,
94 invoke_context,
95 )
96 }
97);
98
99declare_builtin_function!(
100 SyscallGetRandomSeed,
102 fn rust(
103 invoke_context: &mut InvokeContext<'_>,
104 var_addr: u64,
105 _arg2: u64,
106 _arg3: u64,
107 _arg4: u64,
108 _arg5: u64,
109 memory_mapping: &mut MemoryMapping<'_>,
110 ) -> Result<u64, Error> {
111 consume_compute_meter(
112 invoke_context,
113 invoke_context
114 .get_compute_budget()
115 .sysvar_base_cost
116 .saturating_add(std::mem::size_of::<u64>() as u64),
117 )?;
118
119 let random_seed = invoke_context.environment_config.random_seed;
120 let var = translate_type_mut::<u64>(
121 memory_mapping,
122 var_addr,
123 invoke_context.get_check_aligned(),
124 )?;
125 *var = random_seed;
126
127 Ok(SUCCESS)
128 }
129);
130
131const SYSVAR_NOT_FOUND: u64 = 2;
132const OFFSET_LENGTH_EXCEEDS_SYSVAR: u64 = 1;
133
134declare_builtin_function!(
137 SyscallGetSysvar,
139 fn rust(
140 invoke_context: &mut InvokeContext<'_>,
141 sysvar_id_addr: u64,
142 var_addr: u64,
143 offset: u64,
144 length: u64,
145 _arg5: u64,
146 memory_mapping: &mut MemoryMapping<'_>,
147 ) -> Result<u64, Error> {
148 let check_aligned = invoke_context.get_check_aligned();
149 let ComputeBudget {
150 sysvar_base_cost,
151 cpi_bytes_per_unit,
152 mem_op_base_cost,
153 ..
154 } = *invoke_context.get_compute_budget();
155
156 let sysvar_id_cost = 32_u64.checked_div(cpi_bytes_per_unit).unwrap_or(0);
158 let sysvar_buf_cost = length.checked_div(cpi_bytes_per_unit).unwrap_or(0);
159 consume_compute_meter(
160 invoke_context,
161 sysvar_base_cost
162 .saturating_add(sysvar_id_cost)
163 .saturating_add(std::cmp::max(sysvar_buf_cost, mem_op_base_cost)),
164 )?;
165
166 let sysvar_id = translate_type::<Pubkey>(memory_mapping, sysvar_id_addr, check_aligned)?;
168
169 let var = translate_slice_mut::<u8>(memory_mapping, var_addr, length, check_aligned)?;
171
172 let offset_length = offset
174 .checked_add(length)
175 .ok_or(InstructionError::ArithmeticOverflow)?;
176
177 let _ = var_addr
179 .checked_add(length)
180 .ok_or(InstructionError::ArithmeticOverflow)?;
181
182 let cache = invoke_context.get_sysvar_cache();
183
184 let sysvar_buf = match cache.sysvar_id_to_buffer(sysvar_id) {
186 None => return Ok(SYSVAR_NOT_FOUND),
187 Some(ref sysvar_buf) => sysvar_buf,
188 };
189
190 if let Some(sysvar_slice) = sysvar_buf.get(offset as usize..offset_length as usize) {
192 var.copy_from_slice(sysvar_slice);
193 } else {
194 return Ok(OFFSET_LENGTH_EXCEEDS_SYSVAR);
195 }
196
197 Ok(SUCCESS)
198 }
199);