LCOV - code coverage report
Current view: top level - app/firedancer-dev/commands - backtest.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 231 0.0 %
Date: 2026-06-29 05:51:35 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /* The backtest topology exercises offline replay with mocked consensus.
       2             : 
       3             :    The smaller topology is:
       4             :            shred_out             replay_execr
       5             :    backtest-------------->replay------------->execrp
       6             :      ^                    |^ | ^                |
       7             :      |____________________|| | |________________|
       8             :           replay_out       | |   execrp_replay
       9             :                            | |------------------------------>no consumer
      10             :     no producer-------------  stake_out, txsend_out, poh_out
      11             :                 store_replay
      12             : 
      13             : */
      14             : #define _GNU_SOURCE
      15             : #include "../../firedancer/topology.h"
      16             : #include "../../shared/commands/configure/configure.h"
      17             : #include "../../shared/commands/run/run.h" /* initialize_workspaces */
      18             : #include "../../shared/commands/watch/watch.h"
      19             : #include "../../shared/fd_config.h" /* config_t */
      20             : #include "../../../disco/topo/fd_topob.h"
      21             : #include "../../../util/pod/fd_pod_format.h"
      22             : #include "../../../discof/genesis/fd_genesi_tile.h"
      23             : #include "../../../discof/replay/fd_replay_tile.h"
      24             : #include "../../../discof/restore/utils/fd_ssctrl.h"
      25             : #include "../../../discof/restore/utils/fd_ssmsg.h"
      26             : #include "../../../discof/tower/fd_tower_tile.h"
      27             : #include "../../../discof/replay/fd_execrp.h"
      28             : #include "../../../disco/shred/fd_shred_tile.h"
      29             : #include "../../../flamenco/capture/fd_capture_ctx.h"
      30             : #include "../../../disco/pack/fd_pack_cost.h"
      31             : #include "../../../flamenco/progcache/fd_progcache_admin.h"
      32             : #include "../../../flamenco/runtime/fd_cost_tracker.h"
      33             : 
      34             : #include <errno.h>
      35             : #include <unistd.h>
      36             : #include <fcntl.h>
      37             : 
      38             : extern fd_topo_obj_callbacks_t * CALLBACKS[];
      39             : fd_topo_run_tile_t fdctl_tile_run( fd_topo_tile_t const * tile );
      40             : 
      41             : void
      42             : backtest_cmd_args( int *    pargc,
      43             :                    char *** pargv,
      44           0 :                    args_t * args ) {
      45           0 :   args->backtest.no_watch = fd_env_strip_cmdline_contains( pargc, pargv, "--no-watch" );
      46           0 : }
      47             : 
      48             : static void
      49           0 : backtest_topo( config_t * config ) {
      50             : 
      51           0 :   config->development.sandbox  = 0;
      52           0 :   config->development.no_clone = 1;
      53             : 
      54           0 :   config->firedancer.layout.resolv_tile_count = 0;
      55             : 
      56           0 :   ulong execrp_tile_cnt = config->firedancer.layout.execrp_tile_count;
      57             : 
      58           0 :   int disable_snap_loader      = !config->gossip.entrypoints_cnt;
      59           0 :   int solcap_enabled           = strlen( config->capture.solcap_capture )>0;
      60             : 
      61           0 :   fd_topo_t * topo = { fd_topob_new( &config->topo, config->name ) };
      62           0 :   topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
      63           0 :   topo->gigantic_page_threshold = config->hugetlbfs.gigantic_page_threshold_mib << 20;
      64             : 
      65           0 :   ulong cpu_idx = 0;
      66             : 
      67           0 :   fd_topob_wksp( topo, "metric" );
      68           0 :   fd_topob_wksp( topo, "metric_in" );
      69           0 :   fd_topob_tile( topo, "metric", "metric", "metric_in", ULONG_MAX, 0, 0, 0 );
      70             : 
      71           0 :   fd_topob_wksp( topo, "backt" );
      72           0 :   fd_topo_tile_t * backt_tile = fd_topob_tile( topo, "backt", "backt", "metric_in", cpu_idx++, 0, 0, 0 );
      73             : 
      74           0 :   fd_topob_wksp( topo, "replay" );
      75           0 :   fd_topo_tile_t * replay_tile = fd_topob_tile( topo, "replay", "replay", "metric_in", cpu_idx++, 0, 1, 0 );
      76             : 
      77           0 :   fd_topo_obj_t * node_info_obj = fd_topob_obj( topo, "node_info", "replay" );
      78           0 :   fd_topob_tile_uses( topo, replay_tile, node_info_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
      79           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, node_info_obj->id, "node_info" ) );
      80             : 
      81           0 :   fd_topob_wksp( topo, "accdb" )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_FULL;
      82           0 :   fd_topo_tile_t * accdb_tile = fd_topob_tile( topo, "accdb", "accdb", "metric_in", cpu_idx++, 0, 0, 0 );
      83             : 
      84           0 :   fd_topob_wksp( topo, "progcache" );
      85           0 :   setup_topo_progcache( topo, "progcache",
      86           0 :       fd_progcache_est_rec_max( config->firedancer.runtime.program_cache.heap_size_mib<<20,
      87           0 :                                 config->firedancer.runtime.program_cache.mean_cache_entry_size ),
      88           0 :       config->firedancer.runtime.max_live_slots,
      89           0 :       config->firedancer.runtime.program_cache.heap_size_mib<<20 );
      90           0 :   ulong progcache_obj_id; FD_TEST( (progcache_obj_id = fd_pod_query_ulong( topo->props, "progcache", ULONG_MAX ) )!=ULONG_MAX );
      91           0 :   fd_topob_tile_uses( topo, replay_tile, &topo->objs[ progcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_WRITE );
      92             : 
      93           0 :   fd_topob_wksp( topo, "accdb_data" );
      94           0 :   fd_topo_obj_t * accdb_obj = setup_topo_accdb( topo, "accdb_data",
      95           0 :       config->firedancer.accounts.max_accounts,
      96           0 :       config->firedancer.runtime.max_live_slots,
      97           0 :       FD_RUNTIME_MAX_WRITABLE_ACCOUNTS_PER_SLOT,
      98           0 :       8192UL,
      99           0 :       1UL<<35UL,
     100           0 :       config->firedancer.accounts.cache_size_gib*(1UL<<30UL),
     101           0 :       config->tiles.bundle.enabled,
     102           0 :       execrp_tile_cnt+3UL );
     103           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, accdb_obj->id, "accdb" ) );
     104             : 
     105             :   /**********************************************************************/
     106             :   /* Add the executor tiles to topo                                     */
     107             :   /**********************************************************************/
     108           0 :   fd_topob_wksp( topo, "execrp" );
     109           0 :   #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
     110           0 :   FOR(execrp_tile_cnt) fd_topob_tile( topo, "execrp", "execrp", "metric_in", cpu_idx++, 0, 0, 0 );
     111             : 
     112             :   /**********************************************************************/
     113             :   /* Add the capture tile to topo                                       */
     114             :   /**********************************************************************/
     115           0 :   if( solcap_enabled ) {
     116           0 :     fd_topob_wksp( topo, "solcap" );
     117           0 :     fd_topob_tile( topo, "solcap", "solcap", "metric_in", cpu_idx++, 0, 0, 0 );
     118           0 :   }
     119             : 
     120           0 :   fd_topob_wksp( topo, "diag" );
     121           0 :   fd_topob_tile( topo, "diag", "diag", "metric_in", ULONG_MAX, 0, 0, 0 );
     122             : 
     123             :   /**********************************************************************/
     124             :   /* Add the snapshot tiles to topo                                       */
     125             :   /**********************************************************************/
     126           0 :   fd_topo_tile_t * snapin_tile = NULL;
     127           0 :   if( FD_UNLIKELY( !disable_snap_loader ) ) {
     128           0 :     fd_topob_wksp( topo, "snapct" );
     129           0 :     fd_topob_wksp( topo, "snapld" );
     130           0 :     fd_topob_wksp( topo, "snapdc" );
     131           0 :     fd_topob_wksp( topo, "snapin" );
     132           0 :     fd_topob_wksp( topo, "snapwr" );
     133             : 
     134           0 :     fd_topo_tile_t * snapct_tile = fd_topob_tile( topo, "snapct",  "snapct",  "metric_in",  cpu_idx++, 0, 0, 0 );
     135           0 :     fd_topo_tile_t * snapld_tile = fd_topob_tile( topo, "snapld",  "snapld",  "metric_in",  cpu_idx++, 0, 0, 0 );
     136           0 :     fd_topo_tile_t * snapdc_tile = fd_topob_tile( topo, "snapdc",  "snapdc",  "metric_in",  cpu_idx++, 0, 0, 0 );
     137           0 :                      snapin_tile = fd_topob_tile( topo, "snapin",  "snapin",  "metric_in",  cpu_idx++, 0, 0, 0 );
     138           0 :     fd_topo_tile_t * snapwr_tile = fd_topob_tile( topo, "snapwr",  "snapwr",  "metric_in",  cpu_idx++, 0, 0, 0 );
     139             : 
     140           0 :     snapct_tile->allow_shutdown = 1;
     141           0 :     snapld_tile->allow_shutdown = 1;
     142           0 :     snapdc_tile->allow_shutdown = 1;
     143           0 :     snapin_tile->allow_shutdown = 1;
     144           0 :     snapwr_tile->allow_shutdown = 1;
     145           0 :   } else {
     146           0 :     fd_topob_wksp( topo, "genesi" );
     147           0 :     fd_topob_tile( topo, "genesi",  "genesi",  "metric_in",  cpu_idx++, 0, 0, 0 )->allow_shutdown = 1;
     148           0 :   }
     149             : 
     150             :   /**********************************************************************/
     151             :   /* Setup backtest->replay link (repair_out) in topo                 */
     152             :   /**********************************************************************/
     153             : 
     154             :   /* The repair tile is replaced by the backtest tile for the repair to
     155             :      replay link.  The frag interface is a "slice", ie. entry batch,
     156             :      which is provided by the backtest tile, which reads in the entry
     157             :      batches from the CLI-specified source (eg. RocksDB). */
     158             : 
     159           0 :   fd_topob_wksp( topo, "repair_out" );
     160           0 :   fd_topob_link( topo, "repair_out", "repair_out", 65536UL, sizeof(fd_fec_complete_t), 1UL );
     161           0 :   fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "repair_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     162           0 :   fd_topob_tile_out( topo, "backt", 0UL, "repair_out", 0UL );
     163             : 
     164             :   /**********************************************************************/
     165             :   /* Setup snapshot links in topo                                       */
     166             :   /**********************************************************************/
     167           0 :   if( FD_LIKELY( !disable_snap_loader ) ) {
     168           0 :     fd_topob_wksp( topo, "snapct_ld"    );
     169           0 :     fd_topob_wksp( topo, "snapld_dc"    );
     170           0 :     fd_topob_wksp( topo, "snapdc_in"    );
     171             : 
     172           0 :     fd_topob_wksp( topo, "snapin_manif" );
     173           0 :     fd_topob_wksp( topo, "snapct_repr"  );
     174             : 
     175           0 :     fd_topob_wksp( topo, "snapin_ct" );
     176           0 :     fd_topob_wksp( topo, "snapwr_ct" );
     177             : 
     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           0 :     fd_topob_link( topo, "snapin_manif", "snapin_manif", 4UL,     sizeof(fd_snapshot_manifest_t), 1UL ); /* TODO: Should be depth 1 or 2 but replay backpressures */
     183           0 :     fd_topob_link( topo, "snapct_repr",  "snapct_repr",  128UL,   0UL,                            1UL )->permit_no_consumers = 1;
     184             : 
     185           0 :     fd_topob_link( topo, "snapin_ct",    "snapin_ct",    128UL,   0UL,                            1UL );
     186           0 :     fd_topob_link( topo, "snapwr_ct",    "snapwr_ct",    128UL,   0UL,                            1UL );
     187             : 
     188           0 :     fd_topob_tile_in ( topo, "snapct",  0UL, "metric_in", "snapin_ct",    0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     189           0 :     fd_topob_tile_in ( topo, "snapct",  0UL, "metric_in", "snapwr_ct",    0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     190           0 :     fd_topob_tile_in ( topo, "snapct",  0UL, "metric_in", "snapld_dc",    0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     191           0 :     fd_topob_tile_out( topo, "snapct",  0UL,              "snapct_ld",    0UL                                       );
     192           0 :     fd_topob_tile_out( topo, "snapct",  0UL,              "snapct_repr",  0UL                                       );
     193           0 :     fd_topob_tile_in ( topo, "snapld",  0UL, "metric_in", "snapct_ld",    0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     194           0 :     fd_topob_tile_out( topo, "snapld",  0UL,              "snapld_dc",    0UL                                       );
     195           0 :     fd_topob_tile_in ( topo, "snapdc",  0UL, "metric_in", "snapld_dc",    0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     196           0 :     fd_topob_tile_out( topo, "snapdc",  0UL,              "snapdc_in",    0UL                                       );
     197           0 :     fd_topob_tile_in ( topo, "snapin",  0UL, "metric_in", "snapdc_in",    0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     198           0 :     fd_topob_tile_in ( topo, "snapwr",  0UL, "metric_in", "snapdc_in",    0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     199             : 
     200           0 :     fd_topob_tile_out( topo, "snapin",  0UL,              "snapin_manif", 0UL                                       );
     201           0 :     fd_topob_tile_in ( topo, "replay",  0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED   );
     202             : 
     203           0 :     fd_topob_tile_out( topo, "snapin", 0UL,               "snapin_ct",    0UL                                       );
     204           0 :     fd_topob_tile_out( topo, "snapwr", 0UL,               "snapwr_ct",    0UL                                       );
     205           0 :   } else {
     206           0 :     fd_topob_wksp( topo, "genesi_out" );
     207           0 :     fd_topob_link( topo, "genesi_out", "genesi_out", 1UL, FD_GENESIS_TILE_MTU, 0UL );
     208           0 :     fd_topob_tile_out( topo, "genesi", 0UL, "genesi_out", 0UL );
     209           0 :     fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     210           0 :   }
     211             : 
     212             :   /**********************************************************************/
     213             :   /* More backtest->replay links in topo                                */
     214             :   /**********************************************************************/
     215             : 
     216             :   /* The tower tile is replaced by the backtest tile for the tower to
     217             :      replay link.  The backtest tile simply sends monotonically
     218             :      increasing rooted slot numbers to the replay tile, once after each
     219             :      "replayed a full slot" notification received from the replay tile.
     220             :      This allows the replay tile to advance its watermark, and publish
     221             :      various data structures.  This is an oversimplified barebones mock
     222             :      of the tower tile. */
     223           0 :   fd_topob_wksp( topo, "tower_out" );
     224           0 :   fd_topob_link( topo, "tower_out", "tower_out", 1024UL, sizeof(fd_tower_slot_done_t), 1UL );
     225           0 :   fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     226           0 :   fd_topob_tile_out( topo, "backt", 0UL, "tower_out", 0UL );
     227             : 
     228             :   /**********************************************************************/
     229             :   /* Setup replay->stake/send/poh links in topo w/o consumers         */
     230             :   /**********************************************************************/
     231           0 :   fd_topob_wksp( topo, "replay_epoch"    );
     232           0 :   fd_topob_link( topo, "replay_epoch", "replay_epoch", 128UL, FD_EPOCH_OUT_MTU, 1UL );
     233           0 :   fd_topob_tile_out( topo, "replay", 0UL, "replay_epoch",   0UL );
     234           0 :   topo->links[ replay_tile->out_link_id[ fd_topo_find_tile_out_link( topo, replay_tile, "replay_epoch",   0 ) ] ].permit_no_consumers = 1;
     235             : 
     236             :   /**********************************************************************/
     237             :   /* Setup replay->backtest link (replay_notif) in topo                 */
     238             :   /**********************************************************************/
     239             : 
     240           0 :   fd_topob_wksp( topo, "replay_out" );
     241           0 :   fd_topob_link( topo, "replay_out", "replay_out", 8192UL, sizeof( fd_replay_message_t ), 1UL );
     242           0 :   fd_topob_tile_out( topo, "replay", 0UL, "replay_out", 0UL );
     243           0 :   fd_topob_tile_in ( topo, "backt", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     244           0 :   if( FD_LIKELY( !disable_snap_loader ) ) {
     245           0 :     fd_topob_tile_in ( topo, "backt", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     246           0 :   } else {
     247           0 :     fd_topob_tile_in ( topo, "backt", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     248           0 :   }
     249             : 
     250             :   /**********************************************************************/
     251             :   /* Setup replay->exec link in topo                                    */
     252             :   /**********************************************************************/
     253           0 :   fd_topob_wksp( topo, "replay_execrp" );
     254           0 :   fd_topob_link( topo, "replay_execrp", "replay_execrp", 16384UL, 2240UL, 1UL );
     255           0 :   fd_topob_tile_out( topo, "replay", 0UL, "replay_execrp", 0UL );
     256           0 :   for( ulong i=0UL; i<execrp_tile_cnt; i++ ) {
     257           0 :     fd_topob_tile_in( topo, "execrp", i, "metric_in", "replay_execrp", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     258           0 :   }
     259             : 
     260             :   /**********************************************************************/
     261             :   /* Setup exec->replay links in topo, to send solcap account updates
     262             :      so that they are serialized, and to notify replay tile that a txn
     263             :      has been finalized by the exec tile. */
     264             :   /**********************************************************************/
     265           0 :   fd_topob_wksp( topo, "execrp_replay" );
     266             : 
     267           0 :   FOR(execrp_tile_cnt) fd_topob_link( topo, "execrp_replay", "execrp_replay", 16384UL, sizeof(fd_execrp_task_done_msg_t), 1UL );
     268             : 
     269           0 :   FOR(execrp_tile_cnt) fd_topob_tile_out( topo, "execrp", i, "execrp_replay", i );
     270           0 :   FOR(execrp_tile_cnt) fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "execrp_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     271             : 
     272             :   /**********************************************************************/
     273             :   /* Setup the shared objs used by replay and exec tiles                */
     274             :   /**********************************************************************/
     275             : 
     276           0 :   if( FD_UNLIKELY( solcap_enabled ) ) {
     277             :     /* 32 sections of SOLCAP_WRITE_ACCOUNT_DATA_MTU bytes each ≈ 4MB.
     278             :        This is done to ideally avoid cache thrashing and allow for all
     279             :        the links to sit on L3 cache. */
     280           0 :     fd_topob_link( topo, "cap_repl", "solcap", 32UL, SOLCAP_WRITE_ACCOUNT_DATA_MTU, 1UL );
     281           0 :     fd_topob_tile_out( topo, "replay", 0UL, "cap_repl", 0UL );
     282           0 :     fd_topob_tile_in( topo, "solcap", 0UL, "metric_in", "cap_repl", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     283           0 :     FOR(execrp_tile_cnt) fd_topob_link( topo, "cap_execrp", "solcap", 32UL, SOLCAP_WRITE_ACCOUNT_DATA_MTU, 1UL );
     284           0 :     FOR(execrp_tile_cnt) fd_topob_tile_out( topo, "execrp", i, "cap_execrp", i );
     285           0 :     FOR(execrp_tile_cnt) fd_topob_tile_in( topo, "solcap", 0UL, "metric_in", "cap_execrp", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     286           0 :   }
     287             : 
     288           0 :   fd_topob_wksp( topo, "store" );
     289           0 :   ulong store_fec_data_max = fd_ulong_if( config->firedancer.development.fixed_fec_sets, 31840UL, 63985UL );
     290           0 :   fd_topo_obj_t * store_obj = setup_topo_store( topo, "store", config->firedancer.runtime.max_live_slots * FD_SHRED_BLK_MAX, 1, store_fec_data_max );
     291           0 :   fd_topob_tile_uses( topo, backt_tile, store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     292           0 :   fd_topob_tile_uses( topo, replay_tile, store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     293           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, store_obj->id, "store" ) );
     294             : 
     295           0 :   fd_topob_wksp( topo, "banks" );
     296           0 :   fd_topo_obj_t * banks_obj = setup_topo_banks( topo, "banks", config->firedancer.runtime.max_live_slots, config->firedancer.runtime.max_fork_width, 0 );
     297           0 :   fd_topob_tile_uses( topo, replay_tile, banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     298           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 );
     299           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, banks_obj->id, "banks" ) );
     300             : 
     301           0 :   fd_topob_wksp( topo, "txncache"    );
     302           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 );
     303           0 :   fd_topob_tile_uses( topo, replay_tile, txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     304           0 :   if( FD_LIKELY( !disable_snap_loader ) ) fd_topob_tile_uses( topo, snapin_tile, txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     305           0 :   for( ulong i=0UL; i<execrp_tile_cnt; i++ ) {
     306           0 :     fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     307           0 :   }
     308           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
     309             : 
     310           0 :   if( snapin_tile ) fd_topob_tile_uses( topo, snapin_tile, accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     311           0 :   fd_topob_tile_uses( topo, accdb_tile,  accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     312           0 :   fd_topob_tile_uses( topo, replay_tile, accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     313           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 );
     314             : 
     315           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     316           0 :     fd_topo_tile_t * tile = &topo->tiles[ i ];
     317           0 :     fd_topo_configure_tile( tile, config );
     318             : 
     319           0 :     if( !strcmp( tile->name, "replay" ) ) {
     320           0 :       tile->replay.enable_features_cnt = config->tiles.replay.enable_features_cnt;
     321           0 :       for( ulong i = 0; i < tile->replay.enable_features_cnt; i++ ) {
     322           0 :         fd_cstr_ncpy( tile->replay.enable_features[i], config->tiles.replay.enable_features[i], sizeof(tile->replay.enable_features[i]) );
     323           0 :       }
     324           0 :     }
     325           0 :   }
     326             : 
     327             :   // fd_topob_auto_layout( topo, 0 );
     328           0 :   fd_topob_finish( topo, CALLBACKS );
     329           0 : }
     330             : 
     331             : static void
     332           0 : backtest_cmd_topo( config_t * config ) {
     333           0 :   backtest_topo( config );
     334           0 : }
     335             : 
     336             : extern configure_stage_t fd_cfg_stage_keys;
     337             : 
     338             : static args_t
     339           0 : configure_args( void ) {
     340           0 :   args_t args = {
     341           0 :     .configure.command = CONFIGURE_CMD_INIT,
     342           0 :   };
     343             : 
     344           0 :   ulong stage_idx = 0UL;
     345           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_hugetlbfs;
     346           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_snapshots;
     347           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_keys;
     348           0 :   args.configure.stages[ stage_idx++ ] = NULL;
     349             : 
     350           0 :   return args;
     351           0 : }
     352             : 
     353             : void
     354             : backtest_cmd_perm( args_t *         args FD_PARAM_UNUSED,
     355             :                    fd_cap_chk_t *   chk,
     356           0 :                    config_t const * config ) {
     357           0 :   args_t c_args = configure_args();
     358           0 :   configure_cmd_perm( &c_args, chk, config );
     359           0 :   run_cmd_perm( NULL, chk, config );
     360           0 : }
     361             : 
     362             : static void
     363           0 : fixup_config( config_t * config ) {
     364             : 
     365             :   /* FIXME Unfortunately, the fdctl boot procedure constructs the
     366             :            topology before parsing command-line arguments.  So, here,
     367             :            we construct the topology again (a third time ... sigh). */
     368           0 :   backtest_topo( config );
     369           0 : }
     370             : 
     371             : static void
     372             : backtest_cmd_fn( args_t *   args,
     373           0 :                  config_t * config ) {
     374           0 :   fixup_config( config );
     375           0 :   args_t c_args = configure_args();
     376           0 :   configure_cmd_fn( &c_args, config );
     377             : 
     378           0 :   initialize_workspaces( config );
     379           0 :   initialize_stacks( config );
     380           0 :   initialize_accdb_fd( config );
     381             : 
     382           0 :   fd_topo_join_workspaces( &config->topo, FD_SHMEM_JOIN_MODE_READ_WRITE, FD_TOPO_CORE_DUMP_LEVEL_DISABLED );
     383           0 :   fd_topo_fill( &config->topo );
     384             : 
     385           0 :   args_t watch_args;
     386           0 :   int pipefd[2];
     387           0 :   if( !args->backtest.no_watch ) {
     388           0 :     if( FD_UNLIKELY( pipe2( pipefd, O_NONBLOCK ) ) ) FD_LOG_ERR(( "pipe2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     389             : 
     390           0 :     watch_args.watch.drain_output_fd = pipefd[0];
     391           0 :     if( FD_UNLIKELY( -1==dup2( pipefd[ 1 ], STDERR_FILENO ) ) ) FD_LOG_ERR(( "dup2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     392           0 :     if( FD_UNLIKELY( -1==close( pipefd[1] ) ) ) FD_LOG_ERR(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     393           0 :   }
     394             : 
     395           0 :   fd_topo_run_single_process( &config->topo, 2, config->uid, config->gid, fdctl_tile_run );
     396           0 :   if( args->backtest.no_watch ) {
     397           0 :     for(;;) pause();
     398           0 :   } else {
     399           0 :     watch_cmd_fn( &watch_args, config );
     400           0 :   }
     401           0 : }
     402             : 
     403             : action_t fd_action_backtest = {
     404             :   .name        = "backtest",
     405             :   .args        = backtest_cmd_args,
     406             :   .fn          = backtest_cmd_fn,
     407             :   .perm        = backtest_cmd_perm,
     408             :   .topo        = backtest_cmd_topo,
     409             :   .description = "Replay a ledger offline through the replay tile with mocked consensus",
     410             : };

Generated by: LCOV version 1.14