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