66#include "../../flamenco/gossip/fd_gossip_private.h"
77#include "../../disco/metrics/fd_metrics_base.h"
88
9+ FD_IMPORT_BINARY ( ipinfo , "src/disco/gui/ipinfo.bin" );
10+ #define IPINFO_MAX_NODES (1UL<<22UL) /* 4M nodes */
11+
912#define LOGGING 0
1013
1114FD_FN_CONST ulong
@@ -19,6 +22,7 @@ fd_gui_peers_align( void ) {
1922 a = fd_ulong_max ( a , fd_gui_peers_node_pubkey_map_align () );
2023 a = fd_ulong_max ( a , fd_gui_peers_node_sock_map_align () );
2124 a = fd_ulong_max ( a , alignof(fd_gui_peers_ws_conn_t ) );
25+ a = fd_ulong_max ( a , alignof(fd_gui_ipinfo_node_t ) );
2226 FD_TEST ( fd_ulong_pow2_up ( a )== a );
2327 return a ;
2428}
@@ -38,10 +42,86 @@ fd_gui_peers_footprint( ulong max_ws_conn_cnt ) {
3842 l = FD_LAYOUT_APPEND ( l , fd_gui_peers_node_pubkey_map_align (), fd_gui_peers_node_pubkey_map_footprint ( pubkey_chain_cnt ) );
3943 l = FD_LAYOUT_APPEND ( l , fd_gui_peers_node_sock_map_align (), fd_gui_peers_node_sock_map_footprint ( sock_chain_cnt ) );
4044 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 );
4146
4247 return FD_LAYOUT_FINI ( l , fd_gui_peers_align () );
4348}
4449
50+ /* We sort the country codes so that fd_gui_peers_live_table can sort by
51+ table index instead of the codes themselves. */
52+ #define SORT_NAME fd_gui_country_code_sort
53+ #define SORT_KEY_T fd_gui_country_code_t
54+ #define SORT_BEFORE (a ,b ) (strcmp( (char *)&(a), (char *)&(b) ) < 0)
55+ #include "../../util/tmpl/fd_sort.c"
56+
57+ static void
58+ build_ipinfo_trie ( fd_gui_peers_ctx_t * peers ,
59+ fd_gui_ipinfo_node_t * nodes ) {
60+ peers -> ipinfo .nodes = nodes ;
61+ ulong country_code_cnt = FD_LOAD ( ulong , ipinfo );
62+ FD_TEST ( country_code_cnt && country_code_cnt < 256UL ); /* 256 reserved for unknown */
63+ FD_TEST ( ipinfo_sz >=8UL + country_code_cnt * 2UL );
64+
65+ for ( ulong i = 0UL ; i < country_code_cnt ; i ++ ) {
66+ fd_memcpy ( peers -> ipinfo .country_code [ i ].cc , ipinfo + 8UL + i * 2UL , 2UL );
67+ peers -> ipinfo .country_code [ i ].cc [ 2 ] = '\0' ;
68+ }
69+
70+ fd_gui_country_code_sort_insert ( peers -> ipinfo .country_code , country_code_cnt );
71+
72+ ulong processed = 8UL + country_code_cnt * 2UL ;
73+ FD_TEST ( !((ipinfo_sz - processed )%6UL ) );
74+ FD_TEST ( (ipinfo_sz - processed )/6UL <=IPINFO_MAX_NODES - 1UL );
75+
76+ fd_gui_ipinfo_node_t * root = & nodes [ 0 ];
77+ root -> left = NULL ;
78+ root -> right = NULL ;
79+ root -> has_prefix = 0 ;
80+
81+ ulong node_cnt = 1UL ;
82+ while ( processed < ipinfo_sz ) {
83+ uint ip_addr = fd_uint_bswap ( FD_LOAD ( uint , ipinfo + processed ) );
84+ uchar prefix_len = * ( ipinfo + processed + 4UL );
85+ FD_TEST ( prefix_len <=32UL );
86+ uchar country_idx = * ( ipinfo + processed + 5UL );
87+ FD_TEST ( country_idx < country_code_cnt );
88+
89+ fd_gui_ipinfo_node_t * node = root ;
90+ for ( uchar bit_pos = 0 ; bit_pos < prefix_len ; bit_pos ++ ) {
91+ uchar bit = (ip_addr >> (31 - bit_pos )) & 1 ;
92+
93+ fd_gui_ipinfo_node_t * child ;
94+ if ( FD_LIKELY ( !bit ) ) {
95+ child = node -> left ;
96+ if ( FD_LIKELY ( !child ) ) {
97+ FD_TEST ( node_cnt < IPINFO_MAX_NODES );
98+ child = & nodes [ node_cnt ++ ];
99+ child -> left = NULL ;
100+ child -> right = NULL ;
101+ child -> has_prefix = 0 ;
102+ node -> left = child ;
103+ }
104+ } else {
105+ child = node -> right ;
106+ if ( FD_LIKELY ( !child ) ) {
107+ FD_TEST ( node_cnt < IPINFO_MAX_NODES );
108+ child = & nodes [ node_cnt ++ ];
109+ child -> left = NULL ;
110+ child -> right = NULL ;
111+ child -> has_prefix = 0 ;
112+ node -> right = child ;
113+ }
114+ }
115+ node = child ;
116+ }
117+
118+ node -> has_prefix = 1 ;
119+ node -> country_code_idx = country_idx ;
120+
121+ processed += 6UL ;
122+ }
123+ }
124+
45125void *
46126fd_gui_peers_new ( void * shmem ,
47127 fd_http_server_t * http ,
@@ -71,6 +151,7 @@ fd_gui_peers_new( void * shmem,
71151 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 ) );
72152 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 ) );
73153 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 ) );
154+ void * _nodes = FD_SCRATCH_ALLOC_APPEND ( l , alignof(fd_gui_ipinfo_node_t ), sizeof (fd_gui_ipinfo_node_t )* IPINFO_MAX_NODES );
74155
75156 for ( ulong i = 0UL ; i < max_ws_conn_cnt ; i ++ ) ctx -> client_viewports [ i ].connected = 0 ;
76157
@@ -101,6 +182,8 @@ fd_gui_peers_new( void * shmem,
101182 ctx -> node_pubkey_map = fd_gui_peers_node_pubkey_map_join ( fd_gui_peers_node_pubkey_map_new ( _pubkey_map , pubkey_chain_cnt , 42UL ) );
102183 ctx -> node_sock_map = fd_gui_peers_node_sock_map_join ( fd_gui_peers_node_sock_map_new ( _sock_map , sock_chain_cnt , 42UL ) );
103184
185+ build_ipinfo_trie ( ctx , _nodes );
186+
104187 return shmem ;
105188}
106189
@@ -462,10 +545,8 @@ ipinfo_lookup( fd_gui_ipinfo_node_t const * nodes,
462545
463546void
464547fd_gui_peers_handle_gossip_update ( fd_gui_peers_ctx_t * peers ,
465- fd_gui_ipinfo_node_t const * ipinfo_nodes ,
466548 fd_gossip_update_message_t const * update ,
467- long now ,
468- char country_code_map [ static 512 ][ 3 ] ) {
549+ long now ) {
469550 switch ( update -> tag ) {
470551 case FD_GOSSIP_UPDATE_TAG_CONTACT_INFO : {
471552#ifdef FD_GUI_USE_HANDHOLDING
@@ -523,7 +604,7 @@ fd_gui_peers_handle_gossip_update( fd_gui_peers_ctx_t * peers,
523604 peer -> update_time_nanos = now ;
524605 /* fetch and set country code */
525606#if FD_HAS_ZSTD
526- peer -> country_code_idx = ipinfo_lookup ( ipinfo_nodes , peer -> contact_info .sockets [ FD_CONTACT_INFO_SOCKET_GOSSIP ].addr );
607+ peer -> country_code_idx = ipinfo_lookup ( peers -> ipinfo . nodes , peer -> contact_info .sockets [ FD_CONTACT_INFO_SOCKET_GOSSIP ].addr );
527608#else
528609 peer -> country_code_idx = UCHAR_MAX ;
529610#endif
@@ -532,7 +613,7 @@ fd_gui_peers_handle_gossip_update( fd_gui_peers_ctx_t * peers,
532613 fd_gui_peers_node_sock_map_idx_insert ( peers -> node_sock_map , update -> contact_info .idx , peers -> contact_info_table );
533614
534615 /* broadcast update to WebSocket clients */
535- fd_gui_peers_printf_nodes ( peers , (int []){ FD_GUI_PEERS_NODE_UPDATE }, (ulong []){ update -> contact_info .idx }, 1UL , country_code_map );
616+ fd_gui_peers_printf_nodes ( peers , (int []){ FD_GUI_PEERS_NODE_UPDATE }, (ulong []){ update -> contact_info .idx }, 1UL );
536617 fd_http_server_ws_broadcast ( peers -> http );
537618 } else {
538619 FD_TEST ( !fd_gui_peers_node_pubkey_map_ele_query_const ( peers -> node_pubkey_map , & update -> contact_info .contact_info -> pubkey , NULL , peers -> contact_info_table ) );
@@ -547,17 +628,21 @@ fd_gui_peers_handle_gossip_update( fd_gui_peers_ctx_t * peers,
547628 memset ( & peer -> gossip_tx_sum , 0 , sizeof (peer -> gossip_tx_sum ) );
548629 peer -> has_vote_info = 0 ;
549630 peer -> stake = ULONG_MAX ;
550- peer -> valid = 1 ;
631+
632+ 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 );
633+ if ( FD_LIKELY ( info ) ) fd_memcpy ( peer -> name , info -> name , sizeof (info -> name ) );
634+ else peer -> name [ 0 ] = '\0' ;
635+
551636 peer -> update_time_nanos = now ;
552637 fd_memcpy ( & peer -> contact_info , update -> contact_info .contact_info , sizeof (peer -> contact_info ) );
553638
554639 /* fetch and set country code */
555640#if FD_HAS_ZSTD
556- peer -> country_code_idx = ipinfo_lookup ( ipinfo_nodes , peer -> contact_info .sockets [ FD_CONTACT_INFO_SOCKET_GOSSIP ].addr );
641+ peer -> country_code_idx = ipinfo_lookup ( peers -> ipinfo . nodes , peer -> contact_info .sockets [ FD_CONTACT_INFO_SOCKET_GOSSIP ].addr );
557642#else
558643 peer -> country_code_idx = UCHAR_MAX ;
559- (void )ipinfo_nodes ;
560644#endif
645+ peer -> valid = 1 ;
561646
562647 /* update pubkey_map, sock_map */
563648 fd_gui_peers_node_sock_map_idx_insert ( peers -> node_sock_map , update -> contact_info .idx , peers -> contact_info_table );
@@ -571,7 +656,7 @@ fd_gui_peers_handle_gossip_update( fd_gui_peers_ctx_t * peers,
571656 fd_http_server_ws_broadcast ( peers -> http );
572657
573658 /* broadcast update to WebSocket clients */
574- fd_gui_peers_printf_nodes ( peers , (int []){ FD_GUI_PEERS_NODE_ADD }, (ulong []){ update -> contact_info .idx }, 1UL , country_code_map );
659+ fd_gui_peers_printf_nodes ( peers , (int []){ FD_GUI_PEERS_NODE_ADD }, (ulong []){ update -> contact_info .idx }, 1UL );
575660 fd_http_server_ws_broadcast ( peers -> http );
576661 }
577662 break ;
@@ -610,7 +695,7 @@ fd_gui_peers_handle_gossip_update( fd_gui_peers_ctx_t * peers,
610695 fd_http_server_ws_broadcast ( peers -> http );
611696
612697 /* broadcast update to WebSocket clients */
613- fd_gui_peers_printf_nodes ( peers , (int []){ FD_GUI_PEERS_NODE_DELETE }, (ulong []){ update -> contact_info_remove .idx }, 1UL , country_code_map );
698+ fd_gui_peers_printf_nodes ( peers , (int []){ FD_GUI_PEERS_NODE_DELETE }, (ulong []){ update -> contact_info_remove .idx }, 1UL );
614699 fd_http_server_ws_broadcast ( peers -> http );
615700 break ;
616701 }
@@ -638,8 +723,7 @@ fd_gui_peers_handle_vote_update( fd_gui_peers_ctx_t * peers,
638723 fd_gui_peers_vote_t * votes ,
639724 ulong vote_cnt ,
640725 long now ,
641- fd_pubkey_t * identity ,
642- char country_code_map [ static 512 ][ 3 ] ) {
726+ fd_pubkey_t * identity ) {
643727 (void )now ;
644728 fd_gui_peers_vote_t * votes_sorted = votes ;
645729 fd_gui_peers_vote_t * votes_scratch = peers -> votes_scratch ;
@@ -745,7 +829,7 @@ fd_gui_peers_handle_vote_update( fd_gui_peers_ctx_t * peers,
745829 }
746830
747831 if ( FD_UNLIKELY ( count ) ) {
748- fd_gui_peers_printf_nodes ( peers , actions , idxs , count , country_code_map );
832+ fd_gui_peers_printf_nodes ( peers , actions , idxs , count );
749833 fd_http_server_ws_broadcast ( peers -> http );
750834 }
751835}
@@ -1144,18 +1228,17 @@ fd_gui_peers_poll( fd_gui_peers_ctx_t * peers, long now ) {
11441228}
11451229
11461230void
1147- fd_gui_peers_ws_open ( fd_gui_peers_ctx_t * peers ,
1148- ulong ws_conn_id ,
1149- long now ,
1150- char country_code_map [ static 512 ][ 3 ] ) {
1231+ fd_gui_peers_ws_open ( fd_gui_peers_ctx_t * peers ,
1232+ ulong ws_conn_id ,
1233+ long now ) {
11511234 peers -> client_viewports [ ws_conn_id ].connected = 1 ;
11521235 peers -> client_viewports [ ws_conn_id ].connected_time = now ;
11531236 peers -> client_viewports [ ws_conn_id ].start_row = 0 ;
11541237 peers -> client_viewports [ ws_conn_id ].row_cnt = 0 ;
11551238 peers -> client_viewports [ ws_conn_id ].sort_key = FD_GUI_PEERS_LIVE_TABLE_DEFAULT_SORT_KEY ;
11561239 fd_gui_peers_ws_conn_rr_grow ( peers , ws_conn_id );
11571240
1158- fd_gui_peers_printf_node_all ( peers , country_code_map );
1241+ fd_gui_peers_printf_node_all ( peers );
11591242 FD_TEST ( !fd_http_server_ws_send ( peers -> http , ws_conn_id ) );
11601243}
11611244
0 commit comments