LCOV - code coverage report
Current view: top level - flamenco/runtime/tests - fd_gossip_harness.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 315 341 92.4 %
Date: 2026-10-23 17:13:25 Functions: 12 12 100.0 %

          Line data    Source code
       1             : #include "fd_solfuzz_private.h"
       2             : #include "fd_gossip_harness.h"
       3             : #include "../../gossip/fd_gossip_message.h"
       4             : #include "../../../ballet/txn/fd_compact_u16.h"
       5             : #include "../../../disco/fd_disco_base.h"
       6             : #include "generated/gossip.pb.h"
       7             : 
       8             : /* alloc_bytes allocates a pb_bytes_array_t on the spad and copies
       9             :    src[0..len) into it. */
      10             : 
      11             : static pb_bytes_array_t *
      12             : alloc_bytes( fd_spad_t *   spad,
      13             :              uchar const * src,
      14       17433 :              ulong         len ) {
      15       17433 :   pb_bytes_array_t * arr = fd_spad_alloc( spad, alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE( len ) );
      16       17433 :   arr->size = (pb_size_t)len;
      17       17433 :   if( FD_LIKELY( len ) ) memcpy( arr->bytes, src, len );
      18       17433 :   return arr;
      19       17433 : }
      20             : 
      21             : /* Re-parse helpers that walk raw wire bytes to extract fields the
      22             :    main deserializer does not retain (addrs, sockets, extensions,
      23             :    compressed slots). */
      24             : 
      25         169 : #define FD_VARINT_U64_MAX_BYTES (10UL) /* ceil(64/7) */
      26             : 
      27             : static inline int
      28             : skip_varint_u16( uchar const ** p,
      29          96 :                  ulong *        sz ) {
      30          96 :   ulong n = fd_cu16_dec_sz( *p, *sz );
      31          96 :   if( FD_UNLIKELY( !n ) ) return 0;
      32          96 :   *p  += n;
      33          96 :   *sz -= n;
      34          96 :   return 1;
      35          96 : }
      36             : 
      37             : static inline int
      38             : read_varint_u16( ushort *        dst,
      39             :                  uchar const **  p,
      40          92 :                  ulong *         sz ) {
      41          92 :   ulong n = fd_cu16_dec_sz( *p, *sz );
      42          92 :   if( FD_UNLIKELY( !n ) ) return 0;
      43          92 :   *dst = fd_cu16_dec_fixed( *p, n );
      44          92 :   *p  += n;
      45          92 :   *sz -= n;
      46          92 :   return 1;
      47          92 : }
      48             : 
      49             : static inline int
      50             : skip_varint_u64( uchar const ** p,
      51          24 :                  ulong *        sz ) {
      52         169 :   for( ulong i=0UL; i<FD_VARINT_U64_MAX_BYTES; i++ ) {
      53         169 :     if( FD_UNLIKELY( !*sz ) ) return 0;
      54         169 :     uchar byte = **p;
      55         169 :     (*p)++; (*sz)--;
      56         169 :     if( FD_LIKELY( !(byte & 0x80) ) ) return 1;
      57         169 :   }
      58           0 :   return 0;
      59          24 : }
      60             : 
      61         836 : #define NEED(n) do { if( FD_UNLIKELY( sz < (n) ) ) return; } while(0)
      62         265 : #define SKIP(n) do { NEED(n); p += (n); sz -= (n); } while(0)
      63             : 
      64             : static void
      65             : reparse_contact_info_extra( fd_spad_t *                          spad,
      66             :                             uchar const *                        value_start,
      67             :                             ulong                                value_len,
      68          24 :                             fd_exec_test_gossip_contact_info_t * ci ) {
      69          24 :   uchar const * p  = value_start;
      70          24 :   ulong         sz = value_len;
      71             : 
      72          24 :   SKIP( 68UL );  /* signature(64) + tag(4) */
      73          24 :   SKIP( 32UL );  /* origin(32) */
      74          24 :   if( FD_UNLIKELY( !skip_varint_u64( &p, &sz ) ) ) return;  /* wallclock */
      75          24 :   SKIP( 10UL );  /* outset(8) + shred_version(2) */
      76             : 
      77          24 :   if( FD_UNLIKELY( !skip_varint_u16( &p, &sz ) ) ) return;  /* major */
      78          24 :   if( FD_UNLIKELY( !skip_varint_u16( &p, &sz ) ) ) return;  /* minor */
      79          24 :   if( FD_UNLIKELY( !skip_varint_u16( &p, &sz ) ) ) return;  /* patch */
      80          24 :   SKIP( 4UL );  /* commit (u32) */
      81          24 :   SKIP( 4UL );  /* feature_set (u32) */
      82          24 :   if( FD_UNLIKELY( !skip_varint_u16( &p, &sz ) ) ) return;  /* client */
      83             : 
      84             :   /* Addrs */
      85          24 :   ushort addrs_len = 0;
      86          24 :   if( FD_UNLIKELY( !read_varint_u16( &addrs_len, &p, &sz ) ) ) return;
      87          24 :   ci->addrs_count = (pb_size_t)addrs_len;
      88          24 :   if( addrs_len ) {
      89          23 :     ci->addrs = fd_spad_alloc( spad, alignof(fd_exec_test_gossip_ip_addr_t),
      90          23 :                                addrs_len * sizeof(fd_exec_test_gossip_ip_addr_t) );
      91          67 :     for( ushort i=0; i<addrs_len; i++ ) {
      92          44 :       NEED( 4UL );
      93          44 :       uint is_ip6 = FD_LOAD( uint, p );
      94          44 :       p += 4UL; sz -= 4UL;
      95          44 :       if( !is_ip6 ) {
      96          44 :         NEED( 4UL );
      97          44 :         ci->addrs[i].which_addr = FD_EXEC_TEST_GOSSIP_IP_ADDR_IPV4_TAG;
      98          44 :         ci->addrs[i].addr.ipv4  = fd_uint_bswap( FD_LOAD( uint, p ) );
      99          44 :         p += 4UL; sz -= 4UL;
     100          44 :       } else {
     101           0 :         NEED( 16UL );
     102           0 :         ci->addrs[i].which_addr    = FD_EXEC_TEST_GOSSIP_IP_ADDR_IPV6_TAG;
     103           0 :         ci->addrs[i].addr.ipv6.hi  = fd_ulong_bswap( FD_LOAD( ulong, p ) );
     104           0 :         ci->addrs[i].addr.ipv6.lo  = fd_ulong_bswap( FD_LOAD( ulong, p+8UL ) );
     105           0 :         p += 16UL; sz -= 16UL;
     106           0 :       }
     107          44 :     }
     108          23 :   }
     109             : 
     110             :   /* Sockets */
     111          24 :   ushort sockets_len = 0;
     112          24 :   if( FD_UNLIKELY( !read_varint_u16( &sockets_len, &p, &sz ) ) ) return;
     113          24 :   ci->sockets_count = (pb_size_t)sockets_len;
     114          24 :   if( sockets_len ) {
     115          23 :     ci->sockets = fd_spad_alloc( spad, alignof(fd_exec_test_gossip_socket_entry_t),
     116          23 :                                  sockets_len * sizeof(fd_exec_test_gossip_socket_entry_t) );
     117          67 :     for( ushort i=0; i<sockets_len; i++ ) {
     118          44 :       NEED( 2UL );
     119          44 :       ci->sockets[i].key   = *p; p++; sz--;
     120          44 :       ci->sockets[i].index = *p; p++; sz--;
     121          44 :       ushort offset = 0;
     122          44 :       if( FD_UNLIKELY( !read_varint_u16( &offset, &p, &sz ) ) ) return;
     123          44 :       ci->sockets[i].offset = offset;
     124          44 :     }
     125          23 :   }
     126             : 
     127             :   /* Extensions (Agave always sends empty) */
     128          24 :   ci->extensions = NULL;
     129          24 : }
     130             : 
     131             : static void
     132             : reparse_epoch_slots_extra( fd_spad_t *                         spad,
     133             :                            uchar const *                       value_start,
     134             :                            ulong                               value_len,
     135          51 :                            fd_exec_test_gossip_epoch_slots_t * es ) {
     136          51 :   uchar const * p  = value_start;
     137          51 :   ulong         sz = value_len;
     138             : 
     139          51 :   SKIP( 68UL );  /* signature(64) + tag(4) */
     140          51 :   SKIP( 33UL );  /* index(1) + origin(32) */
     141             : 
     142             :   /* slots_len (u64) */
     143          51 :   NEED( 8UL );
     144          51 :   ulong slots_len = FD_LOAD( ulong, p );
     145          51 :   p += 8UL; sz -= 8UL;
     146             : 
     147          51 :   es->slots_count = (pb_size_t)slots_len;
     148          51 :   if( !slots_len ) {
     149           0 :     es->slots = NULL;
     150           0 :     return;
     151           0 :   }
     152             : 
     153          51 :   es->slots = fd_spad_alloc( spad, alignof(fd_exec_test_gossip_compressed_slots_t),
     154          51 :                              slots_len * sizeof(fd_exec_test_gossip_compressed_slots_t) );
     155             : 
     156         126 :   for( ulong i=0UL; i<slots_len; i++ ) {
     157          75 :     fd_exec_test_gossip_compressed_slots_t * slot = &es->slots[i];
     158             : 
     159          75 :     NEED( 4UL );
     160          75 :     uint is_uncompressed = FD_LOAD( uint, p );
     161          75 :     p += 4UL; sz -= 4UL;
     162             : 
     163          75 :     NEED( 8UL );
     164          75 :     slot->first_slot = FD_LOAD( ulong, p );
     165          75 :     p += 8UL; sz -= 8UL;
     166             : 
     167          75 :     NEED( 8UL );
     168          75 :     slot->num = FD_LOAD( ulong, p );
     169          75 :     p += 8UL; sz -= 8UL;
     170             : 
     171          75 :     if( is_uncompressed ) {
     172          43 :       slot->which_data = FD_EXEC_TEST_GOSSIP_COMPRESSED_SLOTS_UNCOMPRESSED_TAG;
     173          43 :       NEED( 1UL );
     174          43 :       uchar has_bits = *p; p++; sz--;
     175             : 
     176          43 :       if( has_bits ) {
     177          28 :         NEED( 8UL );
     178          28 :         ulong bits_cap = FD_LOAD( ulong, p );
     179          28 :         p += 8UL; sz -= 8UL;
     180          28 :         NEED( bits_cap );
     181          28 :         slot->data.uncompressed = alloc_bytes( spad, p, bits_cap );
     182          28 :         p += bits_cap; sz -= bits_cap;
     183          28 :         SKIP( 8UL );  /* bits_cnt */
     184          28 :       } else {
     185          15 :         slot->data.uncompressed = alloc_bytes( spad, NULL, 0UL );
     186          15 :         SKIP( 8UL );  /* bits_cnt */
     187          15 :       }
     188          43 :     } else {
     189          32 :       slot->which_data = FD_EXEC_TEST_GOSSIP_COMPRESSED_SLOTS_FLATE2_TAG;
     190          32 :       NEED( 8UL );
     191          32 :       ulong compressed_len = FD_LOAD( ulong, p );
     192          32 :       p += 8UL; sz -= 8UL;
     193          32 :       NEED( compressed_len );
     194          32 :       slot->data.flate2 = alloc_bytes( spad, p, compressed_len );
     195          32 :       p += compressed_len; sz -= compressed_len;
     196          32 :     }
     197          75 :   }
     198          51 : }
     199             : 
     200             : #undef SKIP
     201             : #undef NEED
     202             : 
     203             : static void
     204             : convert_crds_data( fd_spad_t *                          spad,
     205             :                    fd_gossip_value_t const *            val,
     206             :                    uchar const *                        raw_in,
     207         392 :                    fd_exec_test_gossip_crds_data_t *    out ) {
     208         392 :   switch( val->tag ) {
     209          24 :   case FD_GOSSIP_VALUE_CONTACT_INFO: {
     210          24 :     out->which_data = FD_EXEC_TEST_GOSSIP_CRDS_DATA_CONTACT_INFO_TAG;
     211          24 :     fd_exec_test_gossip_contact_info_t * ci = &out->data.contact_info;
     212          24 :     ci->pubkey              = alloc_bytes( spad, val->origin, sizeof(val->origin) );
     213          24 :     ci->wallclock           = val->wallclock;
     214          24 :     ci->outset              = val->contact_info->outset;
     215          24 :     ci->shred_version       = val->contact_info->shred_version;
     216          24 :     ci->version_major       = val->contact_info->version.major;
     217          24 :     ushort packed_minor     = val->contact_info->version.minor;
     218          24 :     ushort prerelease_bits  = (ushort)((packed_minor >> 14U) & 0x3U);
     219          24 :     ci->version_minor       = (uint)(packed_minor & 0x3FFFU);
     220          24 :     ci->version_patch       = prerelease_bits ? 0U : (uint)val->contact_info->version.patch;
     221          24 :     ci->version_commit      = val->contact_info->version.commit;
     222          24 :     ci->version_feature_set = val->contact_info->version.feature_set;
     223          24 :     ci->version_client      = val->contact_info->version.client;
     224          24 :     reparse_contact_info_extra( spad, raw_in + val->offset, val->length, ci );
     225          24 :     break;
     226           0 :   }
     227          52 :   case FD_GOSSIP_VALUE_VOTE:
     228          52 :     out->which_data = FD_EXEC_TEST_GOSSIP_CRDS_DATA_VOTE_TAG;
     229          52 :     out->data.vote.index       = val->vote->index;
     230          52 :     out->data.vote.from        = alloc_bytes( spad, val->origin, sizeof(val->origin) );
     231          52 :     out->data.vote.wallclock   = val->wallclock;
     232          52 :     out->data.vote.transaction = alloc_bytes( spad, val->vote->transaction, val->vote->transaction_len );
     233          52 :     break;
     234          63 :   case FD_GOSSIP_VALUE_LOWEST_SLOT:
     235          63 :     out->which_data = FD_EXEC_TEST_GOSSIP_CRDS_DATA_LOWEST_SLOT_TAG;
     236          63 :     out->data.lowest_slot.index     = 0;
     237          63 :     out->data.lowest_slot.from      = alloc_bytes( spad, val->origin, sizeof(val->origin) );
     238          63 :     out->data.lowest_slot.lowest    = val->lowest_slot->lowest;
     239          63 :     out->data.lowest_slot.wallclock = val->wallclock;
     240          63 :     break;
     241          51 :   case FD_GOSSIP_VALUE_EPOCH_SLOTS: {
     242          51 :     out->which_data = FD_EXEC_TEST_GOSSIP_CRDS_DATA_EPOCH_SLOTS_TAG;
     243          51 :     fd_exec_test_gossip_epoch_slots_t * es = &out->data.epoch_slots;
     244          51 :     es->index     = val->epoch_slots->index;
     245          51 :     es->from      = alloc_bytes( spad, val->origin, sizeof(val->origin) );
     246          51 :     es->wallclock = val->wallclock;
     247          51 :     reparse_epoch_slots_extra( spad, raw_in + val->offset, val->length, es );
     248          51 :     break;
     249           0 :   }
     250          61 :   case FD_GOSSIP_VALUE_SNAPSHOT_HASHES: {
     251          61 :     out->which_data = FD_EXEC_TEST_GOSSIP_CRDS_DATA_SNAPSHOT_HASHES_TAG;
     252          61 :     fd_exec_test_gossip_snapshot_hashes_t * sh = &out->data.snapshot_hashes;
     253          61 :     sh->from      = alloc_bytes( spad, val->origin, sizeof(val->origin) );
     254          61 :     sh->full_slot = val->snapshot_hashes->full_slot;
     255          61 :     sh->full_hash = alloc_bytes( spad, val->snapshot_hashes->full_hash, sizeof(val->snapshot_hashes->full_hash) );
     256          61 :     sh->wallclock = val->wallclock;
     257          61 :     sh->incremental_count = (pb_size_t)val->snapshot_hashes->incremental_len;
     258          61 :     if( sh->incremental_count ) {
     259          45 :       sh->incremental = fd_spad_alloc( spad, alignof(fd_exec_test_gossip_incremental_hash_t),
     260          45 :                                        sh->incremental_count * sizeof(fd_exec_test_gossip_incremental_hash_t) );
     261         134 :       for( ulong i=0UL; i<sh->incremental_count; i++ ) {
     262          89 :         sh->incremental[i].slot = val->snapshot_hashes->incremental[i].slot;
     263          89 :         sh->incremental[i].hash = alloc_bytes( spad, val->snapshot_hashes->incremental[i].hash,
     264          89 :                                                sizeof(val->snapshot_hashes->incremental[i].hash) );
     265          89 :       }
     266          45 :     }
     267          61 :     break;
     268           0 :   }
     269          46 :   case FD_GOSSIP_VALUE_DUPLICATE_SHRED:
     270          46 :     out->which_data = FD_EXEC_TEST_GOSSIP_CRDS_DATA_DUPLICATE_SHRED_TAG;
     271          46 :     out->data.duplicate_shred.index       = val->duplicate_shred->index;
     272          46 :     out->data.duplicate_shred.from        = alloc_bytes( spad, val->origin, sizeof(val->origin) );
     273          46 :     out->data.duplicate_shred.wallclock   = val->wallclock;
     274          46 :     out->data.duplicate_shred.slot        = val->duplicate_shred->slot;
     275          46 :     out->data.duplicate_shred.shred_index = 0;
     276          46 :     out->data.duplicate_shred.shred_type  = 0;
     277          46 :     out->data.duplicate_shred.num_chunks  = val->duplicate_shred->num_chunks;
     278          46 :     out->data.duplicate_shred.chunk_index = val->duplicate_shred->chunk_index;
     279          46 :     out->data.duplicate_shred.chunk       = val->duplicate_shred->chunk_len
     280          46 :                                               ? alloc_bytes( spad, val->duplicate_shred->chunk,
     281          46 :                                                              val->duplicate_shred->chunk_len )
     282          46 :                                               : NULL;
     283          46 :     break;
     284          95 :   default:
     285          95 :     out->which_data = 0;
     286          95 :     break;
     287         392 :   }
     288         392 : }
     289             : 
     290             : static void
     291             : convert_crds_value( fd_spad_t *                          spad,
     292             :                     fd_gossip_value_t const *            val,
     293             :                     uchar const *                        raw_in,
     294         392 :                     fd_exec_test_gossip_crds_value_t *   out ) {
     295         392 :   out->signature = alloc_bytes( spad, val->signature, sizeof(val->signature) );
     296         392 :   out->has_data  = true;
     297         392 :   convert_crds_data( spad, val, raw_in, &out->data );
     298         392 : }
     299             : 
     300             : static void
     301             : convert_crds_values( fd_spad_t *                           spad,
     302             :                      fd_gossip_value_t const *             vals,
     303             :                      ulong                                 vals_len,
     304             :                      uchar const *                         raw_in,
     305             :                      fd_exec_test_gossip_crds_value_t **   out_vals,
     306         386 :                      pb_size_t *                           out_count ) {
     307         386 :   *out_count = (pb_size_t)vals_len;
     308         386 :   if( !vals_len ) {
     309           0 :     *out_vals = NULL;
     310           0 :     return;
     311           0 :   }
     312         386 :   *out_vals = fd_spad_alloc( spad, alignof(fd_exec_test_gossip_crds_value_t),
     313         386 :                              vals_len * sizeof(fd_exec_test_gossip_crds_value_t) );
     314         772 :   for( ulong i=0UL; i<vals_len; i++ ) {
     315         386 :     convert_crds_value( spad, &vals[i], raw_in, &(*out_vals)[i] );
     316         386 :   }
     317         386 : }
     318             : 
     319             : static void
     320             : convert_bloom( fd_spad_t *                   spad,
     321             :                fd_gossip_bloom_t const *     bloom,
     322           6 :                fd_exec_test_gossip_bloom_t * out ) {
     323           6 :   out->keys_count = (pb_size_t)bloom->keys_len;
     324           6 :   if( bloom->keys_len ) {
     325           0 :     out->keys = fd_spad_alloc( spad, alignof(uint64_t), bloom->keys_len * sizeof(uint64_t) );
     326           0 :     memcpy( out->keys, bloom->keys, bloom->keys_len * sizeof(uint64_t) );
     327           0 :   }
     328             :   /* Copy only block_len() worth of u64 blocks, not bits_cap.
     329             :      https://github.com/tov/bv-rs/blob/0.11.1/src/bit_vec/mod.rs#L243-L245 */
     330           6 :   ulong bits_blocks   = (bloom->bits_len + 63UL) / 64UL;
     331           6 :   ulong bits_byte_len = bits_blocks * sizeof(bloom->bits[0]);
     332           6 :   out->bits = bits_byte_len ? alloc_bytes( spad, (uchar const *)bloom->bits, bits_byte_len ) : NULL;
     333             :   /* Mask trailing bits beyond bits_len in the last block of the
     334             :      protobuf copy.  bv::BitVec::get_block() returns get_masked_block()
     335             :      which zeros bits past bit_len() in the last block.
     336             :      https://github.com/tov/bv-rs/blob/0.11.1/src/bit_vec/impls.rs#L30-L32
     337             :      https://github.com/tov/bv-rs/blob/0.11.1/src/traits/bits.rs#L134-L137 */
     338           6 :   if( bloom->bits_len & 63UL ) {
     339           1 :     ulong last = bits_blocks - 1UL;
     340           1 :     ulong mask = ( 2UL << ((bloom->bits_len - 1UL) & 63UL) ) - 1UL;
     341           1 :     ((ulong *)out->bits->bytes)[ last ] &= mask;
     342           1 :   }
     343           6 :   out->num_bits_set = bloom->num_bits_set;
     344           6 : }
     345             : 
     346             : static void
     347             : convert_gossip_msg( fd_spad_t *                 spad,
     348             :                     fd_gossip_message_t const * msg,
     349             :                     uchar const *               raw_in,
     350        2690 :                     fd_exec_test_gossip_msg_t * out ) {
     351        2690 :   switch( msg->tag ) {
     352         846 :   case FD_GOSSIP_MESSAGE_PING:
     353         846 :     out->which_msg = FD_EXEC_TEST_GOSSIP_MSG_PING_TAG;
     354         846 :     out->msg.ping.from      = alloc_bytes( spad, msg->ping->from,      sizeof(msg->ping->from) );
     355         846 :     out->msg.ping.token     = alloc_bytes( spad, msg->ping->token,     sizeof(msg->ping->token) );
     356         846 :     out->msg.ping.signature = alloc_bytes( spad, msg->ping->signature, sizeof(msg->ping->signature) );
     357         846 :     break;
     358         856 :   case FD_GOSSIP_MESSAGE_PONG:
     359         856 :     out->which_msg = FD_EXEC_TEST_GOSSIP_MSG_PONG_TAG;
     360         856 :     out->msg.pong.from      = alloc_bytes( spad, msg->pong->from,      sizeof(msg->pong->from) );
     361         856 :     out->msg.pong.hash      = alloc_bytes( spad, msg->pong->hash,      sizeof(msg->pong->hash) );
     362         856 :     out->msg.pong.signature = alloc_bytes( spad, msg->pong->signature, sizeof(msg->pong->signature) );
     363         856 :     break;
     364           6 :   case FD_GOSSIP_MESSAGE_PULL_REQUEST: {
     365           6 :     out->which_msg = FD_EXEC_TEST_GOSSIP_MSG_PULL_REQUEST_TAG;
     366           6 :     fd_exec_test_gossip_pull_request_t * pr = &out->msg.pull_request;
     367           6 :     pr->has_filter = true;
     368           6 :     pr->filter.has_filter = true;
     369           6 :     convert_bloom( spad, msg->pull_request->crds_filter->filter, &pr->filter.filter );
     370           6 :     pr->filter.mask_bits = msg->pull_request->crds_filter->mask_bits;
     371             :     /* Agave canonicalizes the mask by setting all (64-mask_bits) low bits to 1.
     372             :        https://github.com/anza-xyz/agave/blob/v4.0.0-beta.6/gossip/src/crds_gossip_pull.rs#L152-L155 */
     373           6 :     ulong lsb_mask = (pr->filter.mask_bits>=64U) ? 0UL : (ULONG_MAX >> pr->filter.mask_bits);
     374           6 :     pr->filter.mask = msg->pull_request->crds_filter->mask | lsb_mask;
     375           6 :     pr->has_value = true;
     376           6 :     convert_crds_value( spad, msg->pull_request->contact_info, raw_in, &pr->value );
     377           6 :     break;
     378           0 :   }
     379         192 :   case FD_GOSSIP_MESSAGE_PULL_RESPONSE: {
     380         192 :     out->which_msg = FD_EXEC_TEST_GOSSIP_MSG_PULL_RESPONSE_TAG;
     381         192 :     fd_exec_test_gossip_pull_response_t * pr = &out->msg.pull_response;
     382         192 :     pr->pubkey = alloc_bytes( spad, msg->pull_response->from, sizeof(msg->pull_response->from) );
     383         192 :     convert_crds_values( spad, msg->pull_response->values,
     384         192 :                          msg->pull_response->values_len,
     385         192 :                          raw_in,
     386         192 :                          &pr->values, &pr->values_count );
     387         192 :     break;
     388           0 :   }
     389         194 :   case FD_GOSSIP_MESSAGE_PUSH: {
     390         194 :     out->which_msg = FD_EXEC_TEST_GOSSIP_MSG_PUSH_MESSAGE_TAG;
     391         194 :     fd_exec_test_gossip_push_message_t * pm = &out->msg.push_message;
     392         194 :     pm->pubkey = alloc_bytes( spad, msg->push->from, sizeof(msg->push->from) );
     393         194 :     convert_crds_values( spad, msg->push->values,
     394         194 :                          msg->push->values_len,
     395         194 :                          raw_in,
     396         194 :                          &pm->values, &pm->values_count );
     397         194 :     break;
     398           0 :   }
     399         599 :   case FD_GOSSIP_MESSAGE_PRUNE: {
     400         599 :     out->which_msg = FD_EXEC_TEST_GOSSIP_MSG_PRUNE_MESSAGE_TAG;
     401         599 :     fd_exec_test_gossip_prune_message_t * pm = &out->msg.prune_message;
     402         599 :     pm->pubkey   = alloc_bytes( spad, msg->prune->sender,      sizeof(msg->prune->sender) );
     403         599 :     pm->has_data = true;
     404         599 :     pm->data.pubkey      = alloc_bytes( spad, msg->prune->pubkey,      sizeof(msg->prune->pubkey) );
     405         599 :     pm->data.signature   = alloc_bytes( spad, msg->prune->signature,   sizeof(msg->prune->signature) );
     406         599 :     pm->data.destination = alloc_bytes( spad, msg->prune->destination, sizeof(msg->prune->destination) );
     407         599 :     pm->data.wallclock   = msg->prune->wallclock;
     408         599 :     pm->data.prunes_count = (pb_size_t)msg->prune->prunes_len;
     409         599 :     if( msg->prune->prunes_len ) {
     410         586 :       pm->data.prunes = fd_spad_alloc( spad, alignof(pb_bytes_array_t *),
     411         586 :                                        msg->prune->prunes_len * sizeof(pb_bytes_array_t *) );
     412        9157 :       for( ulong i=0UL; i<msg->prune->prunes_len; i++ ) {
     413        8571 :         pm->data.prunes[i] = alloc_bytes( spad, msg->prune->prunes[i], sizeof(msg->prune->prunes[i]) );
     414        8571 :       }
     415         586 :     }
     416         599 :     break;
     417           0 :   }
     418           0 :   default:
     419           0 :     out->which_msg = 0;
     420           0 :     break;
     421        2690 :   }
     422        2690 : }
     423             : 
     424             : int
     425             : fd_solfuzz_gossip_decode( fd_solfuzz_runner_t * runner,
     426             :                           uchar *               out,
     427             :                           ulong *               out_sz,
     428             :                           uchar const *         in,
     429        4967 :                           ulong                 in_sz ) {
     430        4967 :   if( FD_UNLIKELY( in_sz>FD_GOSSIP_MTU ) ) FD_LOG_CRIT(( "invariant violation: gossip input %lu bytes exceeds MTU %lu, check fuzzer configuration", in_sz, FD_GOSSIP_MTU ));
     431             : 
     432        4967 :   fd_gossip_message_t msg[1] = {0};
     433        4967 :   fd_exec_test_gossip_effects_t effects = FD_EXEC_TEST_GOSSIP_EFFECTS_INIT_ZERO;
     434             : 
     435        4967 :   int ok = fd_gossip_message_deserialize( msg, in, in_sz );
     436        4967 :   if( ok ) {
     437        2690 :     effects.valid   = true;
     438        2690 :     effects.has_msg = true;
     439        2690 :     convert_gossip_msg( runner->spad, msg, in, &effects.msg );
     440        2690 :   } else {
     441        2277 :     effects.valid   = false;
     442        2277 :     effects.has_msg = false;
     443        2277 :   }
     444             : 
     445        4967 :   return !!sol_compat_encode( out, out_sz, &effects, &fd_exec_test_gossip_effects_t_msg );
     446        4967 : }

Generated by: LCOV version 1.14