Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_vm_fd_vm_base_h
2 : #define HEADER_fd_src_flamenco_vm_fd_vm_base_h
3 :
4 : /* FIXME: Headers included from other modules need cleanup. As it
5 : stands, flamenco_base brings in types/custom, types/meta,
6 : types/bincode, ballet/base58, ballet/sha256, ballet/sha512,
7 : ballet/ed25519, ballet/txnthis also brings in util, flamenco_base,
8 : ballet/base58, util and the optional util/net/ipv4 ballet/sha256,
9 : most of which is probably not necessary to use this module in a
10 : somewhat haphazard fashion (include no-no things that are only
11 : available in hosted environments like stdio and stdlib) */
12 :
13 : #include "../fd_flamenco_base.h"
14 : #include "../../ballet/sbpf/fd_sbpf_loader.h" /* FIXME: functionality needed from here probably should be moved here */
15 : #include "../features/fd_features.h"
16 :
17 : /* Defines the different VM access types */
18 431 : #define FD_VM_ACCESS_TYPE_LD (1)
19 345 : #define FD_VM_ACCESS_TYPE_ST (2)
20 :
21 : /* FD_VM_SUCCESS is zero and returned to indicate that an operation
22 : completed successfully. FD_VM_ERR_* are negative integers and
23 : returned to indicate an operation that failed and why. */
24 :
25 : /* "Standard" Firedancer error codes (FIXME: harmonize and consolidate) */
26 :
27 849216 : #define FD_VM_SUCCESS ( 0) /* success */
28 77 : #define FD_VM_ERR_INVAL (-1) /* invalid request */
29 0 : #define FD_VM_ERR_UNSUP (-3) /* unsupported request */
30 0 : #define FD_VM_ERR_FULL (-5) /* storage full */
31 0 : #define FD_VM_ERR_EMPTY (-6) /* nothing to do */
32 0 : #define FD_VM_ERR_IO (-7) /* input-output error */
33 :
34 : /* VM exec error codes: These are only produced by the VM itself. */
35 :
36 0 : #define FD_VM_ERR_SIGFPE (-18) /* divide by zero */
37 :
38 : /* sBPF validation error codes. These are only produced by
39 : fd_vm_validate. FIXME: Consider having fd_vm_validate return
40 : standard error codes and then provide detail like this through an
41 : info arg. FIXME: Are these exact matches to Solana? If so, provide
42 : link, if not, document and refine name / consolidate further. */
43 :
44 16 : #define FD_VM_ERR_INVALID_OPCODE (-25) /* detected an invalid opcode */
45 0 : #define FD_VM_ERR_INVALID_SRC_REG (-26) /* detected an invalid source register */
46 0 : #define FD_VM_ERR_INVALID_DST_REG (-27) /* detected an invalid destination register */
47 0 : #define FD_VM_ERR_JMP_OUT_OF_BOUNDS (-29) /* detected an out of bounds jump */
48 6 : #define FD_VM_ERR_JMP_TO_ADDL_IMM (-30) /* detected a jump to an addl imm */
49 0 : #define FD_VM_ERR_INVALID_END_IMM (-31) /* detected an invalid immediate for an endianness conversion instruction */
50 0 : #define FD_VM_ERR_INCOMPLETE_LDQ (-32) /* detected an incomplete ldq at program end */
51 0 : #define FD_VM_ERR_LDQ_NO_ADDL_IMM (-33) /* detected a ldq without an addl imm following it */
52 0 : #define FD_VM_ERR_INVALID_REG (-35) /* detected an invalid register */
53 0 : #define FD_VM_ERR_BAD_TEXT (-36) /* detected a bad text section (overflow, outside rodata boundary, etc.,)*/
54 0 : #define FD_VM_SH_OVERFLOW (-37) /* detected a shift overflow, equivalent to VeriferError::ShiftWithOverflow */
55 1 : #define FD_VM_TEXT_SZ_UNALIGNED (-38) /* detected a text section that is not a multiple of 8 */
56 :
57 : /* Syscall Errors
58 : https://github.com/anza-xyz/agave/blob/v2.0.7/programs/bpf_loader/src/syscalls/mod.rs#L81 */
59 :
60 3 : #define FD_VM_SYSCALL_ERR_INVALID_STRING (-1)
61 33 : #define FD_VM_SYSCALL_ERR_ABORT (-2)
62 18 : #define FD_VM_SYSCALL_ERR_PANIC (-3)
63 0 : #define FD_VM_SYSCALL_ERR_INVOKE_CONTEXT_BORROW_FAILED (-4)
64 0 : #define FD_VM_SYSCALL_ERR_MALFORMED_SIGNER_SEED (-5)
65 80 : #define FD_VM_SYSCALL_ERR_BAD_SEEDS (-6)
66 57 : #define FD_VM_SYSCALL_ERR_PROGRAM_NOT_SUPPORTED (-7)
67 286 : #define FD_VM_SYSCALL_ERR_UNALIGNED_POINTER (-8)
68 8 : #define FD_VM_SYSCALL_ERR_TOO_MANY_SIGNERS (-9)
69 0 : #define FD_VM_SYSCALL_ERR_INSTRUCTION_TOO_LARGE (-10)
70 0 : #define FD_VM_SYSCALL_ERR_TOO_MANY_ACCOUNTS (-11)
71 9 : #define FD_VM_SYSCALL_ERR_COPY_OVERLAPPING (-12)
72 0 : #define FD_VM_SYSCALL_ERR_RETURN_DATA_TOO_LARGE (-13)
73 2 : #define FD_VM_SYSCALL_ERR_TOO_MANY_SLICES (-14)
74 19 : #define FD_VM_SYSCALL_ERR_INVALID_LENGTH (-15)
75 0 : #define FD_VM_SYSCALL_ERR_MAX_INSTRUCTION_DATA_LEN_EXCEEDED (-16)
76 0 : #define FD_VM_SYSCALL_ERR_MAX_INSTRUCTION_ACCOUNTS_EXCEEDED (-17)
77 0 : #define FD_VM_SYSCALL_ERR_MAX_INSTRUCTION_ACCOUNT_INFOS_EXCEEDED (-18)
78 23 : #define FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE (-19)
79 125 : #define FD_VM_SYSCALL_ERR_INVALID_POINTER (-20)
80 0 : #define FD_VM_SYSCALL_ERR_ARITHMETIC_OVERFLOW (-21)
81 :
82 : /* These syscall errors are unique to Firedancer and do not have an Agave equivalent. */
83 0 : #define FD_VM_SYSCALL_ERR_INSTR_ERR (-22)
84 1409 : #define FD_VM_SYSCALL_ERR_INVALID_PDA (-23) /* the computed pda was not a valid ed25519 point */
85 1050 : #define FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED (-24) /* compute unit limit exceeded in syscall */
86 597 : #define FD_VM_SYSCALL_ERR_SEGFAULT (-25) /* illegal memory address (e.g. read/write to an address not backed by any memory) in syscall */
87 0 : #define FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME (-26) /* syscall called with vm not running in solana runtime */
88 :
89 : /* Poseidon returns custom errors for some reason */
90 2 : #define FD_VM_SYSCALL_ERR_POSEIDON_INVALID_PARAMS (1)
91 3 : #define FD_VM_SYSCALL_ERR_POSEIDON_INVALID_ENDIANNESS (2)
92 :
93 : /* EbpfError
94 : https://github.com/anza-xyz/sbpf/blob/main/src/error.rs#L20-L78 */
95 :
96 0 : #define FD_VM_ERR_EBPF_ELF_ERROR (-1)
97 0 : #define FD_VM_ERR_EBPF_FUNCTION_ALREADY_REGISTERED (-2)
98 1 : #define FD_VM_ERR_EBPF_CALL_DEPTH_EXCEEDED (-3)
99 0 : #define FD_VM_ERR_EBPF_EXIT_ROOT_CALL_FRAME (-4)
100 1245 : #define FD_VM_ERR_EBPF_DIVIDE_BY_ZERO (-5)
101 0 : #define FD_VM_ERR_EBPF_DIVIDE_OVERFLOW (-6)
102 1 : #define FD_VM_ERR_EBPF_EXECUTION_OVERRUN (-7)
103 56 : #define FD_VM_ERR_EBPF_CALL_OUTSIDE_TEXT_SEGMENT (-8)
104 32 : #define FD_VM_ERR_EBPF_EXCEEDED_MAX_INSTRUCTIONS (-9)
105 0 : #define FD_VM_ERR_EBPF_JIT_NOT_COMPILED (-10)
106 0 : #define FD_VM_ERR_EBPF_INVALID_MEMORY_REGION (-11)
107 730 : #define FD_VM_ERR_EBPF_ACCESS_VIOLATION (-12)
108 39 : #define FD_VM_ERR_EBPF_STACK_ACCESS_VIOLATION (-13)
109 0 : #define FD_VM_ERR_EBPF_INVALID_INSTRUCTION (-14)
110 124 : #define FD_VM_ERR_EBPF_UNSUPPORTED_INSTRUCTION (-15)
111 0 : #define FD_VM_ERR_EBPF_EXHAUSTED_TEXT_SEGMENT (-16)
112 0 : #define FD_VM_ERR_EBPF_LIBC_INVOCATION_FAILED (-17)
113 0 : #define FD_VM_ERR_EBPF_VERIFIER_ERROR (-18)
114 2651 : #define FD_VM_ERR_EBPF_SYSCALL_ERROR (-19)
115 :
116 :
117 : FD_PROTOTYPES_BEGIN
118 :
119 : /* fd_vm_strerror converts an FD_VM_SUCCESS / FD_VM_ERR_* code into
120 : a human readable cstr. The lifetime of the returned pointer is
121 : infinite. The returned pointer is always to a non-NULL cstr. */
122 :
123 : FD_FN_CONST char const * fd_vm_strerror( int err );
124 :
125 : FD_PROTOTYPES_END
126 :
127 : /* fd_vm_limits API ***************************************************/
128 :
129 : /* FIXME: pretty good case these actually belong in ballet/sbpf */
130 : /* FIXME: DOCUMENT THESE / LINK TO SOLANA CODE / ETC */
131 :
132 : /* VM register constants */
133 :
134 0 : #define FD_VM_REG_CNT (11UL)
135 16098 : #define FD_VM_REG_MAX (16UL) /* Actual number of SBPF instruction src/dst register indices */
136 :
137 : #define FD_VM_SHADOW_REG_CNT (4UL)
138 :
139 : /* VM stack constants */
140 :
141 44850 : #define FD_VM_STACK_FRAME_MAX (64UL)
142 51453 : #define FD_VM_STACK_FRAME_SZ FD_VM_STACK_FRAME_SIZE
143 : #define FD_VM_STACK_GUARD_SZ (0x1000UL)
144 40619 : #define FD_VM_STACK_MAX (FD_VM_STACK_FRAME_MAX*(FD_VM_STACK_FRAME_SZ))
145 :
146 : /* VM heap constants */
147 :
148 64663 : #define FD_VM_HEAP_DEFAULT ( 32UL*1024UL) /* FIXME: SHOULD THIS MATCH FD_VM_HEAP_SIZE LIMIT BELOW? */
149 7530 : #define FD_VM_HEAP_MAX (256UL*1024UL)
150 :
151 : /* VM log constants */
152 :
153 : #define FD_VM_LOG_MAX (10000UL)
154 : #define FD_VM_LOG_TAIL (128UL) /* Large enough to cover the worst case syscall log tail clobbering in string parsing */
155 :
156 : /* VM memory map constants
157 :
158 : The sBPF virtual address space is divided into 4 GiB regions:
159 :
160 : SBPF V0-V2:
161 : region 0 0x000000000 (unmapped)
162 : region 1 0x100000000 program (full ELF: rodata + text)
163 : region 2 0x200000000 stack
164 : region 3 0x300000000 heap
165 : region 4 0x400000000 input
166 :
167 : SBPF V3:
168 : region 0 0x000000000 rodata segment (read-only)
169 : region 1 0x100000000 (unmapped, bytecode execute-only)
170 : region 2 0x200000000 stack
171 : region 3 0x300000000 heap
172 : region 4 0x400000000 input
173 :
174 : https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/ebpf.rs#L42-L51 */
175 :
176 : #define FD_VM_LO_REGION (0UL)
177 48309 : #define FD_VM_PROG_REGION (1UL)
178 70455 : #define FD_VM_STACK_REGION (2UL)
179 58735 : #define FD_VM_HEAP_REGION (3UL)
180 1183549 : #define FD_VM_INPUT_REGION (4UL)
181 1183598 : #define FD_VM_HIGH_REGION (5UL)
182 :
183 0 : #define FD_VM_MEM_MAP_RODATA_REGION_START (0x000000000UL) /* SBPF V3+ only */
184 : #define FD_VM_MEM_MAP_PROGRAM_REGION_START (0x100000000UL)
185 16867 : #define FD_VM_MEM_MAP_STACK_REGION_START (0x200000000UL)
186 456 : #define FD_VM_MEM_MAP_HEAP_REGION_START (0x300000000UL)
187 813631 : #define FD_VM_MEM_MAP_INPUT_REGION_START (0x400000000UL)
188 : #define FD_VM_MEM_MAP_REGION_SZ (0x0FFFFFFFFUL)
189 : #define FD_VM_MEM_MAP_REGION_MASK (~FD_VM_MEM_MAP_REGION_SZ)
190 1183598 : #define FD_VM_MEM_MAP_REGION_VIRT_ADDR_BITS (32)
191 :
192 : /* VM compute budget. Note: these names should match exactly the names
193 : used in existing Solana validator. See:
194 : https://github.com/anza-xyz/agave/blob/v1.18.5/program-runtime/src/compute_budget.rs#L19
195 : https://github.com/anza-xyz/agave/blob/v1.18.5/program-runtime/src/compute_budget.rs#L133 */
196 : /* FIXME: DOUBLE CHECK THESE */
197 :
198 : /* FD_VM_COMPUTE_UNIT_LIMIT is the number of compute units that a
199 : transaction or individual instruction is allowed to consume. Compute
200 : units are consumed by program execution, resources they use, etc ... */
201 :
202 0 : #define FD_VM_COMPUTE_UNIT_LIMIT ( 1400000UL)
203 :
204 : /* FD_VM_LOG_64_UNITS is the number of compute units consumed by a
205 : log_64 call */
206 :
207 : #define FD_VM_LOG_64_UNITS ( 100UL)
208 :
209 : /* FD_VM_CREATE_PROGRAM_ADDRESS_UNITS is the number of compute units
210 : consumed by a create_program_address call and a try_find_program_address_call */
211 :
212 : #define FD_VM_CREATE_PROGRAM_ADDRESS_UNITS ( 1500UL)
213 :
214 : /* FD_VM_INVOKE_UNITS is the number of compute units consumed by an
215 : invoke call (not including the cost incurred by the called program)
216 : https://github.com/anza-xyz/agave/blob/v3.1.2/program-runtime/src/execution_budget.rs#L22-L23 */
217 2149 : #define FD_VM_INVOKE_UNITS ( 946UL)
218 :
219 : /* SIMD-0339 uses a fixed size (80 bytes) to bill each account info:
220 : - 32 bytes for account address
221 : - 32 bytes for owner address
222 : - 8 bytes for lamports
223 : - 8 bytes for data length
224 : https://github.com/anza-xyz/agave/blob/v3.1.2/program-runtime/src/cpi.rs#L63-L68
225 : */
226 1332 : #define FD_VM_ACCOUNT_INFO_BYTE_SIZE ( 80UL)
227 :
228 : /* FD_VM_MAX_INVOKE_STACK_HEIGHT is the maximum program instruction
229 : invocation stack height. Invocation stack height starts at 1 for
230 : transaction instructions and the stack height is incremented each
231 : time a program invokes an instruction and decremented when a program
232 : returns */
233 :
234 : #define FD_VM_MAX_INVOKE_STACK_HEIGHT ( 5UL)
235 :
236 : /* FD_VM_MAX_INSTRUCTION_TRACE_LENGTH is the maximum cross-program
237 : invocation and instructions per transaction */
238 :
239 : #define FD_VM_MAX_INSTRUCTION_TRACE_LENGTH ( 64UL)
240 :
241 : /* FD_VM_SHA256_BASE_COST is the base number of compute units consumed
242 : to call SHA256 */
243 :
244 558 : #define FD_VM_SHA256_BASE_COST ( 85UL)
245 :
246 : /* FD_VM_SHA256_BYTE_COST is the incremental number of units consumed by
247 : SHA256 (based on bytes) */
248 :
249 6654 : #define FD_VM_SHA256_BYTE_COST ( 1UL)
250 :
251 : /* FD_VM_SHA256_MAX_SLICES is the maximum number of slices hashed per
252 : syscall */
253 :
254 2 : #define FD_VM_SHA256_MAX_SLICES ( 20000UL)
255 :
256 : /* FD_VM_MAX_CALL_DEPTH is the maximum SBF to BPF call depth */
257 :
258 347 : #define FD_VM_MAX_CALL_DEPTH ( 64UL)
259 :
260 : /* FD_VM_STACK_FRAME_SIZE is the size of a stack frame in bytes, must
261 : match the size specified in the LLVM SBF backend */
262 :
263 51453 : #define FD_VM_STACK_FRAME_SIZE ( 4096UL)
264 :
265 : /* FD_VM_LOG_PUBKEY_UNITS is the number of compute units consumed by
266 : logging a `Pubkey` */
267 :
268 : #define FD_VM_LOG_PUBKEY_UNITS ( 100UL)
269 :
270 : /* FD_VM_MAX_CPI_INSTRUCTION_SIZE is the maximum cross-program
271 : invocation instruction size */
272 :
273 : #define FD_VM_MAX_CPI_INSTRUCTION_SIZE ( 1280UL) /* IPv6 Min MTU size */
274 :
275 : /* FD_VM_CPI_BYTES_PER_UNIT is the number of account data bytes per
276 : compute unit charged during a cross-program invocation */
277 :
278 4364 : #define FD_VM_CPI_BYTES_PER_UNIT ( 250UL) /* ~50MB at 200,000 units */
279 :
280 : /* FD_VM_SYSVAR_BASE_COST is the base number of compute units consumed
281 : to get a sysvar */
282 :
283 : #define FD_VM_SYSVAR_BASE_COST ( 100UL)
284 :
285 : /* FD_VM_SECP256K1_RECOVER_COST is the number of compute units consumed
286 : to call secp256k1_recover */
287 :
288 : #define FD_VM_SECP256K1_RECOVER_COST ( 25000UL)
289 :
290 : /* FD_VM_SYSCALL_BASE_COST is the number of compute units consumed to do
291 : a syscall without any work */
292 :
293 1212 : #define FD_VM_SYSCALL_BASE_COST ( 100UL)
294 :
295 : /* FD_VM_CURVE_EDWARDS_VALIDATE_POINT_COST is the number of compute
296 : units consumed to validate a curve25519 edwards point */
297 :
298 : #define FD_VM_CURVE_EDWARDS_VALIDATE_POINT_COST ( 159UL)
299 :
300 : /* FD_VM_CURVE_EDWARDS_ADD_COST is the number of compute units
301 : consumed to add two curve25519 edwards points */
302 :
303 61 : #define FD_VM_CURVE_EDWARDS_ADD_COST ( 473UL)
304 :
305 : /* FD_VM_CURVE_EDWARDS_SUBTRACT_COST is the number of compute units
306 : consumed to subtract two curve25519 edwards points */
307 :
308 53 : #define FD_VM_CURVE_EDWARDS_SUBTRACT_COST ( 475UL)
309 :
310 : /* FD_VM_CURVE_EDWARDS_MULTIPLY_COST is the number of compute units
311 : consumed to multiply a curve25519 edwards point */
312 :
313 87 : #define FD_VM_CURVE_EDWARDS_MULTIPLY_COST ( 2177UL)
314 :
315 : /* FD_VM_CURVE_EDWARDS_MSM_BASE_COST is the number of compute units
316 : consumed for a multiscalar multiplication (msm) of edwards points.
317 : The total cost is calculated as
318 : `msm_base_cost + (length - 1) * msm_incremental_cost` */
319 :
320 224 : #define FD_VM_CURVE_EDWARDS_MSM_BASE_COST ( 2273UL)
321 :
322 : /* FD_VM_CURVE_EDWARDS_MSM_INCREMENTAL_COST is the number of
323 : compute units consumed for a multiscalar multiplication (msm) of
324 : edwards points. The total cost is calculated as
325 : `msm_base_cost + (length - 1) * msm_incremental_cost` */
326 :
327 224 : #define FD_VM_CURVE_EDWARDS_MSM_INCREMENTAL_COST ( 758UL)
328 :
329 : /* FD_VM_CURVE_RISTRETTO_VALIDATE_POINT_COST is the number of
330 : compute units consumed to validate a curve25519 ristretto point */
331 :
332 : #define FD_VM_CURVE_RISTRETTO_VALIDATE_POINT_COST ( 169UL)
333 :
334 : /* FD_VM_CURVE_RISTRETTO_ADD_COST is the number of compute units
335 : consumed to add two curve25519 ristretto points */
336 :
337 48 : #define FD_VM_CURVE_RISTRETTO_ADD_COST ( 521UL)
338 :
339 : /* FD_VM_CURVE_RISTRETTO_SUBTRACT_COST is the number of compute
340 : units consumed to subtract two curve25519 ristretto points */
341 :
342 54 : #define FD_VM_CURVE_RISTRETTO_SUBTRACT_COST ( 519UL)
343 :
344 : /* FD_VM_CURVE_RISTRETTO_MULTIPLY_COST is the number of compute
345 : units consumed to multiply a curve25519 ristretto point */
346 :
347 66 : #define FD_VM_CURVE_RISTRETTO_MULTIPLY_COST ( 2208UL)
348 :
349 : /* FD_VM_CURVE_RISTRETTO_MSM_BASE_COST is the number of compute
350 : units consumed for a multiscalar multiplication (msm) of ristretto
351 : points. The total cost is calculated as
352 : `msm_base_cost + (length - 1) * msm_incremental_cost` */
353 :
354 235 : #define FD_VM_CURVE_RISTRETTO_MSM_BASE_COST ( 2303UL)
355 :
356 : /* FD_VM_CURVE_RISTRETTO_MSM_INCREMENTAL_COST is the number of
357 : compute units consumed for a multiscalar multiplication (msm) of
358 : ristretto points. The total cost is calculated as
359 : `msm_base_cost + (length - 1) * msm_incremental_cost` */
360 :
361 235 : #define FD_VM_CURVE_RISTRETTO_MSM_INCREMENTAL_COST ( 788UL)
362 :
363 : /* FD_VM_CURVE_BLS12_381_G1_ADD_COST is the number of compute
364 : units consumed for addition in BLS12-381 G1. */
365 :
366 41 : #define FD_VM_CURVE_BLS12_381_G1_ADD_COST ( 128UL)
367 :
368 : /* FD_VM_CURVE_BLS12_381_G2_ADD_COST is the number of compute
369 : units consumed for addition in BLS12-381 G2. */
370 :
371 44 : #define FD_VM_CURVE_BLS12_381_G2_ADD_COST ( 203UL)
372 :
373 : /* FD_VM_CURVE_BLS12_381_G1_SUB_COST is the number of compute
374 : units consumed for subtraction in BLS12-381 G1. */
375 :
376 49 : #define FD_VM_CURVE_BLS12_381_G1_SUB_COST ( 129UL)
377 :
378 : /* FD_VM_CURVE_BLS12_381_G2_SUB_COST is the number of compute
379 : units consumed for subtraction in BLS12-381 G2. */
380 :
381 41 : #define FD_VM_CURVE_BLS12_381_G2_SUB_COST ( 204UL)
382 :
383 : /* FD_VM_CURVE_BLS12_381_G1_MUL_COST is the number of compute
384 : units consumed for multiplication in BLS12-381 G1. */
385 :
386 47 : #define FD_VM_CURVE_BLS12_381_G1_MUL_COST ( 4627UL)
387 :
388 : /* FD_VM_CURVE_BLS12_381_G2_MUL_COST is the number of compute
389 : units consumed for multiplication in BLS12-381 G2. */
390 :
391 48 : #define FD_VM_CURVE_BLS12_381_G2_MUL_COST ( 8255UL)
392 :
393 : /* FD_VM_CURVE_BLS12_381_G1_DECOMPRESS_COST is the number of compute
394 : units consumed for point decompression in BLS12-381 G1. */
395 : #define FD_VM_CURVE_BLS12_381_G1_DECOMPRESS_COST ( 2100UL)
396 :
397 : /* FD_VM_CURVE_BLS12_381_G2_DECOMPRESS_COST is the number of compute
398 : units consumed for point decompression in BLS12-381 G2. */
399 :
400 : #define FD_VM_CURVE_BLS12_381_G2_DECOMPRESS_COST ( 3050UL)
401 :
402 : /* FD_VM_CURVE_BLS12_381_G1_VALIDATE_COST is the number of compute
403 : units consumed for point validation in BLS12-381 G1. */
404 :
405 : #define FD_VM_CURVE_BLS12_381_G1_VALIDATE_COST ( 1565UL)
406 :
407 : /* FD_VM_CURVE_BLS12_381_G2_VALIDATE_COST is the number of compute
408 : units consumed for point validation in BLS12-381 G2. */
409 :
410 : #define FD_VM_CURVE_BLS12_381_G2_VALIDATE_COST ( 1968UL)
411 :
412 : /* FD_VM_CURVE_BLS12_381_PAIRING_*_COST are the number of compute
413 : units consumed for calculating a pairing map in BLS12-381.
414 : The total cost is calculated as
415 : `pairing_base_cost + (length-1) * pairing_incr_cost` */
416 :
417 138 : #define FD_VM_CURVE_BLS12_381_PAIRING_BASE_COST ( 25445UL)
418 138 : #define FD_VM_CURVE_BLS12_381_PAIRING_INCR_COST ( 13023UL)
419 :
420 : /* FD_VM_CURVE_SECP256R1_ADD_COST is the number of compute units
421 : consumed for addition in secp256r1. */
422 :
423 0 : #define FD_VM_CURVE_SECP256R1_ADD_COST ( 520UL)
424 :
425 : /* FD_VM_CURVE_SECP256R1_SUB_COST is the number of compute units
426 : consumed for subtraction in secp256r1. */
427 :
428 0 : #define FD_VM_CURVE_SECP256R1_SUB_COST ( 520UL)
429 :
430 : /* FD_VM_CURVE_SECP256R1_MUL_COST is the number of compute units
431 : consumed for scalar multiplication in secp256r1. */
432 :
433 0 : #define FD_VM_CURVE_SECP256R1_MUL_COST ( 9000UL)
434 :
435 : /* FD_VM_CURVE_SECP256R1_MSM_*_COST are the number of compute units
436 : consumed for multiscalar multiplication in secp256r1.
437 : The total cost is calculated as
438 : `msm_base_cost + (length-1) * msm_incremental_cost` */
439 :
440 0 : #define FD_VM_CURVE_SECP256R1_MSM_BASE_COST ( 9000UL)
441 0 : #define FD_VM_CURVE_SECP256R1_MSM_INCREMENTAL_COST ( 3800UL)
442 :
443 : /* FD_VM_CURVE_SECP256R1_VALIDATE_COST is the number of compute units
444 : consumed for point validation in secp256r1. */
445 :
446 : #define FD_VM_CURVE_SECP256R1_VALIDATE_COST ( 20UL)
447 :
448 : /* FD_VM_CURVE_SECP256R1_DECOMPRESS_COST is the number of compute
449 : units consumed for point decompression in secp256r1. */
450 :
451 : #define FD_VM_CURVE_SECP256R1_DECOMPRESS_COST ( 610UL)
452 :
453 : /* FD_VM_HEAP_SIZE is the program heap region size, default:
454 : solana_sdk::entrypoint::HEAP_LENGTH */
455 :
456 : #define FD_VM_HEAP_SIZE ( 32768UL)
457 :
458 : /* FD_VM_HEAP_COST is the number of compute units per additional 32k
459 : heap above the default (~.5 us per 32k at 15 units/us rounded up) */
460 :
461 11366 : #define FD_VM_HEAP_COST ( 8UL) /* DEFAULT_HEAP_COST */
462 :
463 : /* FD_VM_MEM_OP_BASE_COST is the memory operation syscall base cost */
464 :
465 6654 : #define FD_VM_MEM_OP_BASE_COST ( 10UL)
466 :
467 : /* FD_VM_ALT_BN128_ADDITION_COST is the number of compute units consumed
468 : to call alt_bn128_addition */
469 :
470 95 : #define FD_VM_ALT_BN128_G1_ADDITION_COST ( 334UL)
471 64 : #define FD_VM_ALT_BN128_G2_ADDITION_COST ( 535UL)
472 :
473 : /* FD_VM_ALT_BN128_MULTIPLICATION_COST is the number of compute units
474 : consumed to call alt_bn128_multiplication */
475 :
476 1853 : #define FD_VM_ALT_BN128_G1_MULTIPLICATION_COST ( 3840UL)
477 54 : #define FD_VM_ALT_BN128_G2_MULTIPLICATION_COST ( 15670UL)
478 :
479 : /* FD_VM_ALT_BN128_PAIRING_ONE_PAIR_COST_FIRST
480 : FD_VM_ALT_BN128_PAIRING_ONE_PAIR_COST_OTHER give the total cost as
481 : alt_bn128_pairing_one_pair_cost_first + alt_bn128_pairing_one_pair_cost_other * (num_elems - 1) */
482 :
483 558 : #define FD_VM_ALT_BN128_PAIRING_ONE_PAIR_COST_FIRST ( 36364UL)
484 558 : #define FD_VM_ALT_BN128_PAIRING_ONE_PAIR_COST_OTHER ( 12121UL)
485 :
486 : /* FD_VM_BIG_MODULAR_EXPONENTIATION_COST is the big integer modular
487 : exponentiation cost */
488 :
489 : #define FD_VM_BIG_MODULAR_EXPONENTIATION_COST ( 33UL)
490 :
491 : /* FD_VM_POSEIDON_COST_COEFFICIENT_A is the coefficient `a` of the
492 : quadratic function which determines the number of compute units
493 : consumed to call poseidon syscall for a given number of inputs */
494 :
495 282 : #define FD_VM_POSEIDON_COST_COEFFICIENT_A ( 61UL)
496 :
497 : /* FD_VM_POSEIDON_COST_COEFFICIENT_C is the coefficient `c` of the
498 : quadratic function which determines the number of compute units
499 : consumed to call poseidon syscall for a given number of inputs */
500 :
501 282 : #define FD_VM_POSEIDON_COST_COEFFICIENT_C ( 542UL)
502 :
503 : /* FD_VM_GET_REMAINING_COMPUTE_UNITS_COST is the number of compute units
504 : consumed for reading the remaining compute units */
505 :
506 : #define FD_VM_GET_REMAINING_COMPUTE_UNITS_COST ( 100UL)
507 :
508 : /* FD_VM_ALT_BN128_G1_COMPRESS is the number of compute units consumed
509 : to call alt_bn128_g1_compress */
510 :
511 274 : #define FD_VM_ALT_BN128_G1_COMPRESS ( 30UL)
512 :
513 : /* FD_VM_ALT_BN128_G1_DECOMPRESS is the number of compute units consumed
514 : to call alt_bn128_g1_decompress */
515 :
516 269 : #define FD_VM_ALT_BN128_G1_DECOMPRESS ( 398UL)
517 :
518 : /* FD_VM_ALT_BN128_G2_COMPRESS is the number of compute units consumed
519 : to call alt_bn128_g2_compress */
520 :
521 331 : #define FD_VM_ALT_BN128_G2_COMPRESS ( 86UL)
522 :
523 : /* FD_VM_ALT_BN128_G2_DECOMPRESS is the number of compute units consumed
524 : to call alt_bn128_g2_decompress */
525 :
526 340 : #define FD_VM_ALT_BN128_G2_DECOMPRESS ( 13610UL)
527 :
528 : /* FD_VM_LOADED_ACCOUNTS_DATA_SIZE_LIMIT is the maximum accounts data
529 : size, in bytes, that a transaction is allowed to load */
530 :
531 64940 : #define FD_VM_LOADED_ACCOUNTS_DATA_SIZE_LIMIT (64UL*1024UL*1024UL) /* 64MiB */
532 :
533 : /* fd_vm_trace API ****************************************************/
534 :
535 : /* FIXME: pretty good case this actually belongs in ballet/sbpf */
536 :
537 : struct fd_vm_trace_event_exe {
538 : /* This point is aligned 8 */
539 : ulong multiword; /* 1 if multiword, 0 otherwise */
540 : ulong pc; /* pc */
541 : ulong ic; /* ic */
542 : ulong cu; /* cu */
543 : ulong ic_correction; /* ic_correction */
544 : ulong frame_cnt; /* frame_cnt */
545 : ulong reg[ FD_VM_REG_CNT ]; /* registers */
546 : ulong text[ 2 ]; /* If !multiword, text[1] is omitted */
547 : /* This point is aligned 8 */
548 : };
549 :
550 : typedef struct fd_vm_trace_event_exe fd_vm_trace_event_exe_t;
551 :
552 0 : #define FD_VM_TRACE_MAGIC (0xfdc377ace3a61c01UL) /* FD VM TRACE MAGIC version 1 */
553 :
554 : struct fd_vm_trace {
555 : /* This point is aligned 8 */
556 : ulong magic; /* ==FD_VM_TRACE_MAGIC */
557 : ulong event_max; /* Number bytes of event storage */
558 : ulong event_sz; /* Used bytes of event storage */
559 : /* This point is aligned 8
560 : event_max bytes storage
561 : padding to aligned 8 */
562 : };
563 :
564 : typedef struct fd_vm_trace fd_vm_trace_t;
565 :
566 : FD_PROTOTYPES_BEGIN
567 :
568 : /* trace object structors */
569 : /* FIXME: DOCUMENT (USUAL CONVENTIONS) */
570 :
571 : FD_FN_CONST ulong
572 : fd_vm_trace_align( void );
573 :
574 : FD_FN_CONST ulong
575 : fd_vm_trace_footprint( ulong event_max ); /* Maximum amount of event storage (<=1 EiB) */
576 :
577 : void *
578 : fd_vm_trace_new( void * shmem,
579 : ulong event_max );
580 :
581 : fd_vm_trace_t *
582 : fd_vm_trace_join( void * _trace );
583 :
584 : void *
585 : fd_vm_trace_leave( fd_vm_trace_t * trace );
586 :
587 : void *
588 : fd_vm_trace_delete( void * _trace );
589 :
590 : /* Given a current local join, fd_vm_trace_event returns the location in
591 : the caller's address space where trace events are stored and
592 : fd_vm_trace_event_sz returns number of bytes of trace events stored
593 : at that location. event_max is the number of bytes of event storage
594 : (value used to construct the trace). event will be aligned 8 and
595 : event_sz will be a multiple of 8 in [0,event_max]. The lifetime of
596 : the returned pointer is the lifetime of the current join. Events are
597 : fd_vm_trace_event_exe_t, with text[1] omitted if !multiword. */
598 :
599 0 : FD_FN_CONST static inline void const * fd_vm_trace_event ( fd_vm_trace_t const * trace ) { return (void *)(trace+1); }
600 0 : FD_FN_CONST static inline ulong fd_vm_trace_event_sz ( fd_vm_trace_t const * trace ) { return trace->event_sz; }
601 0 : FD_FN_CONST static inline ulong fd_vm_trace_event_max( fd_vm_trace_t const * trace ) { return trace->event_max; }
602 :
603 : /* fd_vm_trace_reset frees all events in the trace. Returns
604 : FD_VM_SUCCESS (0) on success or FD_VM_ERR code (negative) on failure.
605 : Reasons for failure include NULL trace. */
606 :
607 : static inline int
608 0 : fd_vm_trace_reset( fd_vm_trace_t * trace ) {
609 0 : if( FD_UNLIKELY( !trace ) ) return FD_VM_ERR_INVAL;
610 0 : trace->event_sz = 0UL;
611 0 : return FD_VM_SUCCESS;
612 0 : }
613 :
614 : /* fd_vm_trace_event_exe records the current pc, ic, cu and
615 : register file of the VM and the instruction about to execute. Text
616 : points to the first word of the instruction about to execute and
617 : text_cnt points to the number of words available at that point.
618 : Returns FD_VM_SUCCESS (0) on success and a FD_VM_ERR code (negative)
619 : on failure. Reasons for failure include INVAL (trace NULL, reg NULL,
620 : text NULL, and/or text_cnt 0) and FULL (insufficient trace event
621 : storage available). */
622 :
623 : int
624 : fd_vm_trace_event_exe( fd_vm_trace_t * trace,
625 : ulong pc,
626 : ulong ic,
627 : ulong cu,
628 : ulong reg[ FD_VM_REG_CNT ],
629 : ulong const * text, /* Indexed [0,text_cnt) */
630 : ulong text_cnt,
631 : ulong ic_correction,
632 : ulong frame_cnt );
633 :
634 : /* fd_vm_trace_printf pretty prints the current trace to stdout.
635 : Returns FD_VM_SUCCESS (0) on success and a FD_VM_ERR code (negative) on failure. Reasons for
636 : failure include INVAL (NULL trace) and IO (corruption detected while
637 : parsing the trace events). FIXME: REVAMP THIS API FOR MORE GENERAL
638 : USE CASES. */
639 :
640 : int
641 : fd_vm_trace_printf( fd_vm_trace_t const * trace );
642 :
643 : /* fd_vm_syscall API **************************************************/
644 :
645 : /* FIXME: fd_sbpf_syscalls_t and fd_sbpf_syscall_func_t probably should
646 : be moved from ballet/sbpf to here. */
647 :
648 : /* Note: the syscall map is kept separate from the fd_vm_t itself to
649 : support, for example, multiple fd_vm_t executing transactions
650 : concurrently for a slot. They could use the same syscalls for setup,
651 : memory and cache efficiency. */
652 :
653 : /* fd_vm_syscall_register inserts the syscall with the given cstr name
654 : into the given syscalls. The VM syscall implementation to use is
655 : given by func (NULL is fine though a VM itself may not accept such as
656 : valid). The caller promises there is room in the syscall map.
657 : Returns FD_VM_SUCCESS (0) on success or a FD_VM_ERR code (negative)
658 : on failure. Reasons for failure include INVAL (NULL syscalls, NULL
659 : name, name or the hash of name already in the map). On success,
660 : syscalls retains a read-only interest in name (e.g. use an infinite
661 : lifetime cstr here). (This function is exposed to allow VM users to
662 : add custom syscalls but most use cases probably should just call
663 : fd_vm_syscall_register_slot below.)
664 :
665 : IMPORTANT SAFETY TIP! See notes in syscall/fd_vm_syscall.h on what a
666 : syscall should expect to see and what to return. */
667 :
668 : int
669 : fd_vm_syscall_register( fd_sbpf_syscalls_t * syscalls,
670 : char const * name,
671 : fd_sbpf_syscall_func_t func );
672 :
673 : /* fd_vm_syscall_register_slot unmaps all syscalls in the current map
674 : (also ending any interest in the corresponding name cstr) and
675 : registers all syscalls appropriate for the slot. Returns
676 : FD_VM_SUCCESS (0) on success and FD_VM_ERR code (negative) on
677 : failure. Reasons for failure include INVAL (NULL syscalls) and FULL
678 : (tried to register too many system calls ... compile time map size
679 : needs to be adjusted).
680 :
681 : If features is NULL, slot is ignored and all feature-gated syscalls
682 : are registered.
683 :
684 : is_deploy should be 1 if the set of syscalls registered should be that
685 : used to verify programs before they are deployed, and 0 if it
686 : should be the set used to execute programs. */
687 :
688 : int
689 : fd_vm_syscall_register_slot( fd_sbpf_syscalls_t * syscalls,
690 : ulong slot,
691 : fd_features_t const * features,
692 : uchar is_deploy );
693 :
694 : /* fd_vm_syscall_register_all is a shorthand for registering all
695 : syscalls (see register slot). */
696 :
697 : static inline int
698 7467 : fd_vm_syscall_register_all( fd_sbpf_syscalls_t * syscalls, uchar is_deploy ) {
699 7467 : return fd_vm_syscall_register_slot( syscalls, 0UL, NULL, is_deploy );
700 7467 : }
701 :
702 : FD_PROTOTYPES_END
703 :
704 : #endif /* HEADER_fd_src_flamenco_vm_fd_vm_base_h */
|