[0.1] Further backports and draft release notes - #4710

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2
Jun 18, 2026
Merged

[0.1] Further backports and draft release notes#4710
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Backports #4667, #4684, #4697, #4707, and #4709. Did not include #4673 as its not as trivial and I'm not really sure UTXO lokup implementors should ever return a dup result.

jkczyzand others added 4 commits June 17, 2026 20:07
An offer advertising Quantity::Bounded expects at least one item, but
is_valid_quantity accepted a quantity of 0 since it only checked the
upper bound. Require the quantity to be greater than 0 so that an
invoice request for 0 items is rejected as an InvalidQuantity.
Co-Authored-By: Claude <noreply@anthropic.com>
Backport of 7620124
The `chanmon_consistency` fuzz target found a reconnect ordering where
`signer_pending_revoke_and_ack` and `monitor_pending_revoke_and_ack`
could both describe the same owed `revoke_and_ack`.
The channel first received a `commitment_signed` whose monitor update
completed, but the signer could not provide the next point or secret,
leaving `signer_pending_revoke_and_ack` set. Later, receiving the peer
`revoke_and_ack` freed holding-cell HTLCs and produced a held monitor
update. While that monitor update was still blocked,
`channel_reestablish` saw the peer one state behind and recorded
`monitor_pending_revoke_and_ack`, plus the corresponding monitor-pending
`commitment_signed`, so the messages could be replayed once monitor
updating was restored.
If the signer unblocked before the held monitor update was released,
`signer_maybe_unblocked` generated and sent the already monitor-safe RAA
using `signer_pending_revoke_and_ack`. The monitor-pending flag was not
cleared at that point, so `monitor_updating_restored` later generated
the same RAA again when the held update completed. The peer had already
advanced after accepting the signer-unblocked RAA, so it rejected the
duplicate secret as not corresponding to its current pubkey and
force-closed.
Fix this by clearing `monitor_pending_revoke_and_ack` in the
signer-resume path only once a signer-pending RAA is actually being
returned.
Backport of 27223fd
Conflicts resolved in:
* lightning/src/ln/async_signer_tests.rs
If we have a high (200%+) proportional fee as an intermediate blinded node
combined with a low inbound amount, we previously had some code that calculated
the outbound amount of the forward that would've underflowed. This would've
caused a panic in debug builds and caused us to relay a payment that should've
been rejected (due to being unable to cover our high fee) in release builds.
Reported by Project Loupe.
Backport of e560ec1
If a caller of send_payment_with_route provided a route with either no paths,
or where the first path had 0 hops, the method would panic due to attempting to
unwrap a dummy pubkey that was initialized with 32 bytes instead of the
required 33.
Reported by Project Loupe.
Backport of 54cdd85
@ldk-reviews-bot

ldk-reviews-bot commented Jun 17, 2026

Copy link
Copy Markdown

I've assigned @wpaulino 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.

@ldk-claude-review-bot

ldk-claude-review-bot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

The diff is unchanged from my prior two review passes, as confirmed by my memory notes. All production code changes remain correct.

No issues found.

The diff is unchanged from prior review passes. All production code changes remain correct:

  • lightning/src/blinded_path/payment.rs:525inbound_amt.checked_sub(fee)? properly guards the underflow and returns None as documented.
  • lightning/src/ln/channelmanager.rs:4728 — dummy pubkey corrected to [2; 33] (valid 33-byte compressed key length).
  • lightning-custom-message/src/lib.rs:366Ok(None) instead of unreachable!() correctly handles peer-provided unknown message types within a sub-handler's range.
  • lightning/src/offers/offer.rs:908quantity > 0 && quantity <= n.get() correctly rejects 0 for bounded quantities.
  • lightning/src/ln/channel.rs:6122 — clearing monitor_pending_revoke_and_ack when an RAA is regenerated via the signer-pending path prevents duplicate RAA generation.

The remaining additions are tests and CHANGELOG release notes, consistent with the fixes.

@tnulltnull 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.

