Line data Source code
1 : #include "topology.h"
2 : #include "../shared/fd_config_json.h"
3 :
4 : #include "../../discof/poh/fd_poh.h"
5 : #include "../../discof/replay/fd_execrp.h"
6 : #include "../../discof/genesis/fd_genesi_tile.h"
7 : #include "../../discof/gossip/fd_gossip_tile.h"
8 : #include "../../discof/resolv/fd_resolv_tile.h"
9 : #include "../../discof/repair/fd_repair.h"
10 : #include "../../discof/replay/fd_replay_tile.h"
11 : #include "../../discof/replay/fd_sched.h"
12 : #include "../../discof/votor/fd_votor_tile.h"
13 : #include "../../disco/keyguard/fd_keyguard.h"
14 : #include "../../ballet/bls/fd_bls.h"
15 : #include "../../discof/backup/fd_snapmk_tile.h"
16 : #include "../../discof/backup/fd_snapsv_tile.h"
17 : #include "../../disco/shred/fd_shred_tile.h"
18 : #include "../../disco/store/fd_store.h"
19 : #include "../../discof/rotor/fd_rotor_tile.h"
20 : #include "../../choreo/rotor/fd_rotor.h"
21 : #include "../../disco/net/fd_net_tile.h"
22 : #include "../../discof/backup/fd_backup.h"
23 : #include "../../discof/restore/fd_snapct_tile.h"
24 : #include "../../disco/gui/fd_gui_config_parse.h"
25 : #include "../../disco/quic/fd_tpu.h"
26 : #include "../../disco/pack/fd_pack_cost.h"
27 : #include "../../disco/pack/fd_pack.h"
28 : #include "../../disco/tiles.h"
29 : #include "../../disco/topo/fd_topob.h"
30 : #include "../../disco/topo/fd_cpu_topo.h"
31 : #include "../../disco/bundle/fd_bundle_tile.h"
32 : #include "../../tango/dcache/fd_dcache.h"
33 : #include "../../disco/diag/fd_diag_tile.h"
34 : #include "../../util/pod/fd_pod_format.h"
35 : #include "../../discof/restore/utils/fd_ssctrl.h"
36 : #include "../../discof/restore/utils/fd_ssmsg.h"
37 : #include "../../flamenco/accdb/fd_accdb_cache.h"
38 : #include "../../flamenco/capture/fd_solcap_writer.h"
39 : #include "../../flamenco/progcache/fd_progcache.h"
40 : #include "../../flamenco/runtime/fd_cost_tracker.h"
41 :
42 : #include <sys/random.h>
43 : #include <sys/types.h>
44 : #include <sys/socket.h>
45 : #include <netdb.h>
46 :
47 : extern fd_topo_obj_callbacks_t * CALLBACKS[];
48 : extern fd_topo_run_tile_t * TILES[];
49 :
50 : static ulong
51 0 : tile_max_event_sz( fd_topo_tile_t const * tile ) {
52 0 : for( fd_topo_run_tile_t ** t=TILES; *t; t++ ) {
53 0 : if( FD_UNLIKELY( !strcmp( (*t)->name, tile->name ) ) ) {
54 0 : return (*t)->max_event_sz ? (*t)->max_event_sz( tile ) : 0UL;
55 0 : }
56 0 : }
57 0 : return 0UL;
58 0 : }
59 :
60 : void
61 0 : wire_event_links( fd_topo_t * topo ) {
62 0 : fd_topob_wksp( topo, "event_in" );
63 :
64 0 : ulong tile_cnt = topo->tile_cnt;
65 0 : for( ulong i=0UL; i<tile_cnt; i++ ) {
66 0 : fd_topo_tile_t * tile = &topo->tiles[ i ];
67 0 : if( FD_UNLIKELY( !strcmp( tile->name, "event" ) ) ) continue;
68 :
69 0 : ulong max_sz = tile_max_event_sz( tile );
70 0 : if( FD_LIKELY( !max_sz ) ) continue;
71 :
72 0 : char link_name[ sizeof(((fd_topo_link_t *)0)->name) ];
73 0 : FD_TEST( fd_cstr_printf_check( link_name, sizeof(link_name), NULL, "%s_event", tile->name ) );
74 :
75 : /* The dcache must cover depth*MTU (a smaller region risks undetected
76 : torn reads), so big-MTU links trade depth away to fit the budget. */
77 0 : ulong const event_link_dcache_max = 64UL<<20; /* 64 MiB data region per event link */
78 0 : ulong depth = 1024UL;
79 0 : while( depth>1UL && fd_dcache_req_data_sz( max_sz, depth, 1UL, 1 )>event_link_dcache_max ) depth >>= 1;
80 :
81 0 : fd_topo_link_t * link = fd_topob_link( topo, link_name, "event_in", depth, max_sz, 1UL );
82 0 : link->permit_no_producers = 1; /* written outside fd_stem; topo sees no producer */
83 :
84 0 : tile->event_link_id = link->id;
85 :
86 0 : fd_topob_tile_uses( topo, tile, &topo->objs[ link->mcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_WRITE );
87 0 : fd_topob_tile_uses( topo, tile, &topo->objs[ link->dcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_WRITE );
88 :
89 0 : fd_topob_tile_in( topo, "event", 0UL, "metric_in", link_name, link->kind_id, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
90 0 : }
91 0 : }
92 :
93 : fd_topo_obj_t *
94 : setup_topo_banks( fd_topo_t * topo,
95 : char const * wksp_name,
96 : ulong max_live_slots,
97 : ulong cache_cnt,
98 : ulong stake_delegation_cache_cnt,
99 0 : ulong bench_max_cost_per_block ) {
100 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "banks", wksp_name );
101 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_live_slots, "obj.%lu.max_live_slots", obj->id ) );
102 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, cache_cnt, "obj.%lu.cache_cnt", obj->id ) );
103 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, stake_delegation_cache_cnt, "obj.%lu.stake_delegation_cache_cnt", obj->id ) );
104 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, bench_max_cost_per_block, "obj.%lu.bench_max_cost_per_block", obj->id ) );
105 0 : ulong seed;
106 0 : FD_TEST( fd_rng_secure( &seed, sizeof( ulong ) ) );
107 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, seed, "obj.%lu.seed", obj->id ) );
108 0 : return obj;
109 0 : }
110 :
111 : fd_topo_obj_t *
112 : setup_topo_footer_cache( fd_topo_t * topo,
113 0 : char const * wksp_name ) {
114 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "footer_cache", wksp_name );
115 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
116 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, obj->id, "footer_cache" ) );
117 0 : return obj;
118 0 : }
119 :
120 : fd_topo_obj_t *
121 : setup_topo_fec_sets( fd_topo_t * topo,
122 : char const * wksp_name,
123 0 : ulong sz ) {
124 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "fec_sets", wksp_name );
125 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, sz, "obj.%lu.sz", obj->id ) );
126 0 : return obj;
127 0 : }
128 :
129 : /* Workspace bytes reserved for the topology's own layout around the cache. */
130 0 : #define PROGCACHE_WKSP_OVERHEAD_SZ ( 3UL * fd_topo_workspace_align() )
131 :
132 : ulong
133 0 : setup_topo_progcache_min_sz( ulong txn_max ) {
134 0 : ulong min_sz = fd_progcache_shmem_min_sz( txn_max );
135 0 : if( FD_UNLIKELY( !min_sz ) ) return 0UL;
136 : /* Smallest huge-page multiple holding the cache minimum plus the overhead,
137 : so a workspace of exactly this size is what gets locked. */
138 0 : return fd_ulong_align_up( min_sz + PROGCACHE_WKSP_OVERHEAD_SZ, FD_SHMEM_HUGE_PAGE_SZ );
139 0 : }
140 :
141 : void
142 : setup_topo_progcache( fd_topo_t * topo,
143 : char const * wksp_name,
144 : ulong txn_max,
145 0 : ulong wksp_size ) {
146 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "progcache", wksp_name );
147 0 : FD_TEST( fd_pod_insert_ulong( topo->props, "progcache", obj->id ) );
148 :
149 0 : ulong min_wksp_sz = setup_topo_progcache_min_sz( txn_max );
150 0 : if( FD_UNLIKELY( !min_wksp_sz ) ) {
151 0 : FD_LOG_ERR(( "Invalid [runtime]: max_live_slots is invalid" ));
152 0 : }
153 0 : if( FD_UNLIKELY( wksp_size<min_wksp_sz ) ) {
154 0 : FD_LOG_ERR(( "Invalid [runtime]: program_cache_size_mib must be at least %lu", min_wksp_sz>>20 ));
155 0 : }
156 :
157 : /* The workspace is exactly program_cache_size_mib: the cache gets what is
158 : left after the overhead. For the default 2048 that is 2 gigantic pages. */
159 0 : ulong progcache_sz = wksp_size - PROGCACHE_WKSP_OVERHEAD_SZ;
160 0 : ulong progcache_footprint = fd_progcache_shmem_footprint( txn_max, progcache_sz );
161 0 : if( FD_UNLIKELY( !progcache_footprint ) ) {
162 0 : FD_LOG_ERR(( "Invalid [runtime]: program_cache_size_mib must be at least %lu", min_wksp_sz>>20 ));
163 0 : }
164 :
165 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, txn_max, "obj.%lu.txn_max", obj->id ) );
166 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, progcache_sz, "obj.%lu.progcache_sz", obj->id ) );
167 0 : }
168 :
169 : fd_topo_obj_t *
170 : setup_topo_store( fd_topo_t * topo,
171 : char const * wksp_name,
172 : ulong fec_max,
173 : ulong fec_data_max,
174 : ulong shred_storage_gib,
175 : ulong shred_cache_mib,
176 : ulong fec_set_cnt,
177 : ulong max_shreds_per_block,
178 : char const * db_path,
179 0 : ulong shred_tile_cnt ) {
180 0 : if( FD_UNLIKELY( !shred_cache_mib ) )
181 0 : FD_LOG_ERR(( "tiles.shred.shred_cache_size_mib must be non-zero; the FEC payload cache cannot be disabled" ));
182 0 : if( FD_UNLIKELY( shred_cache_mib>(ULONG_MAX>>20) ) )
183 0 : FD_LOG_ERR(( "tiles.shred.shred_cache_size_mib is too large: %lu", shred_cache_mib ));
184 0 : if( FD_UNLIKELY( shred_storage_gib>FD_SHREDB_MAX_SIZE_GIB ) )
185 0 : FD_LOG_ERR(( "tiles.rserve.shred_storage_limit_gib is %lu, but the maximum supported size is %lu GiB",
186 0 : shred_storage_gib, FD_SHREDB_MAX_SIZE_GIB ));
187 :
188 0 : ulong seed;
189 0 : FD_TEST( fd_rng_secure( &seed, sizeof( ulong ) ) );
190 :
191 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "store", wksp_name );
192 0 : ulong shred_cache_bytes = shred_cache_mib << 20;
193 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, fec_max, "obj.%lu.fec_max", obj->id ) );
194 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, fec_data_max, "obj.%lu.fec_data_max", obj->id ) );
195 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, shred_storage_gib, "obj.%lu.shred_storage_gib", obj->id ) );
196 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, shred_cache_bytes, "obj.%lu.shred_cache_bytes", obj->id ) );
197 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, fec_set_cnt, "obj.%lu.fec_set_cnt", obj->id ) );
198 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_shreds_per_block, "obj.%lu.max_shreds_per_block", obj->id ) );
199 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, seed, "obj.%lu.seed", obj->id ) );
200 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, shred_tile_cnt, "obj.%lu.shred_tile_cnt", obj->id ) );
201 0 : if( db_path ) {
202 0 : FD_TEST( fd_pod_insertf_cstr( topo->props, db_path, "obj.%lu.disk_path", obj->id ) );
203 0 : }
204 0 : return obj;
205 0 : }
206 :
207 : fd_topo_obj_t *
208 : setup_topo_txncache( fd_topo_t * topo,
209 : char const * wksp_name,
210 : ulong max_live_slots,
211 0 : ulong max_txn_per_slot ) {
212 0 : ulong seed;
213 0 : FD_TEST( fd_rng_secure( &seed, sizeof( ulong ) ) );
214 :
215 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "txncache", wksp_name );
216 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_live_slots, "obj.%lu.max_live_slots", obj->id ) );
217 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_txn_per_slot, "obj.%lu.max_txn_per_slot", obj->id ) );
218 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, seed, "obj.%lu.seed", obj->id ) );
219 :
220 0 : return obj;
221 0 : }
222 :
223 : fd_topo_obj_t *
224 : setup_topo_accdb( fd_topo_t * topo,
225 : char const * wksp_name,
226 : ulong max_accounts,
227 : ulong max_live_slots,
228 : ulong max_account_writes_per_slot,
229 : ulong partition_cnt,
230 : ulong partition_sz,
231 : ulong cache_footprint,
232 : int bundle_enabled,
233 : ulong joiner_cnt,
234 0 : ulong max_incremental_accounts ) {
235 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "accdb", wksp_name );
236 :
237 0 : ulong seed;
238 0 : FD_TEST( fd_rng_secure( &seed, sizeof( ulong ) ) );
239 :
240 0 : ulong cache_min_reserved = fd_accdb_cache_min_reserved( bundle_enabled );
241 :
242 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_accounts, "obj.%lu.max_accounts", obj->id ) );
243 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_live_slots, "obj.%lu.max_live_slots", obj->id ) );
244 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_account_writes_per_slot, "obj.%lu.max_account_writes_per_slot", obj->id ) );
245 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, partition_cnt, "obj.%lu.partition_cnt", obj->id ) );
246 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, partition_sz, "obj.%lu.partition_sz", obj->id ) );
247 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, cache_footprint, "obj.%lu.cache_footprint", obj->id ) );
248 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, cache_min_reserved, "obj.%lu.cache_min_reserved", obj->id ) );
249 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, (ulong)!!bundle_enabled, "obj.%lu.bundle_enabled", obj->id ) );
250 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, joiner_cnt, "obj.%lu.joiner_cnt", obj->id ) );
251 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_incremental_accounts, "obj.%lu.max_incremental_accounts", obj->id ) );
252 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, seed, "obj.%lu.seed", obj->id ) );
253 :
254 0 : return obj;
255 0 : }
256 :
257 : void
258 0 : fd_topo_initialize( config_t * config ) {
259 0 : ulong net_tile_cnt = config->layout.net_tile_count;
260 0 : ulong shred_tile_cnt = config->layout.shred_tile_count;
261 0 : ulong quic_tile_cnt = config->layout.quic_tile_count;
262 0 : ulong verify_tile_cnt = config->layout.verify_tile_count;
263 0 : ulong resolv_tile_cnt = config->firedancer.layout.resolv_tile_count;
264 0 : ulong execle_tile_cnt = config->firedancer.layout.execle_tile_count;
265 0 : ulong snapzp_tile_cnt = config->firedancer.layout.enable_snapshot_production
266 0 : ? config->firedancer.layout.snapzp_tile_count : 0UL;
267 0 : ulong snapsv_tile_cnt = ( config->firedancer.snapshots.server.enabled &&
268 0 : config->firedancer.layout.enable_snapshot_production )
269 0 : ? config->firedancer.layout.snapsv_tile_count : 0UL;
270 0 : ulong snapdc_tile_cnt = config->firedancer.layout.snapdc_tile_count;
271 0 : ulong snapin_tile_cnt = config->firedancer.layout.snapin_tile_count;
272 :
273 0 : ulong gossvf_tile_cnt = config->firedancer.layout.gossvf_tile_count;
274 0 : ulong execrp_tile_cnt = config->firedancer.layout.execrp_tile_count;
275 0 : ulong sign_tile_cnt = config->firedancer.layout.sign_tile_count;
276 :
277 0 : ulong genesis_max_message_size = config->firedancer.development.genesis.max_file_size_mib << 20;
278 :
279 0 : int snapshots_enabled = !!config->gossip.entrypoints_cnt;
280 0 : int snapmk_enabled = !!snapzp_tile_cnt;
281 0 : int rpc_enabled = config->tiles.rpc.enabled;
282 0 : int telemetry_enabled = config->telemetry && strcmp( config->tiles.event.url, "" );
283 0 : int leader_enabled = !!config->firedancer.layout.enable_block_production;
284 0 : int rserve_enabled = config->tiles.rserve.enabled;
285 0 : int efficient_mode = !strcmp( config->firedancer.layout.mode, "efficient" );
286 0 : int gossip_vote_enabled = leader_enabled;
287 :
288 0 : if( FD_UNLIKELY( snapmk_enabled ) ) {
289 0 : FD_CHECK_ERR( config->firedancer.snapshots.max_full_snapshots_to_keep,
290 0 : "[snapshots.max_full_snapshots_to_keep] must be nonzero when [layout.snapzp_tile_count] is nonzero" );
291 0 : FD_CHECK_ERR( !config->firedancer.snapshots.incremental_snapshot_interval_blocks ||
292 0 : config->firedancer.snapshots.max_incremental_snapshots_to_keep,
293 0 : "[snapshots.max_incremental_snapshots_to_keep] must be nonzero when incremental snapshot production is enabled" );
294 0 : }
295 :
296 0 : fd_topo_t * topo = fd_topob_new( &config->topo, config->name );
297 :
298 0 : topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
299 0 : topo->gigantic_page_threshold = config->hugetlbfs.gigantic_page_threshold_mib << 20;
300 :
301 0 : int solcap_enabled = strlen( config->capture.solcap_capture ) > 0;
302 :
303 : /* topo, name */
304 0 : fd_topob_wksp( topo, "metric" );
305 0 : fd_topob_wksp( topo, "diag" );
306 0 : fd_topob_wksp( topo, "genesi" );
307 0 : fd_topob_wksp( topo, "ipecho" );
308 0 : fd_topob_wksp( topo, "gossvf" );
309 0 : fd_topob_wksp( topo, "gossip" );
310 0 : fd_topob_wksp( topo, "shred" );
311 0 : fd_topob_wksp( topo, "rotor" );
312 0 : if( rserve_enabled ) fd_topob_wksp( topo, "rserve" );
313 0 : fd_topob_wksp( topo, "replay" );
314 0 : fd_topob_wksp( topo, "accdb" );
315 0 : fd_topob_wksp( topo, "execrp" );
316 0 : fd_topob_wksp( topo, "votor" );
317 0 : fd_topob_wksp( topo, "sign" )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_NEVER;
318 0 : fd_topob_wksp( topo, "admin" )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_NEVER;
319 :
320 0 : if( leader_enabled ) {
321 0 : fd_topob_wksp( topo, "quic" );
322 0 : fd_topob_wksp( topo, "verify" );
323 0 : fd_topob_wksp( topo, "dedup" );
324 0 : fd_topob_wksp( topo, "resolv" );
325 0 : fd_topob_wksp( topo, "pack" );
326 0 : fd_topob_wksp( topo, "execle" );
327 0 : fd_topob_wksp( topo, "motor" );
328 0 : } else {
329 0 : execle_tile_cnt = 0UL;
330 0 : resolv_tile_cnt = 0UL;
331 0 : quic_tile_cnt = 0UL;
332 0 : verify_tile_cnt = 0UL;
333 0 : config->tiles.bundle.enabled = 0;
334 0 : }
335 0 : fd_topob_wksp( topo, "metric_in" );
336 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) fd_topob_wksp( topo, "diag_gui" );
337 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) fd_topob_wksp( topo, "gossip_gui" );
338 :
339 0 : fd_topob_wksp( topo, "net_gossip" );
340 0 : fd_topob_wksp( topo, "net_shred" );
341 0 : fd_topob_wksp( topo, "net_repair" );
342 0 : if( rserve_enabled ) fd_topob_wksp( topo, "net_rserve" );
343 0 : fd_topob_wksp( topo, "net_votor" );
344 0 : if( leader_enabled ) fd_topob_wksp( topo, "net_quic" );
345 :
346 0 : fd_topob_wksp( topo, "genesi_out" );
347 0 : fd_topob_wksp( topo, "ipecho_out" );
348 0 : fd_topob_wksp( topo, "gossvf_gossip" );
349 0 : fd_topob_wksp( topo, "gossip_gossvf" );
350 0 : fd_topob_wksp( topo, "gossip_ciaddr" );
351 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) fd_topob_wksp( topo, "gossip_ciseen" );
352 0 : if( gossip_vote_enabled ) fd_topob_wksp( topo, "gossip_vote" );
353 0 : fd_topob_wksp( topo, "gossip_misc" );
354 :
355 0 : fd_topob_wksp( topo, "shred_out" );
356 0 : fd_topob_wksp( topo, "repair_out" );
357 0 : fd_topob_wksp( topo, "replay_epoch" );
358 0 : fd_topob_wksp( topo, "replay_execrp" );
359 0 : fd_topob_wksp( topo, "replay_out" );
360 0 : fd_topob_wksp( topo, "replay_slot" );
361 0 : fd_topob_wksp( topo, "votor_out" );
362 :
363 0 : if( leader_enabled ) {
364 0 : fd_topob_wksp( topo, "quic_verify" );
365 0 : fd_topob_wksp( topo, "verify_dedup" );
366 0 : fd_topob_wksp( topo, "dedup_resolv" );
367 0 : fd_topob_wksp( topo, "resolv_pack" );
368 0 : fd_topob_wksp( topo, "pack_poh" );
369 0 : fd_topob_wksp( topo, "pack_execle" );
370 0 : fd_topob_wksp( topo, "resolv_replay" );
371 0 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
372 0 : fd_topob_wksp( topo, "execle_pack" );
373 0 : }
374 0 : fd_topob_wksp( topo, "execle_poh" );
375 0 : fd_topob_wksp( topo, "execle_busy" );
376 0 : fd_topob_wksp( topo, "poh_shred" );
377 0 : fd_topob_wksp( topo, "poh_replay" );
378 0 : }
379 :
380 0 : fd_topob_wksp( topo, "adminctl" )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_NEVER;
381 :
382 0 : fd_topob_wksp( topo, "progcache" );
383 0 : fd_topob_wksp( topo, "txncache" );
384 0 : fd_topob_wksp( topo, "accdb_data" )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_FULL;
385 0 : fd_topob_wksp( topo, "banks" );
386 0 : fd_topob_wksp( topo, "store" )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_FULL;
387 0 : fd_topob_wksp( topo, "rnonce" );
388 :
389 0 : fd_topob_wksp( topo, "gossip_sign" );
390 0 : fd_topob_wksp( topo, "sign_gossip" );
391 :
392 0 : fd_topob_wksp( topo, "shred_sign" );
393 0 : fd_topob_wksp( topo, "sign_shred" );
394 :
395 0 : fd_topob_wksp( topo, "repair_sign" );
396 0 : fd_topob_wksp( topo, "sign_repair" );
397 :
398 0 : if( rserve_enabled ) {
399 0 : fd_topob_wksp( topo, "rserve_sign" );
400 0 : fd_topob_wksp( topo, "sign_rserve" );
401 0 : fd_topob_wksp( topo, "rotor_rserve" );
402 0 : }
403 :
404 0 : fd_topob_wksp( topo, "votor_sign" );
405 0 : fd_topob_wksp( topo, "sign_votor" );
406 :
407 0 : fd_topob_wksp( topo, "execrp_replay" );
408 0 : fd_topob_wksp( topo, "admin_replay" );
409 :
410 0 : if( FD_LIKELY( snapshots_enabled ) ) {
411 0 : fd_topob_wksp( topo, "snapct" );
412 0 : fd_topob_wksp( topo, "snapld" );
413 0 : fd_topob_wksp( topo, "snapdc" );
414 0 : fd_topob_wksp( topo, "snapin" );
415 0 : fd_topob_wksp( topo, "snapct_ld" );
416 0 : fd_topob_wksp( topo, "snapld_dc" );
417 0 : fd_topob_wksp( topo, "snapdc_in" );
418 0 : fd_topob_wksp( topo, "snapin_ct" );
419 0 : fd_topob_wksp( topo, "snapin_shmem" );
420 :
421 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) fd_topob_wksp( topo, "snapct_gui" );
422 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) fd_topob_wksp( topo, "snapin_gui" );
423 0 : fd_topob_wksp( topo, "snapin_manif" );
424 0 : fd_topob_wksp( topo, "snapct_repr" );
425 0 : }
426 0 : if( snapmk_enabled ) {
427 0 : fd_topob_wksp( topo, "snapmk" );
428 0 : fd_topob_wksp( topo, "snapzp" );
429 0 : fd_topob_wksp( topo, "snapmk_zp" );
430 0 : fd_topob_wksp( topo, "replay_snapmk" );
431 0 : fd_topob_wksp( topo, "snapmk_out" );
432 0 : fd_topob_wksp( topo, "snaprd" );
433 0 : fd_topob_wksp( topo, "snaprd_out" );
434 0 : if( snapsv_tile_cnt ) {
435 0 : fd_topob_wksp( topo, "snapsv" );
436 0 : fd_topob_wksp( topo, "snapsv_out" );
437 0 : }
438 0 : }
439 :
440 0 : #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
441 :
442 0 : ulong shred_depth = 65536UL;
443 :
444 : /* Under Alpenglow, rotor redelivers every FEC set replay can hold when
445 : replay loses a parent bank, and polls nothing until that is
446 : published, so repair_out holds all of it. */
447 :
448 0 : ulong repair_out_depth = fd_ulong_pow2_up( config->firedancer.runtime.max_live_slots * (config->limits.max_shreds_per_block/FD_FEC_SHRED_CNT) );
449 :
450 : /* topo, link_name, wksp_name, depth, mtu, burst */
451 0 : /**/ fd_topob_link( topo, "gossip_net", "net_gossip", 32768UL, FD_NET_MTU, 1UL );
452 0 : FOR(shred_tile_cnt) fd_topob_link( topo, "shred_net", "net_shred", 32768UL, FD_NET_MTU, 1UL );
453 0 : /**/ fd_topob_link( topo, "repair_net", "net_repair", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
454 0 : FOR(quic_tile_cnt) fd_topob_link( topo, "quic_net", "net_quic", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
455 :
456 0 : if( FD_LIKELY( rserve_enabled ) ) {
457 0 : /**/ fd_topob_link( topo, "rserve_net", "net_rserve", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
458 0 : /**/ fd_topob_link( topo, "rserve_sign", "rserve_sign", 128UL, 32UL, 1UL );
459 0 : /**/ fd_topob_link( topo, "sign_rserve", "sign_rserve", 128UL, sizeof(fd_ed25519_sig_t), 1UL );
460 0 : /**/ fd_topob_link( topo, "rotor_rserve", "rotor_rserve", 2048UL, sizeof(fd_rotor_block_t), 1UL );
461 0 : }
462 :
463 0 : if( FD_LIKELY( snapshots_enabled ) ) {
464 : /* TODO: Revisit the depths of all the snapshot links */
465 0 : /**/ fd_topob_link( topo, "snapct_ld", "snapct_ld", 128UL, sizeof(fd_ssctrl_msg_t), 1UL );
466 0 : /**/ fd_topob_link( topo, "snapld_dc", "snapld_dc", FD_SNAPSHOT_DATA_DEPTH, FD_SNAPSHOT_DATA_MTU, 1UL );
467 0 : FOR(snapdc_tile_cnt) fd_topob_link( topo, "snapdc_in", "snapdc_in", FD_SNAPSHOT_DC_IN_DEPTH, FD_SNAPSHOT_DATA_MTU, 1UL );
468 :
469 : /**/ fd_topob_link( topo, "snapin_manif", "snapin_manif", 4UL, sizeof(fd_snapshot_manifest_t),1UL ); /* only 3 frags ever traverse: FULL, INCREMENTAL, DONE */
470 0 : /**/ fd_topob_link( topo, "snapct_repr", "snapct_repr", 128UL, 0UL, 1UL )->permit_no_consumers = 1; /* TODO: wire in repair later */
471 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
472 0 : /**/ fd_topob_link( topo, "snapct_gui", "snapct_gui", 128UL, sizeof(fd_snapct_update_t), 1UL );
473 0 : FOR(snapin_tile_cnt) fd_topob_link( topo, "snapin_gui", "snapin_gui", 128UL, FD_GUI_CONFIG_PARSE_MAX_VALID_ACCT_SZ, 1UL );
474 0 : }
475 0 : FOR(snapin_tile_cnt) fd_topob_link( topo, "snapin_ct", "snapin_ct", 128UL, 0UL, 1UL );
476 0 : }
477 0 : FOR(snapzp_tile_cnt) fd_topob_link( topo, "snapmk_zp", "snapmk_zp", 1024UL, sizeof(fd_backup_frag_t), 1UL );
478 0 : if( snapmk_enabled ) fd_topob_link( topo, "replay_snapmk", "replay_snapmk", 16UL, sizeof(fd_replay_snap_start_t),1UL );
479 0 : if( snapmk_enabled ) fd_topob_link( topo, "snapmk_out", "snapmk_out", 128UL, sizeof(fd_snapmk_msg_t), 1UL );
480 0 : if( snapmk_enabled ) fd_topob_link( topo, "snaprd_out", "snaprd_out", 1024UL, FD_BACKUP_RD_MTU, 1UL );
481 0 : FOR(snapsv_tile_cnt) fd_topob_link( topo, "snapsv_out", "snapsv_out", 16384UL, sizeof(fd_snapsv_msg_t), 1UL )->permit_no_consumers = 1;
482 0 : fd_topo_obj_t * zp_fseq = NULL;
483 0 : if( snapmk_enabled ) {
484 0 : zp_fseq = fd_topob_obj( topo, "fseq", "snapmk" );
485 0 : FD_TEST( fd_pod_insert_ulong( topo->props, "snapzp.fseq", zp_fseq->id ) );
486 :
487 0 : fd_topo_obj_t * backup = fd_topob_obj( topo, "backup", "snapmk" );
488 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, config->firedancer.accounts.max_accounts, "obj.%lu.max_accounts", backup->id ) );
489 0 : FD_TEST( fd_pod_insert_ulong( topo->props, "backup", backup->id ) );
490 0 : }
491 :
492 0 : /**/ fd_topob_link( topo, "genesi_out", "genesi_out", 1UL, fd_genesi_tile_mtu( genesis_max_message_size ), 1UL );
493 0 : /**/ fd_topob_link( topo, "ipecho_out", "ipecho_out", 2UL, 0UL, 1UL );
494 0 : FOR(gossvf_tile_cnt) fd_topob_link( topo, "gossvf_gossip", "gossvf_gossip", config->net.ingress_buffer_size, FD_GOSSIP_GOSSVF_MTU, 1UL );
495 0 : /**/ fd_topob_link( topo, "gossip_gossvf", "gossip_gossvf", 65536UL*4UL, sizeof(fd_gossip_ping_update_t), 1UL ); /* TODO: Unclear where this depth comes from ... fix */
496 0 : /**/ fd_topob_link( topo, "gossip_ciaddr", "gossip_ciaddr", 65536UL*2UL, sizeof(fd_gossip_update_message_t), 1UL ); /* min pow2 >= gossip's STEM_BURST */
497 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
498 0 : fd_topob_link( topo, "gossip_ciseen", "gossip_ciseen", 65536UL*2UL, sizeof(fd_gossip_update_message_t), 1UL );
499 0 : }
500 0 : if( gossip_vote_enabled ) {
501 0 : fd_topob_link( topo, "gossip_vote", "gossip_vote", 65536UL*4UL, sizeof(fd_gossip_update_message_t), 1UL );
502 0 : }
503 0 : /**/ fd_topob_link( topo, "gossip_misc", "gossip_misc", 65536UL*2UL, sizeof(fd_gossip_update_message_t), 1UL );
504 :
505 0 : FOR(quic_tile_cnt) fd_topob_link( topo, "quic_verify", "quic_verify", config->tiles.verify.receive_buffer_size, sizeof(fd_tpu_msg_t), config->tiles.quic.txn_reassembly_count );
506 0 : FOR(verify_tile_cnt) fd_topob_link( topo, "verify_dedup", "verify_dedup", 1024UL, FD_TPU_PARSED_MTU, 1UL ); /* shallow enough to stay in cache */
507 0 : /**/ fd_topob_link( topo, "replay_epoch", "replay_epoch", 32UL, FD_EPOCH_OUT_MTU, 1UL ); /* replay publishes two epochs at boot and must keep STEM_BURST (4) credits after */
508 0 : /**/ fd_topob_link( topo, "replay_out", "replay_out", 65536UL, sizeof(fd_replay_message_t), 1UL )->permit_no_consumers = 1;
509 0 : /**/ fd_topob_link( topo, "replay_slot", "replay_slot", 4096UL, sizeof(fd_replay_message_t), 1UL );
510 0 : /**/ fd_topob_link( topo, "replay_rotor", "replay_slot", 16UL, sizeof(fd_replay_message_t), 1UL ); /* REPLAY_SIG_MISSING_FEC; >= replay's STEM_BURST (4) */
511 0 : FOR(execrp_tile_cnt) fd_topob_link( topo, "replay_execrp", "replay_execrp", 256UL, sizeof(fd_execrp_task_msg_t), 1UL );
512 0 : /**/ fd_topob_link( topo, "admin_replay", "admin_replay", 32UL, 0UL, 1UL );
513 0 : /**/ fd_topob_link( topo, "replay_admin", "admin_replay", 32UL, 0UL, 1UL );
514 0 : if( leader_enabled ) {
515 0 : /**/ fd_topob_link( topo, "dedup_resolv", "dedup_resolv", 16384UL, FD_TPU_PARSED_MTU, 1UL );
516 0 : FOR(resolv_tile_cnt) fd_topob_link( topo, "resolv_pack", "resolv_pack", 4096UL, FD_TPU_RESOLVED_MTU, 1UL );
517 0 : /**/ fd_topob_link( topo, "pack_poh", "pack_poh", 4096UL, sizeof(fd_done_packing_t), 1UL );
518 0 : FOR(execle_tile_cnt) fd_topob_link( topo, "execle_poh", "execle_poh", 4096UL, FD_EXECLE_POH_MTU, 1UL );
519 0 : FOR(execle_tile_cnt) fd_topob_link( topo, "pack_execle", "pack_execle", 128UL, FD_PACK_EXECLE_MTU, 1UL ); /* execle returns credits per frag, so this can be shallow enough for pack to keep in cache */
520 0 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
521 0 : FOR(execle_tile_cnt) fd_topob_link( topo, "execle_pack", "execle_pack", 1024UL, FD_PACK_REBATE_MAX_SZ, 1UL );
522 0 : }
523 0 : /**/ fd_topob_link( topo, "poh_shred", "poh_shred", 4096UL, FD_POH_SHRED_MTU, 1UL );
524 0 : /**/ fd_topob_link( topo, "poh_replay", "poh_replay", 4096UL, sizeof(fd_poh_leader_slot_ended_t), 1UL );
525 0 : }
526 :
527 0 : FOR(resolv_tile_cnt) fd_topob_link( topo, "resolv_replay", "resolv_replay", 4096UL, sizeof(fd_resolv_slot_exchanged_t), 1UL );
528 :
529 0 : FOR(shred_tile_cnt) fd_topob_link( topo, "shred_sign", "shred_sign", 128UL, 32UL, 1UL );
530 0 : FOR(shred_tile_cnt) fd_topob_link( topo, "sign_shred", "sign_shred", 128UL, sizeof(fd_ed25519_sig_t), 1UL );
531 :
532 : /**/ fd_topob_link( topo, "gossip_sign", "gossip_sign", 128UL, 2048UL, 1UL ); /* TODO: Where does 2048 come from? Depth probably doesn't need to be 128 */
533 0 : /**/ fd_topob_link( topo, "sign_gossip", "sign_gossip", 128UL, sizeof(fd_ed25519_sig_t), 1UL ); /* TODO: Depth probably doesn't need to be 128 */
534 :
535 0 : FOR(sign_tile_cnt-1) fd_topob_link( topo, "repair_sign", "repair_sign", 256UL, FD_REPAIR_MAX_PREIMAGE_SZ, 1UL ); /* See repair_tile.c for explanation */
536 0 : FOR(sign_tile_cnt-1) fd_topob_link( topo, "sign_repair", "sign_repair", 256UL, sizeof(fd_ed25519_sig_t), 1UL );
537 :
538 0 : FOR(shred_tile_cnt) fd_topob_link( topo, "shred_out", "shred_out", shred_depth, sizeof(fd_shred_message_t), FD_SHRED_STEM_BURST );
539 0 : /**/ fd_topob_link( topo, "repair_out", "repair_out", repair_out_depth, sizeof(fd_rotor_replay_fec_t), 1UL );
540 :
541 0 : FOR(execrp_tile_cnt) fd_topob_link( topo, "execrp_replay", "execrp_replay", 16384UL, sizeof(fd_execrp_task_done_msg_t), 1UL );
542 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
543 0 : fd_topob_link( topo, "diag_gui", "diag_gui", 4UL, sizeof(fd_diag_system_resources_t), 1UL );
544 0 : /**/ fd_topob_link( topo, "gossip_gui", "gossip_gui", 256UL, FD_GUI_GOSSIP_BW_MTU, 1UL );
545 0 : FOR(gossvf_tile_cnt) fd_topob_link( topo, "gossvf_gui", "gossip_gui", 256UL, FD_GUI_GOSSIP_BW_MTU, 1UL );
546 0 : }
547 :
548 0 : ushort parsed_tile_to_cpu[ FD_TILE_MAX ];
549 : /* Unassigned tiles will be floating, unless auto topology is enabled. */
550 0 : for( ulong i=0UL; i<FD_TILE_MAX; i++ ) parsed_tile_to_cpu[ i ] = USHORT_MAX;
551 :
552 0 : int is_auto_affinity = !strcmp( config->layout.affinity, "auto" );
553 :
554 0 : fd_topo_cpus_t cpus[1];
555 0 : fd_topo_cpus_init( cpus );
556 :
557 0 : ulong affinity_tile_cnt = 0UL;
558 0 : if( FD_LIKELY( !is_auto_affinity ) ) affinity_tile_cnt = fd_topob_parse_affinity_cstr( config->layout.affinity, parsed_tile_to_cpu, 1, 1 );
559 :
560 0 : ulong tile_to_cpu[ FD_TILE_MAX ];
561 0 : for( ulong i=0UL; i<FD_TILE_MAX; i++ ) tile_to_cpu[ i ] = ULONG_MAX;
562 :
563 0 : for( ulong i=0UL; i<affinity_tile_cnt; i++ ) {
564 0 : ushort cpu_idx = (ushort)( parsed_tile_to_cpu[ i ] & ~FD_TOPOB_CPU_SHARED );
565 0 : if( FD_UNLIKELY( parsed_tile_to_cpu[ i ]!=USHORT_MAX && cpu_idx>=cpus->cpu_cnt ) )
566 0 : FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.affinity] specifies a CPU index of %hu, but the system "
567 0 : "only has %lu CPUs. You should either change the CPU allocations in the affinity string, or increase the number of CPUs "
568 0 : "in the system.",
569 0 : cpu_idx, cpus->cpu_cnt ));
570 0 : tile_to_cpu[ i ] = fd_ulong_if( parsed_tile_to_cpu[ i ]==USHORT_MAX, ULONG_MAX, (ulong)parsed_tile_to_cpu[ i ] );
571 0 : }
572 :
573 0 : if( FD_UNLIKELY( efficient_mode ) ) fd_topob_sleep( topo, "metric_in", tile_to_cpu[ topo->tile_cnt ] );
574 :
575 0 : int xsk_core_dump = config->development.core_dump_level >= FD_TOPO_CORE_DUMP_LEVEL_REGULAR ? 1 : 0;
576 0 : fd_topos_net_tiles( topo, net_tile_cnt, &config->net, config->tiles.netlink.max_routes, config->tiles.netlink.max_peer_routes, config->tiles.netlink.max_neighbors, xsk_core_dump, tile_to_cpu );
577 :
578 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_gossvf", i, config->net.ingress_buffer_size );
579 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_shred", i, config->net.ingress_buffer_size );
580 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_repair", i, config->net.ingress_buffer_size );
581 0 : if( rserve_enabled ) FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_rserve", i, config->net.ingress_buffer_size );
582 0 : if( leader_enabled ) FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_quic", i, config->net.ingress_buffer_size );
583 :
584 : /* topo, tile_name, tile_wksp, metrics_wksp, cpu_idx, uses_id_keyswitch, uses_av_keyswitch, is_waker_client */
585 : /**/ fd_topob_tile( topo, "metric", "metric", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 1 );
586 0 : /**/ fd_topob_tile( topo, "diag", "diag", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
587 0 : if( FD_LIKELY( config->tiles.gui.enabled ) )
588 0 : fd_topob_tile_out( topo, "diag", 0UL, "diag_gui", 0UL );
589 :
590 0 : if( FD_LIKELY( snapshots_enabled ) ) {
591 0 : /**/ fd_topob_tile( topo, "snapct", "snapct", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 1 )->allow_shutdown = 1;
592 0 : /**/ fd_topob_tile( topo, "snapld", "snapld", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 1 )->allow_shutdown = 1;
593 0 : FOR(snapdc_tile_cnt) fd_topob_tile( topo, "snapdc", "snapdc", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
594 0 : FOR(snapin_tile_cnt) fd_topob_tile( topo, "snapin", "snapin", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
595 0 : }
596 0 : if( snapmk_enabled ) {
597 0 : /**/ fd_topob_tile( topo, "snapmk", "snapmk", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
598 0 : FOR(snapzp_tile_cnt) fd_topob_tile( topo, "snapzp", "snapzp", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
599 0 : /**/ fd_topob_tile( topo, "snaprd", "snaprd", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
600 0 : FOR(snapsv_tile_cnt) fd_topob_tile( topo, "snapsv", "snapsv", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
601 0 : }
602 :
603 : /**/ fd_topob_tile( topo, "genesi", "genesi", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 1 )->allow_shutdown = 1;
604 0 : /**/ fd_topob_tile( topo, "ipecho", "ipecho", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 1 );
605 0 : FOR(gossvf_tile_cnt) fd_topob_tile( topo, "gossvf", "gossvf", "metric_in", tile_to_cpu[ topo->tile_cnt ], 1, 0, 0 );
606 0 : /**/ fd_topob_tile( topo, "gossip", "gossip", "metric_in", tile_to_cpu[ topo->tile_cnt ], 1, 0, 0 );
607 :
608 0 : FOR(shred_tile_cnt) fd_topob_tile( topo, "shred", "shred", "metric_in", tile_to_cpu[ topo->tile_cnt ], 1, 0, 0 );
609 0 : /**/ fd_topob_tile( topo, "rotor", "rotor", "metric_in", tile_to_cpu[ topo->tile_cnt ], 1, 0, 0 );
610 0 : if( rserve_enabled) {
611 0 : /**/ fd_topob_tile( topo, "rserve", "rserve", "metric_in", tile_to_cpu[ topo->tile_cnt ], 1, 0, 0 );
612 0 : }
613 0 : /**/ fd_topob_tile( topo, "replay", "replay", "metric_in", tile_to_cpu[ topo->tile_cnt ], 1, 0, 0 );
614 0 : /**/ fd_topob_tile( topo, "accdb", "accdb", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
615 0 : FOR(execrp_tile_cnt) fd_topob_tile( topo, "execrp", "execrp", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
616 0 : /**/ fd_topob_tile( topo, "votor", "votor", "metric_in", tile_to_cpu[ topo->tile_cnt ], 1, 1, 0 );
617 :
618 0 : if( leader_enabled ) {
619 0 : FOR(quic_tile_cnt) fd_topob_tile( topo, "quic", "quic", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
620 0 : FOR(verify_tile_cnt) fd_topob_tile( topo, "verify", "verify", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
621 0 : /**/ fd_topob_tile( topo, "dedup", "dedup", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
622 0 : FOR(resolv_tile_cnt) fd_topob_tile( topo, "resolv", "resolv", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
623 0 : /**/ fd_topob_tile( topo, "pack", "pack", "metric_in", tile_to_cpu[ topo->tile_cnt ], config->tiles.bundle.enabled, 0, 0 );
624 0 : FOR(execle_tile_cnt) fd_topob_tile( topo, "execle", "execle", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
625 0 : /**/ fd_topob_tile( topo, "motor", "motor", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
626 0 : }
627 0 : FOR(sign_tile_cnt) fd_topob_tile( topo, "sign", "sign", "metric_in", tile_to_cpu[ topo->tile_cnt ], 1, 1, 0 );
628 :
629 0 : if( FD_UNLIKELY( rpc_enabled ) ) {
630 0 : fd_topob_wksp( topo, "rpc" );
631 0 : fd_topob_wksp( topo, "rpc_replay" );
632 0 : fd_topob_tile( topo, "rpc", "rpc", "metric_in", tile_to_cpu[ topo->tile_cnt ], 1, 0, 1 );
633 0 : }
634 :
635 0 : if( FD_UNLIKELY( solcap_enabled ) ) {
636 0 : fd_topob_wksp( topo, "solcap" );
637 0 : fd_topob_tile( topo, "solcap", "solcap", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
638 0 : }
639 :
640 0 : fd_topo_tile_t * admin_tile = fd_topob_tile( topo, "admin", "admin", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
641 :
642 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
643 0 : FOR(gossvf_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
644 0 : fd_topob_tile_in( topo, "gossvf", i, "metric_in", "net_gossvf", j, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
645 0 : FOR(shred_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
646 0 : fd_topob_tile_in ( topo, "shred", i, "metric_in", "net_shred", j, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
647 0 : FOR(net_tile_cnt) fd_topob_tile_in( topo, "rotor", 0UL, "metric_in", "net_repair", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
648 0 : /**/ fd_topob_tile_out( topo, "rotor", 0UL, "repair_net", 0UL );
649 0 : FOR(quic_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
650 0 : fd_topob_tile_in( topo, "quic", i, "metric_in", "net_quic", j, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
651 0 : FOR(shred_tile_cnt) fd_topos_tile_in_net( topo, "metric_in", "shred_net", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
652 0 : /**/ fd_topos_tile_in_net( topo, "metric_in", "gossip_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
653 0 : /**/ fd_topos_tile_in_net( topo, "metric_in", "repair_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
654 0 : FOR(quic_tile_cnt) fd_topos_tile_in_net( topo, "metric_in", "quic_net", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
655 :
656 0 : /**/ fd_topob_tile_out( topo, "genesi", 0UL, "genesi_out", 0UL );
657 0 : /**/ fd_topob_tile_in ( topo, "ipecho", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
658 0 : /**/ fd_topob_tile_out( topo, "ipecho", 0UL, "ipecho_out", 0UL );
659 :
660 0 : FOR(gossvf_tile_cnt) fd_topob_tile_out( topo, "gossvf", i, "gossvf_gossip", i );
661 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "gossip_ciaddr", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
662 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "gossip_gossvf", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
663 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
664 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
665 0 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
666 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_ciaddr", 0UL );
667 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
668 0 : fd_topob_tile_out( topo, "gossip", 0UL, "gossip_ciseen", 0UL );
669 0 : }
670 0 : if( gossip_vote_enabled ) {
671 0 : fd_topob_tile_out( topo, "gossip", 0UL, "gossip_vote", 0UL );
672 0 : }
673 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_misc", 0UL );
674 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_net", 0UL );
675 0 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
676 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "gossvf_gossip", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
677 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_gossvf", 0UL );
678 0 : if( rserve_enabled ) {
679 0 : FOR(net_tile_cnt) fd_topob_tile_in( topo, "rserve", 0UL, "metric_in", "net_rserve", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
680 0 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "rserve", 0UL, "metric_in", "shred_out", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
681 0 : /**/ fd_topob_tile_out( topo, "rserve", 0UL, "rserve_net", 0UL );
682 0 : /**/ fd_topos_tile_in_net( topo, "metric_in", "rserve_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
683 0 : /**/ fd_topob_tile_out( topo, "rotor", 0UL, "rotor_rserve", 0UL );
684 0 : /**/ fd_topob_tile_in( topo, "rserve", 0UL, "metric_in", "rotor_rserve", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
685 0 : }
686 0 : if( snapshots_enabled ) {
687 0 : fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
688 0 : }
689 0 : int snapshots_gossip_enabled = config->firedancer.snapshots.sources.gossip.allow_any || config->firedancer.snapshots.sources.gossip.allow_list_cnt>0UL;
690 0 : if( FD_LIKELY( snapshots_enabled ) ) {
691 0 : if( FD_LIKELY( snapshots_gossip_enabled ) ) {
692 0 : /**/ fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "gossip_ciaddr", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
693 0 : }
694 :
695 0 : fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
696 0 : fd_topob_tile_out( topo, "snapct", 0UL, "snapct_ld", 0UL );
697 0 : fd_topob_tile_out( topo, "snapct", 0UL, "snapct_repr", 0UL );
698 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
699 0 : /**/ fd_topob_tile_out( topo, "snapct", 0UL, "snapct_gui", 0UL );
700 0 : }
701 :
702 :
703 0 : FOR(snapin_tile_cnt) fd_topob_tile_out( topo, "snapin", i, "snapin_ct", i );
704 0 : FOR(snapin_tile_cnt) fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapin_ct", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
705 0 : /**/ fd_topob_tile_in ( topo, "snapld", 0UL, "metric_in", "snapct_ld", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
706 0 : /**/ fd_topob_tile_out( topo, "snapld", 0UL, "snapld_dc", 0UL );
707 :
708 0 : FOR(snapdc_tile_cnt) fd_topob_tile_in ( topo, "snapdc", i, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
709 0 : FOR(snapdc_tile_cnt) fd_topob_tile_out( topo, "snapdc", i, "snapdc_in", i );
710 :
711 0 : for( ulong t=0UL; t<snapin_tile_cnt; t++ ) {
712 0 : FOR(snapdc_tile_cnt) fd_topob_tile_in( topo, "snapin", t, "metric_in", "snapdc_in", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
713 0 : }
714 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
715 0 : FOR(snapin_tile_cnt) fd_topob_tile_out( topo, "snapin", i, "snapin_gui", i );
716 0 : }
717 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_manif", 0UL );
718 0 : }
719 :
720 0 : /**/ fd_topob_tile_in( topo, "rotor", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
721 0 : /**/ fd_topob_tile_in( topo, "rotor", 0UL, "metric_in", "gossip_ciaddr", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
722 0 : /**/ fd_topob_tile_in( topo, "rotor", 0UL, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
723 0 : /**/ fd_topob_tile_in( topo, "rotor", 0UL, "metric_in", "replay_slot", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
724 0 : /**/ fd_topob_tile_in( topo, "rotor", 0UL, "metric_in", "replay_rotor", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
725 0 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "rotor", 0UL, "metric_in", "shred_out", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
726 0 : if( snapshots_enabled ) {
727 0 : fd_topob_tile_in( topo, "rotor", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
728 0 : }
729 0 : /**/ fd_topob_tile_out( topo, "rotor", 0UL, "repair_out", 0 );
730 :
731 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "repair_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
732 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
733 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_out", 0UL );
734 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_slot", 0UL );
735 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_rotor", 0UL );
736 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_epoch", 0UL );
737 0 : FOR(execrp_tile_cnt) fd_topob_tile_out( topo, "replay", 0UL, "replay_execrp", i );
738 0 : FOR(execrp_tile_cnt) fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "execrp_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
739 0 : if(leader_enabled) {fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "poh_replay", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );}
740 0 : FOR(resolv_tile_cnt) fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "resolv_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
741 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
742 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "gossip_misc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
743 0 : if( FD_LIKELY( snapshots_enabled ) ) {
744 0 : fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
745 0 : }
746 0 : if( snapmk_enabled ) {
747 0 : /* */fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "snapmk_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
748 0 : }
749 0 : FOR(snapsv_tile_cnt) fd_topob_tile_in ( topo, "snapsv", i, "metric_in", "snapmk_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
750 0 : FOR(snapsv_tile_cnt) fd_topob_tile_out( topo, "snapsv", i, "snapsv_out", i );
751 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "admin_replay", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
752 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_admin", 0UL );
753 0 : /**/ fd_topob_tile_out( topo, "admin", 0UL, "admin_replay", 0UL );
754 0 : /**/ fd_topob_tile_in ( topo, "admin", 0UL, "metric_in", "replay_admin", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
755 :
756 0 : FOR(execrp_tile_cnt) fd_topob_tile_in ( topo, "execrp", i, "metric_in", "replay_execrp", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
757 0 : FOR(execrp_tile_cnt) fd_topob_tile_out( topo, "execrp", i, "execrp_replay", i );
758 :
759 0 : if( leader_enabled ) {
760 0 : FOR(quic_tile_cnt) fd_topob_tile_out( topo, "quic", i, "quic_verify", i );
761 0 : FOR(quic_tile_cnt) fd_topob_tile_out( topo, "quic", i, "quic_net", i );
762 : /* All verify tiles read from all QUIC tiles, packets are round robin. */
763 0 : FOR(verify_tile_cnt) for( ulong j=0UL; j<quic_tile_cnt; j++ )
764 0 : fd_topob_tile_in( topo, "verify", i, "metric_in", "quic_verify", j, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers, verify tiles may be overrun */
765 0 : FOR(verify_tile_cnt) fd_topob_tile_in( topo, "verify", i, "metric_in", "gossip_vote", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
766 0 : FOR(verify_tile_cnt) fd_topob_tile_out( topo, "verify", i, "verify_dedup", i );
767 0 : FOR(verify_tile_cnt) fd_topob_tile_in( topo, "dedup", 0UL, "metric_in", "verify_dedup", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
768 0 : /**/ fd_topob_tile_in( topo, "dedup", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
769 0 : /**/ fd_topob_tile_out( topo, "dedup", 0UL, "dedup_resolv", 0UL );
770 0 : FOR(resolv_tile_cnt) fd_topob_tile_in( topo, "resolv", i, "metric_in", "dedup_resolv", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
771 0 : FOR(resolv_tile_cnt) fd_topob_tile_in( topo, "resolv", i, "metric_in", "replay_slot", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
772 0 : FOR(resolv_tile_cnt) fd_topob_tile_out( topo, "resolv", i, "resolv_pack", i );
773 0 : FOR(resolv_tile_cnt) fd_topob_tile_out( topo, "resolv", i, "resolv_replay", i );
774 0 : FOR(resolv_tile_cnt) fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "resolv_pack", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
775 0 : /**/ fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
776 0 : FOR(execle_tile_cnt) fd_topob_tile_out( topo, "pack", 0UL, "pack_execle", i );
777 0 : /**/ fd_topob_tile_out( topo, "pack", 0UL, "pack_poh" , 0UL );
778 0 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
779 0 : FOR(execle_tile_cnt) fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "execle_pack", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
780 0 : }
781 0 : FOR(execle_tile_cnt) fd_topob_tile_in ( topo, "execle", i, "metric_in", "pack_execle", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
782 0 : FOR(execle_tile_cnt) fd_topob_tile_out( topo, "execle", i, "execle_poh", i );
783 0 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
784 0 : FOR(execle_tile_cnt)fd_topob_tile_out(topo, "execle", i, "execle_pack", i );
785 0 : }
786 0 : FOR(execle_tile_cnt) fd_topob_tile_in ( topo, "motor", 0UL, "metric_in", "execle_poh", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
787 0 : /**/ fd_topob_tile_in ( topo, "motor", 0UL, "metric_in", "pack_poh", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
788 0 : /**/ fd_topob_tile_in ( topo, "motor", 0UL, "metric_in", "replay_slot", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
789 0 : /**/ fd_topob_tile_out( topo, "motor", 0UL, "poh_shred", 0UL );
790 0 : /**/ fd_topob_tile_out( topo, "motor", 0UL, "poh_replay", 0UL );
791 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "poh_shred", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
792 0 : }
793 :
794 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
795 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "gossip_ciaddr", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
796 0 : FOR(shred_tile_cnt) fd_topob_tile_out( topo, "shred", i, "shred_out", i );
797 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
798 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "replay_slot", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
799 0 : FOR(shred_tile_cnt) fd_topob_tile_out( topo, "shred", i, "shred_net", i );
800 :
801 0 : if( FD_LIKELY( telemetry_enabled ) ) {
802 0 : fd_topob_wksp( topo, "event" );
803 0 : fd_topob_wksp( topo, "event_sign" );
804 0 : fd_topob_wksp( topo, "sign_event" );
805 0 : fd_topob_link( topo, "event_sign", "event_sign", 128UL, 317UL, 1UL );
806 0 : fd_topob_link( topo, "sign_event", "sign_event", 128UL, 64UL, 1UL );
807 0 : fd_topob_tile( topo, "event", "event", "metric_in", tile_to_cpu[ topo->tile_cnt ], 1, 0, 1 );
808 0 : fd_topob_tile_in( topo, "event", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
809 0 : fd_topob_tile_in( topo, "event", 0UL, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
810 :
811 0 : if( FD_UNLIKELY( config->development.event.report_shreds ) ) {
812 : /* TODO: This needs to be reliable, else we could miss shreds that
813 : are required to replay the chain, but we can't change it yet as
814 : the XDP tile does not support reliable consumers. */
815 0 : FOR(net_tile_cnt) fd_topob_tile_in( topo, "event", 0UL, "metric_in", "net_shred", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
816 0 : }
817 :
818 0 : if( FD_UNLIKELY( config->development.event.report_transactions && leader_enabled ) ) {
819 0 : fd_topob_tile_in( topo, "event", 0UL, "metric_in", "dedup_resolv", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
820 0 : }
821 :
822 0 : fd_topob_tile_in( topo, "sign", 0UL, "metric_in", "event_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
823 0 : fd_topob_tile_out( topo, "event", 0UL, "event_sign", 0UL );
824 0 : fd_topob_tile_in( topo, "event", 0UL, "metric_in", "sign_event", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
825 0 : fd_topob_tile_out( topo, "sign", 0UL, "sign_event", 0UL );
826 0 : }
827 :
828 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
829 0 : fd_topob_wksp( topo, "bundle_verif" );
830 0 : fd_topob_wksp( topo, "bundle_sign" );
831 0 : fd_topob_wksp( topo, "sign_bundle" );
832 0 : fd_topob_wksp( topo, "pack_sign" );
833 0 : fd_topob_wksp( topo, "sign_pack" );
834 0 : fd_topob_wksp( topo, "bundle" );
835 :
836 0 : /**/ fd_topob_link( topo, "bundle_verif", "bundle_verif", config->tiles.verify.receive_buffer_size, FD_TPU_PARSED_MTU, 1UL );
837 0 : /**/ fd_topob_link( topo, "bundle_sign", "bundle_sign", 65536UL, 9UL, 1UL );
838 0 : /**/ fd_topob_link( topo, "sign_bundle", "sign_bundle", 128UL, 64UL, 1UL );
839 0 : /**/ fd_topob_link( topo, "pack_sign", "pack_sign", 65536UL, 1232UL, 1UL );
840 0 : /**/ fd_topob_link( topo, "sign_pack", "sign_pack", 128UL, 64UL, 1UL );
841 :
842 : /**/ fd_topob_tile( topo, "bundle", "bundle", "metric_in", tile_to_cpu[ topo->tile_cnt ], 1, 0, 1 );
843 :
844 : /**/ fd_topob_tile_out( topo, "bundle", 0UL, "bundle_verif", 0UL );
845 0 : FOR(verify_tile_cnt) fd_topob_tile_in( topo, "verify", i, "metric_in", "bundle_verif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
846 :
847 0 : /**/ fd_topob_tile_in( topo, "sign", 0UL, "metric_in", "bundle_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
848 0 : /**/ fd_topob_tile_out( topo, "bundle", 0UL, "bundle_sign", 0UL );
849 0 : /**/ fd_topob_tile_in( topo, "bundle", 0UL, "metric_in", "sign_bundle", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
850 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_bundle", 0UL );
851 :
852 0 : if( leader_enabled ) {
853 0 : /**/ fd_topob_tile_in( topo, "sign", 0UL, "metric_in", "pack_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
854 0 : /**/ fd_topob_tile_out( topo, "pack", 0UL, "pack_sign", 0UL );
855 0 : /**/ fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "sign_pack", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
856 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_pack", 0UL );
857 0 : }
858 :
859 0 : if( leader_enabled ) fd_topob_tile_in( topo, "bundle", 0UL, "metric_in", "replay_slot", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
860 :
861 0 : if( config->tiles.gui.enabled ) { /* GUI is the only consumer of bundle_status */
862 0 : fd_topob_wksp( topo, "bundle_status" );
863 : /* bundle_status must be kind of deep, to prevent exhausting
864 : shared flow control credits when publishing many packets at
865 : once. */
866 0 : fd_topob_link( topo, "bundle_status", "bundle_status", 128UL, sizeof(fd_bundle_block_engine_update_t), 1UL );
867 0 : fd_topob_tile_out( topo, "bundle", 0UL, "bundle_status", 0UL );
868 0 : }
869 0 : }
870 :
871 : /* Sign links don't need to be reliable because each requester has a
872 : small bounded number of requests in flight: one for the tiles that
873 : sign synchronously and read the response out of band in a spin
874 : loop (their response link is not polled by fd_stem), and up to
875 : FD_SHRED_SIGN_PEND_MAX for shred, which takes its responses as
876 : ordinary polled frags.
877 :
878 : TODO: This can probably be fixed now to be reliable ... ? */
879 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
880 0 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "gossip_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
881 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_sign", 0UL );
882 0 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "sign_gossip", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
883 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_gossip", 0UL );
884 :
885 0 : for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
886 0 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "shred_sign", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
887 0 : /**/ fd_topob_tile_out( topo, "shred", i, "shred_sign", i );
888 0 : /**/ fd_topob_tile_in ( topo, "shred", i, "metric_in", "sign_shred", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
889 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_shred", i );
890 0 : }
891 :
892 0 : FOR(sign_tile_cnt-1UL) fd_topob_tile_out( topo, "rotor", 0UL, "repair_sign", i );
893 0 : FOR(sign_tile_cnt-1UL) fd_topob_tile_in ( topo, "sign", i+1UL, "metric_in", "repair_sign", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
894 0 : FOR(sign_tile_cnt-1UL) fd_topob_tile_out( topo, "sign", i+1UL, "sign_repair", i );
895 0 : FOR(sign_tile_cnt-1UL) fd_topob_tile_in ( topo, "rotor", 0UL, "metric_in", "sign_repair", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* This link is polled because the signing requests are asynchronous */
896 :
897 0 : if( rserve_enabled ) {
898 0 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "rserve_sign", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
899 0 : /**/ fd_topob_tile_out( topo, "rserve", 0UL, "rserve_sign", 0UL );
900 0 : /**/ fd_topob_tile_in ( topo, "rserve", 0UL, "metric_in", "sign_rserve", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
901 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_rserve", 0UL );
902 0 : }
903 :
904 0 : if( FD_UNLIKELY( rpc_enabled ) ) {
905 0 : fd_topob_link( topo, "rpc_replay", "rpc_replay", 8UL, 0UL, 1UL );
906 0 : fd_topob_tile_out( topo, "rpc", 0UL, "rpc_replay", 0UL );
907 :
908 0 : fd_topob_tile_in( topo, "rpc", 0UL, "metric_in", "replay_slot", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
909 0 : fd_topob_tile_in( topo, "rpc", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
910 0 : fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "rpc_replay", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
911 0 : fd_topob_tile_in( topo, "rpc", 0UL, "metric_in", "gossip_ciaddr", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
912 0 : fd_topob_tile_in( topo, "rpc", 0UL, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
913 0 : }
914 :
915 0 : if( FD_UNLIKELY( solcap_enabled ) ) {
916 0 : fd_topob_link( topo, "cap_repl", "solcap", 32UL, SOLCAP_WRITE_ACCOUNT_DATA_MTU, 1UL );
917 0 : fd_topob_tile_out( topo, "replay", 0UL, "cap_repl", 0UL );
918 0 : fd_topob_tile_in( topo, "solcap", 0UL, "metric_in", "cap_repl", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
919 0 : FOR(execrp_tile_cnt) fd_topob_link( topo, "cap_execrp", "solcap", 32UL, SOLCAP_WRITE_ACCOUNT_DATA_MTU, 1UL );
920 0 : FOR(execrp_tile_cnt) fd_topob_tile_out( topo, "execrp", i, "cap_execrp", i );
921 0 : FOR(execrp_tile_cnt) fd_topob_tile_in( topo, "solcap", 0UL, "metric_in", "cap_execrp", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
922 0 : }
923 :
924 0 : if( snapmk_enabled ) {
925 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_snapmk", 0UL );
926 0 : /**/ fd_topob_tile_in ( topo, "snapmk", 0UL, "metric_in", "replay_snapmk", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
927 0 : /**/ fd_topob_tile_in ( topo, "snapmk", 0UL, "metric_in", "snaprd_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
928 0 : FOR(snapzp_tile_cnt) fd_topob_tile_out( topo, "snapmk", 0UL, "snapmk_zp", i );
929 0 : FOR(snapzp_tile_cnt) fd_topob_tile_in ( topo, "snapzp", i, "metric_in", "snapmk_zp", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
930 0 : /**/ fd_topob_tile_out( topo, "snapmk", 0UL, "snapmk_out", 0UL );
931 0 : /**/ fd_topob_tile_out( topo, "snaprd", 0UL, "snaprd_out", 0UL );
932 0 : }
933 :
934 0 : fd_topo_obj_t * admin_ctl = fd_topob_obj_named( topo, "adminctl", "adminctl", "admin" );
935 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, admin_ctl->id, "adminctl" ) );
936 0 : fd_topob_tile_uses( topo, admin_tile, admin_ctl, FD_SHMEM_JOIN_MODE_READ_WRITE );
937 :
938 : /* There is a special fseq that sits between the pack, execle, and poh
939 : tiles to indicate when the execle/poh tiles are done processing a
940 : microblock. Pack uses this to determine when to "unlock" accounts
941 : that it marked as locked because they were being used. */
942 :
943 0 : for( ulong i=0UL; i<execle_tile_cnt; i++ ) {
944 0 : fd_topo_obj_t * busy_obj = fd_topob_obj( topo, "fseq", "execle_busy" );
945 :
946 0 : fd_topo_tile_t * pack_tile = &topo->tiles[ fd_topo_find_tile( topo, "pack", 0UL ) ];
947 0 : fd_topo_tile_t * execle_tile = &topo->tiles[ fd_topo_find_tile( topo, "execle", i ) ];
948 0 : fd_topob_tile_uses( topo, pack_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
949 0 : fd_topob_tile_uses( topo, execle_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
950 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, busy_obj->id, "execle_busy.%lu", i ) );
951 0 : }
952 :
953 : /* Repair and shred share a secret they use to generate the nonces.
954 : It's not super security sensitive, but for good hygiene, we make it
955 : an object. */
956 0 : if( 1 /* just restrict the scope for these variables in this big function */ ) {
957 0 : fd_topo_obj_t * rnonce_ss_obj = fd_topob_obj( topo, "rnonce_ss", "rnonce" );
958 0 : fd_topo_tile_t * repair_tile = &topo->tiles[ fd_topo_find_tile( topo, "rotor", 0UL ) ];
959 0 : fd_topob_tile_uses( topo, repair_tile, rnonce_ss_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
960 0 : for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
961 0 : fd_topo_tile_t * shred_tile = &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ];
962 0 : fd_topob_tile_uses( topo, shred_tile, rnonce_ss_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
963 0 : }
964 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, rnonce_ss_obj->id, "rnonce_ss" ) );
965 0 : }
966 :
967 : /* node_info holds various rarely-changing config that cannot be
968 : represented as simple scalar metrics */
969 0 : fd_topo_obj_t * node_info_obj = fd_topob_obj( topo, "node_info", "replay" );
970 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], node_info_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
971 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, node_info_obj->id, "node_info" ) );
972 :
973 : /* wait_info holds data for the wait command's safe-restart-window checks */
974 0 : fd_topo_obj_t * wait_info_obj = fd_topob_obj( topo, "wait_info", "replay" );
975 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], wait_info_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
976 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, wait_info_obj->id, "wait_info" ) );
977 :
978 0 : if( leader_enabled ) {
979 0 : fd_topo_obj_t * ldr_tt_obj = fd_topob_obj( topo, "ldr_tt", "motor" );
980 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, config->limits.max_txn_per_slot, "obj.%lu.max_txn_per_slot", ldr_tt_obj->id ) );
981 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "motor", 0UL ) ], ldr_tt_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
982 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], ldr_tt_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
983 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, ldr_tt_obj->id, "ldr_tt" ) );
984 0 : }
985 :
986 0 : ulong min_bank_cache_cnt = fd_ulong_min( execrp_tile_cnt, FD_SCHED_MAX_STAGING_LANES )+2UL;
987 0 : if( FD_UNLIKELY( config->firedancer.runtime.bank_cache_cnt<min_bank_cache_cnt ) ) {
988 0 : FD_LOG_ERR(( "Invalid [runtime]: bank_cache_cnt is %lu, but it must be at least %lu (2 more than the smaller of [layout] "
989 0 : "execrp_tile_count %lu and %lu replay staging lanes). Increase [runtime] bank_cache_cnt.",
990 0 : config->firedancer.runtime.bank_cache_cnt, min_bank_cache_cnt, execrp_tile_cnt, FD_SCHED_MAX_STAGING_LANES ));
991 0 : }
992 0 : fd_topo_obj_t * banks_obj = setup_topo_banks( topo, "banks", config->firedancer.runtime.max_live_slots, config->firedancer.runtime.bank_cache_cnt, config->firedancer.runtime.stake_delegation_cache_cnt, config->development.bench.max_cost_per_block );
993 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
994 0 : FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
995 0 : setup_topo_footer_cache( topo, "banks" );
996 0 : FOR(execle_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execle", i ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
997 0 : FOR(resolv_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "resolv", i ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
998 0 : if( snapmk_enabled ) {
999 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapmk", 0UL ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1000 0 : }
1001 0 : if( FD_LIKELY( snapshots_enabled ) ) {
1002 0 : FOR(snapin_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapin", i ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1003 0 : }
1004 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, banks_obj->id, "banks" ) );
1005 :
1006 0 : if( FD_UNLIKELY( config->firedancer.runtime.max_live_slots<32UL ) ) FD_LOG_ERR(( "max_live_slots must be >= 32" ));
1007 :
1008 0 : setup_topo_progcache( topo, "progcache",
1009 0 : config->firedancer.runtime.max_live_slots,
1010 0 : config->firedancer.runtime.program_cache_size_mib<<20 );
1011 0 : ulong progcache_obj_id; FD_TEST( (progcache_obj_id = fd_pod_query_ulong( topo->props, "progcache", ULONG_MAX ))!=ULONG_MAX );
1012 0 : fd_topo_obj_t * progcache_obj = &topo->objs[ progcache_obj_id ];
1013 :
1014 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1015 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "accdb", 0UL ) ], progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1016 0 : FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i ) ], progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1017 0 : FOR(execle_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execle", i ) ], progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1018 :
1019 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
1020 0 : fd_topob_wksp( topo, "gui" );
1021 :
1022 : /**/ fd_topob_tile( topo, "gui", "gui", "metric_in", tile_to_cpu[ topo->tile_cnt ], 1, 0, 1 );
1023 :
1024 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_gui", 0UL );
1025 0 : FOR(gossvf_tile_cnt) fd_topob_tile_out( topo, "gossvf", i, "gossvf_gui", i );
1026 :
1027 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
1028 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "gossvf_gui", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1029 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "repair_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1030 0 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "shred_out", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1031 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "gossip_gui", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1032 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "gossip_ciseen", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1033 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1034 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1035 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1036 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "diag_gui", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1037 0 : if( leader_enabled ) {
1038 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "pack_poh", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1039 0 : FOR(execle_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "pack_execle", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1040 0 : FOR(execle_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "execle_poh", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1041 0 : }
1042 0 : FOR(execrp_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "execrp_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1043 :
1044 0 : if( FD_LIKELY( snapshots_enabled ) ) {
1045 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "snapct_gui", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1046 0 : FOR(snapin_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "snapin_gui", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1047 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1048 0 : }
1049 0 : FOR(snapsv_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "snapsv_out", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1050 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1051 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "bundle_status", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1052 0 : }
1053 0 : }
1054 :
1055 0 : if( FD_LIKELY( !is_auto_affinity ) ) {
1056 0 : if( FD_UNLIKELY( affinity_tile_cnt<topo->tile_cnt ) )
1057 0 : FD_LOG_ERR(( "The topology you are using has %lu tiles, but the CPU affinity specified in the config tile as [layout.affinity] only provides for %lu cores. "
1058 0 : "You should either increase the number of cores dedicated to Firedancer in the affinity string, or decrease the number of cores needed by reducing "
1059 0 : "the total tile count. You can reduce the tile count by decreasing individual tile counts in the [layout] section of the configuration file.",
1060 0 : topo->tile_cnt, affinity_tile_cnt ));
1061 0 : if( FD_UNLIKELY( affinity_tile_cnt>topo->tile_cnt ) )
1062 0 : FD_LOG_WARNING(( "The topology you are using has %lu tiles, but the CPU affinity specified in the config tile as [layout.affinity] provides for %lu cores. "
1063 0 : "Not all cores in the affinity will be used by Firedancer. You may wish to increase the number of tiles in the system by increasing "
1064 0 : "individual tile counts in the [layout] section of the configuration file.",
1065 0 : topo->tile_cnt, affinity_tile_cnt ));
1066 0 : } else {
1067 0 : ushort blocklist_cores[ FD_TILE_MAX ];
1068 0 : topo->blocklist_cores_cnt = fd_topob_parse_affinity_cstr( config->layout.blocklist_cores, blocklist_cores, 0, 0 );
1069 0 : if( FD_UNLIKELY( topo->blocklist_cores_cnt>FD_TILE_MAX ) ) {
1070 0 : FD_LOG_ERR(( "The CPU string in the configuration file under [layout.blocklist_cores] specifies more CPUs than Firedancer can use. "
1071 0 : "You should reduce the number of CPUs in the excluded cores string." ));
1072 0 : }
1073 :
1074 0 : for( ulong i=0UL; i<topo->blocklist_cores_cnt; i++ ) {
1075 : /* Since we use fd_topob_parse_affinity_cstr() like for affinity, the user
1076 : may input a string containing `f`. That's parsed correctly, but it's
1077 : meaningless for blocklisted cores, so we reject it here. */
1078 0 : if( FD_UNLIKELY( blocklist_cores[ i ]==USHORT_MAX ) ) {
1079 0 : FD_LOG_ERR(( "The CPU string in the configuration file under [layout.blocklist_cores] contains invalid values: `f`. "
1080 0 : "You should fix the excluded cores string." ));
1081 0 : }
1082 0 : topo->blocklist_cores_cpu_idx[ i ] = blocklist_cores[ i ];
1083 0 : }
1084 0 : }
1085 :
1086 : /* Alpenglow links and tile connections. The optional GUI tile has
1087 : been created by this point. */
1088 0 : /**/ fd_topob_link( topo, "votor_out", "votor_out", 8192UL, sizeof(fd_votor_msg_t), FD_VOTOR_OUT_BURST );
1089 0 : /**/ fd_topob_link( topo, "votor_net", "net_votor", 32768UL, FD_NET_MTU, FD_VOTOR_NET_BURST ); /* as shred_net: fan-out publishes as it goes and rides depth, burst covers only the deferred aio flush */
1090 0 : /**/ fd_topob_link( topo, "votor_sign", "votor_sign", 128UL, FD_KEYGUARD_SIGN_REQ_MTU, 1UL ); /* TLS 1.3 CertificateVerify payload or vote history file body */
1091 0 : /**/ fd_topob_link( topo, "sign_votor", "sign_votor", 128UL, FD_BLS_SIG_SZ, 1UL ); /* ed25519 sig (TLS) or BLS sig (vote) */
1092 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_votor", i, config->net.ingress_buffer_size );
1093 :
1094 0 : /**/ fd_topob_tile_in ( topo, "votor", 0UL, "metric_in", "replay_slot", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1095 0 : /**/ fd_topob_tile_in ( topo, "votor", 0UL, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1096 0 : /**/ fd_topob_tile_in ( topo, "votor", 0UL, "metric_in", "gossip_ciaddr", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1097 0 : /**/ fd_topob_tile_in ( topo, "votor", 0UL, "metric_in", "ipecho_out", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1098 0 : FOR(net_tile_cnt) fd_topob_tile_in ( topo, "votor", 0UL, "metric_in", "net_votor", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
1099 :
1100 : /* Votor's first two outputs must be votor_out and votor_net. */
1101 0 : /**/ fd_topob_tile_out( topo, "votor", 0UL, "votor_out", 0UL );
1102 0 : /**/ fd_topob_tile_out( topo, "votor", 0UL, "votor_net", 0UL );
1103 0 : /**/ fd_topos_tile_in_net( topo, "metric_in", "votor_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
1104 :
1105 0 : /**/ fd_topob_tile_in ( topo, "rotor", 0UL, "metric_in", "votor_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); /* certified blocks to repair */
1106 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "votor_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1107 0 : if( config->tiles.gui.enabled ) {
1108 0 : /**/ fd_topob_tile_in ( topo, "gui", 0UL, "metric_in", "votor_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1109 0 : }
1110 0 : if( rpc_enabled ) {
1111 0 : /**/ fd_topob_tile_in ( topo, "rpc", 0UL, "metric_in", "votor_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1112 0 : }
1113 :
1114 0 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "votor_sign", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1115 0 : /**/ fd_topob_tile_out( topo, "votor", 0UL, "votor_sign", 0UL );
1116 0 : /**/ fd_topob_tile_in ( topo, "votor", 0UL, "metric_in", "sign_votor", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
1117 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_votor", 0UL );
1118 :
1119 : /* Grant the admin tile access to every keyswitch object in the
1120 : topology for add authorized voters and set identity. */
1121 0 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
1122 0 : if( topo->tiles[ i ].id_keyswitch_obj_id!=ULONG_MAX ) fd_topob_tile_uses( topo, admin_tile, &topo->objs[ topo->tiles[ i ].id_keyswitch_obj_id ], FD_SHMEM_JOIN_MODE_READ_WRITE );
1123 0 : if( topo->tiles[ i ].av_keyswitch_obj_id!=ULONG_MAX ) fd_topob_tile_uses( topo, admin_tile, &topo->objs[ topo->tiles[ i ].av_keyswitch_obj_id ], FD_SHMEM_JOIN_MODE_READ_WRITE );
1124 0 : }
1125 :
1126 0 : if( 0==strcmp( config->net.provider, "mlx5" ) ) {
1127 0 : ulong net_tile_id = fd_topo_find_tile( topo, fd_net_tile_name( config->net.provider ), 0UL );
1128 0 : FD_TEST( net_tile_id!=ULONG_MAX );
1129 0 : fd_topos_sock_lo( topo, &topo->tiles[ net_tile_id ] );
1130 0 : }
1131 :
1132 : /* Auto layout must run after all fd_topob_tile() calls so every tile gets a blocklist-aware CPU assignment. */
1133 0 : if( FD_UNLIKELY( is_auto_affinity ) ) fd_topob_auto_layout( topo );
1134 :
1135 0 : ulong fec_set_cnt = fd_shred_tile_fec_set_cnt( FD_SHRED_FIREDANCER_FEC_EXPOSURE,
1136 0 : config->tiles.shred.max_pending_shred_sets );
1137 0 : ulong store_fec_set_cnt = shred_tile_cnt*fec_set_cnt;
1138 :
1139 : /* store_fec_max is the maximum number of FEC sets Store retains.
1140 :
1141 : With Alpenglow, Store is sized to rotor's window of
1142 : N = max_live_slots slots, each of which can hold up to
1143 : fec_sets_per_slot FEC sets per version of its block. The number of versions in the window
1144 : is bounded as follows.
1145 :
1146 : Assume 20% of stake is malicious, every malicious leader
1147 : equivocates AG_EQVOC_BLOCK_HASH_MAX (7) versions of each of its
1148 : slots, and honest leaders produce one. The expected number of
1149 : versions is then (0.8 + 0.2*7)*N = 2.2*N. In general, bounding
1150 : P(V > budget) to z standard deviations needs a budget of
1151 : ~N*(2.2 + 4.8*z/sqrt(N)).
1152 :
1153 : We size for 2.5*N (FD_ROTOR_BLK_VERSION_NUM/DEN, the same factor
1154 : rotor sizes its blk pool with, see fd_rotor_blk_max), which leaves
1155 : 0.3*N of headroom, ie. ~0.0625*sqrt(N) standard deviations. The
1156 : probability that a window holds more than 2.5*N versions is:
1157 :
1158 : N = 2048 ~2.5e-3
1159 : N = 4096 ~4.2e-5
1160 : N = 30000 ~3e-26
1161 :
1162 : This is for a uniformly random window. The leader schedule is
1163 : known an epoch in advance, so an adversary can target the densest
1164 : window in the epoch, which is somewhat worse.
1165 :
1166 : Fixed 32-data-shred sets need 1024 FEC sets per slot; legacy
1167 : variable sets can contain one data shred and need up to 32768. */
1168 :
1169 0 : ulong fec_sets_per_slot = fd_ulong_if( config->firedancer.development.fixed_fec_sets,
1170 0 : config->limits.max_shreds_per_block/FD_FEC_SHRED_CNT, config->limits.max_shreds_per_block );
1171 0 : ulong store_fec_max = fd_rotor_blk_max( config->firedancer.runtime.max_live_slots ) * fec_sets_per_slot; /* every FEC set of every blk rotor holds */
1172 :
1173 : /* 32 shreds * 995 payload bytes = 31840 bytes with fixed_fec_sets = true
1174 : 67 shreds * 955 payload bytes = 63985 bytes with fixed_fec_sets = false */
1175 :
1176 0 : ulong store_fec_data_max = fd_ulong_if( config->firedancer.development.fixed_fec_sets, 31840UL, 63985UL );
1177 0 : fd_topo_obj_t * store_obj = setup_topo_store( topo, "store", store_fec_max, store_fec_data_max,
1178 0 : rserve_enabled ? config->tiles.rserve.shred_storage_limit_gib : 0UL,
1179 0 : config->tiles.shred.shred_cache_size_mib,
1180 0 : store_fec_set_cnt,
1181 0 : config->limits.max_shreds_per_block,
1182 0 : config->paths.shredb,
1183 0 : shred_tile_cnt );
1184 0 : FOR(shred_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1185 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1186 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "rotor", 0UL ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE ); /* rotor */
1187 0 : if( rserve_enabled ) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "rserve", 0UL ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1188 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, store_obj->id, "store" ) );
1189 :
1190 0 : fd_topo_obj_t * txncache_obj = setup_topo_txncache( topo, "txncache", config->firedancer.runtime.max_live_slots, 2UL*config->limits.max_txn_per_slot /* sig + message hash */ );
1191 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1192 0 : if( FD_LIKELY( snapshots_enabled ) ) {
1193 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1194 0 : }
1195 0 : if( snapmk_enabled ) {
1196 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapmk", 0UL ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1197 0 : }
1198 0 : FOR(execle_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execle", i ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1199 0 : FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1200 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
1201 :
1202 : /* Snapin and genesi are mutually exclusive accdb writers. */
1203 0 : ulong accdb_joiners = 3UL+execle_tile_cnt+execrp_tile_cnt+resolv_tile_cnt
1204 0 : + fd_ulong_if( snapshots_enabled, snapin_tile_cnt, 1UL );
1205 0 : ulong partition_sz = config->development.accdb.partition_size_gib*(1UL<<30UL);
1206 0 : fd_topo_obj_t * accdb_obj = setup_topo_accdb( topo, "accdb_data",
1207 0 : config->firedancer.accounts.max_accounts,
1208 0 : config->firedancer.runtime.max_live_slots,
1209 0 : FD_RUNTIME_MAX_ACC_WRITES_PER_SLOT,
1210 0 : 8192UL,
1211 0 : partition_sz,
1212 0 : config->firedancer.accounts.cache_size_gib*(1UL<<30UL),
1213 0 : config->tiles.bundle.enabled,
1214 0 : accdb_joiners,
1215 0 : snapmk_enabled ? config->firedancer.snapshots.max_incremental_snapshot_accounts : 0UL );
1216 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "accdb", 0UL ) ], accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1217 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1218 0 : if( FD_UNLIKELY( !snapshots_enabled ) ) {
1219 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "genesi", 0UL ) ], accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1220 0 : }
1221 0 : if( FD_LIKELY( snapshots_enabled ) ) {
1222 0 : fd_topo_obj_t * shmem_obj = fd_topob_obj( topo, "snapin_shmem", "snapin_shmem" );
1223 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, shmem_obj->id, "snapin_shmem" ) );
1224 :
1225 0 : fd_topo_obj_t * dc_ticket_obj = fd_topob_obj_named( topo, "fseq", "snapdc", "frame_ticket" );
1226 0 : FOR(snapdc_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapdc", i ) ], dc_ticket_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1227 :
1228 0 : FOR(snapin_tile_cnt) {
1229 0 : fd_topo_tile_t * snapin_tile = &topo->tiles[ fd_topo_find_tile( topo, "snapin", i ) ];
1230 0 : fd_topob_tile_uses( topo, snapin_tile, accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1231 0 : fd_topob_tile_uses( topo, snapin_tile, shmem_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1232 0 : }
1233 0 : }
1234 0 : fd_topo_obj_t * backup_obj = NULL;
1235 0 : if( snapmk_enabled ) {
1236 0 : ulong backup_obj_id = fd_pod_query_ulong( topo->props, "backup", ULONG_MAX );
1237 0 : FD_TEST( backup_obj_id!=ULONG_MAX );
1238 0 : backup_obj = &topo->objs[ backup_obj_id ];
1239 :
1240 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapmk", 0UL ) ], accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1241 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapmk", 0UL ) ], zp_fseq, FD_SHMEM_JOIN_MODE_READ_WRITE );
1242 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapmk", 0UL ) ], backup_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1243 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snaprd", 0UL ) ], accdb_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1244 0 : }
1245 0 : FOR(snapzp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapzp", i ) ], accdb_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1246 0 : FOR(snapzp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapzp", i ) ], zp_fseq, FD_SHMEM_JOIN_MODE_READ_WRITE );
1247 0 : FOR(snapzp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapzp", i ) ], backup_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1248 0 : if( snapmk_enabled ) {
1249 0 : ulong snaprd_out_link_id = fd_topo_find_link( topo, "snaprd_out", 0UL );
1250 0 : FD_TEST( snaprd_out_link_id!=ULONG_MAX );
1251 0 : fd_topo_obj_t * snaprd_out_dcache_obj = &topo->objs[ topo->links[ snaprd_out_link_id ].dcache_obj_id ];
1252 0 : FOR(snapzp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapzp", i ) ], snaprd_out_dcache_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1253 0 : }
1254 :
1255 0 : FOR(execle_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execle", i ) ], accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1256 0 : FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i ) ], accdb_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1257 0 : if( FD_UNLIKELY( rpc_enabled ) ) {
1258 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "rpc", 0UL ) ], accdb_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1259 0 : }
1260 0 : FOR(resolv_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "resolv", i ) ], accdb_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1261 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
1262 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "gui", 0UL ) ], accdb_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1263 0 : }
1264 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, accdb_obj->id, "accdb" ) );
1265 :
1266 : /* Each shred tile publishes the highest slot it relayed on turbine
1267 : (getMaxRetransmitSlot) into an fseq that rpc reads on request. */
1268 0 : if( FD_UNLIKELY( rpc_enabled ) ) {
1269 0 : fd_topo_tile_t * rpc_tile = &topo->tiles[ fd_topo_find_tile( topo, "rpc", 0UL ) ];
1270 0 : FOR(shred_tile_cnt) {
1271 0 : fd_topo_obj_t * fseq_obj = fd_topob_obj( topo, "fseq", "metric" );
1272 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ], fseq_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1273 0 : fd_topob_tile_uses( topo, rpc_tile, fseq_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1274 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, fseq_obj->id, "shred_rtx.%lu", i ) );
1275 0 : }
1276 0 : }
1277 :
1278 : /* Per-RO-joiner accdb epoch fseq objects. Each read-only accdb
1279 : consumer (e.g. the rpc tile) owns a small fseq that it writes its
1280 : current epoch into, so that the accdb compaction tile can defer
1281 : partition reclamation while the RO consumer is mid-read. The
1282 : accdb tile maps each of these fseqs read-only and passes the
1283 : pointer array to fd_accdb_new via external_epoch_slots[]. */
1284 0 : if( FD_UNLIKELY( rpc_enabled ) ) {
1285 0 : fd_topo_obj_t * fseq_obj = fd_topob_obj( topo, "fseq", "metric" );
1286 0 : fd_topo_tile_t * rpc_tile = &topo->tiles[ fd_topo_find_tile( topo, "rpc", 0UL ) ];
1287 0 : fd_topo_tile_t * accdb_tile = &topo->tiles[ fd_topo_find_tile( topo, "accdb", 0UL ) ];
1288 0 : fd_topob_tile_uses( topo, rpc_tile, fseq_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1289 0 : fd_topob_tile_uses( topo, accdb_tile, fseq_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1290 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, fseq_obj->id, "accdb_epoch.rpc" ) );
1291 0 : }
1292 0 : for( ulong i=0UL; i<resolv_tile_cnt; i++ ) {
1293 0 : fd_topo_obj_t * fseq_obj = fd_topob_obj( topo, "fseq", "metric" );
1294 0 : fd_topo_tile_t * resolv_tile = &topo->tiles[ fd_topo_find_tile( topo, "resolv", i ) ];
1295 0 : fd_topo_tile_t * accdb_tile = &topo->tiles[ fd_topo_find_tile( topo, "accdb", 0UL ) ];
1296 0 : fd_topob_tile_uses( topo, resolv_tile, fseq_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1297 0 : fd_topob_tile_uses( topo, accdb_tile, fseq_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1298 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, fseq_obj->id, "accdb_epoch.resolv.%lu", i ) );
1299 0 : }
1300 0 : for( ulong i=0UL; i<snapzp_tile_cnt; i++ ) {
1301 0 : fd_topo_obj_t * fseq_obj = fd_topob_obj( topo, "fseq", "metric" );
1302 0 : fd_topo_tile_t * snapzp_tile = &topo->tiles[ fd_topo_find_tile( topo, "snapzp", i ) ];
1303 0 : fd_topo_tile_t * accdb_tile = &topo->tiles[ fd_topo_find_tile( topo, "accdb", 0UL ) ];
1304 0 : fd_topob_tile_uses( topo, snapzp_tile, fseq_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1305 0 : fd_topob_tile_uses( topo, accdb_tile, fseq_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1306 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, fseq_obj->id, "accdb_epoch.snapzp.%lu", i ) );
1307 0 : }
1308 0 : if( snapmk_enabled ) {
1309 0 : fd_topo_obj_t * fseq_obj = fd_topob_obj( topo, "fseq", "metric" );
1310 0 : fd_topo_tile_t * snapmk_tile = &topo->tiles[ fd_topo_find_tile( topo, "snapmk", 0UL ) ];
1311 0 : fd_topo_tile_t * accdb_tile = &topo->tiles[ fd_topo_find_tile( topo, "accdb", 0UL ) ];
1312 0 : fd_topob_tile_uses( topo, snapmk_tile, fseq_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1313 0 : fd_topob_tile_uses( topo, accdb_tile, fseq_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1314 0 : FD_TEST( fd_pod_insert_ulong( topo->props, "accdb_epoch.snapmk", fseq_obj->id ) );
1315 0 : }
1316 :
1317 0 : fd_pod_insert_int( topo->props, "sandbox", config->development.sandbox ? 1 : 0 );
1318 :
1319 0 : fd_topob_waker( topo );
1320 :
1321 0 : fd_topob_sleep_finish( topo );
1322 :
1323 0 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
1324 0 : fd_topo_configure_tile( &topo->tiles[ i ], config );
1325 0 : if( FD_UNLIKELY( !strcmp( topo->tiles[ i ].name, "gui" ) ) ) topo->tiles[ i ].gui.tile_cnt = topo->tile_cnt;
1326 0 : if( FD_UNLIKELY( ( !strcmp( topo->tiles[ i ].name, "net" ) || !strcmp( topo->tiles[ i ].name, "sock" ) || !strcmp( topo->tiles[ i ].name, "mlx5" ) ) ) ) {
1327 0 : topo->tiles[ i ].net.votor_quic_client_listen_port = config->firedancer.development.votor.quic_client_listen_port;
1328 0 : topo->tiles[ i ].net.votor_quic_server_listen_port = config->firedancer.development.votor.quic_server_listen_port;
1329 0 : }
1330 0 : }
1331 :
1332 0 : if( FD_LIKELY( telemetry_enabled ) ) {
1333 0 : wire_event_links( topo );
1334 :
1335 0 : fd_topo_tile_t * event_tile = &topo->tiles[ fd_topo_find_tile( topo, "event", 0UL ) ];
1336 0 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
1337 0 : fd_topob_tile_uses( topo, event_tile, &topo->objs[ topo->tiles[ i ].metrics_obj_id ], FD_SHMEM_JOIN_MODE_READ_ONLY );
1338 0 : }
1339 0 : }
1340 :
1341 0 : if( FD_LIKELY( telemetry_enabled ) ) {
1342 0 : topo->resolved_config_json_len = fd_config_to_json( config, topo->resolved_config_json, sizeof(topo->resolved_config_json) );
1343 0 : topo->user_config_json_len = fd_config_user_toml_to_json( config, topo->user_config_json, sizeof(topo->user_config_json) );
1344 0 : }
1345 :
1346 0 : FOR(net_tile_cnt) fd_topos_net_tile_finish( topo, i );
1347 0 : fd_topob_finish( topo, CALLBACKS );
1348 0 : config->topo = *topo;
1349 0 : }
1350 :
1351 : static void
1352 : parse_listen_addr( char const * cstr,
1353 : char const * key,
1354 0 : fd_ip6_addr_t * out ) {
1355 0 : if( FD_UNLIKELY( !fd_cstr_to_ip46_addr( cstr, out ) ) )
1356 0 : FD_LOG_ERR(( "[%s] `%s` is not a valid IPv4 or IPv6 address", key, cstr ));
1357 0 : if( FD_UNLIKELY( fd_ip6_addr_is_scoped( out->addr ) && !out->scope_id ) )
1358 0 : FD_LOG_ERR(( "[%s] `%s` is scoped to a network interface, which must be named by a "
1359 0 : "zone ID (e.g. `%s%%eth0`)", key, cstr, cstr ));
1360 0 : }
1361 :
1362 : static int
1363 0 : wfs_hash_is_zero( fd_config_t const * config ) {
1364 0 : return !strcmp( config->firedancer.consensus.wait_for_supermajority_with_bank_hash, "" );
1365 0 : }
1366 :
1367 : static void
1368 : wfs_decode_bank_hash( fd_config_t const * config,
1369 0 : fd_hash_t * out ) {
1370 0 : if( FD_LIKELY( wfs_hash_is_zero( config ) ) ) {
1371 0 : memset( out->uc, 0, sizeof(fd_hash_t) );
1372 0 : } else if( FD_UNLIKELY( !fd_base58_decode_32( config->firedancer.consensus.wait_for_supermajority_with_bank_hash, out->uc ) ) ) {
1373 0 : FD_LOG_ERR(( "[consensus.wait_for_supermajority_with_bank_hash] failed to parse" ));
1374 0 : }
1375 0 : }
1376 :
1377 : void
1378 : fd_topo_configure_tile( fd_topo_tile_t * tile,
1379 0 : fd_config_t * config ) {
1380 0 : if( FD_UNLIKELY( !strcmp( tile->name, "metric" ) ) ) {
1381 :
1382 0 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.metric.prometheus_listen_address, &tile->metric.prometheus_listen_addr ) ) )
1383 0 : FD_LOG_ERR(( "failed to parse prometheus listen address `%s`", config->tiles.metric.prometheus_listen_address ));
1384 0 : tile->metric.prometheus_listen_port = config->tiles.metric.prometheus_listen_port;
1385 :
1386 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "event" ) ) ) {
1387 :
1388 0 : fd_cstr_ncpy( tile->event.identity_key_path, config->paths.identity_key, sizeof(tile->event.identity_key_path) );
1389 0 : fd_cstr_ncpy( tile->event.url, config->tiles.event.url, sizeof(tile->event.url) );
1390 0 : fd_cstr_ncpy( tile->event.action, config->action, sizeof(tile->event.action) );
1391 0 : FD_TEST( fd_cstr_printf_check( tile->event.accounts_path, sizeof(tile->event.accounts_path), NULL, "%s", config->paths.accounts ) );
1392 0 : FD_TEST( fd_cstr_printf_check( tile->event.snapshots_path, sizeof(tile->event.snapshots_path), NULL, "%s", config->paths.snapshots ) );
1393 0 : FD_TEST( fd_cstr_printf_check( tile->event.log_path, sizeof(tile->event.log_path), NULL, "%s", config->log.path ) );
1394 0 : FD_TEST( fd_cstr_printf_check( tile->event.shredb_path, sizeof(tile->event.shredb_path), NULL, "%s", config->paths.shredb ) );
1395 0 : FD_TEST( fd_cstr_printf_check( tile->event.guidb_path, sizeof(tile->event.guidb_path), NULL, "%s", config->paths.guidb ) );
1396 0 : FD_TEST( fd_cstr_printf_check( tile->event.net_interface, sizeof(tile->event.net_interface), NULL, "%s", config->net.interface ) );
1397 0 : tile->event.boot_timestamp_nanos = config->boot_timestamp_nanos;
1398 0 : fd_memcpy( tile->event.launch_cpus, config->launch_cpus, sizeof(tile->event.launch_cpus) );
1399 0 : FD_TEST( fd_cstr_printf_check( tile->event.launch_cgroup, sizeof(tile->event.launch_cgroup), NULL, "%s", config->launch_cgroup ) );
1400 :
1401 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "net" ) ||
1402 0 : !strcmp( tile->name, "sock" ) ||
1403 0 : !strcmp( tile->name, "mlx5" ) ) ) {
1404 :
1405 0 : tile->net.shred_listen_port = config->tiles.shred.shred_listen_port;
1406 0 : if( config->firedancer.layout.enable_block_production ) {
1407 0 : tile->net.quic_transaction_listen_port = config->tiles.quic.quic_transaction_listen_port;
1408 0 : tile->net.legacy_transaction_listen_port = config->tiles.quic.regular_transaction_listen_port;
1409 0 : }
1410 0 : tile->net.gossip_listen_port = config->gossip.port;
1411 0 : tile->net.repair_client_listen_port = config->tiles.repair.repair_client_listen_port;
1412 0 : tile->net.repair_serve_listen_port = fd_ushort_if( config->tiles.rserve.enabled, config->tiles.rserve.repair_serve_listen_port, 0 );
1413 :
1414 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "netlnk" ) ) ) {
1415 :
1416 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "ipecho") ) ) {
1417 :
1418 0 : tile->ipecho.expected_shred_version = config->consensus.expected_shred_version;
1419 0 : tile->ipecho.bind_address = config->net.ip_addr;
1420 0 : tile->ipecho.bind_port = config->gossip.port;
1421 0 : tile->ipecho.entrypoints_cnt = config->gossip.entrypoints_cnt;
1422 0 : for( ulong i=0UL; i<tile->ipecho.entrypoints_cnt; i++ )
1423 0 : fd_cstr_ncpy( tile->ipecho.entrypoints[ i ], config->gossip.entrypoints[ i ], sizeof(tile->ipecho.entrypoints[ i ]) );
1424 :
1425 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "genesi" ) ) ) {
1426 :
1427 0 : tile->genesi.validate_genesis_hash = config->firedancer.development.genesis.validate_genesis_hash;
1428 0 : tile->genesi.allow_download = config->firedancer.snapshots.genesis_download;
1429 0 : fd_cstr_ncpy( tile->genesi.genesis_path, config->paths.genesis, sizeof(tile->genesi.genesis_path) );
1430 0 : tile->genesi.expected_shred_version = config->consensus.expected_shred_version;
1431 0 : tile->genesi.entrypoints_cnt = config->gossip.entrypoints_cnt;
1432 0 : for( ulong i=0UL; i<tile->genesi.entrypoints_cnt; i++ )
1433 0 : fd_cstr_ncpy( tile->genesi.entrypoints[ i ], config->gossip.entrypoints[ i ], sizeof(tile->genesi.entrypoints[ i ]) );
1434 :
1435 0 : tile->genesi.has_expected_genesis_hash = !!strcmp( config->consensus.expected_genesis_hash, "" );
1436 :
1437 0 : if( FD_UNLIKELY( strcmp( config->consensus.expected_genesis_hash, "" ) && !fd_base58_decode_32( config->consensus.expected_genesis_hash, tile->genesi.expected_genesis_hash ) ) ) {
1438 0 : FD_LOG_ERR(( "failed to decode [consensus.expected_genesis_hash] \"%s\" as base58", config->consensus.expected_genesis_hash ));
1439 0 : }
1440 :
1441 0 : tile->genesi.target_gid = config->gid;
1442 0 : tile->genesi.target_uid = config->uid;
1443 :
1444 0 : tile->genesi.max_live_slots = config->firedancer.runtime.max_live_slots;
1445 0 : tile->genesi.accdb_obj_id = fd_pod_query_ulong( config->topo.props, "accdb", ULONG_MAX );
1446 0 : tile->genesi.max_message_size = config->firedancer.development.genesis.max_file_size_mib << 20;
1447 0 : FD_TEST( tile->genesi.accdb_obj_id!=ULONG_MAX );
1448 :
1449 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "admin" ) ) ) {
1450 :
1451 0 : fd_cstr_ncpy( tile->admin.identity_key_path, config->paths.identity_key, sizeof(tile->admin.identity_key_path) );
1452 :
1453 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "gossvf") ) ) {
1454 :
1455 0 : fd_cstr_ncpy( tile->gossvf.identity_key_path, config->paths.identity_key, sizeof(tile->gossvf.identity_key_path) );
1456 0 : tile->gossvf.tcache_depth = 1<<22UL; /* TODO: user defined option */
1457 0 : tile->gossvf.shred_version = 0U;
1458 0 : tile->gossvf.allow_private_address = config->development.gossip.allow_private_address;
1459 0 : tile->gossvf.boot_timestamp_nanos = config->boot_timestamp_nanos;
1460 :
1461 0 : tile->gossvf.entrypoints_cnt = config->gossip.entrypoints_cnt;
1462 0 : for( ulong i=0UL; i<tile->gossvf.entrypoints_cnt; i++ ) {
1463 0 : fd_cstr_ncpy( tile->gossvf.entrypoints[ i ], config->gossip.entrypoints[ i ], sizeof(tile->gossvf.entrypoints[ i ]) );
1464 0 : }
1465 :
1466 0 : fd_cstr_ncpy( tile->gossvf.gossip_host, config->firedancer.gossip.host, sizeof(tile->gossvf.gossip_host) );
1467 0 : tile->gossvf.gossip_addr.addr = config->net.ip_addr;
1468 0 : tile->gossvf.gossip_addr.port = fd_ushort_bswap( config->gossip.port );
1469 :
1470 0 : tile->gossvf.src_addr.addr = config->net.ip_addr;
1471 0 : tile->gossvf.src_addr.port = fd_ushort_bswap( config->gossip.port );
1472 :
1473 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "gossip" ) ) ) {
1474 :
1475 0 : fd_cstr_ncpy( tile->gossip.gossip_host, config->firedancer.gossip.host, sizeof(tile->gossip.gossip_host) );
1476 0 : tile->gossip.net_ip_addr = config->net.ip_addr;
1477 0 : tile->gossip.ip_addr = config->net.ip_addr;
1478 0 : tile->gossip.bind_ip_addr = config->net.ip_addr;
1479 0 : fd_cstr_ncpy( tile->gossip.identity_key_path, config->paths.identity_key, sizeof(tile->gossip.identity_key_path) );
1480 0 : tile->gossip.expected_shred_version = config->consensus.expected_shred_version;
1481 0 : tile->gossip.max_entries = config->tiles.gossip.max_entries;
1482 0 : tile->gossip.boot_timestamp_nanos = config->boot_timestamp_nanos;
1483 :
1484 0 : tile->gossip.wait_for_supermajority_at_slot = config->firedancer.consensus.wait_for_supermajority_at_slot;
1485 0 : tile->gossip.wait_for_supermajority_hash_is_zero = wfs_hash_is_zero( config );
1486 :
1487 0 : tile->gossip.ports.gossip = config->gossip.port;
1488 0 : tile->gossip.ports.tvu = config->tiles.shred.shred_listen_port;
1489 0 : tile->gossip.ports.tpu = config->tiles.quic.regular_transaction_listen_port;
1490 0 : tile->gossip.ports.tpu_quic = config->tiles.quic.quic_transaction_listen_port;
1491 0 : tile->gossip.ports.repair = config->tiles.repair.repair_client_listen_port;
1492 0 : tile->gossip.ports.rserve = fd_ushort_if( config->tiles.rserve.enabled, config->tiles.rserve.repair_serve_listen_port, 0 );
1493 0 : tile->gossip.ports.votor = config->firedancer.development.votor.quic_server_listen_port;
1494 :
1495 0 : tile->gossip.entrypoints_cnt = config->gossip.entrypoints_cnt;
1496 0 : for( ulong i=0UL; i<tile->gossip.entrypoints_cnt; i++ ) {
1497 0 : fd_cstr_ncpy( tile->gossip.entrypoints[ i ], config->gossip.entrypoints[ i ], sizeof(tile->gossip.entrypoints[ i ]) );
1498 0 : }
1499 :
1500 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapct" ) ) ) {
1501 :
1502 0 : fd_memcpy( tile->snapct.snapshots_path, config->paths.snapshots, PATH_MAX );
1503 0 : tile->snapct.entrypoints_cnt = fd_ulong_min( config->gossip.entrypoints_cnt, FD_TOPO_GOSSIP_ENTRYPOINTS_MAX );
1504 0 : for( ulong i=0UL; i<tile->snapct.entrypoints_cnt; i++ ) {
1505 0 : fd_cstr_ncpy( tile->snapct.entrypoints[ i ], config->gossip.entrypoints[ i ], sizeof(tile->snapct.entrypoints[ i ]) );
1506 0 : }
1507 0 : tile->snapct.sources.max_local_full_effective_age = config->firedancer.snapshots.sources.max_local_full_effective_age;
1508 0 : tile->snapct.sources.max_local_incremental_age = config->firedancer.snapshots.sources.max_local_incremental_age;
1509 0 : tile->snapct.incremental_snapshots = config->firedancer.snapshots.incremental_snapshots;
1510 0 : tile->snapct.max_full_snapshots_to_keep = config->firedancer.snapshots.max_full_snapshots_to_keep;
1511 0 : tile->snapct.max_incremental_snapshots_to_keep = config->firedancer.snapshots.max_incremental_snapshots_to_keep;
1512 0 : tile->snapct.max_retry_abort = config->firedancer.snapshots.max_retry_abort;
1513 0 : tile->snapct.wait_for_peers_timeout_nanos = (long)( config->firedancer.snapshots.wait_for_peers_timeout_seconds * (ulong)1e9 );
1514 0 : tile->snapct.wfs_slot = config->firedancer.consensus.wait_for_supermajority_at_slot;
1515 0 : tile->snapct.wfs_hash_is_zero = wfs_hash_is_zero( config );
1516 0 : tile->snapct.wfs_shred_version = config->consensus.expected_shred_version;
1517 0 : tile->snapct.sources.gossip.allow_any = config->firedancer.snapshots.sources.gossip.allow_any;
1518 0 : tile->snapct.sources.gossip.allow_list_cnt = config->firedancer.snapshots.sources.gossip.allow_list_cnt;
1519 0 : tile->snapct.sources.gossip.block_list_cnt = config->firedancer.snapshots.sources.gossip.block_list_cnt;
1520 0 : tile->snapct.sources.servers_cnt = config->firedancer.snapshots.sources.servers_cnt;
1521 0 : for( ulong i=0UL; i<tile->snapct.sources.gossip.allow_list_cnt; i++ ) {
1522 0 : if( FD_UNLIKELY( !fd_base58_decode_32( config->firedancer.snapshots.sources.gossip.allow_list[ i ], tile->snapct.sources.gossip.allow_list[ i ].uc ) ) ) {
1523 0 : FD_LOG_ERR(( "[snapshots.sources.gossip.allow_list[%lu]] invalid (%s)", i, config->firedancer.snapshots.sources.gossip.allow_list[ i ] ));
1524 0 : }
1525 0 : }
1526 0 : for( ulong i=0UL; i<tile->snapct.sources.gossip.block_list_cnt; i++ ) {
1527 0 : if( FD_UNLIKELY( !fd_base58_decode_32( config->firedancer.snapshots.sources.gossip.block_list[ i ], tile->snapct.sources.gossip.block_list[ i ].uc ) ) ) {
1528 0 : FD_LOG_ERR(( "[snapshots.sources.gossip.block_list[%lu]] invalid (%s)", i, config->firedancer.snapshots.sources.gossip.block_list[ i ] ));
1529 0 : }
1530 0 : }
1531 :
1532 0 : for( ulong i=0UL; i<tile->snapct.sources.servers_cnt; i++ ) {
1533 0 : fd_cstr_ncpy( tile->snapct.sources.servers[ i ],
1534 0 : config->firedancer.snapshots.sources.servers[ i ],
1535 0 : sizeof(tile->snapct.sources.servers[ i ]) );
1536 0 : }
1537 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapld" ) ) ) {
1538 :
1539 0 : fd_memcpy( tile->snapld.snapshots_path, config->paths.snapshots, PATH_MAX );
1540 0 : tile->snapld.incremental_snapshots = config->firedancer.snapshots.incremental_snapshots;
1541 0 : tile->snapld.min_download_speed_mibs = config->firedancer.snapshots.min_download_speed_mibs;
1542 0 : tile->snapld.wfs_slot = config->firedancer.consensus.wait_for_supermajority_at_slot;
1543 0 : tile->snapld.wfs_hash_is_zero = wfs_hash_is_zero( config );
1544 0 : tile->snapld.wfs_shred_version = config->consensus.expected_shred_version;
1545 :
1546 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapdc" ) ) ) {
1547 :
1548 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapin" ) ) ) {
1549 :
1550 0 : tile->snapin.wait_for_supermajority_at_slot = config->firedancer.consensus.wait_for_supermajority_at_slot;
1551 0 : wfs_decode_bank_hash( config, &tile->snapin.wait_for_supermajority_with_bank_hash );
1552 0 : tile->snapin.expected_shred_version = config->consensus.expected_shred_version;
1553 0 : tile->snapin.max_live_slots = config->firedancer.runtime.max_live_slots;
1554 0 : tile->snapin.max_txn_per_slot = config->limits.max_txn_per_slot;
1555 0 : tile->snapin.alpenglow = 1;
1556 0 : tile->snapin.accdb_obj_id = fd_pod_query_ulong( config->topo.props, "accdb", ULONG_MAX );
1557 0 : tile->snapin.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX );
1558 0 : tile->snapin.banks_obj_id = fd_pod_query_ulong( config->topo.props, "banks", ULONG_MAX );
1559 0 : tile->snapin.shmem_obj_id = fd_pod_query_ulong( config->topo.props, "snapin_shmem", ULONG_MAX );
1560 :
1561 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "rotor" ) ) ) {
1562 0 : tile->rotor.slot_max = config->firedancer.runtime.max_live_slots;
1563 0 : tile->rotor.fec_max = fd_pod_queryf_ulong( config->topo.props, ULONG_MAX, "obj.%lu.fec_max", fd_pod_query_ulong( config->topo.props, "store", ULONG_MAX ) ); /* as many FEC sets as Store */
1564 0 : tile->rotor.max_shreds_per_block = config->limits.max_shreds_per_block;
1565 0 : tile->rotor.repair_client_listen_port = config->tiles.repair.repair_client_listen_port;
1566 0 : tile->rotor.allow_private_address = config->development.gossip.allow_private_address;
1567 :
1568 0 : for( ulong i=0; i<tile->in_cnt; i++ ) {
1569 0 : if( !strcmp( config->topo.links[ tile->in_link_id[ i ] ].name, "sign_repair" ) ) {
1570 0 : tile->rotor.repair_sign_depth = config->topo.links[ tile->in_link_id[ i ] ].depth;
1571 0 : break;
1572 0 : }
1573 0 : }
1574 0 : tile->rotor.repair_sign_cnt = config->firedancer.layout.sign_tile_count - 1; /* -1 because this excludes the keyguard client */
1575 0 : fd_cstr_ncpy( tile->rotor.identity_key_path, config->paths.identity_key, sizeof(tile->rotor.identity_key_path) );
1576 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "rserve" ) ) ) {
1577 0 : tile->rserve.repair_serve_listen_port = config->tiles.rserve.repair_serve_listen_port;
1578 0 : tile->rserve.max_shreds_per_block = config->limits.max_shreds_per_block;
1579 0 : tile->rserve.ping_cache_entries = 1UL<<16; /* TODO: Configure this from some global metric? */
1580 0 : tile->rserve.blockdb_max = 1UL<<15; /* ~20.6 KiB each. TODO: make configurable */
1581 0 : fd_cstr_ncpy( tile->rserve.identity_key_path, config->paths.identity_key, sizeof(tile->rserve.identity_key_path) );
1582 :
1583 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "replay" ) )) {
1584 :
1585 : /* Please maintain same field order as fd_topo.h */
1586 :
1587 0 : tile->replay.fec_max = config->firedancer.runtime.max_live_slots *
1588 0 : fd_ulong_if( config->firedancer.development.fixed_fec_sets,
1589 0 : config->limits.max_shreds_per_block/FD_FEC_SHRED_CNT, config->limits.max_shreds_per_block );
1590 0 : tile->replay.boot_timestamp_nanos = config->boot_timestamp_nanos;
1591 :
1592 0 : tile->replay.accdb_obj_id = fd_pod_query_ulong( config->topo.props, "accdb", ULONG_MAX );
1593 0 : FD_TEST( tile->replay.accdb_obj_id !=ULONG_MAX );
1594 0 : tile->replay.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX );
1595 0 : FD_TEST( tile->replay.txncache_obj_id !=ULONG_MAX );
1596 :
1597 0 : fd_cstr_ncpy( tile->replay.identity_key_path, config->paths.identity_key, sizeof(tile->replay.identity_key_path) );
1598 0 : tile->replay.ip_addr = config->net.ip_addr;
1599 0 : fd_cstr_ncpy( tile->replay.vote_account_path, config->paths.vote_account, sizeof(tile->replay.vote_account_path) );
1600 :
1601 0 : tile->replay.expected_shred_version = config->consensus.expected_shred_version;
1602 0 : tile->replay.wait_for_vote_to_start_leader = config->consensus.wait_for_vote_to_start_leader;
1603 0 : tile->replay.alpenglow = 1;
1604 :
1605 0 : tile->replay.sched_depth = config->tiles.replay.max_transaction_lookahead_buffer_size;
1606 0 : wfs_decode_bank_hash( config, &tile->replay.wait_for_supermajority_with_bank_hash );
1607 0 : tile->replay.wait_for_supermajority_at_slot = config->firedancer.consensus.wait_for_supermajority_at_slot;
1608 :
1609 0 : tile->replay.max_live_slots = config->firedancer.runtime.max_live_slots;
1610 0 : tile->replay.genesis_max_message_size = config->firedancer.development.genesis.max_file_size_mib << 20;
1611 0 : tile->replay.full_snapshot_interval_blocks = config->firedancer.snapshots.full_snapshot_interval_blocks;
1612 0 : tile->replay.incremental_snapshot_interval_blocks = config->firedancer.snapshots.incremental_snapshot_interval_blocks;
1613 :
1614 0 : fd_cstr_ncpy( tile->replay.genesis_path, config->paths.genesis, sizeof(tile->replay.genesis_path) );
1615 :
1616 0 : tile->replay.max_txn_per_slot = config->limits.max_txn_per_slot;
1617 0 : tile->replay.max_shreds_per_block = config->limits.max_shreds_per_block;
1618 :
1619 : /* not specified by [tiles.replay] */
1620 :
1621 0 : tile->replay.capture_start_slot = config->capture.capture_start_slot;
1622 0 : fd_cstr_ncpy( tile->replay.solcap_capture, config->capture.solcap_capture, sizeof(tile->replay.solcap_capture) );
1623 0 : fd_cstr_ncpy( tile->replay.dump_proto_dir, config->capture.dump_proto_dir, sizeof(tile->replay.dump_proto_dir) );
1624 0 : tile->replay.dump_block_to_pb = config->capture.dump_block_to_pb;
1625 0 : tile->replay.report_runtime_diffs = config->development.event.report_runtime_diffs;
1626 :
1627 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1628 0 : #define PARSE_BUNDLE_PUBKEY( _tile, f ) \
1629 0 : if( FD_UNLIKELY( !fd_base58_decode_32( config->tiles.bundle.f, tile->_tile.bundle.f ) ) ) \
1630 0 : FD_LOG_ERR(( "[tiles.bundle.enabled] set to true, but failed to parse [tiles.bundle."#f"] %s", config->tiles.bundle.f ));
1631 0 : tile->replay.bundle.enabled = 1;
1632 0 : PARSE_BUNDLE_PUBKEY( replay, tip_distribution_program_addr );
1633 0 : PARSE_BUNDLE_PUBKEY( replay, tip_payment_program_addr );
1634 0 : fd_cstr_ncpy( tile->replay.bundle.vote_account_path, config->paths.vote_account, sizeof(tile->replay.bundle.vote_account_path) );
1635 0 : } else {
1636 0 : fd_memset( &tile->replay.bundle, '\0', sizeof(tile->replay.bundle) );
1637 0 : }
1638 :
1639 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "execrp" ) ) ) {
1640 :
1641 0 : tile->execrp.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX ); FD_TEST( tile->execrp.txncache_obj_id !=ULONG_MAX );
1642 0 : tile->execrp.progcache_obj_id = fd_pod_query_ulong( config->topo.props, "progcache", ULONG_MAX ); FD_TEST( tile->execrp.progcache_obj_id!=ULONG_MAX );
1643 0 : tile->execrp.accdb_obj_id = fd_pod_query_ulong( config->topo.props, "accdb", ULONG_MAX ); FD_TEST( tile->execrp.accdb_obj_id !=ULONG_MAX );
1644 :
1645 0 : tile->execrp.max_live_slots = config->firedancer.runtime.max_live_slots;
1646 :
1647 0 : tile->execrp.capture_start_slot = config->capture.capture_start_slot;
1648 0 : fd_cstr_ncpy( tile->execrp.solcap_capture, config->capture.solcap_capture, sizeof(tile->execrp.solcap_capture) );
1649 0 : fd_cstr_ncpy( tile->execrp.dump_proto_dir, config->capture.dump_proto_dir, sizeof(tile->execrp.dump_proto_dir) );
1650 0 : fd_cstr_ncpy( tile->execrp.dump_syscall_name_filter, config->capture.dump_syscall_name_filter, sizeof(tile->execrp.dump_syscall_name_filter) );
1651 0 : fd_cstr_ncpy( tile->execrp.dump_instr_program_id_filter, config->capture.dump_instr_program_id_filter, sizeof(tile->execrp.dump_instr_program_id_filter) );
1652 0 : tile->execrp.dump_instr_to_pb = config->capture.dump_instr_to_pb;
1653 0 : tile->execrp.dump_txn_to_pb = config->capture.dump_txn_to_pb;
1654 0 : tile->execrp.dump_txn_as_fixture = config->capture.dump_txn_as_fixture;
1655 0 : tile->execrp.dump_syscall_to_pb = config->capture.dump_syscall_to_pb;
1656 0 : tile->execrp.report_runtime_diffs = config->development.event.report_runtime_diffs;
1657 :
1658 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "votor" ) ) ) {
1659 0 : tile->votor.quic_client_listen_port = config->firedancer.development.votor.quic_client_listen_port;
1660 0 : tile->votor.quic_server_listen_port = config->firedancer.development.votor.quic_server_listen_port;
1661 0 : tile->votor.ip_addr = config->net.ip_addr;
1662 0 : tile->votor.max_live_slots = config->firedancer.runtime.max_live_slots;
1663 0 : fd_cstr_ncpy( tile->votor.identity_key_path, config->paths.identity_key, sizeof(tile->votor.identity_key_path) );
1664 0 : fd_cstr_ncpy( tile->votor.vote_history_path, config->paths.vote_history, sizeof(tile->votor.vote_history_path) );
1665 0 : tile->votor.target_gid = config->gid;
1666 0 : tile->votor.target_uid = config->uid;
1667 0 : tile->votor.authorized_voter_paths_cnt = config->firedancer.paths.authorized_voter_paths_cnt;
1668 0 : tile->votor.wait_for_supermajority_at_slot = config->firedancer.consensus.wait_for_supermajority_at_slot;
1669 0 : tile->votor.wait_for_supermajority_hash_is_zero = wfs_hash_is_zero( config );
1670 0 : tile->votor.expected_shred_version = config->consensus.expected_shred_version;
1671 :
1672 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "accdb" ) ) ) {
1673 :
1674 0 : tile->accdb.accdb_obj_id = fd_pod_query_ulong( config->topo.props, "accdb", ULONG_MAX );
1675 0 : tile->accdb.max_live_slots = config->firedancer.runtime.max_live_slots;
1676 :
1677 0 : tile->accdb.rpc_epoch_obj_id = fd_pod_query_ulong( config->topo.props, "accdb_epoch.rpc", ULONG_MAX );
1678 :
1679 0 : tile->accdb.resolv_epoch_obj_cnt = config->firedancer.layout.enable_block_production ? config->firedancer.layout.resolv_tile_count : 0UL;
1680 0 : FD_TEST( tile->accdb.resolv_epoch_obj_cnt<=sizeof(tile->accdb.resolv_epoch_obj_ids)/sizeof(tile->accdb.resolv_epoch_obj_ids[0]) );
1681 0 : for( ulong i=0UL; i<tile->accdb.resolv_epoch_obj_cnt; i++ ) {
1682 0 : tile->accdb.resolv_epoch_obj_ids[ i ] = fd_pod_queryf_ulong( config->topo.props, ULONG_MAX, "accdb_epoch.resolv.%lu", i );
1683 0 : FD_TEST( tile->accdb.resolv_epoch_obj_ids[ i ]!=ULONG_MAX );
1684 0 : }
1685 :
1686 0 : tile->accdb.snapmk_epoch_obj_id = fd_pod_query_ulong( config->topo.props, "accdb_epoch.snapmk", ULONG_MAX );
1687 :
1688 0 : tile->accdb.snapzp_epoch_obj_cnt = config->firedancer.layout.enable_snapshot_production
1689 0 : ? config->firedancer.layout.snapzp_tile_count : 0UL;
1690 0 : FD_TEST( tile->accdb.snapzp_epoch_obj_cnt<=sizeof(tile->accdb.snapzp_epoch_obj_ids)/sizeof(tile->accdb.snapzp_epoch_obj_ids[0]) );
1691 0 : for( ulong i=0UL; i<tile->accdb.snapzp_epoch_obj_cnt; i++ ) {
1692 0 : tile->accdb.snapzp_epoch_obj_ids[ i ] = fd_pod_queryf_ulong( config->topo.props, ULONG_MAX, "accdb_epoch.snapzp.%lu", i );
1693 : /* might not exist for topos without snapshot creation */
1694 0 : }
1695 :
1696 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "quic" ) ) ) {
1697 :
1698 0 : tile->quic.reasm_cnt = config->tiles.quic.txn_reassembly_count;
1699 0 : tile->quic.out_depth = config->tiles.verify.receive_buffer_size;
1700 0 : tile->quic.max_concurrent_connections = config->tiles.quic.max_concurrent_connections;
1701 0 : tile->quic.max_concurrent_handshakes = config->tiles.quic.max_concurrent_handshakes;
1702 0 : tile->quic.quic_transaction_listen_port = config->tiles.quic.quic_transaction_listen_port;
1703 0 : tile->quic.idle_timeout_millis = config->tiles.quic.idle_timeout_millis;
1704 0 : tile->quic.ack_delay_millis = config->tiles.quic.ack_delay_millis;
1705 0 : tile->quic.retry = config->tiles.quic.retry;
1706 0 : fd_cstr_fini( fd_cstr_append_cstr_safe( fd_cstr_init( tile->quic.key_log_path ), config->tiles.quic.ssl_key_log_file, sizeof(tile->quic.key_log_path) ) );
1707 :
1708 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "verify" ) ) ) {
1709 :
1710 0 : tile->verify.tcache_depth = config->tiles.verify.signature_cache_size;
1711 :
1712 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "dedup" ) ) ) {
1713 :
1714 0 : tile->dedup.tcache_depth = config->tiles.dedup.signature_cache_size;
1715 :
1716 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "resolv" ) ) ) {
1717 :
1718 0 : tile->resolv.max_live_slots = config->firedancer.runtime.max_live_slots;
1719 0 : tile->resolv.accdb_obj_id = fd_pod_query_ulong( config->topo.props, "accdb", ULONG_MAX );
1720 0 : FD_TEST( tile->resolv.accdb_obj_id!=ULONG_MAX );
1721 0 : tile->resolv.accdb_epoch_fseq_obj_id = fd_pod_queryf_ulong( config->topo.props, ULONG_MAX, "accdb_epoch.resolv.%lu", tile->kind_id );
1722 0 : FD_TEST( tile->resolv.accdb_epoch_fseq_obj_id!=ULONG_MAX );
1723 :
1724 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "pack" ) ) ) {
1725 :
1726 0 : tile->pack.max_pending_transactions = config->tiles.pack.max_pending_transactions;
1727 0 : tile->pack.execle_tile_count = config->firedancer.layout.execle_tile_count;
1728 0 : tile->pack.max_cost_per_block = config->limits.max_cost_per_block;
1729 0 : tile->pack.max_shreds_per_block = config->limits.max_shreds_per_block;
1730 0 : tile->pack.bench_max_shreds_per_block = config->development.bench.max_shreds_per_block;
1731 0 : tile->pack.use_consumed_cus = config->tiles.pack.use_consumed_cus;
1732 0 : tile->pack.schedule_strategy = config->tiles.pack.schedule_strategy_enum;
1733 0 : tile->pack.acct_blocklist_cnt = config->tiles.pack.account_blocklist_cnt;
1734 :
1735 0 : for( ulong i=0UL; i<tile->pack.acct_blocklist_cnt; i++ ) {
1736 0 : if( FD_UNLIKELY( NULL==fd_base58_decode_32( config->tiles.pack.account_blocklist[i], tile->pack.acct_blocklist[i].uc ) ) ) {
1737 0 : FD_LOG_ERR(( "could not parse account %s at index %lu in [tiles.pack.account_blocklist]", config->tiles.pack.account_blocklist[i], i ));
1738 0 : }
1739 0 : }
1740 :
1741 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1742 :
1743 0 : tile->pack.bundle.enabled = 1;
1744 0 : PARSE_BUNDLE_PUBKEY( pack, tip_distribution_program_addr );
1745 0 : PARSE_BUNDLE_PUBKEY( pack, tip_payment_program_addr );
1746 0 : PARSE_BUNDLE_PUBKEY( pack, tip_distribution_authority );
1747 0 : tile->pack.bundle.commission_bps = config->tiles.bundle.commission_bps;
1748 0 : fd_cstr_ncpy( tile->pack.bundle.identity_key_path, config->paths.identity_key, sizeof(tile->pack.bundle.identity_key_path) );
1749 0 : fd_cstr_ncpy( tile->pack.bundle.vote_account_path, config->paths.vote_account, sizeof(tile->pack.bundle.vote_account_path) );
1750 0 : } else {
1751 0 : fd_memset( &tile->pack.bundle, '\0', sizeof(tile->pack.bundle) );
1752 0 : }
1753 :
1754 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "execle" ) ) ) {
1755 :
1756 0 : tile->execle.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX ); FD_TEST( tile->execle.txncache_obj_id !=ULONG_MAX );
1757 0 : tile->execle.progcache_obj_id = fd_pod_query_ulong( config->topo.props, "progcache", ULONG_MAX ); FD_TEST( tile->execle.progcache_obj_id!=ULONG_MAX );
1758 0 : tile->execle.accdb_obj_id = fd_pod_query_ulong( config->topo.props, "accdb", ULONG_MAX ); FD_TEST( tile->execle.accdb_obj_id !=ULONG_MAX );
1759 0 : tile->execle.max_live_slots = config->firedancer.runtime.max_live_slots;
1760 0 : tile->execle.report_runtime_diffs = config->development.event.report_runtime_diffs;
1761 :
1762 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "motor" ) ) ) {
1763 0 : fd_cstr_ncpy( tile->motor.identity_key_path, config->paths.identity_key, sizeof(tile->motor.identity_key_path) );
1764 :
1765 0 : tile->motor.execle_cnt = config->firedancer.layout.execle_tile_count;
1766 0 : tile->motor.max_txn_per_slot = config->limits.max_txn_per_slot;
1767 :
1768 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "shred" ) ) ) {
1769 :
1770 0 : fd_cstr_ncpy( tile->shred.identity_key_path, config->paths.identity_key, sizeof(tile->shred.identity_key_path) );
1771 :
1772 0 : tile->shred.fec_exposure = FD_SHRED_FIREDANCER_FEC_EXPOSURE;
1773 0 : tile->shred.fec_resolver_depth = config->tiles.shred.max_pending_shred_sets;
1774 0 : tile->shred.slot_max = config->firedancer.runtime.max_live_slots;
1775 0 : tile->shred.expected_shred_version = config->consensus.expected_shred_version;
1776 0 : tile->shred.shred_listen_port = config->tiles.shred.shred_listen_port;
1777 0 : tile->shred.max_shreds_per_block = config->limits.max_shreds_per_block;
1778 0 : tile->shred.alpenglow = 1;
1779 0 : tile->shred.bench_max_shreds_per_block = config->development.bench.max_shreds_per_block;
1780 0 : tile->shred.adtl_dests_retransmit_cnt = config->tiles.shred.additional_shred_destinations_retransmit_cnt;
1781 0 : tile->shred.adtl_dests_leader_cnt = config->tiles.shred.additional_shred_destinations_leader_cnt;
1782 0 : fd_memcpy( tile->shred.adtl_dests_retransmit, config->tiles.shred.additional_shred_destinations_retransmit,
1783 0 : tile->shred.adtl_dests_retransmit_cnt*sizeof(tile->shred.adtl_dests_retransmit[ 0 ]) );
1784 0 : fd_memcpy( tile->shred.adtl_dests_leader, config->tiles.shred.additional_shred_destinations_leader,
1785 0 : tile->shred.adtl_dests_leader_cnt*sizeof(tile->shred.adtl_dests_leader[ 0 ]) );
1786 :
1787 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "sign" ) ) ) {
1788 :
1789 0 : fd_cstr_ncpy( tile->sign.identity_key_path, config->paths.identity_key, sizeof(tile->sign.identity_key_path) );
1790 :
1791 0 : tile->sign.authorized_voter_paths_cnt = config->firedancer.paths.authorized_voter_paths_cnt;
1792 0 : for( ulong i=0UL; i<tile->sign.authorized_voter_paths_cnt; i++ ) {
1793 0 : fd_cstr_ncpy( tile->sign.authorized_voter_paths[ i ], config->firedancer.paths.authorized_voter_paths[ i ], sizeof(tile->sign.authorized_voter_paths[ i ]) );
1794 0 : }
1795 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1796 0 : PARSE_BUNDLE_PUBKEY( sign, tip_distribution_program_addr );
1797 0 : PARSE_BUNDLE_PUBKEY( sign, tip_payment_program_addr );
1798 0 : } else {
1799 : /* 0xFF.. is not an invocable program */
1800 0 : memset( tile->sign.bundle.tip_distribution_program_addr, '\xFF', 32UL );
1801 0 : memset( tile->sign.bundle.tip_payment_program_addr, '\xFF', 32UL );
1802 0 : }
1803 :
1804 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "diag" ) ) ) {
1805 :
1806 0 : tile->diag.is_voting = strcmp( config->paths.vote_account, "" );
1807 :
1808 0 : fd_cstr_ncpy( tile->diag.shreds_path, config->tiles.rserve.enabled ? config->paths.shredb : "", sizeof(tile->diag.shreds_path) );
1809 0 : fd_cstr_ncpy( tile->diag.snapshots_path, config->firedancer.layout.enable_snapshot_production ? config->paths.snapshots : "", sizeof(tile->diag.snapshots_path) );
1810 0 : fd_cstr_ncpy( tile->diag.accounts_path, config->paths.accounts, sizeof(tile->diag.accounts_path) );
1811 0 : fd_cstr_ncpy( tile->diag.gui_path, config->paths.guidb, sizeof(tile->diag.gui_path) );
1812 0 : fd_cstr_ncpy( tile->diag.log_path, config->log.path, sizeof(tile->diag.log_path) );
1813 :
1814 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "waker" ) ) ) {
1815 :
1816 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "mwaitx" ) ) ) {
1817 :
1818 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "gui" ) ) ) {
1819 :
1820 0 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.gui.gui_listen_address, &tile->gui.listen_addr ) ) )
1821 0 : FD_LOG_ERR(( "failed to parse gui listen address `%s`", config->tiles.gui.gui_listen_address ));
1822 0 : tile->gui.listen_port = config->tiles.gui.gui_listen_port;
1823 0 : tile->gui.max_txn_per_slot = config->limits.max_txn_per_slot;
1824 0 : tile->gui.is_voting = strcmp( config->paths.vote_account, "" );
1825 0 : tile->gui.is_alpenglow = 1;
1826 0 : fd_cstr_ncpy( tile->gui.cluster, config->cluster, sizeof(tile->gui.cluster) );
1827 0 : fd_cstr_ncpy( tile->gui.identity_key_path, config->paths.identity_key, sizeof(tile->gui.identity_key_path) );
1828 0 : fd_cstr_ncpy( tile->gui.vote_key_path, config->paths.vote_account, sizeof(tile->gui.vote_key_path) );
1829 0 : fd_cstr_ncpy( tile->gui.accounts_database_path, config->paths.accounts, sizeof(tile->gui.accounts_database_path) );
1830 0 : fd_cstr_ncpy( tile->gui.gui_database_path, config->paths.guidb, sizeof(tile->gui.gui_database_path) );
1831 0 : tile->gui.max_http_connections = config->tiles.gui.max_http_connections;
1832 0 : tile->gui.max_websocket_connections = config->tiles.gui.max_websocket_connections;
1833 0 : tile->gui.send_buffer_size_mb = config->tiles.gui.send_buffer_size_mb;
1834 0 : tile->gui.db_size_gib = config->tiles.gui.db_size_gib;
1835 0 : tile->gui.schedule_strategy = config->tiles.pack.schedule_strategy_enum;
1836 0 : tile->gui.websocket_compression = 1;
1837 0 : tile->gui.max_live_slots = config->firedancer.runtime.max_live_slots;
1838 0 : fd_cstr_ncpy( tile->gui.wfs_bank_hash, config->firedancer.consensus.wait_for_supermajority_with_bank_hash, sizeof(tile->gui.wfs_bank_hash) );
1839 0 : tile->gui.wfs_slot = config->firedancer.consensus.wait_for_supermajority_at_slot;
1840 0 : tile->gui.expected_shred_version = config->consensus.expected_shred_version;
1841 0 : tile->gui.cache_size_gib = config->firedancer.accounts.cache_size_gib;
1842 0 : tile->gui.accdb_obj_id = fd_pod_query_ulong( config->topo.props, "accdb", ULONG_MAX );
1843 0 : FD_TEST( tile->gui.accdb_obj_id!=ULONG_MAX );
1844 :
1845 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "rpc" ) ) ) {
1846 :
1847 0 : parse_listen_addr( config->tiles.rpc.rpc_listen_address, "tiles.rpc.rpc_listen_address", &tile->rpc.listen_addr );
1848 0 : tile->rpc.listen_port = config->tiles.rpc.rpc_listen_port;
1849 0 : tile->rpc.delay_startup = config->tiles.rpc.delay_startup;
1850 0 : tile->rpc.alpenglow = 1;
1851 0 : tile->rpc.max_http_connections = config->tiles.rpc.max_http_connections;
1852 0 : tile->rpc.max_websocket_connections = config->tiles.rpc.max_websocket_connections;
1853 0 : tile->rpc.send_buffer_size_mb = config->tiles.rpc.send_buffer_size_mb;
1854 :
1855 0 : tile->rpc.max_live_slots = config->firedancer.runtime.max_live_slots;
1856 0 : tile->rpc.genesis_max_message_size = config->firedancer.development.genesis.max_file_size_mib << 20;
1857 :
1858 0 : tile->rpc.accdb_obj_id = fd_pod_query_ulong( config->topo.props, "accdb", ULONG_MAX );
1859 0 : FD_TEST( tile->rpc.accdb_obj_id!=ULONG_MAX );
1860 0 : tile->rpc.accdb_epoch_fseq_obj_id = fd_pod_query_ulong( config->topo.props, "accdb_epoch.rpc", ULONG_MAX );
1861 0 : FD_TEST( tile->rpc.accdb_epoch_fseq_obj_id!=ULONG_MAX );
1862 :
1863 0 : fd_cstr_ncpy( tile->rpc.identity_key_path, config->paths.identity_key, sizeof(tile->rpc.identity_key_path) );
1864 :
1865 0 : tile->rpc.snapshot_server_enabled = fd_topo_find_tile( &config->topo, "snapsv", 0UL )!=ULONG_MAX;
1866 0 : if( FD_LIKELY( tile->rpc.snapshot_server_enabled ) ) {
1867 0 : fd_cstr_ncpy( tile->rpc.snapshot_server_host, config->firedancer.gossip.host,
1868 0 : sizeof(tile->rpc.snapshot_server_host) );
1869 :
1870 0 : uint listen_port = config->firedancer.snapshots.server.http_listen_port;
1871 0 : FD_CHECK_ERR( listen_port && listen_port<=USHORT_MAX,
1872 0 : "[snapshots.server.http_listen_port] must be in [1,65535]" );
1873 0 : tile->rpc.snapshot_server_port = (ushort)listen_port;
1874 0 : }
1875 :
1876 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "backt" ) ) ) {
1877 :
1878 0 : tile->backtest.root_distance = config->firedancer.development.backtest.root_distance;
1879 0 : fd_cstr_ncpy( tile->backtest.ledger_format, config->firedancer.development.ledger_input.format, sizeof(tile->backtest.ledger_format) );
1880 0 : fd_cstr_ncpy( tile->backtest.ledger_path, config->firedancer.development.ledger_input.path, PATH_MAX );
1881 0 : tile->backtest.end_slot = config->firedancer.development.ledger_input.end_slot;
1882 0 : tile->backtest.boot_timestamp_nanos = config->boot_timestamp_nanos;
1883 :
1884 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "bundle" ) ) ) {
1885 0 : fd_cstr_ncpy( tile->bundle.url, config->tiles.bundle.url, sizeof(tile->bundle.url) );
1886 0 : tile->bundle.url_len = strnlen( tile->bundle.url, sizeof(tile->bundle.url)-1UL );
1887 0 : fd_cstr_ncpy( tile->bundle.sni, config->tiles.bundle.tls_domain_name, sizeof(tile->bundle.sni) );
1888 0 : tile->bundle.sni_len = strnlen( tile->bundle.sni, sizeof(tile->bundle.sni)-1UL );
1889 0 : fd_cstr_ncpy( tile->bundle.identity_key_path, config->paths.identity_key, sizeof(tile->bundle.identity_key_path) );
1890 0 : fd_cstr_ncpy( tile->bundle.key_log_path, config->development.bundle.ssl_key_log_file, sizeof(tile->bundle.key_log_path) );
1891 0 : tile->bundle.buf_sz = config->development.bundle.buffer_size_kib<<10;
1892 0 : tile->bundle.out_depth = config->tiles.verify.receive_buffer_size;
1893 0 : tile->bundle.keepalive_interval_nanos = config->tiles.bundle.keepalive_interval_millis * (ulong)1e6;
1894 0 : tile->bundle.tls_cert_verify = !!config->tiles.bundle.tls_cert_verify;
1895 :
1896 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "solcap" ) ) ) {
1897 :
1898 0 : tile->solcap.capture_start_slot = config->capture.capture_start_slot;
1899 0 : fd_cstr_ncpy( tile->solcap.solcap_capture, config->capture.solcap_capture, sizeof(tile->solcap.solcap_capture) );
1900 0 : tile->solcap.recent_only = config->capture.recent_only;
1901 0 : tile->solcap.recent_slots_per_file = config->capture.recent_slots_per_file;
1902 :
1903 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapmk" ) ) ) {
1904 :
1905 0 : tile->snapmk.accdb_obj_id = fd_pod_query_ulong( config->topo.props, "accdb", ULONG_MAX ); FD_TEST( tile->snapmk.accdb_obj_id!=ULONG_MAX );
1906 0 : tile->snapmk.accdb_epoch_obj_id = fd_pod_query_ulong( config->topo.props, "accdb_epoch.snapmk", ULONG_MAX ); FD_TEST( tile->snapmk.accdb_epoch_obj_id!=ULONG_MAX );
1907 0 : tile->snapmk.visited_set_obj_id = fd_pod_query_ulong( config->topo.props, "backup", ULONG_MAX ); FD_TEST( tile->snapmk.visited_set_obj_id!=ULONG_MAX );
1908 0 : tile->snapmk.banks_obj_id = fd_pod_query_ulong( config->topo.props, "banks", ULONG_MAX ); FD_TEST( tile->snapmk.banks_obj_id!=ULONG_MAX );
1909 0 : tile->snapmk.zp_fseq_id = fd_pod_query_ulong( config->topo.props, "snapzp.fseq", ULONG_MAX ); FD_TEST( tile->snapmk.zp_fseq_id!=ULONG_MAX );
1910 0 : tile->snapmk.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX ); FD_TEST( tile->snapmk.txncache_obj_id!=ULONG_MAX );
1911 0 : tile->snapmk.max_accounts = config->firedancer.accounts.max_accounts;
1912 0 : tile->snapmk.max_live_slots = config->firedancer.runtime.max_live_slots;
1913 0 : tile->snapmk.max_txn_per_slot = config->limits.max_txn_per_slot;
1914 0 : tile->snapmk.max_full_snapshots_to_keep = config->firedancer.snapshots.max_full_snapshots_to_keep;
1915 0 : tile->snapmk.max_incremental_snapshots_to_keep = config->firedancer.snapshots.max_incremental_snapshots_to_keep;
1916 0 : fd_cstr_ncpy( tile->snapmk.snapshots_path, config->paths.snapshots, PATH_MAX );
1917 :
1918 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapzp" ) ) ) {
1919 :
1920 0 : tile->snapzp.accdb_obj_id = fd_pod_query_ulong( config->topo.props, "accdb", ULONG_MAX ); FD_TEST( tile->snapzp.accdb_obj_id!=ULONG_MAX );
1921 0 : tile->snapzp.accdb_epoch_obj_id = fd_pod_queryf_ulong( config->topo.props, ULONG_MAX, "accdb_epoch.snapzp.%lu", tile->kind_id ); FD_TEST( tile->snapzp.accdb_epoch_obj_id!=ULONG_MAX );
1922 0 : tile->snapzp.visited_set_obj_id = fd_pod_query_ulong( config->topo.props, "backup", ULONG_MAX ); FD_TEST( tile->snapzp.visited_set_obj_id!=ULONG_MAX );
1923 0 : tile->snapzp.zp_fseq_id = fd_pod_query_ulong( config->topo.props, "snapzp.fseq", ULONG_MAX ); FD_TEST( tile->snapzp.zp_fseq_id!=ULONG_MAX );
1924 0 : tile->snapzp.max_live_slots = config->firedancer.runtime.max_live_slots;
1925 0 : tile->snapzp.snap_fd_cnt = config->firedancer.snapshots.max_full_snapshots_to_keep+
1926 0 : config->firedancer.snapshots.max_incremental_snapshots_to_keep;
1927 :
1928 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snaprd" ) ) ) {
1929 :
1930 0 : tile->snaprd.accdb_obj_id = fd_pod_query_ulong( config->topo.props, "accdb", ULONG_MAX );
1931 0 : FD_TEST( tile->snaprd.accdb_obj_id!=ULONG_MAX );
1932 :
1933 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapsv" ) ) ) {
1934 :
1935 0 : tile->snapsv.snap_max = config->firedancer.snapshots.max_full_snapshots_to_keep +
1936 0 : config->firedancer.snapshots.max_incremental_snapshots_to_keep;
1937 0 : tile->snapsv.conn_max = config->firedancer.snapshots.server.max_http_connections;
1938 0 : tile->snapsv.io_worker_cnt = config->firedancer.layout.snapsv_io_worker_count;
1939 0 : tile->snapsv.idle_timeout_millis = config->firedancer.snapshots.server.idle_timeout_millis;
1940 0 : tile->snapsv.send_timeout_millis = config->firedancer.snapshots.server.send_timeout_millis;
1941 0 : tile->snapsv.send_buffer_size_kib = config->firedancer.snapshots.server.send_buffer_size_kib;
1942 :
1943 : /* An empty listen address defaults to the RPC listen address */
1944 0 : char const * listen_address = config->firedancer.snapshots.server.http_listen_address;
1945 0 : char const * listen_key = "snapshots.server.http_listen_address";
1946 0 : if( FD_LIKELY( !listen_address[0] ) ) {
1947 0 : listen_address = config->tiles.rpc.rpc_listen_address;
1948 0 : listen_key = "tiles.rpc.rpc_listen_address";
1949 0 : }
1950 0 : parse_listen_addr( listen_address, listen_key, &tile->snapsv.listen_addr );
1951 :
1952 0 : uint listen_port = config->firedancer.snapshots.server.http_listen_port;
1953 0 : FD_CHECK_ERR( listen_port && listen_port<=USHORT_MAX,
1954 0 : "[snapshots.server.http_listen_port] must be in [1,65535]" );
1955 0 : tile->snapsv.listen_port = (ushort)listen_port;
1956 :
1957 0 : } else {
1958 0 : FD_LOG_ERR(( "unknown tile name `%s`", tile->name ));
1959 0 : }
1960 0 : }
|