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