Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_capture_fd_capture_ctx_h
2 : #define HEADER_fd_src_flamenco_capture_fd_capture_ctx_h
3 :
4 : /* fd_capture_ctx provides a context for capturing Solana runtime data
5 : during transaction execution. The capture system supports two output
6 : modes:
7 :
8 : 1. Buffer mode: writes to a shared memory buffer that is consumed by
9 : a capture tile and subsequently written to a file. This is the
10 : default for live firedancer execution and backtest.
11 :
12 : 2. File mode: writes directly to a file. This is used for single-
13 : threaded harnesses that don't need the capture tile.
14 :
15 : Captured data includes account updates, bank preimages, and other
16 : runtime events in the solcap format. */
17 :
18 : #include "fd_solcap_writer.h"
19 : #include "../../util/fd_util_base.h"
20 : #include "../../util/log/fd_log.h"
21 : #include <sys/types.h>
22 : #include "../../tango/fd_tango_base.h"
23 :
24 : typedef struct fd_capture_link_vt fd_capture_link_vt_t;
25 :
26 : /* fd_capture_link_t is the base type for capture links. It uses a
27 : v-table pattern to support polymorphic write operations to either
28 : buffer or file destinations. */
29 :
30 : struct fd_capture_link {
31 : fd_capture_link_vt_t const * vt; /* Virtual function table for this link type */
32 : };
33 : typedef struct fd_capture_link fd_capture_link_t;
34 :
35 : /* fd_capture_link_buf_t is a capture link that writes to a shared
36 : memory buffer (frag stream). This buffer is consumed by a capture
37 : tile which writes the data to a file. */
38 :
39 : struct fd_capture_link_buf {
40 : fd_capture_link_t base;
41 : ulong idx;
42 : fd_wksp_t * mem;
43 : ulong chunk0;
44 : ulong wmark;
45 : ulong chunk;
46 : fd_frag_meta_t * mcache;
47 : ulong depth;
48 : ulong seq;
49 : ulong * fseq;
50 : };
51 : typedef struct fd_capture_link_buf fd_capture_link_buf_t;
52 :
53 : /* fd_capture_link_file_t is a capture link that writes directly to a
54 : file. Used in single-threaded harness mode. */
55 :
56 : struct fd_capture_link_file {
57 : fd_capture_link_t base;
58 : int fd;
59 : };
60 : typedef struct fd_capture_link_file fd_capture_link_file_t;
61 :
62 : /* fd_capture_link_vt_t is the virtual function table for capture
63 : links. This allows the capture context to write to different
64 : destinations (buffer or file) without needing to check the link type
65 : at each call site. */
66 :
67 : struct fd_capture_link_vt {
68 : void (* write_account_update)( fd_capture_ctx_t * ctx,
69 : ulong txn_idx,
70 : fd_pubkey_t const * key,
71 : fd_solana_account_meta_t const * info,
72 : ulong slot,
73 : uchar const * data,
74 : ulong data_sz);
75 :
76 : void (* write_bank_preimage)( fd_capture_ctx_t * ctx,
77 : ulong slot,
78 : fd_hash_t const * bank_hash,
79 : fd_hash_t const * prev_bank_hash,
80 : fd_hash_t const * accounts_lt_hash_checksum,
81 : fd_hash_t const * poh_hash,
82 : ulong signature_cnt);
83 :
84 : void (* write_stake_rewards_begin)( fd_capture_ctx_t * ctx,
85 : ulong slot,
86 : ulong payout_epoch,
87 : ulong reward_epoch,
88 : ulong inflation_lamports,
89 : ulong total_points);
90 :
91 : void (* write_stake_reward_event)( fd_capture_ctx_t * ctx,
92 : ulong slot,
93 : fd_pubkey_t stake_acc_addr,
94 : fd_pubkey_t vote_acc_addr,
95 : uint commission,
96 : long vote_rewards,
97 : long stake_rewards,
98 : long new_credits_observed );
99 :
100 : void (* write_stake_account_payout)( fd_capture_ctx_t * ctx,
101 : ulong slot,
102 : fd_pubkey_t stake_acc_addr,
103 : ulong update_slot,
104 : ulong lamports,
105 : long lamports_delta,
106 : ulong credits_observed,
107 : long credits_observed_delta,
108 : ulong delegation_stake,
109 : long delegation_stake_delta );
110 : };
111 :
112 :
113 : /* Context needed to do solcap capture during execution of transactions */
114 :
115 : struct fd_capture_ctx {
116 : ulong magic; /* ==FD_CAPTURE_CTX_MAGIC */
117 :
118 : fd_capture_link_t * capture_link;
119 : union {
120 : fd_capture_link_buf_t * buf;
121 : fd_capture_link_file_t * file;
122 : } capctx_type;
123 :
124 : /* Solcap */
125 : ulong solcap_start_slot;
126 : fd_solcap_writer_t * capture;
127 :
128 : ulong current_txn_idx;
129 :
130 : /*======== PROTOBUF ========*/
131 : char const * dump_proto_output_dir;
132 : char const * dump_proto_sig_filter;
133 : ulong dump_proto_start_slot;
134 :
135 : /* Instruction Capture */
136 : int dump_instr_to_pb;
137 :
138 : /* Transaction Capture */
139 : int dump_txn_to_pb;
140 :
141 : /* Block Capture */
142 : int dump_block_to_pb;
143 :
144 : /* Syscall Capture */
145 : int dump_syscall_to_pb;
146 :
147 : /* ELF Capture */
148 : int dump_elf_to_pb;
149 :
150 : };
151 : typedef struct fd_capture_ctx fd_capture_ctx_t;
152 :
153 : static inline ulong
154 0 : fd_capture_ctx_align( void ) {
155 0 : return fd_ulong_max( alignof(fd_capture_ctx_t), fd_solcap_writer_align() );
156 0 : }
157 :
158 : static inline ulong
159 0 : fd_capture_ctx_footprint( void ) {
160 0 : ulong l = FD_LAYOUT_INIT;
161 0 : l = FD_LAYOUT_APPEND ( l, fd_capture_ctx_align(), sizeof(fd_capture_ctx_t) );
162 0 : l = FD_LAYOUT_APPEND ( l, fd_solcap_writer_align(), fd_solcap_writer_footprint() );
163 0 : return FD_LAYOUT_FINI ( l, fd_capture_ctx_align() );
164 0 : }
165 :
166 0 : #define FD_CAPTURE_CTX_MAGIC (0x193ECD2A6C395195UL) /* random */
167 :
168 : FD_PROTOTYPES_BEGIN
169 :
170 : void *
171 : fd_capture_ctx_new( void * mem );
172 :
173 : fd_capture_ctx_t *
174 : fd_capture_ctx_join( void * mem );
175 :
176 : void *
177 : fd_capture_ctx_leave( fd_capture_ctx_t * ctx );
178 :
179 : void *
180 : fd_capture_ctx_delete( void * mem );
181 :
182 : FD_PROTOTYPES_END
183 :
184 : /* Solcap capture link functions
185 :
186 : The following functions write solcap messages to either a buffer or
187 : file. They are used as v-table implementations for the capture link
188 : abstraction.
189 :
190 : For each message type, there are two implementations:
191 : - _buf: writes to a shared memory frag stream (buffer mode)
192 : - _file: writes directly to a file descriptor (file mode)
193 :
194 : The v-table dispatch mechanism automatically selects the correct
195 : implementation based on the link type, so callers use the inline
196 : wrapper functions below instead of calling these directly.
197 :
198 : */
199 :
200 : void
201 : fd_capture_link_write_account_update_buf( fd_capture_ctx_t * ctx,
202 : ulong txn_idx,
203 : fd_pubkey_t const * key,
204 : fd_solana_account_meta_t const * info,
205 : ulong slot,
206 : uchar const * data,
207 : ulong data_sz );
208 :
209 : void
210 : fd_capture_link_write_account_update_file( fd_capture_ctx_t * ctx,
211 : ulong txn_idx,
212 : fd_pubkey_t const * key,
213 : fd_solana_account_meta_t const * info,
214 : ulong slot,
215 : uchar const * data,
216 : ulong data_sz );
217 :
218 : /* fd_capture_link_write_account_update writes an account update to the
219 : capture link. Uses v-table dispatch to automatically route to the
220 : correct implementation (buffer or file) based on the link type. */
221 :
222 : static inline void
223 : fd_capture_link_write_account_update( fd_capture_ctx_t * ctx,
224 : ulong txn_idx,
225 : fd_pubkey_t const * key,
226 : fd_solana_account_meta_t const * info,
227 : ulong slot,
228 : uchar const * data,
229 0 : ulong data_sz ) {
230 0 : FD_TEST( ctx && ctx->capture_link );
231 0 : ctx->capture_link->vt->write_account_update( ctx, txn_idx, key, info, slot, data, data_sz );
232 0 : }
233 :
234 : void
235 : fd_capture_link_write_bank_preimage_buf( fd_capture_ctx_t * ctx,
236 : ulong slot,
237 : fd_hash_t const * bank_hash,
238 : fd_hash_t const * prev_bank_hash,
239 : fd_hash_t const * accounts_lt_hash_checksum,
240 : fd_hash_t const * poh_hash,
241 : ulong signature_cnt );
242 :
243 : void
244 : fd_capture_link_write_bank_preimage_file( fd_capture_ctx_t * ctx,
245 : ulong slot,
246 : fd_hash_t const * bank_hash,
247 : fd_hash_t const * prev_bank_hash,
248 : fd_hash_t const * accounts_lt_hash_checksum,
249 : fd_hash_t const * poh_hash,
250 : ulong signature_cnt );
251 :
252 : /* fd_capture_link_write_bank_preimage writes a bank preimage to the
253 : capture link. Uses v-table dispatch to automatically route to the
254 : correct implementation (buffer or file) based on the link type. */
255 :
256 : static inline void
257 : fd_capture_link_write_bank_preimage( fd_capture_ctx_t * ctx,
258 : ulong slot,
259 : fd_hash_t const * bank_hash,
260 : fd_hash_t const * prev_bank_hash,
261 : fd_hash_t const * accounts_lt_hash_checksum,
262 : fd_hash_t const * poh_hash,
263 0 : ulong signature_cnt ) {
264 0 : FD_TEST( ctx && ctx->capture_link );
265 0 : ctx->capture_link->vt->write_bank_preimage( ctx, slot, bank_hash, prev_bank_hash, accounts_lt_hash_checksum, poh_hash, signature_cnt );
266 0 : }
267 :
268 : /* fd_capture_link_write_stake_rewards_begin writes a stake rewards begin to the
269 : capture link. Uses v-table dispatch to automatically route to the
270 : correct implementation (buffer or file) based on the link type. */
271 :
272 : void
273 : fd_capture_link_write_stake_rewards_begin_buf( fd_capture_ctx_t * ctx,
274 : ulong slot,
275 : ulong payout_epoch,
276 : ulong reward_epoch,
277 : ulong inflation_lamports,
278 : ulong total_points );
279 :
280 : void
281 : fd_capture_link_write_stake_rewards_begin_file( fd_capture_ctx_t * ctx,
282 : ulong slot,
283 : ulong payout_epoch,
284 : ulong reward_epoch,
285 : ulong inflation_lamports,
286 : ulong total_points );
287 :
288 : static inline void
289 : fd_capture_link_write_stake_rewards_begin( fd_capture_ctx_t * ctx,
290 : ulong slot,
291 : ulong payout_epoch,
292 : ulong reward_epoch,
293 : ulong inflation_lamports,
294 0 : ulong total_points ) {
295 0 : FD_TEST( ctx && ctx->capture_link );
296 0 : ctx->capture_link->vt->write_stake_rewards_begin( ctx, slot, payout_epoch, reward_epoch, inflation_lamports, total_points );
297 0 : }
298 :
299 : void
300 : fd_capture_link_write_stake_reward_event_buf( fd_capture_ctx_t * ctx,
301 : ulong slot,
302 : fd_pubkey_t stake_acc_addr,
303 : fd_pubkey_t vote_acc_addr,
304 : uint commission,
305 : long vote_rewards,
306 : long stake_rewards,
307 : long new_credits_observed );
308 :
309 : void
310 : fd_capture_link_write_stake_reward_event_file( fd_capture_ctx_t * ctx,
311 : ulong slot,
312 : fd_pubkey_t stake_acc_addr,
313 : fd_pubkey_t vote_acc_addr,
314 : uint commission,
315 : long vote_rewards,
316 : long stake_rewards,
317 : long new_credits_observed );
318 :
319 : static inline void
320 : fd_capture_link_write_stake_reward_event( fd_capture_ctx_t * ctx,
321 : ulong slot,
322 : fd_pubkey_t stake_acc_addr,
323 : fd_pubkey_t vote_acc_addr,
324 : uint commission,
325 : long vote_rewards,
326 : long stake_rewards,
327 0 : long new_credits_observed ) {
328 0 : FD_TEST( ctx && ctx->capture_link );
329 0 : ctx->capture_link->vt->write_stake_reward_event( ctx, slot, stake_acc_addr, vote_acc_addr, commission, vote_rewards, stake_rewards, new_credits_observed );
330 0 : }
331 :
332 : void
333 : fd_capture_link_write_stake_account_payout_buf( fd_capture_ctx_t * ctx,
334 : ulong slot,
335 : fd_pubkey_t stake_acc_addr,
336 : ulong update_slot,
337 : ulong lamports,
338 : long lamports_delta,
339 : ulong credits_observed,
340 : long credits_observed_delta,
341 : ulong delegation_stake,
342 : long delegation_stake_delta );
343 : void
344 : fd_capture_link_write_stake_account_payout_file( fd_capture_ctx_t * ctx,
345 : ulong slot,
346 : fd_pubkey_t stake_acc_addr,
347 : ulong update_slot,
348 : ulong lamports,
349 : long lamports_delta,
350 : ulong credits_observed,
351 : long credits_observed_delta,
352 : ulong delegation_stake,
353 : long delegation_stake_delta );
354 :
355 : static inline void
356 : fd_capture_link_write_stake_account_payout( fd_capture_ctx_t * ctx,
357 : ulong slot,
358 : fd_pubkey_t stake_acc_addr,
359 : ulong update_slot,
360 : ulong lamports,
361 : long lamports_delta,
362 : ulong credits_observed,
363 : long credits_observed_delta,
364 : ulong delegation_stake,
365 0 : long delegation_stake_delta ) {
366 0 : FD_TEST( ctx && ctx->capture_link );
367 0 : ctx->capture_link->vt->write_stake_account_payout( ctx, slot, stake_acc_addr, update_slot, lamports, lamports_delta, credits_observed, credits_observed_delta, delegation_stake, delegation_stake_delta );
368 0 : }
369 :
370 : /* fd_capture_link_buf_vt is the v-table for buffer mode capture links.
371 : It routes all write operations to the buffer implementations. */
372 :
373 : static const
374 : fd_capture_link_vt_t fd_capture_link_buf_vt = {
375 : .write_account_update = fd_capture_link_write_account_update_buf,
376 : .write_bank_preimage = fd_capture_link_write_bank_preimage_buf,
377 : .write_stake_rewards_begin = fd_capture_link_write_stake_rewards_begin_buf,
378 : .write_stake_reward_event = fd_capture_link_write_stake_reward_event_buf,
379 : .write_stake_account_payout = fd_capture_link_write_stake_account_payout_buf,
380 : };
381 :
382 : /* fd_capture_link_file_vt is the v-table for file mode capture links.
383 : It routes all write operations to the file implementations. */
384 :
385 : static const
386 : fd_capture_link_vt_t fd_capture_link_file_vt = {
387 : .write_account_update = fd_capture_link_write_account_update_file,
388 : .write_bank_preimage = fd_capture_link_write_bank_preimage_file,
389 : .write_stake_rewards_begin = fd_capture_link_write_stake_rewards_begin_file,
390 : .write_stake_reward_event = fd_capture_link_write_stake_reward_event_file,
391 : .write_stake_account_payout = fd_capture_link_write_stake_account_payout_file,
392 : };
393 :
394 : #endif /* HEADER_fd_src_flamenco_capture_fd_capture_ctx_h */
395 :
|