Skip to content

Panic when applying monitor update during channel force close #3857

Open
@whfuyn

Description

@whfuyn

if self.latest_update_id + 1 != updates.update_id {
panic!("Attempted to apply ChannelMonitorUpdates out of order, check the update_id before passing an update to update_monitor!");
}

Our node panicked here. The expected update_id for the channel monitor is 104, but we got an update with id 105.

2025-06-13T07:14:36.486669Z DEBUG lightning::ln::channel:5855: Received a valid revoke_and_ack for channel e45b958e1ddde1e145820e8a1bbdef7e3a427d056ba4b5000d2b7f7b1c62bc81. Responding with a commitment update with 0 HTLCs failed. Holding monitor update.
2025-06-13T07:14:36.486742Z DEBUG lightning::ln::peer_handler:2315: Handling SendRevokeAndACK event in peer_handler for node 030e7e79d6b5eae143391535574d320b1f432cd12587b20ad5b2f9334bded49ee0 for channel e45b958e1ddde1e145820e8a1bbdef7e3a427d056ba4b5000d2b7f7b1c62bc81
2025-06-13T07:14:36.486875Z DEBUG lightning::ln::peer_handler:1798: Got Err message from 030e7e79d6b5eae143391535574d320b1f432cd12587b20ad5b2f9334bded49ee0: 
2025-06-13T07:14:36.493859Z ERROR lightning::ln::channelmanager:4166: Force-closing channel e45b958e1ddde1e145820e8a1bbdef7e3a427d056ba4b5000d2b7f7b1c62bc81
2025-06-13T07:14:36.493914Z DEBUG lightning::chain::chainmonitor:824: Updating ChannelMonitor with update ChannelMonitorUpdate {
    updates: [
        ChannelForceClosed {
            should_broadcast: true,
        },
    ],
    counterparty_node_id: Some(
        PublicKey(
            e09ed4de4b33f9b2d50ab28725d12c431f0b324d5735153943e1eab5d6797e0e874ee011af78e4452bd3b16cf4890fc7d8a96ba00a46b85da7cba51fb498f205,
        ),
    ),
    update_id: 105,
    channel_id: Some(
        0xe45b958e1ddde1e145820e8a1bbdef7e3a427d056ba4b5000d2b7f7b1c62bc81,
    ),
} for channel e45b958e1ddde1e145820e8a1bbdef7e3a427d056ba4b5000d2b7f7b1c62bc81
2025-06-13T07:14:36.493926Z DEBUG lightning::chain::chainmonitor:830: pending_monitor_updates lock acquired
2025-06-13T07:14:36.493928Z  INFO lightning::chain::channelmonitor:3225: Applying update to monitor e45b958e1ddde1e145820e8a1bbdef7e3a427d056ba4b5000d2b7f7b1c62bc81, bringing update_id from 103 to 105 with 1 change(s).

Notice the Holding monitor update in the first line of the logs.

let release_monitor = self.context.blocked_monitor_updates.is_empty() && !hold_mon_update;
let release_state_str =
if hold_mon_update { "Holding" } else if release_monitor { "Releasing" } else { "Blocked" };
macro_rules! return_with_htlcs_to_fail {
($htlcs_to_fail: expr) => {
if !release_monitor {
self.context.blocked_monitor_updates.push(PendingChannelMonitorUpdate {
update: monitor_update,
});
return Ok(($htlcs_to_fail, None));
} else {
return Ok(($htlcs_to_fail, Some(monitor_update)));
}
}
}

There are blocked monitor updates not yet applied when the channel is force-closed. But latest_monitor_update_id has been incremented and assigned to these updates.

if !self.channel_state.is_pre_funded_state() {
self.latest_monitor_update_id += 1;
Some((self.get_counterparty_node_id(), funding_txo, self.channel_id(), ChannelMonitorUpdate {
update_id: self.latest_monitor_update_id,
updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast }],
channel_id: Some(self.channel_id()),
}))
} else { None }

The ChannelForceClosed update is applied to the monitor before the blocked updates, leaving a gap in update_id and causing panic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions