Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_stakes_fd_new_votes_h 2 : #define HEADER_fd_src_flamenco_stakes_fd_new_votes_h 3 : 4 : #include "../fd_flamenco_base.h" 5 : #include "../fd_rwlock.h" 6 : 7 : /* fd_new_votes_t tracks vote account presence across epoch boundaries. 8 : It mirrors the memory layout and root/fork-delta pattern of 9 : fd_stake_delegations_t but uses a single shared pool that backs 10 : both the root map and the per-fork delta dlists. */ 11 : 12 594 : #define FD_NEW_VOTES_MAGIC (0xF17EDA2CE7601E72UL) /* FIREDANCER NEWVOT V0 */ 13 4752 : #define FD_NEW_VOTES_ALIGN (128UL) 14 : #define FD_NEW_VOTES_FORK_MAX (4096UL) 15 : 16 : struct fd_new_vote_ele { 17 : fd_pubkey_t pubkey; 18 : uint next; 19 : uint prev; 20 : uchar is_tombstone; 21 : }; 22 : typedef struct fd_new_vote_ele fd_new_vote_ele_t; 23 : 24 : struct fd_new_votes { 25 : ulong magic; 26 : ulong max_vote_accounts; 27 : ulong pool_offset; 28 : ulong map_offset; 29 : ulong fork_pool_offset; 30 : ulong dlist_offsets[ FD_NEW_VOTES_FORK_MAX ]; 31 : 32 : fd_rwlock_t lock; 33 : }; 34 : typedef struct fd_new_votes fd_new_votes_t; 35 : 36 : FD_PROTOTYPES_BEGIN 37 : 38 : ulong 39 : fd_new_votes_align( void ); 40 : 41 : ulong 42 : fd_new_votes_footprint( ulong max_vote_accounts, 43 : ulong expected_vote_accounts, 44 : ulong max_live_forks ); 45 : 46 : void * 47 : fd_new_votes_new( void * mem, 48 : ulong seed, 49 : ulong max_vote_accounts, 50 : ulong expected_vote_accounts, 51 : ulong max_live_forks ); 52 : 53 : fd_new_votes_t * 54 : fd_new_votes_join( void * mem ); 55 : 56 : /* fd_new_votes_reset is used to reset the new votes object to its 57 : initial state. */ 58 : 59 : void 60 : fd_new_votes_reset( fd_new_votes_t * new_votes ); 61 : 62 : /* fd_new_votes_reset_root is used to reset the root map to its initial 63 : state. It does not affect any of the outstanding fork deltas. This 64 : is used when a new epoch boundary is rooted: any old new vote 65 : accounts are no longer relevant. */ 66 : 67 : void 68 : fd_new_votes_reset_root( fd_new_votes_t * new_votes ); 69 : 70 : /* fd_new_votes_root_insert inserts a pubkey directly into the 71 : root map. Duplicate root pubkeys are ignored. */ 72 : 73 : void 74 : fd_new_votes_root_insert( fd_new_votes_t * new_votes, 75 : fd_pubkey_t const * pubkey ); 76 : 77 : /* fd_new_votes_cnt is used to count the number of elements used in the 78 : shared pool between all delta/tombstone elements as well as the 79 : root map. */ 80 : 81 : ulong 82 : fd_new_votes_cnt( fd_new_votes_t const * new_votes ); 83 : 84 : /* fd_new_votes_new_fork is used to allocate a new fork index from the 85 : fork pool. */ 86 : 87 : ushort 88 : fd_new_votes_new_fork( fd_new_votes_t * new_votes ); 89 : 90 : /* fd_new_votes_evict_fork is used to release the fork index to the 91 : fork pool. This is not responsible for applying any elements in the 92 : fork idx into the base. */ 93 : 94 : void 95 : fd_new_votes_evict_fork( fd_new_votes_t * new_votes, 96 : ushort fork_idx ); 97 : 98 : /* fd_new_votes_{insert,remove} are used to track vote accounts as they 99 : are created and removed. Insert marks a pubkey as present, remove 100 : marks it as absent (and introduces a tombstone element). */ 101 : 102 : void 103 : fd_new_votes_insert( fd_new_votes_t * new_votes, 104 : ushort fork_idx, 105 : fd_pubkey_t const * pubkey ); 106 : 107 : void 108 : fd_new_votes_remove( fd_new_votes_t * new_votes, 109 : ushort fork_idx, 110 : fd_pubkey_t const * pubkey ); 111 : 112 : /* Drains the fork's delta dlist into the root map, deduplicating 113 : against existing root entries. Does NOT release the fork pool 114 : slot: the caller must call fd_new_votes_evict_fork afterwards 115 : to return the fork index to the fork pool. */ 116 : 117 : void 118 : fd_new_votes_apply_delta( fd_new_votes_t * new_votes, 119 : ushort fork_idx ); 120 : 121 : 122 : /* Iterates through pubkeys visible from a bank's perspective: first 123 : every entry in the root map, then every entry in the per-fork dlists 124 : (in the order given by fork_idxs), skipping any pubkey already 125 : present in the root map. 126 : 127 : NOTE: dedup is only performed against the root map. If the same 128 : pubkey appears in multiple fork dlists (but not in root), it may be 129 : yielded more than once. Callers must handle this (e.g. by querying 130 : a seen-set before acting on each element). 131 : 132 : The caller provides an array of fork indices (child-to-root order) 133 : and a scratch buffer for the iterator state. 134 : 135 : init acquires a read lock. The caller MUST call fini after the loop 136 : to release it. 137 : 138 : Example: 139 : uchar __attribute__((aligned(FD_NEW_VOTES_ITER_ALIGN))) 140 : iter_mem[ FD_NEW_VOTES_ITER_FOOTPRINT ]; 141 : for( fd_new_votes_iter_t * iter = 142 : fd_new_votes_iter_init( nv, fork_idxs, cnt, iter_mem ); 143 : !fd_new_votes_iter_done( iter ); 144 : fd_new_votes_iter_next( iter ) ) { 145 : fd_pubkey_t const * pk = fd_new_votes_iter_ele( iter, &is_t ); 146 : } 147 : fd_new_votes_iter_fini( iter ); */ 148 : 149 : #define FD_NEW_VOTES_ITER_FOOTPRINT (64UL) 150 : #define FD_NEW_VOTES_ITER_ALIGN (8UL) 151 : 152 : struct fd_new_votes_iter; 153 : typedef struct fd_new_votes_iter fd_new_votes_iter_t; 154 : 155 : fd_new_votes_iter_t * 156 : fd_new_votes_iter_init( fd_new_votes_t * new_votes, 157 : ushort const * fork_idxs, 158 : ulong fork_idx_cnt, 159 : uchar * iter_mem ); 160 : 161 : int 162 : fd_new_votes_iter_done( fd_new_votes_iter_t const * iter ); 163 : 164 : void 165 : fd_new_votes_iter_next( fd_new_votes_iter_t * iter ); 166 : 167 : fd_pubkey_t const * 168 : fd_new_votes_iter_ele( fd_new_votes_iter_t const * iter, 169 : int * is_tombstone ); 170 : 171 : void 172 : fd_new_votes_iter_fini( fd_new_votes_iter_t * iter ); 173 : 174 : FD_PROTOTYPES_END 175 : 176 : #endif /* HEADER_fd_src_flamenco_stakes_fd_new_votes_h */