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

          Line data    Source code
       1             : #include "fd_runtime_init.h"
       2             : #include "fd_runtime_err.h"
       3             : #include <stdio.h>
       4             : #include "../types/fd_types.h"
       5             : #include "context/fd_exec_epoch_ctx.h"
       6             : #include "context/fd_exec_slot_ctx.h"
       7             : #include "../../ballet/lthash/fd_lthash.h"
       8             : #include "fd_system_ids.h"
       9             : 
      10             : /* This file must not depend on fd_executor.h */
      11             : 
      12             : fd_funk_rec_key_t
      13           0 : fd_runtime_epoch_bank_key( void ) {
      14           0 :   fd_funk_rec_key_t id;
      15           0 :   fd_memset(&id, 1, sizeof(id));
      16           0 :   id.c[FD_FUNK_REC_KEY_FOOTPRINT - 1] = FD_BLOCK_EPOCH_BANK_TYPE;
      17             : 
      18           0 :   return id;
      19           0 : }
      20             : 
      21             : fd_funk_rec_key_t
      22           0 : fd_runtime_slot_bank_key( void ) {
      23           0 :   fd_funk_rec_key_t id;
      24           0 :   fd_memset(&id, 1, sizeof(id));
      25           0 :   id.c[FD_FUNK_REC_KEY_FOOTPRINT - 1] = FD_BLOCK_SLOT_BANK_TYPE;
      26             : 
      27           0 :   return id;
      28           0 : }
      29             : 
      30             : int
      31           0 : fd_runtime_save_epoch_bank( fd_exec_slot_ctx_t * slot_ctx ) {
      32           0 :   fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
      33           0 :   ulong sz = sizeof(uint) + fd_epoch_bank_size(epoch_bank);
      34           0 :   fd_funk_rec_key_t id = fd_runtime_epoch_bank_key();
      35           0 :   int opt_err = 0;
      36           0 :   fd_funk_rec_t * rec = fd_funk_rec_write_prepare( slot_ctx->acc_mgr->funk, slot_ctx->funk_txn, &id, sz, 1, NULL, &opt_err );
      37           0 :   if (NULL == rec)
      38           0 :   {
      39           0 :     FD_LOG_WARNING(("fd_runtime_save_banks failed: %s", fd_funk_strerror(opt_err)));
      40           0 :     return opt_err;
      41           0 :   }
      42             : 
      43           0 :   uchar *buf = fd_funk_val(rec, fd_funk_wksp(slot_ctx->acc_mgr->funk));
      44           0 :   *(uint*)buf = FD_RUNTIME_ENC_BINCODE;
      45           0 :   fd_bincode_encode_ctx_t ctx = {
      46           0 :       .data = buf + sizeof(uint),
      47           0 :       .dataend = buf + sz,
      48           0 :   };
      49             : 
      50           0 :   if (FD_UNLIKELY(fd_epoch_bank_encode(epoch_bank, &ctx) != FD_BINCODE_SUCCESS))
      51           0 :   {
      52           0 :     FD_LOG_WARNING(("fd_runtime_save_banks: fd_firedancer_banks_encode failed"));
      53           0 :     return -1;
      54           0 :   }
      55           0 :   FD_TEST(ctx.data == ctx.dataend);
      56             : 
      57           0 :   FD_LOG_DEBUG(( "epoch frozen, slot=%lu bank_hash=%s poh_hash=%s", slot_ctx->slot_bank.slot, FD_BASE58_ENC_32_ALLOCA( slot_ctx->slot_bank.banks_hash.hash ), FD_BASE58_ENC_32_ALLOCA( slot_ctx->slot_bank.poh.hash ) ));
      58             : 
      59           0 :   return FD_RUNTIME_EXECUTE_SUCCESS;
      60           0 : }
      61             : 
      62           0 : int fd_runtime_save_slot_bank( fd_exec_slot_ctx_t * slot_ctx ) {
      63           0 :   ulong sz = sizeof(uint) + fd_slot_bank_size( &slot_ctx->slot_bank );
      64             : 
      65           0 :   fd_funk_rec_key_t id      = fd_runtime_slot_bank_key();
      66           0 :   int               opt_err = 0;
      67           0 :   fd_funk_rec_t *   rec     = fd_funk_rec_write_prepare( slot_ctx->acc_mgr->funk,
      68           0 :                                                          slot_ctx->funk_txn,
      69           0 :                                                          &id,
      70           0 :                                                          sz,
      71           0 :                                                          1,
      72           0 :                                                          NULL,
      73           0 :                                                          &opt_err );
      74           0 :   if( !rec ) {
      75           0 :     FD_LOG_WARNING(( "fd_runtime_save_banks failed: %s", fd_funk_strerror( opt_err ) ));
      76           0 :     return opt_err;
      77           0 :   }
      78             : 
      79           0 :   uchar * buf = fd_funk_val( rec, fd_funk_wksp( slot_ctx->acc_mgr->funk ) );
      80           0 :   *(uint*)buf = FD_RUNTIME_ENC_BINCODE;
      81           0 :   fd_bincode_encode_ctx_t ctx = {
      82           0 :       .data    = buf + sizeof(uint),
      83           0 :       .dataend = buf + sz,
      84           0 :   };
      85             : 
      86           0 :   if( FD_UNLIKELY( fd_slot_bank_encode( &slot_ctx->slot_bank, &ctx ) != FD_BINCODE_SUCCESS ) ) {
      87           0 :     FD_LOG_WARNING(( "fd_runtime_save_banks: fd_firedancer_banks_encode failed" ));
      88           0 :     return -1;
      89           0 :   }
      90             : 
      91           0 :   if( FD_UNLIKELY( ctx.data!=ctx.dataend ) ) {
      92           0 :     FD_LOG_ERR(( "Data does not equal to end of buffer" ));
      93           0 :   }
      94             : 
      95           0 :   FD_LOG_DEBUG(( "slot frozen, slot=%lu bank_hash=%s poh_hash=%s",
      96           0 :                  slot_ctx->slot_bank.slot,
      97           0 :                  FD_BASE58_ENC_32_ALLOCA( slot_ctx->slot_bank.banks_hash.hash ),
      98           0 :                  FD_BASE58_ENC_32_ALLOCA( slot_ctx->slot_bank.poh.hash ) ));
      99             : 
     100           0 :   return FD_RUNTIME_EXECUTE_SUCCESS;
     101           0 : }
     102             : 
     103             : void
     104             : fd_runtime_recover_banks( fd_exec_slot_ctx_t * slot_ctx,
     105             :                           int                  delete_first,
     106             :                           int                  clear_first,
     107           0 :                           fd_spad_t *          runtime_spad ) {
     108             : 
     109           0 :   fd_funk_t *           funk         = slot_ctx->acc_mgr->funk;
     110           0 :   fd_funk_txn_t *       txn          = slot_ctx->funk_txn;
     111           0 :   fd_exec_epoch_ctx_t * epoch_ctx    = slot_ctx->epoch_ctx;
     112           0 :   {
     113           0 :     fd_funk_rec_key_t id = fd_runtime_epoch_bank_key();
     114           0 :     fd_funk_rec_t const * rec = fd_funk_rec_query_global(funk, txn, &id, NULL);
     115           0 :     if ( rec == NULL )
     116           0 :       FD_LOG_ERR(("failed to read banks record: missing record"));
     117           0 :     void * val = fd_funk_val( rec, fd_funk_wksp(funk) );
     118             : 
     119           0 :     if( fd_funk_val_sz( rec ) < sizeof(uint) ) {
     120           0 :       FD_LOG_ERR(("failed to read banks record: empty record"));
     121           0 :     }
     122           0 :     uint magic = *(uint*)val;
     123             : 
     124           0 :     if( clear_first ) {
     125           0 :       fd_exec_epoch_ctx_bank_mem_clear( epoch_ctx );
     126           0 :     }
     127             : 
     128           0 :     fd_bincode_decode_ctx_t ctx = {
     129           0 :       .data    = (uchar*)val + sizeof(uint),
     130           0 :       .dataend = (uchar*)val + fd_funk_val_sz( rec )
     131           0 :     };
     132           0 :     if( magic==FD_RUNTIME_ENC_BINCODE ) {
     133             : 
     134           0 :       ulong total_sz = 0UL;
     135           0 :       int   err      = fd_epoch_bank_decode_footprint( &ctx, &total_sz );
     136           0 :       if( FD_UNLIKELY( err ) ) {
     137           0 :         FD_LOG_WARNING(( "failed to read banks record: invalid decode" ));
     138           0 :         return;
     139           0 :       }
     140             : 
     141           0 :       uchar * mem = fd_spad_alloc( runtime_spad, fd_epoch_bank_align(), total_sz );
     142           0 :       if( FD_UNLIKELY( !mem ) ) {
     143           0 :         FD_LOG_ERR(( "failed to read banks record: unable to allocate memory" ));
     144           0 :       }
     145             : 
     146           0 :       fd_epoch_bank_decode( mem, &ctx );
     147             : 
     148           0 :       epoch_ctx->epoch_bank = *(fd_epoch_bank_t *)mem;
     149           0 :     } else {
     150           0 :       FD_LOG_ERR(( "failed to read banks record: invalid magic number" ));
     151           0 :     }
     152             : 
     153           0 :     FD_LOG_NOTICE(( "recovered epoch_bank" ));
     154           0 :   }
     155             : 
     156           0 :   {
     157           0 :     if( delete_first ) {
     158           0 :       fd_slot_bank_destroy( &slot_ctx->slot_bank );
     159           0 :     }
     160           0 :     fd_funk_rec_key_t     id  = fd_runtime_slot_bank_key();
     161           0 :     fd_funk_rec_t const * rec = fd_funk_rec_query_global( funk, txn, &id, NULL );
     162           0 :     if( FD_UNLIKELY( !rec ) ) {
     163           0 :       FD_LOG_ERR(( "failed to read banks record: missing record" ));
     164           0 :     }
     165           0 :     void * val = fd_funk_val( rec, fd_funk_wksp( funk ) );
     166             : 
     167           0 :     if( fd_funk_val_sz( rec ) < sizeof(uint) ) {
     168           0 :       FD_LOG_ERR(( "failed to read banks record: empty record" ));
     169           0 :     }
     170           0 :     uint magic = *(uint*)val;
     171             : 
     172           0 :     fd_bincode_decode_ctx_t ctx = {
     173           0 :       .data    = (uchar*)val + sizeof(uint),
     174           0 :       .dataend = (uchar*)val + fd_funk_val_sz( rec ),
     175           0 :     };
     176           0 :     if( magic == FD_RUNTIME_ENC_BINCODE ) {
     177             : 
     178           0 :       ulong total_sz = 0UL;
     179           0 :       int   err      = fd_slot_bank_decode_footprint( &ctx, &total_sz );
     180           0 :       if( FD_UNLIKELY( err ) ) {
     181           0 :         FD_LOG_ERR(( "failed to read banks record: invalid decode" ));
     182           0 :       }
     183             : 
     184           0 :       uchar * mem = fd_spad_alloc( runtime_spad, fd_slot_bank_align(), total_sz );
     185           0 :       if( FD_UNLIKELY( !mem ) ) {
     186           0 :         FD_LOG_ERR(( "failed to read banks record: unable to allocate memory" ));
     187           0 :       }
     188             : 
     189           0 :       fd_slot_bank_decode( mem, &ctx );
     190             : 
     191             :       /* FIXME: This memcpy is not good. The slot ctx should just have a pointer
     192             :          to a slot_bank that can be assigned at this point. */
     193           0 :       memcpy( &slot_ctx->slot_bank, mem, sizeof(fd_slot_bank_t) );
     194             : 
     195           0 :     } else {
     196           0 :       FD_LOG_ERR(("failed to read banks record: invalid magic number"));
     197           0 :     }
     198             : 
     199           0 :     FD_LOG_NOTICE(( "recovered slot_bank for slot=%ld banks_hash=%s poh_hash %s lthash %s",
     200           0 :                     (long)slot_ctx->slot_bank.slot,
     201           0 :                     FD_BASE58_ENC_32_ALLOCA( slot_ctx->slot_bank.banks_hash.hash ),
     202           0 :                     FD_BASE58_ENC_32_ALLOCA( slot_ctx->slot_bank.poh.hash ),
     203           0 :                     FD_LTHASH_ENC_32_ALLOCA( (fd_lthash_value_t *) slot_ctx->slot_bank.lthash.lthash ) ));
     204             : 
     205           0 :     slot_ctx->slot_bank.collected_execution_fees = 0;
     206           0 :     slot_ctx->slot_bank.collected_priority_fees = 0;
     207           0 :     slot_ctx->slot_bank.collected_rent = 0;
     208           0 :     slot_ctx->txn_count = 0;
     209           0 :     slot_ctx->nonvote_txn_count = 0;
     210           0 :     slot_ctx->failed_txn_count = 0;
     211           0 :     slot_ctx->nonvote_failed_txn_count = 0;
     212           0 :     slot_ctx->total_compute_units_used = 0;
     213           0 :   }
     214             : 
     215           0 : }
     216             : 
     217             : void
     218           0 : fd_runtime_delete_banks( fd_exec_slot_ctx_t * slot_ctx ) {
     219             : 
     220             :   /* As the collection pointers are not owned by fd_alloc, zero them
     221             :      out to prevent invalid frees by the destroy function.
     222             : 
     223             :      TODO: This free actually doesn't do anything because of spad. */
     224             : 
     225           0 :   fd_exec_epoch_ctx_epoch_bank_delete( slot_ctx->epoch_ctx );
     226           0 :   fd_slot_bank_destroy( &slot_ctx->slot_bank );
     227           0 : }
     228             : 
     229             : 
     230             : /* fd_feature_restore loads a feature from the accounts database and
     231             :    updates the bank's feature activation state, given a feature account
     232             :    address. */
     233             : 
     234             : static void
     235             : fd_feature_restore( fd_exec_slot_ctx_t *    slot_ctx,
     236             :                     fd_feature_id_t const * id,
     237             :                     uchar const             acct[ static 32 ],
     238           0 :                     fd_spad_t *             runtime_spad ) {
     239             : 
     240           0 :   FD_TXN_ACCOUNT_DECL( acct_rec );
     241           0 :   int err = fd_acc_mgr_view( slot_ctx->acc_mgr, slot_ctx->funk_txn, (fd_pubkey_t *)acct, acct_rec );
     242           0 :   if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) {
     243           0 :     return;
     244           0 :   }
     245             : 
     246             :   /* Skip accounts that are not owned by the feature program */
     247           0 :   if( FD_UNLIKELY( memcmp( acct_rec->const_meta->info.owner, fd_solana_feature_program_id.key, sizeof(fd_pubkey_t) ) ) ) {
     248           0 :     return;
     249           0 :   }
     250             : 
     251             :   /* Skip reverted features */
     252           0 :   if( FD_UNLIKELY( id->reverted ) ) {
     253           0 :     return;
     254           0 :   }
     255             : 
     256           0 :   FD_SPAD_FRAME_BEGIN( runtime_spad ) {
     257             : 
     258           0 :     fd_bincode_decode_ctx_t ctx = {
     259           0 :       .data    = acct_rec->const_data,
     260           0 :       .dataend = acct_rec->const_data + acct_rec->const_meta->dlen,
     261           0 :     };
     262             : 
     263           0 :     ulong total_sz   = 0UL;
     264           0 :     int   decode_err = fd_feature_decode_footprint( &ctx, &total_sz );
     265           0 :     if( FD_UNLIKELY( decode_err!=FD_BINCODE_SUCCESS ) ) {
     266           0 :       FD_LOG_ERR(( "Failed to decode feature account %s (%d)", FD_BASE58_ENC_32_ALLOCA( acct ), decode_err ));
     267           0 :     }
     268             : 
     269           0 :     uchar * mem = fd_spad_alloc( runtime_spad, fd_feature_align(), total_sz );
     270           0 :     if( FD_UNLIKELY( !mem ) ) {
     271           0 :       FD_LOG_ERR(( "Failed to allocate memory for feature account %s", FD_BASE58_ENC_32_ALLOCA( acct ) ));
     272           0 :     }
     273             : 
     274           0 :     fd_feature_t * feature = fd_feature_decode( mem, &ctx );
     275             : 
     276           0 :     if( feature->has_activated_at ) {
     277           0 :       FD_LOG_INFO(( "Feature %s activated at %lu", FD_BASE58_ENC_32_ALLOCA( acct ), feature->activated_at ));
     278           0 :       fd_features_set( &slot_ctx->epoch_ctx->features, id, feature->activated_at );
     279           0 :     } else {
     280           0 :       FD_LOG_DEBUG(( "Feature %s not activated at %lu", FD_BASE58_ENC_32_ALLOCA( acct ), feature->activated_at ));
     281           0 :     }
     282             :     /* No need to call destroy, since we are using fd_spad allocator. */
     283           0 :   } FD_SPAD_FRAME_END;
     284           0 : }
     285             : 
     286             : void
     287           0 : fd_features_restore( fd_exec_slot_ctx_t * slot_ctx, fd_spad_t * runtime_spad ) {
     288           0 :   for( fd_feature_id_t const * id = fd_feature_iter_init();
     289           0 :                                    !fd_feature_iter_done( id );
     290           0 :                                id = fd_feature_iter_next( id ) ) {
     291           0 :     fd_feature_restore( slot_ctx, id, id->id.key, runtime_spad );
     292           0 :   }
     293           0 : }

Generated by: LCOV version 1.14