Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_runtime_fd_cost_tracker_h 2 : #define HEADER_fd_src_flamenco_runtime_fd_cost_tracker_h 3 : 4 : /* fd_cost_tracker_t is a block-level tracker for various limits 5 : including CU consumption, writable account usage, and account data 6 : size. A cost is calculated per-transaction and is accumulated to the 7 : block. If a block's limits are exceeded, then the block is marked as 8 : dead. */ 9 : 10 : #include "fd_runtime_err.h" 11 : #include "fd_runtime_const.h" 12 : 13 : /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L62-L79 */ 14 : 15 414 : #define FD_WRITE_LOCK_UNITS (300U) /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/block_cost_limits.rs#L20 */ 16 : 17 : /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L18-L33 */ 18 540 : #define FD_COST_TRACKER_SUCCESS (0) 19 6 : #define FD_COST_TRACKER_ERROR_WOULD_EXCEED_BLOCK_MAX_LIMIT (1) 20 9 : #define FD_COST_TRACKER_ERROR_WOULD_EXCEED_ACCOUNT_MAX_LIMIT (3) 21 3 : #define FD_COST_TRACKER_ERROR_WOULD_EXCEED_ACCOUNT_DATA_BLOCK_LIMIT (4) 22 0 : #define FD_COST_TRACKER_ERROR_WOULD_EXCEED_ACCOUNT_DATA_TOTAL_LIMIT (5) 23 : 24 : /* TODO: Extremely gross. Used because these are in a pool which needs 25 : to be compile time sized T. */ 26 : 27 : /* The average mainnet block uses around 4200 distinct writable 28 : accounts. We size the cost tracker's account map at 8192 chains 29 : to give ~2x headroom over the observed average load. */ 30 462 : #define FD_COST_TRACKER_CHAIN_CNT_EST (8192UL) 31 : #define FD_COST_TRACKER_FOOTPRINT \ 32 : ( FD_LAYOUT_FINI( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( \ 33 : FD_LAYOUT_INIT, \ 34 : 128UL /* alignof(fd_cost_tracker_t) */, 128UL /* sizeof(fd_cost_tracker_t) */ ), \ 35 : 128UL /* alignof(cost_tracker_out_t )*/, 128UL /* sizeof(cost_tracker_out_t ) */ ), \ 36 : 8UL /* alignof(account_cost_map_t) */, FD_COST_TRACKER_CHAIN_CNT_EST*4UL /*sizeof(uint)*/ +24UL /* sizeof(account_cost_map_t) */ ), \ 37 : 4UL /* alignof(account_cost_t) */, FD_RUNTIME_MAX_TXN_ACC_WRITES_PER_SLOT*40UL /*sizeof(account_cost_t)*/ ), \ 38 : 128UL ) ) \ 39 : 40 453 : #define FD_COST_TRACKER_MAGIC (0xF17EDA2CE7C05170UL) /* FIREDANCER COST V0 */ 41 : 42 1407 : #define FD_COST_TRACKER_ALIGN (128UL) 43 : 44 : struct __attribute__((aligned(FD_COST_TRACKER_ALIGN))) fd_cost_tracker { 45 : ulong block_cost; 46 : ulong allocated_accounts_data_size; 47 : 48 : ulong block_cost_limit; 49 : ulong account_cost_limit; 50 : ulong data_size_limit; 51 : 52 : ulong bench_max_cost_per_block; /* [development.bench], floors block_cost_limit */ 53 : }; 54 : 55 : typedef struct fd_cost_tracker fd_cost_tracker_t; 56 : 57 : /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/transaction_cost.rs#L153-L161 */ 58 : 59 : struct fd_usage_cost_details { 60 : uint signature_cost; 61 : uint write_lock_cost; 62 : uint data_bytes_cost; 63 : uint programs_execution_cost; 64 : uint loaded_accounts_data_size_cost; 65 : ulong allocated_accounts_data_size; 66 : }; 67 : typedef struct fd_usage_cost_details fd_usage_cost_details_t; 68 : 69 : struct fd_transaction_cost { 70 : fd_usage_cost_details_t transaction; 71 : }; 72 : 73 : typedef struct fd_transaction_cost fd_transaction_cost_t; 74 : 75 : FD_PROTOTYPES_BEGIN 76 : 77 : static inline int 78 0 : fd_cost_tracker_err_to_runtime_err( int err ) { 79 0 : switch( err ) { 80 0 : case FD_COST_TRACKER_SUCCESS: 81 0 : return FD_RUNTIME_EXECUTE_SUCCESS; 82 0 : case FD_COST_TRACKER_ERROR_WOULD_EXCEED_BLOCK_MAX_LIMIT: 83 0 : return FD_RUNTIME_TXN_ERR_WOULD_EXCEED_MAX_BLOCK_COST_LIMIT; 84 0 : case FD_COST_TRACKER_ERROR_WOULD_EXCEED_ACCOUNT_MAX_LIMIT: 85 0 : return FD_RUNTIME_TXN_ERR_WOULD_EXCEED_MAX_ACCOUNT_COST_LIMIT; 86 0 : case FD_COST_TRACKER_ERROR_WOULD_EXCEED_ACCOUNT_DATA_BLOCK_LIMIT: 87 0 : return FD_RUNTIME_TXN_ERR_WOULD_EXCEED_ACCOUNT_DATA_BLOCK_LIMIT; 88 0 : case FD_COST_TRACKER_ERROR_WOULD_EXCEED_ACCOUNT_DATA_TOTAL_LIMIT: 89 0 : return FD_RUNTIME_TXN_ERR_WOULD_EXCEED_ACCOUNT_DATA_TOTAL_LIMIT; 90 0 : default: 91 0 : FD_LOG_CRIT(( "unexpected cost tracker error %d", err )); 92 0 : } 93 0 : } 94 : 95 : FD_FN_CONST ulong 96 : fd_cost_tracker_align( void ); 97 : 98 : FD_FN_CONST ulong 99 : fd_cost_tracker_footprint( void ); 100 : 101 : void * 102 : fd_cost_tracker_new( void * shmem, 103 : ulong bench_max_cost_per_block, 104 : ulong seed ); 105 : 106 : fd_cost_tracker_t * 107 : fd_cost_tracker_join( void * shct ); 108 : 109 : void 110 : fd_cost_tracker_init( fd_cost_tracker_t * cost_tracker, 111 : fd_features_t const * features, 112 : fd_slot_params_t const * slot_params, 113 : ulong slot ); 114 : 115 : /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L323-L328 */ 116 : FD_FN_PURE uint 117 : fd_cost_tracker_calculate_loaded_accounts_data_size_cost( fd_txn_out_t const * txn_out ); 118 : 119 : /* fd_cost_tracker_calculate_cost_and_add takes a transaction, 120 : calculates the cost of the transaction in terms of various block 121 : level limits and adds it to the cost tracker. If the incremental 122 : transaction fits in the block, then the cost tracking is updated and 123 : FD_COST_TRACKER_SUCCESS is returned. If the transaction does not 124 : fit then FD_COST_TRACKER_ERROR_{*} is returned depending on what 125 : limit is violated. 126 : 127 : This function assumes that the caller is responsible for managing 128 : concurrent callers. 129 : 130 : This function represents the Agave client function: 131 : `CostModel::calculate_cost_for_executed_transaction()` 132 : 133 : https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L69-L95 134 : */ 135 : 136 : void 137 : fd_cost_tracker_calculate_cost( fd_bank_t * bank, 138 : fd_txn_in_t const * txn_in, 139 : fd_txn_out_t * txn_out ); 140 : 141 : /* fd_cost_tracker_try_add_cost takes the cost as calculated by 142 : fd_cost_tracker_calculate_cost and tries to accumulate it into the 143 : cost tracker. If the cost fits, the cost is added and 144 : FD_COST_TRACKER_SUCCESS is returned. If the cost does not fit, the 145 : cost will not be updated and FD_COST_TRACKER_ERROR_* is returned 146 : depending on what limit is violated. 147 : 148 : This function is the Agave client function: 'CostTracker::try_add()' 149 : https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L163-L173 */ 150 : 151 : int 152 : fd_cost_tracker_try_add_cost( fd_cost_tracker_t * cost_tracker, 153 : fd_txn_out_t * txn_out ); 154 : 155 : FD_PROTOTYPES_END 156 : 157 : #endif /* HEADER_fd_src_flamenco_runtime_fd_cost_tracker_h */