LCOV - code coverage report
Current view: top level - flamenco/gossip - fd_gossip_message.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 6 99 6.1 %
Date: 2026-10-22 18:10:43 Functions: 0 162 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_gossip_fd_gossip_message_h
       2             : #define HEADER_fd_src_flamenco_gossip_fd_gossip_message_h
       3             : 
       4             : #include "../../util/fd_util_base.h"
       5             : #include "../../util/cstr/fd_cstr.h"
       6             : #include "fd_gossip_value.h"
       7             : 
       8             : #include <stddef.h>
       9             : 
      10             : /* The maximum number of contact infos that may be present at any one
      11             :    time.  If new contact infos are added, a removal will be issued first
      12             :    to make space.  This is a hard limit, and the consumer of the contact
      13             :    info messages can assume it is always respected.
      14             : 
      15             :    The contact info messages are designed to be consumed in an
      16             :    incremental way.  In particular, CONTACT_INFO and CONTACT_INFO_REMOVE
      17             :    messages are both sent with an idx field, which is the index of the
      18             :    contact info in an imaginary array of contact infos.  Updates will
      19             :    always have the same idx for the same pubkey, and removes will
      20             :    likewise have the same idx for the pubkey being removed.  A consumer
      21             :    of contact info updates can therefore simply maintain a local array
      22             :    of contact infos, and update it with the idx field.  */
      23             : 
      24           0 : #define FD_CONTACT_INFO_TABLE_SIZE (32768UL)
      25             : 
      26             : /* Tightest bound for a single CrdsValue given network constraints.
      27             : 
      28             :      IPv6 minimum MTU             = 1280
      29             :      IPv6 header                  =   40
      30             :      UDP header                   =    8
      31             :      PACKET_DATA_SIZE             = 1232   (= 1280 - 40 - 8)
      32             : 
      33             :      Maximum CrdsValue size inside PushMessage/PullResponse:
      34             :        PACKET_DATA_SIZE - tag(4) - from(32) - values_len(8)  = 1188  */
      35             : 
      36           0 : #define FD_GOSSIP_VALUE_MAX_SZ (1188UL)
      37             : 
      38             : /* Tightest bound for values[] in a Push / PullResponse given network
      39             :    constraints.
      40             : 
      41             :      IPv6 minimum MTU             = 1280
      42             :      IPv6 header                  =   40
      43             :      UDP header                   =    8
      44             :      PACKET_DATA_SIZE             = 1232   (= 1280 - 40 - 8)
      45             : 
      46             :      Minimum bytes consumed before values loop:
      47             :        Protocol tag(4) + from(32) + values_len(8)             =  44
      48             : 
      49             :      Remaining: 1232 - 44 = 1188
      50             :      Each CrdsValue: signature(64) + CrdsData tag(4) = 68 bytes minimum
      51             :      Max values = floor(1188/68) = 17  */
      52             : 
      53           0 : #define FD_GOSSIP_MESSAGE_MAX_CRDS (17UL)
      54             : 
      55           0 : #define FD_GOSSIP_FAILED_NO_CONTACT_INFO (1)
      56           0 : #define FD_GOSSIP_FAILED_WALLCLOCK       (2)
      57           0 : #define FD_GOSSIP_FAILED_DUPLICATE       (3)
      58             : 
      59             : /* FD_GOSSIP_STAKED_THRESHOLD is the minimum stake (in lamports) at
      60             :    which a node is considered an active participant (e.g. it does not
      61             :    need to maintain a connection by responding to pings), whereas nodes
      62             :    below this threshold are treated as unstaked.  This is 100 SOL. */
      63           0 : #define FD_GOSSIP_STAKED_THRESHOLD (100UL*1000000000UL)
      64             : 
      65           0 : #define FD_GOSSIP_UPDATE_SZ_CONTACT_INFO        (offsetof(fd_gossip_update_message_t, contact_info)        + sizeof((fd_gossip_update_message_t *)0)->contact_info)
      66           0 : #define FD_GOSSIP_UPDATE_SZ_CONTACT_INFO_REMOVE (offsetof(fd_gossip_update_message_t, contact_info_remove) + sizeof((fd_gossip_update_message_t *)0)->contact_info_remove)
      67           0 : #define FD_GOSSIP_UPDATE_SZ_VOTE                (offsetof(fd_gossip_update_message_t, vote)                + sizeof((fd_gossip_update_message_t *)0)->vote)
      68           0 : #define FD_GOSSIP_UPDATE_SZ_DUPLICATE_SHRED     (offsetof(fd_gossip_update_message_t, duplicate_shred)     + sizeof((fd_gossip_update_message_t *)0)->duplicate_shred)
      69           0 : #define FD_GOSSIP_UPDATE_SZ_SNAPSHOT_HASHES     (offsetof(fd_gossip_update_message_t, snapshot_hashes)     + sizeof((fd_gossip_update_message_t *)0)->snapshot_hashes)
      70             : 
      71             : /* Gossip messages encode wallclock in millis*, while we
      72             :    parse them into nanoseconds for internal use.
      73             : 
      74             :    * exceptions:
      75             :      - Contact Info outset (AKA instance creation wallclock) is encoded
      76             :        in micros */
      77           0 : #define FD_NANOSEC_TO_MILLI(_ts_) ((long)(_ts_/1000000))
      78           0 : #define FD_MILLI_TO_NANOSEC(_ts_) ((long)(_ts_*1000000))
      79           0 : #define FD_NANOSEC_TO_MICRO(_ts_) ((long)(_ts_/1000))
      80           0 : #define FD_MICRO_TO_NANOSEC(_ts_) ((long)(_ts_*1000))
      81             : 
      82           0 : #define FD_GOSSIP_UPDATE_TAG_CONTACT_INFO        (0)
      83           0 : #define FD_GOSSIP_UPDATE_TAG_CONTACT_INFO_REMOVE (1)
      84           0 : #define FD_GOSSIP_UPDATE_TAG_VOTE                (2)
      85           0 : #define FD_GOSSIP_UPDATE_TAG_DUPLICATE_SHRED     (3)
      86           0 : #define FD_GOSSIP_UPDATE_TAG_SNAPSHOT_HASHES     (4)
      87           0 : #define FD_GOSSIP_UPDATE_TAG_WFS_DONE            (5)
      88           0 : #define FD_GOSSIP_UPDATE_TAG_PEER_SATURATED      (6)
      89             : 
      90           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_GOSSIP            ( 0)
      91           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_SERVE_REPAIR_QUIC ( 1)
      92           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_RPC               ( 2)
      93           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_RPC_PUBSUB        ( 3)
      94           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_SERVE_REPAIR      ( 4)
      95           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU               ( 5)
      96           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_FORWARDS      ( 6)
      97           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_FORWARDS_QUIC ( 7)
      98           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_QUIC          ( 8)
      99           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_VOTE          ( 9)
     100           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TVU               (10)
     101           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TVU_QUIC          (11)
     102           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_VOTE_QUIC     (12)
     103           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_ALPENGLOW         (13)
     104           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_CNT               (14)
     105             : 
     106           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_SOLANA_LABS             (0)
     107           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_JITO_LABS               (1)
     108           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_FRANKENDANCER           (2)
     109           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_AGAVE                   (3)
     110           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_AGAVE_PALADIN           (4)
     111           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_FIREDANCER              (5)
     112           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_AGAVE_BAM               (6)
     113           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_SIG                     (7)
     114           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_RAKURAI                 (8)
     115           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_HARMONIC_FIREDANCER     (9)
     116           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_HARMONIC_AGAVE         (10)
     117           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_HARMONIC_FRANKENDANCER (11)
     118           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_FIRE_BAM               (12)
     119           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_RAIKU                  (13)
     120             : 
     121         824 : #define FD_GOSSIP_MESSAGE_PULL_REQUEST  (0)
     122        1014 : #define FD_GOSSIP_MESSAGE_PULL_RESPONSE (1)
     123        1017 : #define FD_GOSSIP_MESSAGE_PUSH          (2)
     124        1445 : #define FD_GOSSIP_MESSAGE_PRUNE         (3)
     125        1700 : #define FD_GOSSIP_MESSAGE_PING          (4)
     126        1712 : #define FD_GOSSIP_MESSAGE_PONG          (5)
     127             : #define FD_GOSSIP_MESSAGE_CNT           (6)
     128             : 
     129             : struct fd_gossip_vote {
     130             :   uchar index;
     131             :   ulong transaction_len;
     132             :   uchar transaction[ 1232UL ];
     133             : };
     134             : 
     135             : typedef struct fd_gossip_vote fd_gossip_vote_t;
     136             : 
     137             : struct fd_gossip_node_instance {
     138             :   ulong timestamp;
     139             :   ulong token;
     140             : };
     141             : 
     142             : typedef struct fd_gossip_node_instance fd_gossip_node_instance_t;
     143             : 
     144             : /* Tightest bound for chunk[] given network constraints.
     145             : 
     146             :      IPv6 minimum MTU             = 1280
     147             :      IPv6 header                  =   40
     148             :      UDP header                   =    8
     149             :      PACKET_DATA_SIZE             = 1232   (= 1280 - 40 - 8)
     150             : 
     151             :      Maximum CrdsValue size inside PushMessage/PullResponse:
     152             :        PACKET_DATA_SIZE - tag(4) - from(32) - values_len(8) = 1188
     153             : 
     154             :      Minimum bytes consumed before chunk data:
     155             :        signature(64) + CrdsData tag(4) + index(2) + origin(32) +
     156             :        wallclock(8) + slot(8) + unused(4) + shred_type(1) +
     157             :        num_chunks(1) + chunk_index(1) + chunk_len(8)         = 133
     158             : 
     159             :      Remaining: 1188 - 133 = 1055  */
     160             : 
     161             : struct fd_gossip_duplicate_shred {
     162             :   ushort index;
     163             :   ulong  slot;
     164             :   uchar  num_chunks;
     165             :   uchar  chunk_index;
     166             :   ulong  chunk_len;
     167             :   uchar  chunk[ 1055UL ];
     168             : };
     169             : 
     170             : typedef struct fd_gossip_duplicate_shred fd_gossip_duplicate_shred_t;
     171             : 
     172             : /* Tightest bound for incremental[] given network constraints.
     173             : 
     174             :      IPv6 minimum MTU             = 1280
     175             :      IPv6 header                  =   40
     176             :      UDP header                   =    8
     177             :      PACKET_DATA_SIZE             = 1232   (= 1280 - 40 - 8)
     178             : 
     179             :      Maximum CrdsValue size inside PushMessage/PullResponse:
     180             :        PACKET_DATA_SIZE - tag(4) - from(32) - values_len(8) = 1188
     181             : 
     182             :      Bytes consumed before incremental loop:
     183             :        signature(64) + CrdsData tag(4) + origin(32) +
     184             :        full_slot(8) + full_hash(32) + inc_len(8)             = 148
     185             : 
     186             :      Remaining: 1188 - 148 = 1040
     187             :      Each entry: slot(8) + hash(32) = 40 bytes
     188             :      Max entries = floor(1040/40) = 26  */
     189             : 
     190             : struct fd_gossip_snapshot_hashes {
     191             :   ulong full_slot;
     192             :   uchar full_hash[ 32UL ];
     193             : 
     194             :   ulong incremental_len;
     195             :   struct {
     196             :     ulong slot;
     197             :     uchar hash[ 32UL ];
     198             :   } incremental[ 26UL ];
     199             : };
     200             : 
     201             : typedef struct fd_gossip_snapshot_hashes fd_gossip_snapshot_hashes_t;
     202             : 
     203             : struct fd_gossip_socket {
     204             :   ushort port;
     205             :   uint   is_ipv6;
     206             :   union {
     207             :     uint ip4;
     208             :     uchar ip6[ 16UL ];
     209             :   };
     210             : };
     211             : 
     212             : typedef struct fd_gossip_socket fd_gossip_socket_t;
     213             : 
     214             : struct fd_gossip_contact_info {
     215             :   ulong  outset;
     216             :   ushort shred_version;
     217             : 
     218             :   struct {
     219             :     ushort major;
     220             :     ushort minor;
     221             :     ushort patch;
     222             : 
     223             :     uint   commit;
     224             :     uint   feature_set;
     225             : 
     226             :     ushort client;
     227             :   } version;
     228             : 
     229             :   fd_gossip_socket_t sockets[ FD_GOSSIP_CONTACT_INFO_SOCKET_CNT ];
     230             : };
     231             : 
     232             : typedef struct fd_gossip_contact_info fd_gossip_contact_info_t;
     233             : 
     234             : FD_FN_PURE static inline int
     235             : fd_gossip_contact_info_eq( fd_gossip_contact_info_t const * ci1,
     236           0 :                            fd_gossip_contact_info_t const * ci2 ) {
     237           0 :   if( ci1->shred_version      !=ci2->shred_version       ||
     238           0 :       ci1->outset             !=ci2->outset              ||
     239           0 :       ci1->version.client     !=ci2->version.client      ||
     240           0 :       ci1->version.major      !=ci2->version.major       ||
     241           0 :       ci1->version.minor      !=ci2->version.minor       ||
     242           0 :       ci1->version.patch      !=ci2->version.patch       ||
     243           0 :       ci1->version.commit     !=ci2->version.commit      ||
     244           0 :       ci1->version.feature_set!=ci2->version.feature_set ) return 0;
     245             : 
     246           0 :   for( ulong j=0UL; j<FD_GOSSIP_CONTACT_INFO_SOCKET_CNT; j++ ) {
     247           0 :     if( ci1->sockets[ j ].is_ipv6!=ci2->sockets[ j ].is_ipv6 ) return 0;
     248           0 :     if( ci1->sockets[ j ].is_ipv6 ) {
     249           0 :       if( memcmp( ci1->sockets[ j ].ip6, ci2->sockets[ j ].ip6, 16UL ) ) return 0;
     250           0 :     } else {
     251           0 :       if( ci1->sockets[ j ].ip4!=ci2->sockets[ j ].ip4 ) return 0;
     252           0 :     }
     253           0 :     if( ci1->sockets[ j ].port!=ci2->sockets[ j ].port ) return 0;
     254           0 :   }
     255           0 :   return 1;
     256           0 : }
     257             : 
     258             : struct fd_gossip_epoch_slots {
     259             :   uchar index;
     260             : };
     261             : 
     262             : typedef struct fd_gossip_epoch_slots fd_gossip_epoch_slots_t;
     263             : 
     264             : struct fd_gossip_lowest_slot {
     265             :   ulong lowest;
     266             : };
     267             : 
     268             : typedef struct fd_gossip_lowest_slot fd_gossip_lowest_slot_t;
     269             : 
     270             : struct fd_gossip_value {
     271             :   uint tag;
     272             : 
     273             :   uchar signature[ 64UL ];
     274             :   uchar origin[ 32UL ];
     275             :   ulong wallclock;
     276             : 
     277             :   ulong offset;
     278             :   ulong length;
     279             : 
     280             :   union {
     281             :     // DEPRECATED OR UNUSED
     282             :     // fd_gossip_legacy_contact_info_t           legacy_contact_info[ 1 ];
     283             :     // fd_gossip_legacy_snapshot_hashes_t        legacy_snapshot_hashes[ 1 ];
     284             :     // fd_gossip_account_hashes_t                account_hashes[ 1 ];
     285             :     // fd_gossip_legacy_version_t                legacy_version[ 1 ];
     286             :     // fd_gossip_version_t                       version[ 1 ];
     287             :     // fd_gossip_restart_last_voted_fork_slots_t restart_last_voted_fork_slots[ 1 ];
     288             :     // fd_gossip_restart_heaviest_fork_t         restart_heaviest_fork[ 1 ];
     289             : 
     290             :     fd_gossip_lowest_slot_t     lowest_slot[ 1 ];
     291             :     fd_gossip_vote_t            vote[ 1 ];
     292             :     fd_gossip_node_instance_t   node_instance[ 1 ];
     293             :     fd_gossip_duplicate_shred_t duplicate_shred[ 1 ];
     294             :     fd_gossip_snapshot_hashes_t snapshot_hashes[ 1 ];
     295             :     fd_gossip_contact_info_t    contact_info[ 1 ];
     296             :     fd_gossip_epoch_slots_t     epoch_slots[ 1 ];
     297             :   };
     298             : };
     299             : 
     300             : typedef struct fd_gossip_value fd_gossip_value_t;
     301             : 
     302             : /* Tightest bounds for Bloom keys[]/bits[] given network constraints.
     303             : 
     304             :      IPv6 minimum MTU             = 1280
     305             :      IPv6 header                  =   40
     306             :      UDP header                   =    8
     307             :      PACKET_DATA_SIZE             = 1232   (= 1280 - 40 - 8)
     308             : 
     309             :      PullRequest is the only message containing a Bloom filter.
     310             : 
     311             :      Bytes consumed before keys loop:
     312             :        Protocol tag(4) + keys_len(8)                         =  12
     313             : 
     314             :      Remaining: 1232 - 12 = 1220
     315             :      Each key: 8 bytes
     316             :      Max keys = floor(1220/8) = 152
     317             : 
     318             :      Bytes consumed before bits data:
     319             :        Protocol tag(4) + keys_len(8) + has_bits(1) +
     320             :        bits_cap(8)                                           =  21
     321             : 
     322             :      Remaining: 1232 - 21 = 1211
     323             :      Each u64: 8 bytes
     324             :      Max bits = floor(1211/8) = 151  */
     325             : 
     326             : struct fd_gossip_bloom {
     327             :   ulong keys_len;
     328             :   ulong keys[ 152UL ];
     329             :   ulong bits_cap;
     330             :   ulong bits_len;
     331             :   ulong bits[ 151UL ];
     332             :   ulong num_bits_set;
     333             : };
     334             : 
     335             : typedef struct fd_gossip_bloom fd_gossip_bloom_t;
     336             : 
     337             : struct fd_gossip_crds_filter {
     338             :   fd_gossip_bloom_t filter[ 1 ];
     339             :   ulong mask;
     340             :   uint mask_bits;
     341             : };
     342             : 
     343             : typedef struct fd_gossip_crds_filter fd_gossip_crds_filter_t;
     344             : 
     345             : struct fd_gossip_pull_request {
     346             :   fd_gossip_crds_filter_t crds_filter[ 1 ];
     347             : 
     348             :   fd_gossip_value_t contact_info[ 1 ];
     349             : };
     350             : 
     351             : typedef struct fd_gossip_pull_request fd_gossip_pull_request_t;
     352             : 
     353             : struct fd_gossip_pull_response {
     354             :   uchar from[ 32UL ];
     355             :   ulong values_len;
     356             :   fd_gossip_value_t values[ FD_GOSSIP_MESSAGE_MAX_CRDS ];
     357             : };
     358             : 
     359             : typedef struct fd_gossip_pull_response fd_gossip_pull_response_t;
     360             : 
     361             : struct fd_gossip_push {
     362             :   uchar from[ 32UL ];
     363             :   ulong values_len;
     364             :   fd_gossip_value_t values[ FD_GOSSIP_MESSAGE_MAX_CRDS ];
     365             : };
     366             : 
     367             : typedef struct fd_gossip_push fd_gossip_push_t;
     368             : 
     369             : /* Tightest bound for prunes[] given network constraints.
     370             : 
     371             :      IPv6 minimum MTU             = 1280
     372             :      IPv6 header                  =   40
     373             :      UDP header                   =    8
     374             :      PACKET_DATA_SIZE             = 1232   (= 1280 - 40 - 8)
     375             : 
     376             :      Bytes consumed before prunes loop:
     377             :        Protocol tag(4) + sender(32) + pubkey(32) +
     378             :        prunes_len(8)                                         =  76
     379             : 
     380             :      Remaining: 1232 - 76 = 1156
     381             :      Each prune: 32 bytes
     382             :      Max prunes = floor(1156/32) = 36  */
     383             : 
     384             : struct fd_gossip_prune {
     385             :   uchar sender[ 32UL ];
     386             :   uchar pubkey[ 32UL ];
     387             :   ulong prunes_len;
     388             :   uchar prunes[ 36UL ][ 32UL ];
     389             :   uchar signature[ 64UL ];
     390             :   uchar destination[ 32UL ];
     391             :   ulong wallclock;
     392             : };
     393             : 
     394             : typedef struct fd_gossip_prune fd_gossip_prune_t;
     395             : 
     396             : struct fd_gossip_ping {
     397             :   uchar from[ 32UL ];
     398             :   uchar token[ 32UL ];
     399             :   uchar signature[ 64UL ];
     400             : };
     401             : 
     402             : typedef struct fd_gossip_ping fd_gossip_ping_t;
     403             : 
     404             : struct fd_gossip_pong {
     405             :   uchar from[ 32UL ];
     406             :   uchar hash[ 32UL ];
     407             :   uchar signature[ 64UL ];
     408             : };
     409             : 
     410             : typedef struct fd_gossip_pong fd_gossip_pong_t;
     411             : 
     412             : struct fd_gossip_message {
     413             :   uint tag;
     414             : 
     415             :   union {
     416             :     fd_gossip_pull_request_t  pull_request[ 1 ];
     417             :     fd_gossip_pull_response_t pull_response[ 1 ];
     418             :     fd_gossip_push_t          push[ 1 ];
     419             :     fd_gossip_prune_t         prune[ 1 ];
     420             :     fd_gossip_ping_t          ping[ 1 ];
     421             :     fd_gossip_pong_t          pong[ 1 ];
     422             :   };
     423             : };
     424             : 
     425             : typedef struct fd_gossip_message fd_gossip_message_t;
     426             : 
     427             : static inline ulong
     428           0 : fd_gossip_message_used_sz( fd_gossip_message_t const * message ) {
     429           0 :   switch( message->tag ) {
     430           0 :   case FD_GOSSIP_MESSAGE_PULL_RESPONSE: return (ulong)((uchar const *)message->pull_response->values-(uchar const *)message)+message->pull_response->values_len*sizeof(fd_gossip_value_t);
     431           0 :   case FD_GOSSIP_MESSAGE_PUSH:          return (ulong)((uchar const *)message->push->values         -(uchar const *)message)+message->push->values_len         *sizeof(fd_gossip_value_t);
     432           0 :   case FD_GOSSIP_MESSAGE_PULL_REQUEST:  return (ulong)((uchar const *)(message->pull_request+1)-(uchar const *)message);
     433           0 :   case FD_GOSSIP_MESSAGE_PRUNE:         return (ulong)((uchar const *)(message->prune+1)       -(uchar const *)message);
     434           0 :   case FD_GOSSIP_MESSAGE_PING:          return (ulong)((uchar const *)(message->ping+1)        -(uchar const *)message);
     435           0 :   case FD_GOSSIP_MESSAGE_PONG:          return (ulong)((uchar const *)(message->pong+1)        -(uchar const *)message);
     436           0 :   default:                              return sizeof(fd_gossip_message_t);
     437           0 :   }
     438           0 : }
     439             : 
     440             : int
     441             : fd_gossip_message_deserialize( fd_gossip_message_t * message,
     442             :                                uchar const *         payload,
     443             :                                ulong                 payload_sz );
     444             : 
     445             : long
     446             : fd_gossip_value_serialize( fd_gossip_value_t const * value,
     447             :                            uchar *                   out,
     448             :                            ulong                     out_sz );
     449             : 
     450             : struct fd_gossip_update_message {
     451             :   int tag;
     452             : 
     453             :   uchar origin[ 32UL ];
     454             :   ulong wallclock;
     455             : 
     456             :   union {
     457             :     struct {
     458             :       ulong idx;
     459             :       fd_gossip_contact_info_t value[ 1 ];
     460             :     } contact_info[ 1 ];
     461             : 
     462             :     struct {
     463             :       ulong idx;
     464             :     } contact_info_remove[ 1 ];
     465             : 
     466             :     struct {
     467             :       long first_seen_nanos;
     468             :       fd_gossip_socket_t socket[ 1 ];
     469             :       fd_gossip_vote_t value[ 1 ];
     470             :     } vote[ 1 ];
     471             : 
     472             :     fd_gossip_duplicate_shred_t duplicate_shred[ 1 ];
     473             :     fd_gossip_snapshot_hashes_t snapshot_hashes[ 1 ];
     474             :   };
     475             : };
     476             : 
     477             : typedef struct fd_gossip_update_message fd_gossip_update_message_t;
     478             : 
     479             : long
     480             : fd_gossip_pull_request_init( uchar *       payload,
     481             :                              ulong         payload_sz,
     482             :                              ulong         num_keys,
     483             :                              ulong         num_bits,
     484             :                              ulong         mask,
     485             :                              uint          mask_bits,
     486             :                              uchar const * contact_info_crds,
     487             :                              ulong         contact_info_crds_sz,
     488             :                              uchar **      out_bloom_keys,
     489             :                              uchar **      out_bloom_bits,
     490             :                              uchar **      out_bits_set );
     491             : 
     492             : /* fd_gossip_version_cstr converts gossip version fields to a null
     493             :    terminated c-string.  Returns 1 on success and 0 on failure (e.g.
     494             :    small out_sz)
     495             : 
     496             :    The 16-bit minor field has a special encoding to support semver
     497             :    prerelease notation.
     498             :     - High 2 bits: prerelease channel (0=stable, 1=rc, 2=beta, 3=alpha)
     499             :     - Low 14 bits: actual minor version number
     500             : 
     501             :     Patch field semantics:
     502             :         - If prerelease_bits==0 (stable), `patch` is rendered as the
     503             :           normal semver patch component:
     504             :           `<major>.<minor_actual>.<patch>`.
     505             :         - If prerelease_bits!=0 (prerelease), the semver patch component
     506             :           is forced to 0 and `patch` is interpreted as the prerelease
     507             :           sequence number, rendered as:
     508             :           `<major>.<minor_actual>.0-<channel>.<patch>`.
     509             : 
     510             :     Note that due to Frankendancer's existing unique versioning hack,
     511             :     future Frankendancer releases will all be stable (i.e.
     512             :     prerelease_bits==0) and based on stable Agave versions.  This is a
     513             :     permissible compromise given Frankendancer is approaching EOL. */
     514             : static inline int
     515             : fd_gossip_version_cstr( ushort major,
     516             :                  ushort minor,
     517             :                  ushort patch,
     518             :                  char * out,
     519           0 :                  ulong  out_sz ) {
     520           0 :   ushort prerelease_bits = (minor >> 14U) & 0x3U;
     521           0 :   ushort minor_actual = minor & 0x3FFFU;
     522             : 
     523           0 :   if( FD_UNLIKELY( prerelease_bits ) ) {
     524           0 :     const char * names[] = { "", "rc", "beta", "alpha" };
     525           0 :     return fd_cstr_printf_check( out, out_sz, NULL, "%hu.%hu.0-%s.%hu", major, minor_actual, names[ prerelease_bits ], patch );
     526           0 :   } else {
     527           0 :     return fd_cstr_printf_check( out, out_sz, NULL, "%hu.%hu.%hu", major, minor_actual, patch );
     528           0 :   }
     529           0 : }
     530             : 
     531             : #endif /* HEADER_fd_src_flamenco_gossip_fd_gossip_message_h */

Generated by: LCOV version 1.14