LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_slot_hashes.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 49 57 86.0 %
Date: 2026-05-16 06:43:53 Functions: 4 4 100.0 %

          Line data    Source code
       1             : #include "fd_sysvar_slot_hashes.h"
       2             : #include "fd_sysvar.h"
       3             : #include "../fd_system_ids.h"
       4             : #include "../fd_accdb_svm.h"
       5             : 
       6             : void
       7             : fd_sysvar_slot_hashes_init( fd_bank_t *               bank,
       8             :                             fd_accdb_user_t *         accdb,
       9             :                             fd_funk_txn_xid_t const * xid,
      10          27 :                             fd_capture_ctx_t *        capture_ctx ) {
      11          27 :   uchar data[ FD_SYSVAR_SLOT_HASHES_BINCODE_SZ ] = {0};
      12          27 :   fd_sysvar_account_update( bank, accdb, xid, capture_ctx, &fd_sysvar_slot_hashes_id, data, FD_SYSVAR_SLOT_HASHES_BINCODE_SZ );
      13          27 : }
      14             : 
      15             : void
      16             : fd_sysvar_slot_hashes_update( fd_bank_t *               bank,
      17             :                               fd_accdb_user_t *         accdb,
      18             :                               fd_funk_txn_xid_t const * xid,
      19        5076 :                               fd_capture_ctx_t *        capture_ctx ) {
      20             : 
      21        5076 :   fd_accdb_rw_t rw[1];
      22        5076 :   fd_accdb_svm_update_t update[1];
      23        5076 :   if( FD_UNLIKELY( !fd_accdb_svm_open_rw( accdb, bank, xid, rw, update, &fd_sysvar_slot_hashes_id, 0UL, 0 ) ) ) {
      24             :     /* Agave initializes a new empty slot_hashes if it doesn't exist */
      25          21 :     fd_sysvar_slot_hashes_init( bank, accdb, xid, capture_ctx );
      26          21 :     if( FD_UNLIKELY( !fd_accdb_svm_open_rw( accdb, bank, xid, rw, update, &fd_sysvar_slot_hashes_id, 0UL, 0 ) ) ) {
      27           0 :       FD_LOG_ERR(( "state is missing slot hashes sysvar" ));
      28           0 :     }
      29          21 :   }
      30        5076 :   if( FD_UNLIKELY( 0!=memcmp( fd_accdb_ref_owner( rw->ro ), &fd_sysvar_owner_id, sizeof(fd_pubkey_t) ) ) ) {
      31           0 :     FD_LOG_ERR(( "slot hashes sysvar not owned by sysvar owner" ));
      32           0 :   }
      33        5076 :   uchar * data    = fd_accdb_ref_data   ( rw );
      34        5076 :   ulong   data_sz = fd_accdb_ref_data_sz( rw->ro );
      35        5076 :   if( FD_UNLIKELY( data_sz < FD_SYSVAR_SLOT_HASHES_BINCODE_SZ ) ) {
      36           0 :     FD_LOG_HEXDUMP_ERR(( "invalid slot hashes sysvar", data, data_sz ));
      37           0 :   }
      38             : 
      39        5076 :   ulong cnt = FD_LOAD( ulong, data );
      40        5076 :   if( FD_UNLIKELY( cnt > FD_SYSVAR_SLOT_HASHES_CAP ) ) {
      41           0 :     FD_LOG_HEXDUMP_ERR(( "corrupt slot hashes sysvar", data, data_sz ));
      42           0 :   }
      43             : 
      44             :   /* Search for existing entry with parent_slot */
      45        5076 :   fd_slot_hash_t * entries = (fd_slot_hash_t *)(data + sizeof(ulong));
      46        5076 :   int found = 0;
      47      399210 :   for( ulong i=0UL; i<cnt; i++ ) {
      48      394137 :     if( entries[i].slot == bank->f.parent_slot ) {
      49           3 :       fd_memcpy( &entries[i].hash, &bank->f.bank_hash, sizeof(fd_hash_t) );
      50           3 :       found = 1;
      51           3 :       break;
      52           3 :     }
      53      394137 :   }
      54             : 
      55        5076 :   if( !found ) {
      56        5073 :     ulong keep = fd_ulong_min( cnt, FD_SYSVAR_SLOT_HASHES_CAP - 1UL );
      57        5073 :     memmove( &entries[1], &entries[0], keep * sizeof(fd_slot_hash_t) );
      58        5073 :     entries[0].slot = bank->f.parent_slot;
      59        5073 :     fd_memcpy( &entries[0].hash, &bank->f.bank_hash, sizeof(fd_hash_t) );
      60        5073 :     FD_STORE( ulong, data, keep + 1UL );
      61        5073 :   }
      62             : 
      63        5076 :   fd_accdb_svm_close_rw( accdb, bank, capture_ctx, rw, update );
      64        5076 : }
      65             : 
      66             : int
      67             : fd_sysvar_slot_hashes_validate( uchar const * data,
      68        7122 :                                 ulong         sz ) {
      69        7122 :   if( FD_UNLIKELY( sz < sizeof(ulong) ) ) return 0;
      70        7116 :   ulong cnt = FD_LOAD( ulong, data );
      71        7116 :   if( FD_UNLIKELY( cnt > FD_SYSVAR_SLOT_HASHES_CAP ) ) return 0;
      72        7113 :   if( FD_UNLIKELY( sz < sizeof(ulong) + cnt*sizeof(fd_slot_hash_t) ) ) return 0;
      73        7107 :   return 1;
      74        7113 : }
      75             : 
      76             : fd_slot_hashes_t *
      77             : fd_sysvar_slot_hashes_view( fd_slot_hashes_t * view,
      78             :                             uchar const *      data,
      79         132 :                             ulong              sz ) {
      80         132 :   if( FD_UNLIKELY( !fd_sysvar_slot_hashes_validate( data, sz ) ) ) return NULL;
      81         129 :   ulong cnt   = FD_LOAD( ulong, data );
      82         129 :   view->elems = (fd_slot_hash_t const *)( data + sizeof(ulong) );
      83         129 :   view->cnt   = cnt;
      84         129 :   return view;
      85         132 : }

Generated by: LCOV version 1.14