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: 0 110 0.0 %
Date: 2025-07-01 05:00:49 Functions: 0 9 0.0 %

          Line data    Source code
       1             : #include "fd_sysvar_slot_hashes.h"
       2             : #include "fd_sysvar.h"
       3             : #include "../fd_acc_mgr.h"
       4             : #include "../fd_borrowed_account.h"
       5             : #include "../fd_system_ids.h"
       6             : #include "../context/fd_exec_slot_ctx.h"
       7             : /* FIXME These constants should be header defines */
       8             : 
       9             : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/slot_hashes.rs#L11 */
      10             : FD_FN_UNUSED static const ulong slot_hashes_max_entries = 512;
      11             : 
      12             : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/sysvar/slot_hashes.rs#L12 */
      13             : static const ulong slot_hashes_account_size = 20488;
      14             : 
      15             : void
      16             : fd_sysvar_slot_hashes_write( fd_exec_slot_ctx_t *      slot_ctx,
      17           0 :                              fd_slot_hashes_global_t * slot_hashes_global ) {
      18           0 :   uchar enc[slot_hashes_account_size];
      19           0 :   fd_memset( enc, 0, slot_hashes_account_size );
      20           0 :   fd_bincode_encode_ctx_t ctx = {
      21           0 :     .data    = enc,
      22           0 :     .dataend = enc + slot_hashes_account_size,
      23           0 :   };
      24           0 :   if( fd_slot_hashes_encode_global( slot_hashes_global, &ctx ) ) {
      25           0 :     FD_LOG_ERR(("fd_slot_hashes_encode failed"));
      26           0 :   }
      27           0 :   fd_sysvar_set( slot_ctx->bank, slot_ctx->funk, slot_ctx->funk_txn, &fd_sysvar_owner_id, &fd_sysvar_slot_hashes_id, enc, slot_hashes_account_size, slot_ctx->slot );
      28           0 : }
      29             : 
      30             : ulong
      31           0 : fd_sysvar_slot_hashes_footprint( ulong slot_hashes_cap ) {
      32           0 :   return sizeof(fd_slot_hashes_global_t) +
      33           0 :          deq_fd_slot_hash_t_footprint( slot_hashes_cap ) + deq_fd_slot_hash_t_align();
      34           0 : }
      35             : 
      36             : void *
      37             : fd_sysvar_slot_hashes_new( void * mem,
      38           0 :                            ulong  slot_hashes_cap ) {
      39           0 :   if( FD_UNLIKELY( !mem ) ) {
      40           0 :     FD_LOG_ERR(( "Unable to allocate memory for slot hashes" ));
      41           0 :   }
      42           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_SYSVAR_SLOT_HASHES_ALIGN ) ) ) {
      43           0 :     FD_LOG_ERR(( "Memory for slot hashes is not aligned" ));
      44           0 :   }
      45             : 
      46           0 :   fd_slot_hashes_global_t * slot_hashes_global = (fd_slot_hashes_global_t *)mem;
      47             : 
      48           0 :   uchar * slot_hash_mem = (uchar*)fd_ulong_align_up( (ulong)((uchar *)mem + sizeof(fd_slot_hashes_global_t)), deq_fd_slot_hash_t_align() );
      49           0 :   deq_fd_slot_hash_t_new( (void*)slot_hash_mem, slot_hashes_cap );
      50           0 :   slot_hashes_global->hashes_offset = (ulong)slot_hash_mem - (ulong)slot_hashes_global;
      51             : 
      52           0 :   return slot_hashes_global;
      53           0 : }
      54             : 
      55             : fd_slot_hashes_global_t *
      56             : fd_sysvar_slot_hashes_join( void *            shmem,
      57           0 :                             fd_slot_hash_t ** slot_hash ) {
      58           0 :   fd_slot_hashes_global_t * slot_hashes_global = (fd_slot_hashes_global_t *)shmem;
      59           0 :   *slot_hash                                   = deq_fd_slot_hash_t_join( (uchar*)shmem + slot_hashes_global->hashes_offset );
      60             : 
      61           0 :   return slot_hashes_global;
      62           0 : }
      63             : 
      64             : void *
      65             : fd_sysvar_slot_hashes_leave( fd_slot_hashes_global_t * slot_hashes_global,
      66           0 :                              fd_slot_hash_t *          slot_hash ) {
      67           0 :   deq_fd_slot_hash_t_leave( slot_hash );
      68             : 
      69           0 :   return slot_hashes_global;
      70           0 : }
      71             : 
      72             : void *
      73           0 : fd_sysvar_slot_hashes_delete( void * mem ) {
      74           0 :   void * slot_hash_mem = (void *)fd_ulong_align_up( (ulong)((uchar *)mem + sizeof(fd_slot_hashes_global_t)), deq_fd_slot_hash_t_align() );
      75           0 :   deq_fd_slot_hash_t_delete( slot_hash_mem );
      76             : 
      77           0 :   return mem;
      78           0 : }
      79             : 
      80             : void
      81             : fd_sysvar_slot_hashes_init( fd_exec_slot_ctx_t * slot_ctx,
      82           0 :                             fd_spad_t *          runtime_spad ) {
      83           0 :   FD_SPAD_FRAME_BEGIN( runtime_spad ) {
      84           0 :     void * mem                                    = fd_spad_alloc( runtime_spad, FD_SYSVAR_SLOT_HASHES_ALIGN, fd_sysvar_slot_hashes_footprint( FD_SYSVAR_SLOT_HASHES_CAP ) );
      85           0 :     fd_slot_hash_t * shnull                       = NULL;
      86           0 :     fd_slot_hashes_global_t * slot_hashes_global  = fd_sysvar_slot_hashes_join( fd_sysvar_slot_hashes_new( mem, FD_SYSVAR_SLOT_HASHES_CAP ), &shnull );
      87             : 
      88           0 :     fd_sysvar_slot_hashes_write( slot_ctx, slot_hashes_global);
      89           0 :     fd_sysvar_slot_hashes_delete( fd_sysvar_slot_hashes_leave( slot_hashes_global, shnull ) );
      90           0 :   } FD_SPAD_FRAME_END;
      91           0 : }
      92             : 
      93             : /* https://github.com/anza-xyz/agave/blob/b11ca828cfc658b93cb86a6c5c70561875abe237/runtime/src/bank.rs#L2283-L2294 */
      94             : void
      95           0 : fd_sysvar_slot_hashes_update( fd_exec_slot_ctx_t * slot_ctx, fd_spad_t * runtime_spad ) {
      96           0 : FD_SPAD_FRAME_BEGIN( runtime_spad ) {
      97           0 :   fd_slot_hashes_global_t * slot_hashes_global = fd_sysvar_slot_hashes_read( slot_ctx->funk, slot_ctx->funk_txn, runtime_spad );
      98           0 :   fd_slot_hash_t *          hashes             = NULL;
      99           0 :   if( FD_UNLIKELY( !slot_hashes_global ) ) {
     100             :     /* Note: Agave's implementation initializes a new slot_hashes if it doesn't already exist (refer to above URL). */
     101           0 :     void * mem = fd_spad_alloc( runtime_spad, FD_SYSVAR_SLOT_HASHES_ALIGN, fd_sysvar_slot_hashes_footprint( FD_SYSVAR_SLOT_HASHES_CAP ) );
     102           0 :     slot_hashes_global = fd_sysvar_slot_hashes_new( mem, FD_SYSVAR_SLOT_HASHES_CAP );
     103           0 :   }
     104           0 :   slot_hashes_global = fd_sysvar_slot_hashes_join( slot_hashes_global, &hashes );
     105             : 
     106           0 :   uchar found = 0;
     107           0 :   for( deq_fd_slot_hash_t_iter_t iter = deq_fd_slot_hash_t_iter_init( hashes );
     108           0 :        !deq_fd_slot_hash_t_iter_done( hashes, iter );
     109           0 :        iter = deq_fd_slot_hash_t_iter_next( hashes, iter ) ) {
     110           0 :     fd_slot_hash_t * ele = deq_fd_slot_hash_t_iter_ele( hashes, iter );
     111           0 :     if( ele->slot == slot_ctx->slot ) {
     112           0 :       fd_hash_t const * bank_hash = fd_bank_bank_hash_query( slot_ctx->bank );
     113           0 :       memcpy( &ele->hash, bank_hash, sizeof(fd_hash_t) );
     114           0 :       found = 1;
     115           0 :     }
     116           0 :   }
     117             : 
     118           0 :   if( !found ) {
     119             :     // https://github.com/firedancer-io/solana/blob/08a1ef5d785fe58af442b791df6c4e83fe2e7c74/runtime/src/bank.rs#L2371
     120           0 :     fd_slot_hash_t slot_hash = {
     121           0 :       .hash = fd_bank_bank_hash_get( slot_ctx->bank ), // parent hash?
     122           0 :       .slot = fd_bank_prev_slot_get( slot_ctx->bank ),   // parent_slot
     123           0 :     };
     124           0 :     FD_LOG_DEBUG(( "fd_sysvar_slot_hash_update:  slot %lu,  hash %s", slot_hash.slot, FD_BASE58_ENC_32_ALLOCA( slot_hash.hash.key ) ));
     125             : 
     126           0 :     if( deq_fd_slot_hash_t_full( hashes ) )
     127           0 :       memset( deq_fd_slot_hash_t_pop_tail_nocopy( hashes ), 0, sizeof(fd_slot_hash_t) );
     128             : 
     129           0 :     deq_fd_slot_hash_t_push_head( hashes, slot_hash );
     130           0 :   }
     131             : 
     132           0 :   fd_sysvar_slot_hashes_write( slot_ctx, slot_hashes_global );
     133           0 :   fd_sysvar_slot_hashes_leave( slot_hashes_global, hashes );
     134           0 : } FD_SPAD_FRAME_END;
     135           0 : }
     136             : 
     137             : fd_slot_hashes_global_t *
     138             : fd_sysvar_slot_hashes_read( fd_funk_t *     funk,
     139             :                             fd_funk_txn_t * funk_txn,
     140           0 :                             fd_spad_t *     spad ) {
     141           0 :   FD_TXN_ACCOUNT_DECL( rec );
     142           0 :   int err = fd_txn_account_init_from_funk_readonly( rec, (fd_pubkey_t const *)&fd_sysvar_slot_hashes_id, funk, funk_txn );
     143           0 :   if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) {
     144           0 :     return NULL;
     145           0 :   }
     146             : 
     147             :   /* This check is needed as a quirk of the fuzzer. If a sysvar account
     148             :      exists in the accounts database, but doesn't have any lamports,
     149             :      this means that the account does not exist. This wouldn't happen
     150             :      in a real execution environment. */
     151           0 :   if( FD_UNLIKELY( rec->vt->get_lamports( rec )==0 ) ) {
     152           0 :     return NULL;
     153           0 :   }
     154             : 
     155           0 :   fd_bincode_decode_ctx_t decode = {
     156           0 :     .data    = rec->vt->get_data( rec ),
     157           0 :     .dataend = rec->vt->get_data( rec ) + rec->vt->get_data_len( rec )
     158           0 :   };
     159             : 
     160           0 :   ulong total_sz = 0UL;
     161           0 :   err = fd_slot_hashes_decode_footprint( &decode, &total_sz );
     162           0 :   if( FD_UNLIKELY( err ) ) {
     163           0 :     return NULL;
     164           0 :   }
     165             : 
     166           0 :   uchar * mem = fd_spad_alloc( spad, fd_slot_hashes_align(), total_sz );
     167             : 
     168           0 :   if( FD_UNLIKELY( !mem ) ) {
     169           0 :     FD_LOG_ERR(( "Unable to allocate memory for slot hashes" ));
     170           0 :   }
     171             : 
     172           0 :   return fd_slot_hashes_decode_global( mem, &decode );
     173           0 : }

Generated by: LCOV version 1.14