Skip to content

Commit f8a955c

Browse files
committed
Defer monitor update completions after funding spend
When no_further_updates_allowed() is true and the persister returns Completed, ChainMonitor now overrides the return to InProgress and pushes a MonitorEvent::Completed directly into pending_monitor_events. In release_pending_monitor_events, these deferred completions are appended after per-monitor events, so ChannelManager sees the force-close MonitorEvents before the completion. This eliminates phantom InProgress entries that would never complete: previously, a rejected pre-close update (e.g. commitment_signed arriving after funding spend) returned InProgress with no completion path, blocking MonitorUpdateCompletionActions (PaymentClaimed, PaymentForwarded) indefinitely. A subsequent post-close update returning Completed would then violate the in-order completion invariant. AI tools were used in preparing this commit.
1 parent 1d3704d commit f8a955c

File tree

2 files changed

+144
-45
lines changed

2 files changed

+144
-45
lines changed

lightning/src/chain/chainmonitor.rs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,7 +1250,41 @@ where
12501250
}
12511251
}
12521252

1253-
if update_res.is_err() {
1253+
debug_assert!(
1254+
update_res.is_ok() || monitor.no_further_updates_allowed(),
1255+
"update_monitor returned Err but channel is not post-close",
1256+
);
1257+
1258+
// We also check update_res.is_err() as a defensive measure: an
1259+
// error should only occur on a post-close monitor (validated by
1260+
// the debug_assert above), but we defer here regardless to avoid
1261+
// returning Completed for a failed update.
1262+
if (update_res.is_err() || monitor.no_further_updates_allowed())
1263+
&& persist_res == ChannelMonitorUpdateStatus::Completed
1264+
{
1265+
// The channel is post-close (funding spend seen, lockdown, or
1266+
// holder tx signed). Return InProgress so ChannelManager freezes
1267+
// the channel until the force-close MonitorEvents are processed.
1268+
// Push a Completed event into pending_monitor_events so it gets
1269+
// picked up after the per-monitor events in the next
1270+
// release_pending_monitor_events call.
1271+
let funding_txo = monitor.get_funding_txo();
1272+
let channel_id = monitor.channel_id();
1273+
self.pending_monitor_events.lock().unwrap().push((
1274+
funding_txo,
1275+
channel_id,
1276+
vec![MonitorEvent::Completed {
1277+
funding_txo,
1278+
channel_id,
1279+
monitor_update_id: monitor.get_latest_update_id(),
1280+
}],
1281+
monitor.get_counterparty_node_id(),
1282+
));
1283+
log_debug!(
1284+
logger,
1285+
"Deferring completion of ChannelMonitorUpdate id {:?} (channel is post-close)",
1286+
update_id,
1287+
);
12541288
ChannelMonitorUpdateStatus::InProgress
12551289
} else {
12561290
persist_res
@@ -1614,8 +1648,9 @@ where
16141648
for (channel_id, update_id) in self.persister.get_and_clear_completed_updates() {
16151649
let _ = self.channel_monitor_updated(channel_id, update_id);
16161650
}
1617-
let mut pending_monitor_events = self.pending_monitor_events.lock().unwrap().split_off(0);
1618-
for monitor_state in self.monitors.read().unwrap().values() {
1651+
let monitors = self.monitors.read().unwrap();
1652+
let mut pending_monitor_events = Vec::new();
1653+
for monitor_state in monitors.values() {
16191654
let monitor_events = monitor_state.monitor.get_and_clear_pending_monitor_events();
16201655
if monitor_events.len() > 0 {
16211656
let monitor_funding_txo = monitor_state.monitor.get_funding_txo();
@@ -1629,6 +1664,10 @@ where
16291664
));
16301665
}
16311666
}
1667+
// Drain pending_monitor_events (which includes deferred post-close
1668+
// completions) after per-monitor events so that force-close
1669+
// MonitorEvents are processed by ChannelManager first.
1670+
pending_monitor_events.extend(self.pending_monitor_events.lock().unwrap().split_off(0));
16321671
pending_monitor_events
16331672
}
16341673
}

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 102 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3905,11 +3905,28 @@ fn do_test_durable_preimages_on_closed_channel(
39053905
}
39063906
if !close_chans_before_reload {
39073907
check_closed_broadcast(&nodes[1], 1, false);
3908-
let reason = ClosureReason::CommitmentTxConfirmed;
3909-
check_closed_event(&nodes[1], 1, reason, &[node_a_id], 100000);
3908+
// When hold=false, get_and_clear_pending_events also triggers
3909+
// process_background_events (replaying the preimage and force-close updates)
3910+
// and resolves the deferred completions, firing PaymentForwarded alongside
3911+
// ChannelClosed. When hold=true, only ChannelClosed fires.
3912+
let evs = nodes[1].node.get_and_clear_pending_events();
3913+
let expected = if hold_post_reload_mon_update { 1 } else { 2 };
3914+
assert_eq!(evs.len(), expected, "{:?}", evs);
3915+
assert!(evs.iter().any(|e| matches!(
3916+
e,
3917+
Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. }
3918+
)));
3919+
if !hold_post_reload_mon_update {
3920+
assert!(evs.iter().any(|e| matches!(e, Event::PaymentForwarded { .. })));
3921+
check_added_monitors(&nodes[1], mons_added);
3922+
}
39103923
}
39113924
nodes[1].node.timer_tick_occurred();
3912-
check_added_monitors(&nodes[1], mons_added);
3925+
// For !close_chans_before_reload && !hold, background events were already replayed
3926+
// during get_and_clear_pending_events above, so timer_tick adds no monitors.
3927+
let expected_mons =
3928+
if !close_chans_before_reload && !hold_post_reload_mon_update { 0 } else { mons_added };
3929+
check_added_monitors(&nodes[1], expected_mons);
39133930

