LCOV - code coverage report
Current view: top level - app/firedancer-dev/commands/forktest - forktest.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 324 0.0 %
Date: 2026-09-17 04:28:31 Functions: 0 6 0.0 %

          Line data    Source code
       1             : /* The forktest topology exercises offline replay with full consensus.
       2             : Constructed using a full topology which is pruned down. */
       3             : 
       4             : #define _GNU_SOURCE
       5             : #include "../../../firedancer/topology.h"
       6             : #include "../../../shared/fd_action.h"
       7             : #include "../../../shared/commands/configure/configure.h"
       8             : #include "../../../shared/commands/run/run.h"
       9             : #include "../../../shared/commands/watch/watch.h"
      10             : #include "../../../../discof/replay/fd_execrp.h"
      11             : #include "../../../../discof/genesis/fd_genesi_tile.h"
      12             : #include "../../../../discof/tower/fd_tower_tile.h"
      13             : #include "../../../../discof/replay/fd_replay_tile.h"
      14             : #include "../../../../disco/shred/fd_shred_tile.h"
      15             : #include "../../../../disco/net/fd_net_tile.h"
      16             : #include "../../../../disco/pack/fd_pack_cost.h"
      17             : #include "../../../../disco/topo/fd_topob.h"
      18             : #include "../../../../disco/topo/fd_cpu_topo.h"
      19             : #include "../../../../util/pod/fd_pod_format.h"
      20             : #include "../../../../discof/restore/utils/fd_slot_delta_parser.h"
      21             : #include "../../../../discof/restore/utils/fd_ssctrl.h"
      22             : #include "../../../../discof/restore/utils/fd_ssmsg.h"
      23             : #include "../../../../ballet/shred/fd_shred.h"
      24             : #include "../../../../discof/backtest/fd_backtest_src.h"
      25             : #include "../../../../flamenco/runtime/fd_cost_tracker.h"
      26             : 
      27             : #include <errno.h>
      28             : #include <unistd.h> /* pause(2) */
      29             : #include <fcntl.h>
      30             : 
      31             : extern fd_topo_obj_callbacks_t * CALLBACKS[];
      32             : fd_topo_run_tile_t fdctl_tile_run( fd_topo_tile_t const * tile );
      33             : 
      34             : extern configure_stage_t fd_cfg_stage_keys;
      35             : 
      36             : static args_t
      37           0 : configure_args( void ) {
      38           0 :   args_t args = {
      39           0 :     .configure.command = CONFIGURE_CMD_INIT,
      40           0 :   };
      41             : 
      42           0 :   ulong stage_idx = 0UL;
      43           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_hugetlbfs;
      44           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_snapshots;
      45           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_keys;
      46           0 :   args.configure.stages[ stage_idx++ ] = NULL;
      47             : 
      48           0 :   return args;
      49           0 : }
      50             : 
      51             : static void
      52             : forktest_perm( args_t *         args FD_PARAM_UNUSED,
      53             :                fd_cap_chk_t *   chk,
      54           0 :                config_t const * config ) {
      55           0 :   args_t c_args = configure_args();
      56           0 :   configure_cmd_perm( &c_args, chk, config );
      57           0 :   run_cmd_perm( NULL, chk, config );
      58           0 : }
      59             : 
      60             : static ushort
      61           0 : forktest_recover_expected_shred_version( config_t const * config ) {
      62           0 :   fd_backtest_src_opts_t opts = {
      63           0 :     .path   = config->firedancer.development.ledger_input.path,
      64           0 :     .format = config->firedancer.development.ledger_input.format,
      65           0 :   };
      66             : 
      67           0 :   uchar buf[ FD_SHRED_MAX_SZ ];
      68           0 :   ulong shred_sz = fd_backtest_src_first_shred( &opts, buf, sizeof(buf) );
      69           0 :   if( FD_UNLIKELY( !shred_sz ) ) FD_LOG_ERR(( "unable to recover shred version from `%s`", opts.path ));
      70             : 
      71           0 :   fd_shred_t const * shred = fd_shred_parse( buf, shred_sz, FD_SHRED_BLK_MAX );
      72           0 :   if( FD_UNLIKELY( !shred ) ) FD_LOG_ERR(( "unable to parse first shred from `%s`", opts.path ));
      73             : 
      74           0 :   FD_LOG_INFO(( "Recovered expected shred version %hu", shred->version ));
      75           0 :   return shred->version;
      76           0 : }
      77             : 
      78             : static void
      79           0 : forktest_topo( config_t * config ) {
      80             : 
      81           0 :   if( FD_UNLIKELY( !config->consensus.expected_shred_version ) ) {
      82           0 :     config->consensus.expected_shred_version = forktest_recover_expected_shred_version( config );
      83           0 :   }
      84             : 
      85           0 :   config->development.sandbox  = 0;
      86           0 :   config->development.no_clone = 1;
      87             : 
      88           0 :   ulong shred_tile_cnt  = config->layout.shred_tile_count;
      89             : 
      90           0 :   ulong execrp_tile_cnt = config->firedancer.layout.execrp_tile_count;
      91           0 :   ulong sign_tile_cnt   = config->firedancer.layout.sign_tile_count;
      92             : 
      93           0 :   int snapshots_enabled = !!config->gossip.entrypoints_cnt;
      94             : 
      95           0 :   fd_topo_t * topo = fd_topob_new( &config->topo, config->name );
      96             : 
      97           0 :   topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
      98           0 :   topo->gigantic_page_threshold = config->hugetlbfs.gigantic_page_threshold_mib << 20;
      99             : 
     100             :   /*             topo, name */
     101           0 :   fd_topob_wksp( topo, "metric" );
     102           0 :   fd_topob_wksp( topo, "shred"  );
     103           0 :   fd_topob_wksp( topo, "replay" );
     104           0 :   fd_topob_wksp( topo, "execrp" );
     105           0 :   fd_topob_wksp( topo, "tower"  );
     106           0 :   fd_topob_wksp( topo, "sign"   )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_NEVER;
     107             : 
     108           0 :   fd_topob_wksp( topo, "metric_in"    );
     109             : 
     110           0 :   fd_topob_wksp( topo, "net_shred"    );
     111             : 
     112           0 :   fd_topob_wksp( topo, "gossip_out"    );
     113             : 
     114           0 :   fd_topob_wksp( topo, "shred_out"     );
     115           0 :   fd_topob_wksp( topo, "replay_epoch"  );
     116           0 :   fd_topob_wksp( topo, "replay_execrp" );
     117           0 :   fd_topob_wksp( topo, "replay_out"    );
     118           0 :   fd_topob_wksp( topo, "tower_out"     );
     119             : 
     120           0 :   fd_topob_wksp( topo, "progcache"     );
     121           0 :   fd_topob_wksp( topo, "txncache"      );
     122           0 :   fd_topob_wksp( topo, "banks"         );
     123           0 :   fd_topob_wksp( topo, "store"         )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_FULL;
     124           0 :   fd_topob_wksp( topo, "rnonce"        );
     125             : 
     126           0 :   fd_topob_wksp( topo, "shred_sign"    );
     127           0 :   fd_topob_wksp( topo, "sign_shred"    );
     128             : 
     129           0 :   if( FD_UNLIKELY( !snapshots_enabled ) ) {
     130           0 :     fd_topob_wksp( topo, "genesi" );
     131           0 :     fd_topob_wksp( topo, "genesi_out" );
     132           0 :   }
     133             : 
     134           0 :   fd_topob_wksp( topo, "execrp_replay" );
     135             : 
     136           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     137           0 :     fd_topob_wksp( topo, "snapct"      );
     138           0 :     fd_topob_wksp( topo, "snapld"      );
     139           0 :     fd_topob_wksp( topo, "snapdc"      );
     140           0 :     fd_topob_wksp( topo, "snapin"      );
     141           0 :     fd_topob_wksp( topo, "snapwr"      );
     142           0 :     fd_topob_wksp( topo, "snapct_ld"   );
     143           0 :     fd_topob_wksp( topo, "snapld_dc"   );
     144           0 :     fd_topob_wksp( topo, "snapdc_in"   );
     145             : 
     146           0 :     fd_topob_wksp( topo, "snapin_manif" );
     147           0 :     fd_topob_wksp( topo, "snapct_repr"  );
     148             : 
     149           0 :     fd_topob_wksp( topo, "snapin_ct" );
     150           0 :     fd_topob_wksp( topo, "snapwr_ct" );
     151           0 :   }
     152             : 
     153           0 :   fd_topob_wksp( topo, "forkt" );
     154             : 
     155           0 :   #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
     156             : 
     157           0 :   ulong shred_depth = 65536UL; /* from fdctl/topology.c shred_store link. MAKE SURE TO KEEP IN SYNC. */
     158             : 
     159             :   /*                                  topo, link_name,       wksp_name,       depth,                                    mtu,                           burst */
     160           0 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "shred_net",     "net_shred",     32768UL,                                  FD_NET_MTU,                    1UL );
     161             : 
     162           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     163             :   /* TODO: Revisit the depths of all the snapshot links */
     164           0 :     /**/               fd_topob_link( topo, "snapct_ld",     "snapct_ld",     128UL,                                    sizeof(fd_ssctrl_init_t),      1UL );
     165           0 :     /**/               fd_topob_link( topo, "snapld_dc",     "snapld_dc",     FD_SNAPSHOT_DATA_DEPTH,                   FD_SNAPSHOT_DATA_MTU,          1UL );
     166           0 :     /**/               fd_topob_link( topo, "snapdc_in",     "snapdc_in",     FD_SNAPSHOT_DATA_DEPTH,                   FD_SNAPSHOT_DATA_MTU,          1UL );
     167             : 
     168             :     /**/               fd_topob_link( topo, "snapin_manif",  "snapin_manif",  4UL,                                      sizeof(fd_snapshot_manifest_t),1UL );
     169           0 :     /**/               fd_topob_link( topo, "snapct_repr",   "snapct_repr",   128UL,                                    0UL,                           1UL )->permit_no_consumers = 1; /* TODO: wire in repair later */
     170             : 
     171           0 :     /**/               fd_topob_link( topo, "snapin_ct",    "snapin_ct",    128UL,                                    0UL,                           1UL );
     172             : 
     173             :     /**/               fd_topob_link( topo, "snapwr_ct",    "snapwr_ct",    128UL,                                    0UL,                           1UL );
     174           0 :   }
     175             : 
     176           0 :   if( FD_UNLIKELY( !snapshots_enabled ) ) {
     177           0 :     /**/               fd_topob_link( topo, "genesi_out",    "genesi_out",    1UL,                                      fd_genesi_tile_mtu( config->firedancer.development.genesis.max_file_size_mib<<20 ), 1UL );
     178           0 :   }
     179             : 
     180             :   /**/                 fd_topob_link( topo, "gossip_out",    "gossip_out",    65536UL*4UL,                              sizeof(fd_gossip_update_message_t), 1UL ); /* TODO: Unclear where this depth comes from ... fix */
     181             : 
     182           0 :   /**/                 fd_topob_link( topo, "replay_epoch",  "replay_epoch",  16UL,                                     FD_EPOCH_OUT_MTU,              1UL ); /* min pow2 >= replay's STEM_BURST (14); ideally 2, needs per-link burst */
     183           0 :   /**/                 fd_topob_link( topo, "replay_out",    "replay_out",    65536UL,                                  sizeof(fd_replay_message_t),   1UL );
     184           0 :                        fd_topob_link( topo, "replay_execrp", "replay_execrp", 16384UL,                                  sizeof(fd_execrp_task_msg_t),  1UL );
     185             : 
     186           0 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "shred_sign",    "shred_sign",    128UL,                                    32UL,                          1UL );
     187           0 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "sign_shred",    "sign_shred",    128UL,                                    sizeof(fd_ed25519_sig_t),      1UL );
     188           0 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "shred_out",     "shred_out",     shred_depth,                              sizeof(fd_shred_message_t),    FD_SHRED_STEM_BURST );
     189           0 :   /**/                 fd_topob_link( topo, "tower_out",     "tower_out",     16384UL,                                  sizeof(fd_tower_msg_t),        2UL ); /* conf + slot_done. see explanation in fd_tower_tile.h for link_depth */
     190             : 
     191           0 :   FOR(execrp_tile_cnt) fd_topob_link( topo, "execrp_replay", "execrp_replay", 16384UL,                                  sizeof(fd_execrp_task_done_msg_t), 1UL );
     192             : 
     193           0 :   ushort parsed_tile_to_cpu[ FD_TILE_MAX ];
     194             :   /* Unassigned tiles will be floating, unless auto topology is enabled. */
     195           0 :   for( ulong i=0UL; i<FD_TILE_MAX; i++ ) parsed_tile_to_cpu[ i ] = USHORT_MAX;
     196             : 
     197           0 :   int is_auto_affinity = !strcmp( config->firedancer.development.forktest.affinity, "auto" );
     198             : 
     199           0 :   fd_topo_cpus_t cpus[1];
     200           0 :   fd_topo_cpus_init( cpus );
     201             : 
     202           0 :   ulong affinity_tile_cnt = 0UL;
     203           0 :   if( FD_LIKELY( !is_auto_affinity ) ) affinity_tile_cnt = fd_topob_parse_affinity_cstr( config->firedancer.development.forktest.affinity, parsed_tile_to_cpu, 0, 1 );
     204             : 
     205           0 :   ulong tile_to_cpu[ FD_TILE_MAX ] = {0};
     206           0 :   for( ulong i=0UL; i<affinity_tile_cnt; i++ ) {
     207           0 :     ushort cpu_idx = (ushort)( parsed_tile_to_cpu[ i ] & ~FD_TOPOB_CPU_SHARED );
     208           0 :     if( FD_UNLIKELY( parsed_tile_to_cpu[ i ]!=USHORT_MAX && cpu_idx>=cpus->cpu_cnt ) )
     209           0 :       FD_LOG_ERR(( "The CPU affinity string in the configuration file under [development.forktest.affinity] specifies a CPU index of %hu, but the system "
     210           0 :                    "only has %lu CPUs. You should either change the CPU allocations in the affinity string, or increase the number of CPUs "
     211           0 :                    "in the system.",
     212           0 :                    cpu_idx, cpus->cpu_cnt ));
     213           0 :     tile_to_cpu[ i ] = fd_ulong_if( parsed_tile_to_cpu[ i ]==USHORT_MAX, ULONG_MAX, (ulong)parsed_tile_to_cpu[ i ] );
     214           0 :   }
     215             : 
     216           0 :   fd_topob_link( topo, "net_shred", "net_shred", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
     217             : 
     218             :   /*                                  topo, tile_name, tile_wksp, metrics_wksp, cpu_idx,                       is_agave, uses_id_keyswitch, uses_av_keyswitch */
     219             :   /**/                 fd_topob_tile( topo, "metric",  "metric",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        0,                 0,                 1 );
     220             : 
     221           0 :   fd_topo_tile_t * snapin_tile = NULL;
     222           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     223           0 :     /**/               fd_topob_tile( topo, "snapct", "snapct", "metric_in", tile_to_cpu[ topo->tile_cnt ],    0,        0,                 0,                 0 )->allow_shutdown = 1;
     224           0 :     /**/               fd_topob_tile( topo, "snapld", "snapld", "metric_in", tile_to_cpu[ topo->tile_cnt ],    0,        0,                 0,                 0 )->allow_shutdown = 1;
     225           0 :     /**/               fd_topob_tile( topo, "snapdc", "snapdc", "metric_in", tile_to_cpu[ topo->tile_cnt ],    0,        0,                 0,                 0 )->allow_shutdown = 1;
     226           0 :                        snapin_tile =
     227           0 :     /**/               fd_topob_tile( topo, "snapin", "snapin", "metric_in", tile_to_cpu[ topo->tile_cnt ],    0,        0,                 0,                 0 );
     228           0 :                        snapin_tile->allow_shutdown = 1;
     229           0 :     /**/               fd_topob_tile( topo, "snapwr", "snapwr", "metric_in", tile_to_cpu[ topo->tile_cnt ],    0,        0,                 0,                 0 )->allow_shutdown = 1;
     230           0 :   }
     231             : 
     232           0 :   if( FD_UNLIKELY( !snapshots_enabled ) ) {
     233           0 :     /**/               fd_topob_tile( topo, "genesi",  "genesi",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        0,                 0,                 0 )->allow_shutdown = 1;
     234           0 :   }
     235             : 
     236           0 :   FOR(shred_tile_cnt)  fd_topob_tile( topo, "shred",   "shred",   "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        1,                 0,                 0 );
     237           0 :   fd_topo_tile_t * replay_tile =
     238           0 :   /**/                 fd_topob_tile( topo, "replay",  "replay",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        1,                 0,                 0 );
     239           0 :   FOR(execrp_tile_cnt) fd_topob_tile( topo, "execrp",  "execrp",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        0,                 0,                 0 );
     240           0 :   /**/                 fd_topob_tile( topo, "tower",   "tower",   "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        1,                 1,                 0 );
     241             : 
     242           0 :   FOR(sign_tile_cnt)   fd_topob_tile( topo, "sign",    "sign",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        1,               1,               0 );
     243             : 
     244           0 :   fd_topob_tile( topo, "forkt", "forkt", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0, 0 );
     245             : 
     246           0 :   fd_topob_wksp( topo, "accdb" )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_FULL;
     247           0 :   fd_topo_tile_t * accdb_tile = fd_topob_tile( topo, "accdb", "accdb", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0, 0 );
     248             : 
     249           0 :   fd_topob_wksp( topo, "accdb_data" );
     250           0 :   fd_topo_obj_t * accdb_obj = setup_topo_accdb( topo, "accdb_data",
     251           0 :       config->firedancer.accounts.max_accounts,
     252           0 :       config->firedancer.runtime.max_live_slots,
     253           0 :       FD_RUNTIME_MAX_ACC_WRITES_PER_SLOT,
     254           0 :       8192UL,
     255           0 :       1UL<<35UL,
     256           0 :       config->firedancer.accounts.cache_size_gib*(1UL<<30UL),
     257           0 :       config->tiles.bundle.enabled,
     258           0 :       execrp_tile_cnt+3UL,
     259           0 :       0UL );
     260           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, accdb_obj->id, "accdb" ) );
     261             : 
     262           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     263           0 :                           fd_topob_tile_out(    topo, "snapin",  0UL,                       "snapin_ct",    0UL                                            );
     264           0 :                           fd_topob_tile_in (    topo, "snapct",  0UL,          "metric_in", "snapin_ct",    0UL,      FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     265             : 
     266           0 :     /**/              fd_topob_tile_in (    topo, "snapld",  0UL,          "metric_in", "snapct_ld",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     267           0 :     /**/              fd_topob_tile_out(    topo, "snapld",  0UL,                       "snapld_dc",     0UL                                                );
     268             : 
     269           0 :     /**/              fd_topob_tile_in (    topo, "snapdc",  0UL,          "metric_in", "snapld_dc",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     270           0 :     /**/              fd_topob_tile_out(    topo, "snapdc",  0UL,                       "snapdc_in",     0UL                                                );
     271             : 
     272           0 :                       fd_topob_tile_in (    topo, "snapin",  0UL,          "metric_in", "snapdc_in",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     273           0 :                       fd_topob_tile_in (    topo, "snapwr",  0UL,          "metric_in", "snapdc_in",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     274           0 :                       fd_topob_tile_out(    topo, "snapin",  0UL,                       "snapin_manif",  0UL                                                );
     275             : 
     276           0 :                       fd_topob_tile_in (    topo, "snapct",  0UL,          "metric_in", "snapin_ct",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     277           0 :                       fd_topob_tile_in (    topo, "snapct",  0UL,          "metric_in", "snapwr_ct",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     278           0 :                       fd_topob_tile_in (    topo, "snapct",  0UL,          "metric_in", "snapld_dc",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     279           0 :                       fd_topob_tile_out(    topo, "snapct",  0UL,                       "snapct_ld",     0UL                                                );
     280           0 :                       fd_topob_tile_out(    topo, "snapct",  0UL,                       "snapct_repr",   0UL                                                );
     281             : 
     282           0 :                       fd_topob_tile_out(    topo, "snapin", 0UL,                        "snapin_ct",     0UL                                                );
     283           0 :                       fd_topob_tile_out(    topo, "snapwr", 0UL,                        "snapwr_ct",     0UL                                                );
     284           0 :   }
     285             : 
     286           0 :   /**/                 fd_topob_tile_in (   topo, "forkt", 0UL,            "metric_in", "replay_epoch",  0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     287           0 :   /**/                 fd_topob_tile_out(   topo, "forkt", 0UL,                         "gossip_out",    0UL                                                );
     288           0 :   /**/                 fd_topob_tile_in (   topo, "forkt", 0UL,            "metric_in", "tower_out",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     289           0 :   /**/                 fd_topob_tile_in (   topo, "forkt", 0UL,            "metric_in", "replay_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     290             : 
     291           0 :   FOR(shred_tile_cnt) fd_topob_tile_in (    topo, "shred",   i,            "metric_in", "net_shred",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     292           0 :   FOR(shred_tile_cnt) fd_topos_tile_in_net( topo,                          "metric_in", "shred_net",     i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
     293             : 
     294           0 :   if( FD_UNLIKELY( !snapshots_enabled ) ) {
     295           0 :     /**/               fd_topob_tile_out(   topo, "genesi", 0UL,                        "genesi_out",    0UL                                                );
     296           0 :     /**/               fd_topob_tile_in (   topo, "replay",  0UL,          "metric_in", "genesi_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     297           0 :   }
     298           0 :   /**/                 fd_topob_tile_out(   topo, "replay",  0UL,                       "replay_out",    0UL                                                );
     299           0 :   /**/                 fd_topob_tile_out(   topo, "replay",  0UL,                       "replay_epoch",  0UL                                                );
     300           0 :   /**/                 fd_topob_tile_out(   topo, "replay",  0UL,                       "replay_execrp", 0UL                                                );
     301           0 :   FOR(execrp_tile_cnt) fd_topob_tile_in (   topo, "replay",  0UL,          "metric_in", "execrp_replay", i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     302           0 :   /**/                 fd_topob_tile_in (   topo, "replay",  0UL,          "metric_in", "tower_out",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     303           0 :   /**/                 fd_topob_tile_in (   topo, "replay",  0UL,          "metric_in", "gossip_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     304           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     305           0 :                        fd_topob_tile_in (   topo, "replay",  0UL,          "metric_in", "snapin_manif",  0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     306           0 :   }
     307             : 
     308           0 :   FOR(execrp_tile_cnt) fd_topob_tile_in (   topo, "execrp",  i,            "metric_in", "replay_execrp", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     309           0 :   FOR(execrp_tile_cnt) fd_topob_tile_out(   topo, "execrp",  i,                         "execrp_replay", i                                                  );
     310             : 
     311           0 :   /**/                 fd_topob_tile_in (   topo, "tower",   0UL,          "metric_in", "replay_epoch",  0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     312           0 :   /**/                 fd_topob_tile_in (   topo, "tower",   0UL,          "metric_in", "gossip_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     313           0 :   /**/                 fd_topob_tile_in (   topo, "tower",   0UL,          "metric_in", "replay_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     314           0 :   FOR(shred_tile_cnt)  fd_topob_tile_in(    topo, "tower",   0UL,          "metric_in", "shred_out",     i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     315           0 :   FOR(shred_tile_cnt)  fd_topob_tile_in(    topo, "replay",  0UL,          "metric_in", "shred_out",     i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     316           0 :   /**/                 fd_topob_tile_out(   topo, "tower",   0UL,                       "tower_out",     0UL                                                );
     317             : 
     318           0 :   FOR(shred_tile_cnt)    fd_topob_tile_in ( topo, "shred",   i,            "metric_in", "replay_epoch",  0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     319           0 :   FOR(shred_tile_cnt)    fd_topob_tile_in ( topo, "shred",   i,            "metric_in", "gossip_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     320           0 :   FOR(shred_tile_cnt)    fd_topob_tile_out( topo, "shred",   i,                         "shred_out",     i                                                  );
     321           0 :   FOR(shred_tile_cnt)    fd_topob_tile_in ( topo, "shred",   i,            "metric_in", "tower_out",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     322           0 :   FOR(shred_tile_cnt)    fd_topob_tile_out( topo, "shred",   i,                         "shred_net",     i                                                  );
     323             : 
     324             :   /*                                        topo, tile_name, tile_kind_id, fseq_wksp,   link_name,      link_kind_id, reliable,            polled */
     325             : 
     326           0 :   for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
     327           0 :     /**/               fd_topob_tile_in (   topo, "sign",    0UL,          "metric_in", "shred_sign",   i,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED   );
     328           0 :     /**/               fd_topob_tile_out(   topo, "shred",   i,                         "shred_sign",   i                                                    );
     329           0 :     /**/               fd_topob_tile_in (   topo, "shred",   i,            "metric_in", "sign_shred",   i,            FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
     330           0 :     /**/               fd_topob_tile_out(   topo, "sign",    0UL,                       "sign_shred",   i                                                    );
     331           0 :   }
     332             : 
     333           0 :   fd_topob_tile_out( topo, "forkt", 0UL, "net_shred", 0UL );
     334           0 :   FOR(shred_tile_cnt) fd_topob_tile_in( topo, "forkt", 0UL, "metric_in", "shred_net", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     335             : 
     336           0 :   if( FD_LIKELY( !is_auto_affinity ) ) {
     337           0 :     if( FD_UNLIKELY( affinity_tile_cnt<topo->tile_cnt ) )
     338           0 :       FD_LOG_ERR(( "The topology you are using has %lu tiles, but the CPU affinity specified in the config tile as [development.forktest.affinity] only provides for %lu cores. "
     339           0 :                    "You should either increase the number of cores dedicated to Firedancer in the affinity string, or decrease the number of cores needed by reducing "
     340           0 :                    "the total tile count. You can reduce the tile count by decreasing individual tile counts in the [layout] section of the configuration file.",
     341           0 :                    topo->tile_cnt, affinity_tile_cnt ));
     342           0 :     if( FD_UNLIKELY( affinity_tile_cnt>topo->tile_cnt ) )
     343           0 :       FD_LOG_WARNING(( "The topology you are using has %lu tiles, but the CPU affinity specified in the config tile as [development.forktest.affinity] provides for %lu cores. "
     344           0 :                        "Not all cores in the affinity will be used by Firedancer. You may wish to increase the number of tiles in the system by increasing "
     345           0 :                        "individual tile counts in the [layout] section of the configuration file.",
     346           0 :                        topo->tile_cnt, affinity_tile_cnt ));
     347           0 :   } else {
     348           0 :     ushort blocklist_cores[ FD_TILE_MAX ];
     349           0 :     topo->blocklist_cores_cnt = fd_topob_parse_affinity_cstr( config->layout.blocklist_cores, blocklist_cores, 0, 0 );
     350           0 :     if( FD_UNLIKELY( topo->blocklist_cores_cnt>FD_TILE_MAX ) ) {
     351           0 :       FD_LOG_ERR(( "The CPU string in the configuration file under [layout.blocklist_cores] specifies more CPUs than Firedancer can use. "
     352           0 :                     "You should reduce the number of CPUs in the excluded cores string." ));
     353           0 :     }
     354             : 
     355           0 :     for( ulong i=0UL; i<topo->blocklist_cores_cnt; i++ ) {
     356           0 :       if( FD_UNLIKELY( blocklist_cores[ i ]==USHORT_MAX ) ) {
     357           0 :         FD_LOG_ERR(( "The CPU string in the configuration file under [layout.blocklist_cores] contains invalid values: `f`. "
     358           0 :                       "You should fix the excluded cores string." ));
     359           0 :       }
     360           0 :       topo->blocklist_cores_cpu_idx[ i ] = blocklist_cores[ i ];
     361           0 :     }
     362           0 :   }
     363             : 
     364           0 :   if( FD_UNLIKELY( is_auto_affinity ) ) fd_topob_auto_layout( topo, 0 );
     365             : 
     366             :   /* Repair and shred share a secret they use to generate the nonces. */
     367           0 :   if( 1 ) {
     368           0 :     fd_topo_obj_t * rnonce_ss_obj = fd_topob_obj( topo, "rnonce_ss", "rnonce" );
     369           0 :     for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
     370           0 :       fd_topo_tile_t * shred_tile = &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ];
     371           0 :       fd_topob_tile_uses( topo, shred_tile, rnonce_ss_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
     372           0 :     }
     373           0 :     FD_TEST( fd_pod_insertf_ulong( topo->props, rnonce_ss_obj->id, "rnonce_ss" ) );
     374           0 :   }
     375             : 
     376           0 :   setup_topo_progcache( topo, "progcache",
     377           0 :       config->firedancer.runtime.max_live_slots,
     378           0 :       config->firedancer.runtime.program_cache_size_mib<<20 );
     379           0 :   ulong progcache_obj_id; FD_TEST( (progcache_obj_id = fd_pod_query_ulong( topo->props, "progcache", ULONG_MAX ))!=ULONG_MAX );
     380           0 :   fd_topo_obj_t * progcache_obj = &topo->objs[ progcache_obj_id ];
     381             : 
     382           0 :   /**/                 fd_topob_tile_uses( topo, replay_tile, progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     383           0 :   /**/                 fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "accdb", 0UL ) ], progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     384           0 :   FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i   ) ], progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     385             : 
     386           0 :   fd_topo_obj_t * banks_obj = setup_topo_banks( topo, "banks", config->firedancer.runtime.max_live_slots, config->firedancer.runtime.max_fork_width, config->development.bench.max_cost_per_block );
     387           0 :   /**/                 fd_topob_tile_uses( topo, replay_tile, banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     388           0 :   /**/                 fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "tower",  0UL ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_ONLY  );
     389           0 :   FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i   ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     390           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, banks_obj->id, "banks" ) );
     391             : 
     392           0 :   fd_topo_obj_t * node_info_obj = fd_topob_obj( topo, "node_info", "replay" );
     393           0 :   fd_topob_tile_uses( topo, replay_tile, node_info_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     394           0 :   fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "tower", 0UL ) ], node_info_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     395           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, node_info_obj->id, "node_info" ) );
     396             : 
     397           0 :   ulong fec_set_cnt = fd_shred_tile_fec_set_cnt( FD_SHRED_FIREDANCER_FEC_EXPOSURE,
     398           0 :                                                  config->tiles.shred.max_pending_shred_sets );
     399           0 :   ulong store_fec_set_cnt = shred_tile_cnt*fec_set_cnt;
     400             : 
     401           0 :   ulong fec_sets_per_slot = fd_ulong_if( config->firedancer.development.fixed_fec_sets,
     402           0 :                                          config->limits.max_shreds_per_block/FD_FEC_SHRED_CNT, config->limits.max_shreds_per_block );
     403           0 :   ulong store_fec_max = config->firedancer.runtime.max_live_slots * fec_sets_per_slot + (shred_depth * shred_tile_cnt) + 1;
     404           0 :   ulong store_fec_data_max = fd_ulong_if( config->firedancer.development.fixed_fec_sets, 31840UL, 63985UL );
     405           0 :   fd_topo_obj_t * store_obj = setup_topo_store( topo, "store", store_fec_max, store_fec_data_max, 0UL, config->tiles.shred.shred_cache_size_mib, store_fec_set_cnt, config->limits.max_shreds_per_block, config->paths.shredb );
     406           0 :   FOR(shred_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     407           0 :   fd_topob_tile_uses( topo, replay_tile, store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     408           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, store_obj->id, "store" ) );
     409             : 
     410           0 :   fd_topo_obj_t * txncache_obj = setup_topo_txncache( topo, "txncache", config->firedancer.runtime.max_live_slots, 2UL*config->limits.max_txn_per_slot );
     411           0 :   fd_topob_tile_uses( topo, replay_tile, txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     412           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     413           0 :     fd_topob_tile_uses( topo, snapin_tile, txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     414           0 :   }
     415           0 :   FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     416           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
     417             : 
     418           0 :   if( FD_LIKELY( snapshots_enabled ) ) fd_topob_tile_uses( topo, snapin_tile, accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     419           0 :   fd_topob_tile_uses( topo, accdb_tile, accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     420           0 :   fd_topob_tile_uses( topo, replay_tile, accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     421           0 :   FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i ) ], accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     422             : 
     423           0 :   fd_pod_insert_int( topo->props, "sandbox", config->development.sandbox ? 1 : 0 );
     424             : 
     425           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     426           0 :     fd_topo_configure_tile( &topo->tiles[ i ], config );
     427           0 :   }
     428             : 
     429           0 :   fd_topob_waker( topo );
     430           0 :   fd_topob_finish( topo, CALLBACKS );
     431           0 : }
     432             : 
     433             : static void
     434             : forktest_cmd_args( int *    pargc,
     435             :                    char *** pargv,
     436           0 :                    args_t * args ) {
     437           0 :   args->forktest.no_watch = fd_env_strip_cmdline_contains( pargc, pargv, "--no-watch" );
     438           0 : }
     439             : 
     440             : static void
     441             : forktest_fn( args_t *   args,
     442           0 :              config_t * config ) {
     443           0 :   args_t c_args = configure_args();
     444           0 :   configure_cmd_fn( &c_args, config );
     445             : 
     446           0 :   initialize_workspaces( config );
     447           0 :   initialize_stacks( config );
     448           0 :   initialize_accdb_fd( config );
     449           0 :   initialize_store_fds( config );
     450           0 :   initialize_snapshot_fds( config );
     451             : 
     452           0 :   fd_topo_join_workspaces( &config->topo, FD_SHMEM_JOIN_MODE_READ_WRITE, FD_TOPO_CORE_DUMP_LEVEL_DISABLED );
     453           0 :   fd_topo_fill( &config->topo );
     454             : 
     455           0 :   args_t watch_args;
     456           0 :   int pipefd[2];
     457           0 :   if( !args->forktest.no_watch ) {
     458           0 :     if( FD_UNLIKELY( pipe2( pipefd, O_NONBLOCK ) ) ) FD_LOG_ERR(( "pipe2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     459             : 
     460           0 :     watch_args.watch.drain_output_fd = pipefd[0];
     461           0 :     watch_args.watch.full = 1;
     462           0 :     if( FD_UNLIKELY( -1==dup2( pipefd[1], STDERR_FILENO ) ) ) FD_LOG_ERR(( "dup2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     463           0 :     if( FD_UNLIKELY( -1==close( pipefd[1] ) ) ) FD_LOG_ERR(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     464           0 :   }
     465             : 
     466           0 :   fd_topo_run_single_process( &config->topo, 2, config->uid, config->gid, fdctl_tile_run );
     467           0 :   if( args->forktest.no_watch ) {
     468           0 :     for(;;) pause();
     469           0 :   } else {
     470           0 :     watch_cmd_fn( &watch_args, config );
     471           0 :   }
     472           0 : }
     473             : 
     474             : action_t fd_action_forktest = {
     475             :   .name             = "forktest",
     476             :   .args             = forktest_cmd_args,
     477             :   .fn               = forktest_fn,
     478             :   .perm             = forktest_perm,
     479             :   .topo             = forktest_topo,
     480             :   .is_local_cluster = 1,
     481             :   .description      = "Replay a ledger offline through a pruned full topology with real consensus",
     482             : };

Generated by: LCOV version 1.14