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

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

Generated by: LCOV version 1.14