Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/app/firedancer/topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -928,8 +928,9 @@ fd_topo_initialize( config_t * config ) {
FOR(exec_tile_cnt) fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "exec_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );

if( FD_LIKELY( snapshots_enabled ) ) {
/**/ fd_topob_tile_in ( topo, "gui", 0UL, "metric_in", "snapct_gui", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
/**/ fd_topob_tile_in ( topo, "gui", 0UL, "metric_in", "snapin_gui", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
/**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "snapct_gui", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
/**/ fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "snapin_gui", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
fd_topob_tile_in( topo, "gui", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/disco/gui/fd_gui_config_parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct fd_gui_config_parse_info {
char icon_uri[ FD_GUI_CONFIG_PARSE_VALIDATOR_INFO_ICON_URI_SZ + 1UL ];
char keybase_username[ FD_GUI_CONFIG_PARSE_VALIDATOR_INFO_KEYBASE_USERNAME_SZ + 1UL ];

struct { ulong prev, next; } map;
struct { ulong next; } map;
struct { ulong next; } pool;
};

Expand Down
85 changes: 57 additions & 28 deletions src/disco/gui/fd_gui_peers.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ fd_gui_peers_align( void ) {
a = fd_ulong_max( a, fd_gui_peers_live_table_align() );
a = fd_ulong_max( a, fd_gui_peers_bandwidth_tracking_align() );
a = fd_ulong_max( a, fd_gui_peers_node_info_pool_align() );
a = fd_ulong_max( a, fd_gui_peers_node_vote_pool_align() );
a = fd_ulong_max( a, fd_gui_peers_node_info_map_align() );
a = fd_ulong_max( a, fd_gui_peers_node_vote_map_align() );
a = fd_ulong_max( a, fd_gui_peers_node_pubkey_map_align() );
a = fd_ulong_max( a, fd_gui_peers_node_sock_map_align() );
a = fd_ulong_max( a, alignof(fd_gui_peers_ws_conn_t) );
Expand All @@ -30,6 +32,7 @@ fd_gui_peers_align( void ) {
FD_FN_CONST ulong
fd_gui_peers_footprint( ulong max_ws_conn_cnt ) {
ulong info_chain_cnt = fd_gui_peers_node_info_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE );
ulong vote_chain_cnt = fd_gui_peers_node_vote_map_chain_cnt_est ( FD_RUNTIME_MAX_VOTE_ACCOUNTS );
ulong pubkey_chain_cnt = fd_gui_peers_node_pubkey_map_chain_cnt_est( FD_CONTACT_INFO_TABLE_SIZE );
ulong sock_chain_cnt = fd_gui_peers_node_sock_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE );

Expand All @@ -38,11 +41,13 @@ fd_gui_peers_footprint( ulong max_ws_conn_cnt ) {
l = FD_LAYOUT_APPEND( l, fd_gui_peers_live_table_align(), fd_gui_peers_live_table_footprint ( FD_CONTACT_INFO_TABLE_SIZE ) );
l = FD_LAYOUT_APPEND( l, fd_gui_peers_bandwidth_tracking_align(), fd_gui_peers_bandwidth_tracking_footprint( FD_CONTACT_INFO_TABLE_SIZE ) );
l = FD_LAYOUT_APPEND( l, fd_gui_peers_node_info_pool_align(), fd_gui_peers_node_info_pool_footprint ( FD_CONTACT_INFO_TABLE_SIZE ) );
l = FD_LAYOUT_APPEND( l, fd_gui_peers_node_vote_pool_align(), fd_gui_peers_node_vote_pool_footprint ( FD_RUNTIME_MAX_VOTE_ACCOUNTS ) );
l = FD_LAYOUT_APPEND( l, fd_gui_peers_node_info_map_align(), fd_gui_peers_node_info_map_footprint ( info_chain_cnt ) );
l = FD_LAYOUT_APPEND( l, fd_gui_peers_node_vote_map_align(), fd_gui_peers_node_vote_map_footprint ( vote_chain_cnt ) );
l = FD_LAYOUT_APPEND( l, fd_gui_peers_node_pubkey_map_align(), fd_gui_peers_node_pubkey_map_footprint ( pubkey_chain_cnt ) );
l = FD_LAYOUT_APPEND( l, fd_gui_peers_node_sock_map_align(), fd_gui_peers_node_sock_map_footprint ( sock_chain_cnt ) );
l = FD_LAYOUT_APPEND( l, alignof(fd_gui_peers_ws_conn_t), max_ws_conn_cnt*sizeof(fd_gui_peers_ws_conn_t) );
l = FD_LAYOUT_APPEND( l, alignof(fd_gui_ipinfo_node_t), sizeof(fd_gui_ipinfo_node_t)*IPINFO_MAX_NODES );
l = FD_LAYOUT_APPEND( l, alignof(fd_gui_ipinfo_node_t), sizeof(fd_gui_ipinfo_node_t)*IPINFO_MAX_NODES );

return FD_LAYOUT_FINI( l, fd_gui_peers_align() );
}
Expand Down Expand Up @@ -139,6 +144,7 @@ fd_gui_peers_new( void * shmem,
}

ulong info_chain_cnt = fd_gui_peers_node_info_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE );
ulong vote_chain_cnt = fd_gui_peers_node_vote_map_chain_cnt_est ( FD_RUNTIME_MAX_VOTE_ACCOUNTS );
ulong pubkey_chain_cnt = fd_gui_peers_node_pubkey_map_chain_cnt_est( FD_CONTACT_INFO_TABLE_SIZE );
ulong sock_chain_cnt = fd_gui_peers_node_sock_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE );

Expand All @@ -147,7 +153,9 @@ fd_gui_peers_new( void * shmem,
void * _live_table = FD_SCRATCH_ALLOC_APPEND( l, fd_gui_peers_live_table_align(), fd_gui_peers_live_table_footprint ( FD_CONTACT_INFO_TABLE_SIZE ) );
void * _bw_tracking = FD_SCRATCH_ALLOC_APPEND( l, fd_gui_peers_bandwidth_tracking_align(), fd_gui_peers_bandwidth_tracking_footprint( FD_CONTACT_INFO_TABLE_SIZE ) );
void * _info_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_gui_peers_node_info_pool_align(), fd_gui_peers_node_info_pool_footprint ( FD_CONTACT_INFO_TABLE_SIZE ) );
void * _vote_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_gui_peers_node_vote_pool_align(), fd_gui_peers_node_vote_pool_footprint ( FD_RUNTIME_MAX_VOTE_ACCOUNTS ) );
void * _info_map = FD_SCRATCH_ALLOC_APPEND( l, fd_gui_peers_node_info_map_align(), fd_gui_peers_node_info_map_footprint ( info_chain_cnt ) );
void * _vote_map = FD_SCRATCH_ALLOC_APPEND( l, fd_gui_peers_node_vote_map_align(), fd_gui_peers_node_vote_map_footprint ( vote_chain_cnt ) );
void * _pubkey_map = FD_SCRATCH_ALLOC_APPEND( l, fd_gui_peers_node_pubkey_map_align(), fd_gui_peers_node_pubkey_map_footprint ( pubkey_chain_cnt ) );
void * _sock_map = FD_SCRATCH_ALLOC_APPEND( l, fd_gui_peers_node_sock_map_align(), fd_gui_peers_node_sock_map_footprint ( sock_chain_cnt ) );
ctx->client_viewports = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_gui_peers_ws_conn_t), max_ws_conn_cnt*sizeof(fd_gui_peers_ws_conn_t) );
Expand Down Expand Up @@ -178,7 +186,9 @@ fd_gui_peers_new( void * shmem,
fd_gui_peers_bandwidth_tracking_seed( ctx->contact_info_table, FD_CONTACT_INFO_TABLE_SIZE, 42UL );

ctx->node_info_pool = fd_gui_peers_node_info_pool_join ( fd_gui_peers_node_info_pool_new ( _info_pool, FD_CONTACT_INFO_TABLE_SIZE ) );
ctx->node_vote_pool = fd_gui_peers_node_vote_pool_join ( fd_gui_peers_node_vote_pool_new ( _vote_pool, FD_RUNTIME_MAX_VOTE_ACCOUNTS ) );
ctx->node_info_map = fd_gui_peers_node_info_map_join ( fd_gui_peers_node_info_map_new ( _info_map, info_chain_cnt, 42UL ) );
ctx->node_vote_map = fd_gui_peers_node_vote_map_join ( fd_gui_peers_node_vote_map_new ( _vote_map, vote_chain_cnt, 42UL ) );
ctx->node_pubkey_map = fd_gui_peers_node_pubkey_map_join( fd_gui_peers_node_pubkey_map_new( _pubkey_map, pubkey_chain_cnt, 42UL ) );
ctx->node_sock_map = fd_gui_peers_node_sock_map_join ( fd_gui_peers_node_sock_map_new ( _sock_map, sock_chain_cnt, 42UL ) );

Expand Down Expand Up @@ -626,8 +636,9 @@ fd_gui_peers_handle_gossip_update( fd_gui_peers_ctx_t * peers,
memset( &peer->gossip_tx, 0, sizeof(peer->gossip_tx) );
memset( &peer->gossvf_rx_sum, 0, sizeof(peer->gossvf_rx_sum) );
memset( &peer->gossip_tx_sum, 0, sizeof(peer->gossip_tx_sum) );
peer->has_vote_info = 0;
peer->stake = ULONG_MAX;

fd_gui_peers_vote_t * vote = fd_gui_peers_node_vote_map_ele_query( peers->node_vote_map, &update->contact_info.contact_info->pubkey, NULL, peers->node_vote_pool );
peer->stake = FD_LIKELY( vote ) ? vote->stake : ULONG_MAX;

fd_gui_config_parse_info_t * info = fd_gui_peers_node_info_map_ele_query( peers->node_info_map, &update->contact_info.contact_info->pubkey, NULL, peers->node_info_pool );
if( FD_LIKELY( info ) ) fd_memcpy( peer->name, info->name, sizeof(info->name) );
Expand Down Expand Up @@ -722,9 +733,17 @@ void
fd_gui_peers_handle_vote_update( fd_gui_peers_ctx_t * peers,
fd_gui_peers_vote_t * votes,
ulong vote_cnt,
long now,
fd_pubkey_t * identity ) {
(void)now;
if( FD_UNLIKELY( !fd_gui_peers_node_vote_pool_free( peers->node_vote_pool ) ) ) {
FD_LOG_WARNING(( "pool mem exhausted" ));
return;
}

if( FD_UNLIKELY( vote_cnt>FD_RUNTIME_MAX_VOTE_ACCOUNTS ) ) {
FD_LOG_WARNING(( "max vote accounts exceeded" ));
return;
}

fd_gui_peers_vote_t * votes_sorted = votes;
fd_gui_peers_vote_t * votes_scratch = peers->votes_scratch;
fd_memcpy( votes_sorted, votes, vote_cnt*sizeof(fd_gui_peers_vote_t) );
Expand Down Expand Up @@ -785,37 +804,47 @@ fd_gui_peers_handle_vote_update( fd_gui_peers_ctx_t * peers,
fd_http_server_ws_broadcast( peers->http );
}

ulong peer_idx = fd_gui_peers_node_pubkey_map_idx_query( peers->node_pubkey_map, &votes_sorted[ i ].node_account, ULONG_MAX, peers->contact_info_table );
if( FD_UNLIKELY( peer_idx==ULONG_MAX ) ) continue; /* peer not on gossip */

fd_gui_peers_node_t * peer = peers->contact_info_table + peer_idx;

/* TODO: we only publish updates when stake changes, otherwise we'd
have to republish for every peer every slot, which ends up being
too much bandwidth because we republish all the peer info.
Ideally, we decouple the vote updates from the reset of the peer
info which would let us make updates quickly. */
int is_delinquent = ((long)last_vote_slot_p67 - (long)votes_sorted[ i ].last_vote_slot) > 150L;
int vote_eq = peer->has_vote_info
&& !memcmp( peer->vote_account.uc, votes_sorted[ i ].vote_account.uc, sizeof(fd_pubkey_t) )
&& peer->stake ==votes_sorted[ i ].stake
// && peer->last_vote_slot ==votes_sorted[ i ].last_vote_slot
// && peer->last_vote_timestamp ==votes_sorted[ i ].last_vote_timestamp
// && peer->epoch_credits ==votes_sorted[ i ].epoch_credits
&& peer->commission ==votes_sorted[ i ].commission
&& peer->epoch ==votes_sorted[ i ].epoch
&& peer->delinquent ==is_delinquent;
votes_sorted[ i ].delinquent = ((long)last_vote_slot_p67 - (long)votes_sorted[ i ].last_vote_slot) > 150L;

fd_gui_peers_vote_t * vote = fd_gui_peers_node_vote_map_ele_query( peers->node_vote_map, &votes_sorted[ i ].node_account, NULL, peers->node_vote_pool );

int vote_eq = !!vote
&& !memcmp( vote->vote_account.uc, votes_sorted[ i ].vote_account.uc, sizeof(fd_pubkey_t) )
&& vote->stake ==votes_sorted[ i ].stake
// && vote->last_vote_slot ==votes_sorted[ i ].last_vote_slot
// && vote->last_vote_timestamp ==votes_sorted[ i ].last_vote_timestamp
// && vote->epoch_credits ==votes_sorted[ i ].epoch_credits
// && vote->commission ==votes_sorted[ i ].commission
&& vote->epoch ==votes_sorted[ i ].epoch
&& vote->delinquent ==votes_sorted[ i ].delinquent;

if( FD_LIKELY( vote_eq ) ) continue; /* nop */

peer->has_vote_info = 1;
peer->vote_account = votes_sorted[ i ].vote_account;
peer->last_vote_slot = votes_sorted[ i ].last_vote_slot;
peer->last_vote_timestamp = votes_sorted[ i ].last_vote_timestamp;
peer->epoch_credits = votes_sorted[ i ].epoch_credits;
peer->commission = votes_sorted[ i ].commission;
peer->epoch = votes_sorted[ i ].epoch;
peer->delinquent = is_delinquent;
if ( FD_UNLIKELY( !vote ) ) {
vote = fd_gui_peers_node_vote_pool_ele_acquire( peers->node_vote_pool );
fd_memcpy( &vote->node_account, &votes_sorted[ i ].node_account, sizeof(fd_pubkey_t) );
fd_gui_peers_node_vote_map_ele_insert( peers->node_vote_map, vote, peers->node_vote_pool );
}

/* update map entry */
fd_memcpy( vote->vote_account.uc, votes_sorted[ i ].vote_account.uc, sizeof(fd_pubkey_t) );
vote->stake = votes_sorted[ i ].stake;
vote->last_vote_slot = votes_sorted[ i ].last_vote_slot;
vote->last_vote_timestamp = votes_sorted[ i ].last_vote_timestamp;
vote->epoch_credits = votes_sorted[ i ].epoch_credits;
vote->commission = votes_sorted[ i ].commission;
vote->epoch = votes_sorted[ i ].epoch;
vote->delinquent = votes_sorted[ i ].delinquent;

ulong peer_idx = fd_gui_peers_node_pubkey_map_idx_query( peers->node_pubkey_map, &votes_sorted[ i ].node_account, ULONG_MAX, peers->contact_info_table );
if( FD_UNLIKELY( peer_idx==ULONG_MAX ) ) continue; /* peer not on gossip */

fd_gui_peers_node_t * peer = peers->contact_info_table + peer_idx;

if( FD_UNLIKELY( peer->stake!=votes_sorted[ i ].stake ) ) {
fd_gui_peers_live_table_idx_remove( peers->live_table, peer_idx, peers->contact_info_table );
Expand Down
37 changes: 23 additions & 14 deletions src/disco/gui/fd_gui_peers.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ struct fd_gui_peers_vote {
uchar commission;
ulong epoch;
ulong epoch_credits;
int delinquent;

struct { ulong next; } map;
struct { ulong next; } pool;
};

typedef struct fd_gui_peers_vote fd_gui_peers_vote_t;
Expand All @@ -129,17 +133,8 @@ struct fd_gui_peers_node {
fd_gui_peers_metric_rate_t gossvf_rx_sum; /* sum of gossvf_rx */
fd_gui_peers_metric_rate_t gossip_tx_sum; /* sum of gossip_tx */

int has_vote_info;
fd_pubkey_t vote_account;
ulong stake; /* if has_vote_info==0 then stake==ULONG_MAX */
ulong last_vote_slot;
long last_vote_timestamp;
uchar commission;
ulong epoch;
ulong epoch_credits;
uchar country_code_idx;
int delinquent;

ulong stake; /* default ULONG_MAX */
uchar country_code_idx;
struct {
ulong next;
ulong prev;
Expand Down Expand Up @@ -233,16 +228,29 @@ typedef struct fd_gui_peers_gossip_stats fd_gui_peers_gossip_stats_t;
#define POOL_NEXT pool.next
#include "../../util/tmpl/fd_pool.c"

#define POOL_NAME fd_gui_peers_node_vote_pool
#define POOL_T fd_gui_peers_vote_t
#define POOL_NEXT pool.next
#include "../../util/tmpl/fd_pool.c"

#define MAP_NAME fd_gui_peers_node_info_map
#define MAP_ELE_T fd_gui_config_parse_info_t
#define MAP_KEY_T fd_pubkey_t
#define MAP_KEY pubkey
#define MAP_IDX_T ulong
#define MAP_NEXT map.next
#define MAP_PREV map.prev
#define MAP_KEY_HASH(k,s) (fd_hash( (s), (k)->uc, sizeof(fd_pubkey_t) ))
#define MAP_KEY_EQ(k0,k1) (!memcmp((k0)->uc, (k1)->uc, 32UL))
#define MAP_OPTIMIZE_RANDOM_ACCESS_REMOVAL 1
#include "../../util/tmpl/fd_map_chain.c"

#define MAP_NAME fd_gui_peers_node_vote_map
#define MAP_ELE_T fd_gui_peers_vote_t
#define MAP_KEY_T fd_pubkey_t
#define MAP_KEY node_account
#define MAP_IDX_T ulong
#define MAP_NEXT map.next
#define MAP_KEY_HASH(k,s) (fd_hash( (s), (k)->uc, sizeof(fd_pubkey_t) ))
#define MAP_KEY_EQ(k0,k1) (!memcmp((k0)->uc, (k1)->uc, 32UL))
#include "../../util/tmpl/fd_map_chain.c"

#define MAP_NAME fd_gui_peers_node_pubkey_map
Expand Down Expand Up @@ -331,7 +339,9 @@ struct fd_gui_peers_ctx {
long next_gossip_stats_update_nanos; /* ns timestamp when we'll next broadcast out gossip stats message */

fd_gui_config_parse_info_t * node_info_pool;
fd_gui_peers_vote_t * node_vote_pool;
fd_gui_peers_node_info_map_t * node_info_map;
fd_gui_peers_node_vote_map_t * node_vote_map;
fd_gui_peers_node_pubkey_map_t * node_pubkey_map;
fd_gui_peers_node_sock_map_t * node_sock_map;
fd_gui_peers_live_table_t * live_table;
Expand Down Expand Up @@ -410,7 +420,6 @@ void
fd_gui_peers_handle_vote_update( fd_gui_peers_ctx_t * peers,
fd_gui_peers_vote_t * votes,
ulong vote_cnt,
long now,
fd_pubkey_t * identity );

void
Expand Down
15 changes: 8 additions & 7 deletions src/disco/gui/fd_gui_printf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1162,21 +1162,22 @@ peers_printf_node( fd_gui_peers_ctx_t * peers,

jsonp_close_object( peers->http );

if( FD_LIKELY( !peer->has_vote_info ) ) {
fd_gui_peers_vote_t * vote = fd_gui_peers_node_vote_map_ele_query( peers->node_vote_map, &peer->contact_info.pubkey, NULL, peers->node_vote_pool );
if( FD_LIKELY( !vote ) ) {
jsonp_open_array( peers->http, "vote" );
jsonp_close_array( peers->http );
} else {
jsonp_open_array( peers->http, "vote" );
jsonp_open_object( peers->http, NULL );
char vote_account_base58[ FD_BASE58_ENCODED_32_SZ ];
fd_base58_encode_32( peer->vote_account.uc, NULL, vote_account_base58 );
fd_base58_encode_32( vote->vote_account.uc, NULL, vote_account_base58 );
jsonp_string( peers->http, "vote_account", vote_account_base58 );
jsonp_ulong_as_str( peers->http, "activated_stake", peer->stake );
jsonp_ulong( peers->http, "last_vote", peer->last_vote_slot );
jsonp_ulong( peers->http, "epoch_credits", peer->epoch_credits );
jsonp_ulong( peers->http, "commission", peer->commission );
jsonp_ulong_as_str( peers->http, "activated_stake", vote->stake );
jsonp_ulong( peers->http, "last_vote", vote->last_vote_slot );
jsonp_ulong( peers->http, "epoch_credits", vote->epoch_credits );
jsonp_ulong( peers->http, "commission", vote->commission );
jsonp_ulong( peers->http, "root_slot", 0UL );
jsonp_bool( peers->http, "delinquent", peer->delinquent );
jsonp_bool( peers->http, "delinquent", vote->delinquent );
jsonp_close_object( peers->http );
jsonp_close_array( peers->http );
}
Expand Down
Loading
Loading