LCOV - code coverage report
Current view: top level - flamenco/vm/syscall - fd_vm_syscall_hash.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 54 84 64.3 %
Date: 2026-10-22 18:10:43 Functions: 2 3 66.7 %

          Line data    Source code
       1             : #include "fd_vm_syscall.h"
       2             : 
       3             : #include "../../../ballet/keccak256/fd_keccak256.h"
       4             : #include "../../../ballet/sha512/fd_sha512.h"
       5             : 
       6             : /* Syscalls for sha256, keccak256, sha512. */
       7             : 
       8             : /* Agave has a single generic hash syscall:
       9             :    https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1895-L1959
      10             :    With trait impl for sha256 and keccak256:
      11             :    https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L130-L225
      12             : 
      13             :    Notes:
      14             :    1. Max slices, base cost and byte cost are the same for all hash functions:
      15             :       - https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L189-L197
      16             :       - https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L216-L224
      17             :    2. Poseidon doesn't follow this generic hash implementation (so we left it in fd_vm_syscall_crypto.c):
      18             :       - https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1678
      19             : 
      20             :    Implementation notes.
      21             :    Because of the notes above, we implemented fd_vm_syscall_sol_sha256() following the generic hash
      22             :    syscall step by step.
      23             :    The other implementations are just a copy & paste, replacing the hash function.
      24             :    Resisted the temptation to do a macro, because it would complicate future changes, for example if
      25             :    we were to modify CU costs. */
      26             : 
      27             : int
      28             : fd_vm_syscall_sol_sha256( /**/            void *  _vm,
      29             :                           /**/            ulong   vals_addr,
      30             :                           /**/            ulong   vals_len,
      31             :                           /**/            ulong   result_addr,
      32             :                           FD_PARAM_UNUSED ulong   r4,
      33         296 :                           FD_PARAM_UNUSED ulong   r5 ) {
      34             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1897 */
      35         296 :   fd_vm_t * vm = (fd_vm_t *)_vm;
      36             : 
      37             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1911-L1920 */
      38         296 :   if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
      39             :     /* Max msg_sz = 61 - 8 + 6 + 20 + 20 = 99 < 127 => we can use printf */
      40           1 :     fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
      41           1 :       "%s Hashing %lu sequences in one syscall is over the limit %lu",
      42           1 :       "Sha256", vals_len, FD_VM_SHA256_MAX_SLICES );
      43           1 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
      44           1 :     return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES; /* SyscallError::TooManySlices */
      45           1 :   }
      46             : 
      47             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1922 */
      48         589 :   FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
      49         279 :   uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, 32UL );
      50             : 
      51             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1930 */
      52         279 :   fd_sha256_t sha[1];
      53         279 :   fd_sha256_init( sha );
      54             : 
      55         279 :   if( vals_len > 0 ) {
      56             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1932-L1937 */
      57         788 :     fd_vm_vec_t const * input_vec_haddr = (fd_vm_vec_t const *)FD_VM_MEM_HADDR_LD( vm, vals_addr, FD_VM_VEC_ALIGN, vals_len*sizeof(fd_vm_vec_t) );
      58        3713 :     for( ulong i=0UL; i<vals_len; i++ ) {
      59             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1939-L1944 */
      60        3456 :       ulong val_len = input_vec_haddr[i].len;
      61        6910 :       void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
      62             : 
      63             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1945-L1951 */
      64        3454 :       ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
      65        6910 :                                  fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
      66             : 
      67             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1952 */
      68        6910 :       FD_VM_CU_UPDATE( vm, cost );
      69             : 
      70             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1953 */
      71           0 :       fd_sha256_append( sha, bytes, val_len );
      72        3451 :     }
      73         788 :   }
      74             : 
      75             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1956-L1957 */
      76         272 :   fd_sha256_fini( sha, hash_result );
      77         272 :   vm->reg[0] = 0UL;
      78         272 :   return FD_VM_SUCCESS;
      79         279 : }
      80             : 
      81             : int
      82             : fd_vm_syscall_sol_keccak256( /**/            void *  _vm,
      83             :                              /**/            ulong   vals_addr,
      84             :                              /**/            ulong   vals_len,
      85             :                              /**/            ulong   result_addr,
      86             :                              FD_PARAM_UNUSED ulong   r4,
      87         250 :                              FD_PARAM_UNUSED ulong   r5 ) {
      88             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1897 */
      89         250 :   fd_vm_t * vm = (fd_vm_t *)_vm;
      90             : 
      91             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1911-L1920 */
      92         250 :   if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
      93             :     /* Max msg_sz = 61 - 8 + 9 + 20 + 20 = 102 < 127 => we can use printf */
      94           1 :     fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
      95           1 :       "%s Hashing %lu sequences in one syscall is over the limit %lu",
      96           1 :       "Keccak256", vals_len, FD_VM_SHA256_MAX_SLICES );
      97           1 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
      98           1 :     return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES; /* SyscallError::TooManySlices */
      99           1 :   }
     100             : 
     101             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1922 */
     102         497 :   FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
     103         236 :   uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, 32UL );
     104             : 
     105             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1930 */
     106         236 :   fd_keccak256_t sha[1];
     107         236 :   fd_keccak256_init( sha );
     108             : 
     109         236 :   if( vals_len > 0 ) {
     110             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1932-L1937 */
     111         680 :     fd_vm_vec_t const * input_vec_haddr = (fd_vm_vec_t const *)FD_VM_MEM_HADDR_LD( vm, vals_addr, FD_VM_VEC_ALIGN, vals_len*sizeof(fd_vm_vec_t) );
     112        3390 :     for( ulong i=0UL; i<vals_len; i++ ) {
     113             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1939-L1944 */
     114        3169 :       ulong val_len = input_vec_haddr[i].len;
     115        6336 :       void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
     116             : 
     117             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1945-L1951 */
     118        3167 :       ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
     119        6336 :                                   fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
     120             : 
     121             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1952 */
     122        6336 :       FD_VM_CU_UPDATE( vm, cost );
     123             : 
     124             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1953 */
     125           0 :       fd_keccak256_append( sha, bytes, val_len );
     126        3164 :     }
     127         680 :   }
     128             : 
     129             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1956-L1957 */
     130         229 :   fd_keccak256_fini( sha, hash_result );
     131         229 :   vm->reg[0] = 0UL;
     132         229 :   return FD_VM_SUCCESS;
     133         236 : }
     134             : 
     135             : int
     136             : fd_vm_syscall_sol_sha512( /**/            void *  _vm,
     137             :                           /**/            ulong   vals_addr,
     138             :                           /**/            ulong   vals_len,
     139             :                           /**/            ulong   result_addr,
     140             :                           FD_PARAM_UNUSED ulong   r4,
     141           0 :                           FD_PARAM_UNUSED ulong   r5 ) {
     142           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     143             : 
     144           0 :   if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
     145           0 :     fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
     146           0 :       "%s Hashing %lu sequences in one syscall is over the limit %lu",
     147           0 :       "Sha512", vals_len, FD_VM_SHA256_MAX_SLICES );
     148           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
     149           0 :     return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES;
     150           0 :   }
     151             : 
     152           0 :   FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
     153           0 :   uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, FD_SHA512_HASH_SZ );
     154             : 
     155           0 :   fd_sha512_t sha[1];
     156           0 :   fd_sha512_init( sha );
     157             : 
     158           0 :   if( vals_len > 0 ) {
     159           0 :     fd_vm_vec_t const * input_vec_haddr = (fd_vm_vec_t const *)FD_VM_MEM_HADDR_LD( vm, vals_addr, FD_VM_VEC_ALIGN, vals_len*sizeof(fd_vm_vec_t) );
     160           0 :     for( ulong i=0UL; i<vals_len; i++ ) {
     161           0 :       ulong val_len = input_vec_haddr[i].len;
     162           0 :       void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
     163             : 
     164           0 :       ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
     165           0 :                                  fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
     166             : 
     167           0 :       FD_VM_CU_UPDATE( vm, cost );
     168             : 
     169           0 :       fd_sha512_append( sha, bytes, val_len );
     170           0 :     }
     171           0 :   }
     172             : 
     173           0 :   fd_sha512_fini( sha, hash_result );
     174           0 :   vm->reg[0] = 0UL;
     175           0 :   return FD_VM_SUCCESS;
     176           0 : }

Generated by: LCOV version 1.14