Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_stakes_fd_top_votes_h
2 : #define HEADER_fd_src_flamenco_stakes_fd_top_votes_h
3 :
4 : #include "../../funk/fd_funk_base.h"
5 : #include "../../flamenco/fd_flamenco_base.h"
6 : #include "../accdb/fd_accdb_base.h"
7 :
8 : /* With the introduction of VAT, the set of vote accounts that receive
9 : epoch rewards, participate in clock calculation, and are eligible for
10 : becoming leader becomes the top 2000 staked validators.
11 : fd_top_votes_t allows for efficiently populating and querying the
12 : set of top staked validators. This data structure is intended to be
13 : CoW-able and maintained by the banks.
14 :
15 : Under the hood, fd_top_votes_t uses a heap, map, and pool to track
16 : the top set of vote accounts as they are being added. The map allows
17 : for O(1) lookup of a vote account by its public key.
18 :
19 : An important tiebreaking rule is that if the minimum stake value has
20 : a tie, all accounts with that stake value will be excluded from the
21 : top voters set.
22 :
23 : The semantics around whether an account should be included in the
24 : top voters set is quite subtle and is based off of how Agave handles
25 : its stakes cache and epoch stakes. The stakes cache is a cache of
26 : vote and stake accounts that is updated through an epoch. It will
27 : always contain the full set of vote/stake accounts that are active
28 : for the current epoch. The Agave epoch stakes are effectively
29 : snapshots of the stakes cache that are taken at the end of each
30 : epoch. After VAT is enabled, the Agave client will only include the
31 : top 2000 staked vote accounts into the epoch stakes. This means for
32 : the t-1 epoch, the top voters set contains the top 2000 staked vote
33 : accounts (with a BLS pubkey) and the account must exist at the epoch
34 : boundary. However, a vote account can be deleted even if it is in
35 : the top votes set. If this is the case, the account will be marked
36 : as invalid since it can be recreated. */
37 :
38 : struct fd_top_votes;
39 : typedef struct fd_top_votes fd_top_votes_t;
40 :
41 14247 : #define FD_TOP_VOTES_ALIGN (128UL)
42 :
43 : /* FD_TOP_VOTES_MAX_FOOTPRINT is the footprint of the fd_top_votes_t
44 : structure when the max number of vote accounts is
45 : FD_RUNTIME_MAX_VOTE_ACCOUNTS_VAT (2000). */
46 :
47 7491 : #define FD_TOP_VOTES_MAX_FOOTPRINT (194432UL)
48 :
49 : FD_PROTOTYPES_BEGIN
50 :
51 : /* fd_top_votes_align returns the alignment of the fd_top_votes_t
52 : structure. */
53 :
54 : ulong
55 : fd_top_votes_align( void );
56 :
57 : /* fd_top_votes_footprint returns the footprint of the fd_top_votes_t
58 : structure given a max number of vote accounts. */
59 :
60 : ulong
61 : fd_top_votes_footprint( ulong vote_accounts_max );
62 :
63 : /* fd_top_votes_new creates a new fd_top_votes_t structure given a
64 : memory buffer, a max number of vote accounts, and a seed. */
65 :
66 : void *
67 : fd_top_votes_new( void * mem,
68 : ushort vote_accounts_max,
69 : ulong seed );
70 :
71 : /* fd_top_votes_join joins a fd_top_votes_t structure from a memory
72 : region that has been previously initialized with fd_top_votes_new.
73 : Returns a pointer to the fd_top_votes_t structure. */
74 :
75 : fd_top_votes_t *
76 : fd_top_votes_join( void * mem );
77 :
78 : /* fd_top_votes_init is a runtime initialization function for a
79 : fd_top_votes_t structure given a pointer to the structure. */
80 :
81 : void
82 : fd_top_votes_init( fd_top_votes_t * top_votes );
83 :
84 :
85 : /* fd_top_votes_insert inserts a new vote account into the top votes set
86 : given a vote account, node account, and commission. If the vote
87 : account isn't in the top max_vote_accounts in terms of stake, it is
88 : ignored and is treated as a no-op. If the vote account ties the
89 : minimum stake and the struct is full, all elements with that stake
90 : are removed. */
91 :
92 : void
93 : fd_top_votes_insert( fd_top_votes_t * top_votes,
94 : fd_pubkey_t const * pubkey,
95 : fd_pubkey_t const * node_account,
96 : ulong stake,
97 : uchar commission );
98 :
99 : /* fd_top_votes_update updates the last vote timestamp and slot for a
100 : given vote account in the top votes set. If the vote account is not
101 : in the top votes set, the update is ignored and is treated as a
102 : no-op. */
103 :
104 : void
105 : fd_top_votes_update( fd_top_votes_t * top_votes,
106 : fd_pubkey_t const * pubkey,
107 : ulong last_vote_slot,
108 : long last_vote_timestamp );
109 :
110 : /* fd_top_votes_invalidate invalidates a vote account in the top votes
111 : set. This would be done in the case a vote account is withdrawn or
112 : becomes invalid. An account that is invalid, will not be returned by
113 : fd_top_votes_query. */
114 :
115 : void
116 : fd_top_votes_invalidate( fd_top_votes_t * top_votes,
117 : fd_pubkey_t const * pubkey );
118 :
119 : /* fd_top_votes_query queries a fd_top_votes_t structure given a
120 : vote account and returns 1 if the vote account is in the top voters
121 : set and 0 otherwise. If the vote account is in the top voters set,
122 : the node account, stake, last vote slot, and last vote timestamp are
123 : all optionally returned via parameter pointers. */
124 :
125 : int
126 : fd_top_votes_query( fd_top_votes_t const * top_votes,
127 : fd_pubkey_t const * pubkey,
128 : fd_pubkey_t * node_account_out_opt,
129 : ulong * stake_out_opt,
130 : ulong * last_vote_slot_out_opt,
131 : long * last_vote_timestamp_out_opt,
132 : uchar * commission_out_opt );
133 :
134 : /* fd_top_votes_refresh refreshes the top votes set given an accdb
135 : user and a transaction xid. The top votes are populated with a
136 : snapshot manifest before the account data is loaded in. Information
137 : about latest votes and if the account still exists must be refreshed
138 : using the accounts database afterwards. */
139 :
140 : void
141 : fd_top_votes_refresh( fd_top_votes_t * top_votes,
142 : fd_accdb_user_t * accdb,
143 : fd_funk_txn_xid_t const * xid );
144 :
145 : #define FD_TOP_VOTES_ITER_FOOTPRINT (16UL)
146 : #define FD_TOP_VOTES_ITER_ALIGN (8UL)
147 : struct map_iter;
148 : typedef struct map_iter fd_top_votes_iter_t;
149 :
150 : /* A caller can iterate through the entries in the top votes set. The
151 : iterator is initialized by a call to fd_top_votes_iter_init. The
152 : caller is responsible for managing the memory for the iterator.
153 : It is safe to call fd_top_votes_iter_next if the result of
154 : fd_top_votes_iter_done() == 0. It is safe to call
155 : fd_top_votes_iter_ele() to get the current entry if there is a valid
156 : initialized iterator.
157 :
158 : Example use:
159 : uchar __attribute__((aligned(FD_TOP_VOTES_ITER_ALIGN))) iter_mem[ FD_TOP_VOTES_ITER_FOOTPRINT ];
160 : for( fd_top_votes_iter_t * iter = fd_top_votes_iter_init( top_votes, iter_mem );
161 : !fd_top_votes_iter_done( top_votes, iter );
162 : fd_top_votes_iter_next( top_votes, iter ) ) {
163 : int is_valid = fd_top_votes_iter_ele( top_votes, iter, &pubkey, &node_account, &stake, &commission, &last_vote_slot, &last_vote_timestamp );
164 : } */
165 :
166 : fd_top_votes_iter_t *
167 : fd_top_votes_iter_init( fd_top_votes_t const * top_votes,
168 : uchar iter_mem[ static FD_TOP_VOTES_ITER_FOOTPRINT ] );
169 :
170 : int
171 : fd_top_votes_iter_done( fd_top_votes_t const * top_votes,
172 : fd_top_votes_iter_t * iter );
173 :
174 : void
175 : fd_top_votes_iter_next( fd_top_votes_t const * top_votes,
176 : fd_top_votes_iter_t * iter );
177 :
178 : int
179 : fd_top_votes_iter_ele( fd_top_votes_t const * top_votes,
180 : fd_top_votes_iter_t * iter,
181 : fd_pubkey_t * pubkey_out,
182 : fd_pubkey_t * node_account_out_opt,
183 : ulong * stake_out_opt,
184 : uchar * commission_out_opt,
185 : ulong * last_vote_slot_out_opt,
186 : long * last_vote_timestamp_out_opt );
187 :
188 : FD_PROTOTYPES_END
189 :
190 : #endif
|