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

Generated by: LCOV version 1.14