LCOV - code coverage report
Current view: top level - discof/batch - fd_batch_tile.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 266 0.0 %
Date: 2025-06-27 11:04:50 Functions: 0 10 0.0 %

          Line data    Source code
       1             : #include "../../disco/topo/fd_topo.h"
       2             : #include "../../util/pod/fd_pod_format.h"
       3             : #include "../../funk/fd_funk.h"
       4             : #include "../../flamenco/runtime/fd_hashes.h"
       5             : #include "../../flamenco/runtime/fd_txncache.h"
       6             : #include "../../flamenco/snapshot/fd_snapshot_create.h"
       7             : #include "../../flamenco/runtime/fd_runtime.h"
       8             : #include "../../flamenco/runtime/fd_runtime_public.h"
       9             : 
      10             : #include "generated/fd_batch_tile_seccomp.h"
      11             : 
      12             : #include <errno.h>
      13             : #include <unistd.h>
      14             : 
      15           0 : #define REPLAY_OUT_IDX     (0UL)
      16           0 : #define EAH_REPLAY_OUT_SIG (0UL)
      17             : 
      18           0 : #define MEM_FOOTPRINT      (8UL<<30)
      19             : 
      20             : struct fd_snapshot_tile_ctx {
      21             :   /* User defined parameters. */
      22             :   ulong           full_interval;
      23             :   ulong           incremental_interval;
      24             :   char const    * out_dir;
      25             : 
      26             :   /* Shared data structures. */
      27             :   fd_txncache_t * status_cache;
      28             :   ulong         * is_constipated;
      29             :   fd_funk_t       funk[1];
      30             : 
      31             :   /* File descriptors used for snapshot generation. */
      32             :   int             tmp_fd;
      33             :   int             tmp_inc_fd;
      34             :   int             full_snapshot_fd;
      35             :   int             incremental_snapshot_fd;
      36             : 
      37             :   /* Metadata from the full snapshot used for incremental snapshots. */
      38             :   ulong           last_full_snap_slot;
      39             :   fd_hash_t       last_hash;
      40             :   ulong           last_capitalization;
      41             : 
      42             :   /* Replay out link fields for epoch account hash. */
      43             :   fd_wksp_t *     replay_out_mem;
      44             :   ulong           replay_out_chunk;
      45             : 
      46             :   fd_wksp_t  *    runtime_public_wksp;
      47             :   fd_runtime_public_t * runtime_public;
      48             : 
      49             :   /* Bump allocator */
      50             :   fd_spad_t *     spad;
      51             : };
      52             : typedef struct fd_snapshot_tile_ctx fd_snapshot_tile_ctx_t;
      53             : 
      54             : 
      55             : FD_FN_CONST static inline ulong
      56           0 : scratch_align( void ) {
      57           0 :   return 128UL;
      58           0 : }
      59             : 
      60             : FD_FN_PURE static inline ulong
      61           0 : scratch_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED ) {
      62           0 :   ulong l = FD_LAYOUT_INIT;
      63           0 :   l = FD_LAYOUT_APPEND( l, alignof(fd_snapshot_tile_ctx_t), sizeof(fd_snapshot_tile_ctx_t) );
      64           0 :   l = FD_LAYOUT_APPEND( l, fd_spad_align(), fd_spad_footprint( MEM_FOOTPRINT ) );
      65           0 :   return FD_LAYOUT_FINI( l, scratch_align() );
      66           0 : }
      67             : 
      68             : static void
      69             : privileged_init( fd_topo_t      * topo FD_PARAM_UNUSED,
      70           0 :                  fd_topo_tile_t * tile ) {
      71             : 
      72             :   /* First open the relevant files here. TODO: We eventually want to extend
      73             :      this to support multiple files. */
      74             : 
      75           0 :   char tmp_dir_buf[ FD_SNAPSHOT_DIR_MAX ];
      76           0 :   int err = snprintf( tmp_dir_buf, FD_SNAPSHOT_DIR_MAX, "%s/%s", tile->batch.out_dir, FD_SNAPSHOT_TMP_ARCHIVE );
      77           0 :   if( FD_UNLIKELY( err<0 ) ) {
      78           0 :     FD_LOG_ERR(( "Failed to format directory string" ));
      79           0 :   }
      80             : 
      81           0 :   char tmp_inc_dir_buf[ FD_SNAPSHOT_DIR_MAX ];
      82           0 :   err = snprintf( tmp_inc_dir_buf, FD_SNAPSHOT_DIR_MAX, "%s/%s", tile->batch.out_dir, FD_SNAPSHOT_TMP_INCR_ARCHIVE );
      83           0 :   if( FD_UNLIKELY( err<0 ) ) {
      84           0 :     FD_LOG_ERR(( "Failed to format directory string" ));
      85           0 :   }
      86             : 
      87           0 :   char zstd_dir_buf[ FD_SNAPSHOT_DIR_MAX ];
      88           0 :   err = snprintf( zstd_dir_buf, FD_SNAPSHOT_DIR_MAX, "%s/%s", tile->batch.out_dir, FD_SNAPSHOT_TMP_FULL_ARCHIVE_ZSTD );
      89           0 :   if( FD_UNLIKELY( err<0 ) ) {
      90           0 :     FD_LOG_ERR(( "Failed to format directory string" ));
      91           0 :   }
      92             : 
      93           0 :   char zstd_inc_dir_buf[ FD_SNAPSHOT_DIR_MAX ];
      94           0 :   err = snprintf( zstd_inc_dir_buf, FD_SNAPSHOT_DIR_MAX, "%s/%s", tile->batch.out_dir, FD_SNAPSHOT_TMP_INCR_ARCHIVE_ZSTD );
      95           0 :   if( FD_UNLIKELY( err<0 ) ) {
      96           0 :     FD_LOG_ERR(( "Failed to format directory string" ));
      97           0 :   }
      98             : 
      99             :   /* Create and open the relevant files for snapshots. */
     100             : 
     101           0 :   tile->batch.tmp_fd = open( tmp_dir_buf, O_CREAT | O_RDWR | O_TRUNC, 0644 );
     102           0 :   if( FD_UNLIKELY( tile->batch.tmp_fd==-1 ) ) {
     103           0 :     FD_LOG_ERR(( "Failed to open and create tarball for file=%s (%i-%s)", tmp_dir_buf, errno, fd_io_strerror( errno ) ));
     104           0 :   }
     105             : 
     106           0 :   tile->batch.tmp_inc_fd = open( tmp_inc_dir_buf, O_CREAT | O_RDWR | O_TRUNC, 0644 );
     107           0 :   if( FD_UNLIKELY( tile->batch.tmp_inc_fd==-1 ) ) {
     108           0 :     FD_LOG_ERR(( "Failed to open and create tarball for file=%s (%i-%s)", tmp_inc_dir_buf, errno, fd_io_strerror( errno ) ));
     109           0 :   }
     110             : 
     111           0 :   tile->batch.full_snapshot_fd = open( zstd_dir_buf, O_RDWR | O_CREAT | O_TRUNC, 0644 );
     112           0 :   if( FD_UNLIKELY( tile->batch.full_snapshot_fd==-1 ) ) {
     113           0 :     FD_LOG_WARNING(( "Failed to open the snapshot file (%i-%s)", errno, fd_io_strerror( errno ) ));
     114           0 :   }
     115             : 
     116           0 :   tile->batch.incremental_snapshot_fd = open( zstd_inc_dir_buf, O_RDWR | O_CREAT | O_TRUNC, 0644 );
     117           0 :   if( FD_UNLIKELY( tile->batch.incremental_snapshot_fd==-1 ) ) {
     118           0 :     FD_LOG_WARNING(( "Failed to open the snapshot file (%i-%s)", errno, fd_io_strerror( errno ) ));
     119           0 :   }
     120           0 : }
     121             : 
     122             : static void
     123             : unprivileged_init( fd_topo_t      * topo,
     124           0 :                    fd_topo_tile_t * tile ) {
     125             : 
     126           0 :   void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
     127             : 
     128           0 :   if( FD_UNLIKELY( tile->out_cnt!=1UL || strcmp( topo->links[ tile->out_link_id[ REPLAY_OUT_IDX ] ].name, "batch_replay" ) ) ) {
     129           0 :     FD_LOG_ERR(( "batch tile has none or unexpected output links %lu %s",
     130           0 :                  tile->out_cnt, topo->links[ tile->out_link_id[ REPLAY_OUT_IDX ] ].name ));
     131           0 :   }
     132             : 
     133             :   /**********************************************************************/
     134             :   /* scratch (bump)-allocate memory owned by the replay tile            */
     135             :   /**********************************************************************/
     136             : 
     137             :   /* Do not modify order! This is join-order in unprivileged_init. */
     138             : 
     139           0 :   FD_SCRATCH_ALLOC_INIT( l, scratch );
     140           0 :   fd_snapshot_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_snapshot_tile_ctx_t), sizeof(fd_snapshot_tile_ctx_t) );
     141           0 :   memset( ctx, 0, sizeof(fd_snapshot_tile_ctx_t) );
     142           0 :   void * spad_mem            = FD_SCRATCH_ALLOC_APPEND( l, fd_spad_align(), fd_spad_footprint( MEM_FOOTPRINT ) );
     143           0 :   ulong  scratch_alloc_mem   = FD_SCRATCH_ALLOC_FINI  ( l, scratch_align() );
     144             : 
     145           0 :   if( FD_UNLIKELY( scratch_alloc_mem > (ulong)scratch + scratch_footprint(tile) ) ) {
     146           0 :     FD_LOG_ERR(( "scratch overflow" ));
     147           0 :   }
     148             : 
     149           0 :   ctx->full_interval           = tile->batch.full_interval;
     150           0 :   ctx->incremental_interval    = tile->batch.incremental_interval;
     151           0 :   ctx->out_dir                 = tile->batch.out_dir;
     152           0 :   ctx->tmp_fd                  = tile->batch.tmp_fd;
     153           0 :   ctx->tmp_inc_fd              = tile->batch.tmp_inc_fd;
     154           0 :   ctx->full_snapshot_fd        = tile->batch.full_snapshot_fd;
     155           0 :   ctx->incremental_snapshot_fd = tile->batch.incremental_snapshot_fd;
     156             : 
     157             :   /**********************************************************************/
     158             :   /* spads                                                              */
     159             :   /**********************************************************************/
     160             :   /* FIXME: Define a bound for the size of the spad. It likely needs to be
     161             :      larger than this. */
     162           0 :   uchar * spad_mem_cur = spad_mem;
     163           0 :   ctx->spad = fd_spad_join( fd_spad_new( spad_mem_cur, MEM_FOOTPRINT ) );
     164             : 
     165             :   /**********************************************************************/
     166             :   /* funk                                                               */
     167             :   /**********************************************************************/
     168             : 
     169           0 :   if( FD_UNLIKELY( !fd_funk_join( ctx->funk, fd_topo_obj_laddr( topo, tile->batch.funk_obj_id ) ) ) ) {
     170           0 :     FD_LOG_ERR(( "Failed to join database cache" ));
     171           0 :   }
     172             : 
     173             :   /**********************************************************************/
     174             :   /* status cache                                                       */
     175             :   /**********************************************************************/
     176             : 
     177           0 :   ulong status_cache_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "txncache" );
     178           0 :   if( FD_UNLIKELY( status_cache_obj_id==ULONG_MAX ) ) {
     179           0 :     FD_LOG_ERR(( "no status cache object id" ));
     180           0 :   }
     181             : 
     182           0 :   ctx->status_cache = fd_txncache_join( fd_topo_obj_laddr( topo, status_cache_obj_id ) );
     183           0 :   if( FD_UNLIKELY( !ctx->status_cache ) ) {
     184           0 :     FD_LOG_ERR(( "no status cache" ));
     185           0 :   }
     186             : 
     187             :   /**********************************************************************/
     188             :   /* constipated fseq                                                   */
     189             :   /**********************************************************************/
     190             : 
     191           0 :   ulong constipated_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "constipate" );
     192           0 :   if( FD_UNLIKELY( constipated_obj_id==ULONG_MAX ) ) {
     193           0 :     FD_LOG_ERR(( "no constipated object id" ));
     194           0 :   }
     195           0 :   ctx->is_constipated = fd_fseq_join( fd_topo_obj_laddr( topo, constipated_obj_id ) );
     196           0 :   if( FD_UNLIKELY( !ctx->is_constipated ) ) {
     197           0 :     FD_LOG_ERR(( "replay tile has no constipated fseq" ));
     198           0 :   }
     199           0 :   fd_fseq_update( ctx->is_constipated, 0UL );
     200           0 :   if( FD_UNLIKELY( fd_fseq_query( ctx->is_constipated ) ) ) {
     201           0 :     FD_LOG_ERR(( "constipated fseq is not zero" ));
     202           0 :   }
     203             : 
     204             :   /**********************************************************************/
     205             :   /* snapshot                                                           */
     206             :   /**********************************************************************/
     207             : 
     208             :   /* Zero init all of the fields used for incremental snapshot generation
     209             :      that must be persisted across snapshot creation. */
     210             : 
     211           0 :   ctx->last_full_snap_slot = 0UL;
     212           0 :   ctx->last_capitalization = 0UL;
     213           0 :   fd_memset( &ctx->last_hash, 0, sizeof(fd_hash_t) );
     214             : 
     215             :   /****************************************************************************/
     216             :   /* Replay Tile Link                                                         */
     217             :   /****************************************************************************/
     218             : 
     219             :   /* Set up replay output */
     220           0 :   fd_topo_link_t * replay_out = &topo->links[ tile->out_link_id[ REPLAY_OUT_IDX ] ];
     221           0 :   ctx->replay_out_mem         = topo->workspaces[ topo->objs[ replay_out->dcache_obj_id ].wksp_id ].wksp;
     222           0 :   ctx->replay_out_chunk       = fd_dcache_compact_chunk0( ctx->replay_out_mem, replay_out->dcache );;
     223             : 
     224             :   /* replay public setup */
     225           0 :   ulong replay_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "runtime_pub" );
     226           0 :   FD_TEST( replay_obj_id!=ULONG_MAX );
     227           0 :   ctx->runtime_public_wksp = topo->workspaces[ topo->objs[ replay_obj_id ].wksp_id ].wksp;
     228             : 
     229           0 :   if( ctx->runtime_public_wksp==NULL ) {
     230           0 :     FD_LOG_ERR(( "no runtime_public workspace" ));
     231           0 :   }
     232             : 
     233           0 :   ctx->runtime_public = fd_runtime_public_join( fd_topo_obj_laddr( topo, replay_obj_id ) );
     234           0 :   FD_TEST( ctx->runtime_public!=NULL );
     235           0 : }
     236             : 
     237             : static void
     238           0 : produce_snapshot( fd_snapshot_tile_ctx_t * ctx, ulong batch_fseq ) {
     239             : 
     240           0 :   ulong is_incremental = fd_batch_fseq_is_incremental( batch_fseq );
     241           0 :   ulong snapshot_slot  = fd_batch_fseq_get_slot( batch_fseq );
     242             : 
     243           0 :   if( !is_incremental ) {
     244           0 :     ctx->last_full_snap_slot = snapshot_slot;
     245           0 :   }
     246             : 
     247           0 :   FD_LOG_WARNING(( "Creating snapshot incremental=%lu slot=%lu", is_incremental, snapshot_slot ));
     248             : 
     249           0 :   fd_snapshot_ctx_t snapshot_ctx = {
     250           0 :     .features                 = &ctx->runtime_public->features,
     251           0 :     .slot                     = snapshot_slot,
     252           0 :     .out_dir                  = ctx->out_dir,
     253           0 :     .is_incremental           = (uchar)is_incremental,
     254           0 :     .funk                     = ctx->funk,
     255           0 :     .status_cache             = ctx->status_cache,
     256           0 :     .tmp_fd                   = is_incremental ? ctx->tmp_inc_fd              : ctx->tmp_fd,
     257           0 :     .snapshot_fd              = is_incremental ? ctx->incremental_snapshot_fd : ctx->full_snapshot_fd,
     258             :     /* These parameters are ignored if the snapshot is not incremental. */
     259           0 :     .last_snap_slot           = ctx->last_full_snap_slot,
     260           0 :     .last_snap_acc_hash       = &ctx->last_hash,
     261           0 :     .last_snap_capitalization = ctx->last_capitalization,
     262           0 :     .spad                     = ctx->spad
     263           0 :   };
     264             : 
     265             :   /* If this isn't the first snapshot that this tile is creating, the
     266             :       permissions should be made to not acessible by users and should be
     267             :       renamed to the constant file that is expected. */
     268             : 
     269           0 :   char proc_filename[ FD_SNAPSHOT_DIR_MAX ];
     270           0 :   char prev_filename[ FD_SNAPSHOT_DIR_MAX ];
     271           0 :   char new_filename [ FD_SNAPSHOT_DIR_MAX ];
     272           0 :   snprintf( proc_filename, FD_SNAPSHOT_DIR_MAX, "/proc/self/fd/%d", is_incremental ? ctx->incremental_snapshot_fd : ctx->full_snapshot_fd );
     273           0 :   long len = readlink( proc_filename, prev_filename, FD_SNAPSHOT_DIR_MAX );
     274           0 :   if( FD_UNLIKELY( len<=0L ) ) {
     275           0 :     FD_LOG_ERR(( "Failed to readlink the snapshot file" ));
     276           0 :   }
     277           0 :   prev_filename[ len ] = '\0';
     278             : 
     279           0 :   int err = snprintf( new_filename, FD_SNAPSHOT_DIR_MAX, "%s/%s", ctx->out_dir, is_incremental ? FD_SNAPSHOT_TMP_INCR_ARCHIVE_ZSTD : FD_SNAPSHOT_TMP_FULL_ARCHIVE_ZSTD );
     280           0 :   if( FD_UNLIKELY( err<0 ) ) {
     281           0 :     FD_LOG_ERR(( "Can't format filename" ));
     282           0 :     return;
     283           0 :   }
     284             : 
     285           0 :   err = rename( prev_filename, new_filename );
     286           0 :   if( FD_UNLIKELY( err ) ) {
     287           0 :     FD_LOG_ERR(( "Failed to rename file from %s to %s", prev_filename, new_filename ));
     288           0 :   }
     289           0 :   FD_LOG_NOTICE(( "Renaming file from %s to %s", prev_filename, new_filename ));
     290             : 
     291           0 :   err = ftruncate( snapshot_ctx.tmp_fd, 0UL );
     292           0 :   if( FD_UNLIKELY( err==-1 ) ) {
     293           0 :     FD_LOG_ERR(( "Failed to truncate the temporary file (%i-%s)", errno, fd_io_strerror( errno ) ));
     294           0 :   }
     295             : 
     296           0 :   err = ftruncate( snapshot_ctx.snapshot_fd, 0UL );
     297           0 :   if( FD_UNLIKELY( err==-1 ) ) {
     298           0 :     FD_LOG_ERR(( "Failed to truncate the snapshot file (%i-%s)", errno, fd_io_strerror( errno ) ));
     299           0 :   }
     300             : 
     301           0 :   long seek = lseek( snapshot_ctx.tmp_fd, 0UL, SEEK_SET );
     302           0 :   if( FD_UNLIKELY( seek!=0L ) ) {
     303           0 :     FD_LOG_ERR(( "Failed to seek to the beginning of the file" ));
     304           0 :   }
     305             : 
     306             :   /* Now that the files are in an expected state, create the snapshot. */
     307           0 :   FD_SPAD_FRAME_BEGIN( snapshot_ctx.spad ) {
     308           0 :     fd_snapshot_create_new_snapshot( &snapshot_ctx, &ctx->last_hash, &ctx->last_capitalization );
     309           0 :   } FD_SPAD_FRAME_END;
     310             : 
     311           0 :   if( is_incremental ) {
     312           0 :     FD_LOG_NOTICE(( "Done creating a snapshot in %s", snapshot_ctx.out_dir ));
     313           0 :     FD_LOG_ERR(("Successful exit" ));
     314           0 :   }
     315             : 
     316           0 :   FD_LOG_NOTICE(( "Done creating a snapshot in %s", snapshot_ctx.out_dir ));
     317             : 
     318             :   /* At this point the snapshot has been successfully created, so we can
     319             :      unconstipate funk and any related data structures in the replay tile. */
     320             : 
     321           0 :   fd_fseq_update( ctx->is_constipated, 0UL );
     322             : 
     323           0 : }
     324             : 
     325             : static fd_funk_txn_t*
     326           0 : get_eah_txn( fd_funk_t * funk, ulong slot ) {
     327             : 
     328           0 :   fd_funk_txn_all_iter_t txn_iter[1];
     329           0 :   for( fd_funk_txn_all_iter_new( funk, txn_iter ); !fd_funk_txn_all_iter_done( txn_iter ); fd_funk_txn_all_iter_next( txn_iter ) ) {
     330           0 :     fd_funk_txn_t * txn = fd_funk_txn_all_iter_ele( txn_iter );
     331           0 :     if( txn->xid.ul[0]==slot ) {
     332           0 :       FD_LOG_NOTICE(( "Found transaction for eah" ));
     333           0 :       return txn;
     334           0 :     }
     335           0 :   }
     336           0 :   FD_LOG_NOTICE(( "Calculating eah from root" ));
     337           0 :   return NULL;
     338           0 : }
     339             : 
     340             : static void
     341           0 : produce_eah( fd_snapshot_tile_ctx_t * ctx, fd_stem_context_t * stem, ulong batch_fseq ) {
     342           0 :   ulong eah_slot = fd_batch_fseq_get_slot( batch_fseq );
     343             : 
     344           0 :   if( FD_FEATURE_ACTIVE_( eah_slot, ctx->runtime_public->features, accounts_lt_hash ) )
     345           0 :     return;
     346             : 
     347           0 :   ulong tsorig = (ulong)fd_frag_meta_ts_comp( fd_tickcount() );
     348             : 
     349           0 :   FD_LOG_WARNING(( "Begining to produce epoch account hash in background for slot=%lu", eah_slot ));
     350             : 
     351             :   /* TODO: Perhaps it makes sense to factor this out into a function in the
     352             :      runtime as this could technically be considered a layering violation. */
     353             : 
     354             :   /* First, we must retrieve the corresponding slot_bank. We have the guarantee
     355             :      that the root record is frozen from the replay tile. */
     356             : 
     357           0 :   fd_funk_t *           funk     = ctx->funk;
     358           0 :   fd_funk_txn_t *       eah_txn  = get_eah_txn( funk, eah_slot );
     359           0 :   fd_funk_rec_key_t     slot_id  = fd_runtime_slot_bank_key();
     360           0 :   fd_funk_rec_query_t   query[1];
     361           0 :   fd_funk_rec_t const * slot_rec = fd_funk_rec_query_try( funk, eah_txn, &slot_id, query );
     362           0 :   if( FD_UNLIKELY( !slot_rec ) ) {
     363           0 :     FD_LOG_ERR(( "Failed to read slot bank record: missing record" ));
     364           0 :   }
     365           0 :   void * slot_val = fd_funk_val( slot_rec, fd_funk_wksp( funk ) );
     366             : 
     367           0 :   if( FD_UNLIKELY( fd_funk_val_sz( slot_rec )<sizeof(uint) ) ) {
     368           0 :     FD_LOG_ERR(( "Failed to read slot bank record: empty record" ));
     369           0 :   }
     370             : 
     371           0 :   uint slot_magic = *(uint*)slot_val;
     372           0 :   FD_SPAD_FRAME_BEGIN( ctx->spad ) {
     373           0 :     if( FD_UNLIKELY( slot_magic!=FD_RUNTIME_ENC_BINCODE ) ) {
     374           0 :       FD_LOG_ERR(( "Slot bank record has wrong magic" ));
     375           0 :     }
     376             : 
     377           0 :     int err;
     378           0 :     fd_slot_bank_t * slot_bank = fd_bincode_decode_spad( slot_bank, ctx->spad, (uchar *)slot_val+sizeof(uint), fd_funk_val_sz( slot_rec )-sizeof(uint), &err );
     379           0 :     if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) {
     380           0 :       FD_LOG_ERR(( "Failed to read slot bank record: invalid decode" ));
     381           0 :       continue;
     382           0 :     }
     383             : 
     384             :     /* At this point, calculate the epoch account hash. */
     385             : 
     386           0 :     fd_hash_t epoch_account_hash = {0};
     387             : 
     388           0 :     fd_accounts_hash( funk, slot_bank, &epoch_account_hash, ctx->spad, &ctx->runtime_public->features, NULL, NULL );
     389             : 
     390           0 :     FD_LOG_NOTICE(( "Done computing epoch account hash (%s)", FD_BASE58_ENC_32_ALLOCA( &epoch_account_hash ) ));
     391             : 
     392             :     /* Once the hash is calculated, we are ready to push the computed hash
     393             :        onto the out link to replay. We don't need to add any other information
     394             :        as this is the only type of message that is transmitted. */
     395             : 
     396           0 :     uchar * out_buf = fd_chunk_to_laddr( ctx->replay_out_mem, ctx->replay_out_chunk );
     397           0 :     fd_memcpy( out_buf, epoch_account_hash.uc, sizeof(fd_hash_t) );
     398           0 :     ulong tspub = (ulong)fd_frag_meta_ts_comp( fd_tickcount() );
     399           0 :     fd_stem_publish( stem, 0UL, EAH_REPLAY_OUT_SIG, ctx->replay_out_chunk, sizeof(fd_hash_t), 0UL, tsorig, tspub );
     400             : 
     401             :     /* Reset the fseq allowing for the un-constipation of funk and allow for
     402             :        snapshots to be created again. */
     403             : 
     404           0 :     fd_fseq_update( ctx->is_constipated, 0UL );
     405           0 :   } FD_SPAD_FRAME_END;
     406             : 
     407           0 :   FD_TEST( !fd_funk_rec_query_test( query ) );
     408           0 : }
     409             : 
     410             : static void
     411             : after_credit( fd_snapshot_tile_ctx_t * ctx,
     412             :               fd_stem_context_t *      stem,
     413             :               int *                    opt_poll_in FD_PARAM_UNUSED,
     414           0 :               int *                    charge_busy FD_PARAM_UNUSED ) {
     415             : 
     416           0 :   ulong batch_fseq = fd_fseq_query( ctx->is_constipated );
     417             : 
     418             :   /* If batch_fseq == 0, this means that we don't want to calculate/produce
     419             :      anything. Keep this tile spinning. */
     420           0 :   if( !batch_fseq ) {
     421           0 :     return;
     422           0 :   }
     423             : 
     424           0 :   if( fd_batch_fseq_is_snapshot( batch_fseq ) ) {
     425           0 :     produce_snapshot( ctx, batch_fseq );
     426           0 :   } else {
     427             :     // We need features to disable this...
     428           0 :     produce_eah( ctx, stem, batch_fseq );
     429           0 :   }
     430           0 : }
     431             : 
     432             : static ulong
     433             : populate_allowed_seccomp( fd_topo_t const *      topo,
     434             :                           fd_topo_tile_t const * tile,
     435             :                           ulong                  out_cnt,
     436           0 :                           struct sock_filter *   out ) {
     437           0 :   (void)topo;
     438             : 
     439           0 :   populate_sock_filter_policy_fd_batch_tile( out_cnt,
     440           0 :                                              out,
     441           0 :                                              (uint)fd_log_private_logfile_fd(),
     442           0 :                                              (uint)tile->batch.tmp_fd,
     443           0 :                                              (uint)tile->batch.tmp_inc_fd,
     444           0 :                                              (uint)tile->batch.full_snapshot_fd,
     445           0 :                                              (uint)tile->batch.incremental_snapshot_fd );
     446           0 :   return sock_filter_policy_fd_batch_tile_instr_cnt;
     447           0 : }
     448             : 
     449             : static ulong
     450             : populate_allowed_fds( fd_topo_t const *      topo,
     451             :                       fd_topo_tile_t const * tile,
     452             :                       ulong                  out_fds_cnt,
     453           0 :                       int *                  out_fds ) {
     454           0 :   (void)topo;
     455             : 
     456           0 :   if( FD_UNLIKELY( out_fds_cnt<2UL ) ) {
     457           0 :     FD_LOG_ERR(( "out_fds_cnt %lu", out_fds_cnt ));
     458           0 :   }
     459             : 
     460           0 :   ulong out_cnt = 0UL;
     461           0 :   out_fds[ out_cnt++ ] = 2; /* stderr */
     462           0 :   if( FD_LIKELY( -1!=fd_log_private_logfile_fd() ) )
     463           0 :     out_fds[ out_cnt++ ] = fd_log_private_logfile_fd(); /* logfile */
     464             : 
     465           0 :   out_fds[ out_cnt++ ] = tile->batch.tmp_fd;
     466           0 :   out_fds[ out_cnt++ ] = tile->batch.tmp_inc_fd;
     467           0 :   out_fds[ out_cnt++ ] = tile->batch.full_snapshot_fd;
     468           0 :   out_fds[ out_cnt++ ] = tile->batch.incremental_snapshot_fd;
     469           0 :   return out_cnt;
     470           0 : }
     471             : 
     472           0 : #define STEM_BURST (1UL)
     473             : 
     474           0 : #define STEM_CALLBACK_CONTEXT_TYPE          fd_snapshot_tile_ctx_t
     475           0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_snapshot_tile_ctx_t)
     476             : 
     477           0 : #define STEM_CALLBACK_AFTER_CREDIT        after_credit
     478             : 
     479             : #include "../../disco/stem/fd_stem.c"
     480             : 
     481             : fd_topo_run_tile_t fd_tile_batch = {
     482             :   .name                     = "batch",
     483             :   .populate_allowed_seccomp = populate_allowed_seccomp,
     484             :   .populate_allowed_fds     = populate_allowed_fds,
     485             :   .scratch_align            = scratch_align,
     486             :   .scratch_footprint        = scratch_footprint,
     487             :   .privileged_init          = privileged_init,
     488             :   .unprivileged_init        = unprivileged_init,
     489             :   .run                      = stem_run,
     490             : };

Generated by: LCOV version 1.14