LCOV - code coverage report
Current view: top level - discof/restart - fd_restart_tile.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 306 0.0 %
Date: 2025-06-10 05:03:11 Functions: 0 7 0.0 %

          Line data    Source code
       1             : #include "fd_restart.h"
       2             : 
       3             : #include "../../disco/stem/fd_stem.h"
       4             : #include "../../disco/topo/fd_topo.h"
       5             : #include "../../util/pod/fd_pod_format.h"
       6             : #include "../../disco/keyguard/fd_keyload.h"
       7             : #include "../../funk/fd_funk_filemap.h"
       8             : #include "../../flamenco/runtime/fd_runtime.h"
       9             : 
      10           0 : #define GOSSIP_IN_IDX  (0UL)
      11           0 : #define STORE_IN_IDX   (1UL)
      12             : 
      13           0 : #define GOSSIP_OUT_IDX (0UL)
      14           0 : #define STORE_OUT_IDX  (1UL)
      15             : 
      16             : struct fd_restart_tile_ctx {
      17             :   fd_restart_t *        restart;
      18             :   fd_funk_t             funk[1];
      19             :   fd_epoch_bank_t       epoch_bank;
      20             :   int                   is_funk_active;
      21             :   char                  funk_file[ PATH_MAX ];
      22             :   fd_spad_t *           runtime_spad;
      23             :   int                   tower_checkpt_fileno;
      24             :   fd_pubkey_t           identity, coordinator, genesis_hash;
      25             :   fd_slot_pair_t *      new_hard_forks;
      26             :   ulong                 new_hard_forks_len;
      27             :   ulong *               is_constipated;
      28             : 
      29             :   // Gossip tile output
      30             :   fd_frag_meta_t *      gossip_out_mcache;
      31             :   ulong *               gossip_out_sync;
      32             :   ulong                 gossip_out_depth;
      33             :   ulong                 gossip_out_seq;
      34             : 
      35             :   fd_wksp_t *           gossip_out_mem;
      36             :   ulong                 gossip_out_chunk0;
      37             :   ulong                 gossip_out_wmark;
      38             :   ulong                 gossip_out_chunk;
      39             : 
      40             :   // Gossip tile input
      41             :   fd_wksp_t *           gossip_in_mem;
      42             :   ulong                 gossip_in_chunk0;
      43             :   ulong                 gossip_in_wmark;
      44             :   uchar                 restart_gossip_msg[ FD_RESTART_LINK_BYTES_MAX+sizeof(uint) ];
      45             : 
      46             :   // Store tile output
      47             :   fd_frag_meta_t *      store_out_mcache;
      48             :   ulong *               store_out_sync;
      49             :   ulong                 store_out_depth;
      50             :   ulong                 store_out_seq;
      51             : 
      52             :   fd_wksp_t *           store_out_mem;
      53             :   ulong                 store_out_chunk0;
      54             :   ulong                 store_out_wmark;
      55             :   ulong                 store_out_chunk;
      56             : 
      57             :   // Store tile input
      58             :   fd_wksp_t *           store_in_mem;
      59             :   ulong                 store_in_chunk0;
      60             :   ulong                 store_in_wmark;
      61             :   fd_funk_txn_xid_t     store_xid_msg;
      62             : };
      63             : typedef struct fd_restart_tile_ctx fd_restart_tile_ctx_t;
      64             : 
      65             : FD_FN_CONST static inline ulong
      66           0 : scratch_align( void ) {
      67           0 :   return 128UL;
      68           0 : }
      69             : 
      70             : FD_FN_PURE static inline ulong
      71           0 : scratch_footprint( fd_topo_tile_t const * tile ) {
      72             : 
      73             :   /* Do not modify order! This is join-order in unprivileged_init. */
      74           0 :   ulong l = FD_LAYOUT_INIT;
      75           0 :   l = FD_LAYOUT_APPEND( l, alignof(fd_restart_tile_ctx_t), sizeof(fd_restart_tile_ctx_t) );
      76           0 :   l = FD_LAYOUT_APPEND( l, fd_restart_align(), fd_restart_footprint() );
      77           0 :   l = FD_LAYOUT_APPEND( l, fd_spad_align(), fd_spad_footprint( tile->restart.heap_mem_max ) );
      78           0 :   l = FD_LAYOUT_FINI  ( l, scratch_align() );
      79           0 :   return l;
      80           0 : }
      81             : 
      82             : static void
      83             : privileged_init( fd_topo_t      * topo FD_PARAM_UNUSED,
      84           0 :                  fd_topo_tile_t * tile ) {
      85             :   /**********************************************************************/
      86             :   /* tower checkpoint                                                   */
      87             :   /**********************************************************************/
      88             : 
      89           0 :   tile->restart.tower_checkpt_fileno = -1;
      90           0 :   if( FD_LIKELY( strlen( tile->restart.tower_checkpt )>0 ) ) {
      91           0 :     tile->restart.tower_checkpt_fileno  = open( tile->restart.tower_checkpt,
      92           0 :                                                 O_RDWR | O_CREAT,
      93           0 :                                                 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
      94           0 :   }
      95           0 : }
      96             : 
      97             : static void
      98             : unprivileged_init( fd_topo_t      * topo,
      99           0 :                    fd_topo_tile_t * tile ) {
     100           0 :   void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
     101           0 :   FD_SCRATCH_ALLOC_INIT( l, scratch );
     102           0 :   fd_restart_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_restart_tile_ctx_t), sizeof(fd_restart_tile_ctx_t) );
     103           0 :   void * restart_mem          = FD_SCRATCH_ALLOC_APPEND( l, fd_restart_align(), fd_restart_footprint() );
     104           0 :   void * spad_mem             = FD_SCRATCH_ALLOC_APPEND( l, fd_spad_align(), fd_spad_footprint( tile->restart.heap_mem_max ) );
     105           0 :   FD_SCRATCH_ALLOC_FINI( l, scratch_align() );
     106             : 
     107             :   /**********************************************************************/
     108             :   /* restart                                                            */
     109             :   /**********************************************************************/
     110             : 
     111           0 :   ctx->restart = fd_restart_join( fd_restart_new( restart_mem ) );
     112             : 
     113             :   /**********************************************************************/
     114             :   /* funk                                                               */
     115             :   /**********************************************************************/
     116             : 
     117             :   /* TODO: Same as what happens in the batch tile, eventually, funk should
     118             :      be joined via a shared topology object. */
     119           0 :   ctx->is_funk_active = 0;
     120           0 :   memcpy( ctx->funk_file, tile->restart.funk_file, sizeof(tile->restart.funk_file) );
     121             : 
     122             :   /**********************************************************************/
     123             :   /* spad                                                               */
     124             :   /**********************************************************************/
     125             : 
     126           0 :   ctx->runtime_spad = fd_spad_join( fd_spad_new( spad_mem, tile->restart.heap_mem_max ) );
     127           0 :   fd_spad_push( ctx->runtime_spad );
     128             : 
     129             :   /**********************************************************************/
     130             :   /* tower checkpoint                                                   */
     131             :   /**********************************************************************/
     132             : 
     133           0 :   ctx->tower_checkpt_fileno = tile->restart.tower_checkpt_fileno;
     134           0 :   if( ctx->tower_checkpt_fileno<0 ) FD_LOG_ERR(( "Failed at opening the tower checkpoint file %s", tile->restart.tower_checkpt ));
     135             : 
     136             :   /**********************************************************************/
     137             :   /* hash and pubkeys                                                   */
     138             :   /**********************************************************************/
     139             : 
     140           0 :   fd_base58_decode_32( tile->restart.restart_coordinator, ctx->coordinator.key );
     141           0 :   fd_base58_decode_32( tile->restart.genesis_hash, ctx->genesis_hash.key );
     142           0 :   ctx->identity = *(fd_pubkey_t const *)fd_type_pun_const( fd_keyload_load( tile->restart.identity_key_path, 1 ) );
     143             : 
     144             :   /**********************************************************************/
     145             :   /* constipated fseq                                                   */
     146             :   /**********************************************************************/
     147             : 
     148           0 :   ulong constipated_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "constipate" );
     149           0 :   FD_TEST( constipated_obj_id!=ULONG_MAX );
     150           0 :   ctx->is_constipated = fd_fseq_join( fd_topo_obj_laddr( topo, constipated_obj_id ) );
     151           0 :   if( FD_UNLIKELY( !ctx->is_constipated ) ) FD_LOG_ERR(( "restart tile has no constipated fseq" ));
     152             :   //fd_fseq_update( ctx->is_constipated, 0UL );
     153             :   //FD_TEST( 0UL==fd_fseq_query( ctx->is_constipated ) );
     154             : 
     155             :   /**********************************************************************/
     156             :   /* links                                                              */
     157             :   /**********************************************************************/
     158             : 
     159           0 :   if( FD_UNLIKELY( tile->out_cnt < 1 ||
     160           0 :                    strcmp( topo->links[ tile->out_link_id[ GOSSIP_OUT_IDX ] ].name, "rstart_gossi" ) ) ) {
     161           0 :     FD_LOG_ERR(( "restart tile has unexpected output links, out_cnt=%lu %s", tile->out_cnt, topo->links[ tile->out_link_id[ GOSSIP_OUT_IDX ] ].name ));
     162           0 :   }
     163             : 
     164           0 :   fd_topo_link_t * gossip_out = &topo->links[ tile->out_link_id[ GOSSIP_OUT_IDX ] ];
     165           0 :   ctx->gossip_out_mcache      = gossip_out->mcache;
     166           0 :   ctx->gossip_out_sync        = fd_mcache_seq_laddr( ctx->gossip_out_mcache );
     167           0 :   ctx->gossip_out_depth       = fd_mcache_depth( ctx->gossip_out_mcache );
     168           0 :   ctx->gossip_out_seq         = fd_mcache_seq_query( ctx->gossip_out_sync );
     169           0 :   ctx->gossip_out_chunk0      = fd_dcache_compact_chunk0( fd_wksp_containing( gossip_out->dcache ), gossip_out->dcache );
     170           0 :   ctx->gossip_out_mem         = topo->workspaces[ topo->objs[ gossip_out->dcache_obj_id ].wksp_id ].wksp;
     171           0 :   ctx->gossip_out_wmark       = fd_dcache_compact_wmark( ctx->gossip_out_mem, gossip_out->dcache, gossip_out->mtu );
     172           0 :   ctx->gossip_out_chunk       = ctx->gossip_out_chunk0;
     173             : 
     174           0 :   fd_topo_link_t * gossip_in = &topo->links[ tile->in_link_id[ GOSSIP_IN_IDX ] ];
     175           0 :   ctx->gossip_in_mem         = topo->workspaces[ topo->objs[ gossip_in->dcache_obj_id ].wksp_id ].wksp;
     176           0 :   ctx->gossip_in_chunk0      = fd_dcache_compact_chunk0( ctx->gossip_in_mem, gossip_in->dcache );
     177           0 :   ctx->gossip_in_wmark       = fd_dcache_compact_wmark( ctx->gossip_in_mem, gossip_in->dcache, gossip_in->mtu );
     178             : 
     179           0 :   fd_topo_link_t * store_out = &topo->links[ tile->out_link_id[ STORE_OUT_IDX ] ];
     180           0 :   ctx->store_out_mcache      = store_out->mcache;
     181           0 :   ctx->store_out_sync        = fd_mcache_seq_laddr( ctx->store_out_mcache );
     182           0 :   ctx->store_out_depth       = fd_mcache_depth( ctx->store_out_mcache );
     183           0 :   ctx->store_out_seq         = fd_mcache_seq_query( ctx->store_out_sync );
     184           0 :   ctx->store_out_chunk0      = fd_dcache_compact_chunk0( fd_wksp_containing( store_out->dcache ), store_out->dcache );
     185           0 :   ctx->store_out_mem         = topo->workspaces[ topo->objs[ store_out->dcache_obj_id ].wksp_id ].wksp;
     186           0 :   ctx->store_out_wmark       = fd_dcache_compact_wmark( ctx->store_out_mem, store_out->dcache, store_out->mtu );
     187           0 :   ctx->store_out_chunk       = ctx->store_out_chunk0;
     188             : 
     189           0 :   fd_topo_link_t * store_in = &topo->links[ tile->in_link_id[ STORE_IN_IDX ] ];
     190           0 :   ctx->store_in_mem         = topo->workspaces[ topo->objs[ store_in->dcache_obj_id ].wksp_id ].wksp;
     191           0 :   ctx->store_in_chunk0      = fd_dcache_compact_chunk0( ctx->store_in_mem, store_in->dcache );
     192           0 :   ctx->store_in_wmark       = fd_dcache_compact_wmark( ctx->store_in_mem, store_in->dcache, store_in->mtu );
     193             : 
     194           0 : }
     195             : 
     196             : static void
     197             : during_frag( fd_restart_tile_ctx_t * ctx,
     198             :              ulong                   in_idx,
     199             :              ulong                   seq FD_PARAM_UNUSED,
     200             :              ulong                   sig FD_PARAM_UNUSED,
     201             :              ulong                   chunk,
     202             :              ulong                   sz,
     203           0 :              ulong                   ctl FD_PARAM_UNUSED ) {
     204           0 :   if( FD_LIKELY( in_idx==GOSSIP_IN_IDX ) ) {
     205           0 :     if( FD_UNLIKELY( chunk<ctx->gossip_in_chunk0 || chunk>ctx->gossip_in_wmark || sz>FD_RESTART_LINK_BYTES_MAX+sizeof(uint) ) ) {
     206           0 :       FD_LOG_ERR(( "chunk %lu %lu corrupt, not in range [%lu,%lu]", chunk, sz, ctx->gossip_in_chunk0, ctx->gossip_in_wmark ));
     207           0 :     }
     208             : 
     209           0 :     fd_memcpy( ctx->restart_gossip_msg, fd_chunk_to_laddr( ctx->gossip_in_mem, chunk ), sz );
     210           0 :     return;
     211           0 :   }
     212             : 
     213           0 :   if( FD_UNLIKELY( in_idx==STORE_IN_IDX ) ) {
     214           0 :     if( FD_UNLIKELY( chunk<ctx->store_in_chunk0 || chunk>ctx->store_in_wmark || sz!=sizeof(fd_funk_txn_xid_t) ) ) {
     215           0 :       FD_LOG_ERR(( "chunk %lu %lu corrupt, not in range [%lu,%lu]", chunk, sz, ctx->store_in_chunk0, ctx->store_in_wmark ));
     216           0 :     }
     217             : 
     218           0 :     fd_memcpy( &ctx->store_xid_msg, fd_chunk_to_laddr( ctx->store_in_mem, chunk), sz );
     219           0 :     return;
     220           0 :   }
     221           0 : }
     222             : 
     223             : static void
     224             : after_frag( fd_restart_tile_ctx_t * ctx,
     225             :             ulong                  in_idx,
     226             :             ulong                  seq FD_PARAM_UNUSED,
     227             :             ulong                  sig FD_PARAM_UNUSED,
     228             :             ulong                  sz FD_PARAM_UNUSED,
     229             :             ulong                  tsorig FD_PARAM_UNUSED,
     230             :             ulong                  tspub FD_PARAM_UNUSED,
     231           0 :             fd_stem_context_t *    stem FD_PARAM_UNUSED ) {
     232           0 :   if( FD_LIKELY( in_idx==GOSSIP_IN_IDX ) ) {
     233           0 :     ulong heaviest_fork_found = 0, need_repair = 0;
     234           0 :     fd_restart_recv_gossip_msg( ctx->restart, ctx->restart_gossip_msg, &heaviest_fork_found );
     235           0 :     if( FD_UNLIKELY( heaviest_fork_found ) ) {
     236           0 :       fd_restart_find_heaviest_fork_bank_hash( ctx->restart, ctx->funk, &need_repair );
     237           0 :       if( FD_LIKELY( need_repair ) ) {
     238             :         /* Send the heaviest fork slot to the store tile for repair and replay */
     239           0 :         uchar * buf = fd_chunk_to_laddr( ctx->store_out_mem, ctx->store_out_chunk );
     240           0 :         FD_STORE( ulong, buf, ctx->restart->heaviest_fork_slot );
     241           0 :         FD_STORE( ulong, buf+sizeof(ulong), ctx->restart->funk_root );
     242           0 :         fd_mcache_publish( ctx->store_out_mcache, ctx->store_out_depth, ctx->store_out_seq, 1UL, ctx->store_out_chunk,
     243           0 :                            sizeof(ulong)*2, 0UL, 0, 0 );
     244           0 :         ctx->store_out_seq   = fd_seq_inc( ctx->store_out_seq, 1UL );
     245           0 :         ctx->store_out_chunk = fd_dcache_compact_next( ctx->store_out_chunk, sizeof(ulong)*2, ctx->store_out_chunk0, ctx->store_out_wmark );
     246           0 :       }
     247           0 :     }
     248           0 :   }
     249             : 
     250           0 :   if( FD_UNLIKELY( in_idx==STORE_IN_IDX ) ) {
     251             :     /* Decode the slot bank for HeaviestForkSlot from funk, referencing fd_runtime_recover_banks() in fd_runtime_init.c */
     252           0 :     fd_funk_rec_key_t   id      = fd_runtime_slot_bank_key();
     253           0 :     fd_funk_txn_map_t * txn_map = fd_funk_txn_map( ctx->funk );
     254           0 :     fd_funk_txn_start_read( ctx->funk );
     255           0 :     fd_funk_txn_t *    funk_txn = fd_funk_txn_query( &ctx->store_xid_msg, txn_map );
     256           0 :     if( FD_UNLIKELY( !funk_txn ) ) {
     257             :       /* Try again with xid.ul[1] being the slot number instead of the block hash */
     258           0 :       ctx->store_xid_msg.ul[1] = ctx->restart->heaviest_fork_slot;
     259           0 :       funk_txn = fd_funk_txn_query( &ctx->store_xid_msg, txn_map );
     260           0 :       if( FD_UNLIKELY( !funk_txn ) ) {
     261           0 :         FD_LOG_ERR(( "Wen-restart fails due to NULL funk_txn" ));
     262           0 :       }
     263           0 :     }
     264           0 :     fd_funk_txn_end_read( ctx->funk );
     265           0 :     fd_funk_rec_query_t query[1];
     266           0 :     fd_funk_rec_t const * rec = fd_funk_rec_query_try( ctx->funk, funk_txn, &id, query );
     267           0 :     void *                val = fd_funk_val( rec, fd_funk_wksp( ctx->funk ) );
     268           0 :     if( fd_funk_val_sz( rec ) < sizeof(uint) ) {
     269           0 :       FD_LOG_ERR(( "failed to read banks record: empty record" ));
     270           0 :     }
     271           0 :     uint magic = *(uint*)val;
     272             : 
     273           0 :     if( FD_UNLIKELY( magic!=FD_RUNTIME_ENC_BINCODE ) ) {
     274           0 :       FD_LOG_ERR(( "failed to read banks record: invalid magic number" ));
     275           0 :     }
     276             : 
     277           0 :     int err;
     278           0 :     fd_slot_bank_t * slot_bank = fd_bincode_decode_spad(
     279           0 :         slot_bank, ctx->runtime_spad,
     280           0 :         (uchar *)val          + sizeof(uint),
     281           0 :         fd_funk_val_sz( rec ) - sizeof(uint),
     282           0 :         &err );
     283           0 :     if( FD_UNLIKELY( err ) ) {
     284           0 :       FD_LOG_ERR(( "failed to read banks record: invalid decode" ));
     285           0 :     }
     286             : 
     287           0 :     FD_TEST( !fd_funk_rec_query_test( query ) );
     288             : 
     289             :     /* Add a hard fork into the slot bank */
     290           0 :     ulong old_len           = slot_bank->hard_forks.hard_forks_len;
     291           0 :     ctx->new_hard_forks_len = old_len + 1;
     292           0 :     ctx->new_hard_forks     = fd_spad_alloc( ctx->runtime_spad, 8, ctx->new_hard_forks_len*sizeof(fd_slot_pair_t) );
     293           0 :     fd_memcpy( ctx->new_hard_forks, slot_bank->hard_forks.hard_forks, old_len*sizeof(fd_slot_pair_t) );
     294             : 
     295           0 :     ctx->new_hard_forks[ old_len ].slot  = ctx->restart->heaviest_fork_slot;
     296           0 :     ctx->new_hard_forks[ old_len ].val   = 1;
     297           0 :     slot_bank->hard_forks.hard_forks     = ctx->new_hard_forks;
     298           0 :     slot_bank->hard_forks.hard_forks_len = ctx->new_hard_forks_len;
     299             : 
     300             :     /* Write the slot bank back to funk, referencing fd_runtime_save_slot_bank */
     301           0 :     int funk_err = 0;
     302           0 :     fd_funk_rec_prepare_t prepare[1];
     303           0 :     fd_funk_rec_t * new_rec = fd_funk_rec_prepare(
     304           0 :         ctx->funk, funk_txn, &id, prepare, &funk_err );
     305           0 :     if( FD_UNLIKELY( !new_rec ) ) {
     306           0 :       FD_LOG_ERR(( "fd_funk_rec_prepare() failed (%i-%s)", funk_err, fd_funk_strerror( funk_err ) ));
     307           0 :     }
     308             : 
     309           0 :     ulong   sz  = sizeof(uint) + fd_slot_bank_size( slot_bank );
     310           0 :     uchar * buf = fd_funk_val_truncate(
     311           0 :         new_rec,
     312           0 :         fd_funk_alloc( ctx->funk ),
     313           0 :         fd_funk_wksp( ctx->funk ),
     314           0 :         0UL,
     315           0 :         sz,
     316           0 :         &funk_err );
     317           0 :     if( FD_UNLIKELY( !buf ) ) FD_LOG_ERR(( "fd_funk_val_truncate(sz=%lu) failed (%i-%s)", sz, funk_err, fd_funk_strerror( funk_err ) ));
     318           0 :     FD_STORE( uint, buf, FD_RUNTIME_ENC_BINCODE );
     319           0 :     fd_bincode_encode_ctx_t slot_bank_encode_ctx = {
     320           0 :       .data    = buf + sizeof(uint),
     321           0 :       .dataend = buf + sz,
     322           0 :     };
     323           0 :     if( FD_UNLIKELY( fd_slot_bank_encode( slot_bank, &slot_bank_encode_ctx ) != FD_BINCODE_SUCCESS ||
     324           0 :                      slot_bank_encode_ctx.data!=slot_bank_encode_ctx.dataend) ) {
     325           0 :       FD_LOG_ERR(( "Wen-restart fails at inserting a hard fork in slot bank and save it in funk" ));
     326           0 :     }
     327             : 
     328           0 :     fd_funk_rec_publish( ctx->funk, prepare );
     329             : 
     330             :     /* Publish the txn in funk */
     331           0 :     fd_funk_txn_start_write( ctx->funk );
     332           0 :     if( FD_UNLIKELY( !fd_funk_txn_publish( ctx->funk, funk_txn, 1 ) ) ) {
     333           0 :       FD_LOG_ERR(( "Wen-restart fails at funk txn publish" ));
     334           0 :     }
     335           0 :     fd_funk_txn_end_write( ctx->funk );
     336             : 
     337             :     /* Copy the bank hash of HeaviestForkSlot to fd_restart_t */
     338           0 :     ctx->restart->heaviest_fork_bank_hash = slot_bank->banks_hash;
     339           0 :     ctx->restart->heaviest_fork_ready = 1;
     340           0 :   }
     341           0 : }
     342             : 
     343             : static void
     344             : after_credit( fd_restart_tile_ctx_t * ctx,
     345             :               fd_stem_context_t *     stem FD_PARAM_UNUSED,
     346             :               int *                   opt_poll_in FD_PARAM_UNUSED,
     347           0 :               int *                   charge_busy FD_PARAM_UNUSED ) {
     348           0 :   if( FD_UNLIKELY( !ctx->is_funk_active ) ) {
     349             :     /* Setting these parameters are not required because we are joining the
     350             :        funk that was setup in the replay tile. */
     351           0 :     fd_funk_t * funk = fd_funk_open_file(
     352           0 :         ctx->funk, ctx->funk_file,
     353           0 :         1UL, 0UL, 0UL, 0UL, 0UL, FD_FUNK_READ_WRITE, NULL );
     354           0 :     if( FD_UNLIKELY( !funk ) ) {
     355           0 :       FD_LOG_ERR(( "fd_funk_open_file failed" ));
     356           0 :     } else {
     357           0 :       FD_LOG_NOTICE(("Restart tile joins funk successfully"));
     358           0 :     }
     359           0 :     ctx->is_funk_active = 1;
     360             : 
     361             :     /* Decode the slot bank from funk, referencing fd_runtime_recover_banks() in fd_runtime_init.c */
     362           0 :     fd_slot_bank_t * slot_bank = NULL;
     363           0 :     {
     364           0 :       fd_funk_rec_key_t     id  = fd_runtime_slot_bank_key();
     365           0 :       fd_funk_rec_query_t   query[1];
     366           0 :       fd_funk_rec_t const * rec = fd_funk_rec_query_try( ctx->funk, NULL, &id, query );
     367           0 :       void *                val = fd_funk_val( rec, fd_funk_wksp( ctx->funk ) );
     368           0 :       if( fd_funk_val_sz( rec ) < sizeof(uint) ) {
     369           0 :         FD_LOG_ERR(( "failed to read banks record: empty record" ));
     370           0 :       }
     371           0 :       uint magic = *(uint*)val;
     372           0 :       if( FD_UNLIKELY( magic!=FD_RUNTIME_ENC_BINCODE ) ) {
     373           0 :         FD_LOG_ERR(( "failed to read banks record: invalid magic number" ));
     374           0 :       }
     375             : 
     376           0 :       int err;
     377           0 :       slot_bank = fd_bincode_decode_spad(
     378           0 :           slot_bank, ctx->runtime_spad,
     379           0 :           (uchar *)val          + sizeof(uint),
     380           0 :           fd_funk_val_sz( rec ) - sizeof(uint),
     381           0 :           &err );
     382           0 :       if( FD_UNLIKELY( err ) ) {
     383           0 :         FD_LOG_ERR(( "failed to read banks record: invalid decode" ));
     384           0 :       }
     385             : 
     386           0 :       FD_TEST( !fd_funk_rec_query_test( query ) );
     387           0 :     }
     388             : 
     389             :     /* Decode the epoch bank from funk, referencing fd_runtime_recover_banks() in fd_runtime_init.c */
     390           0 :     {
     391           0 :       fd_funk_rec_key_t     id = fd_runtime_epoch_bank_key();
     392           0 :       fd_funk_rec_query_t   query[1];
     393           0 :       fd_funk_rec_t const * rec = fd_funk_rec_query_try( ctx->funk, NULL, &id, query );
     394           0 :       void *                val = fd_funk_val( rec, fd_funk_wksp( ctx->funk ) );
     395           0 :       if( fd_funk_val_sz( rec ) < sizeof(uint) ) {
     396           0 :         FD_LOG_ERR(("failed to read banks record: empty record"));
     397           0 :       }
     398           0 :       uint magic = *(uint*)val;
     399           0 :       if( FD_UNLIKELY( magic!=FD_RUNTIME_ENC_BINCODE ) ) {
     400           0 :           FD_LOG_ERR(( "failed to read banks record: invalid magic number" ));
     401           0 :       }
     402             : 
     403           0 :       int err;
     404           0 :       fd_epoch_bank_t * epoch_bank = fd_bincode_decode_spad(
     405           0 :           epoch_bank, ctx->runtime_spad,
     406           0 :           (uchar *)val          + sizeof(uint),
     407           0 :           fd_funk_val_sz( rec ) - sizeof(uint),
     408           0 :           &err );
     409           0 :       if( FD_UNLIKELY( err ) ) {
     410           0 :         FD_LOG_ERR(( "failed to read banks record: invalid decode" ));
     411           0 :       }
     412             : 
     413           0 :       ctx->epoch_bank = *epoch_bank;
     414             : 
     415           0 :       FD_TEST( !fd_funk_rec_query_test( query ) );
     416           0 :     }
     417             : 
     418             :     /* Decode the slot history sysvar, referencing fd_sysvar_slot_history_read in fd_sysvar_slot_history.c */
     419           0 :     fd_slot_history_t * slot_history = NULL;
     420           0 :     {
     421           0 :       fd_pubkey_t const * program = &fd_sysvar_slot_history_id;
     422           0 :       FD_TXN_ACCOUNT_DECL( rec );
     423           0 :       int err = fd_txn_account_init_from_funk_readonly( rec, program, ctx->funk, NULL );
     424           0 :       if (err)
     425           0 :         FD_LOG_ERR(( "fd_txn_account_init_from_funk_readonly(slot_history) failed: %d", err ));
     426             : 
     427           0 :       slot_history = fd_bincode_decode_spad(
     428           0 :           slot_history, ctx->runtime_spad,
     429           0 :           rec->vt->get_data( rec ),
     430           0 :           rec->vt->get_data_len( rec ),
     431           0 :           &err );
     432           0 :       if( FD_UNLIKELY( err ) ) {
     433           0 :         FD_LOG_ERR(( "fd_slot_history_decode_footprint failed" ));
     434           0 :       }
     435           0 :     }
     436             : 
     437           0 :     fd_vote_accounts_t const * epoch_stakes[ FD_RESTART_EPOCHS_MAX ] = { &ctx->epoch_bank.stakes.vote_accounts,
     438           0 :                                                                          &ctx->epoch_bank.next_epoch_stakes };
     439             : 
     440           0 :     ulong buf_len = 0;
     441           0 :     uchar * buf   = fd_chunk_to_laddr( ctx->gossip_out_mem, ctx->gossip_out_chunk );
     442             : 
     443           0 :     fd_restart_init( ctx->restart,
     444           0 :                      slot_bank->slot,
     445           0 :                      &slot_bank->banks_hash,
     446           0 :                      epoch_stakes,
     447           0 :                      &ctx->epoch_bank.epoch_schedule,
     448           0 :                      ctx->tower_checkpt_fileno,
     449           0 :                      slot_history,
     450           0 :                      &ctx->identity,
     451           0 :                      &ctx->coordinator,
     452           0 :                      buf+sizeof(uint),
     453           0 :                      &buf_len,
     454           0 :                      ctx->runtime_spad );
     455           0 :     buf_len += sizeof(uint);
     456           0 :     FD_STORE( uint, buf, fd_crds_data_enum_restart_last_voted_fork_slots );
     457           0 :     fd_mcache_publish( ctx->gossip_out_mcache, ctx->gossip_out_depth, ctx->gossip_out_seq, 1UL, ctx->gossip_out_chunk,
     458           0 :                        buf_len, 0UL, 0, 0 );
     459           0 :     ctx->gossip_out_seq   = fd_seq_inc( ctx->gossip_out_seq, 1UL );
     460           0 :     ctx->gossip_out_chunk = fd_dcache_compact_next( ctx->gossip_out_chunk, buf_len, ctx->gossip_out_chunk0, ctx->gossip_out_wmark );
     461           0 :   }
     462             : 
     463             :   /* See whether wen-restart can finish */
     464           0 :   ulong send  = 0;
     465           0 :   uchar * buf = fd_chunk_to_laddr( ctx->gossip_out_mem, ctx->gossip_out_chunk );
     466           0 :   fd_restart_verify_heaviest_fork( ctx->restart,
     467           0 :                                    ctx->is_constipated,
     468           0 :                                    ctx->new_hard_forks,
     469           0 :                                    ctx->new_hard_forks_len,
     470           0 :                                    &ctx->genesis_hash,
     471           0 :                                    buf+sizeof(uint),
     472           0 :                                    &send );
     473             : 
     474           0 :   if( FD_UNLIKELY( send ) ) {
     475             :     /* Send the restart_heaviest_fork message to gossip tile */
     476           0 :     ulong buf_len = sizeof(uint) + sizeof(fd_gossip_restart_heaviest_fork_t);
     477           0 :     FD_STORE( uint, buf, fd_crds_data_enum_restart_heaviest_fork );
     478           0 :     fd_mcache_publish( ctx->gossip_out_mcache, ctx->gossip_out_depth, ctx->gossip_out_seq, 1UL, ctx->gossip_out_chunk,
     479           0 :                        buf_len, 0UL, 0, 0 );
     480           0 :     ctx->gossip_out_seq   = fd_seq_inc( ctx->gossip_out_seq, 1UL );
     481           0 :     ctx->gossip_out_chunk = fd_dcache_compact_next( ctx->gossip_out_chunk, buf_len, ctx->gossip_out_chunk0, ctx->gossip_out_wmark );
     482           0 :   }
     483             : 
     484           0 : }
     485             : 
     486           0 : #define STEM_BURST (1UL)
     487             : 
     488           0 : #define STEM_CALLBACK_CONTEXT_TYPE          fd_restart_tile_ctx_t
     489           0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_restart_tile_ctx_t)
     490             : 
     491           0 : #define STEM_CALLBACK_DURING_FRAG   during_frag
     492           0 : #define STEM_CALLBACK_AFTER_FRAG    after_frag
     493           0 : #define STEM_CALLBACK_AFTER_CREDIT  after_credit
     494             : 
     495             : #include "../../disco/stem/fd_stem.c"
     496             : 
     497             : fd_topo_run_tile_t fd_tile_restart = {
     498             :   .name                     = "rstart",
     499             : //  .populate_allowed_seccomp = populate_allowed_seccomp,
     500             : //  .populate_allowed_fds     = populate_allowed_fds,
     501             :   .scratch_align            = scratch_align,
     502             :   .scratch_footprint        = scratch_footprint,
     503             :   .privileged_init          = privileged_init,
     504             :   .unprivileged_init        = unprivileged_init,
     505             :   .run                      = stem_run,
     506             : };

Generated by: LCOV version 1.14