Fix update_id gap during force_shutdown - #3858

Merged
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap
Jun 24, 2025
Merged

Fix update_id gap during force_shutdown#3858
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap

Conversation

@whfuyn

Copy link
Copy Markdown
Contributor

When a channel is force-closed, there might be blocked monitor updates not yet applied. But latest_monitor_update_id has been incremented and assigned to these updates. This results in a panic when trying to apply the ChannelForceClosed update. Use the unblocked update id instead.

Resolves: #3857

@ldk-reviews-bot

ldk-reviews-bot commented Jun 13, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This should work, but do you mind including a test?

There are other scenarios where we also increment by 1, but those should not result in a panic as they are queued in blocked_monitor_updates. The force close update is the only one we let fly through regardless of blocked_monitor_updates.

Comment threadlightning/src/ln/channel.rs Outdated
@wpaulino
wpaulino removed the request for review from jkczyzJune 13, 2025 16:25
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 446155b to 5e6e74cCompareJune 13, 2025 17:23
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

Got it! Will add a test later.

@codecov

codecovBot commented Jun 13, 2025

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.62%. Comparing base (c48e0a8) to head (ceb5a55).
Report is 4 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #3858 +/- ##
==========================================
- Coverage 89.65% 89.62% -0.04% 
==========================================
Files 164 164 Lines 134658 134661 +3 Branches 134658 134661 +3 ==========================================
- Hits 120734 120688 -46 - Misses 11246 11292 +46 - Partials 2678 2681 +3 

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

TheBlueMatt
TheBlueMatt previously approved these changes Jun 16, 2025

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I think there's a few more changes I want to make to this pipeline but this change by itself looks good.

@wpaulino

Copy link
Copy Markdown
Contributor

@whfuyn do you mind rebasing this? We're going to merge this as is to include it in a release and follow up with a test later.

When a channel is force-closed, there might be blocked monitor updates
not yet applied. But `latest_monitor_update_id` has been incremented and
assigned to these updates. This results in a panic when trying to apply
the `ChannelForceClosed` update. Use the unblocked update id instead.
Resolves: lightningdevkit#3857
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 0866405 to ceb5a55CompareJune 24, 2025 04:11
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

@wpaulino Sorry for the late response.

I had some trouble constructing a proper test without using MPP or multi-hop payments. My original test that triggered this problem only involved sending payments between two nodes connected by a single direct channel. However, when I searched the code related to blocked_monitor_updates, it seems only MPP and multi-hop payments can cause monitor updates to be blocked. This feels strange.

I've rebased this PR.

@wpaulino

Copy link
Copy Markdown
Contributor

A revoke_and_ack monitor update can also become blocked until the PaymentSent event is handled.

