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-08-28 06:53:58 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       89835 : #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       71754 :                                        fd_slot_time_gate_t const * gate ) {
      37       71754 :   ulong activation_slot = fd_features_get_activation_slot_from_offset( features, gate->feature_off );
      38       71754 :   if( activation_slot==FD_FEATURE_DISABLED ) return ULONG_MAX;
      39         672 :   return feature_effective_slot( epoch_schedule, activation_slot );
      40       71754 : }
      41             : 
      42             : fd_slot_params_t
      43             : fd_slot_params_at_slot( fd_bank_t const * bank,
      44         564 :                         ulong             slot ) {
      45         564 :   return fd_slot_params_lookup( &bank->f.slot_params_default,
      46         564 :                                 &bank->f.features,
      47         564 :                                 &bank->f.epoch_schedule,
      48         564 :                                 slot );
      49         564 : }
      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        9309 :                        ulong                       slot ) {
      56        9309 :   fd_slot_params_t result = *default_params;
      57       46545 :   for( ulong i=0UL; i<FD_SLOT_TIME_GATE_CNT; i++ ) {
      58       37236 :     fd_slot_time_gate_t const * gate = &fd_slot_time_gates[ i ];
      59       37236 :     ulong eff                        = fd_slot_params_feature_effective_slot( features, epoch_schedule, gate );
      60       37236 :     if( gate->params->ns_per_slot <= result.ns_per_slot && eff!=ULONG_MAX && eff<=slot ) {
      61         234 :       result = *gate->params;
      62         234 :     }
      63       37236 :   }
      64        9309 :   return result;
      65        9309 : }
      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        8658 :                                 ulong                       current_ns_per_slot ) {
      84        8658 :   ulong next = ULONG_MAX;
      85       43290 :   for( ulong i=0UL; i<FD_SLOT_TIME_GATE_CNT; i++ ) {
      86       34632 :     fd_slot_time_gate_t const * gate = &fd_slot_time_gates[ i ];
      87       34632 :     if( gate->params->ns_per_slot > current_ns_per_slot ) continue;
      88       34518 :     ulong eff = fd_slot_params_feature_effective_slot( features, epoch_schedule, gate );
      89       34518 :     if( eff>slot && eff<next ) next = eff;
      90       34518 :   }
      91        8658 :   return next;
      92        8658 : }
      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        8355 :                                        ulong             end_slot ) {
     112        8355 :   fd_slot_params_t const *    default_params = &bank->f.slot_params_default;
     113        8355 :   fd_features_t const *       features       = &bank->f.features;
     114        8355 :   fd_epoch_schedule_t const * epoch_schedule = &bank->f.epoch_schedule;
     115        8355 :   ulong   curr_slot = start_slot;
     116        8355 :   uint128 ns        = 0;
     117       16692 :   while( curr_slot<end_slot ) {
     118        8337 :     fd_slot_params_t params    = fd_slot_params_lookup( default_params, features, epoch_schedule, curr_slot );
     119        8337 :     ulong            next      = fd_slot_params_next_transition( features, epoch_schedule, curr_slot, params.ns_per_slot );
     120        8337 :     ulong            seg_end   = next<end_slot ? next : end_slot;
     121        8337 :                      ns        = fd_uint128_sat_add( ns, fd_uint128_sat_mul( (uint128)( seg_end-curr_slot ), (uint128)params.ns_per_slot ) );
     122        8337 :                      curr_slot = seg_end;
     123        8337 :   }
     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        8355 :   return ns>(uint128)ULONG_MAX ? ULONG_MAX : (ulong)ns;
     130        8355 : }
     131             : 
     132             : FD_FN_PURE double
     133             : fd_slot_params_slot_range_duration_years( fd_bank_t const * bank,
     134             :                                           ulong             start_slot,
     135         303 :                                           ulong             end_slot ) {
     136         303 :   fd_slot_params_t const *    default_params = &bank->f.slot_params_default;
     137         303 :   fd_features_t const *       features       = &bank->f.features;
     138         303 :   fd_epoch_schedule_t const * epoch_schedule = &bank->f.epoch_schedule;
     139         303 :   ulong  curr_slot = start_slot;
     140         303 :   double years     = 0.0;
     141         624 :   while( curr_slot<end_slot ) {
     142         321 :     fd_slot_params_t p         = fd_slot_params_lookup( default_params, features, epoch_schedule, curr_slot );
     143         321 :     ulong            next      = fd_slot_params_next_transition( features, epoch_schedule, curr_slot, p.ns_per_slot );
     144         321 :     ulong            seg_end   = next<end_slot ? next : end_slot;
     145         321 :                      years    += (double)( seg_end-curr_slot ) / p.slots_per_year;
     146         321 :                      curr_slot = seg_end;
     147         321 :   }
     148         303 :   return years;
     149         303 : }

Generated by: LCOV version 1.14