Skip to content

Commit dd002d6

Browse files
fixup: replay spends when commitment broadcast was previously skipped because of funding_seen_onchain=false
1 parent f507f5b commit dd002d6

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
@@ -1175,6 +1175,8 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
11751175
/// True once we've observed either funding transaction on-chain. Older monitors assume this is
11761176
/// `true` when absent during upgrade so holder broadcasts aren't gated unexpectedly.
11771177
funding_seen_onchain: bool,
1178+
/// Tracks whether manual-broadcasting was requested before the funding transaction appeared on-chain.
1179+
manual_broadcast_pending: bool,
11781180

11791181
latest_update_id: u64,
11801182
commitment_transaction_number_obscure_factor: u64,
@@ -1707,6 +1709,7 @@ pub(crate) fn write_chanmon_internal<Signer: EcdsaChannelSigner, W: Writer>(
17071709
(34, channel_monitor.alternative_funding_confirmed, option),
17081710
(35, channel_monitor.is_manual_broadcast, required),
17091711
(37, channel_monitor.funding_seen_onchain, required),
1712+
(39, channel_monitor.manual_broadcast_pending, required),
17101713
});
17111714

17121715
Ok(())
@@ -1884,6 +1887,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
18841887

18851888
is_manual_broadcast,
18861889
funding_seen_onchain: false,
1890+
manual_broadcast_pending: false,
18871891

18881892
latest_update_id: 0,
18891893
commitment_transaction_number_obscure_factor,
@@ -4011,6 +4015,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
40114015
// the funding transaction on-chain, do not queue any transactions.
40124016
if require_funding_seen && self.is_manual_broadcast && !self.funding_seen_onchain {
40134017
log_info!(logger, "Not broadcasting holder commitment for manual-broadcast channel before funding appears on-chain");
4018+
self.manual_broadcast_pending = true;
40144019
return;
40154020
}
40164021
let reason = ClosureReason::HolderForceClosed {
@@ -4023,6 +4028,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
40234028
claimable_outpoints, self.best_block.height, self.best_block.height, broadcaster,
40244029
conf_target, &self.destination_script, fee_estimator, logger,
40254030
);
4031+
self.manual_broadcast_pending = false;
40264032
}
40274033

40284034
fn renegotiated_funding<L: Deref>(
@@ -5274,6 +5280,15 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
52745280

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

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

@@ -5531,13 +5550,14 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
55315550
let should_broadcast = self.should_broadcast_holder_commitment_txn(logger);
55325551
if let Some(payment_hash) = should_broadcast {
55335552
let reason = ClosureReason::HTLCsTimedOut { payment_hash: Some(payment_hash) };
5553+
let (mut new_outpoints, mut new_outputs) =
5554+
self.generate_claimable_outpoints_and_watch_outputs(Some(reason));
55345555
if self.is_manual_broadcast && !self.funding_seen_onchain {
5535-
let _ = self.generate_claimable_outpoints_and_watch_outputs(Some(reason));
5556+
self.manual_broadcast_pending = true;
55365557
} else {
5537-
let (mut new_outpoints, mut new_outputs) =
5538-
self.generate_claimable_outpoints_and_watch_outputs(Some(reason));
55395558
claimable_outpoints.append(&mut new_outpoints);
55405559
watch_outputs.append(&mut new_outputs);
5560+
self.manual_broadcast_pending = false;
55415561
}
55425562
}
55435563

@@ -6493,6 +6513,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
64936513
let mut alternative_funding_confirmed = None;
64946514
let mut is_manual_broadcast = None;
64956515
let mut funding_seen_onchain = None;
6516+
let mut manual_broadcast_pending = None;
64966517
read_tlv_fields!(reader, {
64976518
(1, funding_spend_confirmed, option),
64986519
(3, htlcs_resolved_on_chain, optional_vec),
@@ -6514,6 +6535,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
65146535
(34, alternative_funding_confirmed, option),
65156536
(35, is_manual_broadcast, option),
65166537
(37, funding_seen_onchain, option),
6538+
(39, manual_broadcast_pending, option),
65176539
});
65186540
// Note that `payment_preimages_with_info` was added (and is always written) in LDK 0.1, so
65196541
// we can use it to determine if this monitor was last written by LDK 0.1 or later.
@@ -6548,6 +6570,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
65486570
let channel_parameters = channel_parameters.unwrap_or_else(|| {
65496571
onchain_tx_handler.channel_parameters().clone()
65506572
});
6573+
let manual_broadcast_pending = manual_broadcast_pending.unwrap_or(false);
65516574

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

66386662
latest_update_id,
66396663
commitment_transaction_number_obscure_factor,
@@ -7122,6 +7146,11 @@ mod tests {
71227146
let header = create_dummy_header(prev_hash, 0);
71237147
monitor.best_block_updated(&header, 10, &*broadcaster, &fee_estimator, &logger);
71247148
assert!(broadcaster.txn_broadcast().is_empty());
7149+
{
7150+
let inner = monitor.inner.lock().unwrap();
7151+
assert!(!inner.funding_seen_onchain);
7152+
assert!(inner.manual_broadcast_pending);
7153+
}
71257154

71267155
// Now confirm the funding transaction via transactions_confirmed.
71277156
let fund_block = create_dummy_block(header.block_hash(), 1, vec![funding_tx.clone()]);
@@ -7135,6 +7164,10 @@ mod tests {
71357164
&fee_estimator,
71367165
&logger,
71377166
);
7167+
{
7168+
let inner = monitor.inner.lock().unwrap();
7169+
assert!(!inner.manual_broadcast_pending);
7170+
}
71387171

71397172
// Next height update should allow broadcast.
71407173
{

0 commit comments

Comments
 (0)