Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_gossip_fd_gossip_h
2 : #define HEADER_fd_src_flamenco_gossip_fd_gossip_h
3 :
4 : #include "fd_gossip_message.h"
5 : #include "fd_gossip_out.h"
6 : #include "fd_gossip_purged.h"
7 : #include "fd_ping_tracker.h"
8 : #include "fd_active_set.h"
9 : #include "../stakes/fd_stake_weight.h"
10 : #include "../../util/rng/fd_rng.h"
11 : #include "../../util/net/fd_net_headers.h"
12 :
13 : /* The Solana gossip protocol is used so that distributed nodes can
14 : share key-value pairs and reach an eventually consistent consensus on
15 : what's in the key-value store.
16 :
17 : It is peer to peer, and proceeds with these key pieces:
18 :
19 : - To join the cluster, a node must first contact a known node
20 : (an entrypoint) and register itself, by sending its own contact
21 : information key-value pair. Contact information is the UDP
22 : address and port.
23 :
24 : - The cluster will then agree on that key-value pair, and start
25 : broadcasting updates to the node.
26 :
27 : - Each node must periodically send new messages it has received to
28 : a (somewhat) random selection of peers (referred to as the active
29 : set).
30 :
31 : - In addition, each node can periodically send a "pull request" to
32 : a random selection of peers, asking them to send any messages
33 : they have that the node does not. This is used to ensure that
34 : nodes are eventually consistent in case they miss some pushed
35 : messages. Bloom filters are used to track which messages have
36 : been received, and to avoid sending duplicates.
37 :
38 : - Each node can also send prune messages to peers, asking them
39 : to stop forwarding (pushing) messages from a particular origin.
40 : This is used to avoid receiving too many duplicate messages from
41 : the same origin.
42 :
43 : - Nodes with stake are always considered part of the network, but
44 : low staked nodes need to maintain a connection by responding to
45 : ping messages. These pings are to prevent DDoS attacks which
46 : reflect off gossip nodes.
47 :
48 : Other than this, everything else is implementation details. For
49 : specifics on the network and wire protocol, see https://github.com/eigerco/solana-spec/blob/main/gossip-protocol-spec.md
50 : and for more details on the Agave implementation, see https://github.com/eigerco/solana-spec/blob/main/implementation-details.md
51 :
52 : The Solana gossip protocol is heavily based on Plum Tree, see
53 : https://www.dpss.inesc-id.pt/~ler/reports/srds07.pdf for details. */
54 :
55 : struct fd_gossip_private;
56 : typedef struct fd_gossip_private fd_gossip_t;
57 :
58 : typedef void (*fd_gossip_send_fn)( void * ctx,
59 : fd_stem_context_t * stem,
60 : uchar const * data,
61 : ulong sz,
62 : fd_ip4_port_t const * peer_address,
63 : ulong now );
64 :
65 : typedef void (*fd_gossip_sign_fn)( void * ctx,
66 : uchar const * data,
67 : ulong sz,
68 : int sign_type );
69 :
70 : /* FD_GOSSIP_SIGN_PEND_MAX is the most sign requests in flight, the
71 : depth of the sign links. */
72 :
73 0 : #define FD_GOSSIP_SIGN_PEND_MAX (128UL)
74 :
75 : struct fd_gossip_metrics {
76 : ulong crds_rx_count[ FD_METRICS_ENUM_GOSSIP_CRDS_RESULT_CNT ];
77 :
78 : ulong sign_pend_full_cnt;
79 :
80 : ulong message_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_TYPE_CNT ];
81 : ulong message_tx_bytes[ FD_METRICS_ENUM_GOSSIP_MESSAGE_TYPE_CNT ];
82 :
83 : ulong crds_tx_pull_response[ FD_METRICS_ENUM_CRDS_VALUE_TYPE_CNT ];
84 : ulong crds_tx_pull_response_bytes[ FD_METRICS_ENUM_CRDS_VALUE_TYPE_CNT ];
85 : };
86 :
87 : typedef struct fd_gossip_metrics fd_gossip_metrics_t;
88 :
89 : FD_PROTOTYPES_BEGIN
90 :
91 : FD_FN_CONST ulong
92 : fd_gossip_align( void );
93 :
94 : FD_FN_CONST ulong
95 : fd_gossip_footprint( ulong max_values,
96 : ulong entrypoints_len );
97 :
98 : void *
99 : fd_gossip_new( void * shmem,
100 : fd_rng_t * rng,
101 : uchar const ping_seed[ static 32 ],
102 : ulong max_values,
103 : ulong entrypoints_len,
104 : fd_ip4_port_t const * entrypoints,
105 : uchar const * identity_pubkey,
106 : fd_gossip_contact_info_t const * my_contact_info,
107 : long now,
108 : fd_gossip_send_fn send_fn,
109 : void * send_ctx,
110 : fd_gossip_sign_fn sign_fn,
111 : void * sign_ctx,
112 : fd_ping_tracker_change_fn ping_tracker_change_fn,
113 : void * ping_tracker_change_fn_ctx,
114 : fd_gossip_activity_update_fn activity_update_fn,
115 : void * activity_update_fn_ctx,
116 : fd_gossip_out_ctx_t * gossip_update_out,
117 : fd_gossip_out_ctx_t * gossip_net_out );
118 :
119 : fd_gossip_t *
120 : fd_gossip_join( void * shgossip );
121 :
122 : fd_gossip_metrics_t const *
123 : fd_gossip_metrics( fd_gossip_t const * gossip );
124 :
125 : fd_crds_metrics_t const *
126 : fd_gossip_crds_metrics( fd_gossip_t const * gossip );
127 :
128 : fd_ping_tracker_metrics_t const *
129 : fd_gossip_ping_tracker_metrics( fd_gossip_t const * gossip );
130 :
131 : fd_gossip_purged_metrics_t const *
132 : fd_gossip_purged_metrics2( fd_gossip_t const * gossip );
133 :
134 : fd_active_set_metrics_t const *
135 : fd_gossip_active_set_metrics2( fd_gossip_t const * gossip );
136 :
137 : void
138 : fd_gossip_set_identity( fd_gossip_t * gossip,
139 : uchar const * identity_pubkey,
140 : long now,
141 : ulong identity_outset );
142 :
143 : void
144 : fd_gossip_set_shred_version( fd_gossip_t * gossip,
145 : ushort shred_version );
146 :
147 : void
148 : fd_gossip_stakes_update( fd_gossip_t * gossip,
149 : fd_stake_weight_t const * stake_weights,
150 : ulong stake_weights_cnt );
151 :
152 : /* fd_gossip_advance advances the gossip protocol to the provided time,
153 : performing any necessary updates and actions along the way. The
154 : actions performed include,
155 :
156 : Advancing gossip forward will cause a variety of things to happen,
157 :
158 : - Pings will be sent to any peer nodes that are not validated, or
159 : need their token refreshed.
160 :
161 : - Old entries in the CRDS will be expired.
162 :
163 : - Partially constructed push messages may need to be periodically
164 : flushed.
165 :
166 : - A new pull request will be periodically sent out to a random peer,
167 : to request any messages we might be missing.
168 :
169 : - Contact info messages will be periodically sent out to a random
170 : selection of peers, to inform them of our current contact info.
171 :
172 : - The active set of peers that we are pushing to will be
173 : periodically rotated, with one new peer entering and one old peer
174 : leaving, based on stake weights.
175 :
176 :
177 : Only actions which are necessary and useful will be performed, and
178 : the function is idempotent and fast otherwise. advance should be
179 : called as often as possible. */
180 :
181 : void
182 : fd_gossip_advance( fd_gossip_t * gossip,
183 : long now,
184 : fd_stem_context_t * stem,
185 : int * charge_busy );
186 :
187 : long
188 : fd_gossip_next_deadline( fd_gossip_t const * gossip );
189 :
190 : /* fd_gossip_rx handles an incoming packet received on the gossip socket
191 : from the network. It is expected that the packet is a UDP packet but
192 : otherwise no assumptions are made about the contents of the packet,
193 : in particular it might be malformed, corrupted, malicious, and so on.
194 :
195 : now is the current time in nanoseconds, and is used to determine
196 : whether the packet is stale or not, and to update the internal state
197 : of the gossip protocol.
198 :
199 : Receiving a packet might cause response packets to need to be sent
200 : back to the gossip network. The response packets are queued for
201 : later sending. The caller is responsible for sending the response
202 : packets by calling fd_gossip_tx(). */
203 :
204 : void
205 : fd_gossip_rx( fd_gossip_t * gossip,
206 : fd_ip4_port_t peer,
207 : uchar const * data,
208 : ulong data_sz,
209 : long now,
210 : fd_stem_context_t * stem );
211 :
212 : /* fd_gossip_sign_response delivers the signature of the oldest sign
213 : request still in flight and completes the message it was for */
214 :
215 : void
216 : fd_gossip_sign_response( fd_gossip_t * gossip,
217 : uchar const * signature,
218 : fd_stem_context_t * stem,
219 : long now );
220 :
221 : ulong
222 : fd_gossip_sign_pend_cnt( fd_gossip_t const * gossip );
223 :
224 : /* fd_gossip_ping_tracker_track marks a peer for ping tracking. The
225 : gossip implementation internally keeps track of peers that are
226 : sending us contact info messages, but certain messages are already
227 : filtered out by the gossvf layer. If gossvf is filtering out
228 : messages because it believes the peer is not active, it will still
229 : ask the gossip layer to attempt to ping them, which it notifies with
230 : this function. */
231 :
232 : void
233 : fd_gossip_ping_tracker_track( fd_gossip_t * gossip,
234 : uchar const * peer_pubkey,
235 : fd_ip4_port_t peer_address,
236 : long now );
237 :
238 : int
239 : fd_gossip_push_vote( fd_gossip_t * gossip,
240 : uchar const * txn,
241 : ulong txn_sz,
242 : long now );
243 :
244 : int
245 : fd_gossip_push_duplicate_shred( fd_gossip_t * gossip,
246 : fd_gossip_duplicate_shred_t const * duplicate_shred,
247 : long now );
248 :
249 : FD_PROTOTYPES_END
250 :
251 : #endif /* HEADER_fd_src_flamenco_gossip_fd_gossip_h */
|