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