Skip to content

Commit 7d97bc6

Browse files
fixup: replay spends when commitment broadcast was previously skipped because of funding_seen_onchain=false
1 parent 6d7b7dc commit 7d97bc6

File tree

1 file changed

+40
-7
lines changed

1 file changed

+40
-7
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,8 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
11931193
/// True once we've observed either funding transaction on-chain. Older monitors assume this is
11941194
/// `true` when absent during upgrade so holder broadcasts aren't gated unexpectedly.
11951195
funding_seen_onchain: bool,
1196+
/// Tracks whether manual-broadcasting was requested before the funding transaction appeared on-chain.
1197+
manual_broadcast_pending: bool,
11961198

11971199
latest_update_id: u64,
11981200
commitment_transaction_number_obscure_factor: u64,
@@ -1734,6 +1736,7 @@ pub(crate) fn write_chanmon_internal<Signer: EcdsaChannelSigner, W: Writer>(
17341736
(34, channel_monitor.alternative_funding_confirmed, option),
17351737
(35, channel_monitor.is_manual_broadcast, required),
17361738
(37, channel_monitor.funding_seen_onchain, required),
1739+
(39, channel_monitor.manual_broadcast_pending, required),
17371740
});
17381741

17391742
Ok(())
@@ -1911,6 +1914,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
19111914

19121915
is_manual_broadcast,
19131916
funding_seen_onchain: false,
1917+
manual_broadcast_pending: false,
19141918

19151919
latest_update_id: 0,
19161920
commitment_transaction_number_obscure_factor,
@@ -3983,6 +3987,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
39833987
// the funding transaction on-chain, do not queue any transactions.
39843988
if require_funding_seen && self.is_manual_broadcast && !self.funding_seen_onchain {
39853989
log_info!(logger, "Not broadcasting holder commitment for manual-broadcast channel before funding appears on-chain");
3990+
self.manual_broadcast_pending = true;
39863991
return;
39873992
}
39883993
let reason = ClosureReason::HolderForceClosed {
@@ -3995,6 +4000,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
39954000
claimable_outpoints, self.best_block.height, self.best_block.height, broadcaster,
39964001
conf_target, &self.destination_script, fee_estimator, logger,
39974002
);
4003+
self.manual_broadcast_pending = false;
39984004
}
39994005

40004006
fn renegotiated_funding<L: Deref>(
@@ -5275,6 +5281,15 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
52755281

52765282
let mut watch_outputs = Vec::new();
52775283
let mut claimable_outpoints = Vec::new();
5284+
5285+
if self.is_manual_broadcast && self.funding_seen_onchain && self.manual_broadcast_pending {
5286+
self.queue_latest_holder_commitment_txn_for_broadcast(
5287+
&broadcaster,
5288+
fee_estimator,
5289+
logger,
5290+
true,
5291+
);
5292+
}
52785293
'tx_iter: for tx in &txn_matched {
52795294
let txid = tx.compute_txid();
52805295
log_trace!(logger, "Transaction {} confirmed in block {}", txid , block_hash);
@@ -5489,12 +5504,16 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
54895504
}
54905505

