LCOV - code coverage report
Current view: top level - flamenco/gossip - fd_active_set.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 68 118 57.6 %
Date: 2025-10-13 04:42:14 Functions: 6 8 75.0 %

          Line data    Source code
       1             : #include "fd_active_set.h"
       2             : #include "fd_active_set_private.h"
       3             : 
       4             : FD_FN_CONST ulong
       5          33 : fd_active_set_align( void ) {
       6          33 :   return FD_ACTIVE_SET_ALIGN;
       7          33 : }
       8             : 
       9             : FD_FN_CONST ulong
      10          18 : fd_active_set_footprint( void ) {
      11          18 :   ulong l;
      12          18 :   l = FD_LAYOUT_INIT;
      13          18 :   l = FD_LAYOUT_APPEND( l, FD_ACTIVE_SET_ALIGN, sizeof(fd_active_set_t) );
      14          18 :   l = FD_LAYOUT_APPEND( l, FD_BLOOM_ALIGN,      25UL*12UL*fd_bloom_footprint( 0.1, 32768UL ) );
      15          18 :   return FD_LAYOUT_FINI( l, FD_ACTIVE_SET_ALIGN );
      16          18 : }
      17             : 
      18             : void *
      19             : fd_active_set_new( void *     shmem,
      20           6 :                    fd_rng_t * rng ) {
      21           6 :   if( FD_UNLIKELY( !shmem ) ) {
      22           0 :     FD_LOG_WARNING(( "NULL shmem" ));
      23           0 :     return NULL;
      24           0 :   }
      25             : 
      26           6 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_active_set_align() ) ) ) {
      27           0 :     FD_LOG_WARNING(( "misaligned shmem" ));
      28           0 :     return NULL;
      29           0 :   }
      30             : 
      31           6 :   ulong bloom_footprint = fd_bloom_footprint( 0.1, 32768UL );
      32             : 
      33           6 :   FD_SCRATCH_ALLOC_INIT( l, shmem );
      34           6 :   fd_active_set_t * as = FD_SCRATCH_ALLOC_APPEND( l, FD_ACTIVE_SET_ALIGN, sizeof(fd_active_set_t) );
      35           6 :   uchar * _blooms = FD_SCRATCH_ALLOC_APPEND( l, FD_BLOOM_ALIGN, 25UL*12UL*bloom_footprint );
      36           6 :   FD_TEST( FD_SCRATCH_ALLOC_FINI( l, FD_ACTIVE_SET_ALIGN ) == (ulong)shmem + fd_active_set_footprint() );
      37             : 
      38           6 :   as->rng = rng;
      39         156 :   for( ulong i=0UL; i<25UL; i++ ) {
      40         150 :     fd_active_set_entry_t * entry = as->entries[ i ];
      41         150 :     entry->nodes_idx = 0UL;
      42         150 :     entry->nodes_len = 0UL;
      43             : 
      44        1950 :     for( ulong j=0UL; j<12UL; j++ ) {
      45        1800 :       fd_active_set_peer_t * peer = entry->nodes[ j ];
      46        1800 :       peer->bloom = fd_bloom_join( fd_bloom_new( _blooms, rng, 0.1, 32768UL ) );
      47        1800 :       if( FD_UNLIKELY( !peer->bloom ) ) {
      48           0 :         FD_LOG_WARNING(( "failed to create bloom filter" ));
      49           0 :         return NULL;
      50           0 :       }
      51        1800 :       _blooms += bloom_footprint;
      52        1800 :     }
      53         150 :   }
      54             : 
      55           6 :   FD_COMPILER_MFENCE();
      56           6 :   FD_VOLATILE( as->magic ) = FD_ACTIVE_SET_MAGIC;
      57           6 :   FD_COMPILER_MFENCE();
      58             : 
      59           6 :   return (void *)as;
      60           6 : }
      61             : 
      62             : fd_active_set_t *
      63           6 : fd_active_set_join( void * shas ) {
      64           6 :   if( FD_UNLIKELY( !shas ) ) {
      65           0 :     FD_LOG_WARNING(( "NULL shas" ));
      66           0 :     return NULL;
      67           0 :   }
      68             : 
      69           6 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shas, fd_active_set_align() ) ) ) {
      70           0 :     FD_LOG_WARNING(( "misaligned shas" ));
      71           0 :     return NULL;
      72           0 :   }
      73             : 
      74           6 :   fd_active_set_t * as = (fd_active_set_t *)shas;
      75             : 
      76           6 :   if( FD_UNLIKELY( as->magic!=FD_ACTIVE_SET_MAGIC ) ) {
      77           0 :     FD_LOG_WARNING(( "bad magic" ));
      78           0 :     return NULL;
      79           0 :   }
      80             : 
      81           6 :   return as;
      82           6 : }
      83             : 
      84             : ulong
      85             : fd_active_set_nodes( fd_active_set_t * active_set,
      86             :                      uchar const *     identity_pubkey,
      87             :                      ulong             identity_stake,
      88             :                      uchar const *     origin,
      89             :                      ulong             origin_stake,
      90             :                      int               ignore_prunes_if_peer_is_origin,
      91           3 :                      ulong             out_nodes[ static 12UL ] ) {
      92           3 :   ulong stake_bucket = fd_active_set_stake_bucket( fd_ulong_min( identity_stake, origin_stake ) );
      93           3 :   fd_active_set_entry_t * entry = active_set->entries[ stake_bucket ];
      94             : 
      95           3 :   int identity_eq_origin = !memcmp( identity_pubkey, origin, 32UL );
      96             : 
      97           3 :   ulong out_idx = 0UL;
      98           3 :   for( ulong i=0UL; i<entry->nodes_len; i++ ) {
      99           0 :     fd_active_set_peer_t * peer = entry->nodes[ (entry->nodes_idx+i) % 12UL ];
     100             : 
     101           0 :     int must_push_if_peer_is_origin = ignore_prunes_if_peer_is_origin && !memcmp( peer->pubkey, origin, 32UL );
     102           0 :     int must_push_own_values = identity_eq_origin && !memcmp( peer->pubkey, identity_pubkey, 32UL ); /* why ? */
     103           0 :     if( FD_UNLIKELY( fd_bloom_contains( peer->bloom, origin, 32UL ) && !must_push_own_values && !must_push_if_peer_is_origin ) ) continue;
     104           0 :     out_nodes[ out_idx++ ] = stake_bucket*12UL + i;
     105           0 :   }
     106           3 :   return out_idx;
     107           3 : }
     108             : 
     109             : uchar const *
     110             : fd_active_set_node_pubkey( fd_active_set_t * active_set,
     111           0 :                            ulong             peer_idx ){
     112           0 :   ulong bucket = peer_idx / FD_ACTIVE_SET_PEERS_PER_ENTRY;
     113           0 :   ulong idx    = peer_idx % FD_ACTIVE_SET_PEERS_PER_ENTRY;
     114           0 :   if( FD_UNLIKELY( bucket>=FD_ACTIVE_SET_STAKE_ENTRIES ) ) {
     115           0 :     FD_LOG_ERR(( "peer_idx out of range" ));
     116           0 :   }
     117           0 :   if( FD_UNLIKELY( active_set->entries[ bucket ]->nodes_len<=idx ) ) {
     118           0 :     FD_LOG_ERR(( "peer_idx out of range within bucket" ));
     119           0 :   }
     120             : 
     121           0 :   return active_set->entries[ bucket ]->nodes[ idx ]->pubkey;
     122           0 : }
     123             : 
     124             : void
     125             : fd_active_set_prune( fd_active_set_t * active_set,
     126             :                      uchar const *     push_dest,
     127             :                      uchar const *     origin,
     128             :                      ulong             origin_stake,
     129             :                      uchar const *     identity_pubkey,
     130           0 :                      ulong             identity_stake ) {
     131           0 :   if( FD_UNLIKELY( !memcmp( identity_pubkey, origin, 32UL ) ) ) return;
     132             : 
     133           0 :   ulong bucket = fd_active_set_stake_bucket( fd_ulong_min( identity_stake, origin_stake ) );
     134           0 :   for( ulong i=0UL; i<12UL; i++ ) {
     135           0 :     if( FD_UNLIKELY( !memcmp( active_set->entries[ bucket ]->nodes[ i ]->pubkey, push_dest, 32UL ) ) ) {
     136           0 :       fd_bloom_insert( active_set->entries[ bucket ]->nodes[ i ]->bloom, origin, 32UL );
     137           0 :       return;
     138           0 :     }
     139           0 :   }
     140           0 : }
     141             : 
     142             : ulong
     143             : fd_active_set_rotate( fd_active_set_t * active_set,
     144           3 :                       fd_crds_t *       crds ) {
     145           3 :   ulong num_bloom_filter_items = fd_ulong_max( fd_crds_peer_count( crds ), 512UL );
     146             : 
     147           3 :   ulong bucket = fd_rng_ulong_roll( active_set->rng, 25UL );
     148           3 :   fd_active_set_entry_t * entry = active_set->entries[ bucket ];
     149             : 
     150           3 :   ulong replace_idx;
     151             : 
     152           3 :   if( FD_LIKELY( entry->nodes_len==12UL ) ) {
     153           0 :     replace_idx      = entry->nodes_idx;
     154           0 :     entry->nodes_idx = (entry->nodes_idx+1UL) % 12UL;
     155           0 :     fd_crds_bucket_add( crds, bucket, entry->nodes[ replace_idx ]->pubkey );
     156           3 :   } else {
     157           3 :     replace_idx = entry->nodes_len;
     158           3 :   }
     159             : 
     160           3 :   fd_active_set_peer_t * replace = entry->nodes[ replace_idx ];
     161             : 
     162           3 :   fd_contact_info_t const * new_peer = fd_crds_bucket_sample_and_remove( crds, active_set->rng, bucket );
     163           3 :   if( FD_UNLIKELY( !new_peer ) ) {
     164           0 :     return ULONG_MAX;
     165           0 :   }
     166             : 
     167           3 :   fd_bloom_initialize( replace->bloom, num_bloom_filter_items );
     168           3 :   fd_bloom_insert( replace->bloom, new_peer->pubkey.uc, 32UL );
     169           3 :   fd_memcpy( replace->pubkey, new_peer->pubkey.uc, 32UL );
     170           3 :   entry->nodes_len = fd_ulong_min( entry->nodes_len+1UL, 12UL );
     171           3 :   return bucket*12UL+replace_idx;
     172           3 : }

Generated by: LCOV version 1.14