Line data Source code
1 : #include "fd_vm_syscall.h"
2 : #include "../../runtime/program/fd_vote_program.h"
3 : #include "../../runtime/context/fd_exec_instr_ctx.h"
4 : #include "../../runtime/fd_system_ids.h"
5 : #include "fd_vm_syscall_macros.h"
6 :
7 : /* The VM structs for sysvars that are exposed by the VM are represented
8 : differently from the representations of the accounts in the accounts
9 : database. These structs usually have padding which must be zeroed
10 : out. */
11 : struct fd_vm_epoch_schedule {
12 : ulong slots_per_epoch;
13 : ulong leader_schedule_slot_offset;
14 : uchar warmup; /* 0 or 1 */
15 : uchar padding_[7];
16 : ulong first_normal_epoch;
17 : ulong first_normal_slot;
18 : };
19 : typedef struct fd_vm_epoch_schedule fd_vm_epoch_schedule_t;
20 : FD_STATIC_ASSERT( sizeof(fd_vm_epoch_schedule_t) == 40UL, "vm epoch schedule size mismatch" );
21 : FD_STATIC_ASSERT( alignof(fd_vm_epoch_schedule_t) == FD_VM_ALIGN_RUST_SYSVAR_EPOCH_SCHEDULE, "vm epoch schedule alignment mismatch" );
22 : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_schedule_t, slots_per_epoch ) == 0UL, "vm epoch schedule layout mismatch" );
23 : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_schedule_t, leader_schedule_slot_offset) == 8UL, "vm epoch schedule layout mismatch" );
24 : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_schedule_t, warmup ) == 16UL, "vm epoch schedule layout mismatch" );
25 : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_schedule_t, first_normal_epoch ) == 24UL, "vm epoch schedule layout mismatch" );
26 : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_schedule_t, first_normal_slot ) == 32UL, "vm epoch schedule layout mismatch" );
27 :
28 : struct fd_vm_rent {
29 : ulong lamports_per_uint8_year;
30 : double exemption_threshold;
31 : uchar burn_percent;
32 : uchar padding_[7];
33 : };
34 : typedef struct fd_vm_rent fd_vm_rent_t;
35 : FD_STATIC_ASSERT( sizeof(fd_vm_rent_t) == 24UL, "vm rent size mismatch" );
36 : FD_STATIC_ASSERT( alignof(fd_vm_rent_t) == FD_VM_ALIGN_RUST_SYSVAR_RENT, "vm rent alignment mismatch" );
37 : FD_STATIC_ASSERT( offsetof(fd_vm_rent_t, lamports_per_uint8_year) == 0UL, "vm rent layout mismatch" );
38 : FD_STATIC_ASSERT( offsetof(fd_vm_rent_t, exemption_threshold ) == 8UL, "vm rent layout mismatch" );
39 : FD_STATIC_ASSERT( offsetof(fd_vm_rent_t, burn_percent ) == 16UL, "vm rent layout mismatch" );
40 :
41 : typedef fd_sol_sysvar_clock_t fd_vm_clock_t;
42 : FD_STATIC_ASSERT( sizeof(fd_vm_clock_t) == 40UL, "vm clock size mismatch" );
43 : FD_STATIC_ASSERT( alignof(fd_vm_clock_t) == FD_VM_ALIGN_RUST_SYSVAR_CLOCK, "vm clock alignment mismatch" );
44 : FD_STATIC_ASSERT( offsetof(fd_vm_clock_t, slot ) == 0UL, "vm clock layout mismatch" );
45 : FD_STATIC_ASSERT( offsetof(fd_vm_clock_t, epoch_start_timestamp) == 8UL, "vm clock layout mismatch" );
46 : FD_STATIC_ASSERT( offsetof(fd_vm_clock_t, epoch ) == 16UL, "vm clock layout mismatch" );
47 : FD_STATIC_ASSERT( offsetof(fd_vm_clock_t, leader_schedule_epoch) == 24UL, "vm clock layout mismatch" );
48 : FD_STATIC_ASSERT( offsetof(fd_vm_clock_t, unix_timestamp ) == 32UL, "vm clock layout mismatch" );
49 :
50 : struct __attribute__((aligned(16))) fd_vm_epoch_rewards {
51 : ulong distribution_starting_block_height;
52 : ulong num_partitions;
53 : fd_hash_t parent_blockhash;
54 : fd_w_u128_t total_points;
55 : ulong total_rewards;
56 : ulong distributed_rewards;
57 : uchar active; /* 0 or 1 */
58 : uchar padding_[15];
59 : };
60 : typedef struct fd_vm_epoch_rewards fd_vm_epoch_rewards_t;
61 : FD_STATIC_ASSERT( sizeof(fd_vm_epoch_rewards_t) == 96UL, "vm epoch rewards size mismatch" );
62 : FD_STATIC_ASSERT( alignof(fd_vm_epoch_rewards_t) == FD_VM_ALIGN_RUST_SYSVAR_EPOCH_REWARDS, "vm epoch rewards alignment mismatch" );
63 : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, distribution_starting_block_height) == 0UL, "vm epoch rewards layout mismatch" );
64 : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, num_partitions ) == 8UL, "vm epoch rewards layout mismatch" );
65 : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, parent_blockhash ) == 16UL, "vm epoch rewards layout mismatch" );
66 : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, total_points ) == 48UL, "vm epoch rewards layout mismatch" );
67 : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, total_rewards ) == 64UL, "vm epoch rewards layout mismatch" );
68 : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, distributed_rewards ) == 72UL, "vm epoch rewards layout mismatch" );
69 : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, active ) == 80UL, "vm epoch rewards layout mismatch" );
70 :
71 : /* FIXME: In the original version of this code, there was an FD_TEST
72 : to check if the VM was attached to an instruction context (that
73 : would have crashed anyway because of pointer chasing). If the VM
74 : is being run outside the Solana runtime, it should never invoke
75 : this syscall in the first place. So we treat this as a SIGCALL in
76 : a non-crashing way for the time being. */
77 :
78 : int
79 : fd_vm_syscall_sol_get_clock_sysvar( /**/ void * _vm,
80 : /**/ ulong out_vaddr,
81 : FD_PARAM_UNUSED ulong r2,
82 : FD_PARAM_UNUSED ulong r3,
83 : FD_PARAM_UNUSED ulong r4,
84 : FD_PARAM_UNUSED ulong r5,
85 0 : /**/ ulong * _ret ) {
86 0 : fd_vm_t * vm = _vm;
87 0 : fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
88 0 : if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
89 :
90 0 : FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_vm_clock_t) ) );
91 :
92 : /* See https://github.com/anza-xyz/agave/pull/12130 */
93 0 : if( FD_UNLIKELY( vm->is_deprecated ) ) {
94 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_UNALIGNED_POINTER );
95 0 : return FD_VM_SYSCALL_ERR_UNALIGNED_POINTER;
96 0 : }
97 :
98 0 : if( FD_UNLIKELY( vm->syscall_parameter_address_restrictions && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
99 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
100 0 : return FD_VM_ERR_INVAL;
101 0 : }
102 :
103 0 : fd_vm_haddr_query_t var_query = {
104 0 : .vaddr = out_vaddr,
105 0 : .align = FD_VM_ALIGN_RUST_SYSVAR_CLOCK,
106 0 : .sz = sizeof(fd_vm_clock_t),
107 0 : .is_slice = 0,
108 0 : };
109 :
110 0 : fd_vm_haddr_query_t * queries[] = { &var_query };
111 0 : FD_VM_TRANSLATE_MUT( vm, queries );
112 :
113 0 : fd_vm_clock_t clock = fd_sysvar_cache_clock_read_nofail( instr_ctx->sysvar_cache );
114 0 : memcpy( var_query.haddr, &clock, sizeof(fd_vm_clock_t) );
115 :
116 0 : *_ret = 0UL;
117 0 : return FD_VM_SUCCESS;
118 0 : }
119 :
120 : int
121 : fd_vm_syscall_sol_get_epoch_schedule_sysvar( /**/ void * _vm,
122 : /**/ ulong out_vaddr,
123 : FD_PARAM_UNUSED ulong r2,
124 : FD_PARAM_UNUSED ulong r3,
125 : FD_PARAM_UNUSED ulong r4,
126 : FD_PARAM_UNUSED ulong r5,
127 0 : /**/ ulong * _ret ) {
128 0 : fd_vm_t * vm = _vm;
129 0 : fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
130 0 : if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
131 :
132 0 : FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_vm_epoch_schedule_t) ) );
133 :
134 : /* See https://github.com/anza-xyz/agave/pull/12130 */
135 0 : if( FD_UNLIKELY( vm->is_deprecated ) ) {
136 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_UNALIGNED_POINTER );
137 0 : return FD_VM_SYSCALL_ERR_UNALIGNED_POINTER;
138 0 : }
139 :
140 0 : if( FD_UNLIKELY( vm->syscall_parameter_address_restrictions && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
141 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
142 0 : return FD_VM_ERR_INVAL;
143 0 : }
144 :
145 0 : fd_vm_haddr_query_t var_query = {
146 0 : .vaddr = out_vaddr,
147 0 : .align = FD_VM_ALIGN_RUST_SYSVAR_EPOCH_SCHEDULE,
148 0 : .sz = sizeof(fd_vm_epoch_schedule_t),
149 0 : .is_slice = 0,
150 0 : };
151 :
152 0 : fd_vm_haddr_query_t * queries[] = { &var_query };
153 0 : FD_VM_TRANSLATE_MUT( vm, queries );
154 :
155 0 : fd_epoch_schedule_t schedule;
156 0 : if( FD_UNLIKELY( !fd_sysvar_cache_epoch_schedule_read( instr_ctx->sysvar_cache, &schedule ) ) ) {
157 0 : FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_out, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_out->err.exec_err_idx );
158 0 : return FD_VM_ERR_INVAL;
159 0 : }
160 :
161 : /* Returned value has padding which must be zeroed out. */
162 0 : uchar * dst = var_query.haddr;
163 0 : fd_vm_epoch_schedule_t * vm_schedule = (fd_vm_epoch_schedule_t *)dst;
164 0 : *vm_schedule = (fd_vm_epoch_schedule_t){
165 0 : .slots_per_epoch = schedule.slots_per_epoch,
166 0 : .leader_schedule_slot_offset = schedule.leader_schedule_slot_offset,
167 0 : .warmup = schedule.warmup,
168 0 : .first_normal_epoch = schedule.first_normal_epoch,
169 0 : .first_normal_slot = schedule.first_normal_slot,
170 0 : };
171 :
172 0 : *_ret = 0UL;
173 0 : return FD_VM_SUCCESS;
174 0 : }
175 :
176 : int
177 : fd_vm_syscall_sol_get_rent_sysvar( /**/ void * _vm,
178 : /**/ ulong out_vaddr,
179 : FD_PARAM_UNUSED ulong r2,
180 : FD_PARAM_UNUSED ulong r3,
181 : FD_PARAM_UNUSED ulong r4,
182 : FD_PARAM_UNUSED ulong r5,
183 0 : /**/ ulong * _ret ) {
184 0 : fd_vm_t * vm = _vm;
185 :
186 : /* Unreachable in a real SVM, used for testing */
187 :
188 0 : fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
189 0 : if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
190 :
191 0 : FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_vm_rent_t) ) );
192 :
193 : /* See https://github.com/anza-xyz/agave/pull/12130 */
194 0 : if( FD_UNLIKELY( vm->is_deprecated ) ) {
195 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_UNALIGNED_POINTER );
196 0 : return FD_VM_SYSCALL_ERR_UNALIGNED_POINTER;
197 0 : }
198 :
199 0 : if( FD_UNLIKELY( vm->syscall_parameter_address_restrictions && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
200 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
201 0 : return FD_VM_ERR_INVAL;
202 0 : }
203 :
204 0 : fd_vm_haddr_query_t var_query = {
205 0 : .vaddr = out_vaddr,
206 0 : .align = FD_VM_ALIGN_RUST_SYSVAR_RENT,
207 0 : .sz = sizeof(fd_vm_rent_t),
208 0 : .is_slice = 0,
209 0 : };
210 :
211 0 : fd_vm_haddr_query_t * queries[] = { &var_query };
212 0 : FD_VM_TRANSLATE_MUT( vm, queries );
213 :
214 0 : fd_rent_t rent = fd_sysvar_cache_rent_read_nofail( instr_ctx->sysvar_cache );
215 :
216 : /* The returned value has padding which must be zeroed out. */
217 0 : uchar * dst = var_query.haddr;
218 0 : fd_vm_rent_t * vm_rent = (fd_vm_rent_t *)dst;
219 0 : *vm_rent = (fd_vm_rent_t){
220 0 : .lamports_per_uint8_year = rent.lamports_per_uint8_year,
221 0 : .exemption_threshold = rent.exemption_threshold,
222 0 : .burn_percent = rent.burn_percent,
223 0 : };
224 :
225 0 : *_ret = 0UL;
226 0 : return FD_VM_SUCCESS;
227 0 : }
228 :
229 : /* https://github.com/anza-xyz/agave/blob/v2.3.2/programs/bpf_loader/src/syscalls/sysvar.rs#L149 */
230 : int
231 : fd_vm_syscall_sol_get_last_restart_slot_sysvar( /**/ void * _vm,
232 : /**/ ulong out_vaddr,
233 : FD_PARAM_UNUSED ulong r2,
234 : FD_PARAM_UNUSED ulong r3,
235 : FD_PARAM_UNUSED ulong r4,
236 : FD_PARAM_UNUSED ulong r5,
237 0 : /**/ ulong * _ret ) {
238 0 : fd_vm_t * vm = _vm;
239 0 : fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
240 0 : if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
241 :
242 0 : FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, 8UL ) );
243 :
244 : /* See https://github.com/anza-xyz/agave/pull/12130 */
245 0 : if( FD_UNLIKELY( vm->is_deprecated ) ) {
246 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_UNALIGNED_POINTER );
247 0 : return FD_VM_SYSCALL_ERR_UNALIGNED_POINTER;
248 0 : }
249 :
250 0 : if( FD_UNLIKELY( vm->syscall_parameter_address_restrictions && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
251 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
252 0 : return FD_VM_ERR_INVAL;
253 0 : }
254 :
255 0 : fd_vm_haddr_query_t var_query = {
256 0 : .vaddr = out_vaddr,
257 0 : .align = FD_VM_ALIGN_RUST_SYSVAR_LAST_RESTART_SLOT,
258 0 : .sz = sizeof(ulong),
259 0 : .is_slice = 0,
260 0 : };
261 :
262 0 : fd_vm_haddr_query_t * queries[] = { &var_query };
263 0 : FD_VM_TRANSLATE_MUT( vm, queries );
264 :
265 0 : ulong const * last_restart_slot = fd_sysvar_cache_last_restart_slot_read( vm->instr_ctx->sysvar_cache );
266 0 : if( FD_UNLIKELY( last_restart_slot==NULL ) ) {
267 0 : FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_out, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_out->err.exec_err_idx );
268 0 : return FD_VM_ERR_INVAL;
269 0 : }
270 :
271 0 : memcpy( var_query.haddr, last_restart_slot, sizeof(ulong) );
272 :
273 0 : *_ret = 0UL;
274 0 : return FD_VM_SUCCESS;
275 0 : }
276 :
277 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L167-L232 */
278 : int
279 : fd_vm_syscall_sol_get_sysvar( /**/ void * _vm,
280 : /**/ ulong sysvar_id_vaddr,
281 : /**/ ulong out_vaddr,
282 : /**/ ulong offset,
283 : /**/ ulong sz,
284 : FD_PARAM_UNUSED ulong r5,
285 0 : /**/ ulong * _ret ) {
286 0 : fd_vm_t * vm = _vm;
287 0 : fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
288 0 : if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
289 :
290 : /* sysvar_id_cost seems to just always be 32 / 250 = 0...
291 : https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L190-L197 */
292 0 : ulong sysvar_buf_cost = sz / FD_VM_CPI_BYTES_PER_UNIT;
293 0 : FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, fd_ulong_max( sysvar_buf_cost, FD_VM_MEM_OP_BASE_COST ) ) );
294 :
295 : /* See https://github.com/anza-xyz/agave/pull/12130 */
296 0 : if( FD_UNLIKELY( vm->is_deprecated ) ) {
297 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_UNALIGNED_POINTER );
298 0 : return FD_VM_SYSCALL_ERR_UNALIGNED_POINTER;
299 0 : }
300 :
301 0 : if( FD_UNLIKELY( vm->syscall_parameter_address_restrictions && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
302 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
303 0 : return FD_VM_ERR_INVAL;
304 0 : }
305 :
306 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/sysvar.rs#L207-L211 */
307 0 : fd_vm_haddr_query_t var_query = {
308 0 : .vaddr = out_vaddr,
309 0 : .align = FD_VM_ALIGN_RUST_U8,
310 0 : .sz = sz,
311 0 : .is_slice = 1,
312 0 : };
313 :
314 0 : fd_vm_haddr_query_t * queries[] = { &var_query };
315 0 : FD_VM_TRANSLATE_MUT( vm, queries );
316 :
317 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L199-L200 */
318 0 : const fd_pubkey_t * sysvar_id = FD_VM_MEM_HADDR_LD( vm, sysvar_id_vaddr, FD_VM_ALIGN_RUST_PUBKEY, FD_PUBKEY_FOOTPRINT );
319 :
320 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L205-L208 */
321 0 : ulong offset_length;
322 0 : int err = fd_int_if( __builtin_uaddl_overflow( offset, sz, &offset_length ), FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW, FD_EXECUTOR_INSTR_SUCCESS );
323 0 : if( FD_UNLIKELY( err ) ) {
324 0 : FD_VM_ERR_FOR_LOG_INSTR( vm, err );
325 0 : return FD_VM_SYSCALL_ERR_ABORT;
326 0 : }
327 :
328 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L210-L213
329 : We don't need this, we already checked we can store in out_vaddr with requested sz. */
330 :
331 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L215-L221 */
332 0 : if( FD_UNLIKELY( memcmp( sysvar_id->uc, fd_sysvar_clock_id.uc, FD_PUBKEY_FOOTPRINT ) &&
333 0 : memcmp( sysvar_id->uc, fd_sysvar_epoch_schedule_id.uc, FD_PUBKEY_FOOTPRINT ) &&
334 0 : memcmp( sysvar_id->uc, fd_sysvar_epoch_rewards_id.uc, FD_PUBKEY_FOOTPRINT ) &&
335 0 : memcmp( sysvar_id->uc, fd_sysvar_rent_id.uc, FD_PUBKEY_FOOTPRINT ) &&
336 0 : memcmp( sysvar_id->uc, fd_sysvar_slot_hashes_id.uc, FD_PUBKEY_FOOTPRINT ) &&
337 0 : memcmp( sysvar_id->uc, fd_sysvar_stake_history_id.uc, FD_PUBKEY_FOOTPRINT ) &&
338 0 : memcmp( sysvar_id->uc, fd_sysvar_last_restart_slot_id.uc, FD_PUBKEY_FOOTPRINT ) ) ) {
339 0 : *_ret = 2UL;
340 0 : return FD_VM_SUCCESS;
341 0 : }
342 :
343 0 : ulong sysvar_buf_len;
344 0 : uchar const * sysvar_buf =
345 0 : fd_sysvar_cache_data_query( vm->instr_ctx->sysvar_cache, sysvar_id, &sysvar_buf_len );
346 0 : if( FD_UNLIKELY( !sysvar_buf ) ) {
347 0 : *_ret = 2UL;
348 0 : return FD_VM_SUCCESS;
349 0 : }
350 :
351 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L223-L228
352 : Note the length check is at the very end to fail after performing sufficient checks. */
353 :
354 0 : if( FD_UNLIKELY( offset_length>sysvar_buf_len ) ) {
355 0 : *_ret = 1UL;
356 0 : return FD_VM_SUCCESS;
357 0 : }
358 :
359 0 : if( FD_UNLIKELY( sz==0UL ) ) {
360 0 : *_ret = 0UL;
361 0 : return FD_VM_SUCCESS;
362 0 : }
363 :
364 0 : fd_memcpy( var_query.haddr, sysvar_buf + offset, sz );
365 0 : *_ret = 0;
366 0 : return FD_VM_SUCCESS;
367 0 : }
368 :
369 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2043-L2118 */
370 : int
371 : fd_vm_syscall_sol_get_epoch_stake( /**/ void * _vm,
372 : /**/ ulong var_addr,
373 : FD_PARAM_UNUSED ulong r2,
374 : FD_PARAM_UNUSED ulong r3,
375 : FD_PARAM_UNUSED ulong r4,
376 : FD_PARAM_UNUSED ulong r5,
377 0 : /**/ ulong * _ret ) {
378 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
379 :
380 : /* Var addr of 0 returns the total active stake on the cluster.
381 :
382 : https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2057-L2075 */
383 0 : if( FD_UNLIKELY( var_addr==0UL ) ) {
384 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2065-L2066 */
385 0 : FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
386 :
387 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2074 */
388 0 : *_ret = vm->instr_ctx->bank->f.total_epoch_stake;
389 0 : return FD_VM_SUCCESS;
390 0 : }
391 :
392 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2083-L2091
393 : FD_PUBKEY_FOOTPRINT/FD_VM_CPI_BYTES_PER_UNIT is always 32/250 = 0,
394 : so we can omit it */
395 :
396 0 : FD_VM_CU_UPDATE( vm, FD_VM_MEM_OP_BASE_COST + FD_VM_SYSCALL_BASE_COST );
397 :
398 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2103-L2104 */
399 0 : fd_pubkey_t const * vote_address = FD_VM_MEM_HADDR_LD( vm, var_addr, FD_VM_ALIGN_RUST_PUBKEY, FD_PUBKEY_FOOTPRINT );
400 :
401 : /* https://github.com/anza-xyz/agave/blob/v2.2.14/runtime/src/bank.rs#L6954 */
402 :
403 0 : ulong stake = 0UL;
404 0 : if( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, validator_admission_ticket ) ) {
405 : /* It's okay to ignore if an account is invalid since these stakes
406 : are calculated from an older snapshot of vote account stakes. */
407 0 : fd_top_votes_t const * top_votes = fd_bank_top_votes_t_1_query( vm->instr_ctx->bank );
408 0 : fd_top_votes_query( top_votes, vote_address, NULL, &stake, NULL, NULL, NULL, NULL );
409 0 : } else {
410 0 : fd_vote_stakes_t * vote_stakes = fd_bank_vote_stakes( vm->instr_ctx->bank );
411 0 : fd_vote_stakes_query_t_1( vote_stakes, vm->instr_ctx->bank->vote_stakes_fork_id, vote_address, &stake, NULL, NULL );
412 0 : }
413 :
414 0 : *_ret = stake;
415 :
416 0 : return FD_VM_SUCCESS;
417 0 : }
418 :
419 : int
420 : fd_vm_syscall_sol_get_stack_height( /**/ void * _vm,
421 : FD_PARAM_UNUSED ulong r1,
422 : FD_PARAM_UNUSED ulong r2,
423 : FD_PARAM_UNUSED ulong r3,
424 : FD_PARAM_UNUSED ulong r4,
425 : FD_PARAM_UNUSED ulong r5,
426 0 : /**/ ulong * _ret ) {
427 : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L1547 */
428 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
429 :
430 0 : FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
431 :
432 0 : *_ret = vm->instr_ctx->runtime->instr.stack_sz;
433 0 : return FD_VM_SUCCESS;
434 0 : }
435 :
436 : int
437 : fd_vm_syscall_sol_get_return_data( /**/ void * _vm,
438 : /**/ ulong return_data_vaddr,
439 : /**/ ulong sz,
440 : /**/ ulong program_id_vaddr,
441 : FD_PARAM_UNUSED ulong r4,
442 : FD_PARAM_UNUSED ulong r5,
443 0 : /**/ ulong * _ret ) {
444 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
445 :
446 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1465 */
447 0 : FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
448 :
449 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1467 */
450 0 : fd_txn_return_data_t const * return_data = &vm->instr_ctx->txn_out->details.return_data;
451 :
452 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1468 */
453 0 : ulong length = fd_ulong_min( return_data->len, sz );
454 :
455 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1469-L1492 */
456 0 : if( FD_LIKELY( length ) ) {
457 :
458 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1470-L1474 */
459 0 : FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( length, sizeof(fd_pubkey_t) ) / FD_VM_CPI_BYTES_PER_UNIT );
460 :
461 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1476-L1481 */
462 0 : fd_vm_haddr_query_t return_data_query = {
463 0 : .vaddr = return_data_vaddr,
464 0 : .align = FD_VM_ALIGN_RUST_U8,
465 0 : .sz = length,
466 0 : .is_slice = 1
467 0 : };
468 :
469 0 : fd_vm_haddr_query_t program_id_query = {
470 0 : .vaddr = program_id_vaddr,
471 0 : .align = FD_VM_ALIGN_RUST_PUBKEY,
472 0 : .sz = sizeof(fd_pubkey_t),
473 0 : .is_slice = 0
474 0 : };
475 :
476 0 : fd_vm_haddr_query_t * queries[] = { &return_data_query, &program_id_query };
477 0 : FD_VM_TRANSLATE_MUT( vm, queries );
478 :
479 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1490-L1491 */
480 0 : memcpy( return_data_query.haddr, return_data->data, length );
481 0 : memcpy( program_id_query.haddr, &return_data->program_id, sizeof(fd_pubkey_t) );
482 0 : }
483 :
484 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1495 */
485 0 : *_ret = return_data->len;
486 0 : return FD_VM_SUCCESS;
487 0 : }
488 :
489 : int
490 : fd_vm_syscall_sol_set_return_data( /**/ void * _vm,
491 : /**/ ulong src_vaddr,
492 : /**/ ulong src_sz,
493 : FD_PARAM_UNUSED ulong r3,
494 : FD_PARAM_UNUSED ulong r4,
495 : FD_PARAM_UNUSED ulong r5,
496 0 : /**/ ulong * _ret ) {
497 : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L1297 */
498 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
499 :
500 : /* In the original version of this code, there was an FD_TEST
501 : to check if the VM was attached to an instruction context (that
502 : would have crashed anyway because of pointer chasing). If the VM
503 : is being run outside the Solana runtime, it should never invoke
504 : this syscall in the first place. So we treat this as a SIGCALL in
505 : a non-crashing way for the time being. */
506 0 : fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
507 0 : if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
508 :
509 0 : FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSCALL_BASE_COST, src_sz / FD_VM_CPI_BYTES_PER_UNIT ) );
510 :
511 : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L1316 */
512 0 : if( FD_UNLIKELY( src_sz>FD_VM_RETURN_DATA_MAX ) ) {
513 : /* TODO: this is a bit annoying, we may want to unify return codes...
514 : - FD_VM_SYSCALL_ERR_RETURN_DATA_TOO_LARGE is Agave's return code,
515 : also used for logging */
516 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_RETURN_DATA_TOO_LARGE );
517 0 : return FD_VM_SYSCALL_ERR_RETURN_DATA_TOO_LARGE;
518 0 : }
519 :
520 : /* src_sz == 0 is ok */
521 0 : void const * src = FD_VM_MEM_SLICE_HADDR_LD( vm, src_vaddr, FD_VM_ALIGN_RUST_U8, src_sz );
522 :
523 : /* https://github.com/anza-xyz/agave/blob/v2.2.0/programs/bpf_loader/src/syscalls/mod.rs#L1480-L1484 */
524 0 : fd_pubkey_t const * program_id = NULL;
525 0 : int err = fd_exec_instr_ctx_get_last_program_key( vm->instr_ctx, &program_id );
526 0 : if( FD_UNLIKELY( err ) ) {
527 0 : FD_VM_ERR_FOR_LOG_INSTR( vm, err );
528 0 : return err;
529 0 : }
530 :
531 0 : fd_txn_return_data_t * return_data = &instr_ctx->txn_out->details.return_data;
532 :
533 0 : return_data->len = src_sz;
534 0 : if( FD_LIKELY( src_sz!=0UL ) ) {
535 0 : fd_memcpy( return_data->data, src, src_sz );
536 0 : }
537 0 : return_data->program_id = *program_id;
538 :
539 0 : *_ret = 0;
540 0 : return FD_VM_SUCCESS;
541 0 : }
542 :
543 : /* Used to query and convey information about the sibling instruction
544 : https://github.com/anza-xyz/agave/blob/70089cce5119c9afaeb2986e2ecaa6d4505ec15d/sdk/program/src/instruction.rs#L676
545 :
546 : */
547 : struct fd_vm_syscall_processed_sibling_instruction {
548 : /* Length of the instruction data */
549 : ulong data_len;
550 : /* Number of accounts */
551 : ulong accounts_len;
552 : };
553 : typedef struct fd_vm_syscall_processed_sibling_instruction fd_vm_syscall_processed_sibling_instruction_t;
554 :
555 0 : #define FD_VM_SYSCALL_PROCESSED_SIBLING_INSTRUCTION_SIZE (16UL)
556 0 : #define FD_VM_SYSCALL_PROCESSED_SIBLING_INSTRUCTION_ALIGN (8UL )
557 :
558 : /* https://github.com/anza-xyz/agave/blob/70089cce5119c9afaeb2986e2ecaa6d4505ec15d/programs/bpf_loader/src/syscalls/mod.rs#L1402 */
559 : int
560 : fd_vm_syscall_sol_get_processed_sibling_instruction(
561 : void * _vm,
562 : ulong index,
563 : ulong result_meta_vaddr,
564 : ulong result_program_id_vaddr,
565 : ulong result_data_vaddr,
566 : ulong result_accounts_vaddr,
567 : ulong * _ret
568 0 : ) {
569 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
570 :
571 : /* Consume base compute cost
572 : https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1513 */
573 0 : FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
574 :
575 : /* Get the current instruction stack height. This value is 1-indexed
576 : (top level instruction has a stack height of 1).
577 : https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1517 */
578 0 : ulong stack_height = vm->instr_ctx->runtime->instr.stack_sz;
579 :
580 : /* Reverse iterate through the instruction trace, ignoring anything except instructions on the same level.
581 : https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1518-L1522 */
582 0 : ulong instruction_trace_length = vm->instr_ctx->runtime->instr.trace_length;
583 0 : ulong reverse_index_at_stack_height = 0UL;
584 0 : fd_instr_info_t * found_instruction_context = NULL;
585 0 : for( ulong index_in_trace=instruction_trace_length; index_in_trace>0UL; index_in_trace-- ) {
586 :
587 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1524-L1526
588 : This error can never happen */
589 :
590 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1527-L1529 */
591 0 : fd_instr_info_t * instruction_context = &vm->instr_ctx->runtime->instr.trace[ index_in_trace-1UL ];
592 0 : if( FD_LIKELY( instruction_context->stack_height<stack_height ) ) {
593 0 : break;
594 0 : }
595 :
596 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1530-L1536 */
597 0 : if( FD_UNLIKELY( instruction_context->stack_height==stack_height ) ) {
598 0 : if( FD_UNLIKELY( fd_ulong_sat_add( index, 1UL )==reverse_index_at_stack_height ) ) {
599 0 : found_instruction_context = instruction_context;
600 0 : break;
601 0 : }
602 0 : reverse_index_at_stack_height = fd_ulong_sat_add( reverse_index_at_stack_height, 1UL );
603 0 : }
604 0 : }
605 :
606 : /* If we have found an entry, then copy the instruction into the
607 : result addresses.
608 : https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1539-L1588
609 : */
610 0 : if( FD_LIKELY( found_instruction_context != NULL ) ) {
611 0 : fd_vm_haddr_query_t result_header_query = {
612 0 : .vaddr = result_meta_vaddr,
613 0 : .align = FD_VM_SYSCALL_PROCESSED_SIBLING_INSTRUCTION_ALIGN,
614 0 : .sz = FD_VM_SYSCALL_PROCESSED_SIBLING_INSTRUCTION_SIZE,
615 0 : .is_slice = 0,
616 0 : };
617 :
618 0 : fd_vm_haddr_query_t * queries[] = { &result_header_query };
619 0 : FD_VM_TRANSLATE_MUT( vm, queries );
620 :
621 0 : fd_vm_syscall_processed_sibling_instruction_t * result_header = result_header_query.haddr;
622 :
623 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1546-L1583 */
624 0 : if( result_header->data_len==found_instruction_context->data_sz && result_header->accounts_len==found_instruction_context->acct_cnt ) {
625 0 : fd_vm_haddr_query_t program_id_query = {
626 0 : .vaddr = result_program_id_vaddr,
627 0 : .align = FD_VM_ALIGN_RUST_PUBKEY,
628 0 : .sz = sizeof(fd_pubkey_t),
629 0 : .is_slice = 0,
630 0 : };
631 :
632 0 : fd_vm_haddr_query_t data_query = {
633 0 : .vaddr = result_data_vaddr,
634 0 : .align = FD_VM_ALIGN_RUST_U8,
635 0 : .sz = result_header->data_len,
636 0 : .is_slice = 1,
637 0 : };
638 :
639 0 : fd_vm_haddr_query_t accounts_query = {
640 0 : .vaddr = result_accounts_vaddr,
641 0 : .align = FD_VM_RUST_ACCOUNT_META_ALIGN,
642 0 : .sz = fd_ulong_sat_mul( result_header->accounts_len, FD_VM_RUST_ACCOUNT_META_SIZE ),
643 0 : .is_slice = 1,
644 0 : };
645 :
646 0 : fd_vm_haddr_query_t * queries[] = { &program_id_query, &data_query, &accounts_query, &result_header_query };
647 0 : FD_VM_TRANSLATE_MUT( vm, queries );
648 :
649 0 : fd_pubkey_t * program_id = program_id_query.haddr;
650 0 : uchar * data = data_query.haddr;
651 0 : fd_vm_rust_account_meta_t * accounts = accounts_query.haddr;
652 :
653 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1561-L1562 */
654 0 : fd_pubkey_t const * instr_ctx_program_id = NULL;
655 0 : int err = fd_runtime_get_key_of_account_at_index(
656 0 : vm->instr_ctx->txn_out,
657 0 : found_instruction_context->program_id,
658 0 : &instr_ctx_program_id
659 0 : );
660 0 : if( FD_UNLIKELY( err ) ) {
661 0 : FD_VM_ERR_FOR_LOG_INSTR( vm, err );
662 0 : return err;
663 0 : }
664 0 : fd_memcpy( program_id, instr_ctx_program_id, sizeof(fd_pubkey_t) );
665 :
666 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1563 */
667 0 : fd_memcpy( data, found_instruction_context->data, found_instruction_context->data_sz );
668 :
669 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1564-L1581 */
670 0 : for( ushort i=0; i<found_instruction_context->acct_cnt; i++ ) {
671 0 : fd_pubkey_t const * account_key;
672 0 : ushort txn_idx = found_instruction_context->accounts[ i ].index_in_transaction;
673 0 : err = fd_runtime_get_key_of_account_at_index( vm->instr_ctx->txn_out, txn_idx, &account_key );
674 0 : if( FD_UNLIKELY( err ) ) {
675 0 : FD_VM_ERR_FOR_LOG_INSTR( vm, err );
676 0 : return err;
677 0 : }
678 :
679 0 : fd_memcpy( accounts[ i ].pubkey, account_key, sizeof(fd_pubkey_t) );
680 0 : accounts[ i ].is_signer = !!(found_instruction_context->accounts[ i ].is_signer );
681 0 : accounts[ i ].is_writable = !!(found_instruction_context->accounts[ i ].is_writable );
682 0 : }
683 0 : } else {
684 : /* Copy the actual metadata into the result meta struct
685 : https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1584-L1586 */
686 0 : result_header->data_len = found_instruction_context->data_sz;
687 0 : result_header->accounts_len = found_instruction_context->acct_cnt;
688 0 : }
689 :
690 : /* Return true as we found a sibling instruction
691 : https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1588 */
692 0 : *_ret = 1UL;
693 0 : return FD_VM_SUCCESS;
694 0 : }
695 :
696 : /* Return false if we didn't find a sibling instruction
697 : https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1590 */
698 0 : *_ret = 0UL;
699 0 : return FD_VM_SUCCESS;
700 0 : }
701 :
702 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/sysvar.rs#L80 */
703 : int
704 : fd_vm_syscall_sol_get_epoch_rewards_sysvar( /**/ void * _vm,
705 : /**/ ulong out_vaddr,
706 : FD_PARAM_UNUSED ulong r2,
707 : FD_PARAM_UNUSED ulong r3,
708 : FD_PARAM_UNUSED ulong r4,
709 : FD_PARAM_UNUSED ulong r5,
710 0 : /**/ ulong * _ret ) {
711 0 : fd_vm_t * vm = _vm;
712 0 : fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
713 0 : if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
714 :
715 0 : FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_vm_epoch_rewards_t) ) );
716 :
717 : /* See https://github.com/anza-xyz/agave/pull/12130 */
718 0 : if( FD_UNLIKELY( vm->is_deprecated ) ) {
719 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_UNALIGNED_POINTER );
720 0 : return FD_VM_SYSCALL_ERR_UNALIGNED_POINTER;
721 0 : }
722 :
723 0 : if( FD_UNLIKELY( vm->syscall_parameter_address_restrictions && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
724 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
725 0 : return FD_VM_ERR_INVAL;
726 0 : }
727 :
728 0 : uchar * out = FD_VM_MEM_HADDR_ST( vm, out_vaddr, FD_VM_ALIGN_RUST_SYSVAR_EPOCH_REWARDS, sizeof(fd_vm_epoch_rewards_t) );
729 :
730 0 : fd_sysvar_epoch_rewards_t epoch_rewards;
731 0 : if( FD_UNLIKELY( !fd_sysvar_cache_epoch_rewards_read( instr_ctx->sysvar_cache, &epoch_rewards ) ) ) {
732 0 : FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_out, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_out->err.exec_err_idx );
733 0 : return FD_VM_ERR_INVAL;
734 0 : }
735 :
736 0 : fd_vm_epoch_rewards_t * vm_epoch_rewards = (fd_vm_epoch_rewards_t *)out;
737 0 : *vm_epoch_rewards = (fd_vm_epoch_rewards_t){
738 0 : .distribution_starting_block_height = epoch_rewards.distribution_starting_block_height,
739 0 : .num_partitions = epoch_rewards.num_partitions,
740 0 : .parent_blockhash = epoch_rewards.parent_blockhash,
741 0 : .total_points = epoch_rewards.total_points,
742 0 : .total_rewards = epoch_rewards.total_rewards,
743 0 : .distributed_rewards = epoch_rewards.distributed_rewards,
744 0 : .active = epoch_rewards.active,
745 0 : };
746 :
747 0 : *_ret = 0UL;
748 0 : return FD_VM_SUCCESS;
749 0 : }
|