From 71c6990ee46e0988bd399b66b376687dad6ceaca Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Fri, 23 Jan 2026 14:44:04 +0100 Subject: [PATCH 1/3] `ElectrumSyncClient`: Skip unconfirmed `get_history` entries Electrum's `blockchain.scripthash.get_history` will return the *confirmed* history for any scripthash, but will then also append any matching entries from the mempool, with respective `height` fields set to 0 or -1 (depending on whether all inputs are confirmed or not). Unfortunately we previously only included a filter for confirmed `get_history` entries in the watched output case, and forgot to add such a check also when checking for watched transactions. This would have us treat the entry as confirmed, then failing on the `get_merkle` step which of course couldn't prove block inclusion. Here we simply fix this omission and skip entries that are still unconfirmed (e.g., unconfirmed funding transactions from 0conf channels). Signed-off-by: Elias Rohrer Backport of cc1eb1686ce9ec6dd3d2043a286010bb1a759e63 --- lightning-transaction-sync/src/electrum.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lightning-transaction-sync/src/electrum.rs b/lightning-transaction-sync/src/electrum.rs index 78fca1b168f..a442ff9e119 100644 --- a/lightning-transaction-sync/src/electrum.rs +++ b/lightning-transaction-sync/src/electrum.rs @@ -336,10 +336,21 @@ where script_history.iter().filter(|h| h.tx_hash == **txid); if let Some(history) = filtered_history.next() { let prob_conf_height = history.height as u32; + if prob_conf_height <= 0 { + // Skip if it's a an unconfirmed entry. + continue; + } let confirmed_tx = self.get_confirmed_tx(tx, prob_conf_height)?; confirmed_txs.push(confirmed_tx); } - debug_assert!(filtered_history.next().is_none()); + if filtered_history.next().is_some() { + log_error!( + self.logger, + "Failed due to server returning multiple history entries for Tx {}.", + txid + ); + return Err(InternalError::Failed); + } } for (watched_output, script_history) in @@ -347,6 +358,7 @@ where { for possible_output_spend in script_history { if possible_output_spend.height <= 0 { + // Skip if it's a an unconfirmed entry. continue; } From f2a639817a69538ff239b3212962b217936251d4 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 25 Jan 2026 22:51:55 +0000 Subject: [PATCH 2/3] Update pins for new MSRV breakage --- ci/ci-tests.sh | 13 +++++++++++++ ci/ci-tx-sync-tests.sh | 3 +++ 2 files changed, 16 insertions(+) diff --git a/ci/ci-tests.sh b/ci/ci-tests.sh index 95d2c9ad449..56fc45d753c 100755 --- a/ci/ci-tests.sh +++ b/ci/ci-tests.sh @@ -17,6 +17,18 @@ function PIN_RELEASE_DEPS { # Starting with version 1.39.0, the `tokio` crate has an MSRV of rustc 1.70.0 [ "$RUSTC_MINOR_VERSION" -lt 70 ] && cargo update -p tokio --precise "1.38.1" --verbose + # Starting with version 1.0.104, the `proc-macro2` crate has an MSRV of rustc 1.68 + [ "$RUSTC_MINOR_VERSION" -lt 68 ] && cargo update -p proc-macro2 --precise "1.0.103" --verbose + + # Starting with version 1.0.146, the `serde_json` crate has an MSRV of rustc 1.68 + [ "$RUSTC_MINOR_VERSION" -lt 68 ] && cargo update -p serde_json --precise "1.0.145" --verbose + + # Starting with version 1.0.16, the `itoa` crate has an MSRV of rustc 1.68 + [ "$RUSTC_MINOR_VERSION" -lt 68 ] && cargo update -p itoa --precise "1.0.15" --verbose + + # Starting with version 1.0.21, the `ryu` crate has an MSRV of rustc 1.68 + [ "$RUSTC_MINOR_VERSION" -lt 68 ] && cargo update -p ryu --precise "1.0.20" --verbose + return 0 # Don't fail the script if our rustc is higher than the last check } @@ -62,6 +74,7 @@ pushd lightning-tests [ "$RUSTC_MINOR_VERSION" -lt 68 ] && cargo update -p syn --precise "2.0.106" --verbose [ "$RUSTC_MINOR_VERSION" -lt 68 ] && cargo update -p quote --precise "1.0.41" --verbose [ "$RUSTC_MINOR_VERSION" -lt 65 ] && cargo update -p regex --precise "1.9.6" --verbose +[ "$RUSTC_MINOR_VERSION" -lt 68 ] && cargo update -p proc-macro2 --precise "1.0.103" --verbose cargo test [ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean popd diff --git a/ci/ci-tx-sync-tests.sh b/ci/ci-tx-sync-tests.sh index 5f926a8e37b..116e2c03880 100755 --- a/ci/ci-tx-sync-tests.sh +++ b/ci/ci-tx-sync-tests.sh @@ -20,6 +20,9 @@ PIN_RELEASE_DEPS # pin the release dependencies # Starting with version 1.2.0, the `idna_adapter` crate has an MSRV of rustc 1.81.0. [ "$RUSTC_MINOR_VERSION" -lt 81 ] && cargo update -p idna_adapter --precise "1.1.0" --verbose +# Starting with version 2.12.1, the `indexmap` crate has an MSRV of rustc 1.82. +[ "$RUSTC_MINOR_VERSION" -lt 82 ] && cargo update -p indexmap --precise "2.11.4" --verbose + export RUST_BACKTRACE=1 echo -e "\n\nChecking Transaction Sync Clients with features." From f1488d9289e00655ba4569472f51979f310fd2d4 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 23 Jan 2026 22:21:47 +0000 Subject: [PATCH 3/3] Bump `lightning-transaction-sync` to 0.1.9 and add CHANGELOG entry --- CHANGELOG.md | 6 ++++++ lightning-transaction-sync/Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ee4b667635..c26ff45a644 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 0.1.9 - Jan 26, 2026 - "Electrum Confirmations" + +## Bug Fixes + * The presence of unconfirmed transactions no longer causes + `ElectrumSyncClient` to spuriously fail to sync (#4341). + # 0.1.8 - Dec 2, 2025 - "Async Update Completion" ## Bug Fixes diff --git a/lightning-transaction-sync/Cargo.toml b/lightning-transaction-sync/Cargo.toml index 8256a44ded5..fc0a389be67 100644 --- a/lightning-transaction-sync/Cargo.toml +++ b/lightning-transaction-sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lightning-transaction-sync" -version = "0.1.0" +version = "0.1.9" authors = ["Elias Rohrer"] license = "MIT OR Apache-2.0" repository = "https://github.com/lightningdevkit/rust-lightning"