Skip to content

Commit a522d28

Browse files
committed
Enforce successful initial fee update
So far we'd immediately start background syncing wallets and the fee cache upon `start()` which would work fine, except when these initial syncs failed, in which case we'd use our fallback fee. This might lead to being disconnected from peers as our fallback values are likely out of current fee ranges. To mitigate this we here simply enforce that an initial fee rate update in `start()` is successful. Additionally, we make the fee rate cache update interval configurable.
1 parent edb8633 commit a522d28

File tree

4 files changed

+53
-9
lines changed

4 files changed

+53
-9
lines changed

bindings/ldk_node.udl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ dictionary Config {
88
u32 default_cltv_expiry_delta;
99
u64 onchain_wallet_sync_interval_secs;
1010
u64 wallet_sync_interval_secs;
11+
u64 fee_rate_cache_update_interval_secs;
1112
LogLevel log_level;
1213
};
1314

src/lib.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ const DEFAULT_LISTENING_ADDR: &str = "0.0.0.0:9735";
175175
const DEFAULT_CLTV_EXPIRY_DELTA: u32 = 144;
176176
const DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS: u64 = 60;
177177
const DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS: u64 = 20;
178+
const DEFAULT_FEE_RATE_CACHE_UPDATE_INTERVAL_SECS: u64 = 60 * 60;
178179
const DEFAULT_LOG_LEVEL: LogLevel = LogLevel::Debug;
179180

180181
// The 'stop gap' parameter used by BDK's wallet sync. This seems to configure the threshold
@@ -218,6 +219,7 @@ const WALLET_KEYS_SEED_LEN: usize = 64;
218219
/// | `default_cltv_expiry_delta` | 144 |
219220
/// | `onchain_wallet_sync_interval_secs` | 60 |
220221
/// | `wallet_sync_interval_secs` | 20 |
222+
/// | `fee_rate_cache_update_interval_secs` | 3600 |
221223
/// | `log_level` | `Debug` |
222224
///
223225
pub struct Config {
@@ -237,6 +239,10 @@ pub struct Config {
237239
///
238240
/// **Note:** A minimum of 10 seconds is always enforced.
239241
pub wallet_sync_interval_secs: u64,
242+
/// The time in-between background update attempts to our fee rate cache, in seconds.
243+
///
244+
/// **Note:** A minimum of 10 seconds is always enforced.
245+
pub fee_rate_cache_update_interval_secs: u64,
240246
/// The level at which we log messages.
241247
///
242248
/// Any messages below this level will be excluded from the logs.
@@ -252,6 +258,7 @@ impl Default for Config {
252258
default_cltv_expiry_delta: DEFAULT_CLTV_EXPIRY_DELTA,
253259
onchain_wallet_sync_interval_secs: DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS,
254260
wallet_sync_interval_secs: DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS,
261+
fee_rate_cache_update_interval_secs: DEFAULT_FEE_RATE_CACHE_UPDATE_INTERVAL_SECS,
255262
log_level: DEFAULT_LOG_LEVEL,
256263
}
257264
}
@@ -785,12 +792,35 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
785792

786793
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();
787794

795+
// Block to ensure we update our fee rate cache once on startup
796+
let wallet = Arc::clone(&self.wallet);
797+
let sync_logger = Arc::clone(&self.logger);
798+
runtime.block_on(async move {
799+
let now = Instant::now();
800+
match wallet.update_fee_estimates().await {
801+
Ok(()) => {
802+
log_info!(
803+
sync_logger,
804+
"Initial fee rate cache update finished in {}ms.",
805+
now.elapsed().as_millis()
806+
);
807+
Ok(())
808+
}
809+
Err(e) => {
810+
log_error!(sync_logger, "Initial fee rate cache update failed: {}", e,);
811+
Err(e)
812+
}
813+
}
814+
})?;
815+
788816
// Setup wallet sync
789817
let wallet = Arc::clone(&self.wallet);
790818
let sync_logger = Arc::clone(&self.logger);
791819
let mut stop_sync = self.stop_receiver.clone();
792820
let onchain_wallet_sync_interval_secs =
793821
self.config.onchain_wallet_sync_interval_secs.max(WALLET_SYNC_INTERVAL_MINIMUM_SECS);
822+
let fee_rate_cache_update_interval_secs =
823+
self.config.fee_rate_cache_update_interval_secs.max(WALLET_SYNC_INTERVAL_MINIMUM_SECS);
794824
std::thread::spawn(move || {
795825
tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(
796826
async move {
@@ -799,6 +829,11 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
799829
);
800830
onchain_wallet_sync_interval
801831
.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
832+
let mut fee_rate_update_interval = tokio::time::interval(Duration::from_secs(
833+
fee_rate_cache_update_interval_secs,
834+
));
835+
// We just blocked on updating, so skip the first tick.
836+
fee_rate_update_interval.reset();
802837
loop {
803838
let now = Instant::now();
804839
tokio::select! {
@@ -821,6 +856,22 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
821856
}
822857
}
823858
}
859+
_ = fee_rate_update_interval.tick() => {
860+
match wallet.update_fee_estimates().await {
861+
Ok(()) => log_trace!(
862+
sync_logger,
863+
"Background update of fee rate cache finished in {}ms.",
864+
now.elapsed().as_millis()
865+
),
866+
Err(err) => {
867+
log_error!(
868+
sync_logger,
869+
"Background update of fee rate cache failed: {}",
870+
err
871+
)
872+
}
873+
}
874+
}
824875
}
825876
}
826877
},

src/test/functional_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ fn onchain_spend_receive() {
399399

400400
#[test]
401401
fn sign_verify_msg() {
402-
let (_, electrsd) = setup_bitcoind_and_electrsd();
402+
let (_bitcoind, electrsd) = setup_bitcoind_and_electrsd();
403403
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
404404
let config = random_config();
405405
let builder = Builder::from_config(config.clone());

src/wallet.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,6 @@ where
7373
}
7474
};
7575

76-
match self.update_fee_estimates().await {
77-
Ok(()) => (),
78-
Err(e) => {
79-
log_error!(self.logger, "Fee estimation error: {}", e);
80-
return Err(e);
81-
}
82-
}
83-
8476
let sync_options = SyncOptions { progress: None };
8577
let wallet_lock = self.inner.lock().unwrap();
8678
let res = match wallet_lock.sync(&self.blockchain, sync_options).await {

0 commit comments

Comments
 (0)