Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_vm_syscall_fd_vm_syscall_h
2 : #define HEADER_fd_src_flamenco_vm_syscall_fd_vm_syscall_h
3 :
4 : #include "../fd_vm_private.h"
5 : #include "fd_vm_syscall_macros.h"
6 : #include "fd_vm_cpi.h" /* FIXME: REFINE THIS MORE */
7 : #include "../../runtime/fd_runtime.h" /* FIXME: REFINE THIS MORE */
8 : #include "../../runtime/context/fd_exec_instr_ctx.h"
9 : #include "../../log_collector/fd_log_collector.h"
10 :
11 : #define FD_VM_RETURN_DATA_MAX (1024UL) /* FIXME: DOCUMENT AND DOES THIS BELONG HERE? */
12 :
13 : /* The maximum number of seeds a PDA can have
14 : https://github.com/solana-labs/solana/blob/2afde1b028ed4593da5b6c735729d8994c4bfac6/sdk/program/src/pubkey.rs#L21 */
15 : #define FD_VM_PDA_SEEDS_MAX (16UL)
16 : /* The maximum length of a PDA seed
17 : https://github.com/solana-labs/solana/blob/2afde1b028ed4593da5b6c735729d8994c4bfac6/sdk/program/src/pubkey.rs#L19 */
18 : #define FD_VM_PDA_SEED_MEM_MAX (32UL)
19 :
20 : /* PYTHON3 CODE FOR COMPUTING THE SYSCALL MURMUR3 HASH (e.g. sol_get_epoch_stake):
21 : ```
22 : import mmh3
23 : import ctypes
24 :
25 : def compute_murmur3_hash(input_string):
26 : # Compute the Murmur3 hash of the input string
27 : hash_value = mmh3.hash(input_string)
28 : # Convert the hash value to a 32-bit unsigned integer
29 : u32_hash_value = ctypes.c_uint32(hash_value).value
30 : return u32_hash_value
31 :
32 : input_string = b"sol_get_epoch_stake"
33 : hash_value = compute_murmur3_hash(input_string)
34 : print(f"The Murmur3 hash of '{input_string}' as u32 is: {hex(hash_value)}")
35 :
36 : Output:
37 : The Murmur3 hash of 'b'sol_get_epoch_stake'' as u32 is: 0x5be92f4a
38 : ```
39 : */
40 :
41 : /* https://github.com/solana-labs/solana/blob/2afde1b028ed4593da5b6c735729d8994c4bfac6/sdk/program/src/pubkey.rs#L22 */
42 :
43 : /* FIXME: CONSIDER NOT PREFIXING SYSCALLS WITH SOL_? (OR MAYBE THIS
44 : IS NECESSARY TO DISAMBIGUATE SOLANA SYSCALLS FROM NON-SOLANA?
45 : SYSCALLS? */
46 :
47 : /* FD_VM_SYSCALL_DECL declares a prototype of a syscall. When a
48 : syscall implementation is called, the syscall will see a precise
49 : reporting VM's state at time of the syscall. Notably:
50 :
51 : - vm->pc will be at the syscall instruction
52 : - vm->ic will include the syscall instruction
53 : - vm->cu will include the 1 cu cost of the syscall instruction.
54 : Further, it will be positive.
55 :
56 : r1,r2,r3,r4,r5 are the values in r1,r2,r3,r4,r5 at time of the
57 : syscall.
58 :
59 : When a syscall implementation returns FD_VM_SUCCESS, *_r0 should hold
60 : the application return error value it wants to place in r0.
61 :
62 : When an syscall implementation returns FD_VM_SYSCALL_ERR*, the
63 : syscall is considered to have faulted the VM. It ideally should not
64 : have set *_r0 (or changed any vm state, except vm->cu, though that
65 : often isn't practical, and not critical to consensus).
66 :
67 : It is the syscall's responsibility to deduct from vm->cu its specific
68 : cost model (not including the syscall instruction itself). As such,
69 : when a syscall returns COMPUTE_BUDGET_EXCEEDED, it should have set
70 : vm->cu to zero. When it returns anything else, it should have set cu
71 : to something in [0,cu_at_function_entry] (upper bound inclusive,
72 : despite most syscalls deducing base CUs first thing, some don't,
73 : e.g., sol_sha256).
74 :
75 : To mitigate risks of from syscall implementations that do not
76 : strictly enforce this and other similar risks that can affect
77 : bookkeeping, on return from a syscall, the VM will:
78 :
79 : - Ignore updates to pc, ic and frame_cnt.
80 : - Ignore updates to cu that increase it.
81 : - Treat updates to cu that zero it as SIGCOST.
82 : - Treat SIGCOST returns that didn't update cu to zero as zeroing it.
83 :
84 : FIXME: ADD NO SETTING OF R0 ON VM_ERR IN VM_INTERP. */
85 :
86 : #define FD_VM_SYSCALL_DECL(name) \
87 : int \
88 : fd_vm_syscall_##name( void * _vm, \
89 : ulong r1, \
90 : ulong r2, \
91 : ulong r3, \
92 : ulong r4, \
93 : ulong r5, \
94 : ulong * _ret )
95 :
96 : FD_PROTOTYPES_BEGIN
97 :
98 : /* fd_vm_syscall_util *************************************************/
99 :
100 : /* syscall(b6fc1a11) "abort"
101 : Abort program execution and fail transaction.
102 :
103 : Inputs:
104 :
105 : r1 - ignored
106 : r2 - ignored
107 : r3 - ignored
108 : r4 - ignored
109 : r5 - ignored
110 :
111 : Return:
112 :
113 : FD_VM_SYSCALL_ERR_ABORT: *_ret unchanged. vm->cu unchanged.
114 :
115 : FIXME: SHOULD THIS BE NAMED "SOL_ABORT"? */
116 :
117 : FD_VM_SYSCALL_DECL( abort );
118 :
119 : /* syscall(686093bb) "sol_panic_"
120 : Log panic message, abort program execution, and fail transaction.
121 :
122 : Inputs:
123 :
124 : r1 - msg, byte VM pointer, indexed [0,msg_sz), msg doesn't have to
125 : be \0 terminated and can contain \0 within,
126 : r2 - msg_sz, may be 0,
127 : r3 - ignored
128 : r4 - ignored
129 : r5 - ignored
130 :
131 : Return:
132 :
133 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
134 : budget. *_ret unchanged. vm->cu==0.
135 :
136 : FD_VM_SYSCALL_ERR_INVALID_STRING: Bad filepath string, msg is not
137 : a valid sequence of utf8 bytes. *_ret unchanged and vm->cu>=0.
138 :
139 : FD_VM_SYSCALL_ERR_PANIC: *_ret unchanged. *_ret unchanged. vm->cu
140 : decremented and vm->cu>=0. */
141 :
142 : FD_VM_SYSCALL_DECL( sol_panic );
143 :
144 : /* syscall(207559bd) "sol_log_"
145 : Write message encoded as (msg, msg_sz) to log, prefixed with
146 : "Program log: ".
147 :
148 : Inputs:
149 :
150 : r1 - msg, byte VM pointer, indexed [0,msg_sz),
151 : r2 - msg_sz, may be 0,
152 : r3 - ignored
153 : r4 - ignored
154 : r5 - ignored
155 :
156 : Return:
157 :
158 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
159 : budget. *_ret unchanged. vm->cu==0.
160 :
161 : FD_VM_SYSCALL_ERR_INVALID_STRING: bad message string. *_ret
162 : unchanged. vm->cu decremented and vm->cu>=0.
163 :
164 : FD_VM_SUCCESS: success. *_ret==0. vm->cu decremented and
165 : vm->cu>=0.
166 :
167 : IMPORTANT SAFETY TIP! The log message will be silently truncated
168 : if there was not enough room for the message in the syscall log
169 : when called. */
170 :
171 : FD_VM_SYSCALL_DECL( sol_log );
172 :
173 : /* syscall(5c2a3178) "sol_log_64_"
174 : Write r1:5 to the log as a hexadecimal
175 :
176 : Inputs:
177 :
178 : r1 - ulong
179 : r2 - ulong
180 : r3 - ulong
181 : r4 - ulong
182 : r5 - ulong
183 :
184 : Return:
185 :
186 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
187 : budget. *_ret unchanged. vm->cu==0.
188 :
189 : FD_VM_SUCCESS: success. *_ret=0. vm->cu decremented and
190 : vm->cu>=0.
191 :
192 : IMPORTANT SAFETY TIP! The log message will be silently truncated
193 : if there was not enough room for the message in the syscall log
194 : when called. */
195 :
196 : FD_VM_SYSCALL_DECL( sol_log_64 );
197 :
198 : /* syscall(7ef088ca) "sol_log_pubkey"
199 : Write the base58 encoding of 32 byte array to the log.
200 :
201 : Inputs:
202 :
203 : r1 - pubkey, byte VM pointer, indexed [0,32)
204 : r2 - ignored
205 : r3 - ignored
206 : r4 - ignored
207 : r5 - ignored
208 :
209 : Return:
210 :
211 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
212 : budget. *_ret unchanged. vm->cu==0.
213 :
214 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range. *_ret unchanged.
215 : vm->cu decremented and vm->cu>=0.
216 :
217 : FD_VM_SUCCESS: success. *_ret==0. vm->cu decremented and
218 : vm->cu>=0.
219 :
220 : IMPORTANT SAFETY TIP! The log message will be silently truncated
221 : if there was not enough room for the message in the syscall log
222 : when called. */
223 :
224 : FD_VM_SYSCALL_DECL( sol_log_pubkey );
225 :
226 : /* syscall(52ba5096) "sol_log_compute_units_"
227 : Write remaining compute unit count to log.
228 :
229 : Inputs:
230 :
231 : r1 - ignored
232 : r2 - ignored
233 : r3 - ignored
234 : r4 - ignored
235 : r5 - ignored
236 :
237 : Return:
238 :
239 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
240 : budget. *_ret unchanged. vm->cu==0.
241 :
242 : FD_VM_SUCCESS: success. *_ret=0. vm->cu decremented
243 : and vm->cu>=0. The value logged will be the value of cu when
244 : between when the syscall completed and the next interation starts
245 : and will be >=0.
246 :
247 : IMPORTANT SAFETY TIP! The log message will be silently truncated
248 : if there was not enough room for the message in the syscall log
249 : when called. */
250 :
251 : FD_VM_SYSCALL_DECL( sol_log_compute_units );
252 :
253 : /* syscall(7317b434) "sol_log_data"
254 : Write the base64 encoded cnt data slices to the log.
255 :
256 : Inputs:
257 :
258 : r1 - slice, ulong pair VM pointer, indexed [0,cnt),
259 : r2 - cnt, may be 0,
260 : r3 - ignored
261 : r4 - ignored
262 : r5 - ignored
263 :
264 : slice[i] holds the ulong pair:
265 : mem, byte VM pointer, indexed [0,sz),
266 : sz, may be 0
267 :
268 : Return:
269 :
270 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute budget.
271 : *_ret unchanged. vm->cu==0.
272 :
273 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range. *_ret unchanged. vm->cu
274 : decremented and vm->cu>0.
275 :
276 : FD_VM_SUCCESS: success. *_ret=0. vm->cu decremented and vm->cu>0.
277 :
278 : IMPORTANT SAFETY TIP! The log message will be silently truncated
279 : if there was not enough room for the message in the syscall log
280 : when called. */
281 :
282 : FD_VM_SYSCALL_DECL( sol_log_data );
283 :
284 : /* syscall(83f00e8f) "sol_alloc_free_"
285 : DEPRECATED ... dynamic heap allocation support
286 :
287 : Inputs:
288 :
289 : r1 - sz, ignored if vaddr is not 0
290 : r2 - free_vaddr, byte VM pointer
291 : r3 - ignored
292 : r4 - ignored
293 : r5 - ignored
294 :
295 : Return:
296 :
297 : All cases return FD_VM_SUCCESS and leave vm->cu unchanged.
298 :
299 : If free_vaddr is 0, this is "malloc"-like:
300 :
301 : Let the VM heap region cover bytes [heap_start,heap_end) with
302 : heap_start<=heap_end. If the request was satisfied, on return,
303 : *_ret will point to a range of heap bytes [*_ret,*_ret+sz) that
304 : does not overlap with any other current allocation such that
305 : heap_start<=*_ret<=*_ret+sz<=heap_end. This includes the zero sz
306 : case (note that the zero sz case might return the same value as a
307 : previous zero sz case and/or return the exact value of heap_end).
308 :
309 : If the request cannot be satisfied, *_ret=0 on return and the
310 : heap unchanged.
311 :
312 : IMPORTANT SAFETY TIP! If the VM has check_align set, this
313 : location will have at least 8 byte alignment. Otherwise, this
314 : location will have no particular alignment. Note that this
315 : implies allocations done by this syscall do not conform to the
316 : usual alignment requirements of a standard malloc call for older
317 : VM code.
318 :
319 : If vaddr is not-zero, this is "free"-like. Since the underlying
320 : implementation is necessarily a bump allocator (see implementation
321 : for more details), the specific value is ignored and *_ret=0 on
322 : return. */
323 :
324 : FD_VM_SYSCALL_DECL( sol_alloc_free );
325 :
326 : /* syscall(717cc4a3) "sol_memcpy_"
327 : Copy sz bytes from src to dst. src and dst should not overlap.
328 :
329 : Inputs:
330 :
331 : r1 - dst, byte VM pointer, indexed [0,sz),
332 : r2 - src, byte VM pointer, indexed [0,sz),
333 : r3 - sz,
334 : r4 - ignored
335 : r5 - ignored
336 :
337 : Return:
338 :
339 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
340 : budget. *_ret unchanged. vm->cu==0.
341 :
342 : FD_VM_SYSCALL_ERR_COPY_OVERLAPPING: address ranges for src and dst
343 : overlap (either partially or fully). Empty address ranges are
344 : considered to **never** overlap. *_ret==0. vm->cu decremented and
345 : vm->cu>=0.
346 :
347 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range. *_ret==0. vm->cu
348 : decremented and vm->cu>=0.
349 :
350 : FD_VM_SUCCESS: success. *_ret==0. vm->cu decremented and
351 : vm->cu>=0. On return, dst[i]==src[i] for i in [0,sz). */
352 :
353 : FD_VM_SYSCALL_DECL( sol_memcpy );
354 :
355 : /* syscall(5fdcde31) "sol_memcmp_"
356 : Compare sz bytes at m0 to m1
357 :
358 : Inputs:
359 :
360 : r1 - m0, byte VM pointer, indexed [0,sz), FIXME: WHEN IS NULL OKAY?
361 : r2 - m1, byte VM pointer, indexed [0,sz), FIXME: WHEN IS NULL OKAY?
362 : r3 - sz, FIXME: IS SZ 0 OKAY?
363 : r4 - out, int VM pointer
364 : r5 - ignored
365 :
366 : Return:
367 :
368 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute budget.
369 : *_ret unchanged. vm->cu==0.
370 :
371 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range (including out not 4 byte
372 : aligned). *_ret unchanged. vm->cu decremented and vm->cu>0.
373 : Strict alignment is only required when the VM has check_align set.
374 :
375 : FD_VM_SUCCESS: success. *_ret=0. vm->cu decremented and vm->cu>0.
376 : On return, *_out will hold a positive / zero / negative number if
377 : the region at m0 lexicographically compares strictly greater than /
378 : equal to / strictly less than the region at m1 when treated as
379 : uchars. Specifically, if the regions are different, *_out will be
380 : (int)m0[i] - (int)m1[i] where i is the first differing byte.
381 :
382 : IMPORANT SAFETY TIP! Note that, strangely, this returns the result
383 : in memory instead via *_ret like a libc-style memcmp would. */
384 :
385 : FD_VM_SYSCALL_DECL( sol_memcmp );
386 :
387 : /* syscall(3770fb22) "sol_memset_"
388 : Set sz bytes at dst to the byte value c.
389 :
390 : Inputs:
391 :
392 : r1 - dst, byte VM pointer, indexed [0,sz), FIXME: WHEN IS NULL OKAY?
393 : r2 - c, bits [8,64) ignored (FIXME: CHECK SOLANA DOES THIS)
394 : r3 - sz, may be 0,
395 : r4 - ignored
396 : r5 - ignored
397 :
398 : Return:
399 :
400 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute budget.
401 : *_ret unchanged. vm->cu==0.
402 :
403 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range. *_ret unchanged. vm->cu
404 : decremented and vm->cu>0.
405 :
406 : FD_VM_SUCCESS: success. *_ret=0. vm->cu decremented and vm->cu>0.
407 : On return, dst[i]==(uchar)(c & 255UL) for i in [0,sz). */
408 :
409 : FD_VM_SYSCALL_DECL( sol_memset );
410 :
411 : /* syscall(434371f8) "sol_memmove_"
412 : Copy sz bytes from src to dst. src and dst can overlap.
413 :
414 : Inputs:
415 :
416 : r1 - dst, byte VM pointer, indexed [0,sz),
417 : r2 - src, byte VM pointer, indexed [0,sz),
418 : r3 - sz, may be 0,
419 : r4 - ignored
420 : r5 - ignored
421 :
422 : Return:
423 :
424 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute budget.
425 : *_ret unchanged. vm->cu==0.
426 :
427 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range. *_ret unchanged. vm->cu
428 : decremented and vm->cu>0.
429 :
430 : FD_VM_SUCCESS: success. *_ret=0. vm->cu decremented and vm->cu>0.
431 : On return, dst[i]==src_as_it_was_before_the_call[i] for i in
432 : [0,sz). */
433 :
434 : FD_VM_SYSCALL_DECL( sol_memmove );
435 :
436 : /* fd_vm_syscall_runtime **********************************************/
437 :
438 : /* syscall(d56b5fe9) "sol_get_clock_sysvar"
439 : syscall(23a29a61) "sol_get_epoch_schedule_sysvar"
440 : syscall(bf7188f6) "sol_get_rent_sysvar"
441 : syscall(77f9b9d0) "sol_get_last_restart_slot_sysvar"
442 : Get various sysvar values
443 :
444 : Inputs:
445 :
446 : r1 - out, {clock,schedule,fees,rent,last_restart_slot} VM pointer
447 : r2 - ignored
448 : r3 - ignored
449 : r4 - ignored
450 : r5 - ignored
451 :
452 : Return:
453 :
454 : FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME: the VM is not running within the
455 : Solana runtime. *_ret unchanged. vm->cu unchanged.
456 :
457 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
458 : budget. *_ret unchanged. vm->cu==0.
459 :
460 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range. *_ret unchanged.
461 : vm->cu decremented and vm->cu>=0. out should have:
462 : | align | sz
463 : clock | 8 | 40
464 : schedule | 8 | 40
465 : rent | 8 | 24
466 : last restart slot | 8 | 8
467 : Strict alignment is only required when the VM has check_align set.
468 :
469 : FD_VM_SUCCESS: success. *_ret=0. vm->cu decremented and vm->cu>0.
470 : On return, *out will hold the value of the appropriate sysvar. */
471 :
472 : FD_VM_SYSCALL_DECL( sol_get_clock_sysvar );
473 : FD_VM_SYSCALL_DECL( sol_get_epoch_schedule_sysvar );
474 : FD_VM_SYSCALL_DECL( sol_get_rent_sysvar );
475 : FD_VM_SYSCALL_DECL( sol_get_last_restart_slot_sysvar );
476 : FD_VM_SYSCALL_DECL( sol_get_epoch_rewards_sysvar );
477 :
478 : /* syscall(13c1b505) "sol_get_sysvar"
479 :
480 : Get a slice of a sysvar account's data.
481 :
482 : Inputs:
483 :
484 : r1 - sysvar_id_vaddr, sysvar pubkey VM pointer
485 : r2 - out_vaddr, byte VM pointer
486 : r3 - offset, ulong
487 : r4 - sz, num bytes to store
488 : r5 - ignored
489 :
490 : Return:
491 :
492 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
493 : budget. *_ret unchanged. vm->cu==0.
494 :
495 : FD_VM_SYSCALL_ERR_SEGFAULT: bad sysvar_id_vaddr, bad out_vaddr,
496 : requested slice outside of sysvar data buffer. _ret unchanged.
497 : vm->cu decremented and vm->cu>=0.
498 :
499 : FD_VM_SYSCALL_ERR_ABORT: offset+sz overflow. *_ret unchanged.
500 : vm->cu decremented and vm->cu>=0.
501 :
502 : FD_VM_SUCCESS: success. vm->cu decremented and vm->cu>=0.
503 : - *_ret = 2 if sysvar id is not in {clock,schedule,rewards,rent,
504 : slot hashes,stake history, last restart slot}
505 : OR sysvar account does not exist.
506 : - *_ret = 1 if [offset,offset+sz) is outside of sysvar data
507 : buffer.
508 : - *_ret = 0 if success.
509 :
510 : On return, sz bytes of appropriate offset sysvar data will be
511 : copied into haddr belonging to out_vaddr. */
512 : FD_VM_SYSCALL_DECL( sol_get_sysvar );
513 :
514 : /* syscall(5be92f4a) "sol_get_epoch_stake"
515 :
516 : This syscall is meant to return the latest frozen stakes at an epoch
517 : boundary. So for instance, when we are executing in epoch 7, this
518 : should return the stakes at the end of epoch 6. Note that this is
519 : also the stakes that determined the leader schedule for the upcoming
520 : epoch, namely epoch 8.
521 :
522 : Inputs:
523 :
524 : r1 - var_addr, vote pubkey VM pointer, or zero to get the total
525 : active stake on the cluster.
526 : r2 - ignored
527 : r3 - ignored
528 : r4 - ignored
529 : r5 - ignored
530 :
531 : Return:
532 :
533 : FD_VM_ERR_SIGCOST: insufficient compute budget. *_ret unchanged.
534 : vm->cu==0.
535 :
536 : FD_VM_ERR_SIGSEGV: bad var_addr. _ret unchanged. vm->cu
537 : decremented and vm->cu>=0.
538 :
539 : FD_VM_ERR_ABORT: offset+sz overflow. *_ret unchanged.
540 :
541 : FD_VM_SUCCESS: success. vm->cu decremented and vm->cu>=0.
542 : If var_addr == 0, *_ret is the total active stake on the
543 : cluster. Else, it is the vote account's delegated stake if
544 : var_addr is an existing vote account, and 0 otherwise. */
545 :
546 : FD_VM_SYSCALL_DECL( sol_get_epoch_stake );
547 :
548 : /* syscall(85532d94) "sol_get_stack_height"
549 :
550 : Inputs:
551 :
552 : r1 - ignored
553 : r2 - ignored
554 : r3 - ignored
555 : r4 - ignored
556 : r5 - ignored
557 :
558 : Return:
559 :
560 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
561 : budget. *_ret unchanged. vm->cu==0.
562 :
563 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range. *_ret unchanged.
564 : vm->cu decremented and vm->cu>=0.
565 :
566 : FD_VM_SUCCESS: success. *_ret==stack_height. vm->cu decremented
567 : and vm->cu>=0. */
568 :
569 : FD_VM_SYSCALL_DECL( sol_get_stack_height );
570 :
571 : /* syscall(5d2245e4) "sol_get_return_data"
572 : Get the return data and program id associated with it.
573 :
574 : Inputs:
575 :
576 : r1 - dst, byte VM pointer, indexed [0,dst_max),
577 : r2 - dst_max, may be 0,
578 : r3 - program_id, byte VM pointer, indexed [0,32)
579 : r4 - ignored
580 : r5 - ignored
581 :
582 : Return:
583 :
584 : FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME: the VM is not running within
585 : the Solana runtime. *_ret unchanged. vm->cu unchanged.
586 :
587 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
588 : budget. *_ret unchanged. vm->cu==0.
589 :
590 : FD_VM_SYSCALL_ERR_COPY_OVERLAPPING: dst and program_id address
591 : ranges overlap. *_ret unchanged. vm->cu decremented and
592 : vm->cu>=0.
593 :
594 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range for dst and/or
595 : program_id. *_ret unchanged. Compute budget decremented.
596 :
597 : FD_VM_SUCCESS: success. *_ret=return_data_sz. vm->cu decremented
598 : and vm->cu>=0. On return, if dst_max was non-zero, dst holds the
599 : leading min(return_data_sz,dst_max) bytes of return data (as such,
600 : if return_data_sz>dst_max, the value returned in the buffer was
601 : truncated). Any trailing bytes of dst are unchanged. program_id
602 : holds the program_id associated with the return data.
603 :
604 : If dst_max was zero, dst and program_id are untouched. */
605 :
606 : FD_VM_SYSCALL_DECL( sol_get_return_data );
607 :
608 : /* syscall(a226d3eb) "sol_set_return_data"
609 : Set the return data. The return data will be associated with the
610 : caller's program ID.
611 :
612 : Inputs:
613 :
614 : r1 - src, byte VM pointer, indexed [0,src_sz),
615 : r2 - src_sz, may be 0,
616 : r3 - ignored
617 : r4 - ignored
618 : r5 - ignored
619 :
620 : Return:
621 : FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME: the VM is not running within the
622 : Solana runtime. *_ret unchanged. vm->cu unchanged.
623 :
624 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
625 : budget. *_ret unchanged. vm->cu==0.
626 :
627 : FD_VM_SYSCALL_ERR_RETURN_DATA_TOO_LARGE: src_sz too large. *_ret
628 : unchanged. vm->cu decremented and vm->cu>0.
629 :
630 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range for src. *_ret unchanged.
631 : vm->cu decremented and vm->cu>=0.
632 :
633 : FD_VM_SUCCESS: success. *_ret=0. vm->cu decremented and vm->cu>0. */
634 :
635 : FD_VM_SYSCALL_DECL( sol_set_return_data );
636 :
637 : /* syscall(adb8efc8) "sol_get_processed_sibling_instruction"
638 : Returns the last element from a reverse-ordered list of successfully
639 : processed sibling instructions: the "processed sibling instruction
640 : list".
641 :
642 : For example, given the call flow:
643 : A
644 : B -> C -> D
645 : B -> E
646 : B -> F (current execution point)
647 :
648 : B's processed sibling instruction list is [A]
649 : F's processed sibling instruction list is [E, C]
650 :
651 : This allows the current instruction to know what the last processed
652 : sibling instruction was. This is useful to check that critical
653 : preceding instructions have actually executed: for example, ensuring
654 : that an assert instruction has successfully executed.
655 :
656 : Inputs:
657 :
658 : r1 - index
659 : r2 - result_meta_vaddr, byte VM pointer of the object where
660 : metadata about the last processed sibling instruction will be
661 : stored upon successful execution (the length of the arrays in
662 : the result). Has the type
663 : solana_program::instruction::ProcessedSiblingInstruction
664 : https://github.com/anza-xyz/agave/blob/70089cce5119c9afaeb2986e2ecaa6d4505ec15d/sdk/program/src/instruction.rs#L672-L681
665 : r3 - result_program_id_vaddr, byte VM pointer where the pubkey of
666 : the program ID of the last processed sibling instruction will
667 : be stored upon successful execution
668 : r4 - result_data_vaddr, byte VM pointer where the instruction
669 : data of the last processed sibling instruction will be stored
670 : upon successful execution. The length of the data will be
671 : stored in ProcessedSiblingInstruction.data_len
672 : r5 - result_accounts_vaddr, byte VM pointer where an array of
673 : account meta structures will be stored into upon successful
674 : execution. The length of the data will be stored in
675 : ProcessedSiblingInstruction.accounts_len. Each account meta
676 : has the type solana_program::instruction::AccountMeta
677 : https://github.com/anza-xyz/agave/blob/70089cce5119c9afaeb2986e2ecaa6d4505ec15d/sdk/program/src/instruction.rs#L525-L548
678 :
679 : Return:
680 :
681 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
682 : budget. *_ret unchanged. vm->cu==0.
683 :
684 : FD_VM_SUCCESS: *_ret==1 if the instruction was found and, *_ret==0
685 : otherwise. vm->cu decremented and vm->cu>=0. */
686 :
687 :
688 : FD_VM_SYSCALL_DECL( sol_get_processed_sibling_instruction );
689 :
690 : /* fd_vm_syscall_pda **************************************************/
691 :
692 : /* syscall(9377323c) "sol_create_program_address"
693 :
694 : Compute SHA-256 hash of <program ID> .. &[&[u8]] .. <PDA Marker>
695 : and check whether result is an Ed25519 curve point.
696 :
697 : Inputs:
698 :
699 : r1 - seeds, bytes VM pointer, indexed [0,seed_cnt),
700 : r2 - seed_cnt, may be 0,
701 : r3 - program_id, byte VM pointer, indexed [0,32), FD_PUBKEY_ALIGN
702 : aligned
703 : r4 - out, byte VM pointer, indexed [0,32), FD_PUBKEY_ALIGN aligned
704 : r5 - ignored
705 :
706 : seed[i] holds the ulong pair
707 : mem, byte VM pointer, indexed [0,sz),
708 : sz, may be 0
709 :
710 : Return:
711 :
712 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
713 : budget. *_ret unchanged. vm->cu==0.
714 :
715 : FD_VM_SYSCALL_ERR_BAD_SEEDS: seed_cnt and/or seed[i].sz too large,
716 : bad address range for program_id, seed,
717 : seed[i].mem and/or out (including 8-byte alignment for seed if the
718 : VM has check_align set). *_ret unchanged. Compute budget
719 : decremented.
720 :
721 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range. *_ret unchanged.
722 : vm->cu decremented and vm->cu>=0.
723 :
724 : FD_VM_SUCCESS: success. If *_ret==0, a PDA was created and
725 : stored at out. If *_ret==1, create failed and out was unchanged.
726 : Compute budget decremented. */
727 :
728 : FD_VM_SYSCALL_DECL( sol_create_program_address );
729 :
730 : /* syscall(48504a38) "sol_try_find_program_address"
731 :
732 : Repeatedly derive program address while incrementing nonce in seed
733 : list until a point is found that is not a valid Ed25519 curve point.
734 :
735 : Inputs:
736 :
737 : r1 - seed, ulong pair VM pointer, indexed [0,seed_cnt),
738 : r2 - seed_cnt, may be 0,
739 : r3 - program_id, byte VM pointer, indexed [0,32), FD_PUBKEY_ALIGN
740 : aligned
741 : r4 - out, byte VM pointer, indexed [0,32), FD_PUBKEY_ALIGN aligned
742 : r5 - bump_seed, byte VM pointer, indexed [0,1)
743 :
744 : seed[i] holds the ulong pair
745 : mem, byte VM pointer, indexed [0,sz),
746 : sz, may be 0
747 :
748 : Return:
749 :
750 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute
751 : budget. *_ret unchanged. vm->cu==0.
752 :
753 : FD_VM_SYSCALL_ERR_BAD_SEEDS: seed_cnt and/or seed[i].sz too large,
754 : bad address range for program_id, seed,
755 : seed[i].mem, out and/or bump_seed (including 8-byte alignment for
756 : seed if the VM has check_align set). *_ret unchanged. Compute
757 : budget decremented.
758 :
759 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range. *_ret unchanged.
760 : vm->cu decremented and vm->cu>=0.
761 :
762 : FD_VM_SUCCESS: success. If *_ret==0, a PDA was found and stored at
763 : out and the suffix stored at bump_seed. If *_ret==1, no PDA was
764 : found and out and bump_seed were unchanged. Compute budget
765 : decremented. */
766 :
767 : FD_VM_SYSCALL_DECL( sol_try_find_program_address );
768 :
769 : /* fd_vm_syscall_cpi **************************************************/
770 :
771 : /* Prepare instruction method */
772 : /* FIXME: DOES THIS GO HERE? MAYBE GROUP WITH ADMIN OR OUTSIDE SYSCALL? */
773 :
774 : int
775 : fd_vm_prepare_instruction( fd_instr_info_t * callee_instr,
776 : fd_exec_instr_ctx_t * instr_ctx,
777 : fd_pubkey_t const * callee_program_id_pubkey,
778 : fd_pubkey_t const instr_acct_keys[ FD_INSTR_ACCT_MAX ],
779 : fd_instruction_account_t instruction_accounts[ FD_INSTR_ACCT_MAX ],
780 : ulong * instruction_accounts_cnt,
781 : fd_pubkey_t const * signers,
782 : ulong signers_cnt );
783 :
784 : /* syscall(a22b9c85) "sol_invoke_signed_c"
785 : Dispatch a cross program invocation. Inputs are in C ABI.
786 :
787 : FIXME: BELT SAND AND DOCUMENT */
788 :
789 : FD_VM_SYSCALL_DECL( cpi_c );
790 :
791 : /* syscall(d7449092) "sol_invoke_signed_rust"
792 : Dispatch a cross program invocation. Inputs are in Rust ABI.
793 :
794 : FIXME: BELT SAND AND DOCUMENT */
795 :
796 : FD_VM_SYSCALL_DECL( cpi_rust );
797 :
798 : /* fd_vm_syscall_crypto ***********************************************/
799 :
800 : /* FD_VM_SYSCALL_SOL_ALT_BN128_{ADD,SUB,MUL,PAIRING} specifies the curve operation. */
801 :
802 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_ADD ( 0UL) /* add */
803 : #define FD_VM_SYSCALL_SOL_ALT_BN128_SUB ( 1UL) /* add inverse */
804 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_MUL ( 2UL) /* scalar mult */
805 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_PAIRING ( 3UL) /* pairing */
806 :
807 : /* FD_VM_SYSCALL_SOL_ALT_BN128_{...}COMPRESS specifies the (de)compress operation. */
808 :
809 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_G1_COMPRESS ( 0UL) /* compress point in G1 */
810 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_G1_DECOMPRESS ( 1UL) /* decompress point in G1 */
811 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_G2_COMPRESS ( 2UL) /* compress point in G2 */
812 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_G2_DECOMPRESS ( 3UL) /* decompress point in G2 */
813 :
814 : /* FD_VM_SYSCALL_SOL_ALT_BN128_{...}_SZ specifies the size of inputs/outputs for the Alt_BN128 curve. */
815 :
816 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_G1_SZ ( 64UL) /* size of a point in G1 */
817 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_G1_COMPRESSED_SZ ( 32UL) /* size of a compressed point in G2 */
818 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_G2_SZ (128UL) /* size of a point in G2 */
819 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_G2_COMPRESSED_SZ ( 64UL) /* size of a compressed point in G2 */
820 : #define FD_VM_SYSCALL_SOL_ALT_BN128_SCALAR_SZ ( 32UL) /* size of a scalar */
821 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_PAIRING_INPUT_EL_SZ (192UL) /* size of G1 + G2 */
822 0 : #define FD_VM_SYSCALL_SOL_ALT_BN128_PAIRING_OUTPUT_SZ ( 32UL) /* size of pairing syscall result, i.e. 0 or 1 as 256-bit int ¯\_(ツ)_/¯ */
823 :
824 : /* syscall(ae0c318b) sol_alt_bn128_group_op computes operations on the Alt_BN128 curve,
825 : including point addition in G1, scalar multiplication in G1, and pairing.
826 : See SIMD-0129.
827 :
828 : FIXME: DOCUMENT */
829 :
830 : FD_VM_SYSCALL_DECL( sol_alt_bn128_group_op );
831 :
832 : /* syscall(334fd5ed) sol_alt_bn128_compression allows to compress or decompress points
833 : in G1 or G2 groups over the Alt_BN128 curve.
834 : See SIMD-0129.
835 :
836 : FIXME: DOCUMENT */
837 :
838 : FD_VM_SYSCALL_DECL( sol_alt_bn128_compression );
839 :
840 : /* syscall(174c5122) "sol_blake3"
841 : syscall(d7793abb) "sol_keccak256"
842 : syscall(11f49d86) "sol_sha256"
843 :
844 : Inputs:
845 :
846 : arg0 - slice, ulong pair VM pointer, indexed [0,cnt), FIXME: WHEN IS NULL OKAY?
847 : arg1 - cnt, FIXME: IS 0 OKAY?
848 : arg2 - hash, byte VM pointer, indexed [0,32)
849 : arg3 - ignored
850 : arg4 - ignored
851 :
852 : slice[i] holds the ulong pair:
853 : mem, byte vector VM pointer, indexed [0,sz), FIXME: WHEN IS NULL OKAY?
854 : sz, FIXME: IS 0 OKAY?
855 :
856 : Return:
857 :
858 : FD_VM_ERR_INVAL: cnt too large. *_ret unchanged.
859 :
860 : FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED: insufficient compute budget.
861 : *_ret unchanged. Compute budget decremented.
862 :
863 : FD_VM_SYSCALL_ERR_SEGFAULT: bad address range for slice, hash and/or
864 : slice[i].addr (including slice not 8 byte aligned if the VM has
865 : check_align set). *_ret unchanged. Compute budget decremented.
866 :
867 : FD_VM_SUCCESS: success. *_ret=0 and hash[i] holds the hash of the
868 : concatentation of the slices. Compute budget decremented. */
869 :
870 : FD_VM_SYSCALL_DECL( sol_blake3 );
871 : FD_VM_SYSCALL_DECL( sol_keccak256 );
872 : FD_VM_SYSCALL_DECL( sol_sha256 );
873 :
874 : /* syscall(c4947c21) sol_poseidon computes the Poseidon hash on an array of input values.
875 : See SIMD-0129.
876 :
877 : FIXME: DOCUMENT */
878 :
879 : #define FD_VM_SYSCALL_SOL_POSEIDON_MAX_VALS 12UL
880 :
881 : FD_VM_SYSCALL_DECL( sol_poseidon ); /* Light protocol flavor */
882 :
883 : /* syscall(17e40350) "sol_secp256k1_recover"
884 :
885 : FIXME: BELT SAND AND DOCUMENT */
886 :
887 : FD_VM_SYSCALL_DECL( sol_secp256k1_recover );
888 :
889 : /* fd_vm_syscall_curve ************************************************/
890 :
891 : /* FD_VM_SYSCALL_SOL_CURVE_CURVE25519_{...} specifies the curve ID */
892 :
893 9 : #define FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS ( 0UL) /* ed25519 */
894 18 : #define FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO ( 1UL) /* ristretto255 */
895 :
896 : /* FD_VM_SYSCALL_SOL_CURVE_{...} specifies the curve operation */
897 :
898 6 : #define FD_VM_SYSCALL_SOL_CURVE_ADD ( 0UL) /* add */
899 3 : #define FD_VM_SYSCALL_SOL_CURVE_SUB ( 1UL) /* add inverse */
900 3 : #define FD_VM_SYSCALL_SOL_CURVE_MUL ( 2UL) /* scalar mul */
901 :
902 : /* FD_VM_SYSCALL_SOL_CURVE_CURVE25519_{...}_SZ specifies the size of inputs/outputs. */
903 :
904 24 : #define FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ (32UL) /* point (compressed) */
905 6 : #define FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ (32UL) /* scalar */
906 :
907 : /* syscall(aa2607ca) sol_curve_validate_point
908 :
909 : FIXME: BELT SAND AND DOCUMENT */
910 :
911 : FD_VM_SYSCALL_DECL( sol_curve_validate_point );
912 :
913 : /* syscall(dd1c41a6) sol_curve_validate_point
914 :
915 : FIXME: BELT SAND AND DOCUMENT */
916 :
917 : FD_VM_SYSCALL_DECL( sol_curve_group_op );
918 :
919 : /* syscall(60a40880) sol_curve_validate_point
920 :
921 : FIXME: BELT SAND AND DOCUMENT */
922 :
923 : FD_VM_SYSCALL_DECL( sol_curve_multiscalar_mul );
924 :
925 : int
926 : fd_vm_derive_pda( fd_vm_t * vm,
927 : fd_pubkey_t const * program_id,
928 : void const * * seed_haddrs,
929 : ulong * seed_szs,
930 : ulong seeds_cnt,
931 : uchar * bump_seed,
932 : fd_pubkey_t * out );
933 :
934 : int
935 : fd_vm_translate_and_check_program_address_inputs( fd_vm_t * vm,
936 : ulong seeds_vaddr,
937 : ulong seeds_cnt,
938 : ulong program_id_vaddr,
939 : void const * * out_seed_haddrs,
940 : ulong * out_seed_szs,
941 : fd_pubkey_t const * * out_program_id,
942 : uchar is_syscall );
943 : FD_PROTOTYPES_END
944 :
945 : #endif /* HEADER_src_flamenco_vm_syscall_fd_vm_syscall_h */
|