LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_stake_history.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 35 50 70.0 %
Date: 2026-03-19 18:19:27 Functions: 3 4 75.0 %

          Line data    Source code
       1             : #include "fd_sysvar_stake_history.h"
       2             : #include "fd_sysvar.h"
       3             : #include "../fd_system_ids.h"
       4             : #include "../../accdb/fd_accdb_sync.h"
       5             : 
       6             : /* Ensure that the size declared by our header matches the minimum size
       7             :    of the corresponding fd_types entry. */
       8             : 
       9             : static void
      10             : write_stake_history( 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           2 :                      fd_stake_history_t *      stake_history ) {
      15             :   /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/sysvar/stake_history.rs#L12 */
      16           2 :   uchar __attribute__((aligned(FD_STAKE_HISTORY_ALIGN))) enc[ FD_SYSVAR_STAKE_HISTORY_BINCODE_SZ ] = {0};
      17           2 :   fd_bincode_encode_ctx_t encode =
      18           2 :     { .data    = enc,
      19           2 :       .dataend = enc + sizeof(enc) };
      20           2 :   if( FD_UNLIKELY( fd_stake_history_encode( stake_history, &encode )!=FD_BINCODE_SUCCESS ) )
      21           0 :     FD_LOG_ERR(("fd_stake_history_encode failed"));
      22             : 
      23           2 :   fd_sysvar_account_update( bank, accdb, xid, capture_ctx, &fd_sysvar_stake_history_id, enc, sizeof(enc) );
      24           2 : }
      25             : 
      26             : fd_stake_history_t *
      27             : fd_sysvar_stake_history_read( fd_accdb_user_t *         accdb,
      28             :                               fd_funk_txn_xid_t const * xid,
      29          10 :                               fd_stake_history_t *      stake_history ) {
      30          10 :   fd_accdb_ro_t ro[1];
      31          10 :   if( FD_UNLIKELY( !fd_accdb_open_ro( accdb, ro, xid, &fd_sysvar_stake_history_id ) ) ) {
      32           0 :     return NULL;
      33           0 :   }
      34             : 
      35             :   /* This check is needed as a quirk of the fuzzer. If a sysvar account
      36             :      exists in the accounts database, but doesn't have any lamports,
      37             :      this means that the account does not exist. This wouldn't happen
      38             :      in a real execution environment. */
      39          10 :   if( FD_UNLIKELY( fd_accdb_ref_lamports( ro )==0UL ) ) {
      40           0 :     fd_accdb_close_ro( accdb, ro );
      41           0 :     return NULL;
      42           0 :   }
      43             : 
      44          10 :   stake_history = fd_bincode_decode_static(
      45          10 :       stake_history, stake_history,
      46          10 :       fd_accdb_ref_data_const( ro ),
      47          10 :       fd_accdb_ref_data_sz( ro ) );
      48          10 :   fd_accdb_close_ro( accdb, ro );
      49          10 :   return stake_history;
      50          10 : }
      51             : 
      52             : void
      53             : fd_sysvar_stake_history_init( fd_bank_t *               bank,
      54             :                               fd_accdb_user_t *         accdb,
      55             :                               fd_funk_txn_xid_t const * xid,
      56           0 :                               fd_capture_ctx_t *        capture_ctx ) {
      57           0 :   fd_stake_history_t stake_history;
      58           0 :   fd_stake_history_new( &stake_history );
      59           0 :   write_stake_history( bank, accdb, xid, capture_ctx, &stake_history );
      60           0 : }
      61             : 
      62             : void
      63             : fd_sysvar_stake_history_update( fd_bank_t *                                 bank,
      64             :                                 fd_accdb_user_t *                           accdb,
      65             :                                 fd_funk_txn_xid_t const *                   xid,
      66             :                                 fd_capture_ctx_t *                          capture_ctx,
      67           2 :                                 fd_epoch_stake_history_entry_pair_t const * pair ) {
      68             : 
      69           2 :   fd_stake_history_t stake_history[1];
      70           2 :   if( FD_UNLIKELY( !fd_sysvar_stake_history_read( accdb, xid, stake_history ) ) ) {
      71           0 :     FD_LOG_CRIT(( "Failed to read stake history sysvar" ));
      72           0 :   }
      73             : 
      74           2 :   if( stake_history->fd_stake_history_offset == 0 ) {
      75           2 :     stake_history->fd_stake_history_offset = stake_history->fd_stake_history_size - 1;
      76           2 :   } else {
      77           0 :     stake_history->fd_stake_history_offset--;
      78           0 :   }
      79             : 
      80           2 :   if( stake_history->fd_stake_history_len < stake_history->fd_stake_history_size ) {
      81           2 :     stake_history->fd_stake_history_len++;
      82           2 :   }
      83             : 
      84             :   // This should be done with a bit mask
      85           2 :   ulong idx = stake_history->fd_stake_history_offset;
      86             : 
      87           2 :   stake_history->fd_stake_history[ idx ].epoch              = pair->epoch;
      88           2 :   stake_history->fd_stake_history[ idx ].entry.activating   = pair->entry.activating;
      89           2 :   stake_history->fd_stake_history[ idx ].entry.effective    = pair->entry.effective;
      90           2 :   stake_history->fd_stake_history[ idx ].entry.deactivating = pair->entry.deactivating;
      91             : 
      92           2 :   write_stake_history( bank, accdb, xid, capture_ctx, stake_history );
      93             : 
      94           2 : }

Generated by: LCOV version 1.14