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 366 0.0 %
Date: 2026-05-17 07:08:10 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 "../../../../ballet/lthash/fd_lthash.h"
      11             : #include "../../../../discof/replay/fd_execrp.h"
      12             : #include "../../../../discof/genesis/fd_genesi_tile.h"
      13             : #include "../../../../discof/tower/fd_tower_tile.h"
      14             : #include "../../../../discof/replay/fd_replay_tile.h"
      15             : #include "../../../../disco/shred/fd_shred_tile.h"
      16             : #include "../../../../disco/shred/fd_rnonce_ss.h"
      17             : #include "../../../../disco/net/fd_net_tile.h"
      18             : #include "../../../../disco/pack/fd_pack_cost.h"
      19             : #include "../../../../disco/topo/fd_topob.h"
      20             : #include "../../../../disco/topo/fd_cpu_topo.h"
      21             : #include "../../../../util/pod/fd_pod_format.h"
      22             : #include "../../../../util/tile/fd_tile_private.h"
      23             : #include "../../../../discof/restore/utils/fd_ssctrl.h"
      24             : #include "../../../../discof/restore/utils/fd_ssmsg.h"
      25             : #include "../../../../flamenco/progcache/fd_progcache_admin.h"
      26             : #include "../../../../flamenco/runtime/fd_acc_pool.h"
      27             : #include "../../../../flamenco/accdb/fd_accdb_lineage.h"
      28             : #include "../../../../ballet/shred/fd_shred.h"
      29             : #include "../../../../discof/backtest/fd_backtest_src.h"
      30             : 
      31             : #include <errno.h>
      32             : #include <unistd.h> /* pause(2) */
      33             : #include <fcntl.h>
      34             : 
      35             : extern fd_topo_obj_callbacks_t * CALLBACKS[];
      36             : fd_topo_run_tile_t fdctl_tile_run( fd_topo_tile_t const * tile );
      37             : 
      38             : extern configure_stage_t fd_cfg_stage_keys;
      39             : 
      40             : static args_t
      41           0 : configure_args( void ) {
      42           0 :   args_t args = {
      43           0 :     .configure.command = CONFIGURE_CMD_INIT,
      44           0 :   };
      45             : 
      46           0 :   ulong stage_idx = 0UL;
      47           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_hugetlbfs;
      48           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_snapshots;
      49           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_keys;
      50           0 :   args.configure.stages[ stage_idx++ ] = NULL;
      51             : 
      52           0 :   return args;
      53           0 : }
      54             : 
      55             : static void
      56             : forktest_perm( args_t *         args FD_PARAM_UNUSED,
      57             :                fd_cap_chk_t *   chk,
      58           0 :                config_t const * config ) {
      59           0 :   args_t c_args = configure_args();
      60           0 :   configure_cmd_perm( &c_args, chk, config );
      61           0 :   run_cmd_perm( NULL, chk, config );
      62           0 : }
      63             : 
      64             : static ushort
      65           0 : forktest_recover_expected_shred_version( config_t const * config ) {
      66           0 :   fd_backtest_src_opts_t opts = {
      67           0 :     .path   = config->firedancer.development.ledger_input.path,
      68           0 :     .format = config->firedancer.development.ledger_input.format,
      69           0 :   };
      70             : 
      71           0 :   uchar buf[ FD_SHRED_MAX_SZ ];
      72           0 :   ulong shred_sz = fd_backtest_src_first_shred( &opts, buf, sizeof(buf) );
      73           0 :   if( FD_UNLIKELY( !shred_sz ) ) FD_LOG_ERR(( "unable to recover shred version from `%s`", opts.path ));
      74             : 
      75           0 :   fd_shred_t const * shred = fd_shred_parse( buf, shred_sz );
      76           0 :   if( FD_UNLIKELY( !shred ) ) FD_LOG_ERR(( "unable to parse first shred from `%s`", opts.path ));
      77             : 
      78           0 :   FD_LOG_INFO(( "Recovered expected shred version %hu", shred->version ));
      79           0 :   return shred->version;
      80           0 : }
      81             : 
      82             : static void
      83           0 : forktest_topo( config_t * config ) {
      84             : 
      85           0 :   if( FD_UNLIKELY( !config->consensus.expected_shred_version ) ) {
      86           0 :     config->consensus.expected_shred_version = forktest_recover_expected_shred_version( config );
      87           0 :   }
      88             : 
      89           0 :   config->development.sandbox  = 0;
      90           0 :   config->development.no_clone = 1;
      91             : 
      92           0 :   ulong shred_tile_cnt  = config->layout.shred_tile_count;
      93             : 
      94           0 :   ulong execrp_tile_cnt = config->firedancer.layout.execrp_tile_count;
      95           0 :   ulong sign_tile_cnt   = config->firedancer.layout.sign_tile_count;
      96           0 :   ulong lta_tile_cnt    = config->firedancer.layout.snapshot_hash_tile_count;
      97             : 
      98           0 :   int snapshots_enabled = !!config->gossip.entrypoints_cnt;
      99           0 :   int snapshot_lthash_disabled = config->development.snapshots.disable_lthash_verification;
     100             : 
     101           0 :   fd_topo_t * topo = fd_topob_new( &config->topo, config->name );
     102             : 
     103           0 :   topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
     104           0 :   topo->gigantic_page_threshold = config->hugetlbfs.gigantic_page_threshold_mib << 20;
     105             : 
     106             :   /*             topo, name */
     107           0 :   fd_topob_wksp( topo, "metric" );
     108           0 :   fd_topob_wksp( topo, "shred"  );
     109           0 :   fd_topob_wksp( topo, "replay" );
     110           0 :   fd_topob_wksp( topo, "execrp" );
     111           0 :   fd_topob_wksp( topo, "tower"  );
     112           0 :   fd_topob_wksp( topo, "sign"   )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_NEVER;
     113             : 
     114           0 :   fd_topob_wksp( topo, "metric_in"    );
     115             : 
     116           0 :   fd_topob_wksp( topo, "net_shred"    );
     117             : 
     118           0 :   fd_topob_wksp( topo, "gossip_out"    );
     119             : 
     120           0 :   fd_topob_wksp( topo, "shred_out"     );
     121           0 :   fd_topob_wksp( topo, "replay_epoch"  );
     122           0 :   fd_topob_wksp( topo, "replay_execrp" );
     123           0 :   fd_topob_wksp( topo, "replay_out"    );
     124           0 :   fd_topob_wksp( topo, "tower_out"     );
     125             : 
     126           0 :   fd_topob_wksp( topo, "funk"          )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_FULL;
     127           0 :   fd_topob_wksp( topo, "funk_locks"    )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_FULL;
     128           0 :   fd_topob_wksp( topo, "progcache"     );
     129           0 :   fd_topob_wksp( topo, "fec_sets"      );
     130           0 :   fd_topob_wksp( topo, "txncache"      );
     131           0 :   fd_topob_wksp( topo, "banks"         );
     132           0 :   fd_topob_wksp( topo, "store"         )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_FULL;
     133           0 :   fd_topob_wksp( topo, "rnonce"        );
     134             : 
     135           0 :   fd_topob_wksp( topo, "shred_sign"    );
     136           0 :   fd_topob_wksp( topo, "sign_shred"    );
     137             : 
     138           0 :   if( FD_UNLIKELY( !snapshots_enabled ) ) {
     139           0 :     fd_topob_wksp( topo, "genesi" );
     140           0 :     fd_topob_wksp( topo, "genesi_out" );
     141           0 :   }
     142             : 
     143           0 :   fd_topob_wksp( topo, "execrp_replay" );
     144             : 
     145           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     146           0 :     fd_topob_wksp( topo, "snapct"      );
     147           0 :     fd_topob_wksp( topo, "snapld"      );
     148           0 :     fd_topob_wksp( topo, "snapdc"      );
     149           0 :     fd_topob_wksp( topo, "snapin"      );
     150           0 :     fd_topob_wksp( topo, "snapct_ld"   );
     151           0 :     fd_topob_wksp( topo, "snapld_dc"   );
     152           0 :     fd_topob_wksp( topo, "snapdc_in"   );
     153           0 :     if( snapshot_lthash_disabled ) {
     154           0 :       fd_topob_wksp( topo, "snapin_ct" );
     155           0 :     } else {
     156           0 :       fd_topob_wksp( topo, "snapla"    );
     157           0 :       fd_topob_wksp( topo, "snapls"    );
     158           0 :       fd_topob_wksp( topo, "snapla_ls" );
     159           0 :       fd_topob_wksp( topo, "snapin_ls" );
     160           0 :       fd_topob_wksp( topo, "snapls_ct" );
     161           0 :     }
     162             : 
     163           0 :     fd_topob_wksp( topo, "snapin_manif" );
     164           0 :     fd_topob_wksp( topo, "snapct_repr"  );
     165           0 :   }
     166             : 
     167           0 :   fd_topob_wksp( topo, "forkt" );
     168             : 
     169           0 :   #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
     170             : 
     171           0 :   ulong shred_depth = 65536UL; /* from fdctl/topology.c shred_store link. MAKE SURE TO KEEP IN SYNC. */
     172             : 
     173             :   /*                                  topo, link_name,       wksp_name,       depth,                                    mtu,                           burst */
     174           0 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "shred_net",     "net_shred",     32768UL,                                  FD_NET_MTU,                    1UL );
     175             : 
     176           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     177             :   /* TODO: Revisit the depths of all the snapshot links */
     178           0 :     /**/               fd_topob_link( topo, "snapct_ld",     "snapct_ld",     128UL,                                    sizeof(fd_ssctrl_init_t),      1UL );
     179           0 :     /**/               fd_topob_link( topo, "snapld_dc",     "snapld_dc",     16384UL,                                  USHORT_MAX,                    1UL );
     180           0 :     /**/               fd_topob_link( topo, "snapdc_in",     "snapdc_in",     16384UL,                                  USHORT_MAX,                    1UL );
     181             : 
     182             :     /**/               fd_topob_link( topo, "snapin_manif",  "snapin_manif",  4UL,                                      sizeof(fd_snapshot_manifest_t),1UL );
     183           0 :     /**/               fd_topob_link( topo, "snapct_repr",   "snapct_repr",   128UL,                                    0UL,                           1UL )->permit_no_consumers = 1; /* TODO: wire in repair later */
     184             : 
     185           0 :     if( snapshot_lthash_disabled ) {
     186           0 :       /**/             fd_topob_link( topo, "snapin_ct",    "snapin_ct",    128UL,                                    0UL,                           1UL );
     187           0 :     } else {
     188           0 :       FOR(lta_tile_cnt) fd_topob_link( topo, "snapla_ls",    "snapla_ls",   128UL,                                    sizeof(fd_lthash_value_t),     1UL );
     189           0 :       /**/              fd_topob_link( topo, "snapin_ls",    "snapin_ls",   256UL,                                    sizeof(fd_snapshot_full_account_t), 1UL );
     190           0 :       /**/              fd_topob_link( topo, "snapls_ct",    "snapls_ct",   128UL,                                    0UL,                           1UL );
     191           0 :     }
     192           0 :   }
     193             : 
     194           0 :   if( FD_UNLIKELY( !snapshots_enabled ) ) {
     195           0 :     /**/               fd_topob_link( topo, "genesi_out",    "genesi_out",    1UL,                                      FD_GENESIS_TILE_MTU,           1UL );
     196           0 :   }
     197             : 
     198             :   /**/                 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 */
     199             : 
     200           0 :   /**/                 fd_topob_link( topo, "replay_epoch",  "replay_epoch",  128UL,                                    FD_EPOCH_OUT_MTU,              1UL ); /* TODO: This should be 2 but requires fixing STEM_BURST */
     201           0 :   /**/                 fd_topob_link( topo, "replay_out",    "replay_out",    65536UL,                                  sizeof(fd_replay_message_t),   1UL );
     202           0 :                        fd_topob_link( topo, "replay_execrp", "replay_execrp", 16384UL,                                  sizeof(fd_execrp_task_msg_t),  1UL );
     203             : 
     204           0 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "shred_sign",    "shred_sign",    128UL,                                    32UL,                          1UL );
     205           0 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "sign_shred",    "sign_shred",    128UL,                                    sizeof(fd_ed25519_sig_t),      1UL );
     206           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 */
     207           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 */
     208             : 
     209           0 :   FOR(execrp_tile_cnt) fd_topob_link( topo, "execrp_replay", "execrp_replay", 16384UL,                                  sizeof(fd_execrp_task_done_msg_t), 1UL );
     210             : 
     211           0 :   ushort parsed_tile_to_cpu[ FD_TILE_MAX ];
     212             :   /* Unassigned tiles will be floating, unless auto topology is enabled. */
     213           0 :   for( ulong i=0UL; i<FD_TILE_MAX; i++ ) parsed_tile_to_cpu[ i ] = USHORT_MAX;
     214             : 
     215           0 :   int is_auto_affinity = !strcmp( config->firedancer.development.forktest.affinity, "auto" );
     216             : 
     217           0 :   fd_topo_cpus_t cpus[1];
     218           0 :   fd_topo_cpus_init( cpus );
     219             : 
     220           0 :   ulong affinity_tile_cnt = 0UL;
     221           0 :   if( FD_LIKELY( !is_auto_affinity ) ) affinity_tile_cnt = fd_tile_private_cpus_parse( config->firedancer.development.forktest.affinity, parsed_tile_to_cpu );
     222             : 
     223           0 :   ulong tile_to_cpu[ FD_TILE_MAX ] = {0};
     224           0 :   for( ulong i=0UL; i<affinity_tile_cnt; i++ ) {
     225           0 :     if( FD_UNLIKELY( parsed_tile_to_cpu[ i ]!=USHORT_MAX && parsed_tile_to_cpu[ i ]>=cpus->cpu_cnt ) )
     226           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 "
     227           0 :                    "only has %lu CPUs. You should either change the CPU allocations in the affinity string, or increase the number of CPUs "
     228           0 :                    "in the system.",
     229           0 :                    parsed_tile_to_cpu[ i ], cpus->cpu_cnt ));
     230           0 :     tile_to_cpu[ i ] = fd_ulong_if( parsed_tile_to_cpu[ i ]==USHORT_MAX, ULONG_MAX, (ulong)parsed_tile_to_cpu[ i ] );
     231           0 :   }
     232             : 
     233           0 :   fd_topob_link( topo, "net_shred", "net_shred", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
     234             : 
     235             :   /*                                  topo, tile_name, tile_wksp, metrics_wksp, cpu_idx,                       is_agave, uses_id_keyswitch, uses_av_keyswitch */
     236             :   /**/                 fd_topob_tile( topo, "metric",  "metric",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        0,                 0 );
     237             : 
     238           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     239           0 :     /**/               fd_topob_tile( topo, "snapct", "snapct", "metric_in", tile_to_cpu[ topo->tile_cnt ],    0,        0,                 0 )->allow_shutdown = 1;
     240           0 :     /**/               fd_topob_tile( topo, "snapld", "snapld", "metric_in", tile_to_cpu[ topo->tile_cnt ],    0,        0,                 0 )->allow_shutdown = 1;
     241           0 :     /**/               fd_topob_tile( topo, "snapdc", "snapdc", "metric_in", tile_to_cpu[ topo->tile_cnt ],    0,        0,                 0 )->allow_shutdown = 1;
     242           0 :     /**/               fd_topob_tile( topo, "snapin", "snapin", "metric_in", tile_to_cpu[ topo->tile_cnt ],    0,        0,                 0 )->allow_shutdown = 1;
     243             : 
     244           0 :     if( snapshot_lthash_disabled ) {
     245             :       /* nothing to do here */
     246           0 :     } else {
     247           0 :       FOR(lta_tile_cnt)  fd_topob_tile( topo, "snapla", "snapla", "metric_in", tile_to_cpu[ topo->tile_cnt ],  0,      0,                 0 )->allow_shutdown = 1;
     248           0 :       /**/               fd_topob_tile( topo, "snapls", "snapls", "metric_in", tile_to_cpu[ topo->tile_cnt ],  0,      0,                 0 )->allow_shutdown = 1;
     249           0 :     }
     250           0 :   }
     251             : 
     252           0 :   if( FD_UNLIKELY( !snapshots_enabled ) ) {
     253           0 :     /**/               fd_topob_tile( topo, "genesi",  "genesi",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        0,                 0 )->allow_shutdown = 1;
     254           0 :   }
     255             : 
     256           0 :   FOR(shred_tile_cnt)  fd_topob_tile( topo, "shred",   "shred",   "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        1,                 0 );
     257           0 :   /**/                 fd_topob_tile( topo, "replay",  "replay",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        1,                 0 );
     258           0 :   FOR(execrp_tile_cnt) fd_topob_tile( topo, "execrp",  "execrp",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        0,                 0 );
     259           0 :   /**/                 fd_topob_tile( topo, "tower",   "tower",   "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        1,                 1 );
     260             : 
     261           0 :   FOR(sign_tile_cnt)   fd_topob_tile( topo, "sign",    "sign",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        1,               1 );
     262             : 
     263           0 :   fd_topob_tile( topo, "forkt", "forkt", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
     264             : 
     265             :   /*                                        topo, tile_name, tile_kind_id, fseq_wksp,   link_name,       link_kind_id, reliable,            polled */
     266           0 :   FOR(shred_tile_cnt) fd_topob_tile_in (    topo, "shred",   i,            "metric_in", "net_shred",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     267           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 */
     268             : 
     269           0 :   if( FD_UNLIKELY( !snapshots_enabled ) ) {
     270           0 :     /**/               fd_topob_tile_out(   topo, "genesi", 0UL,                        "genesi_out",    0UL                                                );
     271           0 :   }
     272             : 
     273           0 :   /**/                 fd_topob_tile_in (   topo, "forkt", 0UL,            "metric_in", "replay_epoch",  0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     274           0 :   /**/                 fd_topob_tile_out(   topo, "forkt", 0UL,                         "gossip_out",    0UL                                                );
     275           0 :   /**/                 fd_topob_tile_in (   topo, "forkt", 0UL,            "metric_in", "tower_out",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     276           0 :   /**/                 fd_topob_tile_in (   topo, "forkt", 0UL,            "metric_in", "replay_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     277             : 
     278           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     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 :     if( snapshot_lthash_disabled ) {
     284           0 :       /**/            fd_topob_tile_out(    topo, "snapin",  0UL,                       "snapin_ct",    0UL                                            );
     285           0 :       /**/            fd_topob_tile_in (    topo, "snapct",  0UL,          "metric_in", "snapin_ct",    0UL,      FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     286           0 :     } else {
     287           0 :       /**/              fd_topob_tile_out(  topo, "snapin",  0UL,                       "snapin_ls",    0UL                                            );
     288           0 :       FOR(lta_tile_cnt) fd_topob_tile_in(   topo, "snapla",  i,            "metric_in", "snapdc_in",    0UL,      FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     289           0 :       FOR(lta_tile_cnt) fd_topob_tile_out(  topo, "snapla",  i,                         "snapla_ls",    i                                              );
     290           0 :       /**/              fd_topob_tile_in(   topo, "snapls",  0UL,          "metric_in", "snapin_ls",    0UL,      FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     291           0 :       FOR(lta_tile_cnt) fd_topob_tile_in(   topo, "snapls",  0UL,          "metric_in", "snapla_ls",    i,        FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     292           0 :       /**/              fd_topob_tile_out(  topo, "snapls",  0UL,                       "snapls_ct",    0UL                                            );
     293           0 :       /**/              fd_topob_tile_in (  topo, "snapct",  0UL,          "metric_in", "snapls_ct",    0UL,      FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     294           0 :     }
     295             : 
     296           0 :     /**/              fd_topob_tile_in (    topo, "snapld",  0UL,          "metric_in", "snapct_ld",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     297           0 :     /**/              fd_topob_tile_out(    topo, "snapld",  0UL,                       "snapld_dc",     0UL                                                );
     298             : 
     299           0 :     /**/              fd_topob_tile_in (    topo, "snapdc",  0UL,          "metric_in", "snapld_dc",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     300           0 :     /**/              fd_topob_tile_out(    topo, "snapdc",  0UL,                       "snapdc_in",     0UL                                                );
     301             : 
     302           0 :                       fd_topob_tile_in (    topo, "snapin",  0UL,          "metric_in", "snapdc_in",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     303           0 :                       fd_topob_tile_out(    topo, "snapin",  0UL,                       "snapin_manif",  0UL                                                );
     304           0 :   }
     305             : 
     306           0 :   if( FD_UNLIKELY( !snapshots_enabled ) ) {
     307           0 :     /**/               fd_topob_tile_in (   topo, "replay",  0UL,          "metric_in", "genesi_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     308           0 :   }
     309           0 :   /**/                 fd_topob_tile_out(   topo, "replay",  0UL,                       "replay_out",    0UL                                                );
     310           0 :   /**/                 fd_topob_tile_out(   topo, "replay",  0UL,                       "replay_epoch",  0UL                                                );
     311           0 :   /**/                 fd_topob_tile_out(   topo, "replay",  0UL,                       "replay_execrp", 0UL                                                );
     312           0 :   FOR(execrp_tile_cnt) fd_topob_tile_in (   topo, "replay",  0UL,          "metric_in", "execrp_replay", i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     313           0 :   /**/                 fd_topob_tile_in (   topo, "replay",  0UL,          "metric_in", "tower_out",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     314           0 :   /**/                 fd_topob_tile_in (   topo, "replay",  0UL,          "metric_in", "gossip_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     315           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     316           0 :                        fd_topob_tile_in (   topo, "replay",  0UL,          "metric_in", "snapin_manif",  0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     317           0 :   }
     318             : 
     319           0 :   FOR(execrp_tile_cnt) fd_topob_tile_in (   topo, "execrp",  i,            "metric_in", "replay_execrp", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     320           0 :   FOR(execrp_tile_cnt) fd_topob_tile_out(   topo, "execrp",  i,                         "execrp_replay", i                                                  );
     321             : 
     322           0 :   /**/                 fd_topob_tile_in (   topo, "tower",   0UL,          "metric_in", "replay_epoch",  0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     323           0 :   /**/                 fd_topob_tile_in (   topo, "tower",   0UL,          "metric_in", "gossip_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     324           0 :   /**/                 fd_topob_tile_in (   topo, "tower",   0UL,          "metric_in", "replay_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     325           0 :   FOR(shred_tile_cnt)  fd_topob_tile_in(    topo, "tower",   0UL,          "metric_in", "shred_out",     i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     326           0 :   FOR(shred_tile_cnt)  fd_topob_tile_in(    topo, "replay",  0UL,          "metric_in", "shred_out",     i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     327           0 :   /**/                 fd_topob_tile_out(   topo, "tower",   0UL,                       "tower_out",     0UL                                                );
     328             : 
     329           0 :   FOR(shred_tile_cnt)    fd_topob_tile_in ( topo, "shred",   i,            "metric_in", "replay_epoch",  0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     330           0 :   FOR(shred_tile_cnt)    fd_topob_tile_in ( topo, "shred",   i,            "metric_in", "gossip_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     331           0 :   FOR(shred_tile_cnt)    fd_topob_tile_out( topo, "shred",   i,                         "shred_out",     i                                                  );
     332           0 :   FOR(shred_tile_cnt)    fd_topob_tile_in ( topo, "shred",   i,            "metric_in", "tower_out",     0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     333           0 :   FOR(shred_tile_cnt)    fd_topob_tile_out( topo, "shred",   i,                         "shred_net",     i                                                  );
     334             : 
     335             :   /*                                        topo, tile_name, tile_kind_id, fseq_wksp,   link_name,      link_kind_id, reliable,            polled */
     336             : 
     337           0 :   for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
     338           0 :     /**/               fd_topob_tile_in (   topo, "sign",    0UL,          "metric_in", "shred_sign",   i,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED   );
     339           0 :     /**/               fd_topob_tile_out(   topo, "shred",   i,                         "shred_sign",   i                                                    );
     340           0 :     /**/               fd_topob_tile_in (   topo, "shred",   i,            "metric_in", "sign_shred",   i,            FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
     341           0 :     /**/               fd_topob_tile_out(   topo, "sign",    0UL,                       "sign_shred",   i                                                    );
     342           0 :   }
     343             : 
     344           0 :   fd_topob_tile_out( topo, "forkt", 0UL, "net_shred", 0UL );
     345           0 :   FOR(shred_tile_cnt) fd_topob_tile_in( topo, "forkt", 0UL, "metric_in", "shred_net", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     346             : 
     347           0 :   if( FD_LIKELY( !is_auto_affinity ) ) {
     348           0 :     if( FD_UNLIKELY( affinity_tile_cnt<topo->tile_cnt ) )
     349           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. "
     350           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 "
     351           0 :                    "the total tile count. You can reduce the tile count by decreasing individual tile counts in the [layout] section of the configuration file.",
     352           0 :                    topo->tile_cnt, affinity_tile_cnt ));
     353           0 :     if( FD_UNLIKELY( affinity_tile_cnt>topo->tile_cnt ) )
     354           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. "
     355           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 "
     356           0 :                        "individual tile counts in the [layout] section of the configuration file.",
     357           0 :                        topo->tile_cnt, affinity_tile_cnt ));
     358           0 :   } else {
     359           0 :     ushort blocklist_cores[ FD_TILE_MAX ];
     360           0 :     topo->blocklist_cores_cnt = fd_tile_private_cpus_parse( config->layout.blocklist_cores, blocklist_cores );
     361           0 :     if( FD_UNLIKELY( topo->blocklist_cores_cnt>FD_TILE_MAX ) ) {
     362           0 :       FD_LOG_ERR(( "The CPU string in the configuration file under [layout.blocklist_cores] specifies more CPUs than Firedancer can use. "
     363           0 :                     "You should reduce the number of CPUs in the excluded cores string." ));
     364           0 :     }
     365             : 
     366           0 :     for( ulong i=0UL; i<topo->blocklist_cores_cnt; i++ ) {
     367             :       /* Since we use fd_tile_private_cpus_parse() like for affinity, the user
     368             :          may input a string containing `f`. That's parsed correctly, but it's
     369             :          meaningless for blocklisted cores, so we reject it here.  */
     370           0 :       if( FD_UNLIKELY( blocklist_cores[ i ]==USHORT_MAX ) ) {
     371           0 :         FD_LOG_ERR(( "The CPU string in the configuration file under [layout.blocklist_cores] contains invalid values: `f`. "
     372           0 :                       "You should fix the excluded cores string." ));
     373           0 :       }
     374           0 :       topo->blocklist_cores_cpu_idx[ i ] = blocklist_cores[ i ];
     375           0 :     }
     376           0 :   }
     377             : 
     378           0 :   if( FD_UNLIKELY( is_auto_affinity ) ) fd_topob_auto_layout( topo, 0 );
     379             : 
     380             :   /* Repair and shred share a secret they use to generate the nonces.
     381             :      It's not super security sensitive, but for good hygiene, we make it
     382             :      an object. */
     383           0 :   if( 1 /* just restrict the scope for these variables in this big function */ ) {
     384           0 :     fd_topo_obj_t * rnonce_ss_obj = fd_topob_obj( topo, "rnonce_ss", "rnonce" );
     385           0 :     for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
     386           0 :       fd_topo_tile_t * shred_tile = &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ];
     387           0 :       fd_topob_tile_uses( topo, shred_tile, rnonce_ss_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
     388           0 :     }
     389           0 :     FD_TEST( fd_pod_insertf_ulong( topo->props, rnonce_ss_obj->id, "rnonce_ss" ) );
     390           0 :   }
     391             : 
     392           0 :   setup_topo_funk( topo,
     393           0 :       config->firedancer.accounts.max_accounts,
     394           0 :       config->firedancer.runtime.max_live_slots,
     395           0 :       config->firedancer.accounts.file_size_gib );
     396           0 :   ulong funk_obj_id;       FD_TEST( (funk_obj_id       = fd_pod_query_ulong( topo->props, "funk",       ULONG_MAX ))!=ULONG_MAX );
     397           0 :   ulong funk_locks_obj_id; FD_TEST( (funk_locks_obj_id = fd_pod_query_ulong( topo->props, "funk_locks", ULONG_MAX ))!=ULONG_MAX );
     398           0 :   fd_topo_obj_t * funk_obj       = &topo->objs[ funk_obj_id       ];
     399           0 :   fd_topo_obj_t * funk_locks_obj = &topo->objs[ funk_locks_obj_id ];
     400             : 
     401           0 :   /**/                 fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     402           0 :   /**/                 fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "tower", 0UL  ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_ONLY  );
     403           0 :   FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i   ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     404             : 
     405           0 :   /**/                 fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     406           0 :   /**/                 fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "tower", 0UL  ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     407           0 :   FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i   ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     408             : 
     409           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 );
     410           0 :   /**/                 fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     411           0 :   /**/                 fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "tower",  0UL ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_ONLY  );
     412           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 );
     413           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, banks_obj->id, "banks" ) );
     414             : 
     415           0 :   if( FD_UNLIKELY( config->firedancer.runtime.concurrent_account_limit<FD_ACC_POOL_MIN_ACCOUNT_CNT_PER_TX ) ) {
     416           0 :     FD_LOG_ERR(( "concurrent_account_limit is less than the minimum required for transaction execution: %lu < %lu", config->firedancer.runtime.concurrent_account_limit, FD_ACC_POOL_MIN_ACCOUNT_CNT_PER_TX ));
     417           0 :   }
     418           0 :   if( FD_UNLIKELY( config->firedancer.runtime.max_live_slots<32UL ) ) {
     419           0 :     FD_LOG_ERR(( "max_live_slots must be >= 32 in order to support tower rooting" ));
     420           0 :   }
     421           0 :   if( FD_UNLIKELY( config->firedancer.runtime.max_live_slots>FD_ACCDB_MAX_DEPTH_MAX ) ) {
     422           0 :     FD_LOG_ERR(( "max_live_slots (%lu) exceeds compile-time limit FD_ACCDB_MAX_DEPTH_MAX (%lu)",
     423           0 :                  config->firedancer.runtime.max_live_slots, FD_ACCDB_MAX_DEPTH_MAX ));
     424           0 :   }
     425             : 
     426           0 :   fd_topo_obj_t * acc_pool_obj = setup_topo_acc_pool( topo, config->firedancer.runtime.concurrent_account_limit );
     427           0 :   FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp",   i   ) ], acc_pool_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     428           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, acc_pool_obj->id, "acc_pool" ) );
     429             : 
     430           0 :   setup_topo_progcache( topo, "progcache",
     431           0 :       fd_progcache_est_rec_max( config->firedancer.runtime.program_cache.heap_size_mib<<20,
     432           0 :                                 config->firedancer.runtime.program_cache.mean_cache_entry_size ),
     433           0 :       config->firedancer.runtime.max_live_slots,
     434           0 :       config->firedancer.runtime.program_cache.heap_size_mib<<20 );
     435           0 :   ulong progcache_obj_id; FD_TEST( (progcache_obj_id = fd_pod_query_ulong( topo->props, "progcache", ULONG_MAX ))!=ULONG_MAX );
     436           0 :   fd_topo_obj_t * progcache_obj = &topo->objs[ progcache_obj_id ];
     437             : 
     438           0 :   /**/                 fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     439           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 );
     440             : 
     441           0 :   ulong fec_set_cnt = 2UL*shred_depth + config->tiles.shred.max_pending_shred_sets + 6UL;
     442           0 :   ulong fec_sets_sz = fec_set_cnt*sizeof(fd_fec_set_t); /* mirrors # of dcache entires in frankendancer */
     443           0 :   fd_topo_obj_t * fec_sets_obj = setup_topo_fec_sets( topo, "fec_sets", shred_tile_cnt*fec_sets_sz );
     444           0 :   for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
     445           0 :     fd_topo_tile_t * shred_tile = &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ];
     446           0 :     fd_topob_tile_uses( topo, shred_tile, fec_sets_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     447           0 :   }
     448           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, fec_sets_obj->id, "fec_sets" ) );
     449             : 
     450           0 :   ulong store_fec_max = config->firedancer.runtime.max_live_slots * FD_FEC_BLK_MAX + (shred_depth * shred_tile_cnt) + 1;
     451             : 
     452           0 :   ulong store_fec_data_max = fd_ulong_if( config->firedancer.runtime.fixed_fec_sets, 31840UL, 63985UL );
     453           0 :   fd_topo_obj_t * store_obj = setup_topo_store( topo, "store", store_fec_max, (uint)shred_tile_cnt, store_fec_data_max );
     454           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 );
     455           0 :   fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     456           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, store_obj->id, "store" ) );
     457             : 
     458           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 );
     459           0 :   fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     460           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     461           0 :     fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     462           0 :   }
     463           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 );
     464           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
     465             : 
     466           0 :   if( FD_UNLIKELY( !snapshots_enabled ) ) {
     467           0 :     fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "genesi", 0UL ) ], funk_obj,       FD_SHMEM_JOIN_MODE_READ_WRITE );
     468           0 :     fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "genesi", 0UL ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     469           0 :   }
     470           0 :   if( FD_LIKELY( snapshots_enabled ) ) {
     471           0 :     fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ], funk_obj,       FD_SHMEM_JOIN_MODE_READ_WRITE );
     472           0 :     fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     473           0 :   }
     474             : 
     475           0 :   fd_pod_insert_int( topo->props, "sandbox", config->development.sandbox ? 1 : 0 );
     476             : 
     477           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     478           0 :     fd_topo_configure_tile( &topo->tiles[ i ], config );
     479           0 :   }
     480             : 
     481           0 :   fd_topob_finish( topo, CALLBACKS );
     482           0 : }
     483             : 
     484             : static void
     485             : forktest_cmd_args( int *    pargc,
     486             :                    char *** pargv,
     487           0 :                    args_t * args ) {
     488           0 :   args->forktest.no_watch = fd_env_strip_cmdline_contains( pargc, pargv, "--no-watch" );
     489           0 : }
     490             : 
     491             : static void
     492             : forktest_fn( args_t *   args,
     493           0 :              config_t * config ) {
     494           0 :   args_t c_args = configure_args();
     495           0 :   configure_cmd_fn( &c_args, config );
     496             : 
     497           0 :   initialize_workspaces( config );
     498           0 :   initialize_stacks( config );
     499             : 
     500           0 :   fd_topo_join_workspaces( &config->topo, FD_SHMEM_JOIN_MODE_READ_WRITE, FD_TOPO_CORE_DUMP_LEVEL_DISABLED );
     501           0 :   fd_topo_fill( &config->topo );
     502             : 
     503           0 :   ulong rnonce_ss_id = fd_pod_queryf_ulong( config->topo.props, ULONG_MAX, "rnonce_ss" );
     504           0 :   FD_TEST( rnonce_ss_id!=ULONG_MAX );
     505           0 :   void * shared_rnonce = fd_topo_obj_laddr( &config->topo, rnonce_ss_id );
     506           0 :   ulong * nonce_initialized = (ulong *)(sizeof(fd_rnonce_ss_t)+(uchar *)shared_rnonce);
     507           0 :   FD_TEST( fd_rng_secure( shared_rnonce, sizeof(fd_rnonce_ss_t) ) );
     508           0 :   FD_COMPILER_MFENCE();
     509           0 :   FD_VOLATILE( *nonce_initialized ) = 1UL;
     510             : 
     511           0 :   args_t watch_args;
     512           0 :   int pipefd[2];
     513           0 :   if( !args->forktest.no_watch ) {
     514           0 :     if( FD_UNLIKELY( pipe2( pipefd, O_NONBLOCK ) ) ) FD_LOG_ERR(( "pipe2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     515             : 
     516           0 :     watch_args.watch.drain_output_fd = pipefd[0];
     517           0 :     if( FD_UNLIKELY( -1==dup2( pipefd[1], STDERR_FILENO ) ) ) FD_LOG_ERR(( "dup2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     518           0 :     if( FD_UNLIKELY( -1==close( pipefd[1] ) ) ) FD_LOG_ERR(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     519           0 :   }
     520             : 
     521           0 :   fd_topo_run_single_process( &config->topo, 2, config->uid, config->gid, fdctl_tile_run );
     522           0 :   if( args->forktest.no_watch ) {
     523           0 :     for(;;) pause();
     524           0 :   } else {
     525           0 :     watch_cmd_fn( &watch_args, config );
     526           0 :   }
     527           0 : }
     528             : 
     529             : action_t fd_action_forktest = {
     530             :   .name = "forktest",
     531             :   .args = forktest_cmd_args,
     532             :   .fn   = forktest_fn,
     533             :   .perm = forktest_perm,
     534             :   .topo = forktest_topo,
     535             :   .is_local_cluster = 1
     536             : };

Generated by: LCOV version 1.14