LCOV - code coverage report
Current view: top level - discof/restore/utils - fd_sspeer_selector.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 7 7 100.0 %
Date: 2026-06-29 05:51:35 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_discof_restore_utils_fd_sspeer_selector_h
       2             : #define HEADER_fd_src_discof_restore_utils_fd_sspeer_selector_h
       3             : 
       4             : /* The snapshot peer selector (sspeer_selector) continuously selects
       5             :    the most optimal snapshot peer to download snapshots from.  The
       6             :    most optimal peer is defined as the closest peer that serves the
       7             :    most recent snapshot. */
       8             : 
       9             : #include "../../../util/fd_util_base.h"
      10             : #include "../../../util/net/fd_net_headers.h"
      11             : #include "fd_sspeer.h"
      12             : 
      13         129 : #define FD_SSPEER_SELECTOR_MAGIC (0xF17EDA2CE5593350) /* FIREDANCE SSPING V0 */
      14             : 
      15             : /* Sentinel score returned by fd_sspeer_selector_best when no peer was
      16             :    found and by fd_sspeer_selector_add on failure. */
      17         108 : #define FD_SSPEER_SCORE_INVALID   (ULONG_MAX)
      18             : 
      19             : /* Maximum score a valid peer can have.  FD_SSPEER_SCORE_MAX ensures a
      20             :    valid peer's score is never confused with FD_SSPEER_SCORE_INVALID. */
      21         906 : #define FD_SSPEER_SCORE_MAX       (ULONG_MAX-1UL)
      22             : 
      23             : /* Sentinel value indicating that a snapshot slot (full or incremental)
      24             :    is unknown or absent. */
      25        1650 : #define FD_SSPEER_SLOT_UNKNOWN    (ULONG_MAX)
      26             : 
      27             : /* Sentinel value indicating that peer latency has not been measured. */
      28        1002 : #define FD_SSPEER_LATENCY_UNKNOWN (ULONG_MAX)
      29             : 
      30             : /* Plausibility bound: slots at or above this are silently dropped.
      31             :    ~10^10 is ~125 years of mainnet at 2.5 slots/s. */
      32           3 : #define FD_SSPEER_PLAUSIBLE_MAX_SLOT (10UL*1000UL*1000UL*1000UL)
      33             : 
      34             : /* Return code for fd_sspeer_selector_update (internal). */
      35          90 : #define FD_SSPEER_UPDATE_SUCCESS ( 0)
      36             : 
      37             : /* fd_sscluster_slot stores the max value for full and incremental
      38             :    slot computed from all tracked peers in the cluster. */
      39             : struct fd_sscluster_slot {
      40             :   ulong full;
      41             :   ulong incremental;
      42             : };
      43             : 
      44             : typedef struct fd_sscluster_slot fd_sscluster_slot_t;
      45             : 
      46             :  /* fd_sspeer_t represents a selected peer from the snapshot peer
      47             :     selector, including the peer's address, resolved snapshot slots,
      48             :     and selector score. */
      49             : struct fd_sspeer {
      50             :   fd_sspeer_key_t key;       /* key identifying the peer */
      51             :   fd_ip4_port_t   addr;      /* address of the peer */
      52             :   ulong           full_slot;
      53             :   ulong           incr_slot;
      54             :   ulong           score;    /* selector score of peer */
      55             :   uchar           full_hash[ FD_HASH_FOOTPRINT ];
      56             :   uchar           incr_hash[ FD_HASH_FOOTPRINT ];
      57             : };
      58             : 
      59             : typedef struct fd_sspeer fd_sspeer_t;
      60             : 
      61             : struct fd_sspeer_selector_private;
      62             : typedef struct fd_sspeer_selector_private fd_sspeer_selector_t;
      63             : 
      64             : FD_PROTOTYPES_BEGIN
      65             : 
      66             : FD_FN_CONST ulong
      67             : fd_sspeer_selector_align( void );
      68             : 
      69             : FD_FN_CONST ulong
      70             : fd_sspeer_selector_footprint( ulong max_peers );
      71             : 
      72             : void *
      73             : fd_sspeer_selector_new( void * shmem,
      74             :                         ulong  max_peers,
      75             :                         ulong  seed );
      76             : 
      77             : fd_sspeer_selector_t *
      78             : fd_sspeer_selector_join( void * shselector );
      79             : 
      80             : void *
      81             : fd_sspeer_selector_leave( fd_sspeer_selector_t * selector );
      82             : 
      83             : void *
      84             : fd_sspeer_selector_delete( void * shselector );
      85             : 
      86             : /* Update the selector when a ping response is received.  The only
      87             :    value that can be updated is the latency.  If multiple peers
      88             :    advertise the same address, the update is applied to all of them,
      89             :    since ssping cannot distinguish between these peers.  It returns
      90             :    the number of peers that have been updated. */
      91             : ulong
      92             : fd_sspeer_selector_update_on_ping( fd_sspeer_selector_t * selector,
      93             :                                    fd_ip4_port_t          addr,
      94             :                                    ulong                  latency );
      95             : 
      96             : /* Add a peer to the selector.  If the peer already exists,
      97             :    fd_sspeer_selector_add updates the existing peer's score using the
      98             :    given peer latency and snapshot info.  Returns the updated score.
      99             : 
     100             :    Slot-based incremental clearing: for an existing peer, when
     101             :    incr_slot==FD_SSPEER_SLOT_UNKNOWN and full_slot!=FD_SSPEER_SLOT_UNKNOWN,
     102             :    the peer's incremental data is cleared if it is stale
     103             :    (peer->incr_slot < full_slot).  For a new peer, full_hash and
     104             :    incr_hash are handled independently.
     105             : 
     106             :    Returns the updated score, or FD_SSPEER_SCORE_INVALID on failure. */
     107             : ulong
     108             : fd_sspeer_selector_add( fd_sspeer_selector_t * selector,
     109             :                         fd_sspeer_key_t const * key,
     110             :                         fd_ip4_port_t          addr,
     111             :                         ulong                  peer_latency,
     112             :                         ulong                  full_slot,
     113             :                         ulong                  incr_slot,
     114             :                         uchar const            full_hash[ FD_HASH_FOOTPRINT ],
     115             :                         uchar const            incr_hash[ FD_HASH_FOOTPRINT ] );
     116             : 
     117             : /* Remove a peer from the selector.  Peers are removed when they are
     118             :    not reachable or serving corrupted/malformed snapshots.  This is a
     119             :    no-op if the peer does not exist in the selector.  When removing by
     120             :    address, all peers advertising that address will be removed. */
     121             : void
     122             : fd_sspeer_selector_remove( fd_sspeer_selector_t *  selector,
     123             :                            fd_sspeer_key_t const * key );
     124             : 
     125             : void
     126             : fd_sspeer_selector_remove_by_addr( fd_sspeer_selector_t * selector,
     127             :                                    fd_ip4_port_t          addr );
     128             : 
     129             : /* Select the best peer to download a snapshot from.  incremental
     130             :    indicates to select a peer to download an incremental snapshot.  If
     131             :    incremental is set, base_slot must be a valid full snapshot slot.
     132             :    Peers that do not offer an incremental snapshot
     133             :    (incr_slot==FD_SSPEER_SLOT_UNKNOWN) are excluded from incremental
     134             :    selection. */
     135             : fd_sspeer_t
     136             : fd_sspeer_selector_best( fd_sspeer_selector_t * selector,
     137             :                          int                    incremental,
     138             :                          ulong                  base_slot );
     139             : 
     140             : /* Recompute the selector's internal cluster slot from the max of
     141             :    all tracked peers' slots.  If the max changes, all peers are
     142             :    rescored.  add() and remove() only mark the selector dirty;
     143             :    callers must invoke this function after mutations to apply the
     144             :    recomputation.  No-op when the dirty flag is not set. */
     145             : void
     146             : fd_sspeer_selector_process_cluster_slot( fd_sspeer_selector_t * selector );
     147             : 
     148             : /* Obtain the cluster slot from the selector.  It is the highest
     149             :    of all tracked peers' full/incremental slots. */
     150             : fd_sscluster_slot_t
     151             : fd_sspeer_selector_cluster_slot( fd_sspeer_selector_t * selector );
     152             : 
     153             : /* Helper functions to count how many elements exist in both peer maps
     154             :    (by_key and by_addr).  Mainly used in unit tests.  These are not
     155             :    optimized for performance. */
     156             : ulong
     157             : fd_sspeer_selector_peer_map_by_key_ele_cnt( fd_sspeer_selector_t * selector );
     158             : 
     159             : ulong
     160             : fd_sspeer_selector_peer_map_by_addr_ele_cnt( fd_sspeer_selector_t * selector );
     161             : 
     162             : FD_PROTOTYPES_END
     163             : 
     164             : #endif /* HEADER_fd_src_discof_restore_utils_fd_sspeer_selector_h */

Generated by: LCOV version 1.14