LCOV - code coverage report
Current view: top level - app/shared - fd_config_json.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 454 462 98.3 %
Date: 2026-09-17 04:28:31 Functions: 22 22 100.0 %

          Line data    Source code
       1             : #include "fd_config_json.h"
       2             : 
       3             : #include "../../ballet/toml/fd_toml.h"
       4             : 
       5             : #include <stdarg.h>
       6             : #include <stdio.h>
       7             : #include <string.h>
       8             : 
       9             : /* Renders every member of the config; a config layout change breaks
      10             :    this assert so the new field is considered here (rendered, redacted,
      11             :    or knowingly skipped) before the constant is bumped.  String keys of
      12             :    the user's own file are separately forced through the classification
      13             :    lists below. */
      14             : FD_STATIC_ASSERT( sizeof(fd_config_t)==22987008UL, update_fd_config_to_json_for_the_layout_change );
      15             : 
      16         180 : #define REDACTED "[redacted]"
      17             : 
      18             : struct jw {
      19             :   char * buf;
      20             :   char * cur;
      21             :   ulong  rem;
      22             :   int    fail;
      23             :   int    first; /* no comma needed before the next member */
      24             : };
      25             : 
      26             : typedef struct jw jw_t;
      27             : 
      28             : static void
      29             : jw_raw( jw_t * w, char const * fmt, ... ) __attribute__((format(printf,2,3)));
      30             : 
      31             : static void
      32       38130 : jw_raw( jw_t * w, char const * fmt, ... ) {
      33       38130 :   if( FD_UNLIKELY( w->fail ) ) return;
      34       38130 :   va_list ap;
      35       38130 :   va_start( ap, fmt );
      36       38130 :   int n = vsnprintf( w->cur, w->rem, fmt, ap );
      37       38130 :   va_end( ap );
      38       38130 :   if( FD_UNLIKELY( n<0 || (ulong)n>=w->rem ) ) { w->fail = 1; return; }
      39       38130 :   w->cur += n; w->rem -= (ulong)n;
      40       38130 : }
      41             : 
      42             : static void
      43        1932 : jw_comma( jw_t * w ) {
      44        1932 :   if( !w->first ) jw_raw( w, "," );
      45        1932 :   w->first = 0;
      46        1932 : }
      47             : 
      48             : static void
      49        2478 : jw_cstr( jw_t * w, char const * s ) {
      50        2478 :   if( FD_UNLIKELY( w->fail ) ) return;
      51        2478 :   jw_raw( w, "\"" );
      52       30876 :   for( ; *s && !w->fail; s++ ) {
      53       28398 :     uchar c = (uchar)*s;
      54       28398 :     if(      c=='"' || c=='\\' ) jw_raw( w, "\\%c", (char)c );
      55       28398 :     else if( c<0x20 )            jw_raw( w, "\\u%04x", (uint)c );
      56       28398 :     else                         jw_raw( w, "%c", (char)c );
      57       28398 :   }
      58        2478 :   jw_raw( w, "\"" );
      59        2478 : }
      60             : 
      61         159 : static void jw_obj_open ( jw_t * w, char const * key ) { jw_comma( w ); if( key ) { jw_cstr( w, key ); jw_raw( w, ":" ); } jw_raw( w, "{" ); w->first = 1; }
      62         159 : static void jw_obj_close( jw_t * w )                   { jw_raw( w, "}" ); w->first = 0; }
      63          27 : static void jw_arr_open ( jw_t * w, char const * key ) { jw_comma( w ); jw_cstr( w, key ); jw_raw( w, ":[" ); w->first = 1; }
      64          27 : static void jw_arr_close( jw_t * w )                   { jw_raw( w, "]" ); w->first = 0; }
      65             : 
      66         189 : static void jw_str  ( jw_t * w, char const * key, char const * val ) { jw_comma( w ); jw_cstr( w, key ); jw_raw( w, ":" ); jw_cstr( w, val ); }
      67         315 : static void jw_ulong( jw_t * w, char const * key, ulong val )        { jw_comma( w ); jw_cstr( w, key ); jw_raw( w, ":%lu", val ); }
      68           3 : static void jw_long ( jw_t * w, char const * key, long val )         { jw_comma( w ); jw_cstr( w, key ); jw_raw( w, ":%ld", val ); }
      69           6 : static void jw_f64  ( jw_t * w, char const * key, double val )       { jw_comma( w ); jw_cstr( w, key ); jw_raw( w, ":%.17g", val ); }
      70         138 : static void jw_bool ( jw_t * w, char const * key, int val )          { jw_comma( w ); jw_cstr( w, key ); jw_raw( w, ":%s", val ? "true" : "false" ); }
      71             : 
      72             : /* a path (or other host-identifying string) is reported only as
      73             :    present-or-empty */
      74          90 : static void jw_path ( jw_t * w, char const * key, char const * val ) { jw_str( w, key, val[ 0 ] ? REDACTED : "" ); }
      75             : 
      76             : /* external service URLs (bundle, event, snapshot servers) can carry
      77             :    secrets anywhere in them (credentials, path tokens, query api keys),
      78             :    so they are reported only as present-or-empty, like paths */
      79           6 : static void jw_url( jw_t * w, char const * key, char const * val ) { jw_path( w, key, val ); }
      80             : 
      81             : static void
      82          12 : jw_str_arr( jw_t * w, char const * key, char const * vals, ulong stride, ulong cnt ) {
      83          12 :   jw_arr_open( w, key );
      84          12 :   for( ulong i=0UL; i<cnt; i++ ) { jw_comma( w ); jw_cstr( w, vals+i*stride ); }
      85          12 :   jw_arr_close( w );
      86          12 : }
      87             : 
      88             : static void
      89          15 : jw_path_arr( jw_t * w, char const * key, ulong cnt ) {
      90          15 :   jw_arr_open( w, key );
      91          15 :   for( ulong i=0UL; i<cnt; i++ ) { jw_comma( w ); jw_cstr( w, REDACTED ); }
      92          15 :   jw_arr_close( w );
      93          15 : }
      94             : 
      95             : /* generic pod rendering for the user's override TOML: every
      96             :    string-valued key must appear in exactly one of the lists below,
      97             :    either redacted (the value could identify the host or carry a
      98             :    secret) or reported verbatim.  A string key in neither list aborts,
      99             :    so a new config setting must be classified before it ships in the
     100             :    boot event; test_config_json renders the full default.toml
     101             :    vocabulary through this, so an unclassified key fails the unit test
     102             :    rather than an operator's boot. */
     103             : 
     104             : static char const * const jw_redacted_keys[] = {
     105             :   "user",
     106             :   "paths.base",
     107             :   "paths.identity_key",
     108             :   "paths.vote_account",
     109             :   "paths.authorized_voter_paths",
     110             :   "paths.snapshots",
     111             :   "paths.genesis",
     112             :   "paths.accounts",
     113             :   "paths.shredb",
     114             :   "paths.guidb",
     115             :   "log.path",
     116             :   "gossip.host",
     117             :   "snapshots.sources.servers",
     118             :   "snapshots.server.http_listen_address",
     119             :   "hugetlbfs.mount_path",
     120             :   "net.bind_address",
     121             :   "tiles.quic.ssl_key_log_file",
     122             :   "tiles.bundle.url",
     123             :   "tiles.event.url",
     124             :   "tiles.shred.additional_shred_destinations_retransmit",
     125             :   "tiles.shred.additional_shred_destinations_leader",
     126             :   "tiles.metric.prometheus_listen_address",
     127             :   "gossip.entrypoints",
     128             :   "tiles.gui.gui_listen_address",
     129             :   "tiles.rpc.rpc_listen_address",
     130             :   "development.bundle.ssl_key_log_file",
     131             :   "development.ledger_input.path",
     132             :   "capture.dump_proto_dir",
     133             :   "capture.dump_syscall_name_filter",
     134             :   "capture.solcap_capture",
     135             :   /* legacy aliases accepted by the extractor but not in default.toml */
     136             :   "consensus.identity_path",
     137             :   "consensus.vote_account_path",
     138             :   "ledger.path",
     139             :   "scratch_directory",
     140             : };
     141             : 
     142             : static char const * const jw_reported_keys[] = {
     143             :   "name",
     144             :   "log.colorize",
     145             :   "log.level_logfile",
     146             :   "log.level_stderr",
     147             :   "log.level_flush",
     148             :   "snapshots.sources.gossip.allow_list",
     149             :   "snapshots.sources.gossip.block_list",
     150             :   "consensus.expected_genesis_hash",
     151             :   "consensus.wait_for_supermajority_with_bank_hash",
     152             :   "layout.affinity",
     153             :   "layout.blocklist_cores",
     154             :   "hugetlbfs.max_page_size",
     155             :   "net.provider",
     156             :   "net.interface",
     157             :   "net.xdp.xdp_mode",
     158             :   "net.xdp.xdp_zero_copy",
     159             :   "net.xdp.poll_mode",
     160             :   "net.xdp.rss_queue_mode",
     161             :   "net.xdp.listen_gre",
     162             :   "net.xdp.native_bond",
     163             :   "tiles.bundle.tls_domain_name",
     164             :   "tiles.bundle.tip_distribution_program_addr",
     165             :   "tiles.bundle.tip_payment_program_addr",
     166             :   "tiles.bundle.tip_distribution_authority",
     167             :   "tiles.pack.schedule_strategy",
     168             :   "tiles.pack.account_blocklist",
     169             :   "tiles.replay.enable_features",
     170             :   "development.core_dump",
     171             :   "development.bench.affinity",
     172             :   "development.bench.transaction_mode",
     173             :   "development.pktgen.affinity",
     174             :   "development.pktgen.fake_dst_ip",
     175             :   "development.udpecho.affinity",
     176             :   "development.ledger_input.format",
     177             :   "development.backtest.affinity",
     178             :   "development.forktest.affinity",
     179             :   "capture.dump_instr_program_id_filter",
     180             : };
     181             : 
     182             : static int
     183         387 : jw_key_redacted( char const * path ) {
     184       10170 :   for( ulong i=0UL; i<sizeof(jw_redacted_keys)/sizeof(jw_redacted_keys[0]); i++ ) if( !strcmp( path, jw_redacted_keys[ i ] ) ) return 1;
     185        3912 :   for( ulong i=0UL; i<sizeof(jw_reported_keys)/sizeof(jw_reported_keys[0]); i++ ) if( !strcmp( path, jw_reported_keys[ i ] ) ) return 0;
     186           0 :   FD_LOG_ERR(( "config key %s is not classified for telemetry redaction; add it to jw_redacted_keys or jw_reported_keys in fd_config_json.c", path ));
     187           0 : }
     188             : 
     189             : /* an empty toml array parses to an empty subpod, indistinguishable
     190             :    from an empty table; the array-valued keys of the config vocabulary
     191             :    are listed so they render as [] */
     192             : 
     193             : static char const * const jw_array_keys[] = {
     194             :   "paths.authorized_voter_paths",
     195             :   "gossip.entrypoints",
     196             :   "snapshots.sources.gossip.allow_list",
     197             :   "snapshots.sources.gossip.block_list",
     198             :   "snapshots.sources.servers",
     199             :   "tiles.pack.account_blocklist",
     200             :   "tiles.replay.enable_features",
     201             :   "tiles.shred.additional_shred_destinations_retransmit",
     202             :   "tiles.shred.additional_shred_destinations_leader",
     203             : };
     204             : 
     205             : static int
     206          36 : jw_key_is_array( char const * path ) {
     207         222 :   for( ulong i=0UL; i<sizeof(jw_array_keys)/sizeof(jw_array_keys[0]); i++ ) if( !strcmp( path, jw_array_keys[ i ] ) ) return 1;
     208           9 :   return 0;
     209          36 : }
     210             : 
     211             : static int
     212        1416 : jw_key_is_index( char const * key ) {
     213        1446 :   for( ; *key; key++ ) if( *key<'0' || *key>'9' ) return 0;
     214          30 :   return 1;
     215        1416 : }
     216             : 
     217             : static void
     218         330 : jw_pod( jw_t * w, uchar const * pod, char const * prefix ) {
     219         330 :   fd_pod_iter_t head = fd_pod_iter_init( pod );
     220         330 :   int arr = fd_pod_iter_done( head ) ? jw_key_is_array( prefix )
     221         330 :                                      : !strcmp( fd_pod_iter_info( head ).key, "0" ); /* fd_toml keys arrays 0,1,... */
     222         330 :   jw_raw( w, arr ? "[" : "{" );
     223         330 :   w->first = 1;
     224        1425 :   for( fd_pod_iter_t iter=fd_pod_iter_init( pod ); !fd_pod_iter_done( iter ); iter=fd_pod_iter_next( iter ) ) {
     225        1095 :     fd_pod_info_t info = fd_pod_iter_info( iter );
     226        1095 :     char path[ 512 ];
     227        1095 :     if( jw_key_is_index( info.key ) )   FD_TEST( fd_cstr_printf_check( path, sizeof(path), NULL, "%s", prefix ) ); /* array elements classify as the array */
     228        1065 :     else if( prefix[ 0 ] )              FD_TEST( fd_cstr_printf_check( path, sizeof(path), NULL, "%s.%s", prefix, info.key ) );
     229         102 :     else                                FD_TEST( fd_cstr_printf_check( path, sizeof(path), NULL, "%s", info.key ) );
     230        1095 :     jw_comma( w );
     231        1095 :     if( !arr ) { jw_cstr( w, info.key ); jw_raw( w, ":" ); }
     232        1095 :     switch( info.val_type ) {
     233         321 :       case FD_POD_VAL_TYPE_SUBPOD:
     234         321 :         if( FD_UNLIKELY( jw_key_is_index( info.key ) ) ) FD_LOG_ERR(( "config array %s has a table or nested array element which cannot be classified for telemetry redaction", path ));
     235         321 :         jw_pod( w, (uchar const *)info.val, path );
     236         321 :         break;
     237         387 :       case FD_POD_VAL_TYPE_CSTR: {
     238         387 :         char const * val = info.val_sz ? (char const *)info.val : "";
     239         387 :         jw_cstr( w, ( jw_key_redacted( path ) && val[ 0 ] ) ? REDACTED : val );
     240         387 :         break;
     241         321 :       }
     242         303 :       case FD_POD_VAL_TYPE_LONG: { /* toml integer */
     243         303 :         ulong u; fd_ulong_svw_dec( (uchar const *)info.val, &u );
     244         303 :         jw_raw( w, "%ld", fd_long_zz_dec( u ) );
     245         303 :         break;
     246         321 :       }
     247          84 :       case FD_POD_VAL_TYPE_INT: { /* toml bool */
     248          84 :         ulong u; fd_ulong_svw_dec( (uchar const *)info.val, &u );
     249          84 :         jw_raw( w, "%s", fd_long_zz_dec( u ) ? "true" : "false" );
     250          84 :         break;
     251         321 :       }
     252           0 :       case FD_POD_VAL_TYPE_FLOAT: {
     253           0 :         float val; memcpy( &val, info.val, sizeof(float) );
     254           0 :         jw_raw( w, "%.9g", (double)val );
     255           0 :         break;
     256         321 :       }
     257           0 :       default:
     258           0 :         FD_LOG_ERR(( "unexpected pod value type %d for key %s", info.val_type, info.key ));
     259        1095 :     }
     260        1095 :   }
     261         330 :   jw_raw( w, arr ? "]" : "}" );
     262         330 :   w->first = 0;
     263         330 : }
     264             : 
     265             : ulong
     266             : fd_config_user_toml_to_json( fd_config_t const * config,
     267             :                              char *              buf,
     268           9 :                              ulong               buf_sz ) {
     269           9 :   if( FD_UNLIKELY( !buf_sz ) ) FD_LOG_ERR(( "zero sized buffer" ));
     270           9 :   buf[ 0 ] = '\0';
     271           9 :   if( FD_UNLIKELY( !config->user_config_len ) ) return 0UL;
     272             : 
     273           9 :   static uchar pod_mem[ 1UL<<20 ];
     274           9 :   uchar * pod = fd_pod_join( fd_pod_new( pod_mem, sizeof(pod_mem) ) );
     275           9 :   FD_TEST( pod );
     276             : 
     277           9 :   uchar scratch[ 4096 ];
     278           9 :   int err = fd_toml_parse( config->user_config, config->user_config_len, pod, scratch, sizeof(scratch), NULL );
     279           9 :   if( FD_UNLIKELY( err!=FD_TOML_SUCCESS ) ) FD_LOG_ERR(( "failed to re-parse the user config (%i-%s)", err, fd_toml_strerror( err ) ));
     280             : 
     281           9 :   jw_t w = { .buf = buf, .cur = buf, .rem = buf_sz, .fail = 0, .first = 1 };
     282           9 :   jw_pod( &w, pod, "" );
     283             : 
     284           9 :   fd_pod_delete( fd_pod_leave( pod ) );
     285             : 
     286           9 :   if( FD_UNLIKELY( w.fail ) ) FD_LOG_ERR(( "user config json does not fit in %lu bytes", buf_sz ));
     287           9 :   return (ulong)( w.cur-buf );
     288           9 : }
     289             : 
     290             : ulong
     291             : fd_config_to_json( fd_config_t const * config,
     292             :                    char *              buf,
     293           3 :                    ulong               buf_sz ) {
     294           3 :   FD_TEST( config->is_firedancer );
     295           3 :   fd_configf_t const * f = &config->firedancer;
     296             : 
     297           3 :   jw_t w = { .buf = buf, .cur = buf, .rem = buf_sz, .fail = !buf_sz, .first = 1 };
     298             : 
     299           3 :   jw_raw( &w, "{" );
     300           3 :   jw_str  ( &w, "name",              config->name );
     301           3 :   jw_path ( &w, "user",              config->user );
     302           3 :   jw_path ( &w, "hostname",          config->hostname );
     303           3 :   jw_bool ( &w, "telemetry",         config->telemetry );
     304           3 :   jw_f64  ( &w, "tick_per_ns_mu",    config->tick_per_ns_mu );
     305           3 :   jw_f64  ( &w, "tick_per_ns_sigma", config->tick_per_ns_sigma );
     306           3 :   jw_long ( &w, "boot_timestamp_nanos", config->boot_timestamp_nanos );
     307           3 :   jw_str  ( &w, "cluster",           config->cluster );
     308           3 :   jw_bool ( &w, "is_live_cluster",   config->is_live_cluster );
     309           3 :   jw_ulong( &w, "uid",               config->uid );
     310           3 :   jw_ulong( &w, "gid",               config->gid );
     311           3 :   jw_bool ( &w, "is_firedancer",     config->is_firedancer );
     312           3 :   jw_bool ( &w, "is_dev",            config->is_dev );
     313           3 :   jw_bool ( &w, "has_user_config",   config->has_user_config );
     314           3 :   jw_str  ( &w, "action",            config->action );
     315             : 
     316           3 :   jw_obj_open( &w, "paths" );
     317           3 :     jw_path( &w, "base",         config->paths.base );
     318           3 :     jw_path( &w, "identity_key", config->paths.identity_key );
     319           3 :     jw_path( &w, "vote_account", config->paths.vote_account );
     320           3 :     jw_path( &w, "snapshots",    config->paths.snapshots );
     321           3 :     jw_path( &w, "genesis",      config->paths.genesis );
     322           3 :     jw_path( &w, "accounts",     config->paths.accounts );
     323           3 :     jw_path( &w, "shredb",       config->paths.shredb );
     324           3 :     jw_path( &w, "guidb",        config->paths.guidb );
     325           3 :     jw_path_arr( &w, "authorized_voter_paths", f->paths.authorized_voter_paths_cnt );
     326           3 :   jw_obj_close( &w );
     327             : 
     328           3 :   jw_obj_open( &w, "log" );
     329           3 :     jw_path( &w, "path",          config->log.path );
     330           3 :     jw_str ( &w, "colorize",      config->log.colorize );
     331           3 :     jw_str ( &w, "level_logfile", config->log.level_logfile );
     332           3 :     jw_str ( &w, "level_stderr",  config->log.level_stderr );
     333           3 :     jw_str ( &w, "level_flush",   config->log.level_flush );
     334           3 :   jw_obj_close( &w );
     335             : 
     336           3 :   jw_obj_open( &w, "consensus" );
     337           3 :     jw_ulong( &w, "expected_shred_version",        config->consensus.expected_shred_version );
     338           3 :     jw_str  ( &w, "expected_genesis_hash",         config->consensus.expected_genesis_hash );
     339           3 :     jw_bool ( &w, "wait_for_vote_to_start_leader", config->consensus.wait_for_vote_to_start_leader );
     340           3 :     jw_str  ( &w, "wait_for_supermajority_with_bank_hash", f->consensus.wait_for_supermajority_with_bank_hash );
     341           3 :   jw_obj_close( &w );
     342             : 
     343           3 :   jw_obj_open( &w, "gossip" );
     344           3 :     jw_path_arr( &w, "entrypoints", config->gossip.entrypoints_cnt );
     345           3 :     jw_ulong( &w, "port", config->gossip.port );
     346           3 :     jw_path ( &w, "host", f->gossip.host );
     347           3 :   jw_obj_close( &w );
     348             : 
     349           3 :   jw_obj_open( &w, "layout" );
     350           3 :     jw_str  ( &w, "affinity",          config->layout.affinity );
     351           3 :     jw_str  ( &w, "blocklist_cores",   config->layout.blocklist_cores );
     352           3 :     jw_ulong( &w, "net_tile_count",    config->layout.net_tile_count );
     353           3 :     jw_ulong( &w, "quic_tile_count",   config->layout.quic_tile_count );
     354           3 :     jw_ulong( &w, "verify_tile_count", config->layout.verify_tile_count );
     355           3 :     jw_ulong( &w, "shred_tile_count",  config->layout.shred_tile_count );
     356           3 :     jw_bool ( &w, "enable_block_production",    f->layout.enable_block_production );
     357           3 :     jw_bool ( &w, "enable_snapshot_production", f->layout.enable_snapshot_production );
     358           3 :     jw_ulong( &w, "sign_tile_count",            f->layout.sign_tile_count );
     359           3 :     jw_ulong( &w, "gossvf_tile_count",          f->layout.gossvf_tile_count );
     360           3 :     jw_ulong( &w, "resolv_tile_count",          f->layout.resolv_tile_count );
     361           3 :     jw_ulong( &w, "execle_tile_count",          f->layout.execle_tile_count );
     362           3 :     jw_ulong( &w, "execrp_tile_count",          f->layout.execrp_tile_count );
     363           3 :     jw_ulong( &w, "snapzp_tile_count",          f->layout.snapzp_tile_count );
     364           3 :     jw_ulong( &w, "snapsv_tile_count",          f->layout.snapsv_tile_count );
     365           3 :     jw_ulong( &w, "snapsv_io_worker_count",     f->layout.snapsv_io_worker_count );
     366           3 :   jw_obj_close( &w );
     367             : 
     368           3 :   jw_obj_open( &w, "accounts" );
     369           3 :     jw_ulong( &w, "max_accounts",   f->accounts.max_accounts );
     370           3 :     jw_ulong( &w, "cache_size_gib", f->accounts.cache_size_gib );
     371           3 :   jw_obj_close( &w );
     372             : 
     373           3 :   jw_obj_open( &w, "runtime" );
     374           3 :     jw_ulong( &w, "max_live_slots", f->runtime.max_live_slots );
     375           3 :     jw_ulong( &w, "max_fork_width", f->runtime.max_fork_width );
     376           3 :     jw_ulong( &w, "program_cache_size_mib", f->runtime.program_cache_size_mib );
     377           3 :   jw_obj_close( &w );
     378             : 
     379           3 :   jw_obj_open( &w, "snapshots" );
     380           3 :     jw_obj_open( &w, "sources" );
     381           3 :       jw_ulong( &w, "max_local_full_effective_age", f->snapshots.sources.max_local_full_effective_age );
     382           3 :       jw_ulong( &w, "max_local_incremental_age",    f->snapshots.sources.max_local_incremental_age );
     383           3 :       jw_obj_open( &w, "gossip" );
     384           3 :         jw_bool( &w, "allow_any", f->snapshots.sources.gossip.allow_any );
     385           3 :         jw_str_arr( &w, "allow_list", f->snapshots.sources.gossip.allow_list[ 0 ], sizeof(f->snapshots.sources.gossip.allow_list[ 0 ]), f->snapshots.sources.gossip.allow_list_cnt );
     386           3 :         jw_str_arr( &w, "block_list", f->snapshots.sources.gossip.block_list[ 0 ], sizeof(f->snapshots.sources.gossip.block_list[ 0 ]), f->snapshots.sources.gossip.block_list_cnt );
     387           3 :       jw_obj_close( &w );
     388           3 :       jw_path_arr( &w, "servers", f->snapshots.sources.servers_cnt );
     389           3 :     jw_obj_close( &w );
     390           3 :     jw_bool ( &w, "incremental_snapshots",               f->snapshots.incremental_snapshots );
     391           3 :     jw_bool ( &w, "genesis_download",                    f->snapshots.genesis_download );
     392           3 :     jw_ulong( &w, "max_full_snapshots_to_keep",          f->snapshots.max_full_snapshots_to_keep );
     393           3 :     jw_ulong( &w, "max_incremental_snapshots_to_keep",   f->snapshots.max_incremental_snapshots_to_keep );
     394           3 :     jw_ulong( &w, "max_retry_abort",                     f->snapshots.max_retry_abort );
     395           3 :     jw_ulong( &w, "min_download_speed_mibs",             f->snapshots.min_download_speed_mibs );
     396           3 :     jw_ulong( &w, "wait_for_peers_timeout_seconds",      f->snapshots.wait_for_peers_timeout_seconds );
     397           3 :     jw_ulong( &w, "full_snapshot_interval_blocks",       f->snapshots.full_snapshot_interval_blocks );
     398           3 :     jw_ulong( &w, "incremental_snapshot_interval_blocks",f->snapshots.incremental_snapshot_interval_blocks );
     399           3 :     jw_ulong( &w, "max_incremental_snapshot_accounts",   f->snapshots.max_incremental_snapshot_accounts );
     400           3 :     jw_obj_open( &w, "server" );
     401           3 :       jw_bool ( &w, "enabled",              f->snapshots.server.enabled );
     402           3 :       jw_path ( &w, "http_listen_address",  f->snapshots.server.http_listen_address );
     403           3 :       jw_ulong( &w, "http_listen_port",     f->snapshots.server.http_listen_port );
     404           3 :       jw_ulong( &w, "max_http_connections", f->snapshots.server.max_http_connections );
     405           3 :       jw_ulong( &w, "idle_timeout_millis",  f->snapshots.server.idle_timeout_millis );
     406           3 :       jw_ulong( &w, "send_timeout_millis",  f->snapshots.server.send_timeout_millis );
     407           3 :       jw_ulong( &w, "send_buffer_size_kib", f->snapshots.server.send_buffer_size_kib );
     408           3 :     jw_obj_close( &w );
     409           3 :   jw_obj_close( &w );
     410             : 
     411           3 :   jw_obj_open( &w, "hugetlbfs" );
     412           3 :     jw_path ( &w, "gigantic_page_mount_path",    config->hugetlbfs.gigantic_page_mount_path );
     413           3 :     jw_path ( &w, "huge_page_mount_path",        config->hugetlbfs.huge_page_mount_path );
     414           3 :     jw_path ( &w, "normal_page_mount_path",      config->hugetlbfs.normal_page_mount_path );
     415           3 :     jw_path ( &w, "mount_path",                  config->hugetlbfs.mount_path );
     416           3 :     jw_str  ( &w, "max_page_size",               config->hugetlbfs.max_page_size );
     417           3 :     jw_ulong( &w, "gigantic_page_threshold_mib", config->hugetlbfs.gigantic_page_threshold_mib );
     418           3 :   jw_obj_close( &w );
     419             : 
     420           3 :   jw_obj_open( &w, "net" );
     421           3 :     jw_str  ( &w, "provider",            config->net.provider );
     422           3 :     jw_str  ( &w, "interface",           config->net.interface );
     423           3 :     jw_path ( &w, "bind_address",        config->net.bind_address );
     424           3 :     jw_ulong( &w, "ingress_buffer_size", config->net.ingress_buffer_size );
     425           3 :     jw_obj_open( &w, "xdp" );
     426           3 :       jw_str  ( &w, "xdp_mode",             config->net.xdp.xdp_mode );
     427           3 :       jw_bool ( &w, "xdp_zero_copy",        config->net.xdp.xdp_zero_copy );
     428           3 :       jw_str  ( &w, "poll_mode",            config->net.xdp.poll_mode );
     429           3 :       jw_ulong( &w, "xdp_rx_queue_size",    config->net.xdp.xdp_rx_queue_size );
     430           3 :       jw_ulong( &w, "xdp_tx_queue_size",    config->net.xdp.xdp_tx_queue_size );
     431           3 :       jw_ulong( &w, "flush_timeout_micros", config->net.xdp.flush_timeout_micros );
     432           3 :       jw_str  ( &w, "rss_queue_mode",       config->net.xdp.rss_queue_mode );
     433           3 :       jw_bool ( &w, "listen_gre",           config->net.xdp.listen_gre );
     434           3 :       jw_bool ( &w, "native_bond",          config->net.xdp.native_bond );
     435           3 :     jw_obj_close( &w );
     436           3 :     jw_obj_open( &w, "socket" );
     437           3 :       jw_ulong( &w, "receive_buffer_size", config->net.socket.receive_buffer_size );
     438           3 :       jw_ulong( &w, "send_buffer_size",    config->net.socket.send_buffer_size );
     439           3 :     jw_obj_close( &w );
     440           3 :     jw_obj_open( &w, "mlx5" );
     441           3 :       jw_ulong( &w, "rx_queue_size", config->net.mlx5.rx_queue_size );
     442           3 :       jw_ulong( &w, "tx_queue_size", config->net.mlx5.tx_queue_size );
     443           3 :     jw_obj_close( &w );
     444           3 :   jw_obj_close( &w );
     445             : 
     446           3 :   jw_obj_open( &w, "development" );
     447           3 :     jw_bool( &w, "sandbox",   config->development.sandbox );
     448           3 :     jw_bool( &w, "no_clone",  config->development.no_clone );
     449           3 :     jw_bool( &w, "no_agave",  config->development.no_agave );
     450           3 :     jw_bool( &w, "bootstrap", config->development.bootstrap );
     451           3 :     jw_str ( &w, "core_dump", config->development.core_dump );
     452           3 :     jw_bool( &w, "hard_fork_fatal", f->development.hard_fork_fatal );
     453           3 :     jw_bool( &w, "fixed_fec_sets",  f->development.fixed_fec_sets );
     454           3 :     jw_bool( &w, "alpenglow",       f->development.alpenglow );
     455           3 :     jw_obj_open( &w, "votor" );
     456           3 :       jw_ulong( &w, "quic_client_listen_port", f->development.votor.quic_client_listen_port );
     457           3 :       jw_ulong( &w, "quic_server_listen_port", f->development.votor.quic_server_listen_port );
     458           3 :     jw_obj_close( &w );
     459           3 :     jw_obj_open( &w, "gossip" );
     460           3 :       jw_bool( &w, "allow_private_address", config->development.gossip.allow_private_address );
     461           3 :     jw_obj_close( &w );
     462           3 :     jw_obj_open( &w, "genesis" );
     463           3 :       jw_ulong( &w, "hashes_per_tick",              config->development.genesis.hashes_per_tick );
     464           3 :       jw_ulong( &w, "target_tick_duration_micros",  config->development.genesis.target_tick_duration_micros );
     465           3 :       jw_ulong( &w, "ticks_per_slot",               config->development.genesis.ticks_per_slot );
     466           3 :       jw_ulong( &w, "fund_initial_accounts",        config->development.genesis.fund_initial_accounts );
     467           3 :       jw_ulong( &w, "fund_initial_amount_lamports", config->development.genesis.fund_initial_amount_lamports );
     468           3 :       jw_ulong( &w, "vote_account_stake_lamports",  config->development.genesis.vote_account_stake_lamports );
     469           3 :       jw_bool ( &w, "warmup_epochs",                config->development.genesis.warmup_epochs );
     470           3 :       jw_bool ( &w, "validate_genesis_hash",        f->development.genesis.validate_genesis_hash );
     471           3 :       jw_ulong( &w, "max_file_size_mib",            f->development.genesis.max_file_size_mib );
     472           3 :     jw_obj_close( &w );
     473           3 :     jw_obj_open( &w, "ledger_input" );
     474           3 :       jw_str  ( &w, "format",   f->development.ledger_input.format );
     475           3 :       jw_path ( &w, "path",     f->development.ledger_input.path );
     476           3 :       jw_ulong( &w, "end_slot", f->development.ledger_input.end_slot );
     477           3 :     jw_obj_close( &w );
     478           3 :     jw_obj_open( &w, "backtest" );
     479           3 :       jw_str  ( &w, "affinity",      f->development.backtest.affinity );
     480           3 :       jw_ulong( &w, "root_distance", f->development.backtest.root_distance );
     481           3 :     jw_obj_close( &w );
     482           3 :     jw_obj_open( &w, "forktest" );
     483           3 :       jw_str( &w, "affinity", f->development.forktest.affinity );
     484           3 :     jw_obj_close( &w );
     485           3 :     jw_obj_open( &w, "bench" );
     486           3 :       jw_ulong( &w, "benchg_tile_count",            config->development.bench.benchg_tile_count );
     487           3 :       jw_ulong( &w, "benchs_tile_count",            config->development.bench.benchs_tile_count );
     488           3 :       jw_str  ( &w, "affinity",                     config->development.bench.affinity );
     489           3 :       jw_str  ( &w, "transaction_mode",             config->development.bench.transaction_mode );
     490           3 :       jw_ulong( &w, "max_cost_per_block",           config->development.bench.max_cost_per_block );
     491           3 :       jw_ulong( &w, "max_shreds_per_block",         config->development.bench.max_shreds_per_block );
     492           3 :       jw_ulong( &w, "disable_blockstore_from_slot", config->development.bench.disable_blockstore_from_slot );
     493           3 :       jw_bool ( &w, "disable_status_cache",         config->development.bench.disable_status_cache );
     494           3 :     jw_obj_close( &w );
     495           3 :     jw_obj_open( &w, "bundle" );
     496           3 :       jw_path ( &w, "ssl_key_log_file",  config->development.bundle.ssl_key_log_file );
     497           3 :       jw_ulong( &w, "buffer_size_kib",   config->development.bundle.buffer_size_kib );
     498           3 :     jw_obj_close( &w );
     499           3 :     jw_obj_open( &w, "event" );
     500           3 :       jw_bool( &w, "report_shreds",            config->development.event.report_shreds );
     501           3 :       jw_bool( &w, "report_transactions",      config->development.event.report_transactions );
     502           3 :       jw_bool( &w, "report_runtime_diffs",      config->development.event.report_runtime_diffs );
     503           3 :     jw_obj_close( &w );
     504           3 :     jw_obj_open( &w, "pktgen" );
     505           3 :       jw_str( &w, "affinity",    config->development.pktgen.affinity );
     506           3 :       jw_str( &w, "fake_dst_ip", config->development.pktgen.fake_dst_ip );
     507           3 :     jw_obj_close( &w );
     508           3 :     jw_obj_open( &w, "udpecho" );
     509           3 :       jw_str( &w, "affinity", config->development.udpecho.affinity );
     510           3 :     jw_obj_close( &w );
     511           3 :     jw_obj_open( &w, "snapshot_load" );
     512           3 :       jw_str( &w, "affinity", config->development.snapshot_load.affinity );
     513           3 :     jw_obj_close( &w );
     514           3 :     jw_obj_open( &w, "gui" );
     515           3 :       jw_bool( &w, "websocket_compression", config->development.gui.websocket_compression );
     516           3 :     jw_obj_close( &w );
     517           3 :     jw_obj_open( &w, "accdb" );
     518           3 :       jw_ulong( &w, "partition_size_gib", config->development.accdb.partition_size_gib );
     519           3 :     jw_obj_close( &w );
     520           3 :     jw_obj_open( &w, "hugetlbfs" );
     521           3 :       jw_bool( &w, "min_size", config->development.hugetlbfs.min_size );
     522           3 :     jw_obj_close( &w );
     523           3 :   jw_obj_close( &w );
     524             : 
     525           3 :   jw_obj_open( &w, "tiles" );
     526           3 :     jw_obj_open( &w, "netlink" );
     527           3 :       jw_ulong( &w, "max_routes",      config->tiles.netlink.max_routes );
     528           3 :       jw_ulong( &w, "max_peer_routes", config->tiles.netlink.max_peer_routes );
     529           3 :       jw_ulong( &w, "max_neighbors",   config->tiles.netlink.max_neighbors );
     530           3 :     jw_obj_close( &w );
     531           3 :     jw_obj_open( &w, "gossip" );
     532           3 :       jw_ulong( &w, "max_entries", config->tiles.gossip.max_entries );
     533           3 :     jw_obj_close( &w );
     534           3 :     jw_obj_open( &w, "quic" );
     535           3 :       jw_ulong( &w, "regular_transaction_listen_port", config->tiles.quic.regular_transaction_listen_port );
     536           3 :       jw_ulong( &w, "quic_transaction_listen_port",    config->tiles.quic.quic_transaction_listen_port );
     537           3 :       jw_ulong( &w, "txn_reassembly_count",            config->tiles.quic.txn_reassembly_count );
     538           3 :       jw_ulong( &w, "max_concurrent_connections",      config->tiles.quic.max_concurrent_connections );
     539           3 :       jw_ulong( &w, "max_concurrent_handshakes",       config->tiles.quic.max_concurrent_handshakes );
     540           3 :       jw_ulong( &w, "idle_timeout_millis",             config->tiles.quic.idle_timeout_millis );
     541           3 :       jw_ulong( &w, "ack_delay_millis",                config->tiles.quic.ack_delay_millis );
     542           3 :       jw_bool ( &w, "retry",                           config->tiles.quic.retry );
     543           3 :       jw_path ( &w, "ssl_key_log_file",                config->tiles.quic.ssl_key_log_file );
     544           3 :     jw_obj_close( &w );
     545           3 :     jw_obj_open( &w, "txsend" );
     546           3 :       jw_ulong( &w, "txsend_src_port", config->tiles.txsend.txsend_src_port );
     547           3 :     jw_obj_close( &w );
     548           3 :     jw_obj_open( &w, "verify" );
     549           3 :       jw_ulong( &w, "signature_cache_size", config->tiles.verify.signature_cache_size );
     550           3 :       jw_ulong( &w, "receive_buffer_size",  config->tiles.verify.receive_buffer_size );
     551           3 :       jw_ulong( &w, "mtu",                  config->tiles.verify.mtu );
     552           3 :     jw_obj_close( &w );
     553           3 :     jw_obj_open( &w, "dedup" );
     554           3 :       jw_ulong( &w, "signature_cache_size", config->tiles.dedup.signature_cache_size );
     555           3 :     jw_obj_close( &w );
     556           3 :     jw_obj_open( &w, "bundle" );
     557           3 :       jw_bool ( &w, "enabled",                       config->tiles.bundle.enabled );
     558           3 :       jw_url  ( &w, "url",                           config->tiles.bundle.url );
     559           3 :       jw_str  ( &w, "tls_domain_name",               config->tiles.bundle.tls_domain_name );
     560           3 :       jw_str  ( &w, "tip_distribution_program_addr", config->tiles.bundle.tip_distribution_program_addr );
     561           3 :       jw_str  ( &w, "tip_payment_program_addr",      config->tiles.bundle.tip_payment_program_addr );
     562           3 :       jw_str  ( &w, "tip_distribution_authority",    config->tiles.bundle.tip_distribution_authority );
     563           3 :       jw_ulong( &w, "commission_bps",                config->tiles.bundle.commission_bps );
     564           3 :       jw_ulong( &w, "keepalive_interval_millis",     config->tiles.bundle.keepalive_interval_millis );
     565           3 :       jw_bool ( &w, "tls_cert_verify",               config->tiles.bundle.tls_cert_verify );
     566           3 :     jw_obj_close( &w );
     567           3 :     jw_obj_open( &w, "pack" );
     568           3 :       jw_ulong( &w, "max_pending_transactions", config->tiles.pack.max_pending_transactions );
     569           3 :       jw_bool ( &w, "use_consumed_cus",         config->tiles.pack.use_consumed_cus );
     570           3 :       jw_str  ( &w, "schedule_strategy",        config->tiles.pack.schedule_strategy );
     571           3 :       jw_str_arr( &w, "account_blocklist", config->tiles.pack.account_blocklist[ 0 ], sizeof(config->tiles.pack.account_blocklist[ 0 ]), config->tiles.pack.account_blocklist_cnt );
     572           3 :     jw_obj_close( &w );
     573           3 :     jw_obj_open( &w, "poh" );
     574           3 :       jw_bool( &w, "lagged_consecutive_leader_start", config->tiles.pohh.lagged_consecutive_leader_start );
     575           3 :     jw_obj_close( &w );
     576           3 :     jw_obj_open( &w, "shred" );
     577           3 :       jw_ulong( &w, "max_pending_shred_sets", config->tiles.shred.max_pending_shred_sets );
     578           3 :       jw_ulong( &w, "shred_listen_port",      config->tiles.shred.shred_listen_port );
     579           3 :       jw_path_arr( &w, "additional_shred_destinations_retransmit", config->tiles.shred.additional_shred_destinations_retransmit_cnt );
     580           3 :       jw_path_arr( &w, "additional_shred_destinations_leader",     config->tiles.shred.additional_shred_destinations_leader_cnt );
     581           3 :       jw_ulong( &w, "shred_cache_size_mib",   config->tiles.shred.shred_cache_size_mib );
     582           3 :     jw_obj_close( &w );
     583           3 :     jw_obj_open( &w, "metric" );
     584           3 :       jw_path ( &w, "prometheus_listen_address", config->tiles.metric.prometheus_listen_address );
     585           3 :       jw_ulong( &w, "prometheus_listen_port",    config->tiles.metric.prometheus_listen_port );
     586           3 :     jw_obj_close( &w );
     587           3 :     jw_obj_open( &w, "event" );
     588           3 :       jw_url( &w, "url", config->tiles.event.url );
     589           3 :     jw_obj_close( &w );
     590           3 :     jw_obj_open( &w, "gui" );
     591           3 :       jw_bool ( &w, "enabled",                   config->tiles.gui.enabled );
     592           3 :       jw_path ( &w, "gui_listen_address",        config->tiles.gui.gui_listen_address );
     593           3 :       jw_ulong( &w, "gui_listen_port",           config->tiles.gui.gui_listen_port );
     594           3 :       jw_ulong( &w, "max_http_connections",      config->tiles.gui.max_http_connections );
     595           3 :       jw_ulong( &w, "max_websocket_connections", config->tiles.gui.max_websocket_connections );
     596           3 :       jw_ulong( &w, "max_http_request_length",   config->tiles.gui.max_http_request_length );
     597           3 :       jw_ulong( &w, "send_buffer_size_mb",       config->tiles.gui.send_buffer_size_mb );
     598           3 :       jw_ulong( &w, "db_size_gib",               config->tiles.gui.db_size_gib );
     599           3 :     jw_obj_close( &w );
     600           3 :     jw_obj_open( &w, "rpc" );
     601           3 :       jw_bool ( &w, "enabled",                   config->tiles.rpc.enabled );
     602           3 :       jw_path ( &w, "rpc_listen_address",        config->tiles.rpc.rpc_listen_address );
     603           3 :       jw_ulong( &w, "rpc_listen_port",           config->tiles.rpc.rpc_listen_port );
     604           3 :       jw_ulong( &w, "max_http_connections",      config->tiles.rpc.max_http_connections );
     605           3 :       jw_ulong( &w, "max_websocket_connections", config->tiles.rpc.max_websocket_connections );
     606           3 :       jw_ulong( &w, "max_http_request_length",   config->tiles.rpc.max_http_request_length );
     607           3 :       jw_ulong( &w, "send_buffer_size_mb",       config->tiles.rpc.send_buffer_size_mb );
     608           3 :       jw_bool ( &w, "delay_startup",             config->tiles.rpc.delay_startup );
     609           3 :     jw_obj_close( &w );
     610           3 :     jw_obj_open( &w, "repair" );
     611           3 :       jw_ulong( &w, "repair_client_listen_port", config->tiles.repair.repair_client_listen_port );
     612           3 :       jw_ulong( &w, "slot_max",                  config->tiles.repair.slot_max );
     613           3 :     jw_obj_close( &w );
     614           3 :     jw_obj_open( &w, "rotor" );
     615           3 :       jw_ulong( &w, "slot_max",                  config->tiles.rotor.slot_max );
     616           3 :     jw_obj_close( &w );
     617           3 :     jw_obj_open( &w, "rserve" );
     618           3 :       jw_bool ( &w, "enabled",                   config->tiles.rserve.enabled );
     619           3 :       jw_ulong( &w, "repair_serve_listen_port",  config->tiles.rserve.repair_serve_listen_port );
     620           3 :       jw_ulong( &w, "shred_storage_limit_gib",   config->tiles.rserve.shred_storage_limit_gib );
     621           3 :     jw_obj_close( &w );
     622           3 :     jw_obj_open( &w, "replay" );
     623           3 :       jw_ulong( &w, "max_transaction_lookahead_buffer_size", config->tiles.replay.max_transaction_lookahead_buffer_size );
     624           3 :       jw_str_arr( &w, "enable_features", config->tiles.replay.enable_features[ 0 ], sizeof(config->tiles.replay.enable_features[ 0 ]), config->tiles.replay.enable_features_cnt );
     625           3 :     jw_obj_close( &w );
     626           3 :   jw_obj_close( &w );
     627             : 
     628           3 :   jw_obj_open( &w, "capture" );
     629           3 :     jw_ulong( &w, "capture_start_slot",           config->capture.capture_start_slot );
     630           3 :     jw_path ( &w, "dump_proto_dir",               config->capture.dump_proto_dir );
     631           3 :     jw_path ( &w, "dump_syscall_name_filter",     config->capture.dump_syscall_name_filter );
     632           3 :     jw_str  ( &w, "dump_instr_program_id_filter", config->capture.dump_instr_program_id_filter );
     633           3 :     jw_path ( &w, "solcap_capture",               config->capture.solcap_capture );
     634           3 :     jw_bool ( &w, "recent_only",                  config->capture.recent_only );
     635           3 :     jw_ulong( &w, "recent_slots_per_file",        config->capture.recent_slots_per_file );
     636           3 :     jw_bool ( &w, "dump_syscall_to_pb",           config->capture.dump_syscall_to_pb );
     637           3 :     jw_bool ( &w, "dump_instr_to_pb",             config->capture.dump_instr_to_pb );
     638           3 :     jw_bool ( &w, "dump_txn_to_pb",               config->capture.dump_txn_to_pb );
     639           3 :     jw_bool ( &w, "dump_txn_as_fixture",          config->capture.dump_txn_as_fixture );
     640           3 :     jw_bool ( &w, "dump_block_to_pb",             config->capture.dump_block_to_pb );
     641           3 :   jw_obj_close( &w );
     642             : 
     643           3 :   jw_obj_open( &w, "capctx" );
     644           3 :     jw_path( &w, "path", f->capctx.path );
     645           3 :   jw_obj_close( &w );
     646             : 
     647             : 
     648           3 :   jw_raw( &w, "}" );
     649             : 
     650           3 :   if( FD_UNLIKELY( w.fail ) ) FD_LOG_ERR(( "config json does not fit in %lu bytes", buf_sz ));
     651           3 :   return (ulong)( w.cur-buf );
     652           3 : }

Generated by: LCOV version 1.14