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