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 : char identity_key_base58[ FD_BASE58_ENCODED_32_SZ ];
286 :
287 : char const * version;
288 : char const * cluster;
289 :
290 : ulong vote_distance;
291 : int vote_state;
292 :
293 : long startup_time_nanos;
294 :
295 : uchar startup_progress;
296 : int startup_got_full_snapshot;
297 :
298 : ulong startup_incremental_snapshot_slot;
299 : uint startup_incremental_snapshot_peer_ip_addr;
300 : ushort startup_incremental_snapshot_peer_port;
301 : double startup_incremental_snapshot_elapsed_secs;
302 : double startup_incremental_snapshot_remaining_secs;
303 : double startup_incremental_snapshot_throughput;
304 : ulong startup_incremental_snapshot_total_bytes;
305 : ulong startup_incremental_snapshot_current_bytes;
306 :
307 : ulong startup_full_snapshot_slot;
308 : uint startup_full_snapshot_peer_ip_addr;
309 : ushort startup_full_snapshot_peer_port;
310 : double startup_full_snapshot_elapsed_secs;
311 : double startup_full_snapshot_remaining_secs;
312 : double startup_full_snapshot_throughput;
313 : ulong startup_full_snapshot_total_bytes;
314 : ulong startup_full_snapshot_current_bytes;
315 :
316 : ulong startup_ledger_slot;
317 : ulong startup_ledger_max_slot;
318 :
319 : ulong startup_waiting_for_supermajority_slot;
320 : ulong startup_waiting_for_supermajority_stake_pct;
321 :
322 : int schedule_strategy;
323 :
324 : ulong identity_account_balance;
325 : ulong vote_account_balance;
326 : ulong estimated_slot_duration_nanos;
327 :
328 : ulong sock_tile_cnt;
329 : ulong net_tile_cnt;
330 : ulong quic_tile_cnt;
331 : ulong verify_tile_cnt;
332 : ulong resolv_tile_cnt;
333 : ulong bank_tile_cnt;
334 : ulong shred_tile_cnt;
335 :
336 : ulong slot_rooted;
337 : ulong slot_optimistically_confirmed;
338 : ulong slot_completed;
339 : ulong slot_estimated;
340 :
341 : ulong estimated_tps_history_idx;
342 : ulong estimated_tps_history[ FD_GUI_TPS_HISTORY_SAMPLE_CNT ][ 3UL ];
343 :
344 : fd_gui_txn_waterfall_t txn_waterfall_reference[ 1 ];
345 : fd_gui_txn_waterfall_t txn_waterfall_current[ 1 ];
346 :
347 : fd_gui_tile_stats_t tile_stats_reference[ 1 ];
348 : fd_gui_tile_stats_t tile_stats_current[ 1 ];
349 :
350 : ulong tile_timers_snap_idx;
351 : ulong tile_timers_snap_idx_slot_start;
352 : /* Temporary storage for samples. Will be downsampled into leader history on slot end. */
353 : fd_gui_tile_timers_t tile_timers_snap[ FD_GUI_TILE_TIMER_SNAP_CNT ][ FD_GUI_TILE_TIMER_TILE_CNT ];
354 : ulong tile_timers_history_idx;
355 : 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 ];
356 : ulong tile_timers_leader_history_slot_sample_cnt[ FD_GUI_TILE_TIMER_LEADER_CNT ];
357 : ulong tile_timers_leader_history_slot[ FD_GUI_TILE_TIMER_LEADER_CNT ];
358 : } summary;
359 :
360 : fd_gui_slot_t slots[ FD_GUI_SLOTS_CNT ][ 1 ];
361 :
362 : ulong pack_txn_idx; /* The pack index of the most recently received transaction */
363 : fd_gui_txn_t txs[ FD_GUI_TXN_HISTORY_SZ ][ 1 ];
364 : struct {
365 : int has_block_engine;
366 : char name[ 16 ];
367 : char url[ 256 ];
368 : char ip_cstr[ 40 ]; /* IPv4 or IPv6 cstr */
369 : int status;
370 : } block_engine;
371 :
372 : struct {
373 : int has_epoch[ 2 ];
374 :
375 : struct {
376 : ulong epoch;
377 : long start_time;
378 : long end_time;
379 :
380 : ulong my_total_slots;
381 : ulong my_skipped_slots;
382 :
383 : ulong start_slot;
384 : ulong end_slot;
385 : ulong excluded_stake;
386 : fd_epoch_leaders_t * lsched;
387 : uchar __attribute__((aligned(FD_EPOCH_LEADERS_ALIGN))) _lsched[ FD_EPOCH_LEADERS_FOOTPRINT(50000UL, 432000UL) ];
388 : fd_stake_weight_t stakes[ 50000UL ];
389 : } epochs[ 2 ];
390 : } epoch;
391 :
392 : struct {
393 : ulong peer_cnt;
394 : struct fd_gui_gossip_peer peers[ FD_GUI_MAX_PEER_CNT ];
395 : } gossip;
396 :
397 : struct {
398 : ulong vote_account_cnt;
399 : struct fd_gui_vote_account vote_accounts[ FD_GUI_MAX_PEER_CNT ];
400 : } vote_account;
401 :
402 : struct {
403 : ulong info_cnt;
404 : struct fd_gui_validator_info info[ FD_GUI_MAX_PEER_CNT ];
405 : } validator_info;
406 : };
407 :
408 : typedef struct fd_gui fd_gui_t;
409 :
410 : FD_PROTOTYPES_BEGIN
411 :
412 : FD_FN_CONST ulong
413 : fd_gui_align( void );
414 :
415 : FD_FN_CONST ulong
416 : fd_gui_footprint( void );
417 :
418 : void *
419 : fd_gui_new( void * shmem,
420 : fd_http_server_t * http,
421 : char const * version,
422 : char const * cluster,
423 : uchar const * identity_key,
424 : int is_voting,
425 : int schedule_strategy,
426 : fd_topo_t * topo );
427 :
428 : fd_gui_t *
429 : fd_gui_join( void * shmem );
430 :
431 : void
432 : fd_gui_set_identity( fd_gui_t * gui,
433 : uchar const * identity_pubkey );
434 :
435 : void
436 : fd_gui_ws_open( fd_gui_t * gui,
437 : ulong conn_id );
438 :
439 : int
440 : fd_gui_ws_message( fd_gui_t * gui,
441 : ulong ws_conn_id,
442 : uchar const * data,
443 : ulong data_len );
444 :
445 : void
446 : fd_gui_plugin_message( fd_gui_t * gui,
447 : ulong plugin_msg,
448 : uchar const * msg );
449 :
450 : void
451 : fd_gui_became_leader( fd_gui_t * gui,
452 : long tickcount,
453 : ulong slot,
454 : long start_time_nanos,
455 : long end_time_nanos,
456 : ulong max_compute_units,
457 : ulong max_microblocks );
458 :
459 : void
460 : fd_gui_unbecame_leader( fd_gui_t * gui,
461 : long tickcount,
462 : ulong slot,
463 : ulong microblocks_in_slot );
464 :
465 : void
466 : fd_gui_microblock_execution_begin( fd_gui_t * gui,
467 : long tickcount,
468 : ulong _slot,
469 : fd_txn_p_t * txns,
470 : ulong txn_cnt,
471 : uint microblock_idx,
472 : ulong pack_txn_idx );
473 :
474 : void
475 : fd_gui_microblock_execution_end( fd_gui_t * gui,
476 : long tickcount,
477 : ulong bank_idx,
478 : ulong _slot,
479 : ulong txn_cnt,
480 : fd_txn_p_t * txns,
481 : ulong pack_txn_idx,
482 : uchar txn_start_pct,
483 : uchar txn_load_end_pct,
484 : uchar txn_end_pct,
485 : uchar txn_preload_end_pct,
486 : ulong tips );
487 :
488 : int
489 : fd_gui_poll( fd_gui_t * gui );
490 :
491 : FD_PROTOTYPES_END
492 :
493 : #endif /* HEADER_fd_src_disco_gui_fd_gui_h */
|