AI-generated analysisPublished automatically and not human-verified. Validated context appears in community notes below.
← Watch feed
Moderate 53 Bitcoin

Re-fail perm-failed HTLCs on startup in case of `MonitorEvent` loss

Public commit record

What the developer wrote

Authored by Matt Corallo

85/100 · Strong
Re-fail perm-failed HTLCs on startup in case of `MonitorEvent` loss

`MonitorEvent`s aren't delivered to the `ChannelManager` in a
durable fashion - if the `ChannelManager` fetches the pending
`MonitorEvent`s, then the `ChannelMonitor` gets persisted (i.e. due
to a block update) then the node crashes, prior to persisting the
`ChannelManager` again, the `MonitorEvent` and its effects on the
`ChannelManger` will be lost. This isn't likely in a sync persist
environment, but in an async one this could be an issue.

Note that this is only an issue for closed channels -
`MonitorEvent`s only inform the `ChannelManager` that a channel is
closed (which the `ChannelManager` will learn on startup or when it
next tries to advance the channel state), that
`ChannelMonitorUpdate` writes completed (which the `ChannelManager`
will detect on startup), or that HTLCs resolved on-chain post
closure. Of the three, only the last is problematic to lose prior
to a reload.

In a previous commit we handled the case of claimed HTLCs by
replaying payment preimages on startup to avoid `MonitorEvent` loss
causing us to miss an HTLC claim. Here we handle the HTLC-failed
case similarly.

Unlike with HTLC claims via preimage, we don't already have replay
logic in `ChannelManager` startup, but its easy enough to add one.
Luckily, we already track when an HTLC reaches permanently-failed
state in `ChannelMonitor` (i.e. it has `ANTI_REORG_DELAY`
confirmations on-chain on the failing transaction), so all we need
to do is add the ability to query for that and fail them on
`ChannelManager` startup.
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode
The short version

What changed, and why it matters

This commit fixes a bug in rust-lightning where a Lightning node could permanently lose track of failed payments after a crash. If the node crashed at exactly the wrong moment, it might never report that a payment had failed, leaving funds in limbo and potentially causing the user or downstream nodes to wait forever. The fix makes the node re-check on startup whether any HTLCs (payment contracts) were already resolved as failed on-chain, and if so, properly fail them again in its internal state.

Recommended action

Review and merge. This is a defensive correctness fix for a crash-recovery edge case. Operators using async persistence should prioritize upgrading. No immediate active-exploitation response is required, but nodes should be restarted cleanly after upgrade so the new startup replay logic can reconcile any previously lost failure states.

Security signals we found

01

Loss of MonitorEvent durability leading to missing HTLC failure notifications

02

Async persistence environment crash-recovery failure mode

03

On-chain HTLC timeout resolution not reflected in ChannelManager state after restart

04

Potential payment state inconsistency between ChannelMonitor and ChannelManager

05

New startup replay logic added to close durability gap

Risk score

Why this scored 53/100

Our methodology →
Potential impact 18/30
Exploitability 5/25
Stealth signal 10/15
Affected reach 8/15
Confidence 8/10
Evidence quality 4/5
Human-validated context

Community notes

Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.

No validated notes yet.

The AI analysis stands alone for now. Submit a note if you can add evidence or important context.