Line data Source code
1 : #include "fd_epoch_forks.h" 2 : #include "../../flamenco/runtime/context/fd_exec_epoch_ctx.h" 3 : #include "../../flamenco/runtime/sysvar/fd_sysvar_epoch_schedule.h" 4 : 5 0 : #define VOTE_ACC_MAX (2000000UL) 6 : 7 : static void 8 0 : dump( fd_epoch_forks_t * epoch_forks ) { 9 0 : for( ulong i = 0UL; i<MAX_EPOCH_FORKS; i++ ) { 10 0 : fd_epoch_fork_elem_t * elem = &epoch_forks->forks[ i ]; 11 0 : FD_LOG_WARNING(("fork elem %lu %lu %lu", elem->parent_slot, elem->epoch, (ulong)elem->epoch_ctx)); 12 0 : } 13 0 : } 14 : 15 : void 16 0 : fd_epoch_forks_new( fd_epoch_forks_t * epoch_forks, void * epoch_ctx_base ) { 17 0 : for( ulong i=0UL; i<MAX_EPOCH_FORKS; i++ ) { 18 0 : fd_epoch_fork_elem_t * epoch_fork = &epoch_forks->forks[i]; 19 0 : epoch_fork->parent_slot = ULONG_MAX; 20 0 : epoch_fork->epoch = ULONG_MAX; 21 0 : epoch_fork->epoch_ctx = NULL; 22 0 : } 23 : 24 0 : epoch_forks->epoch_ctx_base = (uchar *) epoch_ctx_base; 25 0 : epoch_forks->curr_epoch_idx = ULONG_MAX; 26 0 : } 27 : 28 : void 29 0 : fd_epoch_forks_publish( fd_epoch_forks_t * epoch_forks, fd_ghost_t * ghost, ulong root ) { 30 0 : ulong idx = fd_epoch_forks_get_epoch_ctx( epoch_forks, ghost, root, NULL ); 31 : 32 0 : if( FD_LIKELY( idx == epoch_forks->curr_epoch_idx ) ) return; 33 : 34 0 : for( ulong i=0UL; i<MAX_EPOCH_FORKS; i++ ) { 35 0 : if( FD_LIKELY( i != idx && epoch_forks->forks[ i ].parent_slot != ULONG_MAX ) ) { 36 0 : epoch_forks->forks[ i ].parent_slot = ULONG_MAX; 37 0 : epoch_forks->forks[ i ].epoch = ULONG_MAX; 38 0 : fd_exec_epoch_ctx_delete( fd_exec_epoch_ctx_leave( epoch_forks->forks[ i ].epoch_ctx ) ); 39 0 : epoch_forks->forks[ i ].epoch_ctx = NULL; 40 0 : } 41 0 : } 42 : 43 0 : epoch_forks->curr_epoch_idx = idx; 44 0 : } 45 : 46 : uint 47 0 : fd_epoch_forks_prepare( fd_epoch_forks_t * epoch_forks, ulong parent_slot, ulong new_epoch, fd_epoch_fork_elem_t ** out_fork ) { 48 0 : ulong empty = ULONG_MAX; 49 0 : ulong i = 0UL; 50 : 51 0 : for( ; i<MAX_EPOCH_FORKS; i++ ) { 52 0 : if( epoch_forks->forks[ i ].parent_slot == ULONG_MAX ) { 53 0 : empty = (empty == ULONG_MAX) ? i : empty; 54 0 : continue; 55 0 : } 56 0 : if( epoch_forks->forks[ i ].epoch == new_epoch && epoch_forks->forks[ i ].parent_slot == parent_slot ) { 57 0 : *out_fork = &epoch_forks->forks[ i ]; 58 0 : return 1; 59 0 : } 60 0 : } 61 : 62 0 : if( FD_LIKELY( empty != ULONG_MAX ) ) { 63 0 : epoch_forks->forks[ empty ].parent_slot = parent_slot; 64 0 : epoch_forks->forks[ empty ].epoch = new_epoch; 65 : 66 0 : uchar * epoch_ctx_mem = epoch_forks->epoch_ctx_base + (empty * fd_ulong_align_up( fd_exec_epoch_ctx_footprint( VOTE_ACC_MAX ), fd_exec_epoch_ctx_align() ) ); 67 0 : epoch_forks->forks[ empty ].epoch_ctx = fd_exec_epoch_ctx_join( fd_exec_epoch_ctx_new( epoch_ctx_mem, VOTE_ACC_MAX ) ); 68 0 : *out_fork = &epoch_forks->forks[ empty ]; 69 0 : } else { 70 0 : dump( epoch_forks ); 71 0 : FD_LOG_CRIT(("Too many forks for epoch boundary.")); 72 0 : } 73 : 74 0 : return 0; 75 0 : } 76 : 77 : ulong 78 0 : fd_epoch_forks_get_epoch_ctx( fd_epoch_forks_t * epoch_forks, fd_ghost_t * ghost, ulong curr_slot, ulong * opt_prev_slot ) { 79 0 : fd_exec_epoch_ctx_t * epoch_ctx = epoch_forks->forks[ epoch_forks->curr_epoch_idx ].epoch_ctx; 80 0 : fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( epoch_ctx ); 81 0 : ulong epoch = fd_slot_to_epoch( &epoch_bank->epoch_schedule, curr_slot, NULL ); 82 0 : if( FD_LIKELY( epoch == epoch_forks->forks[ epoch_forks->curr_epoch_idx ].epoch ) ) return epoch_forks->curr_epoch_idx; 83 : 84 0 : ulong max_parent_root = 0UL; 85 0 : ulong max_idx = ULONG_MAX; 86 0 : for( ulong i=0; i<MAX_EPOCH_FORKS; i++ ) { 87 0 : fd_epoch_fork_elem_t * elem = &epoch_forks->forks[ i ]; 88 0 : if( elem->parent_slot == ULONG_MAX ) continue; 89 : 90 : /* check if this fork has a parent in the entries list, and isn't the parent itself. */ 91 0 : ulong slot = (opt_prev_slot == NULL) ? curr_slot : *opt_prev_slot; 92 0 : if( elem->parent_slot != slot && elem->parent_slot >= ghost->root->slot && fd_ghost_is_descendant( ghost, slot, elem->parent_slot ) ) { 93 0 : if( elem->parent_slot > max_parent_root ) { 94 0 : max_parent_root = elem->parent_slot; 95 0 : max_idx = i; 96 0 : } 97 0 : } 98 0 : } 99 : 100 0 : return (max_idx != ULONG_MAX) ? max_idx : epoch_forks->curr_epoch_idx; 101 0 : }