@TheBlueMatt
TheBlueMatt merged commit 0fe51c5 into lightningdevkit:mainJun 24, 2025
@TheBlueMattTheBlueMatt mentioned this pull request Jul 15, 2025
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Backported in #3932

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Jul 24, 2025
v0.1.5 - Jul 16, 2025 - "Async Path Reduction"
Performance Improvements
========================
* `NetworkGraph`'s expensive internal consistency checks have now been
disabled in debug builds in addition to release builds (lightningdevkit#3687).
Bug Fixes
=========
* Pathfinding which results in a multi-path payment is now substantially
smarter, using fewer paths and better optimizing fees and successes (lightningdevkit#3890).
* A counterparty delaying claiming multiple HTLCs with different expiries can
no longer cause our `ChannelMonitor` to continuously rebroadcast invalid
transactions or RBF bump attempts (lightningdevkit#3923).
* Reorgs can no longer cause us to fail to claim HTLCs after a counterparty
delayed claiming multiple HTLCs with different expiries (lightningdevkit#3923).
* Force-closing a channel while it is blocked on another channel's async
`ChannelMonitorUpdate` can no longer lead to a panic (lightningdevkit#3858).
* `ChannelMonitorUpdate`s can no longer be released to storage too early when
doing async updates or on restart. This only impacts async
`ChannelMonitorUpdate` persistence and can lead to loss of funds only in rare
cases with `ChannelMonitorUpdate` persistence order inversions (lightningdevkit#3907).
Security
========
0.1.5 fixes a vulnerability which could allow a peer to overdraw their reserve
value, potentially cutting into commitment transaction fees on channels with a
low reserve.
* Due to a bug in checking whether an HTLC is dust during acceptance, near-dust
HTLCs were not counted towards the commitment transaction fee, but did
eventually contribute to it when we built a commitment transaction. This can
be used by a counterparty to overdraw their reserve value, or, for channels
with a low reserve value, cut into the commitment transaction fee (lightningdevkit#3933).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panic when applying monitor update during channel force close

4 participants

@whfuyn@ldk-reviews-bot@wpaulino@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fix update_id gap during force_shutdown - #3858

Merged
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap
Jun 24, 2025
Merged

Fix update_id gap during force_shutdown#3858
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap

Conversation

@whfuyn

Copy link
Copy Markdown
Contributor

When a channel is force-closed, there might be blocked monitor updates not yet applied. But latest_monitor_update_id has been incremented and assigned to these updates. This results in a panic when trying to apply the ChannelForceClosed update. Use the unblocked update id instead.

Resolves: #3857

@ldk-reviews-bot

ldk-reviews-bot commented Jun 13, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This should work, but do you mind including a test?

There are other scenarios where we also increment by 1, but those should not result in a panic as they are queued in blocked_monitor_updates. The force close update is the only one we let fly through regardless of blocked_monitor_updates.

Comment threadlightning/src/ln/channel.rs Outdated
@wpaulino
wpaulino removed the request for review from jkczyzJune 13, 2025 16:25
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 446155b to 5e6e74cCompareJune 13, 2025 17:23
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

Got it! Will add a test later.

@codecov

codecovBot commented Jun 13, 2025

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.62%. Comparing base (c48e0a8) to head (ceb5a55).
Report is 4 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #3858 +/- ##
==========================================
- Coverage 89.65% 89.62% -0.04% 
==========================================
Files 164 164 Lines 134658 134661 +3 Branches 134658 134661 +3 ==========================================
- Hits 120734 120688 -46 - Misses 11246 11292 +46 - Partials 2678 2681 +3 

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

TheBlueMatt
TheBlueMatt previously approved these changes Jun 16, 2025

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I think there's a few more changes I want to make to this pipeline but this change by itself looks good.

@wpaulino

Copy link
Copy Markdown
Contributor

@whfuyn do you mind rebasing this? We're going to merge this as is to include it in a release and follow up with a test later.

When a channel is force-closed, there might be blocked monitor updates
not yet applied. But `latest_monitor_update_id` has been incremented and
assigned to these updates. This results in a panic when trying to apply
the `ChannelForceClosed` update. Use the unblocked update id instead.
Resolves: lightningdevkit#3857
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 0866405 to ceb5a55CompareJune 24, 2025 04:11
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

@wpaulino Sorry for the late response.

I had some trouble constructing a proper test without using MPP or multi-hop payments. My original test that triggered this problem only involved sending payments between two nodes connected by a single direct channel. However, when I searched the code related to blocked_monitor_updates, it seems only MPP and multi-hop payments can cause monitor updates to be blocked. This feels strange.

I've rebased this PR.

@wpaulino

Copy link
Copy Markdown
Contributor

A revoke_and_ack monitor update can also become blocked until the PaymentSent event is handled.

@TheBlueMatt
TheBlueMatt merged commit 0fe51c5 into lightningdevkit:mainJun 24, 2025
@TheBlueMattTheBlueMatt mentioned this pull request Jul 15, 2025
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Backported in #3932

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Jul 24, 2025
v0.1.5 - Jul 16, 2025 - "Async Path Reduction"
Performance Improvements
========================
* `NetworkGraph`'s expensive internal consistency checks have now been
disabled in debug builds in addition to release builds (lightningdevkit#3687).
Bug Fixes
=========
* Pathfinding which results in a multi-path payment is now substantially
smarter, using fewer paths and better optimizing fees and successes (lightningdevkit#3890).
* A counterparty delaying claiming multiple HTLCs with different expiries can
no longer cause our `ChannelMonitor` to continuously rebroadcast invalid
transactions or RBF bump attempts (lightningdevkit#3923).
* Reorgs can no longer cause us to fail to claim HTLCs after a counterparty
delayed claiming multiple HTLCs with different expiries (lightningdevkit#3923).
* Force-closing a channel while it is blocked on another channel's async
`ChannelMonitorUpdate` can no longer lead to a panic (lightningdevkit#3858).
* `ChannelMonitorUpdate`s can no longer be released to storage too early when
doing async updates or on restart. This only impacts async
`ChannelMonitorUpdate` persistence and can lead to loss of funds only in rare
cases with `ChannelMonitorUpdate` persistence order inversions (lightningdevkit#3907).
Security
========
0.1.5 fixes a vulnerability which could allow a peer to overdraw their reserve
value, potentially cutting into commitment transaction fees on channels with a
low reserve.
* Due to a bug in checking whether an HTLC is dust during acceptance, near-dust
HTLCs were not counted towards the commitment transaction fee, but did
eventually contribute to it when we built a commitment transaction. This can
be used by a counterparty to overdraw their reserve value, or, for channels
with a low reserve value, cut into the commitment transaction fee (lightningdevkit#3933).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panic when applying monitor update during channel force close

4 participants

@whfuyn@ldk-reviews-bot@wpaulino@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix update_id gap during force_shutdown - #3858

Merged
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap
Jun 24, 2025
Merged

Fix update_id gap during force_shutdown#3858
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap

Conversation

@whfuyn

Copy link
Copy Markdown
Contributor

When a channel is force-closed, there might be blocked monitor updates not yet applied. But latest_monitor_update_id has been incremented and assigned to these updates. This results in a panic when trying to apply the ChannelForceClosed update. Use the unblocked update id instead.

Resolves: #3857

@ldk-reviews-bot

ldk-reviews-bot commented Jun 13, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This should work, but do you mind including a test?

There are other scenarios where we also increment by 1, but those should not result in a panic as they are queued in blocked_monitor_updates. The force close update is the only one we let fly through regardless of blocked_monitor_updates.

Comment threadlightning/src/ln/channel.rs Outdated
@wpaulino
wpaulino removed the request for review from jkczyzJune 13, 2025 16:25
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 446155b to 5e6e74cCompareJune 13, 2025 17:23
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

Got it! Will add a test later.

@codecov

codecovBot commented Jun 13, 2025

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.62%. Comparing base (c48e0a8) to head (ceb5a55).
Report is 4 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #3858 +/- ##
==========================================
- Coverage 89.65% 89.62% -0.04% 
==========================================
Files 164 164 Lines 134658 134661 +3 Branches 134658 134661 +3 ==========================================
- Hits 120734 120688 -46 - Misses 11246 11292 +46 - Partials 2678 2681 +3 

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

TheBlueMatt
TheBlueMatt previously approved these changes Jun 16, 2025

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I think there's a few more changes I want to make to this pipeline but this change by itself looks good.

@wpaulino

Copy link
Copy Markdown
Contributor

@whfuyn do you mind rebasing this? We're going to merge this as is to include it in a release and follow up with a test later.

When a channel is force-closed, there might be blocked monitor updates
not yet applied. But `latest_monitor_update_id` has been incremented and
assigned to these updates. This results in a panic when trying to apply
the `ChannelForceClosed` update. Use the unblocked update id instead.
Resolves: lightningdevkit#3857
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 0866405 to ceb5a55CompareJune 24, 2025 04:11
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

@wpaulino Sorry for the late response.

I had some trouble constructing a proper test without using MPP or multi-hop payments. My original test that triggered this problem only involved sending payments between two nodes connected by a single direct channel. However, when I searched the code related to blocked_monitor_updates, it seems only MPP and multi-hop payments can cause monitor updates to be blocked. This feels strange.

I've rebased this PR.

@wpaulino

Copy link
Copy Markdown
Contributor

A revoke_and_ack monitor update can also become blocked until the PaymentSent event is handled.

@TheBlueMatt
TheBlueMatt merged commit 0fe51c5 into lightningdevkit:mainJun 24, 2025
@TheBlueMattTheBlueMatt mentioned this pull request Jul 15, 2025
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Backported in #3932

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Jul 24, 2025
v0.1.5 - Jul 16, 2025 - "Async Path Reduction"
Performance Improvements
========================
* `NetworkGraph`'s expensive internal consistency checks have now been
disabled in debug builds in addition to release builds (lightningdevkit#3687).
Bug Fixes
=========
* Pathfinding which results in a multi-path payment is now substantially
smarter, using fewer paths and better optimizing fees and successes (lightningdevkit#3890).
* A counterparty delaying claiming multiple HTLCs with different expiries can
no longer cause our `ChannelMonitor` to continuously rebroadcast invalid
transactions or RBF bump attempts (lightningdevkit#3923).
* Reorgs can no longer cause us to fail to claim HTLCs after a counterparty
delayed claiming multiple HTLCs with different expiries (lightningdevkit#3923).
* Force-closing a channel while it is blocked on another channel's async
`ChannelMonitorUpdate` can no longer lead to a panic (lightningdevkit#3858).
* `ChannelMonitorUpdate`s can no longer be released to storage too early when
doing async updates or on restart. This only impacts async
`ChannelMonitorUpdate` persistence and can lead to loss of funds only in rare
cases with `ChannelMonitorUpdate` persistence order inversions (lightningdevkit#3907).
Security
========
0.1.5 fixes a vulnerability which could allow a peer to overdraw their reserve
value, potentially cutting into commitment transaction fees on channels with a
low reserve.
* Due to a bug in checking whether an HTLC is dust during acceptance, near-dust
HTLCs were not counted towards the commitment transaction fee, but did
eventually contribute to it when we built a commitment transaction. This can
be used by a counterparty to overdraw their reserve value, or, for channels
with a low reserve value, cut into the commitment transaction fee (lightningdevkit#3933).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panic when applying monitor update during channel force close

4 participants

@whfuyn@ldk-reviews-bot@wpaulino@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix update_id gap during force_shutdown - #3858

Merged
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap
Jun 24, 2025
Merged

Fix update_id gap during force_shutdown#3858
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap

Conversation

@whfuyn

Copy link
Copy Markdown
Contributor

When a channel is force-closed, there might be blocked monitor updates not yet applied. But latest_monitor_update_id has been incremented and assigned to these updates. This results in a panic when trying to apply the ChannelForceClosed update. Use the unblocked update id instead.

Resolves: #3857

@ldk-reviews-bot

ldk-reviews-bot commented Jun 13, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This should work, but do you mind including a test?

There are other scenarios where we also increment by 1, but those should not result in a panic as they are queued in blocked_monitor_updates. The force close update is the only one we let fly through regardless of blocked_monitor_updates.

Comment threadlightning/src/ln/channel.rs Outdated
@wpaulino
wpaulino removed the request for review from jkczyzJune 13, 2025 16:25
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 446155b to 5e6e74cCompareJune 13, 2025 17:23
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

Got it! Will add a test later.

@codecov

codecovBot commented Jun 13, 2025

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.62%. Comparing base (c48e0a8) to head (ceb5a55).
Report is 4 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #3858 +/- ##
==========================================
- Coverage 89.65% 89.62% -0.04% 
==========================================
Files 164 164 Lines 134658 134661 +3 Branches 134658 134661 +3 ==========================================
- Hits 120734 120688 -46 - Misses 11246 11292 +46 - Partials 2678 2681 +3 

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

TheBlueMatt
TheBlueMatt previously approved these changes Jun 16, 2025

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I think there's a few more changes I want to make to this pipeline but this change by itself looks good.

@wpaulino

Copy link
Copy Markdown
Contributor

@whfuyn do you mind rebasing this? We're going to merge this as is to include it in a release and follow up with a test later.

When a channel is force-closed, there might be blocked monitor updates
not yet applied. But `latest_monitor_update_id` has been incremented and
assigned to these updates. This results in a panic when trying to apply
the `ChannelForceClosed` update. Use the unblocked update id instead.
Resolves: lightningdevkit#3857
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 0866405 to ceb5a55CompareJune 24, 2025 04:11
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

@wpaulino Sorry for the late response.

I had some trouble constructing a proper test without using MPP or multi-hop payments. My original test that triggered this problem only involved sending payments between two nodes connected by a single direct channel. However, when I searched the code related to blocked_monitor_updates, it seems only MPP and multi-hop payments can cause monitor updates to be blocked. This feels strange.

I've rebased this PR.

@wpaulino

Copy link
Copy Markdown
Contributor

A revoke_and_ack monitor update can also become blocked until the PaymentSent event is handled.

@TheBlueMatt
TheBlueMatt merged commit 0fe51c5 into lightningdevkit:mainJun 24, 2025
@TheBlueMattTheBlueMatt mentioned this pull request Jul 15, 2025
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Backported in #3932

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Jul 24, 2025
v0.1.5 - Jul 16, 2025 - "Async Path Reduction"
Performance Improvements
========================
* `NetworkGraph`'s expensive internal consistency checks have now been
disabled in debug builds in addition to release builds (lightningdevkit#3687).
Bug Fixes
=========
* Pathfinding which results in a multi-path payment is now substantially
smarter, using fewer paths and better optimizing fees and successes (lightningdevkit#3890).
* A counterparty delaying claiming multiple HTLCs with different expiries can
no longer cause our `ChannelMonitor` to continuously rebroadcast invalid
transactions or RBF bump attempts (lightningdevkit#3923).
* Reorgs can no longer cause us to fail to claim HTLCs after a counterparty
delayed claiming multiple HTLCs with different expiries (lightningdevkit#3923).
* Force-closing a channel while it is blocked on another channel's async
`ChannelMonitorUpdate` can no longer lead to a panic (lightningdevkit#3858).
* `ChannelMonitorUpdate`s can no longer be released to storage too early when
doing async updates or on restart. This only impacts async
`ChannelMonitorUpdate` persistence and can lead to loss of funds only in rare
cases with `ChannelMonitorUpdate` persistence order inversions (lightningdevkit#3907).
Security
========
0.1.5 fixes a vulnerability which could allow a peer to overdraw their reserve
value, potentially cutting into commitment transaction fees on channels with a
low reserve.
* Due to a bug in checking whether an HTLC is dust during acceptance, near-dust
HTLCs were not counted towards the commitment transaction fee, but did
eventually contribute to it when we built a commitment transaction. This can
be used by a counterparty to overdraw their reserve value, or, for channels
with a low reserve value, cut into the commitment transaction fee (lightningdevkit#3933).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panic when applying monitor update during channel force close

4 participants

@whfuyn@ldk-reviews-bot@wpaulino@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Fix update_id gap during force_shutdown - #3858

Merged
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap
Jun 24, 2025
Merged

Fix update_id gap during force_shutdown#3858
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap

Conversation

@whfuyn

Copy link
Copy Markdown
Contributor

When a channel is force-closed, there might be blocked monitor updates not yet applied. But latest_monitor_update_id has been incremented and assigned to these updates. This results in a panic when trying to apply the ChannelForceClosed update. Use the unblocked update id instead.

Resolves: #3857

@ldk-reviews-bot

ldk-reviews-bot commented Jun 13, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This should work, but do you mind including a test?

There are other scenarios where we also increment by 1, but those should not result in a panic as they are queued in blocked_monitor_updates. The force close update is the only one we let fly through regardless of blocked_monitor_updates.

Comment threadlightning/src/ln/channel.rs Outdated
@wpaulino
wpaulino removed the request for review from jkczyzJune 13, 2025 16:25
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 446155b to 5e6e74cCompareJune 13, 2025 17:23
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

Got it! Will add a test later.

@codecov

codecovBot commented Jun 13, 2025

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.62%. Comparing base (c48e0a8) to head (ceb5a55).
Report is 4 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #3858 +/- ##
==========================================
- Coverage 89.65% 89.62% -0.04% 
==========================================
Files 164 164 Lines 134658 134661 +3 Branches 134658 134661 +3 ==========================================
- Hits 120734 120688 -46 - Misses 11246 11292 +46 - Partials 2678 2681 +3 

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

TheBlueMatt
TheBlueMatt previously approved these changes Jun 16, 2025

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I think there's a few more changes I want to make to this pipeline but this change by itself looks good.

@wpaulino

Copy link
Copy Markdown
Contributor

@whfuyn do you mind rebasing this? We're going to merge this as is to include it in a release and follow up with a test later.

When a channel is force-closed, there might be blocked monitor updates
not yet applied. But `latest_monitor_update_id` has been incremented and
assigned to these updates. This results in a panic when trying to apply
the `ChannelForceClosed` update. Use the unblocked update id instead.
Resolves: lightningdevkit#3857
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 0866405 to ceb5a55CompareJune 24, 2025 04:11
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

@wpaulino Sorry for the late response.

I had some trouble constructing a proper test without using MPP or multi-hop payments. My original test that triggered this problem only involved sending payments between two nodes connected by a single direct channel. However, when I searched the code related to blocked_monitor_updates, it seems only MPP and multi-hop payments can cause monitor updates to be blocked. This feels strange.

I've rebased this PR.

@wpaulino

Copy link
Copy Markdown
Contributor

A revoke_and_ack monitor update can also become blocked until the PaymentSent event is handled.

@TheBlueMatt
TheBlueMatt merged commit 0fe51c5 into lightningdevkit:mainJun 24, 2025
@TheBlueMattTheBlueMatt mentioned this pull request Jul 15, 2025
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Backported in #3932

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Jul 24, 2025
v0.1.5 - Jul 16, 2025 - "Async Path Reduction"
Performance Improvements
========================
* `NetworkGraph`'s expensive internal consistency checks have now been
disabled in debug builds in addition to release builds (lightningdevkit#3687).
Bug Fixes
=========
* Pathfinding which results in a multi-path payment is now substantially
smarter, using fewer paths and better optimizing fees and successes (lightningdevkit#3890).
* A counterparty delaying claiming multiple HTLCs with different expiries can
no longer cause our `ChannelMonitor` to continuously rebroadcast invalid
transactions or RBF bump attempts (lightningdevkit#3923).
* Reorgs can no longer cause us to fail to claim HTLCs after a counterparty
delayed claiming multiple HTLCs with different expiries (lightningdevkit#3923).
* Force-closing a channel while it is blocked on another channel's async
`ChannelMonitorUpdate` can no longer lead to a panic (lightningdevkit#3858).
* `ChannelMonitorUpdate`s can no longer be released to storage too early when
doing async updates or on restart. This only impacts async
`ChannelMonitorUpdate` persistence and can lead to loss of funds only in rare
cases with `ChannelMonitorUpdate` persistence order inversions (lightningdevkit#3907).
Security
========
0.1.5 fixes a vulnerability which could allow a peer to overdraw their reserve
value, potentially cutting into commitment transaction fees on channels with a
low reserve.
* Due to a bug in checking whether an HTLC is dust during acceptance, near-dust
HTLCs were not counted towards the commitment transaction fee, but did
eventually contribute to it when we built a commitment transaction. This can
be used by a counterparty to overdraw their reserve value, or, for channels
with a low reserve value, cut into the commitment transaction fee (lightningdevkit#3933).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panic when applying monitor update during channel force close

4 participants

@whfuyn@ldk-reviews-bot@wpaulino@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix update_id gap during force_shutdown - #3858

Merged
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap
Jun 24, 2025
Merged

Fix update_id gap during force_shutdown#3858
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap

Conversation

@whfuyn

Copy link
Copy Markdown
Contributor

When a channel is force-closed, there might be blocked monitor updates not yet applied. But latest_monitor_update_id has been incremented and assigned to these updates. This results in a panic when trying to apply the ChannelForceClosed update. Use the unblocked update id instead.

Resolves: #3857

@ldk-reviews-bot

ldk-reviews-bot commented Jun 13, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This should work, but do you mind including a test?

There are other scenarios where we also increment by 1, but those should not result in a panic as they are queued in blocked_monitor_updates. The force close update is the only one we let fly through regardless of blocked_monitor_updates.

Comment threadlightning/src/ln/channel.rs Outdated
@wpaulino
wpaulino removed the request for review from jkczyzJune 13, 2025 16:25
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 446155b to 5e6e74cCompareJune 13, 2025 17:23
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

Got it! Will add a test later.

@codecov

codecovBot commented Jun 13, 2025

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.62%. Comparing base (c48e0a8) to head (ceb5a55).
Report is 4 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #3858 +/- ##
==========================================
- Coverage 89.65% 89.62% -0.04% 
==========================================
Files 164 164 Lines 134658 134661 +3 Branches 134658 134661 +3 ==========================================
- Hits 120734 120688 -46 - Misses 11246 11292 +46 - Partials 2678 2681 +3 

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

TheBlueMatt
TheBlueMatt previously approved these changes Jun 16, 2025

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I think there's a few more changes I want to make to this pipeline but this change by itself looks good.

@wpaulino

Copy link
Copy Markdown
Contributor

@whfuyn do you mind rebasing this? We're going to merge this as is to include it in a release and follow up with a test later.

When a channel is force-closed, there might be blocked monitor updates
not yet applied. But `latest_monitor_update_id` has been incremented and
assigned to these updates. This results in a panic when trying to apply
the `ChannelForceClosed` update. Use the unblocked update id instead.
Resolves: lightningdevkit#3857
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 0866405 to ceb5a55CompareJune 24, 2025 04:11
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

@wpaulino Sorry for the late response.

I had some trouble constructing a proper test without using MPP or multi-hop payments. My original test that triggered this problem only involved sending payments between two nodes connected by a single direct channel. However, when I searched the code related to blocked_monitor_updates, it seems only MPP and multi-hop payments can cause monitor updates to be blocked. This feels strange.

I've rebased this PR.

@wpaulino

Copy link
Copy Markdown
Contributor

A revoke_and_ack monitor update can also become blocked until the PaymentSent event is handled.

@TheBlueMatt
TheBlueMatt merged commit 0fe51c5 into lightningdevkit:mainJun 24, 2025
@TheBlueMattTheBlueMatt mentioned this pull request Jul 15, 2025
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Backported in #3932

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Jul 24, 2025
v0.1.5 - Jul 16, 2025 - "Async Path Reduction"
Performance Improvements
========================
* `NetworkGraph`'s expensive internal consistency checks have now been
disabled in debug builds in addition to release builds (lightningdevkit#3687).
Bug Fixes
=========
* Pathfinding which results in a multi-path payment is now substantially
smarter, using fewer paths and better optimizing fees and successes (lightningdevkit#3890).
* A counterparty delaying claiming multiple HTLCs with different expiries can
no longer cause our `ChannelMonitor` to continuously rebroadcast invalid
transactions or RBF bump attempts (lightningdevkit#3923).
* Reorgs can no longer cause us to fail to claim HTLCs after a counterparty
delayed claiming multiple HTLCs with different expiries (lightningdevkit#3923).
* Force-closing a channel while it is blocked on another channel's async
`ChannelMonitorUpdate` can no longer lead to a panic (lightningdevkit#3858).
* `ChannelMonitorUpdate`s can no longer be released to storage too early when
doing async updates or on restart. This only impacts async
`ChannelMonitorUpdate` persistence and can lead to loss of funds only in rare
cases with `ChannelMonitorUpdate` persistence order inversions (lightningdevkit#3907).
Security
========
0.1.5 fixes a vulnerability which could allow a peer to overdraw their reserve
value, potentially cutting into commitment transaction fees on channels with a
low reserve.
* Due to a bug in checking whether an HTLC is dust during acceptance, near-dust
HTLCs were not counted towards the commitment transaction fee, but did
eventually contribute to it when we built a commitment transaction. This can
be used by a counterparty to overdraw their reserve value, or, for channels
with a low reserve value, cut into the commitment transaction fee (lightningdevkit#3933).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panic when applying monitor update during channel force close

4 participants

@whfuyn@ldk-reviews-bot@wpaulino@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix update_id gap during force_shutdown - #3858

Merged
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap
Jun 24, 2025
Merged

Fix update_id gap during force_shutdown#3858
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap

Conversation

@whfuyn

Copy link
Copy Markdown
Contributor

When a channel is force-closed, there might be blocked monitor updates not yet applied. But latest_monitor_update_id has been incremented and assigned to these updates. This results in a panic when trying to apply the ChannelForceClosed update. Use the unblocked update id instead.

Resolves: #3857

@ldk-reviews-bot

ldk-reviews-bot commented Jun 13, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This should work, but do you mind including a test?

There are other scenarios where we also increment by 1, but those should not result in a panic as they are queued in blocked_monitor_updates. The force close update is the only one we let fly through regardless of blocked_monitor_updates.

Comment threadlightning/src/ln/channel.rs Outdated
@wpaulino
wpaulino removed the request for review from jkczyzJune 13, 2025 16:25
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 446155b to 5e6e74cCompareJune 13, 2025 17:23
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

Got it! Will add a test later.

@codecov

codecovBot commented Jun 13, 2025

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.62%. Comparing base (c48e0a8) to head (ceb5a55).
Report is 4 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #3858 +/- ##
==========================================
- Coverage 89.65% 89.62% -0.04% 
==========================================
Files 164 164 Lines 134658 134661 +3 Branches 134658 134661 +3 ==========================================
- Hits 120734 120688 -46 - Misses 11246 11292 +46 - Partials 2678 2681 +3 

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

TheBlueMatt
TheBlueMatt previously approved these changes Jun 16, 2025

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I think there's a few more changes I want to make to this pipeline but this change by itself looks good.

@wpaulino

Copy link
Copy Markdown
Contributor

@whfuyn do you mind rebasing this? We're going to merge this as is to include it in a release and follow up with a test later.

When a channel is force-closed, there might be blocked monitor updates
not yet applied. But `latest_monitor_update_id` has been incremented and
assigned to these updates. This results in a panic when trying to apply
the `ChannelForceClosed` update. Use the unblocked update id instead.
Resolves: lightningdevkit#3857
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 0866405 to ceb5a55CompareJune 24, 2025 04:11
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

@wpaulino Sorry for the late response.

I had some trouble constructing a proper test without using MPP or multi-hop payments. My original test that triggered this problem only involved sending payments between two nodes connected by a single direct channel. However, when I searched the code related to blocked_monitor_updates, it seems only MPP and multi-hop payments can cause monitor updates to be blocked. This feels strange.

I've rebased this PR.

@wpaulino

Copy link
Copy Markdown
Contributor

A revoke_and_ack monitor update can also become blocked until the PaymentSent event is handled.

@TheBlueMatt
TheBlueMatt merged commit 0fe51c5 into lightningdevkit:mainJun 24, 2025
@TheBlueMattTheBlueMatt mentioned this pull request Jul 15, 2025
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Backported in #3932

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Jul 24, 2025
v0.1.5 - Jul 16, 2025 - "Async Path Reduction"
Performance Improvements
========================
* `NetworkGraph`'s expensive internal consistency checks have now been
disabled in debug builds in addition to release builds (lightningdevkit#3687).
Bug Fixes
=========
* Pathfinding which results in a multi-path payment is now substantially
smarter, using fewer paths and better optimizing fees and successes (lightningdevkit#3890).
* A counterparty delaying claiming multiple HTLCs with different expiries can
no longer cause our `ChannelMonitor` to continuously rebroadcast invalid
transactions or RBF bump attempts (lightningdevkit#3923).
* Reorgs can no longer cause us to fail to claim HTLCs after a counterparty
delayed claiming multiple HTLCs with different expiries (lightningdevkit#3923).
* Force-closing a channel while it is blocked on another channel's async
`ChannelMonitorUpdate` can no longer lead to a panic (lightningdevkit#3858).
* `ChannelMonitorUpdate`s can no longer be released to storage too early when
doing async updates or on restart. This only impacts async
`ChannelMonitorUpdate` persistence and can lead to loss of funds only in rare
cases with `ChannelMonitorUpdate` persistence order inversions (lightningdevkit#3907).
Security
========
0.1.5 fixes a vulnerability which could allow a peer to overdraw their reserve
value, potentially cutting into commitment transaction fees on channels with a
low reserve.
* Due to a bug in checking whether an HTLC is dust during acceptance, near-dust
HTLCs were not counted towards the commitment transaction fee, but did
eventually contribute to it when we built a commitment transaction. This can
be used by a counterparty to overdraw their reserve value, or, for channels
with a low reserve value, cut into the commitment transaction fee (lightningdevkit#3933).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panic when applying monitor update during channel force close

4 participants

@whfuyn@ldk-reviews-bot@wpaulino@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Fix update_id gap during force_shutdown - #3858

Merged
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap
Jun 24, 2025
Merged

Fix update_id gap during force_shutdown#3858
TheBlueMatt merged 1 commit into
lightningdevkit:mainfrom
whfuyn:fix-update-id-gap

Conversation

@whfuyn

Copy link
Copy Markdown
Contributor

When a channel is force-closed, there might be blocked monitor updates not yet applied. But latest_monitor_update_id has been incremented and assigned to these updates. This results in a panic when trying to apply the ChannelForceClosed update. Use the unblocked update id instead.

Resolves: #3857

@ldk-reviews-bot

ldk-reviews-bot commented Jun 13, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This should work, but do you mind including a test?

There are other scenarios where we also increment by 1, but those should not result in a panic as they are queued in blocked_monitor_updates. The force close update is the only one we let fly through regardless of blocked_monitor_updates.

Comment threadlightning/src/ln/channel.rs Outdated
@wpaulino
wpaulino removed the request for review from jkczyzJune 13, 2025 16:25
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 446155b to 5e6e74cCompareJune 13, 2025 17:23
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

Got it! Will add a test later.

@codecov

codecovBot commented Jun 13, 2025

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.62%. Comparing base (c48e0a8) to head (ceb5a55).
Report is 4 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #3858 +/- ##
==========================================
- Coverage 89.65% 89.62% -0.04% 
==========================================
Files 164 164 Lines 134658 134661 +3 Branches 134658 134661 +3 ==========================================
- Hits 120734 120688 -46 - Misses 11246 11292 +46 - Partials 2678 2681 +3 

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

TheBlueMatt
TheBlueMatt previously approved these changes Jun 16, 2025

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I think there's a few more changes I want to make to this pipeline but this change by itself looks good.

@wpaulino

Copy link
Copy Markdown
Contributor

@whfuyn do you mind rebasing this? We're going to merge this as is to include it in a release and follow up with a test later.

When a channel is force-closed, there might be blocked monitor updates
not yet applied. But `latest_monitor_update_id` has been incremented and
assigned to these updates. This results in a panic when trying to apply
the `ChannelForceClosed` update. Use the unblocked update id instead.
Resolves: lightningdevkit#3857
@whfuyn
whfuynforce-pushed the fix-update-id-gap branch from 0866405 to ceb5a55CompareJune 24, 2025 04:11
@whfuyn

Copy link
Copy Markdown
ContributorAuthor

@wpaulino Sorry for the late response.

I had some trouble constructing a proper test without using MPP or multi-hop payments. My original test that triggered this problem only involved sending payments between two nodes connected by a single direct channel. However, when I searched the code related to blocked_monitor_updates, it seems only MPP and multi-hop payments can cause monitor updates to be blocked. This feels strange.

I've rebased this PR.

@wpaulino

Copy link
Copy Markdown
Contributor

A revoke_and_ack monitor update can also become blocked until the PaymentSent event is handled.

@TheBlueMatt
TheBlueMatt merged commit 0fe51c5 into lightningdevkit:mainJun 24, 2025
@TheBlueMattTheBlueMatt mentioned this pull request Jul 15, 2025
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Backported in #3932

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Jul 24, 2025
v0.1.5 - Jul 16, 2025 - "Async Path Reduction"
Performance Improvements
========================
* `NetworkGraph`'s expensive internal consistency checks have now been
disabled in debug builds in addition to release builds (lightningdevkit#3687).
Bug Fixes
=========
* Pathfinding which results in a multi-path payment is now substantially
smarter, using fewer paths and better optimizing fees and successes (lightningdevkit#3890).
* A counterparty delaying claiming multiple HTLCs with different expiries can
no longer cause our `ChannelMonitor` to continuously rebroadcast invalid
transactions or RBF bump attempts (lightningdevkit#3923).
* Reorgs can no longer cause us to fail to claim HTLCs after a counterparty
delayed claiming multiple HTLCs with different expiries (lightningdevkit#3923).
* Force-closing a channel while it is blocked on another channel's async
`ChannelMonitorUpdate` can no longer lead to a panic (lightningdevkit#3858).
* `ChannelMonitorUpdate`s can no longer be released to storage too early when
doing async updates or on restart. This only impacts async
`ChannelMonitorUpdate` persistence and can lead to loss of funds only in rare
cases with `ChannelMonitorUpdate` persistence order inversions (lightningdevkit#3907).
Security
========
0.1.5 fixes a vulnerability which could allow a peer to overdraw their reserve
value, potentially cutting into commitment transaction fees on channels with a
low reserve.
* Due to a bug in checking whether an HTLC is dust during acceptance, near-dust
HTLCs were not counted towards the commitment transaction fee, but did
eventually contribute to it when we built a commitment transaction. This can
be used by a counterparty to overdraw their reserve value, or, for channels
with a low reserve value, cut into the commitment transaction fee (lightningdevkit#3933).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panic when applying monitor update during channel force close

4 participants

@whfuyn@ldk-reviews-bot@wpaulino@TheBlueMatt