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: 2025-09-19 04:41:14 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             :    two minutes is eligible to be pinged, except nodes with at least one
      19             :    SOL of stake which are exempt from ping requirements.
      20             : 
      21             :    Once a peer has been pinged, we wait up to twenty seconds for a
      22             :    response before trying again.  We repeatedly retry pinging the peer
      23             :    until the peer responds, or their most recent message becomes older
      24             :    than two minutes.
      25             : 
      26             :    Once a peer is validated by responding to a ping with a valid pong,
      27             :    it is considered valid for 20 minutes.  After 18 minutes, we will
      28             :    begin pinging the peer again, every twenty seconds, to refresh the
      29             :    peer. */
      30             : 
      31             : #include "../../util/rng/fd_rng.h"
      32             : #include "../../util/net/fd_net_headers.h"
      33             : 
      34          45 : #define FD_PING_TRACKER_ALIGN (128UL)
      35             : 
      36          15 : #define FD_PING_TRACKER_MAGIC (0xF17EDA2CE0113100) /* FIREDANCE PINGT V0 */
      37             : 
      38          15 : #define FD_PING_TRACKER_MAX (65536UL)
      39             : 
      40             : struct fd_ping_tracker_private;
      41             : typedef struct fd_ping_tracker_private fd_ping_tracker_t;
      42             : 
      43             : struct fd_ping_tracker_metrics {
      44             :   ulong unpinged_cnt;
      45             :   ulong invalid_cnt;
      46             :   ulong valid_cnt;
      47             :   ulong refreshing_cnt;
      48             : 
      49             :   ulong peers_evicted;
      50             : 
      51             :   ulong tracked_cnt;
      52             :   ulong stake_changed_cnt;
      53             :   ulong address_changed_cnt;
      54             : 
      55             :   ulong pong_result[ 6UL ];
      56             : };
      57             : 
      58             : typedef struct fd_ping_tracker_metrics fd_ping_tracker_metrics_t;
      59             : 
      60           9 : #define FD_PING_TRACKER_CHANGE_TYPE_ACTIVE          (0)
      61           6 : #define FD_PING_TRACKER_CHANGE_TYPE_INACTIVE        (1)
      62           0 : #define FD_PING_TRACKER_CHANGE_TYPE_INACTIVE_STAKED (2)
      63             : 
      64             : typedef void (*fd_ping_tracker_change_fn)( void *        ctx,
      65             :                                            uchar const * peer_pubkey,
      66             :                                            fd_ip4_port_t peer_address,
      67             :                                            long          now,
      68             :                                            int           change_type );
      69             : 
      70             : FD_PROTOTYPES_BEGIN
      71             : 
      72             : FD_FN_CONST ulong
      73             : fd_ping_tracker_align( void );
      74             : 
      75             : FD_FN_CONST ulong
      76             : fd_ping_tracker_footprint( ulong entrypoints_len );
      77             : 
      78             : void *
      79             : fd_ping_tracker_new( void *                    shmem,
      80             :                      fd_rng_t *                rng,
      81             :                      ulong                     entrypoints_len,
      82             :                      fd_ip4_port_t const *     entrypoints,
      83             :                      fd_ping_tracker_change_fn change_fn,
      84             :                      void *                    change_fn_ctx );
      85             : 
      86             : fd_ping_tracker_t *
      87             : fd_ping_tracker_join( void * shpt );
      88             : 
      89             : /* fd_ping_tracker_track marks a peer for ping tracking.  This should be
      90             :    called every time a peer sends us a valid gossip contact info message
      91             :    so that we can start pinging them.
      92             : 
      93             :    The tracker is idempotent, and will only refresh and update
      94             :    information about the peer, based on knowledge that it sent us a new
      95             :    message and is still alive.  It is valid to register a peer pubkey
      96             :    with a new stake amount, or peer address, and the tracker will
      97             :    internally update the information. */
      98             : 
      99             : void
     100             : fd_ping_tracker_track( fd_ping_tracker_t * ping_tracker,
     101             :                        uchar const *       peer_pubkey,
     102             :                        ulong               peer_stake,
     103             :                        fd_ip4_port_t       peer_address,
     104             :                        long                now );
     105             : 
     106             : /* fd_ping_tracker_register registers a response pong from a peer so
     107             :    that they can be considered as valid.  It should be called any time
     108             :    a peer sends a valid-looking pong.  Valid looking, because it might
     109             :    not be ponging an actual ping token we sent, but this function will
     110             :    validate that before marking the peer as active. */
     111             : 
     112             : void
     113             : fd_ping_tracker_register( fd_ping_tracker_t * ping_tracker,
     114             :                           uchar const *       peer_pubkey,
     115             :                           ulong               peer_stake,
     116             :                           fd_ip4_port_t       peer_address,
     117             :                           uchar const *       pong_token,
     118             :                           long                now );
     119             : 
     120             : /* fd_ping_tracker_pop_request informs the caller if a ping request
     121             :    needs to be sent to a peer.  If a ping request needs to be sent, the
     122             :    peer pubkey is returned in out_peer_pubkey.  The caller should send a
     123             :    ping message to the peer.  The structure assumes the ping will be
     124             :    sent, and updates internal state accordingly.
     125             : 
     126             :    Returns 1 if a ping request needs to be sent, or 0 if no ping request
     127             :    is needed.
     128             : 
     129             :    The out_peer_pubkey is only valid if the return value is 1, and
     130             :    should only be used immediately.  The out_peer_pubkey is invalidated
     131             :    by any other call to the ping tracker, and using it after that is
     132             :    undefined behavior. */
     133             : 
     134             : int
     135             : fd_ping_tracker_pop_request( fd_ping_tracker_t *    ping_tracker,
     136             :                              long                   now,
     137             :                              uchar const **         out_peer_pubkey,
     138             :                              fd_ip4_port_t const ** out_peer_address,
     139             :                              uchar const **         out_token );
     140             : 
     141             : fd_ping_tracker_metrics_t const *
     142             : fd_ping_tracker_metrics( fd_ping_tracker_t const * ping_tracker );
     143             : 
     144             : #endif /* HEADER_fd_src_flamenco_gossip_fd_ping_tracker_h */

Generated by: LCOV version 1.14