LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_slot_history.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 116 0.0 %
Date: 2025-03-20 12:08:36 Functions: 0 6 0.0 %

          Line data    Source code
       1             : #include "fd_sysvar_slot_history.h"
       2             : #include "fd_sysvar.h"
       3             : #include "fd_sysvar_rent.h"
       4             : #include "../fd_executor_err.h"
       5             : #include "../fd_system_ids.h"
       6             : 
       7             : /* FIXME These constants should be header defines */
       8             : 
       9             : static const ulong slot_history_min_account_size = 131097;
      10             : 
      11             : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/slot_history.rs#L37 */
      12             : static const ulong slot_history_max_entries = 1024 * 1024;
      13             : 
      14             : /* TODO: move into seperate bitvec library */
      15             : static const ulong bits_per_block = 8 * sizeof(ulong);
      16             : 
      17             : void
      18             : fd_sysvar_slot_history_set( fd_slot_history_t * history,
      19           0 :                             ulong               i ) {
      20           0 :   if( FD_UNLIKELY( i > history->next_slot && i - history->next_slot >= slot_history_max_entries ) ) {
      21           0 :     FD_LOG_WARNING(( "Ignoring out of bounds (i=%lu next_slot=%lu)", i, history->next_slot ));
      22           0 :     return;
      23           0 :   }
      24             : 
      25             :   // Skipped slots, delete them from history
      26           0 :   for( ulong j = history->next_slot; j < i; j++ ) {
      27           0 :     ulong block_idx = (j / bits_per_block) % (history->bits.bits->blocks_len);
      28           0 :     history->bits.bits->blocks[ block_idx ] &= ~( 1UL << ( j % bits_per_block ) );
      29           0 :   }
      30           0 :   ulong block_idx = (i / bits_per_block) % (history->bits.bits->blocks_len);
      31           0 :   history->bits.bits->blocks[ block_idx ] |= ( 1UL << ( i % bits_per_block ) );
      32           0 : }
      33             : 
      34             : static const ulong blocks_len = slot_history_max_entries / bits_per_block;
      35             : 
      36             : int fd_sysvar_slot_history_write_history( fd_exec_slot_ctx_t * slot_ctx,
      37           0 :                                           fd_slot_history_t * history ) {
      38           0 :   ulong sz = fd_slot_history_size( history );
      39           0 :   if (sz < slot_history_min_account_size)
      40           0 :     sz = slot_history_min_account_size;
      41           0 :   uchar enc[ sz ];
      42           0 :   fd_memset( enc, 0, sz );
      43           0 :   fd_bincode_encode_ctx_t ctx;
      44           0 :   ctx.data = enc;
      45           0 :   ctx.dataend = enc + sz;
      46           0 :   int err = fd_slot_history_encode( history, &ctx );
      47           0 :   if (0 != err)
      48           0 :     return err;
      49           0 :   return fd_sysvar_set( slot_ctx, fd_sysvar_owner_id.key, &fd_sysvar_slot_history_id, enc, sz, slot_ctx->slot_bank.slot );
      50           0 : }
      51             : 
      52             : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/slot_history.rs#L16 */
      53             : void
      54           0 : fd_sysvar_slot_history_init( fd_exec_slot_ctx_t * slot_ctx, fd_spad_t * runtime_spad ) {
      55             :   /* Create a new slot history instance */
      56           0 :   fd_slot_history_t         history = {0};
      57           0 :   fd_slot_history_inner_t * inner   = fd_spad_alloc( runtime_spad, alignof(fd_slot_history_inner_t), sizeof(fd_slot_history_inner_t) );
      58           0 :   inner->blocks = fd_spad_alloc( runtime_spad, alignof(ulong), sizeof(ulong) * blocks_len );
      59           0 :   memset( inner->blocks, 0, sizeof(ulong) * blocks_len );
      60           0 :   inner->blocks_len = blocks_len;
      61           0 :   history.bits.bits = inner;
      62           0 :   history.bits.len  = slot_history_max_entries;
      63             : 
      64             :   /* TODO: handle slot != 0 init case */
      65           0 :   fd_sysvar_slot_history_set( &history, slot_ctx->slot_bank.slot );
      66           0 :   history.next_slot = slot_ctx->slot_bank.slot + 1;
      67             : 
      68           0 :   fd_sysvar_slot_history_write_history( slot_ctx, &history );
      69           0 :   fd_slot_history_destroy( &history );
      70           0 : }
      71             : 
      72             : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/runtime/src/bank.rs#L2345 */
      73             : int
      74           0 : fd_sysvar_slot_history_update( fd_exec_slot_ctx_t * slot_ctx, fd_spad_t * runtime_spad ) {
      75             :   /* Set current_slot, and update next_slot */
      76             : 
      77           0 :   fd_pubkey_t const * key = &fd_sysvar_slot_history_id;
      78             : 
      79           0 :   FD_TXN_ACCOUNT_DECL( rec );
      80           0 :   int err = fd_acc_mgr_view( slot_ctx->acc_mgr, slot_ctx->funk_txn, key, rec);
      81           0 :   if (err)
      82           0 :     FD_LOG_CRIT(( "fd_acc_mgr_view(slot_history) failed: %d", err ));
      83             : 
      84           0 :   fd_bincode_decode_ctx_t ctx = {
      85           0 :     .data    = rec->const_data,
      86           0 :     .dataend = rec->const_data + rec->const_meta->dlen
      87           0 :   };
      88             : 
      89           0 :   ulong total_sz = 0UL;
      90           0 :   err = fd_slot_history_decode_footprint( &ctx, &total_sz );
      91           0 :   if( FD_UNLIKELY( err ) ) {
      92           0 :     FD_LOG_ERR(( "fd_slot_history_decode_footprint failed" ));
      93           0 :   }
      94             : 
      95           0 :   uchar * mem = fd_spad_alloc( runtime_spad, fd_slot_history_align(), total_sz );
      96           0 :   if( FD_UNLIKELY( !mem ) ) {
      97           0 :     FD_LOG_ERR(( "Unable to allocate memory for slot history" ));
      98           0 :   }
      99             : 
     100             : 
     101           0 :   fd_slot_history_t * history = fd_slot_history_decode( mem, &ctx );
     102             : 
     103             :   /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/slot_history.rs#L48 */
     104           0 :   fd_sysvar_slot_history_set( history, slot_ctx->slot_bank.slot );
     105           0 :   history->next_slot = slot_ctx->slot_bank.slot + 1;
     106             : 
     107           0 :   ulong sz = fd_slot_history_size( history );
     108           0 :   if( sz < slot_history_min_account_size )
     109           0 :     sz = slot_history_min_account_size;
     110             : 
     111           0 :   err = fd_acc_mgr_modify( slot_ctx->acc_mgr, slot_ctx->funk_txn, key, 1, sz, rec );
     112           0 :   if (err)
     113           0 :     FD_LOG_CRIT(( "fd_acc_mgr_modify(slot_history) failed: %d", err ));
     114             : 
     115           0 :   fd_bincode_encode_ctx_t e_ctx = {
     116           0 :     .data    = rec->data,
     117           0 :     .dataend = rec->data+sz
     118           0 :   };
     119           0 :   if( fd_slot_history_encode( history, &e_ctx ) )
     120           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     121             : 
     122           0 :   fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
     123           0 :   rec->meta->info.lamports = fd_rent_exempt_minimum_balance( &epoch_bank->rent, sz );
     124             : 
     125           0 :   rec->meta->dlen = sz;
     126           0 :   fd_memcpy( rec->meta->info.owner, fd_sysvar_owner_id.key, sizeof(fd_pubkey_t) );
     127             : 
     128           0 :   fd_slot_history_destroy( history );
     129             : 
     130           0 :   return 0;
     131           0 : }
     132             : 
     133             : fd_slot_history_t *
     134             : fd_sysvar_slot_history_read( fd_acc_mgr_t *  acc_mgr,
     135             :                              fd_funk_txn_t * funk_txn,
     136           0 :                              fd_spad_t *     spad ) {
     137             :   /* Set current_slot, and update next_slot */
     138             : 
     139           0 :   fd_pubkey_t const * key = &fd_sysvar_slot_history_id;
     140             : 
     141           0 :   FD_TXN_ACCOUNT_DECL( rec );
     142           0 :   int err = fd_acc_mgr_view( acc_mgr, funk_txn, key, rec );
     143           0 :   if( err ) {
     144           0 :     FD_LOG_CRIT(( "fd_acc_mgr_view(slot_history) failed: %d", err ));
     145           0 :   }
     146             : 
     147           0 :   fd_bincode_decode_ctx_t ctx = {
     148           0 :     .data    = rec->const_data,
     149           0 :     .dataend = rec->const_data + rec->const_meta->dlen
     150           0 :   };
     151             : 
     152           0 :   ulong total_sz = 0UL;
     153           0 :   err = fd_slot_history_decode_footprint( &ctx, &total_sz );
     154           0 :   if( err ) {
     155           0 :     FD_LOG_ERR(( "fd_slot_history_decode_footprint failed" ));
     156           0 :   }
     157             : 
     158           0 :   uchar * mem = fd_spad_alloc( spad, fd_slot_history_align(), total_sz );
     159           0 :   if( !mem ) {
     160           0 :     FD_LOG_ERR(( "Unable to allocate memory for slot history" ));
     161           0 :   }
     162             : 
     163           0 :   return fd_slot_history_decode( mem, &ctx );
     164           0 : }
     165             : 
     166             : int
     167             : fd_sysvar_slot_history_find_slot( fd_slot_history_t const * history,
     168           0 :                                   ulong                     slot ) {
     169           0 :   if( slot > history->next_slot - 1UL ) {
     170           0 :     return FD_SLOT_HISTORY_SLOT_FUTURE;
     171           0 :   } else if ( slot < fd_ulong_sat_sub( history->next_slot, slot_history_max_entries ) ) {
     172           0 :     return FD_SLOT_HISTORY_SLOT_TOO_OLD;
     173           0 :   } else {
     174           0 :     ulong block_idx = (slot / bits_per_block) % (history->bits.bits->blocks_len);
     175           0 :     if( history->bits.bits->blocks[ block_idx ] & ( 1UL << ( slot % bits_per_block ) ) ) {
     176           0 :       return FD_SLOT_HISTORY_SLOT_FOUND;
     177           0 :     } else {
     178           0 :       return FD_SLOT_HISTORY_SLOT_NOT_FOUND;
     179           0 :     }
     180           0 :   }
     181           0 : }

Generated by: LCOV version 1.14