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 89 0.0 %
Date: 2025-12-18 05:07:35 Functions: 0 8 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_system_ids.h"
       5             : #include "../../accdb/fd_accdb_impl_v1.h"
       6             : 
       7             : /* FIXME These constants should be header defines */
       8             : 
       9             : void
      10             : fd_sysvar_slot_hashes_write( fd_bank_t *               bank,
      11             :                              fd_accdb_user_t *         accdb,
      12             :                              fd_funk_txn_xid_t const * xid,
      13             :                              fd_capture_ctx_t *        capture_ctx,
      14           0 :                              fd_slot_hashes_global_t * slot_hashes_global ) {
      15           0 :   uchar __attribute__((aligned(FD_SYSVAR_SLOT_HASHES_ALIGN))) enc[ FD_SYSVAR_SLOT_HASHES_BINCODE_SZ ] = {0};
      16           0 :   fd_bincode_encode_ctx_t ctx = {
      17           0 :     .data    = enc,
      18           0 :     .dataend = enc + FD_SYSVAR_SLOT_HASHES_BINCODE_SZ,
      19           0 :   };
      20           0 :   if( fd_slot_hashes_encode_global( slot_hashes_global, &ctx ) ) {
      21           0 :     FD_LOG_ERR(("fd_slot_hashes_encode failed"));
      22           0 :   }
      23           0 :   fd_sysvar_account_update( bank, accdb, xid, capture_ctx, &fd_sysvar_slot_hashes_id, enc, FD_SYSVAR_SLOT_HASHES_BINCODE_SZ );
      24           0 : }
      25             : 
      26             : ulong
      27           0 : fd_sysvar_slot_hashes_footprint( ulong slot_hashes_cap ) {
      28           0 :   return sizeof(fd_slot_hashes_global_t) +
      29           0 :          deq_fd_slot_hash_t_footprint( slot_hashes_cap ) + deq_fd_slot_hash_t_align();
      30           0 : }
      31             : 
      32             : void *
      33             : fd_sysvar_slot_hashes_new( void * mem,
      34           0 :                            ulong  slot_hashes_cap ) {
      35           0 :   if( FD_UNLIKELY( !mem ) ) {
      36           0 :     FD_LOG_ERR(( "Unable to allocate memory for slot hashes" ));
      37           0 :   }
      38           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_SYSVAR_SLOT_HASHES_ALIGN ) ) ) {
      39           0 :     FD_LOG_ERR(( "Memory for slot hashes is not aligned" ));
      40           0 :   }
      41             : 
      42           0 :   fd_slot_hashes_global_t * slot_hashes_global = (fd_slot_hashes_global_t *)mem;
      43             : 
      44           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() );
      45           0 :   deq_fd_slot_hash_t_new( (void*)slot_hash_mem, slot_hashes_cap );
      46           0 :   slot_hashes_global->hashes_offset = (ulong)slot_hash_mem - (ulong)slot_hashes_global;
      47             : 
      48           0 :   return slot_hashes_global;
      49           0 : }
      50             : 
      51             : fd_slot_hashes_global_t *
      52             : fd_sysvar_slot_hashes_join( void *            shmem,
      53           0 :                             fd_slot_hash_t ** slot_hash ) {
      54           0 :   fd_slot_hashes_global_t * slot_hashes_global = (fd_slot_hashes_global_t *)shmem;
      55           0 :   *slot_hash                                   = deq_fd_slot_hash_t_join( (uchar*)shmem + slot_hashes_global->hashes_offset );
      56             : 
      57           0 :   return slot_hashes_global;
      58           0 : }
      59             : 
      60             : void *
      61             : fd_sysvar_slot_hashes_leave( fd_slot_hashes_global_t * slot_hashes_global,
      62           0 :                              fd_slot_hash_t *          slot_hash ) {
      63           0 :   deq_fd_slot_hash_t_leave( slot_hash );
      64             : 
      65           0 :   return slot_hashes_global;
      66           0 : }
      67             : 
      68             : void *
      69           0 : fd_sysvar_slot_hashes_delete( void * mem ) {
      70           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() );
      71           0 :   deq_fd_slot_hash_t_delete( slot_hash_mem );
      72             : 
      73           0 :   return mem;
      74           0 : }
      75             : 
      76             : /* https://github.com/anza-xyz/agave/blob/b11ca828cfc658b93cb86a6c5c70561875abe237/runtime/src/bank.rs#L2283-L2294 */
      77             : void
      78             : fd_sysvar_slot_hashes_update( fd_bank_t *               bank,
      79             :                               fd_accdb_user_t *         accdb,
      80             :                               fd_funk_txn_xid_t const * xid,
      81           0 :                               fd_capture_ctx_t *        capture_ctx ) {
      82           0 :   fd_funk_t * funk = fd_accdb_user_v1_funk( accdb );
      83           0 :   uchar __attribute__((aligned(FD_SYSVAR_SLOT_HASHES_ALIGN))) slot_hashes_mem[FD_SYSVAR_SLOT_HASHES_FOOTPRINT];
      84           0 :   fd_slot_hashes_global_t * slot_hashes_global = fd_sysvar_slot_hashes_read( funk, xid, slot_hashes_mem );
      85           0 :   fd_slot_hash_t *          hashes             = NULL;
      86           0 :   if( FD_UNLIKELY( !slot_hashes_global ) ) {
      87             :     /* Note: Agave's implementation initializes a new slot_hashes if it doesn't already exist (refer to above URL). */
      88           0 :     slot_hashes_global = fd_sysvar_slot_hashes_new( slot_hashes_mem, FD_SYSVAR_SLOT_HASHES_CAP );
      89           0 :   }
      90           0 :   slot_hashes_global = fd_sysvar_slot_hashes_join( slot_hashes_global, &hashes );
      91             : 
      92           0 :   uchar found = 0;
      93           0 :   for( deq_fd_slot_hash_t_iter_t iter = deq_fd_slot_hash_t_iter_init( hashes );
      94           0 :         !deq_fd_slot_hash_t_iter_done( hashes, iter );
      95           0 :         iter = deq_fd_slot_hash_t_iter_next( hashes, iter ) ) {
      96           0 :     fd_slot_hash_t * ele = deq_fd_slot_hash_t_iter_ele( hashes, iter );
      97           0 :     if( ele->slot == fd_bank_parent_slot_get( bank ) ) {
      98           0 :       fd_hash_t const * bank_hash = fd_bank_bank_hash_query( bank );
      99           0 :       memcpy( &ele->hash, bank_hash, sizeof(fd_hash_t) );
     100           0 :       found = 1;
     101           0 :     }
     102           0 :   }
     103             : 
     104           0 :   if( !found ) {
     105             :     // https://github.com/firedancer-io/solana/blob/08a1ef5d785fe58af442b791df6c4e83fe2e7c74/runtime/src/bank.rs#L2371
     106           0 :     fd_slot_hash_t slot_hash = {
     107           0 :       .hash = fd_bank_bank_hash_get( bank ), // parent hash?
     108           0 :       .slot = fd_bank_parent_slot_get( bank ),   // parent_slot
     109           0 :     };
     110             : 
     111           0 :     if( deq_fd_slot_hash_t_full( hashes ) )
     112           0 :       memset( deq_fd_slot_hash_t_pop_tail_nocopy( hashes ), 0, sizeof(fd_slot_hash_t) );
     113             : 
     114           0 :     deq_fd_slot_hash_t_push_head( hashes, slot_hash );
     115           0 :   }
     116             : 
     117           0 :   fd_sysvar_slot_hashes_write( bank, accdb, xid, capture_ctx, slot_hashes_global );
     118           0 :   fd_sysvar_slot_hashes_leave( slot_hashes_global, hashes );
     119           0 : }
     120             : 
     121             : fd_slot_hashes_global_t *
     122             : fd_sysvar_slot_hashes_read( fd_funk_t *               funk,
     123             :                             fd_funk_txn_xid_t const * xid,
     124           0 :                             uchar *                   slot_hashes_mem ) {
     125           0 :   fd_txn_account_t rec[1];
     126           0 :   int err = fd_txn_account_init_from_funk_readonly( rec, (fd_pubkey_t const *)&fd_sysvar_slot_hashes_id, funk, xid );
     127           0 :   if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) {
     128           0 :     return NULL;
     129           0 :   }
     130             : 
     131             :   /* This check is needed as a quirk of the fuzzer. If a sysvar account
     132             :      exists in the accounts database, but doesn't have any lamports,
     133             :      this means that the account does not exist. This wouldn't happen
     134             :      in a real execution environment. */
     135           0 :   if( FD_UNLIKELY( fd_txn_account_get_lamports( rec )==0UL ) ) {
     136           0 :     return NULL;
     137           0 :   }
     138             : 
     139           0 :   fd_bincode_decode_ctx_t decode = {
     140           0 :     .data    = fd_txn_account_get_data( rec ),
     141           0 :     .dataend = fd_txn_account_get_data( rec ) + fd_txn_account_get_data_len( rec )
     142           0 :   };
     143             : 
     144           0 :   return fd_slot_hashes_decode_global( slot_hashes_mem, &decode );
     145           0 : }

Generated by: LCOV version 1.14