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: 112 112 100.0 %
Date: 2026-06-08 09:27:03 Functions: 4 4 100.0 %

          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, blake3, 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, keccak256 and blake3:
      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 3 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             :                           FD_PARAM_UNUSED ulong   r5,
      34          15 :                           /**/            ulong * _ret ) {
      35             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1897 */
      36          15 :   fd_vm_t * vm = (fd_vm_t *)_vm;
      37             : 
      38             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1911-L1920 */
      39          15 :   if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
      40             :     /* Max msg_sz = 61 - 8 + 6 + 20 + 20 = 99 < 127 => we can use printf */
      41           3 :     fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
      42           3 :       "%s Hashing %lu sequences in one syscall is over the limit %lu",
      43           3 :       "Sha256", vals_len, FD_VM_SHA256_MAX_SLICES );
      44           3 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
      45           3 :     return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES; /* SyscallError::TooManySlices */
      46           3 :   }
      47             : 
      48             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1922 */
      49          24 :   FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
      50          24 :   uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, 32UL );
      51             : 
      52             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1930 */
      53          12 :   fd_sha256_t sha[1];
      54          12 :   fd_sha256_init( sha );
      55             : 
      56          12 :   if( vals_len > 0 ) {
      57             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1932-L1937 */
      58          27 :     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) );
      59          27 :     for( ulong i=0UL; i<vals_len; i++ ) {
      60             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1939-L1944 */
      61          12 :       ulong val_len = input_vec_haddr[i].len;
      62          24 :       void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
      63             : 
      64             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1945-L1951 */
      65          24 :       ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
      66          24 :                                  fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
      67             : 
      68             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1952 */
      69          24 :       FD_VM_CU_UPDATE( vm, cost );
      70             : 
      71             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1953 */
      72          12 :       fd_sha256_append( sha, bytes, val_len );
      73          12 :     }
      74          27 :   }
      75             : 
      76             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1956-L1957 */
      77          12 :   fd_sha256_fini( sha, hash_result );
      78          12 :   *_ret = 0UL;
      79          12 :   return FD_VM_SUCCESS;
      80          12 : }
      81             : 
      82             : int
      83             : fd_vm_syscall_sol_blake3( /**/            void *  _vm,
      84             :                           /**/            ulong   vals_addr,
      85             :                           /**/            ulong   vals_len,
      86             :                           /**/            ulong   result_addr,
      87             :                           FD_PARAM_UNUSED ulong   r4,
      88             :                           FD_PARAM_UNUSED ulong   r5,
      89          15 :                           /**/            ulong * _ret ) {
      90             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1897 */
      91          15 :   fd_vm_t * vm = (fd_vm_t *)_vm;
      92             : 
      93             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1911-L1920 */
      94          15 :   if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
      95             :     /* Max msg_sz = 61 - 8 + 6 + 20 + 20 = 99 < 127 => we can use printf */
      96           3 :     fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
      97           3 :       "%s Hashing %lu sequences in one syscall is over the limit %lu",
      98           3 :       "Blake3", vals_len, FD_VM_SHA256_MAX_SLICES );
      99           3 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
     100           3 :     return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES; /* SyscallError::TooManySlices */
     101           3 :   }
     102             : 
     103             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1922 */
     104          24 :   FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
     105          24 :   uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, 32UL );
     106             : 
     107             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1930 */
     108          12 :   fd_blake3_t sha[1];
     109          12 :   fd_blake3_init( sha );
     110             : 
     111          12 :   if( vals_len > 0 ) {
     112             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1932-L1937 */
     113          27 :     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) );
     114          27 :     for( ulong i=0UL; i<vals_len; i++ ) {
     115             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1939-L1944 */
     116          12 :       ulong val_len = input_vec_haddr[i].len;
     117          24 :       void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
     118             : 
     119             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1945-L1951 */
     120          24 :       ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
     121          24 :                                  fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
     122             : 
     123             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1952 */
     124          24 :       FD_VM_CU_UPDATE( vm, cost );
     125             : 
     126             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1953 */
     127          12 :       fd_blake3_append( sha, bytes, val_len );
     128          12 :     }
     129          27 :   }
     130             : 
     131             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1956-L1957 */
     132          12 :   fd_blake3_fini( sha, hash_result );
     133          12 :   *_ret = 0UL;
     134          12 :   return FD_VM_SUCCESS;
     135          12 : }
     136             : 
     137             : int
     138             : fd_vm_syscall_sol_keccak256( /**/            void *  _vm,
     139             :                              /**/            ulong   vals_addr,
     140             :                              /**/            ulong   vals_len,
     141             :                              /**/            ulong   result_addr,
     142             :                              FD_PARAM_UNUSED ulong   r4,
     143             :                              FD_PARAM_UNUSED ulong   r5,
     144          15 :                              /**/            ulong * _ret ) {
     145             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1897 */
     146          15 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     147             : 
     148             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1911-L1920 */
     149          15 :   if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
     150             :     /* Max msg_sz = 61 - 8 + 9 + 20 + 20 = 102 < 127 => we can use printf */
     151           3 :     fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
     152           3 :       "%s Hashing %lu sequences in one syscall is over the limit %lu",
     153           3 :       "Keccak256", vals_len, FD_VM_SHA256_MAX_SLICES );
     154           3 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
     155           3 :     return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES; /* SyscallError::TooManySlices */
     156           3 :   }
     157             : 
     158             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1922 */
     159          24 :   FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
     160          24 :   uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, 32UL );
     161             : 
     162             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1930 */
     163          12 :   fd_keccak256_t sha[1];
     164          12 :   fd_keccak256_init( sha );
     165             : 
     166          12 :   if( vals_len > 0 ) {
     167             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1932-L1937 */
     168          27 :     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) );
     169          27 :     for( ulong i=0UL; i<vals_len; i++ ) {
     170             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1939-L1944 */
     171          12 :       ulong val_len = input_vec_haddr[i].len;
     172          24 :       void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
     173             : 
     174             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1945-L1951 */
     175          24 :       ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
     176          24 :                                   fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
     177             : 
     178             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1952 */
     179          24 :       FD_VM_CU_UPDATE( vm, cost );
     180             : 
     181             :       /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1953 */
     182          12 :       fd_keccak256_append( sha, bytes, val_len );
     183          12 :     }
     184          27 :   }
     185             : 
     186             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1956-L1957 */
     187          12 :   fd_keccak256_fini( sha, hash_result );
     188          12 :   *_ret = 0UL;
     189          12 :   return FD_VM_SUCCESS;
     190          12 : }
     191             : 
     192             : int
     193             : fd_vm_syscall_sol_sha512( /**/            void *  _vm,
     194             :                           /**/            ulong   vals_addr,
     195             :                           /**/            ulong   vals_len,
     196             :                           /**/            ulong   result_addr,
     197             :                           FD_PARAM_UNUSED ulong   r4,
     198             :                           FD_PARAM_UNUSED ulong   r5,
     199          15 :                           /**/            ulong * _ret ) {
     200          15 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     201             : 
     202          15 :   if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
     203           3 :     fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
     204           3 :       "%s Hashing %lu sequences in one syscall is over the limit %lu",
     205           3 :       "Sha512", vals_len, FD_VM_SHA256_MAX_SLICES );
     206           3 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
     207           3 :     return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES;
     208           3 :   }
     209             : 
     210          24 :   FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
     211          24 :   uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, FD_SHA512_HASH_SZ );
     212             : 
     213          12 :   fd_sha512_t sha[1];
     214          12 :   fd_sha512_init( sha );
     215             : 
     216          12 :   if( vals_len > 0 ) {
     217          27 :     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) );
     218          27 :     for( ulong i=0UL; i<vals_len; i++ ) {
     219          12 :       ulong val_len = input_vec_haddr[i].len;
     220          24 :       void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
     221             : 
     222          24 :       ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
     223          24 :                                  fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
     224             : 
     225          24 :       FD_VM_CU_UPDATE( vm, cost );
     226             : 
     227          12 :       fd_sha512_append( sha, bytes, val_len );
     228          12 :     }
     229          27 :   }
     230             : 
     231          12 :   fd_sha512_fini( sha, hash_result );
     232          12 :   *_ret = 0UL;
     233          12 :   return FD_VM_SUCCESS;
     234          12 : }

Generated by: LCOV version 1.14