Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_runtime_program_vote_fd_vote_codec_h
2 : #define HEADER_fd_src_flamenco_runtime_program_vote_fd_vote_codec_h
3 :
4 : #include "../../../fd_flamenco_base.h"
5 : #include "fd_validator_location.h"
6 :
7 : #include <stddef.h>
8 :
9 : /* Vote program type definitions and (de)serializers.
10 :
11 : Supported versions: v1_14_11, v3, v4. */
12 :
13 : /**********************************************************************/
14 : /* Constants -- vote state */
15 : /**********************************************************************/
16 :
17 : /* Note we add to each of the bounds for the max capacity to account
18 : for edge cases where elements are added beyond theoretical capacity
19 : and then popped within execution. */
20 :
21 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.1.1/vote-interface/src/state/mod.rs#L39 */
22 25992 : #define MAX_LOCKOUT_HISTORY (31UL)
23 4156 : #define MAX_LOCKOUT_HISTORY_CAPACITY (MAX_LOCKOUT_HISTORY+1UL)
24 :
25 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.1.1/vote-interface/src/state/mod.rs#L43 */
26 133267 : #define MAX_EPOCH_CREDITS_HISTORY (64UL)
27 133267 : #define MAX_EPOCH_CREDITS_HISTORY_CAPACITY (MAX_EPOCH_CREDITS_HISTORY+1UL)
28 :
29 : /* This is an implicit bound derived from the vote program logic. When
30 : authorized voters are updated inside the vote program, any authorized
31 : voters outside of the [epoch-1, epoch+2] range are purged. In
32 : between execution, up to 2 authorized voters can be added, so we
33 : need to allocate extra capacity accordingly. */
34 8312 : #define MAX_AUTHORIZED_VOTERS (4UL)
35 8312 : #define MAX_AUTHORIZED_VOTERS_CAPACITY (MAX_AUTHORIZED_VOTERS+2UL)
36 :
37 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.1.1/vote-interface/src/state/mod.rs#L154 */
38 0 : #define PRIOR_VOTERS_MAX (32UL)
39 :
40 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.1.1/vote-interface/src/state/mod.rs#L33 */
41 6567 : #define FD_BLS_PUBKEY_COMPRESSED_SZ (48UL)
42 3264 : #define FD_BLS_PUBKEY_UNCOMPRESSED_SZ (96UL)
43 :
44 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.0.0/vote-interface/src/state/mod.rs#L36 */
45 : #define FD_BLS_PROOF_OF_POSSESSION_COMPRESSED_SZ (96UL)
46 :
47 : /* Default block revenue commission (100%)
48 : https://github.com/anza-xyz/agave/blob/v4.4.0-alpha.5/vote/src/vote_state_view.rs#L117 */
49 3914 : #define FD_VOTE_DEFAULT_BLOCK_REVENUE_COMMISSION_BPS (10000U)
50 :
51 : /* Serialized size of each vote state version */
52 : #define FD_VOTE_STATE_V2_SZ (3731UL)
53 0 : #define FD_VOTE_STATE_V3_SZ (3762UL)
54 2232 : #define FD_VOTE_STATE_V4_SZ (3762UL)
55 0 : #define FD_VOTE_STATE_V5_SZ (951UL)
56 :
57 : /* Maximum number of entries in a V5 commission schedule */
58 0 : #define FD_VOTE_STATE_V5_COMMISSION_MAX (4UL)
59 :
60 0 : #define FD_VOTE_STATE_V5_ACCUMULATED_LAMPORTS_MAX (5UL)
61 :
62 : /**********************************************************************/
63 : /* Constants -- vote instruction footprints */
64 : /**********************************************************************/
65 :
66 : /* Some vote instruction types are dynamically sized:
67 : - tower_sync_switch (contains deque of fd_vote_lockout_t)
68 : - tower_sync (contains deque of fd_vote_lockout_t)
69 : - compact_vote_state_update_switch (vector of fd_lockout_offset_t)
70 : - compact_vote_state_update (vector of fd_lockout_offset_t)
71 : - authorize_checked_with_seed (char vector of current_authority_derived_key_seed)
72 : - authorize_with_seed (char vector of current_authority_derived_key_seed)
73 : - update_vote_state_switch (contains deque of fd_vote_lockout_t)
74 : - update_vote_state (contains deque of fd_vote_lockout_t)
75 : - vote_switch (deque of slot numbers)
76 : - vote (deque of slot numbers)
77 : All other vote instruction types are statically sized.
78 :
79 : A loose bound on the max amount of encoded fd_vote_lockout_t
80 : possible is 1232 bytes/(12 bytes/per lockout) = 102 lockouts. So
81 : the worst case bound for the deque of fd_vote_lockout is
82 : 32 + (102 * sizeof(fd_vote_lockout_t)) = 1644 bytes.
83 :
84 : The worst case vector of fd_lockout_offset_t is one where each
85 : encoded element is 2 bytes. This means that we can have 1232/2 =
86 : 616 elements. They are represented as being 16 bytes each, so the
87 : total footprint would be 9856 bytes.
88 :
89 : The deque of slot numbers is a vector of ulong, which is 8 bytes.
90 : So the worst case is 1232 bytes/8 bytes = 154 elements. So, the
91 : total footprint is 32 + (154 * 8 bytes) = 1264 bytes.
92 :
93 : The worst case char vector is 1232 bytes as each element is 1 byte
94 : up to the txn MTU.
95 :
96 : With this, that means that the compact_vote_state_update_switch
97 : can have the largest worst case footprint where the struct is
98 : 104 bytes (sizeof(fd_compact_vote_state_update_switch_t) + the
99 : worst case lockout vector of 616 elements. */
100 893 : #define FD_VOTE_INSTR_MAX_LOCKOUTS_LEN (102UL)
101 734 : #define FD_VOTE_INSTR_MAX_LOCKOUT_OFFSETS_LEN (616UL)
102 564 : #define FD_VOTE_INSTR_MAX_SLOT_NUMS_LEN (154UL)
103 :
104 : /* Footprints for embedded memory arrays inside vote instruction
105 : sub-structs. Validated by test_vote_instruction_footprints
106 : in test_vote_program. */
107 : #define FD_VOTE_INSTR_SLOTS_ALIGN (8UL)
108 : #define FD_VOTE_INSTR_SLOTS_FOOTPRINT (1264UL)
109 : #define FD_VOTE_INSTR_UPDATE_LOCKOUTS_ALIGN (8UL)
110 : #define FD_VOTE_INSTR_UPDATE_LOCKOUTS_FOOTPRINT (1664UL)
111 : #define FD_VOTE_INSTR_LOCKOUT_OFFSET_ALIGN (8UL)
112 : #define FD_VOTE_INSTR_LOCKOUT_OFFSET_FOOTPRINT (9856UL)
113 : #define FD_VOTE_INSTR_SEED_MAX (1232UL)
114 :
115 : /* Footprints for runtime buffers that hold lockouts / landed votes
116 : derived from vote instruction data. The max element count is
117 : FD_VOTE_INSTR_MAX_LOCKOUT_OFFSETS_LEN (616) because the tower sync
118 : and compact vote state update paths can produce that many entries. */
119 : #define FD_VOTE_INSTR_LOCKOUTS_ALIGN (8UL)
120 : #define FD_VOTE_INSTR_LOCKOUTS_FOOTPRINT (9888UL)
121 : #define FD_VOTE_INSTR_LANDED_VOTES_ALIGN (8UL)
122 : #define FD_VOTE_INSTR_LANDED_VOTES_FOOTPRINT (14816UL)
123 :
124 : /**********************************************************************/
125 : /* Constants -- vote account state footprints */
126 : /**********************************************************************/
127 :
128 : /* Alignments and footprints for the authorized voters pool and treap at
129 : MAX_AUTHORIZED_VOTERS_CAPACITY. Validated by
130 : test_authorized_voters_footprint in test_vote_program. */
131 : #define FD_AUTHORIZED_VOTERS_POOL_ALIGN (128UL)
132 : #define FD_AUTHORIZED_VOTERS_POOL_FOOTPRINT (512UL)
133 : #define FD_AUTHORIZED_VOTERS_TREAP_ALIGN (8UL)
134 : #define FD_AUTHORIZED_VOTERS_TREAP_FOOTPRINT (24UL)
135 :
136 : /* Alignment and footprint for the landed votes at
137 : MAX_LOCKOUT_HISTORY_CAPACITY. Validated by
138 : test_landed_votes_footprint in test_vote_program. */
139 : #define FD_LANDED_VOTES_FOOTPRINT (800UL)
140 : #define FD_LANDED_VOTES_ALIGN (8UL)
141 :
142 : /* Alignment and footprint for the epoch credits at
143 : MAX_EPOCH_CREDITS_HISTORY_CAPACITY. Validated by
144 : test_epoch_credits_footprint in test_vote_program. */
145 : #define FD_EPOCH_CREDITS_FOOTPRINT (1576UL)
146 : #define FD_EPOCH_CREDITS_ALIGN (8UL)
147 :
148 : /**********************************************************************/
149 : /* Shared leaf types */
150 : /**********************************************************************/
151 :
152 : struct fd_vote_lockout {
153 : ulong slot;
154 : uint confirmation_count;
155 : };
156 : typedef struct fd_vote_lockout fd_vote_lockout_t;
157 : #define FD_VOTE_LOCKOUT_ALIGN alignof(fd_vote_lockout_t)
158 :
159 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.1.1/vote-interface/src/authorized_voters.rs#L11-L13 */
160 : struct fd_vote_authorized_voter {
161 : ulong epoch;
162 : fd_pubkey_t pubkey;
163 :
164 : /* Treap/pool index fields. uchar is sufficient because the max
165 : authorized voters capacity is MAX_AUTHORIZED_VOTERS_CAPACITY (6). */
166 : uchar parent;
167 : uchar left;
168 : uchar right;
169 : uchar prio;
170 : };
171 : typedef struct fd_vote_authorized_voter fd_vote_authorized_voter_t;
172 : #define FD_VOTE_AUTHORIZED_VOTER_ALIGN alignof(fd_vote_authorized_voter_t)
173 :
174 : struct fd_vote_prior_voter {
175 : fd_pubkey_t pubkey;
176 : ulong epoch_start;
177 : ulong epoch_end;
178 : };
179 : typedef struct fd_vote_prior_voter fd_vote_prior_voter_t;
180 : #define FD_VOTE_PRIOR_VOTER_ALIGN alignof(fd_vote_prior_voter_t)
181 :
182 : struct __attribute__((packed)) fd_vote_epoch_credits {
183 : ulong epoch;
184 : ulong credits;
185 : ulong prev_credits;
186 : };
187 : typedef struct fd_vote_epoch_credits fd_vote_epoch_credits_t;
188 : #define FD_VOTE_EPOCH_CREDITS_ALIGN alignof(fd_vote_epoch_credits_t)
189 :
190 : /* fd_vote_epoch_credits_is_alpenglow_marker returns 1 if ec is the
191 : tower->Alpenglow migration sentinel, 0 otherwise. */
192 :
193 : FD_FN_PURE static inline int
194 1992 : fd_vote_epoch_credits_is_alpenglow_marker( fd_vote_epoch_credits_t const * ec ) {
195 1992 : return ec->epoch==ULONG_MAX && ec->credits==ULONG_MAX && ec->prev_credits==ULONG_MAX;
196 1992 : }
197 :
198 : struct fd_vote_block_timestamp {
199 : ulong slot;
200 : long timestamp;
201 : };
202 : typedef struct fd_vote_block_timestamp fd_vote_block_timestamp_t;
203 : #define FD_VOTE_BLOCK_TIMESTAMP_ALIGN alignof(fd_vote_block_timestamp_t)
204 :
205 : struct fd_vote_prior_voters {
206 : fd_vote_prior_voter_t buf[PRIOR_VOTERS_MAX];
207 : ulong idx;
208 : uchar is_empty;
209 : };
210 : typedef struct fd_vote_prior_voters fd_vote_prior_voters_t;
211 : #define FD_VOTE_PRIOR_VOTERS_ALIGN alignof(fd_vote_prior_voters_t)
212 :
213 : /* This type is reused between all vote states for simplicity. */
214 : struct fd_landed_vote {
215 : /* Latency is only used in v3+ vote states. */
216 : uchar latency;
217 : fd_vote_lockout_t lockout;
218 : };
219 : typedef struct fd_landed_vote fd_landed_vote_t;
220 : #define FD_LANDED_VOTE_ALIGN alignof(fd_landed_vote_t)
221 :
222 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.0.0/vote-interface/src/state/vote_instruction_data.rs#L253 */
223 : struct fd_voter_with_bls_args {
224 : uchar bls_pubkey[FD_BLS_PUBKEY_COMPRESSED_SZ];
225 : uchar bls_proof_of_possession[FD_BLS_PROOF_OF_POSSESSION_COMPRESSED_SZ];
226 : };
227 : typedef struct fd_voter_with_bls_args fd_voter_with_bls_args_t;
228 : #define FD_VOTER_WITH_BLS_ARGS_ALIGN alignof(fd_voter_with_bls_args_t)
229 :
230 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/programs/vote/src/vote_state/mod.rs#L230 */
231 : struct fd_vote_init {
232 : fd_pubkey_t node_pubkey;
233 : fd_pubkey_t authorized_voter;
234 : fd_pubkey_t authorized_withdrawer;
235 : uchar commission;
236 : };
237 : typedef struct fd_vote_init fd_vote_init_t;
238 : #define FD_VOTE_INIT_ALIGN alignof(fd_vote_init_t)
239 :
240 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.0.0/vote-interface/src/state/vote_instruction_data.rs#L213 */
241 : struct fd_vote_init_v2 {
242 : fd_pubkey_t node_pubkey;
243 : fd_pubkey_t authorized_voter;
244 : uchar authorized_voter_bls_pubkey[FD_BLS_PUBKEY_COMPRESSED_SZ];
245 : uchar authorized_voter_bls_proof_of_possession[FD_BLS_PROOF_OF_POSSESSION_COMPRESSED_SZ];
246 : fd_pubkey_t authorized_withdrawer;
247 : ushort inflation_rewards_commission_bps;
248 : fd_pubkey_t inflation_rewards_collector;
249 : ushort block_revenue_commission_bps;
250 : fd_pubkey_t block_revenue_collector;
251 : };
252 : typedef struct fd_vote_init_v2 fd_vote_init_v2_t;
253 : #define FD_VOTE_INIT_V2_ALIGN alignof(fd_vote_init_v2_t)
254 :
255 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.0.0/vote-interface/src/state/vote_instruction_data.rs#L277 */
256 : struct fd_vote_authorize {
257 : uint discriminant;
258 : fd_voter_with_bls_args_t voter_with_bls;
259 : };
260 : typedef struct fd_vote_authorize fd_vote_authorize_t;
261 : #define FD_VOTE_AUTHORIZE_ALIGN alignof(fd_vote_authorize_t)
262 :
263 : enum {
264 : fd_vote_authorize_enum_voter = 0,
265 : fd_vote_authorize_enum_withdrawer = 1,
266 : fd_vote_authorize_enum_voter_with_bls = 2,
267 : };
268 :
269 : /**********************************************************************/
270 : /* Static asserts for wire-compatible struct layouts. */
271 : /* The custom vote deserializers use direct memcpy for these types, */
272 : /* relying on the in-memory layout matching the bincode wire format */
273 : /* on little-endian platforms. */
274 : /**********************************************************************/
275 :
276 : FD_STATIC_ASSERT( sizeof(fd_vote_prior_voter_t)==48UL, vote_prior_voter_layout );
277 : FD_STATIC_ASSERT( sizeof(fd_vote_epoch_credits_t)==24UL, vote_epoch_credits_layout );
278 : FD_STATIC_ASSERT( sizeof(fd_vote_block_timestamp_t)==16UL, vote_block_timestamp_layout );
279 : FD_STATIC_ASSERT( sizeof(fd_vote_init_t)==97UL, vote_init_layout );
280 :
281 : typedef struct fd_vote_authorized_voters_treap_private fd_vote_authorized_voters_treap_t;
282 :
283 : struct fd_vote_authorized_voters {
284 : fd_vote_authorized_voter_t * pool;
285 : fd_vote_authorized_voters_treap_t * treap;
286 : };
287 : typedef struct fd_vote_authorized_voters fd_vote_authorized_voters_t;
288 : #define FD_VOTE_AUTHORIZED_VOTERS_ALIGN alignof(fd_vote_authorized_voters_t)
289 :
290 : /**********************************************************************/
291 : /* Vote state structs (per version) */
292 : /**********************************************************************/
293 :
294 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.1.1/vote-interface/src/state/vote_state_1_14_11.rs#L16-L46 */
295 : struct fd_vote_state_1_14_11 {
296 : fd_pubkey_t node_pubkey;
297 : fd_pubkey_t authorized_withdrawer;
298 : uchar commission;
299 : fd_landed_vote_t * votes;
300 : ulong root_slot;
301 : uchar has_root_slot;
302 : fd_vote_authorized_voters_t authorized_voters;
303 : fd_vote_prior_voters_t prior_voters;
304 : fd_vote_epoch_credits_t * epoch_credits;
305 : fd_vote_block_timestamp_t last_timestamp;
306 : };
307 : typedef struct fd_vote_state_1_14_11 fd_vote_state_1_14_11_t;
308 :
309 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.1.1/vote-interface/src/state/vote_state_v3.rs#L30-L60 */
310 : struct fd_vote_state_v3 {
311 : fd_pubkey_t node_pubkey;
312 : fd_pubkey_t authorized_withdrawer;
313 : uchar commission;
314 : fd_landed_vote_t * votes;
315 : ulong root_slot;
316 : uchar has_root_slot;
317 : fd_vote_authorized_voters_t authorized_voters;
318 : fd_vote_prior_voters_t prior_voters;
319 : fd_vote_epoch_credits_t * epoch_credits;
320 : fd_vote_block_timestamp_t last_timestamp;
321 : };
322 : typedef struct fd_vote_state_v3 fd_vote_state_v3_t;
323 :
324 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.1.1/vote-interface/src/state/vote_state_v4.rs#L30-L71 */
325 : struct fd_vote_state_v4 {
326 : fd_pubkey_t node_pubkey;
327 : fd_pubkey_t authorized_withdrawer;
328 : fd_pubkey_t inflation_rewards_collector;
329 : fd_pubkey_t block_revenue_collector;
330 : ushort inflation_rewards_commission_bps;
331 : ushort block_revenue_commission_bps;
332 : ulong pending_delegator_rewards;
333 : uchar bls_pubkey_compressed[FD_BLS_PUBKEY_COMPRESSED_SZ];
334 : uchar has_bls_pubkey_compressed;
335 : fd_landed_vote_t * votes;
336 : ulong root_slot;
337 : uchar has_root_slot;
338 : fd_vote_authorized_voters_t authorized_voters;
339 : fd_vote_epoch_credits_t * epoch_credits;
340 : fd_vote_block_timestamp_t last_timestamp;
341 : };
342 : typedef struct fd_vote_state_v4 fd_vote_state_v4_t;
343 :
344 : struct __attribute__((packed)) fd_vote_state_v5_authorized_voter {
345 : ulong epoch;
346 : fd_pubkey_t pubkey;
347 : };
348 : typedef struct fd_vote_state_v5_authorized_voter fd_vote_state_v5_authorized_voter_t;
349 :
350 : /* Vote State V5 layout. This is the exact same layout as the on-chain
351 : struct, to facilitate zero-copy access. */
352 : struct __attribute__((packed,aligned(4))) fd_vote_state_v5 {
353 : /*uint discriminant - present on-chain but omitted here to save memory */
354 : fd_pubkey_t node_pubkey;
355 : fd_pubkey_t authorized_withdrawer;
356 : fd_pubkey_t inflation_rewards_collector;
357 : fd_pubkey_t block_revenue_collector;
358 : fd_validator_location_t location;
359 : ulong pending_delegator_rewards;
360 : uint inflation_rewards_commission_bps_len;
361 : uint block_revenue_commission_bps_len;
362 : ulong inflation_rewards_commission_bps_epochs[ FD_VOTE_STATE_V5_COMMISSION_MAX ];
363 : ushort inflation_rewards_commission_bps[ FD_VOTE_STATE_V5_COMMISSION_MAX ];
364 : ulong block_revenue_commission_bps_epochs[ FD_VOTE_STATE_V5_COMMISSION_MAX ];
365 : ushort block_revenue_commission_bps[ FD_VOTE_STATE_V5_COMMISSION_MAX ];
366 : uchar bls_pubkey_compressed[ FD_BLS_PUBKEY_COMPRESSED_SZ ];
367 : ulong latest_vote;
368 : ulong root_slot;
369 : uint authorized_voters_len;
370 : uint accumulated_lamports_len;
371 : fd_vote_state_v5_authorized_voter_t authorized_voters[ MAX_AUTHORIZED_VOTERS ];
372 : fd_vote_epoch_credits_t accumulated_lamports[ FD_VOTE_STATE_V5_ACCUMULATED_LAMPORTS_MAX ];
373 : fd_vote_block_timestamp_t last_timestamp;
374 : ulong rank_epoch;
375 : ushort rank;
376 : uchar _pad[ 2 ];
377 : };
378 : typedef struct fd_vote_state_v5 fd_vote_state_v5_t;
379 :
380 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, location )==128UL, v5_layout );
381 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, pending_delegator_rewards )==140UL, v5_layout );
382 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, inflation_rewards_commission_bps_len )==148UL, v5_layout );
383 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, block_revenue_commission_bps_len )==152UL, v5_layout );
384 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, inflation_rewards_commission_bps_epochs )==156UL, v5_layout );
385 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, inflation_rewards_commission_bps )==188UL, v5_layout );
386 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, block_revenue_commission_bps_epochs )==196UL, v5_layout );
387 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, block_revenue_commission_bps )==228UL, v5_layout );
388 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, bls_pubkey_compressed )==236UL, v5_layout );
389 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, latest_vote )==284UL, v5_layout );
390 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, root_slot )==292UL, v5_layout );
391 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, authorized_voters_len )==300UL, v5_layout );
392 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, accumulated_lamports_len )==304UL, v5_layout );
393 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, authorized_voters )==308UL, v5_layout );
394 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, accumulated_lamports )==468UL, v5_layout );
395 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, last_timestamp )==588UL, v5_layout );
396 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, rank_epoch )==604UL, v5_layout );
397 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, rank )==612UL, v5_layout );
398 : FD_STATIC_ASSERT( offsetof( fd_vote_state_v5_t, _pad )==614UL, v5_layout );
399 : FD_STATIC_ASSERT( sizeof(fd_vote_state_v5_t)==616UL, v5_layout );
400 : FD_STATIC_ASSERT( alignof(fd_vote_state_v5_t)==4UL, v5_layout );
401 :
402 0 : #define FD_VOTE_STATE_V5_PAD_OFF (sizeof(uint)+offsetof( fd_vote_state_v5_t, _pad ))
403 0 : #define FD_VOTE_STATE_V5_PAD_SZ (FD_VOTE_STATE_V5_SZ-FD_VOTE_STATE_V5_PAD_OFF)
404 :
405 : struct fd_vote_state_v5_commission {
406 : ulong len;
407 : ulong epoch[ FD_VOTE_STATE_V5_COMMISSION_MAX ];
408 : ushort bps [ FD_VOTE_STATE_V5_COMMISSION_MAX ];
409 : };
410 : typedef struct fd_vote_state_v5_commission fd_vote_state_v5_commission_t;
411 :
412 : /**********************************************************************/
413 : /* Versioned vote state (discriminated union) */
414 : /**********************************************************************/
415 :
416 : struct fd_vote_state_versioned {
417 : uint kind;
418 : union {
419 : fd_vote_state_1_14_11_t v1_14_11;
420 : fd_vote_state_v3_t v3;
421 : fd_vote_state_v4_t v4;
422 : fd_vote_state_v5_t v5;
423 : };
424 :
425 : /* Memory for dynamic sub-structures */
426 : uchar landed_votes_mem [ FD_LANDED_VOTES_FOOTPRINT ] __attribute__((aligned(FD_LANDED_VOTES_ALIGN)));
427 : uchar epoch_credits_mem [ FD_EPOCH_CREDITS_FOOTPRINT ] __attribute__((aligned(FD_EPOCH_CREDITS_ALIGN)));
428 : uchar authorized_voters_pool_mem [ FD_AUTHORIZED_VOTERS_POOL_FOOTPRINT ] __attribute__((aligned(FD_AUTHORIZED_VOTERS_POOL_ALIGN)));
429 : uchar authorized_voters_treap_mem [ FD_AUTHORIZED_VOTERS_TREAP_FOOTPRINT] __attribute__((aligned(FD_AUTHORIZED_VOTERS_TREAP_ALIGN)));
430 : };
431 : typedef struct fd_vote_state_versioned fd_vote_state_versioned_t;
432 :
433 : enum {
434 : fd_vote_state_versioned_enum_uninitialized = 0,
435 : fd_vote_state_versioned_enum_v1_14_11 = 1,
436 : fd_vote_state_versioned_enum_v3 = 2,
437 : fd_vote_state_versioned_enum_v4 = 3,
438 : fd_vote_state_versioned_enum_v5 = 4,
439 : };
440 :
441 : /**********************************************************************/
442 : /* Vote instruction sub-types */
443 : /**********************************************************************/
444 :
445 : struct fd_lockout_offset {
446 : ulong offset;
447 : uchar confirmation_count;
448 : };
449 : typedef struct fd_lockout_offset fd_lockout_offset_t;
450 : #define FD_LOCKOUT_OFFSET_ALIGN alignof(fd_lockout_offset_t)
451 :
452 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/programs/vote/src/vote_state/mod.rs#L133 */
453 : struct fd_legacy_vote {
454 : ulong * slots;
455 : fd_hash_t hash;
456 : long timestamp;
457 : uchar has_timestamp;
458 : uchar slots_mem[ FD_VOTE_INSTR_SLOTS_FOOTPRINT ] __attribute__((aligned(FD_VOTE_INSTR_SLOTS_ALIGN)));
459 : };
460 : typedef struct fd_legacy_vote fd_legacy_vote_t;
461 : #define FD_LEGACY_VOTE_ALIGN alignof(fd_legacy_vote_t)
462 :
463 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/programs/vote/src/vote_instruction.rs#L37 */
464 : struct fd_vote_authorize_pubkey {
465 : fd_pubkey_t pubkey;
466 : fd_vote_authorize_t vote_authorize;
467 : };
468 : typedef struct fd_vote_authorize_pubkey fd_vote_authorize_pubkey_t;
469 : #define FD_VOTE_AUTHORIZE_PUBKEY_ALIGN alignof(fd_vote_authorize_pubkey_t)
470 :
471 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/programs/vote/src/vote_instruction.rs#L78 */
472 : struct fd_vote_switch {
473 : fd_legacy_vote_t vote;
474 : fd_hash_t hash;
475 : };
476 : typedef struct fd_vote_switch fd_vote_switch_t;
477 : #define FD_VOTE_SWITCH_ALIGN alignof(fd_vote_switch_t)
478 :
479 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/programs/vote/src/vote_state/mod.rs#L185 */
480 : struct fd_vote_state_update {
481 : fd_vote_lockout_t * lockouts;
482 : ulong root;
483 : uchar has_root;
484 : fd_hash_t hash;
485 : long timestamp;
486 : uchar has_timestamp;
487 : uchar lockouts_mem[ FD_VOTE_INSTR_UPDATE_LOCKOUTS_FOOTPRINT ] __attribute__((aligned(FD_VOTE_INSTR_UPDATE_LOCKOUTS_ALIGN)));
488 : };
489 : typedef struct fd_vote_state_update fd_vote_state_update_t;
490 : #define FD_VOTE_STATE_UPDATE_ALIGN alignof(fd_vote_state_update_t)
491 :
492 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/programs/vote/src/vote_instruction.rs#L104 */
493 : struct fd_update_vote_state_switch {
494 : fd_vote_state_update_t vote_state_update;
495 : fd_hash_t hash;
496 : };
497 : typedef struct fd_update_vote_state_switch fd_update_vote_state_switch_t;
498 : #define FD_UPDATE_VOTE_STATE_SWITCH_ALIGN alignof(fd_update_vote_state_switch_t)
499 :
500 : struct fd_compact_vote_state_update {
501 : ulong root;
502 : ushort lockouts_len;
503 : fd_lockout_offset_t * lockouts;
504 : fd_hash_t hash;
505 : long timestamp;
506 : uchar has_timestamp;
507 : uchar lockouts_mem[ FD_VOTE_INSTR_LOCKOUT_OFFSET_FOOTPRINT ] __attribute__((aligned(FD_VOTE_INSTR_LOCKOUT_OFFSET_ALIGN)));
508 : };
509 : typedef struct fd_compact_vote_state_update fd_compact_vote_state_update_t;
510 : #define FD_COMPACT_VOTE_STATE_UPDATE_ALIGN alignof(fd_compact_vote_state_update_t)
511 :
512 : /* https://github.com/solana-labs/solana/blob/252438e28fbfb2c695fe1215171b83456e4b761c/programs/vote/src/vote_instruction.rs#L143 */
513 : struct fd_compact_vote_state_update_switch {
514 : fd_compact_vote_state_update_t compact_vote_state_update;
515 : fd_hash_t hash;
516 : };
517 : typedef struct fd_compact_vote_state_update_switch fd_compact_vote_state_update_switch_t;
518 : #define FD_COMPACT_VOTE_STATE_UPDATE_SWITCH_ALIGN alignof(fd_compact_vote_state_update_switch_t)
519 :
520 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/programs/vote/src/vote_state/mod.rs#L185 */
521 : struct fd_tower_sync {
522 : fd_vote_lockout_t * lockouts;
523 : ulong lockouts_cnt;
524 : ulong root;
525 : uchar has_root;
526 : fd_hash_t hash;
527 : long timestamp;
528 : uchar has_timestamp;
529 : fd_hash_t block_id;
530 : uchar lockouts_mem[ FD_VOTE_INSTR_LOCKOUTS_FOOTPRINT ] __attribute__((aligned(FD_VOTE_INSTR_LOCKOUTS_ALIGN)));
531 : };
532 : typedef struct fd_tower_sync fd_tower_sync_t;
533 : #define FD_TOWER_SYNC_ALIGN alignof(fd_tower_sync_t)
534 :
535 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/programs/vote/src/vote_instruction.rs#L104 */
536 : struct fd_tower_sync_switch {
537 : fd_tower_sync_t tower_sync;
538 : fd_hash_t hash;
539 : };
540 : typedef struct fd_tower_sync_switch fd_tower_sync_switch_t;
541 : #define FD_TOWER_SYNC_SWITCH_ALIGN alignof(fd_tower_sync_switch_t)
542 :
543 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/programs/vote/src/vote_state/mod.rs#L244 */
544 : struct fd_vote_authorize_with_seed_args {
545 : fd_vote_authorize_t authorization_type;
546 : fd_pubkey_t current_authority_derived_key_owner;
547 : ulong current_authority_derived_key_seed_len;
548 : uchar current_authority_derived_key_seed[ FD_VOTE_INSTR_SEED_MAX ];
549 : fd_pubkey_t new_authority;
550 : };
551 : typedef struct fd_vote_authorize_with_seed_args fd_vote_authorize_with_seed_args_t;
552 : #define FD_VOTE_AUTHORIZE_WITH_SEED_ARGS_ALIGN alignof(fd_vote_authorize_with_seed_args_t)
553 :
554 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/programs/vote/src/vote_state/mod.rs#L252 */
555 : struct fd_vote_authorize_checked_with_seed_args {
556 : fd_vote_authorize_t authorization_type;
557 : fd_pubkey_t current_authority_derived_key_owner;
558 : ulong current_authority_derived_key_seed_len;
559 : uchar current_authority_derived_key_seed[ FD_VOTE_INSTR_SEED_MAX ];
560 : };
561 : typedef struct fd_vote_authorize_checked_with_seed_args fd_vote_authorize_checked_with_seed_args_t;
562 : #define FD_VOTE_AUTHORIZE_CHECKED_WITH_SEED_ARGS_ALIGN alignof(fd_vote_authorize_checked_with_seed_args_t)
563 :
564 : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.0.0/vote-interface/src/instruction.rs#L28-L31 */
565 : struct fd_commission_kind {
566 : uint discriminant;
567 : };
568 : typedef struct fd_commission_kind fd_commission_kind_t;
569 : #define FD_COMMISSION_KIND_ALIGN alignof(fd_commission_kind_t)
570 :
571 : enum {
572 : fd_commission_kind_enum_inflation_rewards = 0,
573 : fd_commission_kind_enum_block_revenue = 1,
574 : };
575 :
576 : struct fd_update_commission_bps_args {
577 : ushort commission_bps;
578 : fd_commission_kind_t kind;
579 : };
580 : typedef struct fd_update_commission_bps_args fd_update_commission_bps_args_t;
581 : #define FD_UPDATE_COMMISSION_BPS_ARGS_ALIGN alignof(fd_update_commission_bps_args_t)
582 :
583 : struct fd_deposit_delegator_rewards_args {
584 : ulong deposit;
585 : };
586 : typedef struct fd_deposit_delegator_rewards_args fd_deposit_delegator_rewards_args_t;
587 : #define FD_DEPOSIT_DELEGATOR_REWARDS_ARGS_ALIGN alignof(fd_deposit_delegator_rewards_args_t)
588 :
589 : /**********************************************************************/
590 : /* Vote instruction (discriminated union) */
591 : /**********************************************************************/
592 :
593 : /* https://github.com/firedancer-io/solana/blob/53a4e5d6c58b2ffe89b09304e4437f8ca198dadd/programs/vote/src/vote_instruction.rs#L21 */
594 : struct fd_vote_instruction {
595 : uint discriminant;
596 : union {
597 : fd_vote_init_t initialize_account;
598 : fd_vote_authorize_pubkey_t authorize;
599 : fd_legacy_vote_t vote;
600 : ulong withdraw;
601 : uchar update_commission;
602 : fd_vote_switch_t vote_switch;
603 : fd_vote_authorize_t authorize_checked;
604 : fd_vote_state_update_t update_vote_state;
605 : fd_update_vote_state_switch_t update_vote_state_switch;
606 : fd_vote_authorize_with_seed_args_t authorize_with_seed;
607 : fd_vote_authorize_checked_with_seed_args_t authorize_checked_with_seed;
608 : fd_compact_vote_state_update_t compact_update_vote_state;
609 : fd_compact_vote_state_update_switch_t compact_update_vote_state_switch;
610 : fd_tower_sync_t tower_sync;
611 : fd_tower_sync_switch_t tower_sync_switch;
612 : fd_vote_init_v2_t initialize_account_v2;
613 : fd_commission_kind_t update_commission_collector;
614 : fd_update_commission_bps_args_t update_commission_bps;
615 : fd_deposit_delegator_rewards_args_t deposit_delegator_rewards;
616 : fd_validator_location_t update_location;
617 : };
618 : };
619 : typedef struct fd_vote_instruction fd_vote_instruction_t;
620 :
621 : enum {
622 : fd_vote_instruction_enum_initialize_account = 0,
623 : fd_vote_instruction_enum_authorize = 1,
624 : fd_vote_instruction_enum_vote = 2,
625 : fd_vote_instruction_enum_withdraw = 3,
626 : fd_vote_instruction_enum_update_validator_identity = 4,
627 : fd_vote_instruction_enum_update_commission = 5,
628 : fd_vote_instruction_enum_vote_switch = 6,
629 : fd_vote_instruction_enum_authorize_checked = 7,
630 : fd_vote_instruction_enum_update_vote_state = 8,
631 : fd_vote_instruction_enum_update_vote_state_switch = 9,
632 : fd_vote_instruction_enum_authorize_with_seed = 10,
633 : fd_vote_instruction_enum_authorize_checked_with_seed = 11,
634 : fd_vote_instruction_enum_compact_update_vote_state = 12,
635 : fd_vote_instruction_enum_compact_update_vote_state_switch = 13,
636 : fd_vote_instruction_enum_tower_sync = 14,
637 : fd_vote_instruction_enum_tower_sync_switch = 15,
638 : fd_vote_instruction_enum_initialize_account_v2 = 16,
639 : fd_vote_instruction_enum_update_commission_collector = 17,
640 : fd_vote_instruction_enum_update_commission_bps = 18,
641 : fd_vote_instruction_enum_deposit_delegator_rewards = 19,
642 : fd_vote_instruction_enum_update_location = 20,
643 : };
644 :
645 : /**********************************************************************/
646 : /* Function declarations */
647 : /**********************************************************************/
648 :
649 : FD_PROTOTYPES_BEGIN
650 :
651 : /* Initializes a fd_vote_state_versioned_t and its dynamic members
652 : (votes deque, epoch_credits deque, authorized_voters pool,
653 : authorized_voters treap). Based on the discriminant, the appropriate
654 : version-specific struct is initialized.
655 :
656 : Returns a pointer to the initialized fd_vote_state_versioned_t, or
657 : NULL if mem is NULL or kind is an unsupported vote state version. */
658 : fd_vote_state_versioned_t *
659 : fd_vote_state_versioned_new( fd_vote_state_versioned_t * self,
660 : uint kind );
661 :
662 : /* Deserializes the vote state from a bincode-encoded buffer into the
663 : provided vote state versioned struct. On success returns self.
664 : Returns NULL on failure (malformed data). */
665 : fd_vote_state_versioned_t *
666 : fd_vote_state_versioned_deserialize( fd_vote_state_versioned_t * self,
667 : uchar const * payload,
668 : ulong payload_sz );
669 :
670 : /* Serializes the vote state into a bincode-encoded buffer. buf must
671 : have at least enough space for the encoded representation. Returns
672 : 0 on success, 1 on failure (e.g. buffer too small). */
673 : int
674 : fd_vote_state_versioned_serialize( fd_vote_state_versioned_t const * self,
675 : uchar * buf,
676 : ulong buf_sz );
677 :
678 : /* Computes the serialized size of self arithmetically without
679 : writing. Returns the size in bytes, or 0 if self has an unrecognized
680 : discriminant. */
681 : ulong
682 : fd_vote_state_versioned_serialized_size( fd_vote_state_versioned_t const * self );
683 :
684 : /**********************************************************************/
685 : /* Direct field accessors */
686 : /* Read fields directly from raw bincode-encoded vote account data */
687 : /* without full deserialization. */
688 : /**********************************************************************/
689 :
690 : /* Reads the node_pubkey directly from raw bincode-encoded vote
691 : account data. Returns 0 on success, 1 on error. */
692 : int
693 : fd_vote_account_node_pubkey( uchar const * data,
694 : ulong data_sz,
695 : fd_pubkey_t * out );
696 :
697 : /* Reads the compressed BLS voting pubkey directly from raw
698 : bincode-encoded v4 vote account data. Returns 0 on success, 1 on
699 : error (not v4, no bls pubkey set, or truncated). */
700 : int
701 : fd_vote_account_bls_pubkey( uchar const * data,
702 : ulong data_sz,
703 : uchar out[ static FD_BLS_PUBKEY_COMPRESSED_SZ ] );
704 :
705 : /* Returns the commission in basis points. If commission_rate_in_bps is
706 : set, returns the v4 commission rate as a raw basis points value.
707 : Otherwise, returns the v4 commission rate in basis points, rounded
708 : down to the nearest whole percentage. For v1_14_11/v3, returns the
709 : raw commission byte * 100.
710 :
711 : Returns 0 on success, 1 on error. */
712 : int
713 : fd_vote_account_commission_bps( uchar const * data,
714 : ulong data_sz,
715 : int commission_rate_in_bps,
716 : ushort * out );
717 :
718 : /* Reads the SIMD-0232 commission collectors directly from raw
719 : bincode-encoded vote account data. Pre-v4 states have no collector
720 : fields and return the defaults: vote_pubkey (inflation) and
721 : node_pubkey (block revenue). Returns 0 on success, 1 on error. */
722 : int
723 : fd_vote_account_collectors( uchar const * data,
724 : ulong data_sz,
725 : fd_pubkey_t const * vote_pubkey,
726 : fd_pubkey_t const * node_pubkey,
727 : fd_pubkey_t * inflation_rewards_collector_out,
728 : fd_pubkey_t * block_revenue_collector_out );
729 :
730 : /* Reads the authorized voter for epoch directly from raw
731 : bincode-encoded vote account data. Returns 0 on success, 1 on error
732 : or if no entry qualifies. */
733 : int
734 : fd_vote_account_authorized_voter( uchar const * data,
735 : ulong data_sz,
736 : ulong epoch,
737 : fd_pubkey_t * out );
738 :
739 : /* Reads the SIMD-0123 block revenue commission in basis points
740 : directly from raw bincode-encoded vote account data.
741 : The stored value is returned as is, not rounded.
742 : Returns 0 on success, 1 on error. */
743 : int
744 : fd_vote_account_block_revenue_commission_bps( uchar const * data,
745 : ulong data_sz,
746 : ushort * out );
747 :
748 : /* Reads the SIMD-0123 pending delegator rewards directly from raw
749 : bincode-encoded vote account data.
750 : Returns 0 on success, 1 on error. */
751 : int
752 : fd_vote_account_pending_delegator_rewards( uchar const * data,
753 : ulong data_sz,
754 : ulong * out );
755 :
756 : /* fd_vote_account_add_pending_delegator_rewards adds lamports to the
757 : pending delegator rewards field in place.
758 : Returns 0 on success, 1 if the data is not an initialized v4 state,
759 : 2 on overflow. */
760 : int
761 : fd_vote_account_add_pending_delegator_rewards( uchar * data,
762 : ulong data_sz,
763 : ulong lamports );
764 :
765 : /* fd_vote_account_reset_pending_delegator_rewards zeroes the pending
766 : delegator rewards field in place and stores the value it held in *old_out.
767 : Returns 0 on success, 1 if the data is not an initialized v4 state.
768 : https://github.com/anza-xyz/agave/blob/v4.4.0-alpha.5/vote/src/vote_state_view_mut.rs#L58-L71 */
769 : int
770 : fd_vote_account_reset_pending_delegator_rewards( uchar * data,
771 : ulong data_sz,
772 : ulong * old_out );
773 :
774 : /* Reads the last_timestamp directly from raw bincode-encoded vote
775 : account data. Returns 0 on success, 1 on error. */
776 : int
777 : fd_vote_account_last_timestamp( uchar const * data,
778 : ulong data_sz,
779 : fd_vote_block_timestamp_t * out );
780 :
781 : /* Returns 1 if the vote account is v4 with has_bls_pubkey_compressed
782 : set, 0 otherwise. */
783 : int
784 : fd_vote_account_has_bls_pubkey( uchar const * data,
785 : ulong data_sz );
786 :
787 : /* Seeks through variable-length fields and returns a zero-copy pointer
788 : to the epoch_credits entries inside the raw buffer. *cnt is set to
789 : the number of entries. Returns NULL on error. */
790 : fd_vote_epoch_credits_t const *
791 : fd_vote_account_epoch_credits( uchar const * data,
792 : ulong data_sz,
793 : ulong * cnt );
794 :
795 : int
796 : fd_vote_account_is_valid_v5( uchar const * data,
797 : ulong data_sz );
798 :
799 : static inline fd_vote_state_v5_t *
800 0 : fd_vote_account_v5( uchar * data ) {
801 : /* Skip the discriminant at the start of the on-chain vote account */
802 0 : return fd_type_pun( data+sizeof(uint) );
803 0 : }
804 :
805 : fd_validator_location_t
806 : fd_vote_account_location( uchar const * data,
807 : ulong data_sz );
808 :
809 : static inline void
810 : fd_vote_state_v5_commission_get( fd_vote_state_v5_t const * self,
811 : uint kind,
812 0 : fd_vote_state_v5_commission_t * out ) {
813 0 : int block = kind==fd_commission_kind_enum_block_revenue;
814 0 : out->len = block ? self->block_revenue_commission_bps_len : self->inflation_rewards_commission_bps_len;
815 0 : for( ulong i=0UL; i<FD_VOTE_STATE_V5_COMMISSION_MAX; i++ ) {
816 0 : out->epoch[ i ] = block ? self->block_revenue_commission_bps_epochs[ i ] : self->inflation_rewards_commission_bps_epochs[ i ];
817 0 : out->bps [ i ] = block ? self->block_revenue_commission_bps [ i ] : self->inflation_rewards_commission_bps [ i ];
818 0 : }
819 0 : }
820 :
821 : static inline void
822 : fd_vote_state_v5_commission_set( fd_vote_state_v5_t * self,
823 : uint kind,
824 0 : fd_vote_state_v5_commission_t const * in ) {
825 0 : if( kind==fd_commission_kind_enum_block_revenue ) {
826 0 : self->block_revenue_commission_bps_len = (uint)in->len;
827 0 : for( ulong i=0UL; i<FD_VOTE_STATE_V5_COMMISSION_MAX; i++ ) {
828 0 : self->block_revenue_commission_bps_epochs[ i ] = in->epoch[ i ];
829 0 : self->block_revenue_commission_bps [ i ] = in->bps [ i ];
830 0 : }
831 0 : } else {
832 0 : self->inflation_rewards_commission_bps_len = (uint)in->len;
833 0 : for( ulong i=0UL; i<FD_VOTE_STATE_V5_COMMISSION_MAX; i++ ) {
834 0 : self->inflation_rewards_commission_bps_epochs[ i ] = in->epoch[ i ];
835 0 : self->inflation_rewards_commission_bps [ i ] = in->bps [ i ];
836 0 : }
837 0 : }
838 0 : }
839 :
840 : FD_FN_PURE static inline int
841 0 : fd_vote_state_v5_commission_is_valid( fd_vote_state_v5_commission_t const * c ) {
842 0 : if( FD_UNLIKELY( c->len<1UL || c->len>FD_VOTE_STATE_V5_COMMISSION_MAX ) ) return 0;
843 0 : for( ulong i=c->len; i<FD_VOTE_STATE_V5_COMMISSION_MAX; i++ ) {
844 0 : if( FD_UNLIKELY( c->epoch[ i ] || c->bps[ i ] ) ) return 0;
845 0 : }
846 0 : return 1;
847 0 : }
848 :
849 : FD_FN_PURE static inline ushort
850 0 : fd_vote_state_v5_commission_latest( fd_vote_state_v5_commission_t const * c ) {
851 0 : return c->len ? c->bps[ c->len-1UL ] : (ushort)0;
852 0 : }
853 :
854 : static inline void
855 : fd_vote_state_v5_commission_schedule( fd_vote_state_v5_commission_t * c,
856 : ulong epoch,
857 0 : ushort bps ) {
858 0 : if( c->len && c->epoch[ c->len-1UL ]==epoch ) {
859 0 : c->bps[ c->len-1UL ] = bps;
860 0 : return;
861 0 : }
862 0 : if( c->len==FD_VOTE_STATE_V5_COMMISSION_MAX ) {
863 0 : for( ulong i=1UL; i<c->len; i++ ) {
864 0 : c->epoch[ i-1UL ] = c->epoch[ i ];
865 0 : c->bps [ i-1UL ] = c->bps [ i ];
866 0 : }
867 0 : c->len--;
868 0 : }
869 0 : c->epoch[ c->len ] = epoch;
870 0 : c->bps [ c->len ] = bps;
871 0 : c->len++;
872 0 : }
873 :
874 : /* fd_vote_instruction_deserialize deserializes a vote instruction from
875 : bincode-encoded data into the provided instruction struct. Dynamic
876 : data (deques, arrays) is placed in memory embedded within the
877 : sub-structs of instruction.
878 :
879 : Only bytes up to FD_TXN_MTU_V0 are parsed, the rest are discarded,
880 : matching Agave's limited_deserialize(data, PACKET_DATA_SIZE).
881 :
882 : On success returns instruction. Returns NULL on failure (malformed
883 : data). */
884 :
885 : fd_vote_instruction_t *
886 : fd_vote_instruction_deserialize( fd_vote_instruction_t * instruction,
887 : uchar const * data,
888 : ulong data_sz );
889 :
890 : FD_PROTOTYPES_END
891 :
892 : #endif /* HEADER_fd_src_flamenco_runtime_program_vote_fd_vote_codec_h */
|