Skip to content

Commit 987506a

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 a24f65c commit 987506a

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
@@ -215,6 +216,7 @@ const WALLET_KEYS_SEED_LEN: usize = 64;
215216
/// | `default_cltv_expiry_delta` | 144 |
216217
/// | `onchain_wallet_sync_interval_secs` | 60 |
217218
/// | `wallet_sync_interval_secs` | 20 |
219+
/// | `fee_rate_cache_update_interval_secs` | 3600 |
218220
/// | `log_level` | `Debug` |
219221
///
220222
pub struct Config {
@@ -234,6 +236,10 @@ pub struct Config {
234236
///
235237
/// **Note:** A minimum of 10 seconds is always enforced.
236238
pub wallet_sync_interval_secs: u64,
239+
/// The time in-between background update attempts to our fee rate cache, in seconds.
240+
///
241+
/// **Note:** A minimum of 10 seconds is always enforced.
242+
pub fee_rate_cache_update_interval_secs: u64,
237243
/// The level at which we log messages.
238244
///
239245
/// Any messages below this level will be excluded from the logs.
@@ -249,6 +255,7 @@ impl Default for Config {
249255
default_cltv_expiry_delta: DEFAULT_CLTV_EXPIRY_DELTA,
250256
onchain_wallet_sync_interval_secs: DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS,
251257
wallet_sync_interval_secs: DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS,
258+
fee_rate_cache_update_interval_secs: DEFAULT_FEE_RATE_CACHE_UPDATE_INTERVAL_SECS,
252259
log_level: DEFAULT_LOG_LEVEL,
253260
}
254261
}
@@ -782,12 +789,35 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
782789

783790
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();
784791

792+
// Block to ensure we update our fee rate cache once on startup
793+
let wallet = Arc::clone(&self.wallet);
794+
let sync_logger = Arc::clone(&self.logger);
795+
runtime.block_on(async move {
796+
let now = Instant::now();
797+
match wallet.update_fee_estimates().await {
798+
Ok(()) => {
799+
log_info!(
800+
sync_logger,
801+
"Initial fee rate cache update finished in {}ms.",
802+
now.elapsed().as_millis()
803+
);
804+
Ok(())
805+
}
806+
Err(e) => {
807+
log_error!(sync_logger, "Initial fee rate cache update failed: {}", e,);
808+
Err(e)
809+
}
810+
}
811+
})?;
812+
785813
// Setup wallet sync
786814
let wallet = Arc::clone(&self.wallet);
787815
let sync_logger = Arc::clone(&self.logger);
788816
let mut stop_sync = self.stop_receiver.clone();
789817
let onchain_wallet_sync_interval_secs =
790818
self.config.onchain_wallet_sync_interval_secs.max(10);
819+
let fee_rate_cache_update_interval_secs =
820+
self.config.fee_rate_cache_update_interval_secs.max(10);
791821
std::thread::spawn(move || {
792822
tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(
793823
async move {
@@ -796,6 +826,11 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
796826
);
797827
onchain_wallet_sync_interval
798828
.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
829+
let mut fee_rate_update_interval = tokio::time::interval(Duration::from_secs(
830+
fee_rate_cache_update_interval_secs,
831+
));
832+
// We just blocked on updating, so skip the first tick.
833+
fee_rate_update_interval.reset();
799834
loop {
800835
let now = Instant::now();
801836
tokio::select! {
@@ -818,6 +853,22 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
818853
}
819854
}
820855
}
856+
_ = fee_rate_update_interval.tick() => {
857+
match wallet.update_fee_estimates().await {
858+
Ok(()) => log_trace!(
859+
sync_logger,
860+
"Background update of fee rate cache finished in {}ms.",
861+
now.elapsed().as_millis()
862+
),
863+
Err(err) => {
864+
log_error!(
865+
sync_logger,
866+
"Background update of fee rate cache failed: {}",
867+
err
868+
)
869+
}
870+
}
871+
}
821872
}
822873
}
823874
},

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)