54915506
if should_broadcast_commitment {
5492-
// Avoid broadcasting in manual-broadcast mode until funding is seen on-chain.
5493-
if !self.is_manual_broadcast || self.funding_seen_onchain {
5494-
let (mut claimables, mut outputs) =
5495-
self.generate_claimable_outpoints_and_watch_outputs(None);
5507+
// Always update holder state, but only enqueue broadcast data once funding is seen in
5508+
// manual-broadcast mode.
5509+
let (mut claimables, mut outputs) =
5510+
self.generate_claimable_outpoints_and_watch_outputs(None);
5511+
if self.is_manual_broadcast && !self.funding_seen_onchain {
5512+
self.manual_broadcast_pending = true;
5513+
} else {
54965514
claimable_outpoints.append(&mut claimables);
54975515
watch_outputs.append(&mut outputs);
5516+
self.manual_broadcast_pending = false;
54985517
}
54995518
}
55005519

@@ -5532,13 +5551,14 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
55325551
let should_broadcast = self.should_broadcast_holder_commitment_txn(logger);
55335552
if let Some(payment_hash) = should_broadcast {
55345553
let reason = ClosureReason::HTLCsTimedOut { payment_hash: Some(payment_hash) };
5554+
let (mut new_outpoints, mut new_outputs) =
5555+
self.generate_claimable_outpoints_and_watch_outputs(Some(reason));
55355556
if self.is_manual_broadcast && !self.funding_seen_onchain {
5536-
let _ = self.generate_claimable_outpoints_and_watch_outputs(Some(reason));
5557+
self.manual_broadcast_pending = true;
55375558
} else {
5538-
let (mut new_outpoints, mut new_outputs) =
5539-
self.generate_claimable_outpoints_and_watch_outputs(Some(reason));
55405559
claimable_outpoints.append(&mut new_outpoints);
55415560
watch_outputs.append(&mut new_outputs);
5561+
self.manual_broadcast_pending = false;
55425562
}
55435563
}
55445564

@@ -6495,6 +6515,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
64956515
let mut alternative_funding_confirmed = None;
64966516
let mut is_manual_broadcast = None;
64976517
let mut funding_seen_onchain = None;
6518+
let mut manual_broadcast_pending = None;
64986519
read_tlv_fields!(reader, {
64996520
(1, funding_spend_confirmed, option),
65006521
(3, htlcs_resolved_on_chain, optional_vec),
@@ -6517,6 +6538,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
65176538
(34, alternative_funding_confirmed, option),
65186539
(35, is_manual_broadcast, option),
65196540
(37, funding_seen_onchain, option),
6541+
(39, manual_broadcast_pending, option),
65206542
});
65216543
// Note that `payment_preimages_with_info` was added (and is always written) in LDK 0.1, so
65226544
// we can use it to determine if this monitor was last written by LDK 0.1 or later.
@@ -6551,6 +6573,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
65516573
let channel_parameters = channel_parameters.unwrap_or_else(|| {
65526574
onchain_tx_handler.channel_parameters().clone()
65536575
});
6576+
let manual_broadcast_pending = manual_broadcast_pending.unwrap_or(false);
65546577

65556578
// Monitors for anchor outputs channels opened in v0.0.116 suffered from a bug in which the
65566579
// wrong `counterparty_payment_script` was being tracked. Fix it now on deserialization to
@@ -6637,6 +6660,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
66376660
is_manual_broadcast: is_manual_broadcast.unwrap_or(false),
66386661
// Assume "seen" when absent to prevent gating holder broadcasts after upgrade.
66396662
funding_seen_onchain: funding_seen_onchain.unwrap_or(true),
6663+
manual_broadcast_pending,
66406664

66416665
latest_update_id,
66426666
commitment_transaction_number_obscure_factor,
@@ -7126,6 +7150,11 @@ mod tests {
71267150
let header = create_dummy_header(prev_hash, 0);
71277151
monitor.best_block_updated(&header, 10, &*broadcaster, &fee_estimator, &logger);
71287152
assert!(broadcaster.txn_broadcast().is_empty());
7153+
{
7154+
let inner = monitor.inner.lock().unwrap();
7155+
assert!(!inner.funding_seen_onchain);
7156+
assert!(inner.manual_broadcast_pending);
7157+
}
71297158

71307159
// Now confirm the funding transaction via transactions_confirmed.
71317160
let fund_block = create_dummy_block(header.block_hash(), 1, vec![funding_tx.clone()]);
@@ -7139,6 +7168,10 @@ mod tests {
71397168
&fee_estimator,
71407169
&logger,
71417170
);
7171+
{
7172+
let inner = monitor.inner.lock().unwrap();
7173+
assert!(!inner.manual_broadcast_pending);
7174+
}
71427175

71437176
// Next height update should allow broadcast.
71447177
{

0 commit comments

Comments
 (0)