From: Matt Corallo Date: Thu, 10 Nov 2022 01:01:31 +0000 (+0000) Subject: Handle `transaction_unconfirmed` as a full reorg to the tx height X-Git-Tag: v0.0.113~34^2 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=refs%2Fheads%2F2022-11-more-robust-unconfirmed;p=rust-lightning Handle `transaction_unconfirmed` as a full reorg to the tx height In `ChannelMonitor`, if we see a `transaction_unconfirmed` for a transaction we last saw in a block at height X, we shouldn't *only* remove the `onchain_events_awaiting_threshold_conf` entry for the given tx but rather for all transactions that we last saw at height >= X. This avoids any potential `onchain_events_awaiting_threshold_conf` inconsistencies due to the order in whcih users mark transactions unconfirmed (which the `chain::Confirm` docs do not currently set any requirements on). This also matches the `OnchainTxHandler` behavior, which does the same lookup. --- diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 0bfd94445..1933a3f52 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -3111,10 +3111,24 @@ impl ChannelMonitorImpl { F::Target: FeeEstimator, L::Target: Logger, { - self.onchain_events_awaiting_threshold_conf.retain(|ref entry| if entry.txid == *txid { - log_info!(logger, "Removing onchain event with txid {}", txid); - false - } else { true }); + let mut removed_height = None; + for entry in self.onchain_events_awaiting_threshold_conf.iter() { + if entry.txid == *txid { + removed_height = Some(entry.height); + break; + } + } + + if let Some(removed_height) = removed_height { + log_info!(logger, "transaction_unconfirmed of txid {} implies height {} was reorg'd out", txid, removed_height); + self.onchain_events_awaiting_threshold_conf.retain(|ref entry| if entry.height >= removed_height { + log_info!(logger, "Transaction {} reorg'd out", entry.txid); + false + } else { true }); + } + + debug_assert!(!self.onchain_events_awaiting_threshold_conf.iter().any(|ref entry| entry.txid == *txid)); + self.onchain_tx_handler.transaction_unconfirmed(txid, broadcaster, fee_estimator, logger); }