Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_gossip_crds_fd_crds_h
2 : #define HEADER_fd_src_flamenco_gossip_crds_fd_crds_h
3 :
4 : #include "fd_gossip_wsample.h"
5 : #include "fd_gossip_message.h"
6 : #include "fd_gossip_out.h"
7 : #include "fd_gossip_purged.h"
8 :
9 : #include "../../util/net/fd_net_headers.h"
10 : #include "../../disco/metrics/generated/fd_metrics_enums.h"
11 :
12 : struct fd_crds_entry_private;
13 : typedef struct fd_crds_entry_private fd_crds_entry_t;
14 :
15 : struct fd_crds_private;
16 : typedef struct fd_crds_private fd_crds_t;
17 :
18 : struct fd_crds_mask_iter_private;
19 : typedef struct fd_crds_mask_iter_private fd_crds_mask_iter_t;
20 :
21 0 : #define FD_CRDS_ALIGN 128UL
22 :
23 0 : #define FD_CRDS_MAGIC (0xf17eda2c37c7d50UL) /* firedancer crds version 0*/
24 :
25 : struct fd_crds_metrics {
26 : ulong count[ FD_METRICS_ENUM_CRDS_VALUE_CNT ];
27 : ulong expired_cnt;
28 : ulong evicted_cnt;
29 :
30 : ulong peer_staked_cnt;
31 : ulong peer_unstaked_cnt;
32 : ulong peer_visible_stake;
33 : ulong peer_evicted_cnt;
34 : };
35 :
36 : typedef struct fd_crds_metrics fd_crds_metrics_t;
37 :
38 0 : #define FD_GOSSIP_ACTIVITY_CHANGE_TYPE_ACTIVE (1)
39 0 : #define FD_GOSSIP_ACTIVITY_CHANGE_TYPE_INACTIVE (2)
40 :
41 : typedef void (*fd_gossip_activity_update_fn)( void * ctx,
42 : fd_pubkey_t const * identity,
43 : fd_gossip_contact_info_t const * ci,
44 : int change_type );
45 :
46 : FD_PROTOTYPES_BEGIN
47 :
48 : FD_FN_CONST ulong
49 : fd_crds_align( void );
50 :
51 : FD_FN_CONST ulong
52 : fd_crds_footprint( ulong ele_max );
53 :
54 : typedef struct fd_active_set_private fd_active_set_t;
55 :
56 : void *
57 : fd_crds_new( void * shmem,
58 : fd_ip4_port_t const * entrypoints,
59 : ulong entrypoints_cnt,
60 : fd_gossip_wsample_t * wsample,
61 : fd_active_set_t * active_set, /* TODO: Remove .. circular dep */
62 : fd_rng_t * rng,
63 : ulong ele_max,
64 : fd_gossip_purged_t * purged,
65 : fd_gossip_activity_update_fn activity_update_fn,
66 : void * activity_update_fn_ctx,
67 : fd_gossip_out_ctx_t * gossip_update_out );
68 :
69 : fd_crds_t *
70 : fd_crds_join( void * shcrds );
71 :
72 : fd_crds_metrics_t const *
73 : fd_crds_metrics( fd_crds_t const * crds );
74 :
75 : /* fd_crds_advance performs housekeeping operations and should be run
76 : as a part of a gossip advance loop. The following operations are
77 : performed:
78 : - expire: removes stale entries from the replicated data store.
79 : CRDS values from staked nodes expire roughly an epoch after they
80 : are created, and values from non-staked nodes expire after 15
81 : seconds. Removed contact info entries are also published as gossip
82 : updates via stem.
83 : - re-weigh: peers are downsampled in the peer sampler if they have
84 : not been refreshed in <60s.
85 :
86 : There is one exception, when the node is first bootstrapping, and
87 : has not yet seen any staked nodes, values do not expire at all. */
88 :
89 : void
90 : fd_crds_advance( fd_crds_t * crds,
91 : long now,
92 : fd_stem_context_t * stem,
93 : int * charge_busy );
94 :
95 : /* fd_crds_len returns the number of entries in the CRDS table. This
96 : does not include purged entries, which have a separate queue tracking
97 : them. See fd_crds_purged_* APIs below. */
98 :
99 : ulong
100 : fd_crds_len( fd_crds_t const * crds );
101 :
102 : /* fd_crds_insert upserts a CRDS value into the data store. If the
103 : value's key is not yet present, a new entry is acquired and indexed.
104 : If a matching key already exists, the candidate is compared against
105 : the incumbent using wallclock (and outset for ContactInfo); the
106 : winner is kept and the loser is purged.
107 :
108 : On top of inserting the CRDS entry, this function also updates the
109 : sidetable of ContactInfo entries and the peer samplers if the entry
110 : is a ContactInfo. is_from_me indicates the CRDS entry originates
111 : from this node. We exclude our own entries from peer samplers.
112 : origin_stake is used to weigh the peer in the samplers.
113 :
114 : stem is used to publish updates to {ContactInfo, Vote, DuplicateShred,
115 : SnapshotHashes} entries.
116 :
117 : Returns 0L on successful upsert, -1L if the candidate was stale
118 : (not inserted), or >0 if the candidate was a duplicate (the return
119 : value is the running duplicate count). */
120 :
121 : long
122 : fd_crds_insert( fd_crds_t * crds,
123 : fd_gossip_value_t const * value,
124 : uchar const * value_bytes,
125 : ulong value_bytes_len,
126 : ulong origin_stake,
127 : int origin_ping_tracked,
128 : int is_me,
129 : long now,
130 : fd_stem_context_t * stem );
131 :
132 : void
133 : fd_crds_entry_value( fd_crds_entry_t const * entry,
134 : uchar const ** value_bytes,
135 : ulong * value_sz );
136 :
137 : /* fd_crds_entry_wallclock returns the originator's wallclock timestamp
138 : for this entry, in milliseconds. This is the wallclock the
139 : originator attached when they created the CRDS value. */
140 :
141 : ulong
142 : fd_crds_entry_wallclock( fd_crds_entry_t const * entry );
143 :
144 : /* fd_crds_entry_hash returns a pointer to the 32b sha256 hash of the
145 : entry's value hash. This is used for constructing a bloom filter. */
146 :
147 : uchar const *
148 : fd_crds_entry_hash( fd_crds_entry_t const * entry );
149 :
150 : /* fd_crds_peer_count returns the number of Contact Info entries
151 : present in the sidetable. The lifetime of a Contact Info entry
152 : tracks the lifetime of the corresponding CRDS entry. */
153 :
154 : ulong
155 : fd_crds_peer_count( fd_crds_t const * crds );
156 :
157 : fd_gossip_contact_info_t const *
158 : fd_crds_ci( fd_crds_t const * crds,
159 : ulong ci_idx );
160 :
161 : uchar const *
162 : fd_crds_ci_pubkey( fd_crds_t const * crds,
163 : ulong ci_idx );
164 :
165 : ulong
166 : fd_crds_ci_idx( fd_crds_t const * crds,
167 : uchar const * pubkey );
168 :
169 : /* fd_crds_mask_iter_{init,next,done,entry} provide an API to
170 : iterate over the CRDS values in the table that whose hashes match
171 : a given mask. In the Gossip CRDS filter, the mask is applied on
172 : the most significant 8 bytes of the CRDS value's hash.
173 :
174 : The Gossip CRDS filter encodes the mask in two values: `mask` and
175 : `mask_bits`. For example, if we set `mask_bits` to 5 and 0b01010 as
176 : `mask`, we get the following 64-bit bitmask:
177 : 01010 11111111111.....
178 :
179 : Therefore, we can frame a mask match as a CRDS value's hash whose
180 : most significant `mask_bits` is `mask`. We can trivially define
181 : the range of matching hash values by setting the non-mask bits to
182 : all 0s or 1s to get the start and end values respectively. */
183 :
184 : fd_crds_mask_iter_t *
185 : fd_crds_mask_iter_init( fd_crds_t const * crds,
186 : ulong mask,
187 : uint mask_bits,
188 : uchar iter_mem[ static 16UL ] );
189 :
190 : fd_crds_mask_iter_t *
191 : fd_crds_mask_iter_next( fd_crds_mask_iter_t * it,
192 : fd_crds_t const * crds );
193 :
194 : int
195 : fd_crds_mask_iter_done( fd_crds_mask_iter_t * it,
196 : fd_crds_t const * crds );
197 :
198 : fd_crds_entry_t const *
199 : fd_crds_mask_iter_entry( fd_crds_mask_iter_t * it,
200 : fd_crds_t const * crds );
201 :
202 : FD_PROTOTYPES_END
203 :
204 : #endif /* HEADER_fd_src_flamenco_gossip_crds_fd_crds_h */
|