LCOV - code coverage report
Current view: top level - flamenco/gossip - fd_gossip_types.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 3 23 13.0 %
Date: 2025-11-29 04:46:19 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_gossip_fd_gossip_types_h
       2             : #define HEADER_fd_src_flamenco_gossip_fd_gossip_types_h
       3             : 
       4             : /* The gossip tile produces an output stream of update messages as it
       5             :    runs, which are published to a link for other tiles to consume.
       6             : 
       7             :    The formt and protocol of the update messages is defined here.
       8             : 
       9             :    Messages are published one by one incrementally, as they are
      10             :    received, although expirations or removals will not be published
      11             :    except for contact information which publishes a removal stream so
      12             :    that consumers of the updates can mirror the true gossip table.
      13             : 
      14             :    Not all gossip messages are published, and some are consumed just by
      15             :    the gossip tile itself. */
      16             : 
      17             : #include "../types/fd_types_custom.h"
      18             : #include "../../util/net/fd_net_headers.h"
      19             : 
      20             : /* The tag is the kind of gossip message that is being sent.  It will be
      21             :    put both in the fragment signature, and in the message itself. */
      22             : 
      23           0 : #define FD_GOSSIP_UPDATE_TAG_CONTACT_INFO        (0)
      24           0 : #define FD_GOSSIP_UPDATE_TAG_CONTACT_INFO_REMOVE (1)
      25           0 : #define FD_GOSSIP_UPDATE_TAG_LOWEST_SLOT         (2)
      26           0 : #define FD_GOSSIP_UPDATE_TAG_VOTE                (3)
      27           0 : #define FD_GOSSIP_UPDATE_TAG_DUPLICATE_SHRED     (4)
      28           0 : #define FD_GOSSIP_UPDATE_TAG_SNAPSHOT_HASHES     (5)
      29             : 
      30             : /* The maximum number of contact infos that may be present at any one
      31             :    time.  If new contact infos are added, a removal will be issued first
      32             :    to make space.  This is a hard limit, and the consumer of the contact
      33             :    info messages can assume it is always respected.
      34             : 
      35             :    The contact info messages are designed to be consumed in an
      36             :    incremental way.  In particular, CONTACT_INFO and CONTACT_INFO_REMOVE
      37             :    messages are both sent with an idx field, which is the index of the
      38             :    contact info in an imaginary array of contact infos.  Updates will
      39             :    always have the same idx for the same pubkey, and removes will
      40             :    likewise have the same idx for the pubkey being removed.  A consumer
      41             :    of contact info updates can therefore simply maintain a local array
      42             :    of contact infos, and update it with the idx field.  */
      43             : 
      44           0 : #define FD_CONTACT_INFO_TABLE_SIZE (32768UL)
      45             : 
      46           6 : #define FD_CONTACT_INFO_SOCKET_GOSSIP            ( 0)
      47           0 : #define FD_CONTACT_INFO_SOCKET_SERVE_REPAIR_QUIC ( 1)
      48           0 : #define FD_CONTACT_INFO_SOCKET_RPC               ( 2)
      49           0 : #define FD_CONTACT_INFO_SOCKET_RPC_PUBSUB        ( 3)
      50           0 : #define FD_CONTACT_INFO_SOCKET_SERVE_REPAIR      ( 4)
      51           0 : #define FD_CONTACT_INFO_SOCKET_TPU               ( 5)
      52           0 : #define FD_CONTACT_INFO_SOCKET_TPU_FORWARDS      ( 6)
      53           0 : #define FD_CONTACT_INFO_SOCKET_TPU_FORWARDS_QUIC ( 7)
      54           0 : #define FD_CONTACT_INFO_SOCKET_TPU_QUIC          ( 8)
      55           0 : #define FD_CONTACT_INFO_SOCKET_TPU_VOTE          ( 9)
      56           0 : #define FD_CONTACT_INFO_SOCKET_TVU               (10)
      57           0 : #define FD_CONTACT_INFO_SOCKET_TVU_QUIC          (11)
      58           0 : #define FD_CONTACT_INFO_SOCKET_TPU_VOTE_QUIC     (12)
      59           0 : #define FD_CONTACT_INFO_SOCKET_ALPENGLOW         (13)
      60          45 : #define FD_CONTACT_INFO_SOCKET_CNT               (14)
      61             : 
      62             : /* https://github.com/anza-xyz/agave/blob/540d5bc56cd44e3cc61b179bd52e9a782a2c99e4/version/src/lib.rs#L95-L105 */
      63             : 
      64             : #define FD_CONTACT_INFO_VERSION_CLIENT_SOLANA_LABS   (0)
      65             : #define FD_CONTACT_INFO_VERSION_CLIENT_JITO_LABS     (1)
      66             : #define FD_CONTACT_INFO_VERSION_CLIENT_FRANKENDANCER (2)
      67             : #define FD_CONTACT_INFO_VERSION_CLIENT_AGAVE         (3)
      68             : #define FD_CONTACT_INFO_VERSION_CLIENT_AGAVE_PALADIN (4)
      69           3 : #define FD_CONTACT_INFO_VERSION_CLIENT_FIREDANCER    (5)
      70             : #define FD_CONTACT_INFO_VERSION_CLIENT_AGAVE_BAM     (6)
      71             : #define FD_CONTACT_INFO_VERSION_CLIENT_SIG           (7)
      72             : 
      73             : /* A contact info represents a peer node in the cluster that is
      74             :    publishing information about itself to the gossip network.  It it
      75             :    sent when the tag is FD_GOSSIP_UPDATE_TAG_CONTACT_INFO.
      76             : 
      77             :    Contact infos are already deduplicated, so the same pubkey will not
      78             :    appear twice, and the number of contact infos outstanding is limited
      79             :    to FD_CONTACT_INFO_TABLE_SIZE.  If more contact infos are received,
      80             :    the oldest ones are first removed with a
      81             :    FD_GOSSIP_UPDATE_TAG_CONTACT_INFO_REMOVE fragment.
      82             : 
      83             :    Contact infos are regularly updated, for example if a node changes
      84             :    its IP address or port.  More typically nodes just periodically
      85             :    republish their contact info with an updated wallclock.  When an
      86             :    existing contact info is updated, a FD_GOSSIP_UPDATE_TAG_CONTACT_INFO
      87             :    fragment is sent with the same pubkey.
      88             : 
      89             :    Contact information is not well-validated by the gossip network, and
      90             :    for example the wallclock may be old, or in the future, and the
      91             :    sockets may be unroutable or invalid (a private network), and the
      92             :    version fields are completely arbitrary.
      93             : 
      94             :    However, the pubkey is authenticated, as messages are signed. */
      95             : 
      96             : struct fd_contact_info {
      97             :   fd_pubkey_t pubkey;          /* The identity public key of the peer node */
      98             :   ushort      shred_version;   /* The shred version of the peer node, should be non-zero but not required */
      99             : 
     100             :   long        instance_creation_wallclock_nanos;
     101             :   long        wallclock_nanos; /* The timestamp on the producer side of when the contact info was signed */
     102             : 
     103             :   /* Peer nodes declare a list of ip:port pairs corresponding to
     104             :      standard Solana protocols that they support.  A value of 0:0
     105             :      indicates the node does not advertise that protocol.  For example,
     106             :      sockets[ FD_CONTACT_INFO_SOCKET_RPC ] is the IP address and port
     107             :      for the RPC service of the node. */
     108             :   fd_ip4_port_t sockets[ FD_CONTACT_INFO_SOCKET_CNT ];
     109             : 
     110             :   struct {
     111             :     ushort client; /* Any ushort in [0, USHORT_MAX], although typically one of FD_CONTACT_INFO_VERSION_CLIENT_* indicating the self-reported client version */
     112             : 
     113             :     ushort major;  /* The self-reported major version of the client */
     114             :     ushort minor;  /* The self-reported minor version of the client */
     115             :     ushort patch;  /* The self-reported patch version of the client */
     116             : 
     117             :     uint   commit; /* The self-reported commit hash of the client, in little-endian order, or 0 if no commit hash was provided */
     118             :     uint   feature_set; /* The self-reported feature set of the client, in little-endian order */
     119             :   } version;
     120             : };
     121             : 
     122             : typedef struct fd_contact_info fd_contact_info_t;
     123             : 
     124             : /* A gossip vote represents a vote transaction that was sent to us by a
     125             :    peer node.  It is sent when the tag is FD_GOSSIP_UPDATE_TAG_VOTE.
     126             :    Votes are typically sent over the TPU, but also via. gossip for
     127             :    redundancy.
     128             : 
     129             :    The transaction is not validated or parsed in any way yet, and in
     130             :    particular the signatures have not been verified.   Transaction data
     131             :    is arbitrary and could be empty or corrupt or malicious.
     132             : 
     133             :    The source peer socket is included for use by downstream monitoring
     134             :    tools. */
     135             : 
     136             : struct fd_gossip_vote {
     137             :   fd_ip4_port_t socket;
     138             :   uchar vote_tower_index;
     139             :   ulong txn_sz;
     140             :   uchar txn[ 1232UL ];
     141             : };
     142             : 
     143             : typedef struct fd_gossip_vote fd_gossip_vote_t;
     144             : 
     145             : #define FD_GOSSIP_DUPLICATE_SHRED_MAX_CHUNKS (1054UL)
     146             : 
     147             : /* An edge case in the network is "equivocation" when a node publishes
     148             :    conflicting shred data for its leader slot.  In future this may be
     149             :    a slashable offense, but for now it simply "proven" on the chain and
     150             :    communicated among peers. */
     151             : 
     152             : struct fd_gossip_duplicate_shred {
     153             :   ushort index;
     154             :   ulong  slot;
     155             :   uchar  num_chunks;
     156             :   uchar  chunk_index;
     157             :   long   wallclock; /* in nanos */
     158             :   ulong  chunk_len;
     159             :   uchar  chunk[ FD_GOSSIP_DUPLICATE_SHRED_MAX_CHUNKS ];
     160             : };
     161             : 
     162             : typedef struct fd_gossip_duplicate_shred fd_gossip_duplicate_shred_t;
     163             : 
     164             : struct fd_gossip_snapshot_hash_pair {
     165             :   ulong slot;
     166             :   uchar hash[ 32UL ];
     167             : };
     168             : 
     169             : typedef struct fd_gossip_snapshot_hash_pair fd_gossip_snapshot_hash_pair_t;
     170             : 
     171             : #define FD_GOSSIP_SNAPSHOT_HASHES_MAX_INCREMENTAL (25UL)
     172             : 
     173             : /* Each peer node which is serving snapshots will periodically
     174             :    publish a snapshot hash update, which contains the hashes of the
     175             :    latest snapshots it has available.  This is sent when the tag is
     176             :    FD_GOSSIP_UPDATE_TAG_SNAPSHOT_HASHES.
     177             : 
     178             :    The full field indicates the full snapshot slot and hash, and then a
     179             :    list of recent incremental snapshots is provided which build on top
     180             :    of the full snapshot. */
     181             : 
     182             : struct fd_gossip_snapshot_hashes {
     183             :   fd_gossip_snapshot_hash_pair_t full[ 1 ];
     184             : 
     185             :   ulong                          incremental_len;
     186             :   fd_gossip_snapshot_hash_pair_t incremental[ FD_GOSSIP_SNAPSHOT_HASHES_MAX_INCREMENTAL ];
     187             : };
     188             : 
     189             : typedef struct fd_gossip_snapshot_hashes fd_gossip_snapshot_hashes_t;
     190             : 
     191             : struct fd_gossip_update_message {
     192             :   uchar tag;
     193             :   uchar origin_pubkey[ 32UL ];
     194             :   ulong origin_stake;
     195             :   long  wallclock_nanos;
     196             : 
     197             :   union {
     198             :     struct {
     199             :       ulong             idx; /* Index into flat array to place this contact info, see comments on FD_CONTACT_INFO_TABLE_SIZE */
     200             :       fd_contact_info_t contact_info[ 1 ];
     201             :     } contact_info;
     202             : 
     203             :     struct {
     204             :       ulong idx; /* Index into flat array of contact info to remove, see FD_CONTACT_INFO_TABLE_SIZE */
     205             :     } contact_info_remove;
     206             : 
     207             :     ulong                       lowest_slot;
     208             :     fd_gossip_vote_t            vote;
     209             :     fd_gossip_duplicate_shred_t duplicate_shred;
     210             :     fd_gossip_snapshot_hashes_t snapshot_hashes;
     211             :   };
     212             : };
     213             : 
     214             : typedef struct fd_gossip_update_message fd_gossip_update_message_t;
     215             : 
     216             : #endif /* HEADER_fd_src_flamenco_gossip_fd_gossip_types_h */

Generated by: LCOV version 1.14