@@ -20,6 +20,7 @@ use core::BLOCK_LIMIT_MAINNET;
2020use chainstate:: stacks:: db:: StacksEpochReceipt ;
2121use chainstate:: stacks:: events:: TransactionOrigin ;
2222
23+ use crate :: util:: db:: set_wal_mode;
2324use crate :: util:: db:: sql_pragma;
2425use crate :: util:: db:: table_exists;
2526
@@ -31,15 +32,15 @@ const SINGLETON_ROW_ID: i64 = 1;
3132const CREATE_TABLE : & ' static str = "
3233CREATE TABLE scalar_fee_estimator (
3334 estimate_key NUMBER PRIMARY KEY,
34- fast NUMBER NOT NULL,
35- medium NUMBER NOT NULL,
36- slow NUMBER NOT NULL
35+ high NUMBER NOT NULL,
36+ middle NUMBER NOT NULL,
37+ low NUMBER NOT NULL
3738)" ;
3839
3940/// This struct estimates fee rates by translating a transaction's `ExecutionCost`
4041/// into a scalar using `ExecutionCost::proportion_dot_product` and computing
4142/// the subsequent fee rate using the actual paid fee. The 5th, 50th and 95th
42- /// percentile fee rates for each block are used as the slow, medium , and fast
43+ /// percentile fee rates for each block are used as the low, middle , and high
4344/// estimates. Estimates are updated via exponential decay windowing.
4445pub struct ScalarFeeRateEstimator < M : CostMetric > {
4546 db : Connection ,
@@ -53,11 +54,16 @@ pub struct ScalarFeeRateEstimator<M: CostMetric> {
5354impl < M : CostMetric > ScalarFeeRateEstimator < M > {
5455 /// Open a fee rate estimator at the given db path. Creates if not existent.
5556 pub fn open ( p : & Path , metric : M ) -> Result < Self , SqliteError > {
56- let db = Connection :: open_with_flags ( p, rusqlite:: OpenFlags :: SQLITE_OPEN_READ_WRITE )
57- . or_else ( |e| {
57+ let db = match Connection :: open_with_flags ( p, rusqlite:: OpenFlags :: SQLITE_OPEN_READ_WRITE ) {
58+ Ok ( db) => {
59+ set_wal_mode ( & db) ?;
60+ Ok ( db)
61+ }
62+ Err ( e) => {
5863 if let SqliteError :: SqliteFailure ( ref internal, _) = e {
5964 if let rusqlite:: ErrorCode :: CannotOpen = internal. code {
6065 let mut db = Connection :: open ( p) ?;
66+ set_wal_mode ( & db) ?;
6167 let tx = tx_begin_immediate_sqlite ( & mut db) ?;
6268 Self :: instantiate_db ( & tx) ?;
6369 tx. commit ( ) ?;
@@ -68,7 +74,9 @@ impl<M: CostMetric> ScalarFeeRateEstimator<M> {
6874 } else {
6975 Err ( e)
7076 }
71- } ) ?;
77+ }
78+ } ?;
79+
7280 Ok ( Self {
7381 db,
7482 metric,
@@ -84,7 +92,6 @@ impl<M: CostMetric> ScalarFeeRateEstimator<M> {
8492
8593 fn instantiate_db ( tx : & SqlTransaction ) -> Result < ( ) , SqliteError > {
8694 if !Self :: db_already_instantiated ( tx) ? {
87- tx. pragma_update ( None , "journal_mode" , & "WAL" . to_string ( ) ) ?;
8895 tx. execute ( CREATE_TABLE , rusqlite:: NO_PARAMS ) ?;
8996 }
9097
@@ -103,18 +110,18 @@ impl<M: CostMetric> ScalarFeeRateEstimator<M> {
103110 // because of integer math, we can end up with some edge effects
104111 // when the estimate is < decay_rate_fraction.1, so just saturate
105112 // on the low end at a rate of "1"
106- next_computed. fast = if next_computed. fast >= 1f64 {
107- next_computed. fast
113+ next_computed. high = if next_computed. high >= 1f64 {
114+ next_computed. high
108115 } else {
109116 1f64
110117 } ;
111- next_computed. medium = if next_computed. medium >= 1f64 {
112- next_computed. medium
118+ next_computed. middle = if next_computed. middle >= 1f64 {
119+ next_computed. middle
113120 } else {
114121 1f64
115122 } ;
116- next_computed. slow = if next_computed. slow >= 1f64 {
117- next_computed. slow
123+ next_computed. low = if next_computed. low >= 1f64 {
124+ next_computed. low
118125 } else {
119126 1f64
120127 } ;
@@ -129,25 +136,25 @@ impl<M: CostMetric> ScalarFeeRateEstimator<M> {
129136 } ;
130137
131138 debug ! ( "Updating fee rate estimate for new block" ;
132- "new_measure_fast " => new_measure. fast ,
133- "new_measure_medium " => new_measure. medium ,
134- "new_measure_slow " => new_measure. slow ,
135- "new_estimate_fast " => next_estimate. fast ,
136- "new_estimate_medium " => next_estimate. medium ,
137- "new_estimate_slow " => next_estimate. slow ) ;
139+ "new_measure_high " => new_measure. high ,
140+ "new_measure_middle " => new_measure. middle ,
141+ "new_measure_low " => new_measure. low ,
142+ "new_estimate_high " => next_estimate. high ,
143+ "new_estimate_middle " => next_estimate. middle ,
144+ "new_estimate_low " => next_estimate. low ) ;
138145
139146 let sql = "INSERT OR REPLACE INTO scalar_fee_estimator
140- (estimate_key, fast, medium, slow ) VALUES (?, ?, ?, ?)" ;
147+ (estimate_key, high, middle, low ) VALUES (?, ?, ?, ?)" ;
141148
142149 let tx = tx_begin_immediate_sqlite ( & mut self . db ) . expect ( "SQLite failure" ) ;
143150
144151 tx. execute (
145152 sql,
146153 rusqlite:: params![
147154 SINGLETON_ROW_ID ,
148- next_estimate. fast ,
149- next_estimate. medium ,
150- next_estimate. slow ,
155+ next_estimate. high ,
156+ next_estimate. middle ,
157+ next_estimate. low ,
151158 ] ,
152159 )
153160 . expect ( "SQLite failure" ) ;
@@ -207,13 +214,13 @@ impl<M: CostMetric> FeeEstimator for ScalarFeeRateEstimator<M> {
207214 let measures_len = all_fee_rates. len ( ) ;
208215 if measures_len > 0 {
209216 // use 5th, 50th, and 95th percentiles from block
210- let fastest_index = measures_len - cmp:: max ( 1 , measures_len / 20 ) ;
217+ let highest_index = measures_len - cmp:: max ( 1 , measures_len / 20 ) ;
211218 let median_index = measures_len / 2 ;
212- let slowest_index = measures_len / 20 ;
219+ let lowest_index = measures_len / 20 ;
213220 let block_estimate = FeeRateEstimate {
214- fast : all_fee_rates[ fastest_index ] ,
215- medium : all_fee_rates[ median_index] ,
216- slow : all_fee_rates[ slowest_index ] ,
221+ high : all_fee_rates[ highest_index ] ,
222+ middle : all_fee_rates[ median_index] ,
223+ low : all_fee_rates[ lowest_index ] ,
217224 } ;
218225
219226 self . update_estimate ( block_estimate) ;
@@ -223,17 +230,17 @@ impl<M: CostMetric> FeeEstimator for ScalarFeeRateEstimator<M> {
223230 }
224231
225232 fn get_rate_estimates ( & self ) -> Result < FeeRateEstimate , EstimatorError > {
226- let sql = "SELECT fast, medium, slow FROM scalar_fee_estimator WHERE estimate_key = ?" ;
233+ let sql = "SELECT high, middle, low FROM scalar_fee_estimator WHERE estimate_key = ?" ;
227234 self . db
228235 . query_row ( sql, & [ SINGLETON_ROW_ID ] , |row| {
229- let fast : f64 = row. get ( 0 ) ?;
230- let medium : f64 = row. get ( 1 ) ?;
231- let slow : f64 = row. get ( 2 ) ?;
232- Ok ( ( fast , medium , slow ) )
236+ let high : f64 = row. get ( 0 ) ?;
237+ let middle : f64 = row. get ( 1 ) ?;
238+ let low : f64 = row. get ( 2 ) ?;
239+ Ok ( ( high , middle , low ) )
233240 } )
234241 . optional ( )
235242 . expect ( "SQLite failure" )
236- . map ( |( fast , medium , slow ) | FeeRateEstimate { fast , medium , slow } )
243+ . map ( |( high , middle , low ) | FeeRateEstimate { high , middle , low } )
237244 . ok_or_else ( || EstimatorError :: NoEstimateAvailable )
238245 }
239246}
0 commit comments