Skip to content

Commit 4ad2172

Browse files
committed
Move fee rate cache updating to ChainSource
1 parent 41fb41f commit 4ad2172

File tree

6 files changed

+122
-122
lines changed

6 files changed

+122
-122
lines changed

src/builder.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -590,11 +590,7 @@ fn build_with_store_internal(
590590
let esplora_client = client_builder.build_async().unwrap();
591591
let tx_broadcaster =
592592
Arc::new(TransactionBroadcaster::new(esplora_client.clone(), Arc::clone(&logger)));
593-
let fee_estimator = Arc::new(OnchainFeeEstimator::new(
594-
esplora_client,
595-
Arc::clone(&config),
596-
Arc::clone(&logger),
597-
));
593+
let fee_estimator = Arc::new(OnchainFeeEstimator::new());
598594

599595
let wallet = Arc::new(Wallet::new(
600596
bdk_wallet,
@@ -607,8 +603,11 @@ fn build_with_store_internal(
607603
let chain_source = Arc::new(ChainSource::new_esplora(
608604
server_url.clone(),
609605
Arc::clone(&wallet),
606+
Arc::clone(&fee_estimator),
607+
Arc::clone(&config),
610608
Arc::clone(&logger),
611609
));
610+
612611
(wallet, chain_source, tx_broadcaster, fee_estimator)
613612
},
614613
None => {
@@ -619,11 +618,7 @@ fn build_with_store_internal(
619618
let esplora_client = client_builder.build_async().unwrap();
620619
let tx_broadcaster =
621620
Arc::new(TransactionBroadcaster::new(esplora_client.clone(), Arc::clone(&logger)));
622-
let fee_estimator = Arc::new(OnchainFeeEstimator::new(
623-
esplora_client,
624-
Arc::clone(&config),
625-
Arc::clone(&logger),
626-
));
621+
let fee_estimator = Arc::new(OnchainFeeEstimator::new());
627622

628623
let wallet = Arc::new(Wallet::new(
629624
bdk_wallet,
@@ -636,6 +631,8 @@ fn build_with_store_internal(
636631
let chain_source = Arc::new(ChainSource::new_esplora(
637632
server_url.clone(),
638633
Arc::clone(&wallet),
634+
Arc::clone(&fee_estimator),
635+
Arc::clone(&config),
639636
Arc::clone(&logger),
640637
));
641638

@@ -1021,7 +1018,6 @@ fn build_with_store_internal(
10211018
wallet,
10221019
chain_source,
10231020
tx_broadcaster,
1024-
fee_estimator,
10251021
event_queue,
10261022
channel_manager,
10271023
chain_monitor,

src/chain/mod.rs

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@
66
// accordance with one or both of these licenses.
77

88
use crate::config::{
9-
BDK_CLIENT_CONCURRENCY, BDK_CLIENT_STOP_GAP, BDK_WALLET_SYNC_TIMEOUT_SECS,
10-
LDK_WALLET_SYNC_TIMEOUT_SECS,
9+
Config, BDK_CLIENT_CONCURRENCY, BDK_CLIENT_STOP_GAP, BDK_WALLET_SYNC_TIMEOUT_SECS,
10+
FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS, LDK_WALLET_SYNC_TIMEOUT_SECS,
1111
};
12-
use crate::logger::{log_error, log_info, FilesystemLogger, Logger};
12+
use crate::fee_estimator::{
13+
apply_post_estimation_adjustments, get_all_conf_targets, get_num_block_defaults_for_target,
14+
OnchainFeeEstimator,
15+
};
16+
use crate::logger::{log_error, log_info, log_trace, FilesystemLogger, Logger};
1317
use crate::types::Wallet;
1418
use crate::Error;
1519

@@ -21,6 +25,9 @@ use bdk_esplora::EsploraAsyncExt;
2125

2226
use esplora_client::AsyncClient as EsploraAsyncClient;
2327

28+
use bitcoin::{FeeRate, Network};
29+
30+
use std::collections::HashMap;
2431
use std::sync::{Arc, Mutex};
2532
use std::time::Duration;
2633

@@ -90,13 +97,16 @@ pub(crate) enum ChainSource {
9097
onchain_wallet_sync_status: Mutex<WalletSyncStatus>,
9198
tx_sync: Arc<EsploraSyncClient<Arc<FilesystemLogger>>>,
9299
lightning_wallet_sync_status: Mutex<WalletSyncStatus>,
100+
fee_estimator: Arc<OnchainFeeEstimator>,
101+
config: Arc<Config>,
93102
logger: Arc<FilesystemLogger>,
94103
},
95104
}
96105

97106
impl ChainSource {
98107
pub(crate) fn new_esplora(
99-
server_url: String, onchain_wallet: Arc<Wallet>, logger: Arc<FilesystemLogger>,
108+
server_url: String, onchain_wallet: Arc<Wallet>, fee_estimator: Arc<OnchainFeeEstimator>,
109+
config: Arc<Config>, logger: Arc<FilesystemLogger>,
100110
) -> Self {
101111
let mut client_builder = esplora_client::Builder::new(&server_url.clone());
102112
client_builder = client_builder.timeout(DEFAULT_ESPLORA_CLIENT_TIMEOUT_SECS);
@@ -111,6 +121,8 @@ impl ChainSource {
111121
onchain_wallet_sync_status,
112122
tx_sync,
113123
lightning_wallet_sync_status,
124+
fee_estimator,
125+
config,
114126
logger,
115127
}
116128
}
@@ -218,6 +230,74 @@ impl ChainSource {
218230
},
219231
}
220232
}
233+
234+
pub(crate) async fn update_fee_rate_estimates(&self) -> Result<(), Error> {
235+
match self {
236+
Self::Esplora { esplora_client, fee_estimator, config, logger, .. } => {
237+
let estimates = tokio::time::timeout(
238+
Duration::from_secs(FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS),
239+
esplora_client.get_fee_estimates(),
240+
)
241+
.await
242+
.map_err(|e| {
243+
log_error!(logger, "Updating fee rate estimates timed out: {}", e);
244+
Error::FeerateEstimationUpdateTimeout
245+
})?
246+
.map_err(|e| {
247+
log_error!(logger, "Failed to retrieve fee rate estimates: {}", e);
248+
Error::FeerateEstimationUpdateFailed
249+
})?;
250+
251+
if estimates.is_empty() && config.network == Network::Bitcoin {
252+
// Ensure we fail if we didn't receive any estimates.
253+
log_error!(
254+
logger,
255+
"Failed to retrieve fee rate estimates: empty fee estimates are dissallowed on Mainnet.",
256+
);
257+
return Err(Error::FeerateEstimationUpdateFailed);
258+
}
259+
260+
let confirmation_targets = get_all_conf_targets();
261+
262+
let mut new_fee_rate_cache = HashMap::with_capacity(10);
263+
for target in confirmation_targets {
264+
let num_blocks = get_num_block_defaults_for_target(target);
265+
266+
let converted_estimate_sat_vb =
267+
esplora_client::convert_fee_rate(num_blocks, estimates.clone()).map_err(
268+
|e| {
269+
log_error!(
270+
logger,
271+
"Failed to convert fee rate estimates for {:?}: {}",
272+
target,
273+
e
274+
);
275+
Error::FeerateEstimationUpdateFailed
276+
},
277+
)?;
278+
279+
let fee_rate =
280+
FeeRate::from_sat_per_kwu((converted_estimate_sat_vb * 250.0) as u64);
281+
282+
// LDK 0.0.118 introduced changes to the `ConfirmationTarget` semantics that
283+
// require some post-estimation adjustments to the fee rates, which we do here.
284+
let adjusted_fee_rate = apply_post_estimation_adjustments(target, fee_rate);
285+
286+
new_fee_rate_cache.insert(target, adjusted_fee_rate);
287+
288+
log_trace!(
289+
logger,
290+
"Fee rate estimation updated for {:?}: {} sats/kwu",
291+
target,
292+
adjusted_fee_rate.to_sat_per_kwu(),
293+
);
294+
}
295+
296+
fee_estimator.set_fee_rate_cache(new_fee_rate_cache);
297+
Ok(())
298+
},
299+
}
300+
}
221301
}
222302

223303
impl Filter for ChainSource {

src/fee_estimator.rs

Lines changed: 9 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,14 @@
55
// http://opensource.org/licenses/MIT>, at your option. You may not use this file except in
66
// accordance with one or both of these licenses.
77

8-
use crate::config::FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS;
9-
use crate::logger::{log_error, log_trace, Logger};
10-
use crate::{Config, Error};
11-
128
use lightning::chain::chaininterface::ConfirmationTarget as LdkConfirmationTarget;
139
use lightning::chain::chaininterface::FeeEstimator as LdkFeeEstimator;
1410
use lightning::chain::chaininterface::FEERATE_FLOOR_SATS_PER_KW;
1511

1612
use bitcoin::FeeRate;
17-
use esplora_client::AsyncClient as EsploraClient;
18-
19-
use bitcoin::Network;
2013

2114
use std::collections::HashMap;
22-
use std::ops::Deref;
23-
use std::sync::{Arc, RwLock};
24-
use std::time::Duration;
15+
use std::sync::RwLock;
2516

2617
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
2718
pub(crate) enum ConfirmationTarget {
@@ -43,87 +34,22 @@ impl From<LdkConfirmationTarget> for ConfirmationTarget {
4334
}
4435
}
4536

46-
pub(crate) struct OnchainFeeEstimator<L: Deref>
47-
where
48-
L::Target: Logger,
49-
{
37+
pub(crate) struct OnchainFeeEstimator {
5038
fee_rate_cache: RwLock<HashMap<ConfirmationTarget, FeeRate>>,
51-
esplora_client: EsploraClient,
52-
config: Arc<Config>,
53-
logger: L,
5439
}
5540

56-
impl<L: Deref> OnchainFeeEstimator<L>
57-
where
58-
L::Target: Logger,
59-
{
60-
pub(crate) fn new(esplora_client: EsploraClient, config: Arc<Config>, logger: L) -> Self {
41+
impl OnchainFeeEstimator {
42+
pub(crate) fn new() -> Self {
6143
let fee_rate_cache = RwLock::new(HashMap::new());
62-
Self { fee_rate_cache, esplora_client, config, logger }
44+
Self { fee_rate_cache }
6345
}
6446

65-
pub(crate) async fn update_fee_estimates(&self) -> Result<(), Error> {
66-
let estimates = tokio::time::timeout(
67-
Duration::from_secs(FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS),
68-
self.esplora_client.get_fee_estimates(),
69-
)
70-
.await
71-
.map_err(|e| {
72-
log_error!(self.logger, "Updating fee rate estimates timed out: {}", e);
73-
Error::FeerateEstimationUpdateTimeout
74-
})?
75-
.map_err(|e| {
76-
log_error!(self.logger, "Failed to retrieve fee rate estimates: {}", e);
77-
Error::FeerateEstimationUpdateFailed
78-
})?;
79-
80-
if estimates.is_empty() && self.config.network == Network::Bitcoin {
81-
// Ensure we fail if we didn't receive any estimates.
82-
log_error!(
83-
self.logger,
84-
"Failed to retrieve fee rate estimates: empty fee estimates are dissallowed on Mainnet.",
85-
);
86-
return Err(Error::FeerateEstimationUpdateFailed);
87-
}
88-
89-
let confirmation_targets = get_all_conf_targets();
90-
for target in confirmation_targets {
91-
let num_blocks = get_num_block_defaults_for_target(target);
92-
93-
let converted_estimate_sat_vb =
94-
esplora_client::convert_fee_rate(num_blocks, estimates.clone()).map_err(|e| {
95-
log_error!(
96-
self.logger,
97-
"Failed to convert fee rate estimates for {:?}: {}",
98-
target,
99-
e
100-
);
101-
Error::FeerateEstimationUpdateFailed
102-
})?;
103-
104-
let fee_rate = FeeRate::from_sat_per_kwu((converted_estimate_sat_vb * 250.0) as u64);
105-
106-
// LDK 0.0.118 introduced changes to the `ConfirmationTarget` semantics that
107-
// require some post-estimation adjustments to the fee rates, which we do here.
108-
let adjusted_fee_rate = apply_post_estimation_adjustments(target, fee_rate);
109-
110-
let mut locked_fee_rate_cache = self.fee_rate_cache.write().unwrap();
111-
locked_fee_rate_cache.insert(target, adjusted_fee_rate);
112-
log_trace!(
113-
self.logger,
114-
"Fee rate estimation updated for {:?}: {} sats/kwu",
115-
target,
116-
adjusted_fee_rate.to_sat_per_kwu(),
117-
);
118-
}
119-
Ok(())
47+
pub(crate) fn set_fee_rate_cache(&self, fee_rate_cache: HashMap<ConfirmationTarget, FeeRate>) {
48+
*self.fee_rate_cache.write().unwrap() = fee_rate_cache;
12049
}
12150
}
12251

123-
impl<L: Deref> FeeEstimator for OnchainFeeEstimator<L>
124-
where
125-
L::Target: Logger,
126-
{
52+
impl FeeEstimator for OnchainFeeEstimator {
12753
fn estimate_fee_rate(&self, confirmation_target: ConfirmationTarget) -> FeeRate {
12854
let locked_fee_rate_cache = self.fee_rate_cache.read().unwrap();
12955

@@ -140,10 +66,7 @@ where
14066
}
14167
}
14268

143-
impl<L: Deref> LdkFeeEstimator for OnchainFeeEstimator<L>
144-
where
145-
L::Target: Logger,
146-
{
69+
impl LdkFeeEstimator for OnchainFeeEstimator {
14770
fn get_est_sat_per_1000_weight(&self, confirmation_target: LdkConfirmationTarget) -> u32 {
14871
self.estimate_fee_rate(confirmation_target.into()).to_sat_per_kwu() as u32
14972
}

src/io/utils.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ use super::*;
99
use crate::config::WALLET_KEYS_SEED_LEN;
1010

1111
use crate::chain::ChainSource;
12+
use crate::fee_estimator::OnchainFeeEstimator;
1213
use crate::logger::{log_error, FilesystemLogger};
1314
use crate::peer_store::PeerStore;
1415
use crate::sweep::DeprecatedSpendableOutputInfo;
15-
use crate::types::{Broadcaster, DynStore, FeeEstimator, KeysManager, Sweeper};
16+
use crate::types::{Broadcaster, DynStore, KeysManager, Sweeper};
1617
use crate::wallet::ser::{ChangeSetDeserWrapper, ChangeSetSerWrapper};
1718
use crate::{Error, EventQueue, PaymentDetails};
1819

@@ -220,7 +221,7 @@ where
220221

221222
/// Read `OutputSweeper` state from the store.
222223
pub(crate) fn read_output_sweeper(
223-
broadcaster: Arc<Broadcaster>, fee_estimator: Arc<FeeEstimator>,
224+
broadcaster: Arc<Broadcaster>, fee_estimator: Arc<OnchainFeeEstimator>,
224225
chain_data_source: Arc<ChainSource>, keys_manager: Arc<KeysManager>, kv_store: Arc<DynStore>,
225226
logger: Arc<FilesystemLogger>,
226227
) -> Result<Sweeper, std::io::Error> {

0 commit comments

Comments
 (0)