LCOV - code coverage report
Current view: top level - flamenco/gossip - fd_ping_tracker.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 6 0.0 %
Date: 2026-10-22 18:10:43 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/net/fd_net_headers.h"
      34             : #include "../../disco/metrics/generated/fd_metrics_enums.h"
      35             : 
      36           0 : #define FD_PING_TRACKER_ALIGN (128UL)
      37             : 
      38           0 : #define FD_PING_TRACKER_MAGIC (0xF17EDA2CE0113100) /* FIREDANCE PINGT V0 */
      39             : 
      40           0 : #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 tracked_cnt;
      52             :   ulong removed[ FD_METRICS_ENUM_PING_PEER_REMOVE_REASON_CNT ];
      53             :   ulong address_changed_cnt;
      54             : 
      55             :   ulong pong_result[ FD_METRICS_ENUM_PONG_RESULT_CNT ];
      56             : };
      57             : 
      58             : typedef struct fd_ping_tracker_metrics fd_ping_tracker_metrics_t;
      59             : 
      60           0 : #define FD_PING_TRACKER_CHANGE_TYPE_ACTIVE          (0)
      61           0 : #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             :                      uchar const               seed[ static 32 ],
      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             :    Peers are tracked per (pubkey, address): a peer seen at a new
      94             :    address gets a separate entry that must pong on its own, and the
      95             :    old one ages out.  Tracking is idempotent and refreshes liveness.
      96             :    A peer that reaches FD_GOSSIP_STAKED_THRESHOLD stake is dropped at
      97             :    every address. */
      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_active returns 1 if the peer is currently active and
     121             :    valid to send messages to, or 0 if the peer is not active. */
     122             : 
     123             : int
     124             : fd_ping_tracker_active( fd_ping_tracker_t * ping_tracker,
     125             :                         uchar const *       peer_pubkey,
     126             :                         fd_ip4_port_t       peer_address );
     127             : 
     128             : /* fd_ping_tracker_remove removes every address of a peer from the
     129             :    ping tracker.  change_fn fires with INACTIVE for each address that
     130             :    was active (VALID or VALID_REFRESHING).  No-op for an untracked
     131             :    peer. */
     132             : 
     133             : void
     134             : fd_ping_tracker_remove( fd_ping_tracker_t * ping_tracker,
     135             :                         uchar const *       peer_pubkey,
     136             :                         long                now );
     137             : 
     138             : /* fd_ping_tracker_remove_all is fd_ping_tracker_remove with the given
     139             :    change type.  Returns the entries removed. */
     140             : 
     141             : ulong
     142             : fd_ping_tracker_remove_all( fd_ping_tracker_t * ping_tracker,
     143             :                             uchar const *       peer_pubkey,
     144             :                             long                now,
     145             :                             int                 change_type );
     146             : 
     147             : /* fd_ping_tracker_pop_request informs the caller if a ping request
     148             :    needs to be sent to a peer.  If a ping request needs to be sent, the
     149             :    peer pubkey is returned in out_peer_pubkey.  The caller should send a
     150             :    ping message to the peer.  The structure assumes the ping will be
     151             :    sent, and updates internal state accordingly.
     152             : 
     153             :    Returns 1 if a ping request needs to be sent, or 0 if no ping request
     154             :    is needed.
     155             : 
     156             :    The out_peer_pubkey is only valid if the return value is 1, and
     157             :    should only be used immediately.  The out_peer_pubkey is invalidated
     158             :    by any other call to the ping tracker, and using it after that is
     159             :    undefined behavior. */
     160             : 
     161             : int
     162             : fd_ping_tracker_pop_request( fd_ping_tracker_t *    ping_tracker,
     163             :                              long                   now,
     164             :                              uchar const **         out_peer_pubkey,
     165             :                              fd_ip4_port_t const ** out_peer_address,
     166             :                              uchar const **         out_token );
     167             : 
     168             : long
     169             : fd_ping_tracker_next_deadline( fd_ping_tracker_t const * ping_tracker );
     170             : 
     171             : fd_ping_tracker_metrics_t const *
     172             : fd_ping_tracker_metrics( fd_ping_tracker_t const * ping_tracker );
     173             : 
     174             : #endif /* HEADER_fd_src_flamenco_gossip_fd_ping_tracker_h */

Generated by: LCOV version 1.14