Line data Source code
1 : #ifndef HEADER_fd_src_discof_replay_fd_replay_tile_h 2 : #define HEADER_fd_src_discof_replay_fd_replay_tile_h 3 : 4 : /* Banks and Reasm 5 : ================= 6 : 7 : OVERVIEW 8 : 9 : Reasm maintains a tree of FEC sets organized as a main tree (rooted 10 : at the published root) plus orphan trees. Each FEC set in the 11 : connected tree may be associated with a bank via bank_idx, or be 12 : still unreplayed. In general, reasm tries to approximate the state 13 : of banks as closely as possible. It's inexact, because reasm is 14 : stored at the FEC unit, while banks are stored at the slot unit. 15 : 16 : When reasm delivers a FEC set (via fd_reasm_pop), the replay tile 17 : processes it by assigning it a bank. If it's the first FEC in a 18 : slot (fec_set_idx==0), a new bank is provisioned from the parent's 19 : bank. Subsequent FECs in the same slot inherit the bank_idx from 20 : the preceding FEC. This means all FEC sets within a single slot 21 : share the same bank_idx, with the exception of equivocating FECs. 22 : 23 : PUBLISHING (ROOT ADVANCEMENT) 24 : 25 : When tower sends a new consensus root, replay advances the 26 : published root along the rooted fork as far as possible. A block 27 : on the rooted fork is safe to prune when it and all minority fork 28 : subtrees branching from it have refcnt 0. Publishing calls 29 : fd_reasm_publish to prune the reasm tree (and the store) of any 30 : FEC sets that do not descend from the new root. 31 : 32 : REASM EVICTION (POOL-PRESSURE EVICTION) 33 : 34 : When the reasm pool is nearly full (1 free element remaining) and a 35 : new FEC needs to be inserted, reasm runs its eviction policy to free 36 : space. The eviction in general prioritizes orphans first, and then 37 : frontier slots that are incomplete. 38 : 39 : If eviction succeeds, the evicted chain is returned as a linked 40 : list of pool elements (removed from maps but still acquired in 41 : the pool). The replay tile is responsible for: 42 : 1. Publishing each evicted FEC to repair (REPLAY_SIG_REASM_EVICTED) 43 : so repair can re-request the data. 44 : 2. Releasing each evicted element back to the reasm pool before 45 : the next insert. 46 : 47 : It's important to note that replay bank eviction is NOT coupled with 48 : reasm FEC eviction. Reasm FEC eviction is triggered by the reasm pool 49 : being full, and is independent of the replay bank eviction. Reasm 50 : FEC eviction is triggered by the reasm pool being full while banks 51 : eviction is triggered by the banks being full and the scheduler 52 : being drained. 53 : 54 : By evicting and publishing evicted FECs to repair, replay is 55 : attempting a "go-around" strategy to ensure progress is made even 56 : when memory pressure is high. An evicted FEC - if valid - will be 57 : requested by repair and eventually re-delivered to replay, where 58 : hopefully by then there will be pool capacity to insert and replay 59 : the FEC. */ 60 : 61 : #include "../poh/fd_poh_tile.h" 62 : #include "../../disco/tiles.h" 63 : #include "../reasm/fd_reasm.h" 64 : 65 0 : #define REPLAY_SIG_SLOT_COMPLETED (0) 66 0 : #define REPLAY_SIG_SLOT_DEAD (1) 67 0 : #define REPLAY_SIG_ROOT_ADVANCED (2) 68 0 : #define REPLAY_SIG_RESET (3) 69 0 : #define REPLAY_SIG_BECAME_LEADER (4) 70 0 : #define REPLAY_SIG_OC_ADVANCED (5) 71 0 : #define REPLAY_SIG_TXN_EXECUTED (6) 72 0 : #define REPLAY_SIG_REASM_EVICTED (7) 73 0 : #define REPLAY_SIG_WFS_DONE (8) 74 : 75 : /* fd_replay_slot_completed promises that it will deliver at most 2 76 : frags for a given slot (at most 2 equivocating blocks). The first 77 : block is the first one we replay to completion. The second version 78 : (if there is) is always the confirmed equivocating block. This 79 : guarantee is provided by fd_reasm. */ 80 : 81 : struct fd_replay_slot_completed { 82 : ulong slot; 83 : ulong root_slot; 84 : ulong storage_slot; 85 : ulong epoch; 86 : ulong slot_in_epoch; 87 : ulong slots_per_epoch; 88 : ulong block_height; 89 : ulong parent_slot; 90 : 91 : fd_hash_t block_id; /* block id (last FEC set's merkle root) of the slot received from replay */ 92 : fd_hash_t parent_block_id; /* parent block id of the slot received from replay */ 93 : fd_hash_t bank_hash; /* bank hash of the slot received from replay */ 94 : fd_hash_t block_hash; /* last microblock header hash of slot received from replay */ 95 : ulong transaction_count; /* since genesis */ 96 : 97 : struct { 98 : double initial; 99 : double terminal; 100 : double taper; 101 : double foundation; 102 : double foundation_term; 103 : } inflation; 104 : 105 : struct { 106 : ulong lamports_per_uint8_year; 107 : double exemption_threshold; 108 : uchar burn_percent; 109 : } rent; 110 : 111 : /* Reference to the bank for this completed slot. TODO: We can 112 : eliminate non-timestamp fields and have consumers just use 113 : bank_idx. */ 114 : ulong bank_idx; 115 : fd_xid_t xid; 116 : 117 : long first_fec_set_received_nanos; /* timestamp when replay received the first fec of the slot from turbine or repair */ 118 : long preparation_begin_nanos; /* timestamp when replay began preparing the state to begin execution of the slot */ 119 : long first_transaction_scheduled_nanos; /* timestamp when replay first sent a transaction to be executed */ 120 : long last_transaction_finished_nanos; /* timestamp when replay received the last execution completion */ 121 : long completion_time_nanos; /* timestamp when replay completed finalizing the slot and notified tower */ 122 : 123 : int is_leader; /* whether we were leader for this slot */ 124 : ulong identity_balance; 125 : 126 : /* since slot start, default ULONG_MAX */ 127 : ulong vote_success; 128 : ulong vote_failed; 129 : ulong nonvote_success; 130 : ulong nonvote_failed; 131 : 132 : ulong transaction_fee; 133 : ulong priority_fee; 134 : ulong tips; 135 : ulong shred_cnt; 136 : 137 : struct { 138 : ulong block_cost; 139 : ulong vote_cost; 140 : ulong allocated_accounts_data_size; 141 : ulong block_cost_limit; 142 : ulong vote_cost_limit; 143 : ulong account_cost_limit; 144 : } cost_tracker; 145 : }; 146 : 147 : typedef struct fd_replay_slot_completed fd_replay_slot_completed_t; 148 : 149 : struct fd_replay_slot_dead { 150 : ulong slot; 151 : fd_hash_t block_id; 152 : }; 153 : typedef struct fd_replay_slot_dead fd_replay_slot_dead_t; 154 : 155 : struct fd_replay_oc_advanced { 156 : ulong slot; 157 : ulong bank_idx; 158 : }; 159 : typedef struct fd_replay_oc_advanced fd_replay_oc_advanced_t; 160 : 161 : struct fd_replay_root_advanced { 162 : ulong bank_idx; 163 : ulong slot; 164 : fd_hash_t bank_hash; 165 : }; 166 : typedef struct fd_replay_root_advanced fd_replay_root_advanced_t; 167 : 168 : struct fd_replay_txn_executed { 169 : fd_txn_p_t txn[ 1 ]; 170 : int is_committable; 171 : int is_fees_only; 172 : int txn_err; 173 : long tick_parsed; 174 : long tick_sigverify_disp; 175 : long tick_sigverify_done; 176 : long tick_exec_disp; 177 : long tick_exec_done; 178 : }; 179 : typedef struct fd_replay_txn_executed fd_replay_txn_executed_t; 180 : 181 : struct fd_replay_fec_evicted { 182 : fd_hash_t mr; 183 : ulong slot; 184 : uint fec_set_idx; 185 : ulong bank_idx; 186 : }; 187 : typedef struct fd_replay_fec_evicted fd_replay_fec_evicted_t; 188 : 189 : 190 : union fd_replay_message { 191 : fd_replay_slot_completed_t slot_completed; 192 : fd_replay_root_advanced_t root_advanced; 193 : fd_replay_oc_advanced_t oc_advanced; 194 : fd_poh_reset_t reset; 195 : fd_became_leader_t became_leader; 196 : fd_replay_txn_executed_t txn_executed; 197 : fd_replay_fec_evicted_t reasm_evicted; 198 : }; 199 : 200 : typedef union fd_replay_message fd_replay_message_t; 201 : 202 : #endif /* HEADER_fd_src_discof_replay_fd_replay_tile_h */