Line data Source code
1 : /* Sender tile signs and sends transactions to the current leader. Currently
2 : only supports transactions which require one signature. */
3 : #define _GNU_SOURCE
4 :
5 : #include "../../disco/topo/fd_topo.h"
6 : #include "generated/fd_sender_tile_seccomp.h"
7 :
8 : #include "../store/fd_store.h"
9 : #include "../../flamenco/repair/fd_repair.h"
10 : #include "../../flamenco/runtime/fd_blockstore.h"
11 : #include "../../flamenco/leaders/fd_leaders.h"
12 : #include "../../flamenco/fd_flamenco.h"
13 : #include "../../util/fd_util.h"
14 : #include "../../choreo/fd_choreo.h"
15 : #include "../../util/net/fd_eth.h"
16 : #include "../../util/net/fd_ip4.h"
17 : #include "../../util/net/fd_udp.h"
18 : #include "../../disco/shred/fd_stake_ci.h"
19 : #include "../../disco/topo/fd_pod_format.h"
20 : #include "../../disco/keyguard/fd_keyload.h"
21 : #include "../../disco/keyguard/fd_keyguard_client.h"
22 : #include "../../disco/keyguard/fd_keyguard.h"
23 : #include "../../flamenco/leaders/fd_leaders.h"
24 : #include "../../flamenco/runtime/fd_runtime.h"
25 : #include "../../disco/fd_disco.h"
26 : #include "../../util/net/fd_net_headers.h"
27 :
28 : #include <unistd.h>
29 : #include <arpa/inet.h>
30 : #include <linux/unistd.h>
31 : #include <sys/random.h>
32 : #include <netdb.h>
33 : #include <netinet/in.h>
34 : #include <sys/socket.h>
35 :
36 0 : #define SCRATCH_MAX (4UL /*KiB*/ << 10)
37 0 : #define SCRATCH_DEPTH (4UL) /* 4 scratch frames */
38 :
39 : struct fd_sender_tile_ctx {
40 : fd_pubkey_t identity_key[ 1 ];
41 : fd_pubkey_t vote_acct_addr[ 1 ];
42 :
43 : fd_stake_ci_t * stake_ci;
44 : ulong * poh_slot;
45 : fd_shred_dest_weighted_t * new_dest_ptr;
46 : ulong new_dest_cnt;
47 :
48 : uchar txn_buf[ sizeof(fd_txn_p_t) ] __attribute__((aligned(alignof(fd_txn_p_t))));
49 :
50 : fd_gossip_peer_addr_t tpu_serve_addr;
51 : fd_ip4_udp_hdrs_t packet_hdr[1];
52 : ushort net_id;
53 :
54 : ulong stake_in_idx;
55 : fd_wksp_t * stake_in_mem;
56 : ulong stake_in_chunk0;
57 : ulong stake_in_wmark;
58 :
59 : ulong contact_in_idx;
60 : fd_wksp_t * contact_in_mem;
61 : ulong contact_in_chunk0;
62 : ulong contact_in_wmark;
63 :
64 : ulong replay_in_idx;
65 : fd_wksp_t * replay_in_mem;
66 : ulong replay_in_chunk0;
67 : ulong replay_in_wmark;
68 :
69 : ulong poh_in_idx;
70 : fd_wksp_t * poh_in_mem;
71 : ulong poh_in_chunk0;
72 : ulong poh_in_wmark;
73 :
74 : ulong gossip_out_idx;
75 : fd_frag_meta_t * gossip_out_mcache;
76 : ulong * gossip_out_sync;
77 : ulong gossip_out_depth;
78 : ulong gossip_out_seq;
79 :
80 : fd_wksp_t * gossip_out_mem;
81 : ulong gossip_out_chunk0;
82 : ulong gossip_out_wmark;
83 : ulong gossip_out_chunk;
84 :
85 : ulong dedup_out_idx;
86 : fd_frag_meta_t * dedup_out_mcache;
87 : ulong * dedup_out_sync;
88 : ulong dedup_out_depth;
89 : ulong dedup_out_seq;
90 :
91 : fd_wksp_t * dedup_out_mem;
92 : ulong dedup_out_chunk0;
93 : ulong dedup_out_wmark;
94 : ulong dedup_out_chunk;
95 :
96 : ulong net_out_idx;
97 : fd_frag_meta_t * net_out_mcache;
98 : ulong * net_out_sync;
99 : ulong net_out_depth;
100 : ulong net_out_seq;
101 :
102 : fd_wksp_t * net_out_mem;
103 : ulong net_out_chunk0;
104 : ulong net_out_wmark;
105 : ulong net_out_chunk;
106 :
107 : ulong sign_in_idx;
108 : ulong sign_out_idx;
109 : fd_keyguard_client_t keyguard_client[ 1 ];
110 :
111 : };
112 : typedef struct fd_sender_tile_ctx fd_sender_tile_ctx_t;
113 :
114 :
115 : FD_FN_CONST static inline ulong
116 0 : scratch_align( void ) {
117 0 : return 128UL;
118 0 : }
119 :
120 : FD_FN_PURE static inline ulong
121 0 : loose_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED ) {
122 0 : return 0UL;
123 0 : }
124 :
125 : FD_FN_PURE static inline ulong
126 0 : scratch_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED) {
127 0 : ulong l = FD_LAYOUT_INIT;
128 0 : l = FD_LAYOUT_APPEND( l, alignof(fd_sender_tile_ctx_t), sizeof(fd_sender_tile_ctx_t) );
129 0 : l = FD_LAYOUT_APPEND( l, fd_stake_ci_align(), fd_stake_ci_footprint() );
130 0 : l = FD_LAYOUT_APPEND( l, fd_scratch_smem_align(), fd_scratch_smem_footprint( SCRATCH_MAX ) );
131 0 : l = FD_LAYOUT_APPEND( l, fd_scratch_fmem_align(), fd_scratch_fmem_footprint( SCRATCH_DEPTH ) );
132 0 : return FD_LAYOUT_FINI( l, scratch_align() );
133 0 : }
134 :
135 : static void
136 : send_packet( fd_sender_tile_ctx_t * ctx,
137 : uint dst_ip_addr,
138 : ushort dst_port,
139 : uchar const * payload,
140 : ulong payload_sz,
141 0 : ulong tsorig ) {
142 0 : uchar * packet = fd_chunk_to_laddr( ctx->net_out_mem, ctx->net_out_chunk );
143 :
144 0 : fd_ip4_udp_hdrs_t * hdr = (fd_ip4_udp_hdrs_t *)packet;
145 0 : *hdr = *ctx->packet_hdr;
146 :
147 0 : fd_ip4_hdr_t * ip4 = hdr->ip4;
148 0 : ip4->daddr = dst_ip_addr;
149 0 : ip4->net_id = fd_ushort_bswap( ctx->net_id++ );
150 0 : ip4->check = 0U;
151 0 : ip4->net_tot_len = fd_ushort_bswap( (ushort)(payload_sz + sizeof(fd_ip4_hdr_t)+sizeof(fd_udp_hdr_t)) );
152 0 : ip4->check = fd_ip4_hdr_check_fast( ip4 );
153 :
154 0 : fd_udp_hdr_t * udp = hdr->udp;
155 0 : udp->net_dport = fd_ushort_bswap( dst_port );
156 0 : udp->net_len = fd_ushort_bswap( (ushort)(payload_sz + sizeof(fd_udp_hdr_t)) );
157 0 : fd_memcpy( packet+sizeof(fd_ip4_udp_hdrs_t), payload, payload_sz );
158 0 : udp->check = 0U;
159 :
160 0 : ulong tspub = fd_frag_meta_ts_comp( fd_tickcount() );
161 0 : ulong sig = fd_disco_netmux_sig( dst_ip_addr, dst_port, dst_ip_addr, DST_PROTO_OUTGOING, sizeof(fd_ip4_udp_hdrs_t) );
162 0 : ulong packet_sz = payload_sz + sizeof(fd_ip4_udp_hdrs_t);
163 0 : fd_mcache_publish( ctx->net_out_mcache, ctx->net_out_depth, ctx->net_out_seq, sig, ctx->net_out_chunk, packet_sz, 0UL, tsorig, tspub );
164 0 : ctx->net_out_seq = fd_seq_inc( ctx->net_out_seq, 1UL );
165 0 : ctx->net_out_chunk = fd_dcache_compact_next( ctx->net_out_chunk, packet_sz, ctx->net_out_chunk0, ctx->net_out_wmark );
166 0 : }
167 :
168 : static int
169 : get_current_leader_tpu_vote_contact( fd_sender_tile_ctx_t * ctx,
170 0 : fd_shred_dest_weighted_t ** out_dest ) {
171 0 : ulong poh_slot = fd_fseq_query( ctx->poh_slot );
172 0 : if( poh_slot==ULONG_MAX ) { return -1; }
173 :
174 0 : fd_epoch_leaders_t const * lsched = fd_stake_ci_get_lsched_for_slot( ctx->stake_ci, poh_slot );
175 0 : if( FD_UNLIKELY( !lsched ) ) { return -1; }
176 :
177 0 : fd_pubkey_t const * slot_leader = fd_epoch_leaders_get( lsched, poh_slot );
178 0 : if( FD_UNLIKELY( !slot_leader ) ) { return -1 ; } /* Count this as bad slot too */
179 :
180 0 : fd_shred_dest_t * sdest = fd_stake_ci_get_sdest_for_slot( ctx->stake_ci, poh_slot );
181 0 : fd_shred_dest_idx_t sdest_idx = fd_shred_dest_pubkey_to_idx( sdest, slot_leader );
182 0 : if( FD_UNLIKELY( sdest_idx==FD_SHRED_DEST_NO_DEST ) ) {
183 0 : return -1;
184 0 : }
185 :
186 0 : *out_dest = fd_shred_dest_idx_to_dest( sdest, sdest_idx );
187 :
188 0 : return 0;
189 0 : }
190 :
191 : static inline void
192 : handle_new_cluster_contact_info( fd_sender_tile_ctx_t * ctx,
193 : uchar const * buf,
194 0 : ulong buf_sz ) {
195 0 : ulong const * header = (ulong const *)fd_type_pun_const( buf );
196 :
197 0 : ulong dest_cnt = buf_sz;
198 :
199 0 : if( dest_cnt >= MAX_SHRED_DESTS )
200 0 : FD_LOG_ERR(( "Cluster nodes had %lu destinations, which was more than the max of %lu", dest_cnt, MAX_SHRED_DESTS ));
201 :
202 0 : fd_shred_dest_wire_t const * in_dests = fd_type_pun_const( header );
203 0 : fd_shred_dest_weighted_t * dests = fd_stake_ci_dest_add_init( ctx->stake_ci );
204 :
205 0 : ctx->new_dest_ptr = dests;
206 0 : ctx->new_dest_cnt = dest_cnt;
207 :
208 0 : for( ulong i=0UL; i<dest_cnt; i++ ) {
209 0 : memcpy( dests[i].pubkey.uc, in_dests[i].pubkey, 32UL );
210 0 : dests[i].ip4 = in_dests[i].ip4_addr;
211 0 : dests[i].port = in_dests[i].udp_port;
212 0 : }
213 0 : }
214 :
215 : static inline void
216 0 : finalize_new_cluster_contact_info( fd_sender_tile_ctx_t * ctx ) {
217 0 : fd_stake_ci_dest_add_fini( ctx->stake_ci, ctx->new_dest_cnt );
218 0 : }
219 :
220 : static void
221 : during_frag( fd_sender_tile_ctx_t * ctx,
222 : ulong in_idx,
223 : ulong seq FD_PARAM_UNUSED,
224 : ulong sig FD_PARAM_UNUSED,
225 : ulong chunk,
226 : ulong sz,
227 0 : ulong ctl FD_PARAM_UNUSED ) {
228 :
229 0 : if( FD_UNLIKELY( in_idx==ctx->sign_in_idx ) ) {
230 0 : FD_LOG_CRIT(( "signing tile send out of band fragment" ));
231 0 : }
232 :
233 0 : if( FD_UNLIKELY( in_idx==ctx->stake_in_idx ) ) {
234 0 : if( FD_UNLIKELY( chunk<ctx->stake_in_chunk0 || chunk>ctx->stake_in_wmark ) )
235 0 : FD_LOG_ERR(( "chunk %lu %lu corrupt, not in range [%lu,%lu]", chunk, sz,
236 0 : ctx->stake_in_chunk0, ctx->stake_in_wmark ));
237 0 : uchar const * dcache_entry = fd_chunk_to_laddr_const( ctx->stake_in_mem, chunk );
238 0 : fd_stake_ci_stake_msg_init( ctx->stake_ci, dcache_entry );
239 0 : }
240 :
241 0 : if( FD_UNLIKELY( in_idx==ctx->contact_in_idx ) ) {
242 0 : if( FD_UNLIKELY( chunk<ctx->contact_in_chunk0 || chunk>ctx->contact_in_wmark ) ) {
243 0 : FD_LOG_ERR(( "chunk %lu %lu corrupt, not in range [%lu,%lu]", chunk, sz, ctx->contact_in_chunk0, ctx->contact_in_wmark ));
244 0 : }
245 :
246 0 : uchar const * dcache_entry = fd_chunk_to_laddr_const( ctx->contact_in_mem, chunk );
247 0 : handle_new_cluster_contact_info( ctx, dcache_entry, sz );
248 0 : }
249 :
250 0 : if( FD_UNLIKELY( in_idx==ctx->replay_in_idx ) ) {
251 0 : if( FD_UNLIKELY( chunk<ctx->replay_in_chunk0 || chunk>ctx->replay_in_wmark || sz!=sizeof(fd_txn_p_t) ) ) {
252 0 : FD_LOG_ERR(( "chunk %lu %lu corrupt, not in range [%lu,%lu]", chunk, sz, ctx->replay_in_chunk0, ctx->replay_in_wmark ));
253 0 : }
254 :
255 0 : uchar const * dcache_entry = fd_chunk_to_laddr_const( ctx->replay_in_mem, chunk );
256 0 : memcpy( ctx->txn_buf, dcache_entry, sz );
257 0 : }
258 0 : }
259 :
260 : static void
261 : after_frag( fd_sender_tile_ctx_t * ctx,
262 : ulong in_idx,
263 : ulong seq,
264 : ulong sig,
265 : ulong sz,
266 : ulong tsorig,
267 : ulong tspub,
268 0 : fd_stem_context_t * stem ) {
269 0 : (void)seq;
270 0 : (void)sig;
271 0 : (void)sz;
272 0 : (void)tsorig;
273 0 : (void)tspub;
274 0 : (void)stem;
275 :
276 0 : if( FD_UNLIKELY( in_idx==ctx->contact_in_idx ) ) {
277 0 : finalize_new_cluster_contact_info( ctx );
278 0 : return;
279 0 : }
280 :
281 0 : if( FD_UNLIKELY( in_idx==ctx->stake_in_idx ) ) {
282 0 : fd_stake_ci_stake_msg_fini( ctx->stake_ci );
283 0 : return;
284 0 : }
285 :
286 0 : if( FD_UNLIKELY( in_idx==ctx->replay_in_idx ) ) {
287 0 : fd_txn_p_t * txn = (fd_txn_p_t *)fd_type_pun(ctx->txn_buf);
288 :
289 : /* sign the txn */
290 0 : uchar * signature = txn->payload + TXN(txn)->signature_off;
291 0 : uchar * message = txn->payload + TXN(txn)->message_off;
292 0 : ulong message_sz = txn->payload_sz - TXN(txn)->message_off;
293 0 : fd_keyguard_client_sign( ctx->keyguard_client, signature, message, message_sz, FD_KEYGUARD_SIGN_TYPE_ED25519 );
294 :
295 0 : uchar * msg_to_gossip = fd_chunk_to_laddr( ctx->gossip_out_mem, ctx->gossip_out_chunk );
296 0 : memcpy( msg_to_gossip, txn->payload, txn->payload_sz );
297 :
298 : /* send to leader */
299 0 : fd_shred_dest_weighted_t * leader_dest = NULL;
300 0 : int res = get_current_leader_tpu_vote_contact( ctx, &leader_dest );
301 : /* TODO: add metrics for successful votes sent and failed votes */
302 0 : if( res==0 ) {
303 0 : send_packet( ctx, leader_dest->ip4, leader_dest->port, msg_to_gossip, txn->payload_sz, 0UL );
304 0 : }
305 :
306 : /* send to gossip */
307 0 : fd_mcache_publish( ctx->gossip_out_mcache, ctx->gossip_out_depth, ctx->gossip_out_seq, 1UL, ctx->gossip_out_chunk,
308 0 : txn->payload_sz, 0UL, 0, 0 );
309 0 : ctx->gossip_out_seq = fd_seq_inc( ctx->gossip_out_seq, 1UL );
310 0 : ctx->gossip_out_chunk = fd_dcache_compact_next( ctx->gossip_out_chunk, txn->payload_sz,
311 0 : ctx->gossip_out_chunk0, ctx->gossip_out_wmark );
312 : /* send to dedup */
313 0 : uchar * msg_to_pack = fd_chunk_to_laddr( ctx->dedup_out_mem, ctx->dedup_out_chunk );
314 0 : memcpy( msg_to_pack, msg_to_gossip, txn->payload_sz );
315 0 : fd_mcache_publish( ctx->dedup_out_mcache, ctx->dedup_out_depth, ctx->dedup_out_seq, 1UL, ctx->dedup_out_chunk,
316 0 : txn->payload_sz, 0UL, 0, 0 );
317 0 : ctx->dedup_out_seq = fd_seq_inc( ctx->dedup_out_seq, 1UL );
318 0 : ctx->dedup_out_chunk = fd_dcache_compact_next( ctx->dedup_out_chunk, txn->payload_sz, ctx->dedup_out_chunk0,
319 0 : ctx->dedup_out_wmark );
320 0 : }
321 0 : }
322 :
323 : static void
324 : privileged_init( fd_topo_t * topo,
325 0 : fd_topo_tile_t * tile ) {
326 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
327 :
328 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
329 0 : fd_sender_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_sender_tile_ctx_t), sizeof(fd_sender_tile_ctx_t) );
330 :
331 0 : if( FD_UNLIKELY( !strcmp( tile->sender.identity_key_path, "" ) ) )
332 0 : FD_LOG_ERR(( "identity_key_path not set" ));
333 :
334 0 : ctx->identity_key[ 0 ] = *(fd_pubkey_t const *)fd_type_pun_const( fd_keyload_load( tile->sender.identity_key_path, /* pubkey only: */ 1 ) );
335 0 : }
336 :
337 : static void
338 : unprivileged_init( fd_topo_t * topo,
339 0 : fd_topo_tile_t * tile ) {
340 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
341 :
342 0 : if( FD_UNLIKELY( !tile->out_cnt ) ) FD_LOG_ERR(( "sender has no primary output link" ));
343 :
344 : /* Scratch mem setup */
345 :
346 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
347 0 : fd_sender_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_sender_tile_ctx_t), sizeof(fd_sender_tile_ctx_t) );
348 : // TODO: set the lo_mark_slot to the actual snapshot slot!
349 0 : ctx->stake_ci = fd_stake_ci_join( fd_stake_ci_new( FD_SCRATCH_ALLOC_APPEND( l, fd_stake_ci_align(), fd_stake_ci_footprint() ), ctx->identity_key ) );
350 0 : void * scratch_smem = FD_SCRATCH_ALLOC_APPEND( l, fd_scratch_smem_align(), fd_scratch_smem_footprint( SCRATCH_MAX ) );
351 0 : void * scratch_fmem = FD_SCRATCH_ALLOC_APPEND( l, fd_scratch_fmem_align(), fd_scratch_fmem_footprint( SCRATCH_DEPTH ) );
352 :
353 : /* scratch space attach */
354 0 : fd_scratch_attach( scratch_smem, scratch_fmem, SCRATCH_MAX, SCRATCH_DEPTH );
355 :
356 0 : ctx->net_id = (ushort)0;
357 :
358 0 : ctx->tpu_serve_addr.addr = tile->sender.ip_addr;
359 0 : ctx->tpu_serve_addr.port = fd_ushort_bswap( tile->sender.tpu_listen_port );
360 0 : fd_ip4_udp_hdr_init( ctx->packet_hdr, FD_TXN_MTU, ctx->tpu_serve_addr.addr, ctx->tpu_serve_addr.port );
361 :
362 0 : ulong poh_slot_obj_id = fd_pod_query_ulong( topo->props, "poh_slot", ULONG_MAX );
363 0 : FD_TEST( poh_slot_obj_id!=ULONG_MAX );
364 0 : ctx->poh_slot = fd_fseq_join( fd_topo_obj_laddr( topo, poh_slot_obj_id ) );
365 :
366 : /* Set up stake input */
367 0 : ctx->stake_in_idx = fd_topo_find_tile_in_link( topo, tile, "stake_out", 0 );
368 0 : FD_TEST( ctx->stake_in_idx!=ULONG_MAX );
369 0 : fd_topo_link_t * stake_in_link = &topo->links[ tile->in_link_id[ ctx->stake_in_idx ] ];
370 0 : ctx->stake_in_mem = topo->workspaces[ topo->objs[ stake_in_link->dcache_obj_id ].wksp_id ].wksp;
371 0 : ctx->stake_in_chunk0 = fd_dcache_compact_chunk0( ctx->stake_in_mem, stake_in_link->dcache );
372 0 : ctx->stake_in_wmark = fd_dcache_compact_wmark( ctx->stake_in_mem, stake_in_link->dcache, stake_in_link->mtu );
373 :
374 : /* Set up contact input */
375 0 : ctx->contact_in_idx = fd_topo_find_tile_in_link( topo, tile, "gossip_voter", 0 );
376 0 : FD_TEST( ctx->contact_in_idx!=ULONG_MAX );
377 0 : fd_topo_link_t * contact_in_link = &topo->links[ tile->in_link_id[ ctx->contact_in_idx ] ];
378 0 : ctx->contact_in_mem = topo->workspaces[ topo->objs[ contact_in_link->dcache_obj_id ].wksp_id ].wksp;
379 0 : ctx->contact_in_chunk0 = fd_dcache_compact_chunk0( ctx->contact_in_mem, contact_in_link->dcache );
380 0 : ctx->contact_in_wmark = fd_dcache_compact_wmark( ctx->contact_in_mem, contact_in_link->dcache, contact_in_link->mtu );
381 :
382 : /* Set up replay tile input */
383 0 : ctx->replay_in_idx = fd_topo_find_tile_in_link( topo, tile, "replay_voter", 0 );
384 0 : FD_TEST( ctx->replay_in_idx!=ULONG_MAX );
385 0 : fd_topo_link_t * replay_in_link = &topo->links[ tile->in_link_id[ ctx->replay_in_idx ] ];
386 0 : ctx->replay_in_mem = topo->workspaces[ topo->objs[ replay_in_link->dcache_obj_id ].wksp_id ].wksp;
387 0 : ctx->replay_in_chunk0 = fd_dcache_compact_chunk0( ctx->replay_in_mem, replay_in_link->dcache );
388 0 : ctx->replay_in_wmark = fd_dcache_compact_wmark( ctx->replay_in_mem, replay_in_link->dcache, replay_in_link->mtu );
389 :
390 : /* Set up repair request output */
391 0 : ctx->gossip_out_idx = fd_topo_find_tile_out_link( topo, tile, "voter_gossip", 0 );
392 0 : FD_TEST( ctx->gossip_out_idx!=ULONG_MAX );
393 0 : fd_topo_link_t * gossip_out_link = &topo->links[ tile->out_link_id[ ctx->gossip_out_idx ] ];
394 0 : ctx->gossip_out_mcache = gossip_out_link->mcache;
395 0 : ctx->gossip_out_sync = fd_mcache_seq_laddr( ctx->gossip_out_mcache );
396 0 : ctx->gossip_out_depth = fd_mcache_depth( ctx->gossip_out_mcache );
397 0 : ctx->gossip_out_seq = fd_mcache_seq_query( ctx->gossip_out_sync );
398 0 : ctx->gossip_out_mem = topo->workspaces[ topo->objs[ gossip_out_link->dcache_obj_id ].wksp_id ].wksp;
399 0 : ctx->gossip_out_chunk0 = fd_dcache_compact_chunk0( ctx->gossip_out_mem, gossip_out_link->dcache );
400 0 : ctx->gossip_out_wmark = fd_dcache_compact_wmark ( ctx->gossip_out_mem, gossip_out_link->dcache, gossip_out_link->mtu );
401 0 : ctx->gossip_out_chunk = ctx->gossip_out_chunk0;
402 :
403 : /* Set up dedup output */
404 0 : ctx->dedup_out_idx = fd_topo_find_tile_out_link( topo, tile, "voter_dedup", 0 );
405 0 : FD_TEST( ctx->dedup_out_idx!=ULONG_MAX );
406 0 : fd_topo_link_t * dedup_out_link = &topo->links[ tile->out_link_id[ ctx->dedup_out_idx ] ];
407 0 : ctx->dedup_out_mcache = dedup_out_link->mcache;
408 0 : ctx->dedup_out_sync = fd_mcache_seq_laddr( ctx->dedup_out_mcache );
409 0 : ctx->dedup_out_depth = fd_mcache_depth( ctx->dedup_out_mcache );
410 0 : ctx->dedup_out_seq = fd_mcache_seq_query( ctx->dedup_out_sync );
411 0 : ctx->dedup_out_mem = topo->workspaces[ topo->objs[ dedup_out_link->dcache_obj_id ].wksp_id ].wksp;
412 0 : ctx->dedup_out_chunk0 = fd_dcache_compact_chunk0( ctx->dedup_out_mem, dedup_out_link->dcache );
413 0 : ctx->dedup_out_wmark = fd_dcache_compact_wmark ( ctx->dedup_out_mem, dedup_out_link->dcache, dedup_out_link->mtu );
414 0 : ctx->dedup_out_chunk = ctx->dedup_out_chunk0;
415 :
416 : /* Set up net output */
417 0 : ctx->net_out_idx = fd_topo_find_tile_out_link( topo, tile, "voter_net", 0 );
418 0 : FD_TEST( ctx->net_out_idx!=ULONG_MAX );
419 0 : fd_topo_link_t * net_out_link = &topo->links[ tile->out_link_id[ ctx->net_out_idx ] ];
420 0 : ctx->net_out_mcache = net_out_link->mcache;
421 0 : ctx->net_out_sync = fd_mcache_seq_laddr( ctx->net_out_mcache );
422 0 : ctx->net_out_depth = fd_mcache_depth( ctx->net_out_mcache );
423 0 : ctx->net_out_seq = fd_mcache_seq_query( ctx->net_out_sync );
424 0 : ctx->net_out_mem = topo->workspaces[ topo->objs[ net_out_link->dcache_obj_id ].wksp_id ].wksp;
425 0 : ctx->net_out_chunk0 = fd_dcache_compact_chunk0( ctx->net_out_mem, net_out_link->dcache );
426 0 : ctx->net_out_wmark = fd_dcache_compact_wmark ( ctx->net_out_mem, net_out_link->dcache, net_out_link->mtu );
427 0 : ctx->net_out_chunk = ctx->net_out_chunk0;
428 :
429 :
430 : /* Set up keyguard(s) */
431 0 : ctx->sign_in_idx = fd_topo_find_tile_in_link( topo, tile, "sign_voter", 0 );
432 0 : ctx->sign_out_idx = fd_topo_find_tile_out_link( topo, tile, "voter_sign", 0 );
433 0 : FD_TEST( ctx->sign_in_idx==( tile->in_cnt-1 ) );
434 :
435 0 : fd_topo_link_t * sign_in = &topo->links[ tile->in_link_id[ ctx->sign_in_idx ] ];
436 0 : fd_topo_link_t * sign_out = &topo->links[ tile->out_link_id[ ctx->sign_out_idx ] ];
437 :
438 0 : if ( fd_keyguard_client_join( fd_keyguard_client_new( ctx->keyguard_client,
439 0 : sign_out->mcache,
440 0 : sign_out->dcache,
441 0 : sign_in->mcache,
442 0 : sign_in->dcache ) )==NULL ) {
443 0 : FD_LOG_ERR(( "Keyguard join failed" ));
444 0 : }
445 0 : ulong scratch_top = FD_SCRATCH_ALLOC_FINI( l, scratch_align() );
446 0 : if( FD_UNLIKELY( scratch_top != (ulong)scratch + scratch_footprint( tile ) ) ) {
447 0 : FD_LOG_ERR(( "scratch overflow %lu %lu %lu", scratch_top - (ulong)scratch - scratch_footprint( tile ), scratch_top, (ulong)scratch + scratch_footprint( tile ) ));
448 0 : }
449 0 : }
450 :
451 :
452 : static ulong
453 : populate_allowed_seccomp( fd_topo_t const * topo,
454 : fd_topo_tile_t const * tile,
455 : ulong out_cnt,
456 0 : struct sock_filter * out ) {
457 0 : (void)topo;
458 0 : (void)tile;
459 :
460 0 : populate_sock_filter_policy_fd_sender_tile( out_cnt, out, (uint)fd_log_private_logfile_fd() );
461 0 : return sock_filter_policy_fd_sender_tile_instr_cnt;
462 0 : }
463 :
464 : static ulong
465 : populate_allowed_fds( fd_topo_t const * topo,
466 : fd_topo_tile_t const * tile,
467 : ulong out_fds_cnt,
468 0 : int * out_fds ) {
469 0 : (void)topo;
470 0 : (void)tile;
471 :
472 0 : if( FD_UNLIKELY( out_fds_cnt<2UL ) ) FD_LOG_ERR(( "out_fds_cnt %lu", out_fds_cnt ));
473 :
474 0 : ulong out_cnt = 0;
475 0 : out_fds[ out_cnt++ ] = 2UL; /* stderr */
476 0 : if( FD_LIKELY( -1!=fd_log_private_logfile_fd() ) )
477 0 : out_fds[ out_cnt++ ] = fd_log_private_logfile_fd(); /* logfile */
478 0 : return out_cnt;
479 0 : }
480 :
481 0 : #define STEM_BURST (1UL)
482 :
483 0 : #define STEM_CALLBACK_CONTEXT_TYPE fd_sender_tile_ctx_t
484 0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_sender_tile_ctx_t)
485 :
486 0 : #define STEM_CALLBACK_DURING_FRAG during_frag
487 0 : #define STEM_CALLBACK_AFTER_FRAG after_frag
488 :
489 : #include "../../disco/stem/fd_stem.c"
490 :
491 : fd_topo_run_tile_t fd_tile_sender = {
492 : .name = "sender",
493 : .loose_footprint = loose_footprint,
494 : .populate_allowed_seccomp = populate_allowed_seccomp,
495 : .populate_allowed_fds = populate_allowed_fds,
496 : .scratch_align = scratch_align,
497 : .scratch_footprint = scratch_footprint,
498 : .privileged_init = privileged_init,
499 : .unprivileged_init = unprivileged_init,
500 : .run = stem_run,
501 : };
|