Skip to content

Commit 6958478

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 c68aaac commit 6958478

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
@@ -174,6 +174,7 @@ const DEFAULT_LISTENING_ADDR: &str = "0.0.0.0:9735";
174174
const DEFAULT_CLTV_EXPIRY_DELTA: u32 = 144;
175175
const DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS: u64 = 60;
176176
const DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS: u64 = 20;
177+
const DEFAULT_FEE_RATE_CACHE_UPDATE_INTERVAL_SECS: u64 = 60 * 60;
177178
const DEFAULT_LOG_LEVEL: LogLevel = LogLevel::Debug;
178179

179180
// The 'stop gap' parameter used by BDK's wallet sync. This seems to configure the threshold
@@ -217,6 +218,7 @@ const WALLET_KEYS_SEED_LEN: usize = 64;
217218
/// | `default_cltv_expiry_delta` | 144 |
218219
/// | `onchain_wallet_sync_interval_secs` | 60 |
219220
/// | `wallet_sync_interval_secs` | 20 |
221+
/// | `fee_rate_cache_update_interval_secs` | 3600 |
220222
/// | `log_level` | `Debug` |
221223
///
222224
pub struct Config {
@@ -236,6 +238,10 @@ pub struct Config {
236238
///
237239
/// **Note:** A minimum of 10 seconds is always enforced.
238240
pub wallet_sync_interval_secs: u64,
241+
/// The time in-between background update attempts to our fee rate cache, in seconds.
242+
///
243+
/// **Note:** A minimum of 10 seconds is always enforced.
244+
pub fee_rate_cache_update_interval_secs: u64,
239245
/// The level at which we log messages.
240246
///
241247
/// Any messages below this level will be excluded from the logs.
@@ -251,6 +257,7 @@ impl Default for Config {
251257
default_cltv_expiry_delta: DEFAULT_CLTV_EXPIRY_DELTA,
252258
onchain_wallet_sync_interval_secs: DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS,
253259
wallet_sync_interval_secs: DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS,
260+
fee_rate_cache_update_interval_secs: DEFAULT_FEE_RATE_CACHE_UPDATE_INTERVAL_SECS,
254261
log_level: DEFAULT_LOG_LEVEL,
255262
}
256263
}
@@ -784,12 +791,35 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
784791

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

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

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)