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_crds.h" 5 : #include "fd_gossip_wsample.h" 6 : #include "../../util/net/fd_net_headers.h" 7 : 8 : /* fd_active_set provides APIs for tracking the active set of nodes we 9 : should push messages to in a gossip network. 10 : 11 : In the Solana gossip protocol, each node selects a random set of up 12 : to 300 peers to send messages to, and then rotates one of the nodes 13 : out for a new, randomly selected one every so often. 14 : 15 : This is simple enough: just keep a list of the peer pubkeys, and 16 : occasionally replace one? 17 : 18 : There's two complications: 19 : 20 : (1) We want to select peers with a good distribution of stakes, so 21 : that we don't end up sending to a lot of low-stake peers if 22 : someone pollutes the gossip table with junk. 23 : 24 : (2) Peers sometimes request that we don't forward messages from 25 : other originating (origin) nodes to them, because they already 26 : have a lot of paths from that node. This is called a prune. 27 : 28 : Complication (1) is handled by keeping a list of the top 12 peers 29 : (sorted by stake) for each of 25 buckets of stakes. These buckets 30 : are all rotated together. 31 : 32 : And problem (2) is solved by keeping a bloom filter for each of the 33 : 12 peers in each bucket. The bloom filter is used to track which 34 : origins the peer has pruned. */ 35 : 36 : typedef struct fd_active_set_private fd_active_set_t; 37 : 38 0 : #define FD_ACTIVE_SET_ALIGN (64UL) 39 : 40 0 : #define FD_ACTIVE_SET_MAGIC (0xF17EDA2CEA5E1000) /* FIREDANCE ASET V0 */ 41 : 42 : typedef void (*fd_gossip_send_fn)( void * ctx, 43 : fd_stem_context_t * stem, 44 : uchar const * data, 45 : ulong sz, 46 : fd_ip4_port_t const * peer_address, 47 : ulong now ); 48 : 49 : struct fd_active_set_metrics { 50 : ulong message_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_CNT ]; 51 : ulong message_tx_bytes[ FD_METRICS_ENUM_GOSSIP_MESSAGE_CNT ]; 52 : 53 : ulong crds_tx_push[ FD_METRICS_ENUM_CRDS_VALUE_CNT ]; 54 : ulong crds_tx_push_bytes[ FD_METRICS_ENUM_CRDS_VALUE_CNT ]; 55 : }; 56 : 57 : typedef struct fd_active_set_metrics fd_active_set_metrics_t; 58 : 59 : FD_PROTOTYPES_BEGIN 60 : 61 : static inline ulong 62 0 : fd_active_set_stake_bucket( ulong _stake ) { 63 0 : ulong stake = _stake / 1000000000; 64 0 : if( FD_UNLIKELY( stake == 0UL ) ) return 0UL; 65 0 : ulong bucket = 64UL - (ulong)__builtin_clzl(stake); 66 0 : return fd_ulong_min( bucket, 24UL ); 67 0 : } 68 : 69 : FD_FN_CONST ulong 70 : fd_active_set_align( void ); 71 : 72 : FD_FN_CONST ulong 73 : fd_active_set_footprint( void ); 74 : 75 : void * 76 : fd_active_set_new( void * shmem, 77 : fd_gossip_wsample_t * wsample, 78 : fd_crds_t * crds, 79 : fd_rng_t * rng, 80 : uchar const * identity_pubkey, 81 : ulong identity_stake, 82 : fd_gossip_send_fn send_fn, 83 : void * send_fn_ctx ); 84 : 85 : fd_active_set_t * 86 : fd_active_set_join( void * shas ); 87 : 88 : fd_active_set_metrics_t const * 89 : fd_active_set_metrics( fd_active_set_t const * active_set ); 90 : 91 : void 92 : fd_active_set_set_identity( fd_active_set_t * active_set, 93 : uchar const * identity_pubkey, 94 : ulong identity_stake ); 95 : 96 : void 97 : fd_active_set_prune( fd_active_set_t * active_set, 98 : uchar const * push_dest, 99 : uchar const * origin, 100 : ulong origin_stake ); 101 : 102 : void 103 : fd_active_set_remove_peer( fd_active_set_t * active_set, 104 : ulong ci_idx ); 105 : 106 : void 107 : fd_active_set_push( fd_active_set_t * active_set, 108 : uchar const * crds_val, 109 : ulong crds_sz, 110 : uchar const * origin_pubkey, 111 : ulong origin_stake, 112 : fd_stem_context_t * stem, 113 : long now, 114 : int flush_immediately ); 115 : 116 : void 117 : fd_active_set_advance( fd_active_set_t * active_set, 118 : fd_stem_context_t * stem, 119 : long now, 120 : int * charge_busy ); 121 : 122 : FD_PROTOTYPES_END 123 : 124 : #endif /* HEADER_fd_src_flamenco_gossip_fd_active_set_h */