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 : }
|