LCOV - code coverage report
Current view: top level - flamenco/gossip - fd_gossip_spy.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 154 0.0 %
Date: 2025-03-20 12:08:36 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /**
       2             : 
       3             :    export RUST_LOG=solana_gossip=TRACE
       4             :    cargo run --bin solana-test-validator
       5             : 
       6             :  **/
       7             : 
       8             : #define _GNU_SOURCE         /* See feature_test_macros(7) */
       9             : 
      10             : #include "fd_gossip.h"
      11             : #include "../../util/fd_util.h"
      12             : #include "../../ballet/base58/fd_base58.h"
      13             : #include "../types/fd_types_yaml.h"
      14             : #include "../../util/net/fd_eth.h"
      15             : #include <stdio.h>
      16             : #include <unistd.h>
      17             : #include <signal.h>
      18             : #include <sys/socket.h>
      19             : #include <netinet/in.h>
      20             : #include <arpa/inet.h>
      21             : #include <sys/random.h>
      22             : #include <errno.h>
      23             : #include <netdb.h>
      24             : #include <stdlib.h>
      25             : 
      26           0 : static void print_data(fd_crds_data_t* data, void* arg) {
      27           0 :   fd_flamenco_yaml_t * yamldump = (fd_flamenco_yaml_t *)arg;
      28           0 :   FILE * dumpfile = (FILE *)fd_flamenco_yaml_file(yamldump);
      29           0 :   fd_crds_data_walk(yamldump, data, fd_flamenco_yaml_walk, NULL, 1U);
      30             : 
      31           0 :   if (data->discriminant == fd_crds_data_enum_vote) {
      32           0 :     fd_gossip_vote_t * v = &data->inner.vote;
      33           0 :     fd_txn_t * txn = v->txn.txn;
      34           0 :     for ( ushort i = 0; i < txn->instr_cnt; ++i ) {
      35           0 :       fd_txn_instr_t const * txn_instr = &txn->instr[i];
      36           0 :       uchar * data    = v->txn.raw + txn_instr->data_off;
      37           0 :       ushort  data_sz = txn_instr->data_sz;
      38           0 :       fd_bincode_decode_ctx_t decode_ctx = {
      39           0 :         .data    = data,
      40           0 :         .dataend = data + data_sz
      41           0 :       };
      42             : 
      43           0 :       ulong total_sz = 0UL;
      44           0 :       if( FD_UNLIKELY( fd_vote_instruction_decode_footprint( &decode_ctx, &total_sz ) ) ) {
      45           0 :         FD_LOG_WARNING(( "failed to decode vote instruction" ));
      46           0 :         return;
      47           0 :       }
      48             : 
      49           0 :       uchar * mem = malloc( total_sz );
      50             : 
      51           0 :       fd_vote_instruction_t * vinsn = fd_vote_instruction_decode( mem, &decode_ctx );
      52           0 :       if( FD_UNLIKELY( decode_ctx.data != decode_ctx.dataend ) ) {
      53           0 :         FD_LOG_WARNING(("failed to decode vote instruction"));
      54           0 :         return;
      55           0 :       }
      56             : 
      57           0 :       fd_vote_instruction_walk( yamldump, vinsn, fd_flamenco_yaml_walk, NULL, 1U );
      58           0 :     }
      59           0 :   }
      60             : 
      61           0 :   fflush( dumpfile );
      62           0 : }
      63             : 
      64             : // SIGINT signal handler
      65             : volatile int stopflag = 0;
      66           0 : static void stop(int sig) { (void)sig; stopflag = 1; }
      67             : 
      68             : static int sockfd = -1;
      69             : 
      70             : /* Convert my style of address to UNIX style */
      71             : static int
      72           0 : gossip_to_sockaddr( uchar * dst, fd_gossip_peer_addr_t const * src ) {
      73           0 :   fd_memset(dst, 0, sizeof(struct sockaddr_in));
      74           0 :   struct sockaddr_in * t = (struct sockaddr_in *)dst;
      75           0 :   t->sin_family = AF_INET;
      76           0 :   t->sin_addr.s_addr = src->addr;
      77           0 :   t->sin_port = src->port;
      78           0 :   return sizeof(struct sockaddr_in);
      79           0 : }
      80             : 
      81             : /* Convert my style of address from UNIX style */
      82             : static int
      83           0 : gossip_from_sockaddr( fd_gossip_peer_addr_t * dst, uchar const * src ) {
      84           0 :   FD_STATIC_ASSERT(sizeof(fd_gossip_peer_addr_t) == sizeof(ulong),"messed up size");
      85           0 :   dst->l = 0;
      86           0 :   const struct sockaddr_in * sa = (const struct sockaddr_in *)src;
      87           0 :   dst->addr = sa->sin_addr.s_addr;
      88           0 :   dst->port = sa->sin_port;
      89           0 :   return 0;
      90           0 : }
      91             : 
      92             : static void
      93           0 : send_packet( uchar const * data, size_t sz, fd_gossip_peer_addr_t const * addr, void * arg ) {
      94           0 :   (void)arg;
      95           0 :   uchar saddr[sizeof(struct sockaddr_in)];
      96           0 :   int saddrlen = gossip_to_sockaddr(saddr, addr);
      97           0 :   if ( sendto(sockfd, data, sz, MSG_DONTWAIT,
      98           0 :               (const struct sockaddr *)saddr, (socklen_t)saddrlen) < 0 ) {
      99           0 :     FD_LOG_WARNING(("sendto failed: %s", strerror(errno)));
     100           0 :   }
     101           0 : }
     102             : 
     103             : static int
     104           0 : main_loop( fd_gossip_t * glob, fd_gossip_config_t * config, volatile int * stopflag ) {
     105           0 :   int fd;
     106           0 :   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
     107           0 :     FD_LOG_ERR(("socket failed: %s", strerror(errno)));
     108           0 :     return -1;
     109           0 :   }
     110           0 :   sockfd = fd;
     111           0 :   int optval = 1<<20;
     112           0 :   if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&optval, sizeof(int)) < 0) {
     113           0 :     FD_LOG_ERR(("setsocketopt failed: %s", strerror(errno)));
     114           0 :     return -1;
     115           0 :   }
     116           0 :   if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&optval, sizeof(int)) < 0) {
     117           0 :     FD_LOG_ERR(("setsocketopt failed: %s", strerror(errno)));
     118           0 :     return -1;
     119           0 :   }
     120           0 :   uchar saddr[sizeof(struct sockaddr_in6)];
     121           0 :   int saddrlen = gossip_to_sockaddr(saddr, &config->my_addr);
     122           0 :   if (saddrlen < 0 || bind(fd, (struct sockaddr*)saddr, (uint)saddrlen) < 0) {
     123           0 :     FD_LOG_ERR(("bind failed: %s", strerror(errno)));
     124           0 :     return -1;
     125           0 :   }
     126           0 :   if( getsockname( fd, (struct sockaddr *)saddr, (uint*)&saddrlen ) < 0 ) {
     127           0 :     FD_LOG_ERR( ( "getsockname failed: %s", strerror( errno ) ) );
     128           0 :     return -1;
     129           0 :   }
     130           0 :   gossip_from_sockaddr( &config->my_addr, saddr );
     131           0 :   fd_gossip_update_addr( glob, &config->my_addr );
     132             : 
     133           0 :   fd_gossip_settime(glob, fd_log_wallclock());
     134           0 :   fd_gossip_start(glob);
     135             : 
     136           0 : #define VLEN 32U
     137           0 :   struct mmsghdr msgs[VLEN];
     138           0 :   struct iovec iovecs[VLEN];
     139           0 :   uchar bufs[VLEN][FD_ETH_PAYLOAD_MAX];
     140           0 :   uchar sockaddrs[VLEN][sizeof(struct sockaddr_in6)]; /* sockaddr is smaller than sockaddr_in6 */
     141             : 
     142           0 :   while ( !*stopflag ) {
     143           0 :     fd_gossip_settime(glob, fd_log_wallclock());
     144           0 :     fd_gossip_continue(glob);
     145             : 
     146           0 :     fd_memset(msgs, 0, sizeof(msgs));
     147           0 :     for (uint i = 0; i < VLEN; i++) {
     148           0 :       iovecs[i].iov_base          = bufs[i];
     149           0 :       iovecs[i].iov_len           = FD_ETH_PAYLOAD_MAX;
     150           0 :       msgs[i].msg_hdr.msg_iov     = &iovecs[i];
     151           0 :       msgs[i].msg_hdr.msg_iovlen  = 1;
     152           0 :       msgs[i].msg_hdr.msg_name    = sockaddrs[i];
     153           0 :       msgs[i].msg_hdr.msg_namelen = sizeof(struct sockaddr_in6);
     154           0 :     }
     155             : 
     156             :     /* Read more packets */
     157           0 :     long retval = recvmmsg(fd, msgs, VLEN, MSG_DONTWAIT, NULL);
     158           0 :     if (retval < 0) {
     159           0 :       if (errno == EINTR || errno == EWOULDBLOCK)
     160           0 :         continue;
     161           0 :       FD_LOG_ERR(("recvmmsg failed: %s", strerror(errno)));
     162           0 :       return -1;
     163           0 :     }
     164           0 :     if (retval == 0)
     165           0 :       continue;
     166             : 
     167           0 :     for (uint i = 0; i < (uint)retval; ++i) {
     168           0 :       fd_gossip_peer_addr_t from;
     169           0 :       gossip_from_sockaddr( &from, msgs[i].msg_hdr.msg_name );
     170           0 :       fd_gossip_recv_packet(glob, bufs[i], (ulong)msgs[i].msg_len, &from);
     171           0 :     }
     172           0 :   }
     173             : 
     174           0 :   close(fd);
     175           0 :   return 0;
     176           0 : }
     177             : 
     178             : /* Convert a host:port string to a gossip network address. If host is
     179             :  * missing, it assumes the local hostname. */
     180             : static fd_gossip_peer_addr_t *
     181           0 : resolve_hostport(const char* str /* host:port */, fd_gossip_peer_addr_t * res) {
     182           0 :   fd_memset(res, 0, sizeof(fd_gossip_peer_addr_t));
     183             : 
     184             :   /* Find the : and copy out the host */
     185           0 :   char buf[128];
     186           0 :   uint i;
     187           0 :   for (i = 0; ; ++i) {
     188           0 :     if (str[i] == '\0' || i > sizeof(buf)-1U) {
     189           0 :       FD_LOG_ERR(("missing colon"));
     190           0 :       return NULL;
     191           0 :     }
     192           0 :     if (str[i] == ':') {
     193           0 :       buf[i] = '\0';
     194           0 :       break;
     195           0 :     }
     196           0 :     buf[i] = str[i];
     197           0 :   }
     198           0 :   if (i == 0)
     199             :     /* :port means $HOST:port */
     200           0 :     gethostname(buf, sizeof(buf));
     201             : 
     202           0 :   struct hostent * host = gethostbyname( buf );
     203           0 :   if (host == NULL) {
     204           0 :     FD_LOG_WARNING(("unable to resolve host %s", buf));
     205           0 :     return NULL;
     206           0 :   }
     207             :   /* Convert result to gossip address */
     208           0 :   res->l = 0;
     209           0 :   res->addr = ((struct in_addr *)host->h_addr)->s_addr;
     210           0 :   int port = atoi(str + i + 1);
     211           0 :   if ((port > 0 && port < 1024) || port > (int)USHORT_MAX) {
     212           0 :     FD_LOG_ERR(("invalid port number"));
     213           0 :     return NULL;
     214           0 :   }
     215           0 :   res->port = htons((ushort)port);
     216             : 
     217           0 :   return res;
     218           0 : }
     219             : 
     220             : int
     221             : main( int     argc,
     222             :       char ** argv ) {
     223             :   fd_boot( &argc, &argv );
     224             : 
     225             :   fd_valloc_t valloc = fd_libc_alloc_virtual();
     226             : 
     227             :   fd_gossip_config_t config;
     228             :   fd_memset(&config, 0, sizeof(config));
     229             : 
     230             :   uchar private_key[32];
     231             :   FD_TEST( 32UL==getrandom( private_key, 32UL, 0 ) );
     232             :   fd_sha512_t sha[1];
     233             :   fd_pubkey_t public_key;
     234             :   FD_TEST( fd_ed25519_public_from_private( public_key.uc, private_key, sha ) );
     235             : 
     236             :   config.public_key = &public_key;
     237             :   config.node_outset = fd_log_wallclock() / 1000000;
     238             : 
     239             :   char hostname[64];
     240             :   gethostname(hostname, sizeof(hostname));
     241             : 
     242             :   FD_TEST( resolve_hostport(":0", &config.my_addr) );
     243             : 
     244             :   config.shred_version = 4274;
     245             : 
     246             :   fd_flamenco_yaml_t * yamldump =
     247             :     fd_flamenco_yaml_init( fd_flamenco_yaml_new(
     248             :       fd_valloc_malloc( valloc, fd_flamenco_yaml_align(), fd_flamenco_yaml_footprint() ) ),
     249             :       stdout );
     250             :   config.deliver_fun = print_data;
     251             :   config.deliver_arg = yamldump;
     252             :   config.send_fun    = send_packet;
     253             :   config.send_arg    = NULL;
     254             : 
     255             :   ulong seed = fd_hash(0, hostname, strnlen(hostname, sizeof(hostname)));
     256             : 
     257             :   void * shm = fd_valloc_malloc(valloc, fd_gossip_align(), fd_gossip_footprint());
     258             :   fd_gossip_t * glob = fd_gossip_join(fd_gossip_new(shm, seed));
     259             : 
     260             :   if ( fd_gossip_set_config(glob, &config) )
     261             :     return 1;
     262             : 
     263             :   fd_gossip_peer_addr_t peeraddr;
     264             :   // if ( fd_gossip_add_active_peer(glob, resolve_hostport("entrypoint.mainnet-beta.solana.com:8001", &peeraddr)) )
     265             :   // return 1;
     266             :   // if ( fd_gossip_add_active_peer(glob, resolve_hostport("entrypoint2.mainnet-beta.solana.com:8001", &peeraddr)) )
     267             :   // return 1;
     268             :   // if ( fd_gossip_add_active_peer(glob, resolve_hostport("entrypoint3.mainnet-beta.solana.com:8001", &peeraddr)) )
     269             :   // return 1;
     270             :   // if ( fd_gossip_add_active_peer(glob, resolve_hostport("entrypoint4.mainnet-beta.solana.com:8001", &peeraddr)) )
     271             :   // return 1;
     272             :   // if ( fd_gossip_add_active_peer(glob, resolve_hostport("entrypoint5.mainnet-beta.solana.com:8001", &peeraddr)) )
     273             :   // return 1;
     274             :   // if ( fd_gossip_add_active_peer(glob, resolve_hostport("entrypoint.testnet.solana.com:8001", &peeraddr)) )
     275             :   //   return 1;
     276             :   // if ( fd_gossip_add_active_peer(glob, resolve_hostport("entrypoint2.testnet.solana.com:8001", &peeraddr)) )
     277             :   //   return 1;
     278             :   // if ( fd_gossip_add_active_peer(glob, resolve_hostport("entrypoint3.testnet.solana.com:8001", &peeraddr)) )
     279             :   //   return 1;
     280             :   if ( fd_gossip_add_active_peer(glob, resolve_hostport(":1024", &peeraddr)) )
     281             :   return 1;
     282             : 
     283             :   signal(SIGINT, stop);
     284             :   signal(SIGPIPE, SIG_IGN);
     285             : 
     286             :   if ( main_loop(glob, &config, &stopflag) )
     287             :     return 1;
     288             : 
     289             :   fd_valloc_free(valloc, fd_flamenco_yaml_delete(yamldump));
     290             : 
     291             :   fd_valloc_free(valloc, fd_gossip_delete(fd_gossip_leave(glob)));
     292             : 
     293             :   fd_halt();
     294             :   return 0;
     295             : }

Generated by: LCOV version 1.14