Line data Source code
1 : #ifndef HEADER_fd_src_choreo_epoch_fd_epoch_h 2 : #define HEADER_fd_src_choreo_epoch_fd_epoch_h 3 : 4 : #include "../fd_choreo_base.h" 5 : #include "../voter/fd_voter.h" 6 : #include "../../flamenco/stakes/fd_vote_states.h" 7 : 8 : /* FD_EPOCH_USE_HANDHOLDING: Define this to non-zero at compile time 9 : to turn on additional runtime checks and logging. */ 10 : 11 : #ifndef FD_EPOCH_USE_HANDHOLDING 12 : #define FD_EPOCH_USE_HANDHOLDING 1 13 : #endif 14 : 15 18 : #define FD_EPOCH_MAGIC (0xf17eda2ce7e90c40UL) /* firedancer epoch version 0 */ 16 : 17 : struct __attribute__((aligned(128UL))) fd_epoch { 18 : ulong magic; /* ==FD_EPOCH_MAGIC */ 19 : ulong epoch_gaddr; /* wksp gaddr of this in the backing wksp, non-zero gaddr */ 20 : ulong total_stake; /* total amount of stake in the epoch. */ 21 : ulong first_slot; /* first slot in the epoch */ 22 : ulong last_slot; /* last slot in the epoch */ 23 : 24 : /* voters_gaddr is the global address of a fd_map_dynamic that 25 : contains all voters in the current epoch keyed by pubkey (vote 26 : account address). */ 27 : 28 : ulong voters_gaddr; 29 : }; 30 : typedef struct fd_epoch fd_epoch_t; 31 : 32 : #define MAP_NAME fd_epoch_voters 33 90 : #define MAP_T fd_voter_t 34 72 : #define MAP_KEY_T fd_pubkey_t 35 108 : #define MAP_KEY_NULL (fd_pubkey_t){0} 36 117 : #define MAP_KEY_EQUAL(k0,k1) (!(memcmp((k0).key,(k1).key,sizeof(fd_pubkey_t)))) 37 72 : #define MAP_KEY_INVAL(k) (MAP_KEY_EQUAL((k),MAP_KEY_NULL)) 38 : #define MAP_KEY_EQUAL_IS_SLOW 1 39 54 : #define MAP_KEY_HASH(key) ((key).ui[3]) 40 : #include "../../util/tmpl/fd_map_dynamic.c" 41 : 42 : /* fd_epoch_{align,footprint} return the required alignment and 43 : footprint of a memory region suitable for use as epoch. align is 44 : double cache line to mitigate false sharing. */ 45 : 46 : FD_FN_CONST static inline ulong 47 201 : fd_epoch_align( void ) { 48 201 : return alignof(fd_epoch_t); 49 201 : } 50 : 51 : FD_FN_CONST static inline ulong 52 36 : fd_epoch_footprint( ulong voter_max ) { 53 36 : int lg_slot_cnt = fd_ulong_find_msb( fd_ulong_pow2_up( voter_max ) ) + 2; /* fill ratio <= 0.25 */ 54 36 : return FD_LAYOUT_FINI( 55 36 : FD_LAYOUT_APPEND( 56 36 : FD_LAYOUT_APPEND( 57 36 : FD_LAYOUT_INIT, 58 36 : alignof(fd_epoch_t), sizeof(fd_epoch_t) ), 59 36 : fd_epoch_voters_align(), fd_epoch_voters_footprint( lg_slot_cnt ) ), 60 36 : fd_epoch_align() ); 61 36 : } 62 : 63 : /* fd_epoch_new formats an unused memory region for use as an epoch. mem 64 : is a non-NULL pointer to this region in the local address space with 65 : the required footprint and alignment. */ 66 : 67 : void * 68 : fd_epoch_new( void * mem, ulong voter_max ); 69 : 70 : /* fd_epoch_join joins the caller to the epoch. epoch points to the 71 : first byte of the memory region backing the epoch in the caller's 72 : address space. 73 : 74 : Returns a pointer in the local address space to epoch on success. */ 75 : 76 : fd_epoch_t * 77 : fd_epoch_join( void * epoch ); 78 : 79 : /* fd_epoch_leave leaves a current local join. Returns a pointer to the 80 : underlying shared memory region on success and NULL on failure (logs 81 : details). Reasons for failure include epoch is NULL. */ 82 : 83 : void * 84 : fd_epoch_leave( fd_epoch_t const * epoch ); 85 : 86 : /* fd_epoch_delete unformats a memory region used as an epoch. Assumes 87 : only the local process is joined to the region. Returns a pointer to 88 : the underlying shared memory region or NULL if used obviously in 89 : error (e.g. epoch is obviously not an epoch ... logs details). The 90 : ownership of the memory region is transferred to the caller. */ 91 : 92 : void * 93 : fd_epoch_delete( void * epoch ); 94 : 95 : /* fd_epoch_init initializes a fd_choreo epoch using vote states from 96 : the runtime bank. Assumes epoch is a valid local join and epoch has 97 : not already been initialized. This should only be called once 98 : at the beginning of an epoch. */ 99 : 100 : void 101 : fd_epoch_init( fd_epoch_t * epoch, 102 : ulong eah_start_slot, 103 : ulong eah_stop_slot, 104 : fd_vote_states_t const * vote_accounts ); 105 : 106 : /* fd_epoch_fini finishes an epoch. Assumes epoch is a valid local join 107 : and epoch has already been initialized. This should only be called 108 : once at the end of an epoch. */ 109 : 110 : void 111 : fd_epoch_fini( fd_epoch_t * epoch ); 112 : 113 : /* fd_epoch_wksp returns the local join to the wksp backing the epoch. 114 : The lifetime of the returned pointer is at least as long as the 115 : lifetime of the local join. Assumes epoch is a current local 116 : join. */ 117 : 118 : FD_FN_PURE static inline fd_wksp_t * 119 54 : fd_epoch_wksp( fd_epoch_t const * epoch ) { 120 54 : return (fd_wksp_t *)( ( (ulong)epoch ) - epoch->epoch_gaddr ); 121 54 : } 122 : 123 : FD_FN_PURE static inline fd_voter_t * 124 54 : fd_epoch_voters( fd_epoch_t * epoch ) { 125 54 : return fd_wksp_laddr_fast( fd_epoch_wksp( epoch ), epoch->voters_gaddr ); 126 54 : } 127 : 128 : FD_FN_PURE static inline fd_voter_t const * 129 0 : fd_epoch_voters_const( fd_epoch_t const * epoch ) { 130 0 : return fd_wksp_laddr_fast( fd_epoch_wksp( epoch ), epoch->voters_gaddr ); 131 0 : } 132 : 133 : #endif /* HEADER_fd_src_choreo_epoch_fd_epoch_h */