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

Generated by: LCOV version 1.14