LCOV - code coverage report
Current view: top level - app/fdctl - topology.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 303 0.0 %
Date: 2026-09-17 04:28:31 Functions: 0 2 0.0 %

          Line data    Source code
       1             : #include "../shared/fd_config.h"
       2             : 
       3             : #include "../../disco/net/fd_net_tile.h"
       4             : #include "../../disco/quic/fd_tpu.h"
       5             : #include "../../disco/tiles.h"
       6             : #include "../../disco/topo/fd_topob.h"
       7             : #include "../../disco/topo/fd_cpu_topo.h"
       8             : #include "../../disco/bundle/fd_bundle_tile.h"
       9             : #include "../../util/pod/fd_pod_format.h"
      10             : #include "../../util/net/fd_ip4.h"
      11             : 
      12             : extern fd_topo_obj_callbacks_t * CALLBACKS[];
      13             : 
      14             : static void
      15           0 : parse_ip_port( const char * name, const char * ip_port, fd_topo_ip_port_t *parsed_ip_port) {
      16           0 :   char buf[ sizeof( "255.255.255.255:65536" ) ];
      17           0 :   memcpy( buf, ip_port, sizeof( buf ) );
      18           0 :   char *ip_end = strchr( buf, ':' );
      19           0 :   if( FD_UNLIKELY( !ip_end ) )
      20           0 :     FD_LOG_ERR(( "[%s] must in the form ip:port", name ));
      21           0 :   *ip_end = '\0';
      22             : 
      23           0 :   if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( buf, &( parsed_ip_port->ip ) ) ) ) {
      24           0 :     FD_LOG_ERR(( "could not parse IP %s in [%s]", buf, name ));
      25           0 :   }
      26             : 
      27           0 :   parsed_ip_port->port = fd_cstr_to_ushort( ip_end+1 );
      28           0 :   if( FD_UNLIKELY( !parsed_ip_port->port ) )
      29           0 :     FD_LOG_ERR(( "could not parse port %s in [%s]", ip_end+1, name ));
      30           0 : }
      31             : 
      32             : void
      33             : fd_topo_configure_tile( fd_topo_tile_t * tile,
      34             :                         fd_config_t *    config );
      35             : 
      36             : void
      37           0 : fd_topo_initialize( config_t * config ) {
      38           0 :   ulong net_tile_cnt    = config->layout.net_tile_count;
      39           0 :   ulong quic_tile_cnt   = config->layout.quic_tile_count;
      40           0 :   ulong verify_tile_cnt = config->layout.verify_tile_count;
      41           0 :   ulong resolh_tile_cnt = config->frankendancer.layout.resolh_tile_count;
      42           0 :   ulong bank_tile_cnt   = config->frankendancer.layout.bank_tile_count;
      43           0 :   ulong shred_tile_cnt  = config->layout.shred_tile_count;
      44           0 :   fd_topo_t * topo = { fd_topob_new( &config->topo, config->name ) };
      45           0 :   topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
      46           0 :   topo->gigantic_page_threshold = config->hugetlbfs.gigantic_page_threshold_mib << 20;
      47             : 
      48             :   /*             topo, name */
      49           0 :   fd_topob_wksp( topo, "metric_in"    );
      50           0 :   fd_topob_wksp( topo, "net_quic"     );
      51           0 :   fd_topob_wksp( topo, "net_shred"    );
      52           0 :   fd_topob_wksp( topo, "quic_verify"  );
      53           0 :   fd_topob_wksp( topo, "verify_dedup" );
      54           0 :   fd_topob_wksp( topo, "dedup_resolh" );
      55           0 :   fd_topob_wksp( topo, "resolh_pack"  );
      56           0 :   fd_topob_wksp( topo, "pack_bank"    );
      57           0 :   fd_topob_wksp( topo, "pack_pohh"    );
      58           0 :   fd_topob_wksp( topo, "bank_pack"    );
      59           0 :   fd_topob_wksp( topo, "bank_pohh"    );
      60           0 :   fd_topob_wksp( topo, "bank_busy"    );
      61           0 :   fd_topob_wksp( topo, "pohh_shred"   );
      62           0 :   fd_topob_wksp( topo, "gossip_dedup" );
      63           0 :   fd_topob_wksp( topo, "shred_store"  );
      64           0 :   fd_topob_wksp( topo, "stake_out"    );
      65           0 :   fd_topob_wksp( topo, "executed_txn" );
      66             : 
      67           0 :   fd_topob_wksp( topo, "shred_sign"   );
      68           0 :   fd_topob_wksp( topo, "sign_shred"   );
      69             : 
      70           0 :   fd_topob_wksp( topo, "quic"         );
      71           0 :   fd_topob_wksp( topo, "verify"       );
      72           0 :   fd_topob_wksp( topo, "dedup"        );
      73           0 :   fd_topob_wksp( topo, "resolh"       );
      74           0 :   fd_topob_wksp( topo, "pack"         );
      75           0 :   fd_topob_wksp( topo, "bank"         );
      76           0 :   fd_topob_wksp( topo, "pohh"         );
      77           0 :   fd_topob_wksp( topo, "shred"        );
      78           0 :   fd_topob_wksp( topo, "store"        );
      79           0 :   fd_topob_wksp( topo, "sign"         )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_NEVER;
      80           0 :   fd_topob_wksp( topo, "metric"       );
      81           0 :   fd_topob_wksp( topo, "diag"         );
      82             : 
      83           0 :   #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
      84             : 
      85             :   /*                                  topo, link_name,      wksp_name,      depth,                                    mtu,                    burst */
      86           0 :   FOR(quic_tile_cnt)   fd_topob_link( topo, "quic_net",     "net_quic",     config->net.ingress_buffer_size,          FD_NET_MTU,             1UL );
      87           0 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "shred_net",    "net_shred",    32768UL,                                  FD_NET_MTU,             1UL );
      88           0 :   FOR(quic_tile_cnt)   fd_topob_link( topo, "quic_verify",  "quic_verify",  config->tiles.verify.receive_buffer_size, sizeof(fd_tpu_msg_t),   config->tiles.quic.txn_reassembly_count );
      89           0 :   FOR(verify_tile_cnt) fd_topob_link( topo, "verify_dedup", "verify_dedup", config->tiles.verify.receive_buffer_size, FD_TPU_PARSED_MTU,      1UL );
      90           0 :   /**/                 fd_topob_link( topo, "gossip_dedup", "gossip_dedup", 2048UL,                                   FD_TPU_RAW_MTU,         1UL );
      91             :   /* dedup_resolh is large currently because pack can encounter stalls when running at very high throughput rates that would
      92             :      otherwise cause drops. */
      93           0 :   /**/                 fd_topob_link( topo, "dedup_resolh", "dedup_resolh", 65536UL,                                  FD_TPU_PARSED_MTU,      1UL );
      94           0 :   FOR(resolh_tile_cnt) fd_topob_link( topo, "resolh_pack",  "resolh_pack",  65536UL,                                  FD_TPU_RESOLVED_MTU,    1UL );
      95           0 :   /**/                 fd_topob_link( topo, "stake_out",    "stake_out",    128UL,                                    FD_STAKE_OUT_MTU,       1UL );
      96           0 :   FOR(bank_tile_cnt)   fd_topob_link( topo, "pack_bank",    "pack_bank",    256UL,                                    USHORT_MAX,             1UL );
      97           0 :   /**/                 fd_topob_link( topo, "pack_pohh",    "pack_pohh",    65536UL,                                  sizeof(fd_done_packing_t), 1UL );
      98           0 :   FOR(bank_tile_cnt)   fd_topob_link( topo, "bank_pohh",    "bank_pohh",    16384UL,                                  USHORT_MAX,             1UL );
      99           0 :   FOR(bank_tile_cnt)   fd_topob_link( topo, "bank_pack",    "bank_pack",    16384UL,                                  USHORT_MAX,             3UL );
     100           0 :   /**/                 fd_topob_link( topo, "pohh_pack",    "bank_pohh",    128UL,                                    sizeof(fd_became_leader_t), 1UL );
     101           0 :   /**/                 fd_topob_link( topo, "pohh_shred",   "pohh_shred",   16384UL,                                  USHORT_MAX,             2UL );
     102           0 :   /**/                 fd_topob_link( topo, "crds_shred",   "pohh_shred",   128UL,                                    8UL  + 108000UL * 46UL,  1UL );
     103           0 :   /**/                 fd_topob_link( topo, "replay_resol", "bank_pohh",    128UL,                                    sizeof(fd_completed_bank_t), 1UL );
     104           0 :   /**/                 fd_topob_link( topo, "executed_txn", "executed_txn", 16384UL,                                  64UL, 1UL );
     105             :   /* See long comment in fd_shred.c for an explanation about the size of this dcache. */
     106           0 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "shred_store",  "shred_store",  65536UL,                                  4UL*FD_SHRED_STORE_MTU, 4UL+config->tiles.shred.max_pending_shred_sets );
     107             : 
     108           0 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "shred_sign",   "shred_sign",   128UL,                                    32UL,                   1UL );
     109           0 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "sign_shred",   "sign_shred",   128UL,                                    64UL,                   1UL );
     110             : 
     111           0 :   ushort parsed_tile_to_cpu[ FD_TILE_MAX ];
     112             :   /* Unassigned tiles will be floating, unless auto topology is enabled. */
     113           0 :   for( ulong i=0UL; i<FD_TILE_MAX; i++ ) parsed_tile_to_cpu[ i ] = USHORT_MAX;
     114             : 
     115           0 :   int is_auto_affinity = !strcmp( config->layout.affinity, "auto" );
     116           0 :   int is_agave_auto_affinity = !strcmp( config->frankendancer.layout.agave_affinity, "auto" );
     117             : 
     118           0 :   if( FD_UNLIKELY( is_auto_affinity != is_agave_auto_affinity ) ) {
     119           0 :     FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.affinity] and [layout.agave_affinity] must both be set to 'auto' or both be set to a specific CPU affinity string." ));
     120           0 :   }
     121             : 
     122           0 :   fd_topo_cpus_t cpus[1];
     123           0 :   fd_topo_cpus_init( cpus );
     124             : 
     125           0 :   ulong affinity_tile_cnt = 0UL;
     126           0 :   if( FD_LIKELY( !is_auto_affinity ) ) affinity_tile_cnt = fd_topob_parse_affinity_cstr( config->layout.affinity, parsed_tile_to_cpu, 0, 1 );
     127             : 
     128           0 :   ulong tile_to_cpu[ FD_TILE_MAX ] = {0};
     129           0 :   for( ulong i=0UL; i<affinity_tile_cnt; i++ ) {
     130           0 :     ushort cpu_idx = (ushort)( parsed_tile_to_cpu[ i ] & ~FD_TOPOB_CPU_SHARED );
     131           0 :     if( FD_UNLIKELY( parsed_tile_to_cpu[ i ]!=USHORT_MAX && cpu_idx>=cpus->cpu_cnt ) )
     132           0 :       FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.affinity] specifies a CPU index of %hu, but the system "
     133           0 :                    "only has %lu CPUs. You should either change the CPU allocations in the affinity string, or increase the number of CPUs "
     134           0 :                    "in the system.",
     135           0 :                    cpu_idx, cpus->cpu_cnt ));
     136           0 :     tile_to_cpu[ i ] = fd_ulong_if( parsed_tile_to_cpu[ i ]==USHORT_MAX, ULONG_MAX, (ulong)parsed_tile_to_cpu[ i ] );
     137           0 :   }
     138             : 
     139           0 :   int xsk_core_dump = config->development.core_dump_level >= FD_TOPO_CORE_DUMP_LEVEL_REGULAR ? 1 : 0;
     140           0 :   fd_topos_net_tiles( topo, config->layout.net_tile_count, &config->net, config->tiles.netlink.max_routes, config->tiles.netlink.max_peer_routes, config->tiles.netlink.max_neighbors, xsk_core_dump, tile_to_cpu );
     141             : 
     142           0 :   FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_quic",  i, config->net.ingress_buffer_size );
     143           0 :   FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_shred", i, config->net.ingress_buffer_size );
     144             : 
     145             :   /*                                  topo, tile_name, tile_wksp, metrics_wksp, cpu_idx,                       is_agave, uses_id_keyswitch, uses_av_keyswitch, is_waker_client */
     146           0 :   FOR(quic_tile_cnt)   fd_topob_tile( topo, "quic",    "quic",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        0,                 0,                 0 );
     147           0 :   FOR(verify_tile_cnt) fd_topob_tile( topo, "verify",  "verify",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        0,                 0,                 0 );
     148           0 :   /**/                 fd_topob_tile( topo, "dedup",   "dedup",   "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        0,                 0,                 0 );
     149           0 :   FOR(resolh_tile_cnt) fd_topob_tile( topo, "resolh",  "resolh",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 1,        0,                 0,                 0 );
     150           0 :   /**/                 fd_topob_tile( topo, "pack",    "pack",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        config->tiles.bundle.enabled, 0, 0 );
     151           0 :   FOR(bank_tile_cnt)   fd_topob_tile( topo, "bank",    "bank",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 1,        0,                 0,                 0 );
     152           0 :   /**/                 fd_topob_tile( topo, "pohh",    "pohh",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 1,        1,                 0,                 0 );
     153           0 :   FOR(shred_tile_cnt)  fd_topob_tile( topo, "shred",   "shred",   "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        1,                 0,                 0 );
     154           0 :   /**/                 fd_topob_tile( topo, "store",   "store",   "metric_in",  tile_to_cpu[ topo->tile_cnt ], 1,        0,                 0,                 0 );
     155           0 :   /**/                 fd_topob_tile( topo, "sign",    "sign",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        1,                 0,                 0 );
     156           0 :   /**/                 fd_topob_tile( topo, "metric",  "metric",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        0,                 0,                 1 );
     157           0 :   /**/                 fd_topob_tile( topo, "diag",    "diag",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0,        0,                 0,                 0 );
     158             : 
     159             :   /*                                      topo, tile_name, tile_kind_id, fseq_wksp,   link_name,      link_kind_id, reliable,            polled */
     160           0 :   for( ulong j=0UL; j<quic_tile_cnt; j++ )
     161           0 :                    fd_topos_tile_in_net(  topo,                          "metric_in", "quic_net",     j,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
     162           0 :   for( ulong j=0UL; j<shred_tile_cnt; j++ )
     163           0 :                    fd_topos_tile_in_net(  topo,                          "metric_in", "shred_net",    j,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
     164             : 
     165           0 :   FOR(quic_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
     166           0 :                        fd_topob_tile_in(  topo, "quic",    i,            "metric_in", "net_quic",     j,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
     167           0 :   FOR(quic_tile_cnt)   fd_topob_tile_out( topo, "quic",    i,                         "quic_verify",  i                                                  );
     168           0 :   FOR(quic_tile_cnt)   fd_topob_tile_out( topo, "quic",    i,                         "quic_net",     i                                                  );
     169             :   /* All verify tiles read from all QUIC tiles, packets are round robin. */
     170           0 :   FOR(verify_tile_cnt) for( ulong j=0UL; j<quic_tile_cnt; j++ )
     171           0 :                        fd_topob_tile_in(  topo, "verify",  i,            "metric_in", "quic_verify",  j,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers, verify tiles may be overrun */
     172           0 :   FOR(verify_tile_cnt) fd_topob_tile_out( topo, "verify",  i,                         "verify_dedup", i                                                  );
     173             :   /* Declare the single gossip link before the variable length verify-dedup links so we could have a compile-time index to the gossip link. */
     174           0 :   /**/                 fd_topob_tile_in(  topo, "dedup",   0UL,          "metric_in", "gossip_dedup", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     175           0 :   FOR(verify_tile_cnt) fd_topob_tile_in(  topo, "dedup",   0UL,          "metric_in", "verify_dedup", i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     176           0 :   /**/                 fd_topob_tile_in(  topo, "dedup",   0UL,          "metric_in", "executed_txn", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     177           0 :   /**/                 fd_topob_tile_out( topo, "dedup",   0UL,                       "dedup_resolh", 0UL                                                );
     178           0 :   FOR(resolh_tile_cnt) fd_topob_tile_in(  topo, "resolh",  i,            "metric_in", "dedup_resolh", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     179           0 :   FOR(resolh_tile_cnt) fd_topob_tile_in(  topo, "resolh",  i,            "metric_in", "replay_resol", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     180           0 :   FOR(resolh_tile_cnt) fd_topob_tile_out( topo, "resolh",  i,                         "resolh_pack",  i                                                  );
     181           0 :   FOR(resolh_tile_cnt) fd_topob_tile_in(  topo, "pack",    0UL,          "metric_in", "resolh_pack",  i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     182             :   /* The PoH to pack link is reliable, and must be.  The fragments going
     183             :      across here are "you became leader" which pack must respond to
     184             :      by publishing microblocks, otherwise the leader TPU will hang
     185             :      forever.
     186             : 
     187             :      It's marked as unreliable since otherwise we have a reliable credit
     188             :      loop which will also starve the pack tile.  This is OK because we
     189             :      will never send more than one leader message until the pack tile
     190             :      must acknowledge it with a packing done frag, so there will be at
     191             :      most one in flight at any time. */
     192           0 :   /**/                 fd_topob_tile_in(  topo, "pack",   0UL,           "metric_in", "pohh_pack",    0UL,          FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     193           0 :   /**/                 fd_topob_tile_in(  topo, "pack",   0UL,           "metric_in", "executed_txn", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     194           0 :   FOR(bank_tile_cnt)   fd_topob_tile_out( topo, "pack",   0UL,                        "pack_bank",    i                                                  );
     195           0 :   /**/                 fd_topob_tile_out( topo, "pack",   0UL,                        "pack_pohh",    0UL                                                );
     196           0 :   FOR(bank_tile_cnt)   fd_topob_tile_in(  topo, "bank",   i,             "metric_in", "pack_bank",    i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     197           0 :   FOR(bank_tile_cnt)   fd_topob_tile_out( topo, "bank",   i,                          "bank_pohh",    i                                                  );
     198           0 :   FOR(bank_tile_cnt)   fd_topob_tile_out( topo, "bank",   i,                          "bank_pack",    i                                                  );
     199           0 :   FOR(bank_tile_cnt)   fd_topob_tile_in(  topo, "pohh",    0UL,          "metric_in", "bank_pohh",    i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     200           0 :   if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) )
     201           0 :     FOR(bank_tile_cnt) fd_topob_tile_in(  topo, "pack",   0UL,           "metric_in", "bank_pack",    i,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     202           0 :   /**/                 fd_topob_tile_in(  topo, "pohh",   0UL,           "metric_in", "stake_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     203           0 :   /**/                 fd_topob_tile_in(  topo, "pohh",   0UL,           "metric_in", "pack_pohh",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     204           0 :   /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "pohh_shred",   0UL                                                );
     205           0 :   /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "pohh_pack",    0UL                                                );
     206           0 :   FOR(shred_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
     207           0 :                        fd_topob_tile_in(  topo, "shred",  i,             "metric_in", "net_shred",    j,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
     208           0 :   FOR(shred_tile_cnt)  fd_topob_tile_in(  topo, "shred",  i,             "metric_in", "pohh_shred",   0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     209           0 :   FOR(shred_tile_cnt)  fd_topob_tile_in(  topo, "shred",  i,             "metric_in", "stake_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     210           0 :   FOR(shred_tile_cnt)  fd_topob_tile_in(  topo, "shred",  i,             "metric_in", "crds_shred",   0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     211           0 :   FOR(shred_tile_cnt)  fd_topob_tile_in(  topo, "shred",  i,             "metric_in", "replay_resol", 0UL,          FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     212           0 :   FOR(shred_tile_cnt)  fd_topob_tile_out( topo, "shred",  i,                          "shred_store",  i                                                  );
     213           0 :   FOR(shred_tile_cnt)  fd_topob_tile_out( topo, "shred",  i,                          "shred_net",    i                                                  );
     214           0 :   FOR(shred_tile_cnt)  fd_topob_tile_in(  topo, "store",  0UL,           "metric_in", "shred_store",  i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     215             : 
     216             :   /* Sign links don't need to be reliable because they are synchronous,
     217             :      so there's at most one fragment in flight at a time anyway.  The
     218             :      sign links are also not polled by fd_stem, instead the tiles will
     219             :      read the sign responses out of band in a dedicated spin loop. */
     220             : 
     221           0 :   for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
     222           0 :     /**/               fd_topob_tile_in(  topo, "sign",   0UL,           "metric_in", "shred_sign",     i,          FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED   );
     223           0 :     /**/               fd_topob_tile_out( topo, "shred",  i,                          "shred_sign",     i                                                  );
     224           0 :     /**/               fd_topob_tile_in(  topo, "shred",  i,             "metric_in", "sign_shred",     i,          FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
     225           0 :     /**/               fd_topob_tile_out( topo, "sign",   0UL,                        "sign_shred",     i                                                  );
     226           0 :   }
     227             : 
     228             :   /* PoH tile represents the Agave address space, so it's
     229             :      responsible for publishing Agave provided data to
     230             :      these links. */
     231             :   /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "gossip_dedup", 0UL                                                  );
     232           0 :   /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "stake_out",    0UL                                                  );
     233           0 :   /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "crds_shred",   0UL                                                  );
     234           0 :   /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "replay_resol", 0UL                                                  );
     235           0 :   /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "executed_txn", 0UL                                                  );
     236             : 
     237             :   /* For now the only plugin consumer is the GUI */
     238           0 :   int plugins_enabled = config->tiles.gui.enabled;
     239           0 :   if( FD_LIKELY( plugins_enabled ) ) {
     240           0 :     fd_topob_wksp( topo, "plugin_in"    );
     241           0 :     fd_topob_wksp( topo, "plugin_out"   );
     242           0 :     fd_topob_wksp( topo, "plugin"       );
     243             : 
     244             :     /* The size of plugin_out is the max of the message size from
     245             :        gossip_plugi and stake_out. */
     246           0 :     ulong plugin_out_mtu = fd_ulong_max( FD_STAKE_OUT_MTU, 8UL+108000UL*(60UL+12UL*6UL) );
     247           0 :     /**/                 fd_topob_link( topo, "plugin_out",   "plugin_out",   128UL,                                    plugin_out_mtu,               1UL  );
     248           0 :     /**/                 fd_topob_link( topo, "replay_plugi", "plugin_in",    128UL,                                    4098*8UL,                     1UL  );
     249           0 :     /**/                 fd_topob_link( topo, "gossip_plugi", "plugin_in",    128UL,                                    8UL+108000UL*(60UL+12UL*6UL), 1UL  );
     250           0 :     /**/                 fd_topob_link( topo, "pohh_plugin",  "plugin_in",    128UL,                                    16UL,                         1UL  );
     251           0 :     /**/                 fd_topob_link( topo, "startp_plugi", "plugin_in",    128UL,                                    56UL,                         1UL  );
     252           0 :     /**/                 fd_topob_link( topo, "votel_plugin", "plugin_in",    128UL,                                    8UL,                          1UL  );
     253           0 :     /**/                 fd_topob_link( topo, "valcfg_plugi", "plugin_in",    128UL,                                    608UL,                        1UL  );
     254             : 
     255             :     /**/                 fd_topob_tile( topo, "plugin",  "plugin",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0, 0, 0, 0 );
     256             : 
     257             :     /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "replay_plugi", 0UL                                                );
     258           0 :     /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "gossip_plugi", 0UL                                                );
     259           0 :     /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "pohh_plugin",  0UL                                                );
     260           0 :     /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "startp_plugi", 0UL                                                );
     261           0 :     /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "votel_plugin", 0UL                                                );
     262           0 :     /**/                 fd_topob_tile_out( topo, "plugin", 0UL,                        "plugin_out",   0UL                                                );
     263           0 :     /**/                 fd_topob_tile_out( topo, "pohh",   0UL,                        "valcfg_plugi", 0UL                                                );
     264             : 
     265           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "replay_plugi", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     266           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "gossip_plugi", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     267           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "stake_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     268           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "pohh_plugin",  0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     269           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "startp_plugi", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     270           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "votel_plugin", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     271           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "valcfg_plugi", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     272           0 :   }
     273             : 
     274           0 :   if( FD_LIKELY( config->tiles.gui.enabled ) ) {
     275           0 :     fd_topob_wksp( topo, "guih"         );
     276           0 :     /**/                 fd_topob_tile( topo, "guih",    "guih",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0, 1, 0, 1 );
     277           0 :     /**/                 fd_topob_tile_in(  topo, "guih",   0UL,           "metric_in", "plugin_out",   0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     278           0 :     /**/                 fd_topob_tile_in(  topo, "guih",   0UL,           "metric_in", "pohh_pack",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     279           0 :     FOR(bank_tile_cnt)   fd_topob_tile_in(  topo, "guih",   0UL,           "metric_in", "pack_bank",    i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     280           0 :     /**/                 fd_topob_tile_in(  topo, "guih",   0UL,           "metric_in", "pack_pohh",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     281           0 :     FOR(bank_tile_cnt)   fd_topob_tile_in(  topo, "guih",   0UL,           "metric_in", "bank_pohh",    i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     282           0 :   }
     283             : 
     284           0 :   if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
     285           0 :     fd_topob_wksp( topo, "bundle_verif" );
     286           0 :     fd_topob_wksp( topo, "bundle_sign"  );
     287           0 :     fd_topob_wksp( topo, "sign_bundle"  );
     288           0 :     fd_topob_wksp( topo, "pack_sign"    );
     289           0 :     fd_topob_wksp( topo, "sign_pack"    );
     290           0 :     fd_topob_wksp( topo, "bundle"       );
     291             : 
     292           0 :     /**/                 fd_topob_link( topo, "bundle_verif", "bundle_verif", config->tiles.verify.receive_buffer_size, FD_TPU_PARSED_MTU,         1UL );
     293           0 :     /**/                 fd_topob_link( topo, "bundle_sign",  "bundle_sign",  65536UL,                                  9UL,                       1UL );
     294           0 :     /**/                 fd_topob_link( topo, "sign_bundle",  "sign_bundle",  128UL,                                    64UL,                      1UL );
     295           0 :     /**/                 fd_topob_link( topo, "pack_sign",    "pack_sign",    65536UL,                                  1232UL,                    1UL );
     296           0 :     /**/                 fd_topob_link( topo, "sign_pack",    "sign_pack",    128UL,                                    64UL,                      1UL );
     297             : 
     298             :     /**/                 fd_topob_tile( topo, "bundle",  "bundle",  "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 0, 1 );
     299             : 
     300             :     /**/                 fd_topob_tile_out( topo, "bundle", 0UL, "bundle_verif", 0UL );
     301           0 :     FOR(verify_tile_cnt) fd_topob_tile_in(  topo, "verify", i,             "metric_in", "bundle_verif",   0UL,        FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED   );
     302             : 
     303           0 :     /**/                 fd_topob_tile_in(  topo, "sign",   0UL,           "metric_in", "bundle_sign",    0UL,        FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED   );
     304           0 :     /**/                 fd_topob_tile_out( topo, "bundle", 0UL,                        "bundle_sign",    0UL                                                );
     305           0 :     /**/                 fd_topob_tile_in(  topo, "bundle", 0UL,           "metric_in", "sign_bundle",    0UL,        FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
     306           0 :     /**/                 fd_topob_tile_out( topo, "sign",   0UL,                        "sign_bundle",    0UL                                                );
     307             : 
     308           0 :     /**/                 fd_topob_tile_in(  topo, "sign",   0UL,           "metric_in", "pack_sign",      0UL,        FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED   );
     309           0 :     /**/                 fd_topob_tile_out( topo, "pack",   0UL,                        "pack_sign",      0UL                                                );
     310           0 :     /**/                 fd_topob_tile_in(  topo, "pack",   0UL,           "metric_in", "sign_pack",      0UL,        FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
     311           0 :     /**/                 fd_topob_tile_out( topo, "sign",   0UL,                        "sign_pack",      0UL                                                );
     312             : 
     313           0 :     if( config->tiles.gui.enabled ) { /* GUI is the only consumer of bundle_status */
     314           0 :       fd_topob_wksp( topo, "bundle_status" );
     315             :       /* bundle_status must be kind of deep, to prevent exhausting
     316             :          shared flow control credits when publishing many packets at
     317             :          once. */
     318           0 :       fd_topob_link( topo, "bundle_status", "bundle_status", 65536UL, sizeof(fd_bundle_block_engine_update_t), 1UL );
     319           0 :       fd_topob_tile_in( topo, "guih", 0UL, "metric_in", "bundle_status", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     320           0 :       fd_topob_tile_out( topo, "bundle", 0UL, "bundle_status", 0UL );
     321           0 :     }
     322           0 :   }
     323             : 
     324           0 :   if( FD_LIKELY( !is_auto_affinity ) ) {
     325           0 :     if( FD_UNLIKELY( affinity_tile_cnt<topo->tile_cnt ) )
     326           0 :       FD_LOG_ERR(( "The topology you are using has %lu tiles, but the CPU affinity specified in the config tile as [layout.affinity] only provides for %lu cores. "
     327           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 "
     328           0 :                    "the total tile count. You can reduce the tile count by decreasing individual tile counts in the [layout] section of the configuration file.",
     329           0 :                    topo->tile_cnt, affinity_tile_cnt ));
     330           0 :     if( FD_UNLIKELY( affinity_tile_cnt>topo->tile_cnt ) )
     331           0 :       FD_LOG_WARNING(( "The topology you are using has %lu tiles, but the CPU affinity specified in the config tile as [layout.affinity] provides for %lu cores. "
     332           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 "
     333           0 :                        "individual tile counts in the [layout] section of the configuration file.",
     334           0 :                        topo->tile_cnt, affinity_tile_cnt ));
     335             : 
     336           0 :     if( FD_LIKELY( strcmp( "", config->frankendancer.layout.agave_affinity ) ) ) {
     337           0 :       ushort agave_cpu[ FD_TILE_MAX ];
     338           0 :       ulong agave_cpu_cnt = fd_topob_parse_affinity_cstr( config->frankendancer.layout.agave_affinity, agave_cpu, 0, 0 );
     339             : 
     340           0 :       for( ulong i=0UL; i<agave_cpu_cnt; i++ ) {
     341           0 :         if( FD_UNLIKELY( agave_cpu[ i ]>=cpus->cpu_cnt ) )
     342           0 :           FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.agave_affinity] specifies a CPU index of %hu, but the system "
     343           0 :                        "only has %lu CPUs. You should either change the CPU allocations in the affinity string, or increase the number of CPUs "
     344           0 :                        "in the system.",
     345           0 :                        agave_cpu[ i ], cpus->cpu_cnt ));
     346             : 
     347           0 :         for( ulong j=0UL; j<topo->tile_cnt; j++ ) {
     348           0 :           fd_topo_tile_t * tile = &topo->tiles[ j ];
     349           0 :           if( tile->cpu_idx==agave_cpu[ i ] ) FD_LOG_WARNING(( "Tile `%s:%lu` is already assigned to CPU %hu, but the CPU is also assigned to Agave. "
     350           0 :                                                                "This may cause contention between the two tiles.", tile->name, tile->kind_id, agave_cpu[ i ] ));
     351           0 :         }
     352             : 
     353           0 :         if( FD_UNLIKELY( topo->agave_affinity_cnt>FD_TILE_MAX ) ) {
     354           0 :           FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.agave_affinity] specifies more CPUs than Firedancer can use. "
     355           0 :                         "You should reduce the number of CPUs in the affinity string." ));
     356           0 :         }
     357           0 :         topo->agave_affinity_cpu_idx[ topo->agave_affinity_cnt++ ] = agave_cpu[ i ];
     358           0 :       }
     359           0 :     }
     360           0 :   } else {
     361           0 :     ushort blocklist_cores[ FD_TILE_MAX ];
     362           0 :     topo->blocklist_cores_cnt = fd_topob_parse_affinity_cstr( config->layout.blocklist_cores, blocklist_cores, 0, 0 );
     363           0 :     if( FD_UNLIKELY( topo->blocklist_cores_cnt>FD_TILE_MAX ) ) {
     364           0 :       FD_LOG_ERR(( "The CPU string in the configuration file under [layout.blocklist_cores] specifies more CPUs than Firedancer can use. "
     365           0 :                     "You should reduce the number of CPUs in the excluded cores string." ));
     366           0 :     }
     367             : 
     368           0 :     for( ulong i=0UL; i<topo->blocklist_cores_cnt; i++ ) {
     369             :       /* Since we use fd_topob_parse_affinity_cstr() like for affinity, the user
     370             :          may input a string containing `f`. That's parsed correctly, but it's
     371             :          meaningless for blocklisted cores, so we reject it here.  */
     372           0 :       if( FD_UNLIKELY( blocklist_cores[ i ]==USHORT_MAX ) ) {
     373           0 :         FD_LOG_ERR(( "The CPU string in the configuration file under [layout.blocklist_cores] contains invalid values: `f`. "
     374           0 :                       "You should fix the excluded cores string." ));
     375           0 :       }
     376           0 :       topo->blocklist_cores_cpu_idx[ i ] = blocklist_cores[ i ];
     377           0 :     }
     378           0 :   }
     379             : 
     380             :   /* There is a special fseq that sits between the pack, bank, and poh
     381             :      tiles to indicate when the bank/poh tiles are done processing a
     382             :      microblock.  Pack uses this to determine when to "unlock" accounts
     383             :      that it marked as locked because they were being used. */
     384             : 
     385           0 :   for( ulong i=0UL; i<bank_tile_cnt; i++ ) {
     386           0 :     fd_topo_obj_t * busy_obj = fd_topob_obj( topo, "fseq", "bank_busy" );
     387             : 
     388           0 :     fd_topo_tile_t * pohh_tile = &topo->tiles[ fd_topo_find_tile( topo, "pohh", 0UL ) ];
     389           0 :     fd_topo_tile_t * pack_tile = &topo->tiles[ fd_topo_find_tile( topo, "pack", 0UL ) ];
     390           0 :     fd_topob_tile_uses( topo, pohh_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     391           0 :     fd_topob_tile_uses( topo, pack_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
     392           0 :     FD_TEST( fd_pod_insertf_ulong( topo->props, busy_obj->id, "execle_busy.%lu", i ) );
     393           0 :   }
     394             : 
     395             :   /* There's another special fseq that's used to communicate the shred
     396             :      version from the Agave boot path to the shred tile. */
     397           0 :   fd_topo_obj_t * pohh_shred_obj = fd_topob_obj( topo, "fseq", "pohh_shred" );
     398           0 :   fd_topo_tile_t * pohh_tile = &topo->tiles[ fd_topo_find_tile( topo, "pohh", 0UL ) ];
     399           0 :   fd_topob_tile_uses( topo, pohh_tile, pohh_shred_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     400           0 :   for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
     401           0 :     fd_topo_tile_t * shred_tile = &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ];
     402           0 :     fd_topob_tile_uses( topo, shred_tile, pohh_shred_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
     403           0 :   }
     404           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, pohh_shred_obj->id, "pohh_shred" ) );
     405             : 
     406           0 :   FOR(net_tile_cnt) fd_topos_net_tile_finish( topo, i );
     407             : 
     408           0 :   fd_topob_waker( topo );
     409             : 
     410           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     411           0 :     fd_topo_tile_t * tile = &topo->tiles[ i ];
     412           0 :     fd_topo_configure_tile( tile, config );
     413           0 :     if( FD_UNLIKELY( !strcmp( tile->name, "guih" ) ) ) tile->gui.tile_cnt = topo->tile_cnt;
     414           0 :   }
     415             : 
     416           0 :   if( FD_UNLIKELY( is_auto_affinity ) ) fd_topob_auto_layout( topo, 1 );
     417             : 
     418           0 :   fd_topob_finish( topo, CALLBACKS );
     419           0 :   config->topo = *topo;
     420           0 : }
     421             : 
     422             : void
     423             : fd_topo_configure_tile( fd_topo_tile_t * tile,
     424             :                         fd_config_t *    config ) {
     425             :   int plugins_enabled = config->tiles.gui.enabled;
     426             : 
     427             :   if( FD_UNLIKELY( !strcmp( tile->name, "net"  ) ||
     428             :                    !strcmp( tile->name, "sock" ) ||
     429             :                    !strcmp( tile->name, "mlx5" ) ) ) {
     430             : 
     431             :     tile->net.shred_listen_port              = config->tiles.shred.shred_listen_port;
     432             :     tile->net.quic_transaction_listen_port   = config->tiles.quic.quic_transaction_listen_port;
     433             :     tile->net.legacy_transaction_listen_port = config->tiles.quic.regular_transaction_listen_port;
     434             : 
     435             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "netlnk" ) ) ) {
     436             : 
     437             :     /* already configured */
     438             : 
     439             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "quic" ) ) ) {
     440             : 
     441             :     tile->quic.reasm_cnt                      = config->tiles.quic.txn_reassembly_count;
     442             :     tile->quic.out_depth                      = config->tiles.verify.receive_buffer_size;
     443             :     tile->quic.max_concurrent_connections     = config->tiles.quic.max_concurrent_connections;
     444             :     tile->quic.max_concurrent_handshakes      = config->tiles.quic.max_concurrent_handshakes;
     445             :     tile->quic.quic_transaction_listen_port   = config->tiles.quic.quic_transaction_listen_port;
     446             :     tile->quic.idle_timeout_millis            = config->tiles.quic.idle_timeout_millis;
     447             :     tile->quic.ack_delay_millis               = config->tiles.quic.ack_delay_millis;
     448             :     tile->quic.retry                          = config->tiles.quic.retry;
     449             :     fd_cstr_fini( fd_cstr_append_cstr_safe( fd_cstr_init( tile->quic.key_log_path ), config->tiles.quic.ssl_key_log_file, sizeof(tile->quic.key_log_path) ) );
     450             : 
     451             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "bundle" ) ) ) {
     452             :     fd_cstr_ncpy( tile->bundle.url, config->tiles.bundle.url, sizeof(tile->bundle.url) );
     453             :     tile->bundle.url_len = strnlen( tile->bundle.url, sizeof(tile->bundle.url)-1UL );
     454             :     fd_cstr_ncpy( tile->bundle.sni, config->tiles.bundle.tls_domain_name, sizeof(tile->bundle.sni) );
     455             :     tile->bundle.sni_len = strnlen( tile->bundle.sni, sizeof(tile->bundle.sni)-1UL );
     456             :     fd_cstr_ncpy( tile->bundle.identity_key_path, config->paths.identity_key, sizeof(tile->bundle.identity_key_path) );
     457             :     fd_cstr_ncpy( tile->bundle.key_log_path, config->development.bundle.ssl_key_log_file, sizeof(tile->bundle.key_log_path) );
     458             :     tile->bundle.buf_sz = config->development.bundle.buffer_size_kib<<10;
     459             :     tile->bundle.out_depth = config->tiles.verify.receive_buffer_size;
     460             :     tile->bundle.keepalive_interval_nanos = config->tiles.bundle.keepalive_interval_millis * (ulong)1e6;
     461             :     tile->bundle.tls_cert_verify = !!config->tiles.bundle.tls_cert_verify;
     462             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "verify" ) ) ) {
     463             :     tile->verify.tcache_depth = config->tiles.verify.signature_cache_size;
     464             : 
     465             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "dedup" ) ) ) {
     466             :     tile->dedup.tcache_depth = config->tiles.dedup.signature_cache_size;
     467             : 
     468             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "resolh" ) ) ) {
     469             : 
     470             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "pack" ) ) ) {
     471             :     tile->pack.max_pending_transactions      = config->tiles.pack.max_pending_transactions;
     472             :     tile->pack.execle_tile_count             = config->frankendancer.layout.bank_tile_count;
     473             :     tile->pack.max_cost_per_block            = config->limits.max_cost_per_block;
     474             :     tile->pack.max_shreds_per_block          = config->limits.max_shreds_per_block;
     475             :     tile->pack.bench_max_shreds_per_block    = config->development.bench.max_shreds_per_block;
     476             :     tile->pack.use_consumed_cus              = config->tiles.pack.use_consumed_cus;
     477             :     tile->pack.schedule_strategy             = config->tiles.pack.schedule_strategy_enum;
     478             :     tile->pack.acct_blocklist_cnt            = config->tiles.pack.account_blocklist_cnt;
     479             : 
     480             :     for( ulong i=0UL; i<tile->pack.acct_blocklist_cnt; i++ ) {
     481             :       if( FD_UNLIKELY( NULL==fd_base58_decode_32( config->tiles.pack.account_blocklist[i], tile->pack.acct_blocklist[i].uc ) ) ) {
     482             :         FD_LOG_ERR(( "could not parse account %s at index %lu in [tiles.pack.account_blocklist]", config->tiles.pack.account_blocklist[i], i ));
     483             :       }
     484             :     }
     485             : 
     486             :     if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
     487             : #define PARSE_BUNDLE_PUBKEY( _tile, f ) \
     488             :       if( FD_UNLIKELY( !fd_base58_decode_32( config->tiles.bundle.f, tile->_tile.bundle.f ) ) )  \
     489             :         FD_LOG_ERR(( "[tiles.bundle.enabled] set to true, but failed to parse [tiles.bundle."#f"] %s", config->tiles.bundle.f ));
     490             :       tile->pack.bundle.enabled = 1;
     491             :       PARSE_BUNDLE_PUBKEY( pack, tip_distribution_program_addr );
     492             :       PARSE_BUNDLE_PUBKEY( pack, tip_payment_program_addr      );
     493             :       PARSE_BUNDLE_PUBKEY( pack, tip_distribution_authority    );
     494             :       tile->pack.bundle.commission_bps = config->tiles.bundle.commission_bps;
     495             :       fd_cstr_ncpy( tile->pack.bundle.identity_key_path, config->paths.identity_key, sizeof(tile->pack.bundle.identity_key_path) );
     496             :       fd_cstr_ncpy( tile->pack.bundle.vote_account_path, config->paths.vote_account, sizeof(tile->pack.bundle.vote_account_path) );
     497             :     } else {
     498             :       fd_memset( &tile->pack.bundle, '\0', sizeof(tile->pack.bundle) );
     499             :     }
     500             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "bank" ) ) ) {
     501             : 
     502             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "pohh" ) ) ) {
     503             :     fd_cstr_ncpy( tile->pohh.identity_key_path, config->paths.identity_key, sizeof(tile->pohh.identity_key_path) );
     504             : 
     505             :     tile->pohh.plugins_enabled = plugins_enabled;
     506             :     tile->pohh.execle_cnt = config->frankendancer.layout.bank_tile_count;
     507             :     tile->pohh.lagged_consecutive_leader_start = config->tiles.pohh.lagged_consecutive_leader_start;
     508             : 
     509             :     if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
     510             :       tile->pohh.bundle.enabled = 1;
     511             :       PARSE_BUNDLE_PUBKEY( pohh, tip_distribution_program_addr );
     512             :       PARSE_BUNDLE_PUBKEY( pohh, tip_payment_program_addr      );
     513             :       fd_cstr_ncpy( tile->pohh.bundle.vote_account_path, config->paths.vote_account, sizeof(tile->pohh.bundle.vote_account_path) );
     514             : 
     515             :     } else {
     516             :       fd_memset( &tile->pohh.bundle, '\0', sizeof(tile->pohh.bundle) );
     517             :     }
     518             : 
     519             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "shred" ) ) ) {
     520             :     fd_cstr_ncpy( tile->shred.identity_key_path, config->paths.identity_key, sizeof(tile->shred.identity_key_path) );
     521             : 
     522             :     tile->shred.fec_exposure                  = config->topo.links[ tile->out_link_id[ 0 ] ].depth;
     523             :     tile->shred.fec_resolver_depth            = config->tiles.shred.max_pending_shred_sets;
     524             :     tile->shred.expected_shred_version        = config->consensus.expected_shred_version;
     525             :     tile->shred.shred_listen_port             = config->tiles.shred.shred_listen_port;
     526             :     tile->shred.max_shreds_per_block          = config->limits.max_shreds_per_block;
     527             :     tile->shred.bench_max_shreds_per_block    = config->development.bench.max_shreds_per_block;
     528             :     for( ulong i=0UL; i<config->tiles.shred.additional_shred_destinations_retransmit_cnt; i++ ) {
     529             :       parse_ip_port( "tiles.shred.additional_shred_destinations_retransmit",
     530             :                       config->tiles.shred.additional_shred_destinations_retransmit[ i ],
     531             :                       &tile->shred.adtl_dests_retransmit[ i ] );
     532             :     }
     533             :     tile->shred.adtl_dests_retransmit_cnt = config->tiles.shred.additional_shred_destinations_retransmit_cnt;
     534             :     for( ulong i=0UL; i<config->tiles.shred.additional_shred_destinations_leader_cnt; i++ ) {
     535             :       parse_ip_port( "tiles.shred.additional_shred_destinations_leader",
     536             :                       config->tiles.shred.additional_shred_destinations_leader[ i ],
     537             :                       &tile->shred.adtl_dests_leader[ i ] );
     538             :     }
     539             :     tile->shred.adtl_dests_leader_cnt = config->tiles.shred.additional_shred_destinations_leader_cnt;
     540             : 
     541             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "store" ) ) ) {
     542             :     tile->store.disable_blockstore_from_slot = config->development.bench.disable_blockstore_from_slot;
     543             : 
     544             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "sign" ) ) ) {
     545             :     fd_cstr_ncpy( tile->sign.identity_key_path, config->paths.identity_key, sizeof(tile->sign.identity_key_path) );
     546             : 
     547             :     /* Frankendancer does not use authorized voters in the sign tile. */
     548             :     tile->sign.authorized_voter_paths_cnt = 0UL;
     549             :     if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
     550             :       PARSE_BUNDLE_PUBKEY( sign, tip_distribution_program_addr );
     551             :       PARSE_BUNDLE_PUBKEY( sign, tip_payment_program_addr      );
     552             :     } else {
     553             :       /* 0xFF.. is not an invocable program */
     554             :       memset( tile->sign.bundle.tip_distribution_program_addr, '\xFF', 32UL );
     555             :       memset( tile->sign.bundle.tip_payment_program_addr,      '\xFF', 32UL );
     556             :     }
     557             :     #undef PARSE_BUNDLE_PUBKEY
     558             : 
     559             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "metric" ) ) ) {
     560             :     if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.metric.prometheus_listen_address, &tile->metric.prometheus_listen_addr ) ) )
     561             :       FD_LOG_ERR(( "failed to parse prometheus listen address `%s`", config->tiles.metric.prometheus_listen_address ));
     562             :     tile->metric.prometheus_listen_port = config->tiles.metric.prometheus_listen_port;
     563             : 
     564             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "diag" ) ) ) {
     565             : 
     566             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "guih" ) ) ) {
     567             :     if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.gui.gui_listen_address, &tile->gui.listen_addr ) ) )
     568             :       FD_LOG_ERR(( "failed to parse gui listen address `%s`", config->tiles.gui.gui_listen_address ));
     569             :     tile->gui.listen_port = config->tiles.gui.gui_listen_port;
     570             :     tile->gui.is_voting = strcmp( config->paths.vote_account, "" );
     571             :     fd_cstr_ncpy( tile->gui.cluster, config->cluster, sizeof(tile->gui.cluster) );
     572             :     fd_cstr_ncpy( tile->gui.identity_key_path, config->paths.identity_key, sizeof(tile->gui.identity_key_path) );
     573             :     fd_cstr_ncpy( tile->gui.vote_key_path, config->paths.vote_account, sizeof(tile->gui.vote_key_path) );
     574             :     tile->gui.max_http_connections      = config->tiles.gui.max_http_connections;
     575             :     tile->gui.max_websocket_connections = config->tiles.gui.max_websocket_connections;
     576             :     tile->gui.max_http_request_length   = config->tiles.gui.max_http_request_length;
     577             :     tile->gui.send_buffer_size_mb       = config->tiles.gui.send_buffer_size_mb;
     578             :     tile->gui.schedule_strategy         = config->tiles.pack.schedule_strategy_enum;
     579             :     tile->gui.websocket_compression     = config->development.gui.websocket_compression;
     580             :     tile->gui.accdb_obj_id              = ULONG_MAX;
     581             : 
     582             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "plugin" ) ) ) {
     583             : 
     584             :   } else if( FD_UNLIKELY( !strcmp( tile->name, "waker" ) ) ) {
     585             : 
     586             :   } else {
     587             :     FD_LOG_ERR(( "unknown tile name %lu `%s`", tile->id, tile->name ));
     588             :   }
     589             : }

Generated by: LCOV version 1.14