Skip to content

Commit 0785f6a

Browse files
randomloginclaude
andcommitted
fix(cbf): advance sync timestamps and handle unknown block on resume
Fixes a hang in start/stop/reinit after a checkpoint-based resume where `wait_for_cbf_sync` timed out because neither sync timestamp advanced. - `sync_lightning_wallet`: when no scripts are registered, still call `update_node_metrics_timestamp` so callers waiting on a strict advance of `latest_lightning_wallet_sync_timestamp` make progress. The empty-scripts and normal paths now share a single timestamp-update site at the end of the closure. - `fee_rate_cache_from_cbf`: treat `FetchBlockError::UnknownHash` as a skip-this-cycle condition instead of an error. After a checkpoint resume, `requester.chain_tip()` can return the checkpoint hash which has no `BlockNode` in kyoto's tree yet, previously surfacing as `FeerateEstimationUpdateFailed` from `node.start()`. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent a70d6ec commit 0785f6a

1 file changed

Lines changed: 39 additions & 27 deletions

File tree

src/chain/cbf.rs

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
1414
use bdk_chain::{BlockId, ConfirmationBlockTime, TxUpdate};
1515
use bdk_wallet::Update;
1616
use bip157::chain::{BlockHeaderChanges, ChainState};
17+
use bip157::error::FetchBlockError;
1718
use bip157::{
1819
BlockHash, Builder, Client, Event, HeaderCheckpoint, Info, Node as CbfNode, Requester,
1920
SyncUpdate, TrustedPeer, Warning,
@@ -729,35 +730,34 @@ impl CbfChainSource {
729730
let scripts: Vec<ScriptBuf> = self.registered_scripts.lock().unwrap().clone();
730731
if scripts.is_empty() {
731732
log_debug!(self.logger, "No registered scripts for CBF lightning sync.");
732-
return Ok(());
733-
}
734-
735-
let timeout_fut = tokio::time::timeout(
736-
Duration::from_secs(
737-
self.sync_config.timeouts_config.lightning_wallet_sync_timeout_secs,
738-
),
739-
self.sync_lightning_wallet_op(
740-
requester,
741-
channel_manager,
742-
chain_monitor,
743-
output_sweeper,
744-
scripts,
745-
),
746-
);
733+
} else {
734+
let timeout_fut = tokio::time::timeout(
735+
Duration::from_secs(
736+
self.sync_config.timeouts_config.lightning_wallet_sync_timeout_secs,
737+
),
738+
self.sync_lightning_wallet_op(
739+
requester,
740+
channel_manager,
741+
chain_monitor,
742+
output_sweeper,
743+
scripts,
744+
),
745+
);
747746

748-
match timeout_fut.await {
749-
Ok(res) => res?,
750-
Err(e) => {
751-
log_error!(self.logger, "Sync of Lightning wallet timed out: {}", e);
752-
return Err(Error::TxSyncTimeout);
753-
},
754-
};
747+
match timeout_fut.await {
748+
Ok(res) => res?,
749+
Err(e) => {
750+
log_error!(self.logger, "Sync of Lightning wallet timed out: {}", e);
751+
return Err(Error::TxSyncTimeout);
752+
},
753+
};
755754

756-
log_debug!(
757-
self.logger,
758-
"Sync of Lightning wallet via CBF finished in {}ms.",
759-
now.elapsed().as_millis()
760-
);
755+
log_debug!(
756+
self.logger,
757+
"Sync of Lightning wallet via CBF finished in {}ms.",
758+
now.elapsed().as_millis()
759+
);
760+
}
761761

762762
update_node_metrics_timestamp(
763763
&self.node_metrics,
@@ -915,6 +915,18 @@ impl CbfChainSource {
915915
.await
916916
{
917917
Ok(Ok(indexed_block)) => indexed_block,
918+
Ok(Err(FetchBlockError::UnknownHash)) => {
919+
// Kyoto doesn't know this block yet (e.g. startup before
920+
// filter sync, or hash is at/below the resume checkpoint).
921+
// Skip this cycle and try again later.
922+
log_debug!(
923+
self.logger,
924+
"CBF node does not yet have block {} for fee estimation; \
925+
skipping until sync progresses.",
926+
current_hash,
927+
);
928+
return Ok(None);
929+
},
918930
Ok(Err(e)) => {
919931
log_error!(
920932
self.logger,

0 commit comments

Comments
 (0)