39143931
// Finally, check that B created a payment preimage transaction and close out the payment.
39153932
let bs_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
@@ -3924,44 +3941,61 @@ fn do_test_durable_preimages_on_closed_channel(
39243941
check_closed_broadcast(&nodes[0], 1, false);
39253942
expect_payment_sent(&nodes[0], payment_preimage, None, true, true);
39263943

3944+
if close_chans_before_reload && !hold_post_reload_mon_update {
3945+
// For close_chans_before_reload with hold=false, the deferred completions
3946+
// haven't been processed yet. Trigger process_pending_monitor_events now.
3947+
let _ = nodes[1].node.get_and_clear_pending_msg_events();
3948+
check_added_monitors(&nodes[1], 0);
3949+
}
3950+
39273951
if !close_chans_before_reload || close_only_a {
39283952
// Make sure the B<->C channel is still alive and well by sending a payment over it.
39293953
let mut reconnect_args = ReconnectArgs::new(&nodes[1], &nodes[2]);
39303954
reconnect_args.pending_responding_commitment_signed.1 = true;
3931-
// The B<->C `ChannelMonitorUpdate` shouldn't be allowed to complete, which is the
3932-
// equivalent to the responding `commitment_signed` being a duplicate for node B, thus we
3933-
// need to set the `pending_responding_commitment_signed_dup` flag.
3934-
reconnect_args.pending_responding_commitment_signed_dup_monitor.1 = true;
3955+
if hold_post_reload_mon_update {
3956+
// When the A-B update is still InProgress, B-C monitor updates are blocked,
3957+
// so the responding commitment_signed is a duplicate that generates no update.
3958+
reconnect_args.pending_responding_commitment_signed_dup_monitor.1 = true;
3959+
}
39353960
reconnect_args.pending_raa.1 = true;
39363961

39373962
reconnect_nodes(reconnect_args);
39383963
}
39393964

3940-
// Once the blocked `ChannelMonitorUpdate` *finally* completes, the pending
3941-
// `PaymentForwarded` event will finally be released.
3942-
let (_, ab_update_id) = nodes[1].chain_monitor.get_latest_mon_update_id(chan_id_ab);
3943-
nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(chan_id_ab, ab_update_id);
3965+
if hold_post_reload_mon_update {
3966+
// When the persister returned InProgress, we need to manually complete the
3967+
// A-B monitor update to unblock the PaymentForwarded completion action.
3968+
let (_, ab_update_id) = nodes[1].chain_monitor.get_latest_mon_update_id(chan_id_ab);
3969+
nodes[1]
3970+
.chain_monitor
3971+
.chain_monitor
3972+
.force_channel_monitor_updated(chan_id_ab, ab_update_id);
3973+
}
39443974

39453975
// If the A<->B channel was closed before we reload, we'll replay the claim against it on
39463976
// reload, causing the `PaymentForwarded` event to get replayed.
39473977
let evs = nodes[1].node.get_and_clear_pending_events();
3948-
assert_eq!(evs.len(), if close_chans_before_reload { 2 } else { 1 });
3949-
for ev in evs {
3950-
if let Event::PaymentForwarded { claim_from_onchain_tx, next_htlcs, .. } = ev {
3951-
if !claim_from_onchain_tx {
3952-
// If the outbound channel is still open, the `next_user_channel_id` should be available.
3953-
// This was previously broken.
3954-
assert!(next_htlcs[0].user_channel_id.is_some())
3978+
if !close_chans_before_reload && !hold_post_reload_mon_update {
3979+
// PaymentForwarded already fired during get_and_clear_pending_events above.
3980+
assert!(evs.is_empty(), "{:?}", evs);
3981+
} else {
3982+
assert_eq!(evs.len(), if close_chans_before_reload { 2 } else { 1 }, "{:?}", evs);
3983+
for ev in evs {
3984+
if let Event::PaymentForwarded { claim_from_onchain_tx, next_htlcs, .. } = ev {
3985+
if !claim_from_onchain_tx {
3986+
assert!(next_htlcs[0].user_channel_id.is_some())
3987+
}
3988+
} else {
3989+
panic!("Unexpected event: {:?}", ev);
39553990
}
3956-
} else {
3957-
panic!();
39583991
}
39593992
}
39603993

39613994
if !close_chans_before_reload || close_only_a {
3962-
// Once we call `process_pending_events` the final `ChannelMonitor` for the B<->C channel
3963-
// will fly, removing the payment preimage from it.
3964-
check_added_monitors(&nodes[1], 1);
3995+
if hold_post_reload_mon_update {
3996+
// The B-C monitor update from the completion action fires now.
3997+
check_added_monitors(&nodes[1], 1);
3998+
}
39653999
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
39664000
send_payment(&nodes[1], &[&nodes[2]], 100_000);
39674001
}
@@ -5423,17 +5457,16 @@ fn test_late_counterparty_commitment_update_after_holder_commitment_spend_dust()
54235457
}
54245458

54255459
#[test]
5426-
#[should_panic(
5427-
expected = "Watch::update_channel returned Completed while prior updates are still InProgress"
5428-
)]
5429-
fn test_monitor_update_fail_after_funding_spend() {
5430-
// When a counterparty commitment transaction confirms (funding spend), the
5431-
// ChannelMonitor sets funding_spend_seen. If a commitment_signed from the
5432-
// counterparty is then processed (a race between chain events and message
5433-
// processing), update_monitor returns Err because no_further_updates_allowed()
5434-
// is true. ChainMonitor overrides the result to InProgress, permanently
5435-
// freezing the channel. A subsequent preimage claim returning Completed then
5436-
// triggers the per-channel assertion.
5460+
fn test_monitor_update_after_funding_spend() {
5461+
// Test that monitor updates still work after a funding spend is detected by the
5462+
// ChainMonitor but before ChannelManager has processed the corresponding block.
5463+
//
5464+
// When the counterparty commitment transaction confirms (funding spend), the
5465+
// ChannelMonitor sets funding_spend_seen and no_further_updates_allowed() returns
5466+
// true. ChainMonitor overrides all subsequent update_channel results to InProgress
5467+
// to freeze the channel. These overridden updates complete via deferred completions
5468+
// in release_pending_monitor_events, so that MonitorUpdateCompletionActions (like
5469+
// PaymentClaimed) can still fire.
54375470
let chanmon_cfgs = create_chanmon_cfgs(2);
54385471
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
54395472
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
@@ -5444,7 +5477,7 @@ fn test_monitor_update_fail_after_funding_spend() {
54445477
let (_, _, chan_id, _) = create_announced_chan_between_nodes(&nodes, 0, 1);
54455478

54465479
// Route payment 1 fully so B can claim it later.
5447-
let (payment_preimage_1, _payment_hash_1, ..) =
5480+
let (payment_preimage_1, payment_hash_1, ..) =
54485481
route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
54495482

54505483
// Get A's commitment tx (this is the "counterparty" commitment from B's perspective).
@@ -5453,10 +5486,14 @@ fn test_monitor_update_fail_after_funding_spend() {
54535486

54545487
// Confirm A's commitment tx on B's chain_monitor ONLY (not on B's ChannelManager).
54555488
// This sets funding_spend_seen in the monitor, making no_further_updates_allowed() true.
5489+
// We also update the best block on the chain_monitor so the broadcaster height is
5490+
// consistent when claiming HTLCs.
54565491
let (block_hash, height) = nodes[1].best_block_info();
54575492
let block = create_dummy_block(block_hash, height + 1, vec![as_commitment_tx[0].clone()]);
54585493
let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
54595494
nodes[1].chain_monitor.chain_monitor.transactions_confirmed(&block.header, &txdata, height + 1);
5495+
nodes[1].chain_monitor.chain_monitor.best_block_updated(&block.header, height + 1);
5496+
nodes[1].blocks.lock().unwrap().push((block, height + 1));
54605497

54615498
// Send payment 2 from A to B.
54625499
let (route, payment_hash_2, _, payment_secret_2) =
@@ -5478,15 +5515,38 @@ fn test_monitor_update_fail_after_funding_spend() {
54785515

54795516
nodes[1].node.handle_update_add_htlc(node_a_id, &payment_event.msgs[0]);
54805517

5481-
// B processes commitment_signed. The monitor's update_monitor succeeds on the
5482-
// update steps, but returns Err at the end because no_further_updates_allowed()
5483-
// is true (funding_spend_seen). ChainMonitor overrides the result to InProgress.
5518+
// B processes commitment_signed. The monitor applies the update but returns Err
5519+
// because no_further_updates_allowed() is true. ChainMonitor overrides to InProgress,
5520+
// freezing the channel.
54845521
nodes[1].node.handle_commitment_signed(node_a_id, &payment_event.commitment_msg[0]);
54855522
check_added_monitors(&nodes[1], 1);
5486-
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
54875523

5488-
// B claims payment 1. The PaymentPreimage monitor update returns Completed
5489-
// (update_monitor succeeds for preimage, and persister returns Completed),
5490-
// but the prior InProgress from the commitment_signed is still pending.
5524+
// B claims payment 1. The preimage monitor update also returns InProgress (deferred),
5525+
// so no Completed-while-InProgress assertion fires.
54915526
nodes[1].node.claim_funds(payment_preimage_1);
5527+
check_added_monitors(&nodes[1], 1);
5528+
5529+
// First event cycle: the force-close MonitorEvent (CommitmentTxConfirmed) fires first,
5530+
// then the deferred completions resolve. The force-close generates a ChannelForceClosed
5531+
// update (also deferred), which blocks completion actions. So we only get ChannelClosed.
5532+
let events = nodes[1].node.get_and_clear_pending_events();
5533+
assert_eq!(events.len(), 1);
5534+
match &events[0] {
5535+
Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {},
5536+
_ => panic!("Unexpected event: {:?}", events[0]),
5537+
}
5538+
check_added_monitors(&nodes[1], 1);
5539+
nodes[1].node.get_and_clear_pending_msg_events();
5540+
5541+
// Second event cycle: the ChannelForceClosed deferred completion resolves, unblocking
5542+
// the PaymentClaimed completion action.
5543+
let events = nodes[1].node.get_and_clear_pending_events();
5544+
assert_eq!(events.len(), 1);
5545+
match &events[0] {
5546+
Event::PaymentClaimed { payment_hash, amount_msat, .. } => {
5547+
assert_eq!(payment_hash_1, *payment_hash);
5548+
assert_eq!(1_000_000, *amount_msat);
5549+
},
5550+
_ => panic!("Unexpected event: {:?}", events[0]),
5551+
}
54925552
}

0 commit comments

Comments
 (0)