Line data Source code
1 : #ifndef HEADER_fd_src_disco_store_fd_epoch_forks_h 2 : #define HEADER_fd_src_disco_store_fd_epoch_forks_h 3 : 4 : #include "../fd_disco_base.h" 5 : #include "../../choreo/ghost/fd_ghost.h" 6 : 7 0 : #define MAX_EPOCH_FORKS 8 8 : 9 : /* fd_epoch_forks is a map which manages forking across an epoch 10 : boundary. It is based on the idea that we need a new epoch_ctx 11 : for every unique subtree of forks spanning across a boundary. 12 : An example fork tree, assuming new epoch starts at slot 100: 13 : 98 14 : | ---------- 15 : | | 16 : 99 | 17 : ----- ----- 104 18 : | | 19 : | | 20 : 100 102 21 : For this example, we hit the epoch boundary for 100, 102 and 104 in 22 : the respective forks. However, since the epoch context is updated based 23 : on parent slot ctx, and remains the same across an epoch, it will be 24 : the same for 100 and 102. Therefore, we allocate 2 epoch fork entries, 25 : one for parent slot 98 (leading to 104), and one for parent slot 99 26 : (leading to 100 or 102). While we are unrooted in the epoch starting at 27 : 100, we maintain these epoch fork entries, but as soon as we root at any 28 : of these slots, we can publish the correct entruy and prune the epoch ctx 29 : entries for the other forks. 30 : 31 : The API is straightforward and initializes a small cache for epoch_ctx 32 : entries and accepts a base pointer to a pre-allocated memory region for 33 : epoch_ctx objects. It allows for preparing a new epoch fork, publishing 34 : the forks, and getting the correct epoch ctx for the current slot. */ 35 : struct fd_epoch_fork_elem { 36 : ulong parent_slot; 37 : ulong epoch; 38 : fd_exec_epoch_ctx_t * epoch_ctx; 39 : }; 40 : 41 : typedef struct fd_epoch_fork_elem fd_epoch_fork_elem_t; 42 : 43 : struct fd_epoch_forks { 44 : fd_epoch_fork_elem_t forks[MAX_EPOCH_FORKS]; 45 : ulong curr_epoch_idx; 46 : uchar * epoch_ctx_base; 47 : }; 48 : 49 : typedef struct fd_epoch_forks fd_epoch_forks_t; 50 : 51 : FD_PROTOTYPES_BEGIN 52 : 53 : /* epoch_forks_new initializes the fork elements and stores the base pointer for 54 : the epoch_ctx allocations. */ 55 : void 56 : fd_epoch_forks_new( fd_epoch_forks_t * epoch_forks, void * epoch_ctx_base ); 57 : 58 : /* epoch_forks_publish checks for whether we have rooted into a new epoch and 59 : clears out the fork entries which can be pruned at that point. It also picks 60 : the correct entry to use for the new epoch. */ 61 : void 62 : fd_epoch_forks_publish( fd_epoch_forks_t * epoch_forks, fd_ghost_t * ghost, ulong root ); 63 : 64 : /* epoch_forks_prepare creates a new entry for the fork crossing the epoch boundary, 65 : or returns the existing entry associated with the fork crossing the epoch boundary. 66 : Crashes with CRIT if we have exceeded max forks. */ 67 : uint 68 : fd_epoch_forks_prepare( fd_epoch_forks_t * epoch_forks, ulong parent_slot, ulong new_epoch, fd_epoch_fork_elem_t ** out_fork ); 69 : 70 : /* epoch_forks_get_epoch_ctx returns the correct entry index for the current epoch, or 71 : in the case of a new epoch fork, the correct entry index related to the fork. */ 72 : ulong 73 : fd_epoch_forks_get_epoch_ctx( fd_epoch_forks_t * epoch_forks, fd_ghost_t * ghost, ulong curr_slot, ulong * opt_prev_slot ); 74 : 75 : FD_PROTOTYPES_END 76 : 77 : #endif /* HEADER_fd_src_disco_store_fd_epoch_forks_h */