LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_slot_params.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 67 85 78.8 %
Date: 2026-07-12 05:24:35 Functions: 7 9 77.8 %

          Line data    Source code
       1             : #include "fd_slot_params.h"
       2             : #include "fd_bank.h"
       3             : #include "../features/fd_features.h"
       4             : #include "sysvar/fd_sysvar_epoch_schedule.h"
       5             : #include "../../util/bits/fd_sat.h"
       6             : #include <stddef.h>
       7             : 
       8             : /* The reduce_slot_time feature gates take effect an epoch after they
       9             :    have been activated, because they affect the turbine shred filtering
      10             :    rules. */
      11             : static ulong
      12             : feature_effective_slot( fd_epoch_schedule_t const * epoch_schedule,
      13         672 :                         ulong                       activation_slot ) {
      14         672 :   ulong activation_epoch = fd_slot_to_epoch( epoch_schedule, activation_slot, NULL );
      15         672 :   return fd_epoch_slot0( epoch_schedule, fd_ulong_sat_add( activation_epoch, 1UL ) );
      16         672 : }
      17             : 
      18       87915 : #define FD_SLOT_TIME_GATE_CNT (4UL)
      19             : struct fd_slot_time_gate {
      20             :   ulong                    feature_off;
      21             :   fd_slot_params_t const * params;
      22             : };
      23             : 
      24             : typedef struct fd_slot_time_gate fd_slot_time_gate_t;
      25             : 
      26             : static fd_slot_time_gate_t const fd_slot_time_gates[ FD_SLOT_TIME_GATE_CNT ] = {
      27             :   { .feature_off = offsetof( fd_features_t, reduce_slot_time_to_350ms ), .params = &FD_SLOT_PARAMS_350MS },
      28             :   { .feature_off = offsetof( fd_features_t, reduce_slot_time_to_300ms ), .params = &FD_SLOT_PARAMS_300MS },
      29             :   { .feature_off = offsetof( fd_features_t, reduce_slot_time_to_250ms ), .params = &FD_SLOT_PARAMS_250MS },
      30             :   { .feature_off = offsetof( fd_features_t, reduce_slot_time_to_200ms ), .params = &FD_SLOT_PARAMS_200MS },
      31             : };
      32             : 
      33             : static ulong
      34             : fd_slot_params_feature_effective_slot( fd_features_t const *       features,
      35             :                                        fd_epoch_schedule_t const * epoch_schedule,
      36       70218 :                                        fd_slot_time_gate_t const * gate ) {
      37       70218 :   ulong activation_slot = fd_features_get_activation_slot_from_offset( features, gate->feature_off );
      38       70218 :   if( activation_slot==FD_FEATURE_DISABLED ) return ULONG_MAX;
      39         672 :   return feature_effective_slot( epoch_schedule, activation_slot );
      40       70218 : }
      41             : 
      42             : fd_slot_params_t
      43             : fd_slot_params_at_slot( fd_bank_t const * bank,
      44         372 :                         ulong             slot ) {
      45         372 :   return fd_slot_params_lookup( &bank->f.slot_params_default,
      46         372 :                                 &bank->f.features,
      47         372 :                                 &bank->f.epoch_schedule,
      48         372 :                                 slot );
      49         372 : }
      50             : 
      51             : fd_slot_params_t
      52             : fd_slot_params_lookup( fd_slot_params_t const *    default_params,
      53             :                        fd_features_t const *       features,
      54             :                        fd_epoch_schedule_t const * epoch_schedule,
      55        9021 :                        ulong                       slot ) {
      56        9021 :   fd_slot_params_t result = *default_params;
      57       45105 :   for( ulong i=0UL; i<FD_SLOT_TIME_GATE_CNT; i++ ) {
      58       36084 :     fd_slot_time_gate_t const * gate = &fd_slot_time_gates[ i ];
      59       36084 :     ulong eff                        = fd_slot_params_feature_effective_slot( features, epoch_schedule, gate );
      60       36084 :     if( gate->params->ns_per_slot <= result.ns_per_slot && eff!=ULONG_MAX && eff<=slot ) {
      61         234 :       result = *gate->params;
      62         234 :     }
      63       36084 :   }
      64        9021 :   return result;
      65        9021 : }
      66             : 
      67             : ulong
      68             : fd_slot_params_effective_slot( fd_slot_params_t const *    params,
      69             :                                fd_features_t const *       features,
      70           0 :                                fd_epoch_schedule_t const * epoch_schedule ) {
      71           0 :   for( ulong i=0UL; i<FD_SLOT_TIME_GATE_CNT; i++ ) {
      72           0 :     fd_slot_time_gate_t const * gate = &fd_slot_time_gates[ i ];
      73           0 :     if( gate->params->ns_per_slot==params->ns_per_slot )
      74           0 :       return fd_slot_params_feature_effective_slot( features, epoch_schedule, gate );
      75           0 :   }
      76           0 :   return 0UL;
      77           0 : }
      78             : 
      79             : static ulong
      80             : fd_slot_params_next_transition( fd_features_t const *       features,
      81             :                                 fd_epoch_schedule_t const * epoch_schedule,
      82             :                                 ulong                       slot,
      83        8562 :                                 ulong                       current_ns_per_slot ) {
      84        8562 :   ulong next = ULONG_MAX;
      85       42810 :   for( ulong i=0UL; i<FD_SLOT_TIME_GATE_CNT; i++ ) {
      86       34248 :     fd_slot_time_gate_t const * gate = &fd_slot_time_gates[ i ];
      87       34248 :     if( gate->params->ns_per_slot > current_ns_per_slot ) continue;
      88       34134 :     ulong eff = fd_slot_params_feature_effective_slot( features, epoch_schedule, gate );
      89       34134 :     if( eff>slot && eff<next ) next = eff;
      90       34134 :   }
      91        8562 :   return next;
      92        8562 : }
      93             : 
      94             : ulong
      95             : fd_slot_params_next_effective_slot( fd_slot_params_t const *    params,
      96             :                                     fd_features_t const *       features,
      97           0 :                                     fd_epoch_schedule_t const * epoch_schedule ) {
      98           0 :   ulong next = ULONG_MAX;
      99           0 :   for( ulong i=0UL; i<FD_SLOT_TIME_GATE_CNT; i++ ) {
     100           0 :     fd_slot_time_gate_t const * gate = &fd_slot_time_gates[ i ];
     101           0 :     if( gate->params->ns_per_slot >= params->ns_per_slot ) continue;
     102           0 :     ulong eff = fd_slot_params_feature_effective_slot( features, epoch_schedule, gate );
     103           0 :     if( eff<next ) next = eff;
     104           0 :   }
     105           0 :   return next;
     106           0 : }
     107             : 
     108             : FD_FN_PURE ulong
     109             : fd_slot_params_slot_range_duration_ns( fd_bank_t const * bank,
     110             :                                        ulong             start_slot,
     111        8373 :                                        ulong             end_slot ) {
     112        8373 :   fd_slot_params_t const *    default_params = &bank->f.slot_params_default;
     113        8373 :   fd_features_t const *       features       = &bank->f.features;
     114        8373 :   fd_epoch_schedule_t const * epoch_schedule = &bank->f.epoch_schedule;
     115        8373 :   ulong   curr_slot = start_slot;
     116        8373 :   uint128 ns        = 0;
     117       16704 :   while( curr_slot<end_slot ) {
     118        8331 :     fd_slot_params_t params    = fd_slot_params_lookup( default_params, features, epoch_schedule, curr_slot );
     119        8331 :     ulong            next      = fd_slot_params_next_transition( features, epoch_schedule, curr_slot, params.ns_per_slot );
     120        8331 :     ulong            seg_end   = next<end_slot ? next : end_slot;
     121        8331 :                      ns        = fd_uint128_sat_add( ns, fd_uint128_sat_mul( (uint128)( seg_end-curr_slot ), (uint128)params.ns_per_slot ) );
     122        8331 :                      curr_slot = seg_end;
     123        8331 :   }
     124             :   /* We saturate here because all the Agave callers do as well. In
     125             :      practice, the callers all limit the inputs such that this range
     126             :      will never overflow ULONG_MAX, but we saturate for defense in
     127             :      depth.
     128             :      https://github.com/anza-xyz/agave/blob/v4.2/runtime/src/bank.rs#L2985-L2987 */
     129        8373 :   return ns>(uint128)ULONG_MAX ? ULONG_MAX : (ulong)ns;
     130        8373 : }
     131             : 
     132             : FD_FN_PURE double
     133             : fd_slot_params_slot_range_duration_years( fd_bank_t const * bank,
     134             :                                           ulong             start_slot,
     135         213 :                                           ulong             end_slot ) {
     136         213 :   fd_slot_params_t const *    default_params = &bank->f.slot_params_default;
     137         213 :   fd_features_t const *       features       = &bank->f.features;
     138         213 :   fd_epoch_schedule_t const * epoch_schedule = &bank->f.epoch_schedule;
     139         213 :   ulong  curr_slot = start_slot;
     140         213 :   double years     = 0.0;
     141         444 :   while( curr_slot<end_slot ) {
     142         231 :     fd_slot_params_t p         = fd_slot_params_lookup( default_params, features, epoch_schedule, curr_slot );
     143         231 :     ulong            next      = fd_slot_params_next_transition( features, epoch_schedule, curr_slot, p.ns_per_slot );
     144         231 :     ulong            seg_end   = next<end_slot ? next : end_slot;
     145         231 :                      years    += (double)( seg_end-curr_slot ) / p.slots_per_year;
     146         231 :                      curr_slot = seg_end;
     147         231 :   }
     148         213 :   return years;
     149         213 : }

Generated by: LCOV version 1.14