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 105 0.0 %
Date: 2024-11-13 11:58:15 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             : #include "../context/fd_exec_epoch_ctx.h"
       7             : 
       8             : const ulong slot_history_min_account_size = 131097;
       9             : 
      10             : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/slot_history.rs#L37 */
      11             : const ulong slot_history_max_entries = 1024 * 1024;
      12             : 
      13             : /* TODO: move into seperate bitvec library */
      14             : const ulong bits_per_block = 8 * sizeof(ulong);
      15           0 : void fd_sysvar_slot_history_set( fd_slot_history_t* history, ulong i ) {
      16             :   // Corrupt history, zero everything out
      17           0 :   if ( i > history->next_slot && i - history->next_slot >= slot_history_max_entries ) {
      18           0 :     for ( ulong j = 0; j < history->bits.bits->blocks_len; j++) {
      19           0 :       history->bits.bits->blocks[ j ] = 0;
      20           0 :     }
      21           0 :   } else {
      22             :     // Skipped slots, delete them from history
      23           0 :     for (ulong j = history->next_slot; j < i; j++) {
      24           0 :       ulong block_idx = (j / bits_per_block) % (history->bits.bits->blocks_len);
      25           0 :       history->bits.bits->blocks[ block_idx ] &= ~( 1UL << ( j % bits_per_block ) );
      26           0 :     }
      27           0 :   }
      28           0 :   ulong block_idx = (i / bits_per_block) % (history->bits.bits->blocks_len);
      29           0 :   history->bits.bits->blocks[ block_idx ] |= ( 1UL << ( i % bits_per_block ) );
      30           0 : }
      31             : 
      32             : const ulong blocks_len = slot_history_max_entries / bits_per_block;
      33             : 
      34             : int fd_sysvar_slot_history_write_history( fd_exec_slot_ctx_t * slot_ctx,
      35           0 :                                           fd_slot_history_t * history ) {
      36           0 :   ulong sz = fd_slot_history_size( history );
      37           0 :   if (sz < slot_history_min_account_size)
      38           0 :     sz = slot_history_min_account_size;
      39           0 :   uchar enc[ sz ];
      40           0 :   fd_memset( enc, 0, sz );
      41           0 :   fd_bincode_encode_ctx_t ctx;
      42           0 :   ctx.data = enc;
      43           0 :   ctx.dataend = enc + sz;
      44           0 :   int err = fd_slot_history_encode( history, &ctx );
      45           0 :   if (0 != err)
      46           0 :     return err;
      47           0 :   return fd_sysvar_set( slot_ctx, fd_sysvar_owner_id.key, &fd_sysvar_slot_history_id, enc, sz, slot_ctx->slot_bank.slot );
      48           0 : }
      49             : 
      50             : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/slot_history.rs#L16 */
      51           0 : void fd_sysvar_slot_history_init( fd_exec_slot_ctx_t * slot_ctx ) {
      52             :   /* Create a new slot history instance */
      53           0 :   fd_slot_history_t history;
      54           0 :   fd_slot_history_inner_t *inner = fd_valloc_malloc( slot_ctx->valloc, 8UL, sizeof(fd_slot_history_inner_t) );
      55           0 :   inner->blocks = fd_valloc_malloc( slot_ctx->valloc, 8UL, sizeof(ulong) * blocks_len );
      56           0 :   memset( inner->blocks, 0, sizeof(ulong) * blocks_len );
      57           0 :   inner->blocks_len = blocks_len;
      58           0 :   history.bits.bits = inner;
      59           0 :   history.bits.len = slot_history_max_entries;
      60             : 
      61             :   /* TODO: handle slot != 0 init case */
      62           0 :   fd_sysvar_slot_history_set( &history, slot_ctx->slot_bank.slot );
      63           0 :   history.next_slot = slot_ctx->slot_bank.slot + 1;
      64             : 
      65           0 :   fd_sysvar_slot_history_write_history( slot_ctx, &history );
      66           0 :   fd_bincode_destroy_ctx_t ctx = { .valloc = slot_ctx->valloc };
      67           0 :   fd_slot_history_destroy( &history, &ctx );
      68           0 : }
      69             : 
      70             : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/runtime/src/bank.rs#L2345 */
      71             : int
      72           0 : fd_sysvar_slot_history_update( fd_exec_slot_ctx_t * slot_ctx ) {
      73             :   /* Set current_slot, and update next_slot */
      74             : 
      75           0 :   fd_pubkey_t const * key = &fd_sysvar_slot_history_id;
      76             : 
      77           0 :   FD_BORROWED_ACCOUNT_DECL(rec);
      78           0 :   int err = fd_acc_mgr_view( slot_ctx->acc_mgr, slot_ctx->funk_txn, key, rec);
      79           0 :   if (err)
      80           0 :     FD_LOG_CRIT(( "fd_acc_mgr_view(slot_history) failed: %d", err ));
      81             : 
      82           0 :   fd_bincode_decode_ctx_t ctx;
      83           0 :   ctx.data    = rec->const_data;
      84           0 :   ctx.dataend = rec->const_data + rec->const_meta->dlen;
      85           0 :   ctx.valloc  = slot_ctx->valloc;
      86           0 :   fd_slot_history_t history[1];
      87           0 :   if( fd_slot_history_decode( history, &ctx ) )
      88           0 :     FD_LOG_ERR(("fd_slot_history_decode failed"));
      89             : 
      90             :   /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/slot_history.rs#L48 */
      91           0 :   fd_sysvar_slot_history_set( history, slot_ctx->slot_bank.slot );
      92           0 :   history->next_slot = slot_ctx->slot_bank.slot + 1;
      93             : 
      94           0 :   ulong sz = fd_slot_history_size( history );
      95           0 :   if( sz < slot_history_min_account_size )
      96           0 :     sz = slot_history_min_account_size;
      97             : 
      98           0 :   err = fd_acc_mgr_modify( slot_ctx->acc_mgr, slot_ctx->funk_txn, key, 1, sz, rec );
      99           0 :   if (err)
     100           0 :     FD_LOG_CRIT(( "fd_acc_mgr_modify(slot_history) failed: %d", err ));
     101             : 
     102           0 :   fd_bincode_encode_ctx_t e_ctx = {
     103           0 :     .data    = rec->data,
     104           0 :     .dataend = rec->data+sz
     105           0 :   };
     106           0 :   if( fd_slot_history_encode( history, &e_ctx ) )
     107           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     108             : 
     109           0 :   fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
     110           0 :   rec->meta->info.lamports = fd_rent_exempt_minimum_balance( &epoch_bank->rent, sz );
     111             : 
     112           0 :   rec->meta->dlen = sz;
     113           0 :   fd_memcpy( rec->meta->info.owner, fd_sysvar_owner_id.key, sizeof(fd_pubkey_t) );
     114             : 
     115           0 :   fd_bincode_destroy_ctx_t ctx_d = { .valloc = slot_ctx->valloc };
     116           0 :   fd_slot_history_destroy( history, &ctx_d );
     117             : 
     118           0 :   return 0;
     119           0 : }
     120             : 
     121             : int
     122             : fd_sysvar_slot_history_read( fd_exec_slot_ctx_t * slot_ctx,
     123             :                             fd_valloc_t valloc,
     124           0 :                             fd_slot_history_t * out_history) {
     125             :   /* Set current_slot, and update next_slot */
     126             : 
     127           0 :   fd_pubkey_t const * key = &fd_sysvar_slot_history_id;
     128             : 
     129           0 :   FD_BORROWED_ACCOUNT_DECL(rec);
     130           0 :   int err = fd_acc_mgr_view( slot_ctx->acc_mgr, slot_ctx->funk_txn, key, rec);
     131           0 :   if (err)
     132           0 :     FD_LOG_CRIT(( "fd_acc_mgr_view(slot_history) failed: %d", err ));
     133             : 
     134           0 :   fd_bincode_decode_ctx_t ctx;
     135           0 :   ctx.data    = rec->const_data;
     136           0 :   ctx.dataend = rec->const_data + rec->const_meta->dlen;
     137           0 :   ctx.valloc  = valloc;
     138           0 :   if( fd_slot_history_decode( out_history, &ctx ) )
     139           0 :     FD_LOG_ERR(("fd_slot_history_decode failed"));
     140             : 
     141           0 :   return 0;
     142           0 : }
     143             : 
     144             : int
     145             : fd_sysvar_slot_history_find_slot( fd_slot_history_t const * history,
     146           0 :                                   ulong slot ) {
     147           0 :   if( slot > history->next_slot - 1) {
     148           0 :     return FD_SLOT_HISTORY_SLOT_FUTURE;
     149           0 :   } else if ( slot < fd_ulong_sat_sub( history->next_slot, slot_history_max_entries ) ) {
     150           0 :     return FD_SLOT_HISTORY_SLOT_TOO_OLD;
     151           0 :   } else {
     152           0 :     ulong block_idx = (slot / bits_per_block) % (history->bits.bits->blocks_len);
     153           0 :     if( history->bits.bits->blocks[ block_idx ] & ( 1UL << ( slot % bits_per_block ) ) ) {
     154           0 :       return FD_SLOT_HISTORY_SLOT_FOUND;
     155           0 :     } else {
     156           0 :       return FD_SLOT_HISTORY_SLOT_NOTFOUND;
     157           0 :     }
     158           0 :   }
     159           0 : }

Generated by: LCOV version 1.14