@@ -18,7 +18,9 @@ fd_gui_peers_align( void ) {
1818 a = fd_ulong_max ( a , fd_gui_peers_live_table_align () );
1919 a = fd_ulong_max ( a , fd_gui_peers_bandwidth_tracking_align () );
2020 a = fd_ulong_max ( a , fd_gui_peers_node_info_pool_align () );
21+ a = fd_ulong_max ( a , fd_gui_peers_node_vote_pool_align () );
2122 a = fd_ulong_max ( a , fd_gui_peers_node_info_map_align () );
23+ a = fd_ulong_max ( a , fd_gui_peers_node_vote_map_align () );
2224 a = fd_ulong_max ( a , fd_gui_peers_node_pubkey_map_align () );
2325 a = fd_ulong_max ( a , fd_gui_peers_node_sock_map_align () );
2426 a = fd_ulong_max ( a , alignof(fd_gui_peers_ws_conn_t ) );
@@ -30,6 +32,7 @@ fd_gui_peers_align( void ) {
3032FD_FN_CONST ulong
3133fd_gui_peers_footprint ( ulong max_ws_conn_cnt ) {
3234 ulong info_chain_cnt = fd_gui_peers_node_info_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE );
35+ ulong vote_chain_cnt = fd_gui_peers_node_vote_map_chain_cnt_est ( FD_RUNTIME_MAX_VOTE_ACCOUNTS );
3336 ulong pubkey_chain_cnt = fd_gui_peers_node_pubkey_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE );
3437 ulong sock_chain_cnt = fd_gui_peers_node_sock_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE );
3538
@@ -38,11 +41,13 @@ fd_gui_peers_footprint( ulong max_ws_conn_cnt ) {
3841 l = FD_LAYOUT_APPEND ( l , fd_gui_peers_live_table_align (), fd_gui_peers_live_table_footprint ( FD_CONTACT_INFO_TABLE_SIZE ) );
3942 l = FD_LAYOUT_APPEND ( l , fd_gui_peers_bandwidth_tracking_align (), fd_gui_peers_bandwidth_tracking_footprint ( FD_CONTACT_INFO_TABLE_SIZE ) );
4043 l = FD_LAYOUT_APPEND ( l , fd_gui_peers_node_info_pool_align (), fd_gui_peers_node_info_pool_footprint ( FD_CONTACT_INFO_TABLE_SIZE ) );
44+ l = FD_LAYOUT_APPEND ( l , fd_gui_peers_node_vote_pool_align (), fd_gui_peers_node_vote_pool_footprint ( FD_RUNTIME_MAX_VOTE_ACCOUNTS ) );
4145 l = FD_LAYOUT_APPEND ( l , fd_gui_peers_node_info_map_align (), fd_gui_peers_node_info_map_footprint ( info_chain_cnt ) );
46+ l = FD_LAYOUT_APPEND ( l , fd_gui_peers_node_vote_map_align (), fd_gui_peers_node_vote_map_footprint ( vote_chain_cnt ) );
4247 l = FD_LAYOUT_APPEND ( l , fd_gui_peers_node_pubkey_map_align (), fd_gui_peers_node_pubkey_map_footprint ( pubkey_chain_cnt ) );
4348 l = FD_LAYOUT_APPEND ( l , fd_gui_peers_node_sock_map_align (), fd_gui_peers_node_sock_map_footprint ( sock_chain_cnt ) );
4449 l = FD_LAYOUT_APPEND ( l , alignof(fd_gui_peers_ws_conn_t ), max_ws_conn_cnt * sizeof (fd_gui_peers_ws_conn_t ) );
45- l = FD_LAYOUT_APPEND ( l , alignof(fd_gui_ipinfo_node_t ), sizeof (fd_gui_ipinfo_node_t )* IPINFO_MAX_NODES );
50+ l = FD_LAYOUT_APPEND ( l , alignof(fd_gui_ipinfo_node_t ), sizeof (fd_gui_ipinfo_node_t )* IPINFO_MAX_NODES );
4651
4752 return FD_LAYOUT_FINI ( l , fd_gui_peers_align () );
4853}
@@ -139,6 +144,7 @@ fd_gui_peers_new( void * shmem,
139144 }
140145
141146 ulong info_chain_cnt = fd_gui_peers_node_info_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE );
147+ ulong vote_chain_cnt = fd_gui_peers_node_vote_map_chain_cnt_est ( FD_RUNTIME_MAX_VOTE_ACCOUNTS );
142148 ulong pubkey_chain_cnt = fd_gui_peers_node_pubkey_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE );
143149 ulong sock_chain_cnt = fd_gui_peers_node_sock_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE );
144150
@@ -147,7 +153,9 @@ fd_gui_peers_new( void * shmem,
147153 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 ) );
148154 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 ) );
149155 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 ) );
156+ 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 ) );
150157 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 ) );
158+ 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 ) );
151159 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 ) );
152160 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 ) );
153161 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 ) );
@@ -178,7 +186,9 @@ fd_gui_peers_new( void * shmem,
178186 fd_gui_peers_bandwidth_tracking_seed ( ctx -> contact_info_table , FD_CONTACT_INFO_TABLE_SIZE , 42UL );
179187
180188 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 ) );
189+ 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 ) );
181190 ctx -> node_info_map = fd_gui_peers_node_info_map_join ( fd_gui_peers_node_info_map_new ( _info_map , info_chain_cnt , 42UL ) );
191+ ctx -> node_vote_map = fd_gui_peers_node_vote_map_join ( fd_gui_peers_node_vote_map_new ( _vote_map , vote_chain_cnt , 42UL ) );
182192 ctx -> node_pubkey_map = fd_gui_peers_node_pubkey_map_join ( fd_gui_peers_node_pubkey_map_new ( _pubkey_map , pubkey_chain_cnt , 42UL ) );
183193 ctx -> node_sock_map = fd_gui_peers_node_sock_map_join ( fd_gui_peers_node_sock_map_new ( _sock_map , sock_chain_cnt , 42UL ) );
184194
@@ -626,8 +636,9 @@ fd_gui_peers_handle_gossip_update( fd_gui_peers_ctx_t * peers,
626636 memset ( & peer -> gossip_tx , 0 , sizeof (peer -> gossip_tx ) );
627637 memset ( & peer -> gossvf_rx_sum , 0 , sizeof (peer -> gossvf_rx_sum ) );
628638 memset ( & peer -> gossip_tx_sum , 0 , sizeof (peer -> gossip_tx_sum ) );
629- peer -> has_vote_info = 0 ;
630- peer -> stake = ULONG_MAX ;
639+
640+ 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 );
641+ peer -> stake = FD_LIKELY ( vote ) ? vote -> stake : ULONG_MAX ;
631642
632643 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 );
633644 if ( FD_LIKELY ( info ) ) fd_memcpy ( peer -> name , info -> name , sizeof (info -> name ) );
@@ -722,9 +733,17 @@ void
722733fd_gui_peers_handle_vote_update ( fd_gui_peers_ctx_t * peers ,
723734 fd_gui_peers_vote_t * votes ,
724735 ulong vote_cnt ,
725- long now ,
726736 fd_pubkey_t * identity ) {
727- (void )now ;
737+ if ( FD_UNLIKELY ( !fd_gui_peers_node_vote_pool_free ( peers -> node_vote_pool ) ) ) {
738+ FD_LOG_WARNING (( "pool mem exhausted" ));
739+ return ;
740+ }
741+
742+ if ( FD_UNLIKELY ( vote_cnt > FD_RUNTIME_MAX_VOTE_ACCOUNTS ) ) {
743+ FD_LOG_WARNING (( "max vote accounts exceeded" ));
744+ return ;
745+ }
746+
728747 fd_gui_peers_vote_t * votes_sorted = votes ;
729748 fd_gui_peers_vote_t * votes_scratch = peers -> votes_scratch ;
730749 fd_memcpy ( votes_sorted , votes , vote_cnt * sizeof (fd_gui_peers_vote_t ) );
@@ -785,37 +804,47 @@ fd_gui_peers_handle_vote_update( fd_gui_peers_ctx_t * peers,
785804 fd_http_server_ws_broadcast ( peers -> http );
786805 }
787806
788- 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 );
789- if ( FD_UNLIKELY ( peer_idx == ULONG_MAX ) ) continue ; /* peer not on gossip */
790-
791- fd_gui_peers_node_t * peer = peers -> contact_info_table + peer_idx ;
792-
793807 /* TODO: we only publish updates when stake changes, otherwise we'd
794808 have to republish for every peer every slot, which ends up being
795809 too much bandwidth because we republish all the peer info.
796810 Ideally, we decouple the vote updates from the reset of the peer
797811 info which would let us make updates quickly. */
798- int is_delinquent = ((long )last_vote_slot_p67 - (long )votes_sorted [ i ].last_vote_slot ) > 150L ;
799- int vote_eq = peer -> has_vote_info
800- && !memcmp ( peer -> vote_account .uc , votes_sorted [ i ].vote_account .uc , sizeof (fd_pubkey_t ) )
801- && peer -> stake == votes_sorted [ i ].stake
802- // && peer->last_vote_slot ==votes_sorted[ i ].last_vote_slot
803- // && peer->last_vote_timestamp ==votes_sorted[ i ].last_vote_timestamp
804- // && peer->epoch_credits ==votes_sorted[ i ].epoch_credits
805- && peer -> commission == votes_sorted [ i ].commission
806- && peer -> epoch == votes_sorted [ i ].epoch
807- && peer -> delinquent == is_delinquent ;
812+ votes_sorted [ i ].delinquent = ((long )last_vote_slot_p67 - (long )votes_sorted [ i ].last_vote_slot ) > 150L ;
813+
814+ 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 );
815+
816+ int vote_eq = !!vote
817+ && !memcmp ( vote -> vote_account .uc , votes_sorted [ i ].vote_account .uc , sizeof (fd_pubkey_t ) )
818+ && vote -> stake == votes_sorted [ i ].stake
819+ // && vote->last_vote_slot ==votes_sorted[ i ].last_vote_slot
820+ // && vote->last_vote_timestamp ==votes_sorted[ i ].last_vote_timestamp
821+ // && vote->epoch_credits ==votes_sorted[ i ].epoch_credits
822+ // && vote->commission ==votes_sorted[ i ].commission
823+ && vote -> epoch == votes_sorted [ i ].epoch
824+ && vote -> delinquent == votes_sorted [ i ].delinquent ;
808825
809826 if ( FD_LIKELY ( vote_eq ) ) continue ; /* nop */
810827
811- peer -> has_vote_info = 1 ;
812- peer -> vote_account = votes_sorted [ i ].vote_account ;
813- peer -> last_vote_slot = votes_sorted [ i ].last_vote_slot ;
814- peer -> last_vote_timestamp = votes_sorted [ i ].last_vote_timestamp ;
815- peer -> epoch_credits = votes_sorted [ i ].epoch_credits ;
816- peer -> commission = votes_sorted [ i ].commission ;
817- peer -> epoch = votes_sorted [ i ].epoch ;
818- peer -> delinquent = is_delinquent ;
828+ if ( FD_UNLIKELY ( !vote ) ) {
829+ vote = fd_gui_peers_node_vote_pool_ele_acquire ( peers -> node_vote_pool );
830+ fd_memcpy ( & vote -> node_account , & votes_sorted [ i ].node_account , sizeof (fd_pubkey_t ) );
831+ fd_gui_peers_node_vote_map_ele_insert ( peers -> node_vote_map , vote , peers -> node_vote_pool );
832+ }
833+
834+ /* update map entry */
835+ fd_memcpy ( vote -> vote_account .uc , votes_sorted [ i ].vote_account .uc , sizeof (fd_pubkey_t ) );
836+ vote -> stake = votes_sorted [ i ].stake ;
837+ vote -> last_vote_slot = votes_sorted [ i ].last_vote_slot ;
838+ vote -> last_vote_timestamp = votes_sorted [ i ].last_vote_timestamp ;
839+ vote -> epoch_credits = votes_sorted [ i ].epoch_credits ;
840+ vote -> commission = votes_sorted [ i ].commission ;
841+ vote -> epoch = votes_sorted [ i ].epoch ;
842+ vote -> delinquent = votes_sorted [ i ].delinquent ;
843+
844+ 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 );
845+ if ( FD_UNLIKELY ( peer_idx == ULONG_MAX ) ) continue ; /* peer not on gossip */
846+
847+ fd_gui_peers_node_t * peer = peers -> contact_info_table + peer_idx ;
819848
820849 if ( FD_UNLIKELY ( peer -> stake != votes_sorted [ i ].stake ) ) {
821850 fd_gui_peers_live_table_idx_remove ( peers -> live_table , peer_idx , peers -> contact_info_table );
0 commit comments