Line data Source code
1 : #ifndef HEADER_fd_src_discof_replay_fd_eslot_mgr_h 2 : #define HEADER_fd_src_discof_replay_fd_eslot_mgr_h 3 : 4 : #include "../../util/fd_util_base.h" 5 : #include "../../disco/fd_disco_base.h" 6 : 7 : FD_PROTOTYPES_BEGIN 8 : 9 0 : #define FD_ESLOT_MGR_MAGIC (0xF17EDA2CE7E51070UL) /* FIREDANCER ESLOT MGR V0 */ 10 : 11 : /* fd_eslot_mgr_t is a manager/tracker for block equivocation. It is 12 : able to handle both leader and non-leader slots. It supports a 13 : dual-key mechanism both by fd_eslot_t (a 64-bit bitfield representing 14 : the slot and prime count) and by the merkle root. The struct serves 15 : as a translation layer between FEC set merkle roots and eslot entries 16 : while also detecting equivocation. 17 : 18 : The eslot manager is implented as two maps (one keyed by fd_eslot_t 19 : and the other keyed by the latest merkle root) backed by a pool. */ 20 : 21 : struct fd_eslot_ele { 22 : fd_eslot_t eslot; 23 : fd_eslot_t parent_eslot; 24 : fd_hash_t merkle_root; 25 : ulong highest_fec_idx_observed; 26 : int is_leader; 27 : 28 : ulong next_; 29 : ulong next_mr_; 30 : }; 31 : typedef struct fd_eslot_ele fd_eslot_ele_t; 32 : 33 : struct fd_eslot_mgr; 34 : typedef struct fd_eslot_mgr fd_eslot_mgr_t; 35 : 36 : /* fd_eslot_mgr_align() returns the alignment of an fd_eslot_mgr_t. */ 37 : 38 : ulong 39 : fd_eslot_mgr_align( void ); 40 : 41 : /* fd_eslot_mgr_footprint returns the footprint of a fd_eslot_mgr_t 42 : given a number of eslots. */ 43 : 44 : ulong 45 : fd_eslot_mgr_footprint( ulong eslot_cnt ); 46 : 47 : /* fd_eslot_mgr_new() creates a new fd_eslot_mgr_t. It takes a pointer 48 : to shared memory, the max number of eslots, and a seed. */ 49 : 50 : uchar * 51 : fd_eslot_mgr_new( void * shmem, 52 : ulong eslot_cnt, 53 : ulong seed ); 54 : 55 : /* fd_eslot_mgr_join() joins an fd_eslot_mgr_t from shared memory. */ 56 : 57 : fd_eslot_mgr_t * 58 : fd_eslot_mgr_join( void * shmem ); 59 : 60 : /* fd_eslot_mgr_ele_insert_fec() processes the information for a new 61 : FEC set (merkle root, chained merkle root, slot, and FEC set index). 62 : It will either return an existing eslot entry or create a new entry 63 : depending on the current state of the eslot manager. Each entry will 64 : correspond to a unique fd_eslot_t. If equivocation is detected, the 65 : is_equiv_out parameter will be set to 1, otherwise it will be set to 66 : 0. 67 : 68 : If the chained merkle root is equal to a merkle root in the eslot 69 : manager, then we can successfully link the eslot to an existing 70 : entry. If we can't link the eslot to an existing entry, it is still 71 : possible for us to process the FEC set. 72 : 73 : If we have linked the FEC to an existing eslot entry, then we have 74 : a few cases to consider: 75 : 1. If the eslot mgr entry has the same slot as the FEC set. Then all 76 : we need to do is increment the entry's merkle root and highest 77 : observed fec set idx. This means that we have not equivocated. 78 : 2. If the eslot mgr entry has a different slot than the FEC set. 79 : Then we need to create a new eslot mgr entry corresponding to the 80 : merkle hash and FEC idx of the FEC set. If we already have a 81 : entry for the FEC's slot, that means we have equivocated. 82 : 83 : If we have not linked the FEC to an existing eslot entry, this means 84 : that we have received an equivocating FEC or there is corruption in 85 : the eslot manager. If we already have an entry for the FEC's slot 86 : and the entry's highest fec idx observed is >= the fec set idx this 87 : means that we have received an equivocating FEC and the equivocation 88 : occured mid-slot. A new eslot mgr entry will be created. */ 89 : 90 : fd_eslot_ele_t * 91 : fd_eslot_mgr_ele_insert_fec( fd_eslot_mgr_t * mgr, 92 : ulong slot, 93 : fd_hash_t const * merkle_root, 94 : fd_hash_t const * chained_merkle_root, 95 : ulong fec_set_idx, 96 : int * is_equiv_out ); 97 : 98 : /* fd_eslot_mgr_ele_insert_leader inserts an eslot entry for a leader 99 : slot. We know that slots that we are leader for will never be 100 : equivocated, so we can safely insert an eslot entry corresponding to 101 : the leader slot and prime count ==0 into the map. We have to case 102 : this differently than FECs that we replay because we don't have 103 : merkle roots for the leader slot until we are done executing it. */ 104 : 105 : fd_eslot_ele_t * 106 : fd_eslot_mgr_ele_insert_leader( fd_eslot_mgr_t * mgr, 107 : ulong slot, 108 : fd_eslot_t parent_eslot ); 109 : 110 : /* fd_eslot_mgr_ele_insert_initial inserts an eslot entry for the 111 : initial slot. This assumes that the initial entry will not be 112 : equivocated and that the actual block id is unknown (it will be set 113 : to a default value). */ 114 : 115 : fd_eslot_ele_t * 116 : fd_eslot_mgr_ele_insert_initial( fd_eslot_mgr_t * mgr, 117 : ulong slot ); 118 : 119 : /* fd_eslot_mgr_is_leader() returns 1 if the eslot manager has an entry 120 : for the given slot which corresponds to a leader slot and 0 121 : otherwise. */ 122 : 123 : int 124 : fd_eslot_mgr_is_leader( fd_eslot_mgr_t * mgr, 125 : ulong slot ); 126 : 127 : /* fd_eslot_mgr_ele_query_eslot() returns the eslot entry for the given 128 : eslot. */ 129 : 130 : fd_eslot_ele_t * 131 : fd_eslot_mgr_ele_query_eslot( fd_eslot_mgr_t * mgr, 132 : fd_eslot_t eslot ); 133 : 134 : /* fd_eslot_mgr_ele_query_merkle_root() returns the eslot entry for the 135 : given merkle root. */ 136 : 137 : fd_eslot_ele_t * 138 : fd_eslot_mgr_ele_query_merkle_root( fd_eslot_mgr_t * mgr, 139 : fd_hash_t const * merkle_root ); 140 : 141 : /* fd_eslot_mgr_rekey_merkle_root updates the merkle root for the given 142 : eslot entry. This should only be used for leader slot entries. */ 143 : 144 : void 145 : fd_eslot_mgr_rekey_merkle_root( fd_eslot_mgr_t * mgr, 146 : fd_eslot_ele_t * ele, 147 : fd_hash_t const * merkle_root ); 148 : 149 : /* fd_eslot_mgr_publish will purge all entries for all slots 150 : monotonically increasing from old_root_slot inclusive to 151 : new_root_slot exclusive. This includes all prime count for each 152 : slot that is purged. After this function is called, some parent 153 : eslot entries may not have entries in the map in the case the parent 154 : eslot entries were pruned away. */ 155 : 156 : void 157 : fd_eslot_mgr_publish( fd_eslot_mgr_t * mgr, 158 : ulong old_root_slot, 159 : ulong new_root_slot ); 160 : 161 : /* TODO: Add a printing function for the eslot manager. */ 162 : 163 : FD_PROTOTYPES_END 164 : 165 : #endif /* HEADER_fd_src_discof_replay_fd_eslot_mgr_h */