LCOV - code coverage report
Current view: top level - flamenco/gossip - fd_active_set.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 2 5 40.0 %
Date: 2025-09-19 04:41:14 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_gossip_fd_active_set_h
       2             : #define HEADER_fd_src_flamenco_gossip_fd_active_set_h
       3             : 
       4             : #include "fd_bloom.h"
       5             : #include "crds/fd_crds.h"
       6             : 
       7             : /* fd_active_set provides APIs for tracking the active set of nodes we
       8             :    should push messages to in a gossip network.
       9             : 
      10             :    In the Solana gossip protocol, each node selects a random set of up
      11             :    to 300 peers to send messages to, and then rotates one of the nodes
      12             :    out for a new, randomly selected one every so often.
      13             : 
      14             :    This is simple enough: just keep a list of the peer pubkeys, and
      15             :    occasionally replace one?
      16             : 
      17             :    There's two complications:
      18             : 
      19             :     (1) We want to select peers with a good distribution of stakes, so
      20             :         that we don't end up sending to a lot of low-stake peers if
      21             :         someone pollutes the gossip table with junk.
      22             : 
      23             :     (2) Peers sometimes request that we don't forward messages from
      24             :         other originating (origin) nodes to them, because they already
      25             :         have a lot of paths from that node.  This is called a prune.
      26             : 
      27             :    Complication (1) is handled by keeping a list of the top 12 peers
      28             :    (sorted by stake) for each of 25 buckets of stakes.  These buckets
      29             :    are all rotated together.
      30             : 
      31             :    And problem (2) is solved by keeping a bloom filter for each of the
      32             :    12 peers in each bucket.  The bloom filter is used to track which
      33             :    origins the peer has pruned. */
      34             : 
      35           0 : #define FD_ACTIVE_SET_STAKE_ENTRIES    (25UL)
      36           0 : #define FD_ACTIVE_SET_PEERS_PER_ENTRY  (12UL)
      37           0 : #define FD_ACTIVE_SET_MAX_PEERS        (FD_ACTIVE_SET_STAKE_ENTRIES*FD_ACTIVE_SET_PEERS_PER_ENTRY) /* 300 */
      38             : struct fd_active_set_peer {
      39             :   uchar        pubkey[ 32UL ];
      40             :   fd_bloom_t * bloom;
      41             : };
      42             : 
      43             : typedef struct fd_active_set_peer fd_active_set_peer_t;
      44             : 
      45             : struct fd_active_set_entry {
      46             :   ulong                nodes_idx; /* points to oldest entry in set */
      47             :   ulong                nodes_len;
      48             :   fd_active_set_peer_t nodes[ FD_ACTIVE_SET_PEERS_PER_ENTRY ][ 1UL ];
      49             : };
      50             : 
      51             : typedef struct fd_active_set_entry fd_active_set_entry_t;
      52             : 
      53           9 : #define FD_ACTIVE_SET_ALIGN     (64UL)
      54             : 
      55             : struct __attribute__((aligned(FD_ACTIVE_SET_ALIGN))) fd_active_set_private {
      56             :   fd_active_set_entry_t entries[ FD_ACTIVE_SET_STAKE_ENTRIES ][ 1UL ];
      57             : 
      58             :   fd_rng_t * rng;
      59             : 
      60             :   ulong magic; /* ==FD_ACTIVE_SET_MAGIC */
      61             : };
      62             : 
      63             : typedef struct fd_active_set_private fd_active_set_t;
      64             : 
      65             : #define FD_ACTIVE_SET_FOOTPRINT (sizeof(fd_active_set_t))
      66             : 
      67           3 : #define FD_ACTIVE_SET_MAGIC (0xF17EDA2CEA5E1000) /* FIREDANCE ASET V0 */
      68             : 
      69             : FD_PROTOTYPES_BEGIN
      70             : 
      71             : FD_FN_CONST ulong
      72             : fd_active_set_align( void );
      73             : 
      74             : FD_FN_CONST ulong
      75             : fd_active_set_footprint( void );
      76             : 
      77             : void *
      78             : fd_active_set_new( void *     shmem,
      79             :                    fd_rng_t * rng );
      80             : 
      81             : fd_active_set_t *
      82             : fd_active_set_join( void * shas );
      83             : 
      84             : /* fd_active_set_nodes retrieves the list of nodes that we should push
      85             :    messages from the origin to.  The list will not include peers that
      86             :    have pruned the origin, except if ignore_prunes_if_peer_is_origin
      87             :    is non-zero, in which case the list will include a peer if its pubkey
      88             :    matches the origin pubkey.
      89             : 
      90             :    Up to 12 peer nodes will be returned in out_nodes.  The values
      91             :    returned in out_nodes are an internal peer index of the active set
      92             :    and should not be used for anything other than calling
      93             :    fd_active_set_node_pubkey to get the pubkey of the peer.  The
      94             :    peer index is only valid for the current active set and should not be
      95             :    used after a call to fd_active_set_rotate or fd_active_set_prune. */
      96             : 
      97             : ulong
      98             : fd_active_set_nodes( fd_active_set_t * active_set,
      99             :                      uchar const *     identity_pubkey,
     100             :                      ulong             identity_stake,
     101             :                      uchar const *     origin,
     102             :                      ulong             origin_stake,
     103             :                      int               ignore_prunes_if_peer_is_origin,
     104             :                      ulong             out_nodes[ static 12UL ] );
     105             : 
     106             : uchar const *
     107             : fd_active_set_node_pubkey( fd_active_set_t * active_set,
     108             :                            ulong             peer_idx );
     109             : 
     110             : void
     111             : fd_active_set_prune( fd_active_set_t * active_set,
     112             :                      uchar const *     push_dest,
     113             :                      uchar const *     origin,
     114             :                      ulong             origin_stake,
     115             :                      uchar const *     identity_pubkey,
     116             :                      ulong             identity_stake );
     117             : 
     118             : /* fd_active_set_rotate chooses a random active set entry to swap/introduce
     119             :    a peer into. The peer is sampled from a distribution
     120             :    (provided by crds) specific to the active set bucket.
     121             : 
     122             :    returns the index that is being replaced within the
     123             :    300 peer set. This allows users to maintain data structures that track the
     124             :    active set. Returns ULONG_MAX if no peer replacement is found. */
     125             : 
     126             : ulong
     127             : fd_active_set_rotate( fd_active_set_t *     active_set,
     128             :                       fd_crds_t *           crds );
     129             : 
     130             : FD_PROTOTYPES_END
     131             : 
     132             : #endif /* HEADER_fd_src_flamenco_gossip_fd_active_set_h */

Generated by: LCOV version 1.14