Line data Source code
1 : #include "../../disco/tiles.h"
2 : #include "generated/fd_exec_tile_seccomp.h"
3 :
4 : #include "../../util/pod/fd_pod_format.h"
5 : #include "../../flamenco/runtime/context/fd_capture_ctx.h"
6 : #include "../../flamenco/runtime/fd_runtime.h"
7 : #include "../../flamenco/runtime/fd_runtime_public.h"
8 : #include "../../flamenco/runtime/fd_executor.h"
9 : #include "../../flamenco/runtime/fd_hashes.h"
10 :
11 : #include "../../funk/fd_funk.h"
12 :
13 : struct fd_exec_tile_out_ctx {
14 : ulong idx;
15 : fd_wksp_t * mem;
16 : ulong chunk;
17 : ulong chunk0;
18 : ulong wmark;
19 : };
20 : typedef struct fd_exec_tile_out_ctx fd_exec_tile_out_ctx_t;
21 :
22 : struct fd_exec_tile_ctx {
23 :
24 : /* link-related data structures. */
25 : ulong replay_exec_in_idx;
26 : ulong tile_cnt;
27 : ulong tile_idx;
28 :
29 : fd_wksp_t * replay_in_mem;
30 : ulong replay_in_chunk0;
31 : ulong replay_in_wmark;
32 :
33 : fd_exec_tile_out_ctx_t exec_writer_out[ 1 ];
34 : uchar boot_msg_sent;
35 :
36 : /* Runtime public and local joins of its members. */
37 : fd_wksp_t * runtime_public_wksp;
38 : fd_runtime_public_t * runtime_public;
39 :
40 : /* Shared bank hash cmp object. */
41 : fd_bank_hash_cmp_t * bank_hash_cmp;
42 :
43 : fd_spad_t * exec_spad;
44 : fd_wksp_t * exec_spad_wksp;
45 :
46 : fd_funk_t funk[1];
47 :
48 : /* Data structures related to managing and executing the transaction.
49 : The fd_txn_p_t is refreshed with every transaction and is sent
50 : from the dispatch/replay tile. The fd_exec_txn_ctx_t * is a valid
51 : local join that lives in the top-most frame of the spad that is
52 : setup when the exec tile is booted; its members are refreshed on
53 : the slot/epoch boundary. */
54 : fd_txn_p_t txn;
55 : fd_exec_txn_ctx_t * txn_ctx;
56 : int exec_res;
57 :
58 : /* The txn/bpf id are sequence numbers. */
59 : /* The txn id is a value that is monotonically increased after
60 : executing a transaction. It is used to prevent race conditions in
61 : interactions between the exec and replay tile. It is expected to
62 : overflow back to 0. */
63 : uint txn_id;
64 : /* The bpf id is the txn_id counterparts for updates to the bpf cache. */
65 : uint bpf_id;
66 :
67 : ulong * exec_fseq;
68 :
69 : /* Pairs len is the number of accounts to hash. */
70 : ulong pairs_len;
71 :
72 : /* Current slot being executed. */
73 : ulong slot;
74 :
75 : /* Current bank being executed. */
76 : fd_banks_t * banks;
77 : fd_bank_t * bank;
78 :
79 : fd_capture_ctx_t * capture_ctx;
80 : };
81 : typedef struct fd_exec_tile_ctx fd_exec_tile_ctx_t;
82 :
83 : FD_FN_CONST static inline ulong
84 0 : scratch_align( void ) {
85 0 : return 128UL;
86 0 : }
87 :
88 : FD_FN_PURE static inline ulong
89 0 : scratch_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED ) {
90 : /* clang-format off */
91 0 : ulong l = FD_LAYOUT_INIT;
92 0 : l = FD_LAYOUT_APPEND( l, alignof(fd_exec_tile_ctx_t), sizeof(fd_exec_tile_ctx_t) );
93 0 : l = FD_LAYOUT_APPEND( l, FD_CAPTURE_CTX_ALIGN, FD_CAPTURE_CTX_FOOTPRINT );
94 0 : return FD_LAYOUT_FINI( l, scratch_align() );
95 : /* clang-format on */
96 0 : }
97 :
98 : static void
99 0 : execute_txn( fd_exec_tile_ctx_t * ctx ) {
100 :
101 0 : FD_SPAD_FRAME_BEGIN( ctx->exec_spad ) {
102 :
103 : /* Query the funk transaction for the given slot. */
104 0 : fd_funk_txn_map_t * txn_map = fd_funk_txn_map( ctx->funk );
105 0 : if( FD_UNLIKELY( !txn_map->map ) ) {
106 0 : FD_LOG_ERR(( "Could not find valid funk transaction map" ));
107 0 : }
108 0 : fd_funk_txn_xid_t xid = { .ul = { ctx->slot, ctx->slot } };
109 0 : fd_funk_txn_start_read( ctx->funk );
110 0 : fd_funk_txn_t * funk_txn = fd_funk_txn_query( &xid, txn_map );
111 0 : if( FD_UNLIKELY( !funk_txn ) ) {
112 0 : FD_LOG_ERR(( "Could not find valid funk transaction" ));
113 0 : }
114 0 : fd_funk_txn_end_read( ctx->funk );
115 0 : ctx->txn_ctx->funk_txn = funk_txn;
116 :
117 : /* Get the bank for the given slot. */
118 0 : fd_banks_lock( ctx->banks );
119 0 : ctx->bank = fd_banks_get_bank( ctx->banks, ctx->slot );
120 0 : if( FD_UNLIKELY( !ctx->bank ) ) {
121 0 : FD_LOG_ERR(( "Could not get bank for slot %lu", ctx->slot ));
122 0 : }
123 :
124 : /* Setup and execute the transaction.*/
125 0 : ctx->txn_ctx->bank = ctx->bank;
126 0 : ctx->txn_ctx->slot = fd_bank_slot_get( ctx->bank );
127 0 : ctx->txn_ctx->features = fd_bank_features_get( ctx->bank );
128 :
129 0 : fd_execute_txn_task_info_t task_info = {
130 0 : .txn_ctx = ctx->txn_ctx,
131 0 : .exec_res = 0,
132 0 : .txn = &ctx->txn,
133 0 : };
134 :
135 0 : fd_txn_t const * txn_descriptor = TXN( task_info.txn );
136 0 : fd_rawtxn_b_t raw_txn = {
137 0 : .raw = task_info.txn->payload,
138 0 : .txn_sz = (ushort)task_info.txn->payload_sz
139 0 : };
140 :
141 0 : task_info.txn->flags = FD_TXN_P_FLAGS_SANITIZE_SUCCESS;
142 :
143 0 : fd_exec_txn_ctx_setup( ctx->txn_ctx, txn_descriptor, &raw_txn );
144 0 : ctx->txn_ctx->capture_ctx = ctx->capture_ctx;
145 :
146 : /* Set up the core account keys. These are the account keys directly
147 : passed in via the serialized transaction, represented as an array.
148 : Note that this does not include additional keys referenced in
149 : address lookup tables. */
150 0 : fd_executor_setup_txn_account_keys( ctx->txn_ctx );
151 :
152 0 : if( FD_UNLIKELY( fd_executor_txn_verify( ctx->txn_ctx )!=0 ) ) {
153 0 : FD_LOG_WARNING(( "sigverify failed: %s", FD_BASE58_ENC_64_ALLOCA( (uchar *)ctx->txn_ctx->_txn_raw->raw+ctx->txn_ctx->txn_descriptor->signature_off ) ));
154 0 : task_info.txn->flags = 0U;
155 0 : task_info.exec_res = FD_RUNTIME_TXN_ERR_SIGNATURE_FAILURE;
156 0 : fd_banks_unlock( ctx->banks );
157 0 : return;
158 0 : }
159 :
160 0 : fd_runtime_pre_execute_check( &task_info );
161 0 : if( FD_UNLIKELY( !( task_info.txn->flags & FD_TXN_P_FLAGS_SANITIZE_SUCCESS ) ) ) {
162 0 : fd_banks_unlock( ctx->banks );
163 0 : return;
164 0 : }
165 :
166 : /* Execute */
167 0 : task_info.txn->flags |= FD_TXN_P_FLAGS_EXECUTE_SUCCESS;
168 0 : ctx->exec_res = fd_execute_txn( &task_info );
169 :
170 0 : if( FD_LIKELY( ctx->exec_res==FD_EXECUTOR_INSTR_SUCCESS ) ) {
171 0 : fd_txn_reclaim_accounts( task_info.txn_ctx );
172 0 : }
173 0 : fd_banks_unlock( ctx->banks );
174 :
175 0 : } FD_SPAD_FRAME_END;
176 0 : }
177 :
178 : // TODO: hashing can be moved into the writer tile
179 : static void
180 : hash_accounts( fd_exec_tile_ctx_t * ctx,
181 0 : fd_runtime_public_hash_bank_msg_t * msg ) {
182 :
183 0 : ctx->slot = msg->slot;
184 0 : fd_funk_txn_map_t * txn_map = fd_funk_txn_map( ctx->funk );
185 0 : if( FD_UNLIKELY( !txn_map->map ) ) {
186 0 : FD_LOG_ERR(( "Could not find valid funk transaction map" ));
187 0 : }
188 0 : fd_funk_txn_xid_t xid = { .ul = { ctx->slot, ctx->slot } };
189 0 : fd_funk_txn_start_read( ctx->funk );
190 0 : fd_funk_txn_t * funk_txn = fd_funk_txn_query( &xid, txn_map );
191 0 : if( FD_UNLIKELY( !funk_txn ) ) {
192 0 : FD_LOG_ERR(( "Could not find valid funk transaction" ));
193 0 : }
194 0 : fd_funk_txn_end_read( ctx->funk );
195 0 : ctx->txn_ctx->funk_txn = funk_txn;
196 :
197 0 : fd_banks_lock( ctx->banks );
198 :
199 0 : ctx->bank = fd_banks_get_bank( ctx->banks, ctx->slot );
200 0 : if( FD_UNLIKELY( !ctx->bank ) ) {
201 0 : FD_LOG_ERR(( "Could not get bank for slot %lu", ctx->slot ));
202 0 : }
203 :
204 0 : ctx->txn_ctx->bank = ctx->bank;
205 0 : ctx->txn_ctx->slot = fd_bank_slot_get( ctx->bank );
206 :
207 0 : ulong start_idx = msg->start_idx;
208 0 : ulong end_idx = msg->end_idx;
209 :
210 0 : fd_accounts_hash_task_info_t * task_info = fd_wksp_laddr_fast( ctx->runtime_public_wksp, msg->task_infos_gaddr );
211 0 : if( FD_UNLIKELY( !task_info ) ) {
212 0 : FD_LOG_ERR(( "Unable to join task info array" ));
213 0 : }
214 :
215 0 : if( FD_UNLIKELY( !msg->lthash_gaddr ) ) {
216 0 : FD_LOG_ERR(( "lthash gaddr is zero" ));
217 0 : }
218 0 : fd_lthash_value_t * lthash = fd_wksp_laddr_fast( ctx->runtime_public_wksp, msg->lthash_gaddr );
219 0 : if( FD_UNLIKELY( !lthash ) ) {
220 0 : FD_LOG_ERR(( "Unable to join lthash" ));
221 0 : }
222 0 : fd_lthash_zero( lthash );
223 :
224 0 : for( ulong i=start_idx; i<=end_idx; i++ ) {
225 0 : fd_account_hash( ctx->txn_ctx->funk,
226 0 : ctx->txn_ctx->funk_txn,
227 0 : &task_info[i],
228 0 : lthash,
229 0 : ctx->txn_ctx->slot,
230 0 : &ctx->txn_ctx->features );
231 0 : }
232 :
233 0 : fd_banks_unlock( ctx->banks );
234 0 : }
235 :
236 : static void
237 0 : snap_hash_count( fd_exec_tile_ctx_t * ctx ) {
238 0 : ctx->pairs_len = fd_accounts_sorted_subrange_count( ctx->funk, (uint)ctx->tile_idx, (uint)ctx->tile_cnt );
239 0 : }
240 :
241 : static void
242 : snap_hash_gather( fd_exec_tile_ctx_t * ctx,
243 0 : fd_runtime_public_snap_hash_msg_t * msg ) {
244 :
245 0 : ulong * num_pairs = fd_wksp_laddr_fast( ctx->runtime_public_wksp, msg->num_pairs_out_gaddr );
246 0 : if( FD_UNLIKELY( !num_pairs ) ) {
247 0 : FD_LOG_ERR(( "Unable to join num_pairs" ));
248 0 : }
249 0 : fd_pubkey_hash_pair_t * pairs = fd_wksp_laddr_fast( ctx->runtime_public_wksp, msg->pairs_gaddr );
250 0 : if( FD_UNLIKELY( !pairs ) ) {
251 0 : FD_LOG_ERR(( "Unable to join pairs" ));
252 0 : }
253 0 : fd_lthash_value_t * lthash_value = fd_wksp_laddr_fast( ctx->runtime_public_wksp, msg->lt_hash_value_out_gaddr );
254 0 : if( FD_UNLIKELY( !lthash_value ) ) {
255 0 : FD_LOG_ERR(( "Unable to join lthash values" ));
256 0 : }
257 :
258 0 : fd_accounts_sorted_subrange_gather( ctx->funk, (uint)ctx->tile_idx, (uint)ctx->tile_cnt,
259 0 : num_pairs, lthash_value,
260 0 : pairs, &ctx->runtime_public->features );
261 0 : }
262 :
263 : static void
264 : during_frag( fd_exec_tile_ctx_t * ctx,
265 : ulong in_idx,
266 : ulong seq FD_PARAM_UNUSED,
267 : ulong sig,
268 : ulong chunk,
269 : ulong sz,
270 0 : ulong ctl FD_PARAM_UNUSED ) {
271 :
272 0 : if( FD_LIKELY( in_idx == ctx->replay_exec_in_idx ) ) {
273 0 : if( FD_UNLIKELY( chunk < ctx->replay_in_chunk0 || chunk > ctx->replay_in_wmark ) ) {
274 0 : FD_LOG_ERR(( "chunk %lu %lu corrupt, not in range [%lu,%lu]",
275 0 : chunk,
276 0 : sz,
277 0 : ctx->replay_in_chunk0,
278 0 : ctx->replay_in_wmark ));
279 0 : }
280 :
281 0 : if( FD_LIKELY( sig==EXEC_NEW_TXN_SIG ) ) {
282 0 : fd_runtime_public_txn_msg_t * txn = (fd_runtime_public_txn_msg_t *)fd_chunk_to_laddr( ctx->replay_in_mem, chunk );
283 0 : ctx->txn = txn->txn;
284 0 : ctx->slot = txn->slot;
285 0 : execute_txn( ctx );
286 0 : return;
287 0 : } else if( sig==EXEC_HASH_ACCS_SIG ) {
288 0 : fd_runtime_public_hash_bank_msg_t * msg = fd_chunk_to_laddr( ctx->replay_in_mem, chunk );
289 0 : FD_LOG_DEBUG(( "hash accs=%lu msg recvd", msg->end_idx - msg->start_idx ));
290 0 : hash_accounts( ctx, msg );
291 0 : return;
292 0 : } else if( sig==EXEC_SNAP_HASH_ACCS_CNT_SIG ) {
293 0 : FD_LOG_DEBUG(( "snap hash count msg recvd" ));
294 0 : snap_hash_count( ctx );
295 0 : } else if( sig==EXEC_SNAP_HASH_ACCS_GATHER_SIG ) {
296 0 : fd_runtime_public_snap_hash_msg_t * msg = fd_chunk_to_laddr( ctx->replay_in_mem, chunk );
297 0 : FD_LOG_DEBUG(( "snap hash gather msg recvd" ));
298 0 : snap_hash_gather( ctx, msg );
299 0 : } else {
300 0 : FD_LOG_ERR(( "Unknown signature" ));
301 0 : }
302 0 : }
303 0 : }
304 :
305 : static void
306 : after_frag( fd_exec_tile_ctx_t * ctx,
307 : ulong in_idx FD_PARAM_UNUSED,
308 : ulong seq FD_PARAM_UNUSED,
309 : ulong sig,
310 : ulong sz FD_PARAM_UNUSED,
311 : ulong tsorig,
312 : ulong tspub,
313 0 : fd_stem_context_t * stem ) {
314 :
315 0 : if( sig==EXEC_NEW_TXN_SIG ) {
316 0 : FD_LOG_DEBUG(( "Sending ack for new txn msg" ));
317 : /* At this point we can assume that the transaction is done
318 : executing. A writer tile will be repsonsible for commiting
319 : the transaction back to funk. */
320 0 : ctx->txn_ctx->exec_err = ctx->exec_res;
321 0 : ctx->txn_ctx->flags = ctx->txn.flags;
322 :
323 0 : fd_exec_tile_out_ctx_t * exec_out = ctx->exec_writer_out;
324 :
325 0 : fd_runtime_public_exec_writer_txn_msg_t * msg = fd_type_pun( fd_chunk_to_laddr( exec_out->mem, exec_out->chunk ) );
326 0 : msg->exec_tile_id = (uchar)ctx->tile_idx;
327 0 : msg->txn_id = ctx->txn_id;
328 :
329 0 : fd_stem_publish( stem,
330 0 : exec_out->idx,
331 0 : FD_WRITER_TXN_SIG,
332 0 : exec_out->chunk,
333 0 : sizeof(*msg),
334 0 : 0UL,
335 0 : tsorig,
336 0 : tspub );
337 0 : exec_out->chunk = fd_dcache_compact_next( exec_out->chunk, sizeof(*msg), exec_out->chunk0, exec_out->wmark );
338 :
339 : /* Make sure that the txn/bpf id can never be equal to the sentinel
340 : value (this means that this is unintialized. )*/
341 0 : ctx->txn_id++;
342 0 : if( FD_UNLIKELY( ctx->txn_id==FD_EXEC_ID_SENTINEL ) ) {
343 0 : ctx->txn_id = 0U;
344 0 : }
345 0 : } else if( sig==EXEC_HASH_ACCS_SIG ) {
346 0 : FD_LOG_DEBUG(( "Sending ack for hash accs msg" ));
347 0 : fd_fseq_update( ctx->exec_fseq, fd_exec_fseq_set_hash_done( ctx->slot ) );
348 0 : } else if( sig==EXEC_SNAP_HASH_ACCS_CNT_SIG ) {
349 0 : FD_LOG_NOTICE(( "Sending ack for snap hash count msg pairs_len=%lu", ctx->pairs_len ));
350 0 : fd_fseq_update( ctx->exec_fseq, fd_exec_fseq_set_snap_hash_cnt_done( (uint)ctx->pairs_len ) );
351 0 : } else if( sig==EXEC_SNAP_HASH_ACCS_GATHER_SIG ) {
352 0 : FD_LOG_NOTICE(("Sending ack for snap hash gather msg" ));
353 0 : fd_fseq_update( ctx->exec_fseq, fd_exec_fseq_set_snap_hash_gather_done() );
354 0 : } else {
355 0 : FD_LOG_ERR(( "Unknown message signature" ));
356 0 : }
357 0 : }
358 :
359 : static void
360 : privileged_init( fd_topo_t * topo FD_PARAM_UNUSED,
361 0 : fd_topo_tile_t * tile FD_PARAM_UNUSED ) {
362 0 : }
363 :
364 : static void
365 : unprivileged_init( fd_topo_t * topo,
366 0 : fd_topo_tile_t * tile ) {
367 :
368 : /********************************************************************/
369 : /* validate allocations */
370 : /********************************************************************/
371 :
372 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
373 :
374 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
375 0 : fd_exec_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_tile_ctx_t), sizeof(fd_exec_tile_ctx_t) );
376 0 : void * capture_ctx_mem = FD_SCRATCH_ALLOC_APPEND( l, FD_CAPTURE_CTX_ALIGN, FD_CAPTURE_CTX_FOOTPRINT );
377 0 : ulong scratch_alloc_mem = FD_SCRATCH_ALLOC_FINI( l, scratch_align() );
378 0 : if( FD_UNLIKELY( scratch_alloc_mem - (ulong)scratch - scratch_footprint( tile ) ) ) {
379 0 : FD_LOG_ERR( ( "Scratch_alloc_mem did not match scratch_footprint diff: %lu alloc: %lu footprint: %lu",
380 0 : scratch_alloc_mem - (ulong)scratch - scratch_footprint( tile ),
381 0 : scratch_alloc_mem,
382 0 : (ulong)scratch + scratch_footprint( tile ) ) );
383 0 : }
384 :
385 : /********************************************************************/
386 : /* validate links */
387 : /********************************************************************/
388 :
389 0 : ctx->tile_cnt = fd_topo_tile_name_cnt( topo, tile->name );
390 0 : ctx->tile_idx = tile->kind_id;
391 :
392 : /* First find and setup the in-link from replay to exec. */
393 0 : ctx->replay_exec_in_idx = fd_topo_find_tile_in_link( topo, tile, "replay_exec", ctx->tile_idx );
394 0 : if( FD_UNLIKELY( ctx->replay_exec_in_idx==ULONG_MAX ) ) {
395 0 : FD_LOG_ERR(( "Could not find replay_exec in-link" ));
396 0 : }
397 0 : fd_topo_link_t * replay_exec_in_link = &topo->links[tile->in_link_id[ctx->replay_exec_in_idx]];
398 0 : if( FD_UNLIKELY( !replay_exec_in_link) ) {
399 0 : FD_LOG_ERR(( "Invalid replay_exec in-link" ));
400 0 : }
401 0 : ctx->replay_in_mem = topo->workspaces[topo->objs[replay_exec_in_link->dcache_obj_id].wksp_id].wksp;
402 0 : ctx->replay_in_chunk0 = fd_dcache_compact_chunk0( ctx->replay_in_mem, replay_exec_in_link->dcache );
403 0 : ctx->replay_in_wmark = fd_dcache_compact_wmark( ctx->replay_in_mem,
404 0 : replay_exec_in_link->dcache,
405 0 : replay_exec_in_link->mtu );
406 :
407 : /* Setup out link. */
408 0 : ulong idx = fd_topo_find_tile_out_link( topo, tile, "exec_writer", ctx->tile_idx );
409 0 : fd_topo_link_t * exec_out_link = &topo->links[ tile->out_link_id[ idx ] ];
410 :
411 0 : if( strcmp( exec_out_link->name, "exec_writer" ) ) {
412 0 : FD_LOG_CRIT(("exec_writer link has unexpected name %s", exec_out_link->name ));
413 0 : }
414 :
415 0 : fd_exec_tile_out_ctx_t * exec_out = ctx->exec_writer_out;
416 0 : exec_out->idx = idx;
417 0 : exec_out->mem = topo->workspaces[ topo->objs[ exec_out_link->dcache_obj_id ].wksp_id ].wksp;
418 0 : exec_out->chunk0 = fd_dcache_compact_chunk0( exec_out->mem, exec_out_link->dcache );
419 0 : exec_out->wmark = fd_dcache_compact_wmark( exec_out->mem, exec_out_link->dcache, exec_out_link->mtu );
420 0 : exec_out->chunk = exec_out->chunk0;
421 0 : ctx->boot_msg_sent = 0U;
422 :
423 : /********************************************************************/
424 : /* runtime public */
425 : /********************************************************************/
426 :
427 0 : ulong runtime_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "runtime_pub" );
428 0 : if( FD_UNLIKELY( runtime_obj_id==ULONG_MAX ) ) {
429 0 : FD_LOG_ERR(( "Could not find topology object for runtime public" ));
430 0 : }
431 :
432 0 : ctx->runtime_public_wksp = topo->workspaces[ topo->objs[ runtime_obj_id ].wksp_id ].wksp;
433 0 : if( FD_UNLIKELY( !ctx->runtime_public_wksp ) ) {
434 0 : FD_LOG_ERR(( "No runtime_public workspace" ));
435 0 : }
436 :
437 0 : ctx->runtime_public = fd_runtime_public_join( fd_topo_obj_laddr( topo, runtime_obj_id ) );
438 0 : if( FD_UNLIKELY( !ctx->runtime_public ) ) {
439 0 : FD_LOG_ERR(( "Failed to join runtime public" ));
440 0 : }
441 :
442 : /********************************************************************/
443 : /* banks */
444 : /********************************************************************/
445 :
446 0 : ulong banks_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "banks" );
447 0 : if( FD_UNLIKELY( banks_obj_id==ULONG_MAX ) ) {
448 0 : FD_LOG_ERR(( "Could not find topology object for banks" ));
449 0 : }
450 :
451 0 : ctx->banks = fd_banks_join( fd_topo_obj_laddr( topo, banks_obj_id ) );
452 0 : if( FD_UNLIKELY( !ctx->banks ) ) {
453 0 : FD_LOG_ERR(( "Failed to join banks" ));
454 0 : }
455 :
456 : /********************************************************************/
457 : /* spad allocator */
458 : /********************************************************************/
459 :
460 : /* First join the correct exec spad and hten the correct runtime spad
461 : which lives inside of the runtime public wksp. */
462 :
463 0 : ulong exec_spad_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "exec_spad.%lu", ctx->tile_idx );
464 0 : if( FD_UNLIKELY( exec_spad_obj_id==ULONG_MAX ) ) {
465 0 : FD_LOG_ERR(( "Could not find topology object for exec spad" ));
466 0 : }
467 :
468 0 : ctx->exec_spad = fd_spad_join( fd_topo_obj_laddr( topo, exec_spad_obj_id ) );
469 0 : if( FD_UNLIKELY( !ctx->exec_spad ) ) {
470 0 : FD_LOG_ERR(( "Failed to join exec spad" ));
471 0 : }
472 0 : ctx->exec_spad_wksp = fd_wksp_containing( ctx->exec_spad );
473 :
474 : /********************************************************************/
475 : /* bank hash cmp */
476 : /********************************************************************/
477 :
478 0 : ulong bank_hash_cmp_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "bh_cmp" );
479 0 : if( FD_UNLIKELY( bank_hash_cmp_obj_id==ULONG_MAX ) ) {
480 0 : FD_LOG_ERR(( "Could not find topology object for bank hash cmp" ));
481 0 : }
482 0 : ctx->bank_hash_cmp = fd_bank_hash_cmp_join( fd_topo_obj_laddr( topo, bank_hash_cmp_obj_id ) );
483 0 : if( FD_UNLIKELY( !ctx->bank_hash_cmp ) ) {
484 0 : FD_LOG_ERR(( "Failed to join bank hash cmp" ));
485 0 : }
486 :
487 : /********************************************************************/
488 : /* funk-specific setup */
489 : /********************************************************************/
490 :
491 0 : if( FD_UNLIKELY( !fd_funk_join( ctx->funk, fd_topo_obj_laddr( topo, tile->exec.funk_obj_id ) ) ) ) {
492 0 : FD_LOG_ERR(( "Failed to join database cache" ));
493 0 : }
494 :
495 : /********************************************************************/
496 : /* setup txncache */
497 : /********************************************************************/
498 :
499 : /* TODO: Implement this. */
500 :
501 : /********************************************************************/
502 : /* setup txn ctx */
503 : /********************************************************************/
504 :
505 0 : fd_spad_push( ctx->exec_spad );
506 : // FIXME account for this in exec spad footprint
507 0 : uchar * txn_ctx_mem = fd_spad_alloc_check( ctx->exec_spad, FD_EXEC_TXN_CTX_ALIGN, FD_EXEC_TXN_CTX_FOOTPRINT );
508 0 : ctx->txn_ctx = fd_exec_txn_ctx_join( fd_exec_txn_ctx_new( txn_ctx_mem ), ctx->exec_spad, ctx->exec_spad_wksp );
509 0 : *ctx->txn_ctx->funk = *ctx->funk;
510 :
511 0 : ctx->txn_ctx->runtime_pub_wksp = ctx->runtime_public_wksp;
512 0 : if( FD_UNLIKELY( !ctx->txn_ctx->runtime_pub_wksp ) ) {
513 0 : FD_LOG_ERR(( "Failed to find public wksp" ));
514 0 : }
515 :
516 0 : ctx->txn_ctx->bank_hash_cmp = ctx->bank_hash_cmp;
517 :
518 : /********************************************************************/
519 : /* setup exec fseq */
520 : /********************************************************************/
521 :
522 0 : ulong exec_fseq_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "exec_fseq.%lu", ctx->tile_idx );
523 0 : ctx->exec_fseq = fd_fseq_join( fd_topo_obj_laddr( topo, exec_fseq_id ) );
524 0 : if( FD_UNLIKELY( !ctx->exec_fseq ) ) {
525 0 : FD_LOG_ERR(( "exec tile %lu has no fseq", ctx->tile_idx ));
526 0 : }
527 0 : fd_fseq_update( ctx->exec_fseq, FD_EXEC_STATE_NOT_BOOTED );
528 :
529 : /* Initialize sequence numbers to be 0. */
530 0 : ctx->txn_id = 0U;
531 0 : ctx->bpf_id = 0U;
532 :
533 0 : FD_LOG_INFO(( "Done booting exec tile idx=%lu", ctx->tile_idx ));
534 :
535 0 : if( strlen(tile->exec.dump_proto_dir) > 0 ) {
536 0 : ctx->capture_ctx = fd_capture_ctx_new( capture_ctx_mem );
537 0 : ctx->capture_ctx->dump_proto_output_dir = tile->exec.dump_proto_dir;
538 0 : ctx->capture_ctx->dump_proto_start_slot = tile->exec.capture_start_slot;
539 0 : ctx->capture_ctx->dump_instr_to_pb = tile->exec.dump_instr_to_pb;
540 0 : ctx->capture_ctx->dump_txn_to_pb = tile->exec.dump_txn_to_pb;
541 0 : ctx->capture_ctx->dump_syscall_to_pb = tile->exec.dump_syscall_to_pb;
542 0 : } else {
543 0 : ctx->capture_ctx = NULL;
544 0 : }
545 0 : }
546 :
547 : static void
548 : after_credit( fd_exec_tile_ctx_t * ctx,
549 : fd_stem_context_t * stem,
550 : int * opt_poll_in,
551 0 : int * charge_busy ) {
552 :
553 0 : (void)opt_poll_in;
554 0 : (void)charge_busy;
555 :
556 0 : if( FD_UNLIKELY( !ctx->boot_msg_sent ) ) {
557 :
558 0 : ctx->boot_msg_sent = 1U;
559 :
560 0 : ulong txn_ctx_gaddr = fd_wksp_gaddr( ctx->exec_spad_wksp, ctx->txn_ctx );
561 0 : if( FD_UNLIKELY( !txn_ctx_gaddr ) ) {
562 0 : FD_LOG_CRIT(( "Could not get gaddr for txn_ctx" ));
563 0 : }
564 :
565 0 : ulong exec_spad_gaddr = fd_wksp_gaddr( ctx->exec_spad_wksp, ctx->exec_spad );
566 0 : if( FD_UNLIKELY( !exec_spad_gaddr ) ) {
567 0 : FD_LOG_CRIT(( "Could not get gaddr for exec_spad" ));
568 0 : }
569 :
570 0 : if( FD_UNLIKELY( txn_ctx_gaddr-exec_spad_gaddr>UINT_MAX ) ) {
571 0 : FD_LOG_CRIT(( "txn_ctx offset from exec spad is too large" ));
572 0 : }
573 :
574 0 : uint txn_ctx_offset = (uint)(txn_ctx_gaddr-exec_spad_gaddr);
575 :
576 : /* Notify writer tiles. */
577 :
578 0 : ulong tsorig = fd_frag_meta_ts_comp( fd_tickcount() );
579 :
580 0 : fd_exec_tile_out_ctx_t * exec_out = ctx->exec_writer_out;
581 :
582 0 : fd_runtime_public_exec_writer_boot_msg_t * msg = fd_type_pun( fd_chunk_to_laddr( exec_out->mem, exec_out->chunk ) );
583 :
584 0 : msg->txn_ctx_offset = txn_ctx_offset;
585 :
586 0 : ulong tspub = fd_frag_meta_ts_comp( fd_tickcount() );
587 0 : fd_stem_publish( stem,
588 0 : exec_out->idx,
589 0 : FD_WRITER_BOOT_SIG,
590 0 : exec_out->chunk,
591 0 : sizeof(*msg),
592 0 : 0UL,
593 0 : tsorig,
594 0 : tspub );
595 0 : exec_out->chunk = fd_dcache_compact_next( exec_out->chunk, sizeof(*msg), exec_out->chunk0, exec_out->wmark );
596 :
597 : /* Notify replay tile. */
598 :
599 0 : fd_fseq_update( ctx->exec_fseq, fd_exec_fseq_set_booted( txn_ctx_offset ) );
600 0 : }
601 0 : }
602 :
603 : static ulong
604 : populate_allowed_seccomp( fd_topo_t const * topo,
605 : fd_topo_tile_t const * tile,
606 : ulong out_cnt,
607 0 : struct sock_filter * out ) {
608 0 : (void)topo;
609 0 : (void)tile;
610 :
611 0 : populate_sock_filter_policy_fd_exec_tile( out_cnt, out, (uint)fd_log_private_logfile_fd() );
612 0 : return sock_filter_policy_fd_exec_tile_instr_cnt;
613 0 : }
614 :
615 : static ulong
616 : populate_allowed_fds( fd_topo_t const * topo,
617 : fd_topo_tile_t const * tile,
618 : ulong out_fds_cnt,
619 0 : int * out_fds ) {
620 0 : (void)topo;
621 0 : (void)tile;
622 :
623 0 : if( FD_UNLIKELY( out_fds_cnt<2UL ) ) FD_LOG_ERR(( "out_fds_cnt %lu", out_fds_cnt ));
624 :
625 0 : ulong out_cnt = 0UL;
626 0 : out_fds[ out_cnt++ ] = 2; /* stderr */
627 0 : if( FD_LIKELY( -1!=fd_log_private_logfile_fd() ) )
628 0 : out_fds[ out_cnt++ ] = fd_log_private_logfile_fd(); /* logfile */
629 0 : return out_cnt;
630 0 : }
631 :
632 : /* The stem burst is bound by the max number of exec tiles that are
633 : posible. */
634 0 : #define STEM_BURST (1UL)
635 :
636 0 : #define STEM_CALLBACK_CONTEXT_TYPE fd_exec_tile_ctx_t
637 0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_exec_tile_ctx_t)
638 :
639 0 : #define STEM_CALLBACK_AFTER_CREDIT after_credit
640 0 : #define STEM_CALLBACK_DURING_FRAG during_frag
641 0 : #define STEM_CALLBACK_AFTER_FRAG after_frag
642 :
643 : #include "../../disco/stem/fd_stem.c"
644 :
645 : fd_topo_run_tile_t fd_tile_execor = {
646 : .name = "exec",
647 : .loose_footprint = 0UL,
648 : .populate_allowed_seccomp = populate_allowed_seccomp,
649 : .populate_allowed_fds = populate_allowed_fds,
650 : .scratch_align = scratch_align,
651 : .scratch_footprint = scratch_footprint,
652 : .privileged_init = privileged_init,
653 : .unprivileged_init = unprivileged_init,
654 : .run = stem_run,
655 : };
|