LCOV - code coverage report
Current view: top level - flamenco/vm - fd_vm_base.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 73 153 47.7 %
Date: 2025-03-20 12:08:36 Functions: 13 333 3.9 %

          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             : /* FD_VM_SUCCESS is zero and returned to indicate that an operation
      18             :    completed successfully.  FD_VM_ERR_* are negative integers and
      19             :    returned to indicate an operation that failed and why. */
      20             : 
      21             : /* "Standard" Firedancer error codes (FIXME: harmonize and consolidate) */
      22             : 
      23    56253117 : #define FD_VM_SUCCESS   ( 0) /* success */
      24     1891752 : #define FD_VM_ERR_INVAL (-1) /* invalid request */
      25           3 : #define FD_VM_ERR_AGAIN (-2) /* try again later */
      26           3 : #define FD_VM_ERR_UNSUP (-3) /* unsupported request */
      27           3 : #define FD_VM_ERR_PERM  (-4) /* unauthorized request */
      28           6 : #define FD_VM_ERR_FULL  (-5) /* storage full */
      29           3 : #define FD_VM_ERR_EMPTY (-6) /* nothing to do */
      30           3 : #define FD_VM_ERR_IO    (-7) /* input-output error */
      31             : 
      32             : /* VM exec error codes:  These are only produced by the VM itself. */
      33             : 
      34         123 : #define FD_VM_ERR_SIGTEXT     ( -8) /* illegal program counter (e.g. execution ran off end of program, jump to outside the program) */
      35           3 : #define FD_VM_ERR_SIGSPLIT    ( -9) /* split multiword instruction (e.g. jump into the middle of a multiword instruction) */
      36           3 : #define FD_VM_ERR_SIGCALL     (-10) /* illegal call (e.g. call target is not the start of function) */
      37           3 : #define FD_VM_ERR_SIGSTACK    (-11) /* call depth limit exceeded */
      38        1203 : #define FD_VM_ERR_SIGILL      (-12) /* illegal instruction (e.g. opcode is not valid) */
      39         153 : #define FD_VM_ERR_SIGSEGV     (-13) /* illegal memory address (e.g. read/write to an address not backed by any memory) */
      40           3 : #define FD_VM_ERR_SIGBUS      (-14) /* misaligned memory address (e.g. read/write to an address with inappropriate alignment) */
      41           3 : #define FD_VM_ERR_SIGRDONLY   (-15) /* illegal write (e.g. write to a read only address) */
      42         684 : #define FD_VM_ERR_SIGCOST     (-16) /* compute unit limit exceeded */
      43             : // #define FD_VM_ERR_INVALID_PDA (-17) /* (deprecated, moved to syscall error) the computed pda was not a valid ed25519 point */
      44         198 : #define FD_VM_ERR_SIGFPE      (-18) /* divide by zero */
      45          36 : #define FD_VM_ERR_SIGFPE_OF   (-19) /* divide overflow */
      46           0 : #define FD_VM_ERR_SIGSYSCALL  (-20) /* Generic syscall error */
      47           0 : #define FD_VM_ERR_SIGABORT    (-21) /* Generic abort error (used in JIT) */
      48             : 
      49             : /* (DEPRECATED) VM syscall error codes.  These are only produced by fd_vm_syscall
      50             :    implementations. */
      51             : 
      52             : // #define FD_VM_ERR_ABORT                        (-119) /* FIXME: description */
      53             : // #define FD_VM_ERR_PANIC                        (-120) /* FIXME: description */
      54             : // #define FD_VM_ERR_MEM_OVERLAP                  (-121) /* FIXME: description */
      55             : // #define FD_VM_ERR_INSTR_ERR                    (-22) /* FIXME: description  */
      56             : // #define FD_VM_ERR_INVOKE_CONTEXT_BORROW_FAILED (-23) /* FIXME: description  */
      57             : // #define FD_VM_ERR_RETURN_DATA_TOO_LARGE        (-24) /* FIXME: description  */
      58             : 
      59             : /* sBPF validation error codes.  These are only produced by
      60             :    fd_vm_validate.  FIXME: Consider having fd_vm_validate return
      61             :    standard error codes and then provide detail like this through an
      62             :    info arg.  FIXME: Are these exact matches to Solana?  If so, provide
      63             :    link, if not, document and refine name / consolidate further. */
      64             : 
      65        1179 : #define FD_VM_ERR_INVALID_OPCODE    (-25) /* detected an invalid opcode */
      66         393 : #define FD_VM_ERR_INVALID_SRC_REG   (-26) /* detected an invalid source register */
      67         585 : #define FD_VM_ERR_INVALID_DST_REG   (-27) /* detected an invalid destination register */
      68           3 : #define FD_VM_ERR_INF_LOOP          (-28) /* detected an infinite loop */
      69         141 : #define FD_VM_ERR_JMP_OUT_OF_BOUNDS (-29) /* detected an out of bounds jump */
      70           3 : #define FD_VM_ERR_JMP_TO_ADDL_IMM   (-30) /* detected a jump to an addl imm */
      71          21 : #define FD_VM_ERR_INVALID_END_IMM   (-31) /* detected an invalid immediate for an endianness conversion instruction */
      72           3 : #define FD_VM_ERR_INCOMPLETE_LDQ    (-32) /* detected an incomplete ldq at program end */
      73           3 : #define FD_VM_ERR_LDQ_NO_ADDL_IMM   (-33) /* detected a ldq without an addl imm following it */
      74           3 : #define FD_VM_ERR_NO_SUCH_EXT_CALL  (-34) /* detected a call imm with no function was registered for that immediate */
      75          18 : #define FD_VM_ERR_INVALID_REG       (-35) /* detected an invalid register */
      76           0 : #define FD_VM_ERR_BAD_TEXT          (-36) /* detected a bad text section (overflow, outside rodata boundary, etc.,)*/
      77          72 : #define FD_VM_SH_OVERFLOW           (-37) /* detected a shift overflow, equivalent to VeriferError::ShiftWithOverflow */
      78           0 : #define FD_VM_TEXT_SZ_UNALIGNED     (-38) /* detected a text section that is not a multiple of 8 */
      79           0 : #define FD_VM_INVALID_FUNCTION      (-39) /* detected an invalid function */
      80           0 : #define FD_VM_INVALID_SYSCALL       (-40) /* detected an invalid syscall */
      81             : 
      82             : /* Syscall Errors
      83             :    https://github.com/anza-xyz/agave/blob/v2.0.7/programs/bpf_loader/src/syscalls/mod.rs#L81 */
      84             : 
      85           0 : #define FD_VM_SYSCALL_ERR_INVALID_STRING                          (-1)
      86           0 : #define FD_VM_SYSCALL_ERR_ABORT                                   (-2)
      87           0 : #define FD_VM_SYSCALL_ERR_PANIC                                   (-3)
      88           0 : #define FD_VM_SYSCALL_ERR_INVOKE_CONTEXT_BORROW_FAILED            (-4)
      89           0 : #define FD_VM_SYSCALL_ERR_MALFORMED_SIGNER_SEED                   (-5)
      90           0 : #define FD_VM_SYSCALL_ERR_BAD_SEEDS                               (-6)
      91           0 : #define FD_VM_SYSCALL_ERR_PROGRAM_NOT_SUPPORTED                   (-7)
      92           0 : #define FD_VM_SYSCALL_ERR_UNALIGNED_POINTER                       (-8)
      93           0 : #define FD_VM_SYSCALL_ERR_TOO_MANY_SIGNERS                        (-9)
      94           0 : #define FD_VM_SYSCALL_ERR_INSTRUCTION_TOO_LARGE                   (-10)
      95           0 : #define FD_VM_SYSCALL_ERR_TOO_MANY_ACCOUNTS                       (-11)
      96          36 : #define FD_VM_SYSCALL_ERR_COPY_OVERLAPPING                        (-12)
      97           0 : #define FD_VM_SYSCALL_ERR_RETURN_DATA_TOO_LARGE                   (-13)
      98           0 : #define FD_VM_SYSCALL_ERR_TOO_MANY_SLICES                         (-14)
      99           3 : #define FD_VM_SYSCALL_ERR_INVALID_LENGTH                          (-15)
     100           0 : #define FD_VM_SYSCALL_ERR_MAX_INSTRUCTION_DATA_LEN_EXCEEDED       (-16)
     101           0 : #define FD_VM_SYSCALL_ERR_MAX_INSTRUCTION_ACCOUNTS_EXCEEDED       (-17)
     102           0 : #define FD_VM_SYSCALL_ERR_MAX_INSTRUCTION_ACCOUNT_INFOS_EXCEEDED  (-18)
     103           3 : #define FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE                       (-19)
     104           0 : #define FD_VM_SYSCALL_ERR_INVALID_POINTER                         (-20)
     105           0 : #define FD_VM_SYSCALL_ERR_ARITHMETIC_OVERFLOW                     (-21)
     106             : 
     107             : /* These syscall errors are unique to Firedancer and do not have an Agave equivalent. */
     108           0 : #define FD_VM_SYSCALL_ERR_INSTR_ERR                               (-22)
     109           0 : #define FD_VM_SYSCALL_ERR_INVALID_PDA                             (-23) /* the computed pda was not a valid ed25519 point */
     110           0 : #define FD_VM_SYSCALL_ERR_COMPUTE_BUDGET_EXCEEDED                 (-24) /* compute unit limit exceeded in syscall */
     111          72 : #define FD_VM_SYSCALL_ERR_SEGFAULT                                (-25) /* illegal memory address (e.g. read/write to an address not backed by any memory) in syscall */
     112           0 : #define FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME                         (-26) /* syscall called with vm not running in solana runtime */
     113             : 
     114             : /* Poseidon returns custom errors for some reason */
     115           0 : #define FD_VM_SYSCALL_ERR_POSEIDON_INVALID_PARAMS                 (1)
     116           0 : #define FD_VM_SYSCALL_ERR_POSEIDON_INVALID_ENDIANNESS             (2)
     117             : 
     118             : /* EbpfError
     119             :    https://github.com/solana-labs/rbpf/blob/v0.8.5/src/error.rs#L17 */
     120             : 
     121           0 : #define FD_VM_ERR_EBPF_ELF_ERROR                                  (-1)
     122           0 : #define FD_VM_ERR_EBPF_FUNCTION_ALREADY_REGISTERED                (-2)
     123           0 : #define FD_VM_ERR_EBPF_CALL_DEPTH_EXCEEDED                        (-3)
     124           0 : #define FD_VM_ERR_EBPF_EXIT_ROOT_CALL_FRAME                       (-4)
     125           0 : #define FD_VM_ERR_EBPF_DIVIDE_BY_ZERO                             (-5)
     126           0 : #define FD_VM_ERR_EBPF_DIVIDE_OVERFLOW                            (-6)
     127           0 : #define FD_VM_ERR_EBPF_EXECUTION_OVERRUN                          (-7)
     128           0 : #define FD_VM_ERR_EBPF_CALL_OUTSIDE_TEXT_SEGMENT                  (-8)
     129           0 : #define FD_VM_ERR_EBPF_EXCEEDED_MAX_INSTRUCTIONS                  (-9)
     130           0 : #define FD_VM_ERR_EBPF_JIT_NOT_COMPILED                           (-10)
     131           0 : #define FD_VM_ERR_EBPF_INVALID_VIRTUAL_ADDRESS                    (-11)
     132           0 : #define FD_VM_ERR_EBPF_INVALID_MEMORY_REGION                      (-12)
     133           0 : #define FD_VM_ERR_EBPF_ACCESS_VIOLATION                           (-13)
     134           0 : #define FD_VM_ERR_EBPF_STACK_ACCESS_VIOLATION                     (-14)
     135           0 : #define FD_VM_ERR_EBPF_INVALID_INSTRUCTION                        (-15)
     136           0 : #define FD_VM_ERR_EBPF_UNSUPPORTED_INSTRUCTION                    (-16)
     137           0 : #define FD_VM_ERR_EBPF_EXHAUSTED_TEXT_SEGMENT                     (-17)
     138           0 : #define FD_VM_ERR_EBPF_LIBC_INVOCATION_FAILED                     (-18)
     139           0 : #define FD_VM_ERR_EBPF_VERIFIER_ERROR                             (-19)
     140           0 : #define FD_VM_ERR_EBPF_SYSCALL_ERROR                              (-20)
     141             : 
     142             : 
     143             : FD_PROTOTYPES_BEGIN
     144             : 
     145             : /* fd_vm_strerror converts an FD_VM_SUCCESS / FD_VM_ERR_* code into
     146             :    a human readable cstr.  The lifetime of the returned pointer is
     147             :    infinite.  The returned pointer is always to a non-NULL cstr. */
     148             : 
     149             : FD_FN_CONST char const * fd_vm_strerror( int err );
     150             : 
     151             : FD_PROTOTYPES_END
     152             : 
     153             : /* fd_vm_limits API ***************************************************/
     154             : 
     155             : /* FIXME: pretty good case these actually belong in ballet/sbpf */
     156             : /* FIXME: DOCUMENT THESE / LINK TO SOLANA CODE / ETC */
     157             : 
     158             : /* VM register constants */
     159             : 
     160         330 : #define FD_VM_REG_CNT (11UL)
     161        7845 : #define FD_VM_REG_MAX (16UL) /* Actual number of SBPF instruction src/dst register indices */
     162             : 
     163             : #define FD_VM_SHADOW_REG_CNT (4UL)
     164             : 
     165             : /* VM stack constants */
     166             : 
     167       27945 : #define FD_VM_STACK_FRAME_MAX (64UL)
     168       31740 : #define FD_VM_STACK_FRAME_SZ  FD_VM_STACK_FRAME_SIZE
     169        7842 : #define FD_VM_STACK_GUARD_SZ  (0x1000UL)
     170       20166 : #define FD_VM_STACK_MAX       (FD_VM_STACK_FRAME_MAX*(FD_VM_STACK_FRAME_SZ))
     171             : 
     172             : /* VM heap constants */
     173             : 
     174         192 : #define FD_VM_HEAP_DEFAULT ( 32UL*1024UL) /* FIXME: SHOULD THIS MATCH FD_VM_HEAP_SIZE LIMIT BELOW? */
     175           0 : #define FD_VM_HEAP_MAX     (256UL*1024UL)
     176             : 
     177             : /* VM log constants */
     178             : 
     179          27 : #define FD_VM_LOG_MAX  (10000UL)
     180             : #define FD_VM_LOG_TAIL (128UL)   /* Large enough to cover the worst case syscall log tail clobbering in string parsing */
     181             : 
     182             : /* VM memory map constants */
     183             : 
     184             : #define FD_VM_LO_REGION    (0UL)
     185       24075 : #define FD_VM_PROG_REGION  (1UL)
     186       24075 : #define FD_VM_STACK_REGION (2UL)
     187       24075 : #define FD_VM_HEAP_REGION  (3UL)
     188       24879 : #define FD_VM_INPUT_REGION (4UL)
     189         822 : #define FD_VM_HIGH_REGION  (5UL)
     190             : 
     191          54 : #define FD_VM_MEM_MAP_PROGRAM_REGION_START  (0x100000000UL)
     192        7845 : #define FD_VM_MEM_MAP_STACK_REGION_START    (0x200000000UL)
     193         180 : #define FD_VM_MEM_MAP_HEAP_REGION_START     (0x300000000UL)
     194        7920 : #define FD_VM_MEM_MAP_INPUT_REGION_START    (0x400000000UL)
     195             : #define FD_VM_MEM_MAP_REGION_SZ             (0x0FFFFFFFFUL)
     196             : #define FD_VM_MEM_MAP_REGION_MASK           (~FD_VM_MEM_MAP_REGION_SZ)
     197         822 : #define FD_VM_MEM_MAP_REGION_VIRT_ADDR_BITS (32)
     198             : 
     199             : /* VM compute budget.  Note: these names should match exactly the names
     200             :    used in existing Solana validator.  See:
     201             :    https://github.com/anza-xyz/agave/blob/v1.18.5/program-runtime/src/compute_budget.rs#L19
     202             :    https://github.com/anza-xyz/agave/blob/v1.18.5/program-runtime/src/compute_budget.rs#L133 */
     203             : /* FIXME: DOUBLE CHECK THESE */
     204             : 
     205             : /* FD_VM_COMPUTE_UNIT_LIMIT is the number of compute units that a
     206             :    transaction or individual instruction is allowed to consume.  Compute
     207             :    units are consumed by program execution, resources they use, etc ... */
     208             : 
     209         186 : #define FD_VM_COMPUTE_UNIT_LIMIT                        (         1400000UL)
     210             : 
     211             : /* FD_VM_LOG_64_UNITS is the number of compute units consumed by a
     212             :    log_64 call */
     213             : 
     214             : #define FD_VM_LOG_64_UNITS                              (             100UL)
     215             : 
     216             : /* FD_VM_CREATE_PROGRAM_ADDRESS_UNITS is the number of compute units
     217             :    consumed by a create_program_address call and a try_find_program_address_call */
     218             : 
     219             : #define FD_VM_CREATE_PROGRAM_ADDRESS_UNITS              (            1500UL)
     220             : 
     221             : /* FD_VM_INVOKE_UNITS is the number of compute units consumed by an
     222             :    invoke call (not including the cost incurred by the called program) */
     223             : 
     224             : #define FD_VM_INVOKE_UNITS                              (            1000UL)
     225             : 
     226             : /* FD_VM_MAX_INVOKE_STACK_HEIGHT is the maximum program instruction
     227             :    invocation stack height. Invocation stack height starts at 1 for
     228             :    transaction instructions and the stack height is incremented each
     229             :    time a program invokes an instruction and decremented when a program
     230             :    returns */
     231             : 
     232             : #define FD_VM_MAX_INVOKE_STACK_HEIGHT                   (               5UL)
     233             : 
     234             : /* FD_VM_MAX_INSTRUCTION_TRACE_LENGTH is the maximum cross-program
     235             :    invocation and instructions per transaction */
     236             : 
     237             : #define FD_VM_MAX_INSTRUCTION_TRACE_LENGTH              (              64UL)
     238             : 
     239             : /* FD_VM_SHA256_BASE_COST is the base number of compute units consumed
     240             :    to call SHA256 */
     241             : 
     242           0 : #define FD_VM_SHA256_BASE_COST                          (              85UL)
     243             : 
     244             : /* FD_VM_SHA256_BYTE_COST is the incremental number of units consumed by
     245             :    SHA256 (based on bytes) */
     246             : 
     247           0 : #define FD_VM_SHA256_BYTE_COST                          (               1UL)
     248             : 
     249             : /* FD_VM_SHA256_MAX_SLICES is the maximum number of slices hashed per
     250             :    syscall */
     251             : 
     252           0 : #define FD_VM_SHA256_MAX_SLICES                         (           20000UL)
     253             : 
     254             : /* FD_VM_MAX_CALL_DEPTH is the maximum SBF to BPF call depth */
     255             : 
     256             : #define FD_VM_MAX_CALL_DEPTH                            (              64UL)
     257             : 
     258             : /* FD_VM_STACK_FRAME_SIZE is the size of a stack frame in bytes, must
     259             :    match the size specified in the LLVM SBF backend */
     260             : 
     261       31740 : #define FD_VM_STACK_FRAME_SIZE                          (            4096UL)
     262             : 
     263             : /* FD_VM_LOG_PUBKEY_UNITS is the number of compute units consumed by
     264             :    logging a `Pubkey` */
     265             : 
     266             : #define FD_VM_LOG_PUBKEY_UNITS                          (             100UL)
     267             : 
     268             : /* FD_VM_MAX_CPI_INSTRUCTION_SIZE is the maximum cross-program
     269             :    invocation instruction size */
     270             : 
     271             : #define FD_VM_MAX_CPI_INSTRUCTION_SIZE                  (            1280UL) /* IPv6 Min MTU size */
     272             : 
     273             : /* FD_VM_CPI_BYTES_PER_UNIT is the number of account data bytes per
     274             :    compute unit charged during a cross-program invocation */
     275             : 
     276           0 : #define FD_VM_CPI_BYTES_PER_UNIT                        (             250UL) /* ~50MB at 200,000 units */
     277             : 
     278             : /* FD_VM_SYSVAR_BASE_COST is the base number of compute units consumed
     279             :    to get a sysvar */
     280             : 
     281             : #define FD_VM_SYSVAR_BASE_COST                          (             100UL)
     282             : 
     283             : /* FD_VM_SECP256K1_RECOVER_COST is the number of compute units consumed
     284             :    to call secp256k1_recover */
     285             : 
     286             : #define FD_VM_SECP256K1_RECOVER_COST                    (           25000UL)
     287             : 
     288             : /* FD_VM_SYSCALL_BASE_COST is the number of compute units consumed to do
     289             :    a syscall without any work */
     290             : 
     291           0 : #define FD_VM_SYSCALL_BASE_COST                         (             100UL)
     292             : 
     293             : /* FD_VM_CURVE25519_EDWARDS_VALIDATE_POINT_COST is the number of compute
     294             :    units consumed to validate a curve25519 edwards point */
     295             : 
     296             : #define FD_VM_CURVE25519_EDWARDS_VALIDATE_POINT_COST    (             159UL)
     297             : 
     298             : /* FD_VM_CURVE25519_EDWARDS_ADD_COST is the number of compute units
     299             :    consumed to add two curve25519 edwards points */
     300             : 
     301           0 : #define FD_VM_CURVE25519_EDWARDS_ADD_COST               (             473UL)
     302             : 
     303             : /* FD_VM_CURVE25519_EDWARDS_SUBTRACT_COST is the number of compute units
     304             :    consumed to subtract two curve25519 edwards points */
     305             : 
     306           0 : #define FD_VM_CURVE25519_EDWARDS_SUBTRACT_COST          (             475UL)
     307             : 
     308             : /* FD_VM_CURVE25519_EDWARDS_MULTIPLY_COST is the number of compute units
     309             :    consumed to multiply a curve25519 edwards point */
     310             : 
     311           0 : #define FD_VM_CURVE25519_EDWARDS_MULTIPLY_COST          (            2177UL)
     312             : 
     313             : /* FD_VM_CURVE25519_EDWARDS_MSM_BASE_COST is the number of compute units
     314             :    consumed for a multiscalar multiplication (msm) of edwards points.
     315             :    The total cost is calculated as
     316             :      `msm_base_cost + (length - 1) * msm_incremental_cost` */
     317             : 
     318           6 : #define FD_VM_CURVE25519_EDWARDS_MSM_BASE_COST          (            2273UL)
     319             : 
     320             : /* FD_VM_CURVE25519_EDWARDS_MSM_INCREMENTAL_COST is the number of
     321             :    compute units consumed for a multiscalar multiplication (msm) of
     322             :    edwards points.  The total cost is calculated as
     323             :      `msm_base_cost + (length - 1) * msm_incremental_cost` */
     324             : 
     325           6 : #define FD_VM_CURVE25519_EDWARDS_MSM_INCREMENTAL_COST   (             758UL)
     326             : 
     327             : /* FD_VM_CURVE25519_RISTRETTO_VALIDATE_POINT_COST is the number of
     328             :    compute units consumed to validate a curve25519 ristretto point */
     329             : 
     330             : #define FD_VM_CURVE25519_RISTRETTO_VALIDATE_POINT_COST  (             169UL)
     331             : 
     332             : /* FD_VM_CURVE25519_RISTRETTO_ADD_COST is the number of compute units
     333             :    consumed to add two curve25519 ristretto points */
     334             : 
     335           6 : #define FD_VM_CURVE25519_RISTRETTO_ADD_COST             (             521UL)
     336             : 
     337             : /* FD_VM_CURVE25519_RISTRETTO_SUBTRACT_COST is the number of compute
     338             :    units consumed to subtract two curve25519 ristretto points */
     339             : 
     340           3 : #define FD_VM_CURVE25519_RISTRETTO_SUBTRACT_COST        (             519UL)
     341             : 
     342             : /* FD_VM_CURVE25519_RISTRETTO_MULTIPLY_COST is the number of compute
     343             :    units consumed to multiply a curve25519 ristretto point */
     344             : 
     345           3 : #define FD_VM_CURVE25519_RISTRETTO_MULTIPLY_COST        (            2208UL)
     346             : 
     347             : /* FD_VM_CURVE25519_RISTRETTO_MSM_BASE_COST is the number of compute
     348             :    units consumed for a multiscalar multiplication (msm) of ristretto
     349             :    points.  The total cost is calculated as
     350             :      `msm_base_cost + (length - 1) * msm_incremental_cost` */
     351             : 
     352           3 : #define FD_VM_CURVE25519_RISTRETTO_MSM_BASE_COST        (            2303UL)
     353             : 
     354             : /* FD_VM_CURVE25519_RISTRETTO_MSM_INCREMENTAL_COST is the number of
     355             :    compute units consumed for a multiscalar multiplication (msm) of
     356             :    ristretto points.  The total cost is calculated as
     357             :      `msm_base_cost + (length - 1) * msm_incremental_cost` */
     358             : 
     359           3 : #define FD_VM_CURVE25519_RISTRETTO_MSM_INCREMENTAL_COST (             788UL)
     360             : 
     361             : /* FD_VM_HEAP_SIZE is the program heap region size, default:
     362             :    solana_sdk::entrypoint::HEAP_LENGTH */
     363             : 
     364             : #define FD_VM_HEAP_SIZE                                 (           32768UL)
     365             : 
     366             : /* FD_VM_HEAP_COST is the number of compute units per additional 32k
     367             :    heap above the default (~.5 us per 32k at 15 units/us rounded up) */
     368             : 
     369           0 : #define FD_VM_HEAP_COST                                 (               8UL) /* DEFAULT_HEAP_COST */
     370             : 
     371             : /* FD_VM_MEM_OP_BASE_COST is the memory operation syscall base cost */
     372             : 
     373           0 : #define FD_VM_MEM_OP_BASE_COST                          (              10UL)
     374             : 
     375             : /* FD_VM_ALT_BN128_ADDITION_COST is the number of compute units consumed
     376             :    to call alt_bn128_addition */
     377             : 
     378           0 : #define FD_VM_ALT_BN128_ADDITION_COST                   (             334UL)
     379             : 
     380             : /* FD_VM_ALT_BN128_MULTIPLICATION_COST is the number of compute units
     381             :    consumed to call alt_bn128_multiplication */
     382             : 
     383           0 : #define FD_VM_ALT_BN128_MULTIPLICATION_COST             (            3840UL)
     384             : 
     385             : /* FD_VM_ALT_BN128_PAIRING_ONE_PAIR_COST_FIRST
     386             :    FD_VM_ALT_BN128_PAIRING_ONE_PAIR_COST_OTHER give the total cost as
     387             :      alt_bn128_pairing_one_pair_cost_first + alt_bn128_pairing_one_pair_cost_other * (num_elems - 1) */
     388             : 
     389           0 : #define FD_VM_ALT_BN128_PAIRING_ONE_PAIR_COST_FIRST     (           36364UL)
     390           0 : #define FD_VM_ALT_BN128_PAIRING_ONE_PAIR_COST_OTHER     (           12121UL)
     391             : 
     392             : /* FD_VM_BIG_MODULAR_EXPONENTIATION_COST is the big integer modular
     393             :    exponentiation cost */
     394             : 
     395             : #define FD_VM_BIG_MODULAR_EXPONENTIATION_COST           (              33UL)
     396             : 
     397             : /* FD_VM_POSEIDON_COST_COEFFICIENT_A is the coefficient `a` of the
     398             :    quadratic function which determines the number of compute units
     399             :    consumed to call poseidon syscall for a given number of inputs */
     400             : 
     401           0 : #define FD_VM_POSEIDON_COST_COEFFICIENT_A               (              61UL)
     402             : 
     403             : /* FD_VM_POSEIDON_COST_COEFFICIENT_C is the coefficient `c` of the
     404             :    quadratic function which determines the number of compute units
     405             :    consumed to call poseidon syscall for a given number of inputs */
     406             : 
     407           0 : #define FD_VM_POSEIDON_COST_COEFFICIENT_C               (             542UL)
     408             : 
     409             : /* FD_VM_GET_REMAINING_COMPUTE_UNITS_COST is the number of compute units
     410             :    consumed for reading the remaining compute units */
     411             : 
     412             : #define FD_VM_GET_REMAINING_COMPUTE_UNITS_COST          (             100UL)
     413             : 
     414             : /* FD_VM_ALT_BN128_G1_COMPRESS is the number of compute units consumed
     415             :    to call alt_bn128_g1_compress */
     416             : 
     417           0 : #define FD_VM_ALT_BN128_G1_COMPRESS                     (              30UL)
     418             : 
     419             : /* FD_VM_ALT_BN128_G1_DECOMPRESS is the number of compute units consumed
     420             :    to call alt_bn128_g1_decompress */
     421             : 
     422           0 : #define FD_VM_ALT_BN128_G1_DECOMPRESS                   (             398UL)
     423             : 
     424             : /* FD_VM_ALT_BN128_G2_COMPRESS is the number of compute units consumed
     425             :    to call alt_bn128_g2_compress */
     426             : 
     427           0 : #define FD_VM_ALT_BN128_G2_COMPRESS                     (              86UL)
     428             : 
     429             : /* FD_VM_ALT_BN128_G2_DECOMPRESS is the number of compute units consumed
     430             :    to call alt_bn128_g2_decompress */
     431             : 
     432           0 : #define FD_VM_ALT_BN128_G2_DECOMPRESS                   (           13610UL)
     433             : 
     434             : /* FD_VM_LOADED_ACCOUNTS_DATA_SIZE_LIMIT is the maximum accounts data
     435             :    size, in bytes, that a transaction is allowed to load */
     436             : 
     437           0 : #define FD_VM_LOADED_ACCOUNTS_DATA_SIZE_LIMIT           (64UL*1024UL*1024UL) /* 64MiB */
     438             : 
     439             : /* fd_vm_disasm API ***************************************************/
     440             : 
     441             : /* FIXME: pretty good case this actually belongs in ballet/sbpf */
     442             : /* FIXME: fd_sbpf_instr_t is nominally a ulong but implemented using
     443             :    bit-fields.  Compilers tend to generate notoriously poor asm for bit
     444             :    fields ... check ASM here. */
     445             : 
     446             : FD_PROTOTYPES_BEGIN
     447             : 
     448             : /* fd_vm_disasm_{instr,program} appends to the *_out_len (in strlen
     449             :    sense) cstr in the out_max byte buffer out a pretty printed cstr of
     450             :    the {instruction,program}.  If syscalls is non-NULL, syscalls will be
     451             :    annotated with the names from the provided syscall mapping.
     452             : 
     453             :    On input, *_out_len should be strlen(out) and in [0,out_max).  For
     454             :    instr, pc is the program counter corresponding to text[0] (as such
     455             :    text_cnt should be positive) and text_cnt is the number of words
     456             :    available at text to support safely printing multiword instructions.
     457             : 
     458             :    Given a valid out on input, on output, *_out_len will be strlen(out)
     459             :    and in [0,out_max), even if there was an error.
     460             : 
     461             :    Returns:
     462             : 
     463             :    FD_VM_SUCCESS - out buffer and *_out_len updated.
     464             : 
     465             :    FD_VM_ERR_INVAL - Invalid input.  For instr, out buffer and *_out_len
     466             :    are unchanged.  For program, out buffer and *_out_len will have been
     467             :    updated up to the point where the error occurred.
     468             : 
     469             :    FD_VM_ERR_UNSUP - For program, too many functions and/or labels for
     470             :    the current implementation.  out buffer and *_out_len unchanged.
     471             : 
     472             :    FD_VM_ERR_FULL - Not enough room in out to hold the result so output
     473             :    was truncated.  out buffer and *_out_len updated.
     474             : 
     475             :    FD_VM_ERR_IO - An error occured formatting the string to append.  For
     476             :    instr, out_buffer and *_out_len unchanged.  For program, out buffer
     477             :    and *_out_len will have been updated up to the point where the error
     478             :    occurred.  In both cases, trailing bytes of out might have been
     479             :    clobbered. */
     480             : 
     481             : int
     482             : fd_vm_disasm_instr( ulong const *              text,      /* Indexed [0,text_cnt) */
     483             :                     ulong                      text_cnt,
     484             :                     ulong                      pc,
     485             :                     fd_sbpf_syscalls_t const * syscalls,
     486             :                     char *                     out,       /* Indexed [0,out_max) */
     487             :                     ulong                      out_max,
     488             :                     ulong *                    _out_len );
     489             : 
     490             : int
     491             : fd_vm_disasm_program( ulong const *              text,       /* Indexed [0,text_cnt) */
     492             :                       ulong                      text_cnt,
     493             :                       fd_sbpf_syscalls_t const * syscalls,
     494             :                       char *                     out,        /* Indexed [0,out_max) */
     495             :                       ulong                      out_max,
     496             :                       ulong *                    _out_len );
     497             : 
     498             : FD_PROTOTYPES_END
     499             : 
     500             : /* fd_vm_trace API ****************************************************/
     501             : 
     502             : /* FIXME: pretty good case this actually belongs in ballet/sbpf */
     503             : 
     504             : /* A FD_VM_TRACE_EVENT_TYPE_* indicates how a fd_vm_trace_event_t should
     505             :    be interpreted. */
     506             : 
     507          30 : #define FD_VM_TRACE_EVENT_TYPE_EXE   (0)
     508          24 : #define FD_VM_TRACE_EVENT_TYPE_READ  (1)
     509          24 : #define FD_VM_TRACE_EVENT_TYPE_WRITE (2)
     510             : 
     511             : struct fd_vm_trace_event_exe {
     512             :   /* This point is aligned 8 */
     513             :   ulong info;                 /* Event info bit field */
     514             :   ulong pc;                   /* pc */
     515             :   ulong ic;                   /* ic */
     516             :   ulong cu;                   /* cu */
     517             :   ulong ic_correction;        /* ic_correction */
     518             :   ulong frame_cnt;            /* frame_cnt */
     519             :   ulong reg[ FD_VM_REG_CNT ]; /* registers */
     520             :   ulong text[ 2 ];            /* If the event has valid clear, this is actually text[1] */
     521             :   /* This point is aligned 8 */
     522             : };
     523             : 
     524             : typedef struct fd_vm_trace_event_exe fd_vm_trace_event_exe_t;
     525             : 
     526             : struct fd_vm_trace_event_mem {
     527             :   /* This point is aligned 8 */
     528             :   ulong info;  /* Event info bit field */
     529             :   ulong vaddr; /* VM address range associated with event */
     530             :   ulong sz;
     531             :   /* This point is aligned 8
     532             :      If event has valid set:
     533             :        min(sz,event_data_max) bytes user data bytes
     534             :        padding to aligned 8 */
     535             : };
     536             : 
     537             : typedef struct fd_vm_trace_event_mem fd_vm_trace_event_mem_t;
     538             : 
     539           3 : #define FD_VM_TRACE_MAGIC (0xfdc377ace3a61c00UL) /* FD VM TRACE MAGIC version 0 */
     540             : 
     541             : struct fd_vm_trace {
     542             :   /* This point is aligned 8 */
     543             :   ulong magic;          /* ==FD_VM_TRACE_MAGIC */
     544             :   ulong event_max;      /* Number bytes of event storage */
     545             :   ulong event_data_max; /* Max bytes to capture per data event */
     546             :   ulong event_sz;       /* Used bytes of event storage */
     547             :   /* This point is aligned 8
     548             :      event_max bytes storage
     549             :      padding to aligned 8 */
     550             : };
     551             : 
     552             : typedef struct fd_vm_trace fd_vm_trace_t;
     553             : 
     554             : FD_PROTOTYPES_BEGIN
     555             : 
     556             : /* trace object structors */
     557             : /* FIXME: DOCUMENT (USUAL CONVENTIONS) */
     558             : 
     559             : FD_FN_CONST ulong
     560             : fd_vm_trace_align( void );
     561             : 
     562             : FD_FN_CONST ulong
     563             : fd_vm_trace_footprint( ulong event_max,        /* Maximum amount of event storage (<=1 EiB) */
     564             :                        ulong event_data_max ); /* Maximum number of bytes that can be captured in an event (<=1 EiB) */
     565             : 
     566             : void *
     567             : fd_vm_trace_new( void * shmem,
     568             :                  ulong  event_max,
     569             :                  ulong  event_data_max );
     570             : 
     571             : fd_vm_trace_t *
     572             : fd_vm_trace_join( void * _trace );
     573             : 
     574             : void *
     575             : fd_vm_trace_leave( fd_vm_trace_t * trace );
     576             : 
     577             : void *
     578             : fd_vm_trace_delete( void * _trace );
     579             : 
     580             : /* Given a current local join, fd_vm_trace_event returns the location in
     581             :    the caller's address space where trace events are stored and
     582             :    fd_vm_trace_event_sz returns number of bytes of trace events stored
     583             :    at that location.  event_max is the number of bytes of event storage
     584             :    (value used to construct the trace) and event_data_max is the maximum
     585             :    number of data bytes that can be captured per event (value used to
     586             :    construct the trace).  event will be aligned 8 and event_sz will be a
     587             :    multiple of 8 in [0,event_max].  The lifetime of the returned pointer
     588             :    is the lifetime of the current join.  The first 8 bytes of an event
     589             :    are an info field used by trace inspection tools how to interpret the
     590             :    event. */
     591             : 
     592           6 : FD_FN_CONST static inline void const * fd_vm_trace_event         ( fd_vm_trace_t const * trace ) { return (void *)(trace+1);     }
     593           6 : FD_FN_CONST static inline ulong        fd_vm_trace_event_sz      ( fd_vm_trace_t const * trace ) { return trace->event_sz;       }
     594           3 : FD_FN_CONST static inline ulong        fd_vm_trace_event_max     ( fd_vm_trace_t const * trace ) { return trace->event_max;      }
     595           6 : FD_FN_CONST static inline ulong        fd_vm_trace_event_data_max( fd_vm_trace_t const * trace ) { return trace->event_data_max; }
     596             : 
     597             : /* fd_vm_trace_event_info returns the event info corresponding to the
     598             :    given (type,valid) tuple.  Assumes type is a FD_VM_TRACE_EVENT_TYPE_*
     599             :    and that valid is in [0,1].  fd_vm_trace_event_info_{type,valid}
     600             :    extract from the given info {type,valid}.  Assumes info is valid. */
     601             : 
     602          45 : FD_FN_CONST static inline ulong fd_vm_trace_event_info( int type, int valid ) { return (ulong)((valid<<2) | type); }
     603             : 
     604          45 : FD_FN_CONST static inline int fd_vm_trace_event_info_type ( ulong info ) { return (int)(info & 3UL); } /* EVENT_TYPE_* */
     605          45 : FD_FN_CONST static inline int fd_vm_trace_event_info_valid( ulong info ) { return (int)(info >> 2);  } /* In [0,1] */
     606             : 
     607             : /* fd_vm_trace_reset frees all events in the trace.  Returns
     608             :    FD_VM_SUCCESS (0) on success or FD_VM_ERR code (negative) on failure.
     609             :    Reasons for failure include NULL trace. */
     610             : 
     611             : static inline int
     612           0 : fd_vm_trace_reset( fd_vm_trace_t * trace ) {
     613           0 :   if( FD_UNLIKELY( !trace ) ) return FD_VM_ERR_INVAL;
     614           0 :   trace->event_sz = 0UL;
     615           0 :   return FD_VM_SUCCESS;
     616           0 : }
     617             : 
     618             : /* fd_vm_trace_event_exe records the current pc, ic, cu and
     619             :    register file of the VM and the instruction about to execute.  Text
     620             :    points to the first word of the instruction about to execute and
     621             :    text_cnt points to the number of words available at that point.
     622             :    Returns FD_VM_SUCCESS (0) on success and a FD_VM_ERR code (negative)
     623             :    on failure.  Reasons for failure include INVAL (trace NULL, reg NULL,
     624             :    text NULL, and/or text_cnt 0) and FULL (insufficient trace event
     625             :    storage available). */
     626             : 
     627             : int
     628             : fd_vm_trace_event_exe( fd_vm_trace_t * trace,
     629             :                        ulong           pc,
     630             :                        ulong           ic,
     631             :                        ulong           cu,
     632             :                        ulong           reg[ FD_VM_REG_CNT ],
     633             :                        ulong const *   text,       /* Indexed [0,text_cnt) */
     634             :                        ulong           text_cnt,
     635             :                        ulong           ic_correction,
     636             :                        ulong           frame_cnt );
     637             : 
     638             : /* fd_vm_trace_event_mem records an attempt to access the VM address
     639             :    range [vaddr,vaddr+sz).  If write==0, it was a read attempt,
     640             :    otherwise, it was a write attempt.  Data points to the location of
     641             :    the memory range in host memory or NULL if the range is invalid.  If
     642             :    data is not NULL and sz is non-zero, this will record
     643             :    min(sz,event_data_max) of data for the event and mark the event has
     644             :    having valid data.  Returns FD_VM_SUCCESS (0) on success and a
     645             :    FD_VM_ERR code (negative) on failure.  Reasons for failure include
     646             :    INVAL (trace NULL) and FULL (insufficient trace event storage
     647             :    available to store the event). */
     648             : 
     649             : int
     650             : fd_vm_trace_event_mem( fd_vm_trace_t * trace,
     651             :                        int             write,
     652             :                        ulong           vaddr,
     653             :                        ulong           sz,
     654             :                        void *          data );
     655             : 
     656             : /* fd_vm_trace_printf pretty prints the current trace to stdout.  If
     657             :    syscalls is non-NULL, the trace will annotate syscalls in its
     658             :    disassembly according the syscall mapping.  Returns FD_VM_SUCCESS (0)
     659             :    on success and a FD_VM_ERR code (negative) on failure.  Reasons for
     660             :    failure include INVAL (NULL trace) and IO (corruption detected while
     661             :    parsing the trace events).  FIXME: REVAMP THIS API FOR MORE GENERAL
     662             :    USE CASES. */
     663             : 
     664             : int
     665             : fd_vm_trace_printf( fd_vm_trace_t      const * trace,
     666             :                     fd_sbpf_syscalls_t const * syscalls );
     667             : 
     668             : /* fd_vm_syscall API **************************************************/
     669             : 
     670             : /* FIXME: fd_sbpf_syscalls_t and fd_sbpf_syscall_func_t probably should
     671             :    be moved from ballet/sbpf to here. */
     672             : 
     673             : /* Note: the syscall map is kept separate from the fd_vm_t itself to
     674             :    support, for example, multiple fd_vm_t executing transactions
     675             :    concurrently for a slot.  They could use the same syscalls for setup,
     676             :    memory and cache efficiency. */
     677             : 
     678             : /* fd_vm_syscall_register inserts the syscall with the given cstr name
     679             :    into the given syscalls.  The VM syscall implementation to use is
     680             :    given by func (NULL is fine though a VM itself may not accept such as
     681             :    valid).  The caller promises there is room in the syscall map.
     682             :    Returns FD_VM_SUCCESS (0) on success or a FD_VM_ERR code (negative)
     683             :    on failure.  Reasons for failure include INVAL (NULL syscalls, NULL
     684             :    name, name or the hash of name already in the map).  On success,
     685             :    syscalls retains a read-only interest in name (e.g. use an infinite
     686             :    lifetime cstr here).  (This function is exposed to allow VM users to
     687             :    add custom syscalls but most use cases probably should just call
     688             :    fd_vm_syscall_register_slot below.)
     689             : 
     690             :    IMPORTANT SAFETY TIP!  See notes in syscall/fd_vm_syscall.h on what a
     691             :    syscall should expect to see and what to return. */
     692             : 
     693             : int
     694             : fd_vm_syscall_register( fd_sbpf_syscalls_t *   syscalls,
     695             :                         char const *           name,
     696             :                         fd_sbpf_syscall_func_t func );
     697             : 
     698             : /* fd_vm_syscall_register_slot unmaps all syscalls in the current map
     699             :    (also ending any interest in the corresponding name cstr) and
     700             :    registers all syscalls appropriate for the slot described by
     701             :    slot_ctx.  Returns FD_VM_SUCCESS (0) on success and FD_VM_ERR code
     702             :    (negative) on failure.  Reasons for failure include INVAL (NULL
     703             :    syscalls) and FULL (tried to register too many system calls ...
     704             :    compile time map size needs to be adjusted).  If slot_ctx is NULL,
     705             :    will register all fd_vm syscall implementations (whether or not that
     706             :    makes sense ... may change between Firedancer versions without
     707             :    warning).  FIXME: probably better to pass the features for a slot
     708             :    than pass the whole slot_ctx.
     709             : 
     710             :    is_deploy should be 1 if the set of syscalls registered should be that
     711             :    used to verify programs before they are deployed, and 0 if it
     712             :    should be the set used to execute programs. */
     713             : 
     714             : int
     715             : fd_vm_syscall_register_slot( fd_sbpf_syscalls_t * syscalls,
     716             :                              ulong                slot,
     717             :                              fd_features_t *      features,
     718             :                              uchar                is_deploy );
     719             : 
     720             : /* fd_vm_syscall_register_all is a shorthand for registering all
     721             :    syscalls (see register slot). */
     722             : 
     723             : static inline int
     724           0 : fd_vm_syscall_register_all( fd_sbpf_syscalls_t * syscalls, uchar is_deploy ) {
     725           0 :   return fd_vm_syscall_register_slot( syscalls, 0UL, NULL, is_deploy );
     726           0 : }
     727             : 
     728             : FD_PROTOTYPES_END
     729             : 
     730             : #endif /* HEADER_fd_src_flamenco_vm_fd_vm_base_h */

Generated by: LCOV version 1.14