Line data Source code
1 : #include "topology.h"
2 :
3 : #include "../../ballet/lthash/fd_lthash.h"
4 : #include "../../discof/reasm/fd_reasm.h"
5 : #include "../../discof/poh/fd_poh.h"
6 : #include "../../discof/replay/fd_exec.h"
7 : #include "../../discof/gossip/fd_gossip_tile.h"
8 : #include "../../discof/tower/fd_tower_tile.h"
9 : #include "../../discof/resolv/fd_resolv_tile.h"
10 : #include "../../discof/repair/fd_repair.h"
11 : #include "../../discof/replay/fd_replay_tile.h"
12 : #include "../../disco/net/fd_net_tile.h"
13 : #include "../../discof/restore/fd_snaprd_tile.h"
14 : #include "../../disco/quic/fd_tpu.h"
15 : #include "../../disco/pack/fd_pack_cost.h"
16 : #include "../../disco/tiles.h"
17 : #include "../../disco/topo/fd_topob.h"
18 : #include "../../disco/topo/fd_cpu_topo.h"
19 : #include "../../util/pod/fd_pod_format.h"
20 : #include "../../util/tile/fd_tile_private.h"
21 : #include "../../discof/restore/utils/fd_ssmsg.h"
22 : #include "../../flamenco/gossip/fd_gossip.h"
23 : #include "../../flamenco/runtime/context/fd_capture_ctx.h"
24 : #include "../../funk/fd_funk.h" /* funk_footprint() */
25 :
26 : #include <sys/random.h>
27 : #include <sys/types.h>
28 : #include <sys/socket.h>
29 : #include <netdb.h>
30 :
31 : extern fd_topo_obj_callbacks_t * CALLBACKS[];
32 :
33 : static void
34 0 : parse_ip_port( const char * name, const char * ip_port, fd_topo_ip_port_t *parsed_ip_port) {
35 0 : char buf[ sizeof( "255.255.255.255:65536" ) ];
36 0 : memcpy( buf, ip_port, sizeof( buf ) );
37 0 : char *ip_end = strchr( buf, ':' );
38 0 : if( FD_UNLIKELY( !ip_end ) )
39 0 : FD_LOG_ERR(( "[%s] must in the form ip:port", name ));
40 0 : *ip_end = '\0';
41 :
42 0 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( buf, &( parsed_ip_port->ip ) ) ) ) {
43 0 : FD_LOG_ERR(( "could not parse IP %s in [%s]", buf, name ));
44 0 : }
45 :
46 0 : parsed_ip_port->port = fd_cstr_to_ushort( ip_end+1 );
47 0 : if( FD_UNLIKELY( !parsed_ip_port->port ) )
48 0 : FD_LOG_ERR(( "could not parse port %s in [%s]", ip_end+1, name ));
49 0 : }
50 :
51 : fd_topo_obj_t *
52 3 : setup_topo_bank_hash_cmp( fd_topo_t * topo, char const * wksp_name ) {
53 3 : fd_topo_obj_t * obj = fd_topob_obj( topo, "bh_cmp", wksp_name );
54 3 : return obj;
55 3 : }
56 :
57 : fd_topo_obj_t *
58 : setup_topo_banks( fd_topo_t * topo,
59 : char const * wksp_name,
60 : ulong max_live_slots,
61 3 : ulong max_fork_width ) {
62 3 : fd_topo_obj_t * obj = fd_topob_obj( topo, "banks", wksp_name );
63 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_live_slots, "obj.%lu.max_live_slots", obj->id ) );
64 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_fork_width, "obj.%lu.max_fork_width", obj->id ) );
65 3 : return obj;
66 3 : }
67 :
68 : static fd_topo_obj_t *
69 3 : setup_topo_fec_sets( fd_topo_t * topo, char const * wksp_name, ulong sz ) {
70 3 : fd_topo_obj_t * obj = fd_topob_obj( topo, "fec_sets", wksp_name );
71 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, sz, "obj.%lu.sz", obj->id ) );
72 3 : return obj;
73 3 : }
74 :
75 : fd_topo_obj_t *
76 : setup_topo_funk( fd_topo_t * topo,
77 : char const * wksp_name,
78 : ulong max_account_records,
79 : ulong max_database_transactions,
80 : ulong heap_size_gib,
81 3 : int lock_pages ) {
82 3 : fd_topo_obj_t * obj = fd_topob_obj( topo, "funk", wksp_name );
83 3 : FD_TEST( fd_pod_insert_ulong( topo->props, "funk", obj->id ) );
84 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_account_records, "obj.%lu.rec_max", obj->id ) );
85 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_database_transactions, "obj.%lu.txn_max", obj->id ) );
86 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, heap_size_gib*(1UL<<30), "obj.%lu.heap_max", obj->id ) );
87 3 : ulong funk_footprint = fd_funk_footprint( max_database_transactions, max_account_records );
88 3 : if( FD_UNLIKELY( !funk_footprint ) ) FD_LOG_ERR(( "Invalid [funk] parameters" ));
89 :
90 : /* Increase workspace partition count */
91 3 : ulong wksp_idx = fd_topo_find_wksp( topo, wksp_name );
92 3 : FD_TEST( wksp_idx!=ULONG_MAX );
93 3 : fd_topo_wksp_t * wksp = &topo->workspaces[ wksp_idx ];
94 3 : ulong part_max = fd_wksp_part_max_est( funk_footprint+(heap_size_gib*(1UL<<30)), 1U<<14U );
95 3 : if( FD_UNLIKELY( !part_max ) ) FD_LOG_ERR(( "fd_wksp_part_max_est(%lu,16KiB) failed", funk_footprint ));
96 3 : wksp->part_max += part_max;
97 3 : wksp->is_locked = lock_pages;
98 :
99 3 : return obj;
100 3 : }
101 :
102 : fd_topo_obj_t *
103 : setup_topo_store( fd_topo_t * topo,
104 : char const * wksp_name,
105 : ulong fec_max,
106 3 : uint part_cnt ) {
107 3 : fd_topo_obj_t * obj = fd_topob_obj( topo, "store", wksp_name );
108 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, fec_max, "obj.%lu.fec_max", obj->id ) );
109 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, part_cnt, "obj.%lu.part_cnt", obj->id ) );
110 3 : return obj;
111 3 : }
112 :
113 : fd_topo_obj_t *
114 : setup_topo_txncache( fd_topo_t * topo,
115 : char const * wksp_name,
116 : ulong max_live_slots,
117 3 : ulong max_txn_per_slot ) {
118 3 : fd_topo_obj_t * obj = fd_topob_obj( topo, "txncache", wksp_name );
119 :
120 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_live_slots, "obj.%lu.max_live_slots", obj->id ) );
121 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, max_txn_per_slot, "obj.%lu.max_txn_per_slot", obj->id ) );
122 :
123 3 : return obj;
124 3 : }
125 :
126 : static int
127 : resolve_address( char const * address,
128 0 : uint * ip_addr ) {
129 0 : struct addrinfo hints = { .ai_family = AF_INET };
130 0 : struct addrinfo * res;
131 0 : int err = getaddrinfo( address, NULL, &hints, &res );
132 0 : if( FD_UNLIKELY( err ) ) {
133 0 : FD_LOG_WARNING(( "cannot resolve address \"%s\": %i-%s", address, err, gai_strerror( err ) ));
134 0 : return 0;
135 0 : }
136 :
137 0 : int resolved = 0;
138 0 : for( struct addrinfo * cur=res; cur; cur=cur->ai_next ) {
139 0 : if( FD_UNLIKELY( cur->ai_addr->sa_family!=AF_INET ) ) continue;
140 0 : struct sockaddr_in const * addr = (struct sockaddr_in const *)cur->ai_addr;
141 0 : *ip_addr = addr->sin_addr.s_addr;
142 0 : resolved = 1;
143 0 : break;
144 0 : }
145 :
146 0 : freeaddrinfo( res );
147 0 : return resolved;
148 0 : }
149 :
150 : static int
151 : resolve_peer( char const * peer,
152 0 : fd_ip4_port_t * ip4_port ) {
153 :
154 : /* Split host:port */
155 0 : char const * host_port = peer;
156 0 : if( FD_LIKELY( strncmp( peer, "http://", 7UL )==0 ) ) {
157 0 : host_port += 7UL;
158 0 : } else if( FD_LIKELY( strncmp( peer, "https://", 8UL )==0 ) ) {
159 0 : host_port += 8UL;
160 0 : }
161 :
162 0 : char const * colon = strrchr( host_port, ':' );
163 0 : if( FD_UNLIKELY( !colon ) ) {
164 0 : FD_LOG_ERR(( "invalid [gossip.entrypoints] entry \"%s\": no port number", host_port ));
165 0 : }
166 :
167 0 : char fqdn[ 255 ];
168 0 : ulong fqdn_len = (ulong)( colon-host_port );
169 0 : if( FD_UNLIKELY( fqdn_len>254 ) ) {
170 0 : FD_LOG_ERR(( "invalid [gossip.entrypoints] entry \"%s\": hostname too long", host_port ));
171 0 : }
172 0 : fd_memcpy( fqdn, host_port, fqdn_len );
173 0 : fqdn[ fqdn_len ] = '\0';
174 :
175 : /* Parse port number */
176 :
177 0 : char const * port_str = colon+1;
178 0 : char const * endptr = NULL;
179 0 : ulong port = strtoul( port_str, (char **)&endptr, 10 );
180 0 : if( FD_UNLIKELY( !endptr || !port || port>USHORT_MAX || *endptr!='\0' ) ) {
181 0 : FD_LOG_ERR(( "invalid [gossip.entrypoints] entry \"%s\": invalid port number", host_port ));
182 0 : }
183 0 : ip4_port->port = (ushort)fd_ushort_bswap( (ushort)port );
184 :
185 : /* Resolve hostname */
186 0 : int resolved = resolve_address( fqdn, &ip4_port->addr );
187 0 : return resolved;
188 0 : }
189 :
190 : static void
191 3 : resolve_gossip_entrypoints( config_t * config ) {
192 3 : ulong entrypoint_cnt = config->gossip.entrypoints_cnt;
193 3 : for( ulong i=0UL; i<entrypoint_cnt; i++ ) {
194 0 : if( FD_UNLIKELY( 0==resolve_peer( config->gossip.entrypoints[ i ], &config->gossip.resolved_entrypoints[ i ] ) ) ) {
195 0 : FD_LOG_ERR(( "failed to resolve address of [gossip.entrypoints] entry \"%s\"", config->gossip.entrypoints[ i ] ));
196 0 : }
197 0 : }
198 3 : }
199 :
200 : void
201 3 : fd_topo_initialize( config_t * config ) {
202 : /* TODO: Not here ... */
203 3 : resolve_gossip_entrypoints( config );
204 :
205 3 : ulong net_tile_cnt = config->layout.net_tile_count;
206 3 : ulong shred_tile_cnt = config->layout.shred_tile_count;
207 3 : ulong quic_tile_cnt = config->layout.quic_tile_count;
208 3 : ulong verify_tile_cnt = config->layout.verify_tile_count;
209 3 : ulong resolv_tile_cnt = config->layout.resolv_tile_count;
210 3 : ulong bank_tile_cnt = config->layout.bank_tile_count;
211 :
212 3 : ulong gossvf_tile_cnt = config->firedancer.layout.gossvf_tile_count;
213 3 : ulong exec_tile_cnt = config->firedancer.layout.exec_tile_count;
214 3 : ulong sign_tile_cnt = config->firedancer.layout.sign_tile_count;
215 :
216 3 : int snapshots_enabled = !!config->gossip.entrypoints_cnt;
217 :
218 3 : fd_topo_t * topo = fd_topob_new( &config->topo, config->name );
219 :
220 3 : topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
221 3 : topo->gigantic_page_threshold = config->hugetlbfs.gigantic_page_threshold_mib << 20;
222 :
223 : /* topo, name */
224 3 : fd_topob_wksp( topo, "metric" );
225 3 : fd_topob_wksp( topo, "genesi" );
226 3 : fd_topob_wksp( topo, "ipecho" );
227 3 : fd_topob_wksp( topo, "gossvf" );
228 3 : fd_topob_wksp( topo, "gossip" );
229 3 : fd_topob_wksp( topo, "shred" );
230 3 : fd_topob_wksp( topo, "repair" );
231 3 : fd_topob_wksp( topo, "replay" );
232 3 : fd_topob_wksp( topo, "exec" );
233 3 : fd_topob_wksp( topo, "tower" );
234 3 : fd_topob_wksp( topo, "send" );
235 :
236 3 : fd_topob_wksp( topo, "quic" );
237 3 : fd_topob_wksp( topo, "verify" );
238 3 : fd_topob_wksp( topo, "dedup" );
239 3 : fd_topob_wksp( topo, "resolv" );
240 3 : fd_topob_wksp( topo, "pack" );
241 3 : fd_topob_wksp( topo, "bank" );
242 3 : fd_topob_wksp( topo, "poh" );
243 3 : fd_topob_wksp( topo, "sign" );
244 :
245 3 : fd_topob_wksp( topo, "metric_in" );
246 :
247 3 : fd_topob_wksp( topo, "net_gossip" );
248 3 : fd_topob_wksp( topo, "net_shred" );
249 3 : fd_topob_wksp( topo, "net_repair" );
250 3 : fd_topob_wksp( topo, "net_send" );
251 3 : fd_topob_wksp( topo, "net_quic" );
252 :
253 3 : fd_topob_wksp( topo, "genesi_out" );
254 3 : fd_topob_wksp( topo, "ipecho_out" );
255 3 : fd_topob_wksp( topo, "gossvf_gossi" );
256 3 : fd_topob_wksp( topo, "gossip_gossv" );
257 3 : fd_topob_wksp( topo, "gossip_out" );
258 :
259 3 : fd_topob_wksp( topo, "shred_out" );
260 3 : fd_topob_wksp( topo, "replay_stake" );
261 3 : fd_topob_wksp( topo, "replay_exec" );
262 3 : fd_topob_wksp( topo, "replay_out" );
263 3 : fd_topob_wksp( topo, "tower_out" );
264 3 : fd_topob_wksp( topo, "send_txns" ); /* TODO: Badly named. Rename to indicate tiles */
265 :
266 3 : fd_topob_wksp( topo, "quic_verify" );
267 3 : fd_topob_wksp( topo, "verify_dedup" );
268 3 : fd_topob_wksp( topo, "dedup_resolv" );
269 3 : fd_topob_wksp( topo, "resolv_pack" );
270 3 : fd_topob_wksp( topo, "pack_poh" );
271 3 : fd_topob_wksp( topo, "pack_bank" );
272 3 : fd_topob_wksp( topo, "resolv_repla" );
273 3 : fd_topob_wksp( topo, "bank_pack" );
274 3 : fd_topob_wksp( topo, "bank_poh" );
275 3 : fd_topob_wksp( topo, "bank_busy" );
276 3 : fd_topob_wksp( topo, "poh_shred" );
277 3 : fd_topob_wksp( topo, "poh_replay" );
278 :
279 : /* TODO: WTF are these for? */
280 3 : fd_topob_wksp( topo, "funk" );
281 3 : fd_topob_wksp( topo, "bh_cmp" );
282 3 : fd_topob_wksp( topo, "fec_sets" );
283 3 : fd_topob_wksp( topo, "txncache" );
284 3 : fd_topob_wksp( topo, "exec_spad" );
285 3 : fd_topob_wksp( topo, "banks" );
286 3 : fd_topob_wksp( topo, "store" );
287 3 : fd_topob_wksp( topo, "executed_txn" );
288 :
289 3 : fd_topob_wksp( topo, "gossip_sign" );
290 3 : fd_topob_wksp( topo, "sign_gossip" );
291 :
292 3 : fd_topob_wksp( topo, "shred_sign" );
293 3 : fd_topob_wksp( topo, "sign_shred" );
294 :
295 3 : fd_topob_wksp( topo, "repair_sign" );
296 3 : fd_topob_wksp( topo, "sign_repair" );
297 :
298 3 : fd_topob_wksp( topo, "send_sign" );
299 3 : fd_topob_wksp( topo, "sign_send" );
300 :
301 3 : if( FD_LIKELY( snapshots_enabled ) ) {
302 0 : fd_topob_wksp( topo, "snapdc" );
303 0 : fd_topob_wksp( topo, "snaprd" );
304 0 : fd_topob_wksp( topo, "snapin" );
305 :
306 0 : fd_topob_wksp( topo, "snapdc_rd" );
307 0 : fd_topob_wksp( topo, "snapin_rd" );
308 0 : fd_topob_wksp( topo, "snap_stream" ); /* TODO: Rename ... */
309 0 : fd_topob_wksp( topo, "snap_zstd" ); /* TODO: Rename ... */
310 0 : fd_topob_wksp( topo, "snap_out" ); /* TODO: Rename ... */
311 0 : fd_topob_wksp( topo, "snaprd_rp" );
312 0 : }
313 :
314 816 : #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
315 :
316 : /* TODO: Explain this .... USHORT_MAX is not dcache max */
317 3 : ulong pending_fec_shreds_depth = fd_ulong_min( fd_ulong_pow2_up( config->tiles.shred.max_pending_shred_sets * FD_REEDSOL_DATA_SHREDS_MAX ), USHORT_MAX + 1 /* dcache max */ );
318 :
319 : /* topo, link_name, wksp_name, depth, mtu, burst */
320 3 : /**/ fd_topob_link( topo, "gossip_net", "net_gossip", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
321 3 : FOR(shred_tile_cnt) fd_topob_link( topo, "shred_net", "net_shred", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
322 3 : /**/ fd_topob_link( topo, "repair_net", "net_repair", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
323 3 : /**/ fd_topob_link( topo, "send_net", "net_send", config->net.ingress_buffer_size, FD_NET_MTU, 2UL ); /* TODO: 2 is probably not correct, should be 1 */
324 3 : FOR(quic_tile_cnt) fd_topob_link( topo, "quic_net", "net_quic", config->net.ingress_buffer_size, FD_NET_MTU, 1UL );
325 :
326 3 : if( FD_LIKELY( snapshots_enabled ) ) {
327 0 : /**/ fd_topob_link( topo, "snap_zstd", "snap_zstd", 8192UL, 16384UL, 1UL ); /* TODO: Rename */
328 0 : /**/ fd_topob_link( topo, "snap_stream", "snap_stream", 2048UL, USHORT_MAX, 1UL ); /* TODO: Rename */
329 0 : /**/ fd_topob_link( topo, "snap_out", "snap_out", 2UL, sizeof(fd_snapshot_manifest_t), 1UL ); /* TODO: Rename */
330 0 : /**/ fd_topob_link( topo, "snaprd_rp", "snaprd_rp", 128UL, 0UL, 1UL )->permit_no_consumers = 1; /* TODO: wire in repair later */
331 0 : /**/ fd_topob_link( topo, "snapdc_rd", "snapdc_rd", 128UL, 0UL, 1UL );
332 0 : /**/ fd_topob_link( topo, "snapin_rd", "snapin_rd", 128UL, 0UL, 1UL );
333 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) /* the gui, which is optional, is the only consumer of snaprd_out */
334 0 : fd_topob_link( topo, "snaprd_out", "snaprd", 128UL, sizeof(fd_snaprd_update_t), 1UL );
335 0 : }
336 :
337 : /**/ fd_topob_link( topo, "genesi_out", "genesi_out", 2UL, 10UL*1024UL*1024UL+32UL+sizeof(fd_lthash_value_t), 1UL );
338 3 : /**/ fd_topob_link( topo, "ipecho_out", "ipecho_out", 2UL, 0UL, 1UL );
339 3 : 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 );
340 3 : /**/ 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 */
341 3 : /**/ 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 */
342 :
343 3 : 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 );
344 18 : FOR(verify_tile_cnt) fd_topob_link( topo, "verify_dedup", "verify_dedup", config->tiles.verify.receive_buffer_size, FD_TPU_PARSED_MTU, 1UL );
345 3 : /**/ fd_topob_link( topo, "dedup_resolv", "dedup_resolv", 65536UL, FD_TPU_PARSED_MTU, 1UL );
346 3 : FOR(resolv_tile_cnt) fd_topob_link( topo, "resolv_pack", "resolv_pack", 65536UL, FD_TPU_RESOLVED_MTU, 1UL );
347 3 : /**/ fd_topob_link( topo, "replay_stake", "replay_stake", 128UL, FD_STAKE_OUT_MTU, 1UL ); /* TODO: This should be 2 but requires fixing STEM_BURST */
348 3 : /**/ fd_topob_link( topo, "replay_out", "replay_out", 8192UL, sizeof(fd_replay_message_t), 1UL );
349 3 : /**/ fd_topob_link( topo, "pack_poh", "pack_poh", 128UL, sizeof(fd_done_packing_t), 1UL );
350 : /* pack_bank is shared across all banks, so if one bank stalls due to complex transactions, the buffer neeeds to be large so that
351 : other banks can keep proceeding. */
352 3 : /**/ fd_topob_link( topo, "pack_bank", "pack_bank", 65536UL, USHORT_MAX, 1UL );
353 3 : FOR(bank_tile_cnt) fd_topob_link( topo, "bank_poh", "bank_poh", 16384UL, USHORT_MAX, 1UL );
354 3 : FOR(bank_tile_cnt) fd_topob_link( topo, "bank_pack", "bank_pack", 16384UL, USHORT_MAX, 1UL );
355 3 : /**/ fd_topob_link( topo, "poh_shred", "poh_shred", 16384UL, USHORT_MAX, 1UL );
356 3 : /**/ fd_topob_link( topo, "poh_replay", "poh_replay", 128UL, sizeof(fd_poh_leader_slot_ended_t), 1UL ); /* TODO: Depth probably doesn't need to be 128 */
357 3 : FOR(resolv_tile_cnt) fd_topob_link( topo, "resolv_repla", "resolv_repla", 128UL, sizeof(fd_resolv_slot_exchanged_t), 1UL );
358 3 : /**/ fd_topob_link( topo, "executed_txn", "executed_txn", 16384UL, 64UL, 1UL ); /* TODO: Rename this ... */
359 :
360 3 : FOR(shred_tile_cnt) fd_topob_link( topo, "shred_sign", "shred_sign", 128UL, 32UL, 1UL );
361 3 : FOR(shred_tile_cnt) fd_topob_link( topo, "sign_shred", "sign_shred", 128UL, sizeof(fd_ed25519_sig_t), 1UL );
362 :
363 : /**/ 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 */
364 3 : /**/ fd_topob_link( topo, "sign_gossip", "sign_gossip", 128UL, sizeof(fd_ed25519_sig_t), 1UL ); /* TODO: Depth probably doesn't need to be 128 */
365 :
366 3 : FOR(sign_tile_cnt-1) fd_topob_link( topo, "repair_sign", "repair_sign", 128UL, FD_REPAIR_MAX_PREIMAGE_SZ, 1UL );
367 3 : FOR(sign_tile_cnt-1) fd_topob_link( topo, "sign_repair", "sign_repair", 128UL, sizeof(fd_ed25519_sig_t), 1UL );
368 :
369 3 : /**/ fd_topob_link( topo, "send_sign", "send_sign", 128UL, FD_TXN_MTU, 1UL ); /* TODO: Depth probably doesn't need to be 128 */
370 3 : /**/ fd_topob_link( topo, "sign_send", "sign_send", 128UL, sizeof(fd_ed25519_sig_t), 1UL ); /* TODO: Depth probably doesn't need to be 128 */
371 :
372 3 : FOR(shred_tile_cnt) fd_topob_link( topo, "shred_out", "shred_out", pending_fec_shreds_depth, FD_SHRED_OUT_MTU, 3UL ); /* TODO: Pretty sure burst of 3 is incorrect here */
373 3 : FOR(shred_tile_cnt) fd_topob_link( topo, "repair_shred", "shred_out", pending_fec_shreds_depth, sizeof(fd_ed25519_sig_t), 1UL ); /* TODO: Also pending_fec_shreds_depth? Seems wrong */
374 3 : /**/ fd_topob_link( topo, "tower_out", "tower_out", 1024UL, sizeof(fd_tower_slot_done_t), 1UL );
375 3 : /**/ fd_topob_link( topo, "send_txns", "send_txns", 128UL, FD_TPU_RAW_MTU, 1UL ); /* TODO: Horribly named. Rename to indicate tile and where its going */
376 :
377 3 : fd_topob_link( topo, "replay_exec", "replay_exec", 16384UL, sizeof(fd_exec_task_msg_t), 1UL );
378 :
379 3 : ushort parsed_tile_to_cpu[ FD_TILE_MAX ];
380 : /* Unassigned tiles will be floating, unless auto topology is enabled. */
381 3075 : for( ulong i=0UL; i<FD_TILE_MAX; i++ ) parsed_tile_to_cpu[ i ] = USHORT_MAX;
382 :
383 3 : int is_auto_affinity = !strcmp( config->layout.affinity, "auto" );
384 :
385 3 : fd_topo_cpus_t cpus[1];
386 3 : fd_topo_cpus_init( cpus );
387 :
388 3 : ulong affinity_tile_cnt = 0UL;
389 3 : if( FD_LIKELY( !is_auto_affinity ) ) affinity_tile_cnt = fd_tile_private_cpus_parse( config->layout.affinity, parsed_tile_to_cpu );
390 :
391 3 : ulong tile_to_cpu[ FD_TILE_MAX ] = {0};
392 3 : for( ulong i=0UL; i<affinity_tile_cnt; i++ ) {
393 0 : if( FD_UNLIKELY( parsed_tile_to_cpu[ i ]!=USHORT_MAX && parsed_tile_to_cpu[ i ]>=cpus->cpu_cnt ) )
394 0 : FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.affinity] specifies a CPU index of %hu, but the system "
395 0 : "only has %lu CPUs. You should either change the CPU allocations in the affinity string, or increase the number of CPUs "
396 0 : "in the system.",
397 0 : parsed_tile_to_cpu[ i ], cpus->cpu_cnt ));
398 0 : tile_to_cpu[ i ] = fd_ulong_if( parsed_tile_to_cpu[ i ]==USHORT_MAX, ULONG_MAX, (ulong)parsed_tile_to_cpu[ i ] );
399 0 : }
400 :
401 3 : 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 );
402 :
403 3 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_gossvf", i, config->net.ingress_buffer_size );
404 3 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_shred", i, config->net.ingress_buffer_size );
405 3 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_repair", i, config->net.ingress_buffer_size );
406 3 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_send", i, config->net.ingress_buffer_size );
407 3 : FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_quic", i, config->net.ingress_buffer_size );
408 :
409 : /* topo, tile_name, tile_wksp, metrics_wksp, cpu_idx, is_agave, uses_keyswitch */
410 : /**/ fd_topob_tile( topo, "metric", "metric", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
411 :
412 3 : if( FD_LIKELY( snapshots_enabled ) ) {
413 0 : fd_topob_tile( topo, "snaprd", "snaprd", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
414 0 : fd_topob_tile( topo, "snapdc", "snapdc", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
415 0 : fd_topob_tile( topo, "snapin", "snapin", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
416 0 : }
417 :
418 : /**/ fd_topob_tile( topo, "genesi", "genesi", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 )->allow_shutdown = 1;
419 3 : /**/ fd_topob_tile( topo, "ipecho", "ipecho", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
420 3 : FOR(gossvf_tile_cnt) fd_topob_tile( topo, "gossvf", "gossvf", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
421 3 : /**/ fd_topob_tile( topo, "gossip", "gossip", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
422 :
423 3 : FOR(shred_tile_cnt) fd_topob_tile( topo, "shred", "shred", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
424 3 : /**/ fd_topob_tile( topo, "repair", "repair", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 ); /* TODO: Wrong? Needs to use keyswitch as signs */
425 3 : /**/ fd_topob_tile( topo, "replay", "replay", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
426 24 : FOR(exec_tile_cnt) fd_topob_tile( topo, "exec", "exec", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
427 3 : /**/ fd_topob_tile( topo, "tower", "tower", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
428 3 : /**/ fd_topob_tile( topo, "send", "send", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
429 :
430 3 : FOR(quic_tile_cnt) fd_topob_tile( topo, "quic", "quic", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
431 18 : FOR(verify_tile_cnt) fd_topob_tile( topo, "verify", "verify", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
432 3 : /**/ fd_topob_tile( topo, "dedup", "dedup", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
433 3 : FOR(resolv_tile_cnt) fd_topob_tile( topo, "resolv", "resolv", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
434 3 : FOR(resolv_tile_cnt) strncpy( topo->tiles[ topo->tile_cnt-1UL-i ].metrics_name, "resolf", 8UL );
435 3 : /**/ fd_topob_tile( topo, "pack", "pack", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, config->tiles.bundle.enabled );
436 3 : FOR(bank_tile_cnt) fd_topob_tile( topo, "bank", "bank", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
437 3 : FOR(bank_tile_cnt) strncpy( topo->tiles[ topo->tile_cnt-1UL-i ].metrics_name, "bankf", 6UL );
438 3 : /**/ fd_topob_tile( topo, "poh", "poh", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
439 6 : FOR(sign_tile_cnt) fd_topob_tile( topo, "sign", "sign", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
440 :
441 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
442 6 : FOR(gossvf_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
443 3 : 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 */
444 6 : FOR(shred_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
445 3 : 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 */
446 3 : 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 */
447 3 : /**/ fd_topob_tile_out( topo, "repair", 0UL, "repair_net", 0UL );
448 3 : /**/ fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "net_send", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
449 6 : FOR(quic_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
450 3 : 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 */
451 :
452 3 : 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 */
453 3 : /**/ 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 */
454 3 : /**/ 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 */
455 3 : /**/ 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 */
456 3 : 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 */
457 :
458 3 : /**/ fd_topob_tile_out( topo, "genesi", 0UL, "genesi_out", 0UL );
459 3 : /**/ fd_topob_tile_in ( topo, "ipecho", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
460 3 : /**/ fd_topob_tile_out( topo, "ipecho", 0UL, "ipecho_out", 0UL );
461 :
462 3 : FOR(gossvf_tile_cnt) fd_topob_tile_out( topo, "gossvf", i, "gossvf_gossi", i );
463 3 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
464 3 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "gossip_gossv", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
465 3 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
466 3 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossvf", i, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
467 3 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
468 3 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_out", 0UL );
469 3 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_net", 0UL );
470 3 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
471 3 : FOR(gossvf_tile_cnt) fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "gossvf_gossi", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
472 3 : /**/ fd_topob_tile_in( topo, "gossip", 0UL, "metric_in", "send_txns", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
473 3 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_gossv", 0UL );
474 :
475 3 : if( FD_LIKELY( snapshots_enabled ) ) {
476 0 : fd_topob_tile_in( topo, "snaprd", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
477 0 : fd_topob_tile_out( topo, "snaprd", 0UL, "snap_zstd", 0UL );
478 0 : fd_topob_tile_in ( topo, "snaprd", 0UL, "metric_in", "snapdc_rd", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
479 0 : fd_topob_tile_in ( topo, "snaprd", 0UL, "metric_in", "snapin_rd", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
480 0 : fd_topob_tile_out( topo, "snaprd", 0UL, "snaprd_rp", 0UL );
481 0 : fd_topob_tile_in ( topo, "snapdc", 0UL, "metric_in", "snap_zstd", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
482 0 : fd_topob_tile_out( topo, "snapdc", 0UL, "snap_stream", 0UL );
483 0 : fd_topob_tile_out( topo, "snapdc", 0UL, "snapdc_rd", 0UL );
484 0 : fd_topob_tile_in ( topo, "snapin", 0UL, "metric_in", "snap_stream", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
485 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snap_out", 0UL );
486 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_rd", 0UL );
487 0 : fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "snap_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
488 0 : if( FD_LIKELY( config->tiles.gui.enabled ) ) /* the gui, which is optional, is the only consumer of snaprd_out */
489 0 : fd_topob_tile_out( topo, "snaprd", 0UL, "snaprd_out", 0UL );
490 0 : }
491 :
492 3 : /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
493 3 : /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
494 3 : /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
495 3 : /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
496 3 : if( snapshots_enabled ) {
497 0 : fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "snap_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
498 0 : }
499 3 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "shred_out", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
500 3 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "shred_out", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
501 3 : FOR(shred_tile_cnt) fd_topob_tile_out( topo, "repair", 0UL, "repair_shred", i );
502 3 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
503 3 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_out", 0UL );
504 3 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_stake", 0UL );
505 3 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "executed_txn", 0UL );
506 3 : /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_exec", 0UL );
507 3 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
508 3 : /**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "send_txns", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
509 3 : FOR(resolv_tile_cnt) fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "resolv_repla", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
510 :
511 3 : /**/ fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "poh_replay", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
512 24 : FOR(exec_tile_cnt) fd_topob_tile_in( topo, "exec", i, "metric_in", "replay_exec", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
513 3 : /**/ fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
514 3 : /**/ fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
515 3 : if( snapshots_enabled ) {
516 0 : fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "snap_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
517 0 : }
518 3 : /**/ fd_topob_tile_out( topo, "tower", 0UL, "tower_out", 0UL );
519 3 : /**/ fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
520 3 : /**/ fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
521 3 : /**/ fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
522 3 : /**/ fd_topob_tile_out( topo, "send", 0UL, "send_net", 0UL );
523 3 : /**/ fd_topob_tile_out( topo, "send", 0UL, "send_txns", 0UL );
524 :
525 3 : FOR(quic_tile_cnt) fd_topob_tile_out( topo, "quic", i, "quic_verify", i );
526 3 : FOR(quic_tile_cnt) fd_topob_tile_out( topo, "quic", i, "quic_net", i );
527 : /* All verify tiles read from all QUIC tiles, packets are round robin. */
528 36 : FOR(verify_tile_cnt) for( ulong j=0UL; j<quic_tile_cnt; j++ )
529 18 : 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 */
530 18 : FOR(verify_tile_cnt) fd_topob_tile_in( topo, "verify", i, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
531 3 : /**/ fd_topob_tile_in( topo, "verify", 0UL, "metric_in", "send_txns", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
532 18 : FOR(verify_tile_cnt) fd_topob_tile_out( topo, "verify", i, "verify_dedup", i );
533 18 : FOR(verify_tile_cnt) fd_topob_tile_in( topo, "dedup", 0UL, "metric_in", "verify_dedup", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
534 3 : /**/ fd_topob_tile_in( topo, "dedup", 0UL, "metric_in", "executed_txn", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
535 3 : /**/ fd_topob_tile_out( topo, "dedup", 0UL, "dedup_resolv", 0UL );
536 3 : FOR(resolv_tile_cnt) fd_topob_tile_in( topo, "resolv", i, "metric_in", "dedup_resolv", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
537 3 : FOR(resolv_tile_cnt) fd_topob_tile_in( topo, "resolv", i, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
538 3 : FOR(resolv_tile_cnt) fd_topob_tile_out( topo, "resolv", i, "resolv_pack", i );
539 3 : FOR(resolv_tile_cnt) fd_topob_tile_out( topo, "resolv", i, "resolv_repla", i );
540 3 : /**/ fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "resolv_pack", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
541 3 : /**/ fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
542 3 : /**/ fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "executed_txn", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
543 3 : fd_topob_tile_out( topo, "pack", 0UL, "pack_bank", 0UL );
544 3 : fd_topob_tile_out( topo, "pack", 0UL, "pack_poh" , 0UL );
545 3 : FOR(bank_tile_cnt) fd_topob_tile_in( topo, "pack", 0UL, "metric_in", "bank_pack", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
546 3 : FOR(bank_tile_cnt) fd_topob_tile_in( topo, "bank", i, "metric_in", "pack_bank", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
547 3 : FOR(bank_tile_cnt) fd_topob_tile_out( topo, "bank", i, "bank_poh", i );
548 3 : FOR(bank_tile_cnt) fd_topob_tile_out( topo, "bank", i, "bank_pack", i );
549 3 : FOR(bank_tile_cnt) fd_topob_tile_in( topo, "poh", 0UL, "metric_in", "bank_poh", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
550 3 : if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) ) {
551 3 : /**/ fd_topob_tile_in( topo, "poh", 0UL, "metric_in", "pack_poh", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
552 3 : }
553 3 : /**/ fd_topob_tile_in( topo, "poh", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
554 3 : /**/ fd_topob_tile_out( topo, "poh", 0UL, "poh_shred", 0UL );
555 3 : /**/ fd_topob_tile_out( topo, "poh", 0UL, "poh_replay", 0UL );
556 3 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
557 3 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
558 3 : FOR(shred_tile_cnt) fd_topob_tile_out( topo, "shred", i, "shred_out", i );
559 3 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "repair_shred", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
560 3 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
561 3 : FOR(shred_tile_cnt) fd_topob_tile_in ( topo, "shred", i, "metric_in", "poh_shred", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
562 3 : FOR(shred_tile_cnt) fd_topob_tile_out( topo, "shred", i, "shred_net", i );
563 :
564 : /* Sign links don't need to be reliable because they are synchronous,
565 : so there's at most one fragment in flight at a time anyway. The
566 : sign links are also not polled by fd_stem, instead the tiles will
567 : read the sign responses out of band in a dedicated spin loop.
568 :
569 : TODO: This can probably be fixed now to be relible ... ? */
570 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
571 3 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "gossip_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
572 3 : /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_sign", 0UL );
573 3 : /**/ fd_topob_tile_in ( topo, "gossip", 0UL, "metric_in", "sign_gossip", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
574 3 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_gossip", 0UL );
575 :
576 6 : for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
577 3 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "shred_sign", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
578 3 : /**/ fd_topob_tile_out( topo, "shred", i, "shred_sign", i );
579 3 : /**/ fd_topob_tile_in ( topo, "shred", i, "metric_in", "sign_shred", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
580 3 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_shred", i );
581 3 : }
582 :
583 3 : FOR(sign_tile_cnt-1UL) fd_topob_tile_out( topo, "repair", 0UL, "repair_sign", i );
584 3 : FOR(sign_tile_cnt-1UL) fd_topob_tile_in ( topo, "sign", i+1UL, "metric_in", "repair_sign", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
585 3 : FOR(sign_tile_cnt-1UL) fd_topob_tile_out( topo, "sign", i+1UL, "sign_repair", i );
586 3 : 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 */
587 :
588 3 : /**/ fd_topob_tile_in ( topo, "sign", 0UL, "metric_in", "send_sign", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
589 3 : /**/ fd_topob_tile_out( topo, "send", 0UL, "send_sign", 0UL );
590 3 : /**/ fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "sign_send", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
591 3 : /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_send", 0UL );
592 :
593 3 : if( FD_UNLIKELY( config->tiles.archiver.enabled ) ) {
594 0 : fd_topob_wksp( topo, "arch_f" );
595 0 : fd_topob_wksp( topo, "arch_w" );
596 0 : fd_topob_wksp( topo, "feeder" );
597 0 : fd_topob_wksp( topo, "arch_f2w" );
598 :
599 0 : fd_topob_link( topo, "feeder", "feeder", 65536UL, 4UL*FD_SHRED_STORE_MTU, 4UL+config->tiles.shred.max_pending_shred_sets );
600 0 : fd_topob_link( topo, "arch_f2w", "arch_f2w", 128UL, 4UL*FD_SHRED_STORE_MTU, 1UL );
601 :
602 0 : fd_topob_tile( topo, "arch_f", "arch_f", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
603 0 : fd_topob_tile( topo, "arch_w", "arch_w", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
604 :
605 0 : fd_topob_tile_out( topo, "replay", 0UL, "feeder", 0UL );
606 0 : fd_topob_tile_in( topo, "arch_f", 0UL, "metric_in", "feeder", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
607 :
608 0 : fd_topob_tile_out( topo, "arch_f", 0UL, "arch_f2w", 0UL );
609 0 : fd_topob_tile_in( topo, "arch_w", 0UL, "metric_in", "arch_f2w", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
610 0 : }
611 :
612 3 : if( FD_UNLIKELY( config->tiles.shredcap.enabled ) ) {
613 0 : fd_topob_wksp( topo, "scap" );
614 :
615 0 : fd_topob_tile( topo, "scap", "scap", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
616 :
617 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "repair_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
618 0 : for( ulong j=0UL; j<net_tile_cnt; j++ ) {
619 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "net_shred", j, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
620 0 : }
621 0 : for( ulong j=0UL; j<shred_tile_cnt; j++ ) {
622 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "shred_out", j, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
623 0 : }
624 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
625 :
626 0 : fd_topob_tile_in( topo, "scap", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
627 :
628 : /* No default fd_topob_tile_in connection to stake_out */
629 0 : }
630 :
631 3 : int rpc_enabled = config->rpc.port;
632 3 : if( FD_UNLIKELY( rpc_enabled ) ) {
633 0 : fd_topob_wksp( topo, "rpcsrv" );
634 0 : fd_topob_tile( topo, "rpcsrv", "rpcsrv", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
635 0 : fd_topob_tile_in( topo, "rpcsrv", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
636 0 : fd_topob_tile_in( topo, "rpcsrv", 0UL, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
637 0 : }
638 :
639 3 : fd_topob_wksp( topo, "exec_replay" );
640 24 : FOR(exec_tile_cnt) fd_topob_link( topo, "exec_replay", "exec_replay", 16384UL, sizeof(fd_exec_task_done_msg_t), 1UL );
641 24 : FOR(exec_tile_cnt) fd_topob_tile_out( topo, "exec", i, "exec_replay", i );
642 24 : FOR(exec_tile_cnt) fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "exec_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
643 :
644 3 : if( FD_LIKELY( config->tiles.gui.enabled ) ) {
645 3 : fd_topob_wksp( topo, "gui" );
646 :
647 : /**/ fd_topob_tile( topo, "gui", "gui", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 1 );
648 :
649 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
650 3 : 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 */
651 3 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "repair_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
652 3 : FOR(shred_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "shred_out", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
653 3 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "gossip_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
654 3 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
655 3 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
656 3 : /**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
657 :
658 3 : if( FD_LIKELY( snapshots_enabled ) ) {
659 0 : fd_topob_tile_in ( topo, "gui", 0UL, "metric_in", "snaprd_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
660 0 : }
661 3 : }
662 :
663 3 : if( FD_LIKELY( !is_auto_affinity ) ) {
664 0 : if( FD_UNLIKELY( affinity_tile_cnt<topo->tile_cnt ) )
665 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. "
666 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 "
667 0 : "the total tile count. You can reduce the tile count by decreasing individual tile counts in the [layout] section of the configuration file.",
668 0 : topo->tile_cnt, affinity_tile_cnt ));
669 0 : if( FD_UNLIKELY( affinity_tile_cnt>topo->tile_cnt ) )
670 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. "
671 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 "
672 0 : "individual tile counts in the [layout] section of the configuration file.",
673 0 : topo->tile_cnt, affinity_tile_cnt ));
674 0 : }
675 :
676 :
677 3 : if( FD_UNLIKELY( is_auto_affinity ) ) fd_topob_auto_layout( topo, 0 );
678 :
679 : /* There is a special fseq that sits between the pack, bank, and poh
680 : tiles to indicate when the bank/poh tiles are done processing a
681 : microblock. Pack uses this to determine when to "unlock" accounts
682 : that it marked as locked because they were being used. */
683 :
684 6 : for( ulong i=0UL; i<bank_tile_cnt; i++ ) {
685 3 : fd_topo_obj_t * busy_obj = fd_topob_obj( topo, "fseq", "bank_busy" );
686 :
687 3 : fd_topo_tile_t * pack_tile = &topo->tiles[ fd_topo_find_tile( topo, "pack", 0UL ) ];
688 3 : fd_topo_tile_t * bank_tile = &topo->tiles[ fd_topo_find_tile( topo, "bank", i ) ];
689 3 : fd_topob_tile_uses( topo, pack_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
690 3 : fd_topob_tile_uses( topo, bank_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
691 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, busy_obj->id, "bank_busy.%lu", i ) );
692 3 : }
693 :
694 3 : fd_topo_obj_t * funk_obj = setup_topo_funk( topo, "funk",
695 3 : config->firedancer.funk.max_account_records,
696 3 : config->firedancer.funk.max_database_transactions,
697 3 : config->firedancer.funk.heap_size_gib,
698 3 : config->firedancer.funk.lock_pages );
699 3 : /**/ 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? */
700 24 : 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 );
701 3 : 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 );
702 3 : 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 );
703 :
704 3 : fd_topo_obj_t * banks_obj = setup_topo_banks( topo, "banks", config->firedancer.runtime.max_live_slots, config->firedancer.runtime.max_fork_width );
705 3 : /**/ 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? */
706 24 : 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? */
707 3 : 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 );
708 3 : 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 );
709 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, banks_obj->id, "banks" ) );
710 :
711 : /* TODO: This should not exist in production */
712 3 : fd_topo_obj_t * bank_hash_cmp_obj = setup_topo_bank_hash_cmp( topo, "bh_cmp" );
713 3 : /**/ fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], bank_hash_cmp_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
714 24 : FOR(exec_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], bank_hash_cmp_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
715 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, bank_hash_cmp_obj->id, "bh_cmp" ) );
716 :
717 3 : ulong shred_depth = 65536UL; /* from fdctl/topology.c shred_store link. MAKE SURE TO KEEP IN SYNC. */
718 3 : ulong fec_set_cnt = shred_depth + config->tiles.shred.max_pending_shred_sets + 4UL;
719 3 : ulong fec_sets_sz = fec_set_cnt*sizeof(fd_shred34_t)*4; /* mirrors # of dcache entires in frankendancer */
720 3 : fd_topo_obj_t * fec_sets_obj = setup_topo_fec_sets( topo, "fec_sets", shred_tile_cnt*fec_sets_sz );
721 6 : for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
722 3 : fd_topo_tile_t * shred_tile = &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ];
723 3 : fd_topob_tile_uses( topo, shred_tile, fec_sets_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
724 3 : }
725 3 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "repair", 0UL ) ], fec_sets_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
726 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, fec_sets_obj->id, "fec_sets" ) );
727 :
728 3 : fd_topo_obj_t * store_obj = setup_topo_store( topo, "store", config->firedancer.store.max_completed_shred_sets, (uint)shred_tile_cnt );
729 3 : 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 );
730 3 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "repair", 0UL ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
731 3 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
732 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, store_obj->id, "store" ) );
733 :
734 3 : fd_topo_obj_t * txncache_obj = setup_topo_txncache( topo, "txncache",
735 3 : config->firedancer.runtime.max_live_slots,
736 3 : fd_ulong_pow2_up( FD_PACK_MAX_TXNCACHE_TXN_PER_SLOT ) );
737 3 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "replay", 0UL ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
738 3 : if( FD_LIKELY( snapshots_enabled ) ) {
739 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
740 0 : }
741 3 : 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 );
742 24 : 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 );
743 3 : FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
744 :
745 27 : for( ulong i=0UL; i<exec_tile_cnt; i++ ) {
746 24 : fd_topo_obj_t * exec_spad_obj = fd_topob_obj( topo, "exec_spad", "exec_spad" );
747 24 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], exec_spad_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
748 24 : FD_TEST( fd_pod_insertf_ulong( topo->props, exec_spad_obj->id, "exec_spad.%lu", i ) );
749 24 : }
750 :
751 3 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "genesi", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
752 3 : 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 );
753 :
754 3 : if( FD_UNLIKELY( rpc_enabled ) ) {
755 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "rpcsrv", 0UL ) ], funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
756 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "rpcsrv", 0UL ) ], store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
757 0 : }
758 :
759 108 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) fd_topo_configure_tile( &topo->tiles[ i ], config );
760 :
761 3 : FOR(net_tile_cnt) fd_topos_net_tile_finish( topo, i );
762 3 : fd_topob_finish( topo, CALLBACKS );
763 3 : config->topo = *topo;
764 3 : }
765 :
766 : void
767 : fd_topo_configure_tile( fd_topo_tile_t * tile,
768 105 : fd_config_t * config ) {
769 105 : if( FD_UNLIKELY( !strcmp( tile->name, "metric" ) ) ) {
770 :
771 3 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.metric.prometheus_listen_address, &tile->metric.prometheus_listen_addr ) ) )
772 0 : FD_LOG_ERR(( "failed to parse prometheus listen address `%s`", config->tiles.metric.prometheus_listen_address ));
773 3 : tile->metric.prometheus_listen_port = config->tiles.metric.prometheus_listen_port;
774 :
775 102 : } else if( FD_UNLIKELY( !strcmp( tile->name, "net" ) || !strcmp( tile->name, "sock" ) ) ) {
776 :
777 3 : tile->net.shred_listen_port = config->tiles.shred.shred_listen_port;
778 3 : tile->net.quic_transaction_listen_port = config->tiles.quic.quic_transaction_listen_port;
779 3 : tile->net.legacy_transaction_listen_port = config->tiles.quic.regular_transaction_listen_port;
780 3 : tile->net.gossip_listen_port = config->gossip.port;
781 3 : tile->net.repair_intake_listen_port = config->tiles.repair.repair_intake_listen_port;
782 3 : tile->net.repair_serve_listen_port = config->tiles.repair.repair_serve_listen_port;
783 3 : tile->net.send_src_port = config->tiles.send.send_src_port;
784 :
785 99 : } else if( FD_UNLIKELY( !strcmp( tile->name, "netlnk" ) ) ) {
786 :
787 96 : } else if( FD_UNLIKELY( !strcmp( tile->name, "ipecho") ) ) {
788 :
789 3 : tile->ipecho.expected_shred_version = config->consensus.expected_shred_version;
790 3 : tile->ipecho.bind_address = config->net.ip_addr;
791 3 : tile->ipecho.bind_port = config->gossip.port;
792 3 : tile->ipecho.entrypoints_cnt = config->gossip.entrypoints_cnt;
793 3 : fd_memcpy( tile->ipecho.entrypoints, config->gossip.resolved_entrypoints, tile->ipecho.entrypoints_cnt * sizeof(fd_ip4_port_t) );
794 :
795 93 : } else if( FD_UNLIKELY( !strcmp( tile->name, "genesi" ) ) ) {
796 :
797 3 : tile->genesi.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX );
798 :
799 3 : tile->genesi.allow_download = config->firedancer.snapshots.genesis_download;
800 3 : strncpy( tile->genesi.genesis_path, config->paths.genesis, sizeof(tile->genesi.genesis_path) );
801 3 : tile->genesi.expected_shred_version = config->consensus.expected_shred_version;
802 3 : tile->genesi.entrypoints_cnt = config->gossip.entrypoints_cnt;
803 3 : fd_memcpy( tile->genesi.entrypoints, config->gossip.resolved_entrypoints, tile->genesi.entrypoints_cnt * sizeof(fd_ip4_port_t) );
804 :
805 90 : } else if( FD_UNLIKELY( !strcmp( tile->name, "gossvf") ) ) {
806 :
807 3 : strncpy( tile->gossvf.identity_key_path, config->paths.identity_key, sizeof(tile->gossvf.identity_key_path) );
808 3 : tile->gossvf.tcache_depth = 1<<22UL; /* TODO: user defined option */
809 3 : tile->gossvf.shred_version = 0U;
810 3 : tile->gossvf.allow_private_address = config->development.gossip.allow_private_address;
811 3 : tile->gossvf.boot_timestamp_nanos = config->boot_timestamp_nanos;
812 :
813 3 : tile->gossvf.entrypoints_cnt = config->gossip.entrypoints_cnt;
814 3 : fd_memcpy( tile->gossvf.entrypoints, config->gossip.resolved_entrypoints, tile->gossvf.entrypoints_cnt * sizeof(fd_ip4_port_t) );
815 :
816 87 : } else if( FD_UNLIKELY( !strcmp( tile->name, "gossip" ) ) ) {
817 :
818 3 : if( FD_UNLIKELY( strcmp( config->firedancer.gossip.host, "" ) ) ) {
819 0 : if( !resolve_address( config->firedancer.gossip.host, &tile->gossip.ip_addr ) )
820 0 : FD_LOG_ERR(( "could not resolve [gossip.host] %s", config->firedancer.gossip.host ));
821 3 : } else {
822 3 : tile->gossip.ip_addr = config->net.ip_addr;
823 3 : }
824 3 : strncpy( tile->gossip.identity_key_path, config->paths.identity_key, sizeof(tile->gossip.identity_key_path) );
825 3 : tile->gossip.shred_version = config->consensus.expected_shred_version;
826 3 : tile->gossip.max_entries = config->tiles.gossip.max_entries;
827 3 : tile->gossip.boot_timestamp_nanos = config->boot_timestamp_nanos;
828 :
829 3 : tile->gossip.ports.gossip = config->gossip.port;
830 3 : tile->gossip.ports.tvu = config->tiles.shred.shred_listen_port;
831 3 : tile->gossip.ports.tpu = config->tiles.quic.regular_transaction_listen_port;
832 3 : tile->gossip.ports.tpu_quic = config->tiles.quic.quic_transaction_listen_port;
833 3 : tile->gossip.ports.repair = config->tiles.repair.repair_intake_listen_port;
834 :
835 3 : tile->gossip.entrypoints_cnt = config->gossip.entrypoints_cnt;
836 3 : fd_memcpy( tile->gossip.entrypoints, config->gossip.resolved_entrypoints, tile->gossip.entrypoints_cnt * sizeof(fd_ip4_port_t) );
837 :
838 84 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snaprd" ) ) ) {
839 :
840 0 : fd_memcpy( tile->snaprd.snapshots_path, config->paths.snapshots, PATH_MAX );
841 0 : tile->snaprd.incremental_snapshot_fetch = config->firedancer.snapshots.incremental_snapshots;
842 0 : tile->snaprd.do_download = config->firedancer.snapshots.download;
843 0 : tile->snaprd.maximum_local_snapshot_age = config->firedancer.snapshots.maximum_local_snapshot_age;
844 0 : tile->snaprd.minimum_download_speed_mib = config->firedancer.snapshots.minimum_download_speed_mib;
845 0 : tile->snaprd.maximum_download_retry_abort = config->firedancer.snapshots.maximum_download_retry_abort;
846 0 : tile->snaprd.max_full_snapshots_to_keep = config->firedancer.snapshots.max_full_snapshots_to_keep;
847 0 : tile->snaprd.max_incremental_snapshots_to_keep = config->firedancer.snapshots.max_incremental_snapshots_to_keep;
848 :
849 0 : tile->snaprd.entrypoints_enabled = config->firedancer.snapshots.sources.entrypoints.enabled;
850 0 : tile->snaprd.gossip_peers_enabled = config->firedancer.snapshots.sources.gossip.enabled;
851 0 : tile->snaprd.gossip_entrypoints_cnt = config->gossip.entrypoints_cnt;
852 :
853 0 : for( ulong i=0UL; i<tile->snaprd.gossip_entrypoints_cnt; i++ ) tile->snaprd.gossip_entrypoints[ i ] = config->gossip.resolved_entrypoints[ i ];
854 :
855 0 : ulong peers_cnt = config->firedancer.snapshots.sources.http.peers_cnt;
856 0 : ulong resolved_peers_cnt = 0UL;
857 :
858 0 : for( ulong j=0UL; j<peers_cnt; j++ ) {
859 0 : if( FD_UNLIKELY( !config->firedancer.snapshots.sources.http.peers[ j ].enabled ) ) continue;
860 :
861 0 : if( FD_UNLIKELY( 0==resolve_peer( config->firedancer.snapshots.sources.http.peers[ j ].url, &tile->snaprd.http.peers[ resolved_peers_cnt ] ) ) ) {
862 0 : FD_LOG_ERR(( "failed to resolve address of [snapshots.sources.http.peers] entry \"%s\"", config->firedancer.snapshots.sources.http.peers[ j ].url ));
863 0 : } else {
864 0 : resolved_peers_cnt++;
865 0 : }
866 0 : }
867 :
868 0 : tile->snaprd.http.peers_cnt = resolved_peers_cnt;
869 : /* TODO: set up known validators and known validators cnt */
870 :
871 84 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapdc" ) ) ) {
872 :
873 84 : } else if( FD_UNLIKELY( !strcmp( tile->name, "snapin" ) ) ) {
874 :
875 0 : tile->snapin.max_live_slots = config->firedancer.runtime.max_live_slots;
876 0 : tile->snapin.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX );
877 0 : tile->snapin.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX );
878 :
879 84 : } else if( FD_UNLIKELY( !strcmp( tile->name, "repair" ) ) ) {
880 3 : tile->repair.max_pending_shred_sets = config->tiles.shred.max_pending_shred_sets;
881 3 : tile->repair.repair_intake_listen_port = config->tiles.repair.repair_intake_listen_port;
882 3 : tile->repair.repair_serve_listen_port = config->tiles.repair.repair_serve_listen_port;
883 3 : tile->repair.slot_max = config->tiles.repair.slot_max;
884 3 : tile->repair.repair_sign_cnt = config->firedancer.layout.sign_tile_count - 1; /* -1 because this excludes the keyguard client */
885 :
886 21 : for( ulong i=0; i<tile->in_cnt; i++ ) {
887 21 : if( !strcmp( config->topo.links[ tile->in_link_id[ i ] ].name, "sign_repair" ) ) {
888 3 : tile->repair.repair_sign_depth = config->topo.links[ tile->in_link_id[ i ] ].depth;
889 3 : break;
890 3 : }
891 21 : }
892 3 : strncpy( tile->repair.identity_key_path, config->paths.identity_key, sizeof(tile->repair.identity_key_path) );
893 :
894 81 : } else if( FD_UNLIKELY( !strcmp( tile->name, "replay" ) )) {
895 :
896 3 : tile->replay.max_live_slots = config->firedancer.runtime.max_live_slots;
897 3 : tile->replay.fec_max = config->tiles.shred.max_pending_shred_sets;
898 3 : tile->replay.max_vote_accounts = config->firedancer.runtime.max_vote_accounts;
899 :
900 : /* specified by [tiles.replay] */
901 :
902 3 : tile->replay.tx_metadata_storage = config->rpc.extended_tx_metadata_storage;
903 :
904 3 : tile->replay.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX );
905 3 : tile->replay.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX );
906 :
907 3 : strncpy( tile->replay.cluster_version, config->tiles.replay.cluster_version, sizeof(tile->replay.cluster_version) );
908 :
909 3 : tile->replay.heap_size_gib = config->tiles.replay.heap_size_gib;
910 3 : tile->replay.max_live_slots = config->firedancer.runtime.max_live_slots;
911 :
912 : /* not specified by [tiles.replay] */
913 :
914 3 : strncpy( tile->replay.identity_key_path, config->paths.identity_key, sizeof(tile->replay.identity_key_path) );
915 3 : tile->replay.ip_addr = config->net.ip_addr;
916 3 : strncpy( tile->replay.vote_account_path, config->paths.vote_account, sizeof(tile->replay.vote_account_path) );
917 3 : tile->replay.enable_bank_hash_cmp = 1;
918 :
919 3 : tile->replay.capture_start_slot = config->capture.capture_start_slot;
920 3 : strncpy( tile->replay.solcap_capture, config->capture.solcap_capture, sizeof(tile->replay.solcap_capture) );
921 3 : strncpy( tile->replay.dump_proto_dir, config->capture.dump_proto_dir, sizeof(tile->replay.dump_proto_dir) );
922 3 : tile->replay.dump_block_to_pb = config->capture.dump_block_to_pb;
923 :
924 3 : FD_TEST( tile->replay.funk_obj_id == fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX ) );
925 :
926 78 : } else if( FD_UNLIKELY( !strcmp( tile->name, "exec" ) ) ) {
927 :
928 24 : tile->exec.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX );
929 24 : tile->exec.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX );
930 :
931 24 : tile->exec.max_live_slots = config->firedancer.runtime.max_live_slots;
932 :
933 24 : tile->exec.capture_start_slot = config->capture.capture_start_slot;
934 24 : strncpy( tile->exec.solcap_capture, config->capture.solcap_capture, sizeof(tile->exec.solcap_capture) );
935 24 : strncpy( tile->exec.dump_proto_dir, config->capture.dump_proto_dir, sizeof(tile->exec.dump_proto_dir) );
936 24 : tile->exec.dump_instr_to_pb = config->capture.dump_instr_to_pb;
937 24 : tile->exec.dump_txn_to_pb = config->capture.dump_txn_to_pb;
938 24 : tile->exec.dump_syscall_to_pb = config->capture.dump_syscall_to_pb;
939 24 : tile->exec.dump_elf_to_pb = config->capture.dump_elf_to_pb;
940 :
941 54 : } else if( FD_UNLIKELY( !strcmp( tile->name, "tower" ) ) ) {
942 :
943 3 : strncpy( tile->tower.identity_key_path, config->paths.identity_key, sizeof(tile->tower.identity_key_path) );
944 3 : strncpy( tile->tower.vote_acc_path, config->paths.vote_account, sizeof(tile->tower.vote_acc_path) );
945 3 : strncpy( tile->tower.ledger_path, config->paths.ledger, sizeof(tile->tower.ledger_path) );
946 :
947 51 : } else if( FD_UNLIKELY( !strcmp( tile->name, "send" ) ) ) {
948 :
949 3 : tile->send.send_src_port = config->tiles.send.send_src_port;
950 3 : tile->send.ip_addr = config->net.ip_addr;
951 3 : strncpy( tile->send.identity_key_path, config->paths.identity_key, sizeof(tile->send.identity_key_path) );
952 :
953 48 : } else if( FD_UNLIKELY( !strcmp( tile->name, "quic" ) ) ) {
954 :
955 3 : tile->quic.reasm_cnt = config->tiles.quic.txn_reassembly_count;
956 3 : tile->quic.out_depth = config->tiles.verify.receive_buffer_size;
957 3 : tile->quic.max_concurrent_connections = config->tiles.quic.max_concurrent_connections;
958 3 : tile->quic.max_concurrent_handshakes = config->tiles.quic.max_concurrent_handshakes;
959 3 : tile->quic.quic_transaction_listen_port = config->tiles.quic.quic_transaction_listen_port;
960 3 : tile->quic.idle_timeout_millis = config->tiles.quic.idle_timeout_millis;
961 3 : tile->quic.ack_delay_millis = config->tiles.quic.ack_delay_millis;
962 3 : tile->quic.retry = config->tiles.quic.retry;
963 3 : 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) ) );
964 :
965 45 : } else if( FD_UNLIKELY( !strcmp( tile->name, "verify" ) ) ) {
966 :
967 18 : tile->verify.tcache_depth = config->tiles.verify.signature_cache_size;
968 :
969 27 : } else if( FD_UNLIKELY( !strcmp( tile->name, "dedup" ) ) ) {
970 :
971 3 : tile->dedup.tcache_depth = config->tiles.dedup.signature_cache_size;
972 :
973 24 : } else if( FD_UNLIKELY( !strcmp( tile->name, "resolv" ) ) ) {
974 :
975 3 : tile->resolv.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX );
976 :
977 21 : } else if( FD_UNLIKELY( !strcmp( tile->name, "pack" ) ) ) {
978 :
979 3 : tile->pack.max_pending_transactions = config->tiles.pack.max_pending_transactions;
980 3 : tile->pack.bank_tile_count = config->layout.bank_tile_count;
981 3 : tile->pack.larger_max_cost_per_block = config->development.bench.larger_max_cost_per_block;
982 3 : tile->pack.larger_shred_limits_per_block = config->development.bench.larger_shred_limits_per_block;
983 3 : tile->pack.use_consumed_cus = config->tiles.pack.use_consumed_cus;
984 3 : tile->pack.schedule_strategy = config->tiles.pack.schedule_strategy_enum;
985 :
986 3 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
987 0 : #define PARSE_PUBKEY( _tile, f ) \
988 0 : if( FD_UNLIKELY( !fd_base58_decode_32( config->tiles.bundle.f, tile->_tile.bundle.f ) ) ) \
989 0 : FD_LOG_ERR(( "[tiles.bundle.enabled] set to true, but failed to parse [tiles.bundle."#f"] %s", config->tiles.bundle.f ));
990 0 : tile->pack.bundle.enabled = 1;
991 0 : PARSE_PUBKEY( pack, tip_distribution_program_addr );
992 0 : PARSE_PUBKEY( pack, tip_payment_program_addr );
993 0 : PARSE_PUBKEY( pack, tip_distribution_authority );
994 0 : tile->pack.bundle.commission_bps = config->tiles.bundle.commission_bps;
995 0 : strncpy( tile->pack.bundle.identity_key_path, config->paths.identity_key, sizeof(tile->pack.bundle.identity_key_path) );
996 0 : strncpy( tile->pack.bundle.vote_account_path, config->paths.vote_account, sizeof(tile->pack.bundle.vote_account_path) );
997 3 : } else {
998 3 : fd_memset( &tile->pack.bundle, '\0', sizeof(tile->pack.bundle) );
999 3 : }
1000 :
1001 18 : } else if( FD_UNLIKELY( !strcmp( tile->name, "bank" ) ) ) {
1002 3 : tile->bank.txncache_obj_id = fd_pod_query_ulong( config->topo.props, "txncache", ULONG_MAX );
1003 3 : tile->bank.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX );
1004 :
1005 3 : tile->bank.max_live_slots = config->firedancer.runtime.max_live_slots;
1006 :
1007 15 : } else if( FD_UNLIKELY( !strcmp( tile->name, "poh" ) ) ) {
1008 3 : strncpy( tile->poh.identity_key_path, config->paths.identity_key, sizeof(tile->poh.identity_key_path) );
1009 :
1010 3 : tile->poh.plugins_enabled = 0;
1011 3 : tile->poh.bank_cnt = config->layout.bank_tile_count;
1012 3 : tile->poh.lagged_consecutive_leader_start = config->tiles.poh.lagged_consecutive_leader_start;
1013 :
1014 3 : if( FD_UNLIKELY( config->tiles.bundle.enabled ) ) {
1015 0 : tile->poh.bundle.enabled = 1;
1016 0 : PARSE_PUBKEY( poh, tip_distribution_program_addr );
1017 0 : PARSE_PUBKEY( poh, tip_payment_program_addr );
1018 0 : strncpy( tile->poh.bundle.vote_account_path, config->paths.vote_account, sizeof(tile->poh.bundle.vote_account_path) );
1019 0 : #undef PARSE_PUBKEY
1020 3 : } else {
1021 3 : fd_memset( &tile->poh.bundle, '\0', sizeof(tile->poh.bundle) );
1022 3 : }
1023 :
1024 12 : } else if( FD_UNLIKELY( !strcmp( tile->name, "shred" ) ) ) {
1025 :
1026 3 : strncpy( tile->shred.identity_key_path, config->paths.identity_key, sizeof(tile->shred.identity_key_path) );
1027 :
1028 3 : tile->shred.depth = config->topo.links[ tile->out_link_id[ 0 ] ].depth;
1029 3 : tile->shred.fec_resolver_depth = config->tiles.shred.max_pending_shred_sets;
1030 3 : tile->shred.expected_shred_version = config->consensus.expected_shred_version;
1031 3 : tile->shred.shred_listen_port = config->tiles.shred.shred_listen_port;
1032 3 : tile->shred.larger_shred_limits_per_block = config->development.bench.larger_shred_limits_per_block;
1033 3 : for( ulong i=0UL; i<config->tiles.shred.additional_shred_destinations_retransmit_cnt; i++ ) {
1034 0 : parse_ip_port( "tiles.shred.additional_shred_destinations_retransmit",
1035 0 : config->tiles.shred.additional_shred_destinations_retransmit[ i ],
1036 0 : &tile->shred.adtl_dests_retransmit[ i ] );
1037 0 : }
1038 3 : tile->shred.adtl_dests_retransmit_cnt = config->tiles.shred.additional_shred_destinations_retransmit_cnt;
1039 3 : for( ulong i=0UL; i<config->tiles.shred.additional_shred_destinations_leader_cnt; i++ ) {
1040 0 : parse_ip_port( "tiles.shred.additional_shred_destinations_leader",
1041 0 : config->tiles.shred.additional_shred_destinations_leader[ i ],
1042 0 : &tile->shred.adtl_dests_leader[ i ] );
1043 0 : }
1044 3 : tile->shred.adtl_dests_leader_cnt = config->tiles.shred.additional_shred_destinations_leader_cnt;
1045 :
1046 9 : } else if( FD_UNLIKELY( !strcmp( tile->name, "sign" ) ) ) {
1047 :
1048 6 : strncpy( tile->sign.identity_key_path, config->paths.identity_key, sizeof(tile->sign.identity_key_path) );
1049 :
1050 6 : } else if( FD_UNLIKELY( !strcmp( tile->name, "plugin" ) ) ) {
1051 :
1052 3 : } else if( FD_UNLIKELY( !strcmp( tile->name, "gui" ) ) ) {
1053 :
1054 3 : if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.gui.gui_listen_address, &tile->gui.listen_addr ) ) )
1055 0 : FD_LOG_ERR(( "failed to parse gui listen address `%s`", config->tiles.gui.gui_listen_address ));
1056 3 : tile->gui.listen_port = config->tiles.gui.gui_listen_port;
1057 3 : tile->gui.is_voting = strcmp( config->paths.vote_account, "" );
1058 3 : strncpy( tile->gui.cluster, config->cluster, sizeof(tile->gui.cluster) );
1059 3 : strncpy( tile->gui.identity_key_path, config->paths.identity_key, sizeof(tile->gui.identity_key_path) );
1060 3 : strncpy( tile->gui.vote_key_path, config->paths.vote_account, sizeof(tile->gui.vote_key_path) );
1061 3 : tile->gui.max_http_connections = config->tiles.gui.max_http_connections;
1062 3 : tile->gui.max_websocket_connections = config->tiles.gui.max_websocket_connections;
1063 3 : tile->gui.max_http_request_length = config->tiles.gui.max_http_request_length;
1064 3 : tile->gui.send_buffer_size_mb = config->tiles.gui.send_buffer_size_mb;
1065 3 : tile->gui.schedule_strategy = config->tiles.pack.schedule_strategy_enum;
1066 3 : tile->gui.websocket_compression = config->development.gui.websocket_compression;
1067 3 : tile->gui.frontend_release_channel = config->development.gui.frontend_release_channel_enum;
1068 :
1069 3 : } else if( FD_UNLIKELY( !strcmp( tile->name, "rpcsrv" ) ) ) {
1070 :
1071 0 : tile->rpcserv.funk_obj_id = fd_pod_query_ulong( config->topo.props, "funk", ULONG_MAX );
1072 0 : tile->rpcserv.store_obj_id = fd_pod_query_ulong( config->topo.props, "store", ULONG_MAX );
1073 0 : tile->rpcserv.rpc_port = config->rpc.port;
1074 0 : tile->rpcserv.tpu_port = config->tiles.quic.regular_transaction_listen_port;
1075 0 : tile->rpcserv.tpu_ip_addr = config->net.ip_addr;
1076 0 : tile->rpcserv.block_index_max = config->rpc.block_index_max;
1077 0 : tile->rpcserv.txn_index_max = config->rpc.txn_index_max;
1078 0 : tile->rpcserv.acct_index_max = config->rpc.acct_index_max;
1079 0 : strncpy( tile->rpcserv.history_file, config->rpc.history_file, sizeof(tile->rpcserv.history_file) );
1080 0 : strncpy( tile->rpcserv.identity_key_path, config->paths.identity_key, sizeof(tile->rpcserv.identity_key_path) );
1081 :
1082 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "arch_f" ) ||
1083 0 : !strcmp( tile->name, "arch_w" ) ) ) {
1084 :
1085 0 : strncpy( tile->archiver.rocksdb_path, config->tiles.archiver.rocksdb_path, sizeof(tile->archiver.rocksdb_path) );
1086 :
1087 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "backt" ) ) ) {
1088 :
1089 0 : tile->archiver.end_slot = config->tiles.archiver.end_slot;
1090 0 : strncpy( tile->archiver.ingest_mode, config->tiles.archiver.ingest_mode, sizeof(tile->archiver.ingest_mode) );
1091 0 : if( FD_UNLIKELY( 0==strlen( tile->archiver.ingest_mode ) ) ) {
1092 0 : FD_LOG_ERR(( "`archiver.ingest_mode` not specified in toml" ));
1093 0 : }
1094 :
1095 : /* Validate arguments based on the ingest mode */
1096 0 : if( !strcmp( tile->archiver.ingest_mode, "rocksdb" ) ) {
1097 0 : strncpy( tile->archiver.rocksdb_path, config->tiles.archiver.rocksdb_path, PATH_MAX );
1098 0 : if( FD_UNLIKELY( 0==strlen( tile->archiver.rocksdb_path ) ) ) {
1099 0 : FD_LOG_ERR(( "`archiver.rocksdb_path` not specified in toml" ));
1100 0 : }
1101 0 : } else if( !strcmp( tile->archiver.ingest_mode, "shredcap" ) ) {
1102 0 : strncpy( tile->archiver.shredcap_path, config->tiles.archiver.shredcap_path, PATH_MAX );
1103 0 : if( FD_UNLIKELY( 0==strlen( tile->archiver.shredcap_path ) ) ) {
1104 0 : FD_LOG_ERR(( "`archiver.shredcap_path` not specified in toml" ));
1105 0 : }
1106 0 : strncpy( tile->archiver.bank_hash_path, config->tiles.archiver.bank_hash_path, PATH_MAX );
1107 0 : if( FD_UNLIKELY( 0==strlen( tile->archiver.bank_hash_path ) ) ) {
1108 0 : FD_LOG_ERR(( "`archiver.bank_hash_path` not specified in toml" ));
1109 0 : }
1110 0 : } else {
1111 0 : FD_LOG_ERR(( "Invalid ingest mode: %s", tile->archiver.ingest_mode ));
1112 0 : }
1113 :
1114 0 : } else if( FD_UNLIKELY( !strcmp( tile->name, "scap" ) ) ) {
1115 :
1116 0 : tile->shredcap.repair_intake_listen_port = config->tiles.repair.repair_intake_listen_port;
1117 0 : strncpy( tile->shredcap.folder_path, config->tiles.shredcap.folder_path, sizeof(tile->shredcap.folder_path) );
1118 0 : tile->shredcap.write_buffer_size = config->tiles.shredcap.write_buffer_size;
1119 0 : tile->shredcap.enable_publish_stake_weights = 0; /* this is not part of the config */
1120 0 : strncpy( tile->shredcap.manifest_path, "", PATH_MAX ); /* this is not part of the config */
1121 :
1122 0 : } else {
1123 0 : FD_LOG_ERR(( "unknown tile name `%s`", tile->name ));
1124 0 : }
1125 105 : }
|