@@ -1863,15 +1863,17 @@ mod bucketed_history {
1863
1863
}
1864
1864
1865
1865
fn recalculate_valid_point_count ( & mut self ) {
1866
- let mut total_valid_points_tracked = 0 ;
1866
+ let mut total_valid_points_tracked = 0u128 ;
1867
1867
for ( min_idx, min_bucket) in self . min_liquidity_offset_history . buckets . iter ( ) . enumerate ( ) {
1868
1868
for max_bucket in self . max_liquidity_offset_history . buckets . iter ( ) . take ( 32 - min_idx) {
1869
1869
// In testing, raising the weights of buckets to a high power led to better
1870
1870
// scoring results. Thus, we raise the bucket weights to the 4th power here (by
1871
- // squaring the result of multiplying the weights).
1871
+ // squaring the result of multiplying the weights). This results in
1872
+ // bucket_weight having at max 64 bits, which means we have to do our summation
1873
+ // in 128-bit math.
1872
1874
let mut bucket_weight = ( * min_bucket as u64 ) * ( * max_bucket as u64 ) ;
1873
1875
bucket_weight *= bucket_weight;
1874
- total_valid_points_tracked += bucket_weight;
1876
+ total_valid_points_tracked += bucket_weight as u128 ;
1875
1877
}
1876
1878
}
1877
1879
self . total_valid_points_tracked = total_valid_points_tracked as f64 ;
@@ -1957,12 +1959,12 @@ mod bucketed_history {
1957
1959
1958
1960
let total_valid_points_tracked = self . tracker . total_valid_points_tracked ;
1959
1961
#[ cfg( debug_assertions) ] {
1960
- let mut actual_valid_points_tracked = 0 ;
1962
+ let mut actual_valid_points_tracked = 0u128 ;
1961
1963
for ( min_idx, min_bucket) in min_liquidity_offset_history_buckets. iter ( ) . enumerate ( ) {
1962
1964
for max_bucket in max_liquidity_offset_history_buckets. iter ( ) . take ( 32 - min_idx) {
1963
1965
let mut bucket_weight = ( * min_bucket as u64 ) * ( * max_bucket as u64 ) ;
1964
1966
bucket_weight *= bucket_weight;
1965
- actual_valid_points_tracked += bucket_weight;
1967
+ actual_valid_points_tracked += bucket_weight as u128 ;
1966
1968
}
1967
1969
}
1968
1970
assert_eq ! ( total_valid_points_tracked, actual_valid_points_tracked as f64 ) ;
@@ -1989,7 +1991,7 @@ mod bucketed_history {
1989
1991
// max-bucket with at least BUCKET_FIXED_POINT_ONE.
1990
1992
let mut highest_max_bucket_with_points = 0 ;
1991
1993
let mut highest_max_bucket_with_full_points = None ;
1992
- let mut total_weight = 0 ;
1994
+ let mut total_weight = 0u128 ;
1993
1995
for ( max_idx, max_bucket) in max_liquidity_offset_history_buckets. iter ( ) . enumerate ( ) {
1994
1996
if * max_bucket >= BUCKET_FIXED_POINT_ONE {
1995
1997
highest_max_bucket_with_full_points = Some ( cmp:: max ( highest_max_bucket_with_full_points. unwrap_or ( 0 ) , max_idx) ) ;
@@ -2002,7 +2004,7 @@ mod bucketed_history {
2002
2004
// squaring the result of multiplying the weights), matching the logic in
2003
2005
// `recalculate_valid_point_count`.
2004
2006
let bucket_weight = ( * max_bucket as u64 ) * ( min_liquidity_offset_history_buckets[ 0 ] as u64 ) ;
2005
- total_weight += bucket_weight * bucket_weight;
2007
+ total_weight += ( bucket_weight * bucket_weight) as u128 ;
2006
2008
}
2007
2009
debug_assert ! ( total_weight as f64 <= total_valid_points_tracked) ;
2008
2010
// Use the highest max-bucket with at least BUCKET_FIXED_POINT_ONE, but if none is
@@ -2055,7 +2057,7 @@ mod bucketed_history {
2055
2057
2056
2058
#[ cfg( test) ]
2057
2059
mod tests {
2058
- use super :: HistoricalBucketRangeTracker ;
2060
+ use super :: { HistoricalBucketRangeTracker , HistoricalLiquidityTracker , ProbabilisticScoringFeeParameters } ;
2059
2061
2060
2062
#[ test]
2061
2063
fn historical_liquidity_bucket_decay ( ) {
@@ -2078,6 +2080,23 @@ mod bucketed_history {
2078
2080
]
2079
2081
) ;
2080
2082
}
2083
+
2084
+ #[ test]
2085
+ fn historical_heavy_buckets_operations ( ) {
2086
+ // Checks that we don't hit overflows when working with tons of data (even an
2087
+ // impossible-to-reach amount of data).
2088
+ let mut tracker = HistoricalLiquidityTracker :: new ( ) ;
2089
+ tracker. min_liquidity_offset_history . buckets = [ 0xffff ; 32 ] ;
2090
+ tracker. max_liquidity_offset_history . buckets = [ 0xffff ; 32 ] ;
2091
+ tracker. recalculate_valid_point_count ( ) ;
2092
+
2093
+ let mut directed = tracker. as_directed_mut ( true ) ;
2094
+ let default_params = ProbabilisticScoringFeeParameters :: default ( ) ;
2095
+ directed. calculate_success_probability_times_billion ( & default_params, 42 , 1000 ) ;
2096
+ directed. track_datapoint ( 42 , 52 , 1000 ) ;
2097
+
2098
+ tracker. decay_buckets ( 1.0 ) ;
2099
+ }
2081
2100
}
2082
2101
}
2083
2102
use bucketed_history:: { LegacyHistoricalBucketRangeTracker , HistoricalBucketRangeTracker , DirectedHistoricalLiquidityTracker , HistoricalLiquidityTracker } ;
0 commit comments