Line data Source code
1 : #ifndef HEADER_fd_src_choreo_tower_fd_tower_lockos_h 2 : #define HEADER_fd_src_choreo_tower_fd_tower_lockos_h 3 : 4 : #include "../fd_choreo_base.h" 5 : #include "fd_tower_voters.h" 6 : 7 : /* fd_tower_lockos_interval tracks a map of lockout intervals. 8 : 9 : We need to track a list of lockout intervals per validator per slot. 10 : Intervals are inclusive. Example: 11 : 12 : After executing slot 33, validator A votes for slot 32, has a tower 13 : 14 : vote | confirmation count | lockout interval 15 : ----- | -------------------|------------------ 16 : 32 | 1 | [32, 33] 17 : 2 | 3 | [2, 6] 18 : 1 | 4 | [1, 9] 19 : 20 : The lockout interval is the interval of slots that the validator is 21 : locked out from voting for if they want to switch off that vote. For 22 : example if validator A wants to switch off fork 1, they have to wait 23 : until slot 9. 24 : 25 : Agave tracks a similar structure. 26 : 27 : key: for an interval [vote, vote+lockout] for validator A, 28 : it is stored like: 29 : vote+lockout -> (vote, validator A) -> (2, validator B) -> (any other vote, any other validator) 30 : 31 : Since a validator can have up to 31 entries in the tower, and we have 32 : a max_vote_accounts, we can pool the interval objects to be 33 : 31*max_vote_accounts entries PER bank / executed slot. We can also 34 : string all the intervals of the same bank together as a linkedlist. */ 35 : 36 : struct fd_tower_lockos_interval { 37 : ulong key; /* vote_slot (32 bits) | expiration_slot (32 bits) ie. vote_slot + (1 << confirmation count) */ 38 : ulong next; /* reserved for fd_map_chain and fd_pool */ 39 : fd_hash_t addr; /* vote account address */ 40 : ulong start; /* start of interval, also vote slot */ 41 : }; 42 : typedef struct fd_tower_lockos_interval fd_tower_lockos_interval_t; 43 : 44 : #define MAP_NAME fd_tower_lockos_interval_map 45 0 : #define MAP_ELE_T fd_tower_lockos_interval_t 46 : #define MAP_MULTI 1 47 0 : #define MAP_KEY key 48 0 : #define MAP_NEXT next 49 : #include "../../util/tmpl/fd_map_chain.c" 50 : 51 : #define POOL_NAME fd_tower_lockos_interval_pool 52 0 : #define POOL_T fd_tower_lockos_interval_t 53 0 : #define POOL_NEXT next 54 : #include "../../util/tmpl/fd_pool.c" 55 : 56 : struct fd_tower_lockos_slot { 57 : ulong fork_slot; 58 : ulong next; /* reserved for fd_map_chain and fd_pool */ 59 : ulong interval_end; 60 : }; 61 : typedef struct fd_tower_lockos_slot fd_tower_lockos_slot_t; 62 : 63 : #define MAP_NAME fd_tower_lockos_slot_map 64 0 : #define MAP_ELE_T fd_tower_lockos_slot_t 65 : #define MAP_MULTI 1 66 0 : #define MAP_KEY fork_slot 67 0 : #define MAP_NEXT next 68 : #include "../../util/tmpl/fd_map_chain.c" 69 : 70 : #define POOL_NAME fd_tower_lockos_slot_pool 71 0 : #define POOL_T fd_tower_lockos_slot_t 72 0 : #define POOL_NEXT next 73 : #include "../../util/tmpl/fd_pool.c" 74 : 75 0 : #define FD_TOWER_LOCKOS_MAX 31UL 76 : 77 : struct __attribute__((aligned(128UL))) fd_tower_lockos { 78 : fd_tower_lockos_slot_map_t * slot_map; 79 : fd_tower_lockos_slot_t * slot_pool; 80 : fd_tower_lockos_interval_map_t * interval_map; 81 : fd_tower_lockos_interval_t * interval_pool; 82 : }; 83 : typedef struct fd_tower_lockos fd_tower_lockos_t; 84 : 85 : FD_PROTOTYPES_BEGIN 86 : 87 : /* fd_tower_lockos_{align,footprint} return the required alignment and 88 : footprint of a memory region suitable for use as a tower_lockos. */ 89 : 90 : FD_FN_CONST static inline ulong 91 0 : fd_tower_lockos_align( void ) { 92 0 : return 128UL; 93 0 : } 94 : 95 : FD_FN_CONST static inline ulong 96 : fd_tower_lockos_footprint( ulong slot_max, 97 0 : ulong vtr_max ) { 98 0 : ulong interval_max = fd_ulong_pow2_up( FD_TOWER_LOCKOS_MAX*slot_max*vtr_max ); 99 0 : return FD_LAYOUT_FINI( 100 0 : FD_LAYOUT_APPEND( 101 0 : FD_LAYOUT_APPEND( 102 0 : FD_LAYOUT_APPEND( 103 0 : FD_LAYOUT_APPEND( 104 0 : FD_LAYOUT_APPEND( 105 0 : FD_LAYOUT_INIT, 106 0 : alignof(fd_tower_lockos_t), sizeof(fd_tower_lockos_t) ), 107 0 : fd_tower_lockos_slot_pool_align(), fd_tower_lockos_slot_pool_footprint ( interval_max ) ), 108 0 : fd_tower_lockos_slot_map_align(), fd_tower_lockos_slot_map_footprint ( slot_max ) ), 109 0 : fd_tower_lockos_interval_pool_align(), fd_tower_lockos_interval_pool_footprint( interval_max ) ), 110 0 : fd_tower_lockos_interval_map_align(), fd_tower_lockos_interval_map_footprint ( interval_max ) ), 111 0 : fd_tower_lockos_align() ); 112 0 : } 113 : 114 : /* fd_tower_lockos_new formats an unused memory region for use as a 115 : tower_lockos. mem is a non-NULL pointer to this region in the local 116 : address space with the required footprint and alignment. */ 117 : 118 : void * 119 : fd_tower_lockos_new( void * shmem, 120 : ulong slot_max, 121 : ulong vtr_max, 122 : ulong seed ); 123 : 124 : /* fd_tower_lockos_join joins the caller to the tower_lockos. shlockos 125 : points to the first byte of the memory region backing the shlockos in 126 : the caller's address space. 127 : 128 : Returns a pointer in the local address space to lockos on success. */ 129 : 130 : fd_tower_lockos_t * 131 : fd_tower_lockos_join( void * shlockos ); 132 : 133 : /* fd_tower_lockos_leave leaves a current local join. Returns a pointer 134 : to the underlying shared memory region on success and NULL on failure 135 : (logs details). Reasons for failure include lockos is NULL. */ 136 : 137 : void * 138 : fd_tower_lockos_leave( fd_tower_lockos_t const * lockos ); 139 : 140 : /* fd_tower_lockos_delete unformats a memory region used as a lockos. 141 : Assumes only the local process is joined to the region. Returns a 142 : pointer to the underlying shared memory region or NULL if used 143 : obviously in error (e.g. lockos is obviously not a lockos ... logs 144 : details). The ownership of the memory region is transferred to the 145 : caller. */ 146 : 147 : void * 148 : fd_tower_lockos_delete( void * lockos ); 149 : 150 : FD_FN_PURE static inline ulong 151 0 : fd_tower_lockos_interval_key( ulong fork_slot, ulong end_interval ) { 152 0 : return (fork_slot << 32) | end_interval; 153 0 : } 154 : 155 : void 156 : fd_tower_lockos_insert( fd_tower_lockos_t * lockos, 157 : ulong slot, 158 : fd_hash_t const * vote_acc, 159 : fd_tower_voters_t * voters ); 160 : 161 : void 162 : fd_tower_lockos_remove( fd_tower_lockos_t * lockos, 163 : ulong slot ); 164 : 165 : FD_PROTOTYPES_END 166 : 167 : #endif /* HEADER_fd_src_choreo_tower_fd_tower_lockos_h */