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

Generate new `ReleasePaymentComplete` monitor updates

Public commit record

What the developer wrote

Authored by Matt Corallo

95/100 · Strong
Generate 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 begin generating the new
`ChannelMonitorUpdateStep::ReleasePaymentComplete` updates,
updating functional tests for the new `ChannelMonitorUpdate`s where
required.
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Mentions testing or verification
The short version

What changed, and why it matters

This commit fixes a reliability bug in the Lightning Dev Kit (LDK) where payment success or failure events could be lost if the node crashes at the wrong moment. The fix adds a new 'ReleasePaymentComplete' monitor update so that once a payment is fully resolved, the ChannelMonitor records it durably. This prevents users from seeing stale or repeated payment events after a restart, especially in setups where persistence happens asynchronously. It is a defensive correctness fix, not an externally exploitable vulnerability.

Recommended action

Review and merge as a defensive reliability fix. Operators using async persistence should prioritize upgrading. No immediate external mitigation is required because the issue is a crash-recovery consistency problem rather than an externally exploitable attack vector.

Security signals we found

01

Durability gap in event delivery between ChannelMonitor and ChannelManager persistence

02

New ChannelMonitorUpdateStep::ReleasePaymentComplete variant

03

New EventCompletionAction::ReleasePaymentCompleteChannelMonitorUpdate variant

04

Startup replay handling for lost MonitorEvents

05

Deduplication logic to avoid duplicate monitor updates

06

Downgrade compatibility note: action dropped on LDK < 0.2

Risk score

Why this scored 53/100

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