Reviewed release notes, LGTM

Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 167d648 to e2c8d21CompareJune 18, 2026 13:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Updated release notes with feedback incl from #4706:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d259c7a23..5fb5c9b157 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -9,3 +9,4 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in BOLT 12 `OfferBuilder` (#4324).+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ now maps 0-amounts to an amount of `None` (#4324).@@ -20,3 +21,4 @@
could have become stuck (#4520).
- * The electrum sync client now properly skips unconfirmed transactions (#4590).+ * The presence of unconfirmed transactions actually no longer causes+ `ElectrumSyncClient` to spuriously fail to sync (#4590).
* `FilesystemStore::list_all_keys` will no longer fail if there are stale

Comment threadCHANGELOG.md Outdated
Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from e2c8d21 to 5cac547CompareJune 18, 2026 16:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a typo and named the release:

$ git diff-tree -U1 e2c8d21de 5cac547d1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fb5c9b157..a6fd5bfb18 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - XXX - "XXX"+# 0.1.10 - Jun 18, 2026 - "An Older Loupe"@@ -9,3 +9,3 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 5cac547 to 8caaa3eCompareJune 18, 2026 16:12
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed further typos from #4706

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6fd5bfb18..67e929a5fc 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -3,9 +3,9 @@
## API Updates
- * `DefaultMessageRouter` will now always generate blinded message paths which+ * `DefaultMessageRouter` will now always generate blinded message paths that
provide no privacy (where our node is the introduction node) for nodes with
public channels. This works around an issue which will appear for any nodes
- with LND peers which enable onion messaging - such peers will refuse to+ with LND peers that enable onion messaging - such peers will refuse to
forward BOLT 12 messages from unknown third parties, which most BOLT 12
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`+ * Explicit `amount_msats` of 0 is rejected in BOLT 12 `Offer`s; `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).
@@ -31,3 +31,3 @@
`ChannelManager::abandon_payment` was called before the payment ultimately
- completing anyway (#4651).+ completes anyway (#4651).
* Syncing a `ChainMonitor` using the `Confirm` trait will no longer write some
@@ -44,4 +44,4 @@
* `InvoiceRequestBuilder` will no longer accept a `quantity` of `0` for a
- `Bolt12Offer` allowing any quantity up to a bound (#4667).- * `lightning-custom-message` handlers which return `Ok(None)` when asked to+ BOLT 12 `Offer`, allowing any quantity up to a bound (#4667).+ * `lightning-custom-message` handlers that return `Ok(None)` when asked to
deserialize a message in their defined range no longer cause panics (#4709).

Comment threadCHANGELOG.md Outdated
@@ -1,9 +1,67 @@
# 0.1.10 - Jun 18, 2026 - "An Older Loupe"

@valentinewallacevalentinewallaceJun 18, 2026

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.

A Strange Loupe

Loupe de Loupe

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I was thinking in reference to the Through the Loupe for 0.2.3. What is strange in reference to?

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.

Ahh. It's a famous book (I haven't read it) https://en.wikipedia.org/wiki/I_Am_a_Strange_Loop

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Took Loupe de Loupe.

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch 2 times, most recently from d35fa91 to 43efc52CompareJune 18, 2026 17:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Corrected the text for 4697:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67e929a5fc..09dfe4e55e 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - Jun 18, 2026 - "An Older Loupe"+# 0.1.10 - Jun 18, 2026 - "Loupe de Loupe"@@ -26,3 +26,4 @@
* When forwarding an HTLC while in a blinded path with proportional fees over
- 100%, LDK will no longer spuriously charge 1 msat too little (#4697).+ 200%, LDK will no longer spuriously allow a forward that pays us 1 msat too+ little in fees (#4697).
* Fixed a rare case where a channel could get stuck on reconnect when using

jkczyzand others added 2 commits June 18, 2026 17:19
A handler built with `composite_custom_message_handler!` routes an incoming
message type to the sub-handler whose pattern matches it and assumed the
sub-handler would always decode it. But per the `CustomMessageReader`
contract a sub-handler returns `Ok(None)` for a type it doesn't recognize,
and a sub-handler's pattern -- a range in particular -- can be broader than
the types it actually decodes.
Since the message type comes from peer input, this let a remote peer panic
the message-processing thread with a single custom message whose type falls
in a sub-handler's pattern but isn't decoded by it. Report such a message as
unknown instead, matching how `wire::do_read` handles an undecoded custom
message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Backport of 77ac339
Silent conflicts resolved in:
* lightning-custom-message/src/lib.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 43efc52 to e225350CompareJune 18, 2026 17:19
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a backport missed conflict:

diff --git a/lightning-custom-message/src/lib.rs b/lightning-custom-message/src/lib.rs
index 0f55dcb842..5a9fa691dc 100644
--- a/lightning-custom-message/src/lib.rs+++ b/lightning-custom-message/src/lib.rs@@ -512,3 +512,3 @@ mod tests {
type CustomMessage = Foo;
- fn read<R: LengthLimitedRead>(+ fn read<R: Read>(
&self, message_type: u16, _b: &mut R,

@TheBlueMattTheBlueMatt mentioned this pull request Jun 18, 2026
@TheBlueMatt
TheBlueMatt merged commit 0cf27ff into lightningdevkit:0.1Jun 18, 2026
3 checks passed
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.

7 participants

@TheBlueMatt@ldk-reviews-bot@ldk-claude-review-bot@tnull@jkczyz@valentinewallace@wpaulino
, '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

[0.1] Further backports and draft release notes - #4710

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2
Jun 18, 2026
Merged

[0.1] Further backports and draft release notes#4710
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Backports #4667, #4684, #4697, #4707, and #4709. Did not include #4673 as its not as trivial and I'm not really sure UTXO lokup implementors should ever return a dup result.

jkczyzand others added 4 commits June 17, 2026 20:07
An offer advertising Quantity::Bounded expects at least one item, but
is_valid_quantity accepted a quantity of 0 since it only checked the
upper bound. Require the quantity to be greater than 0 so that an
invoice request for 0 items is rejected as an InvalidQuantity.
Co-Authored-By: Claude <noreply@anthropic.com>
Backport of 7620124
The `chanmon_consistency` fuzz target found a reconnect ordering where
`signer_pending_revoke_and_ack` and `monitor_pending_revoke_and_ack`
could both describe the same owed `revoke_and_ack`.
The channel first received a `commitment_signed` whose monitor update
completed, but the signer could not provide the next point or secret,
leaving `signer_pending_revoke_and_ack` set. Later, receiving the peer
`revoke_and_ack` freed holding-cell HTLCs and produced a held monitor
update. While that monitor update was still blocked,
`channel_reestablish` saw the peer one state behind and recorded
`monitor_pending_revoke_and_ack`, plus the corresponding monitor-pending
`commitment_signed`, so the messages could be replayed once monitor
updating was restored.
If the signer unblocked before the held monitor update was released,
`signer_maybe_unblocked` generated and sent the already monitor-safe RAA
using `signer_pending_revoke_and_ack`. The monitor-pending flag was not
cleared at that point, so `monitor_updating_restored` later generated
the same RAA again when the held update completed. The peer had already
advanced after accepting the signer-unblocked RAA, so it rejected the
duplicate secret as not corresponding to its current pubkey and
force-closed.
Fix this by clearing `monitor_pending_revoke_and_ack` in the
signer-resume path only once a signer-pending RAA is actually being
returned.
Backport of 27223fd
Conflicts resolved in:
* lightning/src/ln/async_signer_tests.rs
If we have a high (200%+) proportional fee as an intermediate blinded node
combined with a low inbound amount, we previously had some code that calculated
the outbound amount of the forward that would've underflowed. This would've
caused a panic in debug builds and caused us to relay a payment that should've
been rejected (due to being unable to cover our high fee) in release builds.
Reported by Project Loupe.
Backport of e560ec1
If a caller of send_payment_with_route provided a route with either no paths,
or where the first path had 0 hops, the method would panic due to attempting to
unwrap a dummy pubkey that was initialized with 32 bytes instead of the
required 33.
Reported by Project Loupe.
Backport of 54cdd85
@ldk-reviews-bot

ldk-reviews-bot commented Jun 17, 2026

Copy link
Copy Markdown

I've assigned @wpaulino 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.

@ldk-claude-review-bot

ldk-claude-review-bot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

The diff is unchanged from my prior two review passes, as confirmed by my memory notes. All production code changes remain correct.

No issues found.

The diff is unchanged from prior review passes. All production code changes remain correct:

  • lightning/src/blinded_path/payment.rs:525inbound_amt.checked_sub(fee)? properly guards the underflow and returns None as documented.
  • lightning/src/ln/channelmanager.rs:4728 — dummy pubkey corrected to [2; 33] (valid 33-byte compressed key length).
  • lightning-custom-message/src/lib.rs:366Ok(None) instead of unreachable!() correctly handles peer-provided unknown message types within a sub-handler's range.
  • lightning/src/offers/offer.rs:908quantity > 0 && quantity <= n.get() correctly rejects 0 for bounded quantities.
  • lightning/src/ln/channel.rs:6122 — clearing monitor_pending_revoke_and_ack when an RAA is regenerated via the signer-pending path prevents duplicate RAA generation.

The remaining additions are tests and CHANGELOG release notes, consistent with the fixes.

@tnulltnull 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.

Reviewed release notes, LGTM

Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 167d648 to e2c8d21CompareJune 18, 2026 13:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Updated release notes with feedback incl from #4706:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d259c7a23..5fb5c9b157 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -9,3 +9,4 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in BOLT 12 `OfferBuilder` (#4324).+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ now maps 0-amounts to an amount of `None` (#4324).@@ -20,3 +21,4 @@
could have become stuck (#4520).
- * The electrum sync client now properly skips unconfirmed transactions (#4590).+ * The presence of unconfirmed transactions actually no longer causes+ `ElectrumSyncClient` to spuriously fail to sync (#4590).
* `FilesystemStore::list_all_keys` will no longer fail if there are stale

Comment threadCHANGELOG.md Outdated
Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from e2c8d21 to 5cac547CompareJune 18, 2026 16:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a typo and named the release:

$ git diff-tree -U1 e2c8d21de 5cac547d1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fb5c9b157..a6fd5bfb18 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - XXX - "XXX"+# 0.1.10 - Jun 18, 2026 - "An Older Loupe"@@ -9,3 +9,3 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 5cac547 to 8caaa3eCompareJune 18, 2026 16:12
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed further typos from #4706

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6fd5bfb18..67e929a5fc 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -3,9 +3,9 @@
## API Updates
- * `DefaultMessageRouter` will now always generate blinded message paths which+ * `DefaultMessageRouter` will now always generate blinded message paths that
provide no privacy (where our node is the introduction node) for nodes with
public channels. This works around an issue which will appear for any nodes
- with LND peers which enable onion messaging - such peers will refuse to+ with LND peers that enable onion messaging - such peers will refuse to
forward BOLT 12 messages from unknown third parties, which most BOLT 12
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`+ * Explicit `amount_msats` of 0 is rejected in BOLT 12 `Offer`s; `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).
@@ -31,3 +31,3 @@
`ChannelManager::abandon_payment` was called before the payment ultimately
- completing anyway (#4651).+ completes anyway (#4651).
* Syncing a `ChainMonitor` using the `Confirm` trait will no longer write some
@@ -44,4 +44,4 @@
* `InvoiceRequestBuilder` will no longer accept a `quantity` of `0` for a
- `Bolt12Offer` allowing any quantity up to a bound (#4667).- * `lightning-custom-message` handlers which return `Ok(None)` when asked to+ BOLT 12 `Offer`, allowing any quantity up to a bound (#4667).+ * `lightning-custom-message` handlers that return `Ok(None)` when asked to
deserialize a message in their defined range no longer cause panics (#4709).

Comment threadCHANGELOG.md Outdated
@@ -1,9 +1,67 @@
# 0.1.10 - Jun 18, 2026 - "An Older Loupe"

@valentinewallacevalentinewallaceJun 18, 2026

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.

A Strange Loupe

Loupe de Loupe

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I was thinking in reference to the Through the Loupe for 0.2.3. What is strange in reference to?

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.

Ahh. It's a famous book (I haven't read it) https://en.wikipedia.org/wiki/I_Am_a_Strange_Loop

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Took Loupe de Loupe.

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch 2 times, most recently from d35fa91 to 43efc52CompareJune 18, 2026 17:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Corrected the text for 4697:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67e929a5fc..09dfe4e55e 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - Jun 18, 2026 - "An Older Loupe"+# 0.1.10 - Jun 18, 2026 - "Loupe de Loupe"@@ -26,3 +26,4 @@
* When forwarding an HTLC while in a blinded path with proportional fees over
- 100%, LDK will no longer spuriously charge 1 msat too little (#4697).+ 200%, LDK will no longer spuriously allow a forward that pays us 1 msat too+ little in fees (#4697).
* Fixed a rare case where a channel could get stuck on reconnect when using

jkczyzand others added 2 commits June 18, 2026 17:19
A handler built with `composite_custom_message_handler!` routes an incoming
message type to the sub-handler whose pattern matches it and assumed the
sub-handler would always decode it. But per the `CustomMessageReader`
contract a sub-handler returns `Ok(None)` for a type it doesn't recognize,
and a sub-handler's pattern -- a range in particular -- can be broader than
the types it actually decodes.
Since the message type comes from peer input, this let a remote peer panic
the message-processing thread with a single custom message whose type falls
in a sub-handler's pattern but isn't decoded by it. Report such a message as
unknown instead, matching how `wire::do_read` handles an undecoded custom
message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Backport of 77ac339
Silent conflicts resolved in:
* lightning-custom-message/src/lib.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 43efc52 to e225350CompareJune 18, 2026 17:19
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a backport missed conflict:

diff --git a/lightning-custom-message/src/lib.rs b/lightning-custom-message/src/lib.rs
index 0f55dcb842..5a9fa691dc 100644
--- a/lightning-custom-message/src/lib.rs+++ b/lightning-custom-message/src/lib.rs@@ -512,3 +512,3 @@ mod tests {
type CustomMessage = Foo;
- fn read<R: LengthLimitedRead>(+ fn read<R: Read>(
&self, message_type: u16, _b: &mut R,

@TheBlueMattTheBlueMatt mentioned this pull request Jun 18, 2026
@TheBlueMatt
TheBlueMatt merged commit 0cf27ff into lightningdevkit:0.1Jun 18, 2026
3 checks passed
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.

7 participants

@TheBlueMatt@ldk-reviews-bot@ldk-claude-review-bot@tnull@jkczyz@valentinewallace@wpaulino
, '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

[0.1] Further backports and draft release notes - #4710

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2
Jun 18, 2026
Merged

[0.1] Further backports and draft release notes#4710
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Backports #4667, #4684, #4697, #4707, and #4709. Did not include #4673 as its not as trivial and I'm not really sure UTXO lokup implementors should ever return a dup result.

jkczyzand others added 4 commits June 17, 2026 20:07
An offer advertising Quantity::Bounded expects at least one item, but
is_valid_quantity accepted a quantity of 0 since it only checked the
upper bound. Require the quantity to be greater than 0 so that an
invoice request for 0 items is rejected as an InvalidQuantity.
Co-Authored-By: Claude <noreply@anthropic.com>
Backport of 7620124
The `chanmon_consistency` fuzz target found a reconnect ordering where
`signer_pending_revoke_and_ack` and `monitor_pending_revoke_and_ack`
could both describe the same owed `revoke_and_ack`.
The channel first received a `commitment_signed` whose monitor update
completed, but the signer could not provide the next point or secret,
leaving `signer_pending_revoke_and_ack` set. Later, receiving the peer
`revoke_and_ack` freed holding-cell HTLCs and produced a held monitor
update. While that monitor update was still blocked,
`channel_reestablish` saw the peer one state behind and recorded
`monitor_pending_revoke_and_ack`, plus the corresponding monitor-pending
`commitment_signed`, so the messages could be replayed once monitor
updating was restored.
If the signer unblocked before the held monitor update was released,
`signer_maybe_unblocked` generated and sent the already monitor-safe RAA
using `signer_pending_revoke_and_ack`. The monitor-pending flag was not
cleared at that point, so `monitor_updating_restored` later generated
the same RAA again when the held update completed. The peer had already
advanced after accepting the signer-unblocked RAA, so it rejected the
duplicate secret as not corresponding to its current pubkey and
force-closed.
Fix this by clearing `monitor_pending_revoke_and_ack` in the
signer-resume path only once a signer-pending RAA is actually being
returned.
Backport of 27223fd
Conflicts resolved in:
* lightning/src/ln/async_signer_tests.rs
If we have a high (200%+) proportional fee as an intermediate blinded node
combined with a low inbound amount, we previously had some code that calculated
the outbound amount of the forward that would've underflowed. This would've
caused a panic in debug builds and caused us to relay a payment that should've
been rejected (due to being unable to cover our high fee) in release builds.
Reported by Project Loupe.
Backport of e560ec1
If a caller of send_payment_with_route provided a route with either no paths,
or where the first path had 0 hops, the method would panic due to attempting to
unwrap a dummy pubkey that was initialized with 32 bytes instead of the
required 33.
Reported by Project Loupe.
Backport of 54cdd85
@ldk-reviews-bot

ldk-reviews-bot commented Jun 17, 2026

Copy link
Copy Markdown

I've assigned @wpaulino 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.

@ldk-claude-review-bot

ldk-claude-review-bot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

The diff is unchanged from my prior two review passes, as confirmed by my memory notes. All production code changes remain correct.

No issues found.

The diff is unchanged from prior review passes. All production code changes remain correct:

  • lightning/src/blinded_path/payment.rs:525inbound_amt.checked_sub(fee)? properly guards the underflow and returns None as documented.
  • lightning/src/ln/channelmanager.rs:4728 — dummy pubkey corrected to [2; 33] (valid 33-byte compressed key length).
  • lightning-custom-message/src/lib.rs:366Ok(None) instead of unreachable!() correctly handles peer-provided unknown message types within a sub-handler's range.
  • lightning/src/offers/offer.rs:908quantity > 0 && quantity <= n.get() correctly rejects 0 for bounded quantities.
  • lightning/src/ln/channel.rs:6122 — clearing monitor_pending_revoke_and_ack when an RAA is regenerated via the signer-pending path prevents duplicate RAA generation.

The remaining additions are tests and CHANGELOG release notes, consistent with the fixes.

@tnulltnull 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.

Reviewed release notes, LGTM

Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 167d648 to e2c8d21CompareJune 18, 2026 13:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Updated release notes with feedback incl from #4706:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d259c7a23..5fb5c9b157 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -9,3 +9,4 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in BOLT 12 `OfferBuilder` (#4324).+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ now maps 0-amounts to an amount of `None` (#4324).@@ -20,3 +21,4 @@
could have become stuck (#4520).
- * The electrum sync client now properly skips unconfirmed transactions (#4590).+ * The presence of unconfirmed transactions actually no longer causes+ `ElectrumSyncClient` to spuriously fail to sync (#4590).
* `FilesystemStore::list_all_keys` will no longer fail if there are stale

Comment threadCHANGELOG.md Outdated
Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from e2c8d21 to 5cac547CompareJune 18, 2026 16:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a typo and named the release:

$ git diff-tree -U1 e2c8d21de 5cac547d1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fb5c9b157..a6fd5bfb18 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - XXX - "XXX"+# 0.1.10 - Jun 18, 2026 - "An Older Loupe"@@ -9,3 +9,3 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 5cac547 to 8caaa3eCompareJune 18, 2026 16:12
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed further typos from #4706

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6fd5bfb18..67e929a5fc 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -3,9 +3,9 @@
## API Updates
- * `DefaultMessageRouter` will now always generate blinded message paths which+ * `DefaultMessageRouter` will now always generate blinded message paths that
provide no privacy (where our node is the introduction node) for nodes with
public channels. This works around an issue which will appear for any nodes
- with LND peers which enable onion messaging - such peers will refuse to+ with LND peers that enable onion messaging - such peers will refuse to
forward BOLT 12 messages from unknown third parties, which most BOLT 12
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`+ * Explicit `amount_msats` of 0 is rejected in BOLT 12 `Offer`s; `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).
@@ -31,3 +31,3 @@
`ChannelManager::abandon_payment` was called before the payment ultimately
- completing anyway (#4651).+ completes anyway (#4651).
* Syncing a `ChainMonitor` using the `Confirm` trait will no longer write some
@@ -44,4 +44,4 @@
* `InvoiceRequestBuilder` will no longer accept a `quantity` of `0` for a
- `Bolt12Offer` allowing any quantity up to a bound (#4667).- * `lightning-custom-message` handlers which return `Ok(None)` when asked to+ BOLT 12 `Offer`, allowing any quantity up to a bound (#4667).+ * `lightning-custom-message` handlers that return `Ok(None)` when asked to
deserialize a message in their defined range no longer cause panics (#4709).

Comment threadCHANGELOG.md Outdated
@@ -1,9 +1,67 @@
# 0.1.10 - Jun 18, 2026 - "An Older Loupe"

@valentinewallacevalentinewallaceJun 18, 2026

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.

A Strange Loupe

Loupe de Loupe

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I was thinking in reference to the Through the Loupe for 0.2.3. What is strange in reference to?

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.

Ahh. It's a famous book (I haven't read it) https://en.wikipedia.org/wiki/I_Am_a_Strange_Loop

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Took Loupe de Loupe.

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch 2 times, most recently from d35fa91 to 43efc52CompareJune 18, 2026 17:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Corrected the text for 4697:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67e929a5fc..09dfe4e55e 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - Jun 18, 2026 - "An Older Loupe"+# 0.1.10 - Jun 18, 2026 - "Loupe de Loupe"@@ -26,3 +26,4 @@
* When forwarding an HTLC while in a blinded path with proportional fees over
- 100%, LDK will no longer spuriously charge 1 msat too little (#4697).+ 200%, LDK will no longer spuriously allow a forward that pays us 1 msat too+ little in fees (#4697).
* Fixed a rare case where a channel could get stuck on reconnect when using

jkczyzand others added 2 commits June 18, 2026 17:19
A handler built with `composite_custom_message_handler!` routes an incoming
message type to the sub-handler whose pattern matches it and assumed the
sub-handler would always decode it. But per the `CustomMessageReader`
contract a sub-handler returns `Ok(None)` for a type it doesn't recognize,
and a sub-handler's pattern -- a range in particular -- can be broader than
the types it actually decodes.
Since the message type comes from peer input, this let a remote peer panic
the message-processing thread with a single custom message whose type falls
in a sub-handler's pattern but isn't decoded by it. Report such a message as
unknown instead, matching how `wire::do_read` handles an undecoded custom
message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Backport of 77ac339
Silent conflicts resolved in:
* lightning-custom-message/src/lib.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 43efc52 to e225350CompareJune 18, 2026 17:19
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a backport missed conflict:

diff --git a/lightning-custom-message/src/lib.rs b/lightning-custom-message/src/lib.rs
index 0f55dcb842..5a9fa691dc 100644
--- a/lightning-custom-message/src/lib.rs+++ b/lightning-custom-message/src/lib.rs@@ -512,3 +512,3 @@ mod tests {
type CustomMessage = Foo;
- fn read<R: LengthLimitedRead>(+ fn read<R: Read>(
&self, message_type: u16, _b: &mut R,

@TheBlueMattTheBlueMatt mentioned this pull request Jun 18, 2026
@TheBlueMatt
TheBlueMatt merged commit 0cf27ff into lightningdevkit:0.1Jun 18, 2026
3 checks passed
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.

7 participants

@TheBlueMatt@ldk-reviews-bot@ldk-claude-review-bot@tnull@jkczyz@valentinewallace@wpaulino
, '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

[0.1] Further backports and draft release notes - #4710

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2
Jun 18, 2026
Merged

[0.1] Further backports and draft release notes#4710
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Backports #4667, #4684, #4697, #4707, and #4709. Did not include #4673 as its not as trivial and I'm not really sure UTXO lokup implementors should ever return a dup result.

jkczyzand others added 4 commits June 17, 2026 20:07
An offer advertising Quantity::Bounded expects at least one item, but
is_valid_quantity accepted a quantity of 0 since it only checked the
upper bound. Require the quantity to be greater than 0 so that an
invoice request for 0 items is rejected as an InvalidQuantity.
Co-Authored-By: Claude <noreply@anthropic.com>
Backport of 7620124
The `chanmon_consistency` fuzz target found a reconnect ordering where
`signer_pending_revoke_and_ack` and `monitor_pending_revoke_and_ack`
could both describe the same owed `revoke_and_ack`.
The channel first received a `commitment_signed` whose monitor update
completed, but the signer could not provide the next point or secret,
leaving `signer_pending_revoke_and_ack` set. Later, receiving the peer
`revoke_and_ack` freed holding-cell HTLCs and produced a held monitor
update. While that monitor update was still blocked,
`channel_reestablish` saw the peer one state behind and recorded
`monitor_pending_revoke_and_ack`, plus the corresponding monitor-pending
`commitment_signed`, so the messages could be replayed once monitor
updating was restored.
If the signer unblocked before the held monitor update was released,
`signer_maybe_unblocked` generated and sent the already monitor-safe RAA
using `signer_pending_revoke_and_ack`. The monitor-pending flag was not
cleared at that point, so `monitor_updating_restored` later generated
the same RAA again when the held update completed. The peer had already
advanced after accepting the signer-unblocked RAA, so it rejected the
duplicate secret as not corresponding to its current pubkey and
force-closed.
Fix this by clearing `monitor_pending_revoke_and_ack` in the
signer-resume path only once a signer-pending RAA is actually being
returned.
Backport of 27223fd
Conflicts resolved in:
* lightning/src/ln/async_signer_tests.rs
If we have a high (200%+) proportional fee as an intermediate blinded node
combined with a low inbound amount, we previously had some code that calculated
the outbound amount of the forward that would've underflowed. This would've
caused a panic in debug builds and caused us to relay a payment that should've
been rejected (due to being unable to cover our high fee) in release builds.
Reported by Project Loupe.
Backport of e560ec1
If a caller of send_payment_with_route provided a route with either no paths,
or where the first path had 0 hops, the method would panic due to attempting to
unwrap a dummy pubkey that was initialized with 32 bytes instead of the
required 33.
Reported by Project Loupe.
Backport of 54cdd85
@ldk-reviews-bot

ldk-reviews-bot commented Jun 17, 2026

Copy link
Copy Markdown

I've assigned @wpaulino 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.

@ldk-claude-review-bot

ldk-claude-review-bot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

The diff is unchanged from my prior two review passes, as confirmed by my memory notes. All production code changes remain correct.

No issues found.

The diff is unchanged from prior review passes. All production code changes remain correct:

  • lightning/src/blinded_path/payment.rs:525inbound_amt.checked_sub(fee)? properly guards the underflow and returns None as documented.
  • lightning/src/ln/channelmanager.rs:4728 — dummy pubkey corrected to [2; 33] (valid 33-byte compressed key length).
  • lightning-custom-message/src/lib.rs:366Ok(None) instead of unreachable!() correctly handles peer-provided unknown message types within a sub-handler's range.
  • lightning/src/offers/offer.rs:908quantity > 0 && quantity <= n.get() correctly rejects 0 for bounded quantities.
  • lightning/src/ln/channel.rs:6122 — clearing monitor_pending_revoke_and_ack when an RAA is regenerated via the signer-pending path prevents duplicate RAA generation.

The remaining additions are tests and CHANGELOG release notes, consistent with the fixes.

@tnulltnull 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.

Reviewed release notes, LGTM

Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 167d648 to e2c8d21CompareJune 18, 2026 13:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Updated release notes with feedback incl from #4706:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d259c7a23..5fb5c9b157 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -9,3 +9,4 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in BOLT 12 `OfferBuilder` (#4324).+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ now maps 0-amounts to an amount of `None` (#4324).@@ -20,3 +21,4 @@
could have become stuck (#4520).
- * The electrum sync client now properly skips unconfirmed transactions (#4590).+ * The presence of unconfirmed transactions actually no longer causes+ `ElectrumSyncClient` to spuriously fail to sync (#4590).
* `FilesystemStore::list_all_keys` will no longer fail if there are stale

Comment threadCHANGELOG.md Outdated
Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from e2c8d21 to 5cac547CompareJune 18, 2026 16:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a typo and named the release:

$ git diff-tree -U1 e2c8d21de 5cac547d1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fb5c9b157..a6fd5bfb18 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - XXX - "XXX"+# 0.1.10 - Jun 18, 2026 - "An Older Loupe"@@ -9,3 +9,3 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 5cac547 to 8caaa3eCompareJune 18, 2026 16:12
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed further typos from #4706

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6fd5bfb18..67e929a5fc 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -3,9 +3,9 @@
## API Updates
- * `DefaultMessageRouter` will now always generate blinded message paths which+ * `DefaultMessageRouter` will now always generate blinded message paths that
provide no privacy (where our node is the introduction node) for nodes with
public channels. This works around an issue which will appear for any nodes
- with LND peers which enable onion messaging - such peers will refuse to+ with LND peers that enable onion messaging - such peers will refuse to
forward BOLT 12 messages from unknown third parties, which most BOLT 12
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`+ * Explicit `amount_msats` of 0 is rejected in BOLT 12 `Offer`s; `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).
@@ -31,3 +31,3 @@
`ChannelManager::abandon_payment` was called before the payment ultimately
- completing anyway (#4651).+ completes anyway (#4651).
* Syncing a `ChainMonitor` using the `Confirm` trait will no longer write some
@@ -44,4 +44,4 @@
* `InvoiceRequestBuilder` will no longer accept a `quantity` of `0` for a
- `Bolt12Offer` allowing any quantity up to a bound (#4667).- * `lightning-custom-message` handlers which return `Ok(None)` when asked to+ BOLT 12 `Offer`, allowing any quantity up to a bound (#4667).+ * `lightning-custom-message` handlers that return `Ok(None)` when asked to
deserialize a message in their defined range no longer cause panics (#4709).

Comment threadCHANGELOG.md Outdated
@@ -1,9 +1,67 @@
# 0.1.10 - Jun 18, 2026 - "An Older Loupe"

@valentinewallacevalentinewallaceJun 18, 2026

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.

A Strange Loupe

Loupe de Loupe

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I was thinking in reference to the Through the Loupe for 0.2.3. What is strange in reference to?

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.

Ahh. It's a famous book (I haven't read it) https://en.wikipedia.org/wiki/I_Am_a_Strange_Loop

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Took Loupe de Loupe.

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch 2 times, most recently from d35fa91 to 43efc52CompareJune 18, 2026 17:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Corrected the text for 4697:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67e929a5fc..09dfe4e55e 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - Jun 18, 2026 - "An Older Loupe"+# 0.1.10 - Jun 18, 2026 - "Loupe de Loupe"@@ -26,3 +26,4 @@
* When forwarding an HTLC while in a blinded path with proportional fees over
- 100%, LDK will no longer spuriously charge 1 msat too little (#4697).+ 200%, LDK will no longer spuriously allow a forward that pays us 1 msat too+ little in fees (#4697).
* Fixed a rare case where a channel could get stuck on reconnect when using

jkczyzand others added 2 commits June 18, 2026 17:19
A handler built with `composite_custom_message_handler!` routes an incoming
message type to the sub-handler whose pattern matches it and assumed the
sub-handler would always decode it. But per the `CustomMessageReader`
contract a sub-handler returns `Ok(None)` for a type it doesn't recognize,
and a sub-handler's pattern -- a range in particular -- can be broader than
the types it actually decodes.
Since the message type comes from peer input, this let a remote peer panic
the message-processing thread with a single custom message whose type falls
in a sub-handler's pattern but isn't decoded by it. Report such a message as
unknown instead, matching how `wire::do_read` handles an undecoded custom
message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Backport of 77ac339
Silent conflicts resolved in:
* lightning-custom-message/src/lib.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 43efc52 to e225350CompareJune 18, 2026 17:19
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a backport missed conflict:

diff --git a/lightning-custom-message/src/lib.rs b/lightning-custom-message/src/lib.rs
index 0f55dcb842..5a9fa691dc 100644
--- a/lightning-custom-message/src/lib.rs+++ b/lightning-custom-message/src/lib.rs@@ -512,3 +512,3 @@ mod tests {
type CustomMessage = Foo;
- fn read<R: LengthLimitedRead>(+ fn read<R: Read>(
&self, message_type: u16, _b: &mut R,

@TheBlueMattTheBlueMatt mentioned this pull request Jun 18, 2026
@TheBlueMatt
TheBlueMatt merged commit 0cf27ff into lightningdevkit:0.1Jun 18, 2026
3 checks passed
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.

7 participants

@TheBlueMatt@ldk-reviews-bot@ldk-claude-review-bot@tnull@jkczyz@valentinewallace@wpaulino
, '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

[0.1] Further backports and draft release notes - #4710

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2
Jun 18, 2026
Merged

[0.1] Further backports and draft release notes#4710
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Backports #4667, #4684, #4697, #4707, and #4709. Did not include #4673 as its not as trivial and I'm not really sure UTXO lokup implementors should ever return a dup result.

jkczyzand others added 4 commits June 17, 2026 20:07
An offer advertising Quantity::Bounded expects at least one item, but
is_valid_quantity accepted a quantity of 0 since it only checked the
upper bound. Require the quantity to be greater than 0 so that an
invoice request for 0 items is rejected as an InvalidQuantity.
Co-Authored-By: Claude <noreply@anthropic.com>
Backport of 7620124
The `chanmon_consistency` fuzz target found a reconnect ordering where
`signer_pending_revoke_and_ack` and `monitor_pending_revoke_and_ack`
could both describe the same owed `revoke_and_ack`.
The channel first received a `commitment_signed` whose monitor update
completed, but the signer could not provide the next point or secret,
leaving `signer_pending_revoke_and_ack` set. Later, receiving the peer
`revoke_and_ack` freed holding-cell HTLCs and produced a held monitor
update. While that monitor update was still blocked,
`channel_reestablish` saw the peer one state behind and recorded
`monitor_pending_revoke_and_ack`, plus the corresponding monitor-pending
`commitment_signed`, so the messages could be replayed once monitor
updating was restored.
If the signer unblocked before the held monitor update was released,
`signer_maybe_unblocked` generated and sent the already monitor-safe RAA
using `signer_pending_revoke_and_ack`. The monitor-pending flag was not
cleared at that point, so `monitor_updating_restored` later generated
the same RAA again when the held update completed. The peer had already
advanced after accepting the signer-unblocked RAA, so it rejected the
duplicate secret as not corresponding to its current pubkey and
force-closed.
Fix this by clearing `monitor_pending_revoke_and_ack` in the
signer-resume path only once a signer-pending RAA is actually being
returned.
Backport of 27223fd
Conflicts resolved in:
* lightning/src/ln/async_signer_tests.rs
If we have a high (200%+) proportional fee as an intermediate blinded node
combined with a low inbound amount, we previously had some code that calculated
the outbound amount of the forward that would've underflowed. This would've
caused a panic in debug builds and caused us to relay a payment that should've
been rejected (due to being unable to cover our high fee) in release builds.
Reported by Project Loupe.
Backport of e560ec1
If a caller of send_payment_with_route provided a route with either no paths,
or where the first path had 0 hops, the method would panic due to attempting to
unwrap a dummy pubkey that was initialized with 32 bytes instead of the
required 33.
Reported by Project Loupe.
Backport of 54cdd85
@ldk-reviews-bot

ldk-reviews-bot commented Jun 17, 2026

Copy link
Copy Markdown

I've assigned @wpaulino 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.

@ldk-claude-review-bot

ldk-claude-review-bot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

The diff is unchanged from my prior two review passes, as confirmed by my memory notes. All production code changes remain correct.

No issues found.

The diff is unchanged from prior review passes. All production code changes remain correct:

  • lightning/src/blinded_path/payment.rs:525inbound_amt.checked_sub(fee)? properly guards the underflow and returns None as documented.
  • lightning/src/ln/channelmanager.rs:4728 — dummy pubkey corrected to [2; 33] (valid 33-byte compressed key length).
  • lightning-custom-message/src/lib.rs:366Ok(None) instead of unreachable!() correctly handles peer-provided unknown message types within a sub-handler's range.
  • lightning/src/offers/offer.rs:908quantity > 0 && quantity <= n.get() correctly rejects 0 for bounded quantities.
  • lightning/src/ln/channel.rs:6122 — clearing monitor_pending_revoke_and_ack when an RAA is regenerated via the signer-pending path prevents duplicate RAA generation.

The remaining additions are tests and CHANGELOG release notes, consistent with the fixes.

@tnulltnull 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.

Reviewed release notes, LGTM

Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 167d648 to e2c8d21CompareJune 18, 2026 13:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Updated release notes with feedback incl from #4706:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d259c7a23..5fb5c9b157 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -9,3 +9,4 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in BOLT 12 `OfferBuilder` (#4324).+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ now maps 0-amounts to an amount of `None` (#4324).@@ -20,3 +21,4 @@
could have become stuck (#4520).
- * The electrum sync client now properly skips unconfirmed transactions (#4590).+ * The presence of unconfirmed transactions actually no longer causes+ `ElectrumSyncClient` to spuriously fail to sync (#4590).
* `FilesystemStore::list_all_keys` will no longer fail if there are stale

Comment threadCHANGELOG.md Outdated
Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from e2c8d21 to 5cac547CompareJune 18, 2026 16:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a typo and named the release:

$ git diff-tree -U1 e2c8d21de 5cac547d1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fb5c9b157..a6fd5bfb18 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - XXX - "XXX"+# 0.1.10 - Jun 18, 2026 - "An Older Loupe"@@ -9,3 +9,3 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 5cac547 to 8caaa3eCompareJune 18, 2026 16:12
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed further typos from #4706

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6fd5bfb18..67e929a5fc 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -3,9 +3,9 @@
## API Updates
- * `DefaultMessageRouter` will now always generate blinded message paths which+ * `DefaultMessageRouter` will now always generate blinded message paths that
provide no privacy (where our node is the introduction node) for nodes with
public channels. This works around an issue which will appear for any nodes
- with LND peers which enable onion messaging - such peers will refuse to+ with LND peers that enable onion messaging - such peers will refuse to
forward BOLT 12 messages from unknown third parties, which most BOLT 12
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`+ * Explicit `amount_msats` of 0 is rejected in BOLT 12 `Offer`s; `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).
@@ -31,3 +31,3 @@
`ChannelManager::abandon_payment` was called before the payment ultimately
- completing anyway (#4651).+ completes anyway (#4651).
* Syncing a `ChainMonitor` using the `Confirm` trait will no longer write some
@@ -44,4 +44,4 @@
* `InvoiceRequestBuilder` will no longer accept a `quantity` of `0` for a
- `Bolt12Offer` allowing any quantity up to a bound (#4667).- * `lightning-custom-message` handlers which return `Ok(None)` when asked to+ BOLT 12 `Offer`, allowing any quantity up to a bound (#4667).+ * `lightning-custom-message` handlers that return `Ok(None)` when asked to
deserialize a message in their defined range no longer cause panics (#4709).

Comment threadCHANGELOG.md Outdated
@@ -1,9 +1,67 @@
# 0.1.10 - Jun 18, 2026 - "An Older Loupe"

@valentinewallacevalentinewallaceJun 18, 2026

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.

A Strange Loupe

Loupe de Loupe

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I was thinking in reference to the Through the Loupe for 0.2.3. What is strange in reference to?

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.

Ahh. It's a famous book (I haven't read it) https://en.wikipedia.org/wiki/I_Am_a_Strange_Loop

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Took Loupe de Loupe.

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch 2 times, most recently from d35fa91 to 43efc52CompareJune 18, 2026 17:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Corrected the text for 4697:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67e929a5fc..09dfe4e55e 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - Jun 18, 2026 - "An Older Loupe"+# 0.1.10 - Jun 18, 2026 - "Loupe de Loupe"@@ -26,3 +26,4 @@
* When forwarding an HTLC while in a blinded path with proportional fees over
- 100%, LDK will no longer spuriously charge 1 msat too little (#4697).+ 200%, LDK will no longer spuriously allow a forward that pays us 1 msat too+ little in fees (#4697).
* Fixed a rare case where a channel could get stuck on reconnect when using

jkczyzand others added 2 commits June 18, 2026 17:19
A handler built with `composite_custom_message_handler!` routes an incoming
message type to the sub-handler whose pattern matches it and assumed the
sub-handler would always decode it. But per the `CustomMessageReader`
contract a sub-handler returns `Ok(None)` for a type it doesn't recognize,
and a sub-handler's pattern -- a range in particular -- can be broader than
the types it actually decodes.
Since the message type comes from peer input, this let a remote peer panic
the message-processing thread with a single custom message whose type falls
in a sub-handler's pattern but isn't decoded by it. Report such a message as
unknown instead, matching how `wire::do_read` handles an undecoded custom
message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Backport of 77ac339
Silent conflicts resolved in:
* lightning-custom-message/src/lib.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 43efc52 to e225350CompareJune 18, 2026 17:19
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a backport missed conflict:

diff --git a/lightning-custom-message/src/lib.rs b/lightning-custom-message/src/lib.rs
index 0f55dcb842..5a9fa691dc 100644
--- a/lightning-custom-message/src/lib.rs+++ b/lightning-custom-message/src/lib.rs@@ -512,3 +512,3 @@ mod tests {
type CustomMessage = Foo;
- fn read<R: LengthLimitedRead>(+ fn read<R: Read>(
&self, message_type: u16, _b: &mut R,

@TheBlueMattTheBlueMatt mentioned this pull request Jun 18, 2026
@TheBlueMatt
TheBlueMatt merged commit 0cf27ff into lightningdevkit:0.1Jun 18, 2026
3 checks passed
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.

7 participants

@TheBlueMatt@ldk-reviews-bot@ldk-claude-review-bot@tnull@jkczyz@valentinewallace@wpaulino
, '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

[0.1] Further backports and draft release notes - #4710

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2
Jun 18, 2026
Merged

[0.1] Further backports and draft release notes#4710
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Backports #4667, #4684, #4697, #4707, and #4709. Did not include #4673 as its not as trivial and I'm not really sure UTXO lokup implementors should ever return a dup result.

jkczyzand others added 4 commits June 17, 2026 20:07
An offer advertising Quantity::Bounded expects at least one item, but
is_valid_quantity accepted a quantity of 0 since it only checked the
upper bound. Require the quantity to be greater than 0 so that an
invoice request for 0 items is rejected as an InvalidQuantity.
Co-Authored-By: Claude <noreply@anthropic.com>
Backport of 7620124
The `chanmon_consistency` fuzz target found a reconnect ordering where
`signer_pending_revoke_and_ack` and `monitor_pending_revoke_and_ack`
could both describe the same owed `revoke_and_ack`.
The channel first received a `commitment_signed` whose monitor update
completed, but the signer could not provide the next point or secret,
leaving `signer_pending_revoke_and_ack` set. Later, receiving the peer
`revoke_and_ack` freed holding-cell HTLCs and produced a held monitor
update. While that monitor update was still blocked,
`channel_reestablish` saw the peer one state behind and recorded
`monitor_pending_revoke_and_ack`, plus the corresponding monitor-pending
`commitment_signed`, so the messages could be replayed once monitor
updating was restored.
If the signer unblocked before the held monitor update was released,
`signer_maybe_unblocked` generated and sent the already monitor-safe RAA
using `signer_pending_revoke_and_ack`. The monitor-pending flag was not
cleared at that point, so `monitor_updating_restored` later generated
the same RAA again when the held update completed. The peer had already
advanced after accepting the signer-unblocked RAA, so it rejected the
duplicate secret as not corresponding to its current pubkey and
force-closed.
Fix this by clearing `monitor_pending_revoke_and_ack` in the
signer-resume path only once a signer-pending RAA is actually being
returned.
Backport of 27223fd
Conflicts resolved in:
* lightning/src/ln/async_signer_tests.rs
If we have a high (200%+) proportional fee as an intermediate blinded node
combined with a low inbound amount, we previously had some code that calculated
the outbound amount of the forward that would've underflowed. This would've
caused a panic in debug builds and caused us to relay a payment that should've
been rejected (due to being unable to cover our high fee) in release builds.
Reported by Project Loupe.
Backport of e560ec1
If a caller of send_payment_with_route provided a route with either no paths,
or where the first path had 0 hops, the method would panic due to attempting to
unwrap a dummy pubkey that was initialized with 32 bytes instead of the
required 33.
Reported by Project Loupe.
Backport of 54cdd85
@ldk-reviews-bot

ldk-reviews-bot commented Jun 17, 2026

Copy link
Copy Markdown

I've assigned @wpaulino 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.

@ldk-claude-review-bot

ldk-claude-review-bot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

The diff is unchanged from my prior two review passes, as confirmed by my memory notes. All production code changes remain correct.

No issues found.

The diff is unchanged from prior review passes. All production code changes remain correct:

  • lightning/src/blinded_path/payment.rs:525inbound_amt.checked_sub(fee)? properly guards the underflow and returns None as documented.
  • lightning/src/ln/channelmanager.rs:4728 — dummy pubkey corrected to [2; 33] (valid 33-byte compressed key length).
  • lightning-custom-message/src/lib.rs:366Ok(None) instead of unreachable!() correctly handles peer-provided unknown message types within a sub-handler's range.
  • lightning/src/offers/offer.rs:908quantity > 0 && quantity <= n.get() correctly rejects 0 for bounded quantities.
  • lightning/src/ln/channel.rs:6122 — clearing monitor_pending_revoke_and_ack when an RAA is regenerated via the signer-pending path prevents duplicate RAA generation.

The remaining additions are tests and CHANGELOG release notes, consistent with the fixes.

@tnulltnull 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.

Reviewed release notes, LGTM

Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 167d648 to e2c8d21CompareJune 18, 2026 13:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Updated release notes with feedback incl from #4706:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d259c7a23..5fb5c9b157 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -9,3 +9,4 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in BOLT 12 `OfferBuilder` (#4324).+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ now maps 0-amounts to an amount of `None` (#4324).@@ -20,3 +21,4 @@
could have become stuck (#4520).
- * The electrum sync client now properly skips unconfirmed transactions (#4590).+ * The presence of unconfirmed transactions actually no longer causes+ `ElectrumSyncClient` to spuriously fail to sync (#4590).
* `FilesystemStore::list_all_keys` will no longer fail if there are stale

Comment threadCHANGELOG.md Outdated
Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from e2c8d21 to 5cac547CompareJune 18, 2026 16:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a typo and named the release:

$ git diff-tree -U1 e2c8d21de 5cac547d1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fb5c9b157..a6fd5bfb18 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - XXX - "XXX"+# 0.1.10 - Jun 18, 2026 - "An Older Loupe"@@ -9,3 +9,3 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 5cac547 to 8caaa3eCompareJune 18, 2026 16:12
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed further typos from #4706

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6fd5bfb18..67e929a5fc 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -3,9 +3,9 @@
## API Updates
- * `DefaultMessageRouter` will now always generate blinded message paths which+ * `DefaultMessageRouter` will now always generate blinded message paths that
provide no privacy (where our node is the introduction node) for nodes with
public channels. This works around an issue which will appear for any nodes
- with LND peers which enable onion messaging - such peers will refuse to+ with LND peers that enable onion messaging - such peers will refuse to
forward BOLT 12 messages from unknown third parties, which most BOLT 12
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`+ * Explicit `amount_msats` of 0 is rejected in BOLT 12 `Offer`s; `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).
@@ -31,3 +31,3 @@
`ChannelManager::abandon_payment` was called before the payment ultimately
- completing anyway (#4651).+ completes anyway (#4651).
* Syncing a `ChainMonitor` using the `Confirm` trait will no longer write some
@@ -44,4 +44,4 @@
* `InvoiceRequestBuilder` will no longer accept a `quantity` of `0` for a
- `Bolt12Offer` allowing any quantity up to a bound (#4667).- * `lightning-custom-message` handlers which return `Ok(None)` when asked to+ BOLT 12 `Offer`, allowing any quantity up to a bound (#4667).+ * `lightning-custom-message` handlers that return `Ok(None)` when asked to
deserialize a message in their defined range no longer cause panics (#4709).

Comment threadCHANGELOG.md Outdated
@@ -1,9 +1,67 @@
# 0.1.10 - Jun 18, 2026 - "An Older Loupe"

@valentinewallacevalentinewallaceJun 18, 2026

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.

A Strange Loupe

Loupe de Loupe

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I was thinking in reference to the Through the Loupe for 0.2.3. What is strange in reference to?

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.

Ahh. It's a famous book (I haven't read it) https://en.wikipedia.org/wiki/I_Am_a_Strange_Loop

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Took Loupe de Loupe.

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch 2 times, most recently from d35fa91 to 43efc52CompareJune 18, 2026 17:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Corrected the text for 4697:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67e929a5fc..09dfe4e55e 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - Jun 18, 2026 - "An Older Loupe"+# 0.1.10 - Jun 18, 2026 - "Loupe de Loupe"@@ -26,3 +26,4 @@
* When forwarding an HTLC while in a blinded path with proportional fees over
- 100%, LDK will no longer spuriously charge 1 msat too little (#4697).+ 200%, LDK will no longer spuriously allow a forward that pays us 1 msat too+ little in fees (#4697).
* Fixed a rare case where a channel could get stuck on reconnect when using

jkczyzand others added 2 commits June 18, 2026 17:19
A handler built with `composite_custom_message_handler!` routes an incoming
message type to the sub-handler whose pattern matches it and assumed the
sub-handler would always decode it. But per the `CustomMessageReader`
contract a sub-handler returns `Ok(None)` for a type it doesn't recognize,
and a sub-handler's pattern -- a range in particular -- can be broader than
the types it actually decodes.
Since the message type comes from peer input, this let a remote peer panic
the message-processing thread with a single custom message whose type falls
in a sub-handler's pattern but isn't decoded by it. Report such a message as
unknown instead, matching how `wire::do_read` handles an undecoded custom
message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Backport of 77ac339
Silent conflicts resolved in:
* lightning-custom-message/src/lib.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 43efc52 to e225350CompareJune 18, 2026 17:19
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a backport missed conflict:

diff --git a/lightning-custom-message/src/lib.rs b/lightning-custom-message/src/lib.rs
index 0f55dcb842..5a9fa691dc 100644
--- a/lightning-custom-message/src/lib.rs+++ b/lightning-custom-message/src/lib.rs@@ -512,3 +512,3 @@ mod tests {
type CustomMessage = Foo;
- fn read<R: LengthLimitedRead>(+ fn read<R: Read>(
&self, message_type: u16, _b: &mut R,

@TheBlueMattTheBlueMatt mentioned this pull request Jun 18, 2026
@TheBlueMatt
TheBlueMatt merged commit 0cf27ff into lightningdevkit:0.1Jun 18, 2026
3 checks passed
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.

7 participants

@TheBlueMatt@ldk-reviews-bot@ldk-claude-review-bot@tnull@jkczyz@valentinewallace@wpaulino
, '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

[0.1] Further backports and draft release notes - #4710

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2
Jun 18, 2026
Merged

[0.1] Further backports and draft release notes#4710
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Backports #4667, #4684, #4697, #4707, and #4709. Did not include #4673 as its not as trivial and I'm not really sure UTXO lokup implementors should ever return a dup result.

jkczyzand others added 4 commits June 17, 2026 20:07
An offer advertising Quantity::Bounded expects at least one item, but
is_valid_quantity accepted a quantity of 0 since it only checked the
upper bound. Require the quantity to be greater than 0 so that an
invoice request for 0 items is rejected as an InvalidQuantity.
Co-Authored-By: Claude <noreply@anthropic.com>
Backport of 7620124
The `chanmon_consistency` fuzz target found a reconnect ordering where
`signer_pending_revoke_and_ack` and `monitor_pending_revoke_and_ack`
could both describe the same owed `revoke_and_ack`.
The channel first received a `commitment_signed` whose monitor update
completed, but the signer could not provide the next point or secret,
leaving `signer_pending_revoke_and_ack` set. Later, receiving the peer
`revoke_and_ack` freed holding-cell HTLCs and produced a held monitor
update. While that monitor update was still blocked,
`channel_reestablish` saw the peer one state behind and recorded
`monitor_pending_revoke_and_ack`, plus the corresponding monitor-pending
`commitment_signed`, so the messages could be replayed once monitor
updating was restored.
If the signer unblocked before the held monitor update was released,
`signer_maybe_unblocked` generated and sent the already monitor-safe RAA
using `signer_pending_revoke_and_ack`. The monitor-pending flag was not
cleared at that point, so `monitor_updating_restored` later generated
the same RAA again when the held update completed. The peer had already
advanced after accepting the signer-unblocked RAA, so it rejected the
duplicate secret as not corresponding to its current pubkey and
force-closed.
Fix this by clearing `monitor_pending_revoke_and_ack` in the
signer-resume path only once a signer-pending RAA is actually being
returned.
Backport of 27223fd
Conflicts resolved in:
* lightning/src/ln/async_signer_tests.rs
If we have a high (200%+) proportional fee as an intermediate blinded node
combined with a low inbound amount, we previously had some code that calculated
the outbound amount of the forward that would've underflowed. This would've
caused a panic in debug builds and caused us to relay a payment that should've
been rejected (due to being unable to cover our high fee) in release builds.
Reported by Project Loupe.
Backport of e560ec1
If a caller of send_payment_with_route provided a route with either no paths,
or where the first path had 0 hops, the method would panic due to attempting to
unwrap a dummy pubkey that was initialized with 32 bytes instead of the
required 33.
Reported by Project Loupe.
Backport of 54cdd85
@ldk-reviews-bot

ldk-reviews-bot commented Jun 17, 2026

Copy link
Copy Markdown

I've assigned @wpaulino 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.

@ldk-claude-review-bot

ldk-claude-review-bot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

The diff is unchanged from my prior two review passes, as confirmed by my memory notes. All production code changes remain correct.

No issues found.

The diff is unchanged from prior review passes. All production code changes remain correct:

  • lightning/src/blinded_path/payment.rs:525inbound_amt.checked_sub(fee)? properly guards the underflow and returns None as documented.
  • lightning/src/ln/channelmanager.rs:4728 — dummy pubkey corrected to [2; 33] (valid 33-byte compressed key length).
  • lightning-custom-message/src/lib.rs:366Ok(None) instead of unreachable!() correctly handles peer-provided unknown message types within a sub-handler's range.
  • lightning/src/offers/offer.rs:908quantity > 0 && quantity <= n.get() correctly rejects 0 for bounded quantities.
  • lightning/src/ln/channel.rs:6122 — clearing monitor_pending_revoke_and_ack when an RAA is regenerated via the signer-pending path prevents duplicate RAA generation.

The remaining additions are tests and CHANGELOG release notes, consistent with the fixes.

@tnulltnull 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.

Reviewed release notes, LGTM

Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 167d648 to e2c8d21CompareJune 18, 2026 13:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Updated release notes with feedback incl from #4706:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d259c7a23..5fb5c9b157 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -9,3 +9,4 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in BOLT 12 `OfferBuilder` (#4324).+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ now maps 0-amounts to an amount of `None` (#4324).@@ -20,3 +21,4 @@
could have become stuck (#4520).
- * The electrum sync client now properly skips unconfirmed transactions (#4590).+ * The presence of unconfirmed transactions actually no longer causes+ `ElectrumSyncClient` to spuriously fail to sync (#4590).
* `FilesystemStore::list_all_keys` will no longer fail if there are stale

Comment threadCHANGELOG.md Outdated
Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from e2c8d21 to 5cac547CompareJune 18, 2026 16:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a typo and named the release:

$ git diff-tree -U1 e2c8d21de 5cac547d1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fb5c9b157..a6fd5bfb18 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - XXX - "XXX"+# 0.1.10 - Jun 18, 2026 - "An Older Loupe"@@ -9,3 +9,3 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 5cac547 to 8caaa3eCompareJune 18, 2026 16:12
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed further typos from #4706

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6fd5bfb18..67e929a5fc 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -3,9 +3,9 @@
## API Updates
- * `DefaultMessageRouter` will now always generate blinded message paths which+ * `DefaultMessageRouter` will now always generate blinded message paths that
provide no privacy (where our node is the introduction node) for nodes with
public channels. This works around an issue which will appear for any nodes
- with LND peers which enable onion messaging - such peers will refuse to+ with LND peers that enable onion messaging - such peers will refuse to
forward BOLT 12 messages from unknown third parties, which most BOLT 12
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`+ * Explicit `amount_msats` of 0 is rejected in BOLT 12 `Offer`s; `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).
@@ -31,3 +31,3 @@
`ChannelManager::abandon_payment` was called before the payment ultimately
- completing anyway (#4651).+ completes anyway (#4651).
* Syncing a `ChainMonitor` using the `Confirm` trait will no longer write some
@@ -44,4 +44,4 @@
* `InvoiceRequestBuilder` will no longer accept a `quantity` of `0` for a
- `Bolt12Offer` allowing any quantity up to a bound (#4667).- * `lightning-custom-message` handlers which return `Ok(None)` when asked to+ BOLT 12 `Offer`, allowing any quantity up to a bound (#4667).+ * `lightning-custom-message` handlers that return `Ok(None)` when asked to
deserialize a message in their defined range no longer cause panics (#4709).

Comment threadCHANGELOG.md Outdated
@@ -1,9 +1,67 @@
# 0.1.10 - Jun 18, 2026 - "An Older Loupe"

@valentinewallacevalentinewallaceJun 18, 2026

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.

A Strange Loupe

Loupe de Loupe

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I was thinking in reference to the Through the Loupe for 0.2.3. What is strange in reference to?

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.

Ahh. It's a famous book (I haven't read it) https://en.wikipedia.org/wiki/I_Am_a_Strange_Loop

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Took Loupe de Loupe.

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch 2 times, most recently from d35fa91 to 43efc52CompareJune 18, 2026 17:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Corrected the text for 4697:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67e929a5fc..09dfe4e55e 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - Jun 18, 2026 - "An Older Loupe"+# 0.1.10 - Jun 18, 2026 - "Loupe de Loupe"@@ -26,3 +26,4 @@
* When forwarding an HTLC while in a blinded path with proportional fees over
- 100%, LDK will no longer spuriously charge 1 msat too little (#4697).+ 200%, LDK will no longer spuriously allow a forward that pays us 1 msat too+ little in fees (#4697).
* Fixed a rare case where a channel could get stuck on reconnect when using

jkczyzand others added 2 commits June 18, 2026 17:19
A handler built with `composite_custom_message_handler!` routes an incoming
message type to the sub-handler whose pattern matches it and assumed the
sub-handler would always decode it. But per the `CustomMessageReader`
contract a sub-handler returns `Ok(None)` for a type it doesn't recognize,
and a sub-handler's pattern -- a range in particular -- can be broader than
the types it actually decodes.
Since the message type comes from peer input, this let a remote peer panic
the message-processing thread with a single custom message whose type falls
in a sub-handler's pattern but isn't decoded by it. Report such a message as
unknown instead, matching how `wire::do_read` handles an undecoded custom
message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Backport of 77ac339
Silent conflicts resolved in:
* lightning-custom-message/src/lib.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 43efc52 to e225350CompareJune 18, 2026 17:19
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a backport missed conflict:

diff --git a/lightning-custom-message/src/lib.rs b/lightning-custom-message/src/lib.rs
index 0f55dcb842..5a9fa691dc 100644
--- a/lightning-custom-message/src/lib.rs+++ b/lightning-custom-message/src/lib.rs@@ -512,3 +512,3 @@ mod tests {
type CustomMessage = Foo;
- fn read<R: LengthLimitedRead>(+ fn read<R: Read>(
&self, message_type: u16, _b: &mut R,

@TheBlueMattTheBlueMatt mentioned this pull request Jun 18, 2026
@TheBlueMatt
TheBlueMatt merged commit 0cf27ff into lightningdevkit:0.1Jun 18, 2026
3 checks passed
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.

7 participants

@TheBlueMatt@ldk-reviews-bot@ldk-claude-review-bot@tnull@jkczyz@valentinewallace@wpaulino
, '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

[0.1] Further backports and draft release notes - #4710

Merged
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2
Jun 18, 2026
Merged

[0.1] Further backports and draft release notes#4710
TheBlueMatt merged 6 commits into
lightningdevkit:0.1from
TheBlueMatt:2026-06-0.1-backports-2

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Backports #4667, #4684, #4697, #4707, and #4709. Did not include #4673 as its not as trivial and I'm not really sure UTXO lokup implementors should ever return a dup result.

jkczyzand others added 4 commits June 17, 2026 20:07
An offer advertising Quantity::Bounded expects at least one item, but
is_valid_quantity accepted a quantity of 0 since it only checked the
upper bound. Require the quantity to be greater than 0 so that an
invoice request for 0 items is rejected as an InvalidQuantity.
Co-Authored-By: Claude <noreply@anthropic.com>
Backport of 7620124
The `chanmon_consistency` fuzz target found a reconnect ordering where
`signer_pending_revoke_and_ack` and `monitor_pending_revoke_and_ack`
could both describe the same owed `revoke_and_ack`.
The channel first received a `commitment_signed` whose monitor update
completed, but the signer could not provide the next point or secret,
leaving `signer_pending_revoke_and_ack` set. Later, receiving the peer
`revoke_and_ack` freed holding-cell HTLCs and produced a held monitor
update. While that monitor update was still blocked,
`channel_reestablish` saw the peer one state behind and recorded
`monitor_pending_revoke_and_ack`, plus the corresponding monitor-pending
`commitment_signed`, so the messages could be replayed once monitor
updating was restored.
If the signer unblocked before the held monitor update was released,
`signer_maybe_unblocked` generated and sent the already monitor-safe RAA
using `signer_pending_revoke_and_ack`. The monitor-pending flag was not
cleared at that point, so `monitor_updating_restored` later generated
the same RAA again when the held update completed. The peer had already
advanced after accepting the signer-unblocked RAA, so it rejected the
duplicate secret as not corresponding to its current pubkey and
force-closed.
Fix this by clearing `monitor_pending_revoke_and_ack` in the
signer-resume path only once a signer-pending RAA is actually being
returned.
Backport of 27223fd
Conflicts resolved in:
* lightning/src/ln/async_signer_tests.rs
If we have a high (200%+) proportional fee as an intermediate blinded node
combined with a low inbound amount, we previously had some code that calculated
the outbound amount of the forward that would've underflowed. This would've
caused a panic in debug builds and caused us to relay a payment that should've
been rejected (due to being unable to cover our high fee) in release builds.
Reported by Project Loupe.
Backport of e560ec1
If a caller of send_payment_with_route provided a route with either no paths,
or where the first path had 0 hops, the method would panic due to attempting to
unwrap a dummy pubkey that was initialized with 32 bytes instead of the
required 33.
Reported by Project Loupe.
Backport of 54cdd85
@ldk-reviews-bot

ldk-reviews-bot commented Jun 17, 2026

Copy link
Copy Markdown

I've assigned @wpaulino 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.

@ldk-claude-review-bot

ldk-claude-review-bot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

The diff is unchanged from my prior two review passes, as confirmed by my memory notes. All production code changes remain correct.

No issues found.

The diff is unchanged from prior review passes. All production code changes remain correct:

  • lightning/src/blinded_path/payment.rs:525inbound_amt.checked_sub(fee)? properly guards the underflow and returns None as documented.
  • lightning/src/ln/channelmanager.rs:4728 — dummy pubkey corrected to [2; 33] (valid 33-byte compressed key length).
  • lightning-custom-message/src/lib.rs:366Ok(None) instead of unreachable!() correctly handles peer-provided unknown message types within a sub-handler's range.
  • lightning/src/offers/offer.rs:908quantity > 0 && quantity <= n.get() correctly rejects 0 for bounded quantities.
  • lightning/src/ln/channel.rs:6122 — clearing monitor_pending_revoke_and_ack when an RAA is regenerated via the signer-pending path prevents duplicate RAA generation.

The remaining additions are tests and CHANGELOG release notes, consistent with the fixes.

@tnulltnull 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.

Reviewed release notes, LGTM

Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 167d648 to e2c8d21CompareJune 18, 2026 13:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Updated release notes with feedback incl from #4706:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d259c7a23..5fb5c9b157 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -9,3 +9,4 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in BOLT 12 `OfferBuilder` (#4324).+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ now maps 0-amounts to an amount of `None` (#4324).@@ -20,3 +21,4 @@
could have become stuck (#4520).
- * The electrum sync client now properly skips unconfirmed transactions (#4590).+ * The presence of unconfirmed transactions actually no longer causes+ `ElectrumSyncClient` to spuriously fail to sync (#4590).
* `FilesystemStore::list_all_keys` will no longer fail if there are stale

Comment threadCHANGELOG.md Outdated
Comment threadCHANGELOG.md Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from e2c8d21 to 5cac547CompareJune 18, 2026 16:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a typo and named the release:

$ git diff-tree -U1 e2c8d21de 5cac547d1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fb5c9b157..a6fd5bfb18 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - XXX - "XXX"+# 0.1.10 - Jun 18, 2026 - "An Older Loupe"@@ -9,3 +9,3 @@
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuidler`+ * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 5cac547 to 8caaa3eCompareJune 18, 2026 16:12
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed further typos from #4706

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6fd5bfb18..67e929a5fc 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -3,9 +3,9 @@
## API Updates
- * `DefaultMessageRouter` will now always generate blinded message paths which+ * `DefaultMessageRouter` will now always generate blinded message paths that
provide no privacy (where our node is the introduction node) for nodes with
public channels. This works around an issue which will appear for any nodes
- with LND peers which enable onion messaging - such peers will refuse to+ with LND peers that enable onion messaging - such peers will refuse to
forward BOLT 12 messages from unknown third parties, which most BOLT 12
payers rely on today (#4647).
- * Explicit `amount_msats` of 0 is rejected in `Bolt12Offer`s, `OfferBuilder`+ * Explicit `amount_msats` of 0 is rejected in BOLT 12 `Offer`s; `OfferBuilder`
now maps 0-amounts to an amount of `None` (#4324).
@@ -31,3 +31,3 @@
`ChannelManager::abandon_payment` was called before the payment ultimately
- completing anyway (#4651).+ completes anyway (#4651).
* Syncing a `ChainMonitor` using the `Confirm` trait will no longer write some
@@ -44,4 +44,4 @@
* `InvoiceRequestBuilder` will no longer accept a `quantity` of `0` for a
- `Bolt12Offer` allowing any quantity up to a bound (#4667).- * `lightning-custom-message` handlers which return `Ok(None)` when asked to+ BOLT 12 `Offer`, allowing any quantity up to a bound (#4667).+ * `lightning-custom-message` handlers that return `Ok(None)` when asked to
deserialize a message in their defined range no longer cause panics (#4709).

Comment threadCHANGELOG.md Outdated
@@ -1,9 +1,67 @@
# 0.1.10 - Jun 18, 2026 - "An Older Loupe"

@valentinewallacevalentinewallaceJun 18, 2026

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.

A Strange Loupe

Loupe de Loupe

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I was thinking in reference to the Through the Loupe for 0.2.3. What is strange in reference to?

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.

Ahh. It's a famous book (I haven't read it) https://en.wikipedia.org/wiki/I_Am_a_Strange_Loop

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Took Loupe de Loupe.

@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch 2 times, most recently from d35fa91 to 43efc52CompareJune 18, 2026 17:01
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Corrected the text for 4697:

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67e929a5fc..09dfe4e55e 100644
--- a/CHANGELOG.md+++ b/CHANGELOG.md@@ -1,2 +1,2 @@-# 0.1.10 - Jun 18, 2026 - "An Older Loupe"+# 0.1.10 - Jun 18, 2026 - "Loupe de Loupe"@@ -26,3 +26,4 @@
* When forwarding an HTLC while in a blinded path with proportional fees over
- 100%, LDK will no longer spuriously charge 1 msat too little (#4697).+ 200%, LDK will no longer spuriously allow a forward that pays us 1 msat too+ little in fees (#4697).
* Fixed a rare case where a channel could get stuck on reconnect when using

jkczyzand others added 2 commits June 18, 2026 17:19
A handler built with `composite_custom_message_handler!` routes an incoming
message type to the sub-handler whose pattern matches it and assumed the
sub-handler would always decode it. But per the `CustomMessageReader`
contract a sub-handler returns `Ok(None)` for a type it doesn't recognize,
and a sub-handler's pattern -- a range in particular -- can be broader than
the types it actually decodes.
Since the message type comes from peer input, this let a remote peer panic
the message-processing thread with a single custom message whose type falls
in a sub-handler's pattern but isn't decoded by it. Report such a message as
unknown instead, matching how `wire::do_read` handles an undecoded custom
message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Backport of 77ac339
Silent conflicts resolved in:
* lightning-custom-message/src/lib.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2026-06-0.1-backports-2 branch from 43efc52 to e225350CompareJune 18, 2026 17:19
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Fixed a backport missed conflict:

diff --git a/lightning-custom-message/src/lib.rs b/lightning-custom-message/src/lib.rs
index 0f55dcb842..5a9fa691dc 100644
--- a/lightning-custom-message/src/lib.rs+++ b/lightning-custom-message/src/lib.rs@@ -512,3 +512,3 @@ mod tests {
type CustomMessage = Foo;
- fn read<R: LengthLimitedRead>(+ fn read<R: Read>(
&self, message_type: u16, _b: &mut R,

@TheBlueMattTheBlueMatt mentioned this pull request Jun 18, 2026
@TheBlueMatt
TheBlueMatt merged commit 0cf27ff into lightningdevkit:0.1Jun 18, 2026
3 checks passed
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.

7 participants

@TheBlueMatt@ldk-reviews-bot@ldk-claude-review-bot@tnull@jkczyz@valentinewallace@wpaulino