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

Prepare to provide new `ReleasePaymentComplete` monitor updates

Public commit record

What the developer wrote

Authored by Matt Corallo

85/100 · Strong
Prepare to provide new `ReleasePaymentComplete` monitor updates

`MonitorEvent`s aren't delivered to the `ChannelManager` in a
durable fasion - 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 previous commits we ensured that HTLC resolutions which came to
`ChannelManager` via a `MonitorEvent` were replayed on startup if
the `MonitorEvent` was lost. However, in cases where the
`ChannelManager` was so stale that it didn't have the payment state
for an HTLC at all, we only re-add it in cases where
`ChannelMonitor::get_pending_or_resolved_outbound_htlcs` includes
it.

Because constantly re-adding a payment state and then failing it
would generate lots of noise for users on startup (not to mention
risk of confusing stale payment events for the latest state of a
payment when the `PaymentId` has been reused to retry a payment).
Thus, `get_pending_or_resolved_outbound_htlcs` does not include
state for HTLCs which were resolved on chain with a preimage or
HTLCs which were resolved on chain with a timeout after
`ANTI_REORG_DELAY` confirmations.

This critera matches the critera for generating a `MonitorEvent`,
and works great under the assumption that `MonitorEvent`s are
reliably delivered. However, if they are not, and our
`ChannelManager` is lost or substantially old (or, in a future
where we do not persist `ChannelManager` at all), we will not end
up seeing payment resolution events for an HTLC.

Instead, we really want to tell our `ChannelMonitor`s when the
resolution of an HTLC is complete. Note that we don't particularly
care about non-payment HTLCs, as there is no re-hydration of state
to do there - `ChannelManager` load ignores forwarded HTLCs coming
back from `get_pending_or_resolved_outbound_htlcs` as there's
nothing to do - we always attempt to replay the success/failure and
figure out if it mattered based on whether there was still an HTLC
to claim/fail.

Here we prepare to generate the new
`ChannelMonitorUpdateStep::ReleasePaymentComplete` updates, adding
a new `PaymentCompleteUpdate` struct to track the new update before
we generate the `ChannelMonitorUpdate` and passing through to the
right places in `ChannelManager`.

The only cases where we want to generate the new update is after a
`PaymentSent` or `PaymentFailed` event when the event was the
result of a `MonitorEvent` or the equivalent read during 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 is a preparatory patch in the Lightning Dev Kit (LDK) to fix a durability issue where payment completion events from channel monitors could be lost if the node crashes at the wrong moment. It introduces a new internal tracking struct (`PaymentCompleteUpdate`) and wires it through payment-failure and payment-claim paths so that, in a future commit, channel monitors can be explicitly told when an HTLC resolution is fully processed. The change itself does not yet generate the final monitor update, so it is not a complete fix on its own. It is defensive hardening against a crash-recovery edge case, not an exploitable vulnerability in the normal sense.

Recommended action

Treat this as incomplete hardening. Review the follow-up commit that actually generates `ChannelMonitorUpdateStep::ReleasePaymentComplete` and removes the TODOs. Until then, ensure `ChannelManager` is persisted promptly after processing `MonitorEvent`s, especially in async-persistence deployments. No immediate exploitable vector is present in this commit alone, but operators should keep LDK up to date once the full fix lands.

Security signals we found

01

Durability gap between ChannelMonitor persistence and ChannelManager persistence can lose MonitorEvent-derived payment resolution events

02

New internal struct PaymentCompleteUpdate introduced to track HTLC resolution completion

03

fail_htlc_backwards_internal signature extended with optional PaymentCompleteUpdate

04

claim_htlc now takes EventCompletionAction by mutable Option to allow consuming the action only when an event is emitted

05

TODO comments indicate the actual ChannelMonitorUpdateStep::ReleasePaymentComplete generation is deferred to a later commit

06

Duplicate completion-action detection added to avoid double-releasing RAA monitor updates

07

Only affects closed channels and HTLCs resolved on-chain after ANTI_REORG_DELAY confirmations

Risk score

Why this scored 45/100

Our methodology →
Potential impact 12/30
Exploitability 5/25
Stealth signal 8/15
Affected reach 10/15
Confidence 7/10
Evidence quality 3/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.