LCOV - code coverage report
Current view: top level - flamenco/gossip - fd_gossip_message.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 6 59 10.2 %
Date: 2026-06-01 09:39:41 Functions: 0 47 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          57 : #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             : 
      58          21 : #define FD_GOSSIP_UPDATE_SZ_CONTACT_INFO        (offsetof(fd_gossip_update_message_t, contact_info)        + sizeof((fd_gossip_update_message_t *)0)->contact_info)
      59           6 : #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)
      60           0 : #define FD_GOSSIP_UPDATE_SZ_VOTE                (offsetof(fd_gossip_update_message_t, vote)                + sizeof((fd_gossip_update_message_t *)0)->vote)
      61           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)
      62           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)
      63             : 
      64             : /* Gossip messages encode wallclock in millis*, while we
      65             :    parse them into nanoseconds for internal use.
      66             : 
      67             :    * exceptions:
      68             :      - Contact Info outset (AKA instance creation wallclock) is encoded
      69             :        in micros */
      70           0 : #define FD_NANOSEC_TO_MILLI(_ts_) ((long)(_ts_/1000000))
      71           0 : #define FD_MILLI_TO_NANOSEC(_ts_) ((long)(_ts_*1000000))
      72           0 : #define FD_NANOSEC_TO_MICRO(_ts_) ((long)(_ts_/1000))
      73           0 : #define FD_MICRO_TO_NANOSEC(_ts_) ((long)(_ts_*1000))
      74             : 
      75         117 : #define FD_GOSSIP_UPDATE_TAG_CONTACT_INFO        (0)
      76          51 : #define FD_GOSSIP_UPDATE_TAG_CONTACT_INFO_REMOVE (1)
      77           0 : #define FD_GOSSIP_UPDATE_TAG_VOTE                (2)
      78           0 : #define FD_GOSSIP_UPDATE_TAG_DUPLICATE_SHRED     (3)
      79           0 : #define FD_GOSSIP_UPDATE_TAG_SNAPSHOT_HASHES     (4)
      80           0 : #define FD_GOSSIP_UPDATE_TAG_WFS_DONE            (5)
      81           0 : #define FD_GOSSIP_UPDATE_TAG_PEER_SATURATED      (6)
      82             : 
      83           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_GOSSIP            ( 0)
      84           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_SERVE_REPAIR_QUIC ( 1)
      85          36 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_RPC               ( 2)
      86           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_RPC_PUBSUB        ( 3)
      87           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_SERVE_REPAIR      ( 4)
      88           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU               ( 5)
      89           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_FORWARDS      ( 6)
      90           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_FORWARDS_QUIC ( 7)
      91           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_QUIC          ( 8)
      92           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_VOTE          ( 9)
      93           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TVU               (10)
      94           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TVU_QUIC          (11)
      95           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_VOTE_QUIC     (12)
      96           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_ALPENGLOW         (13)
      97           0 : #define FD_GOSSIP_CONTACT_INFO_SOCKET_CNT               (14)
      98             : 
      99           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_SOLANA_LABS   (0)
     100           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_JITO_LABS     (1)
     101           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_FRANKENDANCER (2)
     102           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_AGAVE         (3)
     103           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_AGAVE_PALADIN (4)
     104           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_FIREDANCER    (5)
     105           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_AGAVE_BAM     (6)
     106           0 : #define FD_GOSSIP_CONTACT_INFO_CLIENT_SIG           (7)
     107             : 
     108           0 : #define FD_GOSSIP_MESSAGE_PULL_REQUEST  (0)
     109           0 : #define FD_GOSSIP_MESSAGE_PULL_RESPONSE (1)
     110           0 : #define FD_GOSSIP_MESSAGE_PUSH          (2)
     111           0 : #define FD_GOSSIP_MESSAGE_PRUNE         (3)
     112           0 : #define FD_GOSSIP_MESSAGE_PING          (4)
     113           0 : #define FD_GOSSIP_MESSAGE_PONG          (5)
     114             : #define FD_GOSSIP_MESSAGE_CNT           (6)
     115             : 
     116             : struct fd_gossip_vote {
     117             :   uchar index;
     118             :   ulong transaction_len;
     119             :   uchar transaction[ 1232UL ];
     120             : };
     121             : 
     122             : typedef struct fd_gossip_vote fd_gossip_vote_t;
     123             : 
     124             : struct fd_gossip_node_instance {
     125             :   ulong timestamp;
     126             :   ulong token;
     127             : };
     128             : 
     129             : typedef struct fd_gossip_node_instance fd_gossip_node_instance_t;
     130             : 
     131             : /* Tightest bound for chunk[] given network constraints.
     132             : 
     133             :      IPv6 minimum MTU             = 1280
     134             :      IPv6 header                  =   40
     135             :      UDP header                   =    8
     136             :      PACKET_DATA_SIZE             = 1232   (= 1280 - 40 - 8)
     137             : 
     138             :      Maximum CrdsValue size inside PushMessage/PullResponse:
     139             :        PACKET_DATA_SIZE - tag(4) - from(32) - values_len(8) = 1188
     140             : 
     141             :      Minimum bytes consumed before chunk data:
     142             :        signature(64) + CrdsData tag(4) + index(2) + origin(32) +
     143             :        wallclock(8) + slot(8) + unused(4) + shred_type(1) +
     144             :        num_chunks(1) + chunk_index(1) + chunk_len(8)         = 133
     145             : 
     146             :      Remaining: 1188 - 133 = 1055  */
     147             : 
     148             : struct fd_gossip_duplicate_shred {
     149             :   ushort index;
     150             :   ulong  slot;
     151             :   uchar  num_chunks;
     152             :   uchar  chunk_index;
     153             :   ulong  chunk_len;
     154             :   uchar  chunk[ 1055UL ];
     155             : };
     156             : 
     157             : typedef struct fd_gossip_duplicate_shred fd_gossip_duplicate_shred_t;
     158             : 
     159             : /* Tightest bound for incremental[] given network constraints.
     160             : 
     161             :      IPv6 minimum MTU             = 1280
     162             :      IPv6 header                  =   40
     163             :      UDP header                   =    8
     164             :      PACKET_DATA_SIZE             = 1232   (= 1280 - 40 - 8)
     165             : 
     166             :      Maximum CrdsValue size inside PushMessage/PullResponse:
     167             :        PACKET_DATA_SIZE - tag(4) - from(32) - values_len(8) = 1188
     168             : 
     169             :      Bytes consumed before incremental loop:
     170             :        signature(64) + CrdsData tag(4) + origin(32) +
     171             :        full_slot(8) + full_hash(32) + inc_len(8)             = 148
     172             : 
     173             :      Remaining: 1188 - 148 = 1040
     174             :      Each entry: slot(8) + hash(32) = 40 bytes
     175             :      Max entries = floor(1040/40) = 26  */
     176             : 
     177             : struct fd_gossip_snapshot_hashes {
     178             :   ulong full_slot;
     179             :   uchar full_hash[ 32UL ];
     180             : 
     181             :   ulong incremental_len;
     182             :   struct {
     183             :     ulong slot;
     184             :     uchar hash[ 32UL ];
     185             :   } incremental[ 26UL ];
     186             : };
     187             : 
     188             : typedef struct fd_gossip_snapshot_hashes fd_gossip_snapshot_hashes_t;
     189             : 
     190             : struct fd_gossip_socket {
     191             :   ushort port;
     192             :   uint   is_ipv6;
     193             :   union {
     194             :     uint ip4;
     195             :     uchar ip6[ 16UL ];
     196             :   };
     197             : };
     198             : 
     199             : typedef struct fd_gossip_socket fd_gossip_socket_t;
     200             : 
     201             : struct fd_gossip_contact_info {
     202             :   ulong  outset;
     203             :   ushort shred_version;
     204             : 
     205             :   struct {
     206             :     ushort major;
     207             :     ushort minor;
     208             :     ushort patch;
     209             : 
     210             :     uint   commit;
     211             :     uint   feature_set;
     212             : 
     213             :     ushort client;
     214             :   } version;
     215             : 
     216             :   fd_gossip_socket_t sockets[ FD_GOSSIP_CONTACT_INFO_SOCKET_CNT ];
     217             : };
     218             : 
     219             : typedef struct fd_gossip_contact_info fd_gossip_contact_info_t;
     220             : 
     221             : struct fd_gossip_epoch_slots {
     222             :   uchar index;
     223             : };
     224             : 
     225             : typedef struct fd_gossip_epoch_slots fd_gossip_epoch_slots_t;
     226             : 
     227             : struct fd_gossip_lowest_slot {
     228             :   ulong lowest;
     229             : };
     230             : 
     231             : typedef struct fd_gossip_lowest_slot fd_gossip_lowest_slot_t;
     232             : 
     233             : struct fd_gossip_value {
     234             :   uint tag;
     235             : 
     236             :   uchar signature[ 64UL ];
     237             :   uchar origin[ 32UL ];
     238             :   ulong wallclock;
     239             : 
     240             :   ulong offset;
     241             :   ulong length;
     242             : 
     243             :   union {
     244             :     // DEPRECATED OR UNUSED
     245             :     // fd_gossip_legacy_contact_info_t           legacy_contact_info[ 1 ];
     246             :     // fd_gossip_legacy_snapshot_hashes_t        legacy_snapshot_hashes[ 1 ];
     247             :     // fd_gossip_account_hashes_t                account_hashes[ 1 ];
     248             :     // fd_gossip_legacy_version_t                legacy_version[ 1 ];
     249             :     // fd_gossip_version_t                       version[ 1 ];
     250             :     // fd_gossip_restart_last_voted_fork_slots_t restart_last_voted_fork_slots[ 1 ];
     251             :     // fd_gossip_restart_heaviest_fork_t         restart_heaviest_fork[ 1 ];
     252             : 
     253             :     fd_gossip_lowest_slot_t     lowest_slot[ 1 ];
     254             :     fd_gossip_vote_t            vote[ 1 ];
     255             :     fd_gossip_node_instance_t   node_instance[ 1 ];
     256             :     fd_gossip_duplicate_shred_t duplicate_shred[ 1 ];
     257             :     fd_gossip_snapshot_hashes_t snapshot_hashes[ 1 ];
     258             :     fd_gossip_contact_info_t    contact_info[ 1 ];
     259             :     fd_gossip_epoch_slots_t     epoch_slots[ 1 ];
     260             :   };
     261             : };
     262             : 
     263             : typedef struct fd_gossip_value fd_gossip_value_t;
     264             : 
     265             : /* Tightest bounds for Bloom keys[]/bits[] given network constraints.
     266             : 
     267             :      IPv6 minimum MTU             = 1280
     268             :      IPv6 header                  =   40
     269             :      UDP header                   =    8
     270             :      PACKET_DATA_SIZE             = 1232   (= 1280 - 40 - 8)
     271             : 
     272             :      PullRequest is the only message containing a Bloom filter.
     273             : 
     274             :      Bytes consumed before keys loop:
     275             :        Protocol tag(4) + keys_len(8)                         =  12
     276             : 
     277             :      Remaining: 1232 - 12 = 1220
     278             :      Each key: 8 bytes
     279             :      Max keys = floor(1220/8) = 152
     280             : 
     281             :      Bytes consumed before bits data:
     282             :        Protocol tag(4) + keys_len(8) + has_bits(1) +
     283             :        bits_cap(8)                                           =  21
     284             : 
     285             :      Remaining: 1232 - 21 = 1211
     286             :      Each u64: 8 bytes
     287             :      Max bits = floor(1211/8) = 151  */
     288             : 
     289             : struct fd_gossip_bloom {
     290             :   ulong keys_len;
     291             :   ulong keys[ 152UL ];
     292             :   ulong bits_cap;
     293             :   ulong bits_len;
     294             :   ulong bits[ 151UL ];
     295             :   ulong num_bits_set;
     296             : };
     297             : 
     298             : typedef struct fd_gossip_bloom fd_gossip_bloom_t;
     299             : 
     300             : struct fd_gossip_crds_filter {
     301             :   fd_gossip_bloom_t filter[ 1 ];
     302             :   ulong mask;
     303             :   uint mask_bits;
     304             : };
     305             : 
     306             : typedef struct fd_gossip_crds_filter fd_gossip_crds_filter_t;
     307             : 
     308             : struct fd_gossip_pull_request {
     309             :   fd_gossip_crds_filter_t crds_filter[ 1 ];
     310             : 
     311             :   fd_gossip_value_t contact_info[ 1 ];
     312             : };
     313             : 
     314             : typedef struct fd_gossip_pull_request fd_gossip_pull_request_t;
     315             : 
     316             : struct fd_gossip_pull_response {
     317             :   uchar from[ 32UL ];
     318             :   ulong values_len;
     319             :   fd_gossip_value_t values[ FD_GOSSIP_MESSAGE_MAX_CRDS ];
     320             : };
     321             : 
     322             : typedef struct fd_gossip_pull_response fd_gossip_pull_response_t;
     323             : 
     324             : struct fd_gossip_push {
     325             :   uchar from[ 32UL ];
     326             :   ulong values_len;
     327             :   fd_gossip_value_t values[ FD_GOSSIP_MESSAGE_MAX_CRDS ];
     328             : };
     329             : 
     330             : typedef struct fd_gossip_push fd_gossip_push_t;
     331             : 
     332             : /* Tightest bound for prunes[] given network constraints.
     333             : 
     334             :      IPv6 minimum MTU             = 1280
     335             :      IPv6 header                  =   40
     336             :      UDP header                   =    8
     337             :      PACKET_DATA_SIZE             = 1232   (= 1280 - 40 - 8)
     338             : 
     339             :      Bytes consumed before prunes loop:
     340             :        Protocol tag(4) + sender(32) + pubkey(32) +
     341             :        prunes_len(8)                                         =  76
     342             : 
     343             :      Remaining: 1232 - 76 = 1156
     344             :      Each prune: 32 bytes
     345             :      Max prunes = floor(1156/32) = 36  */
     346             : 
     347             : struct fd_gossip_prune {
     348             :   uchar sender[ 32UL ];
     349             :   uchar pubkey[ 32UL ];
     350             :   ulong prunes_len;
     351             :   uchar prunes[ 36UL ][ 32UL ];
     352             :   uchar signature[ 64UL ];
     353             :   uchar destination[ 32UL ];
     354             :   ulong wallclock;
     355             : };
     356             : 
     357             : typedef struct fd_gossip_prune fd_gossip_prune_t;
     358             : 
     359             : struct fd_gossip_ping {
     360             :   uchar from[ 32UL ];
     361             :   uchar token[ 32UL ];
     362             :   uchar signature[ 64UL ];
     363             : };
     364             : 
     365             : typedef struct fd_gossip_ping fd_gossip_ping_t;
     366             : 
     367             : struct fd_gossip_pong {
     368             :   uchar from[ 32UL ];
     369             :   uchar hash[ 32UL ];
     370             :   uchar signature[ 64UL ];
     371             : };
     372             : 
     373             : typedef struct fd_gossip_pong fd_gossip_pong_t;
     374             : 
     375             : struct fd_gossip_message {
     376             :   uint tag;
     377             : 
     378             :   union {
     379             :     fd_gossip_pull_request_t  pull_request[ 1 ];
     380             :     fd_gossip_pull_response_t pull_response[ 1 ];
     381             :     fd_gossip_push_t          push[ 1 ];
     382             :     fd_gossip_prune_t         prune[ 1 ];
     383             :     fd_gossip_ping_t          ping[ 1 ];
     384             :     fd_gossip_pong_t          pong[ 1 ];
     385             :   };
     386             : };
     387             : 
     388             : typedef struct fd_gossip_message fd_gossip_message_t;
     389             : 
     390             : int
     391             : fd_gossip_message_deserialize( fd_gossip_message_t * message,
     392             :                                uchar const *         payload,
     393             :                                ulong                 payload_sz );
     394             : 
     395             : long
     396             : fd_gossip_value_serialize( fd_gossip_value_t const * value,
     397             :                            uchar *                   out,
     398             :                            ulong                     out_sz );
     399             : 
     400             : struct fd_gossip_update_message {
     401             :   int tag;
     402             : 
     403             :   uchar origin[ 32UL ];
     404             :   ulong wallclock;
     405             : 
     406             :   union {
     407             :     struct {
     408             :       ulong idx;
     409             :       fd_gossip_contact_info_t value[ 1 ];
     410             :     } contact_info[ 1 ];
     411             : 
     412             :     struct {
     413             :       ulong idx;
     414             :     } contact_info_remove[ 1 ];
     415             : 
     416             :     struct {
     417             :       fd_gossip_socket_t socket[ 1 ];
     418             :       fd_gossip_vote_t value[ 1 ];
     419             :     } vote[ 1 ];
     420             : 
     421             :     fd_gossip_duplicate_shred_t duplicate_shred[ 1 ];
     422             :     fd_gossip_snapshot_hashes_t snapshot_hashes[ 1 ];
     423             :   };
     424             : };
     425             : 
     426             : typedef struct fd_gossip_update_message fd_gossip_update_message_t;
     427             : 
     428             : long
     429             : fd_gossip_pull_request_init( uchar *       payload,
     430             :                              ulong         payload_sz,
     431             :                              ulong         num_keys,
     432             :                              ulong         num_bits,
     433             :                              ulong         mask,
     434             :                              uint          mask_bits,
     435             :                              uchar const * contact_info_crds,
     436             :                              ulong         contact_info_crds_sz,
     437             :                              ulong **      out_bloom_keys,
     438             :                              ulong **      out_bloom_bits,
     439             :                              ulong **      out_bits_set );
     440             : 
     441             : /* fd_gossip_version_cstr converts gossip version fields to a null
     442             :    terminated c-string.  Returns 1 on success and 0 on failure (e.g.
     443             :    small out_sz)
     444             : 
     445             :    The 16-bit minor field has a special encoding to support semver
     446             :    prerelease notation.
     447             :     - High 2 bits: prerelease channel (0=stable, 1=rc, 2=beta, 3=alpha)
     448             :     - Low 14 bits: actual minor version number
     449             : 
     450             :     Patch field semantics:
     451             :         - If prerelease_bits==0 (stable), `patch` is rendered as the
     452             :           normal semver patch component:
     453             :           `<major>.<minor_actual>.<patch>`.
     454             :         - If prerelease_bits!=0 (prerelease), the semver patch component
     455             :           is forced to 0 and `patch` is interpreted as the prerelease
     456             :           sequence number, rendered as:
     457             :           `<major>.<minor_actual>.0-<channel>.<patch>`.
     458             : 
     459             :     Note that due to Frankendancer's existing unique versioning hack,
     460             :     future Frankendancer releases will all be stable (i.e.
     461             :     prerelease_bits==0) and based on stable Agave versions.  This is a
     462             :     permissible compromise given Frankendancer is approaching EOL. */
     463             : static inline int
     464             : fd_gossip_version_cstr( ushort major,
     465             :                  ushort minor,
     466             :                  ushort patch,
     467             :                  char * out,
     468           0 :                  ulong  out_sz ) {
     469           0 :   ushort prerelease_bits = (minor >> 14U) & 0x3U;
     470           0 :   ushort minor_actual = minor & 0x3FFFU;
     471             : 
     472           0 :   if( FD_UNLIKELY( prerelease_bits ) ) {
     473           0 :     const char * names[] = { "", "rc", "beta", "alpha" };
     474           0 :     return fd_cstr_printf_check( out, out_sz, NULL, "%hu.%hu.0-%s.%hu", major, minor_actual, names[ prerelease_bits ], patch );
     475           0 :   } else {
     476             :     return fd_cstr_printf_check( out, out_sz, NULL, "%hu.%hu.%hu", major, minor_actual, patch );
     477           0 :   }
     478           0 : }
     479             : 
     480             : #endif /* HEADER_fd_src_flamenco_gossip_fd_gossip_message_h */

Generated by: LCOV version 1.14