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

          Line data    Source code
       1             : /* Repair tile runs the repair protocol for a Firedancer node. */
       2             : #define _GNU_SOURCE
       3             : 
       4             : #include "../../disco/topo/fd_topo.h"
       5             : #include <sys/socket.h>
       6             : #include "generated/fd_rpcserv_tile_seccomp.h"
       7             : 
       8             : #include "../rpcserver/fd_rpc_service.h"
       9             : 
      10             : #include "../../disco/tiles.h"
      11             : #include "../../flamenco/runtime/fd_blockstore.h"
      12             : #include "../../flamenco/fd_flamenco.h"
      13             : #include "../../util/fd_util.h"
      14             : #include "../../disco/fd_disco.h"
      15             : #include "../../disco/shred/fd_stake_ci.h"
      16             : #include "../../disco/topo/fd_pod_format.h"
      17             : #include "../../funk/fd_funk_filemap.h"
      18             : #include "../../disco/keyguard/fd_keyload.h"
      19             : 
      20             : #include <errno.h>
      21             : #include <fcntl.h>
      22             : #include <unistd.h>
      23             : 
      24           0 : #define REPLAY_NOTIF_IDX 0
      25           0 : #define STAKE_CI_IN_IDX 1
      26             : 
      27             : struct fd_rpcserv_tile_ctx {
      28             :   fd_rpcserver_args_t args;
      29             :   char funk_file[ PATH_MAX ];
      30             : 
      31             :   int activated;
      32             : 
      33             :   fd_rpc_ctx_t * ctx;
      34             : 
      35             :   fd_pubkey_t identity_key[1]; /* Just the public key */
      36             : 
      37             :   fd_wksp_t * replay_notif_in_mem;
      38             :   ulong       replay_notif_in_chunk0;
      39             :   ulong       replay_notif_in_wmark;
      40             :   fd_replay_notif_msg_t replay_notif_in_state;
      41             : 
      42             :   fd_wksp_t * stake_ci_in_mem;
      43             :   ulong       stake_ci_in_chunk0;
      44             :   ulong       stake_ci_in_wmark;
      45             : 
      46             :   int blockstore_fd;
      47             : };
      48             : typedef struct fd_rpcserv_tile_ctx fd_rpcserv_tile_ctx_t;
      49             : 
      50           0 : #define FD_RPC_SCRATCH_MAX (1LU<<28)
      51           0 : #define FD_RPC_SCRATCH_DEPTH 64
      52             : 
      53             : const fd_http_server_params_t RPCSERV_HTTP_PARAMS = {
      54             :   .max_connection_cnt    = 10,
      55             :   .max_ws_connection_cnt = 10,
      56             :   .max_request_len       = 1<<16,
      57             :   .max_ws_recv_frame_len = 1<<16,
      58             :   .max_ws_send_frame_cnt = 10,
      59             :   .outgoing_buffer_sz    = 100<<20,
      60             : };
      61             : 
      62             : FD_FN_CONST static inline ulong
      63           0 : scratch_align( void ) {
      64           0 :   return 128UL;
      65           0 : }
      66             : 
      67             : FD_FN_PURE static inline ulong
      68           0 : scratch_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED) {
      69           0 :   ulong l = FD_LAYOUT_INIT;
      70           0 :   l = FD_LAYOUT_APPEND( l, alignof(fd_rpcserv_tile_ctx_t), sizeof(fd_rpcserv_tile_ctx_t) );
      71           0 :   l = FD_LAYOUT_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
      72           0 :   l = FD_LAYOUT_APPEND( l, fd_stake_ci_align(), fd_stake_ci_footprint() );
      73           0 :   l = FD_LAYOUT_APPEND( l, fd_scratch_smem_align(), fd_scratch_smem_footprint( FD_RPC_SCRATCH_MAX ) );
      74           0 :   l = FD_LAYOUT_APPEND( l, fd_scratch_fmem_align(), fd_scratch_fmem_footprint( FD_RPC_SCRATCH_DEPTH ) );
      75           0 :   return FD_LAYOUT_FINI( l, scratch_align() );
      76           0 : }
      77             : 
      78             : FD_FN_PURE static inline ulong
      79           0 : loose_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED ) {
      80           0 :   return 1UL * FD_SHMEM_GIGANTIC_PAGE_SZ;
      81           0 : }
      82             : 
      83             : static inline void
      84             : before_credit( fd_rpcserv_tile_ctx_t * ctx,
      85             :                fd_stem_context_t * stem,
      86           0 :                int *               charge_busy ) {
      87           0 :   (void)stem;
      88             : 
      89           0 :   if( FD_UNLIKELY( !ctx->activated ) ) {
      90           0 :     *charge_busy = 0;
      91           0 :   } else {
      92           0 :     *charge_busy = fd_rpc_ws_poll( ctx->ctx );
      93           0 :   }
      94           0 : }
      95             : 
      96             : static void
      97             : during_frag( fd_rpcserv_tile_ctx_t * ctx,
      98             :              ulong                   in_idx,
      99             :              ulong                   seq FD_PARAM_UNUSED,
     100             :              ulong                   sig FD_PARAM_UNUSED,
     101             :              ulong                   chunk,
     102             :              ulong                   sz,
     103           0 :              ulong                   ctl FD_PARAM_UNUSED ) {
     104             : 
     105           0 :   if( FD_UNLIKELY( in_idx==REPLAY_NOTIF_IDX ) ) {
     106           0 :     if( FD_UNLIKELY( chunk<ctx->replay_notif_in_chunk0 || chunk>ctx->replay_notif_in_wmark ) ) {
     107           0 :       FD_LOG_ERR(( "chunk %lu %lu corrupt, not in range [%lu,%lu]", chunk, sz,
     108           0 :                    ctx->replay_notif_in_chunk0, ctx->replay_notif_in_wmark ));
     109           0 :     }
     110           0 :     fd_rpc_replay_during_frag( ctx->ctx, &ctx->replay_notif_in_state, fd_chunk_to_laddr_const( ctx->replay_notif_in_mem, chunk ), (int)sz );
     111             : 
     112           0 :   } else if( FD_UNLIKELY( in_idx==STAKE_CI_IN_IDX ) ) {
     113           0 :     if( FD_UNLIKELY( chunk<ctx->stake_ci_in_chunk0 || chunk>ctx->stake_ci_in_wmark ) ) {
     114           0 :       FD_LOG_ERR(( "chunk %lu %lu corrupt, not in range [%lu,%lu]", chunk, sz,
     115           0 :                    ctx->stake_ci_in_chunk0, ctx->stake_ci_in_wmark ));
     116           0 :     }
     117           0 :     fd_rpc_stake_during_frag( ctx->ctx, ctx->args.stake_ci, fd_chunk_to_laddr_const( ctx->stake_ci_in_mem, chunk ), (int)sz );
     118             : 
     119           0 :   } else {
     120           0 :     FD_LOG_ERR(("Unknown in_idx %lu for rpc", in_idx));
     121           0 :   }
     122           0 : }
     123             : 
     124             : static void
     125             : after_frag( fd_rpcserv_tile_ctx_t * ctx,
     126             :             ulong                  in_idx,
     127             :             ulong                  seq,
     128             :             ulong                  sig,
     129             :             ulong                  sz,
     130             :             ulong                  tsorig,
     131             :             ulong                  tspub,
     132           0 :             fd_stem_context_t *    stem ) {
     133           0 :   (void)seq;
     134           0 :   (void)sig;
     135           0 :   (void)sz;
     136           0 :   (void)tsorig;
     137           0 :   (void)tspub;
     138           0 :   (void)stem;
     139             : 
     140           0 :   if( FD_LIKELY( in_idx==REPLAY_NOTIF_IDX ) ) {
     141           0 :     if( FD_UNLIKELY( !ctx->activated ) ) {
     142           0 :       fd_rpcserver_args_t * args = &ctx->args;
     143           0 :       args->funk = fd_funk_open_file(
     144           0 :         ctx->funk_file, 1, 0, 0, 0, 0, FD_FUNK_READ_WRITE, NULL );
     145           0 :       if( FD_UNLIKELY( args->funk == NULL ) ) {
     146           0 :         FD_LOG_ERR(( "failed to join a funky" ));
     147           0 :       }
     148             : 
     149           0 :       ctx->activated = 1;
     150           0 :       fd_rpc_start_service( args, ctx->ctx );
     151           0 :     }
     152             : 
     153           0 :     fd_rpc_replay_after_frag( ctx->ctx, &ctx->replay_notif_in_state );
     154             : 
     155           0 :   } else if( FD_UNLIKELY( in_idx==STAKE_CI_IN_IDX ) ) {
     156           0 :     fd_rpc_stake_after_frag( ctx->ctx, ctx->args.stake_ci );
     157             : 
     158           0 :   } else {
     159           0 :     FD_LOG_ERR(("Unknown in_idx %lu for rpc", in_idx));
     160           0 :   }
     161           0 : }
     162             : 
     163             : static void
     164             : privileged_init( fd_topo_t *      topo,
     165           0 :                  fd_topo_tile_t * tile ) {
     166           0 :   void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
     167             : 
     168           0 :   FD_SCRATCH_ALLOC_INIT( l, scratch );
     169           0 :   fd_rpcserv_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_rpcserv_tile_ctx_t), sizeof(fd_rpcserv_tile_ctx_t) );
     170           0 :   void * alloc_shmem = FD_SCRATCH_ALLOC_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
     171           0 :   void * stake_ci_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_ci_align(), fd_stake_ci_footprint() );
     172           0 :   FD_SCRATCH_ALLOC_FINI( l, alignof(fd_rpcserv_tile_ctx_t) );
     173             : 
     174           0 :   if( FD_UNLIKELY( !strcmp( tile->rpcserv.identity_key_path, "" ) ) )
     175           0 :     FD_LOG_ERR( ( "identity_key_path not set" ) );
     176           0 :   ctx->identity_key[0] = *(fd_pubkey_t const *) fd_type_pun_const( fd_keyload_load( tile->rpcserv.identity_key_path, /* pubkey only: */ 1 ) );
     177             : 
     178           0 :   fd_rpcserver_args_t * args = &ctx->args;
     179           0 :   fd_memset( args, 0, sizeof(fd_rpcserver_args_t) );
     180             : 
     181           0 :   args->offline = 0;
     182           0 :   args->params = RPCSERV_HTTP_PARAMS;
     183             : 
     184           0 :   args->port = tile->rpcserv.rpc_port;
     185             : 
     186           0 :   args->tpu_addr.sin_family = AF_INET;
     187           0 :   args->tpu_addr.sin_addr.s_addr = tile->rpcserv.tpu_ip_addr;
     188           0 :   args->tpu_addr.sin_port = htons( (ushort)tile->rpcserv.tpu_port );
     189             : 
     190           0 :   args->stake_ci = fd_stake_ci_join( fd_stake_ci_new( stake_ci_mem, ctx->identity_key ) );
     191             : 
     192           0 :   strncpy( ctx->funk_file, tile->replay.funk_file, sizeof(ctx->funk_file) );
     193             :   /* Open funk after replay tile is booted */
     194             : 
     195             :   /* Blockstore setup */
     196           0 :   ulong blockstore_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "blockstore" );
     197           0 :   FD_TEST( blockstore_obj_id!=ULONG_MAX );
     198           0 :   args->blockstore = fd_blockstore_join( &args->blockstore_ljoin, fd_topo_obj_laddr( topo, blockstore_obj_id ) );
     199           0 :   FD_TEST( args->blockstore!=NULL );
     200           0 :   ctx->blockstore_fd = open( tile->replay.blockstore_file, O_RDONLY );
     201           0 :   if ( FD_UNLIKELY(ctx->blockstore_fd == -1) ){
     202           0 :     FD_LOG_WARNING(("%s: %s", tile->replay.blockstore_file, strerror( errno )));
     203           0 :   }
     204             : 
     205           0 :   args->blockstore_fd = ctx->blockstore_fd;
     206             : 
     207           0 :   void * alloc_shalloc = fd_alloc_new( alloc_shmem, 3UL );
     208           0 :   if( FD_UNLIKELY( !alloc_shalloc ) ) {
     209           0 :     FD_LOG_ERR( ( "fd_alloc_new failed" ) ); }
     210           0 :   fd_alloc_t * alloc = fd_alloc_join( alloc_shalloc, 3UL );
     211           0 :   if( FD_UNLIKELY( !alloc ) ) {
     212           0 :     FD_LOG_ERR( ( "fd_alloc_join failed" ) );
     213           0 :   }
     214           0 :   args->valloc = fd_alloc_virtual( alloc );
     215             : 
     216           0 :   fd_rpc_create_ctx( args, &ctx->ctx );
     217             : 
     218             : 
     219             :   /* Wait until after replay tile boots before starting service */
     220           0 : }
     221             : 
     222             : static void
     223             : unprivileged_init( fd_topo_t *      topo,
     224           0 :                    fd_topo_tile_t * tile ) {
     225           0 :   void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
     226             : 
     227           0 :   if( FD_UNLIKELY( tile->in_cnt != 2 ||
     228           0 :                    strcmp( topo->links[ tile->in_link_id[ REPLAY_NOTIF_IDX ] ].name, "replay_notif") ||
     229           0 :                    strcmp( topo->links[ tile->in_link_id[ STAKE_CI_IN_IDX ] ].name, "stake_out" ) ) ) {
     230           0 :     FD_LOG_ERR(( "repair tile has none or unexpected input links %lu %s %s",
     231           0 :                  tile->in_cnt, topo->links[ tile->in_link_id[ 0 ] ].name, topo->links[ tile->in_link_id[ 1 ] ].name ));
     232           0 :   }
     233             : 
     234           0 :   if( FD_UNLIKELY( tile->out_cnt != 0 ) ) {
     235           0 :     FD_LOG_ERR(( "repair tile has none or unexpected output links %lu %s %s",
     236           0 :                  tile->out_cnt, topo->links[ tile->out_link_id[ 0 ] ].name, topo->links[ tile->out_link_id[ 1 ] ].name ));
     237           0 :   }
     238             : 
     239             :   /* Scratch mem setup */
     240             : 
     241           0 :   FD_SCRATCH_ALLOC_INIT( l, scratch );
     242           0 :   fd_rpcserv_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_rpcserv_tile_ctx_t), sizeof(fd_rpcserv_tile_ctx_t) );
     243           0 :   (void)FD_SCRATCH_ALLOC_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
     244           0 :   (void)FD_SCRATCH_ALLOC_APPEND( l, fd_stake_ci_align(), fd_stake_ci_footprint() );
     245           0 :   void * smem = FD_SCRATCH_ALLOC_APPEND( l, fd_scratch_smem_align(), fd_scratch_smem_footprint( FD_RPC_SCRATCH_MAX ) );
     246           0 :   void * fmem = FD_SCRATCH_ALLOC_APPEND( l, fd_scratch_fmem_align(), fd_scratch_fmem_footprint( FD_RPC_SCRATCH_DEPTH ) );
     247           0 :   ulong scratch_top = FD_SCRATCH_ALLOC_FINI( l, scratch_align() );
     248           0 :   if( FD_UNLIKELY( scratch_top > (ulong)scratch + scratch_footprint( tile ) ) )
     249           0 :     FD_LOG_ERR(( "scratch overflow %lu %lu %lu", scratch_top - (ulong)scratch - scratch_footprint( tile ), scratch_top, (ulong)scratch + scratch_footprint( tile ) ));
     250             : 
     251           0 :   FD_TEST( ( !!smem ) & ( !!fmem ) );
     252           0 :   fd_scratch_attach( smem, fmem, FD_RPC_SCRATCH_MAX, FD_RPC_SCRATCH_DEPTH );
     253             : 
     254           0 :   ctx->activated = 0;
     255             : 
     256           0 :   fd_topo_link_t * replay_notif_in_link   = &topo->links[ tile->in_link_id[ REPLAY_NOTIF_IDX ] ];
     257           0 :   ctx->replay_notif_in_mem    = topo->workspaces[ topo->objs[ replay_notif_in_link->dcache_obj_id ].wksp_id ].wksp;
     258           0 :   ctx->replay_notif_in_chunk0 = fd_dcache_compact_chunk0( ctx->replay_notif_in_mem, replay_notif_in_link->dcache );
     259           0 :   ctx->replay_notif_in_wmark  = fd_dcache_compact_wmark ( ctx->replay_notif_in_mem, replay_notif_in_link->dcache, replay_notif_in_link->mtu );
     260             : 
     261           0 :   fd_topo_link_t * stake_ci_in_link   = &topo->links[ tile->in_link_id[ STAKE_CI_IN_IDX ] ];
     262           0 :   ctx->stake_ci_in_mem    = topo->workspaces[ topo->objs[ stake_ci_in_link->dcache_obj_id ].wksp_id ].wksp;
     263           0 :   ctx->stake_ci_in_chunk0 = fd_dcache_compact_chunk0( ctx->stake_ci_in_mem, stake_ci_in_link->dcache );
     264           0 :   ctx->stake_ci_in_wmark  = fd_dcache_compact_wmark ( ctx->stake_ci_in_mem, stake_ci_in_link->dcache, stake_ci_in_link->mtu );
     265           0 : }
     266             : 
     267             : static ulong
     268             : populate_allowed_seccomp( fd_topo_t const *      topo,
     269             :                           fd_topo_tile_t const * tile,
     270             :                           ulong                  out_cnt,
     271           0 :                           struct sock_filter *   out ) {
     272           0 :   void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
     273           0 :   FD_SCRATCH_ALLOC_INIT( l, scratch );
     274           0 :   fd_rpcserv_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_rpcserv_tile_ctx_t), sizeof(fd_rpcserv_tile_ctx_t) );
     275           0 :   FD_SCRATCH_ALLOC_FINI( l, alignof(fd_rpcserv_tile_ctx_t) );
     276             : 
     277           0 :   populate_sock_filter_policy_fd_rpcserv_tile( out_cnt, out, (uint)fd_log_private_logfile_fd(), (uint)fd_rpc_ws_fd( ctx->ctx ), (uint)ctx->blockstore_fd );
     278           0 :   return sock_filter_policy_fd_rpcserv_tile_instr_cnt;
     279           0 : }
     280             : 
     281             : static ulong
     282             : populate_allowed_fds( fd_topo_t const *      topo,
     283             :                       fd_topo_tile_t const * tile,
     284             :                       ulong                  out_fds_cnt,
     285           0 :                       int *                  out_fds ) {
     286           0 :   void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
     287           0 :   FD_SCRATCH_ALLOC_INIT( l, scratch );
     288           0 :   fd_rpcserv_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_rpcserv_tile_ctx_t), sizeof(fd_rpcserv_tile_ctx_t) );
     289           0 :   FD_SCRATCH_ALLOC_FINI( l, alignof(fd_rpcserv_tile_ctx_t) );
     290             : 
     291           0 :   if( FD_UNLIKELY( out_fds_cnt<3UL ) ) FD_LOG_ERR(( "out_fds_cnt %lu", out_fds_cnt ));
     292             : 
     293           0 :   ulong out_cnt = 0;
     294           0 :   out_fds[ out_cnt++ ] = 2; /* stderr */
     295           0 :   if( FD_LIKELY( -1!=fd_log_private_logfile_fd() ) )
     296           0 :     out_fds[ out_cnt++ ] = fd_log_private_logfile_fd(); /* logfile */
     297           0 :   out_fds[ out_cnt++ ] = fd_rpc_ws_fd( ctx->ctx ); /* listen socket */
     298           0 :   out_fds[ out_cnt++ ] = ctx->blockstore_fd;
     299           0 :   return out_cnt;
     300           0 : }
     301             : 
     302             : /* TODO: This is probably not correct. */
     303           0 : #define STEM_BURST (1UL)
     304             : 
     305           0 : #define STEM_CALLBACK_CONTEXT_TYPE  fd_rpcserv_tile_ctx_t
     306           0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_rpcserv_tile_ctx_t)
     307             : 
     308           0 : #define STEM_CALLBACK_BEFORE_CREDIT before_credit
     309           0 : #define STEM_CALLBACK_DURING_FRAG   during_frag
     310           0 : #define STEM_CALLBACK_AFTER_FRAG    after_frag
     311             : 
     312             : #include "../../disco/stem/fd_stem.c"
     313             : 
     314             : fd_topo_run_tile_t fd_tile_rpcserv = {
     315             :   .name                     = "rpcsrv",
     316             :   .loose_footprint          = loose_footprint,
     317             :   .populate_allowed_seccomp = populate_allowed_seccomp,
     318             :   .populate_allowed_fds     = populate_allowed_fds,
     319             :   .scratch_align            = scratch_align,
     320             :   .scratch_footprint        = scratch_footprint,
     321             :   .unprivileged_init        = unprivileged_init,
     322             :   .privileged_init          = privileged_init,
     323             :   .run                      = stem_run,
     324             : };

Generated by: LCOV version 1.14