Line data Source code
1 : #ifndef HEADER_fd_src_disco_gui_fd_gui_h
2 : #define HEADER_fd_src_disco_gui_fd_gui_h
3 :
4 : #include "../fd_disco_base.h"
5 :
6 : #include "../pack/fd_microblock.h"
7 : #include "../../waltz/http/fd_http_server.h"
8 : #include "../../flamenco/leaders/fd_leaders.h"
9 :
10 : #include "../topo/fd_topo.h"
11 :
12 0 : #define FD_GUI_SLOTS_CNT (864000UL)
13 0 : #define FD_GUI_TPS_HISTORY_WINDOW_DURATION_SECONDS (10L) /* 10 second moving average */
14 0 : #define FD_GUI_TPS_HISTORY_SAMPLE_CNT (150UL)
15 0 : #define FD_GUI_TILE_TIMER_SNAP_CNT (512UL)
16 0 : #define FD_GUI_TILE_TIMER_LEADER_CNT (4096UL)
17 0 : #define FD_GUI_TILE_TIMER_LEADER_DOWNSAMPLE_CNT (50UL)
18 : #define FD_GUI_TILE_TIMER_TILE_CNT (128UL)
19 : #define FD_GUI_MAX_PEER_CNT (40200UL)
20 :
21 0 : #define FD_GUI_SLOT_LEVEL_INCOMPLETE (0)
22 0 : #define FD_GUI_SLOT_LEVEL_COMPLETED (1)
23 0 : #define FD_GUI_SLOT_LEVEL_OPTIMISTICALLY_CONFIRMED (2)
24 0 : #define FD_GUI_SLOT_LEVEL_ROOTED (3)
25 0 : #define FD_GUI_SLOT_LEVEL_FINALIZED (4)
26 :
27 0 : #define FD_GUI_VOTE_STATE_NON_VOTING (0)
28 0 : #define FD_GUI_VOTE_STATE_VOTING (1)
29 0 : #define FD_GUI_VOTE_STATE_DELINQUENT (2)
30 :
31 0 : #define FD_GUI_START_PROGRESS_TYPE_INITIALIZING ( 0)
32 0 : #define FD_GUI_START_PROGRESS_TYPE_SEARCHING_FOR_FULL_SNAPSHOT ( 1)
33 0 : #define FD_GUI_START_PROGRESS_TYPE_DOWNLOADING_FULL_SNAPSHOT ( 2)
34 0 : #define FD_GUI_START_PROGRESS_TYPE_SEARCHING_FOR_INCREMENTAL_SNAPSHOT ( 3)
35 0 : #define FD_GUI_START_PROGRESS_TYPE_DOWNLOADING_INCREMENTAL_SNAPSHOT ( 4)
36 0 : #define FD_GUI_START_PROGRESS_TYPE_CLEANING_BLOCK_STORE ( 5)
37 0 : #define FD_GUI_START_PROGRESS_TYPE_CLEANING_ACCOUNTS ( 6)
38 0 : #define FD_GUI_START_PROGRESS_TYPE_LOADING_LEDGER ( 7)
39 0 : #define FD_GUI_START_PROGRESS_TYPE_PROCESSING_LEDGER ( 8)
40 0 : #define FD_GUI_START_PROGRESS_TYPE_STARTING_SERVICES ( 9)
41 0 : #define FD_GUI_START_PROGRESS_TYPE_HALTED (10)
42 0 : #define FD_GUI_START_PROGRESS_TYPE_WAITING_FOR_SUPERMAJORITY (11)
43 0 : #define FD_GUI_START_PROGRESS_TYPE_RUNNING (12)
44 :
45 : /* Ideally, we would store an entire epoch's worth of transactions. If
46 : we assume any given validator will have at most 5% stake, and average
47 : transactions per slot is around 10_000, then an epoch will have about
48 : 432_000*10_000*0.05 transactions (~2^28).
49 :
50 : Unfortunately, the transaction struct is 100+ bytes. If we sized the
51 : array to 2^28 entries then the memory required would be ~26GB. In
52 : order to keep memory usage to a more reasonable level, we'll
53 : arbitrarily use a fourth of that size. */
54 0 : #define FD_GUI_TXN_HISTORY_SZ (1UL<<26UL)
55 :
56 0 : #define FD_GUI_TXN_FLAGS_STARTED ( 1U)
57 0 : #define FD_GUI_TXN_FLAGS_ENDED ( 2U)
58 0 : #define FD_GUI_TXN_FLAGS_IS_SIMPLE_VOTE ( 4U)
59 0 : #define FD_GUI_TXN_FLAGS_FROM_BUNDLE ( 8U)
60 0 : #define FD_GUI_TXN_FLAGS_LANDED_IN_BLOCK (16U)
61 :
62 : struct fd_gui_gossip_peer {
63 : fd_pubkey_t pubkey[ 1 ];
64 : ulong wallclock;
65 : ushort shred_version;
66 :
67 : int has_version;
68 : struct {
69 : ushort major;
70 : ushort minor;
71 : ushort patch;
72 :
73 : int has_commit;
74 : uint commit;
75 :
76 : uint feature_set;
77 : } version;
78 :
79 : struct {
80 : uint ipv4;
81 : ushort port;
82 : } sockets[ 12 ];
83 : };
84 :
85 : struct fd_gui_vote_account {
86 : fd_pubkey_t pubkey[ 1 ];
87 : fd_pubkey_t vote_account[ 1 ];
88 :
89 : ulong activated_stake;
90 : ulong last_vote;
91 : ulong root_slot;
92 : ulong epoch_credits;
93 : uchar commission;
94 : int delinquent;
95 : };
96 :
97 : struct fd_gui_validator_info {
98 : fd_pubkey_t pubkey[ 1 ];
99 :
100 : char name[ 64 ];
101 : char website[ 128 ];
102 : char details[ 256 ];
103 : char icon_uri[ 128 ];
104 : };
105 :
106 : struct fd_gui_txn_waterfall {
107 : struct {
108 : ulong quic;
109 : ulong udp;
110 : ulong gossip;
111 : ulong block_engine;
112 : ulong pack_cranked;
113 : } in;
114 :
115 : struct {
116 : ulong net_overrun;
117 : ulong quic_overrun;
118 : ulong quic_frag_drop;
119 : ulong quic_abandoned;
120 : ulong tpu_quic_invalid;
121 : ulong tpu_udp_invalid;
122 : ulong verify_overrun;
123 : ulong verify_parse;
124 : ulong verify_failed;
125 : ulong verify_duplicate;
126 : ulong dedup_duplicate;
127 : ulong resolv_lut_failed;
128 : ulong resolv_expired;
129 : ulong resolv_ancient;
130 : ulong resolv_no_ledger;
131 : ulong resolv_retained;
132 : ulong pack_invalid;
133 : ulong pack_invalid_bundle;
134 : ulong pack_expired;
135 : ulong pack_retained;
136 : ulong pack_wait_full;
137 : ulong pack_leader_slow;
138 : ulong bank_invalid;
139 : ulong block_success;
140 : ulong block_fail;
141 : } out;
142 : };
143 :
144 : typedef struct fd_gui_txn_waterfall fd_gui_txn_waterfall_t;
145 :
146 : struct fd_gui_tile_timers {
147 : ulong caughtup_housekeeping_ticks;
148 : ulong processing_housekeeping_ticks;
149 : ulong backpressure_housekeeping_ticks;
150 :
151 : ulong caughtup_prefrag_ticks;
152 : ulong processing_prefrag_ticks;
153 : ulong backpressure_prefrag_ticks;
154 :
155 : ulong caughtup_postfrag_ticks;
156 : ulong processing_postfrag_ticks;
157 : };
158 :
159 : typedef struct fd_gui_tile_timers fd_gui_tile_timers_t;
160 :
161 : struct fd_gui_tile_stats {
162 : long sample_time_nanos;
163 :
164 : ulong net_in_rx_bytes; /* Number of bytes received by the net or sock tile*/
165 : ulong quic_conn_cnt; /* Number of active QUIC connections */
166 : ulong verify_drop_cnt; /* Number of transactions dropped by verify tiles */
167 : ulong verify_total_cnt; /* Number of transactions received by verify tiles */
168 : ulong dedup_drop_cnt; /* Number of transactions dropped by dedup tile */
169 : ulong dedup_total_cnt; /* Number of transactions received by dedup tile */
170 : ulong pack_buffer_cnt; /* Number of buffered transactions in the pack tile */
171 : ulong pack_buffer_capacity; /* Total size of the pack transaction buffer */
172 : ulong bank_txn_exec_cnt; /* Number of transactions processed by the bank tile */
173 : ulong net_out_tx_bytes; /* Number of bytes sent by the net or sock tile */
174 : };
175 :
176 : typedef struct fd_gui_tile_stats fd_gui_tile_stats_t;
177 :
178 0 : #define FD_GUI_SLOT_LEADER_UNSTARTED (0UL)
179 0 : #define FD_GUI_SLOT_LEADER_STARTED (1UL)
180 0 : #define FD_GUI_SLOT_LEADER_ENDED (2UL)
181 :
182 : struct fd_gui_slot {
183 : ulong slot;
184 : ulong parent_slot;
185 : uint max_compute_units;
186 : long completed_time;
187 : int mine;
188 : int skipped;
189 : int must_republish;
190 : int level;
191 : uint total_txn_cnt;
192 : uint vote_txn_cnt;
193 : uint failed_txn_cnt;
194 : uint nonvote_failed_txn_cnt;
195 : uint compute_units;
196 : ulong transaction_fee;
197 : ulong priority_fee;
198 : ulong tips;
199 :
200 : uchar leader_state;
201 :
202 : struct {
203 : long leader_start_time; /* UNIX timestamp of when we first became leader in this slot */
204 : long leader_end_time; /* UNIX timestamp of when we stopped being leader in this slot */
205 :
206 : long reference_ticks; /* A somewhat arbitrary reference tickcount, that we use for compressing the tickcounts
207 : of transaction start and end times in this slot. It is, roughly (not exactly), the
208 : minimum of the first transaction start or end tickcount, and the time of the message
209 : from poh to pack telling it to become leader. */
210 : long reference_nanos; /* The UNIX timestamp in nanoseconds of the reference tick value above. */
211 :
212 : uint microblocks_upper_bound; /* An upper bound on the number of microblocks in the slot. If the number of
213 : microblocks observed is equal to this, the slot can be considered over.
214 : Generally, the bound is set to a "final" state by a done packing message,
215 : which sets it to the exact number of microblocks, but sometimes this message
216 : is not sent, if the max upper bound published by poh was already correct. */
217 : uint begin_microblocks; /* The number of microblocks we have seen be started (sent) from pack to banks. */
218 : uint end_microblocks; /* The number of microblocks we have seen be ended (sent) from banks to poh. The
219 : slot is only considered over if the begin and end microblocks seen are both equal
220 : to the microblock upper bound. */
221 :
222 : ulong start_offset; /* The smallest pack transaction index for this slot. The first transaction for this slot will
223 : be written to gui->txs[ start_offset%FD_GUI_TXN_HISTORY_SZ ]. */
224 : ulong end_offset; /* The largest pack transaction index for this slot, plus 1. The last transaction for this
225 : slot will be written to gui->txs[ (start_offset-1)%FD_GUI_TXN_HISTORY_SZ ]. */
226 : } txs;
227 :
228 : fd_gui_txn_waterfall_t waterfall_begin[ 1 ];
229 : fd_gui_txn_waterfall_t waterfall_end[ 1 ];
230 :
231 : fd_gui_tile_stats_t tile_stats_begin[ 1 ];
232 : fd_gui_tile_stats_t tile_stats_end[ 1 ];
233 :
234 : ulong tile_timers_history_idx;
235 : };
236 :
237 : typedef struct fd_gui_slot fd_gui_slot_t;
238 :
239 : struct __attribute__((packed)) fd_gui_txn {
240 : uchar signature[ FD_SHA512_HASH_SZ ];
241 : ulong transaction_fee;
242 : ulong priority_fee;
243 : ulong tips;
244 : long timestamp_arrival_nanos;
245 :
246 : /* compute_units_requested has both execution and non-execution cus */
247 : uint compute_units_requested : 21; /* <= 1.4M */
248 : uint compute_units_consumed : 21; /* <= 1.4M */
249 : uint bank_idx : 6; /* in [0, 64) */
250 : uint error_code : 6; /* in [0, 64) */
251 : int timestamp_delta_start_nanos;
252 : int timestamp_delta_end_nanos;
253 :
254 : /* txn_{}_pct is used as a fraction of the total microblock
255 : duration. For example, txn_load_end_pct can be used to find the
256 : time when this transaction started executing:
257 :
258 : timestamp_delta_start_exec_nanos = (
259 : (timestamp_delta_end_nanos-timestamp_delta_start_nanos) *
260 : ((double)txn_{}_pct/USHORT_MAX)
261 : ) */
262 : uchar txn_start_pct;
263 : uchar txn_load_end_pct;
264 : uchar txn_end_pct;
265 : uchar txn_preload_end_pct;
266 : uchar flags; /* assigned with the FD_GUI_TXN_FLAGS_* macros */
267 : uint microblock_idx;
268 : };
269 :
270 :
271 : typedef struct fd_gui_txn fd_gui_txn_t;
272 :
273 : struct fd_gui {
274 : fd_http_server_t * http;
275 : fd_topo_t * topo;
276 :
277 : long next_sample_400millis;
278 : long next_sample_100millis;
279 : long next_sample_10millis;
280 :
281 : ulong debug_in_leader_slot;
282 :
283 : struct {
284 : fd_pubkey_t identity_key[ 1 ];
285 : int has_vote_key;
286 : fd_pubkey_t vote_key[ 1 ];
287 : char vote_key_base58[ FD_BASE58_ENCODED_32_SZ ];
288 : char identity_key_base58[ FD_BASE58_ENCODED_32_SZ ];
289 :
290 : char const * version;
291 : char const * cluster;
292 :
293 : ulong vote_distance;
294 : int vote_state;
295 :
296 : long startup_time_nanos;
297 :
298 : uchar startup_progress;
299 : int startup_got_full_snapshot;
300 :
301 : ulong startup_incremental_snapshot_slot;
302 : uint startup_incremental_snapshot_peer_ip_addr;
303 : ushort startup_incremental_snapshot_peer_port;
304 : double startup_incremental_snapshot_elapsed_secs;
305 : double startup_incremental_snapshot_remaining_secs;
306 : double startup_incremental_snapshot_throughput;
307 : ulong startup_incremental_snapshot_total_bytes;
308 : ulong startup_incremental_snapshot_current_bytes;
309 :
310 : ulong startup_full_snapshot_slot;
311 : uint startup_full_snapshot_peer_ip_addr;
312 : ushort startup_full_snapshot_peer_port;
313 : double startup_full_snapshot_elapsed_secs;
314 : double startup_full_snapshot_remaining_secs;
315 : double startup_full_snapshot_throughput;
316 : ulong startup_full_snapshot_total_bytes;
317 : ulong startup_full_snapshot_current_bytes;
318 :
319 : ulong startup_ledger_slot;
320 : ulong startup_ledger_max_slot;
321 :
322 : ulong startup_waiting_for_supermajority_slot;
323 : ulong startup_waiting_for_supermajority_stake_pct;
324 :
325 : int schedule_strategy;
326 :
327 : ulong identity_account_balance;
328 : ulong vote_account_balance;
329 : ulong estimated_slot_duration_nanos;
330 :
331 : ulong sock_tile_cnt;
332 : ulong net_tile_cnt;
333 : ulong quic_tile_cnt;
334 : ulong verify_tile_cnt;
335 : ulong resolv_tile_cnt;
336 : ulong bank_tile_cnt;
337 : ulong shred_tile_cnt;
338 :
339 : ulong slot_rooted;
340 : ulong slot_optimistically_confirmed;
341 : ulong slot_completed;
342 : ulong slot_estimated;
343 :
344 : ulong estimated_tps_history_idx;
345 : ulong estimated_tps_history[ FD_GUI_TPS_HISTORY_SAMPLE_CNT ][ 3UL ];
346 :
347 : fd_gui_txn_waterfall_t txn_waterfall_reference[ 1 ];
348 : fd_gui_txn_waterfall_t txn_waterfall_current[ 1 ];
349 :
350 : fd_gui_tile_stats_t tile_stats_reference[ 1 ];
351 : fd_gui_tile_stats_t tile_stats_current[ 1 ];
352 :
353 : ulong tile_timers_snap_idx;
354 : ulong tile_timers_snap_idx_slot_start;
355 : /* Temporary storage for samples. Will be downsampled into leader history on slot end. */
356 : fd_gui_tile_timers_t tile_timers_snap[ FD_GUI_TILE_TIMER_SNAP_CNT ][ FD_GUI_TILE_TIMER_TILE_CNT ];
357 : ulong tile_timers_history_idx;
358 : fd_gui_tile_timers_t tile_timers_leader_history[ FD_GUI_TILE_TIMER_LEADER_CNT ][ FD_GUI_TILE_TIMER_LEADER_DOWNSAMPLE_CNT ][ FD_GUI_TILE_TIMER_TILE_CNT ];
359 : ulong tile_timers_leader_history_slot_sample_cnt[ FD_GUI_TILE_TIMER_LEADER_CNT ];
360 : ulong tile_timers_leader_history_slot[ FD_GUI_TILE_TIMER_LEADER_CNT ];
361 : } summary;
362 :
363 : fd_gui_slot_t slots[ FD_GUI_SLOTS_CNT ][ 1 ];
364 :
365 : ulong pack_txn_idx; /* The pack index of the most recently received transaction */
366 : fd_gui_txn_t txs[ FD_GUI_TXN_HISTORY_SZ ][ 1 ];
367 : struct {
368 : int has_block_engine;
369 : char name[ 16 ];
370 : char url[ 256 ];
371 : char ip_cstr[ 40 ]; /* IPv4 or IPv6 cstr */
372 : int status;
373 : } block_engine;
374 :
375 : struct {
376 : int has_epoch[ 2 ];
377 :
378 : struct {
379 : ulong epoch;
380 : long start_time;
381 : long end_time;
382 :
383 : ulong my_total_slots;
384 : ulong my_skipped_slots;
385 :
386 : ulong start_slot;
387 : ulong end_slot;
388 : ulong excluded_stake;
389 : fd_epoch_leaders_t * lsched;
390 : uchar __attribute__((aligned(FD_EPOCH_LEADERS_ALIGN))) _lsched[ FD_EPOCH_LEADERS_FOOTPRINT(50000UL, 432000UL) ];
391 : fd_stake_weight_t stakes[ 50000UL ];
392 : } epochs[ 2 ];
393 : } epoch;
394 :
395 : struct {
396 : ulong peer_cnt;
397 : struct fd_gui_gossip_peer peers[ FD_GUI_MAX_PEER_CNT ];
398 : } gossip;
399 :
400 : struct {
401 : ulong vote_account_cnt;
402 : struct fd_gui_vote_account vote_accounts[ FD_GUI_MAX_PEER_CNT ];
403 : } vote_account;
404 :
405 : struct {
406 : ulong info_cnt;
407 : struct fd_gui_validator_info info[ FD_GUI_MAX_PEER_CNT ];
408 : } validator_info;
409 : };
410 :
411 : typedef struct fd_gui fd_gui_t;
412 :
413 : FD_PROTOTYPES_BEGIN
414 :
415 : FD_FN_CONST ulong
416 : fd_gui_align( void );
417 :
418 : FD_FN_CONST ulong
419 : fd_gui_footprint( void );
420 :
421 : void *
422 : fd_gui_new( void * shmem,
423 : fd_http_server_t * http,
424 : char const * version,
425 : char const * cluster,
426 : uchar const * identity_key,
427 : int has_vote_key,
428 : uchar const * vote_key,
429 : int is_voting,
430 : int schedule_strategy,
431 : fd_topo_t * topo );
432 :
433 : fd_gui_t *
434 : fd_gui_join( void * shmem );
435 :
436 : void
437 : fd_gui_set_identity( fd_gui_t * gui,
438 : uchar const * identity_pubkey );
439 :
440 : void
441 : fd_gui_ws_open( fd_gui_t * gui,
442 : ulong conn_id );
443 :
444 : int
445 : fd_gui_ws_message( fd_gui_t * gui,
446 : ulong ws_conn_id,
447 : uchar const * data,
448 : ulong data_len );
449 :
450 : void
451 : fd_gui_plugin_message( fd_gui_t * gui,
452 : ulong plugin_msg,
453 : uchar const * msg );
454 :
455 : void
456 : fd_gui_became_leader( fd_gui_t * gui,
457 : long tickcount,
458 : ulong slot,
459 : long start_time_nanos,
460 : long end_time_nanos,
461 : ulong max_compute_units,
462 : ulong max_microblocks );
463 :
464 : void
465 : fd_gui_unbecame_leader( fd_gui_t * gui,
466 : long tickcount,
467 : ulong slot,
468 : ulong microblocks_in_slot );
469 :
470 : void
471 : fd_gui_microblock_execution_begin( fd_gui_t * gui,
472 : long tickcount,
473 : ulong _slot,
474 : fd_txn_p_t * txns,
475 : ulong txn_cnt,
476 : uint microblock_idx,
477 : ulong pack_txn_idx );
478 :
479 : void
480 : fd_gui_microblock_execution_end( fd_gui_t * gui,
481 : long tickcount,
482 : ulong bank_idx,
483 : ulong _slot,
484 : ulong txn_cnt,
485 : fd_txn_p_t * txns,
486 : ulong pack_txn_idx,
487 : uchar txn_start_pct,
488 : uchar txn_load_end_pct,
489 : uchar txn_end_pct,
490 : uchar txn_preload_end_pct,
491 : ulong tips );
492 :
493 : int
494 : fd_gui_poll( fd_gui_t * gui );
495 :
496 : FD_PROTOTYPES_END
497 :
498 : #endif /* HEADER_fd_src_disco_gui_fd_gui_h */
|