Line data Source code
1 : #include "topology.h"
2 :
3 : #include "../../ballet/lthash/fd_lthash.h"
4 : #include "../../choreo/fd_choreo_base.h"
5 : #include "../../discof/reasm/fd_reasm.h"
6 : #include "../../discof/poh/fd_poh.h"
7 : #include "../../discof/replay/fd_exec.h"
8 : #include "../../discof/gossip/fd_gossip_tile.h"
9 : #include "../../discof/tower/fd_tower_tile.h"
10 : #include "../../discof/resolv/fd_resolv_tile.h"
11 : #include "../../discof/repair/fd_repair.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_peers.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_cpu_topo.h"
21 : #include "../../util/pod/fd_pod_format.h"
22 : #include "../../util/tile/fd_tile_private.h"
23 : #include "../../discof/restore/utils/fd_ssctrl.h"
24 : #include "../../discof/restore/utils/fd_ssmsg.h"
25 : #include "../../flamenco/progcache/fd_progcache_admin.h"
26 : #include "../../vinyl/meta/fd_vinyl_meta.h"
27 : #include "../../vinyl/io/fd_vinyl_io.h" /* FD_VINYL_IO_TYPE_* */
28 :
29 : #include <sys/random.h>
30 : #include <sys/types.h>
31 : #include <sys/socket.h>
32 : #include <stdlib.h>
33 : #include <netdb.h>
34 :
35 : extern fd_topo_obj_callbacks_t * CALLBACKS[];
36 :
37 : static void
38 0 : parse_ip_port( const char * name, const char * ip_port, fd_topo_ip_port_t *parsed_ip_port) {
39 0 : char buf[ sizeof( "255.255.255.255:65536" ) ];
40 0 : memcpy( buf, ip_port, sizeof( buf ) );
41 0 : char *ip_end = strchr( buf, ':' );
42 0 : if( FD_UNLIKELY( !ip_end ) )
43 0 : FD_LOG_ERR(( "[%s] must in the form ip:port", name ));
44 0 : *ip_end = '\0';
45 :
46 0 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( buf, &( parsed_ip_port->ip ) ) ) ) {
47 0 : FD_LOG_ERR(( "could not parse IP %s in [%s]", buf, name ));
48 0 : }
49 :
50 0 : parsed_ip_port->port = fd_cstr_to_ushort( ip_end+1 );
51 0 : if( FD_UNLIKELY( !parsed_ip_port->port ) )
52 0 : FD_LOG_ERR(( "could not parse port %s in [%s]", ip_end+1, name ));
53 0 : }
54 :
55 : fd_topo_obj_t *
56 : setup_topo_banks( fd_topo_t * topo,
57 : char const * wksp_name,
58 : ulong max_live_slots,
59 : ulong max_fork_width,
60 0 : int larger_max_cost_per_block ) {
61 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "banks", wksp_name );
62 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_live_slots, "obj.%lu.max_live_slots", obj->id ) );
63 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_fork_width, "obj.%lu.max_fork_width", obj->id ) );
64 0 : FD_TEST( fd_pod_insertf_int( topo->props, larger_max_cost_per_block, "obj.%lu.larger_max_cost_per_block", obj->id ) );
65 0 : ulong seed;
66 0 : FD_TEST( fd_rng_secure( &seed, sizeof( ulong ) ) );
67 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, seed, "obj.%lu.seed", obj->id ) );
68 0 : return obj;
69 0 : }
70 :
71 : static fd_topo_obj_t *
72 0 : setup_topo_fec_sets( fd_topo_t * topo, char const * wksp_name, ulong sz ) {
73 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "fec_sets", wksp_name );
74 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, sz, "obj.%lu.sz", obj->id ) );
75 0 : return obj;
76 0 : }
77 :
78 : fd_topo_obj_t *
79 : setup_topo_funk( fd_topo_t * topo,
80 : char const * wksp_name,
81 : ulong max_account_records,
82 : ulong max_database_transactions,
83 0 : ulong heap_size_gib ) {
84 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "funk", wksp_name );
85 0 : FD_TEST( fd_pod_insert_ulong( topo->props, "funk", obj->id ) );
86 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_account_records, "obj.%lu.rec_max", obj->id ) );
87 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_database_transactions, "obj.%lu.txn_max", obj->id ) );
88 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, heap_size_gib*(1UL<<30), "obj.%lu.heap_max", obj->id ) );
89 0 : ulong funk_footprint = fd_funk_footprint( max_database_transactions, max_account_records );
90 0 : if( FD_UNLIKELY( !funk_footprint ) ) FD_LOG_ERR(( "Invalid [funk] parameters" ));
91 :
92 : /* Increase workspace partition count */
93 0 : ulong wksp_idx = fd_topo_find_wksp( topo, wksp_name );
94 0 : FD_TEST( wksp_idx!=ULONG_MAX );
95 0 : fd_topo_wksp_t * wksp = &topo->workspaces[ wksp_idx ];
96 0 : ulong size = funk_footprint+(heap_size_gib*(1UL<<30));
97 0 : ulong part_max = fd_wksp_part_max_est( size, 1U<<14U );
98 0 : if( FD_UNLIKELY( !part_max ) ) FD_LOG_ERR(( "fd_wksp_part_max_est(%lu,16KiB) failed", size ));
99 0 : wksp->part_max += part_max;
100 :
101 0 : return obj;
102 0 : }
103 :
104 : fd_topo_obj_t *
105 : setup_topo_progcache( fd_topo_t * topo,
106 : char const * wksp_name,
107 : ulong max_cache_entries,
108 : ulong max_database_transactions,
109 0 : ulong heap_size ) {
110 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "funk", wksp_name );
111 0 : FD_TEST( fd_pod_insert_ulong( topo->props, "progcache", obj->id ) );
112 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_cache_entries, "obj.%lu.rec_max", obj->id ) );
113 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_database_transactions, "obj.%lu.txn_max", obj->id ) );
114 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, heap_size, "obj.%lu.heap_max", obj->id ) );
115 0 : ulong funk_footprint = fd_funk_footprint( max_database_transactions, max_cache_entries );
116 0 : if( FD_UNLIKELY( !funk_footprint ) ) FD_LOG_ERR(( "Invalid [runtime.program_cache] parameters" ));
117 0 : if( FD_UNLIKELY( heap_size<(2*funk_footprint) ) ) {
118 0 : FD_LOG_ERR(( "Invalid [runtime.program_cache] parameters: heap_size_mib should be at least %lu",
119 0 : ( 2*funk_footprint )>>20 ));
120 0 : }
121 :
122 : /* Increase workspace partition count */
123 0 : ulong wksp_idx = fd_topo_find_wksp( topo, wksp_name );
124 0 : FD_TEST( wksp_idx!=ULONG_MAX );
125 0 : fd_topo_wksp_t * wksp = &topo->workspaces[ wksp_idx ];
126 0 : ulong part_max = fd_wksp_part_max_est( heap_size, 1U<<14U );
127 0 : if( FD_UNLIKELY( !part_max ) ) FD_LOG_ERR(( "fd_wksp_part_max_est(%lu,16KiB) failed", funk_footprint ));
128 0 : wksp->part_max += part_max;
129 :
130 0 : return obj;
131 0 : }
132 :
133 : fd_topo_obj_t *
134 : setup_topo_store( fd_topo_t * topo,
135 : char const * wksp_name,
136 : ulong fec_max,
137 0 : uint part_cnt ) {
138 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "store", wksp_name );
139 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, fec_max, "obj.%lu.fec_max", obj->id ) );
140 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, part_cnt, "obj.%lu.part_cnt", obj->id ) );
141 0 : return obj;
142 0 : }
143 :
144 : fd_topo_obj_t *
145 : setup_topo_txncache( fd_topo_t * topo,
146 : char const * wksp_name,
147 : ulong max_live_slots,
148 0 : ulong max_txn_per_slot ) {
149 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "txncache", wksp_name );
150 :
151 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_live_slots, "obj.%lu.max_live_slots", obj->id ) );
152 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_txn_per_slot, "obj.%lu.max_txn_per_slot", obj->id ) );
153 :
154 0 : return obj;
155 0 : }
156 :
157 : void
158 : setup_topo_vinyl_meta( fd_topo_t * topo,
159 0 : fd_configf_t * config ) {
160 0 : fd_topob_wksp( topo, "vinyl_meta" );
161 :
162 0 : fd_topo_obj_t * map_obj = fd_topob_obj( topo, "vinyl_meta", "vinyl_meta" );
163 0 : ulong const meta_max = fd_ulong_pow2_up( config->vinyl.max_account_records );
164 0 : ulong const lock_cnt = fd_vinyl_meta_lock_cnt_est ( meta_max );
165 0 : ulong const probe_max = fd_vinyl_meta_probe_max_est( meta_max );
166 0 : fd_pod_insertf_ulong( topo->props, meta_max, "obj.%lu.ele_max", map_obj->id );
167 0 : fd_pod_insertf_ulong( topo->props, lock_cnt, "obj.%lu.lock_cnt", map_obj->id );
168 0 : fd_pod_insertf_ulong( topo->props, probe_max, "obj.%lu.probe_max", map_obj->id );
169 0 : fd_pod_insertf_ulong( topo->props, (ulong)fd_tickcount(), "obj.%lu.seed", map_obj->id );
170 :
171 0 : fd_topo_obj_t * meta_pool_obj = fd_topob_obj( topo, "vinyl_meta_e", "vinyl_meta" );
172 0 : fd_pod_insertf_ulong( topo->props, meta_max, "obj.%lu.cnt", meta_pool_obj->id );
173 :
174 0 : fd_pod_insert_ulong( topo->props, "vinyl.meta_map", map_obj->id );
175 0 : fd_pod_insert_ulong( topo->props, "vinyl.meta_pool", meta_pool_obj->id );
176 0 : }
177 :
178 : fd_topo_obj_t *
179 : setup_topo_vinyl_cache( fd_topo_t * topo,
180 0 : fd_configf_t * config ) {
181 0 : fd_topob_wksp( topo, "vinyl_data" );
182 0 : fd_topo_obj_t * line_obj = fd_topob_obj( topo, "vinyl_data", "vinyl_data" );
183 0 : ulong const heap_max = config->vinyl.cache_size_gib<<30;
184 0 : fd_pod_insertf_ulong( topo->props, heap_max, "obj.%lu.data_sz", line_obj->id );
185 0 : fd_pod_insert_ulong( topo->props, "vinyl.data", line_obj->id );
186 0 : return line_obj;
187 0 : }
188 :
189 : /* Resolves a hostname to a single ip address. If multiple ip address
190 : records are returned by getaddrinfo, only the first IPV4 address is
191 : returned via ip_addr. */
192 : static int
193 : resolve_address( char const * address,
194 0 : uint * ip_addr ) {
195 0 : struct addrinfo hints = { .ai_family = AF_INET };
196 0 : struct addrinfo * res;
197 0 : int err = getaddrinfo( address, NULL, &hints, &res );
198 0 : if( FD_UNLIKELY( err ) ) {
199 0 : FD_LOG_WARNING(( "cannot resolve address \"%s\": %i-%s", address, err, gai_strerror( err ) ));
200 0 : return 0;
201 0 : }
202 :
203 0 : int resolved = 0;
204 0 : for( struct addrinfo * cur=res; cur; cur=cur->ai_next ) {
205 0 : if( FD_UNLIKELY( cur->ai_addr->sa_family!=AF_INET ) ) continue;
206 0 : struct sockaddr_in const * addr = (struct sockaddr_in const *)cur->ai_addr;
207 0 : *ip_addr = addr->sin_addr.s_addr;
208 0 : resolved = 1;
209 0 : break;
210 0 : }
211 :
212 0 : freeaddrinfo( res );
213 0 : return resolved;
214 0 : }
215 :
216 : /* Resolves a hostname to multiple ip addresses, specified by
217 : ip_addr_cnt. ip_addrs points to an array of fd_ip4_port_t objects.
218 : hints points to an optionally NULL addrinfo hints object. If hints
219 : is NULL, a default hints settings containing the IPV4 address family
220 : hint will be used. */
221 : static int
222 : resolve_addresses( char const * address,
223 : struct addrinfo const * hints,
224 : fd_ip4_port_t * ip_addrs,
225 0 : ulong ip_addr_cnt ) {
226 0 : struct addrinfo default_hints = { .ai_family = AF_INET };
227 0 : if( FD_UNLIKELY( !hints ) ) {
228 0 : hints = &default_hints;
229 0 : }
230 :
231 0 : struct addrinfo * res;
232 0 : int err = getaddrinfo( address, NULL, hints, &res );
233 0 : if( FD_UNLIKELY( err ) ) {
234 0 : FD_LOG_WARNING(( "cannot resolve address \"%s\": %i-%s", address, err, gai_strerror( err ) ));
235 0 : return 0;
236 0 : }
237 :
238 0 : int resolved = 0;
239 0 : for( struct addrinfo * cur=res; cur; cur=cur->ai_next ) {
240 0 : if( FD_UNLIKELY( (ulong)resolved>=ip_addr_cnt ) ) break;
241 0 : if( FD_UNLIKELY( cur->ai_addr->sa_family!=AF_INET ) ) continue;
242 0 : struct sockaddr_in const * addr = (struct sockaddr_in const *)cur->ai_addr;
243 0 : ip_addrs[ resolved ].addr = addr->sin_addr.s_addr;
244 0 : resolved++;
245 0 : }
246 :
247 0 : freeaddrinfo( res );
248 0 : return resolved;
249 0 : }
250 :
251 : static int
252 : resolve_peer( char const * peer,
253 : struct addrinfo const * addr_resolve_hints,
254 : char const * config_str,
255 : char hostname[ static 256UL ],
256 : fd_ip4_port_t * ip4_port,
257 : ulong ip4_port_cnt,
258 0 : int * is_https ) {
259 :
260 : /* Split host:port */
261 0 : int https = 0;
262 0 : char const * host_port = peer;
263 0 : if( FD_LIKELY( strncmp( peer, "http://", 7UL )==0 ) ) {
264 0 : if( FD_LIKELY( is_https ) ) *is_https = 0;
265 0 : host_port += 7UL;
266 0 : } else if( FD_LIKELY( strncmp( peer, "https://", 8UL )==0 ) ) {
267 0 : if( FD_LIKELY( is_https ) ) *is_https = 1;
268 0 : host_port += 8UL;
269 0 : https = 1;
270 0 : }
271 :
272 0 : char const * colon = strrchr( host_port, ':' );
273 0 : char const * host_end = colon;
274 0 : if( FD_UNLIKELY( !colon && !https ) ) {
275 0 : FD_LOG_ERR(( "invalid [%s] entry \"%s\": no port number", config_str, host_port ));
276 0 : } else if( FD_LIKELY( !colon && https ) ) {
277 0 : host_end = host_port + strlen( host_port );
278 0 : }
279 :
280 0 : ulong fqdn_len = (ulong)( host_end-host_port );
281 0 : if( FD_UNLIKELY( fqdn_len>255 ) ) {
282 0 : FD_LOG_ERR(( "invalid [%s] entry \"%s\": hostname too long", config_str, host_port ));
283 0 : }
284 0 : fd_memcpy( hostname, host_port, fqdn_len );
285 0 : hostname[ fqdn_len ] = '\0';
286 :
287 : /* Resolve hostname */
288 0 : int resolved = resolve_addresses( hostname, addr_resolve_hints, ip4_port, ip4_port_cnt );
289 :
290 : /* Parse port number */
291 :
292 0 : if( FD_LIKELY( colon ) ) {
293 0 : char const * port_str = host_end+1;
294 0 : char const * endptr = NULL;
295 0 : ulong port = strtoul( port_str, (char **)&endptr, 10 );
296 0 : if( FD_UNLIKELY( endptr==port_str || !port || port>USHORT_MAX || *endptr!='\0' ) ) {
297 0 : FD_LOG_ERR(( "invalid [%s] entry \"%s\": invalid port number", config_str, host_port ));
298 0 : }
299 0 : for( ulong i=0UL; i<(ulong)resolved; i++ ) ip4_port[ i ].port = fd_ushort_bswap( (ushort)port );
300 0 : } else if( FD_LIKELY( !colon && https ) ) {
301 : /* use default https port */
302 0 : for( ulong i=0UL; i<(ulong)resolved; i++ ) ip4_port[ i ].port = fd_ushort_bswap( 443U );
303 0 : } else {
304 0 : FD_LOG_ERR(( "invalid [%s] entry \"%s\": no port number", config_str, host_port ));
305 0 : }
306 :
307 0 : return resolved;
308 0 : }
309 :
310 : static void
311 0 : resolve_gossip_entrypoints( config_t * config ) {
312 0 : ulong entrypoint_cnt = config->gossip.entrypoints_cnt;
313 0 : for( ulong i=0UL; i<entrypoint_cnt; i++ ) {
314 0 : char hostname[ 256UL ];
315 0 : if( FD_UNLIKELY( 0==resolve_peer( config->gossip.entrypoints[ i ], NULL, "gossip.entrypoints", hostname, &config->gossip.resolved_entrypoints[ i ], 1, NULL ) ) ) {
316 0 : FD_LOG_ERR(( "failed to resolve address of [gossip.entrypoints] entry \"%s\"", config->gossip.entrypoints[ i ] ));
317 0 : }
318 0 : }
319 0 : }
320 :
321 : void
322 0 : fd_topo_initialize( config_t * config ) {
323 : /* TODO: Not here ... */
324 0 : resolve_gossip_entrypoints( config );
325 :
326 0 : ulong net_tile_cnt = config->layout.net_tile_count;
327 0 : ulong shred_tile_cnt = config->layout.shred_tile_count;
328 0 : ulong quic_tile_cnt = config->layout.quic_tile_count;
329 0 : ulong verify_tile_cnt = config->layout.verify_tile_count;
330 0 : ulong resolv_tile_cnt = config->layout.resolv_tile_count;
331 0 : ulong bank_tile_cnt = config->layout.bank_tile_count;
332 :
333 0 : ulong gossvf_tile_cnt = config->firedancer.layout.gossvf_tile_count;
334 0 : ulong exec_tile_cnt = config->firedancer.layout.exec_tile_count;
335 0 : ulong sign_tile_cnt = config->firedancer.layout.sign_tile_count;
336 0 : ulong lta_tile_cnt = config->firedancer.layout.snapla_tile_count;
337 :
338 0 : int snapshots_enabled = !!config->gossip.entrypoints_cnt;
339 0 : int vinyl_enabled = !!config->firedancer.vinyl.enabled;
340 0 : int snapshot_lthash_disabled = config->development.snapshots.disable_lthash_verification;
341 :
342 0 : fd_topo_t * topo = fd_topob_new( &config->topo, config->name );
343 :
344 0 : topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
345 0 : topo->gigantic_page_threshold = config->hugetlbfs.gigantic_page_threshold_mib << 20;
346 :
347 : /* topo, name */
348 0 : fd_topob_wksp( topo, "metric" );
349 0 : fd_topob_wksp( topo, "genesi" );
350 0 : fd_topob_wksp( topo, "ipecho" );
351 0 : fd_topob_wksp( topo, "gossvf" );
352 0 : fd_topob_wksp( topo, "gossip" );
353 0 : fd_topob_wksp( topo, "shred" );
354 0 : fd_topob_wksp( topo, "repair" );
355 0 : fd_topob_wksp( topo, "replay" );
356 0 : fd_topob_wksp( topo, "exec" );
357 0 : fd_topob_wksp( topo, "tower" );
358 0 : fd_topob_wksp( topo, "send" );
359 :
360 0 : fd_topob_wksp( topo, "quic" );
361 0 : fd_topob_wksp( topo, "verify" );
362 0 : fd_topob_wksp( topo, "dedup" );
363 0 : fd_topob_wksp( topo, "resolv" );
364 0 : fd_topob_wksp( topo, "pack" );
365 0 : fd_topob_wksp( topo, "bank" );
366 0 : fd_topob_wksp( topo, "poh" );
367 0 : fd_topob_wksp( topo, "sign" );
368 :
369 0 : fd_topob_wksp( topo, "metric_in" );
370 :
371 0 : fd_topob_wksp( topo, "net_gossip" );
372 0 : fd_topob_wksp( topo, "net_shred" );
373 0 : fd_topob_wksp( topo, "net_repair" );
374 0 : fd_topob_wksp( topo, "net_send" );
375 0 : fd_topob_wksp( topo, "net_quic" );
376 :
377 0 : fd_topob_wksp( topo, "genesi_out" );
378 0 : fd_topob_wksp( topo, "ipecho_out" );
379 0 : fd_topob_wksp( topo, "gossvf_gossi" );
380 0 : fd_topob_wksp( topo, "gossip_gossv" );
381 0 : fd_topob_wksp( topo, "gossip_out" );
382 :
383 0 : fd_topob_wksp( topo, "shred_out" );
384 0 : fd_topob_wksp( topo, "replay_stake" );
385 0 : fd_topob_wksp( topo, "replay_exec" );
386 0 : fd_topob_wksp( topo, "replay_out" );
387 0 : fd_topob_wksp( topo, "tower_out" );
388 0 : fd_topob_wksp( topo, "send_out" );
389 :
390 0 : fd_topob_wksp( topo, "quic_verify" );
391 0 : fd_topob_wksp( topo, "verify_dedup" );
392 0 : fd_topob_wksp( topo, "dedup_resolv" );
393 0 : fd_topob_wksp( topo, "resolv_pack" );
394 0 : fd_topob_wksp( topo, "pack_poh" );
395 0 : fd_topob_wksp( topo, "pack_bank" );
396 0 : fd_topob_wksp( topo, "resolv_repla" );
397 0 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
398 0 : fd_topob_wksp( topo, "bank_pack" );
399 0 : }
400 0 : fd_topob_wksp( topo, "bank_poh" );
401 0 : fd_topob_wksp( topo, "bank_busy" );
402 0 : fd_topob_wksp( topo, "poh_shred" );
403 0 : fd_topob_wksp( topo, "poh_replay" );
404 :
405 0 : fd_topob_wksp( topo, "funk" );
406 0 : fd_topob_wksp( topo, "progcache" );
407 0 : fd_topob_wksp( topo, "fec_sets" );
408 0 : fd_topob_wksp( topo, "txncache" );
409 0 : fd_topob_wksp( topo, "banks" );
410 0 : fd_topob_wksp( topo, "store" );
411 0 : fd_topob_wksp( topo, "executed_txn" );
412 :
413 0 : fd_topob_wksp( topo, "gossip_sign" );
414 0 : fd_topob_wksp( topo, "sign_gossip" );
415 :
416 0 : fd_topob_wksp( topo, "shred_sign" );
417 0 : fd_topob_wksp( topo, "sign_shred" );
418 :
419 0 : fd_topob_wksp( topo, "repair_sign" );
420 0 : fd_topob_wksp( topo, "sign_repair" );
421 :
422 0 : fd_topob_wksp( topo, "send_sign" );
423 0 : fd_topob_wksp( topo, "sign_send" );
424 :
425 0 : fd_topob_wksp( topo, "exec_sig" );
426 :
427 0 : fd_topob_wksp( topo, "cswtch" );
428 :
429 0 : fd_topob_wksp( topo, "exec_replay" );
430 :
431 0 : if( FD_LIKELY( snapshots_enabled ) ) {
432 0 : fd_topob_wksp( topo, "snapct" );
433 0 : fd_topob_wksp( topo, "snapld" );
434 0 : fd_topob_wksp( topo, "snapdc" );
435 0 : fd_topob_wksp( topo, "snapin" );
436 0 : if( vinyl_enabled ) {
437 0 : fd_topob_wksp( topo, "snapwh" );
438 0 : fd_topob_wksp( topo, "snapwr" );
439 0 : }
440 :
441 0 : fd_topob_wksp( topo, "snapct_ld" );
442 0 : fd_topob_wksp( topo, "snapld_dc" );
443 0 : fd_topob_wksp( topo, "snapdc_in" );
444 0 : if( vinyl_enabled ) fd_topob_wksp( topo, "snapin_wr" );
445 :
446 0 : if( FD_UNLIKELY( snapshot_lthash_disabled ) ) {
447 0 : fd_topob_wksp( topo, "snapin_ct" );
448 0 : } else {
449 0 : fd_topob_wksp( topo, "snapls_ct" );
450 0 : }
451 :
452 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) fd_topob_wksp( topo, "snapct_gui" );
453 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) fd_topob_wksp( topo, "snapin_gui" );
454 0 : fd_topob_wksp( topo, "snapin_manif" );
455 0 : fd_topob_wksp( topo, "snapct_repr" );
456 :
457 0 : if( FD_LIKELY( !snapshot_lthash_disabled ) ) {
458 0 : fd_topob_wksp( topo, "snapla" );
459 0 : fd_topob_wksp( topo, "snapls" );
460 0 : fd_topob_wksp( topo, "snapla_ls" );
461 0 : fd_topob_wksp( topo, "snapin_ls" );
462 0 : }
463 0 : }
464 :
465 0 : #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
466 :
467 0 : ulong shred_depth = 65536UL; /* from fdctl/topology.c shred_store link. MAKE SURE TO KEEP IN SYNC. */
468 :
469 : /* topo, link_name, wksp_name, depth, mtu, burst */
470 0 : /**/ fd_topob_link( topo, "gossip_net", "net_gossip", 32768UL, FD_NET_MTU, 1UL );
471 0 : FOR(shred_tile_cnt) fd_topob_link( topo, "shred_net", "net_shred", 32768UL, FD_NET_MTU, 1UL );
472 0 : /**/ fd_topob_link( topo, "repair_net", "net_repair", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
473 0 : /**/ fd_topob_link( topo, "send_net", "net_send", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
474 0 : FOR(quic_tile_cnt) fd_topob_link( topo, "quic_net", "net_quic", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
475 :
476 0 : if( FD_LIKELY( snapshots_enabled ) ) {
477 : /* TODO: Revisit the depths of all the snapshot links */
478 0 : /**/ fd_topob_link( topo, "snapct_ld", "snapct_ld", 128UL, sizeof(fd_ssctrl_init_t), 1UL );
479 0 : /**/ fd_topob_link( topo, "snapld_dc", "snapld_dc", 16384UL, USHORT_MAX, 1UL );
480 0 : /**/ fd_topob_link( topo, "snapdc_in", "snapdc_in", 16384UL, USHORT_MAX, 1UL );
481 0 : if( FD_UNLIKELY( snapshot_lthash_disabled ) ) {
482 0 : fd_topob_link( topo, "snapin_ct", "snapin_ct", 128UL, 0UL, 1UL );
483 0 : } else {
484 0 : fd_topob_link( topo, "snapls_ct", "snapls_ct", 128UL, 0UL, 1UL );
485 0 : }
486 0 : /**/ fd_topob_link( topo, "snapin_manif", "snapin_manif", 4UL, sizeof(fd_snapshot_manifest_t),1UL );
487 0 : /**/ fd_topob_link( topo, "snapct_repr", "snapct_repr", 128UL, 0UL, 1UL )->permit_no_consumers = 1; /* TODO: wire in repair later */
488 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
489 0 : /**/ fd_topob_link( topo, "snapct_gui", "snapct_gui", 128UL, sizeof(fd_snapct_update_t), 1UL );
490 0 : /**/ fd_topob_link( topo, "snapin_gui", "snapin_gui", 128UL, FD_GUI_CONFIG_PARSE_MAX_VALID_ACCT_SZ_WITH_NULL, 1UL );
491 0 : }
492 0 : if( vinyl_enabled ) {
493 0 : fd_topo_link_t * snapin_wh =
494 0 : /**/ fd_topob_link( topo, "snapin_wh", "snapin_wr", 4UL, 16UL<<20, 1UL );
495 0 : /**/ fd_topob_link( topo, "snapwh_wr", "snapin_wr", 4UL, 0UL, 1UL );
496 0 : fd_pod_insertf_ulong( topo->props, 8UL, "obj.%lu.app_sz", snapin_wh->dcache_obj_id );
497 0 : }
498 0 : if( FD_LIKELY( !snapshot_lthash_disabled ) ) {
499 0 : FOR(lta_tile_cnt) fd_topob_link( topo, "snapla_ls", "snapla_ls", 128UL, sizeof(fd_lthash_value_t), 1UL );
500 0 : /**/ fd_topob_link( topo, "snapin_ls", "snapin_ls", 256UL, sizeof(fd_snapshot_full_account_t), 1UL );
501 0 : }
502 0 : }
503 :
504 : /**/ fd_topob_link( topo, "genesi_out", "genesi_out", 2UL, 10UL*1024UL*1024UL+32UL+sizeof(fd_lthash_value_t), 1UL );
505 0 : /**/ fd_topob_link( topo, "ipecho_out", "ipecho_out", 2UL, 0UL, 1UL );
506 0 : FOR(gossvf_tile_cnt) fd_topob_link( topo, "gossvf_gossi", "gossvf_gossi", config->net.ingress_buffer_size, sizeof(fd_gossip_view_t)+FD_NET_MTU, 1UL );
507 0 : /**/ fd_topob_link( topo, "gossip_gossv", "gossip_gossv", 65536UL*4UL, sizeof(fd_gossip_ping_update_t), 1UL ); /* TODO: Unclear where this depth comes from ... fix */
508 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 */
509 :
510 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 );
511 0 : FOR(verify_tile_cnt) fd_topob_link( topo, "verify_dedup", "verify_dedup", config->tiles.verify.receive_buffer_size, FD_TPU_PARSED_MTU, 1UL );
512 0 : /**/ fd_topob_link( topo, "dedup_resolv", "dedup_resolv", 65536UL, FD_TPU_PARSED_MTU, 1UL );
513 0 : FOR(resolv_tile_cnt) fd_topob_link( topo, "resolv_pack", "resolv_pack", 65536UL, FD_TPU_RESOLVED_MTU, 1UL );
514 0 : /**/ fd_topob_link( topo, "replay_stake", "replay_stake", 128UL, FD_STAKE_OUT_MTU, 1UL ); /* TODO: This should be 2 but requires fixing STEM_BURST */
515 0 : /**/ fd_topob_link( topo, "replay_out", "replay_out", 8192UL, sizeof(fd_replay_message_t), 1UL );
516 0 : /**/ fd_topob_link( topo, "pack_poh", "pack_poh", 4096UL, sizeof(fd_done_packing_t), 1UL );
517 : /* pack_bank is shared across all banks, so if one bank stalls due to complex transactions, the buffer needs to be large so that
518 : other banks can keep proceeding. */
519 0 : /**/ fd_topob_link( topo, "pack_bank", "pack_bank", 65536UL, USHORT_MAX, 1UL );
520 0 : FOR(bank_tile_cnt) fd_topob_link( topo, "bank_poh", "bank_poh", 16384UL, USHORT_MAX, 1UL );
521 0 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
522 0 : FOR(bank_tile_cnt) fd_topob_link( topo, "bank_pack", "bank_pack", 16384UL, USHORT_MAX, 1UL );
523 0 : }
524 0 : /**/ fd_topob_link( topo, "poh_shred", "poh_shred", 16384UL, USHORT_MAX, 1UL );
525 0 : /**/ fd_topob_link( topo, "poh_replay", "poh_replay", 4096UL, sizeof(fd_poh_leader_slot_ended_t), 1UL );
526 0 : FOR(resolv_tile_cnt) fd_topob_link( topo, "resolv_repla", "resolv_repla", 4096UL, sizeof(fd_resolv_slot_exchanged_t), 1UL );
527 0 : /**/ fd_topob_link( topo, "executed_txn", "executed_txn", 16384UL, 64UL, 1UL ); /* TODO: Rename this ... */
528 :
529 0 : FOR(shred_tile_cnt) fd_topob_link( topo, "shred_sign", "shred_sign", 128UL, 32UL, 1UL );
530 0 : FOR(shred_tile_cnt) fd_topob_link( topo, "sign_shred", "sign_shred", 128UL, sizeof(fd_ed25519_sig_t), 1UL );
531 :
532 : /**/ fd_topob_link( topo, "gossip_sign", "gossip_sign", 128UL, 2048UL, 1UL ); /* TODO: Where does 2048 come from? Depth probably doesn't need to be 128 */
533 0 : /**/ fd_topob_link( topo, "sign_gossip", "sign_gossip", 128UL, sizeof(fd_ed25519_sig_t), 1UL ); /* TODO: Depth probably doesn't need to be 128 */
534 :
535 0 : FOR(sign_tile_cnt-1) fd_topob_link( topo, "repair_sign", "repair_sign", 128UL, FD_REPAIR_MAX_PREIMAGE_SZ, 1UL );
536 0 : FOR(sign_tile_cnt-1) fd_topob_link( topo, "sign_repair", "sign_repair", 128UL, sizeof(fd_ed25519_sig_t), 1UL );
537 :
538 0 : /**/ fd_topob_link( topo, "send_sign", "send_sign", 128UL, FD_TXN_MTU, 1UL ); /* TODO: Depth probably doesn't need to be 128 */
539 0 : /**/ fd_topob_link( topo, "sign_send", "sign_send", 128UL, sizeof(fd_ed25519_sig_t), 1UL ); /* TODO: Depth probably doesn't need to be 128 */
540 :
541 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 */
542 0 : FOR(shred_tile_cnt) fd_topob_link( topo, "repair_shred", "shred_out", shred_depth, sizeof(fd_ed25519_sig_t), 1UL );
543 0 : /**/ fd_topob_link( topo, "tower_out", "tower_out", 128UL, sizeof(fd_tower_msg_t), 3UL ); /* dup conf + cluster conf + slot_done */
544 0 : /**/ fd_topob_link( topo, "send_out", "send_out", 128UL, FD_TPU_RAW_MTU, 1UL );
545 :
546 0 : fd_topob_link( topo, "replay_exec", "replay_exec", 16384UL, sizeof(fd_exec_task_msg_t), 1UL );
547 :
548 0 : FOR(exec_tile_cnt) fd_topob_link( topo, "exec_sig", "exec_sig", 16384UL, 64UL, 1UL );
549 0 : FOR(exec_tile_cnt) fd_topob_link( topo, "exec_replay", "exec_replay", 16384UL, sizeof(fd_exec_task_done_msg_t), 1UL );
550 :
551 0 : ushort parsed_tile_to_cpu[ FD_TILE_MAX ];
552 : /* Unassigned tiles will be floating, unless auto topology is enabled. */
553 0 : for( ulong i=0UL; i<FD_TILE_MAX; i++ ) parsed_tile_to_cpu[ i ] = USHORT_MAX;
554 :
555 0 : int is_auto_affinity = !strcmp( config->layout.affinity, "auto" );
556 :
557 0 : fd_topo_cpus_t cpus[1];
558 0 : fd_topo_cpus_init( cpus );
559 :
560 0 : ulong affinity_tile_cnt = 0UL;
561 0 : if( FD_LIKELY( !is_auto_affinity ) ) affinity_tile_cnt = fd_tile_private_cpus_parse( config->layout.affinity, parsed_tile_to_cpu );
562 :
563 0 : ulong tile_to_cpu[ FD_TILE_MAX ] = {0};
564 0 : for( ulong i=0UL; i<affinity_tile_cnt; i++ ) {
565 0 : if( FD_UNLIKELY( parsed_tile_to_cpu[ i ]!=USHORT_MAX && parsed_tile_to_cpu[ i ]>=cpus->cpu_cnt ) )
566 0 : FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.affinity] specifies a CPU index of %hu, but the system "
567 0 : "only has %lu CPUs. You should either change the CPU allocations in the affinity string, or increase the number of CPUs "
568 0 : "in the system.",
569 0 : parsed_tile_to_cpu[ i ], cpus->cpu_cnt ));
570 0 : tile_to_cpu[ i ] = fd_ulong_if( parsed_tile_to_cpu[ i ]==USHORT_MAX, ULONG_MAX, (ulong)parsed_tile_to_cpu[ i ] );
571 0 : }
572 :
573 0 : 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, tile_to_cpu );
574 :
575 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_gossvf", i, config->net.ingress_buffer_size );
576 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_shred", i, config->net.ingress_buffer_size );
577 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_repair", i, config->net.ingress_buffer_size );
578 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_send", i, config->net.ingress_buffer_size );
579 0 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_quic", i, config->net.ingress_buffer_size );
580 :
581 : /* topo, tile_name, tile_wksp, metrics_wksp, cpu_idx, is_agave, uses_keyswitch */
582 : /**/ fd_topob_tile( topo, "metric", "metric", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
583 0 : /**/ fd_topob_tile( topo, "cswtch", "cswtch", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
584 :
585 0 : if( FD_LIKELY( snapshots_enabled ) ) {
586 0 : /**/ fd_topob_tile( topo, "snapct", "snapct", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
587 0 : /**/ fd_topob_tile( topo, "snapld", "snapld", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
588 0 : /**/ fd_topob_tile( topo, "snapdc", "snapdc", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
589 0 : /**/ fd_topob_tile( topo, "snapin", "snapin", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
590 0 : if(vinyl_enabled) fd_topob_tile( topo, "snapwh", "snapwh", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
591 0 : if(vinyl_enabled) fd_topob_tile( topo, "snapwr", "snapwr", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
592 :
593 0 : if( FD_LIKELY( !snapshot_lthash_disabled ) ) {
594 0 : FOR(lta_tile_cnt) fd_topob_tile( topo, "snapla", "snapla", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
595 0 : /**/ fd_topob_tile( topo, "snapls", "snapls", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
596 0 : }
597 0 : }
598 :
599 : /**/ fd_topob_tile( topo, "genesi", "genesi", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
600 0 : /**/ fd_topob_tile( topo, "ipecho", "ipecho", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
601 0 : FOR(gossvf_tile_cnt) fd_topob_tile( topo, "gossvf", "gossvf", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
602 0 : /**/ fd_topob_tile( topo, "gossip", "gossip", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
603 :
604 0 : FOR(shred_tile_cnt) fd_topob_tile( topo, "shred", "shred", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
605 0 : /**/ fd_topob_tile( topo, "repair", "repair", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 ); /* TODO: Wrong? Needs to use keyswitch as signs */
606 0 : /**/ fd_topob_tile( topo, "replay", "replay", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
607 0 : FOR(exec_tile_cnt) fd_topob_tile( topo, "exec", "exec", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
608 0 : /**/ fd_topob_tile( topo, "tower", "tower", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
609 0 : /**/ fd_topob_tile( topo, "send", "send", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
610 :
611 0 : FOR(quic_tile_cnt) fd_topob_tile( topo, "quic", "quic", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
612 0 : FOR(verify_tile_cnt) fd_topob_tile( topo, "verify", "verify", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
613 0 : /**/ fd_topob_tile( topo, "dedup", "dedup", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
614 0 : FOR(resolv_tile_cnt) fd_topob_tile( topo, "resolv", "resolv", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
615 0 : FOR(resolv_tile_cnt) strncpy( topo->tiles[ topo->tile_cnt-1UL-i ].metrics_name, "resolf", 8UL );
616 0 : /**/ fd_topob_tile( topo, "pack", "pack", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, config->tiles.bundle.enabled );
617 0 : FOR(bank_tile_cnt) fd_topob_tile( topo, "bank", "bank", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
618 0 : FOR(bank_tile_cnt) strncpy( topo->tiles[ topo->tile_cnt-1UL-i ].metrics_name, "bankf", 6UL );
619 0 : /**/ fd_topob_tile( topo, "poh", "poh", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
620 0 : FOR(sign_tile_cnt) fd_topob_tile( topo, "sign", "sign", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
621 :
622 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
623 0 : FOR(gossvf_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
624 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 */
625 0 : FOR(shred_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
626 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 */
627 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 */
628 0 : /**/ fd_topob_tile_out( topo, "repair", 0UL, "repair_net", 0UL );
629 0 : FOR(net_tile_cnt) fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "net_send", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
630 0 : FOR(quic_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
631 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 */
632 :
633 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 */
634 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 */
635 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 */
636 0 : /**/ fd_topos_tile_in_net( topo, "metric_in", "send_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
637 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 */
638 :
639 0 : /**/ fd_topob_tile_out( topo, "genesi", 0UL, "genesi_out", 0UL );
640 0 : /**/ fd_topob_tile_in ( topo, "ipecho", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
641 0 : /**/ fd_topob_tile_out( topo, "ipecho", 0UL, "ipecho_out", 0UL );
642 :
643 0 : FOR(gossvf_tile_cnt) fd_topob_tile_out( topo, "gossvf", i, "gossvf_gossi", i );
644 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
645 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "gossip_gossv", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
646 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
647 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
648 0 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
649 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_out", 0UL );
650 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_net", 0UL );
651 0 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
652 0 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "gossvf_gossi", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
653 0 : /**/ fd_topob_tile_in( topo, "gossip", 0UL, "metric_in", "send_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
654 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_gossv", 0UL );
655 :
656 0 : int snapshots_gossip_enabled = config->firedancer.snapshots.sources.gossip.allow_any || config->firedancer.snapshots.sources.gossip.allow_list_cnt>0UL;
657 0 : if( FD_LIKELY( snapshots_enabled ) ) {
658 0 : if( FD_LIKELY( snapshots_gossip_enabled ) ) {
659 0 : /**/ fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
660 0 : }
661 :
662 0 : if( FD_UNLIKELY( snapshot_lthash_disabled ) ) {
663 0 : fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapin_ct", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
664 0 : } else {
665 0 : fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapls_ct", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
666 0 : }
667 0 : fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
668 0 : fd_topob_tile_out( topo, "snapct", 0UL, "snapct_ld", 0UL );
669 0 : fd_topob_tile_out( topo, "snapct", 0UL, "snapct_repr", 0UL );
670 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
671 0 : /**/ fd_topob_tile_out( topo, "snapct", 0UL, "snapct_gui", 0UL );
672 0 : }
673 0 : if( vinyl_enabled ) {
674 0 : /**/ fd_topob_tile_out( topo, "snapin", 0UL, "snapin_wh", 0UL );
675 0 : /**/ fd_topob_tile_in ( topo, "snapwh", 0UL, "metric_in", "snapin_wh", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
676 0 : /**/ fd_topob_tile_out( topo, "snapwh", 0UL, "snapwh_wr", 0UL );
677 0 : /**/ fd_topob_tile_in ( topo, "snapwr", 0UL, "metric_in", "snapwh_wr", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
678 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapwr", 0UL ) ], &topo->objs[ topo->links[ fd_topo_find_link( topo, "snapin_wh", 0UL ) ].dcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_ONLY );
679 0 : }
680 :
681 0 : /**/ fd_topob_tile_in ( topo, "snapld", 0UL, "metric_in", "snapct_ld", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
682 0 : /**/ fd_topob_tile_out( topo, "snapld", 0UL, "snapld_dc", 0UL );
683 :
684 0 : /**/ fd_topob_tile_in ( topo, "snapdc", 0UL, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
685 0 : /**/ fd_topob_tile_out( topo, "snapdc", 0UL, "snapdc_in", 0UL );
686 :
687 0 : fd_topob_tile_in ( topo, "snapin", 0UL, "metric_in", "snapdc_in", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
688 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
689 0 : /**/ fd_topob_tile_out( topo, "snapin", 0UL, "snapin_gui", 0UL );
690 0 : }
691 0 : if( FD_UNLIKELY( snapshot_lthash_disabled ) ) {
692 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_ct", 0UL );
693 0 : } else {
694 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_ls", 0UL );
695 0 : }
696 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_manif", 0UL );
697 0 : if( FD_LIKELY( !snapshot_lthash_disabled ) ) {
698 0 : FOR(lta_tile_cnt) fd_topob_tile_in( topo, "snapla", i, "metric_in", "snapdc_in", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
699 0 : FOR(lta_tile_cnt) fd_topob_tile_out( topo, "snapla", i, "snapla_ls", i );
700 0 : /**/ fd_topob_tile_in( topo, "snapls", 0UL, "metric_in", "snapin_ls", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
701 0 : FOR(lta_tile_cnt) fd_topob_tile_in( topo, "snapls", 0UL, "metric_in", "snapla_ls", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
702 0 : /**/ fd_topob_tile_out( topo, "snapls", 0UL, "snapls_ct", 0UL );
703 0 : }
704 0 : }
705 :
706 0 : /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
707 0 : /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
708 0 : /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
709 0 : /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
710 0 : if( snapshots_enabled ) {
711 0 : fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
712 0 : }
713 0 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "shred_out", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
714 0 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "shred_out", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
715 0 : FOR(shred_tile_cnt) fd_topob_tile_out( topo, "repair", 0UL, "repair_shred", i );
716 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
717 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_out", 0UL );
718 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_stake", 0UL );
719 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "executed_txn", 0UL );
720 0 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_exec", 0UL );
721 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
722 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "send_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
723 0 : FOR(resolv_tile_cnt) fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "resolv_repla", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
724 0 : if( FD_LIKELY( snapshots_enabled ) ) {
725 0 : fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
726 0 : }
727 :
728 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "poh_replay", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
729 0 : FOR(exec_tile_cnt) fd_topob_tile_in ( topo, "exec", i, "metric_in", "replay_exec", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
730 :
731 0 : /**/ fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "dedup_resolv", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
732 0 : /**/ fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "replay_exec", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
733 0 : /**/ fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
734 0 : /**/ fd_topob_tile_out( topo, "tower", 0UL, "tower_out", 0UL );
735 :
736 0 : /**/ fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
737 0 : /**/ fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
738 0 : /**/ fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
739 0 : /**/ fd_topob_tile_out( topo, "send", 0UL, "send_net", 0UL );
740 0 : /**/ fd_topob_tile_out( topo, "send", 0UL, "send_out", 0UL );
741 :
742 0 : FOR(quic_tile_cnt) fd_topob_tile_out( topo, "quic", i, "quic_verify", i );
743 0 : FOR(quic_tile_cnt) fd_topob_tile_out( topo, "quic", i, "quic_net", i );
744 : /* All verify tiles read from all QUIC tiles, packets are round robin. */
745 0 : FOR(verify_tile_cnt) for( ulong j=0UL; j<quic_tile_cnt; j++ )
746 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 */
747 0 : FOR(verify_tile_cnt) fd_topob_tile_in( topo, "verify", i, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
748 0 : /**/ fd_topob_tile_in( topo, "verify", 0UL, "metric_in", "send_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
749 0 : FOR(verify_tile_cnt) fd_topob_tile_out( topo, "verify", i, "verify_dedup", i );
750 0 : FOR(verify_tile_cnt) fd_topob_tile_in( topo, "dedup", 0UL, "metric_in", "verify_dedup", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
751 0 : /**/ fd_topob_tile_in( topo, "dedup", 0UL, "metric_in", "executed_txn", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
752 0 : /**/ fd_topob_tile_out( topo, "dedup", 0UL, "dedup_resolv", 0UL );
753 0 : FOR(resolv_tile_cnt) fd_topob_tile_in( topo, "resolv", i, "metric_in", "dedup_resolv", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
754 0 : FOR(resolv_tile_cnt) fd_topob_tile_in( topo, "resolv", i, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
755 0 : FOR(resolv_tile_cnt) fd_topob_tile_out( topo, "resolv", i, "resolv_pack", i );
756 0 : FOR(resolv_tile_cnt) fd_topob_tile_out( topo, "resolv", i, "resolv_repla", i );
757 0 : /**/ fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "resolv_pack", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
758 0 : /**/ fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
759 0 : /**/ fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "executed_txn", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
760 0 : fd_topob_tile_out( topo, "pack", 0UL, "pack_bank", 0UL );
761 0 : fd_topob_tile_out( topo, "pack", 0UL, "pack_poh" , 0UL );
762 0 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
763 0 : FOR(bank_tile_cnt) fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "bank_pack", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
764 0 : }
765 0 : FOR(bank_tile_cnt) fd_topob_tile_in( topo, "bank", i, "metric_in", "pack_bank", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
766 0 : FOR(bank_tile_cnt) fd_topob_tile_out( topo, "bank", i, "bank_poh", i );
767 0 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
768 0 : FOR(bank_tile_cnt) fd_topob_tile_out( topo, "bank", i, "bank_pack", i );
769 0 : }
770 0 : FOR(bank_tile_cnt) fd_topob_tile_in( topo, "poh", 0UL, "metric_in", "bank_poh", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
771 0 : /**/ fd_topob_tile_in( topo, "poh", 0UL, "metric_in", "pack_poh", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
772 0 : /**/ fd_topob_tile_in( topo, "poh", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
773 0 : /**/ fd_topob_tile_out( topo, "poh", 0UL, "poh_shred", 0UL );
774 0 : /**/ fd_topob_tile_out( topo, "poh", 0UL, "poh_replay", 0UL );
775 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
776 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
777 0 : FOR(shred_tile_cnt) fd_topob_tile_out( topo, "shred", i, "shred_out", i );
778 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "repair_shred", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
779 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
780 0 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "poh_shred", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
781 0 : FOR(shred_tile_cnt) fd_topob_tile_out( topo, "shred", i, "shred_net", i );
782 :
783 0 : FOR(exec_tile_cnt) fd_topob_tile_in ( topo, "dedup", 0UL, "metric_in", "exec_sig", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
784 0 : FOR(exec_tile_cnt) fd_topob_tile_in ( topo, "pack", 0UL, "metric_in", "exec_sig", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
785 0 : FOR(exec_tile_cnt) fd_topob_tile_out( topo, "exec", i, "exec_sig", i );
786 0 : FOR(exec_tile_cnt) fd_topob_tile_out( topo, "exec", i, "exec_replay", i );
787 0 : FOR(exec_tile_cnt) fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "exec_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
788 :
789 :
790 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
791 0 : fd_topob_wksp( topo, "bundle_verif" );
792 0 : fd_topob_wksp( topo, "bundle_sign" );
793 0 : fd_topob_wksp( topo, "sign_bundle" );
794 0 : fd_topob_wksp( topo, "pack_sign" );
795 0 : fd_topob_wksp( topo, "sign_pack" );
796 0 : fd_topob_wksp( topo, "bundle" );
797 :
798 0 : /**/ fd_topob_link( topo, "bundle_verif", "bundle_verif", config->tiles.verify.receive_buffer_size, FD_TPU_PARSED_MTU, 1UL );
799 0 : /**/ fd_topob_link( topo, "bundle_sign", "bundle_sign", 65536UL, 9UL, 1UL );
800 0 : /**/ fd_topob_link( topo, "sign_bundle", "sign_bundle", 128UL, 64UL, 1UL );
801 0 : /**/ fd_topob_link( topo, "pack_sign", "pack_sign", 65536UL, 1232UL, 1UL );
802 0 : /**/ fd_topob_link( topo, "sign_pack", "sign_pack", 128UL, 64UL, 1UL );
803 :
804 : /**/ fd_topob_tile( topo, "bundle", "bundle", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
805 :
806 : /**/ fd_topob_tile_out( topo, "bundle", 0UL, "bundle_verif", 0UL );
807 0 : FOR(verify_tile_cnt) fd_topob_tile_in( topo, "verify", i, "metric_in", "bundle_verif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
808 :
809 0 : /**/ fd_topob_tile_in( topo, "sign", 0UL, "metric_in", "bundle_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
810 0 : /**/ fd_topob_tile_out( topo, "bundle", 0UL, "bundle_sign", 0UL );
811 0 : /**/ fd_topob_tile_in( topo, "bundle", 0UL, "metric_in", "sign_bundle", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
812 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_bundle", 0UL );
813 :
814 0 : /**/ fd_topob_tile_in( topo, "sign", 0UL, "metric_in", "pack_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
815 0 : /**/ fd_topob_tile_out( topo, "pack", 0UL, "pack_sign", 0UL );
816 0 : /**/ fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "sign_pack", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
817 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_pack", 0UL );
818 :
819 : /* TODO: bundle gui support needs to be integrated here */
820 0 : }
821 :
822 : /* Sign links don't need to be reliable because they are synchronous,
823 : so there's at most one fragment in flight at a time anyway. The
824 : sign links are also not polled by fd_stem, instead the tiles will
825 : read the sign responses out of band in a dedicated spin loop.
826 :
827 : TODO: This can probably be fixed now to be relible ... ? */
828 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
829 0 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "gossip_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
830 0 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_sign", 0UL );
831 0 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "sign_gossip", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
832 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_gossip", 0UL );
833 :
834 0 : for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
835 0 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "shred_sign", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
836 0 : /**/ fd_topob_tile_out( topo, "shred", i, "shred_sign", i );
837 0 : /**/ fd_topob_tile_in ( topo, "shred", i, "metric_in", "sign_shred", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
838 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_shred", i );
839 0 : }
840 :
841 0 : FOR(sign_tile_cnt-1UL) fd_topob_tile_out( topo, "repair", 0UL, "repair_sign", i );
842 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 );
843 0 : FOR(sign_tile_cnt-1UL) fd_topob_tile_out( topo, "sign", i+1UL, "sign_repair", i );
844 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 */
845 :
846 0 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "send_sign", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
847 0 : /**/ fd_topob_tile_out( topo, "send", 0UL, "send_sign", 0UL );
848 0 : /**/ fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "sign_send", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
849 0 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_send", 0UL );
850 :
851 0 : if( FD_UNLIKELY( config->tiles.archiver.enabled ) ) {
852 0 : fd_topob_wksp( topo, "arch_f" );
853 0 : fd_topob_wksp( topo, "arch_w" );
854 0 : fd_topob_wksp( topo, "feeder" );
855 0 : fd_topob_wksp( topo, "arch_f2w" );
856 :
857 0 : fd_topob_link( topo, "feeder", "feeder", 65536UL, 4UL*FD_SHRED_STORE_MTU, 4UL+config->tiles.shred.max_pending_shred_sets );
858 0 : fd_topob_link( topo, "arch_f2w", "arch_f2w", 128UL, 4UL*FD_SHRED_STORE_MTU, 1UL );
859 :
860 0 : fd_topob_tile( topo, "arch_f", "arch_f", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
861 0 : fd_topob_tile( topo, "arch_w", "arch_w", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
862 :
863 0 : fd_topob_tile_out( topo, "replay", 0UL, "feeder", 0UL );
864 0 : fd_topob_tile_in( topo, "arch_f", 0UL, "metric_in", "feeder", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
865 :
866 0 : fd_topob_tile_out( topo, "arch_f", 0UL, "arch_f2w", 0UL );
867 0 : fd_topob_tile_in( topo, "arch_w", 0UL, "metric_in", "arch_f2w", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
868 0 : }
869 :
870 0 : if( FD_UNLIKELY( config->tiles.shredcap.enabled ) ) {
871 0 : fd_topob_wksp( topo, "scap" );
872 :
873 0 : fd_topob_tile( topo, "scap", "scap", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
874 :
875 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "repair_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
876 0 : for( ulong j=0UL; j<net_tile_cnt; j++ ) {
877 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "net_shred", j, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
878 0 : }
879 0 : for( ulong j=0UL; j<shred_tile_cnt; j++ ) {
880 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "shred_out", j, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
881 0 : }
882 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
883 :
884 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
885 :
886 : /* No default fd_topob_tile_in connection to stake_out */
887 0 : }
888 :
889 0 : int rpc_enabled = config->tiles.rpc.enabled;
890 0 : if( FD_UNLIKELY( rpc_enabled ) ) {
891 0 : fd_topob_wksp( topo, "rpc" );
892 0 : fd_topob_wksp( topo, "rpc_replay" );
893 0 : fd_topob_link( topo, "rpc_replay", "rpc_replay", 4UL, 0UL, 1UL );
894 0 : fd_topob_tile( topo, "rpc", "rpc", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
895 0 : fd_topob_tile_out( topo, "rpc", 0UL, "rpc_replay", 0UL );
896 0 : fd_topob_tile_in( topo, "rpc", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
897 0 : fd_topob_tile_in( topo, "rpc", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
898 0 : fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "rpc_replay", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
899 0 : }
900 :
901 0 : if( FD_LIKELY( !is_auto_affinity ) ) {
902 0 : if( FD_UNLIKELY( affinity_tile_cnt<topo->tile_cnt ) )
903 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. "
904 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 "
905 0 : "the total tile count. You can reduce the tile count by decreasing individual tile counts in the [layout] section of the configuration file.",
906 0 : topo->tile_cnt, affinity_tile_cnt ));
907 0 : if( FD_UNLIKELY( affinity_tile_cnt>topo->tile_cnt ) )
908 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. "
909 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 "
910 0 : "individual tile counts in the [layout] section of the configuration file.",
911 0 : topo->tile_cnt, affinity_tile_cnt ));
912 0 : }
913 :
914 :
915 0 : if( FD_UNLIKELY( is_auto_affinity ) ) fd_topob_auto_layout( topo, 0 );
916 :
917 : /* There is a special fseq that sits between the pack, bank, and poh
918 : tiles to indicate when the bank/poh tiles are done processing a
919 : microblock. Pack uses this to determine when to "unlock" accounts
920 : that it marked as locked because they were being used. */
921 :
922 0 : for( ulong i=0UL; i<bank_tile_cnt; i++ ) {
923 0 : fd_topo_obj_t * busy_obj = fd_topob_obj( topo, "fseq", "bank_busy" );
924 :
925 0 : fd_topo_tile_t * pack_tile = &topo->tiles[ fd_topo_find_tile( topo, "pack", 0UL ) ];
926 0 : fd_topo_tile_t * bank_tile = &topo->tiles[ fd_topo_find_tile( topo, "bank", i ) ];
927 0 : fd_topob_tile_uses( topo, pack_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
928 0 : fd_topob_tile_uses( topo, bank_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
929 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, busy_obj->id, "bank_busy.%lu", i ) );
930 0 : }
931 :
932 0 : fd_topo_obj_t * funk_obj = setup_topo_funk( topo, "funk",
933 0 : config->firedancer.funk.max_account_records,
934 0 : config->firedancer.funk.max_database_transactions,
935 0 : config->firedancer.funk.heap_size_gib );
936 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE ); /* TODO: Should be readonly? */
937 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "tower", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
938 0 : FOR(exec_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
939 0 : FOR(bank_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "bank", i ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
940 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 );
941 :
942 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 );
943 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE ); /* TODO: Should be readonly? */
944 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "tower", 0UL ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
945 0 : FOR(exec_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE ); /* TODO: Should be readonly? */
946 0 : FOR(bank_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "bank", i ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
947 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 );
948 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, banks_obj->id, "banks" ) );
949 :
950 0 : fd_topo_obj_t * progcache_obj = setup_topo_progcache( topo, "progcache",
951 0 : fd_progcache_est_rec_max( config->firedancer.runtime.program_cache.heap_size_mib<<20,
952 0 : config->firedancer.runtime.program_cache.mean_cache_entry_size ),
953 0 : config->firedancer.funk.max_database_transactions,
954 0 : config->firedancer.runtime.program_cache.heap_size_mib<<20 );
955 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
956 0 : FOR(exec_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
957 0 : FOR(bank_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "bank", i ) ], progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
958 :
959 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
960 0 : fd_topob_wksp( topo, "gui" );
961 :
962 : /**/ fd_topob_tile( topo, "gui", "gui", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
963 :
964 : /* Read banks */
965 : /* TODO: SECURITY CRITICAL. GUI SHOULD NOT HAVE WRITE ACCESS TO BANKS, JUST HACKED IN FOR NOW SO RWLOCK WORKS */
966 0 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "gui", 0UL ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
967 :
968 : /* release ownership of banks */
969 : /**/ fd_topob_link( topo, "gui_replay", "gui", 128, 0UL,2UL ); /* burst==2 since a bank and its parent may be sent in one burst */
970 :
971 0 : /**/ fd_topob_tile_out( topo, "gui", 0UL, "gui_replay", 0UL );
972 0 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "gui_replay", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
973 :
974 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
975 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 */
976 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "repair_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
977 0 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "shred_out", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
978 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "gossip_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
979 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
980 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
981 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
982 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
983 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
984 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "pack_poh", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
985 0 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "pack_bank", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
986 0 : FOR(bank_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "bank_poh", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
987 0 : FOR(exec_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "exec_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
988 :
989 0 : if( FD_LIKELY( snapshots_enabled ) ) {
990 0 : /**/ fd_topob_tile_in ( topo, "gui", 0UL, "metric_in", "snapct_gui", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
991 0 : /**/ fd_topob_tile_in ( topo, "gui", 0UL, "metric_in", "snapin_gui", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
992 0 : }
993 0 : }
994 :
995 0 : ulong fec_set_cnt = shred_depth + config->tiles.shred.max_pending_shred_sets + 4UL;
996 0 : ulong fec_sets_sz = fec_set_cnt*sizeof(fd_shred34_t)*4; /* mirrors # of dcache entires in frankendancer */
997 0 : fd_topo_obj_t * fec_sets_obj = setup_topo_fec_sets( topo, "fec_sets", shred_tile_cnt*fec_sets_sz );
998 0 : for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
999 0 : fd_topo_tile_t * shred_tile = &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ];
1000 0 : fd_topob_tile_uses( topo, shred_tile, fec_sets_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1001 0 : }
1002 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "repair", 0UL ) ], fec_sets_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
1003 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, fec_sets_obj->id, "fec_sets" ) );
1004 :
1005 0 : fd_topo_obj_t * store_obj = setup_topo_store( topo, "store", config->firedancer.store.max_completed_shred_sets, (uint)shred_tile_cnt );
1006 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 );
1007 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1008 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, store_obj->id, "store" ) );
1009 :
1010 0 : fd_topo_obj_t * txncache_obj = setup_topo_txncache( topo, "txncache",
1011 0 : config->firedancer.runtime.max_live_slots,
1012 0 : fd_ulong_pow2_up( FD_PACK_MAX_TXNCACHE_TXN_PER_SLOT ) );
1013 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1014 0 : if( FD_LIKELY( snapshots_enabled ) ) {
1015 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1016 0 : }
1017 0 : FOR(bank_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "bank", i ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1018 0 : FOR(exec_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1019 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
1020 :
1021 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "genesi", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1022 0 : if( FD_LIKELY( snapshots_enabled ) ) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1023 :
1024 0 : if( FD_UNLIKELY( rpc_enabled ) ) {
1025 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "rpcsrv", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1026 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "rpcsrv", 0UL ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
1027 0 : }
1028 :
1029 0 : fd_pod_insert_int( topo->props, "sandbox", config->development.sandbox ? 1 : 0 );
1030 :
1031 0 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) fd_topo_configure_tile( &topo->tiles[ i ], config );
1032 :
1033 0 : FOR(net_tile_cnt) fd_topos_net_tile_finish( topo, i );
1034 0 : fd_topob_finish( topo, CALLBACKS );
1035 0 : config->topo = *topo;
1036 0 : }
1037 :
1038 : void
1039 : fd_topo_configure_tile( fd_topo_tile_t * tile,
1040 0 : fd_config_t * config ) {
1041 0 : if( FD_UNLIKELY( !strcmp( tile->name, "metric" ) ) ) {
1042 :
1043 0 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.metric.prometheus_listen_address, &tile->metric.prometheus_listen_addr ) ) )
1044 0 : FD_LOG_ERR(( "failed to parse prometheus listen address `%s`", config->tiles.metric.prometheus_listen_address ));
1045 0 : tile->metric.prometheus_listen_port = config->tiles.metric.prometheus_listen_port;
1046 :
1047 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "net" ) || !strcmp( tile->name, "sock" ) ) ) {
1048 :
1049 0 : tile->net.shred_listen_port = config->tiles.shred.shred_listen_port;
1050 0 : tile->net.quic_transaction_listen_port = config->tiles.quic.quic_transaction_listen_port;
1051 0 : tile->net.legacy_transaction_listen_port = config->tiles.quic.regular_transaction_listen_port;
1052 0 : tile->net.gossip_listen_port = config->gossip.port;
1053 0 : tile->net.repair_intake_listen_port = config->tiles.repair.repair_intake_listen_port;
1054 0 : tile->net.repair_serve_listen_port = config->tiles.repair.repair_serve_listen_port;
1055 0 : tile->net.send_src_port = config->tiles.send.send_src_port;
1056 :
1057 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "netlnk" ) ) ) {
1058 :
1059 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "ipecho") ) ) {
1060 :
1061 0 : tile->ipecho.expected_shred_version = config->consensus.expected_shred_version;
1062 0 : tile->ipecho.bind_address = config->net.ip_addr;
1063 0 : tile->ipecho.bind_port = config->gossip.port;
1064 0 : tile->ipecho.entrypoints_cnt = config->gossip.entrypoints_cnt;
1065 0 : fd_memcpy( tile->ipecho.entrypoints, config->gossip.resolved_entrypoints, tile->ipecho.entrypoints_cnt * sizeof(fd_ip4_port_t) );
1066 :
1067 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "genesi" ) ) ) {
1068 :
1069 0 : tile->genesi.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX );
1070 :
1071 0 : tile->genesi.allow_download = config->firedancer.snapshots.genesis_download;
1072 0 : strncpy( tile->genesi.genesis_path, config->paths.genesis, sizeof(tile->genesi.genesis_path) );
1073 0 : tile->genesi.expected_shred_version = config->consensus.expected_shred_version;
1074 0 : tile->genesi.entrypoints_cnt = config->gossip.entrypoints_cnt;
1075 0 : fd_memcpy( tile->genesi.entrypoints, config->gossip.resolved_entrypoints, tile->genesi.entrypoints_cnt * sizeof(fd_ip4_port_t) );
1076 :
1077 0 : tile->genesi.has_expected_genesis_hash = !!strcmp( config->consensus.expected_genesis_hash, "" );
1078 :
1079 0 : if( FD_UNLIKELY( strcmp( config->consensus.expected_genesis_hash, "" ) && !fd_base58_decode_32( config->consensus.expected_genesis_hash, tile->genesi.expected_genesis_hash ) ) ) {
1080 0 : FD_LOG_ERR(( "failed to decode [consensus.expected_genesis_hash] \"%s\" as base58", config->consensus.expected_genesis_hash ));
1081 0 : }
1082 :
1083 0 : tile->genesi.target_gid = config->gid;
1084 0 : tile->genesi.target_uid = config->uid;
1085 :
1086 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "gossvf") ) ) {
1087 :
1088 0 : strncpy( tile->gossvf.identity_key_path, config->paths.identity_key, sizeof(tile->gossvf.identity_key_path) );
1089 0 : tile->gossvf.tcache_depth = 1<<22UL; /* TODO: user defined option */
1090 0 : tile->gossvf.shred_version = 0U;
1091 0 : tile->gossvf.allow_private_address = config->development.gossip.allow_private_address;
1092 0 : tile->gossvf.boot_timestamp_nanos = config->boot_timestamp_nanos;
1093 :
1094 0 : tile->gossvf.entrypoints_cnt = config->gossip.entrypoints_cnt;
1095 0 : fd_memcpy( tile->gossvf.entrypoints, config->gossip.resolved_entrypoints, tile->gossvf.entrypoints_cnt * sizeof(fd_ip4_port_t) );
1096 :
1097 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "gossip" ) ) ) {
1098 :
1099 0 : if( FD_UNLIKELY( strcmp( config->firedancer.gossip.host, "" ) ) ) {
1100 0 : if( !resolve_address( config->firedancer.gossip.host, &tile->gossip.ip_addr ) )
1101 0 : FD_LOG_ERR(( "could not resolve [gossip.host] %s", config->firedancer.gossip.host ));
1102 0 : } else {
1103 0 : tile->gossip.ip_addr = config->net.ip_addr;
1104 0 : }
1105 0 : strncpy( tile->gossip.identity_key_path, config->paths.identity_key, sizeof(tile->gossip.identity_key_path) );
1106 0 : tile->gossip.shred_version = config->consensus.expected_shred_version;
1107 0 : tile->gossip.max_entries = config->tiles.gossip.max_entries;
1108 0 : tile->gossip.boot_timestamp_nanos = config->boot_timestamp_nanos;
1109 :
1110 0 : tile->gossip.ports.gossip = config->gossip.port;
1111 0 : tile->gossip.ports.tvu = config->tiles.shred.shred_listen_port;
1112 0 : tile->gossip.ports.tpu = config->tiles.quic.regular_transaction_listen_port;
1113 0 : tile->gossip.ports.tpu_quic = config->tiles.quic.quic_transaction_listen_port;
1114 0 : tile->gossip.ports.repair = config->tiles.repair.repair_intake_listen_port;
1115 :
1116 0 : tile->gossip.entrypoints_cnt = config->gossip.entrypoints_cnt;
1117 0 : fd_memcpy( tile->gossip.entrypoints, config->gossip.resolved_entrypoints, tile->gossip.entrypoints_cnt * sizeof(fd_ip4_port_t) );
1118 :
1119 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapct" ) ) ) {
1120 :
1121 0 : fd_memcpy( tile->snapct.snapshots_path, config->paths.snapshots, PATH_MAX );
1122 0 : tile->snapct.sources.max_local_full_effective_age = config->firedancer.snapshots.sources.max_local_full_effective_age;
1123 0 : tile->snapct.sources.max_local_incremental_age = config->firedancer.snapshots.sources.max_local_incremental_age;
1124 0 : tile->snapct.incremental_snapshots = config->firedancer.snapshots.incremental_snapshots;
1125 0 : tile->snapct.max_full_snapshots_to_keep = config->firedancer.snapshots.max_full_snapshots_to_keep;
1126 0 : tile->snapct.max_incremental_snapshots_to_keep = config->firedancer.snapshots.max_incremental_snapshots_to_keep;
1127 0 : tile->snapct.full_effective_age_cancel_threshold = config->firedancer.snapshots.full_effective_age_cancel_threshold;
1128 0 : tile->snapct.sources.gossip.allow_any = config->firedancer.snapshots.sources.gossip.allow_any;
1129 0 : tile->snapct.sources.gossip.allow_list_cnt = config->firedancer.snapshots.sources.gossip.allow_list_cnt;
1130 0 : tile->snapct.sources.gossip.block_list_cnt = config->firedancer.snapshots.sources.gossip.block_list_cnt;
1131 0 : tile->snapct.sources.servers_cnt = config->firedancer.snapshots.sources.servers_cnt;
1132 0 : for( ulong i=0UL; i<tile->snapct.sources.gossip.allow_list_cnt; i++ ) {
1133 0 : if( FD_UNLIKELY( !fd_base58_decode_32( config->firedancer.snapshots.sources.gossip.allow_list[ i ], tile->snapct.sources.gossip.allow_list[ i ].uc ) ) ) {
1134 0 : FD_LOG_ERR(( "[snapshots.sources.gossip.allow_list[%lu]] invalid (%s)", i, config->firedancer.snapshots.sources.gossip.allow_list[ i ] ));
1135 0 : }
1136 0 : }
1137 0 : for( ulong i=0UL; i<tile->snapct.sources.gossip.block_list_cnt; i++ ) {
1138 0 : if( FD_UNLIKELY( !fd_base58_decode_32( config->firedancer.snapshots.sources.gossip.block_list[ i ], tile->snapct.sources.gossip.block_list[ i ].uc ) ) ) {
1139 0 : FD_LOG_ERR(( "[snapshots.sources.gossip.block_list[%lu]] invalid (%s)", i, config->firedancer.snapshots.sources.gossip.block_list[ i ] ));
1140 0 : }
1141 0 : }
1142 :
1143 0 : ulong resolved_peers_cnt = 0UL;
1144 0 : for( ulong i=0UL; i<tile->snapct.sources.servers_cnt; i++ ) {
1145 0 : fd_ip4_port_t resolved_addrs[ FD_TOPO_MAX_RESOLVED_ADDRS ];
1146 0 : struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM };
1147 0 : int num_resolved = resolve_peer( config->firedancer.snapshots.sources.servers[ i ],
1148 0 : &hints,
1149 0 : "snapshots.sources.servers",
1150 0 : tile->snapct.sources.servers[ resolved_peers_cnt ].hostname,
1151 0 : resolved_addrs,
1152 0 : FD_TOPO_MAX_RESOLVED_ADDRS,
1153 0 : &tile->snapct.sources.servers[ resolved_peers_cnt ].is_https );
1154 0 : if( FD_UNLIKELY( 0==num_resolved ) ) {
1155 0 : FD_LOG_ERR(( "[snapshots.sources.servers[%lu]] invalid (%s)", i, config->firedancer.snapshots.sources.servers[ i ] ));
1156 0 : } else {
1157 0 : for( ulong i=0UL; i<(ulong)num_resolved; i++ ) tile->snapct.sources.servers[ resolved_peers_cnt+i ].addr = resolved_addrs[ i ];
1158 0 : for( ulong i=1UL; i<(ulong)num_resolved; i++ ) {
1159 0 : tile->snapct.sources.servers[ resolved_peers_cnt+i ].is_https = tile->snapct.sources.servers[ resolved_peers_cnt ].is_https;
1160 0 : fd_memcpy( tile->snapct.sources.servers[ resolved_peers_cnt+i ].hostname,
1161 0 : tile->snapct.sources.servers[ resolved_peers_cnt ].hostname,
1162 0 : sizeof(tile->snapct.sources.servers[ resolved_peers_cnt ].hostname) );
1163 0 : }
1164 0 : resolved_peers_cnt += (ulong)num_resolved;
1165 0 : }
1166 0 : }
1167 0 : tile->snapct.sources.servers_cnt = resolved_peers_cnt;
1168 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapld" ) ) ) {
1169 :
1170 0 : fd_memcpy( tile->snapld.snapshots_path, config->paths.snapshots, PATH_MAX );
1171 :
1172 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapdc" ) ) ) {
1173 :
1174 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapin" ) ) ) {
1175 :
1176 0 : tile->snapin.max_live_slots = config->firedancer.runtime.max_live_slots;
1177 0 : tile->snapin.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX );
1178 0 : tile->snapin.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX );
1179 :
1180 0 : tile->snapin.use_vinyl = !!config->firedancer.vinyl.enabled;
1181 0 : tile->snapin.lthash_disabled = !!config->development.snapshots.disable_lthash_verification;
1182 0 : if( tile->snapin.use_vinyl ) {
1183 0 : strcpy( tile->snapin.vinyl_path, config->paths.accounts );
1184 0 : tile->snapin.vinyl_meta_map_obj_id = fd_pod_query_ulong( config->topo.props, "vinyl.meta_map", ULONG_MAX );
1185 0 : tile->snapin.vinyl_meta_pool_obj_id = fd_pod_query_ulong( config->topo.props, "vinyl.meta_pool", ULONG_MAX );
1186 :
1187 0 : ulong in_wr_link_id = fd_topo_find_link( &config->topo, "snapin_wh", 0UL );
1188 0 : FD_TEST( in_wr_link_id!=ULONG_MAX );
1189 0 : fd_topo_link_t * in_wr_link = &config->topo.links[ in_wr_link_id ];
1190 0 : tile->snapin.snapwr_depth = in_wr_link->depth;
1191 0 : }
1192 :
1193 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapwh" ) ) ) {
1194 :
1195 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapwr" ) ) ) {
1196 :
1197 0 : strcpy( tile->snapwr.vinyl_path, config->paths.accounts );
1198 0 : ulong in_wr_link_id = fd_topo_find_link( &config->topo, "snapin_wh", 0UL );
1199 0 : FD_TEST( in_wr_link_id!=ULONG_MAX );
1200 0 : fd_topo_link_t * in_wr_link = &config->topo.links[ in_wr_link_id ];
1201 0 : tile->snapwr.dcache_obj_id = in_wr_link->dcache_obj_id;
1202 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapla" ) ) ) {
1203 :
1204 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapls" ) ) ) {
1205 :
1206 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "repair" ) ) ) {
1207 0 : tile->repair.max_pending_shred_sets = config->tiles.shred.max_pending_shred_sets;
1208 0 : tile->repair.repair_intake_listen_port = config->tiles.repair.repair_intake_listen_port;
1209 0 : tile->repair.repair_serve_listen_port = config->tiles.repair.repair_serve_listen_port;
1210 0 : tile->repair.slot_max = config->tiles.repair.slot_max;
1211 0 : tile->repair.repair_sign_cnt = config->firedancer.layout.sign_tile_count - 1; /* -1 because this excludes the keyguard client */
1212 0 : tile->repair.end_slot = 0;
1213 :
1214 0 : for( ulong i=0; i<tile->in_cnt; i++ ) {
1215 0 : if( !strcmp( config->topo.links[ tile->in_link_id[ i ] ].name, "sign_repair" ) ) {
1216 0 : tile->repair.repair_sign_depth = config->topo.links[ tile->in_link_id[ i ] ].depth;
1217 0 : break;
1218 0 : }
1219 0 : }
1220 0 : strncpy( tile->repair.identity_key_path, config->paths.identity_key, sizeof(tile->repair.identity_key_path) );
1221 :
1222 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "replay" ) )) {
1223 :
1224 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1225 0 : #define PARSE_PUBKEY( _tile, f ) \
1226 0 : if( FD_UNLIKELY( !fd_base58_decode_32( config->tiles.bundle.f, tile->_tile.bundle.f ) ) ) \
1227 0 : FD_LOG_ERR(( "[tiles.bundle.enabled] set to true, but failed to parse [tiles.bundle."#f"] %s", config->tiles.bundle.f ));
1228 0 : tile->replay.bundle.enabled = 1;
1229 0 : PARSE_PUBKEY( replay, tip_distribution_program_addr );
1230 0 : PARSE_PUBKEY( replay, tip_payment_program_addr );
1231 0 : strncpy( tile->replay.bundle.vote_account_path, config->paths.vote_account, sizeof(tile->replay.bundle.vote_account_path) );
1232 0 : } else {
1233 0 : fd_memset( &tile->replay.bundle, '\0', sizeof(tile->replay.bundle) );
1234 0 : }
1235 :
1236 0 : tile->replay.max_live_slots = config->firedancer.runtime.max_live_slots;
1237 0 : tile->replay.fec_max = config->tiles.shred.max_pending_shred_sets;
1238 0 : tile->replay.max_vote_accounts = config->firedancer.runtime.max_vote_accounts;
1239 :
1240 0 : tile->replay.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX ); FD_TEST( tile->replay.txncache_obj_id !=ULONG_MAX );
1241 0 : tile->replay.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX ); FD_TEST( tile->replay.funk_obj_id !=ULONG_MAX );
1242 0 : tile->replay.progcache_obj_id = fd_pod_query_ulong( config->topo.props, "progcache", ULONG_MAX ); FD_TEST( tile->replay.progcache_obj_id!=ULONG_MAX );
1243 :
1244 0 : tile->replay.max_live_slots = config->firedancer.runtime.max_live_slots;
1245 :
1246 0 : tile->replay.expected_shred_version = config->consensus.expected_shred_version;
1247 :
1248 0 : tile->replay.larger_max_cost_per_block = config->development.bench.larger_max_cost_per_block;
1249 :
1250 0 : strncpy( tile->replay.genesis_path, config->paths.genesis, sizeof(tile->replay.genesis_path) );
1251 :
1252 : /* not specified by [tiles.replay] */
1253 :
1254 0 : strncpy( tile->replay.identity_key_path, config->paths.identity_key, sizeof(tile->replay.identity_key_path) );
1255 0 : tile->replay.ip_addr = config->net.ip_addr;
1256 0 : strncpy( tile->replay.vote_account_path, config->paths.vote_account, sizeof(tile->replay.vote_account_path) );
1257 :
1258 0 : tile->replay.capture_start_slot = config->capture.capture_start_slot;
1259 0 : strncpy( tile->replay.solcap_capture, config->capture.solcap_capture, sizeof(tile->replay.solcap_capture) );
1260 0 : strncpy( tile->replay.dump_proto_dir, config->capture.dump_proto_dir, sizeof(tile->replay.dump_proto_dir) );
1261 0 : tile->replay.dump_block_to_pb = config->capture.dump_block_to_pb;
1262 :
1263 0 : FD_TEST( tile->replay.funk_obj_id == fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX ) );
1264 :
1265 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "exec" ) ) ) {
1266 :
1267 0 : tile->exec.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX ); FD_TEST( tile->exec.funk_obj_id !=ULONG_MAX );
1268 0 : tile->exec.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX ); FD_TEST( tile->exec.txncache_obj_id !=ULONG_MAX );
1269 0 : tile->exec.progcache_obj_id = fd_pod_query_ulong( config->topo.props, "progcache", ULONG_MAX ); FD_TEST( tile->exec.progcache_obj_id!=ULONG_MAX );
1270 :
1271 0 : tile->exec.max_live_slots = config->firedancer.runtime.max_live_slots;
1272 :
1273 0 : tile->exec.capture_start_slot = config->capture.capture_start_slot;
1274 0 : strncpy( tile->exec.solcap_capture, config->capture.solcap_capture, sizeof(tile->exec.solcap_capture) );
1275 0 : strncpy( tile->exec.dump_proto_dir, config->capture.dump_proto_dir, sizeof(tile->exec.dump_proto_dir) );
1276 0 : tile->exec.dump_instr_to_pb = config->capture.dump_instr_to_pb;
1277 0 : tile->exec.dump_txn_to_pb = config->capture.dump_txn_to_pb;
1278 0 : tile->exec.dump_syscall_to_pb = config->capture.dump_syscall_to_pb;
1279 0 : tile->exec.dump_elf_to_pb = config->capture.dump_elf_to_pb;
1280 :
1281 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "tower" ) ) ) {
1282 :
1283 0 : tile->tower.hard_fork_fatal = config->firedancer.development.hard_fork_fatal;
1284 0 : tile->tower.max_live_slots = config->firedancer.runtime.max_live_slots;
1285 0 : tile->tower.max_vote_lookahead = config->tiles.tower.max_vote_lookahead;
1286 0 : strncpy( tile->tower.identity_key, config->paths.identity_key, sizeof(tile->tower.identity_key) );
1287 0 : strncpy( tile->tower.vote_account, config->paths.vote_account, sizeof(tile->tower.vote_account) );
1288 0 : strncpy( tile->tower.base_path, config->paths.base, sizeof(tile->tower.base_path) );
1289 :
1290 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "send" ) ) ) {
1291 :
1292 0 : tile->send.send_src_port = config->tiles.send.send_src_port;
1293 0 : tile->send.ip_addr = config->net.ip_addr;
1294 0 : strncpy( tile->send.identity_key_path, config->paths.identity_key, sizeof(tile->send.identity_key_path) );
1295 :
1296 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "quic" ) ) ) {
1297 :
1298 0 : tile->quic.reasm_cnt = config->tiles.quic.txn_reassembly_count;
1299 0 : tile->quic.out_depth = config->tiles.verify.receive_buffer_size;
1300 0 : tile->quic.max_concurrent_connections = config->tiles.quic.max_concurrent_connections;
1301 0 : tile->quic.max_concurrent_handshakes = config->tiles.quic.max_concurrent_handshakes;
1302 0 : tile->quic.quic_transaction_listen_port = config->tiles.quic.quic_transaction_listen_port;
1303 0 : tile->quic.idle_timeout_millis = config->tiles.quic.idle_timeout_millis;
1304 0 : tile->quic.ack_delay_millis = config->tiles.quic.ack_delay_millis;
1305 0 : tile->quic.retry = config->tiles.quic.retry;
1306 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) ) );
1307 :
1308 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "verify" ) ) ) {
1309 :
1310 0 : tile->verify.tcache_depth = config->tiles.verify.signature_cache_size;
1311 :
1312 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "dedup" ) ) ) {
1313 :
1314 0 : tile->dedup.tcache_depth = config->tiles.dedup.signature_cache_size;
1315 :
1316 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "resolv" ) ) ) {
1317 :
1318 0 : tile->resolv.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX );
1319 :
1320 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "pack" ) ) ) {
1321 :
1322 0 : tile->pack.max_pending_transactions = config->tiles.pack.max_pending_transactions;
1323 0 : tile->pack.bank_tile_count = config->layout.bank_tile_count;
1324 0 : tile->pack.larger_max_cost_per_block = config->development.bench.larger_max_cost_per_block;
1325 0 : tile->pack.larger_shred_limits_per_block = config->development.bench.larger_shred_limits_per_block;
1326 0 : tile->pack.use_consumed_cus = config->tiles.pack.use_consumed_cus;
1327 0 : tile->pack.schedule_strategy = config->tiles.pack.schedule_strategy_enum;
1328 :
1329 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1330 :
1331 0 : tile->pack.bundle.enabled = 1;
1332 0 : PARSE_PUBKEY( pack, tip_distribution_program_addr );
1333 0 : PARSE_PUBKEY( pack, tip_payment_program_addr );
1334 0 : PARSE_PUBKEY( pack, tip_distribution_authority );
1335 0 : tile->pack.bundle.commission_bps = config->tiles.bundle.commission_bps;
1336 0 : strncpy( tile->pack.bundle.identity_key_path, config->paths.identity_key, sizeof(tile->pack.bundle.identity_key_path) );
1337 0 : strncpy( tile->pack.bundle.vote_account_path, config->paths.vote_account, sizeof(tile->pack.bundle.vote_account_path) );
1338 0 : } else {
1339 0 : fd_memset( &tile->pack.bundle, '\0', sizeof(tile->pack.bundle) );
1340 0 : }
1341 :
1342 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "bank" ) ) ) {
1343 0 : tile->bank.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX );
1344 0 : tile->bank.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX );
1345 0 : tile->bank.progcache_obj_id = fd_pod_query_ulong( config->topo.props, "progcache", ULONG_MAX );
1346 :
1347 0 : tile->bank.max_live_slots = config->firedancer.runtime.max_live_slots;
1348 :
1349 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "poh" ) ) ) {
1350 0 : strncpy( tile->poh.identity_key_path, config->paths.identity_key, sizeof(tile->poh.identity_key_path) );
1351 :
1352 0 : tile->poh.plugins_enabled = 0;
1353 0 : tile->poh.bank_cnt = config->layout.bank_tile_count;
1354 0 : tile->poh.lagged_consecutive_leader_start = config->tiles.poh.lagged_consecutive_leader_start;
1355 :
1356 0 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1357 0 : tile->poh.bundle.enabled = 1;
1358 0 : PARSE_PUBKEY( poh, tip_distribution_program_addr );
1359 0 : PARSE_PUBKEY( poh, tip_payment_program_addr );
1360 0 : strncpy( tile->poh.bundle.vote_account_path, config->paths.vote_account, sizeof(tile->poh.bundle.vote_account_path) );
1361 0 : #undef PARSE_PUBKEY
1362 0 : } else {
1363 0 : fd_memset( &tile->poh.bundle, '\0', sizeof(tile->poh.bundle) );
1364 0 : }
1365 :
1366 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "shred" ) ) ) {
1367 :
1368 0 : strncpy( tile->shred.identity_key_path, config->paths.identity_key, sizeof(tile->shred.identity_key_path) );
1369 :
1370 0 : tile->shred.depth = config->topo.links[ tile->out_link_id[ 0 ] ].depth;
1371 0 : tile->shred.fec_resolver_depth = config->tiles.shred.max_pending_shred_sets;
1372 0 : tile->shred.expected_shred_version = config->consensus.expected_shred_version;
1373 0 : tile->shred.shred_listen_port = config->tiles.shred.shred_listen_port;
1374 0 : tile->shred.larger_shred_limits_per_block = config->development.bench.larger_shred_limits_per_block;
1375 0 : for( ulong i=0UL; i<config->tiles.shred.additional_shred_destinations_retransmit_cnt; i++ ) {
1376 0 : parse_ip_port( "tiles.shred.additional_shred_destinations_retransmit",
1377 0 : config->tiles.shred.additional_shred_destinations_retransmit[ i ],
1378 0 : &tile->shred.adtl_dests_retransmit[ i ] );
1379 0 : }
1380 0 : tile->shred.adtl_dests_retransmit_cnt = config->tiles.shred.additional_shred_destinations_retransmit_cnt;
1381 0 : for( ulong i=0UL; i<config->tiles.shred.additional_shred_destinations_leader_cnt; i++ ) {
1382 0 : parse_ip_port( "tiles.shred.additional_shred_destinations_leader",
1383 0 : config->tiles.shred.additional_shred_destinations_leader[ i ],
1384 0 : &tile->shred.adtl_dests_leader[ i ] );
1385 0 : }
1386 0 : tile->shred.adtl_dests_leader_cnt = config->tiles.shred.additional_shred_destinations_leader_cnt;
1387 :
1388 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "sign" ) ) ) {
1389 :
1390 0 : strncpy( tile->sign.identity_key_path, config->paths.identity_key, sizeof(tile->sign.identity_key_path) );
1391 :
1392 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "plugin" ) ) ) {
1393 :
1394 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "cswtch" ) ) ) {
1395 :
1396 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "gui" ) ) ) {
1397 :
1398 0 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.gui.gui_listen_address, &tile->gui.listen_addr ) ) )
1399 0 : FD_LOG_ERR(( "failed to parse gui listen address `%s`", config->tiles.gui.gui_listen_address ));
1400 0 : tile->gui.listen_port = config->tiles.gui.gui_listen_port;
1401 0 : tile->gui.is_voting = strcmp( config->paths.vote_account, "" );
1402 0 : strncpy( tile->gui.cluster, config->cluster, sizeof(tile->gui.cluster) );
1403 0 : strncpy( tile->gui.identity_key_path, config->paths.identity_key, sizeof(tile->gui.identity_key_path) );
1404 0 : strncpy( tile->gui.vote_key_path, config->paths.vote_account, sizeof(tile->gui.vote_key_path) );
1405 0 : tile->gui.max_http_connections = config->tiles.gui.max_http_connections;
1406 0 : tile->gui.max_websocket_connections = config->tiles.gui.max_websocket_connections;
1407 0 : tile->gui.max_http_request_length = config->tiles.gui.max_http_request_length;
1408 0 : tile->gui.send_buffer_size_mb = config->tiles.gui.send_buffer_size_mb;
1409 0 : tile->gui.schedule_strategy = config->tiles.pack.schedule_strategy_enum;
1410 0 : tile->gui.websocket_compression = 1;
1411 0 : tile->gui.frontend_release_channel = config->development.gui.frontend_release_channel_enum;
1412 :
1413 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "rpc" ) ) ) {
1414 :
1415 0 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.rpc.rpc_listen_address, &tile->rpc.listen_addr ) ) )
1416 0 : FD_LOG_ERR(( "failed to parse rpc listen address `%s`", config->tiles.rpc.rpc_listen_address ));
1417 0 : tile->rpc.listen_port = config->tiles.rpc.rpc_listen_port;
1418 0 : tile->rpc.max_http_connections = config->tiles.rpc.max_http_connections;
1419 0 : tile->rpc.max_http_request_length = config->tiles.rpc.max_http_request_length;
1420 0 : tile->rpc.send_buffer_size_mb = config->tiles.rpc.send_buffer_size_mb;
1421 :
1422 0 : tile->rpc.max_live_slots = config->firedancer.runtime.max_live_slots;
1423 :
1424 0 : strncpy( tile->rpc.identity_key_path, config->paths.identity_key, sizeof(tile->rpc.identity_key_path) );
1425 :
1426 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "arch_f" ) ||
1427 0 : !strcmp( tile->name, "arch_w" ) ) ) {
1428 :
1429 0 : strncpy( tile->archiver.rocksdb_path, config->tiles.archiver.rocksdb_path, sizeof(tile->archiver.rocksdb_path) );
1430 :
1431 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "backt" ) ) ) {
1432 :
1433 0 : tile->backtest.end_slot = config->tiles.archiver.end_slot;
1434 :
1435 : /* Validate arguments based on the ingest mode */
1436 0 : if( !strcmp( config->tiles.archiver.ingest_mode, "rocksdb" ) ) {
1437 0 : strncpy( tile->backtest.rocksdb_path, config->tiles.archiver.rocksdb_path, PATH_MAX );
1438 0 : if( FD_UNLIKELY( 0==strlen( tile->backtest.rocksdb_path ) ) ) {
1439 0 : FD_LOG_ERR(( "`archiver.rocksdb_path` not specified in toml" ));
1440 0 : }
1441 0 : } else if( !strcmp( config->tiles.archiver.ingest_mode, "shredcap" ) ) {
1442 0 : strncpy( tile->backtest.shredcap_path, config->tiles.archiver.shredcap_path, PATH_MAX );
1443 0 : if( FD_UNLIKELY( 0==strlen( tile->backtest.shredcap_path ) ) ) {
1444 0 : FD_LOG_ERR(( "`archiver.shredcap_path` not specified in toml" ));
1445 0 : }
1446 0 : } else {
1447 0 : FD_LOG_ERR(( "Invalid ingest mode: %s", config->tiles.archiver.ingest_mode ));
1448 0 : }
1449 :
1450 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "scap" ) ) ) {
1451 :
1452 0 : tile->shredcap.repair_intake_listen_port = config->tiles.repair.repair_intake_listen_port;
1453 0 : strncpy( tile->shredcap.folder_path, config->tiles.shredcap.folder_path, sizeof(tile->shredcap.folder_path) );
1454 0 : tile->shredcap.write_buffer_size = config->tiles.shredcap.write_buffer_size;
1455 0 : tile->shredcap.enable_publish_stake_weights = 0; /* this is not part of the config */
1456 0 : strncpy( tile->shredcap.manifest_path, "", PATH_MAX ); /* this is not part of the config */
1457 :
1458 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "bundle" ) ) ) {
1459 0 : strncpy( tile->bundle.url, config->tiles.bundle.url, sizeof(tile->bundle.url) );
1460 0 : tile->bundle.url_len = strnlen( tile->bundle.url, 255 );
1461 0 : strncpy( tile->bundle.sni, config->tiles.bundle.tls_domain_name, 256 );
1462 0 : tile->bundle.sni_len = strnlen( tile->bundle.sni, 255 );
1463 0 : strncpy( tile->bundle.identity_key_path, config->paths.identity_key, sizeof(tile->bundle.identity_key_path) );
1464 0 : strncpy( tile->bundle.key_log_path, config->development.bundle.ssl_key_log_file, sizeof(tile->bundle.key_log_path) );
1465 0 : tile->bundle.buf_sz = config->development.bundle.buffer_size_kib<<10;
1466 0 : tile->bundle.ssl_heap_sz = config->development.bundle.ssl_heap_size_mib<<20;
1467 0 : tile->bundle.keepalive_interval_nanos = config->tiles.bundle.keepalive_interval_millis * (ulong)1e6;
1468 0 : tile->bundle.tls_cert_verify = !!config->tiles.bundle.tls_cert_verify;
1469 :
1470 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "vinyl" ) ) ) {
1471 :
1472 0 : tile->vinyl.vinyl_meta_map_obj_id = fd_pod_query_ulong( config->topo.props, "vinyl.meta_map", ULONG_MAX );
1473 0 : tile->vinyl.vinyl_meta_pool_obj_id = fd_pod_query_ulong( config->topo.props, "vinyl.meta_pool", ULONG_MAX );
1474 0 : tile->vinyl.vinyl_line_max = config->firedancer.vinyl.max_cache_entries;
1475 0 : tile->vinyl.vinyl_cnc_obj_id = fd_pod_query_ulong( config->topo.props, "vinyl.cnc", ULONG_MAX );
1476 0 : tile->vinyl.vinyl_data_obj_id = fd_pod_query_ulong( config->topo.props, "vinyl.data", ULONG_MAX );
1477 0 : fd_cstr_ncpy( tile->vinyl.vinyl_bstream_path, config->paths.accounts, sizeof(tile->vinyl.vinyl_bstream_path) );
1478 :
1479 0 : tile->vinyl.io_type = config->firedancer.vinyl.io_uring.enabled ?
1480 0 : FD_VINYL_IO_TYPE_UR : FD_VINYL_IO_TYPE_BD;
1481 0 : tile->vinyl.uring_depth = config->firedancer.vinyl.io_uring.queue_depth;
1482 :
1483 0 : } else {
1484 0 : FD_LOG_ERR(( "unknown tile name `%s`", tile->name ));
1485 0 : }
1486 0 : }
|