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 : }
|