LCOV - code coverage report
Current view: top level - flamenco/gossip - fd_ping_tracker.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 5 6 83.3 %
Date: 2026-08-13 04:56:22 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_gossip_fd_ping_tracker_h
       2             : #define HEADER_fd_src_flamenco_gossip_fd_ping_tracker_h
       3             : 
       4             : /* The gossip network amplifies inbound traffic.  For example, a node
       5             :    can send us a small pull request, with an empty bloom filter and then
       6             :    get back a very large set of pull responses.
       7             : 
       8             :    This is not good because an attacker can use it as a reflection
       9             :    vector for a DDoS attack.  To prevent this, we enforce a rule that we
      10             :    can only send data to peers that have responded to a ping request.
      11             : 
      12             :    The fd_ping_tracker maintains a metadata about the peers available to
      13             :    ping, who has been pinged, and who has responded, so that we can
      14             :    quickly determine before sending a message if we should send it or
      15             :    not.
      16             : 
      17             :    Any peer which has tried to send us a gossip message within the last
      18             :    sixty seconds is eligible to be pinged, except nodes with at least
      19             :    FD_GOSSIP_STAKED_THRESHOLD lamports of stake which are exempt from
      20             :    ping requirements.
      21             : 
      22             :    Once a peer has been pinged, we wait up to twenty seconds for a
      23             :    response before trying again.  We repeatedly retry pinging the peer
      24             :    every 20s for a minute until the peer responds, or their most recent
      25             :    message becomes older than sixty seconds.
      26             : 
      27             :    Once a peer is validated by responding to a ping with a valid pong,
      28             :    it is considered valid for 20 minutes.  After 18 minutes, we will
      29             :    begin pinging the peer again, every twenty seconds, to refresh the
      30             :    peer. */
      31             : 
      32             : #include "fd_gossip_message.h"
      33             : #include "../../util/rng/fd_rng.h"
      34             : #include "../../util/net/fd_net_headers.h"
      35             : 
      36          63 : #define FD_PING_TRACKER_ALIGN (128UL)
      37             : 
      38          21 : #define FD_PING_TRACKER_MAGIC (0xF17EDA2CE0113100) /* FIREDANCE PINGT V0 */
      39             : 
      40          21 : #define FD_PING_TRACKER_MAX (65536UL)
      41             : 
      42             : struct fd_ping_tracker_private;
      43             : typedef struct fd_ping_tracker_private fd_ping_tracker_t;
      44             : 
      45             : struct fd_ping_tracker_metrics {
      46             :   ulong unpinged_cnt;
      47             :   ulong invalid_cnt;
      48             :   ulong valid_cnt;
      49             :   ulong refreshing_cnt;
      50             : 
      51             :   ulong peers_evicted;
      52             : 
      53             :   ulong tracked_cnt;
      54             :   ulong stake_changed_cnt;
      55             :   ulong address_changed_cnt;
      56             : 
      57             :   ulong pong_result[ 6UL ];
      58             : };
      59             : 
      60             : typedef struct fd_ping_tracker_metrics fd_ping_tracker_metrics_t;
      61             : 
      62          18 : #define FD_PING_TRACKER_CHANGE_TYPE_ACTIVE          (0)
      63          24 : #define FD_PING_TRACKER_CHANGE_TYPE_INACTIVE        (1)
      64           0 : #define FD_PING_TRACKER_CHANGE_TYPE_INACTIVE_STAKED (2)
      65             : 
      66             : typedef void (*fd_ping_tracker_change_fn)( void *        ctx,
      67             :                                            uchar const * peer_pubkey,
      68             :                                            fd_ip4_port_t peer_address,
      69             :                                            long          now,
      70             :                                            int           change_type );
      71             : 
      72             : FD_PROTOTYPES_BEGIN
      73             : 
      74             : FD_FN_CONST ulong
      75             : fd_ping_tracker_align( void );
      76             : 
      77             : FD_FN_CONST ulong
      78             : fd_ping_tracker_footprint( ulong entrypoints_len );
      79             : 
      80             : void *
      81             : fd_ping_tracker_new( void *                    shmem,
      82             :                      fd_rng_t *                rng,
      83             :                      ulong                     entrypoints_len,
      84             :                      fd_ip4_port_t const *     entrypoints,
      85             :                      fd_ping_tracker_change_fn change_fn,
      86             :                      void *                    change_fn_ctx );
      87             : 
      88             : fd_ping_tracker_t *
      89             : fd_ping_tracker_join( void * shpt );
      90             : 
      91             : /* fd_ping_tracker_track marks a peer for ping tracking.  This should be
      92             :    called every time a peer sends us a valid gossip contact info message
      93             :    so that we can start pinging them.
      94             : 
      95             :    The tracker is idempotent, and will only refresh and update
      96             :    information about the peer, based on knowledge that it sent us a new
      97             :    message and is still alive.  It is valid to register a peer pubkey
      98             :    with a new stake amount, or peer address, and the tracker will
      99             :    internally update the information. */
     100             : 
     101             : void
     102             : fd_ping_tracker_track( fd_ping_tracker_t * ping_tracker,
     103             :                        uchar const *       peer_pubkey,
     104             :                        ulong               peer_stake,
     105             :                        fd_ip4_port_t       peer_address,
     106             :                        long                now );
     107             : 
     108             : /* fd_ping_tracker_register registers a response pong from a peer so
     109             :    that they can be considered as valid.  It should be called any time
     110             :    a peer sends a valid-looking pong.  Valid looking, because it might
     111             :    not be ponging an actual ping token we sent, but this function will
     112             :    validate that before marking the peer as active. */
     113             : 
     114             : void
     115             : fd_ping_tracker_register( fd_ping_tracker_t * ping_tracker,
     116             :                           uchar const *       peer_pubkey,
     117             :                           ulong               peer_stake,
     118             :                           fd_ip4_port_t       peer_address,
     119             :                           uchar const *       pong_token,
     120             :                           long                now );
     121             : 
     122             : /* fd_ping_tracker_active returns 1 if the peer is currently active and
     123             :    valid to send messages to, or 0 if the peer is not active. */
     124             : 
     125             : int
     126             : fd_ping_tracker_active( fd_ping_tracker_t * ping_tracker,
     127             :                         uchar const *       peer_pubkey,
     128             :                         fd_ip4_port_t       peer_address );
     129             : 
     130             : /* fd_ping_tracker_remove removes a peer from the ping tracker by
     131             :    pubkey.  If the peer was active (VALID or VALID_REFRESHING), the
     132             :    change_fn callback is fired with INACTIVE change type.  If the peer
     133             :    is not in the tracker, this is a no-op. */
     134             : 
     135             : void
     136             : fd_ping_tracker_remove( fd_ping_tracker_t * ping_tracker,
     137             :                         uchar const *       peer_pubkey,
     138             :                         long                now );
     139             : 
     140             : /* fd_ping_tracker_pop_request informs the caller if a ping request
     141             :    needs to be sent to a peer.  If a ping request needs to be sent, the
     142             :    peer pubkey is returned in out_peer_pubkey.  The caller should send a
     143             :    ping message to the peer.  The structure assumes the ping will be
     144             :    sent, and updates internal state accordingly.
     145             : 
     146             :    Returns 1 if a ping request needs to be sent, or 0 if no ping request
     147             :    is needed.
     148             : 
     149             :    The out_peer_pubkey is only valid if the return value is 1, and
     150             :    should only be used immediately.  The out_peer_pubkey is invalidated
     151             :    by any other call to the ping tracker, and using it after that is
     152             :    undefined behavior. */
     153             : 
     154             : int
     155             : fd_ping_tracker_pop_request( fd_ping_tracker_t *    ping_tracker,
     156             :                              long                   now,
     157             :                              uchar const **         out_peer_pubkey,
     158             :                              fd_ip4_port_t const ** out_peer_address,
     159             :                              uchar const **         out_token );
     160             : 
     161             : fd_ping_tracker_metrics_t const *
     162             : fd_ping_tracker_metrics( fd_ping_tracker_t const * ping_tracker );
     163             : 
     164             : #endif /* HEADER_fd_src_flamenco_gossip_fd_ping_tracker_h */

Generated by: LCOV version 1.14