Line data Source code
1 : #include "fd_sysvar_fees.h" 2 : #include "fd_sysvar.h" 3 : #include "../fd_system_ids.h" 4 : #include "../fd_runtime.h" 5 : #include "../context/fd_exec_epoch_ctx.h" 6 : 7 : static void 8 0 : write_fees( fd_exec_slot_ctx_t* slot_ctx, fd_sysvar_fees_t* fees ) { 9 0 : ulong sz = fd_sysvar_fees_size( fees ); 10 0 : uchar enc[sz]; 11 0 : fd_memset( enc, 0, sz ); 12 0 : fd_bincode_encode_ctx_t ctx; 13 0 : ctx.data = enc; 14 0 : ctx.dataend = enc + sz; 15 0 : if ( fd_sysvar_fees_encode( fees, &ctx ) ) 16 0 : FD_LOG_ERR(("fd_sysvar_fees_encode failed")); 17 : 18 0 : fd_sysvar_set( slot_ctx, fd_sysvar_owner_id.key, &fd_sysvar_fees_id, enc, sz, slot_ctx->slot_bank.slot ); 19 0 : } 20 : 21 : fd_sysvar_fees_t * 22 : fd_sysvar_fees_read( fd_sysvar_fees_t * result, 23 : fd_sysvar_cache_t const * sysvar_cache, 24 : fd_acc_mgr_t * acc_mgr, 25 0 : fd_funk_txn_t * funk_txn ) { 26 0 : fd_sysvar_fees_t const * ret = (fd_sysvar_fees_t const *)fd_sysvar_cache_fees( sysvar_cache ); 27 0 : if( FD_UNLIKELY( NULL != ret ) ) { 28 0 : fd_memcpy(result, ret, sizeof(fd_sysvar_fees_t)); 29 0 : return result; 30 0 : } 31 : 32 0 : FD_TXN_ACCOUNT_DECL( acc ); 33 0 : int err = fd_acc_mgr_view( acc_mgr, funk_txn, &fd_sysvar_fees_id, acc ); 34 0 : if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) 35 0 : return NULL; 36 : 37 0 : fd_bincode_decode_ctx_t decode = { 38 0 : .data = acc->const_data, 39 0 : .dataend = acc->const_data + acc->const_meta->dlen 40 0 : }; 41 : 42 0 : ulong total_sz = 0UL; 43 0 : err = fd_sysvar_fees_decode_footprint( &decode, &total_sz ); 44 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) { 45 0 : return NULL; 46 0 : } 47 : 48 0 : fd_sysvar_fees_decode( result, &decode ); 49 0 : return result; 50 0 : } 51 : 52 : /* 53 : https://github.com/firedancer-io/solana/blob/dab3da8e7b667d7527565bddbdbecf7ec1fb868e/sdk/program/src/fee_calculator.rs#L105-L165 54 : */ 55 : void 56 : fd_sysvar_fees_new_derived( 57 : fd_exec_slot_ctx_t * slot_ctx, 58 : fd_fee_rate_governor_t base_fee_rate_governor, 59 : ulong latest_singatures_per_slot 60 0 : ) { 61 0 : fd_fee_rate_governor_t me = { 62 0 : .target_signatures_per_slot = base_fee_rate_governor.target_signatures_per_slot, 63 0 : .target_lamports_per_signature = base_fee_rate_governor.target_lamports_per_signature, 64 0 : .max_lamports_per_signature = base_fee_rate_governor.max_lamports_per_signature, 65 0 : .min_lamports_per_signature = base_fee_rate_governor.min_lamports_per_signature, 66 0 : .burn_percent = base_fee_rate_governor.burn_percent 67 0 : }; 68 : 69 0 : ulong lamports_per_signature = 0; 70 0 : if ( me.target_signatures_per_slot > 0 ) { 71 0 : me.min_lamports_per_signature = fd_ulong_max( 1UL, (ulong)(me.target_lamports_per_signature / 2) ); 72 0 : me.max_lamports_per_signature = me.target_lamports_per_signature * 10; 73 0 : ulong desired_lamports_per_signature = fd_ulong_min( 74 0 : me.max_lamports_per_signature, 75 0 : fd_ulong_max( 76 0 : me.min_lamports_per_signature, 77 0 : me.target_lamports_per_signature 78 0 : * fd_ulong_min(latest_singatures_per_slot, (ulong)UINT_MAX) 79 0 : / me.target_signatures_per_slot 80 0 : ) 81 0 : ); 82 0 : long gap = (long)desired_lamports_per_signature - (long)slot_ctx->slot_bank.lamports_per_signature; 83 0 : if ( gap == 0 ) { 84 0 : lamports_per_signature = desired_lamports_per_signature; 85 0 : } else { 86 0 : long gap_adjust = (long)(fd_ulong_max( 1UL, (ulong)(me.target_lamports_per_signature / 20) )) 87 0 : * (gap != 0) 88 0 : * (gap > 0 ? 1 : -1); 89 0 : lamports_per_signature = fd_ulong_min( 90 0 : me.max_lamports_per_signature, 91 0 : fd_ulong_max( 92 0 : me.min_lamports_per_signature, 93 0 : (ulong)((long) slot_ctx->slot_bank.lamports_per_signature + gap_adjust) 94 0 : ) 95 0 : ); 96 0 : } 97 0 : } else { 98 0 : lamports_per_signature = base_fee_rate_governor.target_lamports_per_signature; 99 0 : me.min_lamports_per_signature = me.target_lamports_per_signature; 100 0 : me.max_lamports_per_signature = me.target_lamports_per_signature; 101 0 : } 102 : 103 0 : if( FD_UNLIKELY( slot_ctx->slot_bank.lamports_per_signature==0UL ) ) { 104 0 : slot_ctx->prev_lamports_per_signature = lamports_per_signature; 105 0 : } else { 106 0 : slot_ctx->prev_lamports_per_signature = slot_ctx->slot_bank.lamports_per_signature; 107 0 : } 108 : 109 0 : slot_ctx->slot_bank.lamports_per_signature = lamports_per_signature; 110 0 : fd_memcpy(&slot_ctx->slot_bank.fee_rate_governor, &me, sizeof(fd_fee_rate_governor_t)); 111 0 : } 112 : 113 : void 114 0 : fd_sysvar_fees_update( fd_exec_slot_ctx_t * slot_ctx ) { 115 0 : if( FD_FEATURE_ACTIVE( slot_ctx->slot_bank.slot, slot_ctx->epoch_ctx->features, disable_fees_sysvar )) 116 0 : return; 117 0 : fd_sysvar_fees_t fees; 118 0 : fd_sysvar_fees_read( &fees, 119 0 : slot_ctx->sysvar_cache, 120 0 : slot_ctx->acc_mgr, 121 0 : slot_ctx->funk_txn ); 122 : /* todo: I need to the lamports_per_signature field */ 123 0 : fees.fee_calculator.lamports_per_signature = slot_ctx->slot_bank.lamports_per_signature; 124 0 : write_fees( slot_ctx, &fees ); 125 0 : } 126 : 127 0 : void fd_sysvar_fees_init( fd_exec_slot_ctx_t * slot_ctx ) { 128 : /* Default taken from https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/fee_calculator.rs#L110 */ 129 : /* TODO: handle non-default case */ 130 0 : fd_sysvar_fees_t fees = { 131 0 : { 132 0 : .lamports_per_signature = 0, 133 0 : } 134 0 : }; 135 0 : write_fees( slot_ctx, &fees ); 136 0 : }