LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_slot_params.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 52 103 50.5 %
Date: 2026-11-11 12:40:43 Functions: 6 11 54.5 %

          Line data    Source code
       1             : #include "fd_slot_params.h"
       2             : #include "fd_bank.h"
       3             : #include "fd_runtime_const.h"
       4             : #include "../genesis/fd_genesis_parse.h"
       5             : #include "../features/fd_features.h"
       6             : #include "sysvar/fd_sysvar_epoch_schedule.h"
       7             : #include "../../util/bits/fd_sat.h"
       8             : #include <stddef.h>
       9             : 
      10             : /* The reduce_slot_time feature gates take effect an epoch after they
      11             :    have been activated, because they affect the turbine shred filtering
      12             :    rules. */
      13             : static ulong
      14             : feature_effective_slot( fd_epoch_schedule_t const * epoch_schedule,
      15         775 :                         ulong                       activation_slot ) {
      16         775 :   ulong activation_epoch = fd_slot_to_epoch( epoch_schedule, activation_slot, NULL );
      17         775 :   return fd_epoch_slot0( epoch_schedule, fd_ulong_sat_add( activation_epoch, 1UL ) );
      18         775 : }
      19             : 
      20        1470 : #define FD_SLOT_TIME_GATE_CNT (4UL)
      21             : struct fd_slot_time_gate {
      22             :   ulong                    feature_off;
      23             :   fd_slot_params_t const * params;
      24             : };
      25             : 
      26             : typedef struct fd_slot_time_gate fd_slot_time_gate_t;
      27             : 
      28             : static fd_slot_time_gate_t const fd_slot_time_gates[ FD_SLOT_TIME_GATE_CNT ] = {
      29             :   { .feature_off = offsetof( fd_features_t, reduce_slot_time_to_350ms ), .params = &FD_SLOT_PARAMS_350MS },
      30             :   { .feature_off = offsetof( fd_features_t, reduce_slot_time_to_300ms ), .params = &FD_SLOT_PARAMS_300MS },
      31             :   { .feature_off = offsetof( fd_features_t, reduce_slot_time_to_250ms ), .params = &FD_SLOT_PARAMS_250MS },
      32             :   { .feature_off = offsetof( fd_features_t, reduce_slot_time_to_200ms ), .params = &FD_SLOT_PARAMS_200MS },
      33             : };
      34             : 
      35             : static ulong
      36             : fd_slot_params_feature_effective_slot( fd_features_t const *       features,
      37             :                                        fd_epoch_schedule_t const * epoch_schedule,
      38        1101 :                                        fd_slot_time_gate_t const * gate ) {
      39        1101 :   ulong activation_slot = fd_features_get_activation_slot_from_offset( features, gate->feature_off );
      40        1101 :   if( activation_slot==FD_FEATURE_DISABLED ) return ULONG_MAX;
      41         775 :   return feature_effective_slot( epoch_schedule, activation_slot );
      42        1101 : }
      43             : 
      44             : fd_slot_params_t
      45           0 : fd_slot_params_from_genesis( fd_genesis_t const * genesis ) {
      46           0 :   uint128          tick_ns = (uint128)genesis->poh.tick_duration_secs*1000000000UL + (uint128)genesis->poh.tick_duration_ns;
      47           0 :   fd_slot_params_t params  = FD_SLOT_PARAMS_400MS;
      48           0 :   params.ns_per_slot          = (ulong)( tick_ns * genesis->poh.ticks_per_slot );
      49           0 :   params.ns_per_slot_adjusted = fd_ulong_sat_sub( params.ns_per_slot, FD_TARGET_SLOT_ADJUSTMENT_NS );
      50           0 :   params.slots_per_year       = SECONDS_PER_YEAR * (1000000000.0 / (double)tick_ns) / (double)genesis->poh.ticks_per_slot;
      51           0 :   params.hashes_per_tick      = genesis->poh.hashes_per_tick;
      52           0 :   return params;
      53           0 : }
      54             : 
      55             : int
      56             : fd_slot_params_any_reduction_effective( fd_features_t const *       features,
      57             :                                         fd_epoch_schedule_t const * epoch_schedule,
      58             :                                         ulong                       slot,
      59           0 :                                         ulong                       ns_per_slot ) {
      60           0 :   for( ulong i=0UL; i<FD_SLOT_TIME_GATE_CNT; i++ ) {
      61           0 :     fd_slot_time_gate_t const * gate = &fd_slot_time_gates[ i ];
      62           0 :     if( gate->params->ns_per_slot > ns_per_slot ) continue;
      63           0 :     ulong eff = fd_slot_params_feature_effective_slot( features, epoch_schedule, gate );
      64           0 :     if( eff!=ULONG_MAX && eff<=slot ) return 1;
      65           0 :   }
      66           0 :   return 0;
      67           0 : }
      68             : 
      69             : fd_slot_params_t
      70             : fd_slot_params_at_slot( fd_bank_t const * bank,
      71         190 :                         ulong             slot ) {
      72         190 :   return fd_slot_params_lookup( &bank->f.slot_params_default,
      73         190 :                                 &bank->f.features,
      74         190 :                                 &bank->f.epoch_schedule,
      75         190 :                                 slot );
      76         190 : }
      77             : 
      78             : fd_slot_params_t
      79             : fd_slot_params_lookup( fd_slot_params_t const *    default_params,
      80             :                        fd_features_t const *       features,
      81             :                        fd_epoch_schedule_t const * epoch_schedule,
      82         242 :                        ulong                       slot ) {
      83         242 :   fd_slot_params_t result = *default_params;
      84        1210 :   for( ulong i=0UL; i<FD_SLOT_TIME_GATE_CNT; i++ ) {
      85         968 :     fd_slot_time_gate_t const * gate = &fd_slot_time_gates[ i ];
      86         968 :     ulong eff                        = fd_slot_params_feature_effective_slot( features, epoch_schedule, gate );
      87         968 :     if( gate->params->ns_per_slot <= result.ns_per_slot && eff!=ULONG_MAX && eff<=slot ) {
      88         601 :       result = *gate->params;
      89         601 :     }
      90         968 :   }
      91         242 :   return result;
      92         242 : }
      93             : 
      94             : ulong
      95             : fd_slot_params_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 :   for( ulong i=0UL; i<FD_SLOT_TIME_GATE_CNT; i++ ) {
      99           0 :     fd_slot_time_gate_t const * gate = &fd_slot_time_gates[ i ];
     100           0 :     if( gate->params->ns_per_slot==params->ns_per_slot )
     101           0 :       return fd_slot_params_feature_effective_slot( features, epoch_schedule, gate );
     102           0 :   }
     103           0 :   return 0UL;
     104           0 : }
     105             : 
     106             : ulong
     107             : fd_slot_params_next_transition( fd_features_t const *       features,
     108             :                                 fd_epoch_schedule_t const * epoch_schedule,
     109             :                                 ulong                       slot,
     110          52 :                                 ulong                       current_ns_per_slot ) {
     111          52 :   ulong next = ULONG_MAX;
     112         260 :   for( ulong i=0UL; i<FD_SLOT_TIME_GATE_CNT; i++ ) {
     113         208 :     fd_slot_time_gate_t const * gate = &fd_slot_time_gates[ i ];
     114         208 :     if( gate->params->ns_per_slot > current_ns_per_slot ) continue;
     115         133 :     ulong eff = fd_slot_params_feature_effective_slot( features, epoch_schedule, gate );
     116         133 :     if( eff>slot && eff<next ) next = eff;
     117         133 :   }
     118          52 :   return next;
     119          52 : }
     120             : 
     121             : ulong
     122             : fd_slot_params_next_effective_slot( fd_slot_params_t const *    params,
     123             :                                     fd_features_t const *       features,
     124           0 :                                     fd_epoch_schedule_t const * epoch_schedule ) {
     125           0 :   ulong next = ULONG_MAX;
     126           0 :   for( ulong i=0UL; i<FD_SLOT_TIME_GATE_CNT; i++ ) {
     127           0 :     fd_slot_time_gate_t const * gate = &fd_slot_time_gates[ i ];
     128           0 :     if( gate->params->ns_per_slot >= params->ns_per_slot ) continue;
     129           0 :     ulong eff = fd_slot_params_feature_effective_slot( features, epoch_schedule, gate );
     130           0 :     if( eff<next ) next = eff;
     131           0 :   }
     132           0 :   return next;
     133           0 : }
     134             : 
     135             : FD_FN_PURE ulong
     136             : fd_slot_params_slot_range_duration_ns( fd_bank_t const * bank,
     137             :                                        ulong             start_slot,
     138           0 :                                        ulong             end_slot ) {
     139           0 :   fd_slot_params_t const *    default_params = &bank->f.slot_params_default;
     140           0 :   fd_features_t const *       features       = &bank->f.features;
     141           0 :   fd_epoch_schedule_t const * epoch_schedule = &bank->f.epoch_schedule;
     142           0 :   ulong   curr_slot = start_slot;
     143           0 :   uint128 ns        = 0;
     144           0 :   while( curr_slot<end_slot ) {
     145           0 :     fd_slot_params_t params    = fd_slot_params_lookup( default_params, features, epoch_schedule, curr_slot );
     146           0 :     ulong            next      = fd_slot_params_next_transition( features, epoch_schedule, curr_slot, params.ns_per_slot );
     147           0 :     ulong            seg_end   = next<end_slot ? next : end_slot;
     148           0 :                      ns        = fd_uint128_sat_add( ns, fd_uint128_sat_mul( (uint128)( seg_end-curr_slot ), (uint128)params.ns_per_slot ) );
     149           0 :                      curr_slot = seg_end;
     150           0 :   }
     151             :   /* We saturate here because all the Agave callers do as well. In
     152             :      practice, the callers all limit the inputs such that this range
     153             :      will never overflow ULONG_MAX, but we saturate for defense in
     154             :      depth.
     155             :      https://github.com/anza-xyz/agave/blob/v4.2/runtime/src/bank.rs#L2985-L2987 */
     156           0 :   return ns>(uint128)ULONG_MAX ? ULONG_MAX : (ulong)ns;
     157           0 : }
     158             : 
     159             : FD_FN_PURE double
     160             : fd_slot_params_slot_range_duration_years( fd_bank_t const * bank,
     161             :                                           ulong             start_slot,
     162          28 :                                           ulong             end_slot ) {
     163          28 :   fd_slot_params_t const *    default_params = &bank->f.slot_params_default;
     164          28 :   fd_features_t const *       features       = &bank->f.features;
     165          28 :   fd_epoch_schedule_t const * epoch_schedule = &bank->f.epoch_schedule;
     166          28 :   ulong  curr_slot = start_slot;
     167          28 :   double years     = 0.0;
     168          80 :   while( curr_slot<end_slot ) {
     169          52 :     fd_slot_params_t p         = fd_slot_params_lookup( default_params, features, epoch_schedule, curr_slot );
     170          52 :     ulong            next      = fd_slot_params_next_transition( features, epoch_schedule, curr_slot, p.ns_per_slot );
     171          52 :     ulong            seg_end   = next<end_slot ? next : end_slot;
     172          52 :                      years    += (double)( seg_end-curr_slot ) / p.slots_per_year;
     173          52 :                      curr_slot = seg_end;
     174          52 :   }
     175          28 :   return years;
     176          28 : }

Generated by: LCOV version 1.14