Line data Source code
1 : #include "topology.h"
2 :
3 : #include "../../ballet/lthash/fd_lthash.h"
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/tower/fd_tower_tile.h"
9 : #include "../../discof/resolv/fd_resolv_tile.h"
10 : #include "../../discof/repair/fd_repair.h"
11 : #include "../../discof/reasm/fd_reasm.h"
12 : #include "../../discof/replay/fd_replay_tile.h"
13 : #include "../../disco/net/fd_net_tile.h"
14 : #include "../../discof/restore/fd_snapct_tile.h"
15 : #include "../../disco/gui/fd_gui_config_parse.h"
16 : #include "../../disco/quic/fd_tpu.h"
17 : #include "../../disco/pack/fd_pack_cost.h"
18 : #include "../../disco/tiles.h"
19 : #include "../../disco/topo/fd_topob.h"
20 : #include "../../disco/topo/fd_topob_vinyl.h"
21 : #include "../../disco/topo/fd_cpu_topo.h"
22 : #include "../../disco/bundle/fd_bundle_tile.h"
23 : #include "../../util/pod/fd_pod_format.h"
24 : #include "../../util/tile/fd_tile_private.h"
25 : #include "../../discof/restore/fd_snapin_tile_private.h"
26 : #include "../../discof/restore/fd_snaplv_tile_private.h"
27 : #include "../../discof/restore/fd_snapwm_tile_private.h"
28 : #include "../../discof/restore/utils/fd_slot_delta_parser.h"
29 : #include "../../discof/restore/utils/fd_ssctrl.h"
30 : #include "../../discof/restore/utils/fd_ssmsg.h"
31 : #include "../../flamenco/capture/fd_solcap_writer.h"
32 : #include "../../funk/fd_funk.h"
33 : #include "../../flamenco/progcache/fd_progcache_admin.h"
34 : #include "../../flamenco/runtime/fd_acc_pool.h"
35 : #include "../../flamenco/accdb/fd_accdb_lineage.h"
36 : #include "../../vinyl/meta/fd_vinyl_meta.h"
37 : #include "../../vinyl/io/fd_vinyl_io.h" /* FD_VINYL_IO_TYPE_* */
38 :
39 : #include <sys/random.h>
40 : #include <sys/types.h>
41 : #include <sys/socket.h>
42 : #include <stdlib.h>
43 : #include <netdb.h>
44 :
45 : extern fd_topo_obj_callbacks_t * CALLBACKS[];
46 :
47 : static void
48 0 : parse_ip_port( const char * name, const char * ip_port, fd_topo_ip_port_t *parsed_ip_port) {
49 0 : char buf[ sizeof( "255.255.255.255:65536" ) ];
50 0 : memcpy( buf, ip_port, sizeof( buf ) );
51 0 : char *ip_end = strchr( buf, ':' );
52 0 : if( FD_UNLIKELY( !ip_end ) )
53 0 : FD_LOG_ERR(( "[%s] must in the form ip:port", name ));
54 0 : *ip_end = '\0';
55 :
56 0 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( buf, &( parsed_ip_port->ip ) ) ) ) {
57 0 : FD_LOG_ERR(( "could not parse IP %s in [%s]", buf, name ));
58 0 : }
59 :
60 0 : parsed_ip_port->port = fd_cstr_to_ushort( ip_end+1 );
61 0 : if( FD_UNLIKELY( !parsed_ip_port->port ) )
62 0 : FD_LOG_ERR(( "could not parse port %s in [%s]", ip_end+1, name ));
63 0 : }
64 :
65 : fd_topo_obj_t *
66 : setup_topo_banks( fd_topo_t * topo,
67 : char const * wksp_name,
68 : ulong max_live_slots,
69 : ulong max_fork_width,
70 0 : int larger_max_cost_per_block ) {
71 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "banks", wksp_name );
72 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_live_slots, "obj.%lu.max_live_slots", obj->id ) );
73 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_fork_width, "obj.%lu.max_fork_width", obj->id ) );
74 0 : FD_TEST( fd_pod_insertf_int( topo->props, larger_max_cost_per_block, "obj.%lu.larger_max_cost_per_block", obj->id ) );
75 0 : ulong seed;
76 0 : FD_TEST( fd_rng_secure( &seed, sizeof( ulong ) ) );
77 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, seed, "obj.%lu.seed", obj->id ) );
78 0 : return obj;
79 0 : }
80 :
81 : fd_topo_obj_t *
82 : setup_topo_banks_locks( fd_topo_t * topo,
83 0 : char const * wksp_name ) {
84 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "banks_locks", wksp_name );
85 0 : return obj;
86 0 : }
87 :
88 : static fd_topo_obj_t *
89 0 : setup_topo_fec_sets( fd_topo_t * topo, char const * wksp_name, ulong sz ) {
90 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "fec_sets", wksp_name );
91 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, sz, "obj.%lu.sz", obj->id ) );
92 0 : return obj;
93 0 : }
94 :
95 : void
96 : setup_topo_funk( fd_topo_t * topo,
97 : ulong max_account_records,
98 : ulong max_database_transactions,
99 0 : ulong heap_size_gib ) {
100 0 : fd_topo_obj_t * funk_obj = fd_topob_obj( topo, "funk", "funk" );
101 0 : FD_TEST( fd_pod_insert_ulong( topo->props, "funk", funk_obj->id ) );
102 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_account_records, "obj.%lu.rec_max", funk_obj->id ) );
103 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_database_transactions, "obj.%lu.txn_max", funk_obj->id ) );
104 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, heap_size_gib*(1UL<<30), "obj.%lu.heap_max", funk_obj->id ) );
105 0 : ulong funk_footprint = fd_funk_shmem_footprint( max_database_transactions, max_account_records );
106 0 : if( FD_UNLIKELY( !funk_footprint ) ) FD_LOG_ERR(( "Invalid [accounts] parameters" ));
107 :
108 : /* Increase workspace partition count */
109 0 : ulong wksp_idx = fd_topo_find_wksp( topo, "funk" );
110 0 : FD_TEST( wksp_idx!=ULONG_MAX );
111 0 : fd_topo_wksp_t * wksp = &topo->workspaces[ wksp_idx ];
112 0 : ulong size = funk_footprint+(heap_size_gib*(1UL<<30));
113 0 : ulong part_max = fd_wksp_part_max_est( size, 1U<<14U );
114 0 : if( FD_UNLIKELY( !part_max ) ) FD_LOG_ERR(( "fd_wksp_part_max_est(%lu,16KiB) failed", size ));
115 0 : wksp->part_max += part_max;
116 :
117 0 : fd_topo_obj_t * locks_obj = fd_topob_obj( topo, "funk_locks", "funk_locks" );
118 0 : FD_TEST( fd_pod_insert_ulong( topo->props, "funk_locks", locks_obj->id ) );
119 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_database_transactions, "obj.%lu.txn_max", locks_obj->id ) );
120 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_account_records, "obj.%lu.rec_max", locks_obj->id ) );
121 0 : }
122 :
123 : void
124 : setup_topo_progcache( fd_topo_t * topo,
125 : char const * wksp_name,
126 : ulong max_cache_entries,
127 : ulong max_database_transactions,
128 0 : ulong heap_size ) {
129 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "progcache", wksp_name );
130 0 : FD_TEST( fd_pod_insert_ulong( topo->props, "progcache", obj->id ) );
131 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_cache_entries, "obj.%lu.rec_max", obj->id ) );
132 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_database_transactions, "obj.%lu.txn_max", obj->id ) );
133 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, heap_size, "obj.%lu.heap_max", obj->id ) );
134 0 : ulong pcache_footprint = fd_progcache_shmem_footprint( max_database_transactions, max_cache_entries );
135 0 : if( FD_UNLIKELY( !pcache_footprint ) ) FD_LOG_ERR(( "Invalid [runtime.program_cache] parameters" ));
136 0 : if( FD_UNLIKELY( heap_size<(2*pcache_footprint) ) ) {
137 0 : FD_LOG_ERR(( "Invalid [runtime.program_cache] parameters: heap_size_mib should be at least %lu",
138 0 : ( 2*pcache_footprint )>>20 ));
139 0 : }
140 :
141 : /* Increase workspace partition count */
142 0 : ulong wksp_idx = fd_topo_find_wksp( topo, wksp_name );
143 0 : FD_TEST( wksp_idx!=ULONG_MAX );
144 0 : fd_topo_wksp_t * wksp = &topo->workspaces[ wksp_idx ];
145 0 : ulong part_max = fd_wksp_part_max_est( heap_size, 1U<<14U );
146 0 : if( FD_UNLIKELY( !part_max ) ) FD_LOG_ERR(( "fd_wksp_part_max_est(%lu,16KiB) failed", pcache_footprint ));
147 0 : wksp->part_max += part_max;
148 0 : }
149 :
150 : fd_topo_obj_t *
151 : setup_topo_store( fd_topo_t * topo,
152 : char const * wksp_name,
153 : ulong fec_max,
154 0 : uint part_cnt ) {
155 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "store", wksp_name );
156 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, fec_max, "obj.%lu.fec_max", obj->id ) );
157 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, part_cnt, "obj.%lu.part_cnt", obj->id ) );
158 0 : return obj;
159 0 : }
160 :
161 : fd_topo_obj_t *
162 : setup_topo_txncache( fd_topo_t * topo,
163 : char const * wksp_name,
164 : ulong max_live_slots,
165 0 : ulong max_txn_per_slot ) {
166 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "txncache", wksp_name );
167 :
168 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_live_slots, "obj.%lu.max_live_slots", obj->id ) );
169 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_txn_per_slot, "obj.%lu.max_txn_per_slot", obj->id ) );
170 :
171 0 : return obj;
172 0 : }
173 :
174 : fd_topo_obj_t *
175 : setup_topo_acc_pool( fd_topo_t * topo,
176 0 : ulong max_account_cnt ) {
177 0 : fd_topob_wksp( topo, "acc_pool" );
178 0 : fd_topo_obj_t * acc_pool_obj = fd_topob_obj( topo, "acc_pool", "acc_pool" );
179 0 : FD_TEST( acc_pool_obj );
180 0 : FD_TEST( acc_pool_obj->id != ULONG_MAX );
181 0 : fd_pod_insertf_ulong( topo->props, max_account_cnt, "obj.%lu.max_account_cnt", acc_pool_obj->id );
182 0 : return acc_pool_obj;
183 0 : }
184 :
185 : void
186 : setup_topo_accdb_meta( fd_topo_t * topo,
187 0 : fd_configf_t * config ) {
188 0 : fd_topob_wksp( topo, "accdb_meta" );
189 :
190 0 : fd_topo_obj_t * map_obj = fd_topob_obj( topo, "vinyl_meta", "accdb_meta" );
191 : /* meta_max, the meta map's max capacity, needs to be a power of 2
192 : and larger than the requested max account records, to guarantee
193 : optimal performance as the map fills up. meta_limit, arbitrarily
194 : set at 0.75 of meta_max, determines when the map stops accepting
195 : new entries. meta_limit must be larger than the requested max
196 : account records. The calculation is verbose intentionally, to
197 : make it easy to upgrade in the future if necessary. */
198 0 : ulong const meta_rec = config->accounts.max_accounts;
199 0 : ulong meta_max = fd_ulong_pow2_up( meta_rec );
200 0 : ulong meta_limit = ( meta_max*3UL )/4UL;
201 0 : if( FD_UNLIKELY( meta_limit<meta_rec ) ) {
202 0 : meta_max <<= 1UL;
203 0 : meta_limit <<= 1UL;
204 0 : }
205 0 : ulong const lock_cnt = fd_vinyl_meta_lock_cnt_est ( meta_max );
206 0 : ulong const probe_max = fd_vinyl_meta_probe_max_est( meta_max );
207 0 : fd_pod_insert_ulong( topo->props, "accdb.meta_limit", meta_limit );
208 0 : fd_pod_insertf_ulong( topo->props, meta_max, "obj.%lu.ele_max", map_obj->id );
209 0 : fd_pod_insertf_ulong( topo->props, lock_cnt, "obj.%lu.lock_cnt", map_obj->id );
210 0 : fd_pod_insertf_ulong( topo->props, probe_max, "obj.%lu.probe_max", map_obj->id );
211 0 : fd_pod_insertf_ulong( topo->props, (ulong)fd_tickcount(), "obj.%lu.seed", map_obj->id );
212 :
213 0 : fd_topo_obj_t * meta_pool_obj = fd_topob_obj( topo, "vinyl_meta_e", "accdb_meta" );
214 0 : fd_pod_insertf_ulong( topo->props, meta_max, "obj.%lu.cnt", meta_pool_obj->id );
215 :
216 0 : fd_pod_insert_ulong( topo->props, "accdb.meta_map", map_obj->id );
217 0 : fd_pod_insert_ulong( topo->props, "accdb.meta_pool", meta_pool_obj->id );
218 0 : }
219 :
220 : fd_topo_obj_t *
221 : setup_topo_accdb_cache( fd_topo_t * topo,
222 0 : fd_configf_t * config ) {
223 0 : fd_topob_wksp( topo, "accdb_data" );
224 0 : fd_topo_obj_t * line_obj = fd_topob_obj( topo, "vinyl_data", "accdb_data" );
225 0 : ulong const heap_max = config->accounts.cache_size_gib<<30;
226 0 : fd_pod_insertf_ulong( topo->props, heap_max, "obj.%lu.data_sz", line_obj->id );
227 0 : fd_pod_insert_ulong( topo->props, "accdb.data", line_obj->id );
228 0 : return line_obj;
229 0 : }
230 :
231 : fd_topo_obj_t *
232 : setup_topo_vinyl_admin( fd_topo_t * topo,
233 0 : char const * wksp_name ) {
234 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "vinyl_admin", wksp_name );
235 0 : return obj;
236 0 : }
237 :
238 : /* Resolves a hostname to a single ip address. If multiple ip address
239 : records are returned by getaddrinfo, only the first IPV4 address is
240 : returned via ip_addr. */
241 : static int
242 : resolve_address( char const * address,
243 0 : uint * ip_addr ) {
244 0 : struct addrinfo hints = { .ai_family = AF_INET };
245 0 : struct addrinfo * res;
246 0 : int err = getaddrinfo( address, NULL, &hints, &res );
247 0 : if( FD_UNLIKELY( err ) ) {
248 0 : FD_LOG_WARNING(( "cannot resolve address \"%s\": %i-%s", address, err, gai_strerror( err ) ));
249 0 : return 0;
250 0 : }
251 :
252 0 : int resolved = 0;
253 0 : for( struct addrinfo * cur=res; cur; cur=cur->ai_next ) {
254 0 : if( FD_UNLIKELY( cur->ai_addr->sa_family!=AF_INET ) ) continue;
255 0 : struct sockaddr_in const * addr = (struct sockaddr_in const *)cur->ai_addr;
256 0 : *ip_addr = addr->sin_addr.s_addr;
257 0 : resolved = 1;
258 0 : break;
259 0 : }
260 :
261 0 : freeaddrinfo( res );
262 0 : return resolved;
263 0 : }
264 :
265 : /* Resolves a hostname to multiple ip addresses, specified by
266 : ip_addr_cnt. ip_addrs points to an array of fd_ip4_port_t objects.
267 : hints points to an optionally NULL addrinfo hints object. If hints
268 : is NULL, a default hints settings containing the IPV4 address family
269 : hint will be used. */
270 : static int
271 : resolve_addresses( char const * address,
272 : struct addrinfo const * hints,
273 : fd_ip4_port_t * ip_addrs,
274 0 : ulong ip_addr_cnt ) {
275 0 : struct addrinfo default_hints = { .ai_family = AF_INET };
276 0 : if( FD_UNLIKELY( !hints ) ) {
277 0 : hints = &default_hints;
278 0 : }
279 :
280 0 : struct addrinfo * res;
281 0 : int err = getaddrinfo( address, NULL, hints, &res );
282 0 : if( FD_UNLIKELY( err ) ) {
283 0 : FD_LOG_WARNING(( "cannot resolve address \"%s\": %i-%s", address, err, gai_strerror( err ) ));
284 0 : return 0;
285 0 : }
286 :
287 0 : int resolved = 0;
288 0 : for( struct addrinfo * cur=res; cur; cur=cur->ai_next ) {
289 0 : if( FD_UNLIKELY( (ulong)resolved>=ip_addr_cnt ) ) break;
290 0 : if( FD_UNLIKELY( cur->ai_addr->sa_family!=AF_INET ) ) continue;
291 0 : struct sockaddr_in const * addr = (struct sockaddr_in const *)cur->ai_addr;
292 0 : ip_addrs[ resolved ].addr = addr->sin_addr.s_addr;
293 0 : resolved++;
294 0 : }
295 :
296 0 : freeaddrinfo( res );
297 0 : return resolved;
298 0 : }
299 :
300 : static int
301 : resolve_peer( char const * peer,
302 : struct addrinfo const * addr_resolve_hints,
303 : char const * config_str,
304 : char hostname[ static 256UL ],
305 : fd_ip4_port_t * ip4_port,
306 : ulong ip4_port_cnt,
307 0 : int * is_https ) {
308 :
309 : /* Split host:port */
310 0 : int https = 0;
311 0 : char const * host_port = peer;
312 0 : if( FD_LIKELY( strncmp( peer, "http://", 7UL )==0 ) ) {
313 0 : if( FD_LIKELY( is_https ) ) *is_https = 0;
314 0 : host_port += 7UL;
315 0 : } else if( FD_LIKELY( strncmp( peer, "https://", 8UL )==0 ) ) {
316 0 : if( FD_LIKELY( is_https ) ) *is_https = 1;
317 0 : host_port += 8UL;
318 0 : https = 1;
319 0 : }
320 :
321 0 : char const * colon = strrchr( host_port, ':' );
322 0 : char const * host_end = colon;
323 0 : if( FD_UNLIKELY( !colon && !https ) ) {
324 0 : FD_LOG_ERR(( "invalid [%s] entry \"%s\": no port number", config_str, host_port ));
325 0 : } else if( FD_LIKELY( !colon && https ) ) {
326 0 : host_end = host_port + strlen( host_port );
327 0 : }
328 :
329 0 : ulong fqdn_len = (ulong)( host_end-host_port );
330 0 : if( FD_UNLIKELY( fqdn_len>255 ) ) {
331 0 : FD_LOG_ERR(( "invalid [%s] entry \"%s\": hostname too long", config_str, host_port ));
332 0 : }
333 0 : fd_memcpy( hostname, host_port, fqdn_len );
334 0 : hostname[ fqdn_len ] = '\0';
335 :
336 : /* Resolve hostname */
337 0 : int resolved = resolve_addresses( hostname, addr_resolve_hints, ip4_port, ip4_port_cnt );
338 :
339 : /* Parse port number */
340 :
341 0 : if( FD_LIKELY( colon ) ) {
342 0 : char const * port_str = host_end+1;
343 0 : char const * endptr = NULL;
344 0 : ulong port = strtoul( port_str, (char **)&endptr, 10 );
345 0 : if( FD_UNLIKELY( endptr==port_str || !port || port>USHORT_MAX || *endptr!='\0' ) ) {
346 0 : FD_LOG_ERR(( "invalid [%s] entry \"%s\": invalid port number", config_str, host_port ));
347 0 : }
348 0 : for( ulong i=0UL; i<(ulong)resolved; i++ ) ip4_port[ i ].port = fd_ushort_bswap( (ushort)port );
349 0 : } else if( FD_LIKELY( !colon && https ) ) {
350 : /* use default https port */
351 0 : for( ulong i=0UL; i<(ulong)resolved; i++ ) ip4_port[ i ].port = fd_ushort_bswap( 443U );
352 0 : } else {
353 0 : FD_LOG_ERR(( "invalid [%s] entry \"%s\": no port number", config_str, host_port ));
354 0 : }
355 :
356 0 : return resolved;
357 0 : }
358 :
359 : void
360 0 : resolve_gossip_entrypoints( config_t * config ) {
361 0 : ulong entrypoint_cnt = config->gossip.entrypoints_cnt;
362 0 : for( ulong i=0UL; i<entrypoint_cnt; i++ ) {
363 0 : char hostname[ 256UL ];
364 0 : if( FD_UNLIKELY( 0==resolve_peer( config->gossip.entrypoints[ i ], NULL, "gossip.entrypoints", hostname, &config->gossip.resolved_entrypoints[ i ], 1, NULL ) ) ) {
365 0 : FD_LOG_ERR(( "failed to resolve address of [gossip.entrypoints] entry \"%s\"", config->gossip.entrypoints[ i ] ));
366 0 : }
367 0 : }
368 0 : }
369 :
370 : void
371 0 : fd_topo_initialize( config_t * config ) {
372 : /* TODO: Not here ... */
373 0 : resolve_gossip_entrypoints( config );
374 :
375 0 : ulong net_tile_cnt = config->layout.net_tile_count;
376 0 : ulong shred_tile_cnt = config->layout.shred_tile_count;
377 0 : ulong quic_tile_cnt = config->layout.quic_tile_count;
378 0 : ulong verify_tile_cnt = config->layout.verify_tile_count;
379 0 : ulong resolv_tile_cnt = config->firedancer.layout.resolv_tile_count;
380 0 : ulong execle_tile_cnt = config->firedancer.layout.execle_tile_count;
381 :
382 0 : ulong gossvf_tile_cnt = config->firedancer.layout.gossvf_tile_count;
383 0 : ulong execrp_tile_cnt = config->firedancer.layout.execrp_tile_count;
384 0 : ulong sign_tile_cnt = config->firedancer.layout.sign_tile_count;
385 0 : ulong lta_tile_cnt = config->firedancer.layout.snapshot_hash_tile_count;
386 0 : ulong snapwr_tile_cnt = config->firedancer.layout.snapwr_tile_count;
387 0 : ulong snaplh_tile_cnt = config->firedancer.layout.snapshot_hash_tile_count;
388 :
389 0 : int snapshots_enabled = !!config->gossip.entrypoints_cnt;
390 0 : int vinyl_enabled = !config->firedancer.accounts.in_memory_only;
391 0 : int snapshot_lthash_disabled = config->development.snapshots.disable_lthash_verification;
392 0 : int rpc_enabled = config->tiles.rpc.enabled;
393 0 : int telemetry_enabled = config->telemetry && strcmp( config->tiles.event.url, "" );
394 0 : int leader_enabled = !!config->firedancer.layout.enable_block_production;
395 :
396 0 : fd_topo_t * topo = fd_topob_new( &config->topo, config->name );
397 :
398 0 : topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
399 0 : topo->gigantic_page_threshold = config->hugetlbfs.gigantic_page_threshold_mib << 20;
400 :
401 0 : int solcap_enabled = strlen( config->capture.solcap_capture ) > 0;
402 :
403 : /* topo, name */
404 0 : fd_topob_wksp( topo, "metric" );
405 0 : fd_topob_wksp( topo, "diag" );
406 0 : fd_topob_wksp( topo, "genesi" );
407 0 : fd_topob_wksp( topo, "ipecho" );
408 0 : fd_topob_wksp( topo, "gossvf" );
409 0 : fd_topob_wksp( topo, "gossip" );
410 0 : fd_topob_wksp( topo, "shred" );
411 0 : fd_topob_wksp( topo, "repair" );
412 0 : fd_topob_wksp( topo, "replay" );
413 0 : fd_topob_wksp( topo, "execrp" );
414 0 : fd_topob_wksp( topo, "tower" );
415 0 : fd_topob_wksp( topo, "txsend" );
416 0 : fd_topob_wksp( topo, "sign" )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_NEVER;
417 :
418 0 : if( leader_enabled ) {
419 0 : fd_topob_wksp( topo, "quic" );
420 0 : fd_topob_wksp( topo, "verify" );
421 0 : fd_topob_wksp( topo, "dedup" );
422 0 : fd_topob_wksp( topo, "resolv" );
423 0 : fd_topob_wksp( topo, "pack" );
424 0 : fd_topob_wksp( topo, "execle" );
425 0 : fd_topob_wksp( topo, "poh" );
426 0 : } else {
427 0 : execle_tile_cnt = 0UL;
428 0 : resolv_tile_cnt = 0UL;
429 0 : quic_tile_cnt = 0UL;
430 0 : verify_tile_cnt = 0UL;
431 0 : config->tiles.bundle.enabled = 0;
432 0 : }
433 :
434 0 : fd_topob_wksp( topo, "metric_in" );
435 :
436 0 : fd_topob_wksp( topo, "net_gossip" );
437 0 : fd_topob_wksp( topo, "net_shred" );
438 0 : fd_topob_wksp( topo, "net_repair" );
439 0 : fd_topob_wksp( topo, "net_txsend" );
440 0 : if( leader_enabled ) fd_topob_wksp( topo, "net_quic" );
441 :
442 0 : fd_topob_wksp( topo, "genesi_out" );
443 0 : fd_topob_wksp( topo, "ipecho_out" );
444 0 : fd_topob_wksp( topo, "gossvf_gossip" );
445 0 : fd_topob_wksp( topo, "gossip_gossvf" );
446 0 : fd_topob_wksp( topo, "gossip_out" );
447 :
448 0 : fd_topob_wksp( topo, "shred_out" );
449 0 : fd_topob_wksp( topo, "repair_out" );
450 0 : fd_topob_wksp( topo, "replay_epoch" );
451 0 : fd_topob_wksp( topo, "replay_execrp" );
452 0 : fd_topob_wksp( topo, "replay_out" );
453 0 : fd_topob_wksp( topo, "tower_out" );
454 0 : fd_topob_wksp( topo, "txsend_out" );
455 :
456 0 : if( leader_enabled ) {
457 0 : fd_topob_wksp( topo, "quic_verify" );
458 0 : fd_topob_wksp( topo, "verify_dedup" );
459 0 : fd_topob_wksp( topo, "dedup_resolv" );
460 0 : fd_topob_wksp( topo, "resolv_pack" );
461 0 : fd_topob_wksp( topo, "pack_poh" );
462 0 : fd_topob_wksp( topo, "pack_execle" );
463 0 : fd_topob_wksp( topo, "resolv_replay" );
464 0 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
465 0 : fd_topob_wksp( topo, "execle_pack" );
466 0 : }
467 0 : fd_topob_wksp( topo, "execle_poh" );
468 0 : fd_topob_wksp( topo, "execle_busy" );
469 0 : fd_topob_wksp( topo, "poh_shred" );
470 0 : fd_topob_wksp( topo, "poh_replay" );
471 0 : }
472 :
473 0 : fd_topob_wksp( topo, "funk" )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_FULL;
474 0 : fd_topob_wksp( topo, "funk_locks" )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_FULL;
475 0 : fd_topob_wksp( topo, "progcache" );
476 0 : fd_topob_wksp( topo, "fec_sets" );
477 0 : fd_topob_wksp( topo, "txncache" );
478 0 : fd_topob_wksp( topo, "banks" );
479 0 : fd_topob_wksp( topo, "banks_locks" );
480 0 : fd_topob_wksp( topo, "store" )->core_dump_level = FD_TOPO_CORE_DUMP_LEVEL_FULL;
481 0 : fd_topob_wksp( topo, "rnonce" );
482 :
483 0 : fd_topob_wksp( topo, "gossip_sign" );
484 0 : fd_topob_wksp( topo, "sign_gossip" );
485 :
486 0 : fd_topob_wksp( topo, "shred_sign" );
487 0 : fd_topob_wksp( topo, "sign_shred" );
488 :
489 0 : fd_topob_wksp( topo, "repair_sign" );
490 0 : fd_topob_wksp( topo, "sign_repair" );
491 :
492 0 : fd_topob_wksp( topo, "txsend_sign" );
493 0 : fd_topob_wksp( topo, "sign_txsend" );
494 :
495 0 : fd_topob_wksp( topo, "execrp_replay" );
496 :
497 0 : if( FD_LIKELY( snapshots_enabled ) ) {
498 0 : fd_topob_wksp( topo, "snapct" );
499 0 : fd_topob_wksp( topo, "snapld" );
500 0 : fd_topob_wksp( topo, "snapdc" );
501 0 : fd_topob_wksp( topo, "snapin" );
502 0 : if( vinyl_enabled ) {
503 0 : fd_topob_wksp( topo, "snapwm" );
504 0 : fd_topob_wksp( topo, "snapwh" );
505 0 : fd_topob_wksp( topo, "snapwr" );
506 0 : }
507 0 : fd_topob_wksp( topo, "snapct_ld" );
508 0 : fd_topob_wksp( topo, "snapld_dc" );
509 0 : fd_topob_wksp( topo, "snapdc_in" );
510 0 : if( vinyl_enabled ) {
511 0 : fd_topob_wksp( topo, "snapin_txn");
512 0 : fd_topob_wksp( topo, "snapin_wm" );
513 0 : fd_topob_wksp( topo, "snapwm_wr" );
514 0 : }
515 0 : if( snapshot_lthash_disabled ) {
516 0 : if( vinyl_enabled ) {
517 0 : fd_topob_wksp( topo, "snapwm_ct" );
518 0 : } else {
519 0 : fd_topob_wksp( topo, "snapin_ct" );
520 0 : }
521 0 : } else {
522 0 : if( vinyl_enabled ) {
523 0 : fd_topob_wksp( topo, "snaplh" );
524 0 : fd_topob_wksp( topo, "snaplv" );
525 0 : fd_topob_wksp( topo, "vinyl_admin" );
526 0 : fd_topob_wksp( topo, "snaplv_lh" );
527 0 : fd_topob_wksp( topo, "snaplh_lv" );
528 0 : fd_topob_wksp( topo, "snapwm_lv" );
529 0 : fd_topob_wksp( topo, "snaplv_ct" );
530 0 : } else {
531 0 : fd_topob_wksp( topo, "snapla" );
532 0 : fd_topob_wksp( topo, "snapls" );
533 0 : fd_topob_wksp( topo, "snapla_ls" );
534 0 : fd_topob_wksp( topo, "snapin_ls" );
535 0 : fd_topob_wksp( topo, "snapls_ct" );
536 0 : }
537 0 : }
538 :
539 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) fd_topob_wksp( topo, "snapct_gui" );
540 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) fd_topob_wksp( topo, "snapin_gui" );
541 0 : fd_topob_wksp( topo, "snapin_manif" );
542 0 : fd_topob_wksp( topo, "snapct_repr" );
543 0 : }
544 :
545 0 : #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
546 :
547 0 : ulong shred_depth = 65536UL; /* from fdctl/topology.c shred_store link. MAKE SURE TO KEEP IN SYNC. */
548 :
549 : /* topo, link_name, wksp_name, depth, mtu, burst */
550 0 : /**/ fd_topob_link( topo, "gossip_net", "net_gossip", 32768UL, FD_NET_MTU, 1UL );
551 0 : FOR(shred_tile_cnt) fd_topob_link( topo, "shred_net", "net_shred", 32768UL, FD_NET_MTU, 1UL );
552 0 : /**/ fd_topob_link( topo, "repair_net", "net_repair", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
553 0 : /**/ fd_topob_link( topo, "txsend_net", "net_txsend", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
554 0 : FOR(quic_tile_cnt) fd_topob_link( topo, "quic_net", "net_quic", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
555 :
556 0 : if( FD_LIKELY( snapshots_enabled ) ) {
557 : /* TODO: Revisit the depths of all the snapshot links */
558 0 : /**/ fd_topob_link( topo, "snapct_ld", "snapct_ld", 128UL, sizeof(fd_ssctrl_init_t), 1UL );
559 0 : /**/ fd_topob_link( topo, "snapld_dc", "snapld_dc", 16384UL, USHORT_MAX, 1UL );
560 0 : /**/ fd_topob_link( topo, "snapdc_in", "snapdc_in", 16384UL, USHORT_MAX, 1UL );
561 :
562 : /**/ fd_topob_link( topo, "snapin_manif", "snapin_manif", 4UL, sizeof(fd_snapshot_manifest_t),1UL );
563 0 : /**/ fd_topob_link( topo, "snapct_repr", "snapct_repr", 128UL, 0UL, 1UL )->permit_no_consumers = 1; /* TODO: wire in repair later */
564 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
565 0 : /**/ fd_topob_link( topo, "snapct_gui", "snapct_gui", 128UL, sizeof(fd_snapct_update_t), 1UL );
566 0 : /**/ fd_topob_link( topo, "snapin_gui", "snapin_gui", 128UL, FD_GUI_CONFIG_PARSE_MAX_VALID_ACCT_SZ, 1UL );
567 0 : }
568 :
569 0 : if( vinyl_enabled ) {
570 : /* snapwm needs all txn_cache data in order to verify the slot
571 : deltas with the slot history. To make this possible, snapin
572 : uses the dcache of the snapin_txn link as the scratch memory.
573 : The depth of the link should match that of snapin_wm, just to
574 : guarantee enough mcache credits. The mtu needs to be adjusted
575 : so that the total dcache size matches what snapin requires.
576 : Round up the mtu (ulong) size using: (...+(depth-1))/depth. */
577 0 : /**/ fd_topob_link( topo, "snapin_txn", "snapin_txn", 16UL, (sizeof(fd_sstxncache_entry_t)*FD_SNAPIN_TXNCACHE_MAX_ENTRIES+15UL/*depth-1*/)/16UL/*depth*/, 1UL );
578 0 : /**/ fd_topob_link( topo, "snapin_wm", "snapin_wm", 16UL, FD_SNAPWM_PAIR_BATCH_SZ_MAX, 1UL );
579 : /* snapwh and snapwr both use snapwm_wh's dcache. snapwh sends
580 : control messages to snapwr, using snapwh_wr link, instructing
581 : which chunks in the dcache are ready to be consumed by snapwr. */
582 0 : fd_topo_link_t * snapwm_wh =
583 0 : /**/ fd_topob_link( topo, "snapwm_wh", "snapwm_wr", 64UL, FD_SNAPWM_WR_MTU, 1UL );
584 0 : /**/ fd_topob_link( topo, "snapwh_wr", "snapwm_wr", 64UL, 0UL, 1UL );
585 0 : fd_pod_insertf_ulong( topo->props, 8UL, "obj.%lu.app_sz", snapwm_wh->dcache_obj_id );
586 0 : }
587 0 : if( snapshot_lthash_disabled ) {
588 0 : if( vinyl_enabled ) {
589 0 : /**/ fd_topob_link( topo, "snapwm_ct", "snapwm_ct", 128UL, 0UL, 1UL );
590 0 : } else {
591 0 : /**/ fd_topob_link( topo, "snapin_ct", "snapin_ct", 128UL, 0UL, 1UL );
592 0 : }
593 0 : } else {
594 0 : if( vinyl_enabled ) {
595 0 : FOR(snaplh_tile_cnt) fd_topob_link( topo, "snaplh_lv", "snaplh_lv", 128UL, sizeof(fd_ssctrl_hash_result_t), 1UL );
596 0 : /**/ fd_topob_link( topo, "snapwm_lv", "snapwm_lv", 32768UL, FD_SNAPWM_DUP_META_BATCH_SZ, 1UL );
597 0 : /**/ fd_topob_link( topo, "snaplv_lh", "snaplv_lh", 262144UL, FD_SNAPLV_DUP_META_SZ, FD_SNAPLV_STEM_BURST ); /* FD_SNAPWM_DUP_META_BATCH_CNT_MAX times the depth of snapwm_lv */
598 0 : /**/ fd_topob_link( topo, "snaplv_ct", "snaplv_ct", 128UL, 0UL, 1UL );
599 0 : } else {
600 0 : FOR(lta_tile_cnt) fd_topob_link( topo, "snapla_ls", "snapla_ls", 128UL, sizeof(fd_lthash_value_t), 1UL );
601 0 : /**/ fd_topob_link( topo, "snapin_ls", "snapin_ls", 256UL, sizeof(fd_snapshot_full_account_t), 1UL );
602 0 : /**/ fd_topob_link( topo, "snapls_ct", "snapls_ct", 128UL, 0UL, 1UL );
603 0 : }
604 0 : }
605 0 : }
606 :
607 0 : /**/ fd_topob_link( topo, "genesi_out", "genesi_out", 1UL, FD_GENESIS_TILE_MTU, 1UL );
608 0 : /**/ fd_topob_link( topo, "ipecho_out", "ipecho_out", 2UL, 0UL, 1UL );
609 0 : FOR(gossvf_tile_cnt) fd_topob_link( topo, "gossvf_gossip", "gossvf_gossip", config->net.ingress_buffer_size, sizeof(fd_gossip_message_t)+FD_GOSSIP_MESSAGE_MAX_CRDS+FD_NET_MTU, 1UL );
610 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 */
611 0 : /**/ fd_topob_link( topo, "gossip_out", "gossip_out", 65536UL*4UL, sizeof(fd_gossip_update_message_t), 1UL ); /* TODO: Unclear where this depth comes from ... fix */
612 :
613 0 : FOR(quic_tile_cnt) fd_topob_link( topo, "quic_verify", "quic_verify", config->tiles.verify.receive_buffer_size, FD_TPU_REASM_MTU, config->tiles.quic.txn_reassembly_count );
614 0 : FOR(verify_tile_cnt) fd_topob_link( topo, "verify_dedup", "verify_dedup", config->tiles.verify.receive_buffer_size, FD_TPU_PARSED_MTU, 1UL );
615 0 : /**/ fd_topob_link( topo, "replay_epoch", "replay_epoch", 128UL, FD_EPOCH_OUT_MTU, 1UL ); /* TODO: This should be 2 but requires fixing STEM_BURST */
616 0 : /**/ fd_topob_link( topo, "replay_out", "replay_out", 65536UL, sizeof(fd_replay_message_t), 1UL );
617 0 : fd_topob_link( topo, "replay_execrp", "replay_execrp", 16384UL, sizeof(fd_execrp_task_msg_t), 1UL );
618 0 : if( leader_enabled ) {
619 0 : /**/ fd_topob_link( topo, "dedup_resolv", "dedup_resolv", 65536UL, FD_TPU_PARSED_MTU, 1UL );
620 0 : FOR(resolv_tile_cnt) fd_topob_link( topo, "resolv_pack", "resolv_pack", 65536UL, FD_TPU_RESOLVED_MTU, 1UL );
621 0 : /**/ fd_topob_link( topo, "pack_poh", "pack_poh", 4096UL, sizeof(fd_done_packing_t), 1UL );
622 0 : FOR(execle_tile_cnt) fd_topob_link( topo, "execle_poh", "execle_poh", 16384UL, USHORT_MAX, 1UL );
623 : /* pack_execle is shared across all execle, so if one executor stalls
624 : due to complex transactions, the buffer needs to be large so that
625 : other executors can keep proceeding. */
626 0 : /**/ fd_topob_link( topo, "pack_execle", "pack_execle", 65536UL, USHORT_MAX, 1UL );
627 0 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
628 0 : FOR(execle_tile_cnt) fd_topob_link( topo, "execle_pack", "execle_pack", 16384UL, USHORT_MAX, 1UL );
629 0 : }
630 0 : /**/ fd_topob_link( topo, "poh_shred", "poh_shred", 16384UL, USHORT_MAX, 1UL );
631 0 : /**/ fd_topob_link( topo, "poh_replay", "poh_replay", 4096UL, sizeof(fd_poh_leader_slot_ended_t), 1UL );
632 0 : }
633 :
634 0 : FOR(resolv_tile_cnt) fd_topob_link( topo, "resolv_replay", "resolv_replay", 4096UL, sizeof(fd_resolv_slot_exchanged_t), 1UL );
635 :
636 0 : FOR(shred_tile_cnt) fd_topob_link( topo, "shred_sign", "shred_sign", 128UL, 32UL, 1UL );
637 0 : FOR(shred_tile_cnt) fd_topob_link( topo, "sign_shred", "sign_shred", 128UL, sizeof(fd_ed25519_sig_t), 1UL );
638 :
639 : /**/ 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 */
640 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 */
641 :
642 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 */
643 0 : FOR(sign_tile_cnt-1) fd_topob_link( topo, "sign_repair", "sign_repair", 128UL, sizeof(fd_ed25519_sig_t), 1UL );
644 :
645 0 : /**/ fd_topob_link( topo, "txsend_sign", "txsend_sign", 128UL, FD_TXN_MTU, 1UL ); /* TODO: Depth probably doesn't need to be 128 */
646 0 : /**/ fd_topob_link( topo, "sign_txsend", "sign_txsend", 128UL, sizeof(fd_ed25519_sig_t)*2UL, 1UL ); /* TODO: Depth probably doesn't need to be 128 */
647 :
648 0 : FOR(shred_tile_cnt) fd_topob_link( topo, "shred_out", "shred_out", shred_depth, FD_SHRED_OUT_MTU, 3UL ); /* TODO: Pretty sure burst of 3 is incorrect here */
649 0 : /**/ fd_topob_link( topo, "repair_out", "repair_out", shred_depth, FD_SHRED_OUT_MTU, 1UL );
650 0 : /**/ fd_topob_link( topo, "tower_out", "tower_out", 16384UL, sizeof(fd_tower_msg_t), 2UL ); /* conf + slot_done. see explanation in fd_tower_tile.h for link_depth */
651 0 : /**/ fd_topob_link( topo, "txsend_out", "txsend_out", 128UL, FD_TPU_RAW_MTU, 1UL );
652 :
653 0 : FOR(execrp_tile_cnt) fd_topob_link( topo, "execrp_replay", "execrp_replay", 16384UL, sizeof(fd_execrp_task_done_msg_t), 1UL );
654 :
655 0 : ushort parsed_tile_to_cpu[ FD_TILE_MAX ];
656 : /* Unassigned tiles will be floating, unless auto topology is enabled. */
657 0 : for( ulong i=0UL; i<FD_TILE_MAX; i++ ) parsed_tile_to_cpu[ i ] = USHORT_MAX;
658 :
659 0 : int is_auto_affinity = !strcmp( config->layout.affinity, "auto" );
660 :
661 0 : fd_topo_cpus_t cpus[1];
662 0 : fd_topo_cpus_init( cpus );
663 :
664 0 : ulong affinity_tile_cnt = 0UL;
665 0 : if( FD_LIKELY( !is_auto_affinity ) ) affinity_tile_cnt = fd_tile_private_cpus_parse( config->layout.affinity, parsed_tile_to_cpu );
666 :
667 0 : ulong tile_to_cpu[ FD_TILE_MAX ] = {0};
668 0 : for( ulong i=0UL; i<affinity_tile_cnt; i++ ) {
669 0 : if( FD_UNLIKELY( parsed_tile_to_cpu[ i ]!=USHORT_MAX && parsed_tile_to_cpu[ i ]>=cpus->cpu_cnt ) )
670 0 : FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.affinity] specifies a CPU index of %hu, but the system "
671 0 : "only has %lu CPUs. You should either change the CPU allocations in the affinity string, or increase the number of CPUs "
672 0 : "in the system.",
673 0 : parsed_tile_to_cpu[ i ], cpus->cpu_cnt ));
674 0 : tile_to_cpu[ i ] = fd_ulong_if( parsed_tile_to_cpu[ i ]==USHORT_MAX, ULONG_MAX, (ulong)parsed_tile_to_cpu[ i ] );
675 0 : }
676 :
677 0 : int xsk_core_dump = config->development.core_dump_level >= FD_TOPO_CORE_DUMP_LEVEL_REGULAR ? 1 : 0;
678 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 );
679 :
680 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_gossvf", i, config->net.ingress_buffer_size );
681 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_shred", i, config->net.ingress_buffer_size );
682 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_repair", i, config->net.ingress_buffer_size );
683 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_txsend", i, config->net.ingress_buffer_size );
684 0 : if(leader_enabled) FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_quic", i, config->net.ingress_buffer_size );
685 :
686 : /* topo, tile_name, tile_wksp, metrics_wksp, cpu_idx, is_agave, uses_id_keyswitch, uses_av_keyswitch */
687 : /**/ fd_topob_tile( topo, "metric", "metric", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
688 0 : /**/ fd_topob_tile( topo, "diag", "diag", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
689 :
690 0 : if( FD_LIKELY( snapshots_enabled ) ) {
691 0 : /**/ fd_topob_tile( topo, "snapct", "snapct", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
692 0 : /**/ fd_topob_tile( topo, "snapld", "snapld", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
693 0 : /**/ fd_topob_tile( topo, "snapdc", "snapdc", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
694 0 : /**/ fd_topob_tile( topo, "snapin", "snapin", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
695 0 : if(vinyl_enabled) fd_topob_tile( topo, "snapwm", "snapwm", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
696 0 : if(vinyl_enabled) fd_topob_tile( topo, "snapwh", "snapwh", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
697 0 : if(vinyl_enabled) FOR(snapwr_tile_cnt)
698 0 : fd_topob_tile( topo, "snapwr", "snapwr", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
699 :
700 0 : if( snapshot_lthash_disabled ) {
701 : /* nothing to do here */
702 0 : } else {
703 0 : if( vinyl_enabled ) {
704 0 : FOR(snaplh_tile_cnt) fd_topob_tile( topo, "snaplh", "snaplh", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
705 0 : /**/ fd_topob_tile( topo, "snaplv", "snaplv", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
706 0 : } else {
707 0 : FOR(lta_tile_cnt) fd_topob_tile( topo, "snapla", "snapla", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
708 0 : /**/ fd_topob_tile( topo, "snapls", "snapls", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
709 0 : }
710 0 : }
711 0 : }
712 :
713 : /**/ fd_topob_tile( topo, "genesi", "genesi", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 )->allow_shutdown = 1;
714 0 : /**/ fd_topob_tile( topo, "ipecho", "ipecho", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
715 0 : FOR(gossvf_tile_cnt) fd_topob_tile( topo, "gossvf", "gossvf", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 0 );
716 0 : /**/ fd_topob_tile( topo, "gossip", "gossip", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 0 );
717 :
718 0 : FOR(shred_tile_cnt) fd_topob_tile( topo, "shred", "shred", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 0 );
719 0 : /**/ fd_topob_tile( topo, "repair", "repair", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 0 );
720 0 : /**/ fd_topob_tile( topo, "replay", "replay", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 0 );
721 0 : FOR(execrp_tile_cnt) fd_topob_tile( topo, "execrp", "execrp", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
722 0 : /**/ fd_topob_tile( topo, "tower", "tower", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 1 );
723 0 : /**/ fd_topob_tile( topo, "txsend", "txsend", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 0 );
724 :
725 0 : if( leader_enabled ) {
726 0 : FOR(quic_tile_cnt) fd_topob_tile( topo, "quic", "quic", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
727 0 : FOR(verify_tile_cnt) fd_topob_tile( topo, "verify", "verify", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
728 0 : /**/ fd_topob_tile( topo, "dedup", "dedup", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
729 0 : FOR(resolv_tile_cnt) fd_topob_tile( topo, "resolv", "resolv", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
730 0 : /**/ fd_topob_tile( topo, "pack", "pack", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, config->tiles.bundle.enabled, 0 );
731 0 : FOR(execle_tile_cnt) fd_topob_tile( topo, "execle", "execle", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
732 0 : /**/ fd_topob_tile( topo, "poh", "poh", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
733 0 : }
734 0 : FOR(sign_tile_cnt) fd_topob_tile( topo, "sign", "sign", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 1 );
735 :
736 0 : if( FD_UNLIKELY( rpc_enabled ) ) {
737 0 : fd_topob_wksp( topo, "rpc" );
738 0 : fd_topob_wksp( topo, "rpc_replay" );
739 0 : fd_topob_tile( topo, "rpc", "rpc", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 0 );
740 0 : }
741 :
742 0 : if( vinyl_enabled ) {
743 0 : setup_topo_accdb_meta( topo, &config->firedancer );
744 :
745 0 : fd_topo_obj_t * accdb_data = setup_topo_accdb_cache( topo, &config->firedancer );
746 :
747 0 : ulong vinyl_map_obj_id = fd_pod_query_ulong( topo->props, "accdb.meta_map", ULONG_MAX ); FD_TEST( vinyl_map_obj_id !=ULONG_MAX );
748 0 : ulong vinyl_pool_obj_id = fd_pod_query_ulong( topo->props, "accdb.meta_pool", ULONG_MAX ); FD_TEST( vinyl_pool_obj_id!=ULONG_MAX );
749 :
750 0 : fd_topo_obj_t * accdb_map_obj = &topo->objs[ vinyl_map_obj_id ];
751 0 : fd_topo_obj_t * accdb_pool_obj = &topo->objs[ vinyl_pool_obj_id ];
752 :
753 0 : fd_topob_wksp( topo, "accdb" );
754 0 : fd_topo_tile_t * accdb_tile = fd_topob_tile( topo, "accdb", "accdb", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
755 0 : fd_topob_tile_uses( topo, accdb_tile, accdb_data, FD_SHMEM_JOIN_MODE_READ_WRITE );
756 0 : fd_topob_tile_uses( topo, accdb_tile, accdb_map_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
757 0 : fd_topob_tile_uses( topo, accdb_tile, accdb_pool_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
758 :
759 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "genesi", 0UL ) ], accdb_data, FD_SHMEM_JOIN_MODE_READ_WRITE );
760 :
761 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], accdb_data, FD_SHMEM_JOIN_MODE_READ_WRITE );
762 0 : for( ulong i=0UL; i<execrp_tile_cnt; i++ ) {
763 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i ) ], accdb_data, FD_SHMEM_JOIN_MODE_READ_WRITE );
764 0 : }
765 0 : for( ulong i=0UL; i<execle_tile_cnt; i++ ) {
766 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execle", i ) ], accdb_data, FD_SHMEM_JOIN_MODE_READ_WRITE );
767 0 : }
768 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "tower", 0UL ) ], accdb_data, FD_SHMEM_JOIN_MODE_READ_ONLY );
769 0 : FOR(resolv_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "resolv", i ) ], accdb_data, FD_SHMEM_JOIN_MODE_READ_ONLY );
770 0 : if( rpc_enabled ) {
771 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "rpc", 0UL ) ], accdb_data, FD_SHMEM_JOIN_MODE_READ_ONLY );
772 0 : }
773 :
774 0 : fd_topob_wksp( topo, "accdb_genesi" );
775 0 : fd_topob_wksp( topo, "accdb_replay" );
776 0 : fd_topob_wksp( topo, "accdb_execrp" );
777 0 : if( leader_enabled ) fd_topob_wksp( topo, "accdb_execle" );
778 0 : fd_topob_wksp( topo, "accdb_tower" );
779 0 : if( leader_enabled ) fd_topob_wksp( topo, "accdb_resolv" );
780 0 : if( config->tiles.rpc.enabled ) fd_topob_wksp( topo, "accdb_rpc" );
781 0 : }
782 :
783 0 : if( FD_UNLIKELY( solcap_enabled ) ) {
784 0 : fd_topob_wksp( topo, "solcap" );
785 0 : fd_topob_tile( topo, "solcap", "solcap", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
786 0 : }
787 :
788 0 : if( FD_LIKELY( snapshots_enabled ) ) {
789 0 : if( vinyl_enabled ) {
790 0 : ulong vinyl_map_obj_id = fd_pod_query_ulong( topo->props, "accdb.meta_map", ULONG_MAX ); FD_TEST( vinyl_map_obj_id !=ULONG_MAX );
791 0 : ulong vinyl_pool_obj_id = fd_pod_query_ulong( topo->props, "accdb.meta_pool", ULONG_MAX ); FD_TEST( vinyl_pool_obj_id!=ULONG_MAX );
792 :
793 0 : fd_topo_obj_t * vinyl_map_obj = &topo->objs[ vinyl_map_obj_id ];
794 0 : fd_topo_obj_t * vinyl_pool_obj = &topo->objs[ vinyl_pool_obj_id ];
795 :
796 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapwm", 0UL ) ], vinyl_map_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
797 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapwm", 0UL ) ], vinyl_pool_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
798 0 : }
799 0 : }
800 :
801 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
802 0 : FOR(gossvf_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
803 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 */
804 0 : FOR(shred_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
805 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 */
806 0 : FOR(net_tile_cnt) fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "net_repair", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
807 0 : /**/ fd_topob_tile_out( topo, "repair", 0UL, "repair_net", 0UL );
808 0 : FOR(net_tile_cnt) fd_topob_tile_in ( topo, "txsend", 0UL, "metric_in", "net_txsend", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
809 0 : FOR(quic_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
810 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 */
811 :
812 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 */
813 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 */
814 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 */
815 0 : /**/ fd_topos_tile_in_net( topo, "metric_in", "txsend_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
816 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 */
817 :
818 0 : /**/ fd_topob_tile_out( topo, "genesi", 0UL, "genesi_out", 0UL );
819 0 : /**/ fd_topob_tile_in ( topo, "ipecho", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
820 0 : /**/ fd_topob_tile_out( topo, "ipecho", 0UL, "ipecho_out", 0UL );
821 :
822 0 : FOR(gossvf_tile_cnt) fd_topob_tile_out( topo, "gossvf", i, "gossvf_gossip", i );
823 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
824 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "gossip_gossvf", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
825 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
826 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
827 0 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
828 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_out", 0UL );
829 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_net", 0UL );
830 0 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
831 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "gossvf_gossip", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
832 0 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "txsend_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
833 0 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
834 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_gossvf", 0UL );
835 0 : if( snapshots_enabled ) {
836 0 : fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
837 0 : }
838 0 : int snapshots_gossip_enabled = config->firedancer.snapshots.sources.gossip.allow_any || config->firedancer.snapshots.sources.gossip.allow_list_cnt>0UL;
839 0 : if( FD_LIKELY( snapshots_enabled ) ) {
840 0 : if( FD_LIKELY( snapshots_gossip_enabled ) ) {
841 0 : /**/ fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
842 0 : }
843 :
844 0 : fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
845 0 : fd_topob_tile_out( topo, "snapct", 0UL, "snapct_ld", 0UL );
846 0 : fd_topob_tile_out( topo, "snapct", 0UL, "snapct_repr", 0UL );
847 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
848 0 : /**/ fd_topob_tile_out( topo, "snapct", 0UL, "snapct_gui", 0UL );
849 0 : }
850 :
851 0 : if( vinyl_enabled ) {
852 0 : /**/ fd_topob_tile_out( topo, "snapin", 0UL, "snapin_wm", 0UL );
853 0 : /**/ fd_topob_tile_in ( topo, "snapwm", 0UL, "metric_in", "snapin_wm", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
854 0 : /**/ fd_topob_tile_out( topo, "snapin", 0UL, "snapin_txn", 0UL );
855 0 : /**/ fd_topob_tile_in ( topo, "snapwm", 0UL, "metric_in", "snapin_txn", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
856 0 : /**/ fd_topob_tile_out( topo, "snapwm", 0UL, "snapwm_wh", 0UL );
857 0 : /**/ fd_topob_tile_in ( topo, "snapwh", 0UL, "metric_in", "snapwm_wh", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
858 0 : /**/ fd_topob_tile_out( topo, "snapwh", 0UL, "snapwh_wr", 0UL );
859 : /* snapwh and snapwr both access snapwm_wh's dcache, avoiding a
860 : memcpy for every account (vinyl pair) that is being processed
861 : (loaded) from the snapshot. */
862 0 : FOR(snapwr_tile_cnt) fd_topob_tile_in(topo, "snapwr", i, "metric_in", "snapwh_wr", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
863 0 : FOR(snapwr_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapwr", i ) ], &topo->objs[ topo->links[ fd_topo_find_link( topo, "snapwm_wh", 0UL ) ].dcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_ONLY );
864 0 : }
865 0 : if( snapshot_lthash_disabled ) {
866 0 : if( vinyl_enabled ) {
867 0 : /**/ fd_topob_tile_out( topo, "snapwm", 0UL, "snapwm_ct", 0UL );
868 0 : fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapwm_ct", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
869 0 : } else {
870 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_ct", 0UL );
871 0 : fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapin_ct", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
872 0 : }
873 0 : } else {
874 0 : if( vinyl_enabled ) {
875 0 : FOR(snaplh_tile_cnt) fd_topob_tile_in ( topo, "snaplh", i, "metric_in", "snapwh_wr", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
876 0 : FOR(snaplh_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snaplh", i ) ], &topo->objs[ topo->links[ fd_topo_find_link( topo, "snapwm_wh", 0UL ) ].dcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_ONLY );
877 0 : FOR(snaplh_tile_cnt) fd_topob_tile_in ( topo, "snaplh", i, "metric_in", "snaplv_lh", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
878 0 : /**/ fd_topob_tile_out( topo, "snaplv", 0UL, "snaplv_lh", 0UL );
879 0 : FOR(snaplh_tile_cnt) fd_topob_tile_out( topo, "snaplh", i, "snaplh_lv", i );
880 0 : /**/ fd_topob_tile_in ( topo, "snaplv", 0UL, "metric_in", "snapwm_lv", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
881 0 : FOR(snaplh_tile_cnt) fd_topob_tile_in ( topo, "snaplv", 0UL, "metric_in", "snaplh_lv", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
882 0 : /**/ fd_topob_tile_out( topo, "snaplv", 0UL, "snaplv_ct", 0UL );
883 0 : /**/ fd_topob_tile_out( topo, "snapwm", 0UL, "snapwm_lv", 0UL );
884 0 : /**/ fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snaplv_ct", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
885 :
886 0 : fd_topo_obj_t * vinyl_admin_obj = setup_topo_vinyl_admin( topo, "vinyl_admin" );
887 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapwm", 0UL ) ], vinyl_admin_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
888 0 : FOR(snapwr_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapwr", i ) ], vinyl_admin_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
889 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snaplv", 0UL ) ], vinyl_admin_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
890 0 : FOR(snaplh_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snaplh", i ) ], vinyl_admin_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
891 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, vinyl_admin_obj->id, "vinyl_admin" ) );
892 0 : } else {
893 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_ls", 0UL );
894 0 : FOR(lta_tile_cnt) fd_topob_tile_in( topo, "snapla", i, "metric_in", "snapdc_in", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
895 0 : FOR(lta_tile_cnt) fd_topob_tile_out( topo, "snapla", i, "snapla_ls", i );
896 0 : /**/ fd_topob_tile_in( topo, "snapls", 0UL, "metric_in", "snapin_ls", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
897 0 : FOR(lta_tile_cnt) fd_topob_tile_in( topo, "snapls", 0UL, "metric_in", "snapla_ls", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
898 0 : /**/ fd_topob_tile_out( topo, "snapls", 0UL, "snapls_ct", 0UL );
899 0 : /**/ fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapls_ct", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
900 0 : }
901 0 : }
902 :
903 0 : /**/ fd_topob_tile_in ( topo, "snapld", 0UL, "metric_in", "snapct_ld", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
904 0 : /**/ fd_topob_tile_out( topo, "snapld", 0UL, "snapld_dc", 0UL );
905 :
906 0 : /**/ fd_topob_tile_in ( topo, "snapdc", 0UL, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
907 0 : /**/ fd_topob_tile_out( topo, "snapdc", 0UL, "snapdc_in", 0UL );
908 :
909 0 : fd_topob_tile_in ( topo, "snapin", 0UL, "metric_in", "snapdc_in", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
910 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
911 0 : /**/ fd_topob_tile_out( topo, "snapin", 0UL, "snapin_gui", 0UL );
912 0 : }
913 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_manif", 0UL );
914 0 : }
915 :
916 0 : /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
917 0 : /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
918 0 : /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
919 0 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "shred_out", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
920 0 : if( snapshots_enabled ) {
921 0 : fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
922 0 : }
923 0 : /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
924 0 : /**/ fd_topob_tile_out( topo, "repair", 0UL, "repair_out", 0 );
925 :
926 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "repair_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
927 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
928 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_out", 0UL );
929 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_epoch", 0UL );
930 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_execrp", 0UL );
931 0 : FOR(execrp_tile_cnt) fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "execrp_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
932 0 : if(leader_enabled) {fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "poh_replay", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );}
933 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
934 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "txsend_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
935 0 : FOR(resolv_tile_cnt) fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "resolv_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
936 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
937 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
938 0 : if( FD_LIKELY( snapshots_enabled ) ) {
939 0 : fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
940 0 : }
941 :
942 0 : FOR(execrp_tile_cnt) fd_topob_tile_in ( topo, "execrp", i, "metric_in", "replay_execrp", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
943 0 : FOR(execrp_tile_cnt) fd_topob_tile_out( topo, "execrp", i, "execrp_replay", i );
944 :
945 0 : if(leader_enabled) {fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "dedup_resolv", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );}
946 0 : /**/ fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
947 0 : /**/ fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
948 0 : /**/ fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
949 0 : /**/ fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
950 0 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "tower", 0UL, "metric_in", "shred_out", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
951 0 : /**/ fd_topob_tile_out( topo, "tower", 0UL, "tower_out", 0UL );
952 :
953 0 : /**/ fd_topob_tile_in ( topo, "txsend", 0UL, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
954 0 : /**/ fd_topob_tile_in ( topo, "txsend", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
955 0 : /**/ fd_topob_tile_in ( topo, "txsend", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
956 0 : /**/ fd_topob_tile_out( topo, "txsend", 0UL, "txsend_net", 0UL );
957 0 : /**/ fd_topob_tile_out( topo, "txsend", 0UL, "txsend_out", 0UL );
958 :
959 0 : if( leader_enabled ) {
960 0 : FOR(quic_tile_cnt) fd_topob_tile_out( topo, "quic", i, "quic_verify", i );
961 0 : FOR(quic_tile_cnt) fd_topob_tile_out( topo, "quic", i, "quic_net", i );
962 : /* All verify tiles read from all QUIC tiles, packets are round robin. */
963 0 : FOR(verify_tile_cnt) for( ulong j=0UL; j<quic_tile_cnt; j++ )
964 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 */
965 0 : FOR(verify_tile_cnt) fd_topob_tile_in( topo, "verify", i, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
966 0 : /**/ fd_topob_tile_in( topo, "verify", 0UL, "metric_in", "txsend_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
967 0 : FOR(verify_tile_cnt) fd_topob_tile_out( topo, "verify", i, "verify_dedup", i );
968 0 : FOR(verify_tile_cnt) fd_topob_tile_in( topo, "dedup", 0UL, "metric_in", "verify_dedup", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
969 0 : /**/ fd_topob_tile_in( topo, "dedup", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
970 0 : /**/ fd_topob_tile_out( topo, "dedup", 0UL, "dedup_resolv", 0UL );
971 0 : FOR(resolv_tile_cnt) fd_topob_tile_in( topo, "resolv", i, "metric_in", "dedup_resolv", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
972 0 : FOR(resolv_tile_cnt) fd_topob_tile_in( topo, "resolv", i, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
973 0 : FOR(resolv_tile_cnt) fd_topob_tile_out( topo, "resolv", i, "resolv_pack", i );
974 0 : FOR(resolv_tile_cnt) fd_topob_tile_out( topo, "resolv", i, "resolv_replay", i );
975 0 : /**/ fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "resolv_pack", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
976 0 : /**/ fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
977 0 : /**/ fd_topob_tile_out( topo, "pack", 0UL, "pack_execle", 0UL );
978 0 : /**/ fd_topob_tile_out( topo, "pack", 0UL, "pack_poh" , 0UL );
979 0 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
980 0 : FOR(execle_tile_cnt) fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "execle_pack", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
981 0 : }
982 0 : FOR(execle_tile_cnt) fd_topob_tile_in ( topo, "execle", i, "metric_in", "pack_execle", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
983 0 : FOR(execle_tile_cnt) fd_topob_tile_out( topo, "execle", i, "execle_poh", i );
984 0 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
985 0 : FOR(execle_tile_cnt)fd_topob_tile_out(topo, "execle", i, "execle_pack", i );
986 0 : }
987 0 : FOR(execle_tile_cnt) fd_topob_tile_in ( topo, "poh", 0UL, "metric_in", "execle_poh", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
988 0 : /**/ fd_topob_tile_in ( topo, "poh", 0UL, "metric_in", "pack_poh", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
989 0 : /**/ fd_topob_tile_in ( topo, "poh", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
990 0 : /**/ fd_topob_tile_out( topo, "poh", 0UL, "poh_shred", 0UL );
991 0 : /**/ fd_topob_tile_out( topo, "poh", 0UL, "poh_replay", 0UL );
992 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "poh_shred", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
993 0 : }
994 :
995 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
996 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
997 0 : FOR(shred_tile_cnt) fd_topob_tile_out( topo, "shred", i, "shred_out", i );
998 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
999 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "tower_out", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1000 0 : FOR(shred_tile_cnt) fd_topob_tile_out( topo, "shred", i, "shred_net", i );
1001 :
1002 0 : if( FD_LIKELY( telemetry_enabled ) ) {
1003 0 : fd_topob_wksp( topo, "event" );
1004 0 : fd_topob_wksp( topo, "event_sign" );
1005 0 : fd_topob_wksp( topo, "sign_event" );
1006 0 : fd_topob_link( topo, "event_sign", "event_sign", 128UL, 32UL, 1UL );
1007 0 : fd_topob_link( topo, "sign_event", "sign_event", 128UL, 64UL, 1UL );
1008 0 : fd_topob_tile( topo, "event", "event", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 0 );
1009 0 : fd_topob_tile_in( topo, "event", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1010 0 : fd_topob_tile_in( topo, "event", 0UL, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1011 :
1012 0 : if( FD_UNLIKELY( config->development.event.report_shreds ) ) {
1013 : /* TODO: This needs to be reliable, else we could miss shreds that
1014 : are required to replay the chain, but we can't change it yet as
1015 : the XDP tile does not support reliable consumers. */
1016 0 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "event", 0UL, "metric_in", "net_shred", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1017 0 : }
1018 :
1019 0 : if( FD_UNLIKELY( config->development.event.report_transactions ) ) {
1020 0 : fd_topob_tile_in( topo, "event", 0UL, "metric_in", "dedup_resolv", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1021 0 : }
1022 :
1023 0 : fd_topob_tile_in( topo, "sign", 0UL, "metric_in", "event_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1024 0 : fd_topob_tile_out( topo, "event", 0UL, "event_sign", 0UL );
1025 0 : fd_topob_tile_in( topo, "event", 0UL, "metric_in", "sign_event", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
1026 0 : fd_topob_tile_out( topo, "sign", 0UL, "sign_event", 0UL );
1027 0 : }
1028 :
1029 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1030 0 : fd_topob_wksp( topo, "bundle_verif" );
1031 0 : fd_topob_wksp( topo, "bundle_sign" );
1032 0 : fd_topob_wksp( topo, "sign_bundle" );
1033 0 : fd_topob_wksp( topo, "pack_sign" );
1034 0 : fd_topob_wksp( topo, "sign_pack" );
1035 0 : fd_topob_wksp( topo, "bundle" );
1036 :
1037 0 : /**/ fd_topob_link( topo, "bundle_verif", "bundle_verif", config->tiles.verify.receive_buffer_size, FD_TPU_PARSED_MTU, 1UL );
1038 0 : /**/ fd_topob_link( topo, "bundle_sign", "bundle_sign", 65536UL, 9UL, 1UL );
1039 0 : /**/ fd_topob_link( topo, "sign_bundle", "sign_bundle", 128UL, 64UL, 1UL );
1040 0 : /**/ fd_topob_link( topo, "pack_sign", "pack_sign", 65536UL, 1232UL, 1UL );
1041 0 : /**/ fd_topob_link( topo, "sign_pack", "sign_pack", 128UL, 64UL, 1UL );
1042 :
1043 : /**/ fd_topob_tile( topo, "bundle", "bundle", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 0 );
1044 :
1045 : /**/ fd_topob_tile_out( topo, "bundle", 0UL, "bundle_verif", 0UL );
1046 0 : FOR(verify_tile_cnt) fd_topob_tile_in( topo, "verify", i, "metric_in", "bundle_verif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1047 :
1048 0 : /**/ fd_topob_tile_in( topo, "sign", 0UL, "metric_in", "bundle_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1049 0 : /**/ fd_topob_tile_out( topo, "bundle", 0UL, "bundle_sign", 0UL );
1050 0 : /**/ fd_topob_tile_in( topo, "bundle", 0UL, "metric_in", "sign_bundle", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
1051 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_bundle", 0UL );
1052 :
1053 0 : if( leader_enabled ) {
1054 0 : /**/ fd_topob_tile_in( topo, "sign", 0UL, "metric_in", "pack_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1055 0 : /**/ fd_topob_tile_out( topo, "pack", 0UL, "pack_sign", 0UL );
1056 0 : /**/ fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "sign_pack", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
1057 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_pack", 0UL );
1058 0 : }
1059 :
1060 0 : if( config->tiles.gui.enabled ) { /* GUI is the only consumer of bundle_status */
1061 0 : fd_topob_wksp( topo, "bundle_status" );
1062 : /* bundle_status must be kind of deep, to prevent exhausting
1063 : shared flow control credits when publishing many packets at
1064 : once. */
1065 0 : fd_topob_link( topo, "bundle_status", "bundle_status", 128UL, sizeof(fd_bundle_block_engine_update_t), 1UL );
1066 0 : fd_topob_tile_out( topo, "bundle", 0UL, "bundle_status", 0UL );
1067 0 : }
1068 0 : }
1069 :
1070 : /* Sign links don't need to be reliable because they are synchronous,
1071 : so there's at most one fragment in flight at a time anyway. The
1072 : sign links are also not polled by fd_stem, instead the tiles will
1073 : read the sign responses out of band in a dedicated spin loop.
1074 :
1075 : TODO: This can probably be fixed now to be relible ... ? */
1076 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
1077 0 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "gossip_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1078 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_sign", 0UL );
1079 0 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "sign_gossip", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
1080 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_gossip", 0UL );
1081 :
1082 0 : for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
1083 0 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "shred_sign", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1084 0 : /**/ fd_topob_tile_out( topo, "shred", i, "shred_sign", i );
1085 0 : /**/ fd_topob_tile_in ( topo, "shred", i, "metric_in", "sign_shred", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
1086 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_shred", i );
1087 0 : }
1088 :
1089 0 : FOR(sign_tile_cnt-1UL) fd_topob_tile_out( topo, "repair", 0UL, "repair_sign", i );
1090 0 : FOR(sign_tile_cnt-1UL) fd_topob_tile_in ( topo, "sign", i+1UL, "metric_in", "repair_sign", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1091 0 : FOR(sign_tile_cnt-1UL) fd_topob_tile_out( topo, "sign", i+1UL, "sign_repair", i );
1092 0 : FOR(sign_tile_cnt-1UL) fd_topob_tile_in ( topo, "repair", 0UL, "metric_in", "sign_repair", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* This link is polled because the signing requests are asynchronous */
1093 :
1094 0 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "txsend_sign", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1095 0 : /**/ fd_topob_tile_out( topo, "txsend", 0UL, "txsend_sign", 0UL );
1096 0 : /**/ fd_topob_tile_in ( topo, "txsend", 0UL, "metric_in", "sign_txsend", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
1097 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_txsend", 0UL );
1098 :
1099 0 : if( FD_UNLIKELY( config->tiles.archiver.enabled ) ) {
1100 0 : fd_topob_wksp( topo, "arch_f" );
1101 0 : fd_topob_wksp( topo, "arch_w" );
1102 0 : fd_topob_wksp( topo, "feeder" );
1103 0 : fd_topob_wksp( topo, "arch_f2w" );
1104 :
1105 0 : fd_topob_link( topo, "feeder", "feeder", 65536UL, 4UL*FD_SHRED_STORE_MTU, 4UL+config->tiles.shred.max_pending_shred_sets );
1106 0 : fd_topob_link( topo, "arch_f2w", "arch_f2w", 128UL, 4UL*FD_SHRED_STORE_MTU, 1UL );
1107 :
1108 0 : fd_topob_tile( topo, "arch_f", "arch_f", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
1109 0 : fd_topob_tile( topo, "arch_w", "arch_w", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
1110 :
1111 0 : fd_topob_tile_out( topo, "replay", 0UL, "feeder", 0UL );
1112 0 : fd_topob_tile_in( topo, "arch_f", 0UL, "metric_in", "feeder", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1113 :
1114 0 : fd_topob_tile_out( topo, "arch_f", 0UL, "arch_f2w", 0UL );
1115 0 : fd_topob_tile_in( topo, "arch_w", 0UL, "metric_in", "arch_f2w", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1116 0 : }
1117 :
1118 0 : if( FD_UNLIKELY( config->tiles.shredcap.enabled ) ) {
1119 0 : fd_topob_wksp( topo, "scap" );
1120 :
1121 0 : fd_topob_tile( topo, "scap", "scap", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0, 0 );
1122 :
1123 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "repair_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1124 0 : for( ulong j=0UL; j<net_tile_cnt; j++ ) {
1125 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "net_shred", j, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1126 0 : }
1127 0 : for( ulong j=0UL; j<shred_tile_cnt; j++ ) {
1128 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "shred_out", j, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1129 0 : }
1130 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1131 :
1132 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1133 :
1134 : /* No default fd_topob_tile_in connection to stake_out */
1135 0 : }
1136 :
1137 0 : if( FD_UNLIKELY( rpc_enabled ) ) {
1138 0 : fd_topob_link( topo, "rpc_replay", "rpc_replay", 8UL, 0UL, 1UL );
1139 0 : fd_topob_tile_out( topo, "rpc", 0UL, "rpc_replay", 0UL );
1140 :
1141 0 : fd_topob_tile_in( topo, "rpc", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1142 0 : fd_topob_tile_in( topo, "rpc", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1143 0 : fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "rpc_replay", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1144 0 : fd_topob_tile_in( topo, "rpc", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1145 0 : }
1146 :
1147 0 : if( FD_UNLIKELY( solcap_enabled ) ) {
1148 0 : fd_topob_link( topo, "cap_repl", "solcap", 32UL, SOLCAP_WRITE_ACCOUNT_DATA_MTU, 1UL );
1149 0 : fd_topob_tile_out( topo, "replay", 0UL, "cap_repl", 0UL );
1150 0 : fd_topob_tile_in( topo, "solcap", 0UL, "metric_in", "cap_repl", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1151 0 : FOR(execrp_tile_cnt) fd_topob_link( topo, "cap_execrp", "solcap", 32UL, SOLCAP_WRITE_ACCOUNT_DATA_MTU, 1UL );
1152 0 : FOR(execrp_tile_cnt) fd_topob_tile_out( topo, "execrp", i, "cap_execrp", i );
1153 0 : FOR(execrp_tile_cnt) fd_topob_tile_in( topo, "solcap", 0UL, "metric_in", "cap_execrp", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1154 0 : }
1155 :
1156 0 : if( FD_LIKELY( !is_auto_affinity ) ) {
1157 0 : if( FD_UNLIKELY( affinity_tile_cnt<topo->tile_cnt ) )
1158 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. "
1159 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 "
1160 0 : "the total tile count. You can reduce the tile count by decreasing individual tile counts in the [layout] section of the configuration file.",
1161 0 : topo->tile_cnt, affinity_tile_cnt ));
1162 0 : if( FD_UNLIKELY( affinity_tile_cnt>topo->tile_cnt ) )
1163 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. "
1164 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 "
1165 0 : "individual tile counts in the [layout] section of the configuration file.",
1166 0 : topo->tile_cnt, affinity_tile_cnt ));
1167 0 : } else {
1168 0 : ushort blocklist_cores[ FD_TILE_MAX ];
1169 0 : topo->blocklist_cores_cnt = fd_tile_private_cpus_parse( config->layout.blocklist_cores, blocklist_cores );
1170 0 : if( FD_UNLIKELY( topo->blocklist_cores_cnt>FD_TILE_MAX ) ) {
1171 0 : FD_LOG_ERR(( "The CPU string in the configuration file under [layout.blocklist_cores] specifies more CPUs than Firedancer can use. "
1172 0 : "You should reduce the number of CPUs in the excluded cores string." ));
1173 0 : }
1174 :
1175 0 : for( ulong i=0UL; i<topo->blocklist_cores_cnt; i++ ) {
1176 : /* Since we use fd_tile_private_cpus_parse() like for affinity, the user
1177 : may input a string containing `f`. That's parsed correctly, but it's
1178 : meaningless for blocklisted cores, so we reject it here. */
1179 0 : if( FD_UNLIKELY( blocklist_cores[ i ]==USHORT_MAX ) ) {
1180 0 : FD_LOG_ERR(( "The CPU string in the configuration file under [layout.blocklist_cores] contains invalid values: `f`. "
1181 0 : "You should fix the excluded cores string." ));
1182 0 : }
1183 0 : topo->blocklist_cores_cpu_idx[ i ] = blocklist_cores[ i ];
1184 0 : }
1185 0 : }
1186 :
1187 0 : if( FD_UNLIKELY( is_auto_affinity ) ) fd_topob_auto_layout( topo, 0 );
1188 :
1189 : /* There is a special fseq that sits between the pack, execle, and poh
1190 : tiles to indicate when the execle/poh tiles are done processing a
1191 : microblock. Pack uses this to determine when to "unlock" accounts
1192 : that it marked as locked because they were being used. */
1193 :
1194 0 : for( ulong i=0UL; i<execle_tile_cnt; i++ ) {
1195 0 : fd_topo_obj_t * busy_obj = fd_topob_obj( topo, "fseq", "execle_busy" );
1196 :
1197 0 : fd_topo_tile_t * pack_tile = &topo->tiles[ fd_topo_find_tile( topo, "pack", 0UL ) ];
1198 0 : fd_topo_tile_t * execle_tile = &topo->tiles[ fd_topo_find_tile( topo, "execle", i ) ];
1199 0 : fd_topob_tile_uses( topo, pack_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1200 0 : fd_topob_tile_uses( topo, execle_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1201 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, busy_obj->id, "execle_busy.%lu", i ) );
1202 0 : }
1203 :
1204 : /* Repair and shred share a secret they use to generate the nonces.
1205 : It's not super security sensitive, but for good hygiene, we make it
1206 : an object. */
1207 0 : if( 1 /* just restrict the scope for these variables in this big function */ ) {
1208 0 : fd_topo_obj_t * rnonce_ss_obj = fd_topob_obj( topo, "rnonce_ss", "rnonce" );
1209 0 : fd_topo_tile_t * repair_tile = &topo->tiles[ fd_topo_find_tile( topo, "repair", 0UL ) ];
1210 0 : fd_topob_tile_uses( topo, repair_tile, rnonce_ss_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1211 0 : for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
1212 0 : fd_topo_tile_t * shred_tile = &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ];
1213 0 : fd_topob_tile_uses( topo, shred_tile, rnonce_ss_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1214 0 : }
1215 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, rnonce_ss_obj->id, "rnonce_ss" ) );
1216 0 : }
1217 :
1218 0 : setup_topo_funk( topo,
1219 0 : config->firedancer.accounts.max_accounts,
1220 0 : config->firedancer.runtime.max_live_slots + config->firedancer.accounts.write_delay_slots,
1221 0 : config->firedancer.accounts.in_memory_only
1222 0 : ? config->firedancer.accounts.file_size_gib
1223 0 : : config->firedancer.accounts.max_unrooted_account_size_gib );
1224 0 : ulong funk_obj_id; FD_TEST( (funk_obj_id = fd_pod_query_ulong( topo->props, "funk", ULONG_MAX ))!=ULONG_MAX );
1225 0 : ulong funk_locks_obj_id; FD_TEST( (funk_locks_obj_id = fd_pod_query_ulong( topo->props, "funk_locks", ULONG_MAX ))!=ULONG_MAX );
1226 0 : fd_topo_obj_t * funk_obj = &topo->objs[ funk_obj_id ];
1227 0 : fd_topo_obj_t * funk_locks_obj = &topo->objs[ funk_locks_obj_id ];
1228 :
1229 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1230 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "tower", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1231 0 : FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1232 0 : FOR(execle_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execle", i ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1233 0 : FOR(resolv_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "resolv", i ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1234 :
1235 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1236 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "tower", 0UL ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1237 0 : FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1238 0 : FOR(execle_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execle", i ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1239 0 : FOR(resolv_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "resolv", i ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1240 :
1241 0 : fd_topo_obj_t * banks_obj = setup_topo_banks( topo, "banks", config->firedancer.runtime.max_live_slots, config->firedancer.runtime.max_fork_width, config->development.bench.larger_max_cost_per_block );
1242 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1243 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "tower", 0UL ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1244 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 );
1245 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 );
1246 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 );
1247 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, banks_obj->id, "banks" ) );
1248 :
1249 0 : fd_topo_obj_t * banks_locks_obj = setup_topo_banks_locks( topo, "banks_locks" );
1250 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], banks_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1251 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "tower", 0UL ) ], banks_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1252 0 : FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i ) ], banks_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1253 0 : FOR(execle_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execle", i ) ], banks_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1254 0 : FOR(resolv_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "resolv", i ) ], banks_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1255 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, banks_locks_obj->id, "banks_locks" ) );
1256 :
1257 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1258 0 : if( FD_UNLIKELY( config->firedancer.runtime.max_account_cnt<FD_ACC_POOL_MIN_ACCOUNT_CNT_PER_BUNDLE ) ) {
1259 0 : FD_LOG_ERR(( "max_account_cnt is less than the minimum required for bundle execution: %lu < %lu", config->firedancer.runtime.max_account_cnt, FD_ACC_POOL_MIN_ACCOUNT_CNT_PER_BUNDLE ));
1260 0 : }
1261 0 : }
1262 0 : if( FD_UNLIKELY( config->firedancer.runtime.max_account_cnt<FD_ACC_POOL_MIN_ACCOUNT_CNT_PER_TX ) ) {
1263 0 : FD_LOG_ERR(( "max_account_cnt is less than the minimum required for transaction execution: %lu < %lu", config->firedancer.runtime.max_account_cnt, FD_ACC_POOL_MIN_ACCOUNT_CNT_PER_TX ));
1264 0 : }
1265 0 : if( FD_UNLIKELY( config->firedancer.runtime.max_live_slots<32UL ) ) {
1266 0 : FD_LOG_ERR(( "max_live_slots must be >= 32 in order to support tower rooting" ));
1267 0 : }
1268 0 : if( FD_UNLIKELY( config->firedancer.runtime.max_live_slots+config->firedancer.accounts.write_delay_slots>FD_ACCDB_MAX_DEPTH_MAX ) ) {
1269 0 : FD_LOG_ERR(( "max_live_slots+write_delay_slots (%lu+%lu) exceeds compile-time limit FD_ACCDB_MAX_DEPTH_MAX (%lu)",
1270 0 : config->firedancer.runtime.max_live_slots, config->firedancer.accounts.write_delay_slots, FD_ACCDB_MAX_DEPTH_MAX ));
1271 0 : }
1272 :
1273 0 : fd_topo_obj_t * acc_pool_obj = setup_topo_acc_pool( topo, config->firedancer.runtime.max_account_cnt );
1274 0 : FOR(execrp_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execrp", i ) ], acc_pool_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1275 0 : FOR(execle_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "execle", i ) ], acc_pool_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1276 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, acc_pool_obj->id, "acc_pool" ) );
1277 :
1278 0 : setup_topo_progcache( topo, "progcache",
1279 0 : fd_progcache_est_rec_max( config->firedancer.runtime.program_cache.heap_size_mib<<20,
1280 0 : config->firedancer.runtime.program_cache.mean_cache_entry_size ),
1281 0 : config->firedancer.runtime.max_live_slots,
1282 0 : config->firedancer.runtime.program_cache.heap_size_mib<<20 );
1283 0 : ulong progcache_obj_id; FD_TEST( (progcache_obj_id = fd_pod_query_ulong( topo->props, "progcache", ULONG_MAX ))!=ULONG_MAX );
1284 0 : fd_topo_obj_t * progcache_obj = &topo->objs[ progcache_obj_id ];
1285 :
1286 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1287 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 );
1288 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 );
1289 :
1290 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
1291 0 : fd_topob_wksp( topo, "gui" );
1292 :
1293 : /**/ fd_topob_tile( topo, "gui", "gui", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1, 0 );
1294 :
1295 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
1296 0 : FOR(net_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "net_gossvf", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
1297 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "repair_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1298 0 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "shred_out", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1299 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "gossip_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
1300 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1301 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1302 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1303 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "replay_epoch", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1304 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1305 0 : if( leader_enabled ) {
1306 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "pack_poh", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1307 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "pack_execle", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1308 0 : FOR(execle_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "execle_poh", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1309 0 : }
1310 0 : FOR(execrp_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "execrp_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1311 :
1312 0 : if( FD_LIKELY( snapshots_enabled ) ) {
1313 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "snapct_gui", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1314 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "snapin_gui", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1315 0 : }
1316 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1317 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "bundle_status", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
1318 0 : }
1319 0 : }
1320 :
1321 0 : ulong fec_set_cnt = 2UL*shred_depth + config->tiles.shred.max_pending_shred_sets + 6UL;
1322 0 : ulong fec_sets_sz = fec_set_cnt*sizeof(fd_fec_set_t); /* mirrors # of dcache entires in frankendancer */
1323 0 : fd_topo_obj_t * fec_sets_obj = setup_topo_fec_sets( topo, "fec_sets", shred_tile_cnt*fec_sets_sz );
1324 0 : for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
1325 0 : fd_topo_tile_t * shred_tile = &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ];
1326 0 : fd_topob_tile_uses( topo, shred_tile, fec_sets_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1327 0 : }
1328 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "repair", 0UL ) ], fec_sets_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1329 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, fec_sets_obj->id, "fec_sets" ) );
1330 :
1331 : /* The Store fec_max parameter is the max number of FEC sets that can
1332 : be retained by store.
1333 :
1334 : The base value is from multiplying max_live_slots by the maximum
1335 : number of FEC sets in a block (which is 1024, given the current
1336 : consensus limit of 32768 shreds per block). This is notably, the
1337 : total capacity of reasm.
1338 :
1339 : Store needs to hold _at least_ depth(shred_out) +
1340 : depth(repair_out) + 1 more FEC sets than reasm. Shred inserts
1341 : FECs into store (before publishing to shred_out) and Replay
1342 : inserts FECs into reasm (after consuming from repair_out), so
1343 : store can be up to depth(shred_out) + depth(repair_out) ahead of
1344 : reasm. We + 1 because replay tile can be mid-process of ingesting
1345 : a FEC set.
1346 :
1347 : store is exactly this total depth ahead of reasm, then this means
1348 : the links must be full and shred is backpressured via repair_out
1349 : -> shred_out. Thus, no more FEC sets will be inserted to store
1350 : until reasm inserts the next FEC, at which point it must be at
1351 : capacity (given store is _at least_ total depth larger) and will
1352 : evict a FEC which is together evicted from store. */
1353 :
1354 0 : fd_topo_link_t * repair_out_link = &topo->links[ fd_topo_find_link( topo, "repair_out", 0UL ) ];
1355 0 : ulong store_fec_max = fd_ulong_pow2_up( config->firedancer.runtime.max_live_slots * FD_FEC_BLK_MAX + (shred_depth * shred_tile_cnt) + repair_out_link->depth + 1 );
1356 :
1357 0 : fd_topo_obj_t * store_obj = setup_topo_store( topo, "store", store_fec_max, (uint)shred_tile_cnt );
1358 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 );
1359 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1360 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, store_obj->id, "store" ) );
1361 :
1362 0 : fd_topo_obj_t * txncache_obj = setup_topo_txncache( topo, "txncache", config->firedancer.runtime.max_live_slots, FD_PACK_MAX_TXNCACHE_TXN_PER_SLOT );
1363 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1364 0 : if( FD_LIKELY( snapshots_enabled ) ) {
1365 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1366 0 : }
1367 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 );
1368 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 );
1369 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
1370 :
1371 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "genesi", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1372 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "genesi", 0UL ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1373 0 : if( FD_LIKELY( snapshots_enabled ) ) {
1374 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1375 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1376 0 : }
1377 :
1378 0 : if( FD_UNLIKELY( rpc_enabled ) ) {
1379 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "rpc", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1380 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "rpc", 0UL ) ], funk_locks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1381 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "rpc", 0UL ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1382 0 : }
1383 :
1384 0 : fd_pod_insert_int( topo->props, "sandbox", config->development.sandbox ? 1 : 0 );
1385 :
1386 0 : if( vinyl_enabled ) {
1387 0 : fd_topob_vinyl_rq( topo, "genesi", 0UL, "accdb_genesi", "genesi", 4UL, 1024UL, 1024UL );
1388 0 : fd_topob_vinyl_rq( topo, "replay", 0UL, "accdb_replay", "replay", 4UL, 1024UL, 1024UL );
1389 0 : for( ulong i=0UL; i<execrp_tile_cnt; i++ ) {
1390 0 : fd_topob_vinyl_rq( topo, "execrp", i, "accdb_execrp", "execrp", 4UL, 1024UL, 1024UL );
1391 0 : }
1392 0 : for( ulong i=0UL; i<execle_tile_cnt; i++ ) {
1393 0 : fd_topob_vinyl_rq( topo, "execle", i, "accdb_execle", "execle", 4UL, 1024UL, 1024UL );
1394 0 : }
1395 0 : fd_topob_vinyl_rq( topo, "tower", 0UL, "accdb_tower", "tower", 4UL, 128UL, 128UL );
1396 0 : FOR(resolv_tile_cnt) fd_topob_vinyl_rq( topo, "resolv", i, "accdb_resolv", "resolv", 4UL, 1UL, 1UL );
1397 0 : if( rpc_enabled ) {
1398 0 : fd_topob_vinyl_rq( topo, "rpc", 0UL, "accdb_rpc", "rpc", 4UL, 1UL, 1UL );
1399 0 : }
1400 0 : }
1401 :
1402 0 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
1403 0 : fd_topo_configure_tile( &topo->tiles[ i ], config );
1404 0 : if( FD_UNLIKELY( !strcmp( topo->tiles[ i ].name, "gui" ) ) ) topo->tiles[ i ].gui.tile_cnt = topo->tile_cnt;
1405 0 : }
1406 :
1407 0 : FOR(net_tile_cnt) fd_topos_net_tile_finish( topo, i );
1408 0 : fd_topob_finish( topo, CALLBACKS );
1409 0 : config->topo = *topo;
1410 0 : }
1411 :
1412 : void
1413 : fd_topo_configure_tile( fd_topo_tile_t * tile,
1414 0 : fd_config_t * config ) {
1415 0 : if( FD_UNLIKELY( !strcmp( tile->name, "metric" ) ) ) {
1416 :
1417 0 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.metric.prometheus_listen_address, &tile->metric.prometheus_listen_addr ) ) )
1418 0 : FD_LOG_ERR(( "failed to parse prometheus listen address `%s`", config->tiles.metric.prometheus_listen_address ));
1419 0 : tile->metric.prometheus_listen_port = config->tiles.metric.prometheus_listen_port;
1420 :
1421 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "event" ) ) ) {
1422 :
1423 0 : fd_cstr_ncpy( tile->event.identity_key_path, config->paths.identity_key, sizeof(tile->event.identity_key_path) );
1424 0 : fd_cstr_ncpy( tile->event.url, config->tiles.event.url, sizeof(tile->event.url) );
1425 :
1426 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "net" ) || !strcmp( tile->name, "sock" ) ) ) {
1427 :
1428 0 : tile->net.shred_listen_port = config->tiles.shred.shred_listen_port;
1429 0 : if( config->firedancer.layout.enable_block_production ) {
1430 0 : tile->net.quic_transaction_listen_port = config->tiles.quic.quic_transaction_listen_port;
1431 0 : tile->net.legacy_transaction_listen_port = config->tiles.quic.regular_transaction_listen_port;
1432 0 : }
1433 0 : tile->net.gossip_listen_port = config->gossip.port;
1434 0 : tile->net.repair_intake_listen_port = config->tiles.repair.repair_intake_listen_port;
1435 0 : tile->net.repair_serve_listen_port = config->tiles.repair.repair_serve_listen_port;
1436 0 : tile->net.txsend_src_port = config->tiles.txsend.txsend_src_port;
1437 :
1438 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "netlnk" ) ) ) {
1439 :
1440 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "ipecho") ) ) {
1441 :
1442 0 : tile->ipecho.expected_shred_version = config->consensus.expected_shred_version;
1443 0 : tile->ipecho.bind_address = config->net.ip_addr;
1444 0 : tile->ipecho.bind_port = config->gossip.port;
1445 0 : tile->ipecho.entrypoints_cnt = config->gossip.entrypoints_cnt;
1446 0 : fd_memcpy( tile->ipecho.entrypoints, config->gossip.resolved_entrypoints, tile->ipecho.entrypoints_cnt * sizeof(fd_ip4_port_t) );
1447 :
1448 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "genesi" ) ) ) {
1449 :
1450 0 : tile->genesi.validate_genesis_hash = config->firedancer.development.genesis.validate_genesis_hash;
1451 0 : tile->genesi.allow_download = config->firedancer.snapshots.genesis_download;
1452 0 : fd_cstr_ncpy( tile->genesi.genesis_path, config->paths.genesis, sizeof(tile->genesi.genesis_path) );
1453 0 : tile->genesi.expected_shred_version = config->consensus.expected_shred_version;
1454 0 : tile->genesi.entrypoints_cnt = config->gossip.entrypoints_cnt;
1455 0 : fd_memcpy( tile->genesi.entrypoints, config->gossip.resolved_entrypoints, tile->genesi.entrypoints_cnt * sizeof(fd_ip4_port_t) );
1456 :
1457 0 : tile->genesi.has_expected_genesis_hash = !!strcmp( config->consensus.expected_genesis_hash, "" );
1458 :
1459 0 : if( FD_UNLIKELY( strcmp( config->consensus.expected_genesis_hash, "" ) && !fd_base58_decode_32( config->consensus.expected_genesis_hash, tile->genesi.expected_genesis_hash ) ) ) {
1460 0 : FD_LOG_ERR(( "failed to decode [consensus.expected_genesis_hash] \"%s\" as base58", config->consensus.expected_genesis_hash ));
1461 0 : }
1462 :
1463 0 : tile->genesi.target_gid = config->gid;
1464 0 : tile->genesi.target_uid = config->uid;
1465 0 : tile->genesi.accdb_max_depth = config->firedancer.runtime.max_live_slots + config->firedancer.accounts.write_delay_slots;
1466 :
1467 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "gossvf") ) ) {
1468 :
1469 0 : fd_cstr_ncpy( tile->gossvf.identity_key_path, config->paths.identity_key, sizeof(tile->gossvf.identity_key_path) );
1470 0 : tile->gossvf.tcache_depth = 1<<22UL; /* TODO: user defined option */
1471 0 : tile->gossvf.shred_version = 0U;
1472 0 : tile->gossvf.allow_private_address = config->development.gossip.allow_private_address;
1473 0 : tile->gossvf.boot_timestamp_nanos = config->boot_timestamp_nanos;
1474 :
1475 0 : tile->gossvf.entrypoints_cnt = config->gossip.entrypoints_cnt;
1476 0 : fd_memcpy( tile->gossvf.entrypoints, config->gossip.resolved_entrypoints, tile->gossvf.entrypoints_cnt * sizeof(fd_ip4_port_t) );
1477 :
1478 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "gossip" ) ) ) {
1479 :
1480 0 : if( FD_UNLIKELY( strcmp( config->firedancer.gossip.host, "" ) ) ) {
1481 0 : if( !resolve_address( config->firedancer.gossip.host, &tile->gossip.ip_addr ) )
1482 0 : FD_LOG_ERR(( "could not resolve [gossip.host] %s", config->firedancer.gossip.host ));
1483 0 : } else {
1484 0 : tile->gossip.ip_addr = config->net.ip_addr;
1485 0 : }
1486 0 : fd_cstr_ncpy( tile->gossip.identity_key_path, config->paths.identity_key, sizeof(tile->gossip.identity_key_path) );
1487 0 : tile->gossip.shred_version = config->consensus.expected_shred_version;
1488 0 : tile->gossip.max_entries = config->tiles.gossip.max_entries;
1489 0 : tile->gossip.boot_timestamp_nanos = config->boot_timestamp_nanos;
1490 :
1491 0 : if( FD_LIKELY( !strcmp( config->firedancer.consensus.wait_for_supermajority_with_bank_hash, "" ) ) ) {
1492 0 : memset( tile->gossip.wait_for_supermajority_with_bank_hash.uc, 0, sizeof(fd_pubkey_t) );
1493 0 : } else if( FD_UNLIKELY( !fd_base58_decode_32( config->firedancer.consensus.wait_for_supermajority_with_bank_hash, tile->gossip.wait_for_supermajority_with_bank_hash.uc ) ) ) {
1494 0 : FD_LOG_ERR(( "[consensus.wait_for_supermajority_with_bank_hash] failed to parse" ));
1495 0 : }
1496 :
1497 0 : tile->gossip.ports.gossip = config->gossip.port;
1498 0 : tile->gossip.ports.tvu = config->tiles.shred.shred_listen_port;
1499 0 : tile->gossip.ports.tpu = config->tiles.quic.regular_transaction_listen_port;
1500 0 : tile->gossip.ports.tpu_quic = config->tiles.quic.quic_transaction_listen_port;
1501 0 : tile->gossip.ports.repair = config->tiles.repair.repair_intake_listen_port;
1502 :
1503 0 : tile->gossip.entrypoints_cnt = config->gossip.entrypoints_cnt;
1504 0 : fd_memcpy( tile->gossip.entrypoints, config->gossip.resolved_entrypoints, tile->gossip.entrypoints_cnt * sizeof(fd_ip4_port_t) );
1505 :
1506 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapct" ) ) ) {
1507 :
1508 0 : fd_memcpy( tile->snapct.snapshots_path, config->paths.snapshots, PATH_MAX );
1509 0 : tile->snapct.sources.max_local_full_effective_age = config->firedancer.snapshots.sources.max_local_full_effective_age;
1510 0 : tile->snapct.sources.max_local_incremental_age = config->firedancer.snapshots.sources.max_local_incremental_age;
1511 0 : tile->snapct.incremental_snapshots = config->firedancer.snapshots.incremental_snapshots;
1512 0 : tile->snapct.max_full_snapshots_to_keep = config->firedancer.snapshots.max_full_snapshots_to_keep;
1513 0 : tile->snapct.max_incremental_snapshots_to_keep = config->firedancer.snapshots.max_incremental_snapshots_to_keep;
1514 0 : tile->snapct.max_retry_abort = config->firedancer.snapshots.max_retry_abort;
1515 0 : tile->snapct.sources.gossip.allow_any = config->firedancer.snapshots.sources.gossip.allow_any;
1516 0 : tile->snapct.sources.gossip.allow_list_cnt = config->firedancer.snapshots.sources.gossip.allow_list_cnt;
1517 0 : tile->snapct.sources.gossip.block_list_cnt = config->firedancer.snapshots.sources.gossip.block_list_cnt;
1518 0 : tile->snapct.sources.servers_cnt = config->firedancer.snapshots.sources.servers_cnt;
1519 0 : for( ulong i=0UL; i<tile->snapct.sources.gossip.allow_list_cnt; i++ ) {
1520 0 : if( FD_UNLIKELY( !fd_base58_decode_32( config->firedancer.snapshots.sources.gossip.allow_list[ i ], tile->snapct.sources.gossip.allow_list[ i ].uc ) ) ) {
1521 0 : FD_LOG_ERR(( "[snapshots.sources.gossip.allow_list[%lu]] invalid (%s)", i, config->firedancer.snapshots.sources.gossip.allow_list[ i ] ));
1522 0 : }
1523 0 : }
1524 0 : for( ulong i=0UL; i<tile->snapct.sources.gossip.block_list_cnt; i++ ) {
1525 0 : if( FD_UNLIKELY( !fd_base58_decode_32( config->firedancer.snapshots.sources.gossip.block_list[ i ], tile->snapct.sources.gossip.block_list[ i ].uc ) ) ) {
1526 0 : FD_LOG_ERR(( "[snapshots.sources.gossip.block_list[%lu]] invalid (%s)", i, config->firedancer.snapshots.sources.gossip.block_list[ i ] ));
1527 0 : }
1528 0 : }
1529 :
1530 0 : ulong resolved_peers_cnt = 0UL;
1531 0 : for( ulong i=0UL; i<tile->snapct.sources.servers_cnt; i++ ) {
1532 0 : fd_ip4_port_t resolved_addrs[ FD_TOPO_MAX_RESOLVED_ADDRS ];
1533 0 : struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM };
1534 0 : int num_resolved = resolve_peer( config->firedancer.snapshots.sources.servers[ i ],
1535 0 : &hints,
1536 0 : "snapshots.sources.servers",
1537 0 : tile->snapct.sources.servers[ resolved_peers_cnt ].hostname,
1538 0 : resolved_addrs,
1539 0 : FD_TOPO_MAX_RESOLVED_ADDRS,
1540 0 : &tile->snapct.sources.servers[ resolved_peers_cnt ].is_https );
1541 0 : if( FD_UNLIKELY( 0==num_resolved ) ) {
1542 0 : FD_LOG_ERR(( "[snapshots.sources.servers[%lu]] invalid (%s)", i, config->firedancer.snapshots.sources.servers[ i ] ));
1543 0 : } else {
1544 0 : for( ulong i=0UL; i<(ulong)num_resolved; i++ ) tile->snapct.sources.servers[ resolved_peers_cnt+i ].addr = resolved_addrs[ i ];
1545 0 : for( ulong i=1UL; i<(ulong)num_resolved; i++ ) {
1546 0 : tile->snapct.sources.servers[ resolved_peers_cnt+i ].is_https = tile->snapct.sources.servers[ resolved_peers_cnt ].is_https;
1547 0 : fd_memcpy( tile->snapct.sources.servers[ resolved_peers_cnt+i ].hostname,
1548 0 : tile->snapct.sources.servers[ resolved_peers_cnt ].hostname,
1549 0 : sizeof(tile->snapct.sources.servers[ resolved_peers_cnt ].hostname) );
1550 0 : }
1551 0 : resolved_peers_cnt += (ulong)num_resolved;
1552 0 : }
1553 0 : }
1554 0 : tile->snapct.sources.servers_cnt = resolved_peers_cnt;
1555 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapld" ) ) ) {
1556 :
1557 0 : fd_memcpy( tile->snapld.snapshots_path, config->paths.snapshots, PATH_MAX );
1558 0 : tile->snapld.incremental_snapshots = config->firedancer.snapshots.incremental_snapshots;
1559 0 : tile->snapld.min_download_speed_mibs = config->firedancer.snapshots.min_download_speed_mibs;
1560 :
1561 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapdc" ) ) ) {
1562 :
1563 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapin" ) ) ) {
1564 :
1565 0 : tile->snapin.max_live_slots = config->firedancer.runtime.max_live_slots;
1566 0 : tile->snapin.accdb_max_depth = config->firedancer.runtime.max_live_slots + config->firedancer.accounts.write_delay_slots;
1567 0 : tile->snapin.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX );
1568 0 : tile->snapin.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX );
1569 :
1570 0 : tile->snapin.use_vinyl = !config->firedancer.accounts.in_memory_only;
1571 0 : tile->snapin.lthash_disabled = !!config->development.snapshots.disable_lthash_verification;
1572 :
1573 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapwm" ) ) ) {
1574 :
1575 0 : strcpy( tile->snapwm.vinyl_path, config->paths.accounts );
1576 0 : tile->snapwm.max_accounts = config->firedancer.accounts.max_accounts;
1577 0 : tile->snapwm.vinyl_meta_map_obj_id = fd_pod_query_ulong( config->topo.props, "accdb.meta_map", ULONG_MAX );
1578 0 : tile->snapwm.vinyl_meta_pool_obj_id = fd_pod_query_ulong( config->topo.props, "accdb.meta_pool", ULONG_MAX );
1579 :
1580 0 : ulong wm_wr_link_id = fd_topo_find_link( &config->topo, "snapwm_wh", 0UL );
1581 0 : FD_TEST( wm_wr_link_id!=ULONG_MAX );
1582 0 : fd_topo_link_t * wm_wr_link = &config->topo.links[ wm_wr_link_id ];
1583 0 : tile->snapwm.snapwr_depth = wm_wr_link->depth;
1584 :
1585 0 : tile->snapwm.lthash_disabled = !!config->development.snapshots.disable_lthash_verification;
1586 :
1587 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapwh" ) ) ) {
1588 :
1589 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapwr" ) ) ) {
1590 :
1591 0 : strcpy( tile->snapwr.vinyl_path, config->paths.accounts );
1592 0 : ulong wm_wr_link_id = fd_topo_find_link( &config->topo, "snapwm_wh", 0UL );
1593 0 : FD_TEST( wm_wr_link_id!=ULONG_MAX );
1594 0 : fd_topo_link_t * wm_wr_link = &config->topo.links[ wm_wr_link_id ];
1595 0 : tile->snapwr.dcache_obj_id = wm_wr_link->dcache_obj_id;
1596 :
1597 0 : tile->snapwr.lthash_disabled = !!config->development.snapshots.disable_lthash_verification;
1598 :
1599 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapla" ) ) ) {
1600 :
1601 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapls" ) ) ) {
1602 :
1603 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snaplh" ) ) ) {
1604 :
1605 0 : strcpy( tile->snaplh.vinyl_path, config->paths.accounts );
1606 0 : ulong wm_wr_link_id = fd_topo_find_link( &config->topo, "snapwm_wh", 0UL );
1607 0 : FD_TEST( wm_wr_link_id!=ULONG_MAX );
1608 0 : fd_topo_link_t * wm_wr_link = &config->topo.links[ wm_wr_link_id ];
1609 0 : tile->snaplh.dcache_obj_id = wm_wr_link->dcache_obj_id;
1610 0 : tile->snaplh.io_uring_enabled = !strcmp(config->firedancer.accounts.io_provider, "io_uring");
1611 :
1612 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snaplv" ) ) ) {
1613 :
1614 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "repair" ) ) ) {
1615 0 : tile->repair.max_pending_shred_sets = config->tiles.shred.max_pending_shred_sets;
1616 0 : tile->repair.repair_intake_listen_port = config->tiles.repair.repair_intake_listen_port;
1617 0 : tile->repair.repair_serve_listen_port = config->tiles.repair.repair_serve_listen_port;
1618 0 : tile->repair.slot_max = config->tiles.repair.slot_max;
1619 0 : tile->repair.repair_sign_cnt = config->firedancer.layout.sign_tile_count - 1; /* -1 because this excludes the keyguard client */
1620 0 : tile->repair.end_slot = 0;
1621 :
1622 0 : for( ulong i=0; i<tile->in_cnt; i++ ) {
1623 0 : if( !strcmp( config->topo.links[ tile->in_link_id[ i ] ].name, "sign_repair" ) ) {
1624 0 : tile->repair.repair_sign_depth = config->topo.links[ tile->in_link_id[ i ] ].depth;
1625 0 : break;
1626 0 : }
1627 0 : }
1628 0 : fd_cstr_ncpy( tile->repair.identity_key_path, config->paths.identity_key, sizeof(tile->repair.identity_key_path) );
1629 :
1630 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "replay" ) )) {
1631 :
1632 : /* Please maintain same field order as fd_topo.h */
1633 :
1634 0 : tile->replay.fec_max = config->firedancer.runtime.max_live_slots * 1024UL; /* FIXME temporary hack to run on 512 gb boxes */
1635 :
1636 0 : FD_TEST( (tile->replay.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX ))!=ULONG_MAX );
1637 :
1638 0 : fd_cstr_ncpy( tile->replay.identity_key_path, config->paths.identity_key, sizeof(tile->replay.identity_key_path) );
1639 0 : tile->replay.ip_addr = config->net.ip_addr;
1640 0 : fd_cstr_ncpy( tile->replay.vote_account_path, config->paths.vote_account, sizeof(tile->replay.vote_account_path) );
1641 :
1642 0 : tile->replay.expected_shred_version = config->consensus.expected_shred_version;
1643 0 : tile->replay.wait_for_vote_to_start_leader = config->consensus.wait_for_vote_to_start_leader;
1644 :
1645 0 : tile->replay.sched_depth = config->firedancer.development.replay.scheduler_depth;
1646 0 : if( FD_LIKELY( !strcmp( config->firedancer.consensus.wait_for_supermajority_with_bank_hash, "" ) ) ) {
1647 0 : memset( tile->replay.wait_for_supermajority_with_bank_hash.uc, 0, sizeof(fd_pubkey_t) );
1648 0 : } else if( FD_UNLIKELY( !fd_base58_decode_32( config->firedancer.consensus.wait_for_supermajority_with_bank_hash, tile->replay.wait_for_supermajority_with_bank_hash.uc ) ) ) {
1649 0 : FD_LOG_ERR(( "[consensus.wait_for_supermajority_with_bank_hash] failed to parse" ));
1650 0 : }
1651 :
1652 0 : tile->replay.max_live_slots = config->firedancer.runtime.max_live_slots;
1653 0 : tile->replay.write_delay_slots = config->firedancer.accounts.write_delay_slots;
1654 :
1655 0 : fd_cstr_ncpy( tile->replay.genesis_path, config->paths.genesis, sizeof(tile->replay.genesis_path) );
1656 :
1657 0 : tile->replay.larger_max_cost_per_block = config->development.bench.larger_max_cost_per_block;
1658 :
1659 : /* not specified by [tiles.replay] */
1660 :
1661 0 : tile->replay.capture_start_slot = config->capture.capture_start_slot;
1662 0 : fd_cstr_ncpy( tile->replay.solcap_capture, config->capture.solcap_capture, sizeof(tile->replay.solcap_capture) );
1663 0 : fd_cstr_ncpy( tile->replay.dump_proto_dir, config->capture.dump_proto_dir, sizeof(tile->replay.dump_proto_dir) );
1664 0 : tile->replay.dump_block_to_pb = config->capture.dump_block_to_pb;
1665 :
1666 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1667 0 : #define PARSE_PUBKEY( _tile, f ) \
1668 0 : if( FD_UNLIKELY( !fd_base58_decode_32( config->tiles.bundle.f, tile->_tile.bundle.f ) ) ) \
1669 0 : FD_LOG_ERR(( "[tiles.bundle.enabled] set to true, but failed to parse [tiles.bundle."#f"] %s", config->tiles.bundle.f ));
1670 0 : tile->replay.bundle.enabled = 1;
1671 0 : PARSE_PUBKEY( replay, tip_distribution_program_addr );
1672 0 : PARSE_PUBKEY( replay, tip_payment_program_addr );
1673 0 : fd_cstr_ncpy( tile->replay.bundle.vote_account_path, config->paths.vote_account, sizeof(tile->replay.bundle.vote_account_path) );
1674 0 : } else {
1675 0 : fd_memset( &tile->replay.bundle, '\0', sizeof(tile->replay.bundle) );
1676 0 : }
1677 :
1678 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "execrp" ) ) ) {
1679 :
1680 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 );
1681 0 : tile->execrp.acc_pool_obj_id = fd_pod_query_ulong( config->topo.props, "acc_pool", ULONG_MAX ); FD_TEST( tile->execrp.acc_pool_obj_id !=ULONG_MAX );
1682 :
1683 0 : tile->execrp.max_live_slots = config->firedancer.runtime.max_live_slots;
1684 0 : tile->execrp.accdb_max_depth = config->firedancer.runtime.max_live_slots + config->firedancer.accounts.write_delay_slots;
1685 :
1686 0 : tile->execrp.capture_start_slot = config->capture.capture_start_slot;
1687 0 : fd_cstr_ncpy( tile->execrp.solcap_capture, config->capture.solcap_capture, sizeof(tile->execrp.solcap_capture) );
1688 0 : fd_cstr_ncpy( tile->execrp.dump_proto_dir, config->capture.dump_proto_dir, sizeof(tile->execrp.dump_proto_dir) );
1689 0 : fd_cstr_ncpy( tile->execrp.dump_syscall_name_filter, config->capture.dump_syscall_name_filter, sizeof(tile->execrp.dump_syscall_name_filter) );
1690 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) );
1691 0 : tile->execrp.dump_instr_to_pb = config->capture.dump_instr_to_pb;
1692 0 : tile->execrp.dump_txn_to_pb = config->capture.dump_txn_to_pb;
1693 0 : tile->execrp.dump_txn_as_fixture = config->capture.dump_txn_as_fixture;
1694 0 : tile->execrp.dump_syscall_to_pb = config->capture.dump_syscall_to_pb;
1695 :
1696 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "tower" ) ) ) {
1697 0 : tile->tower.authorized_voter_paths_cnt = config->firedancer.paths.authorized_voter_paths_cnt;
1698 0 : for( ulong i=0UL; i<tile->tower.authorized_voter_paths_cnt; i++ ) {
1699 0 : fd_cstr_ncpy( tile->tower.authorized_voter_paths[ i ], config->firedancer.paths.authorized_voter_paths[ i ], sizeof(tile->tower.authorized_voter_paths[ i ]) );
1700 0 : }
1701 :
1702 0 : tile->tower.hard_fork_fatal = config->firedancer.development.hard_fork_fatal;
1703 0 : tile->tower.max_live_slots = config->firedancer.runtime.max_live_slots;
1704 0 : tile->tower.accdb_max_depth = config->firedancer.runtime.max_live_slots + config->firedancer.accounts.write_delay_slots;
1705 0 : fd_cstr_ncpy( tile->tower.identity_key, config->paths.identity_key, sizeof(tile->tower.identity_key) );
1706 0 : fd_cstr_ncpy( tile->tower.vote_account, config->paths.vote_account, sizeof(tile->tower.vote_account) );
1707 0 : fd_cstr_ncpy( tile->tower.base_path, config->paths.base, sizeof(tile->tower.base_path) );
1708 :
1709 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "txsend" ) ) ) {
1710 :
1711 0 : tile->txsend.txsend_src_port = config->tiles.txsend.txsend_src_port;
1712 0 : tile->txsend.ip_addr = config->net.ip_addr;
1713 0 : fd_cstr_ncpy( tile->txsend.identity_key_path, config->paths.identity_key, sizeof(tile->txsend.identity_key_path) );
1714 :
1715 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "quic" ) ) ) {
1716 :
1717 0 : tile->quic.reasm_cnt = config->tiles.quic.txn_reassembly_count;
1718 0 : tile->quic.out_depth = config->tiles.verify.receive_buffer_size;
1719 0 : tile->quic.max_concurrent_connections = config->tiles.quic.max_concurrent_connections;
1720 0 : tile->quic.max_concurrent_handshakes = config->tiles.quic.max_concurrent_handshakes;
1721 0 : tile->quic.quic_transaction_listen_port = config->tiles.quic.quic_transaction_listen_port;
1722 0 : tile->quic.idle_timeout_millis = config->tiles.quic.idle_timeout_millis;
1723 0 : tile->quic.ack_delay_millis = config->tiles.quic.ack_delay_millis;
1724 0 : tile->quic.retry = config->tiles.quic.retry;
1725 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) ) );
1726 :
1727 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "verify" ) ) ) {
1728 :
1729 0 : tile->verify.tcache_depth = config->tiles.verify.signature_cache_size;
1730 :
1731 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "dedup" ) ) ) {
1732 :
1733 0 : tile->dedup.tcache_depth = config->tiles.dedup.signature_cache_size;
1734 :
1735 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "resolv" ) ) ) {
1736 :
1737 0 : tile->resolv.accdb_max_depth = config->firedancer.runtime.max_live_slots + config->firedancer.accounts.write_delay_slots;
1738 :
1739 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "pack" ) ) ) {
1740 :
1741 0 : tile->pack.max_pending_transactions = config->tiles.pack.max_pending_transactions;
1742 0 : tile->pack.execle_tile_count = config->firedancer.layout.execle_tile_count;
1743 0 : tile->pack.larger_max_cost_per_block = config->development.bench.larger_max_cost_per_block;
1744 0 : tile->pack.larger_shred_limits_per_block = config->development.bench.larger_shred_limits_per_block;
1745 0 : tile->pack.use_consumed_cus = config->tiles.pack.use_consumed_cus;
1746 0 : tile->pack.schedule_strategy = config->tiles.pack.schedule_strategy_enum;
1747 :
1748 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1749 :
1750 0 : tile->pack.bundle.enabled = 1;
1751 0 : PARSE_PUBKEY( pack, tip_distribution_program_addr );
1752 0 : PARSE_PUBKEY( pack, tip_payment_program_addr );
1753 0 : PARSE_PUBKEY( pack, tip_distribution_authority );
1754 0 : tile->pack.bundle.commission_bps = config->tiles.bundle.commission_bps;
1755 0 : fd_cstr_ncpy( tile->pack.bundle.identity_key_path, config->paths.identity_key, sizeof(tile->pack.bundle.identity_key_path) );
1756 0 : fd_cstr_ncpy( tile->pack.bundle.vote_account_path, config->paths.vote_account, sizeof(tile->pack.bundle.vote_account_path) );
1757 0 : } else {
1758 0 : fd_memset( &tile->pack.bundle, '\0', sizeof(tile->pack.bundle) );
1759 0 : }
1760 :
1761 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "execle" ) ) ) {
1762 0 : tile->execle.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX );
1763 0 : tile->execle.acc_pool_obj_id = fd_pod_query_ulong( config->topo.props, "acc_pool", ULONG_MAX );
1764 :
1765 0 : tile->execle.max_live_slots = config->firedancer.runtime.max_live_slots;
1766 0 : tile->execle.accdb_max_depth = config->firedancer.runtime.max_live_slots + config->firedancer.accounts.write_delay_slots;
1767 :
1768 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "poh" ) ) ) {
1769 0 : fd_cstr_ncpy( tile->poh.identity_key_path, config->paths.identity_key, sizeof(tile->poh.identity_key_path) );
1770 :
1771 0 : tile->poh.execle_cnt = config->firedancer.layout.execle_tile_count;
1772 :
1773 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "shred" ) ) ) {
1774 :
1775 0 : fd_cstr_ncpy( tile->shred.identity_key_path, config->paths.identity_key, sizeof(tile->shred.identity_key_path) );
1776 :
1777 0 : tile->shred.depth = config->topo.links[ tile->out_link_id[ 0 ] ].depth;
1778 0 : tile->shred.fec_resolver_depth = config->tiles.shred.max_pending_shred_sets;
1779 0 : tile->shred.expected_shred_version = config->consensus.expected_shred_version;
1780 0 : tile->shred.shred_listen_port = config->tiles.shred.shred_listen_port;
1781 0 : tile->shred.larger_shred_limits_per_block = config->development.bench.larger_shred_limits_per_block;
1782 0 : for( ulong i=0UL; i<config->tiles.shred.additional_shred_destinations_retransmit_cnt; i++ ) {
1783 0 : parse_ip_port( "tiles.shred.additional_shred_destinations_retransmit",
1784 0 : config->tiles.shred.additional_shred_destinations_retransmit[ i ],
1785 0 : &tile->shred.adtl_dests_retransmit[ i ] );
1786 0 : }
1787 0 : tile->shred.adtl_dests_retransmit_cnt = config->tiles.shred.additional_shred_destinations_retransmit_cnt;
1788 0 : for( ulong i=0UL; i<config->tiles.shred.additional_shred_destinations_leader_cnt; i++ ) {
1789 0 : parse_ip_port( "tiles.shred.additional_shred_destinations_leader",
1790 0 : config->tiles.shred.additional_shred_destinations_leader[ i ],
1791 0 : &tile->shred.adtl_dests_leader[ i ] );
1792 0 : }
1793 0 : tile->shred.adtl_dests_leader_cnt = config->tiles.shred.additional_shred_destinations_leader_cnt;
1794 :
1795 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "sign" ) ) ) {
1796 :
1797 0 : fd_cstr_ncpy( tile->sign.identity_key_path, config->paths.identity_key, sizeof(tile->sign.identity_key_path) );
1798 :
1799 0 : tile->sign.authorized_voter_paths_cnt = config->firedancer.paths.authorized_voter_paths_cnt;
1800 0 : for( ulong i=0UL; i<tile->sign.authorized_voter_paths_cnt; i++ ) {
1801 0 : fd_cstr_ncpy( tile->sign.authorized_voter_paths[ i ], config->firedancer.paths.authorized_voter_paths[ i ], sizeof(tile->sign.authorized_voter_paths[ i ]) );
1802 0 : }
1803 :
1804 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "plugin" ) ) ) {
1805 :
1806 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "diag" ) ) ) {
1807 :
1808 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "gui" ) ) ) {
1809 :
1810 0 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.gui.gui_listen_address, &tile->gui.listen_addr ) ) )
1811 0 : FD_LOG_ERR(( "failed to parse gui listen address `%s`", config->tiles.gui.gui_listen_address ));
1812 0 : tile->gui.listen_port = config->tiles.gui.gui_listen_port;
1813 0 : tile->gui.is_voting = strcmp( config->paths.vote_account, "" );
1814 0 : fd_cstr_ncpy( tile->gui.cluster, config->cluster, sizeof(tile->gui.cluster) );
1815 0 : fd_cstr_ncpy( tile->gui.identity_key_path, config->paths.identity_key, sizeof(tile->gui.identity_key_path) );
1816 0 : fd_cstr_ncpy( tile->gui.vote_key_path, config->paths.vote_account, sizeof(tile->gui.vote_key_path) );
1817 0 : tile->gui.max_http_connections = config->tiles.gui.max_http_connections;
1818 0 : tile->gui.max_websocket_connections = config->tiles.gui.max_websocket_connections;
1819 0 : tile->gui.max_http_request_length = config->tiles.gui.max_http_request_length;
1820 0 : tile->gui.send_buffer_size_mb = config->tiles.gui.send_buffer_size_mb;
1821 0 : tile->gui.schedule_strategy = config->tiles.pack.schedule_strategy_enum;
1822 0 : tile->gui.websocket_compression = 1;
1823 0 : tile->gui.frontend_release_channel = config->development.gui.frontend_release_channel_enum;
1824 :
1825 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "rpc" ) ) ) {
1826 :
1827 0 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.rpc.rpc_listen_address, &tile->rpc.listen_addr ) ) )
1828 0 : FD_LOG_ERR(( "failed to parse rpc listen address `%s`", config->tiles.rpc.rpc_listen_address ));
1829 0 : tile->rpc.listen_port = config->tiles.rpc.rpc_listen_port;
1830 0 : tile->rpc.delay_startup = config->tiles.rpc.delay_startup;
1831 0 : tile->rpc.max_http_connections = config->tiles.rpc.max_http_connections;
1832 0 : tile->rpc.max_http_request_length = config->tiles.rpc.max_http_request_length;
1833 0 : tile->rpc.send_buffer_size_mb = config->tiles.rpc.send_buffer_size_mb;
1834 :
1835 0 : tile->rpc.max_live_slots = config->firedancer.runtime.max_live_slots;
1836 0 : tile->rpc.accdb_max_depth = config->firedancer.runtime.max_live_slots + config->firedancer.accounts.write_delay_slots;
1837 :
1838 0 : fd_cstr_ncpy( tile->rpc.identity_key_path, config->paths.identity_key, sizeof(tile->rpc.identity_key_path) );
1839 :
1840 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "arch_f" ) ||
1841 0 : !strcmp( tile->name, "arch_w" ) ) ) {
1842 :
1843 0 : fd_cstr_ncpy( tile->archiver.rocksdb_path, config->tiles.archiver.rocksdb_path, sizeof(tile->archiver.rocksdb_path) );
1844 :
1845 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "backt" ) ) ) {
1846 :
1847 0 : tile->backtest.end_slot = config->tiles.archiver.end_slot;
1848 0 : tile->backtest.ingest_dead_slots = config->tiles.archiver.ingest_dead_slots;
1849 0 : tile->backtest.root_distance = config->tiles.archiver.root_distance;
1850 :
1851 : /* Validate arguments based on the ingest mode */
1852 0 : if( !strcmp( config->tiles.archiver.ingest_mode, "rocksdb" ) ) {
1853 0 : fd_cstr_ncpy( tile->backtest.rocksdb_path, config->tiles.archiver.rocksdb_path, PATH_MAX );
1854 0 : if( FD_UNLIKELY( 0==strlen( tile->backtest.rocksdb_path ) ) ) {
1855 0 : FD_LOG_ERR(( "`archiver.rocksdb_path` not specified in toml" ));
1856 0 : }
1857 0 : } else if( !strcmp( config->tiles.archiver.ingest_mode, "shredcap" ) ) {
1858 0 : fd_cstr_ncpy( tile->backtest.shredcap_path, config->tiles.archiver.shredcap_path, PATH_MAX );
1859 0 : if( FD_UNLIKELY( 0==strlen( tile->backtest.shredcap_path ) ) ) {
1860 0 : FD_LOG_ERR(( "`archiver.shredcap_path` not specified in toml" ));
1861 0 : }
1862 0 : } else {
1863 0 : FD_LOG_ERR(( "Invalid ingest mode: %s", config->tiles.archiver.ingest_mode ));
1864 0 : }
1865 :
1866 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "scap" ) ) ) {
1867 :
1868 0 : tile->shredcap.repair_intake_listen_port = config->tiles.repair.repair_intake_listen_port;
1869 0 : fd_cstr_ncpy( tile->shredcap.folder_path, config->tiles.shredcap.folder_path, sizeof(tile->shredcap.folder_path) );
1870 0 : tile->shredcap.write_buffer_size = config->tiles.shredcap.write_buffer_size;
1871 0 : tile->shredcap.enable_publish_stake_weights = 0; /* this is not part of the config */
1872 0 : fd_cstr_ncpy( tile->shredcap.manifest_path, "", PATH_MAX ); /* this is not part of the config */
1873 :
1874 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "bundle" ) ) ) {
1875 0 : fd_cstr_ncpy( tile->bundle.url, config->tiles.bundle.url, sizeof(tile->bundle.url) );
1876 0 : tile->bundle.url_len = strnlen( tile->bundle.url, 255 );
1877 0 : fd_cstr_ncpy( tile->bundle.sni, config->tiles.bundle.tls_domain_name, 256 );
1878 0 : tile->bundle.sni_len = strnlen( tile->bundle.sni, 255 );
1879 0 : fd_cstr_ncpy( tile->bundle.identity_key_path, config->paths.identity_key, sizeof(tile->bundle.identity_key_path) );
1880 0 : fd_cstr_ncpy( tile->bundle.key_log_path, config->development.bundle.ssl_key_log_file, sizeof(tile->bundle.key_log_path) );
1881 0 : tile->bundle.buf_sz = config->development.bundle.buffer_size_kib<<10;
1882 0 : tile->bundle.out_depth = config->tiles.verify.receive_buffer_size;
1883 0 : tile->bundle.ssl_heap_sz = config->development.bundle.ssl_heap_size_mib<<20;
1884 0 : tile->bundle.keepalive_interval_nanos = config->tiles.bundle.keepalive_interval_millis * (ulong)1e6;
1885 0 : tile->bundle.tls_cert_verify = !!config->tiles.bundle.tls_cert_verify;
1886 :
1887 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "accdb" ) ) ) {
1888 :
1889 0 : tile->accdb.meta_map_obj_id = fd_pod_query_ulong( config->topo.props, "accdb.meta_map", ULONG_MAX );
1890 0 : tile->accdb.meta_pool_obj_id = fd_pod_query_ulong( config->topo.props, "accdb.meta_pool", ULONG_MAX );
1891 0 : tile->accdb.line_max = (config->firedancer.accounts.cache_size_gib << 30) / config->firedancer.accounts.mean_account_footprint;
1892 0 : tile->accdb.data_obj_id = fd_pod_query_ulong( config->topo.props, "accdb.data", ULONG_MAX );
1893 0 : fd_cstr_ncpy( tile->accdb.bstream_path, config->paths.accounts, sizeof(tile->accdb.bstream_path) );
1894 0 : tile->accdb.pair_cnt_limit = fd_pod_query_ulong( config->topo.props, "accdb.meta_limit", ULONG_MAX );
1895 0 : tile->accdb.io_type = !strcmp(config->firedancer.accounts.io_provider, "io_uring") ?
1896 0 : FD_VINYL_IO_TYPE_UR : FD_VINYL_IO_TYPE_BD;
1897 0 : tile->accdb.uring_depth = config->firedancer.accounts.io_uring.queue_depth;
1898 :
1899 : /* Minimum bound for cache entry count */
1900 0 : ulong required_cache_entries = 0UL;
1901 0 : for( ulong i=0UL; i<(tile->uses_obj_cnt); i++ ) {
1902 0 : ulong rq_obj_id = tile->uses_obj_id[ i ];
1903 0 : fd_topo_obj_t const * rq_obj = &config->topo.objs[ rq_obj_id ];
1904 0 : if( strcmp( rq_obj->name, "vinyl_rq" ) ) continue;
1905 :
1906 0 : ulong quota_max;
1907 0 : FD_TEST( (quota_max = fd_pod_queryf_ulong( config->topo.props, ULONG_MAX, "obj.%lu.quota_max", rq_obj_id ))!=ULONG_MAX );
1908 0 : required_cache_entries += quota_max;
1909 0 : }
1910 0 : if( FD_UNLIKELY( required_cache_entries > tile->accdb.line_max ) ) {
1911 0 : tile->accdb.line_max = required_cache_entries;
1912 0 : }
1913 :
1914 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "solcap" ) ) ) {
1915 :
1916 0 : tile->solcap.capture_start_slot = config->capture.capture_start_slot;
1917 0 : fd_cstr_ncpy( tile->solcap.solcap_capture, config->capture.solcap_capture, sizeof(tile->solcap.solcap_capture) );
1918 0 : tile->solcap.recent_only = config->capture.recent_only;
1919 0 : tile->solcap.recent_slots_per_file = config->capture.recent_slots_per_file;
1920 :
1921 0 : } else {
1922 0 : FD_LOG_ERR(( "unknown tile name `%s`", tile->name ));
1923 0 : }
1924 0 : }
|