LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_runtime_init.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 228 0.0 %
Date: 2025-01-08 12:08:44 Functions: 0 10 0.0 %

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

Generated by: LCOV version 1.14